795
+ − 1 /**
+ − 2 ******************************************************************************
+ − 3 * @file uartProtocol_O2.c
+ − 4 * @author heinrichs weikamp gmbh
+ − 5 * @version V0.0.1
+ − 6 * @date 16-Jun-2023
+ − 7 * @brief Interface functionality to external, UART based O2 sensors
+ − 8 *
+ − 9 @verbatim
+ − 10
+ − 11
+ − 12 @endverbatim
+ − 13 ******************************************************************************
+ − 14 * @attention
+ − 15 *
+ − 16 * <h2><center>© COPYRIGHT(c) 2023 heinrichs weikamp</center></h2>
+ − 17 *
+ − 18 ******************************************************************************
+ − 19 */
+ − 20 /* Includes ------------------------------------------------------------------*/
+ − 21
+ − 22 #include <string.h>
+ − 23 #include "uart.h"
+ − 24 #include "uartProtocol_O2.h"
+ − 25 #include "externalInterface.h"
+ − 26
+ − 27
+ − 28 const uint8_t errorStr[] = "#ERRO";
+ − 29 static uint32_t lastReceiveTick = 0;
+ − 30 static uartO2RxState_t rxState = O2RX_IDLE;
+ − 31 static uint8_t digO2Connected = 0; /* Binary indicator if a sensor is connected or not */
+ − 32 static SSensorDataDiveO2 tmpSensorDataDiveO2; /* intermediate storage for additional sensor data */
+ − 33
+ − 34 static uint8_t activeSensor = 0;
+ − 35 static uint8_t respondErrorDetected = 0;
+ − 36
+ − 37 void uartO2_InitData()
+ − 38 {
+ − 39 digO2Connected = 0;
+ − 40 }
+ − 41
+ − 42 void uartO2_SetupCmd(uint8_t O2State, uint8_t *cmdString, uint8_t *cmdLength)
+ − 43 {
+ − 44 switch (O2State)
+ − 45 {
+ − 46 case UART_O2_CHECK: *cmdLength = snprintf((char*)cmdString, 10, "#LOGO");
+ − 47 break;
+ − 48 case UART_O2_REQ_INFO: *cmdLength = snprintf((char*)cmdString, 10, "#VERS");
+ − 49 break;
+ − 50 case UART_O2_REQ_ID: *cmdLength = snprintf((char*)cmdString, 10, "#IDNR");
+ − 51 break;
800
+ − 52 case UART_O2_REQ_O2: *cmdLength = snprintf((char*)cmdString, 10, "#DOXY");
795
+ − 53 break;
800
+ − 54 case UART_O2_REQ_RAW: *cmdLength = snprintf((char*)cmdString, 10, "#DRAW");
795
+ − 55 break;
+ − 56 default: *cmdLength = 0;
+ − 57 break;
+ − 58 }
+ − 59 if(*cmdLength != 0)
+ − 60 {
+ − 61 cmdString[*cmdLength] = 0x0D;
+ − 62 *cmdLength = *cmdLength + 1;
+ − 63 cmdString[*cmdLength] = 0x0A;
+ − 64 *cmdLength = *cmdLength + 1;
+ − 65 cmdString[*cmdLength] = 0;
+ − 66 *cmdLength = *cmdLength + 1;
+ − 67 }
+ − 68 }
+ − 69
+ − 70 static uint8_t cmdLength = 0;
+ − 71 static uint8_t cmdString[10];
+ − 72
+ − 73 void uartO2_Control(void)
+ − 74 {
+ − 75 static uint8_t lastComState = 0;
+ − 76 static uint8_t lastActiveSensor = 0xFF;
+ − 77
+ − 78 uint8_t activeSensor = externalInterface_GetActiveUartSensor();
+ − 79
+ − 80 uartO2Status_t localComState = externalInterface_GetSensorState(activeSensor + EXT_INTERFACE_MUX_OFFSET);
+ − 81 externalInterface_GetSensorData(activeSensor + EXT_INTERFACE_MUX_OFFSET, (uint8_t*)&tmpSensorDataDiveO2);
+ − 82
+ − 83
+ − 84 if(lastActiveSensor != activeSensor)
+ − 85 {
+ − 86 lastActiveSensor = activeSensor;
+ − 87 if(localComState != UART_O2_ERROR)
+ − 88 {
+ − 89 lastComState = localComState;
+ − 90 }
+ − 91 else
+ − 92 {
+ − 93 lastComState = UART_O2_IDLE;
+ − 94 }
+ − 95 if(localComState == UART_O2_CHECK)
+ − 96 {
+ − 97 localComState = UART_O2_IDLE;
+ − 98 }
+ − 99 UART_FlushRxBuffer();
+ − 100 }
+ − 101
800
+ − 102 if(localComState == UART_O2_INIT)
795
+ − 103 {
+ − 104 memset((char*) &tmpSensorDataDiveO2, 0, sizeof(tmpSensorDataDiveO2));
+ − 105 externalInterface_SetSensorData(0xFF,(uint8_t*)&tmpSensorDataDiveO2);
+ − 106
+ − 107 localComState = UART_O2_CHECK;
+ − 108 lastComState = UART_O2_CHECK;
932
+ − 109 UART_clearRxBuffer(&Uart1Ctrl);
795
+ − 110 uartO2_SetupCmd(localComState,cmdString,&cmdLength);
916
+ − 111 UART_SendCmdString(cmdString);
795
+ − 112 rxState = O2RX_CONFIRM;
+ − 113 respondErrorDetected = 0;
+ − 114 digO2Connected = 0;
+ − 115 }
+ − 116 else
+ − 117 {
+ − 118 if(localComState == UART_O2_ERROR)
+ − 119 {
+ − 120 localComState = lastComState;
+ − 121 }
+ − 122 lastComState = localComState;
+ − 123 if(localComState == UART_O2_IDLE) /* cyclic request of o2 value */
+ − 124 {
+ − 125 if((activeSensor != MAX_MUX_CHANNEL) && (tmpSensorDataDiveO2.sensorId == 0))
+ − 126 {
+ − 127 localComState = UART_O2_REQ_ID;
+ − 128 }
+ − 129 else
+ − 130 {
+ − 131 localComState = UART_O2_REQ_RAW;
+ − 132 }
+ − 133 }
+ − 134 rxState = O2RX_CONFIRM;
+ − 135 uartO2_SetupCmd(localComState,cmdString,&cmdLength);
+ − 136 UART_SendCmdString(cmdString);
957
+ − 137 if(localComState == UART_O2_CHECK)
+ − 138 {
+ − 139 localComState = UART_O2_IDLE; /* confirmation seems to be send after blinking => the response could be longer as the channel switch time => ignore */
+ − 140 }
795
+ − 141 }
+ − 142 externalInterface_SetSensorState(activeSensor + EXT_INTERFACE_MUX_OFFSET,localComState);
+ − 143 }
+ − 144
+ − 145 void uartO2_ProcessData(uint8_t data)
+ − 146 {
+ − 147 static uint8_t cmdReadIndex = 0;
+ − 148 static uint8_t errorReadIndex = 0;
+ − 149 static char tmpRxBuf[30];
+ − 150 static uint8_t tmpRxIdx = 0;
+ − 151
+ − 152 uint32_t tmpO2 = 0;
+ − 153 uint32_t tmpData = 0;
+ − 154
+ − 155 uint32_t tick = HAL_GetTick();
+ − 156
+ − 157 uartO2Status_t localComState = externalInterface_GetSensorState(activeSensor + EXT_INTERFACE_MUX_OFFSET);
+ − 158
+ − 159 lastReceiveTick = tick;
+ − 160 switch(rxState)
+ − 161 {
+ − 162 case O2RX_CONFIRM: if(data == '#')
+ − 163 {
+ − 164 cmdReadIndex = 0;
+ − 165 errorReadIndex = 0;
+ − 166 }
+ − 167 if(errorReadIndex < sizeof(errorStr)-1)
+ − 168 {
+ − 169 if(data == errorStr[errorReadIndex])
+ − 170 {
+ − 171 errorReadIndex++;
+ − 172 }
+ − 173 else
+ − 174 {
+ − 175 errorReadIndex = 0;
+ − 176 }
+ − 177 }
+ − 178 else
+ − 179 {
+ − 180 respondErrorDetected = 1;
+ − 181 errorReadIndex = 0;
+ − 182 if(localComState != UART_O2_IDLE)
+ − 183 {
+ − 184 localComState = UART_O2_ERROR;
+ − 185 }
+ − 186 }
+ − 187 if(data == cmdString[cmdReadIndex])
+ − 188 {
+ − 189 cmdReadIndex++;
+ − 190 if(cmdReadIndex == cmdLength - 3)
+ − 191 {
+ − 192 errorReadIndex = 0;
+ − 193 if((activeSensor == MAX_MUX_CHANNEL))
+ − 194 {
+ − 195 if(respondErrorDetected)
+ − 196 {
+ − 197 digO2Connected = 0; /* the multiplexer mirrors the incoming message and does not generate an error information => no mux connected */
+ − 198 }
+ − 199 else
+ − 200 {
+ − 201 digO2Connected = 1;
+ − 202 }
+ − 203 }
+ − 204 else /* handle sensors which should respond with an error message after channel switch */
+ − 205 {
+ − 206 digO2Connected = 1;
+ − 207 }
+ − 208 tmpRxIdx = 0;
+ − 209 memset((char*) tmpRxBuf, 0, sizeof(tmpRxBuf));
+ − 210 cmdReadIndex = 0;
+ − 211 switch (localComState)
+ − 212 {
+ − 213 case UART_O2_CHECK: localComState = UART_O2_IDLE;
+ − 214 rxState = O2RX_IDLE;
+ − 215 break;
+ − 216 case UART_O2_REQ_ID: rxState = O2RX_GETNR;
+ − 217 break;
+ − 218 case UART_O2_REQ_INFO: rxState = O2RX_GETTYPE;
+ − 219 break;
+ − 220 case UART_O2_REQ_RAW:
+ − 221 case UART_O2_REQ_O2: rxState = O2RX_GETO2;
+ − 222 break;
+ − 223 default: localComState = UART_O2_IDLE;
+ − 224 rxState = O2RX_IDLE;
+ − 225 break;
+ − 226 }
+ − 227 }
+ − 228 }
+ − 229 else
+ − 230 {
+ − 231 cmdReadIndex = 0;
+ − 232 }
+ − 233 break;
+ − 234
+ − 235 case O2RX_GETSTATUS:
+ − 236 case O2RX_GETTEMP:
+ − 237 case O2RX_GETTYPE:
+ − 238 case O2RX_GETVERSION:
+ − 239 case O2RX_GETCHANNEL:
+ − 240 case O2RX_GETSUBSENSORS:
+ − 241 case O2RX_GETO2:
+ − 242 case O2RX_GETNR:
+ − 243 case O2RX_GETDPHI:
+ − 244 case O2RX_INTENSITY:
+ − 245 case O2RX_AMBIENTLIGHT:
+ − 246 case O2RX_PRESSURE:
+ − 247 case O2RX_HUMIDITY:
+ − 248 if(data != 0x0D)
+ − 249 {
+ − 250 if(data != ' ') /* the following data entities are placed within the data stream => no need to store data at the end */
+ − 251 {
+ − 252 tmpRxBuf[tmpRxIdx++] = data;
+ − 253 }
+ − 254 else
+ − 255 {
+ − 256 if(tmpRxIdx != 0)
+ − 257 {
+ − 258 switch(rxState)
+ − 259 {
+ − 260 case O2RX_GETCHANNEL: StringToInt(tmpRxBuf,&tmpData);
+ − 261 rxState = O2RX_GETVERSION;
+ − 262 break;
+ − 263 case O2RX_GETVERSION: StringToInt(tmpRxBuf,&tmpData);
+ − 264 rxState = O2RX_GETSUBSENSORS;
+ − 265 break;
+ − 266 case O2RX_GETTYPE: StringToInt(tmpRxBuf,&tmpData);
+ − 267 rxState = O2RX_GETCHANNEL;
+ − 268 break;
+ − 269
+ − 270 case O2RX_GETO2: StringToInt(tmpRxBuf,&tmpO2);
+ − 271
+ − 272 setExternalInterfaceChannel(activeSensor + EXT_INTERFACE_MUX_OFFSET,(float)(tmpO2 / 10000.0));
+ − 273 rxState = O2RX_GETTEMP;
+ − 274 break;
+ − 275 case O2RX_GETTEMP: StringToInt(tmpRxBuf,(uint32_t*)&tmpSensorDataDiveO2.temperature);
+ − 276 rxState = O2RX_GETSTATUS;
+ − 277 break;
+ − 278 case O2RX_GETSTATUS: StringToInt(tmpRxBuf,&tmpSensorDataDiveO2.status); /* raw data cycle */
+ − 279 rxState = O2RX_GETDPHI;
+ − 280 break;
+ − 281 case O2RX_GETDPHI: /* ignored to save memory and most likly irrelevant for diver */
+ − 282 rxState = O2RX_INTENSITY;
+ − 283 break;
+ − 284 case O2RX_INTENSITY: StringToInt(tmpRxBuf,(uint32_t*)&tmpSensorDataDiveO2.intensity); /* raw data cycle */
+ − 285 rxState = O2RX_AMBIENTLIGHT;
+ − 286 break;
+ − 287 case O2RX_AMBIENTLIGHT: StringToInt(tmpRxBuf,(uint32_t*)&tmpSensorDataDiveO2.ambient); /* raw data cycle */
+ − 288 rxState = O2RX_PRESSURE;
+ − 289 break;
+ − 290 case O2RX_PRESSURE: StringToInt(tmpRxBuf,(uint32_t*)&tmpSensorDataDiveO2.pressure); /* raw data cycle */
+ − 291 rxState = O2RX_HUMIDITY;
+ − 292 break;
+ − 293 default:
+ − 294 break;
+ − 295 }
+ − 296 memset((char*) tmpRxBuf, 0, tmpRxIdx);
+ − 297 tmpRxIdx = 0;
+ − 298 }
+ − 299 }
+ − 300 }
+ − 301 else
+ − 302 { /* the following data items are the last of a sensor respond => store temporal data */
+ − 303 switch (rxState)
+ − 304 {
+ − 305 case O2RX_GETSTATUS: StringToInt(tmpRxBuf,&tmpSensorDataDiveO2.status);
+ − 306 externalInterface_SetSensorData(activeSensor + EXT_INTERFACE_MUX_OFFSET,(uint8_t*)&tmpSensorDataDiveO2);
+ − 307 localComState = UART_O2_IDLE;
+ − 308 rxState = O2RX_IDLE;
+ − 309 break;
+ − 310 case O2RX_GETSUBSENSORS: StringToInt(tmpRxBuf,&tmpData);
+ − 311 localComState = UART_O2_IDLE;
+ − 312 rxState = O2RX_IDLE;
+ − 313 break;
+ − 314 case O2RX_HUMIDITY: StringToInt(tmpRxBuf,(uint32_t*)&tmpSensorDataDiveO2.humidity); /* raw data cycle */
+ − 315 externalInterface_SetSensorData(activeSensor + EXT_INTERFACE_MUX_OFFSET,(uint8_t*)&tmpSensorDataDiveO2);
+ − 316 localComState = UART_O2_IDLE;
+ − 317 rxState = O2RX_IDLE;
+ − 318 break;
+ − 319 case O2RX_GETNR: StringToUInt64((char*)tmpRxBuf,&tmpSensorDataDiveO2.sensorId);
+ − 320 externalInterface_SetSensorData(activeSensor + EXT_INTERFACE_MUX_OFFSET,(uint8_t*)&tmpSensorDataDiveO2);
+ − 321 localComState = UART_O2_IDLE;
+ − 322 rxState = O2RX_IDLE;
+ − 323 break;
+ − 324 default: localComState = UART_O2_IDLE;
+ − 325 rxState = O2RX_IDLE;
+ − 326 break;
+ − 327 }
+ − 328 }
+ − 329 break;
+ − 330 default: rxState = O2RX_IDLE;
+ − 331 break;
+ − 332
+ − 333 }
+ − 334 externalInterface_SetSensorState(activeSensor + EXT_INTERFACE_MUX_OFFSET,localComState);
+ − 335 }
+ − 336
+ − 337
+ − 338 uint8_t uartO2_isSensorConnected()
+ − 339 {
+ − 340 return digO2Connected;
+ − 341 }
+ − 342
+ − 343 void uartO2_SetChannel(uint8_t channel)
+ − 344 {
+ − 345 if(channel <= MAX_MUX_CHANNEL)
+ − 346 {
+ − 347 activeSensor = channel;
+ − 348 }
+ − 349 }
+ − 350