From 90cd2273f17c4912cfae19006f9f25e285eac613 Mon Sep 17 00:00:00 2001 From: ggw Date: Tue, 5 May 2026 14:09:15 -0500 Subject: [PATCH] regular backup --- code/l452_code/Core/Inc/buff.hpp | 18 +- code/l452_code/Core/Inc/datadescriptor.hpp | 2 +- code/l452_code/Core/Inc/stm32l4xx_it.h | 2 + code/l452_code/Core/Src/ads131.cpp | 20 +- code/l452_code/Core/Src/datadescriptor.cpp | 50 ++-- code/l452_code/Core/Src/dma.c | 7 + code/l452_code/Core/Src/main.cpp | 112 +++++--- code/l452_code/Core/Src/sdmmc.c | 41 +++ code/l452_code/Core/Src/stm32l4xx_it.c | 30 ++ code/l452_code/FATFS/Target/sd_diskio.c | 314 +++++++++++++++++++-- code/l452_code/FATFS/Target/sd_diskio.h | 2 +- code/l452_code/Makefile | 2 +- code/l452_code/descriptor_generator.py | 12 +- code/l452_code/l452_code.ioc | 26 +- code/l452_code/packet_parser_ble.py | 155 ++++++++++ code/l452_code/packet_parser_serial.py | 138 +++++++++ 16 files changed, 835 insertions(+), 96 deletions(-) create mode 100644 code/l452_code/packet_parser_ble.py create mode 100644 code/l452_code/packet_parser_serial.py diff --git a/code/l452_code/Core/Inc/buff.hpp b/code/l452_code/Core/Inc/buff.hpp index bfaf024..7cb421f 100644 --- a/code/l452_code/Core/Inc/buff.hpp +++ b/code/l452_code/Core/Inc/buff.hpp @@ -1,8 +1,9 @@ #pragma once -#include "packet.hpp" -#include "usbd_cdc_if.h" +#include "fatfs.h" #include "usart.h" +#include "usbd_cdc_if.h" +#include "packet.hpp" extern uint8_t databank1[1024]; extern uint8_t databank2[1024]; @@ -10,6 +11,8 @@ extern uint16_t pos; volatile extern bool usb_ready; volatile extern bool wb1mmc_ready; +volatile extern bool sd_ready; +extern FIL file; // Every time we get a reading add to the active databank if it fits, // if not we switch banks and write out the now unactive databank @@ -29,6 +32,12 @@ void write(packet_type packet) { HAL_UART_Transmit_DMA(&huart1, databank1, sizeof(databank1)); wb1mmc_ready = false; } + if (sd_ready) { + UINT bytes_written; + FRESULT res = f_write(&file, databank1, sizeof(databank1), &bytes_written); + if (res != FR_OK || bytes_written != sizeof(databank1)) {} + } + memset(databank2, 0, sizeof(databank2)); pos = sizeof(databank1); return write(packet); @@ -47,6 +56,11 @@ void write(packet_type packet) { HAL_UART_Transmit_DMA(&huart1, databank2, sizeof(databank2)); wb1mmc_ready = false; } + if (sd_ready) { + UINT bytes_written; + FRESULT res = f_write(&file, databank2, sizeof(databank2), &bytes_written); + if (res != FR_OK || bytes_written != sizeof(databank2)) {} + } memset(databank1, 0, sizeof(databank1)); pos = 0; return write(packet); diff --git a/code/l452_code/Core/Inc/datadescriptor.hpp b/code/l452_code/Core/Inc/datadescriptor.hpp index 2e67e0e..e8fd226 100644 --- a/code/l452_code/Core/Inc/datadescriptor.hpp +++ b/code/l452_code/Core/Inc/datadescriptor.hpp @@ -1,2 +1,2 @@ -void data_description(); +void data_description(bool to_usb, bool to_file); diff --git a/code/l452_code/Core/Inc/stm32l4xx_it.h b/code/l452_code/Core/Inc/stm32l4xx_it.h index a2344ce..b1faab1 100644 --- a/code/l452_code/Core/Inc/stm32l4xx_it.h +++ b/code/l452_code/Core/Inc/stm32l4xx_it.h @@ -66,6 +66,8 @@ void SPI1_IRQHandler(void); void USART1_IRQHandler(void); void SDMMC1_IRQHandler(void); void TIM6_DAC_IRQHandler(void); +void DMA2_Channel4_IRQHandler(void); +void DMA2_Channel5_IRQHandler(void); void USB_IRQHandler(void); /* USER CODE BEGIN EFP */ diff --git a/code/l452_code/Core/Src/ads131.cpp b/code/l452_code/Core/Src/ads131.cpp index 078aab3..2b8481c 100644 --- a/code/l452_code/Core/Src/ads131.cpp +++ b/code/l452_code/Core/Src/ads131.cpp @@ -20,13 +20,29 @@ void initialize_ads131(SPI_HandleTypeDef *hspi1) { HAL_GPIO_WritePin(GPIOA, ADC_CS_Pin, GPIO_PIN_SET); HAL_Delay(1); - // set OSR + // set OSR, reg 3h cmd[0] = 0b01100001; cmd[1] = 0b10000000; cmd[2] = 0x00; cmd[3] = 0b00001111; - cmd[4] = 0b00010111; // change last one to 0 to get 488Hz + cmd[4] = 0b00011111; + cmd[5] = 0x00; + + HAL_GPIO_WritePin(GPIOA, ADC_CS_Pin, GPIO_PIN_RESET); + HAL_SPI_TransmitReceive(hspi1, (uint8_t*) cmd, (uint8_t*) rx_buff, 18, HAL_MAX_DELAY); + HAL_GPIO_WritePin(GPIOA, ADC_CS_Pin, GPIO_PIN_SET); + HAL_Delay(1); + + memset(cmd, 0, 6); + + // set gain to 8, reg 4h + cmd[0] = 0b01100010; + cmd[1] = 0b00000000; + cmd[2] = 0x00; + + cmd[3] = 0b00000000; + cmd[4] = 0b00000000; cmd[5] = 0x00; HAL_GPIO_WritePin(GPIOA, ADC_CS_Pin, GPIO_PIN_RESET); diff --git a/code/l452_code/Core/Src/datadescriptor.cpp b/code/l452_code/Core/Src/datadescriptor.cpp index 30fd139..ff45a4a 100644 --- a/code/l452_code/Core/Src/datadescriptor.cpp +++ b/code/l452_code/Core/Src/datadescriptor.cpp @@ -1,47 +1,59 @@ #include "datadescriptor.hpp" #include #include +#include "fatfs.h" #include "usbd_cdc_if.h" #include "packet.hpp" -void data_description() { +extern FIL file; + +void data_description(bool to_usb, bool to_file) { char buff[200]; int cx; cx = snprintf(buff, sizeof(buff), "%s %d %d %s %d %d %s %d %d %s %d %d\n\r", "packet_rtc", typecode(), sizeof(packet_rtc), "uint32_t t", offsetof(packet_rtc, t), sizeof(uint32_t), "RTC_TimeTypeDef sTime", offsetof(packet_rtc, sTime), sizeof(RTC_TimeTypeDef), "RTC_DateTypeDef sDate", offsetof(packet_rtc, sDate), sizeof(RTC_DateTypeDef)); - CDC_Transmit_FS((uint8_t*)buff, cx); - HAL_Delay(10); + if (to_file) {unsigned int bw; f_write(&file, buff, cx, &bw);} + if (to_usb) {CDC_Transmit_FS((uint8_t*)buff, cx);} + HAL_Delay(50); cx = snprintf(buff, sizeof(buff), "%s %d %d %s %d %d %s %d %d\n\r", "packet_vbatt", typecode(), sizeof(packet_vbatt), "uint32_t t", offsetof(packet_vbatt, t), sizeof(uint32_t), "uint16_t vbatt_cnts", offsetof(packet_vbatt, vbatt_cnts), sizeof(uint16_t)); - CDC_Transmit_FS((uint8_t*)buff, cx); - HAL_Delay(10); + if (to_file) {unsigned int bw; f_write(&file, buff, cx, &bw);} + if (to_usb) {CDC_Transmit_FS((uint8_t*)buff, cx);} + HAL_Delay(50); cx = snprintf(buff, sizeof(buff), "%s %d %d %s %d %d %s %d %d\n\r", "packet_imu", typecode(), sizeof(packet_imu), "uint32_t t", offsetof(packet_imu, t), sizeof(uint32_t), "uint16_t readings_cnts[4]", offsetof(packet_imu, readings_cnts), sizeof(uint16_t)); - CDC_Transmit_FS((uint8_t*)buff, cx); - HAL_Delay(10); + if (to_file) {unsigned int bw; f_write(&file, buff, cx, &bw);} + if (to_usb) {CDC_Transmit_FS((uint8_t*)buff, cx);} + HAL_Delay(50); cx = snprintf(buff, sizeof(buff), "%s %d %d %s %d %d %s %d %d %s %d %d\n\r", "packet_ekg", typecode(), sizeof(packet_ekg), "uint32_t t", offsetof(packet_ekg, t), sizeof(uint32_t), "uint8_t index", offsetof(packet_ekg, index), sizeof(uint8_t), "int32_t readings_cnts[50]", offsetof(packet_ekg, readings_cnts), sizeof(int32_t)); - CDC_Transmit_FS((uint8_t*)buff, cx); - HAL_Delay(10); + if (to_file) {unsigned int bw; f_write(&file, buff, cx, &bw);} + if (to_usb) {CDC_Transmit_FS((uint8_t*)buff, cx);} + HAL_Delay(50); cx = snprintf(buff, sizeof(buff), "%s %d %d %s %d %d %s %d %d %s %d %d\n\r", "packet_strain", typecode(), sizeof(packet_strain), "uint32_t t", offsetof(packet_strain, t), sizeof(uint32_t), "uint8_t index", offsetof(packet_strain, index), sizeof(uint8_t), "int32_t readings_cnts[5]", offsetof(packet_strain, readings_cnts), sizeof(int32_t)); - CDC_Transmit_FS((uint8_t*)buff, cx); - HAL_Delay(10); + if (to_file) {unsigned int bw; f_write(&file, buff, cx, &bw);} + if (to_usb) {CDC_Transmit_FS((uint8_t*)buff, cx);} + HAL_Delay(50); cx = snprintf(buff, sizeof(buff), "%s %d %d %s %d %d %s %d %d %s %d %d\n\r", "packet_outsideT", typecode(), sizeof(packet_outsideT), "uint32_t t", offsetof(packet_outsideT, t), sizeof(uint32_t), "uint8_t index", offsetof(packet_outsideT, index), sizeof(uint8_t), "int32_t readings_cnts[5]", offsetof(packet_outsideT, readings_cnts), sizeof(int32_t)); - CDC_Transmit_FS((uint8_t*)buff, cx); - HAL_Delay(10); + if (to_file) {unsigned int bw; f_write(&file, buff, cx, &bw);} + if (to_usb) {CDC_Transmit_FS((uint8_t*)buff, cx);} + HAL_Delay(50); cx = snprintf(buff, sizeof(buff), "%s %d %d %s %d %d %s %d %d %s %d %d\n\r", "packet_insideT", typecode(), sizeof(packet_insideT), "uint32_t t", offsetof(packet_insideT, t), sizeof(uint32_t), "uint8_t index", offsetof(packet_insideT, index), sizeof(uint8_t), "int32_t readings_cnts[5]", offsetof(packet_insideT, readings_cnts), sizeof(int32_t)); - CDC_Transmit_FS((uint8_t*)buff, cx); - HAL_Delay(10); + if (to_file) {unsigned int bw; f_write(&file, buff, cx, &bw);} + if (to_usb) {CDC_Transmit_FS((uint8_t*)buff, cx);} + HAL_Delay(50); cx = snprintf(buff, sizeof(buff), "%s %d %d %s %d %d %s %d %d\n\r", "packet_button", typecode(), sizeof(packet_button), "uint32_t t", offsetof(packet_button, t), sizeof(uint32_t), "uint8_t button_vec", offsetof(packet_button, button_vec), sizeof(uint8_t)); - CDC_Transmit_FS((uint8_t*)buff, cx); - HAL_Delay(10); + if (to_file) {unsigned int bw; f_write(&file, buff, cx, &bw);} + if (to_usb) {CDC_Transmit_FS((uint8_t*)buff, cx);} + HAL_Delay(50); cx = snprintf(buff, sizeof(buff), "%s %d %d %s %d %d %s %d %d %s %d %d %s %d %d\n\r", "packet_spo2", typecode(), sizeof(packet_spo2), "uint32_t t", offsetof(packet_spo2, t), sizeof(uint32_t), "uint32_t green_cnts[25]", offsetof(packet_spo2, green_cnts), sizeof(uint32_t), "uint32_t red_cnts[25]", offsetof(packet_spo2, red_cnts), sizeof(uint32_t), "uint32_t ir_cnts[25]", offsetof(packet_spo2, ir_cnts), sizeof(uint32_t)); - CDC_Transmit_FS((uint8_t*)buff, cx); - HAL_Delay(10); + if (to_file) {unsigned int bw; f_write(&file, buff, cx, &bw);} + if (to_usb) {CDC_Transmit_FS((uint8_t*)buff, cx);} + HAL_Delay(50); } diff --git a/code/l452_code/Core/Src/dma.c b/code/l452_code/Core/Src/dma.c index fbd1c86..b805deb 100644 --- a/code/l452_code/Core/Src/dma.c +++ b/code/l452_code/Core/Src/dma.c @@ -41,6 +41,7 @@ void MX_DMA_Init(void) /* DMA controller clock enable */ __HAL_RCC_DMA1_CLK_ENABLE(); + __HAL_RCC_DMA2_CLK_ENABLE(); /* DMA interrupt init */ /* DMA1_Channel4_IRQn interrupt configuration */ @@ -49,6 +50,12 @@ void MX_DMA_Init(void) /* DMA1_Channel5_IRQn interrupt configuration */ HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 0, 0); HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn); + /* DMA2_Channel4_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(DMA2_Channel4_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(DMA2_Channel4_IRQn); + /* DMA2_Channel5_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(DMA2_Channel5_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(DMA2_Channel5_IRQn); } diff --git a/code/l452_code/Core/Src/main.cpp b/code/l452_code/Core/Src/main.cpp index afbea14..3a7c4c5 100644 --- a/code/l452_code/Core/Src/main.cpp +++ b/code/l452_code/Core/Src/main.cpp @@ -82,6 +82,11 @@ volatile uint16_t tim6_reloads = 0; volatile bool usb_ready = false; volatile bool wb1mmc_ready = false; volatile bool print_desc = false; +volatile bool sd_ready = false; + +FATFS fs; +FIL file; +FRESULT res; uint8_t uart_rx_data[1]; @@ -101,10 +106,18 @@ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { } } +volatile bool to_turn_on_sd = false; +volatile bool to_turn_off_sd = false; void USB_CDC_RxHandler(uint8_t* Buf, uint32_t Len) { if (memcmp(Buf, "R", Len) == 0) { usb_ready = true; } + if (memcmp(Buf, "S", Len) == 0) { + to_turn_off_sd = true; + } + if (memcmp(Buf, "T", Len) == 0) { + to_turn_on_sd = true; + } if (memcmp(Buf, "?", Len) == 0) { print_desc = true; } @@ -112,13 +125,62 @@ void USB_CDC_RxHandler(uint8_t* Buf, uint32_t Len) { void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if (uart_rx_data[0] == 'R') { - HAL_GPIO_TogglePin(GPIOB, LED1_Pin | LED2_Pin | LED3_Pin); + //HAL_GPIO_TogglePin(GPIOB, LED1_Pin | LED2_Pin | LED3_Pin); wb1mmc_ready = true; } HAL_UART_Receive_DMA(&huart1, uart_rx_data, sizeof(uart_rx_data)); } void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {} + +void turn_on_sd(void) { + to_turn_on_sd = false; + if (BSP_SD_IsDetected() != SD_PRESENT) { + CDC_Transmit_FS((uint8_t*)"SD NP\n\r", 7); + return; + } + if (sd_ready) { + CDC_Transmit_FS((uint8_t*)"SD RD\n\r", 7); + return; + } + if ((BSP_SD_IsDetected() == SD_PRESENT) && (!sd_ready)) { + CDC_Transmit_FS((uint8_t*)"HERE1\n\r", 7); + res = f_mount(&fs, "", 1); + if (res != FR_OK) { + CDC_Transmit_FS((uint8_t*)"SD NOK1\n\r", 9); + return; + } + CDC_Transmit_FS((uint8_t*)"HERE2\n\r", 7); + alignas(32) char buffer1[32]; + alignas(32) char buffer2[32]; + int cx = snprintf(buffer1, 32, "%06lu.log", TIM6->CNT); + cx = snprintf(buffer2, 32, "%s\n\r", buffer1); + CDC_Transmit_FS((uint8_t*)buffer2, cx); + res = f_open(&file, buffer1, FA_WRITE | FA_CREATE_ALWAYS); + if (res != FR_OK) { + CDC_Transmit_FS((uint8_t*)"SD NOK2\n\r", 9); + return; + } + CDC_Transmit_FS((uint8_t*)"SUCCESS\n\r", 9); + unsigned int bw; + res = f_write(&file, "HERE\n\r", 6, &bw); + cx = snprintf(buffer2, 32, "%d %d\n\r", res, bw); + CDC_Transmit_FS((uint8_t*)buffer2, cx); + //data_description(false, true); + sd_ready = true; + } +} + +void turn_off_sd(void) { + to_turn_off_sd = false; + if (sd_ready) { + f_sync(&file); + f_close(&file); + res = f_mount(NULL, "", 1); + CDC_Transmit_FS((uint8_t*)"CLS\n\r", 7); + sd_ready = false; + } +} /* USER CODE END 0 */ /** @@ -174,50 +236,22 @@ int main(void) // For some reason initializing the ads131 first breaks the lsm6dsv gyro readings initialize_lsm6dsv(&hspi1); initialize_ads131(&hspi1); - + HAL_Delay(3000); while (1) { + if (to_turn_on_sd) { + turn_on_sd(); + } + + if (to_turn_off_sd) { + turn_off_sd(); + } + continue; /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ - - // FATFS fs; - // FIL file; - // FRESULT res; - // bool fs_on = false; - - // if (BSP_SD_IsDetected() == SD_PRESENT) { - // CDC_Transmit_FS((uint8_t*) "Detected\n\r", 10); - - // res = f_mount(&fs, "", 1); - // if (res != FR_OK) { - // char buffer[32]; - // int cx; - // cx = snprintf(buffer, 32, "Err: %d\n\r", res); - // CDC_Transmit_FS((uint8_t*)buffer, cx); - // } else if (res == FR_OK) { - // CDC_Transmit_FS((uint8_t*) "Ok\n\r", 8); - // bool fs_on = true; - // // HAL_Delay(10); - // // DIR dir; - // // FILINFO fno; - // // res = f_opendir(&dir, ""); - // // if (res != FR_OK) { - - // // } else { - // // res = f_readdir(&dir, &fno); - // // if (res != FR_OK || fno.name[0] == 0) - // // } - // // f_open(&file, "") - // f_mount(NULL, "", 0); - // } - // } else { - // CDC_Transmit_FS((uint8_t*) "Not Detected\n\r", 14); - // HAL_Delay(10); - // } - if (print_desc) { - data_description(); + data_description(true, false); print_desc = false; } diff --git a/code/l452_code/Core/Src/sdmmc.c b/code/l452_code/Core/Src/sdmmc.c index 4f75708..298c068 100644 --- a/code/l452_code/Core/Src/sdmmc.c +++ b/code/l452_code/Core/Src/sdmmc.c @@ -25,6 +25,8 @@ /* USER CODE END 0 */ SD_HandleTypeDef hsd1; +DMA_HandleTypeDef hdma_sdmmc1_rx; +DMA_HandleTypeDef hdma_sdmmc1_tx; /* SDMMC1 init function */ @@ -88,6 +90,41 @@ void HAL_SD_MspInit(SD_HandleTypeDef* sdHandle) GPIO_InitStruct.Alternate = GPIO_AF12_SDMMC1; HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); + /* SDMMC1 DMA Init */ + /* SDMMC1_RX Init */ + hdma_sdmmc1_rx.Instance = DMA2_Channel4; + hdma_sdmmc1_rx.Init.Request = DMA_REQUEST_7; + hdma_sdmmc1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_sdmmc1_rx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_sdmmc1_rx.Init.MemInc = DMA_MINC_ENABLE; + hdma_sdmmc1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; + hdma_sdmmc1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; + hdma_sdmmc1_rx.Init.Mode = DMA_NORMAL; + hdma_sdmmc1_rx.Init.Priority = DMA_PRIORITY_LOW; + if (HAL_DMA_Init(&hdma_sdmmc1_rx) != HAL_OK) + { + Error_Handler(); + } + + __HAL_LINKDMA(sdHandle,hdmarx,hdma_sdmmc1_rx); + + /* SDMMC1_TX Init */ + hdma_sdmmc1_tx.Instance = DMA2_Channel5; + hdma_sdmmc1_tx.Init.Request = DMA_REQUEST_7; + hdma_sdmmc1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; + hdma_sdmmc1_tx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_sdmmc1_tx.Init.MemInc = DMA_MINC_ENABLE; + hdma_sdmmc1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; + hdma_sdmmc1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; + hdma_sdmmc1_tx.Init.Mode = DMA_NORMAL; + hdma_sdmmc1_tx.Init.Priority = DMA_PRIORITY_LOW; + if (HAL_DMA_Init(&hdma_sdmmc1_tx) != HAL_OK) + { + Error_Handler(); + } + + __HAL_LINKDMA(sdHandle,hdmatx,hdma_sdmmc1_tx); + /* SDMMC1 interrupt Init */ HAL_NVIC_SetPriority(SDMMC1_IRQn, 0, 0); HAL_NVIC_EnableIRQ(SDMMC1_IRQn); @@ -121,6 +158,10 @@ void HAL_SD_MspDeInit(SD_HandleTypeDef* sdHandle) HAL_GPIO_DeInit(GPIOD, GPIO_PIN_2); + /* SDMMC1 DMA DeInit */ + HAL_DMA_DeInit(sdHandle->hdmarx); + HAL_DMA_DeInit(sdHandle->hdmatx); + /* SDMMC1 interrupt Deinit */ HAL_NVIC_DisableIRQ(SDMMC1_IRQn); /* USER CODE BEGIN SDMMC1_MspDeInit 1 */ diff --git a/code/l452_code/Core/Src/stm32l4xx_it.c b/code/l452_code/Core/Src/stm32l4xx_it.c index 563afb2..022bbdb 100644 --- a/code/l452_code/Core/Src/stm32l4xx_it.c +++ b/code/l452_code/Core/Src/stm32l4xx_it.c @@ -58,6 +58,8 @@ extern PCD_HandleTypeDef hpcd_USB_FS; extern ADC_HandleTypeDef hadc1; extern I2C_HandleTypeDef hi2c1; +extern DMA_HandleTypeDef hdma_sdmmc1_rx; +extern DMA_HandleTypeDef hdma_sdmmc1_tx; extern SD_HandleTypeDef hsd1; extern SPI_HandleTypeDef hspi1; extern TIM_HandleTypeDef htim6; @@ -361,6 +363,34 @@ void TIM6_DAC_IRQHandler(void) /* USER CODE END TIM6_DAC_IRQn 1 */ } +/** + * @brief This function handles DMA2 channel4 global interrupt. + */ +void DMA2_Channel4_IRQHandler(void) +{ + /* USER CODE BEGIN DMA2_Channel4_IRQn 0 */ + + /* USER CODE END DMA2_Channel4_IRQn 0 */ + HAL_DMA_IRQHandler(&hdma_sdmmc1_rx); + /* USER CODE BEGIN DMA2_Channel4_IRQn 1 */ + + /* USER CODE END DMA2_Channel4_IRQn 1 */ +} + +/** + * @brief This function handles DMA2 channel5 global interrupt. + */ +void DMA2_Channel5_IRQHandler(void) +{ + /* USER CODE BEGIN DMA2_Channel5_IRQn 0 */ + + /* USER CODE END DMA2_Channel5_IRQn 0 */ + HAL_DMA_IRQHandler(&hdma_sdmmc1_tx); + /* USER CODE BEGIN DMA2_Channel5_IRQn 1 */ + + /* USER CODE END DMA2_Channel5_IRQn 1 */ +} + /** * @brief This function handles USB event interrupt through EXTI line 17. */ diff --git a/code/l452_code/FATFS/Target/sd_diskio.c b/code/l452_code/FATFS/Target/sd_diskio.c index ea23bc5..c7e538e 100644 --- a/code/l452_code/FATFS/Target/sd_diskio.c +++ b/code/l452_code/FATFS/Target/sd_diskio.c @@ -17,8 +17,8 @@ */ /* USER CODE END Header */ -/* Note: code generation based on sd_diskio_template_bspv1.c v2.1.4 - as "Use dma template" is disabled. */ +/* Note: code generation based on sd_diskio_dma_template_bspv1.c v2.1.4 + as "Use dma template" is enabled. */ /* USER CODE BEGIN firstSection */ /* can be used to modify / undefine following code or add new definitions */ @@ -28,16 +28,17 @@ #include "ff_gen_drv.h" #include "sd_diskio.h" +#include + /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ -/* use the default SD timout as defined in the platform BSP driver*/ -#if defined(SDMMC_DATATIMEOUT) -#define SD_TIMEOUT SDMMC_DATATIMEOUT -#elif defined(SD_DATATIMEOUT) -#define SD_TIMEOUT SD_DATATIMEOUT -#else + + /* + * the following Timeout is useful to give the control back to the applications + * in case of errors in either BSP_SD_ReadCpltCallback() or BSP_SD_WriteCpltCallback() + * the value by default is as defined in the BSP platform driver otherwise 30 secs + */ #define SD_TIMEOUT 30 * 1000 -#endif #define SD_DEFAULT_BLOCK_SIZE 512 @@ -51,10 +52,37 @@ /* #define DISABLE_SD_INIT */ /* USER CODE END disableSDInit */ +/* + * when using cacheable memory region, it may be needed to maintain the cache + * validity. Enable the define below to activate a cache maintenance at each + * read and write operation. + * Notice: This is applicable only for cortex M7 based platform. + */ +/* USER CODE BEGIN enableSDDmaCacheMaintenance */ +/* #define ENABLE_SD_DMA_CACHE_MAINTENANCE 1 */ +/* USER CODE END enableSDDmaCacheMaintenance */ + +/* +* Some DMA requires 4-Byte aligned address buffer to correctly read/write data, +* in FatFs some accesses aren't thus we need a 4-byte aligned scratch buffer to correctly +* transfer data +*/ +/* USER CODE BEGIN enableScratchBuffer */ +/* #define ENABLE_SCRATCH_BUFFER */ +/* USER CODE END enableScratchBuffer */ + /* Private variables ---------------------------------------------------------*/ +#if defined(ENABLE_SCRATCH_BUFFER) +#if defined (ENABLE_SD_DMA_CACHE_MAINTENANCE) +ALIGN_32BYTES(static uint8_t scratch[BLOCKSIZE]); // 32-Byte aligned for cache maintenance +#else +__ALIGN_BEGIN static uint8_t scratch[BLOCKSIZE] __ALIGN_END; +#endif +#endif /* Disk status */ static volatile DSTATUS Stat = STA_NOINIT; +static volatile UINT WriteStatus = 0, ReadStatus = 0; /* Private function prototypes -----------------------------------------------*/ static DSTATUS SD_CheckStatus(BYTE lun); DSTATUS SD_initialize (BYTE); @@ -87,6 +115,21 @@ const Diskio_drvTypeDef SD_Driver = /* Private functions ---------------------------------------------------------*/ +static int SD_CheckStatusWithTimeout(uint32_t timeout) +{ + uint32_t timer = HAL_GetTick(); + /* block until SDIO IP is ready again or a timeout occur */ + while(HAL_GetTick() - timer < timeout) + { + if (BSP_SD_GetCardState() == SD_TRANSFER_OK) + { + return 0; + } + } + + return -1; +} + static DSTATUS SD_CheckStatus(BYTE lun) { Stat = STA_NOINIT; @@ -106,7 +149,6 @@ static DSTATUS SD_CheckStatus(BYTE lun) */ DSTATUS SD_initialize(BYTE lun) { -Stat = STA_NOINIT; #if !defined(DISABLE_SD_INIT) @@ -147,18 +189,109 @@ DSTATUS SD_status(BYTE lun) DRESULT SD_read(BYTE lun, BYTE *buff, DWORD sector, UINT count) { DRESULT res = RES_ERROR; + uint32_t timeout; +#if defined(ENABLE_SCRATCH_BUFFER) + uint8_t ret; +#endif +#if (ENABLE_SD_DMA_CACHE_MAINTENANCE == 1) + uint32_t alignedAddr; +#endif - if(BSP_SD_ReadBlocks((uint32_t*)buff, - (uint32_t) (sector), - count, SD_TIMEOUT) == MSD_OK) + /* + * ensure the SDCard is ready for a new operation + */ + + if (SD_CheckStatusWithTimeout(SD_TIMEOUT) < 0) { - /* wait until the read operation is finished */ - while(BSP_SD_GetCardState()!= MSD_OK) - { - } - res = RES_OK; + return res; } +#if defined(ENABLE_SCRATCH_BUFFER) + if (!((uint32_t)buff & 0x3)) + { +#endif + if(BSP_SD_ReadBlocks_DMA((uint32_t*)buff, + (uint32_t) (sector), + count) == MSD_OK) + { + ReadStatus = 0; + /* Wait that the reading process is completed or a timeout occurs */ + timeout = HAL_GetTick(); + while((ReadStatus == 0) && ((HAL_GetTick() - timeout) < SD_TIMEOUT)) + { + } + /* in case of a timeout return error */ + if (ReadStatus == 0) + { + res = RES_ERROR; + } + else + { + ReadStatus = 0; + timeout = HAL_GetTick(); + + while((HAL_GetTick() - timeout) < SD_TIMEOUT) + { + if (BSP_SD_GetCardState() == SD_TRANSFER_OK) + { + res = RES_OK; +#if (ENABLE_SD_DMA_CACHE_MAINTENANCE == 1) + /* + the SCB_InvalidateDCache_by_Addr() requires a 32-Byte aligned address, + adjust the address and the D-Cache size to invalidate accordingly. + */ + alignedAddr = (uint32_t)buff & ~0x1F; + SCB_InvalidateDCache_by_Addr((uint32_t*)alignedAddr, count*BLOCKSIZE + ((uint32_t)buff - alignedAddr)); +#endif + break; + } + } + } + } +#if defined(ENABLE_SCRATCH_BUFFER) + } + else + { + /* Slow path, fetch each sector a part and memcpy to destination buffer */ + int i; + + for (i = 0; i < count; i++) { + ret = BSP_SD_ReadBlocks_DMA((uint32_t*)scratch, (uint32_t)sector++, 1); + if (ret == MSD_OK) { + /* wait until the read is successful or a timeout occurs */ + + timeout = HAL_GetTick(); + while((ReadStatus == 0) && ((HAL_GetTick() - timeout) < SD_TIMEOUT)) + { + } + if (ReadStatus == 0) + { + res = RES_ERROR; + break; + } + ReadStatus = 0; + +#if (ENABLE_SD_DMA_CACHE_MAINTENANCE == 1) + /* + * + * invalidate the scratch buffer before the next read to get the actual data instead of the cached one + */ + SCB_InvalidateDCache_by_Addr((uint32_t*)scratch, BLOCKSIZE); +#endif + memcpy(buff, scratch, BLOCKSIZE); + buff += BLOCKSIZE; + } + else + { + break; + } + } + + if ((i == count) && (ret == MSD_OK)) + res = RES_OK; + } +#endif + return res; } @@ -178,18 +311,107 @@ DRESULT SD_read(BYTE lun, BYTE *buff, DWORD sector, UINT count) DRESULT SD_write(BYTE lun, const BYTE *buff, DWORD sector, UINT count) { DRESULT res = RES_ERROR; + uint32_t timeout; +#if defined(ENABLE_SCRATCH_BUFFER) + uint8_t ret; + int i; +#endif - if(BSP_SD_WriteBlocks((uint32_t*)buff, - (uint32_t)(sector), - count, SD_TIMEOUT) == MSD_OK) + WriteStatus = 0; +#if (ENABLE_SD_DMA_CACHE_MAINTENANCE == 1) + uint32_t alignedAddr; +#endif + + if (SD_CheckStatusWithTimeout(SD_TIMEOUT) < 0) { - /* wait until the Write operation is finished */ - while(BSP_SD_GetCardState() != MSD_OK) - { - } - res = RES_OK; + return res; } +#if defined(ENABLE_SCRATCH_BUFFER) + if (!((uint32_t)buff & 0x3)) + { +#endif +#if (ENABLE_SD_DMA_CACHE_MAINTENANCE == 1) + + /* + the SCB_CleanDCache_by_Addr() requires a 32-Byte aligned address + adjust the address and the D-Cache size to clean accordingly. + */ + alignedAddr = (uint32_t)buff & ~0x1F; + SCB_CleanDCache_by_Addr((uint32_t*)alignedAddr, count*BLOCKSIZE + ((uint32_t)buff - alignedAddr)); +#endif + + if(BSP_SD_WriteBlocks_DMA((uint32_t*)buff, + (uint32_t)(sector), + count) == MSD_OK) + { + /* Wait that writing process is completed or a timeout occurs */ + + timeout = HAL_GetTick(); + while((WriteStatus == 0) && ((HAL_GetTick() - timeout) < SD_TIMEOUT)) + { + } + /* in case of a timeout return error */ + if (WriteStatus == 0) + { + res = RES_ERROR; + } + else + { + WriteStatus = 0; + timeout = HAL_GetTick(); + + while((HAL_GetTick() - timeout) < SD_TIMEOUT) + { + if (BSP_SD_GetCardState() == SD_TRANSFER_OK) + { + res = RES_OK; + break; + } + } + } + } +#if defined(ENABLE_SCRATCH_BUFFER) + } + else + { + /* Slow path, fetch each sector a part and memcpy to destination buffer */ +#if (ENABLE_SD_DMA_CACHE_MAINTENANCE == 1) + /* + * invalidate the scratch buffer before the next write to get the actual data instead of the cached one + */ + SCB_InvalidateDCache_by_Addr((uint32_t*)scratch, BLOCKSIZE); +#endif + + for (i = 0; i < count; i++) + { + WriteStatus = 0; + + memcpy((void *)scratch, (void *)buff, BLOCKSIZE); + buff += BLOCKSIZE; + + ret = BSP_SD_WriteBlocks_DMA((uint32_t*)scratch, (uint32_t)sector++, 1); + if (ret == MSD_OK) { + /* wait for a message from the queue or a timeout */ + timeout = HAL_GetTick(); + while((WriteStatus == 0) && ((HAL_GetTick() - timeout) < SD_TIMEOUT)) + { + } + if (WriteStatus == 0) + { + break; + } + + } + else + { + break; + } + } + if ((i == count) && (ret == MSD_OK)) + res = RES_OK; + } +#endif return res; } #endif /* _USE_WRITE == 1 */ @@ -252,6 +474,46 @@ DRESULT SD_ioctl(BYTE lun, BYTE cmd, void *buff) /* can be used to modify previous code / undefine following code / add new code */ /* USER CODE END afterIoctlSection */ +/* USER CODE BEGIN callbackSection */ +/* can be used to modify / following code or add new code */ +/* USER CODE END callbackSection */ +/** + * @brief Tx Transfer completed callbacks + * @param hsd: SD handle + * @retval None + */ +void BSP_SD_WriteCpltCallback(void) +{ + + WriteStatus = 1; +} + +/** + * @brief Rx Transfer completed callbacks + * @param hsd: SD handle + * @retval None + */ +void BSP_SD_ReadCpltCallback(void) +{ + ReadStatus = 1; +} + +/* USER CODE BEGIN ErrorAbortCallbacks */ +/* +============================================================================================== + depending on the SD_HAL_Driver version, either the HAL_SD_ErrorCallback() or HAL_SD_AbortCallback() + or both could be defined, activate the callbacks below when suitable and needed +============================================================================================== +void BSP_SD_AbortCallback(void) +{ +} + +void BSP_SD_ErrorCallback(void) +{ +} +*/ +/* USER CODE END ErrorAbortCallbacks */ + /* USER CODE BEGIN lastSection */ /* can be used to modify / undefine previous code or add new code */ /* USER CODE END lastSection */ diff --git a/code/l452_code/FATFS/Target/sd_diskio.h b/code/l452_code/FATFS/Target/sd_diskio.h index 4bcf8a6..66737b6 100644 --- a/code/l452_code/FATFS/Target/sd_diskio.h +++ b/code/l452_code/FATFS/Target/sd_diskio.h @@ -17,7 +17,7 @@ */ /* USER CODE END Header */ -/* Note: code generation based on sd_diskio_template.h */ +/* Note: code generation based on sd_diskio_dma_template.h */ /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __SD_DISKIO_H diff --git a/code/l452_code/Makefile b/code/l452_code/Makefile index a2187fa..2da352f 100644 --- a/code/l452_code/Makefile +++ b/code/l452_code/Makefile @@ -1,5 +1,5 @@ ########################################################################################################################## -# File automatically-generated by tool: [projectgenerator] version: [4.9.0-B19] date: [Thu Apr 30 14:57:20 CDT 2026] +# File automatically-generated by tool: [projectgenerator] version: [4.9.0-B19] date: [Tue May 05 14:07:50 CDT 2026] ########################################################################################################################## # ------------------------------------------------ diff --git a/code/l452_code/descriptor_generator.py b/code/l452_code/descriptor_generator.py index ed3eaa0..ad0872e 100644 --- a/code/l452_code/descriptor_generator.py +++ b/code/l452_code/descriptor_generator.py @@ -24,20 +24,24 @@ for class_type in data.namespace.classes: format_args += f', "{element_type} {element_name}", offsetof({class_name}, {element_name}), sizeof({element_type})' to_format_string += "\\n\\r" work_string += f' cx = snprintf(buff, sizeof(buff), "{to_format_string}", {format_args});\n' - work_string += f' CDC_Transmit_FS((uint8_t*)buff, cx);\n' - work_string += f' HAL_Delay(10);\n\n' + work_string += ' if (to_file) {unsigned int bw; f_write(&file, buff, cx, &bw);}\n' + work_string += ' if (to_usb) {CDC_Transmit_FS((uint8_t*)buff, cx);}\n' + work_string += f' HAL_Delay(50);\n\n' h_file_text = """ -void data_description(); +void data_description(bool to_usb, bool to_file); """ c_file_text = ("""#include "datadescriptor.hpp" #include #include +#include "fatfs.h" #include "usbd_cdc_if.h" #include "packet.hpp" -void data_description() { +extern FIL file; + +void data_description(bool to_usb, bool to_file) { char buff[200]; int cx; diff --git a/code/l452_code/l452_code.ioc b/code/l452_code/l452_code.ioc index 6be7c96..eab0c88 100644 --- a/code/l452_code/l452_code.ioc +++ b/code/l452_code/l452_code.ioc @@ -12,7 +12,27 @@ CAD.pinconfig= CAD.provider= Dma.Request0=USART1_RX Dma.Request1=USART1_TX -Dma.RequestsNb=2 +Dma.Request2=SDMMC1_RX +Dma.Request3=SDMMC1_TX +Dma.RequestsNb=4 +Dma.SDMMC1_RX.2.Direction=DMA_PERIPH_TO_MEMORY +Dma.SDMMC1_RX.2.Instance=DMA2_Channel4 +Dma.SDMMC1_RX.2.MemDataAlignment=DMA_MDATAALIGN_WORD +Dma.SDMMC1_RX.2.MemInc=DMA_MINC_ENABLE +Dma.SDMMC1_RX.2.Mode=DMA_NORMAL +Dma.SDMMC1_RX.2.PeriphDataAlignment=DMA_PDATAALIGN_WORD +Dma.SDMMC1_RX.2.PeriphInc=DMA_PINC_DISABLE +Dma.SDMMC1_RX.2.Priority=DMA_PRIORITY_LOW +Dma.SDMMC1_RX.2.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority +Dma.SDMMC1_TX.3.Direction=DMA_MEMORY_TO_PERIPH +Dma.SDMMC1_TX.3.Instance=DMA2_Channel5 +Dma.SDMMC1_TX.3.MemDataAlignment=DMA_MDATAALIGN_WORD +Dma.SDMMC1_TX.3.MemInc=DMA_MINC_ENABLE +Dma.SDMMC1_TX.3.Mode=DMA_NORMAL +Dma.SDMMC1_TX.3.PeriphDataAlignment=DMA_PDATAALIGN_WORD +Dma.SDMMC1_TX.3.PeriphInc=DMA_PINC_DISABLE +Dma.SDMMC1_TX.3.Priority=DMA_PRIORITY_LOW +Dma.SDMMC1_TX.3.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority Dma.USART1_RX.0.Direction=DMA_PERIPH_TO_MEMORY Dma.USART1_RX.0.Instance=DMA1_Channel5 Dma.USART1_RX.0.MemDataAlignment=DMA_MDATAALIGN_BYTE @@ -32,6 +52,8 @@ Dma.USART1_TX.1.PeriphInc=DMA_PINC_DISABLE Dma.USART1_TX.1.Priority=DMA_PRIORITY_LOW Dma.USART1_TX.1.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority FATFS.BSP.number=1 +FATFS.IPParameters=USE_DMA_CODE_SD +FATFS.USE_DMA_CODE_SD=1 FATFS0.BSP.STBoard=false FATFS0.BSP.api=Unknown FATFS0.BSP.component= @@ -114,6 +136,8 @@ NVIC.ADC1_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false NVIC.DMA1_Channel4_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true NVIC.DMA1_Channel5_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true +NVIC.DMA2_Channel4_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true +NVIC.DMA2_Channel5_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false NVIC.EXTI0_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true NVIC.EXTI3_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true diff --git a/code/l452_code/packet_parser_ble.py b/code/l452_code/packet_parser_ble.py new file mode 100644 index 0000000..9f5d771 --- /dev/null +++ b/code/l452_code/packet_parser_ble.py @@ -0,0 +1,155 @@ +import matplotlib.pyplot as plt +import numpy as np +from scipy import signal +import time + +format_string=( + b"""packet_rtc 1 28 uint32_t t 0 4 RTC_TimeTypeDef sTime 4 20 RTC_DateTypeDef sDate 24 4 +packet_vbatt 2 8 uint32_t t 0 4 uint16_t vbatt_cnts 4 2 +packet_imu 9 12 uint32_t t 0 4 uint16_t readings_cnts[4] 4 2 +packet_ekg 3 208 uint32_t t 0 4 uint8_t index 4 1 int32_t readings_cnts[50] 8 4 +packet_strain 4 28 uint32_t t 0 4 uint8_t index 4 1 int32_t readings_cnts[5] 8 4 +packet_outsideT 5 28 uint32_t t 0 4 uint8_t index 4 1 int32_t readings_cnts[5] 8 4 +packet_insideT 6 28 uint32_t t 0 4 uint8_t index 4 1 int32_t readings_cnts[5] 8 4 +packet_button 7 8 uint32_t t 0 4 uint8_t button_vec 4 1 +packet_spo2 8 304 uint32_t t 0 4 uint32_t green_cnts[25] 4 4 uint32_t red_cnts[25] 104 4 uint32_t ir_cnts[25] 204 4""") + +types = [] + +def arr_sizes(s): + if s[-1:] != b']' or b'[' not in s: + return 1 + v = int(s[s.rindex(b'[') + 1:-1]) + return v + +for line in format_string.split(b"\n"): + line = line.strip(b'\n').strip(b'\r') + if line != b'': + L = line.split(b" ") + types.append({'type_name' : L[0], + 'type_code' : int(L[1]), + 'size' : int(L[2]), + 'elements' : [] + }) + i = 3 + while i < len(L): + types[-1]['elements'].append({'type_name' : L[i], 'name' : L[i + 1], 'offset' : int(L[i + 2]), 'n_elements' : arr_sizes(L[i + 1]), 'size' : int(L[i + 3]) * arr_sizes(L[i + 1]), 'readings' : []}) + i += 4 + +import asyncio +from bleak import BleakScanner, BleakClient + +async def scan(): + return await BleakScanner.find_device_by_name("XX-STM32") + +async def connect(device): + async with BleakClient(device) as client: + value = bytes([0x01]) + #await client.write_gatt_char(TX_UUID, value, response=True) + await client.start_notify(RX_UUID, cb) + await asyncio.sleep(10000) + +RX_UUID = "00000001-8E22-4541-9D4C-21EDAE82ED19" +TX_UUID = "00000000-8E22-4541-9D4C-21EDAE82ED19" + +queue = asyncio.Queue() + +def cb(sender, data): + queue.put_nowait(data) + +def my_filter(arr): + inds = np.where(np.abs(np.diff(arr)) > 0.005)[0] + for ind in inds: + prev_ind = ind - 1 + while prev_ind in inds: + prev_ind -= 1 + next_ind = ind + 1 + while next_ind in inds: + next_ind += 1 + arr[ind] = 0.5 * arr[prev_ind] + 0.5 * arr[next_ind] + return arr + +# I think this is missing a lot of data (70Hz vs should have 250Hz) + +async def update_with_data(): + + fig, axs = plt.subplots(2) + + adcs = [] + accs = [] + gyros = [] + + cons = bytes() + start = time.time() + while(True): + data = await queue.get() + cons = cons + data + if len(cons) >= 1024: + assert(len(cons) == 1024) + + index = 0 + while (index < 1024): + packet_type = (cons[index + 1]<<8) + cons[index] + print(packet_type, index)#, len(cons)) + ind = [i for i,t in enumerate(types) if t['type_code'] == packet_type] + if len(ind) != 1: + if (index == 0): + cons = cons[128:] + else: + cons = bytes() + break + t = types[ind[0]] + d = cons[index + 2 : index + 2 + t['size']] + for e in t['elements']: + block = d[e['offset']:e['offset'] + e['size']] + element_size = int(len(block) / e['n_elements']) + if t['type_name'] == b'packet_ekg' and e['name'] == b'readings_cnts[50]': + chunked = [(2.4 / (1<<24)) * int.from_bytes(block[i:i + element_size], byteorder='little', signed = True) for i in range(0, len(block), element_size)] + adcs += chunked + if len(adcs) > 500: + dat = np.array(adcs[-2048:]) + filtered_dat = my_filter(dat) + dd = np.sort(dat) + center = 0.5 * (dd[-100] + dd[100]) + range_ = dd[-100] - dd[100] + if len(dat) == 2048: + print("Freq:", 2048 / (time.time() - start)) + axs[0].cla() + axs[1].cla() + axs[0].set_title("ADC {:3.3f}mV".format(1000 * (range_))) + + #axs[0].plot(dat, 'r.', linestyle = '--') + axs[0].plot(filtered_dat, 'k.', linestyle = '--') + axs[0].set_ylim(center - range_, center + range_) + _fft = np.log(np.abs(np.fft.fft(filtered_dat)[1:])) + axs[1].plot(250 * np.fft.fftfreq(dat.shape[-1])[1:], _fft, 'k.') + axs[1].axvline(x = 60) + plt.savefig("image.png") + + if t['type_name'] == b'packet_imu' and e['name'] == b'readings_cnts[4]': + imu_reading_type = block[0] >> 3 + imu_reading_tag_cnt = (block[0] >> 1) & 3 + reading_xyz = [int.from_bytes(block[2:4], byteorder = 'big', signed = True), + int.from_bytes(block[4:6], byteorder = 'big', signed = True), + int.from_bytes(block[6:8], byteorder = 'big', signed = True)] + if imu_reading_type == 1: + #print("{:02x} {:d}".format(imu_reading_type, imu_reading_tag_cnt)) + gyros.append([250 * e / (1<<16) for e in reading_xyz]) + elif imu_reading_type == 2: + accs.append([4 * e / (1<<16) for e in reading_xyz]) + else: + print("ERR") + index += 2 + t['size'] + +async def main(): + device = await scan() + if not device: + print("Device not found") + return + + consumer_task = asyncio.create_task(update_with_data()) + + await connect(device) + +asyncio.run(main()) + diff --git a/code/l452_code/packet_parser_serial.py b/code/l452_code/packet_parser_serial.py new file mode 100644 index 0000000..2904c4b --- /dev/null +++ b/code/l452_code/packet_parser_serial.py @@ -0,0 +1,138 @@ +import matplotlib.pyplot as plt +import numpy as np +from scipy import signal +import time +import serial + + +ser = serial.Serial(port = '/dev/ttyACM1', timeout = 10.0) +ser.reset_input_buffer() +start = time.time() +for i in range(50): + ser.write(b'R') + cons = ser.read(1024) +print(1024 * 50 / (time.time() - start)) +quit() + +format_string=( + b"""packet_rtc 1 28 uint32_t t 0 4 RTC_TimeTypeDef sTime 4 20 RTC_DateTypeDef sDate 24 4 +packet_vbatt 2 8 uint32_t t 0 4 uint16_t vbatt_cnts 4 2 +packet_imu 9 12 uint32_t t 0 4 uint16_t readings_cnts[4] 4 2 +packet_ekg 3 208 uint32_t t 0 4 uint8_t index 4 1 int32_t readings_cnts[50] 8 4 +packet_strain 4 28 uint32_t t 0 4 uint8_t index 4 1 int32_t readings_cnts[5] 8 4 +packet_outsideT 5 28 uint32_t t 0 4 uint8_t index 4 1 int32_t readings_cnts[5] 8 4 +packet_insideT 6 28 uint32_t t 0 4 uint8_t index 4 1 int32_t readings_cnts[5] 8 4 +packet_button 7 8 uint32_t t 0 4 uint8_t button_vec 4 1 +packet_spo2 8 304 uint32_t t 0 4 uint32_t green_cnts[25] 4 4 uint32_t red_cnts[25] 104 4 uint32_t ir_cnts[25] 204 4""") + +types = [] + +def arr_sizes(s): + if s[-1:] != b']' or b'[' not in s: + return 1 + v = int(s[s.rindex(b'[') + 1:-1]) + return v + +for line in format_string.split(b"\n"): + line = line.strip(b'\n').strip(b'\r') + if line != b'': + L = line.split(b" ") + types.append({'type_name' : L[0], + 'type_code' : int(L[1]), + 'size' : int(L[2]), + 'elements' : [] + }) + i = 3 + while i < len(L): + types[-1]['elements'].append({'type_name' : L[i], 'name' : L[i + 1], 'offset' : int(L[i + 2]), 'n_elements' : arr_sizes(L[i + 1]), 'size' : int(L[i + 3]) * arr_sizes(L[i + 1]), 'readings' : []}) + i += 4 + +def my_filter(arr): + inds = np.where(np.abs(np.diff(arr)) > 0.005)[0] + for ind in inds: + prev_ind = ind - 1 + while prev_ind in inds: + prev_ind -= 1 + next_ind = ind + 1 + while next_ind in inds: + next_ind += 1 + arr[ind] = 0.5 * arr[prev_ind] + 0.5 * arr[next_ind] + return arr + +def update_with_data(): + + nyquist = 0.5 * 250 + b, a = signal.butter(2, 100 / nyquist, btype='low', analog = False) + + fig, axs = plt.subplots(2) + + adcs = [] + accs = [] + gyros = [] + + ser = serial.Serial(port = '/dev/ttyACM1', timeout = 10.0) + ser.reset_input_buffer() + start = time.time() + while(True): + ser.write(b'R') + cons = ser.read(1024) + if True: + index = 0 + while (index < 1024): + #print(index, len(cons)) + packet_type = (cons[index + 1]<<8) + cons[index] + print(index, packet_type) + ind = [i for i,t in enumerate(types) if t['type_code'] == packet_type] + if len(ind) != 1: + break + t = types[ind[0]] + d = cons[index + 2 : index + 2 + t['size']] + for e in t['elements']: + block = d[e['offset']:e['offset'] + e['size']] + element_size = int(len(block) / e['n_elements']) + if t['type_name'] == b'packet_ekg' and e['name'] == b'readings_cnts[50]': + chunked = [(2.4 / (1<<24)) * int.from_bytes(block[i:i + element_size], byteorder='little', signed = True) for i in range(0, len(block), element_size)] + adcs += chunked + if len(adcs) > 500: + dat = np.array(adcs[-2048:]) + if len(adcs) > 2048: + adcs = adcs[-2048:] + #filtered_dat = my_filter(dat) + filtered_dat = dat + filtered_dat = signal.filtfilt(b, a, filtered_dat) + dd = np.sort(dat) + center = 0.5 * (dd[-100] + dd[100]) + range_ = dd[-100] - dd[100] + if len(dat) == 2048: + print("Freq:", 2048 / (time.time() - start)) + axs[0].cla() + axs[1].cla() + axs[0].set_title("ADC {:3.3f}mV".format(1000 * (range_))) + + #axs[0].plot(dat, 'r.', linestyle = '--') + axs[0].plot(filtered_dat, 'k.', linestyle = '--') + #axs[0].set_ylim(center - range_, center + range_) + _fft = np.log(np.abs(np.fft.fft(filtered_dat)[1:])) + axs[1].plot(250 * np.fft.fftfreq(dat.shape[-1])[1:], _fft, 'k.') + axs[1].axvline(x = 60) + plt.savefig("image.png") + + if t['type_name'] == b'packet_imu' and e['name'] == b'readings_cnts[4]': + imu_reading_type = block[0] >> 3 + imu_reading_tag_cnt = (block[0] >> 1) & 3 + reading_xyz = [int.from_bytes(block[2:4], byteorder = 'big', signed = True), + int.from_bytes(block[4:6], byteorder = 'big', signed = True), + int.from_bytes(block[6:8], byteorder = 'big', signed = True)] + if imu_reading_type == 1: + #print("{:02x} {:d}".format(imu_reading_type, imu_reading_tag_cnt)) + gyros.append([250 * e / (1<<16) for e in reading_xyz]) + elif imu_reading_type == 2: + accs.append([4 * e / (1<<16) for e in reading_xyz]) + else: + print("ERR") + index += 2 + t['size'] + +def main(): + update_with_data() + +main()