@@ -163,6 +163,12 @@ struct shearwater_predator_parser_t {
163163 struct dc_field_cache cache ;
164164};
165165
166+ struct dc_parser_sensor_calibration_t {
167+ double sum_ppo2 ;
168+ double sum_calculated_ppo2 ;
169+ unsigned int ppo2_sample_count ;
170+ };
171+
166172static dc_status_t shearwater_predator_parser_get_datetime (dc_parser_t * abstract , dc_datetime_t * datetime );
167173static dc_status_t shearwater_predator_parser_get_field (dc_parser_t * abstract , dc_field_type_t type , unsigned int flags , void * value );
168174static dc_status_t shearwater_predator_parser_samples_foreach (dc_parser_t * abstract , dc_sample_callback_t callback , void * userdata );
@@ -417,6 +423,20 @@ add_battery_type(shearwater_predator_parser_t *parser, const unsigned char *data
417423 }
418424}
419425
426+ static void print_calibration (shearwater_predator_parser_t * parser )
427+ {
428+ for (size_t i = 0 ; i < 3 ; ++ i ) {
429+ if (parser -> calibrated & (1 << i )) {
430+ static const char * name [] = {
431+ "Sensor 1 calibration [bar / V]" ,
432+ "Sensor 2 calibration [bar / V]" ,
433+ "Sensor 3 calibration [bar / V]" ,
434+ };
435+ dc_field_add_string_fmt (& parser -> cache , name [i ], "%.2f" , parser -> calibration [i ] * 1000 );
436+ }
437+ }
438+ }
439+
420440static dc_status_t
421441shearwater_predator_parser_cache (shearwater_predator_parser_t * parser )
422442{
@@ -777,16 +797,7 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
777797
778798 if (calibration_count > 0 ) {
779799 if (calibration_default_count < calibration_count ) {
780- for (size_t i = 0 ; i < 3 ; ++ i ) {
781- if (parser -> calibrated & (1 << i )) {
782- static const char * name [] = {
783- "Sensor 1 calibration [bar / V]" ,
784- "Sensor 2 calibration [bar / V]" ,
785- "Sensor 3 calibration [bar / V]" ,
786- };
787- dc_field_add_string_fmt (& parser -> cache , name [i ], "%.2f" , parser -> calibration [i ] * 1000 );
788- }
789- }
800+ print_calibration (parser );
790801 } else {
791802 // All calibrated sensors report the default calibration value
792803 // so this could be a DiveCAN controller, where the calibration values
@@ -883,8 +894,33 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
883894 break ;
884895 }
885896
897+ dc_status_t rc = DC_STATUS_SUCCESS ;
886898 if (parser -> needs_divecan_calibration_estimate ) {
887- return shearwater_predator_parser_samples_foreach (abstract , NULL , NULL );
899+ struct dc_parser_sensor_calibration_t data = { 0 };
900+
901+ rc = shearwater_predator_parser_samples_foreach (abstract , NULL , (void * )& data );
902+
903+ bool calibrated = false;
904+ if (data .sum_ppo2 != 0 ) {
905+ double calibration = data .sum_calculated_ppo2 / data .sum_ppo2 ;
906+ if (calibration < 0.95 || calibration > 1.05 ) {
907+ // The calibration scaling is significant, use it.
908+ calibration *= SENSOR_CALIBRATION_DEFAULT / 100000.0 ;
909+ parser -> calibration [0 ] = calibration ;
910+ parser -> calibration [1 ] = calibration ;
911+ parser -> calibration [2 ] = calibration ;
912+
913+ dc_field_add_string_fmt (& parser -> cache , "Estimated (DiveCAN?) sensor calibration [bar / V]" , "%.2f" , calibration * 1000 );
914+
915+ calibrated = true;
916+ }
917+ }
918+
919+ if (!calibrated ) {
920+ print_calibration (parser );
921+ }
922+
923+ parser -> needs_divecan_calibration_estimate = false;
888924 }
889925
890926 return DC_STATUS_SUCCESS ;
@@ -1073,37 +1109,30 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
10731109 double calculated_ppo2 = data [offset + pnf + 6 ] / 100.0 ;
10741110
10751111 if (parser -> needs_divecan_calibration_estimate ) {
1112+ struct dc_parser_sensor_calibration_t * out = (struct dc_parser_sensor_calibration_t * )userdata ;
1113+
10761114 double ppo2_sum = 0.0 ;
10771115 unsigned int ppo2_count = 0 ;
10781116 if (parser -> calibrated & 0x01 ) {
1079- ppo2_sum += data [offset + pnf + 12 ] * SENSOR_CALIBRATION_DEFAULT ;
1117+ ppo2_sum += data [offset + pnf + 12 ] * SENSOR_CALIBRATION_DEFAULT / 100000.0 ;
10801118 ppo2_count ++ ;
10811119 }
10821120
10831121 if (parser -> calibrated & 0x02 ) {
1084- ppo2_sum += data [offset + pnf + 14 ] * SENSOR_CALIBRATION_DEFAULT ;
1122+ ppo2_sum += data [offset + pnf + 14 ] * SENSOR_CALIBRATION_DEFAULT / 100000.0 ;
10851123 ppo2_count ++ ;
10861124 }
10871125
10881126 if (parser -> calibrated & 0x04 ) {
1089- ppo2_sum += data [offset + pnf + 15 ] * SENSOR_CALIBRATION_DEFAULT ;
1127+ ppo2_sum += data [offset + pnf + 15 ] * SENSOR_CALIBRATION_DEFAULT / 100000.0 ;
10901128 ppo2_count ++ ;
10911129 }
10921130
1093- double calibration = SENSOR_CALIBRATION_DEFAULT ;
1094- double calibration_scaling_factor = calculated_ppo2 / (ppo2_sum / ppo2_count );
1095- if (calibration_scaling_factor < 0.95 || calibration_scaling_factor > 1.05 ) {
1096- // The calibration scaling is significant, use it.
1097- calibration *= calibration_scaling_factor ;
1098- }
1099-
1100- parser -> calibration [0 ] = calibration ;
1101- parser -> calibration [1 ] = calibration ;
1102- parser -> calibration [2 ] = calibration ;
1103-
1104- dc_field_add_string_fmt (& parser -> cache , "Estimated DiveCAN calibration [bar / V]" , "%.2f" , calibration * 1000 );
1131+ double ppo2 = ppo2_sum / ppo2_count ;
11051132
1106- parser -> needs_divecan_calibration_estimate = false;
1133+ out -> sum_ppo2 += ppo2 ;
1134+ out -> sum_calculated_ppo2 += calculated_ppo2 ;
1135+ out -> ppo2_sample_count ++ ;
11071136 }
11081137
11091138 if (callback ) {
0 commit comments