# HG changeset patch # User heinrichsweikamp # Date 1660901424 -7200 # Node ID cc542448fb28987f0b7390233af46dedf2ca1b9d # Parent 87bee7cc77b3eeecb395daa7cd17e5ac4f67c073# Parent 49b164022335621c5e7ed987ad177c99d82ab572 Merge diff -r 87bee7cc77b3 -r cc542448fb28 Common/Inc/configuration.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Common/Inc/configuration.h Fri Aug 19 11:30:24 2022 +0200 @@ -0,0 +1,75 @@ +/////////////////////////////////////////////////////////////////////////////// +/// -*- coding: UTF-8 -*- +/// +/// \file Discovery/Inc/configuration.h +/// \brief Header file for variant specific firmware adaptations at compile time +/// \author heinrichs weikamp gmbh +/// \date 29-February-2020 +/// +/// $Id$ +/////////////////////////////////////////////////////////////////////////////// +/// \par Copyright (c) 2014-2020 Heinrichs Weikamp gmbh +/// +/// This program is free software: you can redistribute it and/or modify +/// it under the terms of the GNU General Public License as published by +/// the Free Software Foundation, either version 3 of the License, or +/// (at your option) any later version. +/// +/// This program is distributed in the hope that it will be useful, +/// but WITHOUT ANY WARRANTY; without even the implied warranty of +/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +/// GNU General Public License for more details. +/// +/// You should have received a copy of the GNU General Public License +/// along with this program. If not, see . +////////////////////////////////////////////////////////////////////////////// + +#ifndef CONFIGURATION_HEADER +#define CONFIGURATION_HEADER + +/* Enable this to make the simulator write a logbook entry */ +/* #define SIM_WRITES_LOGBOOK 1 */ + +/* Enable this for support of optical bottle pressure interface */ +/* #define ENABLE_BOTTLE_SENSOR */ + +/* Enable this to show voltage in parallel to charge state */ +/* #define ALWAYS_SHOW_VOLTAGE */ + +/* Enable this to skip coplete scan of dive log during startup */ +#define TRUST_LOG_CONSISTENCY + +/* Enable this to transfer additional data list last dive ID and last sample index during raw data requests */ +/* define SEND_DATA_DETAILS */ + +/* Enable to activate a menu item in reset menu which provide sample ring analysis / repair functionality */ +/* #define ENABLE_ANALYSE_SAMPLES */ + +/* Enable to have access to the debug view options (turn on / off via menu instead of compile switch) */ +/* #define HAVE_DEBUG_VIEW */ + +/* Enable to have access to the motion control selection menu */ +/* #define ENABLE_MOTION_CONTROL */ + +/* Enable to have option to hide not needed gases from dive views */ +/* #define ENABLE_UNUSED_GAS_HIDING */ + +/* Enable to have the new T3 profile view available */ +#define ENABLE_T3_PROFILE_VIEW + +/* Enable to have PPO2 adjustments in T3 sensor view during dive simulation */ +/* #define ENABLE_T3_PPO_SIM */ + +/* Enable to have PSCR functionality available */ +#define ENABLE_PSCR_MODE + +/* Enable to have CO2 sensor functionality available */ +/* #define ENABLE_CO2_SUPPORT */ + +/* Enable to have Sentinel rebreather interface available */ +/* #define ENABLE_SENTINEL_MODE */ + +/* Enable if you are using sensors with a voltage range 8..16 mV at surface / air level */ +#define ENABLE_ALTERNATIVE_SENSORTYP + +#endif diff -r 87bee7cc77b3 -r cc542448fb28 Common/Inc/data_central.h --- a/Common/Inc/data_central.h Mon Nov 01 12:39:34 2021 +0100 +++ b/Common/Inc/data_central.h Fri Aug 19 11:30:24 2022 +0200 @@ -31,6 +31,7 @@ #include "settings.h" #include "stm32f4xx_hal.h" +#include "configuration.h" #define BUEHLMANN_STRUCT_MAX_GASES 11 #define BUEHLMANN_STRUCT_MAX_ASCENDRATES 3 @@ -50,7 +51,8 @@ uint8_t setPoint_cbar; uint8_t change_during_ascent_depth_meter_otherwise_zero; uint8_t GasIdInSettings; - uint8_t temp1_for16bitalign; + uint8_t AppliedDiveMode; + float pscr_factor; } SGas; typedef struct @@ -75,6 +77,13 @@ uint8_t data[12]; } SDataWireless; + +typedef struct +{ + uint16_t CO2_ppm; + uint16_t signalStrength; +} SCO2Sensor; + /* Main structs -------------------------------------------------------------*/ @@ -187,6 +196,8 @@ uint16_t ambient_light_level; SDataWireless wireless_data[4]; uint8_t buttonPICdata[4]; + SCO2Sensor CO2_data; + /* by create DiveSettings() and by setActualGas() * is send to Small CPU2 for nitrogen calculation @@ -221,6 +232,9 @@ float ppO2Sensor_bar[3]; float sensorVoltage_mV[3]; float HUD_battery_voltage_V; + +/* for PSCR Mode */ + float ppo2Simulated_bar; } SLifeData; @@ -323,6 +337,9 @@ */ float internal__pressure_first_stop_ambient_bar_as_upper_limit_for_gf_low_otherwise_zero; uint16_t compassHeading; + + uint8_t pscr_o2_drop; + uint8_t pscr_lung_ratio; } SDiveSettings; enum CHARGE_STATUS{ @@ -454,4 +471,6 @@ _Bool is_ambient_pressure_close_to_surface(SLifeData *lifeData); +uint8_t isLoopMode(uint8_t Mode); + #endif // DATA_CENTRAL_H diff -r 87bee7cc77b3 -r cc542448fb28 Common/Inc/data_exchange.h --- a/Common/Inc/data_exchange.h Mon Nov 01 12:39:34 2021 +0100 +++ b/Common/Inc/data_exchange.h Fri Aug 19 11:30:24 2022 +0200 @@ -31,6 +31,21 @@ #include "settings.h" #include "stm32f4xx_hal.h" +/* Command definitions for control of external interface */ +/* 1st nibble binary on/off states */ +/* 2nd nibble UART protocol selection */ +/* 3rd nibble reserve */ +/* 4th nibble command channel */ +#define EXT_INTERFACE_33V_ON (0x8000u) /* Bit set to enable 3.3V power interface */ +#define EXT_INTERFACE_ADC_ON (0x4000u) /* Bit set to enable ADC conversion */ +#define EXT_INTERFACE_UART_MASK (0x0700u) /* Reserve 3 bits for UART protocol selection */ +#define EXT_INTERFACE_UART_CO2 (0x0100u) /* Activate protocol for CO2 sensor */ +#define EXT_INTERFACE_UART_SENTINEL (0x0200u) /* Activate Sentinel Backup monitor protocol */ +#define EXT_INTERFACE_CO2_CALIB (0x0001u) /* Request calibration of CO2Sensor */ + +#define DATA_BUFFER_ADC (0x01u) +#define DATA_BUFFER_CO2 (0x02u) + enum MODE { MODE_SURFACE = 0, @@ -80,9 +95,11 @@ #define CRBUTTON (0x01) #define CRDATE (0x02) #define CRTIME (0x04) -#define CRCLEARDECO (0x08) -#define CRCOMPASS (0x10) -#define CRDEVICEDATA (0x20) +#define CRCLEARDECO (0x08) +#define CRCOMPASS (0x10) +#define CRDEVICEDATA (0x20) +#define CRBATTERY (0x40) +#define CRACCIDENT (0x80) typedef union{ confirmbit8_t ub; @@ -148,7 +165,10 @@ uint16_t ambient_light_level; uint16_t SPARE_ALIGN32; float extADC_voltage[3]; - uint8_t SPARE_OldWireless[50]; /* 64 - 12 for extADC */ + uint16_t CO2_ppm; + uint16_t CO2_signalStrength; + uint16_t externalInterface_CmdAnswer; + uint8_t SPARE_OldWireless[44]; /* 64 - 12 for extADC - 6 for CO2 */ // PIC data uint8_t button_setting[4]; /* see dependency to SLiveData->buttonPICdata */ uint8_t SPARE1; @@ -166,8 +186,7 @@ int8_t offsetPressureSensor_mbar; int8_t offsetTemperatureSensor_centiDegree; - uint8_t SPARE1; - uint8_t SPARE2; + uint16_t externalInterface_Cmd; float UNUSED1[16-1];//VPM_adjusted_critical_radius_he[16]; float UNUSED2[16];//VPM_adjusted_critical_radius_n2[16]; @@ -208,7 +227,7 @@ uint8_t chargeStatus; uint8_t boolPICdata; confirmbit8_Type confirmRequest; // confirmbit8_Type - uint8_t boolWirelessData; + uint8_t boolADCO2Data; uint8_t boolPressureData; uint8_t boolCompassData; diff -r 87bee7cc77b3 -r cc542448fb28 Common/Inc/decom.h --- a/Common/Inc/decom.h Mon Nov 01 12:39:34 2021 +0100 +++ b/Common/Inc/decom.h Fri Aug 19 11:30:24 2022 +0200 @@ -46,6 +46,8 @@ void test_decom_CreateGasChangeList(void); float decom_calc_ppO2(const float ambiant_pressure_bar, const SGas* pGas); +float decom_calc_SimppO2(float ambiant_pressure_bar, const SGas* pGas); +float decom_calc_SimppO2_O2based(float ambiant_pressure_bar, uint8_t O2PerCent, float factor); void decom_oxygen_calculate_otu(float* oxygen_otu, float pressure_oxygen_real); void decom_oxygen_calculate_otu_degrade(float* oxygen_otu, long seconds_since_last_dive); void decom_oxygen_calculate_cns_degrade(float* oxygen_cns, long seconds_since_last_dive); diff -r 87bee7cc77b3 -r cc542448fb28 Common/Inc/settings.h --- a/Common/Inc/settings.h Mon Nov 01 12:39:34 2021 +0100 +++ b/Common/Inc/settings.h Fri Aug 19 11:30:24 2022 +0200 @@ -36,6 +36,8 @@ // From Common/Drivers/ #include "stm32f4xx_hal.h" +#include "configuration.h" + #include @@ -47,11 +49,13 @@ #define CCRMODE_FixedSetpoint 0 #define CCRMODE_Sensors 1 +#define CCRMODE_Simulation 2 #define DIVEMODE_OC 0 #define DIVEMODE_CCR 1 #define DIVEMODE_Gauge 2 #define DIVEMODE_Apnea 3 +#define DIVEMODE_PSCR 4 #define GF_MODE 1 #define VPM_MODE 2 @@ -71,13 +75,24 @@ #define MAX_COMPASS_COMP (2u) #define MAX_VIEWPORT_MODE (0x7F) -#define MAX_SCRUBBER_TIME (500u) +#define MAX_SCRUBBER_TIME (999u) #define MIN_PPO2_SP_CBAR (40u) +#define PSCR_MAX_O2_DROP (15u) +#define PSCR_MIN_LUNG_RATIO (5u) +#define PSCR_MAX_LUNG_RATIO (20u) + +#define UART_MAX_PROTOCOL (2u) + +#define FUTURE_SPARE_SIZE (28u) /* Applied for reuse of old, not used, scooter block (was 32 bytes)*/ + typedef enum { O2_SENSOR_SOURCE_OPTIC = 0, O2_SENSOR_SOURCE_ANALOG, +#ifdef ENABLE_SENTINEL_MODE + O2_SENSOR_SOURCE_SENTINEL, +#endif O2_SENSOR_SOURCE_MAX } SensorSource; #define MAX_O2_SENSOR_SOURCE (2u) @@ -202,13 +217,11 @@ uint8_t bluetoothActive; /* will be set to zero on each startup at the moment */ uint8_t safetystopDepth; uint32_t updateSettingsAllowedFromHeader; - uint8_t scooterControl; - uint8_t scooterDrag; - uint8_t scooterLoad; - uint8_t scooterNumberOfBatteries; - uint16_t scooterBattSize; - uint8_t scooterSPARE1[7]; - uint8_t scooterSPARE2[19]; + uint8_t pscr_lung_ratio; /* redefined in 0xFFFF0020 */ + uint8_t pscr_o2_drop; /* redefined in 0xFFFF0020 */ + uint8_t co2_sensor_active; /* redefined in 0xFFFF0021 */ + uint8_t ext_uart_protocol; /* redefined in 0xFFFF0022 */ + uint8_t Future_SPARE[FUTURE_SPARE_SIZE]; /* redefined in 0xFFFF0020 (old scooter Block was 32 byte)*/ // new in 0xFFFF0006 uint8_t ppo2sensors_deactivated; uint8_t tX_colorscheme; @@ -340,4 +353,7 @@ uint8_t settingsHelperButtonSens_translate_percentage_to_hwOS_values(uint8_t inputValuePercentage); uint8_t settingsHelperButtonSens_translate_hwOS_values_to_percentage(uint8_t inputValuePIC); +void reset_SettingWarning(); +uint8_t isSettingsWarning(); + #endif // SETTINGS_H diff -r 87bee7cc77b3 -r cc542448fb28 Common/Src/decom.c --- a/Common/Src/decom.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Common/Src/decom.c Fri Aug 19 11:30:24 2022 +0200 @@ -217,24 +217,34 @@ float ppo2_fraction_setpoint; float diluent_divisor; - *fraction_nitrogen = ((float)pGas->nitrogen_percentage) / 100.0f; *fraction_helium = ((float)pGas->helium_percentage) / 100.0f; - if(!pGas->setPoint_cbar) - return; + if(pGas->AppliedDiveMode == DIVEMODE_CCR) + { + // continue with CCR + fraction_all_inertgases = *fraction_nitrogen + *fraction_helium; - // continue with CCR - fraction_all_inertgases = *fraction_nitrogen + *fraction_helium; + ppo2_fraction_setpoint = (float)pGas->setPoint_cbar/ (100 * ambient_pressure_bar); + + diluent_divisor = (1.0f - ppo2_fraction_setpoint) / fraction_all_inertgases; + if(diluent_divisor < 0) + diluent_divisor = 0; - ppo2_fraction_setpoint = (float)pGas->setPoint_cbar/ (100 * ambient_pressure_bar); + *fraction_nitrogen *= diluent_divisor; + *fraction_helium *= diluent_divisor; + } + if(pGas->AppliedDiveMode == DIVEMODE_PSCR) + { + fraction_all_inertgases = *fraction_nitrogen + *fraction_helium; + ppo2_fraction_setpoint = decom_calc_SimppO2(ambient_pressure_bar, pGas) / ambient_pressure_bar; + diluent_divisor = (1.0f - ppo2_fraction_setpoint) / fraction_all_inertgases; + if(diluent_divisor < 0) + diluent_divisor = 0; - diluent_divisor = (1.0f - ppo2_fraction_setpoint) / fraction_all_inertgases; - if(diluent_divisor < 0) - diluent_divisor = 0; - - *fraction_nitrogen *= diluent_divisor; - *fraction_helium *= diluent_divisor; + *fraction_nitrogen *= diluent_divisor; + *fraction_helium *= diluent_divisor; + } } @@ -618,79 +628,47 @@ pInput->decogaslist[count].nitrogen_percentage -= pInput->gas[i].helium_percentage; pInput->decogaslist[count].helium_percentage = pInput->gas[i].helium_percentage; pInput->decogaslist[count].GasIdInSettings = i; - + pInput->decogaslist[count].AppliedDiveMode = DIVEMODE_OC; } } } else { - //divmode CCR + //divmode CCR or PSCR for(i=6; i <= 10; i++) { - if(pInput->gas[i].note.ub.active && pInput->gas[i].depth_meter + if((pInput->gas[i].note.ub.active) && (pInput->gas[i].depth_meter) && (pLifeData->actualGas.GasIdInSettings != i) - &&(pInput->gas[i].depth_meter < pLifeData->depth_meter ) ) + && (pInput->gas[i].depth_meter < pLifeData->depth_meter )) { count = 1; for(j=6;j<= 10;j++) { // if(pInput->gas[j].note.ub.active && pInput->gas[j].depth_meter > 0 &&pInput->gas[j].depth_meter > pInput->gas[i].depth_meter) - if( (pInput->gas[j].note.ub.active && pInput->gas[j].depth_meter > 0) + if(((pInput->gas[j].note.ub.active) && (pInput->gas[j].depth_meter > 0)) && (pLifeData->actualGas.GasIdInSettings != j) // new hw 160905 && (pInput->gas[j].depth_meter > pInput->gas[i].depth_meter)) count++; } pInput->decogaslist[count].change_during_ascent_depth_meter_otherwise_zero = pInput->gas[i].depth_meter; pInput->decogaslist[count].nitrogen_percentage = 100; - pInput->decogaslist[count].nitrogen_percentage -= pInput->gas[i].oxygen_percentage; + if(pInput->diveMode == DIVEMODE_PSCR) + { + pInput->decogaslist[count].AppliedDiveMode = DIVEMODE_PSCR; + pInput->decogaslist[count].setPoint_cbar = decom_calc_SimppO2_O2based((float)(pInput->gas[i].depth_meter / 10.0 + 1.0), pInput->gas[i].oxygen_percentage, pInput->decogaslist[count].pscr_factor ) * 100; + pInput->decogaslist[count].nitrogen_percentage -= pInput->gas[i].oxygen_percentage; + } + else + { + pInput->decogaslist[count].nitrogen_percentage -= pInput->gas[i].oxygen_percentage; + pInput->decogaslist[count].AppliedDiveMode = DIVEMODE_CCR; + pInput->decogaslist[count].setPoint_cbar = pInput->decogaslist[0].setPoint_cbar; /* assume that current setpoint is kept till end of the dive */ + } pInput->decogaslist[count].nitrogen_percentage -= pInput->gas[i].helium_percentage; pInput->decogaslist[count].helium_percentage = pInput->gas[i].helium_percentage; pInput->decogaslist[count].GasIdInSettings = i; - } } - /* Include Setpoint Changes */ - for(j=0; j <= count; j++) - { - uint8_t depth = 0; - uint8_t changedepth = 0; - char newSetpoint; - if(j == 0) - { - depth = pLifeData->depth_meter; - } - else - { - //no setpointchange ? - pInput->decogaslist[j].setPoint_cbar = pInput->decogaslist[j - 1].setPoint_cbar; - depth = pInput->decogaslist[j].change_during_ascent_depth_meter_otherwise_zero + 0.1f; - } - /* Setpoint change at the same depth as gas changes */ - if(nextSetpointChange(pInput,depth + 1, &changedepth,&newSetpoint) && changedepth == depth) - { - pInput->decogaslist[j].setPoint_cbar = newSetpoint; - } - /* Setpoint changes inbetween gas changes */ - while(nextSetpointChange(pInput, depth, &changedepth,&newSetpoint) - && ( - ( (j < count) && (changedepth > pInput->decogaslist[j + 1].change_during_ascent_depth_meter_otherwise_zero)) - || ((j == count) && (changedepth > 0)) - )) - { - //Include new entry with setpoint change in decogaslist - for(int k = count; k > j; k--) - { - pInput->decogaslist[k+1] = pInput->decogaslist[k]; - } - pInput->decogaslist[j + 1] = pInput->decogaslist[j]; - pInput->decogaslist[j + 1].setPoint_cbar = newSetpoint; - j++; - count++; - depth = changedepth; - } - - } - } } void test_decom_CreateGasChangeList(void) @@ -1022,16 +1000,51 @@ float decom_calc_ppO2(const float ambiant_pressure_bar, const SGas* pGas) { - float percent_N2 = 0; + float percent_N2 = 0; float percent_He = 0; float percent_O2 = 0; - decom_get_inert_gases(ambiant_pressure_bar, pGas, &percent_N2, &percent_He); - percent_O2 = 1 - percent_N2 - percent_He; - return (ambiant_pressure_bar - WATER_VAPOUR_PRESSURE) * percent_O2; + decom_get_inert_gases(ambiant_pressure_bar, pGas, &percent_N2, &percent_He); + percent_O2 = 1 - percent_N2 - percent_He; + + return (ambiant_pressure_bar - WATER_VAPOUR_PRESSURE) * percent_O2; } +float decom_calc_SimppO2(float ambiant_pressure_bar, const SGas* pGas) +{ + float o2Ratio = 0.0; + float inertGasRatio = 0.0; + float simulatedPSCRppo2 = 0.0; + + o2Ratio = (100.0 - pGas->nitrogen_percentage - pGas->helium_percentage) / 100.0; + inertGasRatio = 1.0 - o2Ratio; + simulatedPSCRppo2 = (ambiant_pressure_bar - WATER_VAPOUR_PRESSURE) * o2Ratio; + simulatedPSCRppo2 -= (inertGasRatio * pGas->pscr_factor); + if(simulatedPSCRppo2 < 0.0) + { + simulatedPSCRppo2 = 0.0; + } + return simulatedPSCRppo2; +} + +float decom_calc_SimppO2_O2based(float ambiant_pressure_bar, uint8_t O2PerCent, float factor) +{ + float o2Ratio = 0.0; + float inertGasRatio = 0.0; + float simulatedPSCRppo2 = 0.0; + + o2Ratio = O2PerCent / 100.0; + inertGasRatio = 1.0 - o2Ratio; + simulatedPSCRppo2 = (ambiant_pressure_bar - WATER_VAPOUR_PRESSURE) * o2Ratio; + simulatedPSCRppo2 -= (inertGasRatio * factor); + if(simulatedPSCRppo2 < 0.0) + { + simulatedPSCRppo2 = 0.0; + } + return simulatedPSCRppo2; +} + uint8_t decom_get_actual_deco_stop(SDiveState* pDiveState) { SDecoinfo* pDecoinfo; diff -r 87bee7cc77b3 -r cc542448fb28 Current build/OSTC4update_210428.bin Binary file Current build/OSTC4update_210428.bin has changed diff -r 87bee7cc77b3 -r cc542448fb28 Current build/OSTC4update_220819.bin Binary file Current build/OSTC4update_220819.bin has changed diff -r 87bee7cc77b3 -r cc542448fb28 Discovery/Inc/configuration.h --- a/Discovery/Inc/configuration.h Mon Nov 01 12:39:34 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -/// -*- coding: UTF-8 -*- -/// -/// \file Discovery/Inc/configuration.h -/// \brief Header file for variant specific firmware adaptations at compile time -/// \author heinrichs weikamp gmbh -/// \date 29-February-2020 -/// -/// $Id$ -/////////////////////////////////////////////////////////////////////////////// -/// \par Copyright (c) 2014-2020 Heinrichs Weikamp gmbh -/// -/// This program is free software: you can redistribute it and/or modify -/// it under the terms of the GNU General Public License as published by -/// the Free Software Foundation, either version 3 of the License, or -/// (at your option) any later version. -/// -/// This program is distributed in the hope that it will be useful, -/// but WITHOUT ANY WARRANTY; without even the implied warranty of -/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -/// GNU General Public License for more details. -/// -/// You should have received a copy of the GNU General Public License -/// along with this program. If not, see . -////////////////////////////////////////////////////////////////////////////// - - -#ifndef CONFIGURATION_HEADER -#define CONFIGURATION_HEADER - -/* Enable this to make the simulator write a logbook entry */ -/* #define SIM_WRITES_LOGBOOK 1 */ - -/* Enable this for support of optical bottle pressure interface */ -/* #define ENABLE_BOTTLE_SENSOR */ - -/* Enable this to show voltage in parallel to charge state */ -/* #define ALWAYS_SHOW_VOLTAGE */ - -/* Enable this to skip coplete scan of dive log during startup */ -#define TRUST_LOG_CONSISTENCY - -/* Enable this to transfer additional data list last dive ID and last sample index during raw data requests */ -/* define SEND_DATA_DETAILS */ - -/* Enable to activate a menu item in reset menu which provide sample ring analysis / repair functionality */ -/* #define ENABLE_ANALYSE_SAMPLES */ - -/* Enable to have access to the debug view options (turn on / off via menu instead of compile switch) */ -/* #define HAVE_DEBUG_VIEW */ - -/* Enable to have access to the motion control selection menu */ -/* #define ENABLE_MOTION_CONTROL */ - -/* Enable to have option to hide not needed gases from dive views */ -/* #define ENABLE_UNUSED_GAS_HIDING */ - -/* Enable to have the new T3 profile view available */ -/* #define ENABLE_T3_PROFILE_VIEW */ - -/* Enable to have PPO2 adjustments in T3 sensor view during dive simulation */ -/* #define ENABLE_T3_PPO_SIM */ - -#endif diff -r 87bee7cc77b3 -r cc542448fb28 Discovery/Inc/data_exchange_main.h --- a/Discovery/Inc/data_exchange_main.h Mon Nov 01 12:39:34 2021 +0100 +++ b/Discovery/Inc/data_exchange_main.h Fri Aug 19 11:30:24 2022 +0200 @@ -45,7 +45,7 @@ void DataEX_copy_to_LifeData(_Bool *modeChangeFlag); void DataEX_copy_to_deco(void); void DateEx_copy_to_dataOut(void); -void DataEX_merge_deviceData(void); +void DataEX_merge_devicedata(void); uint32_t DataEX_lost_connection_count(void); void DataEX_control_connection_while_asking_for_sleep(void); uint8_t DataEX_check_RTE_version__needs_update(void); @@ -56,4 +56,6 @@ uint16_t DataEX_debug_data(uint16_t *dataOut20x5); +void DataEX_setExtInterface_Cmd(uint16_t Cmd); + #endif /* DATA_EXCHANGE_MAIN_H */ diff -r 87bee7cc77b3 -r cc542448fb28 Discovery/Inc/t7.h --- a/Discovery/Inc/t7.h Mon Nov 01 12:39:34 2021 +0100 +++ b/Discovery/Inc/t7.h Fri Aug 19 11:30:24 2022 +0200 @@ -49,6 +49,9 @@ #ifdef ENABLE_BOTTLE_SENSOR LCC_BottleBar, #endif +#ifdef ENABLE_PSCR_MODE + LCC_SimPpo2, +#endif LLC_END } customview_llc_t; @@ -70,6 +73,7 @@ void init_t7_compass(void); uint8_t t7_GetEnabled_customviews(); +uint8_t t7_customview_disabled(uint8_t view); /* void t7c_refresh(uint32_t FramebufferStartAddress); diff -r 87bee7cc77b3 -r cc542448fb28 Discovery/Inc/tHome.h --- a/Discovery/Inc/tHome.h Mon Nov 01 12:39:34 2021 +0100 +++ b/Discovery/Inc/tHome.h Fri Aug 19 11:30:24 2022 +0200 @@ -71,6 +71,7 @@ CVIEW_Hello, CVIEW_CompassDebug, CVIEW_SummaryOfLeftCorner, + CVIEW_Charger, CVIEW_END, CVIEW_T3_Decostop, CVIEW_T3_TTS, diff -r 87bee7cc77b3 -r cc542448fb28 Discovery/Inc/tMenuEditXtra.h --- a/Discovery/Inc/tMenuEditXtra.h Mon Nov 01 12:39:34 2021 +0100 +++ b/Discovery/Inc/tMenuEditXtra.h Fri Aug 19 11:30:24 2022 +0200 @@ -33,5 +33,6 @@ void openEdit_Xtra(uint8_t line); void refresh_CompassHeading(void); +void refresh_CO2Data(void); #endif /* TMENU_EDIT_XTRA_H */ diff -r 87bee7cc77b3 -r cc542448fb28 Discovery/Inc/tStructure.h --- a/Discovery/Inc/tStructure.h Mon Nov 01 12:39:34 2021 +0100 +++ b/Discovery/Inc/tStructure.h Fri Aug 19 11:30:24 2022 +0200 @@ -195,10 +195,13 @@ #define StMXTRA_CompassHeading _MB(2,4,2,1,0) /* SURFACE MODE */ - #define StMXTRA_ScrubTimer_Max_Minutes _MB(2,4,1,1,0) - #define StMXTRA_ScrubTimer_Reset _MB(2,4,2,1,0) - #define StMXTRA_ScrubTimer_OP_Mode _MB(2,4,3,1,0) - +#define StMXTRA_ScrubTimer_Max_Minutes _MB(2,4,1,1,0) +#define StMXTRA_ScrubTimer_Reset _MB(2,4,2,1,0) +#define StMXTRA_ScrubTimer_OP_Mode _MB(2,4,3,1,0) +#define StMXTRA_PSCR_O2_Drop _MB(2,4,4,1,0) +#define StMXTRA_PSCR_LUNG_RATIO _MB(2,4,5,1,0) +#define StMXTRA_CO2_Sensor _MB(2,4,6,1,0) +#define StMXTRA_CO2_Sensor_Calib _MB(2,4,6,2,0) /* PAGE 5 */ #define StMDECO _MB(2,5,0,0,0) @@ -216,12 +219,13 @@ /* PAGE 5 EDIT FIELD CONTENT */ #define StMDECO1_OC _MB(2,5,1,1,0) #define StMDECO1_CC _MB(2,5,1,2,0) -#define StMDECO1_Apnea _MB(2,5,1,3,0) -#define StMDECO1_Gauge _MB(2,5,1,4,0) +#define StMDECO1_Apnea _MB(2,5,1,3,0) +#define StMDECO1_Gauge _MB(2,5,1,4,0) +#define StMDECO1_PSCR _MB(2,5,1,5,0) #define StMDECO2_CCRmode _MB(2,5,2,1,0) #define StMDECO3_PPO2Max _MB(2,5,3,1,0) -#define StMDECO4_SafetyStop _MB(2,5,4,1,0) +#define StMDECO4_SafetyStop _MB(2,5,4,1,0) #define StMDECO5_FUTURE _MB(2,5,5,1,0) #define StMDECO6_SALINITY _MB(2,5,6,1,0) @@ -310,7 +314,8 @@ #define StMSYS5_RebootMainCPU _MB(2,8,5,9,0) #define StMSYS5_ScreenTest _MB(2,8,5,10,0) #define StMSYS5_SetFactoryBC _MB(2,8,5,11,0) -#define StMSYS5_SetSampleIndx _MB(2,8,5,12,0) +#define StMSYS5_ResetBluetooth _MB(2,8,5,12,0) +#define StMSYS5_SetSampleIndx _MB(2,8,5,13,0) /* PAGE 9 */ diff -r 87bee7cc77b3 -r cc542448fb28 Discovery/Inc/text_multilanguage.h --- a/Discovery/Inc/text_multilanguage.h Mon Nov 01 12:39:34 2021 +0100 +++ b/Discovery/Inc/text_multilanguage.h Fri Aug 19 11:30:24 2022 +0200 @@ -71,10 +71,11 @@ TXT_Temperature, TXT_FutureTTS, TXT_Gas, - TXT_Time, + TXT_ChargeHour, TXT_Date, TXT_Format, TXT_Warning, + TXT_Charging, TXT_o2Sensors, TXT_Brightness, TXT_Cave, @@ -119,6 +120,7 @@ TXT_ClosedCircuit, TXT_Apnoe, TXT_Gauge, + TXT_PSClosedCircuit, TXT_Sensor, TXT_FixedSP, TXT_Decoparameters, @@ -141,6 +143,10 @@ TXT_ScrubTimeReset, TXT_ScrubTimeMode, TXT_Percent, + TXT_PSCRO2Drop, + TXT_PSCRLungRatio, + TXT_SimPpo2, + TXT_CO2Sensor, /* */ TXT_END, @@ -308,6 +314,7 @@ TXT2BYTE_Maintenance, TXT2BYTE_SetBatteryCharge, TXT2BYTE_SetFactoryDefaults, + TXT2BYTE_ResetBluetooth, TXT2BYTE_SetSampleIndex, TXT2BYTE_Reboot, TXT2BYTE_ButtonLeft, @@ -335,6 +342,8 @@ TXT2BYTE_Normal, TXT2BYTE_Maximum, + TXT2BYTE_CheckSettings, + TXT2BYTE_END }; diff -r 87bee7cc77b3 -r cc542448fb28 Discovery/Src/base.c --- a/Discovery/Src/base.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Discovery/Src/base.c Fri Aug 19 11:30:24 2022 +0200 @@ -507,6 +507,7 @@ { DoDisplayRefresh = 0; + updateSetpointStateUsed(); if(stateUsed == stateSimGetPointer()) { simulation_UpdateLifeData(1); @@ -588,8 +589,6 @@ case BaseHome: case BaseMenu: case BaseInfo: - updateSetpointStateUsed(); - DateEx_copy_to_dataOut(); DataEX_copy_to_LifeData(&modeChange); //foto session :-) stateRealGetPointerWrite()->lifeData.battery_charge = 99; @@ -769,17 +768,20 @@ } } else if ((status.page == PageDive) && (status.line != 0)) { - if (pSettings->extraDisplay == EXTRADISPLAY_BIGFONT) + if(get_globalState() == StDMENU) { - pSettings->design = 3; - if(pSettings->MotionDetection == MOTION_DETECT_SECTOR) + if (pSettings->extraDisplay == EXTRADISPLAY_BIGFONT) { - DefineSectorCount(CUSTOMER_DEFINED_VIEWS); - MapCVToSector(); + pSettings->design = 3; + if(pSettings->MotionDetection == MOTION_DETECT_SECTOR) + { + DefineSectorCount(CUSTOMER_DEFINED_VIEWS); + MapCVToSector(); + } } + else if (pSettings->extraDisplay == EXTRADISPLAY_DECOGAME) + pSettings->design = 4; } - else if (pSettings->extraDisplay == EXTRADISPLAY_DECOGAME) - pSettings->design = 4; set_globalState(StD); } else @@ -1151,6 +1153,13 @@ /* important levelAmbient 300 - 1200 */ levelAmbient = 10 * pStateReal->lifeData.ambient_light_level; + if((pStateReal->chargeStatus == CHARGER_running) || (pStateReal->chargeStatus == CHARGER_lostConnection)) + { + levelMax = 1000; + levelMin = 500; + } + else + { switch( pSettings->brightness + blBoost) { case 0: /* Cave */ @@ -1192,6 +1201,7 @@ // wasLostConnection = 0; } // } + } if(levelAmbient > levelActual) levelActual += levelUpStep_100ms; @@ -1203,8 +1213,9 @@ levelActual = levelMax; else if(levelActual < levelMin) + { levelActual = levelMin; - + } // sConfig.Pulse = levelActual / 20; sConfig.Pulse = (levelMin + ((levelMax - levelMin)/2)) / 20; // added 170306 @@ -1212,8 +1223,8 @@ if(sConfig.Pulse > 600) sConfig.Pulse = 600; else - if(sConfig.Pulse < 100) - sConfig.Pulse = 100; + if(sConfig.Pulse < 25) + sConfig.Pulse = 25; HAL_TIM_PWM_ConfigChannel(&TimBacklightHandle, &sConfig, TIM_BACKLIGHT_CHANNEL); HAL_TIM_PWM_Start(&TimBacklightHandle, TIM_BACKLIGHT_CHANNEL); @@ -1716,24 +1727,37 @@ switch(status.base) { case BaseHome: - // added hw 161027 - if(!(stateRealGetPointer()->warnings.lowBattery) && (stateRealGetPointer()->lifeData.battery_charge > 9)) + /* The RTE will mark a charge value as suspect after startup. Main know the update condition and may confirm that the value is most likely valid */ + // if(!(stateRealGetPointer()->warnings.lowBattery) && ((stateRealGetPointer()->lifeData.battery_charge > 9) || (wasFirmwareUpdateCheckBattery))) { - stateRealGetPointerWrite()->lastKnownBatteryPercentage = stateRealGetPointer()->lifeData.battery_charge; + if(stateRealGetPointer()->lifeData.battery_charge < 0.0) + { + if(fabs(stateRealGetPointerWrite()->lastKnownBatteryPercentage - fabs(stateRealGetPointer()->lifeData.battery_charge)) < 1.0) + { + setBatteryPercentage(settingsGetPointer()->lastKnownBatteryPercentage); /* confirm that value provided by RTE is valid (maybe reset happened) */ + } + } + else + { + if(!(stateRealGetPointer()->warnings.lowBattery) && (stateRealGetPointer()->lifeData.battery_charge > 9)) + { + stateRealGetPointerWrite()->lastKnownBatteryPercentage = stateRealGetPointer()->lifeData.battery_charge; + } + } } - else if((wasFirmwareUpdateCheckBattery) && (timeout_in_seconds > 3)) + if((wasFirmwareUpdateCheckBattery) && (timeout_in_seconds > 3)) { wasFirmwareUpdateCheckBattery = 0; setButtonResponsiveness(settingsGetPointer()->ButtonResponsiveness); // added 170306 if( (settingsGetPointer()->lastKnownBatteryPercentage > 0) - && (settingsGetPointer()->lastKnownBatteryPercentage <= 100) + && (settingsGetPointer()->lastKnownBatteryPercentage <= 101.0) && (stateRealGetPointer()->warnings.lowBattery)) { setBatteryPercentage(settingsGetPointer()->lastKnownBatteryPercentage); } } // stuff before and new @161121 CCR-sensor limit 10 minutes - if((settingsGetPointer()->dive_mode == DIVEMODE_CCR) && (settingsGetPointer()->CCR_Mode == CCRMODE_Sensors)) + if(isLoopMode(settingsGetPointer()->dive_mode) && (settingsGetPointer()->CCR_Mode == CCRMODE_Sensors)) { timeout_limit_Surface_in_seconds = settingsGetPointer()->timeoutSurfacemodeWithSensors; } diff -r 87bee7cc77b3 -r cc542448fb28 Discovery/Src/check_warning.c --- a/Discovery/Src/check_warning.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Discovery/Src/check_warning.c Fri Aug 19 11:30:24 2022 +0200 @@ -128,7 +128,7 @@ /* Private functions ---------------------------------------------------------*/ static int8_t check_fallback(SDiveState * pDiveState) { - if(fallback && ((pDiveState->mode != MODE_DIVE) || (pDiveState->diveSettings.diveMode != DIVEMODE_CCR))) + if(fallback && ((pDiveState->mode != MODE_DIVE) || (!isLoopMode(pDiveState->diveSettings.diveMode)))) fallback = 0; pDiveState->warnings.fallback = fallback; @@ -181,7 +181,7 @@ pDiveState->warnings.sensorOutOfBounds[1] = 0; pDiveState->warnings.sensorOutOfBounds[2] = 0; - if((pDiveState->diveSettings.diveMode == DIVEMODE_CCR) && (pDiveState->diveSettings.CCR_Mode == CCRMODE_Sensors)) + if(isLoopMode(pDiveState->diveSettings.diveMode) && (pDiveState->diveSettings.CCR_Mode == CCRMODE_Sensors)) if(settingsGetPointer()->ppo2sensors_source == O2_SENSOR_SOURCE_OPTIC) { @@ -218,7 +218,7 @@ betterGasIdLocal = pLifeData->actualGas.GasIdInSettings; bestGasDepth = 255; - if(pDiveSettings->diveMode == DIVEMODE_CCR) + if(isLoopMode(pDiveSettings->diveMode)) gasIdOffset = NUM_OFFSET_DILUENT; else gasIdOffset = 0; @@ -285,33 +285,31 @@ { pDiveState->warnings.betterSetpoint = 0; betterSetpointId = 0; - - if((stateUsed->mode != MODE_DIVE) || (pDiveState->diveSettings.diveMode != DIVEMODE_CCR) || (pDiveState->diveSettings.CCR_Mode != CCRMODE_FixedSetpoint)) - { - return 0; - } - uint8_t bestSetpointDepth = 0; // travel the deeper, the better uint8_t betterSetpointIdLocal = 0; // nothing better - if(!actualLeftMaxDepth(pDiveState)) /* travel gases */ + + if((stateUsed->mode == MODE_DIVE) && (pDiveState->diveSettings.diveMode == DIVEMODE_CCR)) { - for(int i=1; i<=NUM_GASES; i++) + if(!actualLeftMaxDepth(pDiveState)) /* travel gases */ { - if( (pDiveState->diveSettings.setpoint[i].note.ub.active) - && (pDiveState->diveSettings.setpoint[i].depth_meter) - && (pDiveState->diveSettings.setpoint[i].depth_meter <= ( pDiveState->lifeData.depth_meter + 0.01f )) - && (pDiveState->diveSettings.setpoint[i].depth_meter >= bestSetpointDepth) - ) - { - betterSetpointIdLocal = i; - bestSetpointDepth = pDiveState->diveSettings.setpoint[i].depth_meter; - } - } - if((betterSetpointIdLocal) && (pDiveState->diveSettings.setpoint[betterSetpointIdLocal].setpoint_cbar != pDiveState->lifeData.actualGas.setPoint_cbar)) - { - betterSetpointId = betterSetpointIdLocal; - pDiveState->warnings.betterSetpoint = 1; + for(int i=1; i<=NUM_GASES; i++) + { + if( (pDiveState->diveSettings.setpoint[i].note.ub.active) + && (pDiveState->diveSettings.setpoint[i].depth_meter) + && (pDiveState->diveSettings.setpoint[i].depth_meter <= ( pDiveState->lifeData.depth_meter + 0.01f )) + && (pDiveState->diveSettings.setpoint[i].depth_meter >= bestSetpointDepth) + ) + { + betterSetpointIdLocal = i; + bestSetpointDepth = pDiveState->diveSettings.setpoint[i].depth_meter; + } + } + if((betterSetpointIdLocal) && (pDiveState->diveSettings.setpoint[betterSetpointIdLocal].setpoint_cbar != pDiveState->lifeData.actualGas.setPoint_cbar)) + { + betterSetpointId = betterSetpointIdLocal; + pDiveState->warnings.betterSetpoint = 1; + } } } return pDiveState->warnings.betterSetpoint; @@ -350,7 +348,7 @@ static int8_t check_Battery(SDiveState * pDiveState) { - if(pDiveState->lifeData.battery_charge < 10) + if((pDiveState->lifeData.battery_charge > 0) && (pDiveState->lifeData.battery_charge < 10)) pDiveState->warnings.lowBattery = 1; else pDiveState->warnings.lowBattery = 0; diff -r 87bee7cc77b3 -r cc542448fb28 Discovery/Src/data_central.c --- a/Discovery/Src/data_central.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Discovery/Src/data_central.c Fri Aug 19 11:30:24 2022 +0200 @@ -71,6 +71,7 @@ #include "ostc.h" // for button adjust on hw testboard 1 #include "tCCR.h" #include "crcmodel.h" +#include "configuration.h" static SDiveState stateReal = { 0 }; SDiveState stateSim = { 0 }; @@ -316,21 +317,29 @@ void createDiveSettings(void) { + int i; SSettings* pSettings = settingsGetPointer(); - setActualGasFirst(&stateReal.lifeData); - stateReal.diveSettings.compassHeading = pSettings->compassBearing; stateReal.diveSettings.ascentRate_meterperminute = 10; stateReal.diveSettings.diveMode = pSettings->dive_mode; stateReal.diveSettings.CCR_Mode = pSettings->CCR_Mode; - if(stateReal.diveSettings.diveMode == DIVEMODE_CCR) + if((stateReal.diveSettings.diveMode == DIVEMODE_PSCR) && (stateReal.diveSettings.CCR_Mode == CCRMODE_FixedSetpoint)) + { + /* TODO: update selection of sensor used on/off (currently sensor/fixpoint). As PSCR has no fixed setpoint change to simulated ppo2 if sensors are not active */ + stateReal.diveSettings.CCR_Mode = CCRMODE_Simulation; + } + + if(isLoopMode(stateReal.diveSettings.diveMode)) stateReal.diveSettings.ccrOption = 1; else stateReal.diveSettings.ccrOption = 0; memcpy(stateReal.diveSettings.gas, pSettings->gas,sizeof(pSettings->gas)); memcpy(stateReal.diveSettings.setpoint, pSettings->setpoint,sizeof(pSettings->setpoint)); + + setActualGasFirst(&stateReal.lifeData); + stateReal.diveSettings.gf_high = pSettings->GF_high; stateReal.diveSettings.gf_low = pSettings->GF_low; stateReal.diveSettings.input_next_stop_increment_depth_bar = ((float)pSettings->stop_increment_depth_meter) / 10.0f; @@ -341,13 +350,24 @@ stateReal.diveSettings.ppo2sensors_deactivated = pSettings->ppo2sensors_deactivated; stateReal.diveSettings.future_TTS_minutes = pSettings->future_TTS; + stateReal.diveSettings.pscr_lung_ratio = pSettings->pscr_lung_ratio; + stateReal.diveSettings.pscr_o2_drop = pSettings->pscr_o2_drop; + + if(stateReal.diveSettings.diveMode == DIVEMODE_PSCR) + { + for(i=0; i<5; i++) + { + stateReal.diveSettings.decogaslist[i].pscr_factor = 1.0 / stateReal.diveSettings.pscr_lung_ratio * stateReal.diveSettings.pscr_o2_drop; + } + } + decom_CreateGasChangeList(&stateReal.diveSettings, &stateReal.lifeData); // decogaslist stateReal.diveSettings.internal__pressure_first_stop_ambient_bar_as_upper_limit_for_gf_low_otherwise_zero = 0; /* for safety */ stateReal.diveSettings.input_second_to_last_stop_depth_bar = stateReal.diveSettings.last_stop_depth_bar + stateReal.diveSettings.input_next_stop_increment_depth_bar; /* and the proper calc */ - for(int i = 1; i <10; i++) + for(i = 1; i <10; i++) { if(stateReal.diveSettings.input_next_stop_increment_depth_bar * i > stateReal.diveSettings.last_stop_depth_bar) { @@ -389,9 +409,11 @@ } + + void updateSetpointStateUsed(void) { - if(stateUsed->diveSettings.diveMode != DIVEMODE_CCR) + if(!isLoopMode(stateUsed->diveSettings.diveMode)) { stateUsedWrite->lifeData.actualGas.setPoint_cbar = 0; stateUsedWrite->lifeData.ppO2 = decom_calc_ppO2(stateUsed->lifeData.pressure_ambient_bar, &stateUsed->lifeData.actualGas); @@ -402,7 +424,17 @@ { stateUsedWrite->lifeData.actualGas.setPoint_cbar = get_ppO2SensorWeightedResult_cbar(); } - +#ifdef ENABLE_PSCR_MODE + if(stateUsed->diveSettings.diveMode == DIVEMODE_PSCR) /* calculate a ppO2 value based on assumptions ( transfered approach from hwos code) */ + { + stateUsedWrite->lifeData.ppo2Simulated_bar = decom_calc_SimppO2_O2based(stateUsed->lifeData.pressure_ambient_bar, stateReal.diveSettings.gas[stateUsed->lifeData.actualGas.GasIdInSettings].oxygen_percentage, stateUsed->lifeData.actualGas.pscr_factor); + if(stateUsed->diveSettings.CCR_Mode == CCRMODE_Simulation) + { + stateUsedWrite->lifeData.actualGas.setPoint_cbar = stateUsedWrite->lifeData.ppo2Simulated_bar * 100; + } + } +#endif + /* limit calculated value to the physically possible if needed */ if((stateUsed->lifeData.pressure_ambient_bar * 100) < stateUsed->lifeData.actualGas.setPoint_cbar) stateUsedWrite->lifeData.ppO2 = stateUsed->lifeData.pressure_ambient_bar; else @@ -417,7 +449,7 @@ uint8_t gasId = 0; uint8_t setpoint_cbar = 0; - if(pSettings->dive_mode == DIVEMODE_CCR) + if(isLoopMode(pSettings->dive_mode)) { setpoint_cbar = pSettings->setpoint[1].setpoint_cbar; start = NUM_OFFSET_DILUENT+1; @@ -449,6 +481,7 @@ lifeData->actualGas.helium_percentage =0; lifeData->actualGas.setPoint_cbar = 0; lifeData->actualGas.change_during_ascent_depth_meter_otherwise_zero = 0; + lifeData->actualGas.AppliedDiveMode = stateUsed->diveSettings.diveMode; } @@ -466,8 +499,9 @@ lifeData->actualGas.helium_percentage = pSettings->gas[gasId].helium_percentage; lifeData->actualGas.setPoint_cbar = setpoint_cbar; lifeData->actualGas.change_during_ascent_depth_meter_otherwise_zero = 0; - - if((pSettings->dive_mode == DIVEMODE_CCR) && (gasId > NUM_OFFSET_DILUENT)) + lifeData->actualGas.AppliedDiveMode = stateUsed->diveSettings.diveMode; + lifeData->actualGas.pscr_factor = 1.0 / pSettings->pscr_lung_ratio * pSettings->pscr_o2_drop; + if(isLoopMode(pSettings->dive_mode) && (gasId > NUM_OFFSET_DILUENT)) lifeData->lastDiluent_GasIdInSettings = gasId; } @@ -525,7 +559,7 @@ lifeData->actualGas.helium_percentage = helium; lifeData->actualGas.setPoint_cbar = setpoint_cbar; lifeData->actualGas.change_during_ascent_depth_meter_otherwise_zero = 0; - + lifeData->actualGas.AppliedDiveMode = stateUsed->diveSettings.diveMode; } void setButtonResponsiveness(uint8_t *ButtonSensitivyList) @@ -814,3 +848,12 @@ return compass_compensated; } +uint8_t isLoopMode(uint8_t Mode) +{ + uint8_t retVal = 0; + if((Mode == DIVEMODE_CCR) || (Mode == DIVEMODE_PSCR)) + { + retVal = 1; + } + return retVal; +} diff -r 87bee7cc77b3 -r cc542448fb28 Discovery/Src/data_exchange_main.c --- a/Discovery/Src/data_exchange_main.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Discovery/Src/data_exchange_main.c Fri Aug 19 11:30:24 2022 +0200 @@ -72,7 +72,7 @@ #include "buehlmann.h" #include "externLogbookFlash.h" -//#define TESTBENCH +/* #define TESTBENCH */ /* Exported variables --------------------------------------------------------*/ static uint8_t wasPowerOn = 0; @@ -94,6 +94,8 @@ static uint8_t DeviceDataUpdated = 0; +static uint16_t externalInterface_Cmd = 0; + /* Private types -------------------------------------------------------------*/ #define UNKNOWN_TIME_HOURS 1 #define UNKNOWN_TIME_MINUTES 0 @@ -181,12 +183,12 @@ if(getDeviceDataWasSend) { dataOut.getDeviceDataNow = 0; - requestNecessary.ub.devicedata = 1; } getDeviceDataWasSend = 0; if(dataOut.getDeviceDataNow) { getDeviceDataWasSend = 1; + requestNecessary.ub.devicedata = 1; } if(setEndDiveWasSend) @@ -203,40 +205,39 @@ if(setAccidentFlagWasSend) { dataOut.setAccidentFlag = 0; - requestNecessary.ub.accident = 1; } setAccidentFlagWasSend = 0; if(dataOut.setAccidentFlag) { setAccidentFlagWasSend = 1; + requestNecessary.ub.accident = 1; } if(setDateWasSend) { dataOut.setDateNow = 0; - requestNecessary.ub.date = 1; } setDateWasSend = 0; if(dataOut.setDateNow) { setDateWasSend = 1; + requestNecessary.ub.date = 1; } if(setTimeWasSend) { dataOut.setTimeNow = 0; - requestNecessary.ub.time = 1; } setTimeWasSend = 0; if(dataOut.setTimeNow) { setTimeWasSend = 1; + requestNecessary.ub.time = 1; } if(calibrateCompassWasSend) { dataOut.calibrateCompassNow = 0; - requestNecessary.ub.compass = 1; } calibrateCompassWasSend = 0; if(dataOut.calibrateCompassNow) @@ -247,22 +248,23 @@ if(clearDecoWasSend) { dataOut.clearDecoNow = 0; - requestNecessary.ub.clearDeco = 1; + requestNecessary.ub.compass = 1; } if(dataOut.clearDecoNow) { clearDecoWasSend = 1; + requestNecessary.ub.clearDeco = 1; } if(setButtonSensitivityWasSend) { dataOut.setButtonSensitivityNow = 0; - requestNecessary.ub.button = 1; } setButtonSensitivityWasSend = 0; if(dataOut.setButtonSensitivityNow) { setButtonSensitivityWasSend = 1; + requestNecessary.ub.button = 1; } } @@ -389,6 +391,32 @@ dataOut.data.offsetPressureSensor_mbar = settings->offsetPressure_mbar; dataOut.data.offsetTemperatureSensor_centiDegree = settings->offsetTemperature_centigrad; + + + if(settings->ppo2sensors_source == O2_SENSOR_SOURCE_ANALOG) + { + externalInterface_Cmd |= EXT_INTERFACE_ADC_ON | EXT_INTERFACE_33V_ON; + } + +#ifdef ENABLE_SENTINEL_MODE + if(settings->ppo2sensors_source == O2_SENSOR_SOURCE_SENTINEL) + { + externalInterface_Cmd |= EXT_INTERFACE_33V_ON | EXT_INTERFACE_UART_SENTINEL; + externalInterface_Cmd &= (~EXT_INTERFACE_ADC_ON); + } +#endif + + if(settings->ext_uart_protocol) + { + externalInterface_Cmd |= (settings->ext_uart_protocol << 8); + } + if(settings->co2_sensor_active) + { + externalInterface_Cmd |= EXT_INTERFACE_33V_ON | EXT_INTERFACE_UART_CO2; + } + dataOut.data.externalInterface_Cmd = externalInterface_Cmd; + externalInterface_Cmd = 0; + if((hardwareDataGetPointer()->primarySerial <= 32) || (((hardwareDataGetPointer()->primarySerial == 72) && (hardwareDataGetPointer()->secondarySerial == 15)))) { dataOut.revisionHardware = 0x00; @@ -773,9 +801,14 @@ void DataEX_copy_to_LifeData(_Bool *modeChangeFlag) { + static uint16_t getDeviceDataAfterStartOfMainCPU = 20; + SDiveState *pStateReal = stateRealGetPointerWrite(); - static uint16_t getDeviceDataAfterStartOfMainCPU = 20; uint8_t idx; + float meter = 0; + SSettings *pSettings; + + // wireless - �ltere daten aufr�umen #if 0 @@ -836,23 +869,46 @@ } } - /* new 151207 hw */ - if(requestNecessary.uw != 0) + if((requestNecessary.uw != 0) && (dataIn.confirmRequest.uw != 0)) { if(((dataIn.confirmRequest.uw) & CRBUTTON) != 0) { requestNecessary.ub.button = 0; } + if(((dataIn.confirmRequest.uw) & CRCLEARDECO) != 0) + { + requestNecessary.ub.clearDeco = 0; + } + if(((dataIn.confirmRequest.uw) & CRDATE) != 0) + { + requestNecessary.ub.date = 0; + } + if(((dataIn.confirmRequest.uw) & CRTIME) != 0) + { + requestNecessary.ub.time = 0; + } + if(((dataIn.confirmRequest.uw) & CRCOMPASS) != 0) + { + requestNecessary.ub.compass = 0; + } + if(((dataIn.confirmRequest.uw) & CRDEVICEDATA) != 0) + { + requestNecessary.ub.devicedata = 0; + } + if(((dataIn.confirmRequest.uw) & CRBATTERY) != 0) + { + requestNecessary.ub.batterygauge = 0; + } + if(((dataIn.confirmRequest.uw) & CRACCIDENT) != 0) + { + requestNecessary.ub.accident = 0; + } - if(requestNecessary.ub.button == 1) + if(requestNecessary.ub.button == 1) /* send button values to RTE */ { setButtonResponsiveness(settingsGetPointer()->ButtonResponsiveness); } } - requestNecessary.uw = 0; // clear all - - float meter = 0; - SSettings *pSettings; /* uint8_t IAmStolenPleaseKillMe; */ @@ -883,7 +939,7 @@ { for(idx = 0; idx < 3; idx++) { - pStateReal->lifeData.sensorVoltage_mV[idx] = dataIn.data[0].extADC_voltage[idx]; + pStateReal->lifeData.sensorVoltage_mV[idx] = dataIn.data[(dataIn.boolADCO2Data && DATA_BUFFER_ADC)].extADC_voltage[idx]; if(pStateReal->lifeData.sensorVoltage_mV[idx] < IGNORE_O2_VOLTAGE_LEVEL_MV) { pStateReal->lifeData.sensorVoltage_mV[idx] = 0.0; @@ -909,7 +965,6 @@ pStateReal->lifeData.dateBinaryFormat = dataIn.data[dataIn.boolTimeData].localtime_rtc_dr; pStateReal->lifeData.timeBinaryFormat = dataIn.data[dataIn.boolTimeData].localtime_rtc_tr; } - dataOut.setAccidentFlag = 0; if(pStateReal->data_old__lost_connection_to_slave == 0) { @@ -971,11 +1026,25 @@ pStateReal->lifeData.max_depth_meter = meter; } - if(dataIn.accidentFlags & ACCIDENT_DECOSTOP) - pStateReal->decoMissed_at_the_end_of_dive = 1; - if(dataIn.accidentFlags & ACCIDENT_CNS) - pStateReal->cnsHigh_at_the_end_of_dive = 1; - + if(requestNecessary.ub.clearDeco == 0) /* No "reset deco" is send to RTE ? */ + { + if(dataIn.accidentFlags & ACCIDENT_DECOSTOP) + { + pStateReal->decoMissed_at_the_end_of_dive = 1; + } + else + { + pStateReal->decoMissed_at_the_end_of_dive = 0; + } + if(dataIn.accidentFlags & ACCIDENT_CNS) + { + pStateReal->cnsHigh_at_the_end_of_dive = 1; + } + else + { + pStateReal->cnsHigh_at_the_end_of_dive = 0; + } + } pStateReal->lifeData.dive_time_seconds = (int32_t)dataIn.data[dataIn.boolTimeData].divetime_seconds; pStateReal->lifeData.dive_time_seconds_without_surface_time = (int32_t)dataIn.data[dataIn.boolTimeData].dive_time_seconds_without_surface_time; pStateReal->lifeData.counterSecondsShallowDepth = dataIn.data[dataIn.boolTimeData].counterSecondsShallowDepth; @@ -1030,6 +1099,10 @@ /* sensorErrors */ pStateReal->sensorErrorsRTE = dataIn.sensorErrors; + + /* data from CO2 sensor */ + pStateReal->lifeData.CO2_data.CO2_ppm = dataIn.data[(dataIn.boolADCO2Data && DATA_BUFFER_CO2)].CO2_ppm; + pStateReal->lifeData.CO2_data.signalStrength = dataIn.data[(dataIn.boolADCO2Data && DATA_BUFFER_CO2)].CO2_signalStrength; } /* apnea specials @@ -1205,3 +1278,10 @@ return retval; } + +void DataEX_setExtInterface_Cmd(uint16_t Cmd) +{ + externalInterface_Cmd = Cmd; + return; +} + diff -r 87bee7cc77b3 -r cc542448fb28 Discovery/Src/gfx_engine.c --- a/Discovery/Src/gfx_engine.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Discovery/Src/gfx_engine.c Fri Aug 19 11:30:24 2022 +0200 @@ -2754,7 +2754,14 @@ } // ----------------------------- char_truncated_Height = 0; - height_left = hgfx->Image->ImageHeight - (hgfx->WindowY0 + cfg->Ydelta); + if(!pSettings->FlipDisplay) + { + height_left = hgfx->Image->ImageHeight - (hgfx->WindowY0 + cfg->Ydelta); + } + else + { + height_left = (hgfx->WindowY1 - cfg->Ydelta); + } if(height_left < height) { char_truncated_Height = height - height_left; diff -r 87bee7cc77b3 -r cc542448fb28 Discovery/Src/logbook.c --- a/Discovery/Src/logbook.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Discovery/Src/logbook.c Fri Aug 19 11:30:24 2022 +0200 @@ -1002,7 +1002,7 @@ break; } firstgasid = i + 1; - if(header.diveMode == DIVEMODE_CCR) + if(isLoopMode(header.diveMode)) setPointLast = header.setpoint[0].setpoint_cbar; else setPointLast = 0; @@ -1166,6 +1166,10 @@ gas.setPoint_cbar = setPointVal; if(gasidVal > 0) { + if((gasidVal >= NUM_GASES) && (header.diveMode == DIVEMODE_PSCR)) /* in case gas switches the absolute gas ID is used => map to the 0..NUM_GASES index used in header */ + { + gasidVal -= NUM_GASES; + } gas.helium_percentage = header.gasordil[gasidVal - 1].helium_percentage; gas.nitrogen_percentage = 100 - gas.helium_percentage - header.gasordil[gasidVal - 1].oxygen_percentage; } @@ -1175,7 +1179,15 @@ gas.nitrogen_percentage = 100 - gas.helium_percentage - manualGasVal.percentageO2; } ambiant_pressure_bar =((float)(depthVal + header.surfacePressure_mbar))/1000; - ppO2 = decom_calc_ppO2(ambiant_pressure_bar, &gas ); + + if(header.diveMode == DIVEMODE_PSCR) + { + ppO2 = decom_calc_SimppO2(ambiant_pressure_bar, &gas); + } + else /* open circuit calculation */ + { + ppO2 = decom_calc_ppO2(ambiant_pressure_bar, &gas); + } ppo2[iNum] = (uint16_t) ( ppO2 * 100); } @@ -1297,7 +1309,14 @@ logbook_SetCompartmentDesaturation(pStateReal); logbook_SetLastStop(pStateReal->diveSettings.last_stop_depth_bar); gheader.batteryVoltage = pStateReal->lifeData.battery_voltage * 1000; - gheader.batteryCharge = pStateReal->lifeData.battery_charge; + if(pStateReal->lifeData.battery_charge > 0.0) + { + gheader.batteryCharge = pStateReal->lifeData.battery_charge; + } + else + { + gheader.batteryCharge = 0.0; + } logbook_EndDive(); bDiveMode = 0; } else diff -r 87bee7cc77b3 -r cc542448fb28 Discovery/Src/settings.c --- a/Discovery/Src/settings.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Discovery/Src/settings.c Fri Aug 19 11:30:24 2022 +0200 @@ -36,10 +36,12 @@ #include "t7.h" #include "data_central.h" +static uint8_t settingsWarning = 0; /* Active if setting values have been corrected */ + SSettings Settings; const uint8_t RTErequiredHigh = 2; -const uint8_t RTErequiredLow = 7; +const uint8_t RTErequiredLow = 9; const uint8_t FONTrequiredHigh = 1; const uint8_t FONTrequiredLow = 0; @@ -57,16 +59,16 @@ const SFirmwareData firmware_FirmwareData __attribute__( (section(".firmware_firmware_data")) ) = { .versionFirst = 1, - .versionSecond = 5, - .versionThird = 8, - .versionBeta = 1, + .versionSecond = 6, + .versionThird = 0, + .versionBeta = 0, /* 4 bytes with trailing 0 */ .signature = "mh", - .release_year = 21, - .release_month = 04, - .release_day = 26, + .release_year = 22, + .release_month = 8, + .release_day = 19, .release_sub = 0, /* max 48 with trailing 0 */ @@ -85,10 +87,10 @@ * There might even be entries with fixed values that have no range */ const SSettings SettingsStandard = { - .header = 0xFFFF001F, + .header = 0xFFFF0022, .warning_blink_dsec = 8 * 2, .lastDiveLogId = 0, - .logFlashNextSampleStartAddress = 0, + .logFlashNextSampleStartAddress = SAMPLESTART, .gas[0].oxygen_percentage = 21, .gas[1].oxygen_percentage = 21, @@ -219,7 +221,7 @@ .ppO2_min = 15, .CNS_max = 90, .ascent_MeterPerMinute_max = 30, - .ascent_MeterPerMinute_showGraph = 7, + .ascent_MeterPerMinute_showGraph = 30, .future_TTS = 5, .GF_high = 85, .GF_low = 30, @@ -268,13 +270,9 @@ .bluetoothActive = 0, .safetystopDepth = 5, .updateSettingsAllowedFromHeader = 0xFFFF0002, - .scooterControl = 0, - .scooterDrag = 2, - .scooterLoad = 2, - .scooterNumberOfBatteries = 1, - .scooterBattSize = 760, - .scooterSPARE1[0] = 0, - .scooterSPARE2[0] = 0, + .pscr_lung_ratio = 10, + .pscr_o2_drop = 4, + .co2_sensor_active = 0, .ppo2sensors_deactivated = 0, .tX_colorscheme = 0, .tX_userselectedLeftLowerCornerPrimary = LLC_Temperature, @@ -371,8 +369,6 @@ SSettings* pSettings = settingsGetPointer(); const SSettings* pStandard = settingsGetPointerStandard(); - pSettings->scooterControl = 0; - /* Pointing to the old header data => set new data depending on what had been added since last version */ switch(pSettings->header) { @@ -433,15 +429,7 @@ case 0xFFFF000F: pSettings->compassBearing = 0; // no break - case 0xFFFF0010: - pSettings->scooterDrag = 2; - pSettings->scooterLoad = 2; - pSettings->scooterSPARE1[0] = 0; - pSettings->scooterSPARE2[0] = 0; - // no break case 0xFFFF0011: - pSettings->scooterNumberOfBatteries = 1; - pSettings->scooterBattSize = 760; pSettings->lastKnownBatteryPercentage = 0; // no break case 0xFFFF0012: @@ -496,7 +484,24 @@ pSettings->ppo2sensors_calibCoeff[0] = 0.0; pSettings->ppo2sensors_calibCoeff[1] = 0.0; pSettings->ppo2sensors_calibCoeff[2] = 0.0; + pSettings->amPMTime = 0; // no break + case 0xFFFF001E: + pSettings->autoSetpoint = 0; + pSettings->scrubTimerMax = 0; + pSettings->scrubTimerCur = 0; + pSettings->scrubTimerMode = SCRUB_TIMER_OFF; + // no break + case 0xFFFF001F: + pSettings->pscr_lung_ratio = 10; + pSettings->pscr_o2_drop = 4; + // no break + case 0xFFFF0020: + pSettings->co2_sensor_active = 0; + // no break; + case 0xFFFF0021: + pSettings->ext_uart_protocol = 0; + // no break; default: pSettings->header = pStandard->header; break; // no break before!! @@ -536,6 +541,9 @@ uint8_t firstGasFoundOC = 0; uint8_t firstGasFoundCCR = 0; + + settingsWarning = 0; /* reset warning indicator */ + /* uint32_t header; */ @@ -564,7 +572,8 @@ if( (Settings.dive_mode != DIVEMODE_OC) && (Settings.dive_mode != DIVEMODE_CCR) && (Settings.dive_mode != DIVEMODE_Gauge) && - (Settings.dive_mode != DIVEMODE_Apnea) ) + (Settings.dive_mode != DIVEMODE_Apnea) && + (Settings.dive_mode != DIVEMODE_PSCR)) { Settings.dive_mode = DIVEMODE_OC; corrections++; @@ -618,9 +627,9 @@ } if(Settings.gas[i].note.ub.first) { - if(Settings.setpoint[i].note.ub.active != 1) + if(Settings.gas[i].note.ub.active != 1) { - Settings.setpoint[i].note.ub.active = 1; + Settings.gas[i].note.ub.active = 1; corrections++; } if(Settings.gas[i].note.ub.travel == 1) @@ -671,6 +680,7 @@ Settings.gas[1].note.ub.first = 1; Settings.gas[1].note.ub.travel = 0; Settings.gas[1].note.ub.deco = 0; + corrections++; } if(!firstGasFoundCCR) { @@ -678,6 +688,7 @@ Settings.gas[1 + NUM_GASES].note.ub.first = 1; Settings.gas[1 + NUM_GASES].note.ub.travel = 0; Settings.gas[1 + NUM_GASES].note.ub.deco = 0; + corrections++; } /* SSetpointLine setpoint[1 + NUM_GASES]; */ @@ -747,6 +758,7 @@ /* uint8_t CCR_Mode; */ if( (Settings.CCR_Mode != CCRMODE_Sensors) && + (Settings.CCR_Mode != CCRMODE_Simulation) && (Settings.CCR_Mode != CCRMODE_FixedSetpoint)) { Settings.CCR_Mode = CCRMODE_FixedSetpoint; @@ -1461,10 +1473,41 @@ Settings.scrubTimerMode = SCRUB_TIMER_OFF; corrections++; } + + if((Settings.pscr_lung_ratio > PSCR_MAX_LUNG_RATIO) || (Settings.pscr_lung_ratio < PSCR_MIN_LUNG_RATIO)) + { + Settings.pscr_lung_ratio = 10; + corrections++; + } + if(Settings.pscr_o2_drop > PSCR_MAX_O2_DROP) + { + Settings.pscr_o2_drop = 4; + corrections++; + } + + if(Settings.co2_sensor_active > 1) + { + Settings.co2_sensor_active = 0; + corrections++; + } + if(Settings.co2_sensor_active > UART_MAX_PROTOCOL) + { + Settings.ext_uart_protocol = 0; + corrections++; + } + + if(corrections) + { + settingsWarning = 1; + } + else + if(corrections > 255) - return 255; - else - return (uint8_t)corrections; + { + corrections = 255; + } + + return (uint8_t)corrections; } @@ -2921,3 +2964,13 @@ } } } + +void reset_SettingWarning() +{ + settingsWarning = 0; +} +inline uint8_t isSettingsWarning() +{ + return settingsWarning; +} + diff -r 87bee7cc77b3 -r cc542448fb28 Discovery/Src/show_logbook.c --- a/Discovery/Src/show_logbook.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Discovery/Src/show_logbook.c Fri Aug 19 11:30:24 2022 +0200 @@ -35,6 +35,7 @@ #include "unit.h" #include "configuration.h" #include "logbook_miniLive.h" +#include "text_multilanguage.h" #include #include @@ -515,16 +516,19 @@ switch(logbookHeader.diveMode) { case DIVEMODE_OC: - snprintf(text,20,"open circuit"); + snprintf(text,20,"%c",TXT_OpenCircuit); break; case DIVEMODE_CCR: - snprintf(text,20,"closed circuit"); + snprintf(text,20,"%c",TXT_ClosedCircuit); break; case DIVEMODE_Gauge: - snprintf(text,20,"Gauge"); + snprintf(text,20,"%c",TXT_Gauge); break; case DIVEMODE_Apnea: - snprintf(text,20,"Apnea"); + snprintf(text,20,"%c",TXT_Apnoe); + break; + case DIVEMODE_PSCR: + snprintf(text,20,"%c",TXT_PSClosedCircuit); break; } Gfx_write_label_var(hgfx, 30, 250,60, &FontT42,CLUT_GasSensor4,text); @@ -886,6 +890,10 @@ { SWindowGimpStyle wintemp; SWindowGimpStyle winsmal; + uint8_t gasWasUsed[NUM_GASES * 2]; + int16_t index = 0; + uint8_t loopMode = 0; + wintemp.left = 50; wintemp.right = 799 - wintemp.left; wintemp.top = 50; @@ -899,6 +907,40 @@ uint8_t gasdata[1000]; dataLength = logbook_readSampleData(StepBackwards, 1000, depthdata,gasdata, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + char msg[15]; + char gas_name[15]; + int j = 0; + + loopMode = isLoopMode(logbookHeader.diveMode); + + /* check if gas was used, independent from its active state */ + for(index = 0; index < NUM_GASES * 2; index++) + { + gasWasUsed[index] = 0; + } + for(index = 0; index < dataLength; index++) + { + if(loopMode) + { + if(gasdata[index] < NUM_GASES) /* the log entry starts with a ID in range 1..4 independend if diluent is used at start */ + { + gasdata[index] += NUM_GASES; + } + else + { + loopMode = 0; /* after the first gas change, no matter if diluent or bailout, the correct ID will be stored */ + } + } + if(gasdata[index] > 0) + { + gasWasUsed[gasdata[index]-1] = 1; /* The ID stored in the samples is starting with 1 (array[0] = gasID1) */ + } + else + { + gasWasUsed[0] = 1; + } + } + //--- print coordinate system & depth graph with gaschanges --- show_logbook_draw_depth_graph(hgfx, StepBackwards, &wintemp, 1, dataLength, depthdata, gasdata, NULL); @@ -906,21 +948,38 @@ winsmal.left = wintemp.right - 190; winsmal.right = winsmal.left + 150; - char msg[15]; - char gas_name[15]; - int j = 0; - for(int i = 4;i >= 0;i--) + loopMode = isLoopMode(logbookHeader.diveMode); + for(index = (2 * NUM_GASES) -1; index >= 0; index--) { - if(logbookHeader.gasordil[i].note.ub.active > 0) + if(gasWasUsed[index]) { j++; + if(j > 5) /* limit number of gases displayed to 5 */ + { + break; + } winsmal.top = wintemp.bottom - 5 - j * 26 ; winsmal.bottom = winsmal.top + 21 ; - uint8_t color = get_colour(i); + uint8_t color = get_colour(index); - print_gas_name(gas_name,15,logbookHeader.gasordil[i].oxygen_percentage,logbookHeader.gasordil[i].helium_percentage); - snprintf(msg,15,"G%i: %s",i + 1, gas_name); - //msg[10] = 0; + if(loopMode) + { + if(index < NUM_GASES) /* Switch to Bailout is not covered by log gas list */ + { + snprintf(gas_name,15,"Bailout"); + snprintf(msg,15,"G%d: %s",index +1, gas_name); + } + else + { + print_gas_name(gas_name,15,logbookHeader.gasordil[index-NUM_GASES].oxygen_percentage,logbookHeader.gasordil[index-NUM_GASES].helium_percentage); + snprintf(msg,15,"D%d: %s",index +1 - NUM_GASES, gas_name); + } + } + else + { + print_gas_name(gas_name,15,logbookHeader.gasordil[index].oxygen_percentage,logbookHeader.gasordil[index].helium_percentage); + snprintf(msg,15,"G%d: %s",index +1, gas_name); + } Gfx_write_label_var(hgfx, winsmal.left, winsmal.right,winsmal.top, &FontT24,color,msg); } } @@ -933,6 +992,26 @@ */ } +static uint8_t check_data_array_empty(uint16_t* pdata) +{ + uint8_t ret = 0; + uint8_t index = 0; + uint8_t emptyCnt = 0; + + for (index=0; index < 10; index++) /* read the first 10 data points. If all are 0 then the array is rated as empty */ + { + if(*(pdata+index) == 0) + { + emptyCnt++; + } + } + if(emptyCnt == 10) + { + ret = 1; + } + return ret; +} + static void show_logbook_logbook_show_log_page4(GFX_DrawCfgScreen *hgfx, uint8_t StepBackwards) { SWindowGimpStyle wintemp; SWindowGimpStyle winsmal; @@ -950,18 +1029,55 @@ uint16_t ppO2data[1000]; uint16_t sensor2[1000]; uint16_t sensor3[1000]; - uint16_t *setpoint = ppO2data; - uint16_t *sensor1 = ppO2data; + uint16_t *setpoint = ppO2data; + uint16_t *sensor1 = ppO2data; + uint8_t sensorDataAvailable[] = {0,0,0}; - if(logbookHeader.diveMode != DIVEMODE_CCR) + if(!isLoopMode(logbookHeader.diveMode)) dataLength = logbook_readSampleData(StepBackwards, 1000, depthdata,gasdata, NULL, ppO2data, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); else { - if(logbookHeader.CCRmode == CCRMODE_FixedSetpoint) - dataLength = logbook_readSampleData(StepBackwards, 1000, depthdata, gasdata, NULL, NULL, setpoint, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - else - dataLength = logbook_readSampleData(StepBackwards, 1000, depthdata, gasdata, NULL, NULL, NULL, sensor1, sensor2, sensor3, NULL, NULL, NULL, NULL, NULL); + switch(logbookHeader.CCRmode) + { + case CCRMODE_FixedSetpoint: + default: dataLength = logbook_readSampleData(StepBackwards, 1000, depthdata, gasdata, NULL, NULL, setpoint, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + break; + case CCRMODE_Sensors: dataLength = logbook_readSampleData(StepBackwards, 1000, depthdata, gasdata, NULL, NULL, NULL, sensor1, sensor2, sensor3, NULL, NULL, NULL, NULL, NULL); + if(!check_data_array_empty(sensor1)) + { + sensorDataAvailable[0] = 1; + } + if(!check_data_array_empty(sensor2)) + { + sensorDataAvailable[1] = 1; + } + if(!check_data_array_empty(sensor3)) + { + sensorDataAvailable[2] = 1; + } + if((logbookHeader.diveMode == DIVEMODE_PSCR) && (sensorDataAvailable[0] + sensorDataAvailable[1] + sensorDataAvailable[2] != 3)) /*insert sim data if not all three sensors are in use*/ + { + if(sensorDataAvailable[0] == 0) + { + logbook_readSampleData(StepBackwards, 1000, depthdata,gasdata, NULL, sensor1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + sensorDataAvailable[0] = 1; + } + else if(sensorDataAvailable[1] == 0) + { + logbook_readSampleData(StepBackwards, 1000, depthdata,gasdata, NULL, sensor2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + sensorDataAvailable[1] = 1; + } + else if(sensorDataAvailable[2] == 0) + { + logbook_readSampleData(StepBackwards, 1000, depthdata,gasdata, NULL, sensor3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + sensorDataAvailable[2] = 1; + } + } + break; + case CCRMODE_Simulation: dataLength = logbook_readSampleData(StepBackwards, 1000, depthdata,gasdata, NULL, ppO2data, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + break; + } } @@ -999,14 +1115,25 @@ winsmal.left = 799 - 67;//wintemp.right -67; winsmal.right = winsmal.left;// + 45; - color = CLUT_LogbookTemperature;//LOGBOOK_GRAPH_DEPTH; - if(logbookHeader.diveMode != DIVEMODE_CCR) + color = CLUT_LogbookTemperature; + + if(!isLoopMode(logbookHeader.diveMode)) + { Gfx_write_label_var(hgfx, winsmal.left, winsmal.right,winsmal.top, &FontT24,color,"\002PP O2"); + } else - if(logbookHeader.CCRmode != CCRMODE_Sensors) - Gfx_write_label_var(hgfx, winsmal.left, winsmal.right,winsmal.top, &FontT24,color,"\002SETPOINT"); - else - Gfx_write_label_var(hgfx, winsmal.left, winsmal.right,winsmal.top, &FontT24,color,"\002SENSORS"); + { + switch(logbookHeader.CCRmode) + { + case CCRMODE_FixedSetpoint: + default: Gfx_write_label_var(hgfx, winsmal.left, winsmal.right,winsmal.top, &FontT24,color,"\002SETPOINT"); + break; + case CCRMODE_Sensors: Gfx_write_label_var(hgfx, winsmal.left, winsmal.right,winsmal.top, &FontT24,color,"\002SENSORS"); + break; + case CCRMODE_Simulation: Gfx_write_label_var(hgfx, winsmal.left, winsmal.right,winsmal.top, &FontT24,color,"\002SIM PPO2"); + break; + } + } //*** PP O2 **************************************************** //calc lines and labels @@ -1019,7 +1146,7 @@ if(ppO2data[i]vpm, pDiveState->diveSettings.vpm_conservatism, 0, 0); diff -r 87bee7cc77b3 -r cc542448fb28 Discovery/Src/t3.c --- a/Discovery/Src/t3.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Discovery/Src/t3.c Fri Aug 19 11:30:24 2022 +0200 @@ -947,6 +947,9 @@ SDivetime Stopwatch = {0,0,0,0}; float fAverageDepth, fAverageDepthAbsolute; +#ifdef ENABLE_PSCR_MODE + uint8_t showSimPPO2 = 1; +#endif uint16_t tempWinX0; uint16_t tempWinX1; uint16_t tempWinY0; @@ -1264,11 +1267,22 @@ if((stateUsed->diveSettings.ppo2sensors_deactivated & (1<lifeData.ppO2Sensor_bar[i] == 0.0)) { - text[textpointer++] = '\031'; - text[textpointer++] = ' '; - text[textpointer++] = '-'; - text[textpointer++] = ' '; - text[textpointer++] = 0; +#ifdef ENABLE_PSCR_MODE + if((stateUsed->diveSettings.diveMode == DIVEMODE_PSCR) && (showSimPPO2) && (stateUsed->mode == MODE_DIVE)) /* display ppo2 sim in blue letters in case a slot is not used in the ppo2 custom view */ + { + text[textpointer++] = '\023'; + textpointer += snprintf(&text[textpointer],TEXTSIZE,"%.2f",stateUsed->lifeData.ppo2Simulated_bar); + showSimPPO2 = 0; + } + else +#endif + { + text[textpointer++] = '\031'; + text[textpointer++] = ' '; + text[textpointer++] = '-'; + text[textpointer++] = ' '; + text[textpointer++] = 0; + } } else { @@ -1279,7 +1293,7 @@ GFX_write_string(&FontT105,tXc1,text,0); - if((pSettings->scrubTimerMode != SCRUB_TIMER_OFF) && (pSettings->dive_mode == DIVEMODE_CCR)) + if((pSettings->scrubTimerMode != SCRUB_TIMER_OFF) && isLoopMode(pSettings->dive_mode)) { snprintf(text,TEXTSIZE,"\032\002\f%c",TXT_ScrubTime); GFX_write_string(&FontT42,tXc1,text,0); diff -r 87bee7cc77b3 -r cc542448fb28 Discovery/Src/t7.c --- a/Discovery/Src/t7.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Discovery/Src/t7.c Fri Aug 19 11:30:24 2022 +0200 @@ -35,6 +35,7 @@ #include "gfx_fonts.h" #include "logbook_miniLive.h" #include "math.h" +#include "tComm.h" #include "tHome.h" #include "simulation.h" #include "timer.h" @@ -61,6 +62,7 @@ void t7_miniLiveLogProfile(void); void t7_logo_OSTC(void); +void t7_ChargerView(void); static void t7_colorscheme_mod(char *text); uint8_t t7_test_customview_warnings(void); @@ -136,7 +138,7 @@ CVIEW_Compass, CVIEW_Tissues, CVIEW_sensors_mV, - CVIEW_END, + CVIEW_Charger, CVIEW_END }; @@ -685,6 +687,7 @@ void t7_refresh_surface(void) { static float debounceAmbientPressure = 0; + static uint8_t lastChargeStatus = 0; char text[256]; char timeSuffix; uint8_t hours; @@ -743,8 +746,9 @@ } else */ - if(DataEX_was_power_on()) + if(DataEX_was_power_on()) { GFX_write_string_color(&FontT42,&t7surfaceR,"cold start",4,CLUT_WarningRed); + } /* time and date */ translateDate(stateUsed->lifeData.dateBinaryFormat, &Sdate); @@ -1015,7 +1019,7 @@ else { textIdx = 0; - if(stateUsed->diveSettings.diveMode == DIVEMODE_CCR) + if(isLoopMode(stateUsed->diveSettings.diveMode)) gasOffset = NUM_OFFSET_DILUENT; else gasOffset = 0; @@ -1090,6 +1094,9 @@ case DIVEMODE_CCR: GFX_write_string(&FontT24, &t7c1, "\f\002" "CCR", 0); break; + case DIVEMODE_PSCR: + GFX_write_string(&FontT24, &t7c1, "\f\002" "PSCR", 0); + break; case DIVEMODE_OC: GFX_write_string(&FontT24, &t7c1, "\f\002" "OC", 0); break; @@ -1180,6 +1187,11 @@ } else { + if(lastChargeStatus == CHARGER_off) + { + t7_select_customview(CVIEW_Charger); + } + GFX_write_string_color(&Batt24,&t7batt,text,0,CLUT_BatteryCharging); switch(stateUsed->chargeStatus) @@ -1200,6 +1212,7 @@ GFX_write_string_color(&Batt24,&t7charge,text,0,color); } + lastChargeStatus = stateUsed->chargeStatus; customview_warnings = t7_test_customview_warnings_surface_mode(); @@ -1604,13 +1617,21 @@ { cv_disabled = 1; } + + if ((view == CVIEW_Charger) && (stateUsed->chargeStatus != CHARGER_running) && (stateUsed->chargeStatus != CHARGER_lostConnection)) + { + cv_disabled = 1; + } + + return cv_disabled; } uint8_t t7_change_customview(uint8_t action) { uint8_t *pViews; - uint8_t *pStartView,*pCurView, *pLastView; + uint8_t *pStartView,*pLastView; + uint8_t *pCurView = NULL; _Bool cv_disabled = 0; if(stateUsed->mode == MODE_DIVE) @@ -1694,6 +1715,9 @@ char text[256]; char timeSuffix; uint8_t hoursToDisplay; +#ifdef ENABLE_PSCR_MODE + uint8_t showSimPPO2 = 1; +#endif uint16_t textpointer = 0; uint16_t heading = 0; int16_t start; @@ -1730,6 +1754,13 @@ } break; + case CVIEW_Charger: + snprintf(text,100,"\032\f\001%c",TXT_Charging); + GFX_write_string(&FontT42,&t7cH,text,0); + t7_ChargerView(); + + break; + case CVIEW_SummaryOfLeftCorner: snprintf(text,100,"\032\f\001%c%c",TXT_2BYTE,TXT2BYTE_Summary); GFX_write_string(&FontT42,&t7cH,text,0); @@ -1790,6 +1821,24 @@ } t7cC.WindowNumberOfTextLines = 3; } + else if(isSettingsWarning()) + { + if(warning_count_high_time) + { + shiftWindowY0 += 20; + t7cC.WindowY0 -= shiftWindowY0; + textpointer = 0; + text[textpointer++] = '\001'; + text[textpointer++] = TXT_2BYTE; + text[textpointer++] = TXT2BYTE_CheckSettings; + text[textpointer++] = '\n'; + text[textpointer++] = '\r'; + text[textpointer++] = 0; + GFX_write_string_color(&FontT42,&t7cC,text,1, CLUT_WarningRed); + t7cC.WindowY0 += shiftWindowY0; + } + t7cC.WindowNumberOfTextLines = 1; + } else // customtext { lineCountCustomtext = t7_customtextPrepare(text); @@ -1993,13 +2042,24 @@ { if((stateUsed->diveSettings.ppo2sensors_deactivated & (1<lifeData.ppO2Sensor_bar[i] == 0.0)) { - text[textpointer++] = '\031'; // labelcolor - text[textpointer++] = '\001'; - text[textpointer++] = '-'; - text[textpointer++] = '\n'; - text[textpointer++] = '\r'; - text[textpointer++] = '\030'; // main color - text[textpointer] = 0; +#ifdef ENABLE_PSCR_MODE + if((stateUsed->diveSettings.diveMode == DIVEMODE_PSCR) && (showSimPPO2) && (stateUsed->mode == MODE_DIVE)) /* display ppo2 sim in blue letters in case a slot is not used in the ppo2 custom view */ + { + text[textpointer++] = '\023'; + textpointer += snprintf(&text[textpointer],100,"\001%01.2f\n\r\030",stateUsed->lifeData.ppo2Simulated_bar); + showSimPPO2 = 0; + } + else +#endif + { + text[textpointer++] = '\031'; // labelcolor + text[textpointer++] = '\001'; + text[textpointer++] = '-'; + text[textpointer++] = '\n'; + text[textpointer++] = '\r'; + text[textpointer++] = '\030'; // main color + text[textpointer] = 0; + } } else { @@ -2412,7 +2472,7 @@ TextR1[textPointer++] = '\a'; TextR1[textPointer++] = '\001'; TextR1[textPointer++] = ' '; - textPointer += snprintf(&TextR1[textPointer],TEXTSIZE,"%f01.2",((float)(stateUsed->diveSettings.setpoint[actualBetterSetpointId()].setpoint_cbar))/100); + textPointer += snprintf(&TextR1[textPointer],TEXTSIZE,"%01.2f",(float)(stateUsed->diveSettings.setpoint[actualBetterSetpointId()].setpoint_cbar) / 100.0); TextR1[textPointer++] = '?'; TextR1[textPointer++] = ' '; TextR1[textPointer++] = 0; @@ -2515,9 +2575,10 @@ if(stateUsed->diveSettings.ccrOption) { - if(stateUsed->diveSettings.diveMode == DIVEMODE_CCR) + if(isLoopMode(stateUsed->diveSettings.diveMode)) { snprintf(TextC2,TEXTSIZE,"\020%01.2f",stateUsed->lifeData.ppO2); + if(stateUsed->warnings.betterSetpoint && warning_count_high_time && (stateUsed->diveSettings.diveMode == DIVEMODE_CCR)) { TextC2[0] = '\a'; // inverse instead of color \020 @@ -2547,7 +2608,7 @@ TextC2[1] = TXT_2BYTE; TextC2[2] = TXT2BYTE_WarnCnsHigh; TextC2[3] = 0; - GFX_write_string_color(&FontT48,&t7c1,TextC2,0,CLUT_WarningRed); + GFX_write_string_color(&FontT42,&t7c1,TextC2,0,CLUT_WarningRed); } else { @@ -2568,6 +2629,9 @@ GFX_write_string(&FontT24,&t7c1,"\027\f\002" "CCR",0); // GFX_write_string(&FontT24,&t7c1,"\f\177\177\x80" "CCR",0); else + if(stateUsed->diveSettings.diveMode == DIVEMODE_PSCR) + GFX_write_string(&FontT24,&t7c1,"\027\f\002" "PSCR",0); + else if(stateUsed->diveSettings.ccrOption) GFX_write_string(&FontT24,&t7c1,"\f\002\024" "Bailout",0); // GFX_write_string(&FontT24,&t7c1,"\f\177\177\x80\024" "Bailout",0); @@ -2661,11 +2725,16 @@ { selection_custom_field++; } - if((selection_custom_field == LLC_ScrubberTime) && ((settingsGetPointer()->scrubTimerMode == SCRUB_TIMER_OFF) || (settingsGetPointer()->dive_mode != DIVEMODE_CCR))) + if((selection_custom_field == LLC_ScrubberTime) && ((settingsGetPointer()->scrubTimerMode == SCRUB_TIMER_OFF) || (!isLoopMode(settingsGetPointer()->dive_mode)))) { selection_custom_field++; } - +#ifdef ENABLE_PSCR_MODE + if((selection_custom_field == LCC_SimPpo2) && (settingsGetPointer()->dive_mode != DIVEMODE_PSCR)) + { + selection_custom_field++; + } +#endif if(selection_custom_field >= LLC_END) { selection_custom_field = LLC_Empty; @@ -2803,6 +2872,12 @@ snprintf(text,TEXTSIZE,"\020%u\016\016%%\017", (settingsGetPointer()->scrubTimerCur * 100 / settingsGetPointer()->scrubTimerMax)); } break; +#ifdef ENABLE_PSCR_MODE + case LCC_SimPpo2: + headerText[2] = TXT_SimPpo2; + snprintf(text,TEXTSIZE,"\020%.2f\016\016Bar\017",stateUsed->lifeData.ppo2Simulated_bar); + break; +#endif #ifdef ENABLE_BOTTLE_SENSOR case LCC_BottleBar: @@ -3380,7 +3455,7 @@ text[textpointer++] = TXT_FutureTTS; text[textpointer++] = '\n'; text[textpointer++] = '\r'; - if((pSettings->scrubTimerMode != SCRUB_TIMER_OFF) && (pSettings->dive_mode == DIVEMODE_CCR)) + if((pSettings->scrubTimerMode != SCRUB_TIMER_OFF) && (isLoopMode(pSettings->dive_mode))) { text[textpointer++] = TXT_ScrubTime; @@ -3429,7 +3504,7 @@ else textpointer += snprintf(&text[textpointer],10,"\020%ih", (pDecoinfoFuture->output_time_to_surface_seconds + 59) / 3600); - if((pSettings->scrubTimerMode != SCRUB_TIMER_OFF) && (pSettings->dive_mode == DIVEMODE_CCR)) + if((pSettings->scrubTimerMode != SCRUB_TIMER_OFF) && (isLoopMode(pSettings->dive_mode))) { text[textpointer++] = '\n'; text[textpointer++] = '\r'; @@ -3779,3 +3854,212 @@ windowGimp.top = 40 + 32; GFX_draw_image_monochrome(&t7screen, windowGimp, &ImgOSTC, 0); } + +static uint16_t ChargerLog[60] = {10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10}; + +uint16_t LogDeltaCharge(float charge) +{ + static uint8_t curIndex = 0; + static float averageSpeed = 0.0; + uint16_t level = 0; + uint16_t completeSec = 0; + + if(charge > 0.003) + { + level = 2; + } + else if(charge > 0.0025) + { + level = 3; + } + else if(charge > 0.002) + { + level = 4; + } + else if(charge > 0.0015) + { + level = 5; + } + else if(charge > 0.001) + { + level = 6; + } + else if(charge > 0.0005) + { + level = 7; + } + else if(charge > 0.00) + { + level = 8; + } + else + { + level = 10; + } + if(curIndex < 59) + { + ChargerLog[curIndex++] = level; + } + else + { + memcpy (&ChargerLog[0],&ChargerLog[1],sizeof(ChargerLog) - 1); + ChargerLog[curIndex] = level; + } + if(curIndex > 1) + { + averageSpeed = ((averageSpeed * (curIndex-1)) + charge) / curIndex; + completeSec = (100.0 - stateUsed->lifeData.battery_charge) / averageSpeed; + } + else + { + completeSec = 0xffff; + } + return completeSec; +} + +uint16_t* getChargeLog() +{ + return ChargerLog; +} + +void t7_ChargerView(void) +{ + static float lastCharge = 0.0; + float localCharge = 0.0; + static uint32_t lastTick = 0; + uint32_t curTick = 0; + static float speed = 0.0; + float deltatime = 0.0; + + char text[256+50]; + uint8_t textpointer = 0; + static uint16_t remainingSec = 0; + uint16_t hoursto100 = 0; + char indicator = '~'; + + point_t start, stop; + + SWindowGimpStyle wintemp; + SSettings* pSettings; + pSettings = settingsGetPointer(); + + t7cY0free.WindowLineSpacing = 28 + 48 + 14; + t7cY0free.WindowY0 = t7cH.WindowY0 - 5 - 2 * t7cY0free.WindowLineSpacing; + t7cY0free.WindowNumberOfTextLines = 3; + + + if(pSettings->FlipDisplay) + { + t7cY0free.WindowY0 = t7cH.WindowY0 + 15; + t7cY0free.WindowY1 = t7cY0free.WindowY0 + 250; + } + + localCharge = stateUsed->lifeData.battery_charge; + if(localCharge < 0.0) + { + localCharge *= -1.0; + } + + if(stateUsed->chargeStatus != CHARGER_off) + { + if(lastCharge != localCharge) + { + curTick = HAL_GetTick(); + deltatime = (curTick - lastTick); + lastTick = curTick; + if(lastCharge < localCharge) + { + speed = (localCharge - lastCharge) * 1000.0 / deltatime; + } + + if(localCharge > 100.0) + { + localCharge = 100.0; + } + + lastCharge = localCharge; + } + + + if(deltatime > 1000) + { + deltatime = 0; + remainingSec = LogDeltaCharge(speed); + speed = 0; + } + } + textpointer += snprintf(&text[textpointer],50,"\n\r"); + textpointer += snprintf(&text[textpointer],50,"\001%c\n\r",TXT_ChargeHour); + + GFX_write_string(&FontT24, &t7cY0free, text, 1); + + hoursto100 = remainingSec / 3600; /* reduce to hours */ + if(hoursto100 < 1) + { + indicator = '<'; + hoursto100 = 1; + } + + if(!pSettings->FlipDisplay) + { + t7cY0free.WindowY0 -= 52; + } + else + { + t7cY0free.WindowY1 += 52; + } + + if((stateUsed->lifeData.battery_charge > 0) && (stateUsed->chargeStatus != CHARGER_off)) + { + snprintf(text,60, + "\001%0.2f\016\016%%\017\n\r" + "\001%c%d\n\r" + ,stateUsed->lifeData.battery_charge + ,indicator + ,hoursto100); + } + else + { + snprintf(text,60, + "\001---\n\r" + "\001---\n\r"); + } + GFX_write_string(&FontT42, &t7cY0free, text, 1); + + wintemp.left = CUSTOMBOX_LINE_LEFT + CUSTOMBOX_INSIDE_OFFSET + 50; + wintemp.right = wintemp.left + CUSTOMBOX_SPACE_INSIDE - 100; + + + if(!pSettings->FlipDisplay) + { + wintemp.top = 480 - t7l1.WindowY0 + 115; + wintemp.bottom = wintemp.top + 100; + } + else + { + wintemp.top = t7l1.WindowY1 + 102; + wintemp.bottom = wintemp.top + 100; + } + + start.x = wintemp.left-5; + start.y = 90; + + stop.x = wintemp.right + 5 - start.x; + stop.y = 100; + GFX_draw_box(&t7screen, start, stop,1, CLUT_Font020); + + if(stateUsed->chargeStatus != CHARGER_off) + { + GFX_graph_print(&t7screen, &wintemp, 1,1,0, 10, getChargeLog(), 60, CLUT_Font030, NULL); + } + else + { + GFX_graph_print(&t7screen, &wintemp, 1,1,0, 10, getChargeLog(), 60, CLUT_Font031, NULL); + } + +} diff -r 87bee7cc77b3 -r cc542448fb28 Discovery/Src/tCCR.c --- a/Discovery/Src/tCCR.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Discovery/Src/tCCR.c Fri Aug 19 11:30:24 2022 +0200 @@ -65,6 +65,13 @@ #define BOTTLE_SENSOR_TIMEOUT (6000u) /* signal pressure budget as not received after 10 minutes (6000 * 100ms) */ #define MAX_SENSOR_COMPARE_DEVIATION (0.15f) /* max deviation between two sensors allowed before their results are rated as suspect */ +#define MAX_SENSOR_VOLTAGE_MV (250u) /* max allowed voltage value for a sensor measurement */ + +#ifdef ENABLE_ALTERNATIVE_SENSORTYP +#define MIN_SENSOR_VOLTAGE_MV (3u) /* min allowed voltage value for a sensor measurement (Inspiration, Submatix, Sentinel Typ) */ +#else +#define MIN_SENSOR_VOLTAGE_MV (8u) /* min allowed voltage value for a sensor measurement (legacy OSTC TYP) */ +#endif /* Private variables ---------------------------------------------------------*/ static SIrLink receiveHUD[2]; @@ -173,8 +180,8 @@ if(sensorActive[i]) { - if( (stateUsed->lifeData.sensorVoltage_mV[i] < 8) || - (stateUsed->lifeData.sensorVoltage_mV[i] > 250)) + if( (stateUsed->lifeData.sensorVoltage_mV[i] < MIN_SENSOR_VOLTAGE_MV) || + (stateUsed->lifeData.sensorVoltage_mV[i] > MAX_SENSOR_VOLTAGE_MV)) { sensorActive[i] = 0; switch(i) @@ -330,7 +337,7 @@ } /* decrease scrubber timer only in real dive mode */ - if((pSettings->scrubTimerMode != SCRUB_TIMER_OFF) && (pSettings->dive_mode == DIVEMODE_CCR) && (stateUsed->mode == MODE_DIVE) && (stateUsed == stateRealGetPointer())) + if((pSettings->scrubTimerMode != SCRUB_TIMER_OFF) && (isLoopMode(pSettings->dive_mode)) && (stateUsed->mode == MODE_DIVE) && (stateUsed == stateRealGetPointer())) { ScrubberTimeoutCount++; if(ScrubberTimeoutCount >= 600) /* resolution is minutes */ @@ -444,18 +451,25 @@ static uint8_t tCCR_fallbackToFixedSetpoint(void) { uint8_t retVal = 0; - if((stateUsed->mode == MODE_DIVE) && (stateUsed->diveSettings.diveMode == DIVEMODE_CCR) && (stateUsed->diveSettings.CCR_Mode == CCRMODE_Sensors) && (stateUsed->diveSettings.fallbackOption)) - { - uint8_t setpointCbar, actualGasID; + uint8_t setpointCbar, actualGasID; - setpointCbar = stateUsed->diveSettings.setpoint[1].setpoint_cbar; - stateUsedWrite->diveSettings.CCR_Mode = CCRMODE_FixedSetpoint; + if((stateUsed->mode == MODE_DIVE) && (stateUsed->diveSettings.CCR_Mode == CCRMODE_Sensors) && (stateUsed->diveSettings.fallbackOption)) + { + if(stateUsed->diveSettings.diveMode == DIVEMODE_CCR) + { + setpointCbar = stateUsed->diveSettings.setpoint[1].setpoint_cbar; + stateUsedWrite->diveSettings.CCR_Mode = CCRMODE_FixedSetpoint; + } + else + { + setpointCbar = stateUsed->lifeData.ppo2Simulated_bar * 100; + stateUsedWrite->diveSettings.CCR_Mode = CCRMODE_Simulation; + } + actualGasID = stateUsed->lifeData.actualGas.GasIdInSettings; + setActualGas_DM(&stateUsedWrite->lifeData,actualGasID,setpointCbar); - actualGasID = stateUsed->lifeData.actualGas.GasIdInSettings; - setActualGas_DM(&stateUsedWrite->lifeData,actualGasID,setpointCbar); - - set_warning_fallback(); - retVal = stateUsed->diveSettings.setpoint[1].setpoint_cbar; + set_warning_fallback(); + retVal = setpointCbar; } return retVal; } diff -r 87bee7cc77b3 -r cc542448fb28 Discovery/Src/tComm.c --- a/Discovery/Src/tComm.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Discovery/Src/tComm.c Fri Aug 19 11:30:24 2022 +0200 @@ -2001,7 +2001,8 @@ char aRxBuffer[UART_CMD_BUF_SIZE]; uint8_t sizeAnswer = sizeof(answerOkay) -1; uint8_t result = HAL_OK; - uint8_t index = 0; + uint8_t indexRef = 0; + uint8_t indexBuf = 0; uint8_t answer; memset(aRxBuffer,0,UART_CMD_BUF_SIZE); @@ -2009,25 +2010,46 @@ { do { - if(answerOkay[index] != aRxBuffer[index]) + if(answerOkay[indexRef] == aRxBuffer[indexBuf]) { - index = sizeAnswer; - result = HAL_ERROR; /* unexpected answer => there might be characters left in RX que => read and discard all rx bytes */ - do - { - answer = HAL_UART_Receive(&UartHandle, (uint8_t*)&aRxBuffer[index], 1, 10); - if (index < UART_CMD_BUF_SIZE) - { - index++; - } - }while(answer == HAL_OK); - index = sizeAnswer; + indexRef++; } else { - index++; + if(indexRef != 0) + { + indexRef = 0; + } } - }while(index < sizeAnswer); + indexBuf++; + }while(indexBuf < sizeAnswer); + + if(indexRef != sizeAnswer) /* unexpected answer => there might be characters left in RX que => read and check all rx bytes */ + { + do + { + answer = HAL_UART_Receive(&UartHandle, (uint8_t*)&aRxBuffer[indexBuf], 1, 10); + if (indexBuf < UART_CMD_BUF_SIZE) + { + if(answerOkay[indexRef] == aRxBuffer[indexBuf]) + { + indexRef++; + } + else + { + if(indexRef != 0) + { + indexRef = 0; + } + } + indexBuf++; + } + }while(answer == HAL_OK); + if(indexRef != sizeAnswer) + { + result = HAL_ERROR; + } + } } else { @@ -2175,14 +2197,8 @@ CmdSize = strlen(TxBuffer); if(HAL_UART_Transmit(&UartHandle, (uint8_t*)TxBuffer,CmdSize, 2000) == HAL_OK) { - if(BmTmpConfig == BM_CONFIG_ECHO) /* echo is not yet turned off => read and discard echo */ - { - HAL_UART_Receive(&UartHandle, (uint8_t*)TxBuffer, CmdSize, UART_OPERATION_TIMEOUT); - } - result = tComm_CheckAnswerOK(); - if((BmTmpConfig == BM_CONFIG_BAUD) && (result == HAL_OK) && (UartHandle.Init.BaudRate != 460800)) /* is com already switched to fast speed? */ { HAL_UART_DeInit(&UartHandle); @@ -2190,6 +2206,19 @@ UartHandle.Init.BaudRate = 460800; HAL_UART_Init(&UartHandle); } + if((BmTmpConfig == BM_CONFIG_BAUD) && (result == HAL_OK) && (UartHandle.Init.BaudRate == 460800)) /* This shut not happen because default speed is 115200 => update module configuration */ + { + sprintf(TxBuffer,"AT%%B8\r"); /* set default baudrate */ + CmdSize = strlen(TxBuffer); + HAL_UART_Transmit(&UartHandle, (uint8_t*)TxBuffer,CmdSize, 2000); + HAL_UART_DeInit(&UartHandle); + HAL_Delay(10); + UartHandle.Init.BaudRate = 115200; + HAL_UART_Init(&UartHandle); + sprintf(TxBuffer,"AT&W\r"); /* write configuration */ + CmdSize = strlen(TxBuffer); + HAL_UART_Transmit(&UartHandle, (uint8_t*)TxBuffer,CmdSize, 2000); + } if(result == HAL_OK) { BmTmpConfig++; @@ -2197,6 +2226,7 @@ if(BmTmpConfig == BM_CONFIG_DONE) { ConfigRetryCnt = 0; + RestartModule = 1; } } } @@ -2210,6 +2240,14 @@ { RestartModule = 0; /* only one try */ ConfigRetryCnt = 200; /* used for delay to startup module again */ + + if(BmTmpConfig == BM_CONFIG_ECHO) /* the module did not answer even once => try again with alternative baud rate */ + { + HAL_UART_DeInit(&UartHandle); + HAL_Delay(1); + UartHandle.Init.BaudRate = 460800; + HAL_UART_Init(&UartHandle); + } BmTmpConfig = BM_CONFIG_RETRY; } else /* even restarting module failed => switch bluetooth off */ diff -r 87bee7cc77b3 -r cc542448fb28 Discovery/Src/tHome.c --- a/Discovery/Src/tHome.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Discovery/Src/tHome.c Fri Aug 19 11:30:24 2022 +0200 @@ -590,7 +590,7 @@ } } - if((stateUsed->mode == MODE_SURFACE) && (stateUsed->diveSettings.ppo2sensors_deactivated != 0x07) && (stateUsed->diveSettings.ccrOption != 0)) + if((stateUsed->mode == MODE_SURFACE) && (stateUsed->diveSettings.ppo2sensors_deactivated != 0x07) && (stateUsed->diveSettings.ccrOption != 0) && (!t7_customview_disabled(CVIEW_sensors))) { tHome_tick_count_o2sens++; if(tHome_tick_count_o2sens > AUTORETURN_O2SENS) diff -r 87bee7cc77b3 -r cc542448fb28 Discovery/Src/tMenu.c --- a/Discovery/Src/tMenu.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Discovery/Src/tMenu.c Fri Aug 19 11:30:24 2022 +0200 @@ -58,6 +58,8 @@ #define MENU_WDW_HIGH 390 #define KEY_LABEL_HIGH 25 /* Height of the label used for the the user keys */ +#define SLOW_UPDATE_CNT 10 /* Some content shall not be update in short intervals => add prescalar */ + typedef struct { uint32_t StartAddressForPage[MAXPAGES+1]; @@ -530,7 +532,7 @@ tM_add(StMDECOP); // } - if((pSettings->dive_mode == DIVEMODE_CCR) || (stateUsed->diveSettings.ccrOption == 1)) + if((isLoopMode(pSettings->dive_mode)) || (stateUsed->diveSettings.ccrOption == 1)) { tM_add(StMCG); tM_add(StMSP); @@ -586,23 +588,45 @@ void tM_refresh_live_content(void) { + static uint8_t slowUpdate = SLOW_UPDATE_CNT; uint8_t page = 0; char text[MAX_PAGE_TEXTSIZE]; char subtext[MAX_PAGE_TEXTSIZE]; uint16_t tabPosition; - if((get_globalState() == StMSYS) && (actual_menu_content == MENU_SURFACE)) + uint32_t globalState = get_globalState(); + + slowUpdate--; + page = menu.pageMemoryForNavigation; + switch(globalState) { - page = menu.pageMemoryForNavigation; - tMSystem_refresh(0, text, &tabPosition, subtext); - update_content_with_new_frame(page, text, tabPosition, subtext); + case StMSYS: if(actual_menu_content == MENU_SURFACE) + { + tMSystem_refresh(0, text, &tabPosition, subtext); + update_content_with_new_frame(page, text, tabPosition, subtext); + } + break; + case StMHARD: tMHardware_refresh(0, text, &tabPosition, subtext); + update_content_with_new_frame(page, text, tabPosition, subtext); + break; + case StMOG: if((actual_menu_content != MENU_SURFACE) && (slowUpdate == 0)) + { + tMOG_refresh(0, text, &tabPosition, subtext); + update_content_with_new_frame(page, text, tabPosition, subtext); + } + break; + case StMCG: if((actual_menu_content != MENU_SURFACE) && (slowUpdate == 0)) + { + tMCG_refresh(0, text, &tabPosition, subtext); + update_content_with_new_frame(page, text, tabPosition, subtext); + } + break; + default: + break; } - else - if(get_globalState() == StMHARD) + if(slowUpdate == 0) { - page = menu.pageMemoryForNavigation; - tMHardware_refresh(0, text, &tabPosition, subtext); - update_content_with_new_frame(page, text, tabPosition, subtext); + slowUpdate = SLOW_UPDATE_CNT; } tMscreen.FBStartAdress = menu.StartAddressForPage[page]; diff -r 87bee7cc77b3 -r cc542448fb28 Discovery/Src/tMenuDeco.c --- a/Discovery/Src/tMenuDeco.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Discovery/Src/tMenuDeco.c Fri Aug 19 11:30:24 2022 +0200 @@ -67,6 +67,9 @@ case DIVEMODE_Apnea: divemode = TXT_Apnoe; break; + case DIVEMODE_PSCR: + divemode = TXT_PSClosedCircuit; + break; default : divemode = TXT_OpenCircuit; break; @@ -81,14 +84,22 @@ strcpy(&text[textPointer],"\n\r"); textPointer += 2; - if(data->dive_mode == DIVEMODE_CCR) + if(isLoopMode(data->dive_mode)) { if((line == 0) || (line == 2)) { - if(data->CCR_Mode == CCRMODE_Sensors) - CcrModusTxtId = TXT_Sensor; - else - CcrModusTxtId = TXT_FixedSP; + switch(data->CCR_Mode) + { + case CCRMODE_Sensors: CcrModusTxtId = TXT_Sensor; + break; + case CCRMODE_FixedSetpoint: CcrModusTxtId = TXT_FixedSP; + break; + case CCRMODE_Simulation: CcrModusTxtId = TXT_SimPpo2; + break; + default: CcrModusTxtId = 'X'; + break; + } + textPointer += snprintf(&text[textPointer], 60,\ "%c" diff -r 87bee7cc77b3 -r cc542448fb28 Discovery/Src/tMenuEdit.c --- a/Discovery/Src/tMenuEdit.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Discovery/Src/tMenuEdit.c Fri Aug 19 11:30:24 2022 +0200 @@ -213,6 +213,13 @@ break; case (StMXTRA_CompassHeading & MaskFieldDigit): refreshFct = refresh_CompassHeading; break; + case (StMXTRA_PSCR_O2_Drop & MaskFieldDigit): if(settingsGetPointer()->dive_mode != DIVEMODE_PSCR) /* workaround because PSCR mode is set dynamic */ + { + refreshFct = refresh_CO2Data; + } + break; + case (StMXTRA_CO2_Sensor & MaskFieldDigit): refreshFct = refresh_CO2Data; + break; case (StMSYS4_Info & MaskFieldDigit): refreshFct = &refresh_InformationPage; break; case (StMPLAN5_ExitResult & MaskFieldDigit): refreshFct = refresh_PlanResult; @@ -256,6 +263,7 @@ { if(WriteSettings) { + reset_SettingWarning(); GFX_logoAutoOff(); ext_flash_write_settings(0); WriteSettings = 0; diff -r 87bee7cc77b3 -r cc542448fb28 Discovery/Src/tMenuEditCustom.c --- a/Discovery/Src/tMenuEditCustom.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Discovery/Src/tMenuEditCustom.c Fri Aug 19 11:30:24 2022 +0200 @@ -169,6 +169,12 @@ text[4] = TXT_AtemGasVorrat; break; #endif + +#ifdef ENABLE_PSCR_MODE + case LCC_SimPpo2: + text[4] = TXT_SimPpo2; + break; +#endif /* none */ case LLC_Empty: text[4] = '-'; @@ -713,7 +719,7 @@ uint8_t OnAction_CViewPortLayout(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) { SSettings* pSettings = settingsGetPointer(); - if((pSettings->viewPortMode >> 4) & 0x10 != 0) + if(((pSettings->viewPortMode >> 4) & 0x10) != 0) { pSettings->viewPortMode &= 0xEF; /* 1110 1111 */ } diff -r 87bee7cc77b3 -r cc542448fb28 Discovery/Src/tMenuEditDeco.c --- a/Discovery/Src/tMenuEditDeco.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Discovery/Src/tMenuEditDeco.c Fri Aug 19 11:30:24 2022 +0200 @@ -32,6 +32,7 @@ #include "gfx_fonts.h" #include "tMenuEdit.h" #include "unit.h" +#include "configuration.h" /* Private variables ---------------------------------------------------------*/ static uint8_t lineSelected = 0; @@ -46,11 +47,7 @@ static void openEdit_Salinity(void); /* Announced function prototypes -----------------------------------------------*/ - -static uint8_t OnAction_OC (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); -static uint8_t OnAction_CC (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); -static uint8_t OnAction_Apnea (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); -static uint8_t OnAction_Gauge (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); +static uint8_t OnAction_setMode (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); static uint8_t OnAction_FutureTTS (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); static uint8_t OnAction_ppO2Max (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); static uint8_t OnAction_SafetyStop (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); @@ -66,7 +63,7 @@ lineSelected = line; - if((data->dive_mode != DIVEMODE_CCR )&& (line > 1)) + if((!isLoopMode(data->dive_mode)) && (line > 1)) line += 1; switch(line) @@ -101,6 +98,7 @@ #define APNEAANDGAUGE char text[32]; + uint8_t lineOffset = 0; uint8_t actualDiveMode, active; SSettings *pSettings = settingsGetPointer(); actualDiveMode = pSettings->dive_mode; @@ -113,6 +111,10 @@ text[1] = 0; +#ifdef ENABLE_PSCR_MODE + lineOffset = ME_Y_LINE_STEP; +#endif + text[0] = TXT_OpenCircuit; if(actualDiveMode == DIVEMODE_OC) active = 1; @@ -127,89 +129,81 @@ active = 0; write_field_on_off(StMDECO1_CC, 30, 500, ME_Y_LINE2, &FontT48, text, active); - #ifdef APNEAANDGAUGE +#ifdef ENABLE_PSCR_MODE + text[0] = TXT_PSClosedCircuit; + if(actualDiveMode == DIVEMODE_PSCR) + active = 1; + else + active = 0; + write_field_on_off(StMDECO1_PSCR, 30, 500, ME_Y_LINE3, &FontT48, text, active); +#endif +#ifdef APNEAANDGAUGE text[0] = TXT_Apnoe; if(actualDiveMode == DIVEMODE_Apnea) active = 1; else active = 0; - write_field_on_off(StMDECO1_Apnea, 30, 500, ME_Y_LINE3, &FontT48, text, active); + write_field_on_off(StMDECO1_Apnea, 30, 500, ME_Y_LINE3 + lineOffset, &FontT48, text, active); text[0] = TXT_Gauge; if(actualDiveMode == DIVEMODE_Gauge) active = 1; else active = 0; - write_field_on_off(StMDECO1_Gauge, 30, 500, ME_Y_LINE4, &FontT48, text, active); - #endif + write_field_on_off(StMDECO1_Gauge, 30, 500, ME_Y_LINE4 + lineOffset, &FontT48, text, active); +#endif - setEvent(StMDECO1_OC, (uint32_t)OnAction_OC); - setEvent(StMDECO1_CC, (uint32_t)OnAction_CC); - #ifdef APNEAANDGAUGE - setEvent(StMDECO1_Apnea, (uint32_t)OnAction_Apnea); - setEvent(StMDECO1_Gauge, (uint32_t)OnAction_Gauge); - #endif + setEvent(StMDECO1_OC, (uint32_t)OnAction_setMode); + setEvent(StMDECO1_CC, (uint32_t)OnAction_setMode); +#ifdef ENABLE_PSCR_MODE + setEvent(StMDECO1_PSCR, (uint32_t)OnAction_setMode); +#endif + +#ifdef APNEAANDGAUGE + setEvent(StMDECO1_Apnea, (uint32_t)OnAction_setMode); + setEvent(StMDECO1_Gauge, (uint32_t)OnAction_setMode); +#endif write_buttonTextline(TXT2BYTE_ButtonBack,TXT2BYTE_ButtonEnter,TXT2BYTE_ButtonNext); } -static uint8_t OnAction_OC (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) + +static uint8_t OnAction_setMode (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) //(uint32_t newMode) { - SSettings *pSettings = settingsGetPointer(); - if(pSettings->dive_mode == DIVEMODE_OC) - return EXIT_TO_MENU; - pSettings->dive_mode = DIVEMODE_OC; - setActualGasFirst(&stateRealGetPointerWrite()->lifeData); - tMenuEdit_set_on_off(editId, 1); - tMenuEdit_set_on_off(StMDECO1_CC, 0); - tMenuEdit_set_on_off(StMDECO1_Apnea, 0); - tMenuEdit_set_on_off(StMDECO1_Gauge, 0); - return UPDATE_DIVESETTINGS; -} + uint32_t modeArray[] = {StMDECO1_OC, StMDECO1_CC, StMDECO1_Gauge, StMDECO1_Apnea /* definition needs to follow order of DIVEMODE (settings.h) */ +#ifdef ENABLE_PSCR_MODE + , StMDECO1_PSCR +#endif + }; + + uint8_t index = 0; + SSettings *pSettings = settingsGetPointer(); + uint8_t retVal = EXIT_TO_MENU; + uint8_t lastMode = pSettings->dive_mode; -static uint8_t OnAction_CC (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) -{ - SSettings *pSettings = settingsGetPointer(); - if(pSettings->dive_mode == DIVEMODE_CCR) - return EXIT_TO_MENU; - pSettings->dive_mode = DIVEMODE_CCR; - setActualGasFirst(&stateRealGetPointerWrite()->lifeData); - tMenuEdit_set_on_off(editId, 1); - tMenuEdit_set_on_off(StMDECO1_OC, 0); - tMenuEdit_set_on_off(StMDECO1_Apnea, 0); - tMenuEdit_set_on_off(StMDECO1_Gauge, 0); - return UPDATE_DIVESETTINGS; -} - - -static uint8_t OnAction_Apnea (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) -{ - SSettings *pSettings = settingsGetPointer(); - if(pSettings->dive_mode == DIVEMODE_Apnea) - return EXIT_TO_MENU; - pSettings->dive_mode = DIVEMODE_Apnea; - setActualGasFirst(&stateRealGetPointerWrite()->lifeData); - tMenuEdit_set_on_off(editId, 1); - tMenuEdit_set_on_off(StMDECO1_CC, 0); - tMenuEdit_set_on_off(StMDECO1_OC, 0); - tMenuEdit_set_on_off(StMDECO1_Gauge, 0); - return UPDATE_DIVESETTINGS; -} - - -static uint8_t OnAction_Gauge (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) -{ - SSettings *pSettings = settingsGetPointer(); - if(pSettings->dive_mode == DIVEMODE_Gauge) - return EXIT_TO_MENU; - pSettings->dive_mode = DIVEMODE_Gauge; - setActualGasFirst(&stateRealGetPointerWrite()->lifeData); - tMenuEdit_set_on_off(editId, 1); - tMenuEdit_set_on_off(StMDECO1_CC, 0); - tMenuEdit_set_on_off(StMDECO1_Apnea, 0); - tMenuEdit_set_on_off(StMDECO1_OC, 0); - return UPDATE_DIVESETTINGS; + setActualGasFirst(&stateRealGetPointerWrite()->lifeData); + while(index < sizeof(modeArray) / 4) /* calculate number of items out of array size (bytes) */ + { + if(editId == modeArray[index]) + { + if(pSettings->dive_mode != index) + { + tMenuEdit_set_on_off(modeArray[index], 1); + pSettings->dive_mode = index; + retVal = UPDATE_DIVESETTINGS; + } + } + else + { + if(lastMode == index) /* reset state of previous mode selection */ + { + tMenuEdit_set_on_off(modeArray[index], 0); + } + } + index++; + } + return retVal; } diff -r 87bee7cc77b3 -r cc542448fb28 Discovery/Src/tMenuEditGasOC.c --- a/Discovery/Src/tMenuEditGasOC.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Discovery/Src/tMenuEditGasOC.c Fri Aug 19 11:30:24 2022 +0200 @@ -92,7 +92,7 @@ { if(line == 6) { - if((settingsGetPointer()->dive_mode == DIVEMODE_CCR) || (stateUsed->diveSettings.ccrOption == 1)) + if(isLoopMode(settingsGetPointer()->dive_mode) || (stateUsed->diveSettings.ccrOption == 1)) { selectPage(StMOG); } @@ -122,7 +122,7 @@ { if(line == 6) { - if((settingsGetPointer()->dive_mode == DIVEMODE_CCR) || (stateUsed->diveSettings.ccrOption == 1)) + if(isLoopMode(settingsGetPointer()->dive_mode) || (stateUsed->diveSettings.ccrOption == 1)) { selectPage(StMCG); } @@ -167,9 +167,12 @@ /* select gas in divemode */ void openEdit_DiveGasSelect(uint8_t line, uint8_t ccr) { - openEdit_DiveGasSelect_Subroutine(line, ccr); - if(!ccr) - tMEGas_check_switch_to_bailout(); + if(!ccr) + { + tMEGas_check_switch_to_bailout(); + } + openEdit_DiveGasSelect_Subroutine(line, ccr); + exitMenuEdit_to_Home_with_Menu_Update(); } @@ -367,7 +370,7 @@ void tMEGas_check_switch_to_bailout(void) { - if(stateUsed->diveSettings.diveMode == DIVEMODE_CCR) + if(isLoopMode(stateUsed->diveSettings.diveMode)) { stateUsedWrite->diveSettings.diveMode = DIVEMODE_OC; block_diluent_page(); diff -r 87bee7cc77b3 -r cc542448fb28 Discovery/Src/tMenuEditHardware.c --- a/Discovery/Src/tMenuEditHardware.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Discovery/Src/tMenuEditHardware.c Fri Aug 19 11:30:24 2022 +0200 @@ -336,11 +336,18 @@ switch(settingsGetPointer()->ppo2sensors_source) { default: - case O2_SENSOR_SOURCE_OPTIC: text[1] = TXT2BYTE_O2IFOptic; + case O2_SENSOR_SOURCE_OPTIC: text[1] = TXT2BYTE_O2IFOptic; + text[2] = 0; + break; + case O2_SENSOR_SOURCE_ANALOG: text[1] = TXT2BYTE_O2IFAnalog; + text[2] = 0; break; - case O2_SENSOR_SOURCE_ANALOG: text[1] = TXT2BYTE_O2IFAnalog; +#ifdef ENABLE_SENTINEL_MODE + case O2_SENSOR_SOURCE_SENTINEL: snprintf(text, 10,"Sentinel"); + break; +#endif } - text[2] = 0; + write_label_var( 400, 800, ME_Y_LINE6, &FontT48, text); } tMenuEdit_refresh_field(StMHARD3_O2_Sensor1); @@ -378,12 +385,16 @@ write_field_on_off(StMHARD3_O2_Sensor2, 30, 95, ME_Y_LINE2, &FontT48, "", sensorActive[1]); write_field_on_off(StMHARD3_O2_Sensor3, 30, 95, ME_Y_LINE3, &FontT48, "", sensorActive[2]); - if(settingsGetPointer()->ppo2sensors_source == O2_SENSOR_SOURCE_ANALOG) + if((settingsGetPointer()->ppo2sensors_source == O2_SENSOR_SOURCE_ANALOG) +#ifdef ENABLE_SENTINEL_MODE + || (settingsGetPointer()->ppo2sensors_source == O2_SENSOR_SOURCE_SENTINEL) +#endif + ) { write_label_fix( 30, 800, ME_Y_LINE4, &FontT48, TXT2BYTE_O2Calib); write_label_var( 400, 800, ME_Y_LINE4, &FontT48, "\016\016 %\017"); - write_field_toggle(StMHARD3_O2_Calibrate, 400, 800, ME_Y_LINE4, &FontT48, "", 21, 100); + write_field_toggle(StMHARD3_O2_Calibrate, 400, 800, ME_Y_LINE4, &FontT48, "", 21, 98); } text[0] = TXT_Fallback; @@ -399,7 +410,11 @@ setEvent(StMHARD3_O2_Sensor1, (uint32_t)OnAction_Sensor1); setEvent(StMHARD3_O2_Sensor2, (uint32_t)OnAction_Sensor2); setEvent(StMHARD3_O2_Sensor3, (uint32_t)OnAction_Sensor3); - if(settingsGetPointer()->ppo2sensors_source == O2_SENSOR_SOURCE_ANALOG) + if((settingsGetPointer()->ppo2sensors_source == O2_SENSOR_SOURCE_ANALOG) +#ifdef ENABLE_SENTINEL_MODE + || (settingsGetPointer()->ppo2sensors_source == O2_SENSOR_SOURCE_SENTINEL) +#endif + ) { setEvent(StMHARD3_O2_Calibrate, (uint32_t)OnAction_O2_Calibrate); } @@ -517,7 +532,7 @@ { if(O2_calib_gas == 21) { - O2_calib_gas = 100; + O2_calib_gas = 98; } else { @@ -537,11 +552,8 @@ { uint8_t source = settingsGetPointer()->ppo2sensors_source; - if(source == O2_SENSOR_SOURCE_OPTIC) - { - source = O2_SENSOR_SOURCE_ANALOG; - } - else + source++; + if(source == O2_SENSOR_SOURCE_MAX) { source = O2_SENSOR_SOURCE_OPTIC; } diff -r 87bee7cc77b3 -r cc542448fb28 Discovery/Src/tMenuEditPlanner.c --- a/Discovery/Src/tMenuEditPlanner.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Discovery/Src/tMenuEditPlanner.c Fri Aug 19 11:30:24 2022 +0200 @@ -307,7 +307,7 @@ strncpy(text, " " "\016\016" - " l\\min" + " l/min" "\017" " " "\016\016" @@ -315,36 +315,18 @@ "\017" " " "\016\016" - " l\\min" + " l/min" "\017", 40 ); write_label_var( 400, 800, y_line, &FontT48, text); write_field_udigit(StMPLAN4_Settings, 400, 800, y_line, &FontT48, "## ##", (uint32_t)travel_lbar, (uint32_t)deco_lbar, 0, 0); -// write_field_udigit(StMPLAN4_Settings, 400, 800, y_line, &FontT48, "##\016\016 l\\min\017 \016\016deco\017 ##\016\016 l\\min\017", (uint32_t)travel_lbar, (uint32_t)deco_lbar, 0, 0); // note : text max is 32 byte! -> ok and it does not like small fonts in between -> problem write_buttonTextline(TXT2BYTE_ButtonMinus,TXT2BYTE_ButtonEnter,TXT2BYTE_ButtonPlus); setEvent(StMPLAN4_Settings, (uint32_t)OnAction_PlanSettings); startEdit(); - -/* - text[textPointer++] = TXT_2BYTE; - text[textPointer++] = TXT2BYTE_SimConsumption; - text[textPointer++] = '\t'; - textPointer += snprintf(&text[textPointer],30, - "%u" - "\016\016 l\\min\017" - ,tMplan_gasConsumTravel); - text[textPointer++] = ' '; - text[textPointer++] = ' '; - textPointer += snprintf(&text[textPointer],30, - "\016\016deco\017" - " %u" - "\016\016 l\\min\017" - ,tMplan_gasConsumDeco); -*/ } @@ -622,14 +604,14 @@ switch(j) { case 0: // descent - textpointer = snprintf(&text[textpointer],20,"-%u\016\016 m\\min\017",tMplan_Summary.descentRateMeterPerMinute); + textpointer = snprintf(&text[textpointer],20,"-%u\016\016 m/min\017",tMplan_Summary.descentRateMeterPerMinute); break; case 1: // level textpointer = snprintf(&text[textpointer],20,"%1.2f\016\016 %c\017",tMplan_Summary.ppO2AtBottom, TXT_ppO2); break; case 2: // first stop case 3: // surface - textpointer = snprintf(&text[textpointer],20,"%u\016\016 m\\min\017",tMplan_Summary.ascentRateMeterPerMinute); + textpointer = snprintf(&text[textpointer],20,"%u\016\016 m/min\017",tMplan_Summary.ascentRateMeterPerMinute); break; default: break; @@ -689,7 +671,7 @@ textpointer += snprintf(&text[textpointer],20,"GF %u/%u", stateUsed->diveSettings.gf_low, stateUsed->diveSettings.gf_high); break; case 1: - if(settingsGetPointer()->dive_mode == DIVEMODE_CCR) + if(isLoopMode(settingsGetPointer()->dive_mode)) text[textpointer++] = 'C'; else text[textpointer++] = 'O'; diff -r 87bee7cc77b3 -r cc542448fb28 Discovery/Src/tMenuEditSetpoint.c --- a/Discovery/Src/tMenuEditSetpoint.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Discovery/Src/tMenuEditSetpoint.c Fri Aug 19 11:30:24 2022 +0200 @@ -58,6 +58,8 @@ void openEdit_Setpoint(uint8_t line) { uint8_t useSensorSubMenu = 0; + char text[20]; + uint8_t sensorActive[3]; /* dive mode */ if(actual_menu_content != MENU_SURFACE) @@ -66,7 +68,7 @@ setpointCbar = 100; // actualGasID - if(stateUsedWrite->diveSettings.diveMode != DIVEMODE_CCR) + if(!isLoopMode(stateUsedWrite->diveSettings.diveMode)) { actualGasID = stateUsedWrite->lifeData.lastDiluent_GasIdInSettings; if((actualGasID <= NUM_OFFSET_DILUENT) || (actualGasID > NUM_GASES + NUM_OFFSET_DILUENT)) @@ -76,7 +78,7 @@ actualGasID = stateUsedWrite->lifeData.actualGas.GasIdInSettings; // setpointCbar, CCR_Mode and sensor menu - if(line < 6) + if((line < 6) && (stateUsedWrite->diveSettings.diveMode != DIVEMODE_PSCR)) /* setpoints inactive in PSCR mode */ { setpointCbar = stateUsedWrite->diveSettings.setpoint[line].setpoint_cbar; stateUsedWrite->diveSettings.CCR_Mode = CCRMODE_FixedSetpoint; @@ -96,25 +98,32 @@ stateUsedWrite->diveSettings.setpoint[line].note.ub.first = 1; } } - else + else /* menu item not pointing to setpoint selection => use sensor or ppo2 simulation */ { - if(stateUsedWrite->diveSettings.CCR_Mode != CCRMODE_Sensors) - { - /* setpoint_cbar will be written by updateSetpointStateUsed() in main.c loop */ - setpointCbar = 255; - stateUsedWrite->diveSettings.CCR_Mode = CCRMODE_Sensors; - } - else - { - useSensorSubMenu = 1; - } + if((stateUsedWrite->diveSettings.diveMode == DIVEMODE_PSCR) && (line == 2)) + { + stateUsedWrite->diveSettings.CCR_Mode = CCRMODE_Simulation; + } + else /* => use sensor */ + { + if(stateUsedWrite->diveSettings.CCR_Mode != CCRMODE_Sensors) + { + /* setpoint_cbar will be written by updateSetpointStateUsed() in main.c loop */ + setpointCbar = 255; + stateUsedWrite->diveSettings.CCR_Mode = CCRMODE_Sensors; + } + else + { + useSensorSubMenu = 1; + } + } } setActualGas_DM(&stateUsedWrite->lifeData,actualGasID,setpointCbar); - if(stateUsedWrite->diveSettings.diveMode != DIVEMODE_CCR) + if(!isLoopMode(stateUsedWrite->diveSettings.diveMode)) { - stateUsedWrite->diveSettings.diveMode = DIVEMODE_CCR; + stateUsedWrite->diveSettings.diveMode = settingsGetPointer()->dive_mode; unblock_diluent_page(); } @@ -129,9 +138,6 @@ set_globalState_Menu_Line(line); resetMenuEdit(CLUT_MenuPageGasSP); - char text[20]; - uint8_t sensorActive[3]; - text[0] = '\001'; text[1] = TXT_o2Sensors; text[2] = 0; @@ -145,6 +151,7 @@ else { snprintf (text,20,"Sensor 1 (%01.2f)", stateUsed->lifeData.ppO2Sensor_bar[0] ); + sensorActive[0] = 1; } write_label_var( 96, 600, ME_Y_LINE1, &FontT48, text); if(stateUsedWrite->diveSettings.ppo2sensors_deactivated & 2) @@ -155,6 +162,7 @@ else { snprintf (text,20,"Sensor 2 (%01.2f)", stateUsed->lifeData.ppO2Sensor_bar[1] ); + sensorActive[1] = 1; } write_label_var( 96, 600, ME_Y_LINE2, &FontT48, text); if(stateUsedWrite->diveSettings.ppo2sensors_deactivated & 4) @@ -165,13 +173,10 @@ else { snprintf (text,20,"Sensor 3 (%01.2f)", stateUsed->lifeData.ppO2Sensor_bar[2] ); + sensorActive[2] = 1; } write_label_var( 96, 600, ME_Y_LINE3, &FontT48, text); - sensorActive[0] = 1; - sensorActive[1] = 1; - sensorActive[2] = 1; - write_field_on_off(StMSP_Sensor1, 30, 95, ME_Y_LINE1, &FontT48, "", sensorActive[0]); write_field_on_off(StMSP_Sensor2, 30, 95, ME_Y_LINE2, &FontT48, "", sensorActive[1]); write_field_on_off(StMSP_Sensor3, 30, 95, ME_Y_LINE3, &FontT48, "", sensorActive[2]); @@ -329,23 +334,26 @@ uint8_t spId; uint8_t depth; - spId = actualBetterSetpointId(); - - depth = stateUsedWrite->diveSettings.setpoint[spId].depth_meter; - - // BetterSetpoint warning only once -> clear active - for(int i=0; i<=NUM_GASES; i++) + if(stateUsedWrite->diveSettings.diveMode != DIVEMODE_PSCR) /* no setpoints in PSCR mode */ { - stateUsedWrite->diveSettings.setpoint[i].note.ub.first = 0; - if(stateUsedWrite->diveSettings.setpoint[i].depth_meter <= depth) - stateUsedWrite->diveSettings.setpoint[i].note.ub.active = 0; - } + spId = actualBetterSetpointId(); + + depth = stateUsedWrite->diveSettings.setpoint[spId].depth_meter; - // new setpoint - stateUsedWrite->diveSettings.setpoint[spId].note.ub.first = 1; + // BetterSetpoint warning only once -> clear active + for(int i=0; i<=NUM_GASES; i++) + { + stateUsedWrite->diveSettings.setpoint[i].note.ub.first = 0; + if(stateUsedWrite->diveSettings.setpoint[i].depth_meter <= depth) + stateUsedWrite->diveSettings.setpoint[i].note.ub.active = 0; + } - // change in lifeData - setActualGas_DM(&stateUsedWrite->lifeData, stateUsedWrite->lifeData.actualGas.GasIdInSettings, stateUsedWrite->diveSettings.setpoint[spId].setpoint_cbar); + // new setpoint + stateUsedWrite->diveSettings.setpoint[spId].note.ub.first = 1; + + // change in lifeData + setActualGas_DM(&stateUsedWrite->lifeData, stateUsedWrite->lifeData.actualGas.GasIdInSettings, stateUsedWrite->diveSettings.setpoint[spId].setpoint_cbar); + } } static uint8_t OnAction_SP_DM_Sensor1 (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) diff -r 87bee7cc77b3 -r cc542448fb28 Discovery/Src/tMenuEditSystem.c --- a/Discovery/Src/tMenuEditSystem.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Discovery/Src/tMenuEditSystem.c Fri Aug 19 11:30:24 2022 +0200 @@ -1081,7 +1081,7 @@ #endif - if(stateRealGetPointer()->lifeData.battery_charge == 0) + if(stateRealGetPointer()->lifeData.battery_charge <= 0) { text[0] = TXT_2BYTE; text[1] = TXT2BYTE_SetBatteryCharge; diff -r 87bee7cc77b3 -r cc542448fb28 Discovery/Src/tMenuEditXtra.c --- a/Discovery/Src/tMenuEditXtra.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Discovery/Src/tMenuEditXtra.c Fri Aug 19 11:30:24 2022 +0200 @@ -35,6 +35,7 @@ #include "tMenuEdit.h" #include "data_exchange_main.h" #include "motion.h" +#include "configuration.h" /* Private function prototypes -----------------------------------------------*/ @@ -47,10 +48,26 @@ static void openEdit_ScrubberTimer(uint8_t line); static void openEdit_ScrubberReset(void); static void openEdit_ScrubberTimerMode(void); +#ifdef ENABLE_PSCR_MODE +static void openEdit_PSCRO2Drop(uint8_t line); +static void openEdit_PSCRLungRatio(uint8_t line); +#endif +#ifdef ENABLE_CO2_SUPPORT +static void openEdit_CO2Sensor(void); +#endif /* Announced function prototypes -----------------------------------------------*/ uint8_t OnAction_CompassHeading (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); static uint8_t OnAction_ScrubberTimer(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); +#ifdef ENABLE_PSCR_MODE +static uint8_t OnAction_PSCRO2Drop(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); +static uint8_t OnAction_PSCRLungRation(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); +#endif + +#ifdef ENABLE_CO2_SUPPORT +static uint8_t OnAction_CO2OnOff(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); +static uint8_t OnAction_CO2Calib(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); +#endif /* Exported functions --------------------------------------------------------*/ @@ -91,6 +108,11 @@ } else /* surface mode */ { + if((settingsGetPointer()->dive_mode != DIVEMODE_PSCR) && (line > 3)) /* PSCR items are only optional */ + { + line = 6; + } + switch(line) { case 1: openEdit_ScrubberTimer(line); @@ -99,6 +121,16 @@ break; case 3: openEdit_ScrubberTimerMode(); break; +#ifdef ENABLE_PSCR_MODE + case 4: openEdit_PSCRO2Drop(line); + break; + case 5: openEdit_PSCRLungRatio(line); + break; +#endif +#ifdef ENABLE_CO2_SUPPORT + case 6: openEdit_CO2Sensor(); + break; +#endif default: break; } @@ -191,6 +223,103 @@ exitMenuEdit_to_Menu_with_Menu_Update(); } +#ifdef ENABLE_PSCR_MODE +static void openEdit_PSCRO2Drop(uint8_t line) +{ + uint8_t localO2Drop; + uint16_t y_line; + + char text[32]; + SSettings *pSettings = settingsGetPointer(); + localO2Drop = pSettings->pscr_o2_drop; + + y_line = ME_Y_LINE_BASE + (line * ME_Y_LINE_STEP); + + text[0] = '\001'; + text[1] = TXT_PSCRO2Drop; + text[2] = 0; + write_topline(text); + + text[0] = '\002'; + text[1] = '\016'; + text[2] = '\016'; + text[3] = '%'; + text[4] = 0; + write_label_fix( 20, 800, y_line, &FontT48, TXT_PSCRO2Drop); + write_label_var( 435, 780, y_line, &FontT48, text); + write_field_udigit(StMXTRA_PSCR_O2_Drop, 710, 779, y_line, &FontT48, "##", (uint32_t)localO2Drop, 0, 0, 0); + + write_buttonTextline(TXT2BYTE_ButtonMinus,TXT2BYTE_ButtonEnter,TXT2BYTE_ButtonPlus); + + setEvent(StMXTRA_PSCR_O2_Drop, (uint32_t)OnAction_PSCRO2Drop); + startEdit(); +} + +static void openEdit_PSCRLungRatio(uint8_t line) +{ + uint8_t localLungRatio; + uint16_t y_line; + + char text[32]; + SSettings *pSettings = settingsGetPointer(); + localLungRatio = pSettings->pscr_lung_ratio; + + y_line = ME_Y_LINE_BASE + (line * ME_Y_LINE_STEP); + + text[0] = '\001'; + text[1] = TXT_PSCRO2Drop; + text[2] = 0; + write_topline(text); + + text[0] = '\002'; + text[1] = '1'; + text[2] = '/'; + text[3] = 0; + + write_label_fix( 20, 800, y_line, &FontT48, TXT_PSCRLungRatio); + write_label_var( 435, 710, y_line, &FontT48, text); + write_field_udigit(StMXTRA_PSCR_LUNG_RATIO, 710, 779, y_line, &FontT48, "##", (uint32_t)localLungRatio, 0, 0, 0); + + write_buttonTextline(TXT2BYTE_ButtonMinus,TXT2BYTE_ButtonEnter,TXT2BYTE_ButtonPlus); + + setEvent(StMXTRA_PSCR_LUNG_RATIO, (uint32_t)OnAction_PSCRLungRation); + startEdit(); +} +#endif + +#ifdef ENABLE_CO2_SUPPORT +static void openEdit_CO2Sensor() +{ + char text[32]; + snprintf(text,32,"\001%c",TXT_CO2Sensor); + write_topline(text); + + refresh_CO2Data(); + if(settingsGetPointer()->co2_sensor_active) + { + text[0] = '\005'; + } + else + { + text[0] = '\006'; + } + text[0] = TXT_CO2Sensor; + text[1] = 0; + + write_field_on_off(StMXTRA_CO2_Sensor, 30, 95, ME_Y_LINE3, &FontT48, text, settingsGetPointer()->co2_sensor_active); + + text[0] = TXT_2BYTE; + text[1] = TXT2BYTE_O2Calib; + text[2] = 0; + write_field_button(StMXTRA_CO2_Sensor_Calib,30, 800, ME_Y_LINE4, &FontT48, text); + + setEvent(StMXTRA_CO2_Sensor, (uint32_t)OnAction_CO2OnOff); + setEvent(StMXTRA_CO2_Sensor_Calib, (uint32_t)OnAction_CO2Calib); + + write_buttonTextline(TXT2BYTE_ButtonBack,TXT2BYTE_ButtonEnter,TXT2BYTE_ButtonNext); +} +#endif + void refresh_CompassHeading(void) { uint16_t heading; @@ -209,6 +338,23 @@ tMenuEdit_refresh_field(StMXTRA_CompassHeading); } +void refresh_CO2Data(void) +{ + char text[32]; + + snprintf(text,32,"\001%c",TXT_CO2Sensor); + write_topline(text); + + snprintf(text,32,"CO2: %d ppm",stateUsed->lifeData.CO2_data.CO2_ppm); + write_label_var( 30, 800, ME_Y_LINE1, &FontT48, text); + + snprintf(text,32,"Signal: %d",stateUsed->lifeData.CO2_data.signalStrength); + write_label_var( 30, 800, ME_Y_LINE2, &FontT48, text); + + tMenuEdit_refresh_field(StMXTRA_CO2_Sensor); + tMenuEdit_refresh_field(StMXTRA_CO2_Sensor_Calib); +} + void openEdit_CompassHeading(void) { @@ -267,4 +413,107 @@ } return digitContentNew; } +#ifdef ENABLE_PSCR_MODE +static uint8_t OnAction_PSCRO2Drop(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) +{ + SSettings *pSettings; + uint8_t digitContentNew = EXIT_TO_MENU; + uint32_t newO2Drop; + if(action == ACTION_BUTTON_ENTER) + { + return digitContent; + } + if(action == ACTION_BUTTON_ENTER_FINAL) + { + evaluateNewString(editId, &newO2Drop, 0, 0, 0); + + if(newO2Drop > PSCR_MAX_O2_DROP) + newO2Drop = PSCR_MAX_O2_DROP; + + pSettings = settingsGetPointer(); + pSettings->pscr_o2_drop = newO2Drop; + + tMenuEdit_newInput(editId, newO2Drop, 0, 0, 0); + digitContentNew = UPDATE_AND_EXIT_TO_MENU; + } + if(action == ACTION_BUTTON_NEXT) + { + digitContentNew = digitContent + 1; + if(digitContentNew > '9') + digitContentNew = '0'; + } + if(action == ACTION_BUTTON_BACK) + { + digitContentNew = digitContent - 1; + if(digitContentNew < '0') + digitContentNew = '9'; + } + return digitContentNew; +} + +static uint8_t OnAction_PSCRLungRation(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) +{ + SSettings *pSettings; + uint8_t digitContentNew = EXIT_TO_MENU; + uint32_t newLungRatio; + + if(action == ACTION_BUTTON_ENTER) + { + return digitContent; + } + if(action == ACTION_BUTTON_ENTER_FINAL) + { + evaluateNewString(editId, &newLungRatio, 0, 0, 0); + + if(newLungRatio > PSCR_MAX_LUNG_RATIO) + newLungRatio = PSCR_MAX_LUNG_RATIO; + + if(newLungRatio < PSCR_MIN_LUNG_RATIO) + newLungRatio = PSCR_MIN_LUNG_RATIO; + + pSettings = settingsGetPointer(); + pSettings->pscr_lung_ratio = newLungRatio; + + tMenuEdit_newInput(editId, newLungRatio, 0, 0, 0); + digitContentNew = UPDATE_AND_EXIT_TO_MENU; + } + if(action == ACTION_BUTTON_NEXT) + { + digitContentNew = digitContent + 1; + if(digitContentNew > '9') + digitContentNew = '0'; + } + if(action == ACTION_BUTTON_BACK) + { + digitContentNew = digitContent - 1; + if(digitContentNew < '0') + digitContentNew = '9'; + } + return digitContentNew; +} +#endif + +#ifdef ENABLE_CO2_SUPPORT +static uint8_t OnAction_CO2OnOff(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) +{ + SSettings *pSettings = settingsGetPointer(); + if(pSettings->co2_sensor_active) + { + pSettings->co2_sensor_active = 0; + tMenuEdit_set_on_off(StMXTRA_CO2_Sensor,0); + } + else + { + pSettings->co2_sensor_active = 1; + tMenuEdit_set_on_off(StMXTRA_CO2_Sensor,1); + } + return UPDATE_DIVESETTINGS; +} + +static uint8_t OnAction_CO2Calib(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) +{ + DataEX_setExtInterface_Cmd(EXT_INTERFACE_CO2_CALIB); + return UPDATE_DIVESETTINGS; +} +#endif diff -r 87bee7cc77b3 -r cc542448fb28 Discovery/Src/tMenuGas.c --- a/Discovery/Src/tMenuGas.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Discovery/Src/tMenuGas.c Fri Aug 19 11:30:24 2022 +0200 @@ -55,7 +55,7 @@ } else { - if (stateUsed->diveSettings.diveMode == DIVEMODE_CCR) + if (isLoopMode(stateUsed->diveSettings.diveMode)) gas_mode = OCGAS_BAILOUT_INACTIVE; else gas_mode = OCGAS_BAILOUT_ACTIVE; @@ -328,7 +328,7 @@ text[textPointer++] = 0; } else /* switch to bailout selection in surface mode */ - if((settingsGetPointer()->dive_mode == DIVEMODE_CCR) || (stateUsed->diveSettings.ccrOption == 1)) + if((isLoopMode(settingsGetPointer()->dive_mode)) || (stateUsed->diveSettings.ccrOption == 1)) { text[textPointer++] = '\024'; if(gasMode == CCGAS_STANDARD) diff -r 87bee7cc77b3 -r cc542448fb28 Discovery/Src/tMenuPlanner.c --- a/Discovery/Src/tMenuPlanner.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Discovery/Src/tMenuPlanner.c Fri Aug 19 11:30:24 2022 +0200 @@ -130,14 +130,14 @@ text[textPointer++] = '\t'; textPointer += snprintf(&text[textPointer],30, "%u" - "\016\016 l\\min\017", + "\016\016 l/min\017", tMplan_gasConsumTravel); text[textPointer++] = ' '; text[textPointer++] = ' '; textPointer += snprintf(&text[textPointer],30, "\016\016deco\017" " %u" - "\016\016 l\\min\017", + "\016\016 l/min\017", tMplan_gasConsumDeco); } strcpy(&text[textPointer],"\n\r"); diff -r 87bee7cc77b3 -r cc542448fb28 Discovery/Src/tMenuSetpoint.c --- a/Discovery/Src/tMenuSetpoint.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Discovery/Src/tMenuSetpoint.c Fri Aug 19 11:30:24 2022 +0200 @@ -53,76 +53,79 @@ *tab = 130; *subtext = 0; - for(int spId=1;spId<=NUM_GASES;spId++) + if((actual_menu_content == MENU_SURFACE) || (stateUsed->diveSettings.diveMode != DIVEMODE_PSCR)) /* do not show setpoints in PSCR mode */ { - if(line && (line != spId)) - { - first = pSetpointLine[spId].note.ub.first; - if(first == 0) - { - strcpy(&text[textPointer], - "\t" - "\177" - "*" - "\n\r" - ); - textPointer += 5; - } - else - { - strcpy(&text[textPointer],"\n\r"); - textPointer += 2; - } - } - else - { - setpoint_cbar = pSetpointLine[spId].setpoint_cbar; - depthUp = pSetpointLine[spId].depth_meter; - //active = pSetpointLine[spId].note.ub.active; - first = pSetpointLine[spId].note.ub.first; + for(int spId=1;spId<=NUM_GASES;spId++) + { + if(line && (line != spId)) + { + first = pSetpointLine[spId].note.ub.first; + if(first == 0) + { + strcpy(&text[textPointer], + "\t" + "\177" + "*" + "\n\r" + ); + textPointer += 5; + } + else + { + strcpy(&text[textPointer],"\n\r"); + textPointer += 2; + } + } + else + { + setpoint_cbar = pSetpointLine[spId].setpoint_cbar; + depthUp = pSetpointLine[spId].depth_meter; + //active = pSetpointLine[spId].note.ub.active; + first = pSetpointLine[spId].note.ub.first; - strcpy(&text[textPointer],"\020"); // if(active) always active - textPointer += 1; + strcpy(&text[textPointer],"\020"); // if(active) always active + textPointer += 1; - sp_high = setpoint_cbar / 100; + sp_high = setpoint_cbar / 100; - text[textPointer++] = 'S'; - text[textPointer++] = 'P'; - text[textPointer++] = '0' + spId; - text[textPointer++] = '\t'; + text[textPointer++] = 'S'; + text[textPointer++] = 'P'; + text[textPointer++] = '0' + spId; + text[textPointer++] = '\t'; - if((first == 0) || (actual_menu_content != MENU_SURFACE)) - strcpy(&text[textPointer++],"\177"); + if((first == 0) || (actual_menu_content != MENU_SURFACE)) + strcpy(&text[textPointer++],"\177"); - char color = '\031'; - if(depthUp) - color = '\020'; + char color = '\031'; + if(depthUp) + color = '\020'; - textPointer += snprintf(&text[textPointer], 57, - "* " - "%u.%02u" - "\016\016" - " bar" - "\017" - "\034" - " " - "\016\016" - " " - "\017" - "%c" - "%3u" - "\016\016" - " %c%c" - "\017" - "\035" - "\n\r", - sp_high, setpoint_cbar - (100 * sp_high), - color, - unit_depth_integer(depthUp), - unit_depth_char1(), - unit_depth_char2() - ); - } + textPointer += snprintf(&text[textPointer], 57, + "* " + "%u.%02u" + "\016\016" + " bar" + "\017" + "\034" + " " + "\016\016" + " " + "\017" + "%c" + "%3u" + "\016\016" + " %c%c" + "\017" + "\035" + "\n\r", + sp_high, setpoint_cbar - (100 * sp_high), + color, + unit_depth_integer(depthUp), + unit_depth_char1(), + unit_depth_char2() + ); + } + } } if((actual_menu_content != MENU_SURFACE) /*&& (line == 0)*/) { @@ -131,6 +134,12 @@ text[textPointer++] = TXT2BYTE_UseSensor; text[textPointer++] = '\n'; text[textPointer++] = '\r'; + + + if(stateUsed->diveSettings.diveMode == DIVEMODE_PSCR) + { + textPointer += snprintf(&text[textPointer], 20,"\020%c", TXT_SimPpo2); + } text[textPointer++] = 0; } else diff -r 87bee7cc77b3 -r cc542448fb28 Discovery/Src/tMenuXtra.c --- a/Discovery/Src/tMenuXtra.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Discovery/Src/tMenuXtra.c Fri Aug 19 11:30:24 2022 +0200 @@ -47,6 +47,8 @@ *tab = 500; *subtext = 0; + SSettings *pSettings = settingsGetPointer(); + /* DIVE MODE */ if(actual_menu_content != MENU_SURFACE) { @@ -133,7 +135,7 @@ "\017" ,TXT_ScrubTime ,TXT_Maximum - ,settingsGetPointer()->scrubTimerMax + ,pSettings->scrubTimerMax ,TXT_Minutes ); } @@ -144,14 +146,14 @@ textPointer += snprintf(&text[textPointer], 60,\ "%c\002%03u\016\016 %c\017" ,TXT_ScrubTimeReset - ,settingsGetPointer()->scrubTimerCur + ,pSettings->scrubTimerCur ,TXT_Minutes); } strcpy(&text[textPointer],"\n\r"); textPointer += 2; if((line == 0) || (line == 3)) { - switch(settingsGetPointer()->scrubTimerMode) + switch(pSettings->scrubTimerMode) { case SCRUB_TIMER_OFF: default: textPointer += snprintf(&text[textPointer], 60,"%c\002%c%c",TXT_ScrubTimeMode, TXT_2BYTE, TXT2BYTE_MoCtrlNone ); @@ -165,6 +167,35 @@ strcpy(&text[textPointer],"\n\r"); textPointer += 2; +#ifdef ENABLE_PSCR_MODE + if(pSettings->dive_mode == DIVEMODE_PSCR) + { + if((line == 0) || (line == 4)) + { + textPointer += snprintf(&text[textPointer], 60,\ + "%c\002%02u\016\016%%\017" + ,TXT_PSCRO2Drop + ,pSettings->pscr_o2_drop); + } + strcpy(&text[textPointer],"\n\r"); + textPointer += 2; + if((line == 0) || (line == 5)) + { + textPointer += snprintf(&text[textPointer], 60,\ + "%c\002 1/%02u" + ,TXT_PSCRLungRatio + ,pSettings->pscr_lung_ratio); + } + strcpy(&text[textPointer],"\n\r"); + textPointer += 2; + } +#endif +#ifdef ENABLE_CO2_SUPPORT + if((line == 0) || (line == 6)) + { + textPointer += snprintf(&text[textPointer], 60, "%c", TXT_CO2Sensor); + } +#endif } return StMXTRA; } diff -r 87bee7cc77b3 -r cc542448fb28 Discovery/Src/text_multilanguage.c --- a/Discovery/Src/text_multilanguage.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Discovery/Src/text_multilanguage.c Fri Aug 19 11:30:24 2022 +0200 @@ -453,11 +453,17 @@ static uint8_t text_IT_ClosedCircuit[] = "Ciurcuito chiuso"; static uint8_t text_ES_ClosedCircuit[] = "Circuito cerrado"; -static uint8_t text_EN_Time[] = "Time"; -static uint8_t text_DE_Time[] = "Uhrzeit"; -static uint8_t text_FR_Time[] = "Heure"; -static uint8_t text_IT_Time[] = "Ora"; -static uint8_t text_ES_Time[] = "Hora"; +static uint8_t text_EN_PSClosedCircuit[] = "PSC circuit"; +static uint8_t text_DE_PSClosedCircuit[] = "PSC Kreislauf"; +static uint8_t text_FR_PSClosedCircuit[] = "PSC circuit"; +static uint8_t text_IT_PSClosedCircuit[] = "PSC circuit"; +static uint8_t text_ES_PSClosedCircuit[] = "PSC circuit"; + +static uint8_t text_EN_ChargeHour[] = "Hour(s) till 100%"; +static uint8_t text_DE_ChargeHour[] = "Stunde(n) bis 100%"; +static uint8_t text_FR_ChargeHour[] = ""; +static uint8_t text_IT_ChargeHour[] = ""; +static uint8_t text_ES_ChargeHour[] = ""; static uint8_t text_EN_Date[] = "Date"; static uint8_t text_DE_Date[] = "Datum"; @@ -1134,6 +1140,13 @@ static uint8_t text_IT_Warning[] = "Pericolo"; static uint8_t text_ES_Warning[] = "Peligro"; +// Customview Header +static uint8_t text_EN_Charging[] = "Charging"; +static uint8_t text_DE_Charging[] = "Ladezyklus"; +static uint8_t text_FR_Charging[] = ""; +static uint8_t text_IT_Charging[] = ""; +static uint8_t text_ES_Charging[] = ""; + // Menu SYS2 sub Information static uint8_t text_EN_Usage_Battery[] = "Battery life"; static uint8_t text_DE_Usage_Battery[] = "Batterie-Nutzung"; @@ -1704,6 +1717,37 @@ static uint8_t text_IT_Percent[] = "Percent"; static uint8_t text_ES_Percent[] = "Percent"; +static uint8_t text_EN_PSCRO2Drop[] = "PSCR O2 drop"; +static uint8_t text_DE_PSCRO2Drop[] = "PSCR O2 Abfall"; +static uint8_t text_FR_PSCRO2Drop[] = "PSCR O2 drop"; +static uint8_t text_IT_PSCRO2Drop[] = "PSCR O2 drop"; +static uint8_t text_ES_PSCRO2Drop[] = "PSCR O2 drop"; + +static uint8_t text_EN_LungRatio[] = "PSCR lung ratio"; +static uint8_t text_DE_LungRatio[] = "PSCR Lungen Faktor"; +static uint8_t text_FR_LungRatio[] = "PSCR lung ratio"; +static uint8_t text_IT_LungRatio[] = "PSCR lung ratio"; +static uint8_t text_ES_LungRatio[] = "PSCR lung ratio"; + +static uint8_t text_EN_CheckSettings[] = "Check settings"; +static uint8_t text_DE_CheckSettings[] = "Prüfe Optionen"; +static uint8_t text_FR_CheckSettings[] = "Check settings"; +static uint8_t text_IT_CheckSettings[] = "Check settings"; +static uint8_t text_ES_CheckSettings[] = "Check settings"; + +static uint8_t text_EN_SimPpo2[] = "Sim ppO2"; +static uint8_t text_DE_SimPpo2[] = "Sim ppO2"; +static uint8_t text_FR_SimPpo2[] = "Sim ppO2"; +static uint8_t text_IT_SimPpo2[] = "Sim ppO2"; +static uint8_t text_ES_SimPpo2[] = "Sim ppO2"; + +static uint8_t text_EN_CO2Sensor[] = "CO2 Sensor"; +static uint8_t text_DE_CO2Sensor[] = "CO2 Sensor"; +static uint8_t text_FR_CO2Sensor[] = "CO2 Sensor"; +static uint8_t text_IT_CO2Sensor[] = "CO2 Sensor"; +static uint8_t text_ES_CO2Sensor[] = "CO2 Sensor"; + + /* Lookup Table -------------------------------------------------------------*/ const tText text_array[] = @@ -1725,10 +1769,11 @@ {(uint8_t)TXT_ActualGradient, {text_EN_ActualGradient, text_DE_ActualGradient, text_FR_ActualGradient, text_IT_ActualGradient, text_ES_ActualGradient}}, {(uint8_t)TXT_Stopwatch, {text_EN_Stopwatch, text_DE_Stopwatch, text_FR_Stopwatch, text_IT_Stopwatch, text_ES_Stopwatch}}, {(uint8_t)TXT_Gas, {text_EN_Gas, text_DE_Gas, text_FR_Gas, text_IT_Gas, text_ES_Gas}}, - {(uint8_t)TXT_Time, {text_EN_Time, text_DE_Time, text_FR_Time, text_IT_Time, text_ES_Time}}, + {(uint8_t)TXT_ChargeHour, {text_EN_ChargeHour, text_DE_ChargeHour, text_FR_ChargeHour, text_IT_ChargeHour, text_ES_ChargeHour}}, {(uint8_t)TXT_Date, {text_EN_Date, text_DE_Date, text_FR_Date, text_IT_Date, text_ES_Date}}, {(uint8_t)TXT_Format, {text_EN_Format, text_DE_Format, text_FR_Format, text_IT_Format, text_ES_Format}}, {(uint8_t)TXT_Warning, {text_EN_Warning, text_DE_Warning, text_FR_Warning, text_IT_Warning, text_ES_Warning}}, + {(uint8_t)TXT_Charging, {text_EN_Charging, text_DE_Charging, text_FR_Charging, text_IT_Charging, text_ES_Charging}}, {(uint8_t)TXT_o2Sensors, {text_EN_o2Sensors, text_DE_o2Sensors, text_FR_o2Sensors, text_IT_o2Sensors, text_ES_o2Sensors}}, {(uint8_t)TXT_Brightness, {text_EN_Brightness, text_DE_Brightness, text_FR_Brightness, text_IT_Brightness, text_ES_Brightness}}, {(uint8_t)TXT_Cave, {text_EN_Cave, text_DE_Cave, text_FR_Cave, text_IT_Cave, text_ES_Cave}}, @@ -1770,7 +1815,8 @@ {(uint8_t)TXT_ClosedCircuit, {text_EN_ClosedCircuit, text_DE_ClosedCircuit, text_FR_ClosedCircuit, text_IT_ClosedCircuit, text_ES_ClosedCircuit}}, {(uint8_t)TXT_Apnoe, {text_EN_Apnoe, text_DE_Apnoe, text_FR_Apnoe, text_IT_Apnoe, text_ES_Apnoe}}, {(uint8_t)TXT_Gauge, {text_EN_Gauge, text_DE_Gauge, text_FR_Gauge, text_IT_Gauge, text_ES_Gauge}}, - {(uint8_t)TXT_Sensor, {text_EN_Sensor, text_DE_Sensor, text_FR_Sensor, text_IT_Sensor, text_ES_Sensor}}, + {(uint8_t)TXT_PSClosedCircuit, {text_EN_PSClosedCircuit, text_DE_PSClosedCircuit, text_FR_PSClosedCircuit, text_IT_PSClosedCircuit, text_ES_PSClosedCircuit}}, + {(uint8_t)TXT_Sensor, {text_EN_Sensor, text_DE_Sensor, text_FR_Sensor, text_IT_Sensor, text_ES_Sensor}}, {(uint8_t)TXT_FixedSP, {text_EN_FixedSP, text_DE_FixedSP, text_FR_FixedSP, text_IT_FixedSP, text_ES_FixedSP}}, {(uint8_t)TXT_Decoparameters, {text_EN_Decoparameters, text_DE_Decoparameters, text_FR_Decoparameters, text_IT_Decoparameters, text_ES_Decoparameters}}, {(uint8_t)TXT_LastDecostop, {text_EN_LastDecostop, text_DE_LastDecostop, text_FR_LastDecostop, text_IT_LastDecostop, text_ES_LastDecostop}}, @@ -1787,7 +1833,10 @@ {(uint8_t)TXT_ScrubTimeReset, {text_EN_ScrubTimeReset, text_DE_ScrubTimeReset, text_FR_ScrubTimeReset, text_IT_ScrubTimeReset, text_ES_ScrubTimeReset}}, {(uint8_t)TXT_ScrubTimeMode, {text_EN_ScrubTimeMode, text_DE_ScrubTimeMode, text_FR_ScrubTimeMode, text_IT_ScrubTimeMode, text_ES_ScrubTimeMode}}, {(uint8_t)TXT_Percent, {text_EN_Percent, text_DE_Percent, text_FR_Percent, text_IT_Percent, text_ES_Percent}}, - + {(uint8_t)TXT_PSCRO2Drop, {text_EN_PSCRO2Drop, text_DE_PSCRO2Drop, text_FR_PSCRO2Drop, text_IT_PSCRO2Drop, text_ES_PSCRO2Drop}}, + {(uint8_t)TXT_PSCRLungRatio, {text_EN_LungRatio, text_DE_LungRatio, text_FR_LungRatio, text_IT_LungRatio, text_ES_LungRatio}}, + {(uint8_t)TXT_SimPpo2, {text_EN_SimPpo2, text_DE_SimPpo2, text_FR_SimPpo2, text_IT_SimPpo2, text_ES_SimPpo2}}, + {(uint8_t)TXT_CO2Sensor, {text_EN_CO2Sensor, text_DE_CO2Sensor, text_FR_CO2Sensor, text_IT_CO2Sensor, text_ES_CO2Sensor}}, }; const tText text_array2[] = @@ -1955,4 +2004,8 @@ {(uint8_t)TXT2BYTE_Minimum, {text_EN_Minimum, text_DE_Minimum, text_FR_Minimum, text_IT_Minimum, text_ES_Minimum}}, {(uint8_t)TXT2BYTE_Normal, {text_EN_Normal, text_DE_Normal, text_FR_Normal, text_IT_Normal, text_ES_Normal}}, {(uint8_t)TXT2BYTE_Maximum, {text_EN_Maximum, text_DE_Maximum, text_FR_Maximum, text_IT_Maximum, text_ES_Maximum}}, + + {(uint8_t)TXT2BYTE_CheckSettings, {text_EN_CheckSettings, text_DE_CheckSettings, text_FR_CheckSettings, text_IT_CheckSettings, text_ES_CheckSettings}}, + + }; diff -r 87bee7cc77b3 -r cc542448fb28 Small_CPU/Inc/batteryCharger.h --- a/Small_CPU/Inc/batteryCharger.h Mon Nov 01 12:39:34 2021 +0100 +++ b/Small_CPU/Inc/batteryCharger.h Fri Aug 19 11:30:24 2022 +0200 @@ -31,9 +31,30 @@ /* Includes ------------------------------------------------------------------*/ #include -uint8_t get_charge_status(void); +#define CHARGE_IN_PIN GPIO_PIN_2 +#define CHARGE_IN_GPIO_PORT GPIOC +#define CHARGE_IN_GPIO_ENABLE() __GPIOC_CLK_ENABLE() + +#define CHARGE_OUT_PIN GPIO_PIN_1 +#define CHARGE_OUT_GPIO_PORT GPIOC +#define CHARGE_OUT_GPIO_ENABLE() __GPIOC_CLK_ENABLE() + typedef enum + { + Charger_NotConnected = 0, /* This is identified reading CHARGE_IN_PIN == HIGH */ + Charger_WarmUp, /* Charging started but counter did not yet reach a certain limit (used to debounce connect / disconnect events to avoid multiple increases of statistic charging cycle counter) */ + Charger_Active, /* Charging identified by CHARGE_IN_PIN == LOW for a certain time */ + Charger_Finished, + Charger_LostConnection, /* Intermediate state to debounce disconnecting events (including charging error state like over temperature) */ + Charger_ColdStart, /* Cold start condition => check if an loaded battery has been inserted */ + Charger_END + } chargerState_t; + + +uint8_t get_charge_status(void); void init_battery_charger_status(void); +void set_charge_state(chargerState_t newState); +uint8_t get_charge_state(void); void ReInit_battery_charger_status_pins(void); void DeInit_battery_charger_status_pins(void); void battery_charger_get_status_and_contral_battery_gas_gauge(uint8_t cycleTimeBase); diff -r 87bee7cc77b3 -r cc542448fb28 Small_CPU/Inc/batteryGasGauge.h --- a/Small_CPU/Inc/batteryGasGauge.h Mon Nov 01 12:39:34 2021 +0100 +++ b/Small_CPU/Inc/batteryGasGauge.h Fri Aug 19 11:30:24 2022 +0200 @@ -31,6 +31,12 @@ #include +#define BATTERY_DEFAULT_VOLTAGE (6.0f) +#define BATTERY_ENDOF_CHARGE_VOLTAGE (4.05f) +#define BATTERY_CHARGER_CONNECTED_VOLTAGE (4.2f) + +#define BATTERY_CHARGE_UNKNOWN (-1.0f) + void init_battery_gas_gauge(void); float get_voltage(void); @@ -41,6 +47,10 @@ void battery_gas_gauge_set(float percentage); uint8_t battery_gas_gauge_CheckConfigOK(void); +uint8_t battery_gas_gauge_isChargeValueValid(void); +void battery_gas_gauge_setChargeValueValid(void); + + #ifdef __cplusplus } #endif diff -r 87bee7cc77b3 -r cc542448fb28 Small_CPU/Inc/externalInterface.h --- a/Small_CPU/Inc/externalInterface.h Mon Nov 01 12:39:34 2021 +0100 +++ b/Small_CPU/Inc/externalInterface.h Fri Aug 19 11:30:24 2022 +0200 @@ -32,10 +32,27 @@ #define MAX_ADC_CHANNEL (3u) /* number of channels to be read */ #define EXTERNAL_ADC_NO_DATA 0xFF +#define EXT33V_CONTROL_PIN GPIO_PIN_7 /* PortC */ + void externalInterface_Init(void); +void externalInterface_InitPower33(void); uint8_t externalInterface_StartConversion(uint8_t channel); uint8_t externalInterface_ReadAndSwitch(); float externalInterface_CalculateADCValue(uint8_t channel); float getExternalInterfaceChannel(uint8_t channel); +uint8_t setExternalInterfaceChannel(uint8_t channel, float value); +void externalInterface_SwitchPower33(uint8_t state); +void externalInterface_SwitchADC(uint8_t state); +uint8_t externalInterface_isEnabledPower33(void); +uint8_t externalInterface_isEnabledADC(void); + +void externalInterface_SetCO2Value(uint16_t CO2_ppm); +void externalInterface_SetCO2SignalStrength(uint16_t LED_qa); +uint16_t externalInterface_GetCO2Value(void); +uint16_t externalInterface_GetCO2SignalStrength(void); +void externalInterface_SetCO2State(uint16_t state); +uint16_t externalInterface_GetCO2State(void); + +void externalInterface_ExecuteCmd(uint16_t Cmd); #endif /* EXTERNAL_INTERFACE_H */ diff -r 87bee7cc77b3 -r cc542448fb28 Small_CPU/Inc/uart.h --- a/Small_CPU/Inc/uart.h Mon Nov 01 12:39:34 2021 +0100 +++ b/Small_CPU/Inc/uart.h Fri Aug 19 11:30:24 2022 +0200 @@ -24,11 +24,39 @@ #include "stm32f4xx_hal.h" -void MX_USART2_UART_Init(void); -void MX_USART2_UART_DeInit(void); -uint8_t UART_ButtonAdjust(uint8_t *array); + + typedef enum + { + RX_Ready= 0, /* Initial state */ + RX_DetectStart, /* validate start byte */ + RX_SelectData, /* Data contained in this frame */ + RX_Data0, /* Process incoming data */ + RX_Data1, + RX_Data2, + RX_Data3, + RX_Data4, + RX_Data5, + RX_Data6, + RX_Data7, + RX_Data8, + RX_Data9, + RX_Data10, + RX_Data11, + RX_Data12, + RX_DataComplete + } receiveState_t; +void MX_USART1_UART_Init(void); +void MX_USART1_UART_DeInit(void); +void MX_USART1_DMA_Init(void); +uint8_t UART_ButtonAdjust(uint8_t *array); +#ifdef ENABLE_CO2_SUPPORT +void HandleUARTCO2Data(void); +#endif +#ifdef ENABLE_SENTINEL_MODE +void HandleUARTSentinelData(void); +#endif #ifdef __cplusplus } #endif diff -r 87bee7cc77b3 -r cc542448fb28 Small_CPU/Src/baseCPU2.c --- a/Small_CPU/Src/baseCPU2.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Small_CPU/Src/baseCPU2.c Fri Aug 19 11:30:24 2022 +0200 @@ -142,6 +142,7 @@ #include "scheduler.h" #include "tm_stm32f4_otp.h" #include "externalInterface.h" +#include "uart.h" // From Common/Inc: #include "calc_crush.h" @@ -165,16 +166,16 @@ // See CPU2-RTE.ld const SFirmwareData cpu2_FirmwareData __attribute__(( section(".firmware_data") ))= { .versionFirst = 2, - .versionSecond = 7, + .versionSecond = 9, .versionThird = 0, .versionBeta = 0, /* 4 bytes with trailing 0 */ .signature = "mh", - .release_year = 21, - .release_month = 4, - .release_day = 26, + .release_year = 22, + .release_month = 8, + .release_day = 19, .release_sub = 0, /* max 48 with trailing 0 */ @@ -230,6 +231,10 @@ #define WIRELSS_POWER_GPIO_PORT GPIOB #define WIRELSS_POWER_HAL_RCC_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE() + +#define LED_CONTROL_PIN GPIO_PIN_3 /* PortC */ +#define MAINCPU_CONTROL_PIN GPIO_PIN_0 /* PortC */ + /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ @@ -353,12 +358,18 @@ HAL_Delay(10); battery_gas_gauge_get_data(); + global.lifeData.battery_voltage = get_voltage(); + global.lifeData.battery_charge = get_charge(); + copyBatteryData(); + MX_SPI3_Init(); if(coldstart != 0xA5) /* Not reading a 0xA5 means the memory cells has not been initialized before => cold start */ { coldstart = 0xA5; - battery_gas_gauge_set(0); + + set_charge_state(Charger_ColdStart); + global.dataSendToMaster.power_on_reset = 1; global.deviceDataSendToMaster.power_on_reset = 1; @@ -373,13 +384,16 @@ } } } - - global.lifeData.battery_voltage = get_voltage(); - global.lifeData.battery_charge = get_charge(); - copyBatteryData(); + else + { + set_charge_state(Charger_NotConnected); + } ADCx_Init(); GPIO_Power_MainCPU_Init(); + + externalInterface_InitPower33(); + global.mode = MODE_POWERUP; #else init_pressure(); @@ -408,6 +422,7 @@ SPI_synchronize_with_Master(); MX_DMA_Init(); MX_SPI1_Init(); + MX_USART1_UART_Init(); SPI_Start_single_TxRx_with_Master(); /* be prepared for the first data exchange */ Scheduler_Request_sync_with_SPI(SPI_SYNC_METHOD_HARD); EXTI_Test_Button_Init(); @@ -478,7 +493,9 @@ EXTI_Wakeup_Button_Init(); NOT_USED_AT_THE_MOMENT_scheduleSleepMode(); */ + EXTI_Test_Button_DeInit(); + externalInterface_SwitchPower33(false); if (hasExternalClock()) SystemClock_Config_HSI(); sleep_prepare(); @@ -500,6 +517,11 @@ MX_SPI1_Init(); SPI_Start_single_TxRx_with_Master(); + if(externalInterface_isEnabledPower33()) + { + externalInterface_SwitchPower33(true); + } + // EXTILine0_Button_DeInit(); not now, later after testing break; } @@ -793,7 +815,7 @@ GPIO_InitTypeDef GPIO_InitStructure; __GPIOC_CLK_ENABLE(); - GPIO_InitStructure.Pin = GPIO_PIN_3; + GPIO_InitStructure.Pin = LED_CONTROL_PIN; GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStructure.Pull = GPIO_PULLUP; GPIO_InitStructure.Speed = GPIO_SPEED_FAST; @@ -805,7 +827,7 @@ GPIO_InitTypeDef GPIO_InitStructure; __GPIOC_CLK_ENABLE(); - GPIO_InitStructure.Pin = GPIO_PIN_3; + GPIO_InitStructure.Pin = LED_CONTROL_PIN; GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStructure.Pull = GPIO_PULLUP; GPIO_InitStructure.Speed = GPIO_SPEED_FAST; @@ -815,33 +837,33 @@ void GPIO_new_DEBUG_LOW(void) { #ifdef DEBUG_PIN_ACTIVE - HAL_GPIO_WritePin(GPIOC,GPIO_PIN_3,GPIO_PIN_RESET); + HAL_GPIO_WritePin(GPIOC,LED_CONTROL_PIN,GPIO_PIN_RESET); #endif } void GPIO_new_DEBUG_HIGH(void) { #ifdef DEBUG_PIN_ACTIVE - HAL_GPIO_WritePin(GPIOC,GPIO_PIN_3,GPIO_PIN_SET); + HAL_GPIO_WritePin(GPIOC,LED_CONTROL_PIN,GPIO_PIN_SET); #endif } static void GPIO_Power_MainCPU_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; __GPIOC_CLK_ENABLE(); - GPIO_InitStructure.Pin = GPIO_PIN_0; + GPIO_InitStructure.Pin = MAINCPU_CONTROL_PIN; GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStructure.Pull = GPIO_PULLUP; GPIO_InitStructure.Speed = GPIO_SPEED_LOW; HAL_GPIO_Init( GPIOC, &GPIO_InitStructure); - HAL_GPIO_WritePin( GPIOC, GPIO_PIN_0, GPIO_PIN_RESET); + HAL_GPIO_WritePin( GPIOC, MAINCPU_CONTROL_PIN, GPIO_PIN_RESET); } static void GPIO_Power_MainCPU_ON(void) { - HAL_GPIO_WritePin( GPIOC, GPIO_PIN_0, GPIO_PIN_RESET); + HAL_GPIO_WritePin( GPIOC, MAINCPU_CONTROL_PIN, GPIO_PIN_RESET); } static void GPIO_Power_MainCPU_OFF(void) { - HAL_GPIO_WritePin( GPIOC, GPIO_PIN_0, GPIO_PIN_SET); + HAL_GPIO_WritePin( GPIOC, MAINCPU_CONTROL_PIN, GPIO_PIN_SET); } /** @@ -938,11 +960,7 @@ void sleep_prepare(void) { EXTI_Wakeup_Button_Init(); - /* - GPIO_InitStruct.Pull = GPIO_PULLUP; - GPIO_InitStruct.Pin = GPIO_PIN_0; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - */ + compass_sleep(); HAL_Delay(100); accelerator_sleep(); @@ -972,8 +990,8 @@ GPIO_InitStruct.Pin = GPIO_PIN_All - ^ ( GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_14 - | GPIO_PIN_15); /* power off & charger in & charge out & OSC32*/ + ^ ( MAINCPU_CONTROL_PIN | CHARGE_OUT_PIN | CHARGE_IN_PIN | EXT33V_CONTROL_PIN | LED_CONTROL_PIN); /* power off & charger in & charge out & OSC32 & ext33Volt */ + HAL_GPIO_Init( GPIOC, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_All ^ ( GPIO_PIN_0); diff -r 87bee7cc77b3 -r cc542448fb28 Small_CPU/Src/batteryCharger.c --- a/Small_CPU/Src/batteryCharger.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Small_CPU/Src/batteryCharger.c Fri Aug 19 11:30:24 2022 +0200 @@ -37,29 +37,12 @@ /* Use This compile switch to select the new charger status control implementation */ #define ENABLE_CHARGER_STATUS_V2 -#define CHARGE_IN_PIN GPIO_PIN_2 -#define CHARGE_IN_GPIO_PORT GPIOC -#define CHARGE_IN_GPIO_ENABLE() __GPIOC_CLK_ENABLE() +#define CHARGER_DEBOUNCE_SECONDS (6u) /* 6 seconds used to avoid problems with charger interrupts / disconnections */ -#define CHARGE_OUT_PIN GPIO_PIN_1 -#define CHARGE_OUT_GPIO_PORT GPIOC -#define CHARGE_OUT_GPIO_ENABLE() __GPIOC_CLK_ENABLE() - -#define CHARGER_DEBOUNCE_SECONDS (5u) /* 5 seconds used to avoid problems with charger interrupts / disconnections */ - -uint8_t battery_i_charge_status = 0; -uint16_t battery_charger_counter = 0; +static uint8_t battery_i_charge_status = 0; +static uint16_t battery_charger_counter = 0; #ifdef ENABLE_CHARGER_STATUS_V2 -typedef enum -{ - Charger_NotConnected = 0, /* This is identified reading CHARGE_IN_PIN == HIGH */ - Charger_WarmUp, /* Charging started but counter did not yet reach a certain limit (used to debounce connect / disconnect events to avoid multiple increases of statistic charging cycle counter) */ - Charger_Active, /* Charging identified by CHARGE_IN_PIN == LOW for a certain time */ - Charger_Finished, - Charger_LostConnection /* Intermediate state to debounce disconnecting events (including charging error state like over temperature) */ -} chargerState_t; - static chargerState_t batteryChargerState = Charger_NotConnected; #endif @@ -73,6 +56,21 @@ return battery_i_charge_status; } +void set_charge_state(uint8_t newState) +{ +#ifdef ENABLE_CHARGER_STATUS_V2 + if(newState < Charger_END) + { + batteryChargerState = newState; + } +#endif +} + +uint8_t get_charge_state(void) +{ + return batteryChargerState; +} + void init_battery_charger_status(void) { #ifdef OSTC_ON_DISCOVERY_HARDWARE @@ -150,115 +148,140 @@ #endif #ifdef ENABLE_CHARGER_STATUS_V2 - /* on disconnection or while disconnected */ - if(HAL_GPIO_ReadPin(CHARGE_IN_GPIO_PORT,CHARGE_IN_PIN)) + + if(batteryChargerState == Charger_ColdStart) /* wait for the first valid voltage meassurement */ { - switch(batteryChargerState) + if((global.lifeData.battery_voltage != BATTERY_DEFAULT_VOLTAGE) && (global.lifeData.battery_voltage < BATTERY_CHARGER_CONNECTED_VOLTAGE)) { - case Charger_Active: global.dataSendToMaster.chargeStatus = CHARGER_lostConnection; - global.deviceDataSendToMaster.chargeStatus = CHARGER_lostConnection; - batteryChargerState = Charger_LostConnection; - battery_charger_counter = CHARGER_DEBOUNCE_SECONDS; - - if(get_voltage() >= 4.1f) /* the charger stops charging when charge current is 1/10. */ - { /* Basically it is OK to rate a charging as complete if a defined voltage is reached */ - batteryChargerState = Charger_Finished; - global.dataSendToMaster.chargeStatus = CHARGER_complete; - global.deviceDataSendToMaster.chargeStatus = CHARGER_complete; - battery_charger_counter = 15; - notifyChargeComplete = 1; - } - break; - case Charger_WarmUp: - case Charger_Finished: - case Charger_LostConnection: if(battery_charger_counter >= cycleTimeBase) - { - battery_charger_counter -= cycleTimeBase; - global.dataSendToMaster.chargeStatus = CHARGER_lostConnection; - global.deviceDataSendToMaster.chargeStatus = CHARGER_lostConnection; - batteryChargerState = Charger_LostConnection; - } - else - { - battery_charger_counter = 0; - battery_i_charge_status = 0; - global.dataSendToMaster.chargeStatus = CHARGER_off; - global.deviceDataSendToMaster.chargeStatus = CHARGER_off; - - if(notifyChargeComplete) - { - battery_gas_gauge_set_charge_full(); - scheduleUpdateDeviceDataChargerFull(); - notifyChargeComplete = 0; - } - batteryChargerState = Charger_NotConnected; - } - break; - default: break; + if(global.lifeData.battery_voltage > BATTERY_ENDOF_CHARGE_VOLTAGE) /* Voltage close to full state => maybe new battery inserted */ + { + battery_gas_gauge_set_charge_full(); + } + batteryChargerState = Charger_NotConnected; } } else - { - /* connected */ - /* wait for disconnection to write and reset */ - switch(batteryChargerState) + { /* on disconnection or while disconnected */ + if(HAL_GPIO_ReadPin(CHARGE_IN_GPIO_PORT,CHARGE_IN_PIN)) { - case Charger_NotConnected: battery_i_charge_status = 1; - battery_charger_counter = 0; - batteryChargerState = Charger_WarmUp; - break; - case Charger_LostConnection: batteryChargerState = Charger_Active; - break; - case Charger_WarmUp: battery_charger_counter += cycleTimeBase; - if(battery_charger_counter >= CHARGER_DEBOUNCE_SECONDS ) - { - battery_i_charge_status = 2; - scheduleUpdateDeviceDataChargerCharging(); - batteryChargerState = Charger_Active; - } - /* no break */ - case Charger_Finished: - case Charger_Active: global.dataSendToMaster.chargeStatus = CHARGER_running; - global.deviceDataSendToMaster.chargeStatus = CHARGER_running; - - /* drive the output pin high to determine the state of the charger */ - GPIO_InitTypeDef GPIO_InitStructure; - GPIO_InitStructure.Pin = CHARGE_OUT_PIN; - GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; - GPIO_InitStructure.Pull = GPIO_NOPULL; - GPIO_InitStructure.Speed = GPIO_SPEED_LOW; - HAL_GPIO_Init(CHARGE_OUT_GPIO_PORT, &GPIO_InitStructure); - HAL_GPIO_WritePin(CHARGE_OUT_GPIO_PORT, CHARGE_OUT_PIN,GPIO_PIN_SET); - HAL_Delay(1); - - if(HAL_GPIO_ReadPin(CHARGE_IN_GPIO_PORT,CHARGE_IN_PIN)) /* high => charger stopped charging */ - { - batteryChargerState = Charger_Finished; - global.dataSendToMaster.chargeStatus = CHARGER_complete; - global.deviceDataSendToMaster.chargeStatus = CHARGER_complete; - battery_charger_counter = 30; - notifyChargeComplete = 1; - } - else - { - if(batteryChargerState == Charger_Finished) /* voltage dropped below the hysteresis again => charging restarted */ + switch(batteryChargerState) + { + case Charger_WarmUp: + case Charger_Active: global.dataSendToMaster.chargeStatus = CHARGER_lostConnection; + global.deviceDataSendToMaster.chargeStatus = CHARGER_lostConnection; + batteryChargerState = Charger_LostConnection; + if(cycleTimeBase > CHARGER_DEBOUNCE_SECONDS) /* adapt connection lost detection to sleep mode */ + { + battery_charger_counter = cycleTimeBase + 1; + } + else { - batteryChargerState = Charger_Active; + battery_charger_counter = CHARGER_DEBOUNCE_SECONDS; + } + break; + case Charger_Finished: battery_charger_counter = 0; + batteryChargerState = Charger_LostConnection; + /* no break */ + case Charger_LostConnection: /* the charger stops charging when charge current is 1/10 */ + /* Basically it is OK to rate a charging as complete if a defined voltage is reached */ + if(((battery_gas_gauge_isChargeValueValid() == 0) || (global.lifeData.battery_charge < 90)) && (get_voltage() >= BATTERY_ENDOF_CHARGE_VOLTAGE) && (get_voltage() < BATTERY_CHARGER_CONNECTED_VOLTAGE)) + { + notifyChargeComplete = 1; + } + else + { notifyChargeComplete = 0; } - } + if(battery_charger_counter >= cycleTimeBase) + { + battery_charger_counter -= cycleTimeBase; + } + else + { + battery_charger_counter = 0; + battery_i_charge_status = 0; + global.dataSendToMaster.chargeStatus = CHARGER_off; + global.deviceDataSendToMaster.chargeStatus = CHARGER_off; - /* restore high impedance to be able to detect disconnection */ - GPIO_InitStructure.Pin = CHARGE_OUT_PIN; - GPIO_InitStructure.Mode = GPIO_MODE_ANALOG; - GPIO_InitStructure.Pull = GPIO_NOPULL; - GPIO_InitStructure.Speed = GPIO_SPEED_LOW; - HAL_GPIO_Init(CHARGE_OUT_GPIO_PORT, &GPIO_InitStructure); - HAL_Delay(1); - break; + if(notifyChargeComplete) + { + battery_gas_gauge_set_charge_full(); + scheduleUpdateDeviceDataChargerFull(); + notifyChargeComplete = 0; + } + batteryChargerState = Charger_NotConnected; + } + break; + default: break; + } + } + else + { + /* connected */ + /* wait for disconnection to write and reset */ + switch(batteryChargerState) + { + case Charger_NotConnected: battery_i_charge_status = 1; + battery_charger_counter = 0; + batteryChargerState = Charger_WarmUp; + break; + case Charger_LostConnection: batteryChargerState = Charger_Active; + break; + case Charger_WarmUp: battery_charger_counter += cycleTimeBase; + if(battery_charger_counter >= CHARGER_DEBOUNCE_SECONDS ) + { + battery_i_charge_status = 2; + scheduleUpdateDeviceDataChargerCharging(); + batteryChargerState = Charger_Active; + } + /* no break */ + case Charger_Finished: + case Charger_Active: global.dataSendToMaster.chargeStatus = CHARGER_running; + global.deviceDataSendToMaster.chargeStatus = CHARGER_running; - default: /* wait for disconnection */ - break; + /* drive the output pin high to determine the state of the charger */ + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.Pin = CHARGE_OUT_PIN; + GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStructure.Pull = GPIO_NOPULL; + GPIO_InitStructure.Speed = GPIO_SPEED_LOW; + HAL_GPIO_Init(CHARGE_OUT_GPIO_PORT, &GPIO_InitStructure); + HAL_GPIO_WritePin(CHARGE_OUT_GPIO_PORT, CHARGE_OUT_PIN,GPIO_PIN_SET); + HAL_Delay(1); + + if(HAL_GPIO_ReadPin(CHARGE_IN_GPIO_PORT,CHARGE_IN_PIN)) /* high => charger stopped charging */ + { + batteryChargerState = Charger_Finished; + global.dataSendToMaster.chargeStatus = CHARGER_complete; + global.deviceDataSendToMaster.chargeStatus = CHARGER_complete; + battery_charger_counter = 30; + notifyChargeComplete = 1; + } + else + { + if(global.lifeData.battery_charge > 100.0) /* still charging but indicator is set to full => decrease to 99% to keep count increasing */ + { + battery_gas_gauge_set(99.0); + } + if(batteryChargerState == Charger_Finished) /* voltage dropped below the hysteresis again => charging restarted */ + { + batteryChargerState = Charger_Active; + notifyChargeComplete = 0; + } + } + + /* restore high impedance to be able to detect disconnection */ + GPIO_InitStructure.Pin = CHARGE_OUT_PIN; + GPIO_InitStructure.Mode = GPIO_MODE_ANALOG; + GPIO_InitStructure.Pull = GPIO_NOPULL; + GPIO_InitStructure.Speed = GPIO_SPEED_LOW; + HAL_GPIO_Init(CHARGE_OUT_GPIO_PORT, &GPIO_InitStructure); + HAL_Delay(1); + break; + + default: /* wait for disconnection */ + break; + } } } #else diff -r 87bee7cc77b3 -r cc542448fb28 Small_CPU/Src/batteryGasGauge.c --- a/Small_CPU/Src/batteryGasGauge.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Small_CPU/Src/batteryGasGauge.c Fri Aug 19 11:30:24 2022 +0200 @@ -28,8 +28,10 @@ #include "stm32f4xx_hal.h" #include "i2c.h" -static float battery_f_voltage = 6.0; /* max assumed voltage */ +static float battery_f_voltage = BATTERY_DEFAULT_VOLTAGE; /* max assumed voltage */ static float battery_f_charge_percent = 0; +static uint8_t chargeValueKnown = 0; /* indicator if the charge of the battery is known (for example after a full charge cycle) */ + #define BGG_BATTERY_OFFSET (26123) //; 65536-(3,35Ah/0,085mAh) #define BGG_BATTERY_DIVIDER (394) //; 3,35Ah/0,085mAh/100 [%] @@ -66,7 +68,7 @@ // F8 = 11111000: // ADC auto mode (11) // Prescale M = 128 (111) - // AL/CC pin disable (0) + // AL/CC pin disable (00) // Shutdown (0) buffer[1] = 0xF8; I2C_Master_Transmit(DEVICE_BATTERYGAUGE, buffer, 2); @@ -152,6 +154,7 @@ bufferSend[2] = 0xFF; I2C_Master_Transmit( DEVICE_BATTERYGAUGE, bufferSend, 3); init_battery_gas_gauge(); + chargeValueKnown = 1; } @@ -177,7 +180,17 @@ bufferSend[2] = (uint8_t)(mAhSend & 0xFF); I2C_Master_Transmit( DEVICE_BATTERYGAUGE, bufferSend, 3); init_battery_gas_gauge(); + chargeValueKnown = 1; } +uint8_t battery_gas_gauge_isChargeValueValid(void) +{ + return chargeValueKnown; +} + +void battery_gas_gauge_setChargeValueValid(void) +{ + chargeValueKnown = 1; +} /************************ (C) COPYRIGHT heinrichs weikamp *****END OF FILE****/ diff -r 87bee7cc77b3 -r cc542448fb28 Small_CPU/Src/dma.c --- a/Small_CPU/Src/dma.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Small_CPU/Src/dma.c Fri Aug 19 11:30:24 2022 +0200 @@ -34,6 +34,7 @@ */ /* Includes ------------------------------------------------------------------*/ #include "dma.h" +#include "uart.h" /* USER CODE BEGIN 0 */ @@ -55,6 +56,7 @@ /* DMA controller clock enable */ __DMA2_CLK_ENABLE(); + MX_USART1_DMA_Init(); /* DMA interrupt init */ } diff -r 87bee7cc77b3 -r cc542448fb28 Small_CPU/Src/externalInterface.c --- a/Small_CPU/Src/externalInterface.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Small_CPU/Src/externalInterface.c Fri Aug 19 11:30:24 2022 +0200 @@ -27,8 +27,11 @@ #include "i2c.h" #include "externalInterface.h" #include "scheduler.h" +#include "uart.h" +#include "data_exchange.h" extern SGlobal global; +extern UART_HandleTypeDef huart1; #define ADC_ANSWER_LENGTH (5u) /* 3424 will provide addr + 4 data bytes */ #define ADC_TIMEOUT (10u) /* conversion stuck for unknown reason => restart */ @@ -52,6 +55,11 @@ static uint8_t externalInterfacePresent = 0; float externalChannel_mV[MAX_ADC_CHANNEL]; +static uint8_t externalV33_On = 0; +static uint8_t externalADC_On = 0; +static uint16_t externalCO2Value; +static uint16_t externalCO2SignalStrength; +static uint16_t externalCO2Status = 0; void externalInterface_Init(void) @@ -65,6 +73,12 @@ global.deviceDataSendToMaster.hw_Info.extADC = 1; } global.deviceDataSendToMaster.hw_Info.checkADC = 1; + +/* init data values */ + externalV33_On = 0; + externalCO2Value = 0; + externalCO2SignalStrength = 0; + externalCO2Status = 0; } @@ -168,3 +182,122 @@ } return retval; } + +uint8_t setExternalInterfaceChannel(uint8_t channel, float value) +{ + uint8_t retval = 0; + + if(channel < MAX_ADC_CHANNEL) + { + externalChannel_mV[channel] = value; + retval = 1; + } + return retval; +} + +void externalInterface_InitPower33(void) +{ + GPIO_InitTypeDef GPIO_InitStructure; + + GPIO_InitStructure.Pin = GPIO_PIN_7; + GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStructure.Pull = GPIO_PULLUP; + GPIO_InitStructure.Speed = GPIO_SPEED_LOW; + HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); + HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,GPIO_PIN_SET); +} + + +uint8_t externalInterface_isEnabledPower33() +{ + return externalV33_On; +} + +uint8_t externalInterface_isEnabledADC() +{ + return externalADC_On; +} + +void externalInterface_SwitchPower33(uint8_t state) +{ + if(state != externalV33_On) + { + if(state) + { + HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,GPIO_PIN_RESET); + externalV33_On = 1; + MX_USART1_UART_Init(); + } + else + { + HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,GPIO_PIN_SET); + externalV33_On = 0; + externalInterface_SetCO2Value(0); + externalInterface_SetCO2SignalStrength(0); + MX_USART1_UART_DeInit(); + } + } +} +void externalInterface_SwitchADC(uint8_t state) +{ + if((state) && (externalInterfacePresent)) + { + externalInterface_StartConversion(activeChannel); + externalADC_On = 1; + } + else + { + externalADC_On = 0; + } +} + +void externalInterface_SetCO2Value(uint16_t CO2_ppm) +{ + externalCO2Value = CO2_ppm; +} + +void externalInterface_SetCO2SignalStrength(uint16_t LED_qa) +{ + externalCO2SignalStrength = LED_qa; +} + +uint16_t externalInterface_GetCO2Value(void) +{ + return externalCO2Value; +} + +uint16_t externalInterface_GetCO2SignalStrength(void) +{ + return externalCO2SignalStrength; +} + + +void externalInterface_SetCO2State(uint16_t state) +{ + externalCO2Status = state; +} + +uint16_t externalInterface_GetCO2State(void) +{ + return externalCO2Status; +} + +void externalInterface_ExecuteCmd(uint16_t Cmd) +{ + char cmdString[10]; + uint8_t cmdLength = 0; + + switch(Cmd & 0x00FF) /* lower byte is reserved for commands */ + { + case EXT_INTERFACE_CO2_CALIB: cmdLength = snprintf(cmdString, 10, "G\r\n"); + break; + default: + break; + } + if(cmdLength != 0) + { + HAL_UART_Transmit(&huart1,(uint8_t*)cmdString,cmdLength,10); + } + return; +} + diff -r 87bee7cc77b3 -r cc542448fb28 Small_CPU/Src/pressure.c --- a/Small_CPU/Src/pressure.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Small_CPU/Src/pressure.c Fri Aug 19 11:30:24 2022 +0200 @@ -49,8 +49,12 @@ /* remove comment to use a predefined profile for pressure changes instead of real world data */ /* #define SIMULATE_PRESSURE */ + #define PRESSURE_SURFACE_MAX_MBAR (1060.0f) /* It is unlikely that pressure at surface is greater than this value => clip to it */ +#define PRESSURE_MINIMUM (0.0f) +#define TEMPERATURE_MINIMUM (-100.0f) + #define PRESSURE_SURFACE_QUE (30u) /* history buffer [minutes] for past pressure measurements */ #define PRESSURE_SURFACE_EVA_WINDOW (15u) /* Number of entries evaluated during instability test. Used to avoid detection while dive enters water */ #define PRESSURE_SURFACE_STABLE_LIMIT (10u) /* Define pressure as stable if delta (mBar) is below this value */ @@ -664,6 +668,11 @@ ambient_temperature = ((float)local_Tx100) / 100; ambient_temperature += temperature_offset; + if(ambient_temperature < TEMPERATURE_MINIMUM) + { + ambient_temperature = 20.0; + } + calc_pressure = ((float)local_Px10) / 10; calc_pressure += pressure_offset; @@ -673,6 +682,11 @@ avgCnt++; /* by the measurement range of the sensor which is focused on under water pressure measurement */ } ambient_pressure_mbar = runningAvg; + + if(ambient_pressure_mbar < PRESSURE_MINIMUM) + { + ambient_pressure_mbar = 1000.0; + } } diff -r 87bee7cc77b3 -r cc542448fb28 Small_CPU/Src/scheduler.c --- a/Small_CPU/Src/scheduler.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Small_CPU/Src/scheduler.c Fri Aug 19 11:30:24 2022 +0200 @@ -42,6 +42,7 @@ #include "decom.h" #include "tm_stm32f4_otp.h" #include "externalInterface.h" +#include "uart.h" /* uncomment to enable restoting of last known date in case of a power loss (RTC looses timing data) */ /* #define RESTORE_LAST_KNOWN_DATE */ @@ -90,6 +91,7 @@ void copyDeviceData(void); void copyPICdata(void); void copyExtADCdata(); +void copyExtCO2data(); static void schedule_update_timer_helper(int8_t thisSeconds); uint32_t time_elapsed_ms(uint32_t ticksstart,uint32_t ticksnow); @@ -125,6 +127,8 @@ global.I2C_SystemStatus = HAL_ERROR; // 0x00 would be everything working + global.lifeData.battery_voltage = BATTERY_DEFAULT_VOLTAGE; + global.lifeData.pressure_ambient_bar = INVALID_PREASURE_VALUE; global.lifeData.pressure_surface_bar = INVALID_PREASURE_VALUE; decom_reset_with_1000mbar(&global.lifeData); @@ -301,6 +305,26 @@ memcpy(&DeviceDataFlash, &global.dataSendToSlave.data.DeviceData, sizeof(SDevice)); deviceDataFlashValid = 1; + + /* handle external interface requests */ + + if((global.dataSendToSlave.data.externalInterface_Cmd && EXT_INTERFACE_33V_ON) != externalInterface_isEnabledPower33()) + { + externalInterface_SwitchPower33(global.dataSendToSlave.data.externalInterface_Cmd && EXT_INTERFACE_33V_ON); + } + + if(((global.dataSendToSlave.data.externalInterface_Cmd & EXT_INTERFACE_ADC_ON) != 0) != externalInterface_isEnabledADC()) + { + externalInterface_SwitchADC(global.dataSendToSlave.data.externalInterface_Cmd && EXT_INTERFACE_ADC_ON); + } + + + if(global.dataSendToSlave.data.externalInterface_Cmd & 0x00FF) /* lowest nibble for commands */ + { + externalInterface_ExecuteCmd(global.dataSendToSlave.data.externalInterface_Cmd); + } + + #if 0 //TODO: Temporary placed here. Duration ~210 ms. if (global.I2C_SystemStatus != HAL_OK) { @@ -487,6 +511,20 @@ lasttick = HAL_GetTick(); ticksdiff = time_elapsed_ms(Scheduler.tickstart,lasttick); +#ifdef ENABLE_CO2_SUPPORT + if(global.dataSendToSlave.data.externalInterface_Cmd & EXT_INTERFACE_UART_SENTINEL) + { + HandleUARTCO2Data(); + } +#endif +#ifdef ENABLE_SENTINEL_MODE + if(global.dataSendToSlave.data.externalInterface_Cmd & EXT_INTERFACE_UART_SENTINEL) + { + HandleUARTSentinelData(); + } +#endif + + if(ticksdiff >= Scheduler.counterSPIdata100msec * 100 + 10) { if(SPI_Evaluate_RX_Data()!=0) /* did we receive something ? */ @@ -495,12 +533,16 @@ } schedule_check_resync(); - extAdcChannel = externalInterface_ReadAndSwitch(); - if(extAdcChannel != EXTERNAL_ADC_NO_DATA) + if(externalInterface_isEnabledADC()) { - externalInterface_CalculateADCValue(extAdcChannel); - copyExtADCdata(); + extAdcChannel = externalInterface_ReadAndSwitch(); + if(extAdcChannel != EXTERNAL_ADC_NO_DATA) + { + externalInterface_CalculateADCValue(extAdcChannel); + } } + copyExtADCdata(); + copyExtCO2data(); } //Evaluate pressure at 20 ms, 120 ms, 220 ms,.... @@ -761,10 +803,11 @@ void scheduleSurfaceMode(void) { - uint32_t ticksdiff = 0; uint32_t lasttick = 0; uint8_t extAdcChannel = 0; + uint8_t batteryToggle = 0; /* ADC is operating in automatic 2 second cycles => consider for battery charge function call */ + Scheduler.tickstart = HAL_GetTick(); Scheduler.counterSPIdata100msec = 0; Scheduler.counterCompass100msec = 0; @@ -786,7 +829,20 @@ if(scheduleSetButtonResponsiveness()) setButtonsNow = 0; } - + +#ifdef ENABLE_CO2_SUPPORT + if(global.dataSendToSlave.data.externalInterface_Cmd & EXT_INTERFACE_UART_SENTINEL) + { + HandleUARTCO2Data(); + } +#endif +#ifdef ENABLE_SENTINEL_MODE + if(global.dataSendToSlave.data.externalInterface_Cmd & EXT_INTERFACE_UART_SENTINEL) + { + HandleUARTSentinelData(); + } +#endif + /* Evaluate received data at 10 ms, 110 ms, 210 ms,... duration ~<1ms */ if(ticksdiff >= Scheduler.counterSPIdata100msec * 100 + 10) { @@ -795,12 +851,17 @@ Scheduler.counterSPIdata100msec++; } schedule_check_resync(); - extAdcChannel = externalInterface_ReadAndSwitch(); - if(extAdcChannel != EXTERNAL_ADC_NO_DATA) + if(externalInterface_isEnabledADC()) { - externalInterface_CalculateADCValue(extAdcChannel); - copyExtADCdata(); + extAdcChannel = externalInterface_ReadAndSwitch(); + if(extAdcChannel != EXTERNAL_ADC_NO_DATA) + { + externalInterface_CalculateADCValue(extAdcChannel); + + } } + copyExtADCdata(); + copyExtCO2data(); } /* Evaluate pressure at 20 ms, 120 ms, 220 ms,... duration ~22ms] */ @@ -886,14 +947,24 @@ { global.lifeData.desaturation_time_minutes = 0; } - battery_gas_gauge_get_data(); - battery_charger_get_status_and_contral_battery_gas_gauge(1); + + if(!batteryToggle) + { + battery_gas_gauge_get_data(); + battery_charger_get_status_and_contral_battery_gas_gauge(2); + batteryToggle = 1; + } + else + { + batteryToggle = 0; + } copyCnsAndOtuData(); copyTimeData(); copyBatteryData(); copyDeviceData(); + /* check if I2C is not up an running and try to reactivate if necessary. Also do initialization if problem occured during startup */ if(global.I2C_SystemStatus != HAL_OK) { @@ -1034,6 +1105,7 @@ { global.dataSendToMaster.mode = 0; global.deviceDataSendToMaster.mode = 0; + secondsCount = 0; /* prevent button wake up problem while in sleep_prepare * sleep prepare does I2C_DeInit() @@ -1056,6 +1128,7 @@ if(global.mode == MODE_SLEEP) secondsCount += 2; + externalInterface_InitPower33(); MX_I2C1_Init(); pressure_sensor_get_pressure_raw(); @@ -1069,19 +1142,18 @@ MX_I2C1_Init(); HAL_Delay(100); - if((global.I2C_SystemStatus == HAL_OK) && (!is_init_pressure_done())) { init_pressure(); } } - if(secondsCount >= 30) + if((secondsCount >= 30) || (global.mode != MODE_SLEEP)) /* Service battery charge state in case sleep is left */ { pressure_sensor_get_temperature_raw(); battery_gas_gauge_get_data(); -// ReInit_battery_charger_status_pins(); - battery_charger_get_status_and_contral_battery_gas_gauge(30); + ReInit_battery_charger_status_pins(); + battery_charger_get_status_and_contral_battery_gas_gauge(secondsCount); // DeInit_battery_charger_status_pins(); secondsCount = 0; } @@ -1120,6 +1192,7 @@ clearDecoNow = 0; setButtonsNow = 0; reinitGlobals(); + ReInit_battery_charger_status_pins(); } @@ -1363,7 +1436,7 @@ } break; - case MODE_SLEEP: + case MODE_SLEEP: case MODE_SHUTDOWN: break; } @@ -1549,8 +1622,17 @@ void copyBatteryData(void) { uint8_t boolBatteryData = !global.dataSendToMaster.boolBatteryData; + global.lifeData.battery_charge = get_charge(); global.dataSendToMaster.data[boolBatteryData].battery_voltage = get_voltage(); - global.dataSendToMaster.data[boolBatteryData].battery_charge= get_charge(); + + if(battery_gas_gauge_isChargeValueValid()) + { + global.dataSendToMaster.data[boolBatteryData].battery_charge= global.lifeData.battery_charge; + } + else + { + global.dataSendToMaster.data[boolBatteryData].battery_charge = global.lifeData.battery_charge * -1.0; /* negate value to show that this is just an assumption */ + } global.dataSendToMaster.boolBatteryData = boolBatteryData; } @@ -1629,13 +1711,44 @@ uint8_t channel = 0; + uint8_t boolADCBuffer = ~(global.dataSendToMaster.boolADCO2Data & DATA_BUFFER_ADC); + + boolADCBuffer &= DATA_BUFFER_ADC; + global.dataSendToMaster.boolADCO2Data &= ~DATA_BUFFER_ADC; + for(channel = 0; channel < MAX_ADC_CHANNEL; channel++) { value = getExternalInterfaceChannel(channel); - global.dataSendToMaster.data[0].extADC_voltage[channel] = value; + global.dataSendToMaster.data[boolADCBuffer && DATA_BUFFER_ADC].extADC_voltage[channel] = value; } + global.dataSendToMaster.boolADCO2Data |= boolADCBuffer; } +void copyExtCO2data() +{ + uint16_t value; + uint8_t boolCO2Buffer = ~(global.dataSendToMaster.boolADCO2Data & DATA_BUFFER_CO2); + + global.dataSendToMaster.boolADCO2Data &= ~DATA_BUFFER_CO2; + boolCO2Buffer &= DATA_BUFFER_CO2; + + if(externalInterface_GetCO2State()) + { + value = externalInterface_GetCO2Value(); + global.dataSendToMaster.data[(boolCO2Buffer && DATA_BUFFER_CO2)].CO2_ppm = value; + value = externalInterface_GetCO2SignalStrength(); + global.dataSendToMaster.data[(boolCO2Buffer && DATA_BUFFER_CO2)].CO2_signalStrength = value; + global.dataSendToMaster.data[(boolCO2Buffer && DATA_BUFFER_CO2)].externalInterface_CmdAnswer = externalInterface_GetCO2State(); + externalInterface_SetCO2State(EXT_INTERFACE_33V_ON); /* clear command responses */ + } + else + { + global.dataSendToMaster.data[(boolCO2Buffer && DATA_BUFFER_CO2)].CO2_ppm = 0; + global.dataSendToMaster.data[(boolCO2Buffer && DATA_BUFFER_CO2)].CO2_signalStrength = 0; + global.dataSendToMaster.data[(boolCO2Buffer && DATA_BUFFER_CO2)].externalInterface_CmdAnswer = 0; + } + global.dataSendToMaster.boolADCO2Data |= boolCO2Buffer; +} typedef enum { diff -r 87bee7cc77b3 -r cc542448fb28 Small_CPU/Src/spi.c --- a/Small_CPU/Src/spi.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Small_CPU/Src/spi.c Fri Aug 19 11:30:24 2022 +0200 @@ -350,7 +350,6 @@ /* stop data exchange? */ if (global.mode == MODE_SHUTDOWN) { - global.mode = MODE_SLEEP; global.dataSendToSlavePending = 0; global.dataSendToSlaveIsValid = 1; global.dataSendToSlaveIsNotValidCount = 0; diff -r 87bee7cc77b3 -r cc542448fb28 Small_CPU/Src/stm32f4xx_hal_msp_v3.c --- a/Small_CPU/Src/stm32f4xx_hal_msp_v3.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Small_CPU/Src/stm32f4xx_hal_msp_v3.c Fri Aug 19 11:30:24 2022 +0200 @@ -229,14 +229,18 @@ { GPIO_InitTypeDef GPIO_InitStruct; - if(huart->Instance==USART2) + if(huart->Instance==USART1) { - __USART2_CLK_ENABLE(); - GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3; + __GPIOA_CLK_ENABLE(); + __USART1_CLK_ENABLE(); + GPIO_InitStruct.Pin = GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; - GPIO_InitStruct.Speed = GPIO_SPEED_LOW; - GPIO_InitStruct.Alternate = GPIO_AF7_USART2; + GPIO_InitStruct.Speed = GPIO_SPEED_FAST; //GPIO_SPEED_LOW; + GPIO_InitStruct.Alternate = GPIO_AF7_USART1; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = GPIO_PIN_10; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); } } @@ -244,10 +248,11 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) { - if(huart->Instance==USART2) + if(huart->Instance==USART1) { - __USART2_CLK_DISABLE(); - HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3); + HAL_NVIC_DisableIRQ(USART1_IRQn); + __USART1_CLK_DISABLE(); + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); } } diff -r 87bee7cc77b3 -r cc542448fb28 Small_CPU/Src/stm32f4xx_it_v3.c --- a/Small_CPU/Src/stm32f4xx_it_v3.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Small_CPU/Src/stm32f4xx_it_v3.c Fri Aug 19 11:30:24 2022 +0200 @@ -58,6 +58,9 @@ extern RTC_HandleTypeDef RTCHandle; extern ADC_HandleTypeDef AdcHandle; +extern UART_HandleTypeDef huart1; +extern DMA_HandleTypeDef hdma_usart1_rx; + /* Private function prototypes -----------------------------------------------*/ /* Private functions ---------------------------------------------------------*/ @@ -233,6 +236,11 @@ * @retval None */ +void DMA2_Stream5_IRQHandler(void) +{ + HAL_DMA_IRQHandler(&hdma_usart1_rx); +} + /******************************************************************************/ /* STM32F4xx Peripherals Interrupt Handlers */ @@ -295,6 +303,12 @@ HAL_ADC_IRQHandler(&AdcHandle); } + +void USART1_IRQHandler(void) +{ + HAL_UART_IRQHandler(&huart1); +} + /** * @brief This function handles PPP interrupt request. * @param None diff -r 87bee7cc77b3 -r cc542448fb28 Small_CPU/Src/uart.c --- a/Small_CPU/Src/uart.c Mon Nov 01 12:39:34 2021 +0100 +++ b/Small_CPU/Src/uart.c Fri Aug 19 11:30:24 2022 +0200 @@ -20,57 +20,370 @@ */ /* Includes ------------------------------------------------------------------*/ #include "uart.h" +#include "externalInterface.h" +#include "data_exchange.h" /* Private variables ---------------------------------------------------------*/ -UART_HandleTypeDef huart2; +#define CHUNK_SIZE (20u) /* the DMA will handle chunk size transfers */ +#define CHUNKS_PER_BUFFER (3u) +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 receiption needs to be started */ +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_USART2_UART_Init(void) +void MX_USART1_UART_Init(void) { -/* pullup special */ - GPIO_InitTypeDef GPIO_InitStructure; - __GPIOA_CLK_ENABLE(); - GPIO_InitStructure.Pin = GPIO_PIN_2; - GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; - GPIO_InitStructure.Pull = GPIO_PULLUP; - GPIO_InitStructure.Speed = GPIO_SPEED_FAST; - HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); +/* regular init */ + + huart1.Instance = USART1; + 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); + + rxReadIndex = 0; + lastCmdIndex = 0; + rxWriteIndex = 0; + dmaActive = 0; +} + +void MX_USART1_UART_DeInit(void) +{ + HAL_DMA_DeInit(&hdma_usart1_rx); + HAL_UART_DeInit(&huart1); +} + +void MX_USART1_DMA_Init() +{ + /* DMA controller clock enable */ + __DMA2_CLK_ENABLE(); -/* regular init */ - huart2.Instance = USART2; - huart2.Init.BaudRate = 1200; - huart2.Init.WordLength = UART_WORDLENGTH_8B; - huart2.Init.StopBits = UART_STOPBITS_1; - huart2.Init.Parity = UART_PARITY_NONE; - huart2.Init.Mode = UART_MODE_TX_RX; - huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE; - huart2.Init.OverSampling = UART_OVERSAMPLING_16; - HAL_UART_Init(&huart2); + /* 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 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; + } } -uint8_t UART_ButtonAdjust(uint8_t *array) +#ifdef ENABLE_CO2_SUPPORT +void HandleUARTCO2Data(void) +{ + uint8_t localRX = rxReadIndex; + uint8_t dataType = 0; + uint32_t dataValue = 0; + static receiveState_t rxState = RX_Ready; + static uint32_t lastReceiveTick = 0; + + while(localRX != rxWriteIndex) + { + 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((rxState >= RX_Data0) && (rxState <= RX_Data4)) + { + if((rxBuffer[localRX] >= '0') && (rxBuffer[localRX] <= '9')) + { + dataValue = dataValue * 10 + (rxBuffer[localRX] - '0'); + rxState++; + } + } + 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: break; + } + } + if(rxState != RX_Data0) /* reset state machine because message in wrong format */ + { + rxState = RX_Ready; + } + } + + 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); + } + + if((dmaActive == 0) && (externalInterface_isEnabledPower33())) /* Should never happen in normal operation => restart in case of communication error */ + { + if(HAL_OK == HAL_UART_Receive_DMA (&huart1, &rxBuffer[rxWriteIndex], CHUNK_SIZE)) + { + dmaActive = 1; + } + } +} +#endif + +#ifdef ENABLE_SENTINEL_MODE +void HandleUARTSentinelData(void) { - uint8_t answer[4]; - - HAL_UART_Transmit(&huart2,array,4,1000); - HAL_UART_Receive(&huart2,answer,4,2000); - if( (answer[0] == array[0]) - &&(answer[1] == array[1]) - &&(answer[2] == array[2]) - &&(answer[3] == array[3])) - return 1; - else - return 0; + 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; + char checksum_str[]="00"; + + while(localRX != rxWriteIndex) + { + 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)); + } + 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); + } + lastAlive = curAlive; + } + + if((dmaActive == 0) && (externalInterface_isEnabledPower33())) /* Should never happen in normal operation => restart in case of communication error */ + { + if(HAL_OK == HAL_UART_Receive_DMA (&huart1, &rxBuffer[rxWriteIndex], CHUNK_SIZE)) + { + dmaActive = 1; + } + } } +#endif -void MX_USART2_UART_DeInit(void) +void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { - HAL_UART_DeInit(&huart2); + if(huart == &huart1) + { + dmaActive = 0; + rxWriteIndex+=CHUNK_SIZE; + if(rxWriteIndex >= CHUNK_SIZE * CHUNKS_PER_BUFFER) + { + rxWriteIndex = 0; + } + if((rxWriteIndex / CHUNK_SIZE) != (rxReadIndex / CHUNK_SIZE)) /* start next transfer if we did not catch up with read index */ + { + if(externalInterface_isEnabledPower33()) + { + if(HAL_OK == HAL_UART_Receive_DMA (&huart1, &rxBuffer[rxWriteIndex], CHUNK_SIZE)) + { + dmaActive = 1; + } + } + } + } } + + + + + + /************************ (C) COPYRIGHT heinrichs weikamp *****END OF FILE****/