comparison Small_CPU/Src/externalInterface.c @ 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 19ab6f3ed52a
children e9eba334b942
comparison
equal deleted inserted replaced
793:9da81033ad44 794:bb37d4f3e50e
23 */ 23 */
24 /* Includes ------------------------------------------------------------------*/ 24 /* Includes ------------------------------------------------------------------*/
25 25
26 #include <math.h> 26 #include <math.h>
27 #include <string.h> 27 #include <string.h>
28 #include "data_central.h"
28 #include "i2c.h" 29 #include "i2c.h"
29 #include "externalInterface.h" 30 #include "externalInterface.h"
30 #include "scheduler.h" 31 #include "scheduler.h"
31 #include "uart.h" 32 #include "uart.h"
32 #include "data_exchange.h" 33 #include "data_exchange.h"
33 #include "pressure.h" 34 #include "pressure.h"
35 #include "uartProtocol_O2.h"
34 36
35 extern SGlobal global; 37 extern SGlobal global;
36 extern UART_HandleTypeDef huart1; 38 extern UART_HandleTypeDef huart1;
37 39
38 #define ADC_ANSWER_LENGTH (5u) /* 3424 will provide addr + 4 data bytes */ 40 #define ADC_ANSWER_LENGTH (5u) /* 3424 will provide addr + 4 data bytes */
52 #define ANSWER_CONFBYTE_INDEX (4u) 54 #define ANSWER_CONFBYTE_INDEX (4u)
53 55
54 #define LOOKUP_CO2_CORR_TABLE_SCALE (1000u) 56 #define LOOKUP_CO2_CORR_TABLE_SCALE (1000u)
55 #define LOOKUP_CO2_CORR_TABLE_MAX (30000u) 57 #define LOOKUP_CO2_CORR_TABLE_MAX (30000u)
56 58
59 #define REQUEST_INT_SENSOR_MS (1500) /* Minimum time interval for cyclic sensor data requests per sensor (UART mux) */
60 #define COMMAND_TX_DELAY (30u) /* The time the sensor needs to recover from a invalid command request */
61 #define TIMEOUT_SENSOR_ANSWER (300) /* Time till a request is repeated if no answer was received */
62
63 #define activeSensorId (activeUartChannel + EXT_INTERFACE_MUX_OFFSET) /* Used if UART channels are applied to Sensor map */
64
57 static uint8_t activeChannel = 0; /* channel which is in request */ 65 static uint8_t activeChannel = 0; /* channel which is in request */
58 static uint8_t recBuf[ADC_ANSWER_LENGTH]; 66 static uint8_t recBuf[ADC_ANSWER_LENGTH];
59 static uint8_t timeoutCnt = 0; 67 static uint8_t timeoutCnt = 0;
60 static uint8_t externalInterfacePresent = 0; 68 static uint8_t externalInterfacePresent = 0;
61 69
63 static uint8_t externalV33_On = 0; 71 static uint8_t externalV33_On = 0;
64 static uint8_t externalADC_On = 0; 72 static uint8_t externalADC_On = 0;
65 static uint8_t externalUART_Protocol = 0; 73 static uint8_t externalUART_Protocol = 0;
66 static uint16_t externalCO2Value; 74 static uint16_t externalCO2Value;
67 static uint16_t externalCO2SignalStrength; 75 static uint16_t externalCO2SignalStrength;
68 static uint16_t externalCO2Status = 0; 76 static uint16_t externalCO2Status = 0;
77 static float externalCO2Scale = 0.0;
69 78
70 static uint8_t lastSensorDataId = 0; 79 static uint8_t lastSensorDataId = 0;
71 static SSensorDataDiveO2 sensorDataDiveO2[MAX_ADC_CHANNEL]; 80 static SSensorDataDiveO2 sensorDataDiveO2[EXT_INTERFACE_SENSOR_CNT];
72 static externalInterfaceAutoDetect_t externalAutoDetect = DETECTION_OFF; 81 static externalInterfaceAutoDetect_t externalAutoDetect = DETECTION_OFF;
73 static externalInterfaceSensorType SensorMap[EXT_INTERFACE_SENSOR_CNT] ={ SENSOR_OPTIC, SENSOR_OPTIC, SENSOR_OPTIC, SENSOR_NONE, SENSOR_NONE}; 82 static externalInterfaceSensorType SensorMap[EXT_INTERFACE_SENSOR_CNT] ={ SENSOR_OPTIC, SENSOR_OPTIC, SENSOR_OPTIC, SENSOR_NONE, SENSOR_NONE};
74 static externalInterfaceSensorType tmpSensorMap[EXT_INTERFACE_SENSOR_CNT]; 83 static externalInterfaceSensorType tmpSensorMap[EXT_INTERFACE_SENSOR_CNT];
75 static externalInterfaceSensorType MasterSensorMap[EXT_INTERFACE_SENSOR_CNT]; 84 static externalInterfaceSensorType MasterSensorMap[EXT_INTERFACE_SENSOR_CNT];
85 static externalInterfaceSensorType foundSensorMap[EXT_INTERFACE_SENSOR_CNT];
86 static uint8_t Mux2ADCMap[MAX_ADC_CHANNEL];
87 static uint8_t externalInterface_SensorState[EXT_INTERFACE_SENSOR_CNT];
76 88
77 static float LookupCO2PressureCorrection[LOOKUP_CO2_CORR_TABLE_MAX / LOOKUP_CO2_CORR_TABLE_SCALE]; /* lookup table for pressure compensation values */ 89 static float LookupCO2PressureCorrection[LOOKUP_CO2_CORR_TABLE_MAX / LOOKUP_CO2_CORR_TABLE_SCALE]; /* lookup table for pressure compensation values */
78 90
91 static uint16_t externalInterfaceMuxReqIntervall = 0; /* delay between switching from one MUX channel to the next */
92 static uint8_t activeUartChannel = 0; /* Index of the sensor port which is selected by the mux or 0 if no mux is connected */
79 93
80 void externalInterface_Init(void) 94 void externalInterface_Init(void)
81 { 95 {
82 uint16_t index; 96 uint16_t index;
83 uint16_t coeff; 97 uint16_t coeff;
88 { 102 {
89 externalInterfacePresent = 1; 103 externalInterfacePresent = 1;
90 global.deviceDataSendToMaster.hw_Info.extADC = 1; 104 global.deviceDataSendToMaster.hw_Info.extADC = 1;
91 } 105 }
92 global.deviceDataSendToMaster.hw_Info.checkADC = 1; 106 global.deviceDataSendToMaster.hw_Info.checkADC = 1;
107
108 memset(Mux2ADCMap,0xFF, sizeof(Mux2ADCMap));
93 109
94 /* Create a lookup table based on GSS application note AN001: PRESSURE COMPENSATION OF A CO2 SENSOR */ 110 /* Create a lookup table based on GSS application note AN001: PRESSURE COMPENSATION OF A CO2 SENSOR */
95 /* The main purpose of the sensor in the dive application is to be a warning indicator */ 111 /* The main purpose of the sensor in the dive application is to be a warning indicator */
96 /* => no exact values necessary => a lookup table with 1000ppm scaling should be sufficient */ 112 /* => no exact values necessary => a lookup table with 1000ppm scaling should be sufficient */
97 LookupCO2PressureCorrection [0] = -0.0014; 113 LookupCO2PressureCorrection [0] = -0.0014;
115 131
116 for(index = 0; index < MAX_ADC_CHANNEL; index++) 132 for(index = 0; index < MAX_ADC_CHANNEL; index++)
117 { 133 {
118 externalChannel_mV[index] = 0.0; 134 externalChannel_mV[index] = 0.0;
119 } 135 }
136 memset(externalInterface_SensorState,UART_O2_INIT,sizeof(externalInterface_SensorState));
120 } 137 }
121 138
122 139
123 uint8_t externalInterface_StartConversion(uint8_t channel) 140 uint8_t externalInterface_StartConversion(uint8_t channel)
124 { 141 {
238 } 255 }
239 256
240 uint8_t setExternalInterfaceChannel(uint8_t channel, float value) 257 uint8_t setExternalInterfaceChannel(uint8_t channel, float value)
241 { 258 {
242 uint8_t retval = 0; 259 uint8_t retval = 0;
243 260 uint8_t localId = channel;
244 if(channel < MAX_ADC_CHANNEL) 261 uint8_t index = 0;
245 { 262
246 externalChannel_mV[channel] = value; 263 if(localId >= MAX_ADC_CHANNEL) /* at the moment sensor visualization is focused on the three ADC channels => map Mux sensors */
264 {
265 for(index = 0; index < MAX_ADC_CHANNEL; index++)
266 {
267 if(Mux2ADCMap[index] == localId)
268 {
269 localId = index;
270 break;
271 }
272 }
273 }
274
275 if(localId < MAX_ADC_CHANNEL)
276 {
277 externalChannel_mV[localId] = value;
247 retval = 1; 278 retval = 1;
248 } 279 }
249 return retval; 280 return retval;
250 } 281 }
251 282
357 default: 388 default:
358 break; 389 break;
359 } 390 }
360 } 391 }
361 392
393 uint8_t externalInterface_GetActiveUartSensor()
394 {
395 return activeUartChannel;
396 }
397
398 void externalInterface_SetSensorState(uint8_t sensorIdx, uint8_t state)
399 {
400 if(sensorIdx < EXT_INTERFACE_SENSOR_CNT)
401 {
402 externalInterface_SensorState[sensorIdx] = state;
403 }
404 }
405
406 uint8_t externalInterface_GetSensorState(uint8_t sensorIdx)
407 {
408 uint8_t ret = COMMON_SENSOR_STATE_INVALID;
409 if(sensorIdx < EXT_INTERFACE_SENSOR_CNT)
410 {
411 ret = externalInterface_SensorState[sensorIdx];
412 }
413 return ret;
414 }
415
416 /* The supported sensors from GSS have different scaling factors depending on their accuracy. The factor may be read out of the sensor */
417 void externalInterface_SetCO2Scale(float CO2Scale)
418 {
419 if((CO2Scale == 10) || (CO2Scale == 100))
420 {
421 externalCO2Scale = CO2Scale;
422 }
423 }
424 float externalInterface_GetCO2Scale()
425 {
426 return externalCO2Scale;
427 }
428
362 void externalInterface_SetCO2Value(uint16_t CO2_ppm) 429 void externalInterface_SetCO2Value(uint16_t CO2_ppm)
363 { 430 {
364 float local_ppm = CO2_ppm * 10.0; /* scalfactor */ 431 float local_ppm = CO2_ppm * externalCO2Scale;
365 432
366 #ifndef ENABLE_EXTERNAL_PRESSURE 433 #ifndef ENABLE_EXTERNAL_PRESSURE
367 float local_corr = 0.0; 434 float local_corr = 0.0;
368 435
369 if (local_ppm >= LOOKUP_CO2_CORR_TABLE_MAX) 436 if (local_ppm >= LOOKUP_CO2_CORR_TABLE_MAX)
377 local_ppm = local_ppm / (1.0 + (local_corr * (get_surface_mbar() - get_pressure_mbar()))); 444 local_ppm = local_ppm / (1.0 + (local_corr * (get_surface_mbar() - get_pressure_mbar())));
378 #else 445 #else
379 /* The external pressure value is passed via ADC channel2 and calibration is done at firmware => just forward sensor data */ 446 /* The external pressure value is passed via ADC channel2 and calibration is done at firmware => just forward sensor data */
380 /* 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 */ 447 /* 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 */
381 #endif 448 #endif
382 externalCO2Value = local_ppm / 10.0; 449 externalCO2Value = local_ppm / externalCO2Scale;
383 } 450 }
384 451
385 void externalInterface_SetCO2SignalStrength(uint16_t LED_qa) 452 void externalInterface_SetCO2SignalStrength(uint16_t LED_qa)
386 { 453 {
387 externalCO2SignalStrength = LED_qa; 454 externalCO2SignalStrength = LED_qa;
409 } 476 }
410 477
411 478
412 uint8_t externalInterface_GetSensorData(uint8_t sensorId, uint8_t* pDataStruct) 479 uint8_t externalInterface_GetSensorData(uint8_t sensorId, uint8_t* pDataStruct)
413 { 480 {
481 uint8_t index = 0;
414 uint8_t localId = sensorId; 482 uint8_t localId = sensorId;
415 if(localId == 0xFF) 483 if(localId == 0xFF)
416 { 484 {
417 localId = lastSensorDataId; 485 localId = lastSensorDataId;
418 } 486 }
419 487
420 if((pDataStruct != NULL) && (localId <= MAX_ADC_CHANNEL)) 488 if((pDataStruct != NULL) && (localId <= EXT_INTERFACE_SENSOR_CNT))
421 { 489 {
422 memcpy(pDataStruct, &sensorDataDiveO2[localId], sizeof(SSensorDataDiveO2)); 490 memcpy(pDataStruct, &sensorDataDiveO2[localId], sizeof(SSensorDataDiveO2));
423 } 491 }
424 else 492 else
425 { 493 {
426 localId = 0xFF; 494 localId = 0xFF;
427 } 495 }
496 if(localId > MAX_ADC_CHANNEL) /* at the moment sensor visualization is focused on the three ADC channels => map Mux sensors */
497 {
498 for(index = 0; index < MAX_ADC_CHANNEL; index++)
499 {
500 if(Mux2ADCMap[index] == localId)
501 {
502 localId = index;
503 }
504 }
505 }
506
428 return localId; 507 return localId;
429 } 508 }
430 509
431 void externalInterface_SetSensorData(uint8_t sensorId, uint8_t* pDataStruct) 510 void externalInterface_SetSensorData(uint8_t sensorId, uint8_t* pDataStruct)
432 { 511 {
512 uint8_t index = 0;
513
433 if(pDataStruct != NULL) 514 if(pDataStruct != NULL)
434 { 515 {
435 if((sensorId != 0xFF) && (sensorId < MAX_ADC_CHANNEL)) 516 if((sensorId != 0xFF) && (sensorId < EXT_INTERFACE_SENSOR_CNT))
436 { 517 {
437 memcpy(&sensorDataDiveO2[sensorId], pDataStruct, sizeof(SSensorDataDiveO2)); 518 memcpy(&sensorDataDiveO2[sensorId], pDataStruct, sizeof(SSensorDataDiveO2));
438 lastSensorDataId = sensorId; 519 lastSensorDataId = sensorId;
520 for(index = 0; index < MAX_MUX_CHANNEL; index++)
521 {
522 if(Mux2ADCMap[index] == sensorId)
523 {
524 memcpy(&sensorDataDiveO2[index], pDataStruct, sizeof(SSensorDataDiveO2));
525 lastSensorDataId = index;
526 break;
527 }
528 }
439 } 529 }
440 else 530 else
441 { 531 {
442 memset(&sensorDataDiveO2,0,sizeof(sensorDataDiveO2)); 532 memset(&sensorDataDiveO2,0,sizeof(sensorDataDiveO2));
443 lastSensorDataId = 0xFF; 533 lastSensorDataId = 0xFF;
447 537
448 void externalInface_SetSensorMap(uint8_t* pMap) 538 void externalInface_SetSensorMap(uint8_t* pMap)
449 { 539 {
450 if(pMap != NULL) 540 if(pMap != NULL)
451 { 541 {
452 memcpy(MasterSensorMap, pMap, 5); /* the map is not directly copied. Copy is done via cmd request */ 542 memcpy(MasterSensorMap, pMap, EXT_INTERFACE_SENSOR_CNT); /* the map is not directly copied. Copy is done via cmd request */
453 } 543 }
454 544
455 } 545 }
456 uint8_t* externalInterface_GetSensorMapPointer(uint8_t finalMap) 546 uint8_t* externalInterface_GetSensorMapPointer(uint8_t finalMap)
457 { 547 {
468 return pret; 558 return pret;
469 } 559 }
470 560
471 void externalInterface_AutodetectSensor() 561 void externalInterface_AutodetectSensor()
472 { 562 {
473 static uint8_t tmpMuxMapping[MAX_MUX_CHANNEL];
474 static uint8_t sensorIndex = 0; 563 static uint8_t sensorIndex = 0;
475 static uint8_t uartMuxChannel = 0; 564 static uint8_t uartMuxChannel = 0;
476 uint8_t index = 0; 565 uint8_t index = 0;
566 uint8_t index2 = 0;
567 uint8_t cntSensor = 0;
568 uint8_t cntUARTSensor = 0;
569 uint8_t cmdString[10];
570 uint8_t cmdLength = 0;
477 571
478 if(externalAutoDetect != DETECTION_OFF) 572 if(externalAutoDetect != DETECTION_OFF)
479 { 573 {
480 switch(externalAutoDetect) 574 switch(externalAutoDetect)
481 { 575 {
482 case DETECTION_INIT: sensorIndex = 0; 576 case DETECTION_INIT: externalInterfaceMuxReqIntervall = 1100;
577 sensorIndex = 0;
483 uartMuxChannel = 0; 578 uartMuxChannel = 0;
484 tmpSensorMap[0] = SENSOR_OPTIC; 579 tmpSensorMap[0] = SENSOR_OPTIC;
485 tmpSensorMap[1] = SENSOR_OPTIC; 580 tmpSensorMap[1] = SENSOR_OPTIC;
486 tmpSensorMap[2] = SENSOR_OPTIC; 581 tmpSensorMap[2] = SENSOR_OPTIC;
487 tmpSensorMap[3] = SENSOR_NONE; 582 tmpSensorMap[3] = SENSOR_NONE;
488 tmpSensorMap[4] = SENSOR_NONE; 583 tmpSensorMap[4] = SENSOR_NONE;
489 584
490 for(index = 0; index < MAX_ADC_CHANNEL; index++) 585 memset(foundSensorMap, SENSOR_NONE, sizeof(foundSensorMap));
491 { 586 memset(externalInterface_SensorState,UART_O2_INIT,sizeof(externalInterface_SensorState));
492 UART_MapDigO2_Channel(index,index); /* request all addresses */ 587 memset(Mux2ADCMap,0, sizeof(Mux2ADCMap));
493 tmpMuxMapping[index] = 0xff;
494 }
495 UART_MapDigO2_Channel(2,3);
496 588
497 if(externalInterfacePresent) 589 if(externalInterfacePresent)
498 { 590 {
499 externalInterface_SwitchPower33(0); 591 externalInterface_SwitchPower33(0);
500 externalInterface_SwitchUART(0); 592 externalInterface_SwitchUART(0);
521 case DETECTION_ANALOG2: for(index = 0; index < MAX_ADC_CHANNEL; index++) 613 case DETECTION_ANALOG2: for(index = 0; index < MAX_ADC_CHANNEL; index++)
522 { 614 {
523 if(externalChannel_mV[index] > MIN_ADC_VOLTAGE_MV) 615 if(externalChannel_mV[index] > MIN_ADC_VOLTAGE_MV)
524 { 616 {
525 tmpSensorMap[sensorIndex++] = SENSOR_ANALOG; 617 tmpSensorMap[sensorIndex++] = SENSOR_ANALOG;
618 foundSensorMap[index] = SENSOR_ANALOG;
526 } 619 }
527 else 620 else
528 { 621 {
529 tmpSensorMap[sensorIndex++] = SENSOR_NONE; 622 tmpSensorMap[sensorIndex++] = SENSOR_NONE;
530 } 623 }
531 } 624 }
532 externalAutoDetect = DETECTION_UARTMUX; 625 externalAutoDetect = DETECTION_UARTMUX;
533 externalInterface_SwitchUART(EXT_INTERFACE_UART_O2 >> 8); 626 externalInterface_SwitchUART(EXT_INTERFACE_UART_O2 >> 8);
534 UART_SetDigO2_Channel(MAX_MUX_CHANNEL); 627 UART_MUX_SelectAddress(MAX_MUX_CHANNEL);
535 break; 628 uartO2_SetChannel(MAX_MUX_CHANNEL);
536 case DETECTION_UARTMUX: if(UART_isDigO2Connected()) 629 activeUartChannel = MAX_MUX_CHANNEL;
630 tmpSensorMap[EXT_INTERFACE_SENSOR_CNT-1] = SENSOR_MUX;
631 break;
632 case DETECTION_UARTMUX: if(uartO2_isSensorConnected())
537 { 633 {
538 uartMuxChannel = 1; 634 uartMuxChannel = 1;
635 tmpSensorMap[EXT_INTERFACE_SENSOR_CNT-1] = SENSOR_MUX;
636 foundSensorMap[EXT_INTERFACE_SENSOR_CNT-1] = SENSOR_MUX;
637 }
638 else
639 {
640 tmpSensorMap[EXT_INTERFACE_SENSOR_CNT-1] = SENSOR_NONE;
539 } 641 }
540 externalAutoDetect = DETECTION_DIGO2_0; 642 externalAutoDetect = DETECTION_DIGO2_0;
541 externalInterface_SwitchUART(EXT_INTERFACE_UART_O2 >> 8); 643 externalInterface_SwitchUART(EXT_INTERFACE_UART_O2 >> 8);
542 UART_SetDigO2_Channel(0); 644 UART_MUX_SelectAddress(0);
543 645 uartO2_SetChannel(0);
646 activeUartChannel = 0;
647 tmpSensorMap[EXT_INTERFACE_MUX_OFFSET] = SENSOR_DIGO2;
648 externalInterface_SensorState[EXT_INTERFACE_MUX_OFFSET] = UART_O2_INIT;
649 externalInterface_SwitchUART(EXT_INTERFACE_UART_O2 >> 8);
544 break; 650 break;
545 case DETECTION_DIGO2_0: 651 case DETECTION_DIGO2_0:
546 case DETECTION_DIGO2_1: 652 case DETECTION_DIGO2_1:
547 case DETECTION_DIGO2_2: 653 case DETECTION_DIGO2_2:
548 case DETECTION_DIGO2_3: 654 case DETECTION_DIGO2_3:
549 if(UART_isDigO2Connected()) 655 if(uartO2_isSensorConnected())
550 { 656 {
551 for(index = 0; index < 3; index++) /* lookup a channel which may be used by digO2 */ 657 foundSensorMap[externalAutoDetect - DETECTION_DIGO2_0 + EXT_INTERFACE_MUX_OFFSET] = SENSOR_DIGO2;
658 }
659
660 if(uartMuxChannel)
661 {
662 externalInterface_SwitchUART(EXT_INTERFACE_UART_O2 >> 8);
663 UART_MUX_SelectAddress(uartMuxChannel);
664 externalInterface_SensorState[uartMuxChannel + EXT_INTERFACE_MUX_OFFSET] = UART_O2_INIT;
665 uartO2_SetChannel(uartMuxChannel);
666 activeUartChannel = uartMuxChannel;
667 tmpSensorMap[uartMuxChannel - 1 + EXT_INTERFACE_MUX_OFFSET] = SENSOR_NONE;
668 tmpSensorMap[uartMuxChannel + EXT_INTERFACE_MUX_OFFSET] = SENSOR_DIGO2;
669
670 if(uartMuxChannel < MAX_MUX_CHANNEL - 1)
671 {
672 uartMuxChannel++;
673 }
674 }
675 else
676 {
677 externalAutoDetect = DETECTION_DIGO2_3; /* skip detection of other serial sensors */
678 }
679 externalAutoDetect++;
680 #ifdef ENABLE_CO2_SUPPORT
681 if(externalAutoDetect == DETECTION_CO2)
682 {
683 externalInterface_SwitchUART(EXT_INTERFACE_UART_CO2 >> 8);
684 if(tmpSensorMap[EXT_INTERFACE_SENSOR_CNT-1] == SENSOR_MUX) /* switch sensor operation mode depending on HW config */
685 {
686 DigitalCO2_SendCmd(CO2CMD_MODE_POLL, cmdString, &cmdLength);
687 }
688 else
689 {
690 DigitalCO2_SendCmd(CO2CMD_MODE_STREAM, cmdString, &cmdLength);
691 }
692 }
693 break;
694 case DETECTION_CO2: if(UART_isCO2Connected())
695 {
696 for(index = 0; index < 3; index++) /* lookup a channel which may be used by CO2*/
552 { 697 {
553 if(tmpSensorMap[index] == SENSOR_NONE) 698 if(tmpSensorMap[index] == SENSOR_NONE)
554 { 699 {
555 break; 700 break;
556 } 701 }
557 } 702 }
558 if(index == 3) 703 if(index == 3)
559 { 704 {
560 tmpSensorMap[2] = SENSOR_DIGO2; /* digital sensor overwrites ADC */
561 }
562 else
563 {
564 tmpSensorMap[index] = SENSOR_DIGO2;
565 tmpMuxMapping[externalAutoDetect - DETECTION_DIGO2_0] = index;
566 if(externalAutoDetect == DETECTION_DIGO2_2 ) /* special handling needed because channel is used twice during mux detection */
567 {
568 UART_MapDigO2_Channel(0xff, externalAutoDetect - DETECTION_DIGO2_0);
569 }
570 }
571 }
572 else
573 {
574 UART_MapDigO2_Channel(0xff, externalAutoDetect - DETECTION_DIGO2_0);
575 }
576 if(uartMuxChannel)
577 {
578 externalInterface_SwitchUART(EXT_INTERFACE_UART_O2 >> 8);
579 UART_SetDigO2_Channel(uartMuxChannel);
580 if(uartMuxChannel < MAX_ADC_CHANNEL - 1)
581 {
582 uartMuxChannel++;
583 }
584 }
585 else
586 {
587 externalAutoDetect = DETECTION_DIGO2_3; /* skip detection of other serial sensors */
588 }
589 externalAutoDetect++;
590 #ifdef ENABLE_CO2_SUPPORT
591 if(externalAutoDetect == DETECTION_CO2)
592 {
593 externalInterface_SwitchUART(EXT_INTERFACE_UART_CO2 >> 8);
594 }
595 break;
596 case DETECTION_CO2: if(UART_isCO2Connected())
597 {
598 for(index = 0; index < 3; index++) /* lookup a channel which may be used by CO2*/
599 {
600 if(tmpSensorMap[index] == SENSOR_NONE)
601 {
602 break;
603 }
604 }
605 if(index == 3)
606 {
607 tmpSensorMap[sensorIndex++] = SENSOR_CO2; /* place Co2 sensor behind O2 sensors (not visible) */ 705 tmpSensorMap[sensorIndex++] = SENSOR_CO2; /* place Co2 sensor behind O2 sensors (not visible) */
608 } 706 }
609 else 707 else
610 { 708 {
611 tmpSensorMap[index] = SENSOR_CO2; 709 tmpSensorMap[index] = SENSOR_CO2;
633 sensorIndex = 3; 731 sensorIndex = 3;
634 } 732 }
635 externalAutoDetect++; 733 externalAutoDetect++;
636 #endif 734 #endif
637 break; 735 break;
638 case DETECTION_DONE: if(uartMuxChannel) 736 case DETECTION_DONE: externalAutoDetect = DETECTION_OFF;
639 {
640 tmpSensorMap[EXT_INTERFACE_SENSOR_CNT-1] = SENSOR_MUX;
641 }
642
643 for(index = 0; index < MAX_MUX_CHANNEL; index++)
644 {
645 UART_MapDigO2_Channel(tmpMuxMapping[index], index);
646 }
647
648 externalAutoDetect = DETECTION_OFF;
649 externalInterface_SwitchUART(0); 737 externalInterface_SwitchUART(0);
650 738 activeUartChannel = 0xFF;
651 739 cntSensor = 0;
652 for(index = 0; index < MAX_ADC_CHANNEL; index++) 740 cntUARTSensor = 0;
653 { 741 for(index = 0; index < EXT_INTERFACE_SENSOR_CNT-1; index++)
654 if(tmpSensorMap[index] == SENSOR_DIGO2) /* set Channel to first valid entry */ 742 {
655 { 743 if((foundSensorMap[index] >= SENSOR_ANALOG) && (foundSensorMap[index] < SENSOR_TYPE_O2_END))
656 UART_SetDigO2_Channel(index); 744 {
657 break; 745 cntSensor++;
658 } 746 }
659 } 747
660 for(index = 0; index < MAX_ADC_CHANNEL; index++) 748 if((foundSensorMap[index] == SENSOR_DIGO2) || (foundSensorMap[index] == SENSOR_CO2))
661 { 749 {
662 if(tmpSensorMap[index] != SENSOR_NONE) 750 cntUARTSensor++;
663 { 751 }
664 break; 752
665 } 753 /* Map Mux O2 sensors to ADC Slot if ADC slot is not in use */
666 } 754 if(foundSensorMap[index] == SENSOR_DIGO2)
667 755 {
668 if(index == MAX_ADC_CHANNEL) /* return default sensor map if no sensor at all has been detected */ 756 for(index2 = 0; index2 < MAX_ADC_CHANNEL; index2++)
669 { 757 {
670 tmpSensorMap[0] = SENSOR_OPTIC; 758 if(foundSensorMap[index2] == SENSOR_NONE)
671 tmpSensorMap[1] = SENSOR_OPTIC; 759 {
672 tmpSensorMap[2] = SENSOR_OPTIC; 760 foundSensorMap[index2] = SENSOR_DIGO2M; /* store a mirror instance needed for visualization */
673 } 761 Mux2ADCMap[index2] = index;
674 memcpy(SensorMap, tmpSensorMap, sizeof(tmpSensorMap)); 762 break;
675 763 }
764 }
765 }
766 }
767 externalInterfaceMuxReqIntervall = 0xFFFF;
768 if(cntSensor == 0) /* return default sensor map if no sensor at all has been detected */
769 {
770 foundSensorMap[0] = SENSOR_OPTIC;
771 foundSensorMap[1] = SENSOR_OPTIC;
772 foundSensorMap[2] = SENSOR_OPTIC;
773 }
774 else
775 {
776 if(cntUARTSensor != 0)
777 {
778 externalInterfaceMuxReqIntervall = REQUEST_INT_SENSOR_MS / cntUARTSensor;
779 }
780 }
781 memcpy(SensorMap, foundSensorMap, sizeof(foundSensorMap));
782 memset(externalInterface_SensorState,UART_O2_INIT,sizeof(externalInterface_SensorState));
676 break; 783 break;
677 default: 784 default:
678 break; 785 break;
679 } 786 }
680 } 787 }
683 790
684 void externalInterface_ExecuteCmd(uint16_t Cmd) 791 void externalInterface_ExecuteCmd(uint16_t Cmd)
685 { 792 {
686 char cmdString[10]; 793 char cmdString[10];
687 uint8_t cmdLength = 0; 794 uint8_t cmdLength = 0;
688 uint8_t index; 795 uint8_t index, index2;
796 uint8_t cntUARTSensor = 0;
797 uint8_t lastMappedID = 0;
798
689 799
690 switch(Cmd & 0x00FF) /* lower byte is reserved for commands */ 800 switch(Cmd & 0x00FF) /* lower byte is reserved for commands */
691 { 801 {
692 case EXT_INTERFACE_AUTODETECT: externalAutoDetect = DETECTION_INIT; 802 case EXT_INTERFACE_AUTODETECT: externalAutoDetect = DETECTION_INIT;
693 for(index = 0; index < 3; index++) 803 for(index = 0; index < 3; index++)
697 break; 807 break;
698 case EXT_INTERFACE_CO2_CALIB: cmdLength = snprintf(cmdString, 10, "G\r\n"); 808 case EXT_INTERFACE_CO2_CALIB: cmdLength = snprintf(cmdString, 10, "G\r\n");
699 break; 809 break;
700 case EXT_INTERFACE_COPY_SENSORMAP: if(externalAutoDetect == DETECTION_OFF) 810 case EXT_INTERFACE_COPY_SENSORMAP: if(externalAutoDetect == DETECTION_OFF)
701 { 811 {
702 memcpy(SensorMap, MasterSensorMap, 5); 812 memcpy(SensorMap, MasterSensorMap, sizeof(MasterSensorMap));
703 for(index = 0; index < 3; index++) 813 for(index = 0; index < EXT_INTERFACE_SENSOR_CNT; index++)
704 { 814 {
705 if(SensorMap[index] == SENSOR_DIGO2) 815 if((SensorMap[index] == SENSOR_DIGO2) || (SensorMap[index] == SENSOR_CO2))
706 { 816 {
707 break; 817 cntUARTSensor++;
708 } 818 }
819 if(SensorMap[index] == SENSOR_DIGO2M) /* find matching sensor for mirror */
820 {
821 for(index2 = EXT_INTERFACE_MUX_OFFSET; index2 < EXT_INTERFACE_SENSOR_CNT; index2++)
822 {
823 if(SensorMap[index2] == SENSOR_DIGO2)
824 {
825 if(lastMappedID < index2)
826 {
827 lastMappedID = index2;
828 Mux2ADCMap[index] = index2;
829 break;
830 }
831 }
832 }
833 }
834 }
835 if(cntUARTSensor > 0)
836 {
837 externalInterfaceMuxReqIntervall = REQUEST_INT_SENSOR_MS / cntUARTSensor;
838 activeUartChannel = 0xFF;
839 }
840 else
841 {
842 externalInterfaceMuxReqIntervall = 0xFFFF;
709 } 843 }
710 } 844 }
711 break; 845 break;
712 default: 846 default:
713 break; 847 break;
717 HAL_UART_Transmit(&huart1,(uint8_t*)cmdString,cmdLength,10); 851 HAL_UART_Transmit(&huart1,(uint8_t*)cmdString,cmdLength,10);
718 } 852 }
719 return; 853 return;
720 } 854 }
721 855
856 uint8_t ExternalInterface_SelectUsedMuxChannel(uint8_t currentChannel)
857 {
858 uint8_t index = currentChannel;
859 uint8_t newChannel = index;
860 uint8_t *pmap = externalInterface_GetSensorMapPointer(0);
861
862 do
863 {
864 index++;
865 if(index == MAX_MUX_CHANNEL)
866 {
867 index = 0;
868 }
869 if(((pmap[index + EXT_INTERFACE_MUX_OFFSET] == SENSOR_DIGO2) || (pmap[index + EXT_INTERFACE_MUX_OFFSET] == SENSOR_CO2))
870 && (index != activeUartChannel))
871 {
872 newChannel = index;
873 break;
874 }
875 } while(index != currentChannel);
876
877 return newChannel;
878 }
879
880 void externalInterface_HandleUART()
881 {
882 static uint8_t retryRequest = 0;
883 static uint32_t lastRequestTick = 0;
884 static uint32_t TriggerTick = 0;
885 uint8_t index = 0;
886 static uint8_t timeToTrigger = 0;
887 uint32_t tick = HAL_GetTick();
888 uint8_t *pmap = externalInterface_GetSensorMapPointer(0);
889
890
891 UART_ReadData(pmap[activeSensorId]);
892
893 if(activeUartChannel == 0xFF)
894 {
895 activeUartChannel = ExternalInterface_SelectUsedMuxChannel(0);
896 uartO2_SetChannel(activeUartChannel);
897 if(pmap[EXT_INTERFACE_SENSOR_CNT-1] == SENSOR_MUX)
898 {
899 UART_MUX_SelectAddress(activeUartChannel);
900 }
901 UART_FlushRxBuffer();
902 }
903
904 if(externalInterfaceMuxReqIntervall != 0xFFFF)
905 {
906 if(externalInterface_SensorState[activeSensorId] == UART_O2_INIT)
907 {
908 lastRequestTick = tick;
909 TriggerTick = tick - 10; /* just to make sure control is triggered */
910 timeToTrigger = 1;
911 retryRequest = 0;
912 }
913 else if(((retryRequest == 0) /* timeout or error */
914 && (((time_elapsed_ms(lastRequestTick,tick) > (TIMEOUT_SENSOR_ANSWER)) && (externalInterface_SensorState[activeSensorId] != UART_O2_IDLE)) /* retry if no answer after half request interval */
915 || (externalInterface_SensorState[activeSensorId] == UART_O2_ERROR))))
916 {
917 /* The channel switch will cause the sensor to respond with an error message. */
918 /* The sensor needs ~30ms to recover before he is ready to receive the next command => transmission delay needed */
919
920 TriggerTick = tick;
921 timeToTrigger = COMMAND_TX_DELAY;
922 retryRequest = 1;
923 }
924
925 else if(time_elapsed_ms(lastRequestTick,tick) > externalInterfaceMuxReqIntervall) /* switch sensor and / or trigger next request */
926 {
927 lastRequestTick = tick;
928 TriggerTick = tick;
929 retryRequest = 0;
930 timeToTrigger = 1;
931
932 if((externalInterface_SensorState[activeSensorId] == UART_O2_REQ_O2) /* timeout */
933 || (externalInterface_SensorState[activeSensorId] == UART_O2_REQ_RAW))
934 {
935 setExternalInterfaceChannel(activeSensorId,0.0);
936 }
937
938 if(pmap[EXT_INTERFACE_SENSOR_CNT-1] == SENSOR_MUX) /* select next sensor if mux is connected */
939 {
940 if(activeUartChannel < MAX_MUX_CHANNEL)
941 {
942 index = ExternalInterface_SelectUsedMuxChannel(activeUartChannel);
943 if(index != activeUartChannel)
944 {
945 timeToTrigger = 100;
946 activeUartChannel = index;
947 if(pmap[index + EXT_INTERFACE_MUX_OFFSET] == SENSOR_DIGO2)
948 {
949 uartO2_SetChannel(activeUartChannel);
950 UART_MUX_SelectAddress(activeUartChannel);
951 }
952 }
953 }
954 }
955 else
956 {
957 timeToTrigger = 1;
958 }
959 }
960 if((timeToTrigger != 0) && (time_elapsed_ms(TriggerTick,tick) > timeToTrigger))
961 {
962 timeToTrigger = 0;
963 switch (pmap[activeSensorId])
964 {
965 case SENSOR_MUX:
966 case SENSOR_DIGO2: uartO2_Control();
967 break;
968 // case SENSOR_CO2: uartCO2_Control();
969 break;
970 default:
971 break;
972 }
973 }
974 }
975
976
977
978 #if 0
979 #ifdef ENABLE_CO2_SUPPORT
980 if(externalInterface_GetUARTProtocol() & (EXT_INTERFACE_UART_CO2 >> 8))
981 {
982 UART_HandleCO2Data();
983 }
984 #endif
985 #ifdef ENABLE_SENTINEL_MODE
986 if(externalInterface_GetUARTProtocol() & (EXT_INTERFACE_UART_SENTINEL >> 8))
987 {
988 UART_HandleSentinelData();
989 }
990 #endif
991 if(externalInterface_GetUARTProtocol() & (EXT_INTERFACE_UART_O2 >> 8))
992 {
993 UART_HandleDigitalO2();
994 }
995 #endif
996
997
998 }