# HG changeset patch
# User Ideenmodellierer
# Date 1753720485 -7200
# Node ID 33b91584d8279b7356f74da47c22eec451427a25
# Parent cd4561c33758aa56509e17a7d8ab3320071e43bb
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.
diff -r cd4561c33758 -r 33b91584d827 Common/CPU1-F429.ld
--- 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.*)
diff -r cd4561c33758 -r 33b91584d827 Common/Inc/configuration.h
--- 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 */
diff -r cd4561c33758 -r 33b91584d827 Discovery/Inc/cv_heartbeat.h
--- /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 .
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef INC_CV_HEARTBEAT_H_
+#define INC_CV_HEARTBEAT_H_
+
+#include
+
+
+#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_ */
diff -r cd4561c33758 -r 33b91584d827 Discovery/Inc/ostc.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
diff -r cd4561c33758 -r 33b91584d827 Discovery/Inc/tStructure.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)
diff -r cd4561c33758 -r 33b91584d827 Discovery/Inc/text_multilanguage.h
--- 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,
};
diff -r cd4561c33758 -r 33b91584d827 Discovery/Src/base.c
--- 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:
diff -r cd4561c33758 -r 33b91584d827 Discovery/Src/cv_heartbeat.c
--- /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 .
+//////////////////////////////////////////////////////////////////////////////
+
+#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);
+}
+
diff -r cd4561c33758 -r 33b91584d827 Discovery/Src/ostc.c
--- 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)
{
diff -r cd4561c33758 -r 33b91584d827 Discovery/Src/tMenuCvOption.c
--- 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)
diff -r cd4561c33758 -r 33b91584d827 Discovery/Src/tMenuEdit.c
--- 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:
diff -r cd4561c33758 -r 33b91584d827 Discovery/Src/tMenuEditCvOption.c
--- 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;
}
}
diff -r cd4561c33758 -r 33b91584d827 Discovery/Src/text_multilanguage.c
--- 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}},
};