diff --git a/docs/ApplicationUserGuide.md b/docs/ApplicationUserGuide.md index 14516ab..6055754 100644 --- a/docs/ApplicationUserGuide.md +++ b/docs/ApplicationUserGuide.md @@ -87,7 +87,7 @@ The NDP120 is configured by identifying the firmware images that will be loaded - [Video Link (3 minutes)](http://avnet.me/RASynChangingMlModelsVideo) -There are two areas in the config.ini file to configure which NDP120 files are loaded to the NDP120 at startup. +There are two areas in the config.ini file to configure which NDP120 files/model(s) are loaded to the NDP120 at startup. 1. ```[NDP Firmware]-->Mode=x``` @@ -101,6 +101,11 @@ Each ```[Function_x]``` block defines a description, and the three required NDP1 - ```MCU``` refers to the ARM-M0 firmware that runs on the NDP120. This firmware manages the devices and data flow. - ```DSP``` refers to the dsp firmware that runs on the NDP120. This firmware does data pre-processing plus other functions. - ```DNN``` refers to the Nerual Network Parameters and ML model. This firmware implements the ML model. +- ```Event_Watch_Mode``` tells the NDP120 what data streams to watch and needs to align with the model defined in the ```DNN``` entry. + - 1 == Audio + - 2 == IMU + - 3 == Combined Audio & IMU data + ![](./assets/images/ndpConfig.jpg "") @@ -131,9 +136,10 @@ There are two different ways to redefine the decimation_inshift vaules at startu ![](./assets/images/decimationInshift02.jpg "") - ## LED control -The ```[LED]``` block allows the user to assign different RGB LED colors to each inference index. When the NDP120 detects a feature in the data the inference results are passed to the application. The application uses the index of the inference result [0 - n] to identify how to light the RGB LED on the I/O board. The comments in the config.ini file associate each index with the 5-keyword model, but this feature works with any model that's loaded. +The ```[Led Network x]``` blocks allow the user to assign different RGB LED colors to each neural network and inference index. When the NDP120 detects a feature in the data the network number and inference results are passed to the application. The application uses the +neural network number and the index of the inference result [0 - n] to identify how to light the RGB LED on the I/O board. The comments +in the config.ini file associate each index with the 5-keyword model, but this feature works with any model that's loaded. - [Video Link (3 minutes)](http://avnet.me/RASynChangeLedColorsVideo) diff --git a/docs/assets/images/ledConfig.jpg b/docs/assets/images/ledConfig.jpg index 351cdd8..9c76482 100644 Binary files a/docs/assets/images/ledConfig.jpg and b/docs/assets/images/ledConfig.jpg differ diff --git a/docs/assets/images/ndpConfig.jpg b/docs/assets/images/ndpConfig.jpg index 94feaab..352e184 100644 Binary files a/docs/assets/images/ndpConfig.jpg and b/docs/assets/images/ndpConfig.jpg differ diff --git a/ndp120/synpkg_files/alexa334_circular_v2-2024-06-24.synpkg b/ndp120/synpkg_files/alexa334_circular_v2-2024-06-24.synpkg new file mode 100644 index 0000000..7d017db Binary files /dev/null and b/ndp120/synpkg_files/alexa334_circular_v2-2024-06-24.synpkg differ diff --git a/ndp120/synpkg_files/config.ini b/ndp120/synpkg_files/config.ini index 3bfde24..460ca74 100644 --- a/ndp120/synpkg_files/config.ini +++ b/ndp120/synpkg_files/config.ini @@ -13,6 +13,7 @@ Description="5-keywords Single Mic" MCU=mcu_fw_120.synpkg DSP=dsp_firmware.synpkg DNN=menu_demo_512_general_v110_rasyn_pdm0_ext_icm.synpkg +Event_Watch_Mode=1 # 1==Audio, 2==IMU, 3==Audio&IMU #DECIMATION_INSHIFT_VALUE=10 # http://avnet.me/RASynDocsDecimationInshift # Reduce the 5-keyword model input audio gain by 6db for better performance @@ -23,6 +24,7 @@ Description="5-keywords Dual Mic" MCU=mcu_fw_120.synpkg DSP=dsp_firmware_noaec_ff.synpkg DNN=menu_demo_512_noaec_ff_v110_rasyn_pdm0_ext_icm.synpkg +Event_Watch_Mode=1 # 1==Audio, 2==IMU, 3==Audio&IMU [Function_3] Description="Circle Motion" @@ -30,12 +32,14 @@ MCU=mcu_fw_120.synpkg DSP=dsp_firmware.synpkg DNN=circular_motion_NDP120B0_icm42670_pcm_ext.synpkg Button_shift=imu # redefine the short press user button to capture the IMU data +Event_Watch_Mode=2 # 1==Audio, 2==IMU, 3==Audio&IMU [Function_4] Description="Edge Impulse Audio Model Configuration" MCU=mcu_fw_120.synpkg DSP=dsp_firmware.synpkg DNN=ei_model.synpkg +Event_Watch_Mode=1 # 1==Audio, 2==IMU, 3==Audio&IMU [Function_5] Description="Edge Impulse Motion Model Configuration" @@ -43,34 +47,66 @@ MCU=mcu_fw_120.synpkg DSP=dsp_firmware.synpkg DNN=ei_motion_model.synpkg Button_shift=imu +Event_Watch_Mode=2 # 1==Audio, 2==IMU, 3==Audio&IMU [Function_6] Description="Alexa Single Mic" MCU=mcu_fw_120.synpkg DSP=dsp_firmware.synpkg DNN=alexa_334_NDP120_B0_v11.synpkg +Event_Watch_Mode=1 # 1==Audio, 2==IMU, 3==Audio&IMU [Function_7] Description="Alexa Dual Mic" MCU=mcu_fw_120.synpkg DSP=dsp_firmware_noaec_ff.synpkg DNN=alexa_334ua__v2_ndp120b0_noaec_ff.synpkg +Event_Watch_Mode=1 # 1==Audio, 2==IMU, 3==Audio&IMU [Function_8] Description="5-keywords Single Mic and Circular Motion Fusion" MCU=mcu_fw_120.synpkg DSP=dsp_firmware.synpkg DNN=combined_imu_kws_ndp120_v3.synpkg +Event_Watch_Mode=3 # 1==Audio, 2==IMU, 3==Audio&IMU +# Reduce the 5-keyword model input audio gain by 6db for better performance +DECIMATION_INSHIFT_OFFSET=-1 + +[Function_9] +Description="Alexa Single Mic and Circular Motion Fusion" +MCU=mcu_fw_120.synpkg +DSP=dsp_firmware.synpkg +DNN=alexa334_circular_v2-2024-06-24.synpkg +Event_Watch_Mode=3 # 1==Audio, 2==IMU, 3==Audio&IMU + +[Function_10] +Description="RASynPuck Demo" +MCU=mcu_fw_120.synpkg +DSP=dsp_firmware.synpkg +DNN=RASynPuckDemoV1.synpkg +Button_shift=imu # redefine the short press user button to capture the IMU data +Event_Watch_Mode=2 # 1==Audio, 2==IMU, 3==Audio&IMU # http://avnet.me/RASynDocsLeds -[Led] +# Define which color LED the application will light for network 0 inference events +[Led Network 0] # set led response color for each voice command, choose from # "red","green","blue","yellow","cyan" and "magenta". -IDX0=yellow # ok-syntiant +IDX0=blue # ok-syntiant IDX1=cyan # up IDX2=magenta # down IDX3=red # back IDX4=green # next +# http://avnet.me/RASynDocsLeds +# Define which color LED the application will light for network 1 inference events +[Led Network 1] +# set led response color for each voice command, choose from # "red","green","blue","yellow","cyan" and "magenta". +IDX0=green +IDX1=red +IDX2=blue +IDX3=cyan +IDX4=yellow + # http://avnet.me/RASynDocsDebugPort [Debug Print] # Select debug port for application debug: diff --git a/ndp120/synpkg_files/v1.6.0MicroSdCardFiles.txt b/ndp120/synpkg_files/v1.6.1MicroSdCardFiles.txt similarity index 100% rename from ndp120/synpkg_files/v1.6.0MicroSdCardFiles.txt rename to ndp120/synpkg_files/v1.6.1MicroSdCardFiles.txt diff --git a/releaseNotes.md b/releaseNotes.md index 0b119f7..9562811 100644 --- a/releaseNotes.md +++ b/releaseNotes.md @@ -1,3 +1,24 @@ +## Version: 1.6.1 +Release type: **Feature Release** + +Date: June 25, 2024 + +## Note: The V1.6.1 release is compatible with Edge Impulse Models generated after June 10th 2024 + +### New Features +- AAGBT-166: Add config.ini support to identify how the NDP120 pulls in data for each model (audio, IMU, or audio & IMU) +- AAGBT-168: Add config.ini support to identify which LED color lights by neural network number and inference index + +### Bug Fixes +None + +### Known Issues +- AAGBT-165: When capturing IMU data converted from ADC values to accelerometer and gyro units to debug sometimes the application hangs. This appears to be a floating point printf() issue and is currently masked by reducing the floating point precision to 3 places. For full precision data, please capture converted IMU data to the microSD card file system. +- AAGBT-159: The EVK does not power up with powered by just a battery. See [troubleshooting guide](https://github.com/Avnet/RASynBoard-Out-of-Box-Demo/blob/rasynboard_v2_tiny/docs/RASynTroubleshootingGuide.md#the-rasynboard-evk-io-board--core-board-does-not-power-up-when-using-just-a-lipo-battery) for a work around +- AAGBT-159: When powering EVK from a battery the RGB LEDs are not powered. See [troubleshooting guide](https://github.com/Avnet/RASynBoard-Out-of-Box-Demo/blob/rasynboard_v2_tiny/docs/RASynTroubleshootingGuide.md#the-rasynboard-evk-io-board--core-board-does-not-power-up-when-using-just-a-lipo-battery) for a hardware work around +- AAGBT-105: When using a custom BLE name, the OOB application is not able to connect to the Python GUI demo application +- AAGBT-123: When capturing audio, or IMU data if there is an issue receiving data from the NDP120 the application hangs + ## Version: 1.6.0 Release type: **Feature Release** diff --git a/src/fat_load.c b/src/fat_load.c index fc2a5a2..1cdd8fd 100644 --- a/src/fat_load.c +++ b/src/fat_load.c @@ -33,6 +33,7 @@ struct config_ini_items config_items ={ /* default settings */ LED_EVENT_NONE }, .recording_period = 10, + .event_watch_mode = 1, .imu_conversion_enabled = 1, .imu_write_to_file = IMU_FUNC_ENABLE, .imu_print_to_terminal = IMU_FUNC_DISABLE, @@ -67,7 +68,6 @@ static uint32_t fatfs_total_sectors; static int boot_mode = BOOT_MODE_NONE; static int sdcard_slot_status = SDCARD_IN_SLOT; static int print_console_type = CONSOLE_UART; -static uint32_t event_watch_mode = WATCH_TYPE_AUDIO; //default char mode_description[64] = {0}; int mode; @@ -504,30 +504,6 @@ void write_extraction_file_end(void) } } -static void parse_event_watch_mode( void ) -{ - switch (mode) - { - case 3: - case 5: - event_watch_mode = WATCH_TYPE_MOTION; - break; - - case 8: - event_watch_mode = WATCH_TYPE_AUDIO | WATCH_TYPE_MOTION; - break; - - case 1: - case 2: - case 4: - case 6: - case 7: - default: - event_watch_mode = WATCH_TYPE_AUDIO; - break; - } -} - static uint32_t read_config_file( void ) { FRESULT res; @@ -535,6 +511,7 @@ static uint32_t read_config_file( void ) char inifile[] = "0:/config.ini"; char color[16] = {0}; char key[6] = {0}; + char net[16] = {0}; char section[24] = {0}; // mount @@ -557,7 +534,6 @@ static uint32_t read_config_file( void ) /* Read config.ini from sdcard */ mode = ini_getl("NDP Firmware", "Mode", 0, inifile); sprintf(section, "Function_%d", mode); - parse_event_watch_mode(); ini_gets(section, "Description", NULL, config_items.mode_description, sizeof(config_items.mode_description), inifile); @@ -571,37 +547,40 @@ static uint32_t read_config_file( void ) config_items.button_switch, sizeof(config_items.button_switch), inifile); config_items.dec_inshift_value = ini_getl(section, "DECIMATION_INSHIFT_VALUE", DEC_INSHIFT_VALUE_DEFAULT, inifile); config_items.dec_inshift_offset = ini_getl(section, "DECIMATION_INSHIFT_OFFSET", DEC_INSHIFT_OFFSET_DEFAULT, inifile); - - /* Get led color according according to voice command */ - for (int idx = 0; idx < LED_EVENT_NUM; idx++) - { - sprintf(key, "IDX%d", idx); - ini_gets("Led", key, "-", color, sizeof(color), inifile); - - if( strncmp(color, "red", 3) == 0) - { - config_items.led_event_color[idx] = LED_COLOR_RED; - } else if( strncmp(color, "green", 5) == 0) - { - config_items.led_event_color[idx] = LED_COLOR_GREEN; - } else if( strncmp(color, "blue", 4) == 0) - { - config_items.led_event_color[idx] = LED_COLOR_BLUE; - } else if( strncmp(color, "cyan", 4) == 0) - { - config_items.led_event_color[idx] = LED_COLOR_CYAN; - } else if( strncmp(color, "magenta", 6) == 0) - { - config_items.led_event_color[idx] = LED_COLOR_MAGENTA; - } else if( strncmp(color, "yellow", 6) == 0) - { - config_items.led_event_color[idx] = LED_COLOR_YELLOW; - } else - { - config_items.led_event_color[idx] = LED_EVENT_NONE; - } + config_items.event_watch_mode = ini_getl(section, "Event_Watch_Mode", WATCH_TYPE_AUDIO, inifile); + + /* Get led color according to network number and inference index */ + for (int network = 0; network < LED_NETWORK_NUM; network++){ + for (int idx = 0; idx < LED_EVENT_NUM; idx++) + { + sprintf(net, "LED Network %d", network); + sprintf(key, "IDX%d", idx); + ini_gets(net, key, "-", color, sizeof(color), inifile); + + if( strncmp(color, "red", 3) == 0) + { + config_items.led_event_color_data[network][idx] = LED_COLOR_RED; + } else if( strncmp(color, "green", 5) == 0) + { + config_items.led_event_color_data[network][idx] = LED_COLOR_GREEN; + } else if( strncmp(color, "blue", 4) == 0) + { + config_items.led_event_color_data[network][idx] = LED_COLOR_BLUE; + } else if( strncmp(color, "cyan", 4) == 0) + { + config_items.led_event_color_data[network][idx] = LED_COLOR_CYAN; + } else if( strncmp(color, "magenta", 6) == 0) + { + config_items.led_event_color_data[network][idx] = LED_COLOR_MAGENTA; + } else if( strncmp(color, "yellow", 6) == 0) + { + config_items.led_event_color_data[network][idx] = LED_COLOR_YELLOW; + } else + { + config_items.led_event_color_data[network][idx] = LED_EVENT_NONE; + } + } } - print_console_type = ini_getl("Debug Print", "Port", CONSOLE_UART, inifile); config_items.recording_period = ini_getl("Recording Period", "Recording_Period", 10, inifile); config_items.low_power_mode = ini_getl("Low Power Mode", "Power_Mode",DOWN_DOWN_LP_MODE, inifile); @@ -755,12 +734,7 @@ int get_print_console_type( void ) uint32_t get_event_watch_mode() { - return event_watch_mode; -} - -void set_event_watch_mode(uint32_t watch_mode) -{ - event_watch_mode = watch_mode; + return config_items.event_watch_mode; } // Returns number of seconds to record data (audio or IMU data) @@ -832,8 +806,8 @@ void printConfg(void) printf("\n Operation mode=%d selected: %s\r\n", mode, config_items.mode_description); printf(" Event Watching Mode: %s %s\r\n", - (event_watch_mode&WATCH_TYPE_AUDIO)?"Key-Word":"", - (event_watch_mode&WATCH_TYPE_MOTION)?"IMU-Motion":""); + (get_event_watch_mode()&WATCH_TYPE_AUDIO)?"Key-Word":"", + (get_event_watch_mode()&WATCH_TYPE_MOTION)?"IMU-Motion":""); // Output recording feature driven by Low Power Mode Selection if(config_items.low_power_mode == DOWN_DOWN_LP_MODE){ diff --git a/src/fat_load.h b/src/fat_load.h index fa5e879..668f013 100644 --- a/src/fat_load.h +++ b/src/fat_load.h @@ -36,6 +36,7 @@ #undef FLOATING_POINT_PRINTF_BUG #define LED_EVENT_NUM 10 +#define LED_NETWORK_NUM 2 enum FW_LOAD_TYPE { BOOT_MODE_FLASH = 0, @@ -116,7 +117,9 @@ enum WIF_CONFIG_TYPE { struct config_ini_items { /* save the settings from config.ini */ char button_switch[8]; /** [Function_x]-->Button_shift **/ - int led_event_color[LED_EVENT_NUM]; /** [Led]-->IDXn **/ + int event_watch_mode; /** [Function_x]-->event_watch_mode **/ + int led_event_color[LED_EVENT_NUM]; + int led_event_color_data[LED_NETWORK_NUM][ LED_EVENT_NUM]; /** [Led Network x]-->IDXn **/ int recording_period; /** [Recording Period]-->Recording_Period **/ int imu_write_to_file; /** [IMU data stream]-->Write_to_file **/ diff --git a/src/ndp_thread_entry.c b/src/ndp_thread_entry.c index 198f9ac..40e856e 100644 --- a/src/ndp_thread_entry.c +++ b/src/ndp_thread_entry.c @@ -14,7 +14,7 @@ #include "usb_pcdc_vcom.h" #include "iotc_thread_entry.h" -#define led_event_color(x) (config_items.led_event_color[x]) +#define led_event_color(x,y) (config_items.led_event_color_data[x][y]) #define SYNTIANT_NDP120_MAX_CLASSES 32 #define SYNTIANT_NDP120_MAX_NNETWORKS 4 #define NDP120_MCU_LABELS_MAX_LEN (0x200) @@ -195,7 +195,7 @@ void ndp_print_imu(void) ndp_core2_platform_tiny_mspi_config(); ndp_core2_platform_tiny_mspi_write(IMU_SENSOR_MSSB, 1, ®, 0); ndp_core2_platform_tiny_mspi_read(IMU_SENSOR_MSSB, 1, &imu_val, 1); - printf("attched IMU ID = 0x%02x\n", imu_val); /*id = 0x67*/ + printf("attached IMU ID = 0x%02x\n", imu_val); /*id = 0x67*/ } void ndp_info_display(void) @@ -365,7 +365,6 @@ void ndp_thread_entry(void *pvParameters) // read back info from FLASH config_data_in_flash_t flash_data = {0}; if (0 == ndp_flash_read_infos(&flash_data)){ - set_event_watch_mode (flash_data.watch_mode); memcpy(&config_items, &flash_data.cfg, sizeof(struct config_ini_items)); } @@ -426,7 +425,7 @@ void ndp_thread_entry(void *pvParameters) /* TODO: add your own code here */ while (1) { - /* Wait until NDP recognized voice keywords */ + /* Wait until NDP inference event detection */ evbits = xEventGroupWaitBits(g_ndp_event_group, EVENT_BIT_VOICE | EVENT_BIT_FLASH, pdTRUE, pdFALSE , portMAX_DELAY); @@ -458,7 +457,7 @@ void ndp_thread_entry(void *pvParameters) case 9: /* Voice: OK-Syntiant; light Amber Led */ current_stat.led = LED_EVENT_NONE; - q_event = led_event_color(ndp_class_idx); + q_event = led_event_color(ndp_nn_idx, ndp_class_idx); xQueueSend(g_led_queue, (void *)&q_event, 0U ); send_ble_update(ble_at_string[V_WAKEUP], 1000, buf, sizeof(buf)); enqueInferenceData(ndp_nn_idx, ndp_class_idx); @@ -474,7 +473,7 @@ void ndp_thread_entry(void *pvParameters) if (last_stat.led != LED_COLOR_MAGENTA) { /* first receive 'Down' keyword */ - q_event = led_event_color(ndp_class_idx); + q_event = led_event_color(ndp_nn_idx, ndp_class_idx); xQueueSend(g_led_queue, (void *)&q_event, 0U ); send_ble_update(ble_at_string[V_DOWN],1000,buf, sizeof(buf)); enqueInferenceData(ndp_nn_idx, ndp_class_idx); @@ -498,7 +497,7 @@ void ndp_thread_entry(void *pvParameters) else { /* invalid time */ - q_event = led_event_color(ndp_class_idx); + q_event = led_event_color(ndp_nn_idx, ndp_class_idx); xQueueSend(g_led_queue, (void *)&q_event, 0U ); send_ble_update(ble_at_string[V_DOWN],1000,buf, sizeof(buf)); enqueInferenceData(ndp_nn_idx, ndp_class_idx); @@ -506,7 +505,7 @@ void ndp_thread_entry(void *pvParameters) } } else{ - q_event = led_event_color(ndp_class_idx); + q_event = led_event_color(ndp_nn_idx, ndp_class_idx); xQueueSend(g_led_queue, (void *)&q_event, 0U ); send_ble_update(ble_at_string[V_DOWN],1000,buf, sizeof(buf)); enqueInferenceData(ndp_nn_idx, ndp_class_idx); diff --git a/src/version_string.h b/src/version_string.h index 2a2c3f7..9fcd67c 100644 --- a/src/version_string.h +++ b/src/version_string.h @@ -22,7 +22,7 @@ // Increment Build Version when Major and Minor versions do not change // If Major or Minor versions change, reset BUILD_VERSION to 0 -#define BUILD_VERSION "0" +#define BUILD_VERSION "1" #else #define BUILD_VERSION "Engineering Build"