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
976
+ − 78 uint8_t *pmap = externalInterface_GetSensorMapPointer(0);
795
+ − 79 uint8_t activeSensor = externalInterface_GetActiveUartSensor();
+ − 80
+ − 81 uartO2Status_t localComState = externalInterface_GetSensorState(activeSensor + EXT_INTERFACE_MUX_OFFSET);
+ − 82 externalInterface_GetSensorData(activeSensor + EXT_INTERFACE_MUX_OFFSET, (uint8_t*)&tmpSensorDataDiveO2);
+ − 83
+ − 84
+ − 85 if(lastActiveSensor != activeSensor)
+ − 86 {
+ − 87 lastActiveSensor = activeSensor;
+ − 88 if(localComState != UART_O2_ERROR)
+ − 89 {
+ − 90 lastComState = localComState;
+ − 91 }
+ − 92 else
+ − 93 {
+ − 94 lastComState = UART_O2_IDLE;
+ − 95 }
+ − 96 if(localComState == UART_O2_CHECK)
+ − 97 {
+ − 98 localComState = UART_O2_IDLE;
+ − 99 }
976
+ − 100 UART_ReadData(SENSOR_DIGO2, 1); /* flush buffer */
795
+ − 101 }
+ − 102
800
+ − 103 if(localComState == UART_O2_INIT)
795
+ − 104 {
+ − 105 memset((char*) &tmpSensorDataDiveO2, 0, sizeof(tmpSensorDataDiveO2));
+ − 106 externalInterface_SetSensorData(0xFF,(uint8_t*)&tmpSensorDataDiveO2);
+ − 107
+ − 108 localComState = UART_O2_CHECK;
+ − 109 lastComState = UART_O2_CHECK;
976
+ − 110 UART_ReadData(SENSOR_DIGO2, 1); /* flush buffer */
795
+ − 111 uartO2_SetupCmd(localComState,cmdString,&cmdLength);
916
+ − 112 UART_SendCmdString(cmdString);
976
+ − 113 if(pmap[EXT_INTERFACE_SENSOR_CNT-1] != SENSOR_MUX) /* stand alone mode => add some time for sensor com setup */
+ − 114 {
+ − 115 HAL_Delay(80);
+ − 116 }
795
+ − 117 rxState = O2RX_CONFIRM;
+ − 118 respondErrorDetected = 0;
+ − 119 digO2Connected = 0;
+ − 120 }
+ − 121 else
+ − 122 {
+ − 123 if(localComState == UART_O2_ERROR)
+ − 124 {
+ − 125 localComState = lastComState;
+ − 126 }
+ − 127 lastComState = localComState;
+ − 128 if(localComState == UART_O2_IDLE) /* cyclic request of o2 value */
+ − 129 {
+ − 130 if((activeSensor != MAX_MUX_CHANNEL) && (tmpSensorDataDiveO2.sensorId == 0))
+ − 131 {
+ − 132 localComState = UART_O2_REQ_ID;
+ − 133 }
+ − 134 else
+ − 135 {
+ − 136 localComState = UART_O2_REQ_RAW;
+ − 137 }
+ − 138 }
+ − 139 rxState = O2RX_CONFIRM;
+ − 140 uartO2_SetupCmd(localComState,cmdString,&cmdLength);
+ − 141 UART_SendCmdString(cmdString);
957
+ − 142 if(localComState == UART_O2_CHECK)
+ − 143 {
+ − 144 localComState = UART_O2_IDLE; /* confirmation seems to be send after blinking => the response could be longer as the channel switch time => ignore */
+ − 145 }
795
+ − 146 }
+ − 147 externalInterface_SetSensorState(activeSensor + EXT_INTERFACE_MUX_OFFSET,localComState);
+ − 148 }
+ − 149
+ − 150 void uartO2_ProcessData(uint8_t data)
+ − 151 {
+ − 152 static uint8_t cmdReadIndex = 0;
+ − 153 static uint8_t errorReadIndex = 0;
+ − 154 static char tmpRxBuf[30];
+ − 155 static uint8_t tmpRxIdx = 0;
+ − 156
+ − 157 uint32_t tmpO2 = 0;
+ − 158 uint32_t tmpData = 0;
+ − 159
+ − 160 uint32_t tick = HAL_GetTick();
+ − 161
+ − 162 uartO2Status_t localComState = externalInterface_GetSensorState(activeSensor + EXT_INTERFACE_MUX_OFFSET);
+ − 163
+ − 164 lastReceiveTick = tick;
+ − 165 switch(rxState)
+ − 166 {
+ − 167 case O2RX_CONFIRM: if(data == '#')
+ − 168 {
+ − 169 cmdReadIndex = 0;
+ − 170 errorReadIndex = 0;
+ − 171 }
+ − 172 if(errorReadIndex < sizeof(errorStr)-1)
+ − 173 {
+ − 174 if(data == errorStr[errorReadIndex])
+ − 175 {
+ − 176 errorReadIndex++;
+ − 177 }
+ − 178 else
+ − 179 {
+ − 180 errorReadIndex = 0;
+ − 181 }
+ − 182 }
+ − 183 else
+ − 184 {
+ − 185 respondErrorDetected = 1;
+ − 186 errorReadIndex = 0;
+ − 187 if(localComState != UART_O2_IDLE)
+ − 188 {
+ − 189 localComState = UART_O2_ERROR;
+ − 190 }
+ − 191 }
+ − 192 if(data == cmdString[cmdReadIndex])
+ − 193 {
+ − 194 cmdReadIndex++;
+ − 195 if(cmdReadIndex == cmdLength - 3)
+ − 196 {
+ − 197 errorReadIndex = 0;
+ − 198 if((activeSensor == MAX_MUX_CHANNEL))
+ − 199 {
+ − 200 if(respondErrorDetected)
+ − 201 {
+ − 202 digO2Connected = 0; /* the multiplexer mirrors the incoming message and does not generate an error information => no mux connected */
+ − 203 }
+ − 204 else
+ − 205 {
+ − 206 digO2Connected = 1;
+ − 207 }
+ − 208 }
+ − 209 else /* handle sensors which should respond with an error message after channel switch */
+ − 210 {
+ − 211 digO2Connected = 1;
+ − 212 }
+ − 213 tmpRxIdx = 0;
+ − 214 memset((char*) tmpRxBuf, 0, sizeof(tmpRxBuf));
+ − 215 cmdReadIndex = 0;
+ − 216 switch (localComState)
+ − 217 {
+ − 218 case UART_O2_CHECK: localComState = UART_O2_IDLE;
+ − 219 rxState = O2RX_IDLE;
+ − 220 break;
+ − 221 case UART_O2_REQ_ID: rxState = O2RX_GETNR;
+ − 222 break;
+ − 223 case UART_O2_REQ_INFO: rxState = O2RX_GETTYPE;
+ − 224 break;
+ − 225 case UART_O2_REQ_RAW:
+ − 226 case UART_O2_REQ_O2: rxState = O2RX_GETO2;
+ − 227 break;
+ − 228 default: localComState = UART_O2_IDLE;
+ − 229 rxState = O2RX_IDLE;
+ − 230 break;
+ − 231 }
+ − 232 }
+ − 233 }
+ − 234 else
+ − 235 {
+ − 236 cmdReadIndex = 0;
+ − 237 }
+ − 238 break;
+ − 239
+ − 240 case O2RX_GETSTATUS:
+ − 241 case O2RX_GETTEMP:
+ − 242 case O2RX_GETTYPE:
+ − 243 case O2RX_GETVERSION:
+ − 244 case O2RX_GETCHANNEL:
+ − 245 case O2RX_GETSUBSENSORS:
+ − 246 case O2RX_GETO2:
+ − 247 case O2RX_GETNR:
+ − 248 case O2RX_GETDPHI:
+ − 249 case O2RX_INTENSITY:
+ − 250 case O2RX_AMBIENTLIGHT:
+ − 251 case O2RX_PRESSURE:
+ − 252 case O2RX_HUMIDITY:
+ − 253 if(data != 0x0D)
+ − 254 {
+ − 255 if(data != ' ') /* the following data entities are placed within the data stream => no need to store data at the end */
+ − 256 {
+ − 257 tmpRxBuf[tmpRxIdx++] = data;
+ − 258 }
+ − 259 else
+ − 260 {
+ − 261 if(tmpRxIdx != 0)
+ − 262 {
+ − 263 switch(rxState)
+ − 264 {
+ − 265 case O2RX_GETCHANNEL: StringToInt(tmpRxBuf,&tmpData);
+ − 266 rxState = O2RX_GETVERSION;
+ − 267 break;
+ − 268 case O2RX_GETVERSION: StringToInt(tmpRxBuf,&tmpData);
+ − 269 rxState = O2RX_GETSUBSENSORS;
+ − 270 break;
+ − 271 case O2RX_GETTYPE: StringToInt(tmpRxBuf,&tmpData);
+ − 272 rxState = O2RX_GETCHANNEL;
+ − 273 break;
+ − 274
+ − 275 case O2RX_GETO2: StringToInt(tmpRxBuf,&tmpO2);
+ − 276
+ − 277 setExternalInterfaceChannel(activeSensor + EXT_INTERFACE_MUX_OFFSET,(float)(tmpO2 / 10000.0));
+ − 278 rxState = O2RX_GETTEMP;
+ − 279 break;
+ − 280 case O2RX_GETTEMP: StringToInt(tmpRxBuf,(uint32_t*)&tmpSensorDataDiveO2.temperature);
+ − 281 rxState = O2RX_GETSTATUS;
+ − 282 break;
+ − 283 case O2RX_GETSTATUS: StringToInt(tmpRxBuf,&tmpSensorDataDiveO2.status); /* raw data cycle */
+ − 284 rxState = O2RX_GETDPHI;
+ − 285 break;
+ − 286 case O2RX_GETDPHI: /* ignored to save memory and most likly irrelevant for diver */
+ − 287 rxState = O2RX_INTENSITY;
+ − 288 break;
+ − 289 case O2RX_INTENSITY: StringToInt(tmpRxBuf,(uint32_t*)&tmpSensorDataDiveO2.intensity); /* raw data cycle */
+ − 290 rxState = O2RX_AMBIENTLIGHT;
+ − 291 break;
+ − 292 case O2RX_AMBIENTLIGHT: StringToInt(tmpRxBuf,(uint32_t*)&tmpSensorDataDiveO2.ambient); /* raw data cycle */
+ − 293 rxState = O2RX_PRESSURE;
+ − 294 break;
+ − 295 case O2RX_PRESSURE: StringToInt(tmpRxBuf,(uint32_t*)&tmpSensorDataDiveO2.pressure); /* raw data cycle */
+ − 296 rxState = O2RX_HUMIDITY;
+ − 297 break;
+ − 298 default:
+ − 299 break;
+ − 300 }
+ − 301 memset((char*) tmpRxBuf, 0, tmpRxIdx);
+ − 302 tmpRxIdx = 0;
+ − 303 }
+ − 304 }
+ − 305 }
+ − 306 else
+ − 307 { /* the following data items are the last of a sensor respond => store temporal data */
+ − 308 switch (rxState)
+ − 309 {
+ − 310 case O2RX_GETSTATUS: StringToInt(tmpRxBuf,&tmpSensorDataDiveO2.status);
+ − 311 externalInterface_SetSensorData(activeSensor + EXT_INTERFACE_MUX_OFFSET,(uint8_t*)&tmpSensorDataDiveO2);
+ − 312 localComState = UART_O2_IDLE;
+ − 313 rxState = O2RX_IDLE;
+ − 314 break;
+ − 315 case O2RX_GETSUBSENSORS: StringToInt(tmpRxBuf,&tmpData);
+ − 316 localComState = UART_O2_IDLE;
+ − 317 rxState = O2RX_IDLE;
+ − 318 break;
+ − 319 case O2RX_HUMIDITY: StringToInt(tmpRxBuf,(uint32_t*)&tmpSensorDataDiveO2.humidity); /* raw data cycle */
+ − 320 externalInterface_SetSensorData(activeSensor + EXT_INTERFACE_MUX_OFFSET,(uint8_t*)&tmpSensorDataDiveO2);
+ − 321 localComState = UART_O2_IDLE;
+ − 322 rxState = O2RX_IDLE;
+ − 323 break;
+ − 324 case O2RX_GETNR: StringToUInt64((char*)tmpRxBuf,&tmpSensorDataDiveO2.sensorId);
+ − 325 externalInterface_SetSensorData(activeSensor + EXT_INTERFACE_MUX_OFFSET,(uint8_t*)&tmpSensorDataDiveO2);
+ − 326 localComState = UART_O2_IDLE;
+ − 327 rxState = O2RX_IDLE;
+ − 328 break;
+ − 329 default: localComState = UART_O2_IDLE;
+ − 330 rxState = O2RX_IDLE;
+ − 331 break;
+ − 332 }
+ − 333 }
+ − 334 break;
+ − 335 default: rxState = O2RX_IDLE;
+ − 336 break;
+ − 337
+ − 338 }
+ − 339 externalInterface_SetSensorState(activeSensor + EXT_INTERFACE_MUX_OFFSET,localComState);
+ − 340 }
+ − 341
+ − 342
+ − 343 uint8_t uartO2_isSensorConnected()
+ − 344 {
+ − 345 return digO2Connected;
+ − 346 }
+ − 347
+ − 348 void uartO2_SetChannel(uint8_t channel)
+ − 349 {
+ − 350 if(channel <= MAX_MUX_CHANNEL)
+ − 351 {
+ − 352 activeSensor = channel;
+ − 353 }
+ − 354 }
+ − 355