view Small_CPU/Src/uart.c @ 787:aeb72882f30a

Dev Bugfx Empty buffer indication and stability improvments: The mux prototype used ASCII coding for channel selection while the current realization used real number (0...4) for addressing the mux. The UART read function uses the '0' to indicate an empty buffer element. The mux now loops back '0' used by channel selection causing the read function to process the data. As result data interrups are visible at the display. To avoid this another character has been defined indicate empty buffer locations. Beside this the functionality has been improved with regard to access speed and better recovery in case of transition failure.
author Ideenmodellierer
date Sun, 04 Jun 2023 21:59:26 +0200
parents 3c0b16473af4
children bb37d4f3e50e
line wrap: on
line source

/**
  ******************************************************************************
  * @file    uart.c 
  * @author  heinrichs weikamp gmbh
  * @version V0.0.1
  * @date    27-March-2014
  * @brief   button control
  *           
  @verbatim                 
  ============================================================================== 
                        ##### How to use #####
  ============================================================================== 
  @endverbatim
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT(c) 2015 heinrichs weikamp</center></h2>
  *
  ******************************************************************************
  */ 
/* Includes ------------------------------------------------------------------*/
#include "uart.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;

uint8_t rxBuffer[CHUNK_SIZE * CHUNKS_PER_BUFFER];		/* The complete buffer has a X * chunk size to allow fariations in buffer read time */
static uint8_t rxWriteIndex;							/* Index of the data item which is analysed */
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) */

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 --------------------------------------------------------*/

void MX_USART1_UART_Init(void)
{
/* regular init */	

  huart1.Instance = USART1;

  if(externalInterface_GetUARTProtocol() == 0x04)
  {
	  huart1.Init.BaudRate = 19200;
	  Comstatus_O2 = UART_O2_INIT;
  }
  else
  {
	  huart1.Init.BaudRate = 9600;
  }
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;

  HAL_UART_Init(&huart1);

  MX_USART1_DMA_Init();

  memset(rxBuffer,BUFFER_NODATA,sizeof(rxBuffer));
  rxReadIndex = 0;
  lastCmdIndex = 0;
  rxWriteIndex = 0;
  dmaActive = 0;
  digO2Connected = 0;
  CO2Connected = 0;
  SentinelConnected = 0;
  Comstatus_O2 = UART_O2_INIT;
}

void MX_USART1_UART_DeInit(void)
{
	HAL_DMA_Abort(&hdma_usart1_rx);
	HAL_DMA_DeInit(&hdma_usart1_rx);
	HAL_UART_DeInit(&huart1);
}

void  MX_USART1_DMA_Init()
{
  /* DMA controller clock enable */
  __DMA2_CLK_ENABLE();

  /* Peripheral DMA init*/
  hdma_usart1_rx.Instance = DMA2_Stream5;
  hdma_usart1_rx.Init.Channel = DMA_CHANNEL_4;
  hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; //DMA_MEMORY_TO_PERIPH;
  hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
  hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;
  hdma_usart1_rx.Init.PeriphDataAlignment = DMA_MDATAALIGN_BYTE;
  hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
  hdma_usart1_rx.Init.Mode = DMA_NORMAL;
  hdma_usart1_rx.Init.Priority = DMA_PRIORITY_LOW;
  hdma_usart1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
  HAL_DMA_Init(&hdma_usart1_rx);

  __HAL_LINKDMA(&huart1,hdmarx,hdma_usart1_rx);

  /* DMA interrupt init */
  HAL_NVIC_SetPriority(DMA2_Stream5_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA2_Stream5_IRQn);
}


void DigitalO2_SelectSensor(uint8_t channel)
{
	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(sensorMapping[muxAddress] == channel)
		{
			break;
		}
	}
	indexstr[1] = muxAddress;
	HAL_UART_Transmit(&huart1,indexstr,4,10);
}

void DigitalO2_SetupCmd(uint8_t O2State, uint8_t *cmdString, uint8_t *cmdLength)
{
	switch (O2State)
	{
		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;
		default: *cmdLength = 0;
			break;
	}
	if(*cmdLength != 0)
	{
		cmdString[*cmdLength] = 0x0D;
		*cmdLength = *cmdLength + 1;
	}
}

void StringToInt(char *pstr, uint32_t *puInt32)
{
	uint8_t index = 0;
	uint32_t result = 0;
	while((pstr[index] >= '0') && (pstr[index] <= '9'))
	{
		result *=10;
		result += pstr[index] - '0';
		index++;
	}
	*puInt32 = result;
}

void StringToUInt64(char *pstr, uint64_t *puint64)
{
	uint8_t index = 0;
	uint64_t result = 0;
	while((pstr[index] >= '0') && (pstr[index] <= '9'))
	{
		result *=10;
		result += pstr[index] - '0';
		index++;
	}
	*puint64 = result;
}
void ConvertByteToHexString(uint8_t byte, char* str)
{
	uint8_t worker = 0;
	uint8_t digit = 0;
	uint8_t digitCnt = 1;

	worker = byte;
	while((worker!=0) && (digitCnt != 255))
	{
		digit = worker % 16;
		if( digit < 10)
		{
			digit += '0';
		}
		else
		{
			digit += 'A' - 10;
		}
		str[digitCnt--]= digit;
		worker = worker / 16;
	}
}

void UART_StartDMA_Receiption()
{
	if(HAL_OK == HAL_UART_Receive_DMA (&huart1, &rxBuffer[rxWriteIndex], CHUNK_SIZE))
	{
		dmaActive = 1;
	}
}

#ifdef ENABLE_CO2_SUPPORT
void UART_HandleCO2Data(void)
{
	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;


	while((rxBuffer[localRX]!=0))
	{
		lastReceiveTick = HAL_GetTick();
		if(rxState == RX_Ready)		/* identify data content */
		{
			switch(rxBuffer[localRX])
			{
				case 'l':
				case 'D':
				case 'Z':
									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;
					default:			rxState = RX_Ready;
						break;
				}
			}
			if(rxState != RX_Data0)	/* reset state machine because message in wrong format */
			{
				rxState = RX_Ready;
			}
		}
		rxBuffer[localRX] = 0;
		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 */
	{
		UART_StartDMA_Receiption();
	}
}
#endif

#ifdef ENABLE_SENTINEL_MODE
void UART_HandleSentinelData(void)
{
	uint8_t localRX = rxReadIndex;
	static uint8_t dataType = 0;
	static uint32_t dataValue[3];
	static uint8_t dataValueIdx = 0;
	static receiveState_t rxState = RX_Ready;
	static uint32_t lastReceiveTick = 0;
	static uint8_t lastAlive = 0;
	static uint8_t curAlive = 0;
	static uint8_t checksum = 0;
	static char checksum_str[]="00";

	while((rxBuffer[localRX]!=0))
	{
		lastReceiveTick = HAL_GetTick();

		switch(rxState)
		{
			case RX_Ready:	if((rxBuffer[localRX] >= 'a') && (rxBuffer[localRX] <= 'z'))
							{
								rxState = RX_DetectStart;
								curAlive = rxBuffer[localRX];
								checksum = 0;
							}
					break;

			case RX_DetectStart: 	checksum += rxBuffer[localRX];
									if(rxBuffer[localRX] == '1')
								 	{
								 		rxState = RX_SelectData;
								 		dataType = 0xFF;

								 	}
									else
									{
										rxState = RX_Ready;
									}
					break;

			case RX_SelectData:		checksum += rxBuffer[localRX];
									switch(rxBuffer[localRX])
									{
										case 'T':	dataType = rxBuffer[localRX];
											break;
										case '0': 	if(dataType != 0xff)
													{
														rxState = RX_Data0;
														dataValueIdx = 0;
														dataValue[0] = 0;

													}
													else
													{
														rxState = RX_Ready;
													}
											break;
										default:	rxState = RX_Ready;
									}
					break;

			case RX_Data0:
			case RX_Data1:
			case RX_Data2:
			case RX_Data4:
			case RX_Data5:
			case RX_Data6:
			case RX_Data8:
			case RX_Data9:
			case RX_Data10: checksum += rxBuffer[localRX];
							if((rxBuffer[localRX] >= '0') && (rxBuffer[localRX] <= '9'))
							{
								dataValue[dataValueIdx] = dataValue[dataValueIdx] * 10 + (rxBuffer[localRX] - '0');
								rxState++;
							}
							else
							{
								rxState = RX_Ready;
							}
					break;

			case RX_Data3:
			case RX_Data7:	checksum += rxBuffer[localRX];
							if(rxBuffer[localRX] == '0')
							{
								rxState++;
								dataValueIdx++;
								dataValue[dataValueIdx] = 0;
							}
							else
							{
								rxState = RX_Ready;
							}
					break;
			case RX_Data11: rxState = RX_DataComplete;
							ConvertByteToHexString(checksum,checksum_str);
							if(rxBuffer[localRX] == checksum_str[0])
							{
								rxState = RX_DataComplete;
							}
							else
							{
								rxState = RX_Ready;
							}

				break;

			case RX_DataComplete:	if(rxBuffer[localRX] == checksum_str[1])
									{
										setExternalInterfaceChannel(0,(float)(dataValue[0] / 10.0));
										setExternalInterfaceChannel(1,(float)(dataValue[1] / 10.0));
										setExternalInterfaceChannel(2,(float)(dataValue[2] / 10.0));
										SentinelConnected = 1;
									}
									rxState = RX_Ready;
				break;


			default:				rxState = RX_Ready;
				break;

		}
		localRX++;
		rxReadIndex++;
		if(rxReadIndex >= CHUNK_SIZE * CHUNKS_PER_BUFFER)
		{
			localRX = 0;
			rxReadIndex = 0;
		}
	}

	if(time_elapsed_ms(lastReceiveTick,HAL_GetTick()) > 4000)	/* check for communication timeout */
	{
		if(curAlive == lastAlive)
		{
			setExternalInterfaceChannel(0,0.0);
			setExternalInterfaceChannel(1,0.0);
			setExternalInterfaceChannel(2,0.0);
			SentinelConnected = 0;
		}
		lastAlive = curAlive;
	}

	if((dmaActive == 0)	&& (externalInterface_isEnabledPower33()))	/* Should never happen in normal operation => restart in case of communication error */
	{
		UART_StartDMA_Receiption();
	}
}
#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;
}
uint8_t UART_isSentinelConnected()
{
	return SentinelConnected;
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if(huart == &huart1)
    {
    	dmaActive = 0;
    	rxWriteIndex+=CHUNK_SIZE;
    	if(rxWriteIndex >= CHUNK_SIZE * CHUNKS_PER_BUFFER)
    	{
    		rxWriteIndex = 0;
    	}
    	if((rxWriteIndex / CHUNK_SIZE) != (rxReadIndex / CHUNK_SIZE) || (rxWriteIndex == rxReadIndex))	/* start next transfer if we did not catch up with read index */
    	{
    		if(externalInterface_GetUARTProtocol() != 0)
    		{
				UART_StartDMA_Receiption();
    		}
    	}
    }
}



/************************ (C) COPYRIGHT heinrichs weikamp *****END OF FILE****/