changeset 1077:bd8ab302ef4a Icon_Integration

Added uart support for HUD: the protocol implementation for the HUD has been added. It may be activated by the compile switch ENABLE_HUD_SUPPORT. Because the HUD will not mapped to the three classic o2 value display slots, the sensor data structure has been increased to the max number of devices => all devices may now raise device specific data.
author Ideenmodellierer
date Mon, 02 Mar 2026 17:22:25 +0100
parents c87753e73eb8
children 082825daccb5
files Small_CPU/Inc/externalInterface.h Small_CPU/Inc/uart.h Small_CPU/Inc/uartProtocol_HUD.h Small_CPU/Src/externalInterface.c Small_CPU/Src/scheduler.c Small_CPU/Src/uart.c Small_CPU/Src/uartProtocol_HUD.c
diffstat 7 files changed, 421 insertions(+), 61 deletions(-) [+]
line wrap: on
line diff
--- a/Small_CPU/Inc/externalInterface.h	Sun Feb 22 21:23:57 2026 +0100
+++ b/Small_CPU/Inc/externalInterface.h	Mon Mar 02 17:22:25 2026 +0100
@@ -82,6 +82,12 @@
 	DETECTION_SENTINEL,		/* check UART channel for connected Sentinel */
 	DETECTION_SENTINEL2,
 #endif
+#ifdef ENABLE_HUD_SUPPORT
+	DETECTION_HUD_0,
+	DETECTION_HUD_1,
+	DETECTION_HUD_2,
+	DETECTION_HUD_3,
+#endif
 	DETECTION_DONE
  } externalInterfaceAutoDetect_t;
 
@@ -111,6 +117,8 @@
 uint16_t externalInterface_GetCO2SignalStrength(void);
 void externalInterface_SetBottlePressure(uint8_t bottle, uint8_t bar);
 uint8_t externalInterface_GetBottlePressure(uint8_t bottle);
+void externalInterface_GetHUDSequence(uint8_t* pSequence, uint8_t* brightness);
+void externalInterface_SetHUDSequence(uint8_t* pSequence, uint8_t brightness);
 uint8_t externalInterface_GetSensorData(uint8_t sensorId, uint8_t* pDataStruct);
 void externalInterface_SetSensorData(uint8_t sensorId, uint8_t* pDataStruct);
 void externalInface_SetSensorMap(uint8_t* pMap);
--- a/Small_CPU/Inc/uart.h	Sun Feb 22 21:23:57 2026 +0100
+++ b/Small_CPU/Inc/uart.h	Mon Mar 02 17:22:25 2026 +0100
@@ -74,6 +74,9 @@
 #ifdef ENABLE_SENTINEL_MODE
 void UART_HandleSentinelData(void);
 #endif
+#ifdef ENABLE_HUD_SUPPORT
+void UART_HandleHUDData(void);
+#endif
 void UART_SetGnssCtrl(sUartComCtrl* pTarget);
 sUartComCtrl* UART_GetGnssCtrl();
 void UART_clearRxBuffer(sUartComCtrl* pUartCtrl);
@@ -81,6 +84,7 @@
 uint8_t UART_isSentinelConnected();
 void UART_setTargetChannel(uint8_t channel);
 void  UART_MUX_SelectAddress(uint8_t muxAddress);
+void UART_SendCmdRaw(const uint8_t *cmd, uint8_t cmdLength);
 void UART_SendCmdString(uint8_t *cmdString);
 void UART_SendCmdUbx(const uint8_t *cmd, uint8_t len);
 void UART_ReadData(uint8_t sensorType, uint8_t flush);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Small_CPU/Inc/uartProtocol_HUD.h	Mon Mar 02 17:22:25 2026 +0100
@@ -0,0 +1,77 @@
+/**
+  ******************************************************************************
+  * @file    uartProtocol_HUD.h
+  * @author  heinrichs weikamp gmbh
+  * @version V0.0.1
+  * @date    24-Feb-2026
+  * @brief	 Interface functionality to handle external, UART based CO2 sensors
+  *
+  @verbatim
+  ==============================================================================
+                        ##### How to use #####
+  ==============================================================================
+  @endverbatim
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2014 heinrichs weikamp</center></h2>
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef UART_PROTOCOL_HUD_H
+#define UART_PROTOCOL_HUD_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "configuration.h"
+#include "stm32f4xx_hal.h"
+
+
+#define HUD_INFO_DATA_LENGTH		(24u)	/* expected number of received info data */
+#define HUD_MAX_CMD_LENGTH			(32u) 	/* max length for a command sequence */
+
+#define HUD_CMD_BYTE_START			(0xAA)	/* Start byte */
+#define HUD_CMD_BYTE_INFO			(0x10)	/* Request HUD info */
+#define HUD_CMD_BYTE_UPDATE			(0x20)	/* Update LED sequence command */
+#define HUD_CMD_BYTE_STOP			(0x30)	/* Stip LED sequence execution */
+
+ typedef enum
+  {
+	UART_HUD_INIT = 0,		/* Default Status for every sensor type */
+	UART_HUD_IDLE,			/* sensor detected and no communication pending */
+	UART_HUD_ERROR,
+ 	UART_HUD_SETUP = 10,	/* collecting data */
+  	UART_HUD_UPDATE,		/* update the HUD status LEDs */
+	UART_HUD_ABORT,			/* abort status sequence */
+  } uartHUDStatus_t;
+
+  typedef enum
+  {
+  	HUDRX_Ready= 0,					/* Initial state */
+ 	HUDRX_DetectStart,				/* validate start byte */
+  	HUDRX_RXData,
+	HUDRX_CheckSum_L,
+	HUDRX_CheckSum_H,
+ 	HUDRX_DataComplete
+  } receiveStateHUD_t;
+
+
+ typedef enum
+ {
+	HUDCMD_GETINFO = 0,	/* Get HUD info */
+ 	HUDCMD_UPDATE,		/* Update LED sequence */
+ 	HUDCMD_ABORTSEQ		/* Abort LED sequence */
+ } hudSensorCmd_t;
+
+
+void uartHUD_Control(void);
+void uartHUD_ProcessData(uint8_t data);
+void uartHUD_SendCmd(uint8_t HUDCmd);
+uint8_t uartHUD_isSensorConnected();
+
+#endif /* UART_PROTOCOL_HUD_H */
--- a/Small_CPU/Src/externalInterface.c	Sun Feb 22 21:23:57 2026 +0100
+++ b/Small_CPU/Src/externalInterface.c	Mon Mar 02 17:22:25 2026 +0100
@@ -36,6 +36,7 @@
 #include "uartProtocol_Co2.h"
 #include "uartProtocol_Sentinel.h"
 #include "uartProtocol_GNSS.h"
+#include "uartProtocol_HUD.h"
 
 extern SGlobal global;
 extern UART_HandleTypeDef huart1;
@@ -85,9 +86,12 @@
 static float 	externalCO2Scale = 0.0;
 
 static uint8_t externalBottleBar[PRESSURE_BOTTLE_CNT] = {0,0};
+static uint8_t externalHUDBrightness = 0;
+static uint8_t externalHUDSequence[EXT_INTERFACE_HUD_LED_MAX];
+
 
 static uint8_t lastSensorDataId = 0;
-static SSensorDataDiveO2 sensorDataDiveO2[EXT_INTERFACE_SENSOR_CNT];
+static uint8_t sensorData[EXT_INTERFACE_SENSOR_CNT][EXTIF_SENSOR_INFO_SIZE];
 static externalInterfaceAutoDetect_t externalAutoDetect = DETECTION_OFF;
 static externalInterfaceSensorType SensorMap[EXT_INTERFACE_SENSOR_CNT] ={ SENSOR_OPTIC, SENSOR_OPTIC, SENSOR_OPTIC, SENSOR_NONE, SENSOR_NONE};
 static externalInterfaceSensorType tmpSensorMap[EXT_INTERFACE_SENSOR_CNT];
@@ -399,39 +403,12 @@
 
 void externalInterface_SwitchUART(uint8_t protocol)
 {
-	switch(protocol)
+	lastSensorDataId = 0;
+	externalUART_Protocol = protocol;
+	MX_USART1_UART_DeInit();
+	if( protocol != EXT_INTERFACE_UART_OFF)
 	{
-		case EXT_INTERFACE_UART_OFF:
-		case EXT_INTERFACE_UART_CO2:
-		case EXT_INTERFACE_UART_O2:
-		case EXT_INTERFACE_UART_SENTINEL:
-		case EXT_INTERFACE_UART_GNSS:
-				if((externalAutoDetect <= DETECTION_START)
-					|| ((protocol == EXT_INTERFACE_UART_O2) && (externalAutoDetect >= DETECTION_UARTMUX) && (externalAutoDetect <= DETECTION_DIGO2_3))
-
-#ifdef ENABLE_CO2_SUPPORT
-					|| ((externalAutoDetect >= DETECTION_CO2_0) && (externalAutoDetect <= DETECTION_CO2_3))
-#endif
-#ifdef ENABLE_GNSS_EXTERN
-					|| ((externalAutoDetect >= DETECTION_GNSS_0) && (externalAutoDetect <= DETECTION_GNSS_3))
-#endif
-
-#ifdef ENABLE_SENTINEL_MODE
-														   || ((protocol == EXT_INTERFACE_UART_SENTINEL) && (externalAutoDetect == DETECTION_SENTINEL))
-#endif
-					)
-				{
-					lastSensorDataId = 0;
-					externalUART_Protocol = protocol;
-					MX_USART1_UART_DeInit();
-					if( protocol != 0)
-					{
-						MX_USART1_UART_Init();
-					}
-				}
-			break;
-		default:
-			break;
+		MX_USART1_UART_Init();
 	}
 }
 
@@ -509,12 +486,17 @@
 	return externalCO2SignalStrength;
 }
 
-void externalInterface_SetBottlePressure(uint8_t bottle, uint8_t bar)
+
+void externalInterface_GetHUDSequence(uint8_t* pSequence, uint8_t* brightness)
 {
-	if(bottle < PRESSURE_BOTTLE_CNT)
-	{
-		externalBottleBar[bottle] = bar;
-	}
+	memcpy(pSequence, externalHUDSequence, EXT_INTERFACE_HUD_LED_MAX);
+	*brightness = externalHUDBrightness;
+}
+
+void externalInterface_SetHUDSequence(uint8_t* pSequence, uint8_t brightness)
+{
+	memcpy(externalHUDSequence, pSequence, EXT_INTERFACE_HUD_LED_MAX);
+	externalHUDBrightness = brightness;
 }
 
 uint8_t externalInterface_GetBottlePressure(uint8_t bottle)
@@ -528,6 +510,30 @@
 	return ret;
 }
 
+void externalInterface_SetBottlePressure(uint8_t bottle, uint8_t bar)
+{
+	if(bottle < PRESSURE_BOTTLE_CNT)
+	{
+		externalBottleBar[bottle] = bar;
+	}
+}
+
+void externalInterface_CopySensorData(uint8_t sensorId, uint8_t* target, uint8_t* source)
+{
+	if(sensorId < EXT_INTERFACE_SENSOR_CNT)
+	{
+		switch(SensorMap[sensorId])
+		{
+			case SENSOR_DIGO2M:
+			case SENSOR_DIGO2:	memcpy(target, source, sizeof(SSensorDataDiveO2));
+				break;
+			case SENSOR_HUD:	memcpy(target, source, HUD_INFO_DATA_LENGTH);
+				break;
+			default:
+			break;
+		}
+	}
+}
 
 uint8_t externalInterface_GetSensorData(uint8_t sensorId, uint8_t* pDataStruct)
 {
@@ -540,7 +546,7 @@
 
 	if((pDataStruct != NULL) && (localId <= EXT_INTERFACE_SENSOR_CNT))
 	{
-		memcpy(pDataStruct, &sensorDataDiveO2[localId], sizeof(SSensorDataDiveO2));
+		externalInterface_CopySensorData(localId, pDataStruct, &sensorData[localId][0]);
 	}
 	else
 	{
@@ -568,7 +574,7 @@
 	{
 		if((sensorId != 0xFF) && (sensorId < EXT_INTERFACE_SENSOR_CNT))
 		{
-			memcpy(&sensorDataDiveO2[sensorId], pDataStruct, sizeof(SSensorDataDiveO2));
+			externalInterface_CopySensorData(sensorId, &sensorData[sensorId][0], pDataStruct);
 			lastSensorDataId = sensorId;
 			if(sensorId >= MAX_ADC_CHANNEL)
 			{
@@ -576,7 +582,7 @@
 				{
 					if(Mux2ADCMap[index] == sensorId)
 					{
-						memcpy(&sensorDataDiveO2[index], pDataStruct, sizeof(SSensorDataDiveO2));
+						externalInterface_CopySensorData(index, &sensorData[index][0], pDataStruct);
 						lastSensorDataId = index;
 						break;
 					}
@@ -585,7 +591,7 @@
 		}
 		else
 		{
-			memset(&sensorDataDiveO2,0,sizeof(sensorDataDiveO2));
+			memset(&sensorData,0,EXTIF_SENSOR_INFO_SIZE * EXT_INTERFACE_SENSOR_CNT);
 			lastSensorDataId = 0xFF;
 		}
 	}
@@ -858,13 +864,17 @@
 									{
 
 
-#if defined ENABLE_SENTINEL_MODE || defined ENABLE_GNSS_EXTERN
+#if defined ENABLE_SENTINEL_MODE || defined ENABLE_GNSS_EXTERN || defined ENABLE_HUD_SUPPORT
 #ifdef ENABLE_GNSS_EXTERN
 										externalAutoDetect = DETECTION_GNSS_0;
 										externalInterface_SwitchUART(EXT_INTERFACE_UART_GNSS);
 #else
 #ifdef ENABLE_SENTINEL_MODE
 										externalAutoDetect = DETECTION_SENTINEL;
+#else
+#ifdef ENABLE_HUD_SUPPORT
+										externalAutoDetect = DETECTION_HUD_0;
+#endif
 #endif
 #endif
 #else
@@ -958,6 +968,51 @@
 									}
 									externalAutoDetect++;
 #endif
+
+#ifdef ENABLE_HUD_SUPPORT
+									if(externalAutoDetect == DETECTION_HUD_0)
+									{
+										tmpSensorMap[uartMuxChannel + EXT_INTERFACE_MUX_OFFSET] = SENSOR_NONE;
+										if(foundSensorMap[EXT_INTERFACE_SENSOR_CNT-1] == SENSOR_MUX)
+										{
+											externalInterface_CheckBaudrate(SENSOR_DIGO2);
+											UART_MUX_SelectAddress(0);
+										}
+										activeUartChannel = 0;
+										tmpSensorMap[uartMuxChannel - 1 + EXT_INTERFACE_MUX_OFFSET] = SENSOR_NONE;
+										uartMuxChannel = 1;
+										tmpSensorMap[EXT_INTERFACE_MUX_OFFSET] = SENSOR_HUD;
+										externalInterface_SensorState[EXT_INTERFACE_MUX_OFFSET] = UART_COMMON_INIT;
+										externalInterface_CheckBaudrate(SENSOR_HUD);
+										externalInterfaceMuxReqIntervall = 500;	/* iterations needed for module config */
+									}
+							break;
+			case DETECTION_HUD_0:
+			case DETECTION_HUD_1:
+			case DETECTION_HUD_2:
+			case DETECTION_HUD_3:
+										if(uartHUD_isSensorConnected())
+										{
+											foundSensorMap[EXT_INTERFACE_MUX_OFFSET + activeUartChannel] = SENSOR_HUD;
+											externalAutoDetect = DETECTION_DONE;		/* only one HUD sensor supported */
+										}
+										else if(foundSensorMap[EXT_INTERFACE_SENSOR_CNT-1] == SENSOR_MUX)
+										{
+											externalInterface_CheckBaudrate(SENSOR_DIGO2);
+											UART_MUX_SelectAddress(uartMuxChannel);
+											activeUartChannel = uartMuxChannel;
+											tmpSensorMap[uartMuxChannel - 1 + EXT_INTERFACE_MUX_OFFSET] = SENSOR_NONE;
+											tmpSensorMap[EXT_INTERFACE_MUX_OFFSET + uartMuxChannel] = SENSOR_CO2;
+											externalInterface_SensorState[EXT_INTERFACE_MUX_OFFSET + uartMuxChannel] = UART_COMMON_INIT;
+											externalInterface_CheckBaudrate(SENSOR_HUD);
+											externalAutoDetect++;
+											uartMuxChannel++;
+										}
+										else
+										{
+											externalAutoDetect = DETECTION_DONE;
+										}
+#endif
 				break;
 			case DETECTION_DONE:	externalAutoDetect = DETECTION_OFF;
 									externalInterface_SwitchUART(EXT_INTERFACE_UART_OFF);
@@ -971,7 +1026,7 @@
 											cntSensor++;
 										}
 
-										if((foundSensorMap[index] == SENSOR_DIGO2) || (foundSensorMap[index] == SENSOR_CO2) || (foundSensorMap[index] == SENSOR_GNSS))
+										if((foundSensorMap[index] == SENSOR_DIGO2) || (foundSensorMap[index] == SENSOR_CO2) || (foundSensorMap[index] == SENSOR_GNSS) || (foundSensorMap[index] == SENSOR_HUD))
 										{
 											cntUARTSensor++;
 										}
@@ -986,23 +1041,22 @@
 									}
 									externalInface_MapUartToLegacyADC(foundSensorMap);
 									externalInterfaceMuxReqIntervall = 0xFFFF;
-									if(cntSensor == 0)		/* return default sensor map if no sensor at all has been detected */
+									if((cntSensor == 0)		/* return default sensor map if no sensor at all has been detected */
+										|| ((foundSensorMap[0] == SENSOR_NONE) && (foundSensorMap[1] == SENSOR_NONE) && (foundSensorMap[2] == SENSOR_NONE)))
 									{
 										foundSensorMap[0] = SENSOR_OPTIC;
 										foundSensorMap[1] = SENSOR_OPTIC;
 										foundSensorMap[2] = SENSOR_OPTIC;
 									}
-									else
+									if(cntUARTSensor != 0)
 									{
-										if(cntUARTSensor != 0)
+										externalInterfaceMuxReqIntervall = REQUEST_INT_SENSOR_MS / cntUARTSensor;
+										if(foundSensorMap[0] == SENSOR_SENTINELM)	/* special case: Sentinel sends combined data */
 										{
-											externalInterfaceMuxReqIntervall = REQUEST_INT_SENSOR_MS / cntUARTSensor;
-											if(foundSensorMap[0] == SENSOR_SENTINELM)	/* special case: Sentinel sends combined data */
-											{
-												externalInterfaceMuxReqIntervall = 4000;
-											}
+											externalInterfaceMuxReqIntervall = 4000;
 										}
 									}
+
 									memcpy(SensorMap, foundSensorMap, sizeof(foundSensorMap));
 									memset(externalInterface_SensorState, UART_COMMON_INIT, sizeof(externalInterface_SensorState));
 				break;
@@ -1075,7 +1129,20 @@
 											externalInterface_SensorState[index] = UART_O2_CHECK;
 										}
 			break;
-
+#ifdef ENABLE_HUD_SUPPORT
+		case EXT_INTERFACE_HUD_UPDATE:	index = (Cmd >> 8) & 0x000F;
+										if(SensorMap[index] == SENSOR_HUD)
+										{
+											externalInterface_SensorState[index] = UART_HUD_UPDATE;
+										}
+					break;
+		case EXT_INTERFACE_HUD_ABORT:	index = (Cmd >> 8) & 0x000F;
+										if(SensorMap[index] == SENSOR_HUD)
+										{
+											externalInterface_SensorState[index] = UART_HUD_ABORT;
+										}
+					break;
+#endif
 		default:
 			break;
 	}
@@ -1101,7 +1168,8 @@
 		}
 		if(((pmap[index + EXT_INTERFACE_MUX_OFFSET] == SENSOR_DIGO2)
 				|| (pmap[index + EXT_INTERFACE_MUX_OFFSET] == SENSOR_CO2)
-				|| (pmap[index + EXT_INTERFACE_MUX_OFFSET] == SENSOR_GNSS))
+				|| (pmap[index + EXT_INTERFACE_MUX_OFFSET] == SENSOR_GNSS)
+				|| (pmap[index + EXT_INTERFACE_MUX_OFFSET] == SENSOR_HUD))
 				&& (index != activeUartChannel))
 		{
 			newChannel = index;
@@ -1122,6 +1190,7 @@
 			case SENSOR_SENTINEL:
 			case SENSOR_CO2:		newBaudrate = 9600;
 				break;
+			case SENSOR_HUD:
 			case SENSOR_DIGO2:
 		default:	newBaudrate = 19200;
 			break;
@@ -1286,6 +1355,10 @@
 				case SENSOR_SENTINEL: uartSentinel_Control();
 				break;
 #endif
+#ifdef ENABLE_HUD_SUPPORT
+				case SENSOR_HUD: uartHUD_Control();
+				break;
+#endif
 				default:
 					break;
 			}
--- a/Small_CPU/Src/scheduler.c	Sun Feb 22 21:23:57 2026 +0100
+++ b/Small_CPU/Src/scheduler.c	Mon Mar 02 17:22:25 2026 +0100
@@ -336,7 +336,10 @@
 	{
 		externalInterface_SwitchADC(1-externalInterface_isEnabledADC());
 	}
-
+	if((global.dataSendToSlave.data.externalInterface_Cmd & 0x00FF) == EXT_INTERFACE_HUD_UPDATE)	/* update HUD sequence */
+	{
+		externalInterface_SetHUDSequence(global.dataSendToSlave.data.externalInterface_HUD_Update, global.dataSendToSlave.data.externalInterface_HUD_Brightness);
+	}
 	externalInface_SetSensorMap(global.dataSendToSlave.data.externalInterface_SensorMap);
 	if(global.dataSendToSlave.data.externalInterface_Cmd & 0x00FF)	/* lowest nibble for commands */
 	{
--- a/Small_CPU/Src/uart.c	Sun Feb 22 21:23:57 2026 +0100
+++ b/Small_CPU/Src/uart.c	Mon Mar 02 17:22:25 2026 +0100
@@ -24,6 +24,7 @@
 #include "uartProtocol_Co2.h"
 #include "uartProtocol_Sentinel.h"
 #include "uartProtocol_GNSS.h"
+#include "uartProtocol_HUD.h"
 #include "externalInterface.h"
 #include "data_exchange.h"
 #include "gpio.h"
@@ -199,11 +200,8 @@
 	}
 }
 
-
-void UART_SendCmdString(uint8_t *cmdString)
+void UART_SendCmdRaw(const uint8_t *cmd, uint8_t cmdLength)
 {
-	uint8_t cmdLength = strlen((char*)cmdString);
-
 	if(Uart1Ctrl.dmaTxActive == 0)
 	{
 		if(cmdLength < TX_BUF_SIZE)		/* A longer string is an indication for a missing 0 termination */
@@ -212,7 +210,7 @@
 			{
 				UART_StartDMA_Receiption(&Uart1Ctrl);
 			}
-			memcpy(txBuffer, cmdString, cmdLength);
+			memcpy(txBuffer, cmd, cmdLength);
 			if(HAL_OK == HAL_UART_Transmit_DMA(&huart1,txBuffer,cmdLength))
 			{
 				Uart1Ctrl.dmaTxActive = 1;
@@ -222,11 +220,18 @@
 	}
 	else
 	{
-		memcpy(txBufferQue, cmdString, cmdLength);
+		memcpy(txBufferQue, cmd, cmdLength);
 		Uart1Ctrl.txBufferQueLen = cmdLength;
 	}
 }
 
+void UART_SendCmdString(uint8_t *cmdString)
+{
+	uint8_t cmdLength = strlen((char*)cmdString);
+
+	UART_SendCmdRaw(cmdString, cmdLength);
+}
+
 void UART_AddFletcher(uint8_t* pBuffer, uint8_t length)
 {
 	uint8_t ck_A = 0;
@@ -459,6 +464,10 @@
 					case SENSOR_SENTINEL:	uartSentinel_ProcessData(pUartCtrl->pRxBuffer[localRX]);
 						break;
 #endif
+#ifdef ENABLE_HUD_SUPPORT
+					case SENSOR_HUD:	uartHUD_ProcessData(pUartCtrl->pRxBuffer[localRX]);
+						break;
+#endif
 					default:
 						break;
 				}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Small_CPU/Src/uartProtocol_HUD.c	Mon Mar 02 17:22:25 2026 +0100
@@ -0,0 +1,186 @@
+/**
+  ******************************************************************************
+  * @file    uartProtocol_HUD.c
+  * @author  heinrichs weikamp gmbh
+  * @version V0.0.1
+  * @date    24-Feb-2026
+  * @brief   Interface functionality to external, UART based HUD
+  *
+  @verbatim
+
+
+  @endverbatim
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2023 heinrichs weikamp</center></h2>
+  *
+  ******************************************************************************
+  */
+/* Includes ------------------------------------------------------------------*/
+
+#include <string.h>
+#include <uartProtocol_HUD.h>
+#include "uart.h"
+#include "externalInterface.h"
+
+#ifdef ENABLE_HUD_SUPPORT
+static uint8_t HUDConnected = 0;						/* Binary indicator if a sensor is connected or not */
+static receiveStateHUD_t rxState = HUDRX_Ready;
+
+
+
+void uartHUD_SendCmd(uint8_t HUDCmd)
+{
+	uint8_t cmdLength = 0;
+	uint8_t cmdBuf[HUD_MAX_CMD_LENGTH];
+	uint8_t index = 0;
+	uint16_t checkSum = 0;
+
+	cmdBuf[0] = HUD_CMD_BYTE_START;
+	switch (HUDCmd)
+	{
+		case HUDCMD_GETINFO:	cmdBuf[1] = HUD_CMD_BYTE_INFO;
+								cmdLength = 1;
+				break;
+		case HUDCMD_UPDATE:		cmdBuf[1] = HUD_CMD_BYTE_UPDATE;
+								externalInterface_GetHUDSequence(&cmdBuf[3],&cmdBuf[2]);
+								cmdLength = 19;
+				break;
+		case HUDCMD_ABORTSEQ:	cmdBuf[1] = HUD_CMD_BYTE_STOP;
+								cmdLength = 1;
+				break;
+		default: cmdLength = 0;
+			break;
+	}
+	if(cmdLength != 0)
+	{
+		cmdLength++; 	/* add Startbyte */
+		for(index = 0; index < cmdLength; index++)
+		{
+			if(index > 2)		/* hard coded number of pulses = 2 */
+			{
+				cmdBuf[index] |= 0x10;
+			}
+			checkSum += cmdBuf[index];
+		}
+		cmdBuf[cmdLength++] = (checkSum & 0x00FF);	/* low byte */
+		cmdBuf[cmdLength++] = (checkSum >> 8);		/* high byte */
+		UART_SendCmdRaw(cmdBuf,cmdLength);
+	}
+}
+
+
+void uartHUD_Control(void)
+{
+	static uint8_t cmdString[20];
+	static uint8_t cmdLength = 0;
+	static uint8_t lastComState = UART_HUD_INIT;
+
+	uint8_t activeSensor = externalInterface_GetActiveUartSensor();
+	uartHUDStatus_t localComState = externalInterface_GetSensorState(activeSensor + EXT_INTERFACE_MUX_OFFSET);
+
+	if(localComState == UART_HUD_ERROR)
+	{
+		localComState = lastComState;
+	}
+
+	switch(localComState)
+	{
+		case UART_HUD_INIT:		HUDConnected = 0;
+								UART_ReadData(SENSOR_HUD, 1);	/* flush buffer */
+								UART_StartDMA_Receiption(&Uart1Ctrl);
+								localComState = UART_HUD_SETUP;
+								uartHUD_SendCmd(HUDCMD_GETINFO);
+			break;
+		case UART_HUD_SETUP:	uartHUD_SendCmd(HUDCMD_GETINFO);
+								rxState = HUDRX_DetectStart;
+			break;
+		case UART_HUD_UPDATE:	uartHUD_SendCmd(HUDCMD_UPDATE);
+								rxState = HUDRX_Ready;
+			break;
+		case UART_HUD_ABORT:	uartHUD_SendCmd(HUDCMD_ABORTSEQ);
+								rxState = HUDRX_Ready;
+			break;
+		default:				if(cmdLength != 0)
+								{
+									UART_SendCmdString(cmdString);		/* resend last command */
+									cmdLength = 0;
+								}
+			break;
+	}
+	lastComState = localComState;
+	externalInterface_SetSensorState(activeSensor + EXT_INTERFACE_MUX_OFFSET,localComState);
+}
+
+void uartHUD_ProcessData(uint8_t data)
+{
+	static uint8_t dataValue[HUD_INFO_DATA_LENGTH];
+	static uint8_t dataIndex = 0;
+	static uint16_t checkSum = 0;
+	static uint16_t rxCheckSum = 0;
+	uint8_t activeSensor = externalInterface_GetActiveUartSensor();
+	uartHUDStatus_t localComState = externalInterface_GetSensorState(activeSensor + EXT_INTERFACE_MUX_OFFSET);
+
+	if((localComState == UART_HUD_SETUP) && (rxState == HUDRX_Ready))
+	{
+		rxState = HUDRX_DetectStart;
+	}
+	switch(rxState)
+	{
+		case HUDRX_DetectStart:	if(data == 0xAA)
+								{
+									dataIndex = 0;
+									memset(dataValue,0,HUD_INFO_DATA_LENGTH);
+									dataValue[dataIndex++] = data;
+									checkSum = data;
+									rxState = HUDRX_RXData;
+								}
+			break;
+		case HUDRX_RXData:		dataValue[dataIndex++] = data;
+								checkSum += data;
+								if(dataIndex == HUD_INFO_DATA_LENGTH)
+								{
+									rxState = HUDRX_CheckSum_L;
+								}
+			break;
+		case HUDRX_CheckSum_L:	rxCheckSum = data;
+								rxState++;
+			break;
+		case HUDRX_CheckSum_H:	rxCheckSum |= (data << 8);
+								if(checkSum == rxCheckSum)
+								{
+									HUDConnected = 1;
+									if(localComState == UART_HUD_SETUP)
+									{
+										externalInterface_SetSensorData(activeSensor + EXT_INTERFACE_MUX_OFFSET, &dataValue[1]);
+										localComState = UART_HUD_ABORT;		/* reset default sequence */
+									}
+								}
+								rxState = HUDRX_DetectStart;
+			break;
+		default:				if(data == 'K')		/* OK respond from HUD */
+								{
+									localComState = UART_HUD_IDLE;
+								}
+								if(data == 'N')		/* NOK respond from HUD */
+								{
+									localComState = UART_HUD_ERROR;
+								}
+								if(data == 0xff)
+								{
+									localComState = UART_HUD_IDLE;
+								}
+			break;
+	}
+
+	externalInterface_SetSensorState(activeSensor + EXT_INTERFACE_MUX_OFFSET,localComState);
+}
+
+uint8_t uartHUD_isSensorConnected()
+{
+	return HUDConnected;
+}
+
+#endif
+