changeset 1037:2af07aa38531 GasConsumption

Merge with external development branches: Some features have been prepared for integration: Profiles, DMA UART on Firmware part, Bluetooth discovery and messges logging for development phase. All these new function are deactivated by compile switch and may be activated using the configuration.h for testing purpose.
author Ideenmodellierer
date Mon, 15 Sep 2025 21:12:44 +0200
parents e938901f6386 (current diff) 5865f0aeb438 (diff)
children 677d293c669f
files Common/Inc/configuration.h Discovery/Inc/tStructure.h Discovery/Src/base.c Discovery/Src/tMenu.c Discovery/Src/tMenuEdit.c Discovery/Src/tMenuEditSystem.c Discovery/Src/tMenuSystem.c FontPack/base_upperRegion.c
diffstat 27 files changed, 1493 insertions(+), 61 deletions(-) [+]
line wrap: on
line diff
--- a/Common/Inc/configuration.h	Sun Sep 07 20:44:35 2025 +0200
+++ b/Common/Inc/configuration.h	Mon Sep 15 21:12:44 2025 +0200
@@ -96,8 +96,20 @@
 /* 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 */
 
+/* Enable to receive data from the radio connection usart */
+/* #define ENABLE_USART_RADIO */
+
+/* Enable to show messages which are den during runtime in a popup window */
+/* #define ENABLE_LOGGER_WINDOW */
+
+/* Enable to have the possibility to switch between four individual sets of settings */
+/* #define ENABLE_SETTING_PROFILES */
+
 
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discovery/Inc/cv_heartbeat.h	Mon Sep 15 21:12:44 2025 +0200
@@ -0,0 +1,143 @@
+///////////////////////////////////////////////////////////////////////////////
+/// -*- 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,
+	CHARACTERISTIC_INDICATOR,
+	DESCRIPTOR_INDICATOR,
+	PULSE_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,
+	BT_READ_CHAR_CONHANDLE,
+	BT_READ_CHAR_ATTRIBUTE,
+	BT_READ_CHAR_PROPERTY,
+	BT_READ_CHAR_VALUEHANDLE,
+	BT_READ_CHAR_UUID,
+	BT_READ_DESC_CONHANDLE,
+	BT_READ_DESC_CHARHANDLE,
+	BT_READ_DESC_DESCHANDLE,
+	BT_READ_DESC_UUID,
+	BT_READ_PULSE_CONHANDLE,
+	BT_READ_PULSE_VALUEHANDLE,
+	BT_READ_PULSE_DATA,
+} 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_DISCONNECT,
+	SENSOR_HB_SERVICES,
+	SENSOR_HB_CHARACTERISTIC,
+	SENSOR_HB_DESCRIPTOR,
+	SENSOR_HB_SUBSCRIBE,
+	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;
+
+typedef struct
+{
+	uint8_t conHandle;
+	uint8_t attrHandle[10];
+	uint8_t properties[10];
+	uint8_t valueHandle[10];
+	uint8_t uuid[50];
+} btDeviceCharacteristic_t;
+
+typedef struct
+{
+	uint8_t conHandle;
+	uint8_t charHandle[10];
+	uint8_t descHandle[10];
+	uint8_t uuid[50];
+} btDeviceDescriptor_t;
+
+typedef struct {
+    uint16_t heart_rate;
+    uint16_t energy_expended;
+    uint16_t rr_intervals[10];
+    uint8_t rr_count;
+} HRMeasurement_t;
+
+sensorHeartbeat_State_t cv_heartbeat_getState();
+void refresh_Heartbeat(void);
+void cv_heartbeat_Control(void);
+uint8_t cv_heartbeat_HandleData();
+
+#endif /* INC_CV_HEARTBEAT_H_ */
--- a/Discovery/Inc/demo.h	Sun Sep 07 20:44:35 2025 +0200
+++ b/Discovery/Inc/demo.h	Mon Sep 15 21:12:44 2025 +0200
@@ -35,4 +35,6 @@
 void demoConfigureSettings(void);
 void demoSendCommand(uint8_t action);
 
+void demo_HandleData(void);
+
 #endif // DEMO_H
--- a/Discovery/Inc/ostc.h	Sun Sep 07 20:44:35 2025 +0200
+++ b/Discovery/Inc/ostc.h	Mon Sep 15 21:12:44 2025 +0200
@@ -60,6 +60,10 @@
 #define DISPLAY_VERSION_LCD						(0u)
 #define DISPLAY_VERSION_NEW						(1u)
 
+#define CHUNK_SIZE				(160u)		/* 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,15 @@
 void SetDisplayVersion(uint8_t version);
 uint8_t isNewDisplay(void);
 
+uint8_t UART_getChar();
+
+#ifdef ENABLE_PULSE_SENSOR_BT
+void UART_StartDMARx();
+#endif
+#ifdef ENABLE_USART_RADIO
+void MX_UART_RADIO_Init_DMA();
+void UART_StartDMARxRadio();
+#endif
+
 
 #endif // OSTC_H
--- a/Discovery/Inc/ostc_hw2.h	Sun Sep 07 20:44:35 2025 +0200
+++ b/Discovery/Inc/ostc_hw2.h	Mon Sep 15 21:12:44 2025 +0200
@@ -167,6 +167,22 @@
 #define USART_IR_HUD_IRQn                           USART2_IRQn
 // to it directly#define USART_IR_HUD_IRQHandler    USART2_IRQHandler
 
+#define USART_RADIO                                 USART3
+#define USART_RADIO_CLK_ENABLE()                   __USART3_CLK_ENABLE();
+#define USART_RADIO_FORCE_RESET()                  __USART3_FORCE_RESET()
+#define USART_RADIO_RELEASE_RESET()                __USART3_RELEASE_RESET()
+//#define USART_IR_HUD_TX_AF                          GPIO_AF7_USART3
+//#define USART_IR_HUD_TX_PIN                         GPIO_PIN_5
+//#define USART_IR_HUD_TX_GPIO_PORT                   GPIOD
+//#define USART_IR_HUD_TX_GPIO_CLK_ENABLE()           __GPIOD_CLK_ENABLE()
+
+#define USART_RADIO_RX_AF                          GPIO_AF7_USART3
+#define USART_RADIO_RX_PIN                         GPIO_PIN_11
+#define USART_RADIO_RX_GPIO_PORT                   GPIOB
+#define USART_RADIO_RX_GPIO_CLK_ENABLE()           __GPIOB_CLK_ENABLE()
+#define USART_RADIO_IRQn                           USART3_IRQn
+
+
 #define TIMx                                        TIM4
 #define TIMx_CLK_ENABLE                             __TIM4_CLK_ENABLE
 #define TIMx_IRQn                                   TIM4_IRQn
--- a/Discovery/Inc/tHome.h	Sun Sep 07 20:44:35 2025 +0200
+++ b/Discovery/Inc/tHome.h	Mon Sep 15 21:12:44 2025 +0200
@@ -81,7 +81,10 @@
 		CVIEW_CcrSummary,
         CVIEW_Timer,
 		CVIEW_Position,
-		CVIEW_END			/* The ID is used in shift operation => 31 is the max number of supported views */
+#ifdef ENABLE_LOGGER_WINDOW
+		CVIEW_Logger = 25,			/* keep development views at the end of the list to avoid id problems in official releases */
+#endif
+		CVIEW_END	= 32			/* The ID is used in shift operation => 31 is the max number of supported views */
 };
 
 enum CUSTOMVIEWS_BF
--- a/Discovery/Inc/tInfo.h	Sun Sep 07 20:44:35 2025 +0200
+++ b/Discovery/Inc/tInfo.h	Mon Sep 15 21:12:44 2025 +0200
@@ -69,5 +69,6 @@
 void tInfo_set_on_off(uint32_t editID, uint8_t int1);
 void exitInfo(void);
 void exitInfoToBack(void);
+void exitInfoSilent(void);
 
 #endif /* TINFO_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discovery/Inc/tInfoLogger.h	Mon Sep 15 21:12:44 2025 +0200
@@ -0,0 +1,47 @@
+///////////////////////////////////////////////////////////////////////////////
+/// -*- coding: UTF-8 -*-
+///
+/// \file   Discovery/Inc/tInfoSensor.h
+/// \brief  Infopage content for visualisation of UART protocol flow
+/// \author heinrichs weikamp gmbh
+/// \date   17-07-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/>.
+//////////////////////////////////////////////////////////////////////////////
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef TINFO_LOGGER_H
+#define TINFO_LOGGER_H
+
+#define LINE_HEADER_BYTES (3u)
+#define MAX_CHAR_PER_LINE (60u)
+#define MAX_LOGGER_LINES  (13u)
+
+#define LOG_TX_LINE	(0u)
+#define LOG_RX_LINE (1u)
+
+#include "gfx_engine.h"
+
+/* Exported functions --------------------------------------------------------*/
+void openInfo_Logger();
+void refreshInfo_Logger(GFX_DrawCfgScreen s);
+void sendActionToInfoLogger(uint8_t sendAction);
+void InfoLogger_writeLine(uint8_t* pLine,uint8_t lineLength,uint8_t direction);
+uint8_t InfoLogger_isUpdated();
+
+#endif /* TINFO_LOGGER_H */
--- a/Discovery/Inc/tStructure.h	Sun Sep 07 20:44:35 2025 +0200
+++ b/Discovery/Inc/tStructure.h	Mon Sep 15 21:12:44 2025 +0200
@@ -66,6 +66,7 @@
 #define InfoPageCompass 6
 #define InfoPageSensor  8
 #define InfoPagePreDive 9
+#define InfoPageLogger  10
 
 #define StI 			_MB(0,1,0,0,0)
 #define StILOGLIST		_MB(0,2,0,0,0)
@@ -76,6 +77,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)
@@ -313,6 +315,7 @@
 #define StMSYS1_GNSSDT  _MB(2,8,1,5,0)
 #define StMSYS1_ZONE	_MB(2,8,1,6,0)
 
+#ifdef ENABLE_SETTING_PROFILES
 #define StMSYS_Profile		_MB(2,8,2,0,0)
 #define StMSYS_ProfileA 	_MB(2,8,2,1,0)
 #define StMSYS_ProfileB 	_MB(2,8,2,2,0)
@@ -331,7 +334,7 @@
 #define StMSYS3_Debug	_MB(2,8,4,3,0)
 #endif
 
- #define StMSYS4_Info	_MB(2,8,5,1,0)
+#define StMSYS4_Info	_MB(2,8,5,1,0)
 
 #define StMSYS5_Exit			_MB(2,8,6,1,0)
 #define StMSYS5_LogbookOffset	_MB(2,8,6,7,0)
@@ -350,6 +353,39 @@
 #define StMSYS5_AdjustSurfPres  _MB(2,8,6,14,0)
 #define StMSYS5_FlashBoot		_MB(2,8,6,15,0)
 
+#else
+
+#define StMSYS2_English	_MB(2,8,2,1,0)
+#define StMSYS2_German	_MB(2,8,2,2,0)
+#define StMSYS2_French	_MB(2,8,2,3,0)
+#define StMSYS2_Italian	_MB(2,8,2,4,0)
+#define StMSYS2_Espanol	_MB(2,8,2,5,0)
+
+#define StMSYS3_Units	_MB(2,8,3,1,0)
+#define StMSYS3_Colors	_MB(2,8,3,2,0)
+#ifdef HAVE_DEBUG_VIEW
+#define StMSYS3_Debug	_MB(2,8,3,3,0)
+#endif
+
+#define StMSYS4_Info	_MB(2,8,4,1,0)
+
+#define StMSYS5_Exit			_MB(2,8,5,1,0)
+#define StMSYS5_LogbookOffset	_MB(2,8,5,7,0)
+#define StMSYS5_ResetAll		_MB(2,8,5,2,0)
+#define StMSYS5_ResetDeco		_MB(2,8,5,3,0)
+#define StMSYS5_Reboot			_MB(2,8,5,4,0)
+#define StMSYS5_Maintenance		_MB(2,8,5,5,0)
+#define StMSYS5_ResetLogbook	_MB(2,8,5,6,0)
+#define StMSYS5_SetBattCharge	_MB(2,8,5,7,0)
+#define StMSYS5_RebootRTE		_MB(2,8,5,8,0)
+#define StMSYS5_RebootMainCPU	_MB(2,8,5,9,0)
+#define StMSYS5_ScreenTest		_MB(2,8,5,10,0)
+#define StMSYS5_SetFactoryBC	_MB(2,8,5,11,0)
+#define StMSYS5_ResetBluetooth	_MB(2,8,5,12,0)
+#define StMSYS5_SetSampleIndx   _MB(2,8,5,13,0)
+#define StMSYS5_AdjustSurfPres  _MB(2,8,5,14,0)
+#define StMSYS5_FlashBoot		_MB(2,8,5,15,0)
+#endif
 
 
 #define StMSYS_Custom0			_MB(2,8,1,0,0)
@@ -406,6 +442,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	Sun Sep 07 20:44:35 2025 +0200
+++ b/Discovery/Inc/text_multilanguage.h	Mon Sep 15 21:12:44 2025 +0200
@@ -395,6 +395,8 @@
 		TXT2BYTE_TIMEZONE,
 
 		TXT2BYTE_BUZZER,
+		TXT2BYTE_Pulse,
+		TXT2BYTE_Logger,
 
 		TXT2BYTE_END,
 };
--- a/Discovery/Src/base.c	Sun Sep 07 20:44:35 2025 +0200
+++ b/Discovery/Src/base.c	Mon Sep 15 21:12:44 2025 +0200
@@ -237,12 +237,17 @@
 #include "t7.h"
 #include "t3.h"
 #include "tMenuEditSetpoint.h"
+#include "cv_heartbeat.h"
+#include "tInfoLogger.h"
 
 #ifdef DEMOMODE
 #include "demo.h"
 static void TIM_DEMO_init(void);
 #endif
 
+#ifdef ENABLE_USART_RADIO
+#include "demo.h"
+#endif
 
 //#include "lodepng.h"
 //#include <stdlib.h> // for malloc and free
@@ -501,6 +506,7 @@
             resetToFirmwareUpdate();
 
         tCCR_control();
+
         if( tComm_control() )// will stop while loop if tComm Mode started until exit from UART
         {
             createDiveSettings();
@@ -526,12 +532,22 @@
         {
         	TriggerButtonAction();
         }
+#ifdef ENABLE_PULSE_SENSOR_BT
+        cv_heartbeat_HandleData();
+#endif
+
+#ifdef ENABLE_USART_RADIO
+        demo_HandleData();
+#endif
         if(DoHousekeeping)
         {
            	DoHousekeeping = housekeepingFrame();
         }
         if(DoDisplayRefresh)							/* set every 100ms by timer interrupt */
         {
+#ifdef ENABLE_PULSE_SENSOR_BT
+        	cv_heartbeat_Control();
+#endif
 	        DoDisplayRefresh = 0;
 
 	        updateSetpointStateUsed();
@@ -727,6 +743,15 @@
 {
 	SStateList status;
 	get_globalStateList(&status);
+
+#ifdef ENABLE_LOGGER_WINDOW
+	if((status.base != 0) && (get_globalState() != StILOGGER) && (InfoLogger_isUpdated()))
+	{
+		openInfo_Logger();
+		get_globalStateList(&status);
+	}
+#endif
+
 	switch(status.base)
 	{
 	case BaseHome:
@@ -919,6 +944,8 @@
 								break;
 							case InfoPagePreDive: 	sendActionToInfoPreDive(action);
 								break;
+							case InfoPageLogger: 	exitInfo();
+								break;
 							default:				sendActionToInfo(action);
 								break;
 						}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discovery/Src/cv_heartbeat.c	Mon Sep 15 21:12:44 2025 +0200
@@ -0,0 +1,668 @@
+///////////////////////////////////////////////////////////////////////////////
+/// -*- 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 "configuration.h"
+
+#ifdef ENABLE_PULSE_SENSOR_BT
+#include "cv_heartbeat.h"
+#include "tMenuEdit.h"
+
+#include "gfx_fonts.h"
+#include "tHome.h"
+#include "ostc.h"
+#include "tComm.h"
+#include "tInfoLogger.h"
+#include "stdlib.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 btDeviceCharacteristic_t curDevCharacteristic[10];
+static btDeviceDescriptor_t curDevDescriptor;
+
+
+static uint8_t curCharacteristicIndex = 0;
+static uint8_t curServiceIndex = 0;
+static uint8_t curBtIndex = 0;
+static uint8_t connHandle = ' ';
+static uint8_t evaluateDevIndex = 0xFF;
+static uint8_t evaluateSrvIndex = 0xFF;
+static uint8_t evaluateCharIndex = 0xFF;
+
+static void parsePulseMeasurement(uint8_t* pData, uint8_t length)
+{
+	uint8_t rawData[10];
+
+	char* enptr;
+	uint8_t flags = 0;
+	uint16_t rr = 0;
+	uint8_t index = 0;
+	uint8_t* pRaw = (uint8_t*)&rawData;
+	char tmpStr[3];
+
+	tmpStr[2] = 0;
+
+	HRMeasurement_t pulseData;
+
+	for(index = 0; index < length; index +=2)
+	{
+		memcpy(tmpStr,&pData[index],2);
+		rawData[index / 2] = strtol(tmpStr, &enptr,16);
+	}
+	flags = pRaw[0];
+	index = 1;
+    /* 0: Heart Rate Format bit (0 = UINT8, 1 = UINT16) */
+	if (flags & 0x01)
+	{
+	   	pulseData.heart_rate = pRaw[index] | (pRaw[index + 1] << 8);
+	    index += 2;
+	} else
+	{
+	  	pulseData.heart_rate = pRaw[index];
+	    index += 1;
+	}
+
+	/* 3: Energy Expended Status	*/
+	if (flags & 0x08)
+	{
+	   	pulseData.energy_expended = pRaw[index] | (pRaw[index + 1] << 8);
+	    index += 2;
+	} else
+	{
+	  	pulseData.energy_expended = 0;
+	}
+    /* 4: RR-Interval bit			*/
+	pulseData.rr_count = 0;
+	if (flags & 0x10)
+	{
+	    while (index + 1 < 4 && pulseData.rr_count < 10)
+	    {
+	        rr = pRaw[index] | (pRaw[index + 1] << 8);
+	        pulseData.rr_intervals[pulseData.rr_count++] = rr;
+	        index += 2;
+	    }
+	}
+//			snprintf(text,40,"Pulse: %d",pulseData.heart_rate);
+//			InfoLogger_writeLine((uint8_t*)text,strlen(text),0);
+}
+
+static indicatior_t checkIndicators(uint8_t* pdata)
+{
+	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;
+	}
+	else if(strcmp((char*)pdata,"+UBTGDCS:") == 0)
+	{
+		ret = CHARACTERISTIC_INDICATOR;
+	}
+	else if(strcmp((char*)pdata,"+UBTGDCD:") == 0)
+	{
+		ret = DESCRIPTOR_INDICATOR;
+	}
+	else if(strcmp((char*)pdata,"+UUBTGN:") == 0)
+	{
+		ret = PULSE_INDICATOR;
+	}
+	return ret;
+}
+
+static void handleOK()
+{
+	uint8_t index = 0;
+
+	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: 	if(curBtIndex > 0)
+									{
+										heartbeatState = SENSOR_HB_CONNECT;
+										evaluateDevIndex = 0;
+									}
+									else
+									{
+										heartbeatState = SENSOR_HB_OFFLINE;
+									}
+
+							break;
+		case SENSOR_HB_SERVICES: 	evaluateSrvIndex = 0xFF;
+									if(curServiceIndex != 0)
+									{
+										for(index = 0; index <= curServiceIndex; index++)
+										{
+											if(strcmp((char*)curDeviceService[index].uuid,"180D") == 0)
+											{
+												heartbeatState = SENSOR_HB_CHARACTERISTIC;
+												evaluateSrvIndex = index;
+												curCharacteristicIndex = 0;
+												break;
+											}
+										}
+									}
+									if(evaluateSrvIndex == 0xFF)		/* device does not provide heartbeat data => disconnect */
+									{
+										heartbeatState = SENSOR_HB_DISCONNECT;
+									}
+							break;
+		case SENSOR_HB_CHARACTERISTIC:	evaluateCharIndex = 0xFF;
+										if(curCharacteristicIndex != 0)
+										{
+											for(index = 0; index < curCharacteristicIndex; index++)
+											{
+												if(strcmp((char*)curDevCharacteristic[index].uuid,"2A37") == 0)
+												{
+													heartbeatState = SENSOR_HB_DESCRIPTOR;
+													evaluateCharIndex = index;
+													break;
+												}
+											}
+										}
+										if(evaluateCharIndex == 0xFF)		/* device does not provide heartbeat data => disconnect */
+										{
+											heartbeatState = SENSOR_HB_DISCONNECT;
+										}
+							break;
+		case SENSOR_HB_DESCRIPTOR:		if(strcmp((char*)curDevDescriptor.uuid,"2902") == 0)
+										{
+											heartbeatState = SENSOR_HB_SUBSCRIBE;
+										}
+										else
+										{
+											heartbeatState = SENSOR_HB_DISCONNECT;
+										}
+							break;
+
+		case SENSOR_HB_SUBSCRIBE:		heartbeatState = SENSOR_HB_CONNECTED;
+							break;
+		case SENSOR_HB_DISCONNECT:		evaluateDevIndex++;
+										connHandle= ' ';
+										if(evaluateDevIndex < curBtIndex)	/* more devices to be evaluated? */
+										{
+											heartbeatState = SENSOR_HB_CONNECT;
+										}
+										else
+										{
+											heartbeatState = SENSOR_HB_OFFLINE;
+										}
+							break;
+		case SENSOR_HB_CONNECT:			/* handled in data rx section */
+		default:
+							break;
+	}
+}
+
+static void handleERROR()
+{
+	switch(heartbeatState)
+	{
+		case SENSOR_HB_DISCONNECT:			evaluateDevIndex++;
+											connHandle= ' ';
+											if(evaluateDevIndex < curBtIndex)	/* more devices to be evaluated? */
+											{
+												heartbeatState = SENSOR_HB_CONNECT;
+											}
+											else
+											{
+												heartbeatState = SENSOR_HB_OFFLINE;
+											}
+						break;
+		default:
+						break;
+	}
+}
+
+uint8_t cv_heartbeat_HandleData()
+{
+	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;
+
+	uint8_t data = 0;
+	data = UART_getChar();
+
+	while((data != 0) && (complete == 0))
+	{
+		if(curLineIndex == MAX_CHAR_PER_LINE - 1)		/* 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) && (curServiceIndex < 10))
+											{
+												memcpy(curDeviceService[curServiceIndex].uuid, parameter, writeIndex);
+											}
+											curServiceIndex++;
+								break;
+				case BT_READ_CHAR_UUID: 	if(writeIndex < 50)
+											{
+												memcpy(curDevCharacteristic[curCharacteristicIndex].uuid, parameter, writeIndex);
+												curCharacteristicIndex++;
+											}
+								break;
+				case BT_READ_DESC_UUID: 	if(writeIndex < 50)
+											{
+												memcpy(curDevDescriptor.uuid, parameter, writeIndex);
+											}
+								break;
+				case BT_READ_PULSE_DATA: 	if(writeIndex < 50)
+											{
+												parsePulseMeasurement(parameter, writeIndex);
+											}
+								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;
+					case CHARACTERISTIC_INDICATOR: readType = BT_READ_CHAR_CONHANDLE;
+						break;
+					case DESCRIPTOR_INDICATOR: 	readType = BT_READ_DESC_CONHANDLE;
+						break;
+					case PULSE_INDICATOR:		readType = BT_READ_PULSE_CONHANDLE;
+						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;
+													curServiceIndex = 0;
+										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;
+						case BT_READ_CHAR_CONHANDLE: curDevCharacteristic[curCharacteristicIndex].conHandle = parameter[0];
+													 readType = BT_READ_CHAR_ATTRIBUTE;
+										break;
+						case BT_READ_CHAR_ATTRIBUTE: if(writeIndex < 10)
+													{
+														memcpy(curDevCharacteristic[curCharacteristicIndex].attrHandle, parameter, writeIndex);
+													}
+													readType = BT_READ_CHAR_PROPERTY;
+										break;
+						case BT_READ_CHAR_PROPERTY: if(writeIndex < 10)
+													{
+														memcpy(curDevCharacteristic[curCharacteristicIndex].properties, parameter, writeIndex);
+													}
+													readType = BT_READ_CHAR_VALUEHANDLE;
+										break;
+						case BT_READ_CHAR_VALUEHANDLE: if(writeIndex < 10)
+													{
+														memcpy(curDevCharacteristic[curCharacteristicIndex].valueHandle, parameter, writeIndex);
+													}
+													readType = BT_READ_CHAR_UUID;
+										break;
+						case BT_READ_DESC_CONHANDLE: curDevDescriptor.conHandle = parameter[0];
+													 readType = BT_READ_DESC_CHARHANDLE;
+										break;
+						case BT_READ_DESC_CHARHANDLE: if(writeIndex < 10)
+													{
+														memcpy(curDevDescriptor.charHandle, parameter, writeIndex);
+													}
+													readType = BT_READ_DESC_DESCHANDLE;
+										break;
+						case BT_READ_DESC_DESCHANDLE: if(writeIndex < 10)
+													{
+														memcpy(curDevDescriptor.descHandle, parameter, writeIndex);
+													}
+													readType = BT_READ_DESC_UUID;
+										break;
+						case BT_READ_PULSE_CONHANDLE: curDevDescriptor.conHandle = parameter[0];
+													  readType = BT_READ_PULSE_VALUEHANDLE;
+										break;
+						case BT_READ_PULSE_VALUEHANDLE: if(writeIndex < 10)
+														{
+											//				if(strcmp((char*)curDevCharacteristic[evaluateCharIndex].valueHandle,(char*) parameter) == 0)
+															{
+																readType = BT_READ_PULSE_DATA;
+															}
+#if 0
+															else
+															{
+																readType = BT_READ_NOTHING;
+															}
+#endif
+														}
+										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)
+{
+    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;
+	char cmd[50];
+
+	cmd[0] = 0;
+
+	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"
+											curBtIndex = 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(evaluateDevIndex < curBtIndex)
+										{
+											snprintf(cmd, sizeof(cmd), "AT+UBTACLC=%s\r\n",btDeviceList[evaluateDevIndex].address);
+										}
+				break;
+			case SENSOR_HB_DISCONNECT:		snprintf(cmd, sizeof(cmd), "AT+UBTACLD=%c\r\n",connHandle);
+				break;
+			case SENSOR_HB_SERVICES:	if((connHandle >= '0') && (connHandle <= '9') && (lastState != SENSOR_HB_SERVICES))
+										{
+											snprintf(cmd, sizeof(cmd), "AT+UBTGDP=%c\r\n",connHandle);
+											memset(curDeviceService, 0, sizeof(curDeviceService));
+										}
+				break;
+			case SENSOR_HB_CHARACTERISTIC:	snprintf(cmd, sizeof(cmd), "AT+UBTGDCS=%c,%s,%s\r\n",connHandle,curDeviceService[evaluateSrvIndex].start
+																								,curDeviceService[evaluateSrvIndex].end);
+											memset(curDevCharacteristic, 0, sizeof(curDevCharacteristic));
+				break;
+			case SENSOR_HB_DESCRIPTOR: 		snprintf(cmd, sizeof(cmd), "AT+UBTGDCD=%c,%s,%s\r\n",connHandle,curDevCharacteristic[evaluateCharIndex].valueHandle
+																											,curDeviceService[evaluateSrvIndex].end);
+				break;
+			case SENSOR_HB_SUBSCRIBE: 		snprintf(cmd, sizeof(cmd), "AT+UBTGWC=%c,%s,1\r\n",connHandle,curDevDescriptor.descHandle);
+				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);
+}
+#endif
--- a/Discovery/Src/demo.c	Sun Sep 07 20:44:35 2025 +0200
+++ b/Discovery/Src/demo.c	Mon Sep 15 21:12:44 2025 +0200
@@ -28,6 +28,8 @@
 #include "data_exchange_main.h" // for time_elapsed_ms()
 #include "settings.h"
 #include "ostc.h"
+#include "tInfoLogger.h"
+#include <string.h>
 
 #ifndef DEMOMODE
 
@@ -425,5 +427,62 @@
 
 #endif // DEMO
 
+#ifdef ENABLE_USART_RADIO				/* debug function to check receiption of radio data */
+void demo_HandleData(void)
+{
+	static uint8_t comStarted = 0;
+	static uint8_t text[50];
+	static uint8_t index = 0;
+	static uint32_t startTick = 0;
+	static uint8_t firstData = 1;
+	uint8_t data = 0;
+
+	switch(comStarted)
+	{
+		case 0: 	startTick = HAL_GetTick();
+					comStarted++;
+				break;
+		case 1:		if(time_elapsed_ms(startTick, HAL_GetTick()) > 5000)
+					{
+						MX_UART_RADIO_Init_DMA();
+						UART_StartDMARxRadio();
+						comStarted++;
+						sprintf((char*)text,"RadioStarted");
+						InfoLogger_writeLine(text,strlen((char*)text),1);
+					}
+			break;
+		case 2:				data = UART_getChar();
+							if(data != 0)
+							{
+								if(firstData)
+								{
+									firstData = 0;
+									sprintf((char*)text,"FirstData");
+									InfoLogger_writeLine(text,strlen((char*)text),1);
+								}
+								if((index == 50) || (data =='r')  || (data =='n'))
+								{
+									if(index > 0)
+									{
+										InfoLogger_writeLine(text,index,0);
+										index = 0;
+									}
+								}
+								else
+								{
+									text[index++] = data;
+								}
+							}
+			break;
+		default:
+			break;
+	}
+
+
+	{
+	}
+}
+#endif
+
 
 /************************ (C) COPYRIGHT heinrichs weikamp *****END OF FILE****/
--- a/Discovery/Src/ostc.c	Sun Sep 07 20:44:35 2025 +0200
+++ b/Discovery/Src/ostc.c	Mon Sep 15 21:12:44 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"
@@ -45,6 +47,10 @@
 #endif
 UART_HandleTypeDef UartIR_HUD_Handle;
 
+#ifdef ENABLE_USART_RADIO
+UART_HandleTypeDef UartRadio_Handle;
+#endif
+
 __IO ITStatus UartReady = RESET;
 __IO ITStatus UartReadyHUD = RESET;
 
@@ -54,6 +60,19 @@
 
 /* Private variables with external access via get_xxx() function -------------*/
 static uint8_t	hardwareDisplay = 0;		//< either OSTC4 LCD (=0) or new Screen (=1)
+
+#ifdef ENABLE_PULSE_SENSOR_BT
+static DMA_HandleTypeDef  hdma_uart_BT_rx;
+#endif
+
+#ifdef ENABLE_USART_RADIO
+static DMA_HandleTypeDef  hdma_uart_radio_rx;
+#endif
+
+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 --------------------------------------------------------*/
@@ -378,8 +397,122 @@
 
     HAL_UART_Init(&UartIR_HUD_Handle);
 #endif
+
+#ifdef ENABLE_USART_RADIO
+    UartRadio_Handle.Instance        = USART_RADIO;
+    UartRadio_Handle.Init.BaudRate   = 9600;
+    UartRadio_Handle.Init.WordLength = UART_WORDLENGTH_8B;
+    UartRadio_Handle.Init.StopBits   = UART_STOPBITS_1;
+    UartRadio_Handle.Init.Parity     = UART_PARITY_NONE;
+    UartRadio_Handle.Init.HwFlowCtl  = UART_HWCONTROL_NONE;
+    UartRadio_Handle.Init.Mode       = UART_MODE_RX;
+
+    HAL_UART_Init(&UartRadio_Handle);
+#endif
+
 }
 
+#ifdef ENABLE_PULSE_SENSOR_BT
+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);
+}
+#endif
+
+#ifdef ENABLE_USART_RADIO
+void MX_UART_RADIO_Init_DMA()
+{
+
+	__DMA2_CLK_ENABLE();
+	 __HAL_RCC_DMA2_CLK_ENABLE();
+
+	hdma_uart_radio_rx.Instance = DMA2_Stream1;
+	hdma_uart_radio_rx.Init.Channel = DMA_CHANNEL_4;
+	hdma_uart_radio_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
+	hdma_uart_radio_rx.Init.PeriphInc = DMA_PINC_DISABLE;
+	hdma_uart_radio_rx.Init.MemInc = DMA_MINC_ENABLE;
+	hdma_uart_radio_rx.Init.PeriphDataAlignment = DMA_MDATAALIGN_BYTE;
+	hdma_uart_radio_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
+	hdma_uart_radio_rx.Init.Mode = DMA_NORMAL;
+	hdma_uart_radio_rx.Init.Priority = DMA_PRIORITY_LOW;
+	hdma_uart_radio_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
+	HAL_DMA_Init(&hdma_uart_radio_rx);
+
+	__HAL_LINKDMA(&UartRadio_Handle, hdmarx, hdma_uart_radio_rx);
+
+	HAL_NVIC_SetPriority(DMA2_Stream1_IRQn, 0, 0);
+	HAL_NVIC_EnableIRQ(DMA2_Stream1_IRQn);
+}
+#endif
+
+
+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;
+}
+#ifdef ENABLE_PULSE_SENSOR_BT
+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);
+}
+#endif
+
+#ifdef ENABLE_USART_RADIO
+void UART_StartDMARxRadio()
+{
+	HAL_UART_Receive_DMA (&UartRadio_Handle, &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_radio_rx);
+}
+#endif
+
 void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
 {
     if(huart == &UartHandle)
@@ -390,7 +523,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/stm32f4xx_hal_msp_hw2.c	Sun Sep 07 20:44:35 2025 +0200
+++ b/Discovery/Src/stm32f4xx_hal_msp_hw2.c	Mon Sep 15 21:12:44 2025 +0200
@@ -630,18 +630,20 @@
 
   /* USER CODE END USART3_MspInit 0 */
     /* Peripheral clock enable */
-    __USART3_CLK_ENABLE();
+	USART_RADIO_RX_GPIO_CLK_ENABLE();
 
     /**USART3 GPIO Configuration
-    PC10     ------> USART3_TX
-    PC11     ------> USART3_RX
+    PB11     ------> USART3_RX
     */
-    GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
+    GPIO_InitStruct.Pin = USART_RADIO_RX_PIN;
     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
     GPIO_InitStruct.Pull = GPIO_PULLUP;
     GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
-    GPIO_InitStruct.Alternate = GPIO_AF7_USART3;
-    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
+    GPIO_InitStruct.Alternate = USART_RADIO_RX_AF;
+    HAL_GPIO_Init(USART_RADIO_RX_GPIO_PORT, &GPIO_InitStruct);
+
+    HAL_NVIC_SetPriority(USART_RADIO_IRQn, 0, 1);
+    HAL_NVIC_EnableIRQ(USART_RADIO_IRQn);
 
   /* USER CODE BEGIN USART3_MspInit 1 */
 
@@ -706,7 +708,7 @@
     PC10     ------> USART3_TX
     PC11     ------> USART3_RX
     */
-    HAL_GPIO_DeInit(GPIOC, GPIO_PIN_10|GPIO_PIN_11);
+    HAL_GPIO_DeInit(USART_RADIO_RX_GPIO_PORT, USART_RADIO_RX_PIN);
 
   /* USER CODE BEGIN USART3_MspDeInit 1 */
 
--- a/Discovery/Src/tDebug.c	Sun Sep 07 20:44:35 2025 +0200
+++ b/Discovery/Src/tDebug.c	Mon Sep 15 21:12:44 2025 +0200
@@ -58,9 +58,12 @@
 
 void exitDebugMode(void)
 {
-    MX_Bluetooth_PowerOff();
-    settingsGetPointer()->debugModeOnStart = 0;
-    tD_debugModeActive = 0;
+	if(tD_debugModeActive)
+	{
+		MX_Bluetooth_PowerOff();
+		settingsGetPointer()->debugModeOnStart = 0;
+		tD_debugModeActive = 0;
+	}
 }
 
 
--- a/Discovery/Src/tHome.c	Sun Sep 07 20:44:35 2025 +0200
+++ b/Discovery/Src/tHome.c	Mon Sep 15 21:12:44 2025 +0200
@@ -59,7 +59,13 @@
 static uint16_t tHome_tick_count_field;
 static uint16_t tHome_tick_count_o2sens;
 
-const uint8_t cv_changelist[] = {CVIEW_Compass, CVIEW_SummaryOfLeftCorner, CVIEW_Tissues, CVIEW_Profile, CVIEW_EADTime, CVIEW_Gaslist, CVIEW_noneOrDebug, CVIEW_Decolist, CVIEW_sensors,CVIEW_sensors_mV, CVIEW_Timer, CVIEW_END};
+const uint8_t cv_changelist[] = {CVIEW_Compass, CVIEW_SummaryOfLeftCorner, CVIEW_Tissues,
+								 CVIEW_Profile, CVIEW_EADTime, CVIEW_Gaslist, CVIEW_noneOrDebug,
+								 CVIEW_Decolist, CVIEW_sensors,CVIEW_sensors_mV, CVIEW_Timer,
+#ifdef ENABLE_LOGGER_WINDOW
+	CVIEW_Logger,
+#endif
+								 CVIEW_END};
 const uint8_t cv_changelist_BS[] = {CVIEW_T3_Decostop, CVIEW_sensors, CVIEW_Compass, CVIEW_T3_MaxDepth,CVIEW_T3_StopWatch, CVIEW_T3_TTS, CVIEW_T3_GasList, CVIEW_T3_ppO2andGas, CVIEW_noneOrDebug,
 									CVIEW_T3_Navigation, CVIEW_T3_DepthData, CVIEW_T3_DecoTTS,
 #ifdef ENABLE_T3_PROFILE_VIEW
--- a/Discovery/Src/tInfo.c	Sun Sep 07 20:44:35 2025 +0200
+++ b/Discovery/Src/tInfo.c	Mon Sep 15 21:12:44 2025 +0200
@@ -38,6 +38,7 @@
 #include "tInfoCompass.h"
 #include "tInfoSensor.h"
 #include "tInfoPreDive.h"
+#include "tInfoLogger.h"
 #include "tMenu.h"
 #include "tMenuEdit.h"
 
@@ -227,6 +228,12 @@
     							infoColor = CLUT_MenuPageGasCC;
     							refreshInfo_PreDive(tIscreen);
     				break;
+#ifdef ENABLE_LOGGER_WINDOW
+    		case StILOGGER: 	tIscreen.FBStartAdress = getFrame(14);
+    							infoColor = CLUT_MenuPageCvOption;
+    							refreshInfo_Logger(tIscreen);
+    				break;
+#endif
 
     		default:
     				break;
@@ -256,6 +263,11 @@
     exitMenuEdit_to_BackMenu();
 }
 
+void exitInfoSilent(void)	/* no changes were done on info screen => just free buffer */
+{
+    releaseFrame(14,tIscreen.FBStartAdress);
+    updateMenu();
+}
 
 void sendActionToInfo(uint8_t sendAction)
 {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discovery/Src/tInfoLogger.c	Mon Sep 15 21:12:44 2025 +0200
@@ -0,0 +1,170 @@
+///////////////////////////////////////////////////////////////////////////////
+/// -*- coding: UTF-8 -*-
+///
+/// \file   Discovery/Src/tInfoLogger.c
+/// \brief  Show data which is received / send through UART interface
+/// \author heinrichs weikamp gmbh
+/// \date   23-Feb-2015
+///
+/// \details
+///
+/// $Id$
+///////////////////////////////////////////////////////////////////////////////
+/// \par Copyright (c) 2014-2018 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/>.
+//////////////////////////////////////////////////////////////////////////////
+
+/* Includes ------------------------------------------------------------------*/
+
+#include "gfx_engine.h"
+#include "gfx_fonts.h"
+#include "tHome.h"
+#include "tInfo.h"
+#include "tInfoLogger.h"
+#include "tMenuEdit.h"
+#include "data_exchange_main.h"
+#include "t7.h"
+
+#include <string.h>
+#include <inttypes.h>
+
+
+/* Private variables ---------------------------------------------------------*/
+static uint8_t lines[MAX_LOGGER_LINES][MAX_CHAR_PER_LINE + LINE_HEADER_BYTES];
+static uint8_t lineWriteIndex = 0;
+static uint8_t lineReadIndex = 0;
+static uint32_t receivedLinesCount = 0;
+
+static uint32_t loggerUpdateTime = 0;
+static uint32_t previousGlobalState = 0;
+
+/* Exported functions --------------------------------------------------------*/
+
+
+void InfoLogger_writeLine(uint8_t* pLine,uint8_t lineLength,uint8_t direction)
+{
+#ifdef ENABLE_LOGGER_WINDOW
+	uint8_t LogIndex = 0;
+
+	if(!t7_customview_disabled(CVIEW_Logger))
+	{
+		if(lineLength <= MAX_CHAR_PER_LINE)
+		{
+			memset(&lines[lineWriteIndex][0],0, (MAX_CHAR_PER_LINE + LINE_HEADER_BYTES));
+			if(direction == LOG_TX_LINE)
+			{
+				lines[lineWriteIndex][LogIndex] = '\002';	/* align right */
+				LogIndex++;
+			}
+			memcpy(&lines[lineWriteIndex][LogIndex],pLine,lineLength);
+			lineWriteIndex++;
+			if(lineWriteIndex == MAX_LOGGER_LINES)
+			{
+				lineWriteIndex = 0;
+			}
+			receivedLinesCount++;
+		}
+	}
+#endif
+}
+
+uint8_t InfoLogger_isUpdated()
+{
+	uint8_t ret = 0;
+	if(lineReadIndex != lineWriteIndex)
+	{
+		ret = 1;
+	}
+	return ret;
+}
+
+void openInfo_Logger()
+{
+	previousGlobalState = get_globalState();
+	set_globalState(StILOGGER);
+
+	loggerUpdateTime = HAL_GetTick();
+}
+
+void refreshInfo_Logger(GFX_DrawCfgScreen s)
+{
+	uint8_t index = 0;
+    char text[31];
+    uint8_t displayLine = 0;
+    uint8_t color = CLUT_Font020;
+
+	sprintf(text,"\001%c%c", TXT_2BYTE, TXT2BYTE_Logger);
+
+	tInfo_write_content_simple(  30, 770, ME_Y_LINE_BASE, &FontT48, text, CLUT_InfoSurface);
+
+
+	if(InfoLogger_isUpdated())
+	{
+		loggerUpdateTime = HAL_GetTick();
+	}
+	if(receivedLinesCount > MAX_LOGGER_LINES)
+	{
+		displayLine = MAX_LOGGER_LINES-1;
+	}
+	else
+	{
+		displayLine = lineWriteIndex;
+	}
+
+	if(lineReadIndex != lineWriteIndex)			/* needed for isUpdated function */
+	{
+		lineReadIndex++;
+		if(lineReadIndex == MAX_LOGGER_LINES)
+		{
+			lineReadIndex = 0;
+		}
+	}
+	while (index < displayLine)
+	{
+		color = CLUT_Font020;
+		if(lines[index][0] == '\002')
+		{
+			color = CLUT_NiceGreen;
+		}
+		if(lineReadIndex == index)
+		{
+			color = CLUT_NiceBlue;
+		}
+		tInfo_write_content_simple(  30, 770, 60 + (index * 30), &FontT24, (char*)lines[index], color);
+
+		if(lineReadIndex != lineWriteIndex)			/* needed for isUpdated function */
+		{
+			lineReadIndex++;
+			if(lineReadIndex == MAX_LOGGER_LINES)
+			{
+				lineReadIndex = 0;
+			}
+		}
+		index++;
+	}
+	if((time_elapsed_ms(loggerUpdateTime, HAL_GetTick()) > 10000))
+	{
+		set_globalState(previousGlobalState); /* restore state which was active before log data was received */
+		exitInfo();
+	}
+}
+
+void sendActionToInfoLogger(uint8_t sendAction)
+{
+/* TODO: at the moment a generic return to home is used because the logger window could be opened from everywhere => implement context based return from view */
+    set_globalState(previousGlobalState); /* restore state which was active before log data was received */
+    exitInfoSilent();
+}
+
--- a/Discovery/Src/tMenu.c	Sun Sep 07 20:44:35 2025 +0200
+++ b/Discovery/Src/tMenu.c	Mon Sep 15 21:12:44 2025 +0200
@@ -826,7 +826,12 @@
         update_content_actual_page(text, tabPosition, subtext);
         break;
     case StMSYS:
-        if((line == get_lineOfID(StMSYS1_DateTime)) || (line == get_lineOfID(StMSYS2_English)) || (line == get_lineOfID(StMSYS_Profile)))
+        if((line == get_lineOfID(StMSYS1_DateTime)) || (line == get_lineOfID(StMSYS2_English))
+#ifdef ENABLE_SETTING_PROFILES
+        		|| (line == get_lineOfID(StMSYS_Profile)))
+#else
+        	)
+#endif
         {
             tM_rebuild_pages();
             menu.lineMemoryForNavigationForPage[page] = line; // fix 160623
--- a/Discovery/Src/tMenuCvOption.c	Sun Sep 07 20:44:35 2025 +0200
+++ b/Discovery/Src/tMenuCvOption.c	Mon Sep 15 21:12:44 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	Sun Sep 07 20:44:35 2025 +0200
+++ b/Discovery/Src/tMenuEdit.c	Mon Sep 15 21:12:44 2025 +0200
@@ -42,6 +42,7 @@
 #include "tMenuEditSystem.h"
 #include "tMenuEditXtra.h"
 #include "tMenuEditCustom.h"
+#include "cv_heartbeat.h"
 
 /* Private types -------------------------------------------------------------*/
 #define TEXTSIZE 16
@@ -260,6 +261,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/tMenuEditCustom.c	Sun Sep 07 20:44:35 2025 +0200
+++ b/Discovery/Src/tMenuEditCustom.c	Mon Sep 15 21:12:44 2025 +0200
@@ -528,6 +528,10 @@
     case CVIEW_noneOrDebug:
     	text = TXT2BYTE_DispNoneDbg;
     	break;
+#ifdef ENABLE_LOGGER_WINDOW
+    case CVIEW_Logger: text = TXT2BYTE_Logger;
+    	break;
+#endif
     default:
         break;
     }
--- a/Discovery/Src/tMenuEditCvOption.c	Sun Sep 07 20:44:35 2025 +0200
+++ b/Discovery/Src/tMenuEditCvOption.c	Mon Sep 15 21:12:44 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,15 @@
     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;
+#ifdef ENABLE_PULSE_SENSOR_BT
+		case 3: 	openEdit_Heartbeat();
+#endif
+			break;
     }
 }
 
--- a/Discovery/Src/tMenuEditSystem.c	Sun Sep 07 20:44:35 2025 +0200
+++ b/Discovery/Src/tMenuEditSystem.c	Mon Sep 15 21:12:44 2025 +0200
@@ -46,16 +46,19 @@
 
 /*#define HAVE_DEBUG_VIEW */
 static uint8_t infoPage = 0;
+#ifdef ENABLE_SETTING_PROFILES
 static uint32_t profileStartCrc[NUMBER_OF_PROFILES];
 static uint8_t profileActiveStart = 0;
-
+#endif
 
 /* Private function prototypes -----------------------------------------------*/
 void openEdit_DateTime(void);
 void openEdit_DateFormat(void);
 void openEdit_Language(void);
 void openEdit_Design(void);
+#ifdef ENABLE_SETTING_PROFILES
 void openEdit_Profile(void);
+#endif
 void openEdit_Information(void);
 void openEdit_Reset(void);
 void openEdit_Maintenance(void);
@@ -98,9 +101,10 @@
 uint8_t OnAction_Units				(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action);
 uint8_t OnAction_Colorscheme	(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action);
 uint8_t OnAction_DebugInfo		(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action);
+#ifdef ENABLE_SETTING_PROFILES
 uint8_t OnAction_Profile(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action);
 uint8_t OnAction_SetProfile(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action);
-
+#endif
 uint8_t OnAction_Exit					(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action);
 uint8_t OnAction_Confirm			(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action);
 uint8_t OnAction_Maintenance			(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action);
@@ -137,29 +141,33 @@
 
     if(actual_menu_content == MENU_SURFACE)
     {
-        switch(line)
-        {
-        case 1:
-        default:
-            openEdit_DateTime();
-        break;
-        case 2:
-           	openEdit_Profile();
-        break;
-        case 3:
-            openEdit_Language();
-        break;
-        case 4:
-            openEdit_Design();
-        break;
-        case 5:
-            openEdit_Information();
-        break;
-        case 6:
-            openEdit_Reset();
-        break;
 
-        }
+    	if(line == get_lineOfID(StMSYS1_DateTime))
+    	{
+    		openEdit_DateTime();
+    	}
+    	else if(line == get_lineOfID(StMSYS2_English))
+    	{
+    		 openEdit_Language();
+    	}
+    	else if(line == get_lineOfID(StMSYS3_Units))
+    	{
+    		openEdit_Design();
+    	}
+    	else if(line == get_lineOfID(StMSYS4_Info))
+    	{
+    		openEdit_Information();
+    	}
+    	else if(line == get_lineOfID(StMSYS5_ResetAll))
+    	{
+    		openEdit_Reset();
+    	}
+#ifdef ENABLE_SETTING_PROFILES
+    	else if(line == get_lineOfID(StMSYS_Profile))
+    	{
+    		openEdit_Profile();
+    	}
+#endif
     }
     else
     {
@@ -919,6 +927,7 @@
 #endif
 }
 
+#ifdef ENABLE_SETTING_PROFILES
 void changeActiveProfil(uint8_t newProfile)
 {
 	SSettings *pSettings = settingsGetPointer();
@@ -992,7 +1001,8 @@
 	}
 	exitMenuEdit(1);
 }
-
+#endif
+#ifdef ENABLE_SETTING_PROFILES
 void openEdit_Profile(void)
 {
 	char text[50];
@@ -1035,7 +1045,7 @@
 
     write_buttonTextline(TXT2BYTE_ButtonBack,TXT2BYTE_ButtonEnter,TXT2BYTE_ButtonNext);
 }
-
+#endif
 
 
 void refresh_Design(void)
@@ -1076,16 +1086,6 @@
     text[1] = 0;
     write_label_var( 400, 700, ME_Y_LINE2, &FontT48, text);
 
-#if 0
-    /* profile */
-    sprintf(text,"Profile:");
-    write_label_var(  30, 300, ME_Y_LINE3, &FontT48, text);
-
-    memset(text,0, sizeof(text));
-    sprintf(text,"%s",pSettings->profileName[pSettings->activeProfile]);
-    tMenuEdit_newInputText(StMSYS_Profile,(uint8_t*)text);
-  //  write_label_var( 400, 700, ME_Y_LINE3, &FontT48, text);
-#endif
 #ifdef HAVE_DEBUG_VIEW
     // specials
     text[0] = TXT_2BYTE;
@@ -1143,6 +1143,7 @@
     return UPDATE_DIVESETTINGS;
 }
 
+#ifdef ENABLE_SETTING_PROFILES
 uint8_t OnAction_SetProfile(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action)
 {
 	SSettings *pSettings = settingsGetPointer();
@@ -1159,6 +1160,7 @@
 	tMenuEdit_newButtonText(editId,(char*)pSettings->profileName[pSettings->activeProfile]);
     return UNSPECIFIC_RETURN;
 }
+
 uint8_t OnAction_Profile(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action)
 {
     SSettings *pSettings = settingsGetPointer();
@@ -1237,7 +1239,7 @@
     }
     return returnValue;
 }
-
+#endif
 
 /*
 uint8_t OnAction_Design_t7ft		(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action)
--- a/Discovery/Src/tMenuSystem.c	Sun Sep 07 20:44:35 2025 +0200
+++ b/Discovery/Src/tMenuSystem.c	Mon Sep 15 21:12:44 2025 +0200
@@ -145,7 +145,7 @@
         strcpy(&text[textPointer],"\n\r");
         textPointer += 2;
     }
-
+#ifdef ENABLE_SETTING_PROFILES
     if((line == 0) || (line == 2))
     {
     	textPointer += snprintf(&text[textPointer], 40,"%c%c:\t%s\n\r",TXT_2BYTE,TXT2BYTE_Profile,data->profileName[data->activeProfile]);
@@ -155,7 +155,12 @@
     	strcpy(&text[textPointer],"\n\r");
     	textPointer += 2;
     }
+#endif
+#ifdef ENABLE_SETTING_PROFILES
     if((line == 0) || (line == 3))
+#else
+    if((line == 0) || (line == 2))
+#endif
     {
         text[textPointer++] = TXT_Language;
         text[textPointer++] = '\t';
@@ -169,8 +174,11 @@
         strcpy(&text[textPointer],"\n\r");
         textPointer += 2;
     }
-
+#ifdef ENABLE_SETTING_PROFILES
     if((line == 0) || (line == 4))
+#else
+    if((line == 0) || (line == 3))
+#endif
     {
         text[textPointer++] = TXT_2BYTE;
         text[textPointer++] = TXT2BYTE_Layout;
@@ -243,7 +251,11 @@
         textPointer += 2;
     }
 
+#ifdef ENABLE_SETTING_PROFILES
     if((line == 0) || (line == 5))
+#else
+    if((line == 0) || (line == 4))
+#endif
     {
         text[textPointer++] = TXT_Information;
         text[textPointer++] = '\t';
@@ -258,7 +270,11 @@
     strcpy(&text[textPointer],"\n\r");
     textPointer += 2;
 
+#ifdef ENABLE_SETTING_PROFILES
     if((line == 0) || (line == 6))
+#else
+    if((line == 0) || (line == 5))
+#endif
     {
         text[textPointer++] = TXT_2BYTE;
         text[textPointer++] = TXT2BYTE_ResetMenu;
--- a/Discovery/Src/text_multilanguage.c	Sun Sep 07 20:44:35 2025 +0200
+++ b/Discovery/Src/text_multilanguage.c	Mon Sep 15 21:12:44 2025 +0200
@@ -2005,6 +2005,18 @@
 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[] = "";
+
+static uint8_t text_EN_Logger[] = "Debug Messages";
+static uint8_t text_DE_Logger[] = "Logger";
+static uint8_t text_FR_Logger[] = "";
+static uint8_t text_IT_Logger[] = "";
+static uint8_t text_ES_Logger[] = "";
+
 /* Lookup Table -------------------------------------------------------------*/
 
 const tText text_array[] =
@@ -2319,6 +2331,8 @@
  	{(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}},
+	{(uint8_t)TXT2BYTE_Logger, 			{text_EN_Logger, text_DE_Logger, text_FR_Logger, text_IT_Logger, text_ES_Logger}},
 
 
 };