changeset 798:e9eba334b942

Migrated CO2 protocol implementation to new format: The previous implementation was a monolithic protocol implementation which was not usable together with the multiplexer. The new implementation moves the CO2 implementation into a separate C file and decoubles the upper layer external interface, which is not able to handle DiveO2 and CO2 sensors in parallel without restriction to port assignments.
author Ideenmodellierer
date Mon, 07 Aug 2023 20:29:44 +0200
parents acf6614dc396
children 1e3c12d772eb
files Small_CPU/Inc/externalInterface.h Small_CPU/Inc/uart.h Small_CPU/Inc/uartProtocol_Co2.h Small_CPU/Inc/uartProtocol_O2.h Small_CPU/Src/externalInterface.c Small_CPU/Src/uart.c Small_CPU/Src/uartProtocol_Co2.c Small_CPU/Src/uartProtocol_O2.c
diffstat 8 files changed, 446 insertions(+), 280 deletions(-) [+]
line wrap: on
line diff
--- a/Small_CPU/Inc/externalInterface.h	Mon Jul 31 20:10:27 2023 +0200
+++ b/Small_CPU/Inc/externalInterface.h	Mon Aug 07 20:29:44 2023 +0200
@@ -41,7 +41,7 @@
 #define MIN_ADC_VOLTAGE_MV	(5.0f)		/* miminal voltage to rate an ADC channel as active */
 
 #define COMMON_SENSOR_STATE_INIT	(0x0u)	/* All individual state definitions shall start with a INIT state = 0 */
-#define COMMON_SENSOR_STATE_INVALID (0xFFu) /* All individual state devinitions shall not use 0xFF for operation control */
+#define COMMON_SENSOR_STATE_INVALID (0xFFu) /* All individual state definitions shall not use 0xFF for operation control */
 
  typedef enum
  {
@@ -56,7 +56,10 @@
 	DETECTION_DIGO2_2,
 	DETECTION_DIGO2_3,
 #ifdef ENABLE_CO2_SUPPORT
-	DETECTION_CO2,			/* check UART channel for connected CO2 sensor */
+	DETECTION_CO2_0,			/* check UART channel for connected CO2 sensor */
+	DETECTION_CO2_1,
+	DETECTION_CO2_2,
+	DETECTION_CO2_3,
 #endif
 #ifdef ENABLE_SENTINEL_MODE
 	DETECTION_SENTINEL,		/* check UART channel for connected Sentinel */
--- a/Small_CPU/Inc/uart.h	Mon Jul 31 20:10:27 2023 +0200
+++ b/Small_CPU/Inc/uart.h	Mon Aug 07 20:29:44 2023 +0200
@@ -25,47 +25,9 @@
 #include "stm32f4xx_hal.h"
 
 
-#define BUFFER_NODATA			(7u)		/* The read function needs a byte which indecated that no data for processing is available.*/
+#define BUFFER_NODATA			(7u)		/* The read function needs a byte which indicated that no data for processing is available.*/
 											/* This byte shall never appear in a normal data steam */
 
- typedef enum
- {
- 	UART_CO2_INIT = 0,
-	UART_CO2_SETUP,			/* collecting data needed to be read out of the sensor once at startup */
- 	UART_CO2_OPERATING,		/* normal operation */
- } uartCO2Status_t;
-
- typedef enum
- {
- 	RX_Ready= 0,					/* Initial state */
-	RX_DetectStart,					/* validate start byte */
-	RX_SelectData,					/* Data contained in this frame */
- 	RX_Data0,						/* Process incoming data */
-	RX_Data1,
-	RX_Data2,
-	RX_Data3,
-	RX_Data4,
-	RX_Data5,
-	RX_Data6,
-	RX_Data7,
-	RX_Data8,
-	RX_Data9,
-	RX_Data10,
-	RX_Data11,
-	RX_Data12,
-	RX_DataComplete
- } receiveState_t;
-
-
-typedef enum
-{
-	CO2CMD_MODE_POLL,		/* Set operation mode of sensor to polling => only send data if requested */
-	CO2CMD_MODE_STREAM,		/* Set operation mode of sensor to streaming => send data every two seconds */
-	CO2CMD_CALIBRATE,		/* Calibrate sensor */
-	CO2CMD_GETSCALE,		/* Get scaling factor */
-	CO2CMD_GETDATA			/* Read sensor data */
-} co2SensorCmd_t;
-
 void MX_USART1_UART_Init(void);
 void MX_USART1_UART_DeInit(void);
 void MX_USART1_DMA_Init(void);
@@ -85,7 +47,7 @@
 void UART_SendCmdString(uint8_t *cmdString);
 void UART_ReadData(uint8_t sensorType);
 void UART_FlushRxBuffer(void);
-
+void UART_ChangeBaudrate(uint32_t newBaudrate);
 
 void StringToInt(char *pstr, uint32_t *puInt32);
 void StringToUInt64(char *pstr, uint64_t *puint64);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Small_CPU/Inc/uartProtocol_Co2.h	Mon Aug 07 20:29:44 2023 +0200
@@ -0,0 +1,81 @@
+/**
+  ******************************************************************************
+  * @file    uartProtocol_Co2.h
+  * @author  heinrichs weikamp gmbh
+  * @version V0.0.1
+  * @date    31-Jul-2023
+  * @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_CO2_H
+#define UART_PROTOCOL_CO2_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "configuration.h"
+#include "stm32f4xx_hal.h"
+
+ typedef enum
+  {
+	UART_CO2_INIT = 0,		/* Default Status for every sensor type */
+	UART_CO2_IDLE,			/* sensor detected and no communication pending */
+	UART_CO2_ERROR,
+ 	UART_CO2_SETUP = 10,	/* collecting data needed to be read out of the sensor once at startup */
+  	UART_CO2_OPERATING,		/* normal operation */
+	UART_CO2_CALIBRATE		/* request calibration */
+  } uartCO2Status_t;
+
+  typedef enum
+  {
+  	RX_Ready= 0,					/* Initial state */
+ 	RX_DetectStart,					/* validate start byte */
+ 	RX_SelectData,					/* Data contained in this frame */
+  	RX_Data0,						/* Process incoming data */
+ 	RX_Data1,
+ 	RX_Data2,
+ 	RX_Data3,
+ 	RX_Data4,
+ 	RX_Data5,
+ 	RX_Data6,
+ 	RX_Data7,
+ 	RX_Data8,
+ 	RX_Data9,
+ 	RX_Data10,
+ 	RX_Data11,
+ 	RX_Data12,
+ 	RX_DataComplete
+  } receiveState_t;
+
+
+ typedef enum
+ {
+ 	CO2CMD_MODE_POLL,		/* Set operation mode of sensor to polling => only send data if requested */
+ 	CO2CMD_MODE_STREAM,		/* Set operation mode of sensor to streaming => send data every two seconds */
+ 	CO2CMD_CALIBRATE,		/* Calibrate sensor */
+ 	CO2CMD_GETSCALE,		/* Get scaling factor */
+ 	CO2CMD_GETDATA			/* Read sensor data */
+ } co2SensorCmd_t;
+
+
+void uartCo2_Control(void);
+void uartCo2_ProcessData(uint8_t data);
+void uartCo2_SendCmd(uint8_t CO2Cmd, uint8_t *cmdString, uint8_t *cmdLength);
+uint8_t uartCo2_isSensorConnected();
+
+#endif /* UART_PROTOCOL_CO2_H */
--- a/Small_CPU/Inc/uartProtocol_O2.h	Mon Jul 31 20:10:27 2023 +0200
+++ b/Small_CPU/Inc/uartProtocol_O2.h	Mon Aug 07 20:29:44 2023 +0200
@@ -31,17 +31,23 @@
 #include "configuration.h"
 #include "stm32f4xx_hal.h"
 
+ typedef enum
+ {
+ 	UART_COMMON_INIT = 0,	/* Default Status for every sensor type */
+	UART_COMMON_IDLE,		/* sensor detected and no communication pending */
+	UART_COMMON_ERROR,		/* Error message received from sensor */
+ } uartCommonStatus_t;
 
  typedef enum
  {
- 	UART_O2_INIT = 0,
- 	UART_O2_CHECK,			/* send blink command and check if sensor answers */
- 	UART_O2_REQ_INFO,		/* request information about available internal sensors of sensor */
-	UART_O2_REQ_ID,			/* request ID of sensor */
- 	UART_O2_IDLE,			/* sensor detected and no communication pending */
- 	UART_O2_REQ_O2,			/* O2 value has been requested and is in receiption progress */
-	UART_O2_REQ_RAW,		/* Request O2 and extended raw data */
- 	UART_O2_ERROR			/* Error message received from sensor */
+	UART_O2_INIT = UART_COMMON_INIT,		/* Default Status for every sensor type */
+	UART_O2_IDLE = UART_COMMON_IDLE,		/* sensor detected and no communication pending */
+	UART_O2_ERROR = UART_COMMON_ERROR,		/* Error message received from sensor */
+ 	UART_O2_CHECK,							/* send blink command and check if sensor answers */
+ 	UART_O2_REQ_INFO,						/* request information about available internal sensors of sensor */
+	UART_O2_REQ_ID,							/* request ID of sensor */
+ 	UART_O2_REQ_O2,							/* O2 value has been requested and is in receiption progress */
+	UART_O2_REQ_RAW,						/* Request O2 and extended raw data */
  } uartO2Status_t;
 
 
--- a/Small_CPU/Src/externalInterface.c	Mon Jul 31 20:10:27 2023 +0200
+++ b/Small_CPU/Src/externalInterface.c	Mon Aug 07 20:29:44 2023 +0200
@@ -33,6 +33,7 @@
 #include "data_exchange.h"
 #include "pressure.h"
 #include "uartProtocol_O2.h"
+#include "uartProtocol_Co2.h"
 
 extern SGlobal global;
 extern UART_HandleTypeDef huart1;
@@ -133,7 +134,7 @@
 	{
 		externalChannel_mV[index] = 0.0;
 	}
-	memset(externalInterface_SensorState,UART_O2_INIT,sizeof(externalInterface_SensorState));
+	memset(externalInterface_SensorState,UART_COMMON_INIT,sizeof(externalInterface_SensorState));
 }
 
 
@@ -363,13 +364,10 @@
 		case (EXT_INTERFACE_UART_O2 >> 8):
 		case (EXT_INTERFACE_UART_SENTINEL >> 8):
 				if((externalAutoDetect <= DETECTION_START)
-															|| ((protocol == EXT_INTERFACE_UART_O2 >> 8) && (externalAutoDetect == DETECTION_DIGO2_0))
-															|| ((protocol == EXT_INTERFACE_UART_O2 >> 8) && (externalAutoDetect == DETECTION_DIGO2_1))
-															|| ((protocol == EXT_INTERFACE_UART_O2 >> 8) && (externalAutoDetect == DETECTION_DIGO2_2))
-															|| ((protocol == EXT_INTERFACE_UART_O2 >> 8) && (externalAutoDetect == DETECTION_DIGO2_3))
-															|| ((protocol == EXT_INTERFACE_UART_O2 >> 8) && (externalAutoDetect == DETECTION_UARTMUX))
+					|| ((protocol == EXT_INTERFACE_UART_O2 >> 8) && (externalAutoDetect >= DETECTION_UARTMUX) && (externalAutoDetect <= DETECTION_DIGO2_3))
+
 #ifdef ENABLE_CO2_SUPPORT
-															|| ((protocol == EXT_INTERFACE_UART_CO2 >> 8) && (externalAutoDetect == DETECTION_CO2))
+					|| ((externalAutoDetect >= DETECTION_CO2_0) && (externalAutoDetect <= DETECTION_CO2_3))
 #endif
 #ifdef ENABLE_SENTINEL_MODE
 														   || ((protocol == EXT_INTERFACE_UART_SENTINEL >> 8) && (externalAutoDetect == DETECTION_SENTINEL))
@@ -566,8 +564,10 @@
 	uint8_t index2 = 0;
 	uint8_t cntSensor = 0;
 	uint8_t cntUARTSensor = 0;
+#ifdef ENABLE_CO2_SUPPORT
 	uint8_t cmdString[10];
 	uint8_t cmdLength = 0;
+#endif
 
 	if(externalAutoDetect != DETECTION_OFF)
 	{
@@ -583,7 +583,7 @@
 									tmpSensorMap[4] = SENSOR_NONE;
 
 									memset(foundSensorMap, SENSOR_NONE, sizeof(foundSensorMap));
-									memset(externalInterface_SensorState,UART_O2_INIT,sizeof(externalInterface_SensorState));
+									memset(externalInterface_SensorState,UART_COMMON_INIT,sizeof(externalInterface_SensorState));
 									memset(Mux2ADCMap,0, sizeof(Mux2ADCMap));
 
 									if(externalInterfacePresent)
@@ -640,12 +640,11 @@
 											tmpSensorMap[EXT_INTERFACE_SENSOR_CNT-1] = SENSOR_NONE;
 										}
 										externalAutoDetect = DETECTION_DIGO2_0;
-										externalInterface_SwitchUART(EXT_INTERFACE_UART_O2 >> 8);
 										UART_MUX_SelectAddress(0);
 										uartO2_SetChannel(0);
 										activeUartChannel = 0;
 										tmpSensorMap[EXT_INTERFACE_MUX_OFFSET] = SENSOR_DIGO2;
-										externalInterface_SensorState[EXT_INTERFACE_MUX_OFFSET] = UART_O2_INIT;
+										externalInterface_SensorState[EXT_INTERFACE_MUX_OFFSET] = UART_COMMON_INIT;
 										externalInterface_SwitchUART(EXT_INTERFACE_UART_O2 >> 8);
 				break;
 			case DETECTION_DIGO2_0:
@@ -661,7 +660,7 @@
 									{
 										externalInterface_SwitchUART(EXT_INTERFACE_UART_O2 >> 8);
 										UART_MUX_SelectAddress(uartMuxChannel);
-										externalInterface_SensorState[uartMuxChannel + EXT_INTERFACE_MUX_OFFSET] = UART_O2_INIT;
+										externalInterface_SensorState[uartMuxChannel + EXT_INTERFACE_MUX_OFFSET] = UART_COMMON_INIT;
 										uartO2_SetChannel(uartMuxChannel);
 										activeUartChannel = uartMuxChannel;
 										tmpSensorMap[uartMuxChannel - 1 + EXT_INTERFACE_MUX_OFFSET] = SENSOR_NONE;
@@ -678,39 +677,50 @@
 									}
 									externalAutoDetect++;
 #ifdef ENABLE_CO2_SUPPORT
-									if(externalAutoDetect == DETECTION_CO2)
+									if(externalAutoDetect == DETECTION_CO2_0)
 									{
+										UART_MUX_SelectAddress(0);
+										activeUartChannel = 0;
+										tmpSensorMap[uartMuxChannel - 1 + EXT_INTERFACE_MUX_OFFSET] = SENSOR_NONE;
+										uartMuxChannel = 1;
+										tmpSensorMap[EXT_INTERFACE_MUX_OFFSET] = SENSOR_CO2;
+										externalInterface_SensorState[EXT_INTERFACE_MUX_OFFSET] = UART_COMMON_INIT;
 										externalInterface_SwitchUART(EXT_INTERFACE_UART_CO2 >> 8);
 										if(tmpSensorMap[EXT_INTERFACE_SENSOR_CNT-1] == SENSOR_MUX)		/* switch sensor operation mode depending on HW config */
 										{
-											DigitalCO2_SendCmd(CO2CMD_MODE_POLL, cmdString, &cmdLength);
+											uartCo2_SendCmd(CO2CMD_MODE_POLL, cmdString, &cmdLength);
 										}
 										else
 										{
-											DigitalCO2_SendCmd(CO2CMD_MODE_STREAM, cmdString, &cmdLength);
+											uartCo2_SendCmd(CO2CMD_MODE_STREAM, cmdString, &cmdLength);
 										}
 									}
 				break;
-			case DETECTION_CO2:		if(UART_isCO2Connected())
+			case DETECTION_CO2_0:
+			case DETECTION_CO2_1:
+			case DETECTION_CO2_2:
+			case DETECTION_CO2_3:	if(uartCo2_isSensorConnected())
+									{
+										foundSensorMap[EXT_INTERFACE_MUX_OFFSET + activeUartChannel] = SENSOR_CO2;
+										externalAutoDetect = DETECTION_DONE;	/* only one CO2 sensor supported */
+									}
+									else if(foundSensorMap[EXT_INTERFACE_SENSOR_CNT-1] == SENSOR_MUX)
 									{
-										for(index = 0; index < 3; index++)	/* lookup a channel which may be used by CO2*/
-										{
-											if(tmpSensorMap[index] == SENSOR_NONE)
-											{
-												break;
-											}
-										}
-										if(index == 3)
-										{
-											tmpSensorMap[sensorIndex++] = SENSOR_CO2;  /* place Co2 sensor behind O2 sensors (not visible) */
-										}
-										else
-										{
-											tmpSensorMap[index] = SENSOR_CO2;
-										}
-
+										externalInterface_SwitchUART(EXT_INTERFACE_UART_O2 >> 8);
+										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_SwitchUART(EXT_INTERFACE_UART_CO2 >> 8);
+										uartCo2_SendCmd(CO2CMD_MODE_POLL, cmdString, &cmdLength);
+										externalAutoDetect++;
+										uartMuxChannel++;
 									}
-									externalAutoDetect++;
+									else
+									{
+										externalAutoDetect = DETECTION_DONE;
+									}
 #endif
 #ifdef ENABLE_SENTINEL_MODE
 									if(externalAutoDetect == DETECTION_SENTINEL)
@@ -740,7 +750,7 @@
 									cntUARTSensor = 0;
 									for(index = 0; index < EXT_INTERFACE_SENSOR_CNT-1; index++)
 									{
-										if((foundSensorMap[index] >= SENSOR_ANALOG) && (foundSensorMap[index] < SENSOR_TYPE_O2_END))
+										if((foundSensorMap[index] >= SENSOR_ANALOG) && (foundSensorMap[index] < SENSOR_MUX))
 										{
 											cntSensor++;
 										}
@@ -764,6 +774,21 @@
 											}
 										}
 									}
+									for(index = 0; index < EXT_INTERFACE_SENSOR_CNT-1; index++)
+									{
+										if(foundSensorMap[index] == SENSOR_CO2)
+										{
+											for(index2 = 0; index2 < MAX_ADC_CHANNEL; index2++)
+											{
+												if(foundSensorMap[index2] == SENSOR_NONE)
+												{
+													foundSensorMap[index2] = SENSOR_CO2M;		/* store a mirror instance needed for visualization */
+													Mux2ADCMap[index2] = index;
+													break;
+												}
+											}
+										}
+									}
 									externalInterfaceMuxReqIntervall = 0xFFFF;
 									if(cntSensor == 0)		/* return default sensor map if no sensor at all has been detected */
 									{
@@ -779,7 +804,7 @@
 										}
 									}
 									memcpy(SensorMap, foundSensorMap, sizeof(foundSensorMap));
-									memset(externalInterface_SensorState,UART_O2_INIT,sizeof(externalInterface_SensorState));
+									memset(externalInterface_SensorState, UART_COMMON_INIT, sizeof(externalInterface_SensorState));
 				break;
 			default:
 				break;
@@ -805,7 +830,14 @@
 											SensorMap[index] = SENSOR_SEARCH;
 										}
 			break;
-		case EXT_INTERFACE_CO2_CALIB:	cmdLength = snprintf(cmdString, 10, "G\r\n");
+		case EXT_INTERFACE_CO2_CALIB:	for(index = 0; index < EXT_INTERFACE_SENSOR_CNT; index++)
+										{
+											if(SensorMap[index] == SENSOR_CO2)
+											{
+												externalInterface_SensorState[index] = UART_CO2_CALIBRATE;
+												break;
+											}
+										}
 			break;
 		case EXT_INTERFACE_COPY_SENSORMAP:	if(externalAutoDetect == DETECTION_OFF)
 											{
@@ -877,6 +909,26 @@
 	return newChannel;
 }
 
+void externalInterface_CheckBaudrate(uint8_t sensorType)
+{
+	static uint32_t lastBaudRate = 0;
+	uint32_t newBaudrate = 0;
+
+	switch(sensorType)
+	{
+			case SENSOR_CO2:		newBaudrate = 9600;
+				break;
+			case SENSOR_DIGO2:
+		default:	newBaudrate = 19200;
+			break;
+	}
+	if(lastBaudRate != newBaudrate)
+	{
+		UART_ChangeBaudrate(newBaudrate);
+		lastBaudRate = newBaudrate;
+	}
+}
+
 void externalInterface_HandleUART()
 {
 	static uint8_t retryRequest = 0;
@@ -898,12 +950,13 @@
 		{
 			UART_MUX_SelectAddress(activeUartChannel);
 		}
+		externalInterface_CheckBaudrate(pmap[activeUartChannel + EXT_INTERFACE_MUX_OFFSET]);
 		UART_FlushRxBuffer();
 	}
 
 	if(externalInterfaceMuxReqIntervall != 0xFFFF)
 	{
-		if(externalInterface_SensorState[activeSensorId] == UART_O2_INIT)
+		if(externalInterface_SensorState[activeSensorId] == UART_COMMON_INIT)
 		{
 			lastRequestTick = tick;
 			TriggerTick = tick - 10;	/* just to make sure control is triggered */
@@ -930,9 +983,19 @@
 			timeToTrigger = 1;
 
 			if((externalInterface_SensorState[activeSensorId] == UART_O2_REQ_O2)		/* timeout */
-					|| (externalInterface_SensorState[activeSensorId] == UART_O2_REQ_RAW))
+					|| (externalInterface_SensorState[activeSensorId] == UART_O2_REQ_RAW)
+					|| (externalInterface_SensorState[activeSensorId] == UART_CO2_OPERATING))
 			{
-				setExternalInterfaceChannel(activeSensorId,0.0);
+				switch(pmap[activeSensorId])
+				{
+					case SENSOR_DIGO2: setExternalInterfaceChannel(activeSensorId,0.0);
+						break;
+					case SENSOR_CO2: externalInterface_SetCO2Value(0.0);
+									 externalInterface_SetCO2State(0);
+						break;
+					default:
+						break;
+				}
 			}
 
 			if(pmap[EXT_INTERFACE_SENSOR_CNT-1] == SENSOR_MUX) /* select next sensor if mux is connected */
@@ -944,10 +1007,13 @@
 					{
 						timeToTrigger = 100;
 						activeUartChannel = index;
-						if(pmap[index + EXT_INTERFACE_MUX_OFFSET] == SENSOR_DIGO2)
+						if((pmap[index + EXT_INTERFACE_MUX_OFFSET] == SENSOR_DIGO2)
+								|| (pmap[index + EXT_INTERFACE_MUX_OFFSET] == SENSOR_CO2))
 						{
 							uartO2_SetChannel(activeUartChannel);
+							externalInterface_CheckBaudrate(SENSOR_MUX);
 							UART_MUX_SelectAddress(activeUartChannel);
+							externalInterface_CheckBaudrate(pmap[activeUartChannel + EXT_INTERFACE_MUX_OFFSET]);
 						}
 					}
 				}
@@ -965,8 +1031,10 @@
 				case SENSOR_MUX:
 				case SENSOR_DIGO2:	uartO2_Control();
 					break;
-			//	case SENSOR_CO2:	uartCO2_Control();
+#ifdef ENABLE_CO2_SUPPORT
+				case SENSOR_CO2:	uartCo2_Control();
 					break;
+#endif
 				default:
 					break;
 			}
@@ -976,22 +1044,12 @@
 
 
 #if 0
-#ifdef ENABLE_CO2_SUPPORT
-		if(externalInterface_GetUARTProtocol() & (EXT_INTERFACE_UART_CO2 >> 8))
-		{
-			UART_HandleCO2Data();
-		}
-#endif
 #ifdef ENABLE_SENTINEL_MODE
 		if(externalInterface_GetUARTProtocol() & (EXT_INTERFACE_UART_SENTINEL >> 8))
 		{
 			UART_HandleSentinelData();
 		}
 #endif
-		if(externalInterface_GetUARTProtocol() & (EXT_INTERFACE_UART_O2 >> 8))
-		{
-			UART_HandleDigitalO2();
-		}
 #endif
 
 
--- a/Small_CPU/Src/uart.c	Mon Jul 31 20:10:27 2023 +0200
+++ b/Small_CPU/Src/uart.c	Mon Aug 07 20:29:44 2023 +0200
@@ -21,6 +21,7 @@
 /* Includes ------------------------------------------------------------------*/
 #include "uart.h"
 #include "uartProtocol_O2.h"
+#include "uartProtocol_Co2.h"
 #include "externalInterface.h"
 #include "data_exchange.h"
 #include <string.h>	/* memset */
@@ -42,22 +43,13 @@
 static uint8_t lastCmdIndex;							/* Index of last command which has not been completly received */
 static uint8_t dmaActive;								/* Indicator if DMA reception needs to be started */
 
-static uint8_t CO2Connected = 0;						/* Binary indicator if a sensor is connected or not */
+
 static uint8_t SentinelConnected = 0;					/* Binary indicator if a sensor is connected or not */
 
 
-
-static uartCO2Status_t ComStatus_CO2 = UART_CO2_INIT;
-
-float LED_Level = 0.0;							/* Normalized LED value which may be used as indication for the health status of the sensor */
-float LED_ZeroOffset = 0.0;
-float pCO2 = 0.0;
 /* Exported functions --------------------------------------------------------*/
 
 
-
-//huart.Instance->BRR = UART_BRR_SAMPLING8(HAL_RCC_GetPCLK2Freq(), new_baudrate);
-
 void MX_USART1_UART_Init(void)
 {
 /* regular init */	
@@ -71,7 +63,6 @@
   else
   {
 	  huart1.Init.BaudRate = 9600;
-	  ComStatus_CO2 = UART_CO2_INIT;
   }
   huart1.Init.WordLength = UART_WORDLENGTH_8B;
   huart1.Init.StopBits = UART_STOPBITS_1;
@@ -90,7 +81,6 @@
   rxWriteIndex = 0;
   dmaActive = 0;
 
-  CO2Connected = 0;
   SentinelConnected = 0;
 
 }
@@ -157,28 +147,6 @@
 	}
 }
 
-void DigitalCO2_SendCmd(uint8_t CO2Cmd, uint8_t *cmdString, uint16_t *cmdLength)
-{
-	switch (CO2Cmd)
-	{
-		case CO2CMD_MODE_POLL:		*cmdLength = snprintf((char*)cmdString, 10, "K 2\r\n");
-				break;
-		case CO2CMD_MODE_STREAM:	*cmdLength = snprintf((char*)cmdString, 10, "K 1\r\n");
-				break;
-		case CO2CMD_CALIBRATE:		*cmdLength = snprintf((char*)cmdString, 10, "G\r\n");
-				break;
-		case CO2CMD_GETDATA:		*cmdLength = snprintf((char*)cmdString, 10, "Q\r\n");
-				break;
-		case CO2CMD_GETSCALE:		*cmdLength = snprintf((char*)cmdString, 10, ".\r\n");
-				break;
-		default: *cmdLength = 0;
-			break;
-	}
-	if(cmdLength != 0)
-	{
-		HAL_UART_Transmit(&huart1,cmdString,*cmdLength,10);
-	}
-}
 
 void StringToInt(char *pstr, uint32_t *puInt32)
 {
@@ -230,154 +198,36 @@
 
 void UART_StartDMA_Receiption()
 {
-	if(HAL_OK == HAL_UART_Receive_DMA (&huart1, &rxBuffer[rxWriteIndex], CHUNK_SIZE))
+	if(dmaActive == 0)
 	{
-		dmaActive = 1;
+		if(HAL_OK == HAL_UART_Receive_DMA (&huart1, &rxBuffer[rxWriteIndex], CHUNK_SIZE))
+		{
+			dmaActive = 1;
+		}
 	}
 }
 
-#ifdef ENABLE_CO2_SUPPORT
-void UART_HandleCO2Data(void)
+void UART_ChangeBaudrate(uint32_t newBaudrate)
 {
-	uint8_t localRX = rxReadIndex;
-	static uint8_t dataType = 0;
-	static uint32_t dataValue = 0;
-	static receiveState_t rxState = RX_Ready;
-	static uint32_t lastReceiveTick = 0;
-	static uint32_t lastTransmitTick = 0;
-	static uint8_t cmdString[10];
-	static uint16_t cmdLength = 0;
-
-	uint32_t Tick = HAL_GetTick();
-
-	uint8_t *pmap = externalInterface_GetSensorMapPointer(0);
-
-	if(ComStatus_CO2 == UART_CO2_INIT)
-	{
-		UART_StartDMA_Receiption();
-		ComStatus_CO2 = UART_CO2_SETUP;
-	}
 
-	if(ComStatus_CO2 == UART_CO2_SETUP)
-	{
-		if(time_elapsed_ms(lastTransmitTick,Tick) > 200)
-		{
-			if(externalInterface_GetCO2Scale() == 0.0)
-			{
-				DigitalCO2_SendCmd(CO2CMD_GETDATA, cmdString, &cmdLength);
-				lastTransmitTick = Tick;
-			}
-			else
-			{
-				ComStatus_CO2 = UART_CO2_OPERATING;
-			}
-		}
-	}
-	else
-	{
-		if(pmap[EXT_INTERFACE_SENSOR_CNT-1] == SENSOR_MUX)		/* sensor is working in polling mode if mux is connected to avoid interference with other sensors */
-		{
-			if(time_elapsed_ms(lastTransmitTick,Tick) > 2000)	/* poll every two seconds */
-			{
-				lastTransmitTick = Tick;
-				if(cmdLength == 0)							/* poll data */
-				{
-					DigitalCO2_SendCmd(CO2CMD_GETDATA, cmdString, &cmdLength);
-				}
-				else											/* resend last command */
-				{
-					HAL_UART_Transmit(&huart1,cmdString,strlen((char*)cmdString),10);
-					cmdLength = 0;
-				}
-			}
-		}
-	}
-	while((rxBuffer[localRX]!=BUFFER_NODATA))
+//	HAL_DMA_Abort(&hdma_usart1_rx);
+		MX_USART1_UART_DeInit();
+		//HAL_UART_Abort(&huart1);
+		//HAL_DMA_DeInit(&hdma_usart1_rx);
+
+
+//	huart1.Instance->BRR = UART_BRR_SAMPLING8(HAL_RCC_GetPCLK2Freq()/2, newBaudrate);
+	huart1.Init.BaudRate = newBaudrate;
+	HAL_UART_Init(&huart1);
+	MX_USART1_DMA_Init();
+	if(dmaActive)
 	{
-		lastReceiveTick = Tick;
-		if(rxState == RX_Ready)		/* identify data content */
-		{
-			switch(rxBuffer[localRX])
-			{
-				case 'l':
-				case 'D':
-				case 'Z':
-				case '.':
-									dataType = rxBuffer[localRX];
-									rxState = RX_Data0;
-									dataValue = 0;
-					break;
-
-				default:			/* unknown or corrupted => ignore */
-					break;
-			}
-		}
-		else if((rxBuffer[localRX] >= '0') && (rxBuffer[localRX] <= '9'))
-		{
-			if((rxState >= RX_Data0) && (rxState <= RX_Data4))
-			{
-				dataValue = dataValue * 10 + (rxBuffer[localRX] - '0');
-				rxState++;
-				if(rxState == RX_Data5)
-				{
-					rxState = RX_DataComplete;
-					CO2Connected = 1;
-				}
-			}
-			else	/* protocol error data has max 5 digits */
-			{
-				rxState = RX_Ready;
-			}
-		}
-		if((rxBuffer[localRX] == ' ') || (rxBuffer[localRX] == '\n'))	/* Abort data detection */
-		{
-			if(rxState == RX_DataComplete)
-			{
-				if(externalInterface_GetCO2State() == 0)
-				{
-					externalInterface_SetCO2State(EXT_INTERFACE_33V_ON);
-				}
-				switch(dataType)
-				{
-					case 'D':			externalInterface_SetCO2SignalStrength(dataValue);
-						break;
-					case 'l':			LED_ZeroOffset = dataValue;
-						break;
-					case 'Z':			externalInterface_SetCO2Value(dataValue);
-						break;
-					case '.':			externalInterface_SetCO2Scale(dataValue);
-						break;
-					default:			rxState = RX_Ready;
-						break;
-				}
-			}
-			if(rxState != RX_Data0)	/* reset state machine because message in wrong format */
-			{
-				rxState = RX_Ready;
-			}
-		}
-		rxBuffer[localRX] = BUFFER_NODATA;
-		localRX++;
-		rxReadIndex++;
-		if(rxReadIndex >= CHUNK_SIZE * CHUNKS_PER_BUFFER)
-		{
-			localRX = 0;
-			rxReadIndex = 0;
-		}
-	}
-
-	if(time_elapsed_ms(lastReceiveTick,HAL_GetTick()) > 2000)	/* check for communication timeout */
-	{
-		externalInterface_SetCO2State(0);
-		CO2Connected = 0;
-	}
-
-	if((dmaActive == 0)	&& (externalInterface_isEnabledPower33()))	/* Should never happen in normal operation => restart in case of communication error */
-	{
+		rxReadIndex = 0;
+		rxWriteIndex = 0;
+		dmaActive = 0;
 		UART_StartDMA_Receiption();
 	}
 }
-#endif
 
 #ifdef ENABLE_SENTINEL_MODE
 void UART_HandleSentinelData(void)
@@ -531,10 +381,7 @@
 #endif
 
 
-uint8_t UART_isCO2Connected()
-{
-	return CO2Connected;
-}
+
 uint8_t UART_isSentinelConnected()
 {
 	return SentinelConnected;
@@ -571,8 +418,10 @@
 			case SENSOR_MUX:
 			case SENSOR_DIGO2:	uartO2_ProcessData(rxBuffer[localRX]);
 				break;
-	//	case SENSOR_CO2:	uartCO2_Control();
+#ifdef ENABLE_CO2_SUPPORT
+			case SENSOR_CO2:	uartCo2_ProcessData(rxBuffer[localRX]);
 				break;
+#endif
 			default:
 				break;
 		}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Small_CPU/Src/uartProtocol_Co2.c	Mon Aug 07 20:29:44 2023 +0200
@@ -0,0 +1,207 @@
+/**
+  ******************************************************************************
+  * @file    uartProtocol_Co2.c
+  * @author  heinrichs weikamp gmbh
+  * @version V0.0.1
+  * @date    31-Jul-2023
+  * @brief   Interface functionality to external, UART based CO2 sensors
+  *
+  @verbatim
+
+
+  @endverbatim
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2023 heinrichs weikamp</center></h2>
+  *
+  ******************************************************************************
+  */
+/* Includes ------------------------------------------------------------------*/
+
+#include <string.h>
+#include <uartProtocol_Co2.h>
+#include "uart.h"
+#include "externalInterface.h"
+
+
+#ifdef ENABLE_CO2_SUPPORT
+static uint8_t CO2Connected = 0;						/* Binary indicator if a sensor is connected or not */
+static receiveState_t rxState = RX_Ready;
+
+
+
+float LED_Level = 0.0;							/* Normalized LED value which may be used as indication for the health status of the sensor */
+float LED_ZeroOffset = 0.0;
+float pCO2 = 0.0;
+
+
+
+void uartCo2_SendCmd(uint8_t CO2Cmd, uint8_t *cmdString, uint8_t *cmdLength)
+{
+	switch (CO2Cmd)
+	{
+		case CO2CMD_MODE_POLL:		*cmdLength = snprintf((char*)cmdString, 10, "K 2\r\n");
+				break;
+		case CO2CMD_MODE_STREAM:	*cmdLength = snprintf((char*)cmdString, 10, "K 1\r\n");
+				break;
+		case CO2CMD_CALIBRATE:		*cmdLength = snprintf((char*)cmdString, 10, "G\r\n");
+				break;
+		case CO2CMD_GETDATA:		*cmdLength = snprintf((char*)cmdString, 10, "Q\r\n");
+				break;
+		case CO2CMD_GETSCALE:		*cmdLength = snprintf((char*)cmdString, 10, ".\r\n");
+				break;
+		default: *cmdLength = 0;
+			break;
+	}
+	if(cmdLength != 0)
+	{
+		UART_SendCmdString(cmdString);
+	}
+}
+
+
+void uartCo2_Control(void)
+{
+	static uint8_t cmdString[10];
+	static uint8_t cmdLength = 0;
+	static uint8_t lastComState = 0;
+
+	uint8_t activeSensor = externalInterface_GetActiveUartSensor();
+	uartCO2Status_t localComState = externalInterface_GetSensorState(activeSensor + EXT_INTERFACE_MUX_OFFSET);
+
+	uint8_t *pmap = externalInterface_GetSensorMapPointer(0);
+
+
+	if(localComState == UART_CO2_ERROR)
+	{
+		localComState = lastComState;
+	}
+
+	if(localComState == UART_CO2_INIT)
+	{
+		externalInterface_SetCO2Scale(0.0);
+		UART_StartDMA_Receiption();
+		localComState = UART_CO2_SETUP;
+	}
+	if(localComState == UART_CO2_SETUP)
+	{
+		if(externalInterface_GetCO2Scale() == 0.0)
+		{
+			uartCo2_SendCmd(CO2CMD_GETSCALE, cmdString, &cmdLength);
+		}
+		else
+		{
+			localComState = UART_CO2_IDLE;
+		}
+	}
+	else
+	{
+		if(localComState == UART_CO2_CALIBRATE)
+		{
+			uartCo2_SendCmd(CO2CMD_CALIBRATE, cmdString, &cmdLength);
+		}
+		else if(pmap[EXT_INTERFACE_SENSOR_CNT-1] == SENSOR_MUX)		/* sensor is working in polling mode if mux is connected to avoid interference with other sensors */
+		{
+			//if(cmdLength == 0)							/* poll data */
+			if(localComState == UART_CO2_IDLE)
+			{
+				uartCo2_SendCmd(CO2CMD_GETDATA, cmdString, &cmdLength);
+				localComState = UART_CO2_OPERATING;
+			}
+			else											/* resend last command */
+			{
+				UART_SendCmdString(cmdString);
+				cmdLength = 0;
+			}
+		}
+		else
+		{
+			localComState = UART_CO2_OPERATING;					/* sensor in streaming mode if not connected to mux => operating */
+		}
+	}
+	lastComState = localComState;
+	externalInterface_SetSensorState(activeSensor + EXT_INTERFACE_MUX_OFFSET,localComState);
+}
+
+
+void uartCo2_ProcessData(uint8_t data)
+{
+	static uint8_t dataType = 0;
+	static uint32_t dataValue = 0;
+	uint8_t activeSensor = externalInterface_GetActiveUartSensor();
+	uartCO2Status_t localComState = externalInterface_GetSensorState(activeSensor + EXT_INTERFACE_MUX_OFFSET);
+
+	if(rxState == RX_Ready)		/* identify data content */
+	{
+		switch(data)
+		{
+			case 'G':
+			case 'l':
+			case 'D':
+			case 'Z':
+			case '.':			dataType = data;
+								rxState = RX_Data0;
+								dataValue = 0;
+				break;
+			case '?':			localComState = UART_CO2_ERROR;
+				break;
+			default:			/* unknown or corrupted => ignore */
+					break;
+		}
+	}
+	else if((data >= '0') && (data <= '9'))
+	{
+		if((rxState >= RX_Data0) && (rxState <= RX_Data4))
+		{
+			dataValue = dataValue * 10 + (data - '0');
+			rxState++;
+			if(rxState == RX_Data5)
+			{
+				rxState = RX_DataComplete;
+				CO2Connected = 1;
+			}
+		}
+		else	/* protocol error data has max 5 digits */
+		{
+			rxState = RX_Ready;
+		}
+	}
+	if((data == ' ') || (data == '\n'))	/* Abort data detection */
+	{
+		if(rxState == RX_DataComplete)
+		{
+			localComState = UART_CO2_IDLE;
+			if(externalInterface_GetCO2State() == 0)
+			{
+				externalInterface_SetCO2State(EXT_INTERFACE_33V_ON);
+			}
+			switch(dataType)
+			{
+				case 'D':			externalInterface_SetCO2SignalStrength(dataValue);
+					break;
+				case 'l':			LED_ZeroOffset = dataValue;
+					break;
+				case 'Z':			externalInterface_SetCO2Value(dataValue);
+					break;
+				case '.':			externalInterface_SetCO2Scale(dataValue);
+					break;
+				default:			rxState = RX_Ready;
+					break;
+			}
+		}
+		if(rxState != RX_Data0)	/* reset state machine because message in wrong format */
+		{
+			rxState = RX_Ready;
+		}
+	}
+	externalInterface_SetSensorState(activeSensor + EXT_INTERFACE_MUX_OFFSET,localComState);
+}
+
+uint8_t uartCo2_isSensorConnected()
+{
+	return CO2Connected;
+}
+
+#endif
+
--- a/Small_CPU/Src/uartProtocol_O2.c	Mon Jul 31 20:10:27 2023 +0200
+++ b/Small_CPU/Src/uartProtocol_O2.c	Mon Aug 07 20:29:44 2023 +0200
@@ -49,9 +49,9 @@
 					break;
 		case UART_O2_REQ_ID: 	*cmdLength = snprintf((char*)cmdString, 10, "#IDNR");
 			break;
-		case UART_O2_REQ_O2: 	*cmdLength = snprintf((char*)cmdString, 10, "#DOXY");
+		case UART_O2_REQ_O2: 	*cmdLength = snprintf((char*)cmdString, 10, "#MOXY");
 			break;
-		case UART_O2_REQ_RAW:	*cmdLength = snprintf((char*)cmdString, 10, "#DRAW");
+		case UART_O2_REQ_RAW:	*cmdLength = snprintf((char*)cmdString, 10, "#MRAW");
 			break;
 		default: *cmdLength = 0;
 			break;
@@ -99,7 +99,7 @@
 		UART_FlushRxBuffer();
 	}
 
-	if(localComState == UART_O2_INIT)
+	if(localComState == UART_COMMON_INIT)
 	{
 		memset((char*) &tmpSensorDataDiveO2, 0, sizeof(tmpSensorDataDiveO2));
 		externalInterface_SetSensorData(0xFF,(uint8_t*)&tmpSensorDataDiveO2);