changeset 794:bb37d4f3e50e

Restructure UART based sensor handling: In the previous version every UART sensor instance had its own protocol handling instance (requests, timeout, errors). With the introduction of the multiplexer these functionalities had to be harmonized. E.g. only one errorhandling which is applied to all sensors. In the new structure the sensor communication is split into one function which takes care for the control needs of a sensor and one function which handles the incoming data. The functions behalf the same independend if the sensor are connected to multiplexer or directly to the OSTC. Second big change in the external sensor concepts is that the data processing is no longer focussed at the three existing ADC channels. Every external sensor (up to 3 ADC and 4 UART) sensor has its own instance. If the ADC slots are not in use then they may be used for visiualization of UART sensors by creating a mirror instance but this is no longer a must.
author Ideenmodellierer
date Mon, 31 Jul 2023 19:46:29 +0200
parents 9da81033ad44
children d4083ac09b5d
files Small_CPU/Inc/externalInterface.h Small_CPU/Inc/uart.h Small_CPU/Src/externalInterface.c Small_CPU/Src/scheduler.c Small_CPU/Src/uart.c
diffstat 5 files changed, 543 insertions(+), 577 deletions(-) [+]
line wrap: on
line diff
--- a/Small_CPU/Inc/externalInterface.h	Thu Jul 27 21:52:19 2023 +0200
+++ b/Small_CPU/Inc/externalInterface.h	Mon Jul 31 19:46:29 2023 +0200
@@ -29,7 +29,8 @@
 
 /* Includes ------------------------------------------------------------------*/
 #include "configuration.h"
-
+#include "data_central.h"
+#include "data_exchange.h"
 
 #define MAX_ADC_CHANNEL		(3u)		/* number of channels to be read */
 #define MAX_MUX_CHANNEL		(4u)		/* number of channels provided by the UART multiplexer */
@@ -39,6 +40,8 @@
 
 #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 */
 
  typedef enum
  {
@@ -78,8 +81,10 @@
 void externalInterface_SwitchUART(uint8_t protocol);
 uint8_t externalInterface_isEnabledPower33(void);
 uint8_t externalInterface_isEnabledADC(void);
-uint8_t externalInterface_GetUARTProtocol();
-
+uint8_t externalInterface_GetUARTProtocol(void);
+void externalInterface_HandleUART(void);
+void externalInterface_SetCO2Scale(float CO2Scale);
+float externalInterface_GetCO2Scale(void);
 void externalInterface_SetCO2Value(uint16_t CO2_ppm);
 void externalInterface_SetCO2SignalStrength(uint16_t LED_qa);
 uint16_t externalInterface_GetCO2Value(void);
@@ -93,4 +98,10 @@
 void externalInterface_AutodetectSensor(void);
 void externalInterface_ExecuteCmd(uint16_t Cmd);
 
+uint8_t externalInterface_GetActiveUartSensor(void);
+void externalInterface_SetSensorState(uint8_t sensorIdx, uint8_t state);
+uint8_t externalInterface_GetSensorState(uint8_t sensorIdx);
+
+
+
 #endif /* EXTERNAL_INTERFACE_H */
--- a/Small_CPU/Inc/uart.h	Thu Jul 27 21:52:19 2023 +0200
+++ b/Small_CPU/Inc/uart.h	Mon Jul 31 19:46:29 2023 +0200
@@ -25,6 +25,16 @@
 #include "stm32f4xx_hal.h"
 
 
+#define BUFFER_NODATA			(7u)		/* The read function needs a byte which indecated 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 */
@@ -46,39 +56,15 @@
 	RX_DataComplete
  } receiveState_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 state which could not be resolved => only exit via de-/activation cycle */
- } uartO2Status_t;
 
-
- typedef enum
-  {
-	O2RX_IDLE = 0,			/* no reception pending */
-	O2RX_CONFIRM,			/* check the command echo */
-	O2RX_GETNR,				/* extract the sensor number */
-	O2RX_GETO2,				/* extract the ppo2 */
-	O2RX_GETTEMP,			/* extract the temperature */
-	O2RX_GETSTATUS,			/* extract the sensor status */
-	O2RX_GETTYPE,			/* extract the sensor type (should be 8) */
-	O2RX_GETCHANNEL,		/* extract the number of sensor channels (should be 1) */
-	O2RX_GETVERSION,		/* extract the sensor version */
-	O2RX_GETSUBSENSORS,		/* extract the available measures (O2, temperature, humidity etc) */
-	O2RX_GETDPHI,			/* extract phase shift */
-	O2RX_INTENSITY,			/* extract intensity of signal */
-	O2RX_AMBIENTLIGHT,		/* extract the intensity of the ambient light */
-	O2RX_PRESSURE,			/* extract pressor within the sensor housing */
-	O2RX_HUMIDITY			/* extract humidity within the sensor housing */
-  } uartO2RxState_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);
@@ -87,19 +73,22 @@
 void UART_StartDMA_Receiption(void);
 #ifdef ENABLE_CO2_SUPPORT
 void UART_HandleCO2Data(void);
+void DigitalCO2_SendCmd(uint8_t CO2Cmd, uint8_t *cmdString, uint8_t *cmdLength);
 #endif
 #ifdef ENABLE_SENTINEL_MODE
 void UART_HandleSentinelData(void);
 #endif
-void UART_HandleDigitalO2(void);
-void UART_MapDigO2_Channel(uint8_t channel, uint8_t muxAddress);
-void UART_SetDigO2_Channel(uint8_t channel);
-uint8_t UART_isDigO2Connected();
 uint8_t UART_isCO2Connected();
 uint8_t UART_isSentinelConnected();
 void UART_setTargetChannel(uint8_t channel);
+void  UART_MUX_SelectAddress(uint8_t muxAddress);
+void UART_SendCmdString(uint8_t *cmdString);
+void UART_ReadData(uint8_t sensorType);
+void UART_FlushRxBuffer(void);
 
 
+void StringToInt(char *pstr, uint32_t *puInt32);
+void StringToUInt64(char *pstr, uint64_t *puint64);
 
 #ifdef __cplusplus
 }
--- a/Small_CPU/Src/externalInterface.c	Thu Jul 27 21:52:19 2023 +0200
+++ b/Small_CPU/Src/externalInterface.c	Mon Jul 31 19:46:29 2023 +0200
@@ -25,12 +25,14 @@
 
 #include <math.h>
 #include <string.h>
+#include "data_central.h"
 #include "i2c.h"
 #include "externalInterface.h"
 #include "scheduler.h"
 #include "uart.h"
 #include "data_exchange.h"
 #include "pressure.h"
+#include "uartProtocol_O2.h"
 
 extern SGlobal global;
 extern UART_HandleTypeDef huart1;
@@ -54,6 +56,12 @@
 #define LOOKUP_CO2_CORR_TABLE_SCALE	(1000u)
 #define LOOKUP_CO2_CORR_TABLE_MAX	(30000u)
 
+#define REQUEST_INT_SENSOR_MS	(1500)		/* Minimum time interval for cyclic sensor data requests per sensor (UART mux) */
+#define COMMAND_TX_DELAY		(30u)		/* The time the sensor needs to recover from a invalid command request */
+#define TIMEOUT_SENSOR_ANSWER	(300)		/* Time till a request is repeated if no answer was received */
+
+#define activeSensorId (activeUartChannel + EXT_INTERFACE_MUX_OFFSET)	/* Used if UART channels are applied to Sensor map */
+
 static uint8_t activeChannel = 0;			/* channel which is in request */
 static uint8_t recBuf[ADC_ANSWER_LENGTH];
 static uint8_t timeoutCnt = 0;
@@ -65,17 +73,23 @@
 static uint8_t  externalUART_Protocol = 0;
 static uint16_t externalCO2Value;
 static uint16_t externalCO2SignalStrength;
-static uint16_t  externalCO2Status = 0;
+static uint16_t externalCO2Status = 0;
+static float 	externalCO2Scale = 0.0;
 
 static uint8_t lastSensorDataId = 0;
-static SSensorDataDiveO2 sensorDataDiveO2[MAX_ADC_CHANNEL];
+static SSensorDataDiveO2 sensorDataDiveO2[EXT_INTERFACE_SENSOR_CNT];
 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];
 static externalInterfaceSensorType MasterSensorMap[EXT_INTERFACE_SENSOR_CNT];
+static externalInterfaceSensorType foundSensorMap[EXT_INTERFACE_SENSOR_CNT];
+static uint8_t	Mux2ADCMap[MAX_ADC_CHANNEL];
+static uint8_t externalInterface_SensorState[EXT_INTERFACE_SENSOR_CNT];
 
 static float LookupCO2PressureCorrection[LOOKUP_CO2_CORR_TABLE_MAX / LOOKUP_CO2_CORR_TABLE_SCALE];		/* lookup table for pressure compensation values */
 
+static uint16_t externalInterfaceMuxReqIntervall = 0;		/* delay between switching from one MUX channel to the next */
+static uint8_t activeUartChannel = 0;						/* Index of the sensor port which is selected by the mux or 0 if no mux is connected */
 
 void externalInterface_Init(void)
 {
@@ -91,6 +105,8 @@
 	}
 	global.deviceDataSendToMaster.hw_Info.checkADC = 1;
 
+	memset(Mux2ADCMap,0xFF, sizeof(Mux2ADCMap));
+
 /* Create a lookup table based on GSS application note AN001: PRESSURE COMPENSATION OF A CO2 SENSOR */
 /* The main purpose of the sensor in the dive application is to be a warning indicator */
 /* => no exact values necessary => a lookup table with 1000ppm scaling should be sufficient */
@@ -117,6 +133,7 @@
 	{
 		externalChannel_mV[index] = 0.0;
 	}
+	memset(externalInterface_SensorState,UART_O2_INIT,sizeof(externalInterface_SensorState));
 }
 
 
@@ -240,10 +257,24 @@
 uint8_t setExternalInterfaceChannel(uint8_t channel, float value)
 {
 	uint8_t retval = 0;
+	uint8_t localId = channel;
+	uint8_t index = 0;
 
-	if(channel < MAX_ADC_CHANNEL)
+	if(localId >= MAX_ADC_CHANNEL)		/* at the moment sensor visualization is focused on the three ADC channels => map Mux sensors */
 	{
-		externalChannel_mV[channel] = value;
+		for(index = 0; index < MAX_ADC_CHANNEL; index++)
+		{
+			if(Mux2ADCMap[index] == localId)
+			{
+				localId = index;
+				break;
+			}
+		}
+	}
+
+	if(localId < MAX_ADC_CHANNEL)
+	{
+		externalChannel_mV[localId] = value;
 		retval = 1;
 	}
 	return retval;
@@ -359,9 +390,45 @@
 	}
 }
 
+uint8_t externalInterface_GetActiveUartSensor()
+{
+	return activeUartChannel;
+}
+
+void externalInterface_SetSensorState(uint8_t sensorIdx, uint8_t state)
+{
+	if(sensorIdx < EXT_INTERFACE_SENSOR_CNT)
+	{
+		externalInterface_SensorState[sensorIdx] = state;
+	}
+}
+
+uint8_t externalInterface_GetSensorState(uint8_t sensorIdx)
+{
+	uint8_t ret = COMMON_SENSOR_STATE_INVALID;
+	if(sensorIdx < EXT_INTERFACE_SENSOR_CNT)
+	{
+		ret = externalInterface_SensorState[sensorIdx];
+	}
+	return ret;
+}
+
+/* The supported sensors from GSS have different scaling factors depending on their accuracy. The factor may be read out of the sensor */
+void externalInterface_SetCO2Scale(float CO2Scale)
+{
+	if((CO2Scale == 10) || (CO2Scale == 100))
+	{
+		externalCO2Scale = CO2Scale;
+	}
+}
+float externalInterface_GetCO2Scale()
+{
+	return externalCO2Scale;
+}
+
 void externalInterface_SetCO2Value(uint16_t CO2_ppm)
 {
-	float local_ppm = CO2_ppm * 10.0;		/* scalfactor */
+	float local_ppm = CO2_ppm * externalCO2Scale;
 
 #ifndef ENABLE_EXTERNAL_PRESSURE
 	float local_corr = 0.0;
@@ -379,7 +446,7 @@
 /* The external pressure value is passed via ADC channel2 and calibration is done at firmware => just forward sensor data */
 /* compensation is done at firmware side. This is for testing only. Take care the the same algorithm is taken as used for the lookup table */
 #endif
-	externalCO2Value = local_ppm / 10.0;
+	externalCO2Value = local_ppm / externalCO2Scale;
 }
 
 void externalInterface_SetCO2SignalStrength(uint16_t LED_qa)
@@ -411,13 +478,14 @@
 
 uint8_t externalInterface_GetSensorData(uint8_t sensorId, uint8_t* pDataStruct)
 {
+	uint8_t index = 0;
 	uint8_t localId = sensorId;
 	if(localId == 0xFF)
 	{
 		localId = lastSensorDataId;
 	}
 
-	if((pDataStruct != NULL) && (localId <= MAX_ADC_CHANNEL))
+	if((pDataStruct != NULL) && (localId <= EXT_INTERFACE_SENSOR_CNT))
 	{
 		memcpy(pDataStruct, &sensorDataDiveO2[localId], sizeof(SSensorDataDiveO2));
 	}
@@ -425,17 +493,39 @@
 	{
 		localId = 0xFF;
 	}
+	if(localId > MAX_ADC_CHANNEL)		/* at the moment sensor visualization is focused on the three ADC channels => map Mux sensors */
+	{
+		for(index = 0; index < MAX_ADC_CHANNEL; index++)
+		{
+			if(Mux2ADCMap[index] == localId)
+			{
+				localId = index;
+			}
+		}
+	}
+
 	return localId;
 }
 
 void externalInterface_SetSensorData(uint8_t sensorId, uint8_t* pDataStruct)
 {
+	uint8_t index = 0;
+
 	if(pDataStruct != NULL)
 	{
-		if((sensorId != 0xFF) && (sensorId < MAX_ADC_CHANNEL))
+		if((sensorId != 0xFF) && (sensorId < EXT_INTERFACE_SENSOR_CNT))
 		{
 			memcpy(&sensorDataDiveO2[sensorId], pDataStruct, sizeof(SSensorDataDiveO2));
 			lastSensorDataId = sensorId;
+			for(index = 0; index < MAX_MUX_CHANNEL; index++)
+			{
+				if(Mux2ADCMap[index] == sensorId)
+				{
+					memcpy(&sensorDataDiveO2[index], pDataStruct, sizeof(SSensorDataDiveO2));
+					lastSensorDataId = index;
+					break;
+				}
+			}
 		}
 		else
 		{
@@ -449,7 +539,7 @@
 {
 	if(pMap != NULL)
 	{
-		memcpy(MasterSensorMap, pMap, 5);		/* the map is not directly copied. Copy is done via cmd request */
+		memcpy(MasterSensorMap, pMap, EXT_INTERFACE_SENSOR_CNT);		/* the map is not directly copied. Copy is done via cmd request */
 	}
 
 }
@@ -470,16 +560,21 @@
 
 void externalInterface_AutodetectSensor()
 {
-	static uint8_t tmpMuxMapping[MAX_MUX_CHANNEL];
 	static uint8_t sensorIndex = 0;
 	static uint8_t uartMuxChannel = 0;
 	uint8_t index = 0;
+	uint8_t index2 = 0;
+	uint8_t cntSensor = 0;
+	uint8_t cntUARTSensor = 0;
+	uint8_t cmdString[10];
+	uint8_t cmdLength = 0;
 
 	if(externalAutoDetect != DETECTION_OFF)
 	{
 		switch(externalAutoDetect)
 		{
-			case DETECTION_INIT:	sensorIndex = 0;
+			case DETECTION_INIT:	externalInterfaceMuxReqIntervall = 1100;
+									sensorIndex = 0;
 									uartMuxChannel = 0;
 									tmpSensorMap[0] = SENSOR_OPTIC;
 									tmpSensorMap[1] = SENSOR_OPTIC;
@@ -487,12 +582,9 @@
 									tmpSensorMap[3] = SENSOR_NONE;
 									tmpSensorMap[4] = SENSOR_NONE;
 
-									for(index = 0; index < MAX_ADC_CHANNEL; index++)
-									{
-										UART_MapDigO2_Channel(index,index);		/* request all addresses */
-										tmpMuxMapping[index] = 0xff;
-									}
-									UART_MapDigO2_Channel(2,3);
+									memset(foundSensorMap, SENSOR_NONE, sizeof(foundSensorMap));
+									memset(externalInterface_SensorState,UART_O2_INIT,sizeof(externalInterface_SensorState));
+									memset(Mux2ADCMap,0, sizeof(Mux2ADCMap));
 
 									if(externalInterfacePresent)
 									{
@@ -523,6 +615,7 @@
 										if(externalChannel_mV[index] > MIN_ADC_VOLTAGE_MV)
 										{
 											tmpSensorMap[sensorIndex++] = SENSOR_ANALOG;
+											foundSensorMap[index] = SENSOR_ANALOG;
 										}
 										else
 										{
@@ -531,53 +624,50 @@
 									}
 									externalAutoDetect = DETECTION_UARTMUX;
 									externalInterface_SwitchUART(EXT_INTERFACE_UART_O2 >> 8);
-									UART_SetDigO2_Channel(MAX_MUX_CHANNEL);
+									UART_MUX_SelectAddress(MAX_MUX_CHANNEL);
+									uartO2_SetChannel(MAX_MUX_CHANNEL);
+									activeUartChannel = MAX_MUX_CHANNEL;
+									tmpSensorMap[EXT_INTERFACE_SENSOR_CNT-1] = SENSOR_MUX;
 				break;
-			case DETECTION_UARTMUX:  	if(UART_isDigO2Connected())
+			case DETECTION_UARTMUX:  	if(uartO2_isSensorConnected())
 										{
 											uartMuxChannel = 1;
+											tmpSensorMap[EXT_INTERFACE_SENSOR_CNT-1] = SENSOR_MUX;
+											foundSensorMap[EXT_INTERFACE_SENSOR_CNT-1] = SENSOR_MUX;
+										}
+										else
+										{
+											tmpSensorMap[EXT_INTERFACE_SENSOR_CNT-1] = SENSOR_NONE;
 										}
 										externalAutoDetect = DETECTION_DIGO2_0;
 										externalInterface_SwitchUART(EXT_INTERFACE_UART_O2 >> 8);
-										UART_SetDigO2_Channel(0);
-										
+										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_SwitchUART(EXT_INTERFACE_UART_O2 >> 8);
 				break;
 			case DETECTION_DIGO2_0:
 			case DETECTION_DIGO2_1: 
 			case DETECTION_DIGO2_2:
 			case DETECTION_DIGO2_3:
-									if(UART_isDigO2Connected())
+									if(uartO2_isSensorConnected())
 									{
-										for(index = 0; index < 3; index++)	/* lookup a channel which may be used by digO2 */
-										{
-											if(tmpSensorMap[index] == SENSOR_NONE)
-											{
-												break;
-											}
-										}
-										if(index == 3)
-										{
-											tmpSensorMap[2] = SENSOR_DIGO2;  /* digital sensor overwrites ADC */
-										}
-										else
-										{
-											tmpSensorMap[index] = SENSOR_DIGO2;
-											tmpMuxMapping[externalAutoDetect - DETECTION_DIGO2_0] = index;
-											if(externalAutoDetect == DETECTION_DIGO2_2 )	/* special handling needed because channel is used twice during mux detection */
-											{
-												UART_MapDigO2_Channel(0xff, externalAutoDetect - DETECTION_DIGO2_0);
-											}
-										}
+										foundSensorMap[externalAutoDetect - DETECTION_DIGO2_0 + EXT_INTERFACE_MUX_OFFSET] = SENSOR_DIGO2;
 									}
-									else
-									{
-										UART_MapDigO2_Channel(0xff, externalAutoDetect - DETECTION_DIGO2_0);
-									}
+
 									if(uartMuxChannel)
 									{
 										externalInterface_SwitchUART(EXT_INTERFACE_UART_O2 >> 8);
-										UART_SetDigO2_Channel(uartMuxChannel);
-										if(uartMuxChannel < MAX_ADC_CHANNEL - 1)
+										UART_MUX_SelectAddress(uartMuxChannel);
+										externalInterface_SensorState[uartMuxChannel + EXT_INTERFACE_MUX_OFFSET] = UART_O2_INIT;
+										uartO2_SetChannel(uartMuxChannel);
+										activeUartChannel = uartMuxChannel;
+										tmpSensorMap[uartMuxChannel - 1 + EXT_INTERFACE_MUX_OFFSET] = SENSOR_NONE;
+										tmpSensorMap[uartMuxChannel + EXT_INTERFACE_MUX_OFFSET] = SENSOR_DIGO2;
+
+										if(uartMuxChannel < MAX_MUX_CHANNEL - 1)
 										{
 											uartMuxChannel++;
 										}
@@ -591,6 +681,14 @@
 									if(externalAutoDetect == DETECTION_CO2)
 									{
 										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);
+										}
+										else
+										{
+											DigitalCO2_SendCmd(CO2CMD_MODE_STREAM, cmdString, &cmdLength);
+										}
 									}
 				break;
 			case DETECTION_CO2:		if(UART_isCO2Connected())
@@ -635,44 +733,53 @@
 									externalAutoDetect++;
 #endif
 				break;
-			case DETECTION_DONE:	if(uartMuxChannel)
+			case DETECTION_DONE:	externalAutoDetect = DETECTION_OFF;
+									externalInterface_SwitchUART(0);
+									activeUartChannel = 0xFF;
+									cntSensor = 0;
+									cntUARTSensor = 0;
+									for(index = 0; index < EXT_INTERFACE_SENSOR_CNT-1; index++)
 									{
-										tmpSensorMap[EXT_INTERFACE_SENSOR_CNT-1] = SENSOR_MUX;
-									}
-
-									for(index = 0; index < MAX_MUX_CHANNEL; index++)
-									{
-										UART_MapDigO2_Channel(tmpMuxMapping[index], index);
-									}
+										if((foundSensorMap[index] >= SENSOR_ANALOG) && (foundSensorMap[index] < SENSOR_TYPE_O2_END))
+										{
+											cntSensor++;
+										}
 
-									externalAutoDetect = DETECTION_OFF;
-									externalInterface_SwitchUART(0);
-
+										if((foundSensorMap[index] == SENSOR_DIGO2) || (foundSensorMap[index] == SENSOR_CO2))
+										{
+											cntUARTSensor++;
+										}
 
-									for(index = 0; index < MAX_ADC_CHANNEL; index++)
-									{
-										if(tmpSensorMap[index] == SENSOR_DIGO2) /* set Channel to first valid entry */
+										/* Map Mux O2 sensors to ADC Slot if ADC slot is not in use */
+										if(foundSensorMap[index] == SENSOR_DIGO2)
 										{
-											UART_SetDigO2_Channel(index);
-											break;
+											for(index2 = 0; index2 < MAX_ADC_CHANNEL; index2++)
+											{
+												if(foundSensorMap[index2] == SENSOR_NONE)
+												{
+													foundSensorMap[index2] = SENSOR_DIGO2M;		/* store a mirror instance needed for visualization */
+													Mux2ADCMap[index2] = index;
+													break;
+												}
+											}
 										}
 									}
-									for(index = 0; index < MAX_ADC_CHANNEL; index++)
+									externalInterfaceMuxReqIntervall = 0xFFFF;
+									if(cntSensor == 0)		/* return default sensor map if no sensor at all has been detected */
 									{
-										if(tmpSensorMap[index] != SENSOR_NONE)
+										foundSensorMap[0] = SENSOR_OPTIC;
+										foundSensorMap[1] = SENSOR_OPTIC;
+										foundSensorMap[2] = SENSOR_OPTIC;
+									}
+									else
+									{
+										if(cntUARTSensor != 0)
 										{
-											break;
+											externalInterfaceMuxReqIntervall = REQUEST_INT_SENSOR_MS / cntUARTSensor;
 										}
 									}
-
-									if(index == MAX_ADC_CHANNEL)		/* return default sensor map if no sensor at all has been detected */
-									{
-										tmpSensorMap[0] = SENSOR_OPTIC;
-										tmpSensorMap[1] = SENSOR_OPTIC;
-										tmpSensorMap[2] = SENSOR_OPTIC;
-									}
-									memcpy(SensorMap, tmpSensorMap, sizeof(tmpSensorMap));
-
+									memcpy(SensorMap, foundSensorMap, sizeof(foundSensorMap));
+									memset(externalInterface_SensorState,UART_O2_INIT,sizeof(externalInterface_SensorState));
 				break;
 			default:
 				break;
@@ -685,7 +792,10 @@
 {
 	char cmdString[10];
 	uint8_t cmdLength = 0;
-	uint8_t index;
+	uint8_t index, index2;
+	uint8_t cntUARTSensor = 0;
+	uint8_t lastMappedID = 0;
+
 
 	switch(Cmd & 0x00FF)		/* lower byte is reserved for commands */
 	{
@@ -699,14 +809,38 @@
 			break;
 		case EXT_INTERFACE_COPY_SENSORMAP:	if(externalAutoDetect == DETECTION_OFF)
 											{
-												memcpy(SensorMap, MasterSensorMap, 5);
-												for(index = 0; index < 3; index++)
+												memcpy(SensorMap, MasterSensorMap, sizeof(MasterSensorMap));
+												for(index = 0; index < EXT_INTERFACE_SENSOR_CNT; index++)
 												{
-													if(SensorMap[index] == SENSOR_DIGO2)
+													if((SensorMap[index] == SENSOR_DIGO2) || (SensorMap[index] == SENSOR_CO2))
+													{
+														cntUARTSensor++;
+													}
+													if(SensorMap[index] == SENSOR_DIGO2M)		/* find matching sensor for mirror */
 													{
-														break;
+														for(index2 = EXT_INTERFACE_MUX_OFFSET; index2 < EXT_INTERFACE_SENSOR_CNT; index2++)
+														{
+															if(SensorMap[index2] == SENSOR_DIGO2)
+															{
+																if(lastMappedID < index2)
+																{
+																	lastMappedID = index2;
+																	Mux2ADCMap[index] = index2;
+																	break;
+																}
+															}
+														}
 													}
 												}
+												if(cntUARTSensor > 0)
+												{
+													externalInterfaceMuxReqIntervall = REQUEST_INT_SENSOR_MS / cntUARTSensor;
+													activeUartChannel = 0xFF;
+												}
+												else
+												{
+													externalInterfaceMuxReqIntervall = 0xFFFF;
+												}
 											}
 			break;
 		default:
@@ -719,3 +853,146 @@
 	return;
 }
 
+uint8_t ExternalInterface_SelectUsedMuxChannel(uint8_t currentChannel)
+{
+	uint8_t index = currentChannel;
+	uint8_t newChannel = index;
+	uint8_t *pmap = externalInterface_GetSensorMapPointer(0);
+
+	do
+	{
+		index++;
+		if(index == MAX_MUX_CHANNEL)
+		{
+			index = 0;
+		}
+		if(((pmap[index + EXT_INTERFACE_MUX_OFFSET] == SENSOR_DIGO2) || (pmap[index + EXT_INTERFACE_MUX_OFFSET] == SENSOR_CO2))
+				&& (index != activeUartChannel))
+		{
+			newChannel = index;
+			break;
+		}
+	} while(index != currentChannel);
+
+	return newChannel;
+}
+
+void externalInterface_HandleUART()
+{
+	static uint8_t retryRequest = 0;
+	static uint32_t lastRequestTick = 0;
+	static uint32_t TriggerTick = 0;
+	uint8_t index = 0;
+	static uint8_t timeToTrigger = 0;
+	uint32_t tick =  HAL_GetTick();
+	uint8_t *pmap = externalInterface_GetSensorMapPointer(0);
+
+
+	UART_ReadData(pmap[activeSensorId]);
+
+	if(activeUartChannel == 0xFF)
+	{
+		activeUartChannel = ExternalInterface_SelectUsedMuxChannel(0);
+		uartO2_SetChannel(activeUartChannel);
+		if(pmap[EXT_INTERFACE_SENSOR_CNT-1] == SENSOR_MUX)
+		{
+			UART_MUX_SelectAddress(activeUartChannel);
+		}
+		UART_FlushRxBuffer();
+	}
+
+	if(externalInterfaceMuxReqIntervall != 0xFFFF)
+	{
+		if(externalInterface_SensorState[activeSensorId] == UART_O2_INIT)
+		{
+			lastRequestTick = tick;
+			TriggerTick = tick - 10;	/* just to make sure control is triggered */
+			timeToTrigger = 1;
+			retryRequest = 0;
+		}
+		else if(((retryRequest == 0)		/* timeout or error */
+				&& (((time_elapsed_ms(lastRequestTick,tick) > (TIMEOUT_SENSOR_ANSWER)) && (externalInterface_SensorState[activeSensorId] != UART_O2_IDLE))	/* retry if no answer after half request interval */
+					|| (externalInterface_SensorState[activeSensorId] == UART_O2_ERROR))))
+		{
+			/* The channel switch will cause the sensor to respond with an error message. */
+			/* The sensor needs ~30ms to recover before he is ready to receive the next command => transmission delay needed */
+
+			TriggerTick = tick;
+			timeToTrigger = COMMAND_TX_DELAY;
+			retryRequest = 1;
+		}
+
+		else if(time_elapsed_ms(lastRequestTick,tick) > externalInterfaceMuxReqIntervall)	/* switch sensor and / or trigger next request */
+		{
+			lastRequestTick = tick;
+			TriggerTick = tick;
+			retryRequest = 0;
+			timeToTrigger = 1;
+
+			if((externalInterface_SensorState[activeSensorId] == UART_O2_REQ_O2)		/* timeout */
+					|| (externalInterface_SensorState[activeSensorId] == UART_O2_REQ_RAW))
+			{
+				setExternalInterfaceChannel(activeSensorId,0.0);
+			}
+
+			if(pmap[EXT_INTERFACE_SENSOR_CNT-1] == SENSOR_MUX) /* select next sensor if mux is connected */
+			{
+				if(activeUartChannel < MAX_MUX_CHANNEL)
+				{
+					index = ExternalInterface_SelectUsedMuxChannel(activeUartChannel);
+					if(index != activeUartChannel)
+					{
+						timeToTrigger = 100;
+						activeUartChannel = index;
+						if(pmap[index + EXT_INTERFACE_MUX_OFFSET] == SENSOR_DIGO2)
+						{
+							uartO2_SetChannel(activeUartChannel);
+							UART_MUX_SelectAddress(activeUartChannel);
+						}
+					}
+				}
+			}
+			else
+			{
+				timeToTrigger = 1;
+			}
+		}
+		if((timeToTrigger != 0) && (time_elapsed_ms(TriggerTick,tick) > timeToTrigger))
+		{
+			timeToTrigger = 0;
+			switch (pmap[activeSensorId])
+			{
+				case SENSOR_MUX:
+				case SENSOR_DIGO2:	uartO2_Control();
+					break;
+			//	case SENSOR_CO2:	uartCO2_Control();
+					break;
+				default:
+					break;
+			}
+		}
+	}
+
+
+
+#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/scheduler.c	Thu Jul 27 21:52:19 2023 +0200
+++ b/Small_CPU/Src/scheduler.c	Mon Jul 31 19:46:29 2023 +0200
@@ -516,21 +516,9 @@
 		lasttick = HAL_GetTick();
 		ticksdiff = time_elapsed_ms(Scheduler.tickstart,lasttick);
 
-#ifdef ENABLE_CO2_SUPPORT
-		if(externalInterface_GetUARTProtocol() & (EXT_INTERFACE_UART_CO2 >> 8))
+		if(externalInterface_GetUARTProtocol() != 0)
 		{
-			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();
+			externalInterface_HandleUART();
 		}
 
 		if(ticksdiff >= Scheduler.counterSPIdata100msec * 100 + 10)
@@ -838,22 +826,9 @@
 				setButtonsNow = 0;
 		}
 
-#ifdef ENABLE_CO2_SUPPORT
-		if(externalInterface_GetUARTProtocol() & (EXT_INTERFACE_UART_CO2 >> 8))
+		if(externalInterface_GetUARTProtocol() != 0)
 		{
-			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();
+			externalInterface_HandleUART();
 		}
 
 		/* Evaluate received data at 10 ms, 110 ms, 210 ms,... duration ~<1ms */
--- a/Small_CPU/Src/uart.c	Thu Jul 27 21:52:19 2023 +0200
+++ b/Small_CPU/Src/uart.c	Mon Jul 31 19:46:29 2023 +0200
@@ -20,19 +20,18 @@
   */ 
 /* Includes ------------------------------------------------------------------*/
 #include "uart.h"
+#include "uartProtocol_O2.h"
 #include "externalInterface.h"
 #include "data_exchange.h"
 #include <string.h>	/* memset */
 
 /* Private variables ---------------------------------------------------------*/
 
-#define BUFFER_NODATA			(7u)		/* The read function needs a byte which indecated that no data for processing is available.*/
-											/* This byte shall never appear in a normal data steam */
+
 
 #define CHUNK_SIZE				(25u)		/* the DMA will handle chunk size transfers */
 #define CHUNKS_PER_BUFFER		(5u)
-#define COMMAND_TX_DELAY		(30u)		/* The time the sensor needs to recover from a invalid command request */
-#define REQUEST_INT_SENSOR_MS	(1500)		/* Minimum time interval for cyclic sensor data requests per sensor */
+
 UART_HandleTypeDef huart1;
 
 DMA_HandleTypeDef  hdma_usart1_rx;
@@ -42,24 +41,23 @@
 static uint8_t rxReadIndex;								/* Index at which new data is stared */
 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 digO2Connected = 0;						/* Binary indicator if a sensor is connected or not */
+
 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 SSensorDataDiveO2 tmpSensorDataDiveO2;			/* intermediate storage for additional sensor data */
+
 
-char tmpRxBuf[30];
-uint8_t tmpRxIdx = 0;
-
-static uartO2Status_t Comstatus_O2 = UART_O2_INIT;
-static uint8_t activeSensor = 0;
-static uint8_t sensorMapping[MAX_MUX_CHANNEL];			/* The mapping is used to assign the visible sensor channel to the mux address (DiveO2) */
+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 */	
@@ -69,11 +67,11 @@
   if(externalInterface_GetUARTProtocol() == 0x04)
   {
 	  huart1.Init.BaudRate = 19200;
-	  Comstatus_O2 = UART_O2_INIT;
   }
   else
   {
 	  huart1.Init.BaudRate = 9600;
+	  ComStatus_CO2 = UART_CO2_INIT;
   }
   huart1.Init.WordLength = UART_WORDLENGTH_8B;
   huart1.Init.StopBits = UART_STOPBITS_1;
@@ -91,10 +89,10 @@
   lastCmdIndex = 0;
   rxWriteIndex = 0;
   dmaActive = 0;
-  digO2Connected = 0;
+
   CO2Connected = 0;
   SentinelConnected = 0;
-  Comstatus_O2 = UART_O2_INIT;
+
 }
 
 void MX_USART1_UART_DeInit(void)
@@ -129,49 +127,56 @@
   HAL_NVIC_EnableIRQ(DMA2_Stream5_IRQn);
 }
 
-
-void DigitalO2_SelectSensor(uint8_t channel)
+void  UART_MUX_SelectAddress(uint8_t muxAddress)
 {
 	uint8_t indexstr[4];
-	uint8_t muxAddress = 0;
-	indexstr[0] = '~';
-	indexstr[1] = '1';
-	indexstr[2] = 0x0D;
-	indexstr[3] = 0x0A;
 
-	/* Lookup mux address mapped to the provided channel. If no mapping is found the the MUX itself will be selected */
-	for(muxAddress = 0; muxAddress < MAX_MUX_CHANNEL; muxAddress++)
+	if(muxAddress <= MAX_MUX_CHANNEL)
 	{
-		if(sensorMapping[muxAddress] == channel)
-		{
-			break;
-		}
+		indexstr[0] = '~';
+		indexstr[1] = muxAddress;
+		indexstr[2] = 0x0D;
+		indexstr[3] = 0x0A;
+
+		HAL_UART_Transmit(&huart1,indexstr,4,10);
 	}
-	indexstr[1] = muxAddress;
-	HAL_UART_Transmit(&huart1,indexstr,4,10);
 }
 
-void DigitalO2_SetupCmd(uint8_t O2State, uint8_t *cmdString, uint8_t *cmdLength)
+
+void UART_SendCmdString(uint8_t *cmdString)
 {
-	switch (O2State)
+	uint8_t cmdLength = strlen((char*)cmdString);
+
+	if(cmdLength < 20)		/* A longer string is an indication for a missing 0 termination */
 	{
-		case UART_O2_CHECK:		*cmdLength = snprintf((char*)cmdString, 10, "#LOGO");
-			break;
-		case UART_O2_REQ_INFO: 	*cmdLength = snprintf((char*)cmdString, 10, "#VERS");
-					break;
-		case UART_O2_REQ_ID: 	*cmdLength = snprintf((char*)cmdString, 10, "#IDNR");
-			break;
-		case UART_O2_REQ_O2: 	*cmdLength = snprintf((char*)cmdString, 10, "#DOXY");
-			break;
-		case UART_O2_REQ_RAW:	*cmdLength = snprintf((char*)cmdString, 10, "#DRAW");
-			break;
+		if(dmaActive == 0)
+		{
+			UART_StartDMA_Receiption();
+		}
+		HAL_UART_Transmit(&huart1,cmdString,cmdLength,10);
+	}
+}
+
+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)
+	if(cmdLength != 0)
 	{
-		cmdString[*cmdLength] = 0x0D;
-		*cmdLength = *cmdLength + 1;
+		HAL_UART_Transmit(&huart1,cmdString,*cmdLength,10);
 	}
 }
 
@@ -239,11 +244,57 @@
 	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;
+	}
 
-	while((rxBuffer[localRX]!=0))
+	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
 	{
-		lastReceiveTick = HAL_GetTick();
+		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))
+	{
+		lastReceiveTick = Tick;
 		if(rxState == RX_Ready)		/* identify data content */
 		{
 			switch(rxBuffer[localRX])
@@ -251,6 +302,7 @@
 				case 'l':
 				case 'D':
 				case 'Z':
+				case '.':
 									dataType = rxBuffer[localRX];
 									rxState = RX_Data0;
 									dataValue = 0;
@@ -293,6 +345,8 @@
 						break;
 					case 'Z':			externalInterface_SetCO2Value(dataValue);
 						break;
+					case '.':			externalInterface_SetCO2Scale(dataValue);
+						break;
 					default:			rxState = RX_Ready;
 						break;
 				}
@@ -302,7 +356,7 @@
 				rxState = RX_Ready;
 			}
 		}
-		rxBuffer[localRX] = 0;
+		rxBuffer[localRX] = BUFFER_NODATA;
 		localRX++;
 		rxReadIndex++;
 		if(rxReadIndex >= CHUNK_SIZE * CHUNKS_PER_BUFFER)
@@ -477,386 +531,6 @@
 #endif
 
 
-
-void UART_HandleDigitalO2(void)
-{
-	static uint32_t lastO2ReqTick = 0;
-	static uint8_t errorStr[] = "#ERRO";
-	static uartO2RxState_t rxState = O2RX_IDLE;
-	static uint32_t lastReceiveTick = 0;
-	static uint8_t lastAlive = 0;
-	static uint8_t curAlive = 0;
-
-	static uint8_t cmdLength = 0;
-	static uint8_t cmdString[10];
-	static uint8_t cmdReadIndex = 0;
-	static uint8_t errorReadIndex = 0;
-	static	uint32_t tickToTX =  0;
-	static uint32_t delayStartTick = 0;
-	static uint16_t requestIntervall = 0;
-	static uint8_t	retryRequest = 1;
-	static uint8_t lastComState = 0;
-	static uint8_t respondErrorDetected = 0;
-	static uint8_t switchChannel = 0;
-
-	uint8_t index = 0;
-	uint32_t tmpO2 = 0;
-	uint32_t tmpData = 0;
-	uint8_t localRX = rxReadIndex;
-	uint32_t tick =  HAL_GetTick();
-
-	uint8_t *pmap = externalInterface_GetSensorMapPointer(0);
-
-	/* The channel switch will cause the sensor to respond with an error message. */
-	/* The sensor needs ~30ms to recover before he is ready to receive the next command => transmission delay needed */
-	if((tickToTX) && (time_elapsed_ms(delayStartTick,tick) >= tickToTX ))
-	{
-		HAL_UART_Transmit(&huart1,cmdString,cmdLength,10);
-		tickToTX = 0;
-	}
-	else
-	{
-		if(Comstatus_O2 == UART_O2_INIT)
-		{
-			memset((char*)&rxBuffer[rxWriteIndex],(int)BUFFER_NODATA, sizeof(rxBuffer));
-			memset((char*) &tmpSensorDataDiveO2, 0, sizeof(tmpSensorDataDiveO2));
-			externalInterface_SetSensorData(0xFF,(uint8_t*)&tmpSensorDataDiveO2);
-
-			lastAlive = 0;
-			curAlive = 0;
-
-			Comstatus_O2 = UART_O2_CHECK;
-			lastComState = UART_O2_IDLE;
-			DigitalO2_SetupCmd(Comstatus_O2,cmdString,&cmdLength);
-
-			if(activeSensor < MAX_MUX_CHANNEL)
-			{
-				externalInterface_GetSensorData(activeSensor, (uint8_t*)&tmpSensorDataDiveO2);
-			}
-
-			tickToTX = COMMAND_TX_DELAY;
-
-			rxState = O2RX_CONFIRM;
-			cmdReadIndex = 0;
-			errorReadIndex = 0;
-			respondErrorDetected = 0;
-			digO2Connected = 0;
-			switchChannel = 1;
-
-			requestIntervall = 0;
-			for(index = 0; index < MAX_MUX_CHANNEL; index++)
-			{
-				if(pmap[index] == SENSOR_DIGO2)
-				{
-					requestIntervall++;
-				}
-			}
-			if(requestIntervall != 0)
-			{
-				requestIntervall = REQUEST_INT_SENSOR_MS / requestIntervall;
-			}
-			else
-			{
-				requestIntervall = REQUEST_INT_SENSOR_MS;
-			}
-			UART_StartDMA_Receiption();
-			lastO2ReqTick = tick + requestIntervall + 1;
-		}
-		if(time_elapsed_ms(lastO2ReqTick,tick) > requestIntervall)		/* repeat request or iterate to next sensor */
-		{
-			respondErrorDetected = 0;
-			lastO2ReqTick = tick;
-			index = activeSensor;
-			if((lastComState == Comstatus_O2) && (Comstatus_O2 != UART_O2_IDLE))
-			{
-				if(retryRequest)
-				{
-					retryRequest = 0;
-				}
-				else			/* no answer even repeating the request => abort request */
-				{
-					if(Comstatus_O2 == UART_O2_REQ_RAW)
-					{
-						setExternalInterfaceChannel(activeSensor,0.0);
-					}
-					Comstatus_O2 = UART_O2_IDLE;
-				}
-			}
-			lastComState = Comstatus_O2;
-			if(Comstatus_O2 == UART_O2_IDLE)							/* cyclic request of o2 value */
-			{
-				retryRequest = 1;
-				if(pmap[EXT_INTERFACE_SENSOR_CNT-1] == SENSOR_MUX) /* select next sensor if mux is connected */
-				{
-					if(activeSensor < MAX_MUX_CHANNEL)
-					{
-						do
-						{
-							index++;
-							if(index == MAX_MUX_CHANNEL)
-							{
-								index = 0;
-							}
-							if((pmap[index] == SENSOR_DIGO2) && (index != activeSensor))
-							{
-								activeSensor = index;
-								switchChannel = 1;
-								break;
-							}
-						} while(index != activeSensor);
-						externalInterface_GetSensorData(activeSensor, (uint8_t*)&tmpSensorDataDiveO2);
-					}
-				}
-				if((activeSensor != MAX_MUX_CHANNEL) && (tmpSensorDataDiveO2.sensorId == 0))
-				{
-					Comstatus_O2 = UART_O2_REQ_ID;
-				}
-				else
-				{
-					Comstatus_O2 = UART_O2_REQ_RAW;
-				}
-			}
-			rxState = O2RX_CONFIRM;
-			if(switchChannel)
-			{
-				switchChannel = 0;
-				delayStartTick = tick;
-				DigitalO2_SelectSensor(activeSensor);
-				tickToTX = COMMAND_TX_DELAY;
-			}
-			else
-			{
-				tickToTX = 0;
-				HAL_UART_Transmit(&huart1,cmdString,cmdLength,10);
-			}
-			DigitalO2_SetupCmd(Comstatus_O2,cmdString,&cmdLength);
-		}
-	}
-	while((rxBuffer[localRX] != BUFFER_NODATA))
-	{
-		lastReceiveTick = tick;
-		switch(rxState)
-		{
-			case O2RX_CONFIRM:	if(rxBuffer[localRX] == '#')
-								{
-									cmdReadIndex = 0;
-									errorReadIndex = 0;
-								}
-								if(errorReadIndex < sizeof(errorStr)-1)
-								{
-									if(rxBuffer[localRX] == errorStr[errorReadIndex])
-									{
-										errorReadIndex++;
-									}
-									else
-									{
-										errorReadIndex = 0;
-									}
-								}
-								else
-								{
-									respondErrorDetected = 1;
-									errorReadIndex = 0;
-								}
-								if(rxBuffer[localRX] == cmdString[cmdReadIndex])
-								{
-									cmdReadIndex++;
-									if(cmdReadIndex == cmdLength - 1)
-									{
-										if((activeSensor == MAX_MUX_CHANNEL))
-										{
-											if(respondErrorDetected)
-											{
-												digO2Connected = 0;		/* the multiplexer mirrors the incoming message and does not generate an error information => no mux connected */
-											}
-											else
-											{
-												digO2Connected = 1;
-											}
-										}
-										else							/* handle sensors which should respond with an error message after channel switch */
-										{
-											if(respondErrorDetected)
-											{
-												digO2Connected = 1;
-											}
-										}
-										tmpRxIdx = 0;
-										memset((char*) tmpRxBuf, 0, sizeof(tmpRxBuf));
-										cmdReadIndex = 0;
-										switch (Comstatus_O2)
-										{
-												case UART_O2_CHECK:	Comstatus_O2 = UART_O2_IDLE;
-																	rxState = O2RX_IDLE;
-													break;
-												case UART_O2_REQ_ID: rxState = O2RX_GETNR;
-													break;
-												case UART_O2_REQ_INFO: rxState = O2RX_GETTYPE;
-													break;
-												case UART_O2_REQ_RAW:
-												case UART_O2_REQ_O2:	rxState = O2RX_GETO2;
-													break;
-												default:	Comstatus_O2 = UART_O2_IDLE;
-															rxState = O2RX_IDLE;
-														break;
-										}
-									}
-								}
-								else
-								{
-									cmdReadIndex = 0;
-								}
-					break;
-
-				case O2RX_GETSTATUS:
-				case O2RX_GETTEMP:
-				case O2RX_GETTYPE:
-				case O2RX_GETVERSION:
-				case O2RX_GETCHANNEL:
-				case O2RX_GETSUBSENSORS:
-				case O2RX_GETO2:
-				case O2RX_GETNR:
-				case O2RX_GETDPHI:
-				case O2RX_INTENSITY:
-				case O2RX_AMBIENTLIGHT:
-				case O2RX_PRESSURE:
-				case O2RX_HUMIDITY:
-									if(rxBuffer[localRX] != 0x0D)
-									{
-										if(rxBuffer[localRX] != ' ')		/* the following data entities are placed within the data stream => no need to store data at the end */
-										{
-											tmpRxBuf[tmpRxIdx++] = rxBuffer[localRX];
-										}
-										else
-										{
-											if(tmpRxIdx != 0)
-											{
-												switch(rxState)
-												{
-													case O2RX_GETCHANNEL:	StringToInt(tmpRxBuf,&tmpData);
-																			rxState = O2RX_GETVERSION;
-															break;
-													case O2RX_GETVERSION:	StringToInt(tmpRxBuf,&tmpData);
-																			rxState = O2RX_GETSUBSENSORS;
-															break;
-													case O2RX_GETTYPE: 		StringToInt(tmpRxBuf,&tmpData);
-																			rxState = O2RX_GETCHANNEL;
-															break;
-
-													case O2RX_GETO2: 		StringToInt(tmpRxBuf,&tmpO2);
-																			setExternalInterfaceChannel(activeSensor,(float)(tmpO2 / 10000.0));
-																			rxState = O2RX_GETTEMP;
-														break;
-													case O2RX_GETTEMP:		StringToInt(tmpRxBuf,(uint32_t*)&tmpSensorDataDiveO2.temperature);
-																			rxState = O2RX_GETSTATUS;
-														break;
-													case O2RX_GETSTATUS:	StringToInt(tmpRxBuf,&tmpSensorDataDiveO2.status);				/* raw data cycle */
-																			rxState = O2RX_GETDPHI;
-														break;
-													case O2RX_GETDPHI:		/* ignored to save memory and most likly irrelevant for diver */
-																			rxState = O2RX_INTENSITY;
-																										break;
-													case O2RX_INTENSITY:	StringToInt(tmpRxBuf,(uint32_t*)&tmpSensorDataDiveO2.intensity);				/* raw data cycle */
-																			rxState = O2RX_AMBIENTLIGHT;
-																										break;
-													case O2RX_AMBIENTLIGHT:	StringToInt(tmpRxBuf,(uint32_t*)&tmpSensorDataDiveO2.ambient);				/* raw data cycle */
-																			rxState = O2RX_PRESSURE;
-																										break;
-													case O2RX_PRESSURE:	StringToInt(tmpRxBuf,(uint32_t*)&tmpSensorDataDiveO2.pressure);					/* raw data cycle */
-																			rxState = O2RX_HUMIDITY;
-																										break;
-													default:
-														break;
-												}
-												memset((char*) tmpRxBuf, 0, tmpRxIdx);
-												tmpRxIdx = 0;
-											}
-										}
-									}
-									else
-									{							/* the following data items are the last of a sensor respond => store temporal data */
-										switch (rxState)
-										{
-											case O2RX_GETSTATUS:		StringToInt(tmpRxBuf,&tmpSensorDataDiveO2.status);
-																		externalInterface_SetSensorData(activeSensor,(uint8_t*)&tmpSensorDataDiveO2);
-																		Comstatus_O2 = UART_O2_IDLE;
-																		rxState = O2RX_IDLE;
-													break;
-											case O2RX_GETSUBSENSORS:	StringToInt(tmpRxBuf,&tmpData);
-																		Comstatus_O2 = UART_O2_IDLE;
-																		rxState = O2RX_IDLE;
-													break;
-											case O2RX_HUMIDITY:			StringToInt(tmpRxBuf,(uint32_t*)&tmpSensorDataDiveO2.humidity);				/* raw data cycle */
-																		externalInterface_SetSensorData(activeSensor,(uint8_t*)&tmpSensorDataDiveO2);
-																		Comstatus_O2 = UART_O2_IDLE;
-																		rxState = O2RX_IDLE;
-													break;
-											case  O2RX_GETNR: 			StringToUInt64((char*)tmpRxBuf,&tmpSensorDataDiveO2.sensorId);
-																		externalInterface_SetSensorData(activeSensor,(uint8_t*)&tmpSensorDataDiveO2);
-																		index = activeSensor;
-																		Comstatus_O2 = UART_O2_IDLE;
-																		rxState = O2RX_IDLE;
-												break;
-											default:		Comstatus_O2 = UART_O2_IDLE;
-															rxState = O2RX_IDLE;
-												break;
-										}
-									}
-						break;
-				default:				rxState = O2RX_IDLE;
-					break;
-
-		}
-		rxBuffer[localRX] = BUFFER_NODATA;
-		localRX++;
-		rxReadIndex++;
-		if(rxReadIndex >= CHUNK_SIZE * CHUNKS_PER_BUFFER)
-		{
-			localRX = 0;
-			rxReadIndex = 0;
-		}
-	}
-
-	if((digO2Connected) && time_elapsed_ms(lastReceiveTick,HAL_GetTick()) > 4000)	/* check for communication timeout */
-	{
-		digO2Connected = 0;
-		if(curAlive == lastAlive)
-		{
-			for(index = 0; index < MAX_ADC_CHANNEL; index++)
-			{
-				if(pmap[index] == SENSOR_DIGO2)
-				{
-					setExternalInterfaceChannel(index,0.0);
-				}
-			}
-		}
-		lastAlive = curAlive;
-	}
-	if((dmaActive == 0)	&& (externalInterface_isEnabledPower33()))	/* Should never happen in normal operation => restart in case of communication error */
-	{
-		UART_StartDMA_Receiption();
-	}
-}
-
-void UART_SetDigO2_Channel(uint8_t channel)
-{
-	if(channel <= MAX_MUX_CHANNEL)
-	{
-		activeSensor = channel;
-	}
-}
-void UART_MapDigO2_Channel(uint8_t channel, uint8_t muxAddress)
-{
-	if(((channel < MAX_ADC_CHANNEL) || (channel == 0xff)) && (muxAddress < MAX_MUX_CHANNEL))
-	{
-		sensorMapping[muxAddress] = channel;
-	}
-}
-
-uint8_t UART_isDigO2Connected()
-{
-	return digO2Connected;
-}
 uint8_t UART_isCO2Connected()
 {
 	return CO2Connected;
@@ -886,6 +560,46 @@
     }
 }
 
+void UART_ReadData(uint8_t sensorType)
+{
+	uint8_t localRX = rxReadIndex;
 
+	while((rxBuffer[localRX]!=BUFFER_NODATA))
+	{
+		switch (sensorType)
+		{
+			case SENSOR_MUX:
+			case SENSOR_DIGO2:	uartO2_ProcessData(rxBuffer[localRX]);
+				break;
+	//	case SENSOR_CO2:	uartCO2_Control();
+				break;
+			default:
+				break;
+		}
+
+		rxBuffer[localRX] = BUFFER_NODATA;
+		localRX++;
+		rxReadIndex++;
+		if(rxReadIndex >= CHUNK_SIZE * CHUNKS_PER_BUFFER)
+		{
+			localRX = 0;
+			rxReadIndex = 0;
+		}
+	}
+}
+
+void UART_FlushRxBuffer(void)
+{
+	while(rxBuffer[rxReadIndex] != BUFFER_NODATA)
+	{
+		rxBuffer[rxReadIndex] = BUFFER_NODATA;
+		rxReadIndex++;
+		if(rxReadIndex >= CHUNK_SIZE * CHUNKS_PER_BUFFER)
+		{
+			rxReadIndex = 0;
+		}
+	}
+
+}
 
 /************************ (C) COPYRIGHT heinrichs weikamp *****END OF FILE****/