From 824e035473ef51c6b97217cd83dfa1194f5600c0 Mon Sep 17 00:00:00 2001 From: "AMOUSSOU Z. Kenneth" Date: Sat, 27 May 2023 13:05:11 +0200 Subject: [PATCH 1/3] fix #2: Seperation of configuration and recording commands --- README.md | 67 ++++++------ mimo.c | 100 ++++++++++++------ mimo.h | 2 +- opt/opt.c | 86 ++++++++++----- opt/opt.h | 8 ++ ti/ethernet/src/mmwl_port_ethernet.c | 152 +++++++++++++++------------ ti/ethernet/src/mmwl_port_ethernet.h | 7 +- ti/mmwave/mmwave.c | 51 ++++++++- ti/mmwave/mmwave.h | 2 +- 9 files changed, 311 insertions(+), 164 deletions(-) diff --git a/README.md b/README.md index ea9913d..995a247 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# mmwave +# MMWAVE The MMWCAS-RF-EVM and MMWCAS-DSP-EVM boards from Texas Instruments (TI) are supported with the TI-provided software `mmwave studio`. As so, one needs a Windows OS and Matlab @@ -35,23 +35,23 @@ You can first check if `mmwave` is properly installed by typing the `help` comma mmwave -h ``` -You shall the see a help menu similar to the one below. +You shall see a help menu similar to the one below. ```txt -usage: mmwave [-d] [-p] [-i] [-c] [-r] [-t] [-f] [-h] [-v] - -Configuration and control tool for TI MMWave cascade Evaluation Module - -options: - -d, --capture-dir Name of the director where to store recordings on the DSP board - -p, --port Port number the DSP board server app is listening on - -i, --ip-addr IP Address of the MMWCAS DSP evaluation module - -c, --configure Configure the MMWCAS-RF-EVM board - -r, --record Trigger data recording. This assumes that configuration is completed. - -t, --time Indicate how long the recording should last in minutes. Default: 1 min - -f, --cfg TOML Configuration file. Overwrite the default config when provided - -h, --help Print CLI option help and exit. - -v, --version Print program version and exit. +usage: mmwave [command] [option] + +Configuration and control tool for TI MMWave Evaluation Modules + +Arguments: + configure Configure the MMWCAS-RF-EVM board + record Trigger data recording. This assumes that configuration is completed. + -d, --capture-dir Name of the director where to store recordings on the DSP board + -p, --port Port number the DSP board server app is listening on + -i, --ip IP Address of the MMWCAS DSP evaluation module + -t, --time Indicate how long the recording should last in minutes. Default: 1 min + -f, --cfg TOML Configuration file. Overwrite the default config when provided + -h, --help Print CLI option help and exit. + -v, --version Print program version and exit ``` A default configuration is already implemented (as described below) and can be used. @@ -63,7 +63,7 @@ A default configuration is already implemented (as described below) and can be u ``` If the DSP board has been reconfigured with another IP address, you can provide the new -IP address in argument with the `--ip-addr` CLI option. +IP address in argument with the `--ip` CLI option. ## Recording data @@ -72,10 +72,12 @@ IP address in argument with the `--ip-addr` CLI option. To record data, the typical command is: ```bash -mmwave -d --configure --record --time +mmwave configure +mmwave record -d --time # Exmaple -mmwave -d outdoor0 --configure --record --time 10 +mmwave configure +mmwave record -d outdoor0 --time 10 ``` With this command, the radar chips are configured with the default configuration @@ -114,22 +116,24 @@ dataFmt: ``` If the capture directory is not indicated (with the `-d` option), the capture folder is -automatically created as `MMW_Capture_`; with `` is placeholder for +automatically created as `MMW_Capture_`; with `` a placeholder for the Unix timestamp at which the command has been issued. ### Self-defined configuration It's possible to define custom configurations suitable for a given recording setup -with TOML config files. Some examples of config files are present on the `config` +with TOML config files. Some examples of config files are present in the `config` folder of this repository. With a config file, one can use the command below: ```bash -mmwave -f --configure --record --time +mmwave configure -f +mmwave record --time # Example -mmwave -f config/short-range-cfg.toml --configure --record --time 2 +mmwave configure -f config/short-range-cfg.toml +mmwave record --time 2 ``` ### Check and copy recorded data @@ -206,20 +210,23 @@ The structure of the repository is as follows: ``` The content of the folders `ti/mmwavelink` and `ti/firmware` must not be modified. Those -are respectively libraries and firmware provided by Texas Instruments and should not be -modified unless one knows what it's all about. Any update to those can be directly obtained -from TI or by copying them from the installation folder of `mmwave studio` and -`mmwave dfp`. +are respectively libraries and firmware provided by Texas Instruments and should ideally not be +modified. Any update to those can be directly obtained from TI or by copying them from the installation +folder of `mmwave studio` and `mmwave dfp`. The folders `ti/ethernet` and `ti/mmwave` are based on examples source files provided by -TI. Since the original sources were only compatible with windows, these have been modified +TI. Since the original sources were only compatible with Windows OS, these have been modified to operate on Linux OS. One can update these modules to extend the capabilities of this driver. - The folder `opt` holds the source handling the CLI option parsing - The `toml` folder handles the parsing of configuration files. - The entry point of the program is in the `mimo.c` file. -**NOTE**: the files `toml/toml.c` and `toml/toml.h` have been authored by +**NOTE**: + +* The files `toml/toml.c` and `toml/toml.h` have been authored by [cktan](https://github.com/cktan) and released with an MIT license on Github at https://github.com/cktan/tomlc99. Therefore, this reference is the perfect place to -seek for new updates of the `TOML` parser library. +seek new updates to the `TOML` parser library. + +* See [opt](https://github.com/azinke/opt) for updates of the CLI parser diff --git a/mimo.c b/mimo.c index 47d64ea..0c9dcb6 100644 --- a/mimo.c +++ b/mimo.c @@ -247,7 +247,17 @@ void check(int status, const char *success_msg, const char *error_msg, } } - +/** + * @brief Initialize the master RADAR chip of the MMWCAS-RF-EVM board + * + * The configuration defines the number of channels to enbaled and the + * output format of the RADAR chips' ADC module. The patch firmware is also + * uploaded to the chip + * + * @param channelCfg Channel configuration + * @param adcOutCfg ADC configs + * @return int32_t Configuration status + */ int32_t initMaster(rlChanCfg_t channelCfg, rlAdcOutCfg_t adcOutCfg) { const unsigned int masterId = 0; const unsigned int masterMap = 1 << masterId; @@ -293,6 +303,17 @@ int32_t initMaster(rlChanCfg_t channelCfg, rlAdcOutCfg_t adcOutCfg) { } +/** + * @brief Initialize the Slave RADAR chips of the MMWCAS-RF-EVM board + * + * The configuration defines the number of channels to enbaled and the + * output format of the RADAR chips' ADC module. The patch firmware is also + * uploaded to the chips + * + * @param channelCfg Channel configuration + * @param adcOutCfg ADC configs + * @return int32_t Configuration status + */ int32_t initSlaves(rlChanCfg_t channelCfg, rlAdcOutCfg_t adcOutCfg) { int status = 0; uint8_t slavesMap = (1 << 1) | (1 << 2) | (1 << 3); @@ -342,6 +363,12 @@ int32_t initSlaves(rlChanCfg_t channelCfg, rlAdcOutCfg_t adcOutCfg) { } +/** + * @brief Handle the global configuration of the MMWCAS board + * + * @param config Device configuration + * @return uint32_t Configuration status + */ uint32_t configure (devConfig_t config) { int status = 0; status += initMaster(config.channelCfg, config.adcOutCfg); @@ -445,7 +472,7 @@ parser_t *g_parser = NULL; * Print program version */ void print_version() { - printf(PROG_NAME " version " PROG_VERSION ", " PROG_COPYRIGHT "\n"); + printf(PROG_NAME " " PROG_VERSION ", " PROG_COPYRIGHT "\n"); exit(0); } @@ -491,17 +518,32 @@ int main (int argc, char *argv[]) { unsigned char default_capture_directory[64]; sprintf(default_capture_directory, "%s_%lu", "MMWL_Capture", (unsigned long int)time(NULL)); int status = 0; + // unsigned char vdefault = 0; float default_recording_duration = 1.0; // min parser_t parser = init_parser( PROG_NAME, - "Configuration and control tool for TI MMWave cascade Evaluation Module" + "Configuration and control tool for TI MMWave Evaluation Modules" ); g_parser = &parser; atexit(cleanup); // Call the cleanup function before exiting the program signal(SIGINT, signal_handler); // Catch CTRL+C to enable memory deallocation + option_t opt_config = { + .args = "configure", + .help = "Configure the MMWCAS-RF-EVM board", + .type = OPT_BOOL, + }; + add_arg(&parser, &opt_config); + + option_t opt_record = { + .args = "record", + .help = "Trigger data recording. This assumes that configuration is completed.", + .type = OPT_BOOL, + }; + add_arg(&parser, &opt_record); + option_t opt_capturedir = { .args = "-d", .argl = "--capture-dir", @@ -522,29 +564,13 @@ int main (int argc, char *argv[]) { option_t opt_ipaddr = { .args = "-i", - .argl = "--ip-addr", + .argl = "--ip", .help = "IP Address of the MMWCAS DSP evaluation module", .type = OPT_STR, .default_value = default_ip_addr, }; add_arg(&parser, &opt_ipaddr); - option_t opt_config = { - .args = "-c", - .argl = "--configure", - .help = "Configure the MMWCAS-RF-EVM board", - .type = OPT_BOOL, - }; - add_arg(&parser, &opt_config); - - option_t opt_record = { - .args = "-r", - .argl = "--record", - .help = "Trigger data recording. This assumes that configuration is completed.", - .type = OPT_BOOL, - }; - add_arg(&parser, &opt_record); - option_t opt_record_duration = { .args = "-t", .argl = "--time", @@ -590,9 +616,9 @@ int main (int argc, char *argv[]) { exit(0); } - unsigned char *ip_addr = (unsigned char*)get_option(&parser, "ip-addr"); - unsigned int port = *(unsigned int*)get_option(&parser, "port"); - unsigned char *capture_directory = (unsigned char*)get_option(&parser, "capture-dir"); + unsigned char *ip_addr = (unsigned char*)get_option(&parser, "--ip"); + unsigned int port = *(unsigned int*)get_option(&parser, "--port"); + unsigned char *capture_directory = (unsigned char*)get_option(&parser, "--capture-dir"); strcat(capture_path, capture_directory); /* Record CLI option possible values are: * - start: To start a recording and exit @@ -600,10 +626,10 @@ int main (int argc, char *argv[]) { * - oneshot: Start a recording, wait for it's complemention and stop it. */ unsigned char *record = (unsigned char*)get_option(&parser, "record"); - float record_duration = *(float*)get_option(&parser, "time"); + float record_duration = *(float*)get_option(&parser, "--time"); record_duration *= 60 * 1000; // convert into milliseconds - unsigned char *config_filename = (unsigned char*)get_option(&parser, "cfg"); + unsigned char *config_filename = (unsigned char*)get_option(&parser, "--cfg"); // Configuration devConfig_t config; @@ -651,19 +677,25 @@ int main (int argc, char *argv[]) { .dataPacking = 0, // 0: 16-bit | 1: 12-bit }; - if ((unsigned char *)get_option(&parser, "configure") != NULL) { - // Connect to TDA - status = MMWL_TDAInit(ip_addr, port, config.deviceMap); - check(status, + // Connect to TDA + status = MMWL_TDAInit(ip_addr, port); + check(status, "[MMWCAS-DSP] TDA Connected!", "[MMWCAS-DSP] Couldn't connect to TDA board!\n", 32, TRUE); + if ((unsigned char *)get_option(&parser, "configure") != NULL) { + // Configure TDA board + status = MMWL_ConfigureDeviveMap(config.deviceMap); + check(status, + "[MMWCAS-DSP] TDA Initialized!", + "[MMWCAS-DSP] Couldn't initialize the TDA board!\n", config.deviceMap, TRUE); + // Start configuration configure(config); - msleep(2000); + msleep(1000); } - if ((unsigned char *)get_option(&parser, "record") != NULL) { + else if ((unsigned char *)get_option(&parser, "record") != NULL) { // Arm TDA status = MMWL_ArmingTDA(tdaCfg); check(status, @@ -693,5 +725,11 @@ int main (int argc, char *argv[]) { "[MMWCAS-RF] Failed to de-arm TDA board!\n", 32, TRUE); msleep(1000); } + + // Disconnect from TDA + status = MMWL_TDADeInit(); + check(status, + "[MMWCAS-DSP] TDA successfully disconnected!", + "[MMWCAS-DSP] Couldn't disconnect from TDA board!\n", 32, TRUE); return 0; } diff --git a/mimo.h b/mimo.h index 765097d..566d66a 100644 --- a/mimo.h +++ b/mimo.h @@ -18,7 +18,7 @@ #define PROG_NAME "mmwave" // Name of the program #define PROG_VERSION "0.1" // Program version -#define PROG_COPYRIGHT "Copyright (C) 2022" +#define PROG_COPYRIGHT "Copyright (C) 2022 - 2023" /* Enable development environment Status messages are printed. Set to '0' to disable the diff --git a/opt/opt.c b/opt/opt.c index 1efd3b3..7908d43 100644 --- a/opt/opt.c +++ b/opt/opt.c @@ -90,27 +90,24 @@ void free_parser(parser_t *parser) { * @param parser Pointer to the parser */ void print_help(parser_t* parser) { - printf("usage: %s", parser->name); - arg_t *argc = parser->first_arg; - while(argc != NULL) { - if (argc->opt->args != NULL) printf(" [%s]", argc->opt->args); - else printf(" [%s]", argc->opt->argl); - argc = (arg_t*)argc->next; - } - + printf("usage: %s [command] [option]", parser->name); printf("\n\n%s\n\n", parser->description); - printf("options:\n"); + printf("Arguments:\n"); - argc = parser->first_arg; - const int buffer_size = 32; + arg_t *argc = parser->first_arg; + const int buffer_size = 256; char buf[buffer_size]; while(argc != NULL) { memset(buf, '\0', buffer_size); - if (argc->opt->args != NULL){ - strcpy(buf, argc->opt->args); - strcat(buf, ", "); + if (argc->opt->args != NULL) { + if (*(argc->opt->args) == '-') strcat(buf, " "); + strcat(buf, argc->opt->args); + if (*(argc->opt->args) == '-') strcat(buf, ","); + } + if (argc->opt->argl != NULL) { + if (*(argc->opt->argl) == '-') strcat(buf, " "); + strcat(buf, argc->opt->argl); } - if (argc->opt->argl != NULL) strcat(buf, argc->opt->argl); printf(" %-30s ", buf); printf("%s \n", argc->opt->help); argc = (arg_t*)argc->next; @@ -128,11 +125,23 @@ void print_help(parser_t* parser) { * @return int */ int parse(parser_t *parser, int argc, char* argv[]) { - if (argc <= 1) return 0; + unsigned char option_found = 0; + unsigned char missing_value = 0; + for (int idx = 1; idx < argc; idx++) { arg_t *arg = parser->first_arg; + option_found = 0; + missing_value = 0; while (arg != NULL) { if (is_arg(argv[idx], arg) == OPT_SUCCESS) { + option_found = 1; + if ((arg->opt->type != OPT_BOOL) && (idx+1 >= argc)) { + printf( + "\033[0;31mValue expected for option '%s', " + "but none provided.\033[0m\n\n", argv[idx]); + missing_value = 1; + break; + } switch (arg->opt->type) { case OPT_BOOL: { // Set the boolean as "True" when present @@ -174,7 +183,36 @@ int parse(parser_t *parser, int argc, char* argv[]) { } arg = (arg_t*)arg->next; } + if (!option_found) { + printf("\033[0;31mUnkonwn option: '%s'\033[0m\n\n", argv[idx]); + } + if (missing_value || !option_found) { + print_help(parser); + free_parser(parser); + exit(1); + } + } + + /** Check for required CLI options */ + arg_t *arg = parser->first_arg; + unsigned int arg_count = 0; + while(arg != NULL) { + if (arg->opt->required && !arg->is_set) { + if (arg_count == 0) printf("\033[0;31mOption "); + if (arg->opt->argl != NULL) printf("'%s' ", arg->opt->argl); + else printf("'%s' ", arg->opt->args); + arg_count++; + } + arg = (arg_t*) arg->next; } + if (arg_count == 1) printf("is required.\033[0m\n\n"); + else if (arg_count > 1) printf("are required.\033[0m\n\n"); + if (arg_count != 0) { + print_help(parser); + free_parser(parser); + exit(1); + } + return OPT_SUCCESS; } @@ -210,20 +248,18 @@ void* get_option(parser_t *parser, char *cli_arg) { * EOPT_ARG_NO_MATCH : Not matched */ int is_arg(char *cli_arg, arg_t *arg) { - // Number of single or double dash at the begining of a CLI - // argument - int ndash = 0; - if (cli_arg[0] == '-') ndash++; - if (cli_arg[1] == '-') ndash++; - - int arglen = strlen(cli_arg + ndash); + int arglen = strlen(cli_arg); int smatch = -1; int lmatch = -1; if (arg->opt->args != NULL) { - smatch = strncmp(cli_arg + ndash, arg->opt->args + 1, arglen); + if (strlen(arg->opt->args) == arglen) { + smatch = strncmp(cli_arg, arg->opt->args, arglen); + } } if (arg->opt->argl != NULL) { - lmatch = strncmp(cli_arg + ndash, arg->opt->argl + 2, arglen); + if (strlen(arg->opt->argl) == arglen) { + lmatch = strncmp(cli_arg, arg->opt->argl, arglen); + } } if ((smatch == 0) || (lmatch == 0)) return OPT_SUCCESS; return EOPT_ARG_NO_MATCH; diff --git a/opt/opt.h b/opt/opt.h index 6c57a41..76c333d 100644 --- a/opt/opt.h +++ b/opt/opt.h @@ -86,6 +86,14 @@ typedef struct cli_option { */ cli_option_action_t action; + /** + * @brief Indicates if an argument is required + * + * Its default value would be '0'. When set to one, + * the CLI parser should make sure that the argument is provided. + */ + unsigned char required; + /** * @brief Callbacl function to call when the argument is received * diff --git a/ti/ethernet/src/mmwl_port_ethernet.c b/ti/ethernet/src/mmwl_port_ethernet.c index 2e4e5da..842c08e 100644 --- a/ti/ethernet/src/mmwl_port_ethernet.c +++ b/ti/ethernet/src/mmwl_port_ethernet.c @@ -76,7 +76,7 @@ NetworkRadarDeviceMap_param gDeviceMapParams; NetworkTDA_Obj gNetworkTDA_obj; Network_SockObj gNetwork_SockObj; pthread_mutex_t gNetwork_Write_cs; - + uint32_t TDA_HostIntrThreadLoop[TDA_NUM_CONNECTED_DEVICES_MAX]; uint32_t TDA_HostIntrExitThread = 0; uint32_t TDA_NumOfRunningSPIThreads = 0; @@ -370,16 +370,15 @@ STATUS Radar_processData(Radar_EthDataPacketPrms *pDataPacket_ptr, uint32_t prmS return status; } -/** @fn STATUS ethernetConnect(unsigned char *ipAddr, uint32_t configPort, uint32_t deviceMap) +/** @fn STATUS ethernetConnect(unsigned char *ipAddr, uint32_t configPort) * * @brief Configures the Ethernet connection and the port creation * @param[in] ipAddr - pointer to the IP Address of the TDA * @param[in] configPort - configuration port -* @param[in] deviceMap - devices to be enabled by the TDA * * @return int Success - 0, Failure - Error Code */ -STATUS ethernetConnect(unsigned char *ipAddr, uint32_t configPort, uint32_t deviceMap) { +STATUS ethernetConnect(unsigned char *ipAddr, uint32_t configPort) { int32_t status = SYSTEM_LINK_STATUS_SOK; // Initializing Network parameters @@ -392,11 +391,11 @@ STATUS ethernetConnect(unsigned char *ipAddr, uint32_t configPort, uint32_t devi strncpy(gNetworkTDA_obj.ipAddr, ipAddr, strlen(ipAddr)); - //Initializing sockets - Network_init(); - //Connecting to the server - status = ConnectToServer(); + DEBUG_PRINT("# INFO: Network: Connecting to the server %s:%d ...\n", \ + gNetworkTDA_obj.ipAddr, gNetworkTDA_obj.serverPort); + + status = Network_connect(&gNetwork_SockObj, gNetworkTDA_obj.ipAddr, gNetworkTDA_obj.serverPort); if (status != SYSTEM_LINK_STATUS_SOK) { DEBUG_PRINT("# ERROR: Connecting to the server failed\n"); return SYSTEM_LINK_STATUS_EFAIL; @@ -462,38 +461,6 @@ STATUS ethernetConnect(unsigned char *ipAddr, uint32_t configPort, uint32_t devi } } - //Send the devices to be enabled for configuration and capture - status = ConfigureDeviceMap(deviceMap); - if (status != SYSTEM_LINK_STATUS_SOK) { - DEBUG_PRINT("# ERROR: Configure DeviceMap command failed\n"); - return SYSTEM_LINK_STATUS_EFAIL; - } - - Sleep(50); - - //Initialize the GPIO and other peripherals - pDataPacket[4].ackType = ACK_ON_PROCESS; - pDataPacket[4].devSelection = 1; - status = Radar_formEthDataPacket(&pDataPacket[4], &pDevCtrlPrms[4], - CAPTURE_CONFIG_CONNECT, DATA_HEADER_LENGTH, - NULL); - if (status != SYSTEM_LINK_STATUS_SOK) { - DEBUG_PRINT("# ERROR: Ethernet packet formation failed\n"); - return SYSTEM_LINK_STATUS_EFAIL; - } - - /* Create data buffer and print it into file */ - char tempBuff[2048] = { 0 }; - int offset = 0; - for (unsigned int i = 0; i < pDevCtrlPrms[4].respParamSize; i++) { - int j = 0; - j = sprintf(&tempBuff[offset], "0x%02X ", pDevCtrlPrms[4].respParam[i]); - offset = offset + j; - } - sprintf(&tempBuff[offset], "\r\n"); - DEBUG_PRINT("[GN]%s", tempBuff); - - handleDevCtrl((uint8_t*)&pDevCtrlPrms[4].respParam, pDevCtrlPrms[4].respParamSize); return status; } @@ -506,30 +473,6 @@ STATUS ethernetConnect(unsigned char *ipAddr, uint32_t configPort, uint32_t devi */ STATUS ethernetDisconnect() { int32_t status = SYSTEM_LINK_STATUS_SOK; - - //Deinitialize the GPIO and other peripherals - pDataPacket[4].ackType = ACK_ON_RECEIVE; - pDataPacket[4].devSelection = 1; - status = Radar_formEthDataPacket(&pDataPacket[4], &pDevCtrlPrms[4], - CAPTURE_CONFIG_DISCONNECT, DATA_HEADER_LENGTH, - NULL); - if (status != SYSTEM_LINK_STATUS_SOK) { - DEBUG_PRINT("# ERROR: Ethernet packet formation failed\n"); - return SYSTEM_LINK_STATUS_EFAIL; - } - - /* Create data buffer and print it into file */ - char tempBuff[2048] = { 0 }; - int offset = 0; - for (unsigned int i = 0; i < pDevCtrlPrms[4].respParamSize; i++) { - int j = 0; - j = sprintf(&tempBuff[offset], "0x%02X ", pDevCtrlPrms[4].respParam[i]); - offset = offset + j; - } - sprintf(&tempBuff[offset], "\r\n"); - DEBUG_PRINT("[GN]%s", tempBuff); - - handleDevCtrl((uint8_t*)&pDevCtrlPrms[4].respParam, pDevCtrlPrms[4].respParamSize); // Send the stop trace command to close the trace file status = stopTrace(); @@ -538,12 +481,12 @@ STATUS ethernetDisconnect() { return SYSTEM_LINK_STATUS_EFAIL; } - Sleep(1000); + Sleep(100); // Disable the Rx thread TDA_NetworkThreadRunning = 0; - Sleep(1000); + Sleep(100); /* Close the socket */ status = CloseConnection(); @@ -551,13 +494,9 @@ STATUS ethernetDisconnect() { return SYSTEM_LINK_STATUS_EFAIL; } - /* Terminates socket operations for all threads */ - status = Network_deInit(); - /* Close the file handle for trace */ CloseTraceFile(); - // DeleteCriticalSection(&gNetwork_Write_cs); pthread_mutex_destroy(&gNetwork_Write_cs); return status; } @@ -659,6 +598,79 @@ STATUS ConfigureDeviceMap(uint32_t deviceMap) { } +/** + * @fn STATUS ConfigurePeripherals() + * + * @brief Initialize GPIO and other peripherals + * + * @return STATUS + */ +STATUS ConfigurePeripherals() { + int32_t status = SYSTEM_LINK_STATUS_SOK; + + //Initialize the GPIO and other peripherals + pDataPacket[4].ackType = ACK_ON_PROCESS; + pDataPacket[4].devSelection = 1; + status = Radar_formEthDataPacket(&pDataPacket[4], &pDevCtrlPrms[4], + CAPTURE_CONFIG_CONNECT, DATA_HEADER_LENGTH, + NULL); + if (status != SYSTEM_LINK_STATUS_SOK) { + DEBUG_PRINT("# ERROR: Ethernet packet formation failed\n"); + return SYSTEM_LINK_STATUS_EFAIL; + } + + /* Create data buffer and print it into file */ + char tempBuff[2048] = { 0 }; + int offset = 0; + for (unsigned int i = 0; i < pDevCtrlPrms[4].respParamSize; i++) { + int j = 0; + j = sprintf(&tempBuff[offset], "0x%02X ", pDevCtrlPrms[4].respParam[i]); + offset = offset + j; + } + sprintf(&tempBuff[offset], "\r\n"); + DEBUG_PRINT("[GN]%s", tempBuff); + + handleDevCtrl((uint8_t*)&pDevCtrlPrms[4].respParam, pDevCtrlPrms[4].respParamSize); + return status; +} + +/** + * @fn STATUS ResetPeripherals() + * + * @brief De-initialize GPIO and other peripherals + * + * @return STATUS + */ +STATUS ResetPeripherals() { + int32_t status = SYSTEM_LINK_STATUS_SOK; + + //Deinitialize the GPIO and other peripherals + pDataPacket[4].ackType = ACK_ON_RECEIVE; + pDataPacket[4].devSelection = 1; + status = Radar_formEthDataPacket(&pDataPacket[4], &pDevCtrlPrms[4], + CAPTURE_CONFIG_DISCONNECT, DATA_HEADER_LENGTH, + NULL); + if (status != SYSTEM_LINK_STATUS_SOK) { + DEBUG_PRINT("# ERROR: Ethernet packet formation failed\n"); + return SYSTEM_LINK_STATUS_EFAIL; + } + + /* Create data buffer and print it into file */ + char tempBuff[2048] = { 0 }; + int offset = 0; + for (unsigned int i = 0; i < pDevCtrlPrms[4].respParamSize; i++) { + int j = 0; + j = sprintf(&tempBuff[offset], "0x%02X ", pDevCtrlPrms[4].respParam[i]); + offset = offset + j; + } + sprintf(&tempBuff[offset], "\r\n"); + DEBUG_PRINT("[GN]%s", tempBuff); + + handleDevCtrl((uint8_t*)&pDevCtrlPrms[4].respParam, pDevCtrlPrms[4].respParamSize); + return status; +} + + /** @fn STATUS TDACreateApplication() * * @brief Notify the TDA to create the capture application diff --git a/ti/ethernet/src/mmwl_port_ethernet.h b/ti/ethernet/src/mmwl_port_ethernet.h index ad6050d..0a216ac 100644 --- a/ti/ethernet/src/mmwl_port_ethernet.h +++ b/ti/ethernet/src/mmwl_port_ethernet.h @@ -667,8 +667,7 @@ STATUS Radar_processData(Radar_EthDataPacketPrms *pDataPacket_ptr, /********************** Capture Card Configuration API's *********************/ EXPORT STATUS ethernetConnect(unsigned char *ipAddr, - uint32_t configPort, - uint32_t deviceMap); + uint32_t configPort); EXPORT STATUS ethernetDisconnect(); @@ -676,6 +675,10 @@ EXPORT STATUS IsConnected(); EXPORT STATUS ConfigureDeviceMap(uint32_t deviceMap); +EXPORT STATUS ConfigurePeripherals(); + +EXPORT STATUS ResetPeripherals(); + EXPORT STATUS TDACreateApplication(); EXPORT STATUS readHWVersion(); diff --git a/ti/mmwave/mmwave.c b/ti/mmwave/mmwave.c index f89ca1c..37204e0 100644 --- a/ti/mmwave/mmwave.c +++ b/ti/mmwave/mmwave.c @@ -2460,7 +2460,7 @@ int MMWL_DeArmingTDA() { /** * @brief * - * @param deviceMap + * @param deviceMap All cascaded device map * @return int */ int MMWL_DeviceDeInit(unsigned int deviceMap) { @@ -2483,15 +2483,41 @@ int MMWL_DeviceDeInit(unsigned int deviceMap) { } +/** + * @brief Configure the devices to enable and their pheripherals + * + * @param deviceMap All cascaded device map + * @return int + */ +int MMWL_ConfigureDeviveMap(unsigned char deviceMap) { + uint32_t status = RL_RET_CODE_OK; + + //Send the devices to be enabled for configuration and capture + status = ConfigureDeviceMap(deviceMap); + if (status != SYSTEM_LINK_STATUS_SOK) { + DEBUG_PRINT("# ERROR: Configure DeviceMap command failed\n"); + return SYSTEM_LINK_STATUS_EFAIL; + } + + msleep(20); + status = ConfigurePeripherals(); + if (status != SYSTEM_LINK_STATUS_SOK) { + DEBUG_PRINT("# ERROR: Configure Peripherals command failed\n"); + return SYSTEM_LINK_STATUS_EFAIL; + } + return status; +} + + + /** * @brief Connect to ethernet and init TDA board * * @param ipAddr IP Address of the TDA board (default: 192.168.33.30) * @param port Port number to communication with the TDA (default: 5001) - * @param deviceMap All cascaded device map * @return int Initialization status */ -int MMWL_TDAInit(unsigned char *ipAddr, unsigned int port, uint8_t deviceMap) { +int MMWL_TDAInit(unsigned char *ipAddr, unsigned int port) { int retVal = RL_RET_CODE_OK; int timeOutCnt = 0; @@ -2510,7 +2536,7 @@ int MMWL_TDAInit(unsigned char *ipAddr, unsigned int port, uint8_t deviceMap) { mmwl_bTDA_CaptureCardConnect = 0U; /* Connect to the TDA Capture card */ - retVal = ethernetConnect(ipAddr, port, deviceMap); + retVal = ethernetConnect(ipAddr, port); if (retVal != RL_RET_CODE_OK) { DEBUG_PRINT( "ERROR: Connecting to TDA failed with error %d. Check whether the capture card is connected to the network! \n\n", @@ -2541,6 +2567,23 @@ int MMWL_TDAInit(unsigned char *ipAddr, unsigned int port, uint8_t deviceMap) { } +/** + * @brief Teardown trace logs and close ethernet connection + * + * @return int + */ +int MMWL_TDADeInit() { + int retVal = RL_RET_CODE_OK; + /* Disconnect from the TDA Capture card */ + retVal = ethernetDisconnect(); + if (retVal != RL_RET_CODE_OK) { + DEBUG_PRINT("ERROR: Failed to disconnect from TDA Board with error %d \n\n", retVal); + return -1; + } + return retVal; +} + + /** * @brief Assign device map * diff --git a/ti/mmwave/mmwave.h b/ti/mmwave/mmwave.h index fd56762..7b8de2a 100644 --- a/ti/mmwave/mmwave.h +++ b/ti/mmwave/mmwave.h @@ -295,7 +295,7 @@ int MMWL_DevicePowerUp(unsigned char deviceMap, uint32_t rlClientCbsTimeout, uin int MMWL_powerOnMaster(unsigned char deviceMap, uint32_t rlClientCbsTimeout); /** Connect to ethernet and init TDA */ -int MMWL_TDAInit(unsigned char *ipAddr, unsigned int port, uint8_t deviceMap); +int MMWL_TDAInit(unsigned char *ipAddr, unsigned int port); /** Setup the TDA for recording */ int MMWL_ArmingTDA(rlTdaArmCfg_t tdaArmCfgArgs); From 2e4ecde9fd305c85816b5f26553b8239c36979dd Mon Sep 17 00:00:00 2001 From: "AMOUSSOU Z. Kenneth" Date: Mon, 12 Jun 2023 22:37:28 +0200 Subject: [PATCH 2/3] fix: Ack check after device configuration --- ti/mmwave/mmwave.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/ti/mmwave/mmwave.c b/ti/mmwave/mmwave.c index 37204e0..4732906 100644 --- a/ti/mmwave/mmwave.c +++ b/ti/mmwave/mmwave.c @@ -2491,6 +2491,7 @@ int MMWL_DeviceDeInit(unsigned int deviceMap) { */ int MMWL_ConfigureDeviveMap(unsigned char deviceMap) { uint32_t status = RL_RET_CODE_OK; + mmwl_bTDA_CaptureCardConnect = 0U; //Send the devices to be enabled for configuration and capture status = ConfigureDeviceMap(deviceMap); @@ -2505,6 +2506,22 @@ int MMWL_ConfigureDeviveMap(unsigned char deviceMap) { DEBUG_PRINT("# ERROR: Configure Peripherals command failed\n"); return SYSTEM_LINK_STATUS_EFAIL; } + + while (1) { + if (mmwl_bTDA_CaptureCardConnect == 0U) { + msleep(1); /*Sleep 1 msec*/ + timeOutCnt++; + if (timeOutCnt > MMWL_API_TDA_TIMEOUT) { + DEBUG_PRINT("ERROR: No Acknowlegment received from the capture card! \n\n"); + retVal = RL_RET_CODE_RESP_TIMEOUT; + return retVal; + } + } + else { + break; + } + } + return status; } @@ -2534,7 +2551,6 @@ int MMWL_TDAInit(unsigned char *ipAddr, unsigned int port) { DEBUG_PRINT("INFO: Registered Async event handler with TDA \n\n"); } - mmwl_bTDA_CaptureCardConnect = 0U; /* Connect to the TDA Capture card */ retVal = ethernetConnect(ipAddr, port); if (retVal != RL_RET_CODE_OK) { @@ -2543,23 +2559,7 @@ int MMWL_TDAInit(unsigned char *ipAddr, unsigned int port) { retVal ); return -1; - } - while (1) { - if (mmwl_bTDA_CaptureCardConnect == 0U) { - msleep(1); /*Sleep 1 msec*/ - timeOutCnt++; - if (timeOutCnt > MMWL_API_TDA_TIMEOUT) { - DEBUG_PRINT("ERROR: No Acknowlegment received from the capture card! \n\n"); - retVal = RL_RET_CODE_RESP_TIMEOUT; - return retVal; - } - } - else { - break; - } - } - - if (retVal == RL_RET_CODE_OK) { + } else { DEBUG_PRINT("INFO: Connection to TDA successful! \n\n"); } From 4c64e94ef3b1c5116a370889f7873b98934ecbc9 Mon Sep 17 00:00:00 2001 From: "AMOUSSOU Z. Kenneth" Date: Sat, 2 Sep 2023 19:32:28 +0200 Subject: [PATCH 3/3] fix: Perform frame configuration during recording --- README.md | 8 +++--- mimo.c | 61 ++++++++++++++++++++++++++-------------------- ti/mmwave/mmwave.c | 29 +++++----------------- 3 files changed, 44 insertions(+), 54 deletions(-) diff --git a/README.md b/README.md index 995a247..f0e183b 100644 --- a/README.md +++ b/README.md @@ -125,15 +125,15 @@ It's possible to define custom configurations suitable for a given recording set with TOML config files. Some examples of config files are present in the `config` folder of this repository. -With a config file, one can use the command below: +With a config file, one can use the commands below: ```bash mmwave configure -f -mmwave record --time +mmwave record -f --time # Example mmwave configure -f config/short-range-cfg.toml -mmwave record --time 2 +mmwave record -f config/short-range-cfg.toml --time 2 ``` ### Check and copy recorded data @@ -215,7 +215,7 @@ modified. Any update to those can be directly obtained from TI or by copying the folder of `mmwave studio` and `mmwave dfp`. The folders `ti/ethernet` and `ti/mmwave` are based on examples source files provided by -TI. Since the original sources were only compatible with Windows OS, these have been modified +TI. Since the initial sources were only compatible with Windows OS, these have been modified to operate on Linux OS. One can update these modules to extend the capabilities of this driver. - The folder `opt` holds the source handling the CLI option parsing diff --git a/mimo.c b/mimo.c index 0c9dcb6..dc1307d 100644 --- a/mimo.c +++ b/mimo.c @@ -421,32 +421,6 @@ uint32_t configure (devConfig_t config) { "[ALL] Chirp configuration successful!", "[ALL] Chirp configuration failed!", config.deviceMap, TRUE); - // Master frame config. - status += MMWL_frameConfig( - config.masterMap, - config.frameCfg, - config.channelCfg, - config.adcOutCfg, - config.datapathCfg, - config.profileCfg - ); - check(status, - "[MASTER] Frame configuration completed!", - "[MASTER] Frame configuration failed!", config.masterMap, TRUE); - - // Slaves frame config - status += MMWL_frameConfig( - config.slavesMap, - config.frameCfg, - config.channelCfg, - config.adcOutCfg, - config.datapathCfg, - config.profileCfg - ); - check(status, - "[SLAVE] Frame configuration completed!", - "[SLAVE] Frame configuration failed!", config.slavesMap, TRUE); - check(status, "[MIMO] Configuration completed!\n", "[MIMO] Configuration completed with error!", config.deviceMap, TRUE); @@ -684,7 +658,7 @@ int main (int argc, char *argv[]) { "[MMWCAS-DSP] Couldn't connect to TDA board!\n", 32, TRUE); if ((unsigned char *)get_option(&parser, "configure") != NULL) { - // Configure TDA board + // Configure Device Map and Initialize TDA peripherals status = MMWL_ConfigureDeviveMap(config.deviceMap); check(status, "[MMWCAS-DSP] TDA Initialized!", @@ -696,6 +670,39 @@ int main (int argc, char *argv[]) { } else if ((unsigned char *)get_option(&parser, "record") != NULL) { + /** + * NOTE: Frame configurations define the application width and height that is + * needed to arm the TDA. Hence, these are done during the record command. + * + * When using a custom configuration file, it should also be provided in parameter + * when recording. + */ + // Master frame config. + status += MMWL_frameConfig( + config.masterMap, + config.frameCfg, + config.channelCfg, + config.adcOutCfg, + config.datapathCfg, + config.profileCfg + ); + check(status, + "[MASTER] Frame configuration completed!", + "[MASTER] Frame configuration failed!", config.masterMap, TRUE); + + // Slaves frame config + status += MMWL_frameConfig( + config.slavesMap, + config.frameCfg, + config.channelCfg, + config.adcOutCfg, + config.datapathCfg, + config.profileCfg + ); + check(status, + "[SLAVE] Frame configuration completed!", + "[SLAVE] Frame configuration failed!", config.slavesMap, TRUE); + // Arm TDA status = MMWL_ArmingTDA(tdaCfg); check(status, diff --git a/ti/mmwave/mmwave.c b/ti/mmwave/mmwave.c index 4732906..ae20fa6 100644 --- a/ti/mmwave/mmwave.c +++ b/ti/mmwave/mmwave.c @@ -1477,6 +1477,9 @@ int MMWL_chirpConfig(unsigned char deviceMap, rlChirpCfg_t chirpCfgArgs) { * * @brief Frame configuration API. * +* Compute the TDA application width and height. This function must be called +* before calling `MMWL_ArmingTDA`. +* * @param[in] deviceMap - Devic Index * @param[in] frameCfgArgs - Frame config * @param[in] rfChanCfgArgs - Channel config @@ -2163,24 +2166,6 @@ int MMWL_ArmingTDA(rlTdaArmCfg_t tdaArmCfgArgs) { int retVal = RL_RET_CODE_OK; int timeOutCnt = 0U; - /* Set width and height for all devices*/ - /* Master */ - /* - retVal = setWidthAndHeight(1, mmwl_TDA_width[0], mmwl_TDA_height[0]); - if (retVal != RL_RET_CODE_OK) { - DEBUG_PRINT( - "ERROR: Device map 1 : Setting width = %u and height = %u failed with error code %d \n\n", - mmwl_TDA_width[0], mmwl_TDA_height[0], retVal - ); - return -1; - } - else { - DEBUG_PRINT( - "INFO: Device map 1 : Setting width = %u and height = %u successful\n\n", - mmwl_TDA_width[0], mmwl_TDA_height[0] - ); - } - */ for (int i = 0; i < 4; i++) { retVal = setWidthAndHeight(1 << i, mmwl_TDA_width[i], mmwl_TDA_height[i]); if (retVal != RL_RET_CODE_OK) { @@ -2198,8 +2183,6 @@ int MMWL_ArmingTDA(rlTdaArmCfg_t tdaArmCfgArgs) { } } - - mmwl_bTDA_FramePeriodicityACK = 0U; /* Send frame periodicity for syncing the data being received at VIP ports */ retVal = sendFramePeriodicitySync(tdaArmCfgArgs.framePeriodicity); @@ -2491,6 +2474,7 @@ int MMWL_DeviceDeInit(unsigned int deviceMap) { */ int MMWL_ConfigureDeviveMap(unsigned char deviceMap) { uint32_t status = RL_RET_CODE_OK; + uint32_t timeOutCnt = 0; mmwl_bTDA_CaptureCardConnect = 0U; //Send the devices to be enabled for configuration and capture @@ -2513,8 +2497,8 @@ int MMWL_ConfigureDeviveMap(unsigned char deviceMap) { timeOutCnt++; if (timeOutCnt > MMWL_API_TDA_TIMEOUT) { DEBUG_PRINT("ERROR: No Acknowlegment received from the capture card! \n\n"); - retVal = RL_RET_CODE_RESP_TIMEOUT; - return retVal; + status = RL_RET_CODE_RESP_TIMEOUT; + return status; } } else { @@ -2526,7 +2510,6 @@ int MMWL_ConfigureDeviveMap(unsigned char deviceMap) { } - /** * @brief Connect to ethernet and init TDA board *