Mercurial > public > ostc4
changeset 1032:33b91584d827 Puls_Integration
New CV Pulse:
The basic infrastructure for external puls measurement via Bluetooth has been added. Precondition is an OSTC with an activated central role. The OSTC will then search for a BLE device with puls measurement service. Reading data and visualization is not implemented yet.
| author | Ideenmodellierer |
|---|---|
| date | Mon, 28 Jul 2025 18:34:45 +0200 |
| parents | cd4561c33758 |
| children | 5f66e44d69f0 |
| files | Common/CPU1-F429.ld Common/Inc/configuration.h Discovery/Inc/cv_heartbeat.h Discovery/Inc/ostc.h Discovery/Inc/tStructure.h Discovery/Inc/text_multilanguage.h Discovery/Src/base.c Discovery/Src/cv_heartbeat.c Discovery/Src/ostc.c Discovery/Src/tMenuCvOption.c Discovery/Src/tMenuEdit.c Discovery/Src/tMenuEditCvOption.c Discovery/Src/text_multilanguage.c |
| diffstat | 13 files changed, 676 insertions(+), 9 deletions(-) [+] |
line wrap: on
line diff
--- a/Common/CPU1-F429.ld Mon Jul 28 18:32:23 2025 +0200 +++ b/Common/CPU1-F429.ld Mon Jul 28 18:34:45 2025 +0200 @@ -208,7 +208,7 @@ /* Define Known Address for Each Font */ /* Flash Sector 23 is protected (bootloader font + image) => use end of sector 22 */ -.lower_fonts 0x080A0000 : { +.lower_fonts 0x080AA000 : { *(.lower_fonts.image_data_*) *(.lower_fonts.*)
--- a/Common/Inc/configuration.h Mon Jul 28 18:32:23 2025 +0200 +++ b/Common/Inc/configuration.h Mon Jul 28 18:34:45 2025 +0200 @@ -96,6 +96,9 @@ /* Enable to have a faster transfer speed between bluetooth module and CPU */ #define ENABLE_FAST_COMM +/* Enable to have support of Polar HC10 heartbeat sensor active */ +#define ENABLE_PULSE_SENSOR_BT + /* Enable RTE sleep mode debugging */ /* #define ENABLE_SLEEP_DEBUG */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Discovery/Inc/cv_heartbeat.h Mon Jul 28 18:34:45 2025 +0200 @@ -0,0 +1,101 @@ +/////////////////////////////////////////////////////////////////////////////// +/// -*- coding: UTF-8 -*- +/// +/// \file Discovery/Inc/cv_heartbeat.h +/// \brief Function definitions for connecting to a Polar HC10 heartbeat sensor +/// \date 3 July 2025 + +/////////////////////////////////////////////////////////////////////////////// +/// \par Copyright (c) 2014-2015 Heinrichs Weikamp gmbh +/// +/// This program is free software: you can redistribute it and/or modify +/// it under the terms of the GNU General Public License as published by +/// the Free Software Foundation, either version 3 of the License, or +/// (at your option) any later version. +/// +/// This program is distributed in the hope that it will be useful, +/// but WITHOUT ANY WARRANTY; without even the implied warranty of +/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +/// GNU General Public License for more details. +/// +/// You should have received a copy of the GNU General Public License +/// along with this program. If not, see <http://www.gnu.org/licenses/>. +////////////////////////////////////////////////////////////////////////////// + +#ifndef INC_CV_HEARTBEAT_H_ +#define INC_CV_HEARTBEAT_H_ + +#include <stdint.h> + + +#define BLUEMOD_ADDR_SIZE (20u) /* length of address respond */ +#define BLUEMOD_RSSI_SIZE (5u) +#define BLUEMOD_NAME_SIZE (40u) + +void openEdit_Heartbeat(void); + +typedef enum +{ + NO_INDICATOR = 0, + DEVICE_INDICATOR, + CONNECTION_INDICATOR, + SERVICE_INDICATOR, + OK_INDICATOR, /* module control */ + ERROR_INDICATOR /* module control */ +} indicatior_t; + +typedef enum +{ + BT_READ_NOTHING = 0, + BT_READ_DEVICE_ADDR, + BT_READ_DEVICE_RSSI, + BT_READ_DEVICE_NAME, + BT_READ_CON_DETAILS, + BT_READ_SERV_HANDLE, + BT_READ_SERV_START, + BT_READ_SERV_END, + BT_READ_SERV_UUID +} readDataType_t; + +typedef enum + { + SENSOR_HB_OFFLINE = 0, /* Default Status no data available */ + SENSOR_HB_ENABLE_BLE, + SENSOR_HB_CHECK_CONFIG, + SENSOR_HB_DISCOVER, + SENSOR_HB_CONNECT, + SENSOR_HB_SERVICES, + SENSOR_HB_RESTART, + SENSOR_HB_DETECTION_INDICATOR, /* searching for indicators to identify data items */ + SENSOR_HB_DETECTION_RSSI, + SENSOR_HB_DETECTION_NAME, + SENSOR_HB_DETECTION_MAN, + SENSOR_HB_DETECTION_UUID, + SENSOR_HB_FOUND, /* A device providing the requested service was found */ + SENSOR_HB_CONNECTED, /* Connection to heartbeat sensor established */ + SENSOR_HB_OFFLINEMODE, /* Oflline measurement started */ + } sensorHeartbeat_State_t; + +typedef struct +{ + uint8_t address[BLUEMOD_ADDR_SIZE]; + uint8_t rssi[BLUEMOD_RSSI_SIZE]; + uint8_t name[BLUEMOD_NAME_SIZE]; +} btDdeviceData_t; + + +typedef struct +{ + uint8_t handle; + uint8_t start[6]; + uint8_t end[6]; + uint8_t uuid[50]; +} btDeviceService_t; + + + +sensorHeartbeat_State_t cv_heartbeat_getState(); +void refresh_Heartbeat(void); +void cv_heartbeat_Control(void); + +#endif /* INC_CV_HEARTBEAT_H_ */
--- a/Discovery/Inc/ostc.h Mon Jul 28 18:32:23 2025 +0200 +++ b/Discovery/Inc/ostc.h Mon Jul 28 18:34:45 2025 +0200 @@ -60,6 +60,10 @@ #define DISPLAY_VERSION_LCD (0u) #define DISPLAY_VERSION_NEW (1u) +#define CHUNK_SIZE (150u) /* the DMA will handle chunk size transfers */ +#define CHUNKS_PER_BUFFER (3u) + + /* Exported variables --------------------------------------------------------*/ extern SPI_HandleTypeDef hspiDisplay; @@ -82,6 +86,7 @@ void MX_SPI_Init(void); void MX_GPIO_Init(void); void MX_UART_Init(void); +void MX_UART_BT_Init_DMA(); uint8_t MX_UART_ButtonAdjust(uint8_t *array); void MX_SmallCPU_Reset_To_Boot(void); @@ -104,5 +109,8 @@ void SetDisplayVersion(uint8_t version); uint8_t isNewDisplay(void); +uint8_t UART_getChar(); +void UART_StartDMARx(); + #endif // OSTC_H
--- a/Discovery/Inc/tStructure.h Mon Jul 28 18:32:23 2025 +0200 +++ b/Discovery/Inc/tStructure.h Mon Jul 28 18:34:45 2025 +0200 @@ -76,6 +76,7 @@ #define StIDEBUG _MB(0,7,0,0,0) #define StISENINFO _MB(0,8,0,0,0) #define StIPREDIVE _MB(0,9,0,0,0) +#define StILOGGER _MB(0,10,0,0,0) #define StI_GoToLogbook _MB(0,1,1,0,0) #define StI_GoToPlanner _MB(0,1,2,0,0) @@ -396,6 +397,8 @@ #define StMOption_Timer _MB(2,10,2,0,0) #define StMOption_Timer_Value _MB(2,10,2,1,0) +#define StMOption_Heartbeat _MB(2,10,3,0,0) + /* PAGE 11 */ #define StMPLAN _MB(2,11,0,0,0)
--- a/Discovery/Inc/text_multilanguage.h Mon Jul 28 18:32:23 2025 +0200 +++ b/Discovery/Inc/text_multilanguage.h Mon Jul 28 18:34:45 2025 +0200 @@ -395,6 +395,7 @@ TXT2BYTE_TIMEZONE, TXT2BYTE_BUZZER, + TXT2BYTE_Pulse, TXT2BYTE_END, };
--- a/Discovery/Src/base.c Mon Jul 28 18:32:23 2025 +0200 +++ b/Discovery/Src/base.c Mon Jul 28 18:34:45 2025 +0200 @@ -501,6 +501,7 @@ resetToFirmwareUpdate(); tCCR_control(); + if( tComm_control() )// will stop while loop if tComm Mode started until exit from UART { createDiveSettings(); @@ -532,6 +533,8 @@ } if(DoDisplayRefresh) /* set every 100ms by timer interrupt */ { + cv_heartbeat_Control(); + DoDisplayRefresh = 0; updateSetpointStateUsed(); @@ -727,6 +730,13 @@ { SStateList status; get_globalStateList(&status); + + if((status.base != 0) && (InfoLogger_isUpdated())) + { + openInfo_Logger(); + get_globalStateList(&status); + } + switch(status.base) { case BaseHome:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Discovery/Src/cv_heartbeat.c Mon Jul 28 18:34:45 2025 +0200 @@ -0,0 +1,437 @@ +/////////////////////////////////////////////////////////////////////////////// +/// -*- coding: UTF-8 -*- +/// +/// \file Discovery/Src/cv_heartbeat.c +/// \brief providing functionality to connect OSTC to a Polar HC10 heartbeat sensor +/// \author heinrichs weikamp gmbh +/// \date 03-July-2025 +/// +/// $Id$ +/////////////////////////////////////////////////////////////////////////////// +/// \par Copyright (c) 2014-2025 Heinrichs Weikamp gmbh +/// +/// This program is free software: you can redistribute it and/or modify +/// it under the terms of the GNU General Public License as published by +/// the Free Software Foundation, either version 3 of the License, or +/// (at your option) any later version. +/// +/// This program is distributed in the hope that it will be useful, +/// but WITHOUT ANY WARRANTY; without even the implied warranty of +/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +/// GNU General Public License for more details. +/// +/// You should have received a copy of the GNU General Public License +/// along with this program. If not, see <http://www.gnu.org/licenses/>. +////////////////////////////////////////////////////////////////////////////// + +#include "cv_heartbeat.h" +#include "tMenuEdit.h" + +#include "gfx_fonts.h" +#include "tHome.h" +#include "ostc.h" +#include "tComm.h" +#include "tInfoLogger.h" + +static sensorHeartbeat_State_t heartbeatState = SENSOR_HB_OFFLINE; + +static uint8_t OnAction_Heartbeat(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); +static uint32_t startDetection_ms; + +#define MAX_BT_DEVICE 10 /* max number of device which may be handled */ +static btDdeviceData_t btDeviceList[MAX_BT_DEVICE]; +static btDeviceService_t curDeviceService[10]; +static uint8_t curServiceIndex = 0; +static uint8_t curBtIndex = 0; +static uint8_t connHandle = ' '; + +static indicatior_t checkIndicators(uint8_t* pdata) +{ +#if 0 + static uint8_t foundRSSI = 0; + static uint8_t foundNAME = 0; + static uint8_t foundMNF = 0; + static uint8_t foundUUID = 0; + static uint8_t foundOK = 0; +#endif + indicatior_t ret = NO_INDICATOR; + + if(strcmp((char*)pdata,"+UBTD:") == 0) + { + ret = DEVICE_INDICATOR; + } + else if(strcmp((char*)pdata,"+UUBTACLC:") == 0) + { + ret = CONNECTION_INDICATOR; + } + else if(strcmp((char*)pdata,"+UBTGDP:") == 0) + { + ret = SERVICE_INDICATOR; + } + + return ret; +} + +static void handleOK() +{ + switch(heartbeatState) + { + case SENSOR_HB_ENABLE_BLE: heartbeatState = SENSOR_HB_CHECK_CONFIG; + break; + case SENSOR_HB_CHECK_CONFIG: heartbeatState = SENSOR_HB_DISCOVER; + break; + case SENSOR_HB_RESTART: heartbeatState = SENSOR_HB_OFFLINE; + break; + case SENSOR_HB_DISCOVER: heartbeatState = SENSOR_HB_CONNECT; + break; + case SENSOR_HB_SERVICES: heartbeatState = SENSOR_HB_OFFLINE; + break; + default: + break; + } +} + +static void handleERROR() +{ + +} + +static uint8_t getDeviceList() +{ + static uint8_t firstDevice = 1; + static uint8_t curLine[MAX_CHAR_PER_LINE]; /* holds complete line and is used for logging */ + static uint8_t curLineIndex = 0; + static uint8_t parameter[40]; /* content of the parameter in read state */ + static uint8_t writeIndex = 0; + static uint8_t complete = 0; + + static readDataType_t readType = BT_READ_NOTHING; + + char text[40]; + uint8_t data = 0; + data = UART_getChar(); + + while((data != 0) && (complete == 0)) + { + if(curLineIndex == MAX_CHAR_PER_LINE) /* avoid overflow */ + { + InfoLogger_writeLine(curLine,curLineIndex,0); + memset(curLine,0,sizeof(curLine)); + curLineIndex = 0; + } + if((data == '\r') || (data == '\n')) + { + if(curLineIndex > 0) + { + InfoLogger_writeLine(curLine,curLineIndex,0); + if(strcmp((char*)curLine,"OK") == 0) + { + handleOK(); + } + else + { + if(strcmp((char*)curLine,"ERROR") == 0) + { + handleERROR(); + } + } + } + switch(readType) + { + case BT_READ_DEVICE_NAME: if(writeIndex < BLUEMOD_NAME_SIZE) + { + memcpy (btDeviceList[curBtIndex].name, parameter, writeIndex); + } + break; + case BT_READ_SERV_UUID: if(writeIndex < 50) + { + memcpy(curDeviceService[curServiceIndex].uuid, parameter, writeIndex); + } + curServiceIndex++; + break; + default: + break; + } + curLineIndex = 0; + writeIndex = 0; + memset(curLine,0,sizeof(curLine)); + readType = BT_READ_NOTHING; + } + else + { + if(curLineIndex < MAX_CHAR_PER_LINE) curLine[curLineIndex++] = data; + + if(data == ':') + { + switch(checkIndicators(curLine)) + { + case DEVICE_INDICATOR: readType = BT_READ_DEVICE_ADDR; + break; + case CONNECTION_INDICATOR: readType = BT_READ_CON_DETAILS; + break; + case SERVICE_INDICATOR: readType = BT_READ_SERV_HANDLE; + break; + default: + break; + } + writeIndex = 0; + memset(parameter,0,sizeof(parameter)); + } + else + { + if(data == ',') /* parameter end */ + { + switch(readType) + { + case BT_READ_DEVICE_ADDR: if(writeIndex < BLUEMOD_ADDR_SIZE-1) + { + if(firstDevice) + { + firstDevice = 0; + } + else + { + curBtIndex++; + } + parameter[writeIndex-1] = 0; /*remove 'p' from address */ + strcpy((char*)btDeviceList[curBtIndex].address, (char*)parameter); + } + readType = BT_READ_DEVICE_RSSI; + break; + case BT_READ_DEVICE_RSSI: if(writeIndex < BLUEMOD_RSSI_SIZE-1) + { + strcpy((char*)btDeviceList[curBtIndex].rssi, (char*)parameter); + } + readType = BT_READ_DEVICE_NAME; + break; + case BT_READ_DEVICE_NAME: if(writeIndex < BLUEMOD_NAME_SIZE-1) + { + memcpy(btDeviceList[curBtIndex].name, parameter, writeIndex); + } + readType = BT_READ_NOTHING; + break; + case BT_READ_CON_DETAILS: connHandle = parameter[0]; + heartbeatState = SENSOR_HB_SERVICES; + readType = BT_READ_NOTHING; + break; + case BT_READ_SERV_HANDLE: curDeviceService[curServiceIndex].handle = parameter[0]; + readType = BT_READ_SERV_START; + break; + case BT_READ_SERV_START: if(writeIndex < 6) + { + memcpy(curDeviceService[curServiceIndex].start, parameter, writeIndex); + } + readType = BT_READ_SERV_END; + break; + case BT_READ_SERV_END: if(writeIndex < 6) + { + memcpy(curDeviceService[curServiceIndex].end, parameter, writeIndex); + } + readType = BT_READ_SERV_UUID; + break; + + default: readType = BT_READ_NOTHING; + break; + } + writeIndex = 0; + memset(parameter,0 , sizeof(parameter)); + } + else + { + // if(readType != BT_READ_NOTHING) + { + parameter[writeIndex++] = data; + } + } + } + } + data = UART_getChar(); + } + return complete; +} + +sensorHeartbeat_State_t cv_heartbeat_getState() +{ + return heartbeatState; +} + +void openEdit_Heartbeat(void) +{ + SSettings *settings = settingsGetPointer(); + + char text[32]; + snprintf(text, 32, "\001%c%c", TXT_2BYTE, TXT2BYTE_Pulse); + write_topline(text); + + set_globalState(StMOption_Heartbeat); + resetMenuEdit(CLUT_MenuPageCvOption); + + snprintf(text, 32, "%c%c", TXT_2BYTE, TXT2BYTE_SensorDetect); + write_field_button(StMOption_Heartbeat, 30, 299, ME_Y_LINE1, &FontT48, text); + + write_buttonTextline(TXT2BYTE_ButtonMinus, TXT2BYTE_ButtonEnter, TXT2BYTE_ButtonPlus); + + setEvent(StMOption_Heartbeat, (uint32_t)OnAction_Heartbeat); +} + +static uint8_t OnAction_Heartbeat(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) +{ + switch(heartbeatState) + { + case SENSOR_HB_OFFLINE: + HAL_UART_AbortReceive_IT(&UartHandle); + MX_UART_BT_Init_DMA(); + UART_StartDMARx(); + heartbeatState = SENSOR_HB_ENABLE_BLE; + startDetection_ms = HAL_GetTick(); + curBtIndex = 0; + memset(btDeviceList, 0, sizeof(btDeviceList)); + break; + + default: + break; + } + return UNSPECIFIC_RETURN; +} + +void cv_heartbeat_Control(void) +{ + static uint8_t action = 0; + static uint8_t retry = 0; + static uint8_t lastState = 0; + static uint8_t devicesIndex = 0; + + + char cmd[50]; + + cmd[0] = 0; + + getDeviceList(); + + if(action == 3) + { + action = 0; + switch(heartbeatState) + { + case SENSOR_HB_ENABLE_BLE: HAL_Delay(1000); + snprintf(cmd, sizeof(cmd), "+++" ); //"AT+UBTD=2,1,5000\r\n" + InfoLogger_writeLine((uint8_t*)cmd,3,1); + HAL_UART_Transmit(&UartHandle, (uint8_t*)cmd, 3, 5000); + HAL_Delay(1000); + cmd[0] = 0; + break; + case SENSOR_HB_CHECK_CONFIG: snprintf(cmd, sizeof(cmd), "AT+UBTCFG=2\r\n" ); // AT+UBTLE? + +#if 0 + if(settingsGetPointer()->dive_mode == DIVEMODE_OC) + { + snprintf(cmd, sizeof(cmd), "AT+UBTLE=2\r\n" ); //+UBTLE=1 //"AT+UBTD=2,1,5000\r\n" + } + else + { + snprintf(cmd, sizeof(cmd), "AT+UBTLE=3\r\n" ); //+UBTLE=1 //"AT+UBTD=2,1,5000\r\n" + } +#endif + break; + case SENSOR_HB_DISCOVER: if(lastState != SENSOR_HB_DISCOVER) + { + snprintf(cmd, sizeof(cmd), "AT+UBTD=2,1\r\n" ); //+UBTLE=1 //"AT+UBTD=2,1,5000\r\n" + devicesIndex = 0; + } + + //snprintf(cmd, sizeof(cmd), "AT&W\r\n" ); // AT+UBTD=2,1\r\n "AT+UBTD=2,1,5000\r\n" + break; +#if 0 + case SENSOR_HB_RESTART: snprintf(cmd, sizeof(cmd), "AT+UBTD=2,1\r\n" ); //+UBTLE=1 //"AT+UBTD=2,1,5000\r\n" + + // snprintf(cmd, sizeof(cmd), "AT+CPWROFF\r\n" ); // AT+UBTD=2,1\r\n "AT+UBTD=2,1,5000\r\n" + break; +#endif + case SENSOR_HB_CONNECT: if(curBtIndex != devicesIndex) + { + snprintf(cmd, sizeof(cmd), "AT+UBTACLC=%s\r\n",btDeviceList[devicesIndex].address); + devicesIndex++; + } + break; + case SENSOR_HB_SERVICES: if((connHandle >= '0') && (connHandle <= '9') && (lastState != SENSOR_HB_SERVICES)) + { + snprintf(cmd, sizeof(cmd), "AT+UBTGDP=0%c\r\n",connHandle); + } + else + { + heartbeatState = SENSOR_HB_OFFLINE; + } + break; + + default: + break; + } + if(cmd[0] != 0) + { + { + InfoLogger_writeLine((uint8_t*)cmd,strlen(cmd),1); + HAL_UART_Transmit(&UartHandle, (uint8_t*)cmd, strlen(cmd), 5000); + retry++; + if(retry == 3) + { + heartbeatState = SENSOR_HB_OFFLINE; + } + } + } + if(lastState != heartbeatState) + { + lastState = heartbeatState; + retry = 0; + } + } + else + { + action++; + } +} +void refresh_Heartbeat(void) +{ + char text[32]; + uint8_t index = 0; + + snprintf(text, 32, "\001%c%c", TXT_2BYTE, TXT2BYTE_Pulse); + write_topline(text); + + switch(heartbeatState) + { + case SENSOR_HB_OFFLINE: + default: snprintf(text, 32, "%c%c", TXT_2BYTE, TXT2BYTE_SensorDetect); + write_label_var(30, 299, ME_Y_LINE1, &FontT48, text); + + if(curBtIndex > 0) + { + while((index < curBtIndex) && (index < 3)) + { + snprintf(text, 40, "%s", btDeviceList[index].address); + write_label_var( 30, 300, ME_Y_LINE3 + (index * ME_Y_LINE_STEP), &FontT48, text); + index++; + } + } + break; + case SENSOR_HB_ENABLE_BLE: snprintf(text, 32, "Activate BLE"); + write_label_var( 30, 300, ME_Y_LINE1, &FontT48, text); + break; + case SENSOR_HB_DISCOVER: + snprintf(text, 32, "Searching"); + write_label_var( 30, 300, ME_Y_LINE1, &FontT48, text); + + if(curBtIndex > 0) + { + while((index < curBtIndex) && (index < 4)) + { + snprintf(text, 40, "%s", btDeviceList[index].address); + write_label_var( 30, 300, ME_Y_LINE2 + (index * ME_Y_LINE_STEP), &FontT48, text); + index++; + } + } + break; + } + + write_buttonTextline(TXT2BYTE_ButtonMinus, TXT2BYTE_ButtonEnter, TXT2BYTE_ButtonPlus); +} +
--- a/Discovery/Src/ostc.c Mon Jul 28 18:32:23 2025 +0200 +++ b/Discovery/Src/ostc.c Mon Jul 28 18:34:45 2025 +0200 @@ -27,8 +27,10 @@ ////////////////////////////////////////////////////////////////////////////// /* Includes ------------------------------------------------------------------*/ +#include "configuration.h" #include "ostc.h" #include "stm32f4xx_hal.h" +#include "cv_heartbeat.h" #ifndef BOOTLOADER_STANDALONE #include "tCCR.h" @@ -54,6 +56,11 @@ /* Private variables with external access via get_xxx() function -------------*/ static uint8_t hardwareDisplay = 0; //< either OSTC4 LCD (=0) or new Screen (=1) + +static uint16_t rxBufRead = 0; +static uint16_t rxBufWrite = 0; +static uint8_t rxBufferUart[CHUNK_SIZE * CHUNKS_PER_BUFFER]; /* The complete buffer has a X * chunk size to allow variations in buffer read time */ + /* Private function prototypes -----------------------------------------------*/ /* Exported functions --------------------------------------------------------*/ @@ -380,6 +387,64 @@ #endif } +static DMA_HandleTypeDef hdma_uart_BT_rx; + +void MX_UART_BT_Init_DMA() +{ + + __DMA2_CLK_ENABLE(); + __HAL_RCC_DMA2_CLK_ENABLE(); + + hdma_uart_BT_rx.Instance = DMA2_Stream2; + hdma_uart_BT_rx.Init.Channel = DMA_CHANNEL_4; + hdma_uart_BT_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_uart_BT_rx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_uart_BT_rx.Init.MemInc = DMA_MINC_ENABLE; + hdma_uart_BT_rx.Init.PeriphDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_uart_BT_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_uart_BT_rx.Init.Mode = DMA_NORMAL; + hdma_uart_BT_rx.Init.Priority = DMA_PRIORITY_LOW; + hdma_uart_BT_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + HAL_DMA_Init(&hdma_uart_BT_rx); + + __HAL_LINKDMA(&UartHandle, hdmarx, hdma_uart_BT_rx); + + HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn); +} + + +uint8_t UART_getChar() +{ + uint8_t retChar = 0; + + if((rxBufRead != rxBufWrite) && (rxBufferUart[rxBufRead] != 0)) + { + retChar = rxBufferUart[rxBufRead]; + rxBufferUart[rxBufRead++] = 0; + if(rxBufRead == CHUNK_SIZE * CHUNKS_PER_BUFFER) + { + rxBufRead = 0; + } + } + return retChar; +} + +void UART_StartDMARx() +{ + HAL_UART_Receive_DMA (&UartHandle, &rxBufferUart[rxBufWrite], CHUNK_SIZE); + rxBufWrite += CHUNK_SIZE; + if(rxBufWrite >= CHUNK_SIZE * CHUNKS_PER_BUFFER) + { + rxBufWrite = 0; + } +} + +void DMA2_Stream2_IRQHandler(void) +{ + HAL_DMA_IRQHandler(&hdma_uart_BT_rx); +} + void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) { if(huart == &UartHandle) @@ -390,7 +455,20 @@ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(huart == &UartHandle) - UartReady = SET; + { +#ifdef ENABLE_PULSE_SENSOR_BT + if(cv_heartbeat_getState() != SENSOR_HB_OFFLINE) + { + UART_StartDMARx(); + } + else + { + UartReady = SET; + } +#else + UartReady = SET; +#endif + } else if(huart == &UartIR_HUD_Handle) {
--- a/Discovery/Src/tMenuCvOption.c Mon Jul 28 18:32:23 2025 +0200 +++ b/Discovery/Src/tMenuCvOption.c Mon Jul 28 18:34:45 2025 +0200 @@ -76,6 +76,15 @@ } nextline(text,&textPointer); +#ifdef ENABLE_PULSE_SENSOR_BT + if (line == 0 || line == 3) + { + textPointer += snprintf(&text[textPointer], 21, "%c%c", TXT_2BYTE, TXT2BYTE_Pulse); + } + nextline(text,&textPointer); + +#endif + return StMOption; } void tMCvOption_checkLineStatus(void)
--- a/Discovery/Src/tMenuEdit.c Mon Jul 28 18:32:23 2025 +0200 +++ b/Discovery/Src/tMenuEdit.c Mon Jul 28 18:34:45 2025 +0200 @@ -42,6 +42,7 @@ #include "tMenuEditSystem.h" #include "tMenuEditXtra.h" #include "tMenuEditCustom.h" +#include "cv_heartbeat.h" /* Private types -------------------------------------------------------------*/ #define TEXTSIZE 16 @@ -256,6 +257,11 @@ case StMCustom3_CViewSelection5: case StMCustom3_CViewSelection6: refreshFct = CustomviewDivemode_refresh; break; +#ifdef ENABLE_PULSE_SENSOR_BT + case (StMOption_Heartbeat): refreshFct = refresh_Heartbeat; + break; +#endif + #ifdef ENABLE_MOTION_CONTROL case (StMCustom5_CViewPortCalib & MaskFieldDigit): case StMCustom5_CViewPortLayout:
--- a/Discovery/Src/tMenuEditCvOption.c Mon Jul 28 18:32:23 2025 +0200 +++ b/Discovery/Src/tMenuEditCvOption.c Mon Jul 28 18:34:45 2025 +0200 @@ -35,6 +35,8 @@ #include "tMenuEdit.h" #include "tHome.h" +#include "cv_heartbeat.h" + /* Private function prototypes -----------------------------------------------*/ static void openEdit_Timer(void); void openEdit_Compass(void); @@ -56,13 +58,13 @@ switch(line) { case 1: - default: - resetMenuEdit(CLUT_MenuPageHardware); - openEdit_Compass(); - break; - case 2: - openEdit_Timer(); - break; + default: resetMenuEdit(CLUT_MenuPageHardware); + openEdit_Compass(); + break; + case 2: openEdit_Timer(); + break; + case 3: openEdit_Heartbeat(); + break; } }
--- a/Discovery/Src/text_multilanguage.c Mon Jul 28 18:32:23 2025 +0200 +++ b/Discovery/Src/text_multilanguage.c Mon Jul 28 18:34:45 2025 +0200 @@ -2005,6 +2005,14 @@ static uint8_t text_IT_Reverse[] = "Invertire"; static uint8_t text_ES_Reverse[] = "Invertir"; +static uint8_t text_EN_Pulse[] = "Heartbeat sensor (BT)"; +static uint8_t text_DE_Pulse[] = "Pulssensor (BT)"; +static uint8_t text_FR_Pulse[] = ""; +static uint8_t text_IT_Pulse[] = ""; +static uint8_t text_ES_Pulse[] = ""; + + + /* Lookup Table -------------------------------------------------------------*/ const tText text_array[] = @@ -2319,6 +2327,7 @@ {(uint8_t)TXT2BYTE_Log, {text_EN_Log, text_DE_Log, text_FR_Log, text_IT_Log, text_ES_Log}}, {(uint8_t)TXT2BYTE_Reverse, {text_EN_Reverse, text_DE_Reverse, text_FR_Reverse, text_IT_Reverse, text_ES_Reverse}}, + {(uint8_t)TXT2BYTE_Pulse, {text_EN_Pulse, text_DE_Pulse, text_FR_Pulse, text_IT_Pulse, text_ES_Pulse}}, };
