Mercurial > public > ostc4
changeset 1048:493a5903ec20 GasConsumption
Merge with 9d9d506a82d3162b6b2323819cc08652887d7dd4 (Bootloader)
| author | Ideenmodellierer |
|---|---|
| date | Sat, 15 Nov 2025 19:29:44 +0100 |
| parents | 6fb16ca39125 (diff) 9d9d506a82d3 (current diff) |
| children | d91345e9c009 |
| files | BootLoader/Src/base_bootlader.c BootLoader/Src/display_mini.c BootLoader/Src/externLogbookFlash_mini.c BootLoader/Src/gfx_engine_mini.c BootLoader/Src/ostc_mini.c BootLoader/Src/tComm_mini.c Discovery/Inc/tComm.h OtherSources/data_central_mini.c |
| diffstat | 99 files changed, 5315 insertions(+), 2037 deletions(-) [+] |
line wrap: on
line diff
--- a/BootLoader/Src/base_bootlader.c Sun Nov 02 19:30:58 2025 +0100 +++ b/BootLoader/Src/base_bootlader.c Sat Nov 15 19:29:44 2025 +0100 @@ -262,8 +262,8 @@ .signature = "mh", .release_year = 25, - .release_month = 1, - .release_day = 13, + .release_month = 11, + .release_day = 15, .release_sub = 0, /* max 48 with trailing 0 */ @@ -280,7 +280,7 @@ { // first 52 bytes - .primarySerial = 0xFFFF, + .primarySerial = 0x06a4, .primaryLicence = 0x00, .revision8bit = 0x02, .production_year = 0x19, @@ -688,7 +688,7 @@ tComm_init(); tInfo_button_text("exit","","sleep"); - tInfo_newpage("bootloader 251102"); + tInfo_newpage("bootloader 251115"); tInfo_write("start bluetooth"); tInfo_write(textVersion); #if 0
--- a/BootLoader/Src/display_mini.c Sun Nov 02 19:30:58 2025 +0100 +++ b/BootLoader/Src/display_mini.c Sat Nov 15 19:29:44 2025 +0100 @@ -175,7 +175,7 @@ aTxBuffer[1] = OLED_VFP_SET_13h; send((uint8_t*)aTxBuffer, 2); aTxBuffer[0] = 0x72; - aTxBuffer[1] = 0x08; + aTxBuffer[1] = 0x0C; send((uint8_t*)aTxBuffer, 2); aTxBuffer[0] = 0x70;
--- a/BootLoader/Src/externLogbookFlash_mini.c Sun Nov 02 19:30:58 2025 +0100 +++ b/BootLoader/Src/externLogbookFlash_mini.c Sat Nov 15 19:29:44 2025 +0100 @@ -80,17 +80,6 @@ #define HEADER2OFFSET 0x400 -typedef enum{ - EF_HEADER, - EF_SAMPLE, - EF_DEVICEDATA, - EF_VPMDATA, - EF_SETTINGS, - EF_FIRMWARE, - EF_FIRMWARE2, -}which_ring_enum; - - typedef struct{ uint8_t IsBusy:1; uint8_t IsWriteEnabled:1; @@ -320,7 +309,11 @@ } else if(pSample2) { - actualAddress += length1; + /* actualAddress += length1; do dummy read to get EEPROM to the correct address */ + for(uint32_t i = 0; i<length1; i++) + { + ext_flash_read_block(&pSample2[0], EF_FIRMWARE2); + } for(uint32_t i = 0; i<length2; i++) { ext_flash_read_block(&pSample2[i], EF_FIRMWARE2);
--- a/BootLoader/Src/gfx_engine_mini.c Sun Nov 02 19:30:58 2025 +0100 +++ b/BootLoader/Src/gfx_engine_mini.c Sat Nov 15 19:29:44 2025 +0100 @@ -850,7 +850,7 @@ /* this is NOT fast nor optimized */ -static void GFX_draw_pixel(GFX_DrawCfgScreen *hgfx, int16_t x, int16_t y, uint8_t color) +void GFX_draw_pixel(GFX_DrawCfgScreen *hgfx, int16_t x, int16_t y, uint8_t color) { uint16_t* pDestination; @@ -2544,7 +2544,7 @@ #define Vsync_d1 2 #define VFP_d1 4 // make sure this value * VSYNC is also set in display.c for OLED_VFP_SET -#define VBP_d1 4 // make sure this value * VSYNC is also set in display.c for OLED_VBP_SET +#define VBP_d1 6 // make sure this value * VSYNC is also set in display.c for OLED_VBP_SET /* Horizontal synchronization width = Hsync - 1 */ LtdcHandle.Init.HorizontalSync = Hsync_d1 - 1;
--- a/BootLoader/Src/ostc_mini.c Sun Nov 02 19:30:58 2025 +0100 +++ b/BootLoader/Src/ostc_mini.c Sat Nov 15 19:29:44 2025 +0100 @@ -350,7 +350,7 @@ UartHandle.Init.StopBits = UART_STOPBITS_1; UartHandle.Init.Parity = UART_PARITY_NONE; UartHandle.Init.Mode = UART_MODE_TX_RX; - HAL_UART_Init(&UartHandle); + /* HAL_UART_Init(&UartHandle); moved final init step into BT config function to avoid problems while module power is off */ #ifdef USART_PIEZO UartPiezoTxHandle.Instance = USART_PIEZO;
--- a/BootLoader/Src/tComm_mini.c Sun Nov 02 19:30:58 2025 +0100 +++ b/BootLoader/Src/tComm_mini.c Sat Nov 15 19:29:44 2025 +0100 @@ -750,16 +750,16 @@ // get model + features case 0x60: aTxBuffer[count++] = 0x00; // hardware descriptor HIGH byte - aTxBuffer[count++] = 0x3B; // hardware descriptor LOW byte // 0x3B is OSTC4 // 0x1A is OTSC3 + aTxBuffer[count++] = 0x3B; // hardware descriptor LOW byte // 0x3B is OSTC 4/5 // 0x1A is OTSC3 aTxBuffer[count++] = 0x00; // feature descriptor HIGH byte aTxBuffer[count++] = 0x00; // feature descriptor LOW byte - aTxBuffer[count++] = 0x43; // model id + aTxBuffer[count++] = 0x44; // model id OSTC5 aTxBuffer[count++] = prompt4D4C(receiveStartByteUart); break; // get model case 0x6A: - aTxBuffer[count++] = 0x3B; // 0x3B is OSTC4 // 0x1A is OTSC3 + aTxBuffer[count++] = 0x3B; // 0x3B is OSTC 4/5 // 0x1A is OTSC3 aTxBuffer[count++] = prompt4D4C(receiveStartByteUart); break; @@ -1076,6 +1076,7 @@ const uint8_t id_Region1_firmware = 0xFF; const uint8_t id_RTE = 0xFE; uint8_t textpointer = 0; + uint32_t index = 0; //Get length if(HAL_UART_Receive(&UartHandle, sBuffer, 4,5000)!= HAL_OK) // 58000 @@ -1233,7 +1234,7 @@ return 0xFF; } else - //if(region == 2) + if(id == id_FONT) { uint8_t ptr = 0; ptr += gfx_number_to_string(7,0,&display_text[ptr],lengthTotal); @@ -1248,7 +1249,7 @@ } - // only non RTE !! + /* only non RTE !! (at this point RTE path already performed a return some lines above */ uint8_t* pBufferCompare = (uint8_t*)getFrame(20); ByteCompareStatus = 0; @@ -1262,14 +1263,14 @@ if(lengthCompare != length1) ByteCompareStatus = 10000; - for(int i = 0; i < length1; i++) + for(index = 0; index < length1; index++) { - if(pBuffer1[0] != pBufferCompare[0]) + if(pBuffer1[index] != pBufferCompare[index]) ByteCompareStatus++; } } else - //if(region == 2) + if(id == id_FONT) { /* upper region firmware can be larger (1MB) */ if(ext_flash_read_firmware2(0, pBufferCompare,4, 0,0) != 0xFFFFFFFF) @@ -1281,16 +1282,16 @@ ByteCompareStatus = 10000; if(offsetTotal != offsetCompare) ByteCompareStatus += 20000; - for(int i = 0; i < length1; i++) + for(index = 0; index < length1; index++) { - if(pBuffer1[0] != pBufferCompare[0]) + if(pBuffer1[index] != pBufferCompare[index]) ByteCompareStatus++; } lengthCompare = ext_flash_read_firmware2(0, 0,768000, pBufferCompare,768000); - for(int i = 0; i < length2; i++) + for(index = 0; index < length2; index++) { - if(pBuffer2[0] != pBufferCompare[0]) + if(pBuffer2[index] != pBufferCompare[index]) ByteCompareStatus++; } } @@ -1553,7 +1554,14 @@ { if(indexRef != 0) { - indexRef = 0; + if((answerOkay[0] == aRxBuffer[indexBuf])) + { + indexRef = 1; + } + else + { + indexRef = 0; + } } } indexBuf++; @@ -1747,12 +1755,13 @@ void tComm_StartBlueModConfig() { + HAL_UART_Init(&UartHandle); + #ifdef OSTC4_HW uint8_t answer = HAL_OK; uint8_t RxBuffer[UART_CMD_BUF_SIZE]; uint8_t index = 0; - BmTmpConfig = BM_CONFIG_ECHO; do /* flush RX buffer */ { @@ -1838,16 +1847,19 @@ BmTmpConfig++; break; case BM_INIT_POWERON: MX_Bluetooth_PowerOn(); + HAL_UART_Init(&UartHandle); BmTmpConfig++; break; - case BM_INIT_TRIGGER_ON: HAL_Delay(2000); - HAL_GPIO_WritePin(BLE_UBLOX_DSR_GPIO_PORT,BLE_UBLOX_DSR_PIN,GPIO_PIN_RESET); + case BM_INIT_COMMAND_ON: HAL_Delay(2600); + HAL_GPIO_WritePin(BLE_UBLOX_DSR_GPIO_PORT,BLE_UBLOX_DSR_PIN,GPIO_PIN_SET); BmTmpConfig++; break; +#if 0 case BM_INIT_TRIGGER_OFF: HAL_GPIO_WritePin(BLE_UBLOX_DSR_GPIO_PORT,BLE_UBLOX_DSR_PIN,GPIO_PIN_SET); HAL_Delay(2000); BmTmpConfig++; break; +#endif case BM_INIT_ECHO: case BM_INIT_ECHO2: sprintf(TxBuffer,"ATE0\r"); break; @@ -1878,6 +1890,7 @@ break; case BM_INIT_DONE: tInfo_write("Done"); BmTmpConfig = BM_CONFIG_DONE; + HAL_GPIO_WritePin(BLE_UBLOX_DSR_GPIO_PORT,BLE_UBLOX_DSR_PIN,GPIO_PIN_RESET); break; default: break;
--- a/Common/CPU1-F429.ld Sun Nov 02 19:30:58 2025 +0100 +++ b/Common/CPU1-F429.ld Sat Nov 15 19:29:44 2025 +0100 @@ -208,7 +208,7 @@ /* Define Known Address for Each Font */ /* Flash Sector 23 is protected (bootloader font + image) => use end of sector 22 */ -.lower_fonts 0x080A0000 : { +.lower_fonts 0x080AA000 : { *(.lower_fonts.image_data_*) *(.lower_fonts.*)
--- a/Common/Inc/configuration.h Sun Nov 02 19:30:58 2025 +0100 +++ b/Common/Inc/configuration.h Sat Nov 15 19:29:44 2025 +0100 @@ -72,8 +72,14 @@ /* Enable to have CO2 sensor functionality available */ #define ENABLE_CO2_SUPPORT -/* Enable to have GPS sensor functionality available */ -/* #define ENABLE_GNSS_SUPPORT */ +/* Enable to have external GPS sensor functionality available */ +/*#define ENABLE_GNSS_EXTERN*/ + +/* Enable to have internal (OSTC5) GPS sensor functionality available */ +/*#define ENABLE_GNSS_INTERN*/ + +/* Enable to provide UTC time to GNSS module at startup. ! CAUTION ! Incorrect time will reduce performance of module */ +/* #define ENABLE_GNSS_TIME_INIT */ /* Enable to have Sentinel rebreather interface available */ /* #define ENABLE_SENTINEL_MODE */ @@ -90,11 +96,20 @@ /* Enable to have a faster transfer speed between bluetooth module and CPU */ #define ENABLE_FAST_COMM -/* Enable to have position sensor support active */ -/* #define ENABLE_GPIO_V2 */ +/* Enable to have support of Polar HC10 heartbeat sensor active */ +/* #define ENABLE_PULSE_SENSOR_BT */ /* Enable RTE sleep mode debugging */ /* #define ENABLE_SLEEP_DEBUG */ +/* Enable to receive data from the radio connection usart */ +/* #define ENABLE_USART_RADIO */ + +/* Enable to show messages which are den during runtime in a popup window */ +/* #define ENABLE_LOGGER_WINDOW */ + +/* Enable to have the possibility to switch between four individual sets of settings */ +/* #define ENABLE_SETTING_PROFILES */ + #endif
--- a/Common/Inc/data_central.h Sun Nov 02 19:30:58 2025 +0100 +++ b/Common/Inc/data_central.h Sat Nov 15 19:29:44 2025 +0100 @@ -44,7 +44,8 @@ #define EXT_INTERFACE_SENSOR_CNT (8u) /* 1 MUX + 7 sensors may be connected to the external interface (1 MUX + 3 ADC + 4 UART) */ #define EXT_INTERFACE_MUX_OFFSET (3u) /* the sensor struct starts with 3 ADC sensors */ -#define EXT_INTERFACE_BUZZER_ON_TIME_MS (2000u) /* max time the buzzer should be active without break */ +#define EXT_INTERFACE_BUZZER_ON_TIME_MS (2000u) /* max time the buzzer should be active without break (continuous Operation) */ +#define EXT_INTERFACE_BUZZER_PING_TIME_MS (1000u) /* max time the buzzer should be active for single ping */ #define EXT_INTERFACE_BUZZER_STABLE_TIME_MS (500u) /* min time a state (ON / OFF) should be stable before it may be changed */ @@ -343,6 +344,8 @@ uint16_t info_compassHeadingUpdate; int16_t gnssPositionUpdate; SGnssCoord info_gnssPosition; + int16_t scrubberState; + uint16_t info_scrubberState; } SEvents; @@ -591,10 +594,13 @@ uint8_t drawingColor_from_ascentspeed(float speed); +void formatStringOfTime(char* pString, uint8_t strLen, RTC_TimeTypeDef Stime, uint8_t showAlive, uint8_t showSeconds); void convertStringOfDate_DDMMYY(char* pString, uint8_t strLen, uint8_t day, uint8_t month, uint8_t year); void getStringOfFormat_DDMMYY(char* pString, uint8_t strLen); void convertUTCToLocal(uint8_t utcHours, uint8_t utcMinutes, uint8_t* pLocalHours, uint8_t* pLocalMinutes); uint8_t calculateSlowExit(uint16_t* pCountDownSec, float* pExitDepthMeter, uint8_t* pColor); +bool isScrubberTimerEnabled(const SSettings *settings); +bool isScrubberTimerRunning(const SDiveState *diveState, const SSettings *settings); #endif // DATA_CENTRAL_H
--- a/Common/Inc/data_exchange.h Sun Nov 02 19:30:58 2025 +0100 +++ b/Common/Inc/data_exchange.h Sat Nov 15 19:29:44 2025 +0100 @@ -339,7 +339,7 @@ uint8_t revisionHardware; uint8_t revisionCRCx0x7A; - uint8_t spare1_3; + uint8_t displayVersion; uint8_t spare1_4; uint8_t setAccidentFlag;
--- a/Common/Inc/settings.h Sun Nov 02 19:30:58 2025 +0100 +++ b/Common/Inc/settings.h Sat Nov 15 19:29:44 2025 +0100 @@ -32,8 +32,7 @@ // From Common/Inc: #include "FirmwareData.h" - -//#include "data_central.h" +#include "firmwareEraseProgram.h" #include "global_constants.h" // From Common/Drivers/ @@ -76,10 +75,16 @@ #define PRESSURE_OFFSET_LIMIT_MBAR 50 #define MAX_COMPASS_COMP (2u) + +#define MAX_COMPASS_DECLINATION_DEG 99 + #define MAX_VIEWPORT_MODE (0x7F) -#define MAX_SCRUBBER_TIME (999u) +#define MAX_SCRUBBER_TIME (999u) #define MIN_SCRUBBER_TIME -99 +#define SCRUBBER_WARNING_TIME 30 +#define SCRUBBER_ERROR_TIME 0 + #define MIN_PPO2_SP_CBAR (40u) #define PSCR_MAX_O2_DROP (15u) @@ -90,6 +95,8 @@ #define FUTURE_SPARE_SIZE (0u) /* Applied for reuse of old, not used, scooter block (was 32 bytes)*/ +#define NUMBER_OF_PROFILES (4u) + typedef enum { O2_SENSOR_SOURCE_OPTIC = 0, @@ -105,7 +112,7 @@ typedef enum { - SCRUB_TIMER_OFF = 0, + INVALID_SCRUB_TIMER_OFF = 0, SCRUB_TIMER_MINUTES, SCRUB_TIMER_PERCENT, SCRUB_TIMER_END @@ -255,7 +262,7 @@ uint8_t co2_sensor_active; /* redefined in 0xFFFF0021 */ uint8_t ext_uart_protocol; /* redefined in 0xFFFF0022 */ - uint8_t scubberActiveId; /* redefined in 0xFFFF0023 */ + uint8_t scrubberActiveId; /* redefined in 0xFFFF0023 */ SScrubberData scrubberData[2]; uint8_t ext_sensor_map_Obsolete[5]; uint8_t buttonLockActive; /* redefined in 0xFFFF0025 */ @@ -324,35 +331,11 @@ /* new in 0xFFFF002c */ StimeZone timeZone; uint8_t warningBuzzer; + /* new in 0xFFFF002d */ + uint8_t profileName[NUMBER_OF_PROFILES][9]; + uint8_t activeProfile; } SSettings; -typedef struct -{ - // 8 bytes - uint16_t primarySerial; - uint8_t primaryLicence; - uint8_t revision8bit; - uint8_t production_year; - uint8_t production_month; - uint8_t production_day; - uint8_t production_bluetooth_name_set; - - // 44 bytes - char production_info[44]; - - // 8 bytes - uint16_t secondarySerial; - uint8_t secondaryLicence; - uint8_t secondaryReason8bit; - uint8_t secondary_year; - uint8_t secondary_month; - uint8_t secondary_day; - uint8_t secondary_bluetooth_name_set; - - // 4 bytes - char secondary_info[4]; -} SHardwareData; - uint8_t writeData(uint8_t *); uint8_t readData(uint8_t what,uint8_t *); uint8_t readDataLimits__8and16BitValues_4and7BytesOutput(uint8_t what, uint8_t * data); @@ -364,9 +347,11 @@ uint8_t getDecoType(void); uint8_t getFutureTTS(void); +uint16_t settingsGetSize(); SSettings* settingsGetPointer(void); +SSettings* profileGetPointer(uint8_t number); const SSettings* settingsGetPointerStandard(void); -void set_settings_to_Standard(void); +void set_settings_to_Standard(uint8_t whichSettings); void mod_settings_for_first_start_with_empty_ext_flash(void); const SFirmwareData* firmwareDataGetPointer(void); const SHardwareData* hardwareDataGetPointer(void); @@ -382,8 +367,9 @@ void setActualRTEversion(uint8_t high, uint8_t low); void getActualRTEandFONTversion(uint8_t *RTEhigh, uint8_t *RTElow, uint8_t *FONThigh, uint8_t *FONTlow); -void set_new_settings_missing_in_ext_flash(void); -uint8_t check_and_correct_settings(void); +void setFlipDisplay(uint8_t flipDisplay); +void set_new_settings_missing_in_ext_flash(uint8_t whichSettings); +uint8_t check_and_correct_settings(uint8_t whichSettings); uint8_t newFirmwareVersionCheckViaSettings(void); void set_settings_button_to_factory_with_individual_buttonBalance(void); uint8_t getLicence(void); @@ -405,4 +391,7 @@ uint8_t isSettingsWarning(); bool checkAndFixSetpointSettings(void); + +bool isScrubberWarning(const SScrubberData *scrubberData); +bool isScrubberError(const SScrubberData *scrubberData); #endif // SETTINGS_H
--- a/Current build/readme.txt Sun Nov 02 19:30:58 2025 +0100 +++ b/Current build/readme.txt Sat Nov 15 19:29:44 2025 +0100 @@ -1,3 +1,3 @@ -Heinrichs Weikamp OSTC4 update files. +Heinrichs Weikamp OSTC4 / OSTC 5 update files. The builds are for testing purposes only. Be careful, they might not work and are definitely not recommended for real dives. \ No newline at end of file
--- a/Discovery/Inc/base.h Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Inc/base.h Sat Nov 15 19:29:44 2025 +0100 @@ -111,6 +111,7 @@ void set_globalState_Menu_Line(uint8_t line); uint8_t get_globalState_Menu_Line(void); void get_idSpecificStateList(uint32_t id, SStateList *output); +uint8_t get_lineOfID(uint32_t id); void delayMicros(uint32_t micros); void get_RTC_DateTime(RTC_DateTypeDef * sdatestructureget, RTC_TimeTypeDef * stimestructureget); void set_RTC_DateTime(RTC_DateTypeDef * sdatestructure, RTC_TimeTypeDef * stimestructure);
--- a/Discovery/Inc/check_warning.h Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Inc/check_warning.h Sat Nov 15 19:29:44 2025 +0100 @@ -30,6 +30,12 @@ #include <stdint.h> #include "data_central.h" + +#define REQUEST_BUZZER_OFF (0u) +#define REQUEST_BUZZER_ONCE (1u) +#define REQUEST_BUZZER_CONTINUOUS (2u) + + /* Exported function prototypes ----------------------------------------------*/ void check_warning(void); void check_warning2(SDiveState *pDiveState); @@ -46,5 +52,7 @@ uint8_t getSetpointLowId(void); uint8_t getSetpointDecoId(void); void requestBuzzerActivation(uint8_t active); +uint8_t getBuzzerActivationRequest(); uint8_t getBuzzerActivationState(); +void deactivateBuzzer(); #endif // CHECK_WARNING_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Discovery/Inc/cv_heartbeat.h Sat Nov 15 19:29:44 2025 +0100 @@ -0,0 +1,143 @@ +/////////////////////////////////////////////////////////////////////////////// +/// -*- coding: UTF-8 -*- +/// +/// \file Discovery/Inc/cv_heartbeat.h +/// \brief Function definitions for connecting to a Polar HC10 heartbeat sensor +/// \date 3 July 2025 + +/////////////////////////////////////////////////////////////////////////////// +/// \par Copyright (c) 2014-2015 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 <http://www.gnu.org/licenses/>. +////////////////////////////////////////////////////////////////////////////// + +#ifndef INC_CV_HEARTBEAT_H_ +#define INC_CV_HEARTBEAT_H_ + +#include <stdint.h> + + +#define BLUEMOD_ADDR_SIZE (20u) /* length of address respond */ +#define BLUEMOD_RSSI_SIZE (5u) +#define BLUEMOD_NAME_SIZE (40u) + +void openEdit_Heartbeat(void); + +typedef enum +{ + NO_INDICATOR = 0, + DEVICE_INDICATOR, + CONNECTION_INDICATOR, + SERVICE_INDICATOR, + CHARACTERISTIC_INDICATOR, + DESCRIPTOR_INDICATOR, + PULSE_INDICATOR, + OK_INDICATOR, /* module control */ + ERROR_INDICATOR /* module control */ +} indicatior_t; + +typedef enum +{ + BT_READ_NOTHING = 0, + BT_READ_DEVICE_ADDR, + BT_READ_DEVICE_RSSI, + BT_READ_DEVICE_NAME, + BT_READ_CON_DETAILS, + BT_READ_SERV_HANDLE, + BT_READ_SERV_START, + BT_READ_SERV_END, + BT_READ_SERV_UUID, + BT_READ_CHAR_CONHANDLE, + BT_READ_CHAR_ATTRIBUTE, + BT_READ_CHAR_PROPERTY, + BT_READ_CHAR_VALUEHANDLE, + BT_READ_CHAR_UUID, + BT_READ_DESC_CONHANDLE, + BT_READ_DESC_CHARHANDLE, + BT_READ_DESC_DESCHANDLE, + BT_READ_DESC_UUID, + BT_READ_PULSE_CONHANDLE, + BT_READ_PULSE_VALUEHANDLE, + BT_READ_PULSE_DATA, +} readDataType_t; + +typedef enum + { + SENSOR_HB_OFFLINE = 0, /* Default Status no data available */ + SENSOR_HB_ENABLE_BLE, + SENSOR_HB_CHECK_CONFIG, + SENSOR_HB_DISCOVER, + SENSOR_HB_CONNECT, + SENSOR_HB_DISCONNECT, + SENSOR_HB_SERVICES, + SENSOR_HB_CHARACTERISTIC, + SENSOR_HB_DESCRIPTOR, + SENSOR_HB_SUBSCRIBE, + SENSOR_HB_RESTART, + SENSOR_HB_DETECTION_INDICATOR, /* searching for indicators to identify data items */ + SENSOR_HB_DETECTION_RSSI, + SENSOR_HB_DETECTION_NAME, + SENSOR_HB_DETECTION_MAN, + SENSOR_HB_DETECTION_UUID, + SENSOR_HB_FOUND, /* A device providing the requested service was found */ + SENSOR_HB_CONNECTED, /* Connection to heartbeat sensor established */ + SENSOR_HB_OFFLINEMODE, /* Oflline measurement started */ + } sensorHeartbeat_State_t; + +typedef struct +{ + uint8_t address[BLUEMOD_ADDR_SIZE]; + uint8_t rssi[BLUEMOD_RSSI_SIZE]; + uint8_t name[BLUEMOD_NAME_SIZE]; +} btDdeviceData_t; + + +typedef struct +{ + uint8_t handle; + uint8_t start[6]; + uint8_t end[6]; + uint8_t uuid[50]; +} btDeviceService_t; + +typedef struct +{ + uint8_t conHandle; + uint8_t attrHandle[10]; + uint8_t properties[10]; + uint8_t valueHandle[10]; + uint8_t uuid[50]; +} btDeviceCharacteristic_t; + +typedef struct +{ + uint8_t conHandle; + uint8_t charHandle[10]; + uint8_t descHandle[10]; + uint8_t uuid[50]; +} btDeviceDescriptor_t; + +typedef struct { + uint16_t heart_rate; + uint16_t energy_expended; + uint16_t rr_intervals[10]; + uint8_t rr_count; +} HRMeasurement_t; + +sensorHeartbeat_State_t cv_heartbeat_getState(); +void refresh_Heartbeat(void); +void cv_heartbeat_Control(void); +uint8_t cv_heartbeat_HandleData(); + +#endif /* INC_CV_HEARTBEAT_H_ */
--- a/Discovery/Inc/demo.h Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Inc/demo.h Sat Nov 15 19:29:44 2025 +0100 @@ -35,4 +35,6 @@ void demoConfigureSettings(void); void demoSendCommand(uint8_t action); +void demo_HandleData(void); + #endif // DEMO_H
--- a/Discovery/Inc/externLogbookFlash.h Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Inc/externLogbookFlash.h Sat Nov 15 19:29:44 2025 +0100 @@ -41,7 +41,17 @@ */ #define DDSTART 0x00000000 #define DDSTOP 0x00000FFF -#define unused1START 0x00001000 + +#define PROFILE0_START 0x00001000 /* store profiles within one 4k sector because they are always read / written as one block */ +#define PROFILE0_STOP 0x000013FF /* no ring functionality is implemented because changes are not expected very often */ +#define PROFILE1_START 0x00001400 +#define PROFILE1_STOP 0x000017FF +#define PROFILE2_START 0x00001800 +#define PROFILE2_STOP 0x00001BFF +#define PROFILE3_START 0x00001C00 +#define PROFILE3_STOP 0x00001FFF + +#define unused1START 0x00002000 #define unused1STOP 0x00007FFF /* 32 KB */ @@ -84,6 +94,22 @@ #define SECTOR_INUSE (4) #define SECTOR_EMPTY (5) + +typedef enum{ + EF_HEADER, + EF_SAMPLE, + EF_DEVICEDATA, + EF_VPMDATA, + EF_SETTINGS, + EF_FIRMWARE, + EF_FIRMWARE2, + EF_PROFILE0, + EF_PROFILE1, + EF_PROFILE2, + EF_PROFILE3, +}which_ring_enum; + + /* Exported types ------------------------------------------------------------*/ typedef struct{ uint8_t byteLow; @@ -108,8 +134,8 @@ } convert16_Type; /* Exported functions --------------------------------------------------------*/ -void ext_flash_write_settings(uint8_t resetRing); -uint8_t ext_flash_read_settings(void); +void ext_flash_write_settings(uint8_t whichSettings, uint8_t resetRing); +uint8_t ext_flash_read_settings(uint8_t whichSettings); void ext_flash_write_devicedata(uint8_t resetRing); uint16_t ext_flash_read_devicedata(uint8_t *buffer, uint16_t max_length);
--- a/Discovery/Inc/firmwareEraseProgram.h Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Inc/firmwareEraseProgram.h Sat Nov 15 19:29:44 2025 +0100 @@ -41,11 +41,42 @@ #define HARDWAREDATA_ADDRESS (0x08000000 + 0x0000A040) /* Exported functions --------------------------------------------------------*/ + typedef struct + { + // 8 bytes + uint16_t primarySerial; + uint8_t primaryLicence; + uint8_t revision8bit; + uint8_t production_year; + uint8_t production_month; + uint8_t production_day; + uint8_t production_bluetooth_name_set; + // 44 bytes + char production_info[44]; + + // 8 bytes + uint16_t secondarySerial; + uint8_t secondaryLicence; + uint8_t secondaryReason8bit; + uint8_t secondary_year; + uint8_t secondary_month; + uint8_t secondary_day; + uint8_t secondary_bluetooth_name_set; + + // 4 bytes + char secondary_info[4]; + } SHardwareData; + + +uint32_t CalcFletcher32(uint32_t startAddr, uint32_t endAddr); uint8_t firmware_eraseFlashMemory(void); uint8_t firmware_programFlashMemory(uint8_t *pBuffer1, uint32_t length1);//, uint8_t *pBuffer2, uint32_t length2) +uint8_t bootloader_eraseFlashMemory(void); +uint8_t bootloader_programFlashMemory(uint8_t *pBuffer1, uint32_t length1, SHardwareData* pHwInfo); + uint8_t firmware2_variable_upperpart_eraseFlashMemory(uint32_t length, uint32_t offset); uint8_t firmware2_variable_upperpart_programFlashMemory(uint32_t length, uint32_t offset, uint8_t *pBuffer1, uint32_t pBuffer1Size, uint8_t *pBuffer2);
--- a/Discovery/Inc/gfx_colors.h Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Inc/gfx_colors.h Sat Nov 15 19:29:44 2025 +0100 @@ -87,8 +87,8 @@ CLUT_MenuPageHardware, CLUT_MenuPageSystem, CLUT_MenuPageCustomView, + CLUT_MenuPageCvOption, CLUT_MenuPageDivePlanner, - CLUT_MenuPage10, CLUT_ButtonSymbols, CLUT_InfoSurface, CLUT_InfoDive,
--- a/Discovery/Inc/gfx_engine.h Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Inc/gfx_engine.h Sat Nov 15 19:29:44 2025 +0100 @@ -140,6 +140,7 @@ void GFX_clear_window_immediately(GFX_DrawCfgWindow* hgfx); //void GFX_draw_circle_with_MEMORY(uint8_t use_memory, GFX_DrawCfgScreen *hgfx, point_t center, uint8_t radius, int8_t color); +void GFX_draw_pixel(GFX_DrawCfgScreen *hgfx, int16_t x, int16_t y, uint8_t color); void GFX_draw_circle(GFX_DrawCfgScreen *hgfx, point_t center, uint8_t radius, int8_t color); void GFX_draw_colorline(GFX_DrawCfgScreen *hgfx, point_t start, point_t stop, uint8_t color); void GFX_draw_thick_line(uint8_t thickness, GFX_DrawCfgScreen *hgfx, point_t start, point_t stop, uint8_t color);
--- a/Discovery/Inc/logbook.h Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Inc/logbook.h Sat Nov 15 19:29:44 2025 +0100 @@ -212,7 +212,7 @@ uint8_t logbook_getHeader(uint8_t StepBackwards,SLogbookHeader* pLogbookHeader); uint16_t logbook_readSampleData(uint8_t StepBackwards, uint16_t length,uint16_t* depth, uint8_t* gasid, int16_t* temperature, uint16_t* ppo2, uint16_t* setpoint, uint16_t* sensor1, uint16_t* sensor2, uint16_t* sensor3, uint16_t* cns, uint8_t* bailout, - uint16_t* decostopDepth, uint16_t* tank, SGnssCoord* pPosition, uint8_t* event); + uint16_t* decostopDepth, uint16_t* tank, uint16_t* compassHeading, SGnssCoord* pPosition, uint16_t* scrubberState, uint8_t* event); void logbook_test(void); void logbook_InitAndWrite(SDiveState* pStateReal); void logbook_recover_brokenlog(uint8_t headerId); @@ -221,4 +221,6 @@ uint16_t logbook_fillDummySampleBuffer(SLogbookHeader* pHeader); void logbook_readDummySamples(uint8_t* pTarget, uint16_t length); +void logScrubberState(const SScrubberData *scrubberData); + #endif /* LOGBOOK_H */
--- a/Discovery/Inc/ostc.h Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Inc/ostc.h Sat Nov 15 19:29:44 2025 +0100 @@ -60,6 +60,10 @@ #define DISPLAY_VERSION_LCD (0u) #define DISPLAY_VERSION_NEW (1u) +#define CHUNK_SIZE (160u) /* the DMA will handle chunk size transfers */ +#define CHUNKS_PER_BUFFER (3u) + + /* Exported variables --------------------------------------------------------*/ extern SPI_HandleTypeDef hspiDisplay; @@ -82,6 +86,7 @@ void MX_SPI_Init(void); void MX_GPIO_Init(void); void MX_UART_Init(void); +void MX_UART_BT_Init_DMA(); uint8_t MX_UART_ButtonAdjust(uint8_t *array); void MX_SmallCPU_Reset_To_Boot(void); @@ -104,5 +109,15 @@ void SetDisplayVersion(uint8_t version); uint8_t isNewDisplay(void); +uint8_t UART_getChar(); + +#ifdef ENABLE_PULSE_SENSOR_BT +void UART_StartDMARx(); +#endif +#ifdef ENABLE_USART_RADIO +void MX_UART_RADIO_Init_DMA(); +void UART_StartDMARxRadio(); +#endif + #endif // OSTC_H
--- a/Discovery/Inc/ostc_hw2.h Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Inc/ostc_hw2.h Sat Nov 15 19:29:44 2025 +0100 @@ -167,6 +167,22 @@ #define USART_IR_HUD_IRQn USART2_IRQn // to it directly#define USART_IR_HUD_IRQHandler USART2_IRQHandler +#define USART_RADIO USART3 +#define USART_RADIO_CLK_ENABLE() __USART3_CLK_ENABLE(); +#define USART_RADIO_FORCE_RESET() __USART3_FORCE_RESET() +#define USART_RADIO_RELEASE_RESET() __USART3_RELEASE_RESET() +//#define USART_IR_HUD_TX_AF GPIO_AF7_USART3 +//#define USART_IR_HUD_TX_PIN GPIO_PIN_5 +//#define USART_IR_HUD_TX_GPIO_PORT GPIOD +//#define USART_IR_HUD_TX_GPIO_CLK_ENABLE() __GPIOD_CLK_ENABLE() + +#define USART_RADIO_RX_AF GPIO_AF7_USART3 +#define USART_RADIO_RX_PIN GPIO_PIN_11 +#define USART_RADIO_RX_GPIO_PORT GPIOB +#define USART_RADIO_RX_GPIO_CLK_ENABLE() __GPIOB_CLK_ENABLE() +#define USART_RADIO_IRQn USART3_IRQn + + #define TIMx TIM4 #define TIMx_CLK_ENABLE __TIM4_CLK_ENABLE #define TIMx_IRQn TIM4_IRQn
--- a/Discovery/Inc/simulation.h Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Inc/simulation.h Sat Nov 15 19:29:44 2025 +0100 @@ -63,7 +63,11 @@ SDecoinfo* simulation_decoplaner_Bachelorarbeit_VPM(uint16_t depth_meter, uint16_t intervall_time_minutes, uint16_t dive_time_minutes, SgasChangeList *pGasChangeList); void simulation_gas_consumption(uint16_t *outputConsumptionList, uint16_t depth_meter, uint16_t dive_time_minutes, SDecoinfo *decoInfoInput, uint8_t gasConsumTravelInput, uint8_t gasConsumDecoInput, const SgasChangeList *pGasChangeList); void simulation_helper_change_points(SSimDataSummary *outputSummary, uint16_t depth_meter, uint16_t dive_time_minutes, SDecoinfo *decoInfoInput, const SgasChangeList *pGasChangeList); - +void simulation_evaluate_profil(uint16_t *outputConsumptionList, + SSimDataSummary *outputSummary, + uint16_t depth_meter, uint16_t dive_time_minutes,uint8_t gasConsumTravelInput, uint8_t gasConsumDecoInput, + SDecoinfo *decoInfoInput, + const SgasChangeList *pGasChangeList); void Sim_Descend (void); void Sim_Ascend (void);
--- a/Discovery/Inc/t3.h Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Inc/t3.h Sat Nov 15 19:29:44 2025 +0100 @@ -44,6 +44,6 @@ uint8_t t3_customview_disabled(uint8_t view); void t3_handleAutofocus(void); -int printScrubberText(char *text, size_t size, const SScrubberData *scrubberData, SSettings *settings); +unsigned printScrubberText(char *text, size_t size, const SScrubberData scrubberData[], const SSettings *settings, bool useTwoLines); #endif /* T3_H */
--- a/Discovery/Inc/tComm.h Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Inc/tComm.h Sat Nov 15 19:29:44 2025 +0100 @@ -43,10 +43,13 @@ BM_CONFIG_SILENCE, BM_CONFIG_DONE, BM_CONFIG_RETRY, + BM_CONFIG5_ESCAPE1 = 50, + BM_CONFIG5_ESCAPE2, + BM_CONFIG5_BAUD, + BM_CONFIG5_DATAMODE, BM_INIT_POWEROFF = 100, BM_INIT_POWERON, - BM_INIT_TRIGGER_ON, - BM_INIT_TRIGGER_OFF, + BM_INIT_COMMAND_ON, BM_INIT_ECHO, BM_INIT_FACTORY, BM_INIT_ECHO2,
--- a/Discovery/Inc/tHome.h Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Inc/tHome.h Sat Nov 15 19:29:44 2025 +0100 @@ -81,7 +81,10 @@ CVIEW_CcrSummary, CVIEW_Timer, CVIEW_Position, - CVIEW_END /* The ID is used in shift operation => 31 is the max number of supported views */ +#ifdef ENABLE_LOGGER_WINDOW + CVIEW_Logger = 25, /* keep development views at the end of the list to avoid id problems in official releases */ +#endif + CVIEW_END = 32 /* The ID is used in shift operation => 31 is the max number of supported views */ }; enum CUSTOMVIEWS_BF
--- a/Discovery/Inc/tInfo.h Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Inc/tInfo.h Sat Nov 15 19:29:44 2025 +0100 @@ -60,10 +60,15 @@ void tInfo_write_buttonTextline(GFX_DrawCfgScreen *screenPtr, uint8_t left2ByteCode, char middle2ByteCode, char right2ByteCode); void tInfo_write_buttonTextline_simple(uint8_t left2ByteCode, char middle2ByteCode, char right2ByteCode); +void tInfo_drawPixel(int16_t x, int16_t y, uint8_t color); +void tInfo_draw_colorline(point_t start, point_t stop, uint8_t color); +void t_Info_draw_circle(point_t center, uint8_t radius, int8_t color); + void tInfo_setEvent(uint32_t inputEventID, uint32_t inputFunctionCall); void tInfo_set_on_off(uint32_t editID, uint8_t int1); void exitInfo(void); void exitInfoToBack(void); +void exitInfoSilent(void); #endif /* TINFO_H */
--- a/Discovery/Inc/tInfoCompass.h Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Inc/tInfoCompass.h Sat Nov 15 19:29:44 2025 +0100 @@ -28,6 +28,15 @@ #ifndef TINFO_COMPASS_H #define TINFO_COMPASS_H +#include "gfx.h" + +typedef struct +{ + point_t coord; + point_t eclipse; + uint8_t check[360]; +} axisIndicator_t; + /* Exported functions --------------------------------------------------------*/ void openInfo_Compass(void); void refreshInfo_Compass(GFX_DrawCfgScreen s);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Discovery/Inc/tInfoLogger.h Sat Nov 15 19:29:44 2025 +0100 @@ -0,0 +1,47 @@ +/////////////////////////////////////////////////////////////////////////////// +/// -*- coding: UTF-8 -*- +/// +/// \file Discovery/Inc/tInfoSensor.h +/// \brief Infopage content for visualisation of UART protocol flow +/// \author heinrichs weikamp gmbh +/// \date 17-07-2025 +/// +/// $Id$ +/////////////////////////////////////////////////////////////////////////////// +/// \par Copyright (c) 2014-2025 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 <http://www.gnu.org/licenses/>. +////////////////////////////////////////////////////////////////////////////// + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef TINFO_LOGGER_H +#define TINFO_LOGGER_H + +#define LINE_HEADER_BYTES (3u) +#define MAX_CHAR_PER_LINE (60u) +#define MAX_LOGGER_LINES (13u) + +#define LOG_TX_LINE (0u) +#define LOG_RX_LINE (1u) + +#include "gfx_engine.h" + +/* Exported functions --------------------------------------------------------*/ +void openInfo_Logger(); +void refreshInfo_Logger(GFX_DrawCfgScreen s); +void sendActionToInfoLogger(uint8_t sendAction); +void InfoLogger_writeLine(uint8_t* pLine,uint8_t lineLength,uint8_t direction); +uint8_t InfoLogger_isUpdated(); + +#endif /* TINFO_LOGGER_H */
--- a/Discovery/Inc/tMenu.h Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Inc/tMenu.h Sat Nov 15 19:29:44 2025 +0100 @@ -68,6 +68,7 @@ void nextline(char * text, uint8_t *textPointer); void tM_init(void); +void tM_build_pages(void); void openMenu(uint8_t freshWithFlipPages); void openMenu_first_page_with_OC_gas_update(void); void updateMenu(void); @@ -94,4 +95,5 @@ void clearDisabledMenuLines(void); char *makeGrey(bool isGrey); +char printCheckbox(bool isChecked); #endif /* TMENU_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Discovery/Inc/tMenuCvOption.h Sat Nov 15 19:29:44 2025 +0100 @@ -0,0 +1,47 @@ +/////////////////////////////////////////////////////////////////////////////// +/// -*- coding: UTF-8 -*- +/// +/// \file Discovery/Inc/tMenuCvOption.h +/// \brief Header file of Menu Lines for System settings +/// \author heinrichs weikamp gmbh +/// \date 24-April-2025 +/// +/// $Id$ +/////////////////////////////////////////////////////////////////////////////// +/// \par Copyright (c) 2014-2025 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 <http://www.gnu.org/licenses/>. +////////////////////////////////////////////////////////////////////////////// + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef TMENU_CVOPTION_H +#define TMENU_CVOPTION_H + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" +#include "gfx_engine.h" + +/** @addtogroup Template + * @{ + */ + +/* Exported variables --------------------------------------------------------*/ + + +/* Exported functions --------------------------------------------------------*/ + +uint32_t tMCvOption_refresh(uint8_t line, char *text, uint16_t *tab, char *subtext); +void tMCvOption_checkLineStatus(void); + +#endif /* TMENU_CVOPTION_H */
--- a/Discovery/Inc/tMenuEdit.h Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Inc/tMenuEdit.h Sat Nov 15 19:29:44 2025 +0100 @@ -68,7 +68,10 @@ void tMenuEdit_select(uint32_t editID); void evaluateNewString (uint32_t editID, uint32_t *pNewValue1, uint32_t *pNewValue2, uint32_t *pNewValue3, uint32_t *pNewValue4); +void evaluateNewStringText(uint32_t editID, uint8_t *pNewString); + void tMenuEdit_newInput (uint32_t editID, uint32_t int1, uint32_t int2, uint32_t int3, uint32_t int4); +void tMenuEdit_newInputText(uint32_t editID, uint8_t* ptext); void tMenuEdit_newButtonText(uint32_t editID, char *text); void tMenuEdit_set_on_off(uint32_t editID, uint32_t int1); @@ -91,6 +94,7 @@ void write_field_toggle(uint32_t editID, uint16_t XleftGimpStyle, uint16_t XrightGimpStyle, uint16_t YtopGimpStyle, const tFont *Font, const char *text, uint8_t int1, uint8_t int2); void write_field_on_off(uint32_t editID, uint16_t XleftGimpStyle, uint16_t XrightGimpStyle, uint16_t YtopGimpStyle, const tFont *Font, const char *text, uint8_t int1); void write_field_fpoint(uint32_t editID, uint16_t XleftGimpStyle, uint16_t XrightGimpStyle, uint16_t YtopGimpStyle, const tFont *Font, const char *text, float input); +void write_field_text(uint32_t editID, uint16_t XleftGimpStyle, uint16_t XrightGimpStyle, uint16_t YtopGimpStyle, const tFont *Font, const char *text, uint8_t* pInput); void stop_cursor_fields(void);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Discovery/Inc/tMenuEditCvOption.h Sat Nov 15 19:29:44 2025 +0100 @@ -0,0 +1,43 @@ +/////////////////////////////////////////////////////////////////////////////// +/// -*- coding: UTF-8 -*- +/// +/// \file Discovery/Inc/tMenuEditCvOption.h +/// \brief Header file for editing Hardware Settings +/// \author heinrichs weikamp gmbh +/// \date 24-Apr-2025 +/// +/// $Id$ +/////////////////////////////////////////////////////////////////////////////// +/// \par Copyright (c) 2014-2025 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 <http://www.gnu.org/licenses/>. +////////////////////////////////////////////////////////////////////////////// + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef TMENU_EDIT_CVOPTION_H +#define TMENU_EDIT_CVOPTION_H + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" +#include "gfx_engine.h" +#include "global_constants.h" +#include "settings.h" +#include "data_central.h" + +void openEdit_CvOption(uint8_t line); +void refresh_CompassEdit(void); +uint32_t tMCvOption_refresh(uint8_t line, char *text, uint16_t *tab, char *subtext); +void tMCvOption_checkLineStatus(void); + +#endif /* TMENU_EDIT_CVOPTION_H */
--- a/Discovery/Inc/tMenuSystem.h Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Inc/tMenuSystem.h Sat Nov 15 19:29:44 2025 +0100 @@ -36,6 +36,16 @@ * @{ */ +#define CUSTOM_BLOCK_INFO_ADDR (0x0811FFF0) + +typedef struct +{ + uint32_t Reserved; /* for future use */ + uint32_t Type; /* type => block purpose */ + uint32_t fletcher; /* fletcher check sum */ + uint32_t length; /* length of block starting from 0x08100000 */ +} customBlockInfo_t; + void set_CustomsviewsSubpage(uint8_t page); /* Exported variables --------------------------------------------------------*/ @@ -44,6 +54,5 @@ /* Exported functions --------------------------------------------------------*/ uint32_t tMSystem_refresh(uint8_t line, char *text, uint16_t *tab, char *subtext); -void tMSystem_checkLineStatus(void); #endif /* TMENU_SYSTEM_H */
--- a/Discovery/Inc/tStructure.h Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Inc/tStructure.h Sat Nov 15 19:29:44 2025 +0100 @@ -66,6 +66,7 @@ #define InfoPageCompass 6 #define InfoPageSensor 8 #define InfoPagePreDive 9 +#define InfoPageLogger 10 #define StI _MB(0,1,0,0,0) #define StILOGLIST _MB(0,2,0,0,0) @@ -76,6 +77,7 @@ #define StIDEBUG _MB(0,7,0,0,0) #define StISENINFO _MB(0,8,0,0,0) #define StIPREDIVE _MB(0,9,0,0,0) +#define StILOGGER _MB(0,10,0,0,0) #define StI_GoToLogbook _MB(0,1,1,0,0) #define StI_GoToPlanner _MB(0,1,2,0,0) @@ -214,17 +216,14 @@ #define StMXTRA_CCRmode _MB(2,4,1,1,0) #define StMXTRA_O2_Fallback _MB(2,4,2,1,0) #define StMXTRA_ScrubTimer _MB(2,4,3,1,0) -#define StMXTRA_ScrubTimer_Max _MB(2,4,3,2,0) -#define StMXTRA_ScrubTimer_Reset _MB(2,4,3,3,0) -#define StMXTRA_ScrubTimer_OP_Mode _MB(2,4,3,5,0) +#define StMXTRA_ScrubTimer_Active _MB(2,4,3,2,0) +#define StMXTRA_ScrubTimer_Max _MB(2,4,3,3,0) +#define StMXTRA_ScrubTimer_Reset _MB(2,4,3,4,0) +#define StMXTRA_ScrubTimer_OP_Mode _MB(2,4,3,6,0) #define StMXTRA_PSCR_O2_Drop _MB(2,4,4,1,0) #define StMXTRA_PSCR_LUNG_RATIO _MB(2,4,4,2,0) #define StMXTRA_Predive_Check _MB(2,4,5,1,0) - - - - /* PAGE 5 */ #define StMDECO _MB(2,5,0,0,0) @@ -273,136 +272,185 @@ #define StMHARD1_Bluetooth _MB(2,7,1,1,0) -#define StMHARD2_Compass _MB(2,7,2,0,0) -#define StMHARD2_Compass_SetCourse _MB(2,7,2,2,0) -#define StMHARD2_Compass_ResetCourse _MB(2,7,2,3,0) -#define StMHARD2_Compass_Calibrate _MB(2,7,2,4,0) -#define StMHARD2_Compass_Inertia _MB(2,7,2,5,0) -#define StMHARD2_Compass_Declination _MB(2,7,2,6,0) - //#define StMHARD2_Exit _MB(2,7,2,2,0) -#define StMHARD3_Sensors _MB(2,7,3,0,0) -#define StMHARD3_O2_Sensor1 _MB(2,7,3,1,0) -#define StMHARD3_O2_Sensor2 _MB(2,7,3,2,0) -#define StMHARD3_O2_Sensor3 _MB(2,7,3,3,0) -#define StMHARD3_O2_Calibrate _MB(2,7,3,4,0) -#define StMHARD3_Sensor_Info _MB(2,7,3,5,0) -#define StMHARD3_Sensor_Detect _MB(2,7,3,6,0) +#define StMHARD3_Sensors _MB(2,7,2,0,0) +#define StMHARD3_O2_Sensor1 _MB(2,7,2,1,0) +#define StMHARD3_O2_Sensor2 _MB(2,7,2,2,0) +#define StMHARD3_O2_Sensor3 _MB(2,7,2,3,0) +#define StMHARD3_O2_Calibrate _MB(2,7,2,4,0) +#define StMHARD3_Sensor_Info _MB(2,7,2,5,0) +#define StMHARD3_Sensor_Detect _MB(2,7,2,6,0) -#define StMHARD4_BrightnessEco _MB(2,7,4,1,0) -#define StMHARD4_BrightnessStd _MB(2,7,4,2,0) -#define StMHARD4_BrightnessHigh _MB(2,7,4,3,0) -#define StMHARD4_BrightnessMax _MB(2,7,4,4,0) +#define StMHARD4_BrightnessEco _MB(2,7,3,1,0) +#define StMHARD4_BrightnessStd _MB(2,7,3,2,0) +#define StMHARD4_BrightnessHigh _MB(2,7,3,3,0) +#define StMHARD4_BrightnessMax _MB(2,7,3,4,0) -#define StMHARD5_Button1 _MB(2,7,5,1,0) -#define StMHARD5_ButtonBalance1 _MB(2,7,5,2,0) -#define StMHARD5_ButtonBalance2 _MB(2,7,5,3,0) -#define StMHARD5_ButtonBalance3 _MB(2,7,5,4,0) -#define StMHARD5_ButtonLock _MB(2,7,5,5,0) +#define StMHARD5_Button1 _MB(2,7,4,1,0) +#define StMHARD5_ButtonBalance1 _MB(2,7,4,2,0) +#define StMHARD5_ButtonBalance2 _MB(2,7,4,3,0) +#define StMHARD5_ButtonBalance3 _MB(2,7,4,4,0) +#define StMHARD5_ButtonLock _MB(2,7,4,5,0) + +#define StMHARD6_WarningBuz _MB(2,7,5,1,0) //#define StMHARD6_UpdateCPU2_No _MB(2,7,6,1,0) //#define StMHARD6_UpdateCPU2_Yes _MB(2,7,6,2,0) //#define StMHARD6_UpdateCPU2_Now _MB(2,7,6,3,0) /* PAGE 8 */ -#define StMSYS _MB(2,8,0,0,0) +#define StMOption _MB(2,8,0,0,0) +#define StMOption_Compass _MB(2,8,1,0,0) +#define StMOption_Compass_SetCourse _MB(2,8,1,1,0) +#define StMOption_Compass_ResetCourse _MB(2,8,1,2,0) +#define StMOption_Compass_Calibrate _MB(2,8,1,3,0) +#define StMOption_Compass_Inertia _MB(2,8,1,4,0) +#define StMOption_Compass_Declination _MB(2,8,1,5,0) -/* PAGE 8 EDIT FIELD CONTENT */ -#define StMSYS1_DateTime _MB(2,8,1,0,0) -#define StMSYS1_Date _MB(2,8,1,1,0) -#define StMSYS1_Time _MB(2,8,1,2,0) -#define StMSYS1_FORMAT _MB(2,8,1,3,0) -#define StMSYS1_DDMMYY _MB(2,8,1,3,1) -#define StMSYS1_MMDDYY _MB(2,8,1,3,2) -#define StMSYS1_YYMMDD _MB(2,8,1,3,3) -#define StMSYS1_12HR _MB(2,8,1,4,0) -#define StMSYS1_GNSSDT _MB(2,8,1,5,0) -#define StMSYS1_ZONE _MB(2,8,1,6,0) +#define StMOption_Timer _MB(2,8,2,0,0) +#define StMOption_Timer_Value _MB(2,8,2,1,0) + +#define StMOption_Heartbeat _MB(2,8,3,0,0) + +/* PAGE 9 */ +#define StMSYS _MB(2,9,0,0,0) -#define StMSYS_Timer _MB(2,8,2,1,0) +/* PAGE 9 EDIT FIELD CONTENT */ +#define StMSYS1_DateTime _MB(2,9,1,0,0) +#define StMSYS1_Date _MB(2,9,1,1,0) +#define StMSYS1_Time _MB(2,9,1,2,0) +#define StMSYS1_FORMAT _MB(2,9,1,3,0) +#define StMSYS1_DDMMYY _MB(2,9,1,3,1) +#define StMSYS1_MMDDYY _MB(2,9,1,3,2) +#define StMSYS1_YYMMDD _MB(2,9,1,3,3) +#define StMSYS1_12HR _MB(2,9,1,4,0) +#define StMSYS1_GNSSDT _MB(2,9,1,5,0) +#define StMSYS1_ZONE _MB(2,9,1,6,0) -#define StMSYS2_English _MB(2,8,3,1,0) -#define StMSYS2_German _MB(2,8,3,2,0) -#define StMSYS2_French _MB(2,8,3,3,0) -#define StMSYS2_Italian _MB(2,8,3,4,0) -#define StMSYS2_Espanol _MB(2,8,3,5,0) +#ifdef ENABLE_SETTING_PROFILES +#define StMSYS_Profile _MB(2,9,2,0,0) +#define StMSYS_ProfileA _MB(2,9,2,1,0) +#define StMSYS_ProfileB _MB(2,9,2,2,0) +#define StMSYS_ProfileC _MB(2,9,2,3,0) +#define StMSYS_ProfileD _MB(2,9,2,4,0) -#define StMSYS3_Units _MB(2,8,4,1,0) -#define StMSYS3_Colors _MB(2,8,4,2,0) -#define StMSYS3_Debug _MB(2,8,4,3,0) +#define StMSYS2_English _MB(2,9,3,1,0) +#define StMSYS2_German _MB(2,9,3,2,0) +#define StMSYS2_French _MB(2,9,3,3,0) +#define StMSYS2_Italian _MB(2,9,3,4,0) +#define StMSYS2_Espanol _MB(2,9,3,5,0) -#define StMSYS4_Info _MB(2,8,5,1,0) +#define StMSYS3_Units _MB(2,9,4,1,0) +#define StMSYS3_Colors _MB(2,9,4,2,0) +#ifdef HAVE_DEBUG_VIEW +#define StMSYS3_Debug _MB(2,9,4,3,0) +#endif + +#define StMSYS4_Info _MB(2,9,5,1,0) -#define StMSYS5_Exit _MB(2,8,6,1,0) -#define StMSYS5_LogbookOffset _MB(2,8,6,7,0) -#define StMSYS5_ResetAll _MB(2,8,6,2,0) -#define StMSYS5_ResetDeco _MB(2,8,6,3,0) -#define StMSYS5_Reboot _MB(2,8,6,4,0) -#define StMSYS5_Maintenance _MB(2,8,6,5,0) -#define StMSYS5_ResetLogbook _MB(2,8,6,6,0) -#define StMSYS5_SetBattCharge _MB(2,8,6,7,0) -#define StMSYS5_RebootRTE _MB(2,8,6,8,0) -#define StMSYS5_RebootMainCPU _MB(2,8,6,9,0) -#define StMSYS5_ScreenTest _MB(2,8,6,10,0) -#define StMSYS5_SetFactoryBC _MB(2,8,6,11,0) -#define StMSYS5_ResetBluetooth _MB(2,8,6,12,0) -#define StMSYS5_SetSampleIndx _MB(2,8,6,13,0) -#define StMSYS5_AdjustSurfPres _MB(2,8,6,14,0) +#define StMSYS5_Exit _MB(2,9,6,1,0) +#define StMSYS5_LogbookOffset _MB(2,9,6,7,0) +#define StMSYS5_ResetAll _MB(2,9,6,2,0) +#define StMSYS5_ResetDeco _MB(2,9,6,3,0) +#define StMSYS5_Reboot _MB(2,9,6,4,0) +#define StMSYS5_Maintenance _MB(2,9,6,5,0) +#define StMSYS5_ResetLogbook _MB(2,9,6,6,0) +#define StMSYS5_SetBattCharge _MB(2,9,6,7,0) +#define StMSYS5_RebootRTE _MB(2,9,6,8,0) +#define StMSYS5_RebootMainCPU _MB(2,9,6,9,0) +#define StMSYS5_ScreenTest _MB(2,9,6,10,0) +#define StMSYS5_SetFactoryBC _MB(2,9,6,11,0) +#define StMSYS5_ResetBluetooth _MB(2,9,6,12,0) +#define StMSYS5_SetSampleIndx _MB(2,9,6,13,0) +#define StMSYS5_AdjustSurfPres _MB(2,9,6,14,0) +#define StMSYS5_FlashBoot _MB(2,9,6,15,0) + +#else + +#define StMSYS2_English _MB(2,9,2,1,0) +#define StMSYS2_German _MB(2,9,2,2,0) +#define StMSYS2_French _MB(2,9,2,3,0) +#define StMSYS2_Italian _MB(2,9,2,4,0) +#define StMSYS2_Espanol _MB(2,9,2,5,0) + +#define StMSYS3_Units _MB(2,9,3,1,0) +#define StMSYS3_Colors _MB(2,9,3,2,0) +#ifdef HAVE_DEBUG_VIEW +#define StMSYS3_Debug _MB(2,9,3,3,0) +#endif -#define StMSYS_Custom0 _MB(2,8,1,0,0) -#define StMSYS_Custom1 _MB(2,8,2,0,0) -#define StMSYS_Custom2 _MB(2,8,3,0,0) -#define StMSYS_Custom3 _MB(2,8,4,0,0) -#define StMSYS_Custom4 _MB(2,8,5,0,0) -#define StMSYS_Custom5 _MB(2,8,6,0,0) +#define StMSYS4_Info _MB(2,9,4,1,0) - /* PAGE 9 */ +#define StMSYS5_Exit _MB(2,9,5,1,0) +#define StMSYS5_LogbookOffset _MB(2,9,5,7,0) +#define StMSYS5_ResetAll _MB(2,9,5,2,0) +#define StMSYS5_ResetDeco _MB(2,9,5,3,0) +#define StMSYS5_Reboot _MB(2,9,5,4,0) +#define StMSYS5_Maintenance _MB(2,9,5,5,0) +#define StMSYS5_ResetLogbook _MB(2,9,5,6,0) +#define StMSYS5_SetBattCharge _MB(2,9,5,7,0) +#define StMSYS5_RebootRTE _MB(2,9,5,8,0) +#define StMSYS5_RebootMainCPU _MB(2,9,5,9,0) +#define StMSYS5_ScreenTest _MB(2,9,5,10,0) +#define StMSYS5_SetFactoryBC _MB(2,9,5,11,0) +#define StMSYS5_ResetBluetooth _MB(2,9,5,12,0) +#define StMSYS5_SetSampleIndx _MB(2,9,5,13,0) +#define StMSYS5_AdjustSurfPres _MB(2,9,5,14,0) +#define StMSYS5_FlashBoot _MB(2,9,5,15,0) +#endif - # define StMCustom _MB(2,9,0,0,0) +/* Temporary line markers for dive mode custom view configuration */ +/* These use line numbers 21-26 which don't conflict with actual menu items */ +#define StMSYS_Custom0 _MB(2,9,21,0,0) +#define StMSYS_Custom1 _MB(2,9,22,0,0) +#define StMSYS_Custom2 _MB(2,9,23,0,0) +#define StMSYS_Custom3 _MB(2,9,24,0,0) +#define StMSYS_Custom4 _MB(2,9,25,0,0) +#define StMSYS_Custom5 _MB(2,9,26,0,0) - /* PAGE 9 EDIT FIELD CONTENT */ +/* PAGE 10 */ +#define StMCustom _MB(2,10,0,0,0) + + /* PAGE 10 EDIT FIELD CONTENT */ // -#define StMCustom1_CViewTimeout _MB(2,9,1,1,0) -#define StMCustom1_CViewStandard _MB(2,9,1,2,0) -#define StMCustom1_CViewStandardBF _MB(2,9,1,3,0) -#define StMCustom1_CViewAutoFocusBF _MB(2,9,1,4,0) -#define StMCustom1_CornerTimeout _MB(2,9,1,5,0) -#define StMCustom1_CornerStandard _MB(2,9,1,6,0) +#define StMCustom1_CViewTimeout _MB(2,10,1,1,0) +#define StMCustom1_CViewStandard _MB(2,10,1,2,0) +#define StMCustom1_CViewStandardBF _MB(2,10,1,3,0) +#define StMCustom1_CViewAutoFocusBF _MB(2,10,1,4,0) +#define StMCustom1_CornerTimeout _MB(2,10,1,5,0) +#define StMCustom1_CornerStandard _MB(2,10,1,6,0) -#define StMCustom2_BFSelection _MB(2,9,2,1,0) +#define StMCustom2_BFSelection _MB(2,10,2,1,0) -#define StMCustom3_CViewSelection1 _MB(2,9,3,1,0) -#define StMCustom3_CViewSelection2 _MB(2,9,3,2,0) -#define StMCustom3_CViewSelection3 _MB(2,9,3,3,0) -#define StMCustom3_CViewSelection4 _MB(2,9,3,4,0) -#define StMCustom3_CViewSelection5 _MB(2,9,3,5,0) -#define StMCustom3_CViewSelection6 _MB(2,9,3,6,0) +#define StMCustom3_CViewSelection1 _MB(2,10,3,1,0) +#define StMCustom3_CViewSelection2 _MB(2,10,3,2,0) +#define StMCustom3_CViewSelection3 _MB(2,10,3,3,0) +#define StMCustom3_CViewSelection4 _MB(2,10,3,4,0) +#define StMCustom3_CViewSelection5 _MB(2,10,3,5,0) +#define StMCustom3_CViewSelection6 _MB(2,10,3,6,0) -#define StMCustom4_CViewSelection1 _MB(2,9,4,1,0) +#define StMCustom4_CViewSelection1 _MB(2,10,4,1,0) #ifdef ENABLE_MOTION_CONTROL -#define StMCustom5_CViewPortCalib _MB(2,9,5,1,0) -#define StMCustom5_CViewPortSpotSize _MB(2,9,5,2,0) -#define StMCustom5_CViewPortLayout _MB(2,9,5,3,0) -#define StMCustom5_CViewPortAmbient _MB(2,9,5,4,0) -#define StMCustom5_CViewPortControl _MB(2,9,5,5,0) -#endif -#ifdef ENABLE_GPIO_V2 -#define StMCustom5_CViewWarningBuz _MB(2,9,5,1,0) +#define StMCustom5_CViewPortCalib _MB(2,10,5,1,0) +#define StMCustom5_CViewPortSpotSize _MB(2,10,5,2,0) +#define StMCustom5_CViewPortLayout _MB(2,10,5,3,0) +#define StMCustom5_CViewPortAmbient _MB(2,10,5,4,0) +#define StMCustom5_CViewPortControl _MB(2,10,5,5,0) #endif -/* PAGE 10 */ -#define StMPLAN _MB(2,10,0,0,0) +/* PAGE 11 */ +#define StMPLAN _MB(2,11,0,0,0) -/* PAGE 10 EDIT FIELD CONTENT */ -#define StMPLAN2_Interval _MB(2,10,2,1,0) -#define StMPLAN3_DiveTime _MB(2,10,3,1,0) -#define StMPLAN4_MaxDepth _MB(2,10,4,1,0) -#define StMPLAN5_ExitResult _MB(2,10,5,1,0) -#define StMPLAN4_Settings _MB(2,10,6,1,0) +/* PAGE 11 EDIT FIELD CONTENT */ +#define StMPLAN2_Interval _MB(2,11,2,1,0) +#define StMPLAN3_DiveTime _MB(2,11,3,1,0) +#define StMPLAN4_MaxDepth _MB(2,11,4,1,0) +#define StMPLAN5_ExitResult _MB(2,11,5,1,0) +#define StMPLAN4_Settings _MB(2,11,6,1,0)
--- a/Discovery/Inc/text_multilanguage.h Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Inc/text_multilanguage.h Sat Nov 15 19:29:44 2025 +0100 @@ -395,6 +395,8 @@ TXT2BYTE_TIMEZONE, TXT2BYTE_BUZZER, + TXT2BYTE_Pulse, + TXT2BYTE_Logger, TXT2BYTE_END, };
--- a/Discovery/Src/base.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Src/base.c Sat Nov 15 19:29:44 2025 +0100 @@ -237,12 +237,17 @@ #include "t7.h" #include "t3.h" #include "tMenuEditSetpoint.h" +#include "cv_heartbeat.h" +#include "tInfoLogger.h" #ifdef DEMOMODE #include "demo.h" static void TIM_DEMO_init(void); #endif +#ifdef ENABLE_USART_RADIO +#include "demo.h" +#endif //#include "lodepng.h" //#include <stdlib.h> // for malloc and free @@ -377,33 +382,26 @@ MX_GPIO_Init(); // MX_SmallCPU_NO_Reset_Helper(); //161116 hw - MX_Bluetooth_PowerOff(); /* disable module, needed in case of e.g. a reset event to make sure module is configured from scratch */ MX_SPI_Init(); MX_UART_Init(); SDRAM_Config(); HAL_Delay( 100 ); stateRealGetPointerWrite()->lastKnownBatteryPercentage = 0; // damit das nicht in settings kopiert wird. - set_settings_to_Standard(); + set_settings_to_Standard(EF_SETTINGS); /* initialize setting structure with default value => will be overwritten by flash read operation */ mod_settings_for_first_start_with_empty_ext_flash(); - ext_flash_read_settings(); + ext_flash_read_settings(EF_SETTINGS); if( newFirmwareVersionCheckViaSettings() ) // test for old firmware version in loaded settings { wasFirmwareUpdateCheckBattery = 1; set_settings_button_to_factory_with_individual_buttonBalance(); // will adapt individual values } - //settingsGetPointer()->bluetoothActive = 0; /* MX_Bluetooth_PowerOff(); unnecessary as part of MX_GPIO_Init() */ - //settingsGetPointer()->compassBearing = 0; - set_new_settings_missing_in_ext_flash(); // includes update of firmware version 161121 + + set_new_settings_missing_in_ext_flash(EF_SETTINGS); // includes update of firmware version 161121 GFX_init( &pLayerInvisible ); TIM_BACKLIGHT_init(); - // new 170508: bluetooth on at start - settingsGetPointer()->bluetoothActive = 1; - MX_Bluetooth_PowerOn(); - tComm_StartBlueModConfig(); - /* if( (hardwareDataGetPointer()->primarySerial == 20+18) || (hardwareDataGetPointer()->primarySerial == 20+25) @@ -413,7 +411,7 @@ tComm_Set_Bluetooth_Name(1); } */ - errorsInSettings = check_and_correct_settings(); + errorsInSettings = check_and_correct_settings(EF_SETTINGS); createDiveSettings(); #ifdef QUICK_SLEEP @@ -438,6 +436,12 @@ display_power_on__2_of_2__post_RGB(); GFX_use_colorscheme( settingsGetPointer()->tX_colorscheme ); + + // new 170508: bluetooth on at start + settingsGetPointer()->bluetoothActive = 1; + MX_Bluetooth_PowerOn(); + tComm_StartBlueModConfig(); + tHome_init(); tI_init(); tM_init(); @@ -472,7 +476,7 @@ if( settingsGetPointer()->debugModeOnStart ) { settingsGetPointer()->debugModeOnStart = 0; - ext_flash_write_settings(0); + ext_flash_write_settings(EF_SETTINGS,0); setDebugMode(); openInfo( StIDEBUG ); } @@ -502,11 +506,13 @@ resetToFirmwareUpdate(); tCCR_control(); + if( tComm_control() )// will stop while loop if tComm Mode started until exit from UART { createDiveSettings(); updateMenu(); - ext_flash_write_settings(0); + ext_flash_write_settings(EF_SETTINGS,0); + time_without_button_pressed_deciseconds = 0; /* reset timeout to avoid shutdown after long time in Comm state */ } /* check if tasks depending on global state are pending */ @@ -527,12 +533,22 @@ { TriggerButtonAction(); } +#ifdef ENABLE_PULSE_SENSOR_BT + cv_heartbeat_HandleData(); +#endif + +#ifdef ENABLE_USART_RADIO + demo_HandleData(); +#endif if(DoHousekeeping) { DoHousekeeping = housekeepingFrame(); } if(DoDisplayRefresh) /* set every 100ms by timer interrupt */ { +#ifdef ENABLE_PULSE_SENSOR_BT + cv_heartbeat_Control(); +#endif DoDisplayRefresh = 0; updateSetpointStateUsed(); @@ -728,6 +744,15 @@ { SStateList status; get_globalStateList(&status); + +#ifdef ENABLE_LOGGER_WINDOW + if((status.base != 0) && (get_globalState() != StILOGGER) && (InfoLogger_isUpdated())) + { + openInfo_Logger(); + get_globalStateList(&status); + } +#endif + switch(status.base) { case BaseHome: @@ -920,6 +945,8 @@ break; case InfoPagePreDive: sendActionToInfoPreDive(action); break; + case InfoPageLogger: exitInfo(); + break; default: sendActionToInfo(action); break; } @@ -1024,7 +1051,7 @@ GFX_logoAutoOff(); display_power_off(); ext_flash_write_devicedata(true); /* write data at default position */ - ext_flash_write_settings(true); /* write data at default position */ + ext_flash_write_settings(EF_SETTINGS,true); /* write data at default position */ set_globalState(StStop); } @@ -1056,6 +1083,16 @@ output->mode = (uint8_t)((id ) & 0xFF); } +uint8_t get_lineOfID(uint32_t id) +{ + uint8_t ret = (uint8_t)((id >> 16) & 0xFF); + if(ret > 6) + { + ret = 0; + } + return ret; +} + SButtonLock get_ButtonLock(void) { return ButtonLockState;
--- a/Discovery/Src/check_warning.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Src/check_warning.c Sat Nov 15 19:29:44 2025 +0100 @@ -79,7 +79,7 @@ #endif static uint8_t buzzerOn = 0; /* current state of the buzzer */ -static void setBuzzer(int8_t warningActive); +static void handleBuzzer(int8_t warningActive); /* Exported functions --------------------------------------------------------*/ void requestBuzzerActivation(uint8_t active) @@ -87,22 +87,39 @@ buzzerRequestActive = active; } +uint8_t getBuzzerActivationRequest() +{ + return buzzerRequestActive; +} + uint8_t getBuzzerActivationState() { return buzzerOn; } -static void setBuzzer(int8_t warningActive) +static void handleBuzzer(int8_t warningActive) { static uint32_t guiTimeoutCnt = 0; /* max delay till buzzer will be activated independend from gui request */ static uint32_t stateTick = 0; /* activation tick of current state */ static uint8_t lastWarningState = 0; /* the parameter value of the last call*/ + static uint8_t lastBuzzerRequest = 0; + static uint8_t guiTrigger = 0; uint32_t tick = HAL_GetTick(); - if(warningActive) + if(stateUsed->mode == MODE_SURFACE) { - if(!lastWarningState) /* init structures */ + warningActive = 0; /* no warning buzzer in surface mode => overwrite value */ + } + + /* There are two sources for buzzer activation: the warning detection and activation by gui => both need to be merged */ + if((buzzerRequestActive != REQUEST_BUZZER_OFF) && (lastBuzzerRequest == REQUEST_BUZZER_OFF)) + { + guiTrigger = 1; + } + if((warningActive) || (buzzerRequestActive != REQUEST_BUZZER_OFF)) + { + if((lastWarningState == 0) && (lastBuzzerRequest == REQUEST_BUZZER_OFF)) /* init structures */ { guiTimeoutCnt = tick; stateTick = tick; @@ -111,22 +128,38 @@ { if(time_elapsed_ms(stateTick, tick) > EXT_INTERFACE_BUZZER_STABLE_TIME_MS) /* buzzer has to be on for a certain time */ { - if((!buzzerRequestActive) || (time_elapsed_ms(stateTick, tick) > EXT_INTERFACE_BUZZER_ON_TIME_MS)) + if((buzzerRequestActive == REQUEST_BUZZER_OFF) + || ((buzzerRequestActive == REQUEST_BUZZER_ONCE) && (time_elapsed_ms(stateTick, tick) > EXT_INTERFACE_BUZZER_PING_TIME_MS)) + || (time_elapsed_ms(stateTick, tick) > EXT_INTERFACE_BUZZER_ON_TIME_MS)) { buzzerOn = 0; stateTick = tick; guiTimeoutCnt = tick; + buzzerRequestActive = REQUEST_BUZZER_OFF; } } } else { - if(time_elapsed_ms(stateTick, tick) > EXT_INTERFACE_BUZZER_STABLE_TIME_MS) /* buzzer has to be off for a certain time */ + if((time_elapsed_ms(stateTick, tick) > EXT_INTERFACE_BUZZER_STABLE_TIME_MS) || ( guiTrigger)) /* buzzer has to be off for a certain time */ { - if((buzzerRequestActive) || (time_elapsed_ms(guiTimeoutCnt, tick) > EXT_INTERFACE_BUZZER_ON_TIME_MS + GUI_BUZZER_TIMEOUT_MS)) + if((warningActive) || (buzzerRequestActive != REQUEST_BUZZER_OFF)) { - buzzerOn = 1; - stateTick = tick; + if(((stateUsed->mode != MODE_SURFACE) && (time_elapsed_ms(guiTimeoutCnt, tick)) > (EXT_INTERFACE_BUZZER_ON_TIME_MS + GUI_BUZZER_TIMEOUT_MS)) + || ( guiTrigger)) + { + buzzerOn = 1; + stateTick = tick; + guiTrigger = 0; + if(buzzerRequestActive == REQUEST_BUZZER_ONCE) + { + buzzerRequestActive = REQUEST_BUZZER_OFF; + } + } + if((time_elapsed_ms(guiTimeoutCnt, tick)) > (EXT_INTERFACE_BUZZER_ON_TIME_MS + EXT_INTERFACE_BUZZER_STABLE_TIME_MS)) /* timeout request */ + { + buzzerRequestActive = REQUEST_BUZZER_OFF; + } } } } @@ -135,9 +168,16 @@ { buzzerOn = 0; } + lastBuzzerRequest = buzzerRequestActive; lastWarningState = warningActive; } +void deactivateBuzzer() +{ + buzzerRequestActive = REQUEST_BUZZER_OFF; + buzzerOn = 0; +} + void check_warning(void) { check_warning2(stateUsedWrite); @@ -160,7 +200,7 @@ if(settingsGetPointer()->warningBuzzer) { - setBuzzer(pDiveState->warnings.numWarnings); + handleBuzzer(pDiveState->warnings.numWarnings); } /* Warnings checked after this line will not cause activation of the buzzer */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Discovery/Src/cv_heartbeat.c Sat Nov 15 19:29:44 2025 +0100 @@ -0,0 +1,668 @@ +/////////////////////////////////////////////////////////////////////////////// +/// -*- coding: UTF-8 -*- +/// +/// \file Discovery/Src/cv_heartbeat.c +/// \brief providing functionality to connect OSTC to a Polar HC10 heartbeat sensor +/// \author heinrichs weikamp gmbh +/// \date 03-July-2025 +/// +/// $Id$ +/////////////////////////////////////////////////////////////////////////////// +/// \par Copyright (c) 2014-2025 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 <http://www.gnu.org/licenses/>. +////////////////////////////////////////////////////////////////////////////// + +#include "configuration.h" + +#ifdef ENABLE_PULSE_SENSOR_BT +#include "cv_heartbeat.h" +#include "tMenuEdit.h" + +#include "gfx_fonts.h" +#include "tHome.h" +#include "ostc.h" +#include "tComm.h" +#include "tInfoLogger.h" +#include "stdlib.h" + +static sensorHeartbeat_State_t heartbeatState = SENSOR_HB_OFFLINE; + +static uint8_t OnAction_Heartbeat(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); +static uint32_t startDetection_ms; + +#define MAX_BT_DEVICE 10 /* max number of device which may be handled */ +static btDdeviceData_t btDeviceList[MAX_BT_DEVICE]; +static btDeviceService_t curDeviceService[10]; +static btDeviceCharacteristic_t curDevCharacteristic[10]; +static btDeviceDescriptor_t curDevDescriptor; + + +static uint8_t curCharacteristicIndex = 0; +static uint8_t curServiceIndex = 0; +static uint8_t curBtIndex = 0; +static uint8_t connHandle = ' '; +static uint8_t evaluateDevIndex = 0xFF; +static uint8_t evaluateSrvIndex = 0xFF; +static uint8_t evaluateCharIndex = 0xFF; + +static void parsePulseMeasurement(uint8_t* pData, uint8_t length) +{ + uint8_t rawData[10]; + + char* enptr; + uint8_t flags = 0; + uint16_t rr = 0; + uint8_t index = 0; + uint8_t* pRaw = (uint8_t*)&rawData; + char tmpStr[3]; + + tmpStr[2] = 0; + + HRMeasurement_t pulseData; + + for(index = 0; index < length; index +=2) + { + memcpy(tmpStr,&pData[index],2); + rawData[index / 2] = strtol(tmpStr, &enptr,16); + } + flags = pRaw[0]; + index = 1; + /* 0: Heart Rate Format bit (0 = UINT8, 1 = UINT16) */ + if (flags & 0x01) + { + pulseData.heart_rate = pRaw[index] | (pRaw[index + 1] << 8); + index += 2; + } else + { + pulseData.heart_rate = pRaw[index]; + index += 1; + } + + /* 3: Energy Expended Status */ + if (flags & 0x08) + { + pulseData.energy_expended = pRaw[index] | (pRaw[index + 1] << 8); + index += 2; + } else + { + pulseData.energy_expended = 0; + } + /* 4: RR-Interval bit */ + pulseData.rr_count = 0; + if (flags & 0x10) + { + while (index + 1 < 4 && pulseData.rr_count < 10) + { + rr = pRaw[index] | (pRaw[index + 1] << 8); + pulseData.rr_intervals[pulseData.rr_count++] = rr; + index += 2; + } + } +// snprintf(text,40,"Pulse: %d",pulseData.heart_rate); +// InfoLogger_writeLine((uint8_t*)text,strlen(text),0); +} + +static indicatior_t checkIndicators(uint8_t* pdata) +{ + indicatior_t ret = NO_INDICATOR; + + if(strcmp((char*)pdata,"+UBTD:") == 0) + { + ret = DEVICE_INDICATOR; + } + else if(strcmp((char*)pdata,"+UUBTACLC:") == 0) + { + ret = CONNECTION_INDICATOR; + } + else if(strcmp((char*)pdata,"+UBTGDP:") == 0) + { + ret = SERVICE_INDICATOR; + } + else if(strcmp((char*)pdata,"+UBTGDCS:") == 0) + { + ret = CHARACTERISTIC_INDICATOR; + } + else if(strcmp((char*)pdata,"+UBTGDCD:") == 0) + { + ret = DESCRIPTOR_INDICATOR; + } + else if(strcmp((char*)pdata,"+UUBTGN:") == 0) + { + ret = PULSE_INDICATOR; + } + return ret; +} + +static void handleOK() +{ + uint8_t index = 0; + + switch(heartbeatState) + { + case SENSOR_HB_ENABLE_BLE: heartbeatState = SENSOR_HB_CHECK_CONFIG; + break; + case SENSOR_HB_CHECK_CONFIG: heartbeatState = SENSOR_HB_DISCOVER; + break; + case SENSOR_HB_RESTART: heartbeatState = SENSOR_HB_OFFLINE; + break; + case SENSOR_HB_DISCOVER: if(curBtIndex > 0) + { + heartbeatState = SENSOR_HB_CONNECT; + evaluateDevIndex = 0; + } + else + { + heartbeatState = SENSOR_HB_OFFLINE; + } + + break; + case SENSOR_HB_SERVICES: evaluateSrvIndex = 0xFF; + if(curServiceIndex != 0) + { + for(index = 0; index <= curServiceIndex; index++) + { + if(strcmp((char*)curDeviceService[index].uuid,"180D") == 0) + { + heartbeatState = SENSOR_HB_CHARACTERISTIC; + evaluateSrvIndex = index; + curCharacteristicIndex = 0; + break; + } + } + } + if(evaluateSrvIndex == 0xFF) /* device does not provide heartbeat data => disconnect */ + { + heartbeatState = SENSOR_HB_DISCONNECT; + } + break; + case SENSOR_HB_CHARACTERISTIC: evaluateCharIndex = 0xFF; + if(curCharacteristicIndex != 0) + { + for(index = 0; index < curCharacteristicIndex; index++) + { + if(strcmp((char*)curDevCharacteristic[index].uuid,"2A37") == 0) + { + heartbeatState = SENSOR_HB_DESCRIPTOR; + evaluateCharIndex = index; + break; + } + } + } + if(evaluateCharIndex == 0xFF) /* device does not provide heartbeat data => disconnect */ + { + heartbeatState = SENSOR_HB_DISCONNECT; + } + break; + case SENSOR_HB_DESCRIPTOR: if(strcmp((char*)curDevDescriptor.uuid,"2902") == 0) + { + heartbeatState = SENSOR_HB_SUBSCRIBE; + } + else + { + heartbeatState = SENSOR_HB_DISCONNECT; + } + break; + + case SENSOR_HB_SUBSCRIBE: heartbeatState = SENSOR_HB_CONNECTED; + break; + case SENSOR_HB_DISCONNECT: evaluateDevIndex++; + connHandle= ' '; + if(evaluateDevIndex < curBtIndex) /* more devices to be evaluated? */ + { + heartbeatState = SENSOR_HB_CONNECT; + } + else + { + heartbeatState = SENSOR_HB_OFFLINE; + } + break; + case SENSOR_HB_CONNECT: /* handled in data rx section */ + default: + break; + } +} + +static void handleERROR() +{ + switch(heartbeatState) + { + case SENSOR_HB_DISCONNECT: evaluateDevIndex++; + connHandle= ' '; + if(evaluateDevIndex < curBtIndex) /* more devices to be evaluated? */ + { + heartbeatState = SENSOR_HB_CONNECT; + } + else + { + heartbeatState = SENSOR_HB_OFFLINE; + } + break; + default: + break; + } +} + +uint8_t cv_heartbeat_HandleData() +{ + static uint8_t firstDevice = 1; + static uint8_t curLine[MAX_CHAR_PER_LINE]; /* holds complete line and is used for logging */ + static uint8_t curLineIndex = 0; + static uint8_t parameter[40]; /* content of the parameter in read state */ + static uint8_t writeIndex = 0; + static uint8_t complete = 0; + + static readDataType_t readType = BT_READ_NOTHING; + + uint8_t data = 0; + data = UART_getChar(); + + while((data != 0) && (complete == 0)) + { + if(curLineIndex == MAX_CHAR_PER_LINE - 1) /* avoid overflow */ + { + InfoLogger_writeLine(curLine,curLineIndex,0); + memset(curLine,0,sizeof(curLine)); + curLineIndex = 0; + } + if((data == '\r') || (data == '\n')) + { + if(curLineIndex > 0) + { + InfoLogger_writeLine(curLine,curLineIndex,0); + if(strcmp((char*)curLine,"OK") == 0) + { + handleOK(); + } + else + { + if(strcmp((char*)curLine,"ERROR") == 0) + { + handleERROR(); + } + } + } + switch(readType) + { + case BT_READ_DEVICE_NAME: if(writeIndex < BLUEMOD_NAME_SIZE) + { + memcpy (btDeviceList[curBtIndex].name, parameter, writeIndex); + } + break; + case BT_READ_SERV_UUID: if((writeIndex < 50) && (curServiceIndex < 10)) + { + memcpy(curDeviceService[curServiceIndex].uuid, parameter, writeIndex); + } + curServiceIndex++; + break; + case BT_READ_CHAR_UUID: if(writeIndex < 50) + { + memcpy(curDevCharacteristic[curCharacteristicIndex].uuid, parameter, writeIndex); + curCharacteristicIndex++; + } + break; + case BT_READ_DESC_UUID: if(writeIndex < 50) + { + memcpy(curDevDescriptor.uuid, parameter, writeIndex); + } + break; + case BT_READ_PULSE_DATA: if(writeIndex < 50) + { + parsePulseMeasurement(parameter, writeIndex); + } + break; + default: + break; + } + curLineIndex = 0; + writeIndex = 0; + memset(curLine,0,sizeof(curLine)); + readType = BT_READ_NOTHING; + } + else + { + if(curLineIndex < MAX_CHAR_PER_LINE) curLine[curLineIndex++] = data; + + if(data == ':') + { + switch(checkIndicators(curLine)) + { + case DEVICE_INDICATOR: readType = BT_READ_DEVICE_ADDR; + break; + case CONNECTION_INDICATOR: readType = BT_READ_CON_DETAILS; + break; + case SERVICE_INDICATOR: readType = BT_READ_SERV_HANDLE; + break; + case CHARACTERISTIC_INDICATOR: readType = BT_READ_CHAR_CONHANDLE; + break; + case DESCRIPTOR_INDICATOR: readType = BT_READ_DESC_CONHANDLE; + break; + case PULSE_INDICATOR: readType = BT_READ_PULSE_CONHANDLE; + break; + default: + break; + } + writeIndex = 0; + memset(parameter,0,sizeof(parameter)); + } + else + { + if(data == ',') /* parameter end */ + { + switch(readType) + { + case BT_READ_DEVICE_ADDR: if(writeIndex < BLUEMOD_ADDR_SIZE-1) + { + if(firstDevice) + { + firstDevice = 0; + } + else + { + curBtIndex++; + } + parameter[writeIndex-1] = 0; /*remove 'p' from address */ + strcpy((char*)btDeviceList[curBtIndex].address, (char*)parameter); + } + readType = BT_READ_DEVICE_RSSI; + break; + case BT_READ_DEVICE_RSSI: if(writeIndex < BLUEMOD_RSSI_SIZE-1) + { + strcpy((char*)btDeviceList[curBtIndex].rssi, (char*)parameter); + } + readType = BT_READ_DEVICE_NAME; + break; + case BT_READ_DEVICE_NAME: if(writeIndex < BLUEMOD_NAME_SIZE-1) + { + memcpy(btDeviceList[curBtIndex].name, parameter, writeIndex); + } + readType = BT_READ_NOTHING; + break; + case BT_READ_CON_DETAILS: connHandle = parameter[0]; + heartbeatState = SENSOR_HB_SERVICES; + readType = BT_READ_NOTHING; + curServiceIndex = 0; + break; + case BT_READ_SERV_HANDLE: curDeviceService[curServiceIndex].handle = parameter[0]; + readType = BT_READ_SERV_START; + break; + case BT_READ_SERV_START: if(writeIndex < 6) + { + memcpy(curDeviceService[curServiceIndex].start, parameter, writeIndex); + } + readType = BT_READ_SERV_END; + break; + case BT_READ_SERV_END: if(writeIndex < 6) + { + memcpy(curDeviceService[curServiceIndex].end, parameter, writeIndex); + } + readType = BT_READ_SERV_UUID; + break; + case BT_READ_CHAR_CONHANDLE: curDevCharacteristic[curCharacteristicIndex].conHandle = parameter[0]; + readType = BT_READ_CHAR_ATTRIBUTE; + break; + case BT_READ_CHAR_ATTRIBUTE: if(writeIndex < 10) + { + memcpy(curDevCharacteristic[curCharacteristicIndex].attrHandle, parameter, writeIndex); + } + readType = BT_READ_CHAR_PROPERTY; + break; + case BT_READ_CHAR_PROPERTY: if(writeIndex < 10) + { + memcpy(curDevCharacteristic[curCharacteristicIndex].properties, parameter, writeIndex); + } + readType = BT_READ_CHAR_VALUEHANDLE; + break; + case BT_READ_CHAR_VALUEHANDLE: if(writeIndex < 10) + { + memcpy(curDevCharacteristic[curCharacteristicIndex].valueHandle, parameter, writeIndex); + } + readType = BT_READ_CHAR_UUID; + break; + case BT_READ_DESC_CONHANDLE: curDevDescriptor.conHandle = parameter[0]; + readType = BT_READ_DESC_CHARHANDLE; + break; + case BT_READ_DESC_CHARHANDLE: if(writeIndex < 10) + { + memcpy(curDevDescriptor.charHandle, parameter, writeIndex); + } + readType = BT_READ_DESC_DESCHANDLE; + break; + case BT_READ_DESC_DESCHANDLE: if(writeIndex < 10) + { + memcpy(curDevDescriptor.descHandle, parameter, writeIndex); + } + readType = BT_READ_DESC_UUID; + break; + case BT_READ_PULSE_CONHANDLE: curDevDescriptor.conHandle = parameter[0]; + readType = BT_READ_PULSE_VALUEHANDLE; + break; + case BT_READ_PULSE_VALUEHANDLE: if(writeIndex < 10) + { + // if(strcmp((char*)curDevCharacteristic[evaluateCharIndex].valueHandle,(char*) parameter) == 0) + { + readType = BT_READ_PULSE_DATA; + } +#if 0 + else + { + readType = BT_READ_NOTHING; + } +#endif + } + break; + default: readType = BT_READ_NOTHING; + break; + } + writeIndex = 0; + memset(parameter,0 , sizeof(parameter)); + } + else + { + if(readType != BT_READ_NOTHING) + { + parameter[writeIndex++] = data; + } + } + } + } + data = UART_getChar(); + } + return complete; +} + +sensorHeartbeat_State_t cv_heartbeat_getState() +{ + return heartbeatState; +} + +void openEdit_Heartbeat(void) +{ + char text[32]; + snprintf(text, 32, "\001%c%c", TXT_2BYTE, TXT2BYTE_Pulse); + write_topline(text); + + set_globalState(StMOption_Heartbeat); + resetMenuEdit(CLUT_MenuPageCvOption); + + snprintf(text, 32, "%c%c", TXT_2BYTE, TXT2BYTE_SensorDetect); + write_field_button(StMOption_Heartbeat, 30, 299, ME_Y_LINE1, &FontT48, text); + + write_buttonTextline(TXT2BYTE_ButtonMinus, TXT2BYTE_ButtonEnter, TXT2BYTE_ButtonPlus); + + setEvent(StMOption_Heartbeat, (uint32_t)OnAction_Heartbeat); +} + +static uint8_t OnAction_Heartbeat(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) +{ + switch(heartbeatState) + { + case SENSOR_HB_OFFLINE: + HAL_UART_AbortReceive_IT(&UartHandle); + MX_UART_BT_Init_DMA(); + UART_StartDMARx(); + heartbeatState = SENSOR_HB_ENABLE_BLE; + startDetection_ms = HAL_GetTick(); + curBtIndex = 0; + memset(btDeviceList, 0, sizeof(btDeviceList)); + break; + + default: + break; + } + return UNSPECIFIC_RETURN; +} + +void cv_heartbeat_Control(void) +{ + static uint8_t action = 0; + static uint8_t retry = 0; + static uint8_t lastState = 0; + char cmd[50]; + + cmd[0] = 0; + + if(action == 3) + { + action = 0; + switch(heartbeatState) + { + case SENSOR_HB_ENABLE_BLE: HAL_Delay(1000); + snprintf(cmd, sizeof(cmd), "+++" ); //"AT+UBTD=2,1,5000\r\n" + InfoLogger_writeLine((uint8_t*)cmd,3,1); + HAL_UART_Transmit(&UartHandle, (uint8_t*)cmd, 3, 5000); + HAL_Delay(1000); + cmd[0] = 0; + break; + case SENSOR_HB_CHECK_CONFIG: snprintf(cmd, sizeof(cmd), "AT+UBTCFG=2\r\n" ); // AT+UBTLE? + +#if 0 + if(settingsGetPointer()->dive_mode == DIVEMODE_OC) + { + snprintf(cmd, sizeof(cmd), "AT+UBTLE=2\r\n" ); //+UBTLE=1 //"AT+UBTD=2,1,5000\r\n" + } + else + { + snprintf(cmd, sizeof(cmd), "AT+UBTLE=3\r\n" ); //+UBTLE=1 //"AT+UBTD=2,1,5000\r\n" + } +#endif + break; + case SENSOR_HB_DISCOVER: if(lastState != SENSOR_HB_DISCOVER) + { + snprintf(cmd, sizeof(cmd), "AT+UBTD=2,1\r\n" ); //+UBTLE=1 //"AT+UBTD=2,1,5000\r\n" + curBtIndex = 0; + } + + //snprintf(cmd, sizeof(cmd), "AT&W\r\n" ); // AT+UBTD=2,1\r\n "AT+UBTD=2,1,5000\r\n" + break; +#if 0 + case SENSOR_HB_RESTART: snprintf(cmd, sizeof(cmd), "AT+UBTD=2,1\r\n" ); //+UBTLE=1 //"AT+UBTD=2,1,5000\r\n" + + // snprintf(cmd, sizeof(cmd), "AT+CPWROFF\r\n" ); // AT+UBTD=2,1\r\n "AT+UBTD=2,1,5000\r\n" + break; +#endif + case SENSOR_HB_CONNECT: if(evaluateDevIndex < curBtIndex) + { + snprintf(cmd, sizeof(cmd), "AT+UBTACLC=%s\r\n",btDeviceList[evaluateDevIndex].address); + } + break; + case SENSOR_HB_DISCONNECT: snprintf(cmd, sizeof(cmd), "AT+UBTACLD=%c\r\n",connHandle); + break; + case SENSOR_HB_SERVICES: if((connHandle >= '0') && (connHandle <= '9') && (lastState != SENSOR_HB_SERVICES)) + { + snprintf(cmd, sizeof(cmd), "AT+UBTGDP=%c\r\n",connHandle); + memset(curDeviceService, 0, sizeof(curDeviceService)); + } + break; + case SENSOR_HB_CHARACTERISTIC: snprintf(cmd, sizeof(cmd), "AT+UBTGDCS=%c,%s,%s\r\n",connHandle,curDeviceService[evaluateSrvIndex].start + ,curDeviceService[evaluateSrvIndex].end); + memset(curDevCharacteristic, 0, sizeof(curDevCharacteristic)); + break; + case SENSOR_HB_DESCRIPTOR: snprintf(cmd, sizeof(cmd), "AT+UBTGDCD=%c,%s,%s\r\n",connHandle,curDevCharacteristic[evaluateCharIndex].valueHandle + ,curDeviceService[evaluateSrvIndex].end); + break; + case SENSOR_HB_SUBSCRIBE: snprintf(cmd, sizeof(cmd), "AT+UBTGWC=%c,%s,1\r\n",connHandle,curDevDescriptor.descHandle); + break; + default: + break; + } + if(cmd[0] != 0) + { + { + InfoLogger_writeLine((uint8_t*)cmd,strlen(cmd),1); + HAL_UART_Transmit(&UartHandle, (uint8_t*)cmd, strlen(cmd), 5000); + retry++; + if(retry == 3) + { + heartbeatState = SENSOR_HB_OFFLINE; + } + } + } + if(lastState != heartbeatState) + { + lastState = heartbeatState; + retry = 0; + } + } + else + { + action++; + } +} +void refresh_Heartbeat(void) +{ + char text[32]; + uint8_t index = 0; + + snprintf(text, 32, "\001%c%c", TXT_2BYTE, TXT2BYTE_Pulse); + write_topline(text); + + switch(heartbeatState) + { + case SENSOR_HB_OFFLINE: + default: snprintf(text, 32, "%c%c", TXT_2BYTE, TXT2BYTE_SensorDetect); + write_label_var(30, 299, ME_Y_LINE1, &FontT48, text); + + if(curBtIndex > 0) + { + while((index < curBtIndex) && (index < 3)) + { + snprintf(text, 40, "%s", btDeviceList[index].address); + write_label_var( 30, 300, ME_Y_LINE3 + (index * ME_Y_LINE_STEP), &FontT48, text); + index++; + } + } + break; + case SENSOR_HB_ENABLE_BLE: snprintf(text, 32, "Activate BLE"); + write_label_var( 30, 300, ME_Y_LINE1, &FontT48, text); + break; + case SENSOR_HB_DISCOVER: + snprintf(text, 32, "Searching"); + write_label_var( 30, 300, ME_Y_LINE1, &FontT48, text); + + if(curBtIndex > 0) + { + while((index < curBtIndex) && (index < 4)) + { + snprintf(text, 40, "%s", btDeviceList[index].address); + write_label_var( 30, 300, ME_Y_LINE2 + (index * ME_Y_LINE_STEP), &FontT48, text); + index++; + } + } + break; + } + + write_buttonTextline(TXT2BYTE_ButtonMinus, TXT2BYTE_ButtonEnter, TXT2BYTE_ButtonPlus); +} +#endif
--- a/Discovery/Src/data_central.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Src/data_central.c Sat Nov 15 19:29:44 2025 +0100 @@ -717,10 +717,12 @@ uint32_t CRC_CalcBlockCRC_moreThan768000(uint32_t *buffer1, uint32_t *buffer2, uint32_t words) { - cm_t crc_model; - uint32_t word_to_do; - uint8_t byte_to_do; - int i; + cm_t crc_model; + uint32_t word_to_do; + uint8_t byte_to_do; + int i; + + uint32_t wordCnt = 0; // Values for the STM32F generator. @@ -733,10 +735,10 @@ cm_ini(&crc_model); - while (words--) + do { // The STM32F10x hardware does 32-bit words at a time!!! - if(words > (768000/4)) + if(wordCnt >= (768000/4)) word_to_do = *buffer2++; else word_to_do = *buffer1++; @@ -765,7 +767,8 @@ cm_nxt(&crc_model, byte_to_do); } - } + wordCnt++; + } while (wordCnt != words); // Return the final result. @@ -843,30 +846,33 @@ { float newTarget = newHeading; - if(settingsGetPointer()->compassInertia == 0) + if((newHeading > 0.0) && (newHeading < 360)) { - compass_compensated = newHeading; - } - else - { - if((compass_compensated > 270.0) && (newHeading < 90.0)) /* transition passing 0 clockwise */ + if(settingsGetPointer()->compassInertia == 0) { - newTarget = newHeading + 360.0; + compass_compensated = newHeading; } + else + { + if((compass_compensated > 270.0) && (newHeading < 90.0)) /* transition passing 0 clockwise */ + { + newTarget = newHeading + 360.0; + } - if((compass_compensated < 90.0) && (newHeading > 270.0)) /* transition passing 0 counter clockwise */ - { - newTarget = newHeading - 360.0; - } + if((compass_compensated < 90.0) && (newHeading > 270.0)) /* transition passing 0 counter clockwise */ + { + newTarget = newHeading - 360.0; + } - compass_compensated = compass_compensated + ((newTarget - compass_compensated) / (COMPASS_FRACTION * (settingsGetPointer()->compassInertia))); - if(compass_compensated < 0.0) - { - compass_compensated += 360.0; - } - if(compass_compensated >= 360.0) - { - compass_compensated -= 360.0; + compass_compensated = compass_compensated + ((newTarget - compass_compensated) / (COMPASS_FRACTION * (settingsGetPointer()->compassInertia))); + if(compass_compensated < 0.0) + { + compass_compensated += 360.0; + } + if(compass_compensated >= 360.0) + { + compass_compensated -= 360.0; + } } } } @@ -972,6 +978,62 @@ return color; } +void formatStringOfTime(char* pString, uint8_t strLen, RTC_TimeTypeDef Stime, uint8_t showAlive, uint8_t showSeconds) +{ + char timeSuffix[] = {0,0,0}; + uint8_t hours; + + if(strLen > 10) + { + + hours = Stime.Hours; + if (settingsGetPointer()->amPMTime) + { + timeSuffix[1] = 'M'; + if (Stime.Hours > 11) + { + timeSuffix[0] = 'P'; + } + else + { + timeSuffix[0] = 'A'; + } + + if (Stime.Hours % 12 == 0) + { + hours = 12; + } + else + { + hours = (Stime.Hours % 12); + } + } + + if(showSeconds) + { + if((Stime.Seconds % 2) || (!showAlive)) + { + snprintf(pString, strLen,"%02d:%02d:%02d\016\016%s\017",hours, Stime.Minutes, Stime.Seconds,timeSuffix); + } + else + { + snprintf(pString, strLen,"%02d\031:\030%02d\031:\030%02d\016\016%s\017",hours, Stime.Minutes, Stime.Seconds,timeSuffix); + } + } + else + { + if((Stime.Seconds % 2) || (!showAlive)) + { + snprintf(pString, strLen,"%02d:%02d\016\016%s\017",hours, Stime.Minutes,timeSuffix); + } + else + { + snprintf(pString, strLen,"%02d\031:\030%02d\016\016%s\017",hours, Stime.Minutes,timeSuffix); + } + } + } +} + /* returns the date in the order defined by the settings DDMMYY => X */ void convertStringOfDate_DDMMYY(char* pString, uint8_t strLen, uint8_t day, uint8_t month, uint8_t year) {
--- a/Discovery/Src/data_exchange_main.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Src/data_exchange_main.c Sat Nov 15 19:29:44 2025 +0100 @@ -412,7 +412,7 @@ break; case SENSOR_CO2: SensorActive[SENSOR_CO2] = 1; break; -#if defined ENABLE_GPIO_V2 || defined ENABLE_GNSS_SUPPORT +#if defined ENABLE_GNSS_INTERNAL || defined ENABLE_GNSS_EXTERN case SENSOR_GNSS: SensorActive[SENSOR_GNSS] = 1; break; #endif @@ -442,12 +442,10 @@ } #endif -#ifdef ENABLE_GPIO_V2 - if(getBuzzerActivationState()) + if((isNewDisplay()) && getBuzzerActivationState()) { externalInterface_Cmd |= EXT_INTERFACE_BUZZER_ON; } -#endif dataOut.data.externalInterface_Cmd = externalInterface_Cmd; externalInterface_Cmd = 0; @@ -468,7 +466,11 @@ dataOut.revisionHardware = 0xFF; dataOut.revisionCRCx0x7A = 0xFF; } - + if(isNewDisplay()) + { + dataOut.displayVersion = 1; + } + if(DataEX_check_header_and_footer_ok() && !told_reset_logik_alles_ok) { MX_tell_reset_logik_alles_ok(); @@ -847,8 +849,7 @@ SDiveState *pStateReal = stateRealGetPointerWrite(); uint8_t idx; float meter = 0; - SSettings *pSettings; - + #ifdef ENABLE_EXTERNAL_PRESSURE float CO2Corr = 0.0; #endif @@ -912,6 +913,7 @@ } } + SSettings *pSettings = settingsGetPointer(); if((requestNecessary.uw != 0) && (dataIn.confirmRequest.uw != 0)) { if(((dataIn.confirmRequest.uw) & CRBUTTON) != 0) @@ -949,14 +951,12 @@ if(requestNecessary.ub.button == 1) /* send button values to RTE */ { - setButtonResponsiveness(settingsGetPointer()->ButtonResponsiveness); + setButtonResponsiveness(pSettings->ButtonResponsiveness); } } /* uint8_t IAmStolenPleaseKillMe; */ - pSettings = settingsGetPointer(); - if(pSettings->IAmStolenPleaseKillMe > 3) { pSettings->salinity = 0; @@ -1044,7 +1044,7 @@ disableTimer(); // new 170508 - settingsGetPointer()->bluetoothActive = 0; + pSettings->bluetoothActive = 0; MX_Bluetooth_PowerOff(); //Init dive Mode decoLock = DECO_CALC_init_as_is_start_of_dive; @@ -1374,3 +1374,12 @@ return; } +bool isScrubberTimerEnabled(const SSettings *settings) +{ + return settings->scrubberActiveId != 0x00 && isLoopMode(settings->dive_mode); +} + +bool isScrubberTimerRunning(const SDiveState *diveState, const SSettings *settings) +{ + return isScrubberTimerEnabled(settings) && diveState->mode == MODE_DIVE && isLoopMode(diveState->diveSettings.diveMode); +}
--- a/Discovery/Src/demo.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Src/demo.c Sat Nov 15 19:29:44 2025 +0100 @@ -28,6 +28,8 @@ #include "data_exchange_main.h" // for time_elapsed_ms() #include "settings.h" #include "ostc.h" +#include "tInfoLogger.h" +#include <string.h> #ifndef DEMOMODE @@ -425,5 +427,62 @@ #endif // DEMO +#ifdef ENABLE_USART_RADIO /* debug function to check receiption of radio data */ +void demo_HandleData(void) +{ + static uint8_t comStarted = 0; + static uint8_t text[50]; + static uint8_t index = 0; + static uint32_t startTick = 0; + static uint8_t firstData = 1; + uint8_t data = 0; + + switch(comStarted) + { + case 0: startTick = HAL_GetTick(); + comStarted++; + break; + case 1: if(time_elapsed_ms(startTick, HAL_GetTick()) > 5000) + { + MX_UART_RADIO_Init_DMA(); + UART_StartDMARxRadio(); + comStarted++; + sprintf((char*)text,"RadioStarted"); + InfoLogger_writeLine(text,strlen((char*)text),1); + } + break; + case 2: data = UART_getChar(); + if(data != 0) + { + if(firstData) + { + firstData = 0; + sprintf((char*)text,"FirstData"); + InfoLogger_writeLine(text,strlen((char*)text),1); + } + if((index == 50) || (data =='r') || (data =='n')) + { + if(index > 0) + { + InfoLogger_writeLine(text,index,0); + index = 0; + } + } + else + { + text[index++] = data; + } + } + break; + default: + break; + } + + + { + } +} +#endif + /************************ (C) COPYRIGHT heinrichs weikamp *****END OF FILE****/
--- a/Discovery/Src/display.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Src/display.c Sat Nov 15 19:29:44 2025 +0100 @@ -407,7 +407,7 @@ aTxBuffer[1] = OLED_VFP_SET_13h; send((uint8_t*)aTxBuffer, 2); aTxBuffer[0] = 0x72; - aTxBuffer[1] = 0x08; + aTxBuffer[1] = 0x0C; send((uint8_t*)aTxBuffer, 2); aTxBuffer[0] = 0x70;
--- a/Discovery/Src/externLogbookFlash.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Src/externLogbookFlash.c Sat Nov 15 19:29:44 2025 +0100 @@ -84,17 +84,6 @@ #define HEADER2OFFSET 0x400 -typedef enum{ - EF_HEADER, - EF_SAMPLE, - EF_DEVICEDATA, - EF_VPMDATA, - EF_SETTINGS, - EF_FIRMWARE, - EF_FIRMWARE2, -}which_ring_enum; - - typedef struct{ uint8_t IsBusy:1; uint8_t IsWriteEnabled:1; @@ -130,6 +119,7 @@ static uint32_t actualPointerDevicedata = DDSTART; static uint32_t actualPointerVPM = 0; static uint32_t actualPointerSettings = SETTINGSSTART; +static uint32_t actualPointerProfile = PROFILE0_START; static uint32_t actualPointerFirmware = 0; static uint32_t actualPointerFirmware2 = 0; @@ -344,7 +334,11 @@ } else if(pSample2) { - actualAddress += length1; + /* actualAddress += length1; do dummy read to get EEPROM to the correct address */ + for(uint32_t i = 0; i<length1; i++) + { + ext_flash_read_block(&pSample2[0], EF_FIRMWARE2); + } for(uint32_t i = 0; i<length2; i++) { ext_flash_read_block(&pSample2[i], EF_FIRMWARE2); @@ -527,28 +521,44 @@ return; } #else -void ext_flash_write_settings(uint8_t resetRing) +void ext_flash_write_settings(uint8_t whichSettings, uint8_t resetRing) { - uint8_t *pData; + SSettings *pSettings; const uint16_t length = sizeof(SSettings); uint8_t length_lo, length_hi; uint8_t dataLength[2] = { 0 }; + pSettings = settingsGetPointer(); + ext_flash_disable_protection(); - if(stateRealGetPointer()->lastKnownBatteryPercentage) + switch (whichSettings) { - settingsGetPointer()->lastKnownBatteryPercentage = stateRealGetPointer()->lastKnownBatteryPercentage; - } - settingsGetPointer()->backup_localtime_rtc_tr = stateRealGetPointer()->lifeData.timeBinaryFormat; - settingsGetPointer()->backup_localtime_rtc_dr = stateRealGetPointer()->lifeData.dateBinaryFormat; - - pData = (uint8_t *)settingsGetPointer(); - - /* Reset the Ring to the start address if requested (e.g. because we write the default block during shutdown) */ - if((resetRing) || ((actualPointerSettings + length) >= SETTINGSSTOP)) - { - actualPointerSettings = SETTINGSSTART; + default: + case EF_SETTINGS: if(stateRealGetPointer()->lastKnownBatteryPercentage) + { + pSettings->lastKnownBatteryPercentage = stateRealGetPointer()->lastKnownBatteryPercentage; + } + pSettings->backup_localtime_rtc_tr = stateRealGetPointer()->lifeData.timeBinaryFormat; + pSettings->backup_localtime_rtc_dr = stateRealGetPointer()->lifeData.dateBinaryFormat; + /* Reset the Ring to the start address if requested (e.g. because we write the default block during shutdown) */ + if((resetRing) || ((actualPointerSettings + length) >= SETTINGSSTOP)) + { + actualPointerSettings = SETTINGSSTART; + } + break; + case EF_PROFILE0: actualPointerProfile = PROFILE0_START; + pSettings = profileGetPointer(0); + break; + case EF_PROFILE1: actualPointerProfile = PROFILE1_START; + pSettings = profileGetPointer(1); + break; + case EF_PROFILE2: actualPointerProfile = PROFILE2_START; + pSettings = profileGetPointer(2); + break; + case EF_PROFILE3: actualPointerProfile = PROFILE3_START; + pSettings = profileGetPointer(3); + break; } length_lo = (uint8_t)(length & 0xFF); @@ -556,8 +566,8 @@ dataLength[0] = length_lo; dataLength[1] = length_hi; - ef_write_block(dataLength,2, EF_SETTINGS, 0); - ef_write_block(pData,length, EF_SETTINGS, 0); + ef_write_block(dataLength,2, whichSettings, 0); + ef_write_block((uint8_t*)pSettings,length, whichSettings, 0); // ext_flash_enable_protection(); } #endif @@ -570,7 +580,7 @@ * new settings should be fine as they are added * and loaded before calling this function */ -uint8_t ext_flash_read_settings(void) +uint8_t ext_flash_read_settings(uint8_t whichSettings) { uint8_t returnValue = HAL_BUSY; uint8_t exit = 0; @@ -579,69 +589,90 @@ uint8_t length_lo, length_hi; uint16_t lengthOnEEPROM; uint32_t header; - SSettings *pSettings = settingsGetPointer(); - - actualAddress = SETTINGSSTART; + SSettings* pSettings = settingsGetPointer(); - ext_flash_read_block_start(); - ext_flash_read_block(&length_lo, EF_SETTINGS); - ext_flash_read_block(&length_hi, EF_SETTINGS); - - while ((length_lo != 0xFF) && (length_hi != 0xFF) && (exit == 0)) /* get the latest stored setting block */ + switch(whichSettings) + { + case EF_SETTINGS: pSettings = settingsGetPointer(); + actualAddress = SETTINGSSTART; + break; + case EF_PROFILE0: pSettings = profileGetPointer(0); + actualAddress = PROFILE0_START; + break; + case EF_PROFILE1: pSettings = profileGetPointer(1); + actualAddress = PROFILE1_START; + break; + case EF_PROFILE2: pSettings = profileGetPointer(2); + actualAddress = PROFILE2_START; + break; + case EF_PROFILE3: pSettings = profileGetPointer(3); + actualAddress = PROFILE3_START; + break; + default: returnValue = HAL_ERROR; + } + + if(returnValue != HAL_ERROR) { - lengthOnEEPROM = length_hi * 256; - lengthOnEEPROM += length_lo; - if(lengthOnEEPROM <= lengthStandardNow) /* EEPROM Header size equal or smaller => settings constant or upgraded */ + ext_flash_read_block_start(); + ext_flash_read_block(&length_lo, whichSettings); + ext_flash_read_block(&length_hi, whichSettings); + + while ((length_lo != 0xFF) && (length_hi != 0xFF) && (exit == 0)) /* get the latest stored setting block */ { - ext_flash_read_block_multi(&header, 4, EF_SETTINGS); - if((header <= pSettings->header) && (header >= pSettings->updateSettingsAllowedFromHeader)) /* check to allow update of header */ + lengthOnEEPROM = length_hi * 256; + lengthOnEEPROM += length_lo; + if(lengthOnEEPROM <= lengthStandardNow) /* EEPROM Header size equal or smaller => settings constant or upgraded */ { - returnValue = HAL_OK; - pSettings->header = header; - pData = (uint8_t *)pSettings + 4; /* header */ - for(uint16_t i = 0; i < (lengthOnEEPROM-4); i++) - ext_flash_read_block(&pData[i], EF_SETTINGS); - if(header != pSettings->header) /* setting layout changed => no additional setting sets expected */ + ext_flash_read_block_multi(&header, 4, whichSettings); + if((header <= pSettings->header) && (header >= pSettings->updateSettingsAllowedFromHeader)) /* check to allow update of header */ { + returnValue = HAL_OK; + pSettings->header = header; + pData = (uint8_t *)pSettings + 4; /* header */ + for(uint16_t i = 0; i < (lengthOnEEPROM-4); i++) + ext_flash_read_block(&pData[i], whichSettings); + if(header != pSettings->header) /* setting layout changed => no additional setting sets expected */ + { + exit = 1; + } + } + else + { + returnValue = HAL_ERROR; exit = 1; } } - else + else /* size of settings decreased => possible downgrade of firmware */ { - returnValue = HAL_ERROR; + ext_flash_read_block_multi(&header, 4, whichSettings); + + if(header > 0xFFFF0014) /* verify that new (old) header should be compatible (only less bytes, no change in layout) */ + { + returnValue = HAL_OK; + pSettings->header = header; + pData = (uint8_t *)pSettings + 4; /* header */ + for(uint16_t i = 0; i < (lengthStandardNow-4); i++) /* only read the data fitting into the structure */ + ext_flash_read_block(&pData[i], whichSettings); + } + else + { + returnValue = HAL_ERROR; + } exit = 1; } + ext_flash_read_block(&length_lo, whichSettings); + ext_flash_read_block(&length_hi, whichSettings); } - else /* size of settings decreased => possible downgrade of firmware */ - { - ext_flash_read_block_multi(&header, 4, EF_SETTINGS); + ext_flash_decf_address_ring(whichSettings); /* set pointer back to empty address */ + ext_flash_decf_address_ring(whichSettings); + ext_flash_read_block_stop(); - if(header > 0xFFFF0014) /* verify that new (old) header should be compatible (only less bytes, no change in layout) */ - { - returnValue = HAL_OK; - pSettings->header = header; - pData = (uint8_t *)pSettings + 4; /* header */ - for(uint16_t i = 0; i < (lengthStandardNow-4); i++) /* only read the data fitting into the structure */ - ext_flash_read_block(&pData[i], EF_SETTINGS); - } - else - { - returnValue = HAL_ERROR; - } - exit = 1; + if(actualAddress > actualPointerSettings) /* the write pointer has not yet been set up probably */ + { + actualPointerSettings = actualAddress; } - ext_flash_read_block(&length_lo, EF_SETTINGS); - ext_flash_read_block(&length_hi, EF_SETTINGS); + ext_flash_read_block_stop(); } - ext_flash_decf_address_ring(EF_SETTINGS); /* set pointer back to empty address */ - ext_flash_decf_address_ring(EF_SETTINGS); - ext_flash_read_block_stop(); - - if(actualAddress > actualPointerSettings) /* the write pointer has not yet been set up probably */ - { - actualPointerSettings = actualAddress; - } - ext_flash_read_block_stop(); return returnValue; } @@ -1851,6 +1882,13 @@ ringStart = FWSTART2; ringStop = FWSTOP2; break; + case EF_PROFILE0: + case EF_PROFILE1: + case EF_PROFILE2: + case EF_PROFILE3: actualAddress = actualPointerProfile; + ringStart = PROFILE0_START; + ringStop = PROFILE3_STOP; + break; default: ringStart = FLASHSTART; ringStop = FLASHSTOP; @@ -1932,6 +1970,11 @@ case EF_FIRMWARE2: actualPointerFirmware2 = actualAddress; break; + case EF_PROFILE0: + case EF_PROFILE1: + case EF_PROFILE2: + case EF_PROFILE3: actualPointerProfile = actualAddress; + break; default: break; } @@ -1996,6 +2039,13 @@ ringStart = SETTINGSSTART; ringStop = SETTINGSSTOP; break; + case EF_PROFILE0: + case EF_PROFILE1: + case EF_PROFILE2: + case EF_PROFILE3: ringStart = PROFILE0_START; + ringStop = PROFILE3_STOP; + break; + default: ringStart = FLASHSTART; ringStop = FLASHSTOP; @@ -2145,6 +2195,12 @@ ringStart = FWSTART2; ringStop = FWSTOP2; break; + case EF_PROFILE0: + case EF_PROFILE1: + case EF_PROFILE2: + case EF_PROFILE3: ringStart = PROFILE0_START; + ringStop = PROFILE3_STOP; + break; default: ringStart = FLASHSTART; ringStop = FLASHSTOP; @@ -2190,6 +2246,13 @@ ringStart = FWSTART2; ringStop = FWSTOP2; break; + case EF_PROFILE0: + case EF_PROFILE1: + case EF_PROFILE2: + case EF_PROFILE3: ringStart = PROFILE0_START; + ringStop = PROFILE3_STOP; + break; + default: ringStart = FLASHSTART; ringStop = FLASHSTOP;
--- a/Discovery/Src/gfx_colors.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Src/gfx_colors.c Sat Nov 15 19:29:44 2025 +0100 @@ -89,8 +89,8 @@ 0x00AC00ff,//0x00E5AE18, // CLUT_MenuPageHardware 0x00ff00ff,//0x00E5AEFF, // CLUT_MenuPageSystem 0x00FF55FF,//0x00FFFF00, // CLUT_MenuPageCustomView + 0x00FFAAFF, // CLUT_MenuPageCVOption 0x00C4EACC, // CLUT_MenuPageDivePlanner - 0x00000000, // CLUT_MenuPage10 - UNUSED 0x00FFFFFF, // CLUT_ButtonSymbols 0x000092D0, // CLUT_InfoSurface 0x000092D0, // CLUT_InfoDive - UNUSED
--- a/Discovery/Src/gfx_engine.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Src/gfx_engine.c Sat Nov 15 19:29:44 2025 +0100 @@ -1075,7 +1075,7 @@ /* this is NOT fast nor optimized */ -static void GFX_draw_pixel(GFX_DrawCfgScreen *hgfx, int16_t x, int16_t y, uint8_t color) +void GFX_draw_pixel(GFX_DrawCfgScreen *hgfx, int16_t x, int16_t y, uint8_t color) { uint16_t* pDestination; @@ -3483,7 +3483,7 @@ #define Vsync_d1 2 #define VFP_d1 4 // make sure this value * VSYNC is also set in display.c for OLED_VFP_SET -#define VBP_d1 4 // make sure this value * VSYNC is also set in display.c for OLED_VBP_SET +#define VBP_d1 6 // make sure this value * VSYNC is also set in display.c for OLED_VBP_SET /* Horizontal synchronization width = Hsync - 1 */ LtdcHandle.Init.HorizontalSync = Hsync_d1 - 1; @@ -3828,7 +3828,7 @@ hgfx.WindowX1 = 779; if(Font == &FontT24) { - hgfx.WindowX0 = hgfx.WindowX1 - (Font->spacesize*3); + hgfx.WindowX0 = hgfx.WindowX1 - (Font->spacesize*7); } else {
--- a/Discovery/Src/logbook.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Src/logbook.c Sat Nov 15 19:29:44 2025 +0100 @@ -67,6 +67,9 @@ #define DEFAULT_SAMPLES (100) /* Number of sample data bytes in case of an broken header information */ #define DUMMY_SAMPLES (1000) /* Maximum number of samples profided by a dummy dive profile */ +#define SCRUBBER_ERROR_FLAG 0x4000 +#define SCRUBBER_WARNING_FLAG 0x2000 + typedef struct /* don't forget to adjust void clear_divisor(void) */ { uint8_t temperature; @@ -467,6 +470,10 @@ eventByte1.ub.bit7 = 1; eventByte2.ub.bit2 = 1; } + if (state->events.scrubberState) { + eventByte1.ub.bit7 = 1; + eventByte2.ub.bit3 = 1; + } //Add EventByte 1 if(eventByte1.uw > 0) @@ -510,8 +517,9 @@ } if (state->events.compassHeadingUpdate) { // New heading and type of heading - sample[length++] = state->events.info_compassHeadingUpdate & 0xFF; - sample[length++] = (state->events.info_compassHeadingUpdate & 0xFF00) >> 8; + pdata = (uint8_t*)&state->events.info_compassHeadingUpdate; + sample[length++] = *pdata++; + sample[length++] = *pdata++; } if (state->events.gnssPositionUpdate) { pdata = (uint8_t*)&state->events.info_gnssPosition.fLon; @@ -525,6 +533,11 @@ sample[length++] = *pdata++; sample[length++] = *pdata++; } + if (state->events.scrubberState) { + pdata = (uint8_t*)&state->events.info_scrubberState; + sample[length++] = *pdata++; + sample[length++] = *pdata++; + } if(divisor.temperature == 0) { @@ -706,7 +719,7 @@ */ static uint16_t readSample(int32_t* depth, int16_t * gasid, int16_t* setpoint_cbar, int32_t* temperature, int32_t* sensor1, int32_t* sensor2, int32_t* sensor3, int32_t* cns, SManualGas* manualGas, int16_t* bailout, int16_t* decostopDepth, uint16_t* tank, - SGnssCoord* pPosition, uint8_t* event) + uint16_t* compassHeading, SGnssCoord* pPosition, uint16_t* scrubberState, uint8_t* event) { int length = 0; _Bool bEvent = 0; @@ -740,6 +753,12 @@ if(tank) *tank = 0; + if (compassHeading) + *compassHeading = UINT16_MAX; + + if (scrubberState) + *scrubberState = UINT16_MAX; + if(manualGas) { manualGas->percentageO2 =-1; @@ -836,6 +855,14 @@ if(gasid) *gasid = 0; } + + // Compass heading + if (eventByte2.ub.bit1) { + ext_flash_read_next_sample_part((uint8_t*)compassHeading, 2); + bytesRead += 2; + length -= 2; + } + /* gnss position start dive */ if(eventByte2.ub.bit2) { @@ -864,6 +891,13 @@ memcpy(&pPosition->fLat, &tempU32, 4); } } + + // Scrubber state + if (eventByte2.ub.bit3) { + ext_flash_read_next_sample_part((uint8_t*)scrubberState, 2); + bytesRead += 2; + length -= 2; + } } if(divisor.temperature == 0) @@ -1006,7 +1040,7 @@ */ uint16_t logbook_readSampleData(uint8_t StepBackwards, uint16_t length,uint16_t* depth, uint8_t* gasid, int16_t* temperature, uint16_t* ppo2, uint16_t* setpoint, uint16_t* sensor1, uint16_t* sensor2, uint16_t* sensor3, uint16_t* cns, uint8_t* bailout, - uint16_t* decostopDepth, uint16_t* tank, SGnssCoord* pPosition, uint8_t* event) + uint16_t* decostopDepth, uint16_t* tank, uint16_t* compassHeading, SGnssCoord* pPosition, uint16_t* scrubberState, uint8_t* event) { //Test read //SLogbookHeader header; @@ -1043,6 +1077,10 @@ uint16_t tankVal = 0; uint32_t small_profileLength = 0; uint8_t eventdata; + uint16_t compassHeadingVal; + uint16_t compassHeadingLast = UINT16_MAX; + uint16_t scrubberStateVal; + uint16_t scrubberStateLast = UINT16_MAX; SGnssCoord posCoord; posCoord.fLat = 0.0; posCoord.fLon = 0.0; @@ -1126,7 +1164,7 @@ ext_flash_set_entry_point(); divisorBackup = divisor; retVal = readSample(&depthVal,&gasidVal, &setPointVal, &temperatureVal, &sensor1Val, &sensor2Val, &sensor3Val, &cnsVal, &manualGasVal, - &bailoutVal, &decostepDepthVal, &tankVal, &posCoord, &eventdata); + &bailoutVal, &decostepDepthVal, &tankVal, &compassHeadingVal, &posCoord, &scrubberStateVal, &eventdata); if(retVal == 0) { @@ -1134,7 +1172,7 @@ ext_flash_reopen_read_sample_at_entry_point(); divisor = divisorBackup; retVal = readSample(&depthVal,&gasidVal,&setPointVal, &temperatureVal, &sensor1Val, &sensor2Val, &sensor3Val, &cnsVal, - &manualGasVal, &bailoutVal, &decostepDepthVal, &tankVal, &posCoord, &eventdata); + &manualGasVal, &bailoutVal, &decostepDepthVal, &tankVal, &compassHeadingVal, &posCoord, &scrubberStateVal, &eventdata); if(retVal == 0) break; @@ -1201,6 +1239,16 @@ else decostepDepthLast = decostepDepthVal; + if (compassHeadingVal == UINT16_MAX) + compassHeadingVal = compassHeadingLast; + else + compassHeadingLast = compassHeadingVal; + + if (scrubberStateVal == UINT16_MAX) + scrubberStateVal = scrubberStateLast; + else + scrubberStateLast = scrubberStateVal; + counter++; // Heed compression // Write here to arrays @@ -1264,6 +1312,13 @@ sensor2[iNum] = (sensor2Val / 0xFFFF) & 0xFF; if(sensor3) sensor3[iNum] = (sensor3Val / 0xFFFF) & 0xFF; + + if (compassHeading) + compassHeading[iNum] = compassHeadingVal; + + if (scrubberState) + scrubberState[iNum] = scrubberStateVal; + iNum++; counter = 0; @@ -1274,6 +1329,7 @@ } } } + if(pPosition) { memcpy(pPosition, &posCoord, sizeof(posCoord)); @@ -1321,8 +1377,23 @@ { //InitdiveProfile pSettings->totalDiveCounter++; - logbook_initNewdiveProfile(pStateReal,settingsGetPointer()); + logbook_initNewdiveProfile(pStateReal, pSettings); min_temperature_float_celsius = pStateReal->lifeData.temperature_celsius; + if (isScrubberTimerRunning(pStateReal, pSettings)) { + int16_t maxScrubberTime = INT16_MIN; + SScrubberData *longestScrubberData = NULL; + for (unsigned timerId = 0; timerId < 2; timerId++) { + if (pSettings->scrubberActiveId & (1 << timerId)) { + SScrubberData *scrubberData = &pStateReal->scrubberDataDive[timerId]; + if (scrubberData->TimerCur > maxScrubberTime) { + maxScrubberTime = scrubberData->TimerCur; + longestScrubberData = scrubberData; + } + } + } + + logScrubberState(longestScrubberData); + } //Write logbook sample logbook_writeSample(pStateReal); @@ -1355,13 +1426,13 @@ { pSettings->logbookOffset++; } - ext_flash_write_settings(0); + ext_flash_write_settings(EF_SETTINGS,0); ext_flash_disable_protection_for_logbook(); ext_flash_CloseSector(); /* this is just a repair function which invalidates a not used sector in case a log maintenance was called before dive */ bDiveMode = 3; -#if defined ENABLE_GNSS_SUPPORT || defined ENABLE_GPIO_V2 +#if defined ENABLE_GNSS_INTERN || defined ENABLE_GNSS_EXTERN pStateReal->events.gnssPositionUpdate = 1; if(pStateReal->lifeData.gnssData.alive & GNSS_ALIVE_BACKUP_POS) @@ -1873,7 +1944,9 @@ int16_t decostepDepthVal = 0; uint16_t tankVal = 0; uint8_t eventdata; + uint16_t compassHeadingVal; SGnssCoord posCoord; + uint16_t scrubberStateVal; //uint16_t* ppo2, uint16_t* cns# uint32_t bytesRead = 0; @@ -1894,21 +1967,21 @@ ext_flash_set_entry_point(); divisorBackup = divisor; retVal = readSample(&depthVal,&gasidVal, &setPointVal, &temperatureVal, &sensor1Val, &sensor2Val, &sensor3Val, &cnsVal, &manualGasVal, - &bailoutVal, &decostepDepthVal,&tankVal, &posCoord, &eventdata); + &bailoutVal, &decostepDepthVal, &tankVal, &compassHeadingVal, &posCoord, &scrubberStateVal, &eventdata); if(retVal == 0) { //Error try to read again!!! ext_flash_reopen_read_sample_at_entry_point(); divisor = divisorBackup; retVal = readSample(&depthVal,&gasidVal, &setPointVal, &temperatureVal, &sensor1Val, &sensor2Val, &sensor3Val, &cnsVal, &manualGasVal, - &bailoutVal, &decostepDepthVal, &tankVal, &posCoord, &eventdata); + &bailoutVal, &decostepDepthVal, &tankVal, &compassHeadingVal, &posCoord, &scrubberStateVal, &eventdata); if(retVal == 0) { //Error try to read again!!! ext_flash_reopen_read_sample_at_entry_point(); divisor = divisorBackup; retVal = readSample(&depthVal,&gasidVal, &setPointVal, &temperatureVal, &sensor1Val, &sensor2Val, &sensor3Val, &cnsVal, &manualGasVal, - &bailoutVal, &decostepDepthVal,&tankVal, &posCoord, &eventdata); + &bailoutVal, &decostepDepthVal, &tankVal, &compassHeadingVal, &posCoord, &scrubberStateVal, &eventdata); if(retVal == 0) { ext_flash_reopen_read_sample_at_entry_point(); @@ -2146,5 +2219,19 @@ dummyReadIdx += length; } +void logScrubberState(const SScrubberData *scrubberData) +{ + uint16_t scrubberState = scrubberData->TimerCur & 0x0FFF; // truncate to 12 bit + if (isScrubberError(scrubberData)) { + scrubberState |= SCRUBBER_ERROR_FLAG; + } + + if (isScrubberWarning(scrubberData)) { + scrubberState |= SCRUBBER_WARNING_FLAG; + } + + stateUsedWrite->events.scrubberState = 1; + stateUsedWrite->events.info_scrubberState = scrubberState; +} /************************ (C) COPYRIGHT heinrichs weikamp *****END OF FILE****/
--- a/Discovery/Src/logbook_miniLive.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Src/logbook_miniLive.c Sat Nov 15 19:29:44 2025 +0100 @@ -367,7 +367,7 @@ ReplayDataOffset = StepBackwards; logbook_getHeader(StepBackwards ,&logbookHeader); - dataLength = logbook_readSampleData(StepBackwards, DEPTH_DATA_LENGTH, ReplayDepthData,NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ReplayMarkerData); + dataLength = logbook_readSampleData(StepBackwards, DEPTH_DATA_LENGTH, ReplayDepthData,NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ReplayMarkerData); /* check if a marker is provided. If not disable marker functionality for the replay block */ for(index = 0; index < dataLength; index++)
--- a/Discovery/Src/ostc.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Src/ostc.c Sat Nov 15 19:29:44 2025 +0100 @@ -27,8 +27,10 @@ ////////////////////////////////////////////////////////////////////////////// /* Includes ------------------------------------------------------------------*/ +#include "configuration.h" #include "ostc.h" #include "stm32f4xx_hal.h" +#include "cv_heartbeat.h" #ifndef BOOTLOADER_STANDALONE #include "tCCR.h" @@ -45,6 +47,10 @@ #endif UART_HandleTypeDef UartIR_HUD_Handle; +#ifdef ENABLE_USART_RADIO +UART_HandleTypeDef UartRadio_Handle; +#endif + __IO ITStatus UartReady = RESET; __IO ITStatus UartReadyHUD = RESET; @@ -54,6 +60,19 @@ /* Private variables with external access via get_xxx() function -------------*/ static uint8_t hardwareDisplay = 0; //< either OSTC4 LCD (=0) or new Screen (=1) + +#ifdef ENABLE_PULSE_SENSOR_BT +static DMA_HandleTypeDef hdma_uart_BT_rx; +#endif + +#ifdef ENABLE_USART_RADIO +static DMA_HandleTypeDef hdma_uart_radio_rx; +#endif + +static uint16_t rxBufRead = 0; +static uint16_t rxBufWrite = 0; +static uint8_t rxBufferUart[CHUNK_SIZE * CHUNKS_PER_BUFFER]; /* The complete buffer has a X * chunk size to allow variations in buffer read time */ + /* Private function prototypes -----------------------------------------------*/ /* Exported functions --------------------------------------------------------*/ @@ -138,7 +157,10 @@ SMALLCPU_CSB_GPIO_ENABLE(); OSCILLOSCOPE_GPIO_ENABLE(); OSCILLOSCOPE2_GPIO_ENABLE(); - BLE_UBLOX_DSR_GPIO_ENABLE(); + if(isNewDisplay()) + { + BLE_UBLOX_DSR_GPIO_ENABLE(); + } GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; @@ -232,12 +254,15 @@ HAL_GPIO_Init(BLE_NENABLE_GPIO_PORT, &GPIO_InitStruct); HAL_GPIO_WritePin(BLE_NENABLE_GPIO_PORT,BLE_NENABLE_PIN,GPIO_PIN_RESET); - GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; - GPIO_InitStruct.Pull = GPIO_PULLDOWN; - GPIO_InitStruct.Speed = GPIO_SPEED_LOW; - GPIO_InitStruct.Pin = BLE_UBLOX_DSR_PIN; - HAL_GPIO_Init(BLE_UBLOX_DSR_GPIO_PORT, &GPIO_InitStruct); - HAL_GPIO_WritePin(BLE_UBLOX_DSR_GPIO_PORT,BLE_UBLOX_DSR_PIN,GPIO_PIN_RESET); + if(isNewDisplay()) + { + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_PULLDOWN; + GPIO_InitStruct.Speed = GPIO_SPEED_LOW; + GPIO_InitStruct.Pin = BLE_UBLOX_DSR_PIN; + HAL_GPIO_Init(BLE_UBLOX_DSR_GPIO_PORT, &GPIO_InitStruct); + HAL_GPIO_WritePin(BLE_UBLOX_DSR_GPIO_PORT,BLE_UBLOX_DSR_PIN,GPIO_PIN_RESET); + } } @@ -248,7 +273,11 @@ GPIO_InitStruct.Pin = BLE_NENABLE_PIN; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(BLE_NENABLE_GPIO_PORT, &GPIO_InitStruct); - HAL_GPIO_WritePin(BLE_UBLOX_DSR_GPIO_PORT,BLE_UBLOX_DSR_PIN,GPIO_PIN_RESET); + + if(isNewDisplay()) + { + HAL_GPIO_WritePin(BLE_UBLOX_DSR_GPIO_PORT,BLE_UBLOX_DSR_PIN,GPIO_PIN_RESET); + } } @@ -353,7 +382,7 @@ UartHandle.Init.StopBits = UART_STOPBITS_1; UartHandle.Init.Parity = UART_PARITY_NONE; UartHandle.Init.Mode = UART_MODE_TX_RX; - HAL_UART_Init(&UartHandle); + /* HAL_UART_Init(&UartHandle); moved final init step into BT config function to avoid problems while module power is off */ #ifdef USART_PIEZO UartPiezoTxHandle.Instance = USART_PIEZO; @@ -378,8 +407,122 @@ HAL_UART_Init(&UartIR_HUD_Handle); #endif + +#ifdef ENABLE_USART_RADIO + UartRadio_Handle.Instance = USART_RADIO; + UartRadio_Handle.Init.BaudRate = 9600; + UartRadio_Handle.Init.WordLength = UART_WORDLENGTH_8B; + UartRadio_Handle.Init.StopBits = UART_STOPBITS_1; + UartRadio_Handle.Init.Parity = UART_PARITY_NONE; + UartRadio_Handle.Init.HwFlowCtl = UART_HWCONTROL_NONE; + UartRadio_Handle.Init.Mode = UART_MODE_RX; + + HAL_UART_Init(&UartRadio_Handle); +#endif + } +#ifdef ENABLE_PULSE_SENSOR_BT +void MX_UART_BT_Init_DMA() +{ + + __DMA2_CLK_ENABLE(); + __HAL_RCC_DMA2_CLK_ENABLE(); + + hdma_uart_BT_rx.Instance = DMA2_Stream2; + hdma_uart_BT_rx.Init.Channel = DMA_CHANNEL_4; + hdma_uart_BT_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_uart_BT_rx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_uart_BT_rx.Init.MemInc = DMA_MINC_ENABLE; + hdma_uart_BT_rx.Init.PeriphDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_uart_BT_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_uart_BT_rx.Init.Mode = DMA_NORMAL; + hdma_uart_BT_rx.Init.Priority = DMA_PRIORITY_LOW; + hdma_uart_BT_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + HAL_DMA_Init(&hdma_uart_BT_rx); + + __HAL_LINKDMA(&UartHandle, hdmarx, hdma_uart_BT_rx); + + HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn); +} +#endif + +#ifdef ENABLE_USART_RADIO +void MX_UART_RADIO_Init_DMA() +{ + + __DMA2_CLK_ENABLE(); + __HAL_RCC_DMA2_CLK_ENABLE(); + + hdma_uart_radio_rx.Instance = DMA2_Stream1; + hdma_uart_radio_rx.Init.Channel = DMA_CHANNEL_4; + hdma_uart_radio_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_uart_radio_rx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_uart_radio_rx.Init.MemInc = DMA_MINC_ENABLE; + hdma_uart_radio_rx.Init.PeriphDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_uart_radio_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_uart_radio_rx.Init.Mode = DMA_NORMAL; + hdma_uart_radio_rx.Init.Priority = DMA_PRIORITY_LOW; + hdma_uart_radio_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + HAL_DMA_Init(&hdma_uart_radio_rx); + + __HAL_LINKDMA(&UartRadio_Handle, hdmarx, hdma_uart_radio_rx); + + HAL_NVIC_SetPriority(DMA2_Stream1_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(DMA2_Stream1_IRQn); +} +#endif + + +uint8_t UART_getChar() +{ + uint8_t retChar = 0; + + if((rxBufRead != rxBufWrite) && (rxBufferUart[rxBufRead] != 0)) + { + retChar = rxBufferUart[rxBufRead]; + rxBufferUart[rxBufRead++] = 0; + if(rxBufRead == CHUNK_SIZE * CHUNKS_PER_BUFFER) + { + rxBufRead = 0; + } + } + return retChar; +} +#ifdef ENABLE_PULSE_SENSOR_BT +void UART_StartDMARx() +{ + HAL_UART_Receive_DMA (&UartHandle, &rxBufferUart[rxBufWrite], CHUNK_SIZE); + rxBufWrite += CHUNK_SIZE; + if(rxBufWrite >= CHUNK_SIZE * CHUNKS_PER_BUFFER) + { + rxBufWrite = 0; + } +} +void DMA2_Stream2_IRQHandler(void) +{ + HAL_DMA_IRQHandler(&hdma_uart_BT_rx); +} +#endif + +#ifdef ENABLE_USART_RADIO +void UART_StartDMARxRadio() +{ + HAL_UART_Receive_DMA (&UartRadio_Handle, &rxBufferUart[rxBufWrite], CHUNK_SIZE); + rxBufWrite += CHUNK_SIZE; + if(rxBufWrite >= CHUNK_SIZE * CHUNKS_PER_BUFFER) + { + rxBufWrite = 0; + } +} + +void DMA2_Stream2_IRQHandler(void) +{ + HAL_DMA_IRQHandler(&hdma_uart_radio_rx); +} +#endif + void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) { if(huart == &UartHandle) @@ -390,7 +533,20 @@ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(huart == &UartHandle) - UartReady = SET; + { +#ifdef ENABLE_PULSE_SENSOR_BT + if(cv_heartbeat_getState() != SENSOR_HB_OFFLINE) + { + UART_StartDMARx(); + } + else + { + UartReady = SET; + } +#else + UartReady = SET; +#endif + } else if(huart == &UartIR_HUD_Handle) {
--- a/Discovery/Src/settings.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Src/settings.c Sat Nov 15 19:29:44 2025 +0100 @@ -33,6 +33,10 @@ #include "externLogbookFlash.h" // for SAMPLESTART and SAMPLESTOP #include "text_multilanguage.h" // for LANGUAGE_END #include "tHome.h" // for CVIEW_END +#include "tMenu.h" +#include "tMenuEdit.h" +#include "tInfo.h" +#include "tInfoLog.h" #include "motion.h" #include "t7.h" #include "data_central.h" @@ -42,8 +46,10 @@ SSettings Settings; +SSettings Profile[NUMBER_OF_PROFILES]; /* may be optimized if RAM is getting short. profile copies are only used by profile dialog */ + /* static structure is used to keep things simple avoiding larger code changes */ const uint8_t RTErequiredHigh = 3; -const uint8_t RTErequiredLow = 4; +const uint8_t RTErequiredLow = 7; const uint8_t FONTrequiredHigh = 1; const uint8_t FONTrequiredLow = 0; @@ -61,16 +67,16 @@ const SFirmwareData firmware_FirmwareData __attribute__( (section(".firmware_firmware_data")) ) = { .versionFirst = 1, - .versionSecond = 6, - .versionThird = 9, + .versionSecond = 7, + .versionThird = 4, .versionBeta = 0, /* 4 bytes with trailing 0 */ .signature = "mh", .release_year = 25, - .release_month = 1, - .release_day = 18, + .release_month = 6, + .release_day = 9, .release_sub = 0, /* max 48 with trailing 0 */ @@ -89,7 +95,7 @@ * There might even be entries with fixed values that have no range */ const SSettings SettingsStandard = { - .header = 0xFFFF002C, + .header = 0xFFFF002D, .warning_blink_dsec = 8 * 2, .lastDiveLogId = 0, .logFlashNextSampleStartAddress = SAMPLESTART, @@ -326,7 +332,7 @@ .autoSetpoint = 0, .scrubTimerMax_Obsolete = 0, .scrubTimerCur_Obsolete = 0, - .scrubTimerMode = SCRUB_TIMER_OFF, + .scrubTimerMode = SCRUB_TIMER_MINUTES, .ext_sensor_map[0] = SENSOR_OPTIC, .ext_sensor_map[1] = SENSOR_OPTIC, .ext_sensor_map[2] = SENSOR_OPTIC, @@ -343,15 +349,48 @@ .slowExitTime = 0, .timeZone.hours = 0, .timeZone.minutes = 0, - .warningBuzzer = 0 + .warningBuzzer = 0, + .profileName[0] = "STANDARD", + .profileName[1] = "OC_TX___", + .profileName[2] = "MCCR____", + .profileName[3] = "ECCR____", + .activeProfile = 0, }; /* Private function prototypes -----------------------------------------------*/ uint8_t checkValue(uint8_t value,uint8_t from, uint8_t to); +/* The profiles are store in a 4k flash block => make sure that size does not violate the size of the flash block (settings * 4) */ +_Static_assert(sizeof(Settings) < 1000, "To much settings to support multiple profiles"); + + /* Functions -----------------------------------------------------------------*/ +uint16_t settingsGetSize() +{ + return sizeof (Settings); +} + + +void setFlipDisplay(uint8_t flipDisplay) +{ + bool settingChanged = flipDisplay != Settings.FlipDisplay; + Settings.FlipDisplay = flipDisplay; + if (settingChanged) { + // reinit all views + tHome_init(); + tI_init(); + tM_init(); + tMenuEdit_init(); + tInfoLog_init(); + tM_build_pages(); + GFX_build_logo_frame(); + GFX_build_hw_background_frame(); + } +} + + // =============================================================================== // set_new_settings_missing_in_ext_flash /// @brief Add all the new setting variables of this version @@ -361,34 +400,49 @@ /// // =============================================================================== SSettings* pSettings; -void set_new_settings_missing_in_ext_flash(void) +void set_new_settings_missing_in_ext_flash(uint8_t whichSettings) { uint32_t tmp = 0; + pSettings = settingsGetPointer(); + switch(whichSettings) + { + default: + case EF_SETTINGS: + break; + case EF_PROFILE0: pSettings = profileGetPointer(0); + break; + case EF_PROFILE1: pSettings = profileGetPointer(1); + break; + case EF_PROFILE2: pSettings = profileGetPointer(2); + break; + case EF_PROFILE3: pSettings = profileGetPointer(3); + break; + } // never delete this part setting the serial if(hardwareDataGetPointer()->secondarySerial != 0xFFFF) { - settingsGetPointer()->serialHigh = (hardwareDataGetPointer()->secondarySerial / 256); - settingsGetPointer()->serialLow = (hardwareDataGetPointer()->secondarySerial & 0xFF); + pSettings->serialHigh = (hardwareDataGetPointer()->secondarySerial / 256); + pSettings->serialLow = (hardwareDataGetPointer()->secondarySerial & 0xFF); } else if(hardwareDataGetPointer()->primarySerial != 0xFFFF) { - settingsGetPointer()->serialHigh = (hardwareDataGetPointer()->primarySerial / 256); - settingsGetPointer()->serialLow = (hardwareDataGetPointer()->primarySerial & 0xFF); + pSettings->serialHigh = (hardwareDataGetPointer()->primarySerial / 256); + pSettings->serialLow = (hardwareDataGetPointer()->primarySerial & 0xFF); } else { - settingsGetPointer()->serialHigh = 0; - settingsGetPointer()->serialLow = 0; + pSettings->serialHigh = 0; + pSettings->serialLow = 0; } - settingsGetPointer()->firmwareVersion[0] = firmware_FirmwareData.versionFirst; - settingsGetPointer()->firmwareVersion[1] = firmware_FirmwareData.versionSecond; - settingsGetPointer()->firmwareVersion[2] = firmware_FirmwareData.versionThird; - settingsGetPointer()->firmwareVersion[3] = firmware_FirmwareData.versionBeta; + pSettings->firmwareVersion[0] = firmware_FirmwareData.versionFirst; + pSettings->firmwareVersion[1] = firmware_FirmwareData.versionSecond; + pSettings->firmwareVersion[2] = firmware_FirmwareData.versionThird; + pSettings->firmwareVersion[3] = firmware_FirmwareData.versionBeta; - pSettings = settingsGetPointer(); + const SSettings* pStandard = settingsGetPointerStandard(); /* Pointing to the old header data => set new data depending on what had been added since last version */ @@ -442,7 +496,7 @@ pSettings->gasConsumption_deco_l_min = pStandard->gasConsumption_deco_l_min; // no break case 0xFFFF000C: - memcpy(pSettings->customtext, " hwOS 4\n\r" " welcome\n\r", 60); + strncpy(pSettings->customtext, " hwOS 4\n\r" " welcome\n\r", sizeof(pSettings->customtext)); // no break case 0xFFFF000D: // nothing to do from 0xFFFF000D to 0xFFFF000E, just about header :-) case 0xFFFF000E: @@ -476,10 +530,11 @@ pSettings->FactoryButtonBalance[2] = pStandard->FactoryButtonBalance[2]; // no break case 0xFFFF0017: - pSettings->FlipDisplay = 0; - // no break + setFlipDisplay(0); + // no break case 0xFFFF0018: pSettings->cv_configuration = 0xFFFFFFFF; + pSettings->cv_configuration &= ~(1 << CVIEW_sensors | 1 << CVIEW_sensors_mV | 1 << CVIEW_Timer); // no break case 0xFFFF0019: pSettings->MotionDetection = MOTION_DETECT_OFF; @@ -487,13 +542,13 @@ case 0xFFFF001A: /* deactivate new views => to be activated by customer */ pSettings->cv_config_BigScreen = 0xFFFFFFFF; - pSettings->cv_config_BigScreen &= pSettings->cv_configuration ^= 1 << (CVIEW_T3_Navigation + LEGACY_T3_START_ID_PRE_TIMER); - pSettings->cv_config_BigScreen &= pSettings->cv_configuration ^= 1 << (CVIEW_T3_DepthData + LEGACY_T3_START_ID_PRE_TIMER); + pSettings->cv_config_BigScreen &= 1 << (CVIEW_T3_Navigation + LEGACY_T3_START_ID_PRE_TIMER); + pSettings->cv_config_BigScreen &= 1 << (CVIEW_T3_DepthData + LEGACY_T3_START_ID_PRE_TIMER); // no break case 0xFFFF001B: pSettings->compassInertia = 0; /* no inertia */ pSettings->tX_customViewPrimaryBF = CVIEW_T3_Decostop; - pSettings->cv_config_BigScreen &= pSettings->cv_configuration ^= 1 << (CVIEW_T3_DecoTTS + LEGACY_T3_START_ID_PRE_TIMER); + pSettings->cv_config_BigScreen &= 1 << (CVIEW_T3_DecoTTS + LEGACY_T3_START_ID_PRE_TIMER); // no break case 0xFFFF001C: pSettings->viewPortMode = 0; @@ -512,7 +567,7 @@ pSettings->autoSetpoint = 0; pSettings->scrubTimerMax_Obsolete = 0; pSettings->scrubTimerCur_Obsolete = 0; - pSettings->scrubTimerMode = SCRUB_TIMER_OFF; + pSettings->scrubTimerMode = SCRUB_TIMER_MINUTES; // no break case 0xFFFF001F: pSettings->pscr_lung_ratio = 10; @@ -525,7 +580,7 @@ pSettings->ext_uart_protocol = 0; // no break; case 0xFFFF0022: - pSettings->scubberActiveId = 0; + pSettings->scrubberActiveId = 0; pSettings->scrubberData[0].TimerCur = pSettings->scrubTimerCur_Obsolete; pSettings->scrubberData[0].TimerMax = pSettings->scrubTimerMax_Obsolete; pSettings->scrubberData[0].lastDive.WeekDay = 0; @@ -590,15 +645,23 @@ case 0xFFFF0028: // no break; case 0xFFFF0029: - Settings.cvAutofocus = 0; + pSettings->cvAutofocus = 0; // no break; case 0xFFFF002A: - Settings.slowExitTime = 0; + pSettings->slowExitTime = 0; // no break; case 0xFFFF002B: - Settings.timeZone.hours = 0; - Settings.timeZone.minutes = 0; - Settings.warningBuzzer = 0; + pSettings->timeZone.hours = 0; + pSettings->timeZone.minutes = 0; + pSettings->warningBuzzer = 0; + // no break; + case 0xFFFF002C: + sprintf((char*)pSettings->profileName[0],"STANDARD"); + sprintf((char*)pSettings->profileName[1],"OC_TX___"); + sprintf((char*)pSettings->profileName[2],"MCCR____"); + sprintf((char*)pSettings->profileName[3],"ECCR____"); + pSettings->activeProfile = 0; + // no break; default: pSettings->header = pStandard->header; @@ -714,7 +777,7 @@ } } -uint8_t check_and_correct_settings(void) +uint8_t check_and_correct_settings(uint8_t whichSettings) { uint32_t corrections = 0; uint8_t firstGasFoundOC = 0; @@ -725,114 +788,133 @@ settingsWarning = 0; /* reset warning indicator */ SettingsStatus.FirstCorrection = 0xFF; + pSettings = settingsGetPointer(); + + switch(whichSettings) + { + default: + case EF_SETTINGS: + break; + case EF_PROFILE0: pSettings = profileGetPointer(0); + break; + case EF_PROFILE1: pSettings = profileGetPointer(1); + break; + case EF_PROFILE2: pSettings = profileGetPointer(2); + break; + case EF_PROFILE3: pSettings = profileGetPointer(3); + break; + } + + + /* uint32_t header; */ /* uint8_t warning_blink_dsec; 1/10 seconds */ - if((Settings.warning_blink_dsec < 1) || (Settings.warning_blink_dsec > 100)) + if((pSettings->warning_blink_dsec < 1) || (pSettings->warning_blink_dsec > 100)) { - Settings.warning_blink_dsec = SettingsStandard.warning_blink_dsec; + pSettings->warning_blink_dsec = SettingsStandard.warning_blink_dsec; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 1 */ /* uint8_t lastDiveLogId; */ /* uint32_t logFlashNextSampleStartAddress; */ - if((Settings.logFlashNextSampleStartAddress < SAMPLESTART) || (Settings.logFlashNextSampleStartAddress > SAMPLESTOP)) + if((pSettings->logFlashNextSampleStartAddress < SAMPLESTART) || (pSettings->logFlashNextSampleStartAddress > SAMPLESTOP)) { - Settings.logFlashNextSampleStartAddress = SAMPLESTART; + pSettings->logFlashNextSampleStartAddress = SAMPLESTART; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 2 */ /* uint8_t dive_mode; has to before the gases */ - 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_PSCR)) + if( (pSettings->dive_mode != DIVEMODE_OC) && + (pSettings->dive_mode != DIVEMODE_CCR) && + (pSettings->dive_mode != DIVEMODE_Gauge) && + (pSettings->dive_mode != DIVEMODE_Apnea) && + (pSettings->dive_mode != DIVEMODE_PSCR)) { - Settings.dive_mode = DIVEMODE_OC; + pSettings->dive_mode = DIVEMODE_OC; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++;/* 3 */ /* SGasLine gas[1 + (2*NUM_GASES)]; */ for(int i=1; i<=2*NUM_GASES;i++) { - if(Settings.gas[i].oxygen_percentage < 4) + if(pSettings->gas[i].oxygen_percentage < 4) { - Settings.gas[i].oxygen_percentage = 4; + pSettings->gas[i].oxygen_percentage = 4; corrections++; setFirstCorrection(parameterId); } - if(Settings.gas[i].oxygen_percentage > 100) + if(pSettings->gas[i].oxygen_percentage > 100) { - Settings.gas[i].oxygen_percentage = 100; + pSettings->gas[i].oxygen_percentage = 100; corrections++; setFirstCorrection(parameterId); } - if((Settings.gas[i].oxygen_percentage + Settings.gas[i].helium_percentage) > 100) + if((pSettings->gas[i].oxygen_percentage + pSettings->gas[i].helium_percentage) > 100) { - Settings.gas[i].helium_percentage = 100 - Settings.gas[i].oxygen_percentage; + pSettings->gas[i].helium_percentage = 100 - pSettings->gas[i].oxygen_percentage; corrections++; setFirstCorrection(parameterId); } - if(Settings.gas[i].note.ub.deco) + if(pSettings->gas[i].note.ub.deco) { - if(Settings.gas[i].note.ub.active != 1) + if(pSettings->gas[i].note.ub.active != 1) { - Settings.gas[i].note.ub.active = 1; + pSettings->gas[i].note.ub.active = 1; corrections++; setFirstCorrection(parameterId); } - if(Settings.gas[i].note.ub.travel == 1) + if(pSettings->gas[i].note.ub.travel == 1) { - Settings.gas[i].note.ub.travel = 0; + pSettings->gas[i].note.ub.travel = 0; corrections++; setFirstCorrection(parameterId); } } - if(Settings.gas[i].note.ub.travel) + if(pSettings->gas[i].note.ub.travel) { - if(Settings.gas[i].note.ub.active != 1) + if(pSettings->gas[i].note.ub.active != 1) { - Settings.gas[i].note.ub.active = 1; + pSettings->gas[i].note.ub.active = 1; corrections++; setFirstCorrection(parameterId); } - if(Settings.gas[i].note.ub.deco == 1) + if(pSettings->gas[i].note.ub.deco == 1) { - Settings.gas[i].note.ub.deco = 0; + pSettings->gas[i].note.ub.deco = 0; corrections++; setFirstCorrection(parameterId); } } - if(Settings.gas[i].note.ub.first) + if(pSettings->gas[i].note.ub.first) { - if(Settings.gas[i].note.ub.active != 1) + if(pSettings->gas[i].note.ub.active != 1) { - Settings.gas[i].note.ub.active = 1; + pSettings->gas[i].note.ub.active = 1; corrections++; setFirstCorrection(parameterId); } - if(Settings.gas[i].note.ub.travel == 1) + if(pSettings->gas[i].note.ub.travel == 1) { - Settings.gas[i].note.ub.travel = 0; + pSettings->gas[i].note.ub.travel = 0; corrections++; setFirstCorrection(parameterId); } - if(Settings.gas[i].note.ub.deco == 1) + if(pSettings->gas[i].note.ub.deco == 1) { - Settings.gas[i].note.ub.deco = 0; + pSettings->gas[i].note.ub.deco = 0; corrections++; setFirstCorrection(parameterId); } @@ -842,480 +924,480 @@ if((i>NUM_GASES) && (!firstGasFoundCCR)) firstGasFoundCCR = 1; else - Settings.gas[i].note.ub.first = 0; + pSettings->gas[i].note.ub.first = 0; } - if(Settings.gas[i].bottle_size_liter > 40) + if(pSettings->gas[i].bottle_size_liter > 40) { - Settings.gas[i].bottle_size_liter = 40; + pSettings->gas[i].bottle_size_liter = 40; corrections++; setFirstCorrection(parameterId); } - if(Settings.gas[i].depth_meter > 250) + if(pSettings->gas[i].depth_meter > 250) { - Settings.gas[i].depth_meter = 250; + pSettings->gas[i].depth_meter = 250; corrections++; setFirstCorrection(parameterId); } - if(Settings.gas[i].depth_meter_travel > 250) + if(pSettings->gas[i].depth_meter_travel > 250) { - Settings.gas[i].depth_meter_travel = 250; + pSettings->gas[i].depth_meter_travel = 250; corrections++; setFirstCorrection(parameterId); } - /*if(Settings.gas[i].note.ub.senderCode) + /*if(pSettings->gas[i].note.ub.senderCode) { } - if(Settings.gas[i].bottle_wireless_id) + if(pSettings->gas[i].bottle_wireless_id) { } */ } // for(int i=1; i<=2*NUM_GASES;i++) - parameterId++; + parameterId++; /* 4 */ if(!firstGasFoundOC) { - Settings.gas[1].note.ub.active = 1; - Settings.gas[1].note.ub.first = 1; - Settings.gas[1].note.ub.travel = 0; - Settings.gas[1].note.ub.deco = 0; + pSettings->gas[1].note.ub.active = 1; + pSettings->gas[1].note.ub.first = 1; + pSettings->gas[1].note.ub.travel = 0; + pSettings->gas[1].note.ub.deco = 0; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 5 */ if(!firstGasFoundCCR) { - Settings.gas[1 + NUM_GASES].note.ub.active = 1; - 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; + pSettings->gas[1 + NUM_GASES].note.ub.active = 1; + pSettings->gas[1 + NUM_GASES].note.ub.first = 1; + pSettings->gas[1 + NUM_GASES].note.ub.travel = 0; + pSettings->gas[1 + NUM_GASES].note.ub.deco = 0; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 6 */ /* SSetpointLine setpoint[1 + NUM_GASES]; */ for(int i=1; i<=NUM_GASES;i++) { - if(Settings.setpoint[i].setpoint_cbar < MIN_PPO2_SP_CBAR) + if(pSettings->setpoint[i].setpoint_cbar < MIN_PPO2_SP_CBAR) { - Settings.setpoint[i].setpoint_cbar = MIN_PPO2_SP_CBAR; + pSettings->setpoint[i].setpoint_cbar = MIN_PPO2_SP_CBAR; corrections++; setFirstCorrection(parameterId); } - if(Settings.setpoint[i].setpoint_cbar > 160) + if(pSettings->setpoint[i].setpoint_cbar > 160) { - Settings.setpoint[i].setpoint_cbar = 160; + pSettings->setpoint[i].setpoint_cbar = 160; corrections++; setFirstCorrection(parameterId); } - if(Settings.setpoint[i].depth_meter > 250) + if(pSettings->setpoint[i].depth_meter > 250) { - Settings.setpoint[i].depth_meter = 250; + pSettings->setpoint[i].depth_meter = 250; corrections++; setFirstCorrection(parameterId); } } // for(int i=1; i<=NUM_GASES;i++) - parameterId++; + parameterId++; /* 7 */ if (checkAndFixSetpointSettings()) { corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 8 */ /* uint8_t CCR_Mode; */ - if( (Settings.CCR_Mode != CCRMODE_Sensors) && - (Settings.CCR_Mode != CCRMODE_Simulation) && - (Settings.CCR_Mode != CCRMODE_FixedSetpoint)) + if( (pSettings->CCR_Mode != CCRMODE_Sensors) && + (pSettings->CCR_Mode != CCRMODE_Simulation) && + (pSettings->CCR_Mode != CCRMODE_FixedSetpoint)) { - Settings.CCR_Mode = CCRMODE_FixedSetpoint; + pSettings->CCR_Mode = CCRMODE_FixedSetpoint; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 9 */ /* split2x4_Type deco_type; */ - if( (Settings.deco_type.ub.standard != GF_MODE) && - (Settings.deco_type.ub.standard != VPM_MODE)) + if( (pSettings->deco_type.ub.standard != GF_MODE) && + (pSettings->deco_type.ub.standard != VPM_MODE)) { - Settings.deco_type.ub.standard = VPM_MODE; + pSettings->deco_type.ub.standard = VPM_MODE; corrections++; setFirstCorrection(parameterId); } - parameterId++; - if(Settings.deco_type.ub.alternative != GF_MODE) + parameterId++; /* 10 */ + if(pSettings->deco_type.ub.alternative != GF_MODE) { - Settings.deco_type.ub.alternative = GF_MODE; + pSettings->deco_type.ub.alternative = GF_MODE; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 11 */ /* uint8_t ppO2_max_deco; */ - if(Settings.ppO2_max_deco > 190) + if(pSettings->ppO2_max_deco > 190) { - Settings.ppO2_max_deco = 190; + pSettings->ppO2_max_deco = 190; corrections++; setFirstCorrection(parameterId); } - parameterId++; - if(Settings.ppO2_max_deco < 100) + parameterId++; /* 12 */ + if(pSettings->ppO2_max_deco < 100) { - Settings.ppO2_max_deco = 100; + pSettings->ppO2_max_deco = 100; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 13 */ /* uint8_t ppO2_max_std; */ - if(Settings.ppO2_max_std > 190) + if(pSettings->ppO2_max_std > 190) { - Settings.ppO2_max_std = 190; + pSettings->ppO2_max_std = 190; corrections++; setFirstCorrection(parameterId); } - parameterId++; - if(Settings.ppO2_max_std < 100) + parameterId++; /* 14 */ + if(pSettings->ppO2_max_std < 100) { - Settings.ppO2_max_std = 100; + pSettings->ppO2_max_std = 100; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 15 */ /* uint8_t ppO2_min; */ - if(Settings.ppO2_min != 15) + if(pSettings->ppO2_min != 15) { - Settings.ppO2_min = 15; + pSettings->ppO2_min = 15; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 16 */ /* uint8_t CNS_max; */ - if(Settings.CNS_max != 90) + if(pSettings->CNS_max != 90) { - Settings.CNS_max = 90; + pSettings->CNS_max = 90; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 17 */ /* uint8_t ascent_MeterPerMinute_max; */ - if(Settings.ascent_MeterPerMinute_max != 30) + if(pSettings->ascent_MeterPerMinute_max != 30) { - Settings.ascent_MeterPerMinute_max = 30; + pSettings->ascent_MeterPerMinute_max = 30; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 18 */ /* uint8_t ascent_MeterPerMinute_showGraph; */ - if(Settings.ascent_MeterPerMinute_showGraph != 30) + if(pSettings->ascent_MeterPerMinute_showGraph != 30) { - Settings.ascent_MeterPerMinute_showGraph = 30; + pSettings->ascent_MeterPerMinute_showGraph = 30; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 19 */ /* uint8_t future_TTS; */ - if(Settings.future_TTS > 15) + if(pSettings->future_TTS > 15) { - Settings.future_TTS = 15; + pSettings->future_TTS = 15; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 20 */ /* uint8_t GF_high; */ - if(Settings.GF_high > 99) + if(pSettings->GF_high > 99) { - Settings.GF_high = 99; + pSettings->GF_high = 99; corrections++; setFirstCorrection(parameterId); } - parameterId++; - if(Settings.GF_high < 45) + parameterId++; /* 21 */ + if(pSettings->GF_high < 45) { - Settings.GF_high = 45; + pSettings->GF_high = 45; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 22 */ /* uint8_t GF_low; */ - if(Settings.GF_low > 99) + if(pSettings->GF_low > 99) { - Settings.GF_low = 99; + pSettings->GF_low = 99; corrections++; setFirstCorrection(parameterId); } - parameterId++; - if(Settings.GF_low < 10) + parameterId++; /* 23 */ + if(pSettings->GF_low < 10) { - Settings.GF_low = 10; + pSettings->GF_low = 10; corrections++; setFirstCorrection(parameterId); } - parameterId++; - if(Settings.GF_low > Settings.GF_high) + parameterId++; /* 24 */ + if(pSettings->GF_low > pSettings->GF_high) { - Settings.GF_low = Settings.GF_high; + pSettings->GF_low = pSettings->GF_high; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 25 */ /* uint8_t aGF_high; */ - if(Settings.aGF_high > 99) + if(pSettings->aGF_high > 99) { - Settings.aGF_high = 99; + pSettings->aGF_high = 99; corrections++; setFirstCorrection(parameterId); } - parameterId++; - if(Settings.aGF_high < 45) + parameterId++; /* 26 */ + if(pSettings->aGF_high < 45) { - Settings.aGF_high = 45; + pSettings->aGF_high = 45; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 27 */ /* uint8_t aGF_low; */ - if(Settings.aGF_low > 99) + if(pSettings->aGF_low > 99) { - Settings.aGF_low = 99; + pSettings->aGF_low = 99; corrections++; setFirstCorrection(parameterId); } - parameterId++; - if(Settings.aGF_low < 10) + parameterId++; /* 28 */ + if(pSettings->aGF_low < 10) { - Settings.aGF_low = 10; + pSettings->aGF_low = 10; corrections++; setFirstCorrection(parameterId); } - parameterId++; - if(Settings.aGF_low > Settings.aGF_high) + parameterId++; /* 29 */ + if(pSettings->aGF_low > pSettings->aGF_high) { - Settings.aGF_low = Settings.aGF_high; + pSettings->aGF_low = pSettings->aGF_high; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 30 */ /* split2x4_Type VPM_conservatism; */ - if(Settings.VPM_conservatism.ub.standard > 5) + if(pSettings->VPM_conservatism.ub.standard > 5) { - Settings.VPM_conservatism.ub.standard = 5; + pSettings->VPM_conservatism.ub.standard = 5; corrections++; setFirstCorrection(parameterId); } - parameterId++; - if(Settings.VPM_conservatism.ub.alternative > 5) + parameterId++; /* 31 */ + if(pSettings->VPM_conservatism.ub.alternative > 5) { - Settings.VPM_conservatism.ub.alternative = 5; + pSettings->VPM_conservatism.ub.alternative = 5; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 32 */ /* uint8_t safetystopDuration; */ - if(Settings.safetystopDuration > 5) + if(pSettings->safetystopDuration > 5) { - Settings.safetystopDuration = 5; + pSettings->safetystopDuration = 5; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 33 */ /* uint8_t AtemMinutenVolumenLiter; */ - if(Settings.AtemMinutenVolumenLiter != 25) + if(pSettings->AtemMinutenVolumenLiter != 25) { - Settings.AtemMinutenVolumenLiter = 25; + pSettings->AtemMinutenVolumenLiter = 25; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 34 */ /* uint8_t ReserveFractionDenominator; */ - if(Settings.ReserveFractionDenominator != 4) + if(pSettings->ReserveFractionDenominator != 4) { - Settings.ReserveFractionDenominator = 4; + pSettings->ReserveFractionDenominator = 4; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 35 */ /* uint8_t salinity; */ - if(Settings.salinity > 4) + if(pSettings->salinity > 4) { - Settings.salinity = 4; + pSettings->salinity = 4; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 36 */ /* uint8_t last_stop_depth_meter; */ - if(Settings.last_stop_depth_meter > 9) + if(pSettings->last_stop_depth_meter > 9) { - Settings.last_stop_depth_meter = 9; + pSettings->last_stop_depth_meter = 9; corrections++; setFirstCorrection(parameterId); } - parameterId++; - if(Settings.last_stop_depth_meter < 3) + parameterId++; /* 37 */ + if(pSettings->last_stop_depth_meter < 3) { - Settings.last_stop_depth_meter = 3; + pSettings->last_stop_depth_meter = 3; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 38 */ /* uint8_t stop_increment_depth_meter; */ - if(Settings.stop_increment_depth_meter != 3) + if(pSettings->stop_increment_depth_meter != 3) { - Settings.stop_increment_depth_meter = 3; + pSettings->stop_increment_depth_meter = 3; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 39 */ /* uint8_t brightness; */ - if(Settings.brightness > 4) + if(pSettings->brightness > 4) { - Settings.brightness = 4; + pSettings->brightness = 4; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 40 */ /* uint8_t date_format; */ - if( (Settings.date_format != DDMMYY) && - (Settings.date_format != MMDDYY) && - (Settings.date_format != YYMMDD)) + if( (pSettings->date_format != DDMMYY) && + (pSettings->date_format != MMDDYY) && + (pSettings->date_format != YYMMDD)) { - Settings.date_format = DDMMYY; + pSettings->date_format = DDMMYY; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 41 */ /* uint8_t selected_language; */ - if(Settings.selected_language >= LANGUAGE_END) + if(pSettings->selected_language >= LANGUAGE_END) { - Settings.selected_language = LANGUAGE_English; + pSettings->selected_language = LANGUAGE_English; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 42 */ /* char customtext[60]; */ - if(Settings.customtext[59] != 0) + if(pSettings->customtext[59] != 0) { - Settings.customtext[59] = 0; + pSettings->customtext[59] = 0; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 43 */ /* uint16_t timeoutSurfacemode; */ - if( (Settings.timeoutSurfacemode != 20) && // Quick Sleep Option - (Settings.timeoutSurfacemode != 120)) + if( (pSettings->timeoutSurfacemode != 20) && // Quick Sleep Option + (pSettings->timeoutSurfacemode != 120)) { - Settings.timeoutSurfacemode = 120; + pSettings->timeoutSurfacemode = 120; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 44 */ /* uint8_t timeoutMenuSurface; */ - if(Settings.timeoutMenuSurface != 120) + if(pSettings->timeoutMenuSurface != 120) { - Settings.timeoutMenuSurface = 120; + pSettings->timeoutMenuSurface = 120; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 45 */ /* uint8_t timeoutMenuDive; */ - if(Settings.timeoutMenuDive != 120) + if(pSettings->timeoutMenuDive != 120) { - Settings.timeoutMenuDive = 120; + pSettings->timeoutMenuDive = 120; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 46 */ /* uint8_t timeoutMenuEdit; */ - if(Settings.timeoutMenuEdit != 120) + if(pSettings->timeoutMenuEdit != 120) { - Settings.timeoutMenuEdit = 120; + pSettings->timeoutMenuEdit = 120; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 47 */ /* uint8_t timeoutInfo; */ - if(Settings.timeoutInfo != 120) + if(pSettings->timeoutInfo != 120) { - Settings.timeoutInfo = 120; + pSettings->timeoutInfo = 120; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 48 */ /* uint8_t timeoutInfoCompass; */ - if(Settings.timeoutInfoCompass != 60) + if(pSettings->timeoutInfoCompass != 60) { - Settings.timeoutInfoCompass = 60; + pSettings->timeoutInfoCompass = 60; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 49 */ /* uint8_t design; */ - if(Settings.design != 7) + if(pSettings->design != 7) { - Settings.design = 7; + pSettings->design = 7; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 50 */ /* uint16_t timeoutDiveReachedZeroDepth; */ - if(Settings.timeoutDiveReachedZeroDepth != 300) + if(pSettings->timeoutDiveReachedZeroDepth != 300) { - Settings.timeoutDiveReachedZeroDepth = 300; + pSettings->timeoutDiveReachedZeroDepth = 300; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 51 */ /* uint16_t divetimeToCreateLogbook; */ - if(Settings.divetimeToCreateLogbook != 60) + if(pSettings->divetimeToCreateLogbook != 60) { - Settings.divetimeToCreateLogbook = 60; + pSettings->divetimeToCreateLogbook = 60; corrections++; setFirstCorrection(parameterId); } - parameterId++; - if(Settings.slowExitTime > 9) + parameterId++; /* 52 */ + if(pSettings->slowExitTime > 9) { - Settings.divetimeToCreateLogbook = 0; + pSettings->divetimeToCreateLogbook = 0; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 53 */ - if(Settings.warningBuzzer > 1) + if(pSettings->warningBuzzer > 1) { - Settings.warningBuzzer = 0; + pSettings->warningBuzzer = 0; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 54 */ /* uint8_t serialHigh; @@ -1343,533 +1425,532 @@ */ #ifdef HAVE_DEBUG_VIEW - if(Settings.showDebugInfo > 1) + if(pSettings->showDebugInfo > 1) { - Settings.showDebugInfo = 0; + pSettings->showDebugInfo = 0; corrections++; } #else - Settings.showDebugInfo = 0; + pSettings->showDebugInfo = 0; #endif /* uint8_t ButtonResponsiveness[4]; */ // Base value, index 3 - if(Settings.ButtonResponsiveness[3] < MIN_BUTTONRESPONSIVENESS_GUI) + if(pSettings->ButtonResponsiveness[3] < MIN_BUTTONRESPONSIVENESS_GUI) { - Settings.ButtonResponsiveness[3] = MIN_BUTTONRESPONSIVENESS_GUI; + pSettings->ButtonResponsiveness[3] = MIN_BUTTONRESPONSIVENESS_GUI; corrections++; setFirstCorrection(parameterId); } else - if(Settings.ButtonResponsiveness[3] > MAX_BUTTONRESPONSIVENESS_GUI) + if(pSettings->ButtonResponsiveness[3] > MAX_BUTTONRESPONSIVENESS_GUI) { - Settings.ButtonResponsiveness[3] = MAX_BUTTONRESPONSIVENESS_GUI; + pSettings->ButtonResponsiveness[3] = MAX_BUTTONRESPONSIVENESS_GUI; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 55 */ // flex values 0, 1, 2 for(int i=0; i<3;i++) { - if(Settings.ButtonResponsiveness[i] < MIN_BUTTONRESPONSIVENESS) // 50-10 //Fix for broken buttons. :) + if(pSettings->ButtonResponsiveness[i] < MIN_BUTTONRESPONSIVENESS) // 50-10 //Fix for broken buttons. :) { - Settings.ButtonResponsiveness[i] = MIN_BUTTONRESPONSIVENESS; + pSettings->ButtonResponsiveness[i] = MIN_BUTTONRESPONSIVENESS; corrections++; setFirstCorrection(parameterId); } else - if(Settings.ButtonResponsiveness[i] > MAX_BUTTONRESPONSIVENESS) // 110+20 + if(pSettings->ButtonResponsiveness[i] > MAX_BUTTONRESPONSIVENESS) // 110+20 { - Settings.ButtonResponsiveness[i] = MAX_BUTTONRESPONSIVENESS; + pSettings->ButtonResponsiveness[i] = MAX_BUTTONRESPONSIVENESS; corrections++; setFirstCorrection(parameterId); } } - parameterId++; + parameterId++; /* 56 */ /* uint8_t buttonBalance[3]; */ for(int i=0; i<3;i++) { - if(Settings.buttonBalance[i] < 2) // 2 = -10 + if(pSettings->buttonBalance[i] < 2) // 2 = -10 { - Settings.buttonBalance[i] = 2; + pSettings->buttonBalance[i] = 2; corrections++; setFirstCorrection(parameterId); } else - if(Settings.buttonBalance[i] > 5) // 3 = 0, 4 = +10, 5 = +20 + if(pSettings->buttonBalance[i] > 5) // 3 = 0, 4 = +10, 5 = +20 { - Settings.buttonBalance[i] = 5; + pSettings->buttonBalance[i] = 5; corrections++; setFirstCorrection(parameterId); } } - parameterId++; + parameterId++; /* 57 */ /* uint8_t nonMetricalSystem; */ - if(Settings.nonMetricalSystem > 1) + if(pSettings->nonMetricalSystem > 1) { - Settings.nonMetricalSystem = 1; + pSettings->nonMetricalSystem = 1; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 58 */ /* uint8_t fallbackToFixedSetpoint; */ - if(Settings.fallbackToFixedSetpoint > 1) + if(pSettings->fallbackToFixedSetpoint > 1) { - Settings.fallbackToFixedSetpoint = 1; + pSettings->fallbackToFixedSetpoint = 1; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 59 */ /* uint8_t bluetoothActive; */ - if(Settings.bluetoothActive > 1) + if(pSettings->bluetoothActive > 1) { - Settings.bluetoothActive = 1; + pSettings->bluetoothActive = 1; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 60 */ /* uint8_t safetystopDepth; */ - if(Settings.safetystopDepth > 6) + if(pSettings->safetystopDepth > 6) { - Settings.safetystopDepth = 6; + pSettings->safetystopDepth = 6; corrections++; setFirstCorrection(parameterId); } - parameterId++; - if(Settings.safetystopDepth < 3) + parameterId++; /* 61 */ + if(pSettings->safetystopDepth < 3) { - Settings.safetystopDepth = 3; + pSettings->safetystopDepth = 3; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 62 */ /* uint32_t updateSettingsAllowedFromHeader; */ /* uint8_t ppo2sensors_deactivated; */ - if(Settings.ppo2sensors_deactivated > (1+2+4)) + if(pSettings->ppo2sensors_deactivated > (1+2+4)) { - Settings.ppo2sensors_deactivated = 0; + pSettings->ppo2sensors_deactivated = 0; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 63 */ /* uint8_t tX_colorscheme; */ - if(Settings.tX_colorscheme > 3) + if(pSettings->tX_colorscheme > 3) { - Settings.tX_colorscheme = 0; + pSettings->tX_colorscheme = 0; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 64 */ /* uint8_t tX_userselectedLeftLowerCornerPrimary; */ - if(Settings.tX_userselectedLeftLowerCornerPrimary >= LLC_END) + if(pSettings->tX_userselectedLeftLowerCornerPrimary >= LLC_END) { - Settings.tX_userselectedLeftLowerCornerPrimary = LLC_Temperature; + pSettings->tX_userselectedLeftLowerCornerPrimary = LLC_Temperature; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 65 */ /* uint8_t tX_userselectedLeftLowerCornerTimeout; */ - if(Settings.tX_userselectedLeftLowerCornerTimeout > 60) + if(pSettings->tX_userselectedLeftLowerCornerTimeout > 60) { - Settings.tX_userselectedLeftLowerCornerTimeout = 0; + pSettings->tX_userselectedLeftLowerCornerTimeout = 0; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 66 */ /* uint8_t tX_customViewPrimary; */ - if(Settings.tX_customViewPrimary >= CVIEW_END) + if(pSettings->tX_customViewPrimary >= CVIEW_END) { - Settings.tX_customViewPrimary = 1; + pSettings->tX_customViewPrimary = 1; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 67 */ /* uint8_t tX_customViewTimeout; */ - if(Settings.tX_customViewTimeout > 60) + if(pSettings->tX_customViewTimeout > 60) { - Settings.tX_customViewTimeout = 0; + pSettings->tX_customViewTimeout = 0; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 68 */ /* uint8_t timeoutEnterButtonSelectDive; */ - if(Settings.timeoutEnterButtonSelectDive != 10) + if(pSettings->timeoutEnterButtonSelectDive != 10) { - Settings.timeoutEnterButtonSelectDive = 10; + pSettings->timeoutEnterButtonSelectDive = 10; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 69 */ /* uint8_t logbookOffset; */ - if(Settings.logbookOffset > 9000) + if(pSettings->logbookOffset > 9000) { - Settings.logbookOffset = 0; + pSettings->logbookOffset = 0; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 70 */ /* uint8_t alwaysShowPPO2; */ - if(Settings.alwaysShowPPO2 > 1) + if(pSettings->alwaysShowPPO2 > 1) { - Settings.alwaysShowPPO2 = 0; + pSettings->alwaysShowPPO2 = 0; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 71 */ /* uint8_t extraDisplay; */ - if(Settings.extraDisplay >= EXTRADISPLAY_END) + if(pSettings->extraDisplay >= EXTRADISPLAY_END) { - Settings.extraDisplay = EXTRADISPLAY_BIGFONT; + pSettings->extraDisplay = EXTRADISPLAY_BIGFONT; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 72 */ /* int8_t offsetPressure_mbar; */ - if((Settings.offsetPressure_mbar > PRESSURE_OFFSET_LIMIT_MBAR) || - (Settings.offsetPressure_mbar < -1 * PRESSURE_OFFSET_LIMIT_MBAR)) + if((pSettings->offsetPressure_mbar > PRESSURE_OFFSET_LIMIT_MBAR) || + (pSettings->offsetPressure_mbar < -1 * PRESSURE_OFFSET_LIMIT_MBAR)) { - Settings.offsetPressure_mbar = 0; + pSettings->offsetPressure_mbar = 0; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 73 */ /* int8_t offsetTemperature_centigrad; */ - if((Settings.offsetTemperature_centigrad > 20) || - (Settings.offsetTemperature_centigrad < -20)) + if((pSettings->offsetTemperature_centigrad > 20) || + (pSettings->offsetTemperature_centigrad < -20)) { - Settings.offsetTemperature_centigrad = 0; + pSettings->offsetTemperature_centigrad = 0; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 74 */ /* uint8_t gasConsumption_travel_l_min; */ - if((Settings.gasConsumption_travel_l_min < 5) || - (Settings.gasConsumption_travel_l_min > 50)) + if((pSettings->gasConsumption_travel_l_min < 5) || + (pSettings->gasConsumption_travel_l_min > 50)) { - Settings.gasConsumption_travel_l_min = 20; + pSettings->gasConsumption_travel_l_min = 20; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 75 */ /* uint8_t gasConsumption_bottom_l_min; */ - if((Settings.gasConsumption_bottom_l_min < 5) || - (Settings.gasConsumption_bottom_l_min > 50)) + if((pSettings->gasConsumption_bottom_l_min < 5) || + (pSettings->gasConsumption_bottom_l_min > 50)) { - Settings.gasConsumption_bottom_l_min = 20; + pSettings->gasConsumption_bottom_l_min = 20; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 76 */ /* uint8_t gasConsumption_deco_l_min; */ - if((Settings.gasConsumption_deco_l_min < 5) || - (Settings.gasConsumption_deco_l_min > 50)) + if((pSettings->gasConsumption_deco_l_min < 5) || + (pSettings->gasConsumption_deco_l_min > 50)) { - Settings.gasConsumption_deco_l_min = 20; + pSettings->gasConsumption_deco_l_min = 20; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 77 */ /* uint8_t showDebugInfo; */ #ifdef BOOT16 - Settings.showDebugInfo = 0; + pSettings->showDebugInfo = 0; #else - if(Settings.showDebugInfo > 1) - Settings.showDebugInfo = 0; + if(pSettings->showDebugInfo > 1) + pSettings->showDebugInfo = 0; #endif /* uint8_t selected_language; */ #ifdef BOOT16 - if(Settings.selected_language > 1) - Settings.selected_language = 0; + if(pSettings->selected_language > 1) + pSettings->selected_language = 0; #else - if(Settings.selected_language > 4) - Settings.selected_language = 0; + if(pSettings->selected_language > 4) + pSettings->selected_language = 0; #endif /* uint8_t display_toogle_desc; 1/10 seconds */ - if((Settings.display_toogle_desc < 20) || (Settings.display_toogle_desc > 600)) + if((pSettings->display_toogle_desc < 20) || (pSettings->display_toogle_desc > 600)) { - Settings.display_toogle_desc = SettingsStandard.display_toogle_desc; + pSettings->display_toogle_desc = SettingsStandard.display_toogle_desc; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 78 */ /* uint8_t debugModeOnStart; */ - if(Settings.debugModeOnStart > 1) + if(pSettings->debugModeOnStart > 1) { - Settings.debugModeOnStart = 0; + pSettings->debugModeOnStart = 0; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 79 */ /* uint8_t IAmStolenPleaseKillMe; */ if(hardwareDataGetPointer()->primarySerial == 90) - Settings.IAmStolenPleaseKillMe++; + pSettings->IAmStolenPleaseKillMe++; else - Settings.IAmStolenPleaseKillMe = 0; + pSettings->IAmStolenPleaseKillMe = 0; /* uint8_t debugModeOnStart; */ - if(Settings.compassBearing > 360) + if(pSettings->compassBearing > 360) { - Settings.compassBearing = 0; + pSettings->compassBearing = 0; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 80 */ /* uint8_t lastKnownBatteryPercentage; */ - if(Settings.lastKnownBatteryPercentage > 100) + if(pSettings->lastKnownBatteryPercentage > 100) { - Settings.lastKnownBatteryPercentage = 100; + pSettings->lastKnownBatteryPercentage = 100; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 81 */ /* uint8_t VPM_model */ - if((Settings.VPM_model != VPM_FROM_FORTRAN) && (Settings.VPM_model != VPM_BACHELORWORK)) + if((pSettings->VPM_model != VPM_FROM_FORTRAN) && (pSettings->VPM_model != VPM_BACHELORWORK)) { - Settings.VPM_model = VPM_FROM_FORTRAN; + pSettings->VPM_model = VPM_FROM_FORTRAN; corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 82 */ /* uint8_t Buehlmann_model */ - if((Settings.GF_model != BUEHLMANN_OSTC4) && (Settings.GF_model != BUEHLMANN_hwOS)) + if((pSettings->GF_model != BUEHLMANN_OSTC4) && (pSettings->GF_model != BUEHLMANN_hwOS)) { - Settings.GF_model = BUEHLMANN_OSTC4; + pSettings->GF_model = BUEHLMANN_OSTC4; corrections++; setFirstCorrection(parameterId); } - parameterId++; - if(Settings.FlipDisplay > 1) /* only boolean values allowed */ - { - Settings.FlipDisplay = 0; + parameterId++; /* 83 */ + if(pSettings->FlipDisplay > 1) /* only boolean values allowed */ + { + setFlipDisplay(1); corrections++; setFirstCorrection(parameterId); } - parameterId++; + parameterId++; /* 84 */ #ifdef ENABLE_MOTION_CONTROL - if(Settings.MotionDetection >= MOTION_DETECT_END) + if(pSettings->MotionDetection >= MOTION_DETECT_END) { - Settings.MotionDetection = MOTION_DETECT_OFF; + pSettings->MotionDetection = MOTION_DETECT_OFF; corrections++; setFirstCorrection(parameterId); } #else - Settings.MotionDetection = MOTION_DETECT_OFF; - Settings.viewPortMode = 0; - Settings.viewRoll = 0.0; - Settings.viewPitch = 0.0; - Settings.viewYaw = 0.0; + pSettings->MotionDetection = MOTION_DETECT_OFF; + pSettings->viewPortMode = 0; + pSettings->viewRoll = 0.0; + pSettings->viewPitch = 0.0; + pSettings->viewYaw = 0.0; #endif - parameterId++; - if(Settings.compassInertia > MAX_COMPASS_COMP) + parameterId++; /* 85 */ + if(pSettings->compassInertia > MAX_COMPASS_COMP) { - Settings.compassInertia = 0; + pSettings->compassInertia = 0; corrections++; setFirstCorrection(parameterId); } - parameterId++; - if(Settings.tX_customViewPrimaryBF > CVIEW_T3_END) + parameterId++; /* 86 */ + if(pSettings->tX_customViewPrimaryBF > CVIEW_T3_END) { - Settings.tX_customViewPrimaryBF = CVIEW_T3_Decostop; + pSettings->tX_customViewPrimaryBF = CVIEW_T3_Decostop; corrections++; setFirstCorrection(parameterId); } - parameterId++; - if(Settings.viewPortMode > MAX_VIEWPORT_MODE) + parameterId++; /* 87 */ + if(pSettings->viewPortMode > MAX_VIEWPORT_MODE) { - Settings.viewPortMode = 0; + pSettings->viewPortMode = 0; corrections++; setFirstCorrection(parameterId); } - parameterId++; - if(Settings.ppo2sensors_source >= O2_SENSOR_SOURCE_MAX) + parameterId++; /* 88 */ + if(pSettings->ppo2sensors_source >= O2_SENSOR_SOURCE_MAX) { - Settings.ppo2sensors_source = O2_SENSOR_SOURCE_OPTIC; - Settings.ppo2sensors_calibCoeff[0] = 0.0; - Settings.ppo2sensors_calibCoeff[1] = 0.0; - Settings.ppo2sensors_calibCoeff[2] = 0.0; + pSettings->ppo2sensors_source = O2_SENSOR_SOURCE_OPTIC; + pSettings->ppo2sensors_calibCoeff[0] = 0.0; + pSettings->ppo2sensors_calibCoeff[1] = 0.0; + pSettings->ppo2sensors_calibCoeff[2] = 0.0; corrections++; setFirstCorrection(parameterId); } - parameterId++; - if(Settings.amPMTime > 1) /* only boolean values allowed */ + parameterId++; /* 89 */ + if(pSettings->amPMTime > 1) /* only boolean values allowed */ { - Settings.amPMTime = 0; + pSettings->amPMTime = 0; corrections++; setFirstCorrection(parameterId); } - parameterId++; - if(Settings.autoSetpoint > 1) /* only boolean values allowed */ + parameterId++; /* 90 */ + if(pSettings->autoSetpoint > 1) /* only boolean values allowed */ { - Settings.autoSetpoint = 0; + pSettings->autoSetpoint = 0; corrections++; setFirstCorrection(parameterId); } - parameterId++; - if(Settings.scubberActiveId > 1) + parameterId++; /* 91 */ + if (pSettings->scrubberActiveId > 0x03) { + /* scrubber active is used as bitfield => two timer => 2 bits in use */ + pSettings->scrubberActiveId = 0x00; + corrections++; + setFirstCorrection(parameterId); + } + parameterId++; /* 92 */ + if((pSettings->scrubberData[0].TimerMax > MAX_SCRUBBER_TIME) || pSettings->scrubberData[0].TimerCur < MIN_SCRUBBER_TIME || pSettings->scrubberData[0].TimerCur > (int16_t)MAX_SCRUBBER_TIME) { - Settings.scubberActiveId = 0; - corrections++; - setFirstCorrection(parameterId); - } - parameterId++; - if((Settings.scrubberData[0].TimerMax > MAX_SCRUBBER_TIME) || Settings.scrubberData[0].TimerCur < MIN_SCRUBBER_TIME || Settings.scrubberData[0].TimerCur > (int16_t)MAX_SCRUBBER_TIME) - { - Settings.scrubberData[0].TimerMax = 0; - Settings.scrubberData[0].TimerCur = 0; + pSettings->scrubberData[0].TimerMax = 0; + pSettings->scrubberData[0].TimerCur = 0; corrections++; setFirstCorrection(parameterId); } - parameterId++; - if((Settings.scrubberData[1].TimerMax > MAX_SCRUBBER_TIME) || Settings.scrubberData[1].TimerCur < MIN_SCRUBBER_TIME || Settings.scrubberData[1].TimerCur > (int16_t)MAX_SCRUBBER_TIME) + parameterId++; /* 93 */ + if((pSettings->scrubberData[1].TimerMax > MAX_SCRUBBER_TIME) || pSettings->scrubberData[1].TimerCur < MIN_SCRUBBER_TIME || pSettings->scrubberData[1].TimerCur > (int16_t)MAX_SCRUBBER_TIME) { - Settings.scrubberData[1].TimerMax = 0; - Settings.scrubberData[1].TimerCur = 0; + pSettings->scrubberData[1].TimerMax = 0; + pSettings->scrubberData[1].TimerCur = 0; corrections++; setFirstCorrection(parameterId); } - parameterId++; - if(Settings.scrubTimerMode > SCRUB_TIMER_END) - { - Settings.scrubTimerMode = SCRUB_TIMER_OFF; + parameterId++; /* 94 */ + if (pSettings->scrubTimerMode == INVALID_SCRUB_TIMER_OFF || pSettings->scrubTimerMode > SCRUB_TIMER_END) { + pSettings->scrubTimerMode = SCRUB_TIMER_MINUTES; corrections++; setFirstCorrection(parameterId); } - parameterId++; - if((Settings.pscr_lung_ratio > PSCR_MAX_LUNG_RATIO) || (Settings.pscr_lung_ratio < PSCR_MIN_LUNG_RATIO)) + parameterId++; /* 95 */ + if((pSettings->pscr_lung_ratio > PSCR_MAX_LUNG_RATIO) || (pSettings->pscr_lung_ratio < PSCR_MIN_LUNG_RATIO)) { - Settings.pscr_lung_ratio = 10; + pSettings->pscr_lung_ratio = 10; corrections++; setFirstCorrection(parameterId); } - parameterId++; - if(Settings.pscr_o2_drop > PSCR_MAX_O2_DROP) + parameterId++; /* 96 */ + if(pSettings->pscr_o2_drop > PSCR_MAX_O2_DROP) { - Settings.pscr_o2_drop = 4; + pSettings->pscr_o2_drop = 4; corrections++; setFirstCorrection(parameterId); } - parameterId++; - if(Settings.co2_sensor_active > 1) + parameterId++; /* 97 */ + if(pSettings->co2_sensor_active > 1) { - Settings.co2_sensor_active = 0; + pSettings->co2_sensor_active = 0; corrections++; setFirstCorrection(parameterId); } - parameterId++; - if(Settings.ext_uart_protocol > UART_MAX_PROTOCOL) + parameterId++; /* 98 */ + if(pSettings->ext_uart_protocol > UART_MAX_PROTOCOL) { - Settings.ext_uart_protocol = 0; + pSettings->ext_uart_protocol = 0; corrections++; setFirstCorrection(parameterId); } - parameterId++; - if((Settings.ext_sensor_map[0] >= SENSOR_END) - || (Settings.ext_sensor_map[1] >= SENSOR_END) - || (Settings.ext_sensor_map[2] >= SENSOR_END) - || (Settings.ext_sensor_map[3] >= SENSOR_END) - || (Settings.ext_sensor_map[4] >= SENSOR_END) - || (Settings.ext_sensor_map[5] >= SENSOR_END) - || (Settings.ext_sensor_map[6] >= SENSOR_END) - || (Settings.ext_sensor_map[7] >= SENSOR_END)) + parameterId++; /* 99 */ + if((pSettings->ext_sensor_map[0] >= SENSOR_END) + || (pSettings->ext_sensor_map[1] >= SENSOR_END) + || (pSettings->ext_sensor_map[2] >= SENSOR_END) + || (pSettings->ext_sensor_map[3] >= SENSOR_END) + || (pSettings->ext_sensor_map[4] >= SENSOR_END) + || (pSettings->ext_sensor_map[5] >= SENSOR_END) + || (pSettings->ext_sensor_map[6] >= SENSOR_END) + || (pSettings->ext_sensor_map[7] >= SENSOR_END)) { - Settings.ext_sensor_map[0] = SENSOR_OPTIC; - Settings.ext_sensor_map[1] = SENSOR_OPTIC; - Settings.ext_sensor_map[2] = SENSOR_OPTIC; - Settings.ext_sensor_map[3] = SENSOR_NONE; - Settings.ext_sensor_map[4] = SENSOR_NONE; - Settings.ext_sensor_map[5] = SENSOR_NONE; - Settings.ext_sensor_map[6] = SENSOR_NONE; - Settings.ext_sensor_map[7] = SENSOR_NONE; + pSettings->ext_sensor_map[0] = SENSOR_OPTIC; + pSettings->ext_sensor_map[1] = SENSOR_OPTIC; + pSettings->ext_sensor_map[2] = SENSOR_OPTIC; + pSettings->ext_sensor_map[3] = SENSOR_NONE; + pSettings->ext_sensor_map[4] = SENSOR_NONE; + pSettings->ext_sensor_map[5] = SENSOR_NONE; + pSettings->ext_sensor_map[6] = SENSOR_NONE; + pSettings->ext_sensor_map[7] = SENSOR_NONE; corrections++; setFirstCorrection(parameterId); } - parameterId++; - if(Settings.buttonLockActive > 1) + parameterId++; /* 100 */ + if(pSettings->buttonLockActive > 1) { - Settings.buttonLockActive = 1; + pSettings->buttonLockActive = 1; corrections++; setFirstCorrection(parameterId); } - parameterId++; - if (Settings.compassDeclinationDeg > 99) { - Settings.compassDeclinationDeg = 99; + parameterId++; /* 101 */ + if (pSettings->compassDeclinationDeg > MAX_COMPASS_DECLINATION_DEG) { + pSettings->compassDeclinationDeg = MAX_COMPASS_DECLINATION_DEG; corrections++; setFirstCorrection(parameterId); - } else if (Settings.compassDeclinationDeg < -99) { - Settings.compassDeclinationDeg = -99; + } else if (pSettings->compassDeclinationDeg < -MAX_COMPASS_DECLINATION_DEG) { + pSettings->compassDeclinationDeg = -MAX_COMPASS_DECLINATION_DEG; corrections++; setFirstCorrection(parameterId); } - parameterId++; - if (Settings.timerDurationS > 599) { - Settings.timerDurationS = 599; + parameterId++; /* 102 */ + if (pSettings->timerDurationS > 599) { + pSettings->timerDurationS = 599; corrections++; setFirstCorrection(parameterId); - } else if (Settings.timerDurationS < 1) { - Settings.timerDurationS = 1; + } else if (pSettings->timerDurationS < 1) { + pSettings->timerDurationS = 1; corrections++; setFirstCorrection(parameterId); } - parameterId++; - if(Settings.cvAutofocus > 1) + parameterId++; /* 103 */ + if(pSettings->cvAutofocus > 1) { corrections++; - Settings.cvAutofocus = 0; + pSettings->cvAutofocus = 0; } - parameterId++; - if((Settings.timeZone.hours > 14) - || (Settings.timeZone.hours < -12) - || (Settings.timeZone.minutes > 45)) + parameterId++; /* 104 */ + if((pSettings->timeZone.hours > 14) + || (pSettings->timeZone.hours < -12) + || (pSettings->timeZone.minutes > 45)) { - Settings.timeZone.hours = 0; - Settings.timeZone.minutes = 0; + pSettings->timeZone.hours = 0; + pSettings->timeZone.minutes = 0; corrections++; } - parameterId++; + parameterId++; /* 105 */ if(corrections) { settingsWarning = 1; @@ -1893,6 +1974,7 @@ } +#if 0 #ifndef SPECIALPROGRAMM const SHardwareData* hardwareDataGetPointer(void) { @@ -1900,6 +1982,7 @@ } #endif #endif +#endif const SSettings* settingsGetPointerStandard(void) { return &SettingsStandard; @@ -1934,7 +2017,17 @@ { return &Settings; } +SSettings* profileGetPointer(uint8_t number) +{ + SSettings* returnPointer = NULL; + if(number < NUMBER_OF_PROFILES) + { + returnPointer = &Profile[number]; + } + + return returnPointer; +} // =============================================================================== // set_settings_to_Standard @@ -1948,28 +2041,70 @@ /// 160622 added lastDiveLogIdBackup /// // =============================================================================== -void set_settings_to_Standard(void) +void set_settings_to_Standard(uint8_t whichSettings) { SSettings *pSettings; const SSettings *pSettingsStandard; uint16_t personalDiveCountBackup; uint8_t lastDiveLogIdBackup; + uint32_t sampleStartBackup; pSettings = settingsGetPointer(); pSettingsStandard = settingsGetPointerStandard(); + uint8_t profileBackup = pSettings->activeProfile; + + switch(whichSettings) + { + default: + case EF_SETTINGS: + break; + case EF_PROFILE0: pSettings = profileGetPointer(0); + break; + case EF_PROFILE1: pSettings = profileGetPointer(1); + break; + case EF_PROFILE2: pSettings = profileGetPointer(2); + break; + case EF_PROFILE3: pSettings = profileGetPointer(3); + break; + } personalDiveCountBackup = pSettings->personalDiveCount; lastDiveLogIdBackup = pSettings->lastDiveLogId; + sampleStartBackup = pSettings->logFlashNextSampleStartAddress; + memcpy(pSettings,pSettingsStandard,sizeof(*pSettings)); pSettings->personalDiveCount = personalDiveCountBackup; pSettings->lastDiveLogId = lastDiveLogIdBackup; + pSettings->logFlashNextSampleStartAddress = sampleStartBackup; pSettings->firmwareVersion[0] = firmware_FirmwareData.versionFirst; pSettings->firmwareVersion[1] = firmware_FirmwareData.versionSecond; pSettings->firmwareVersion[2] = firmware_FirmwareData.versionThird; pSettings->firmwareVersion[3] = firmware_FirmwareData.versionBeta; - set_new_settings_missing_in_ext_flash(); - check_and_correct_settings(); + memset(pSettings->customtext,0,60); + sprintf(pSettings->customtext," <your name>\n <address>"); + pSettings->cv_configuration &= ~(1 << CVIEW_sensors | 1 << CVIEW_sensors_mV | 1 << CVIEW_Timer); + + switch(whichSettings) /* some default data may be dependend on the default value => adapt setting */ + { + default: + case EF_SETTINGS: pSettings->activeProfile = profileBackup; + break; + case EF_PROFILE0: pSettings = profileGetPointer(0); + break; + case EF_PROFILE1: pSettings = profileGetPointer(1); + break; + case EF_PROFILE2: pSettings = profileGetPointer(2); /* MCCR */ + pSettings->dive_mode = DIVEMODE_CCR; + break; + case EF_PROFILE3: pSettings = profileGetPointer(3); /* ECCR */ + pSettings->dive_mode = DIVEMODE_CCR; + pSettings->CCR_Mode = CCRMODE_Sensors; + break; + } + + set_new_settings_missing_in_ext_flash(whichSettings); + check_and_correct_settings(whichSettings); // has to be called too: createDiveSettings(); } @@ -2120,6 +2255,13 @@ return 0; } +bool checkValueSigned(int8_t value, int8_t from, int8_t to) +{ + if(value >= from && value <= to) + return true; + return false; +} + uint8_t writeData(uint8_t * data) { uint32_t newSensitivity; @@ -2256,7 +2398,11 @@ Settings.date_format = data[1]; break; case 0x34: + if (!checkValueSigned(data[1], -MAX_COMPASS_DECLINATION_DEG, MAX_COMPASS_DECLINATION_DEG)) return ERROR_; + Settings.compassDeclinationDeg = (int8_t)data[1]; + + break; case 0x35: if(data[1] & 0x80) { @@ -2288,7 +2434,11 @@ Settings.fallbackToFixedSetpoint = data[1]; break; case 0x39: + if (!checkValue(data[1], 0, 1)) return ERROR_; + setFlipDisplay(data[1]); + + break; case 0x3A: if(!checkValue(data[1],70,110)) return ERROR_; @@ -2617,10 +2767,10 @@ break; case 0x34: - data[datacounter++] = PARAM_UNKNOWN ; - data[datacounter++] = 0; - data[datacounter++] = 0; // compass gain, is unknown,, settingsGetPointerStandard()->; - data[datacounter++] = 0; + data[datacounter++] = PARAM_SINT; + data[datacounter++] = (uint8_t)-MAX_COMPASS_DECLINATION_DEG; + data[datacounter++] = (uint8_t)settingsGetPointerStandard()->compassDeclinationDeg; + data[datacounter++] = MAX_COMPASS_DECLINATION_DEG; break; case 0x35: @@ -2660,8 +2810,8 @@ case 0x39: data[datacounter++] = PARAM_BOOL; data[datacounter++] = 0; - data[datacounter++] = 0; // flipscreen, not yet :-) settingsGetPointerStandard()->; - data[datacounter++] = 0; + data[datacounter++] = settingsGetPointerStandard()->FlipDisplay; + data[datacounter++] = 1; break; case 0x3A: @@ -2921,7 +3071,7 @@ data[0] = Settings.date_format; break; case 0x34: - data[0] = 7; // gain should be always 7 as far as I understand the code in RTE + data[0] = (uint8_t)Settings.compassDeclinationDeg; break; case 0x35: data[0] = Settings.offsetPressure_mbar; @@ -2939,7 +3089,7 @@ data[0] = Settings.fallbackToFixedSetpoint; break; case 0x39: - data[0] = 0; // flip screen + data[0] = Settings.FlipDisplay; break; case 0x3A: data[0] = Settings.ButtonResponsiveness[3]; @@ -3344,7 +3494,27 @@ { settingsWarning = 0; } + inline uint8_t isSettingsWarning() { return settingsWarning; } + +bool isScrubberError(const SScrubberData *scrubberData) +{ + if (scrubberData->TimerCur <= SCRUBBER_ERROR_TIME) { + return true; + } + + return false; +} + +bool isScrubberWarning(const SScrubberData *scrubberData) +{ + if (scrubberData->TimerCur <= SCRUBBER_WARNING_TIME) { + return true; + } + + return false; +} +
--- a/Discovery/Src/show_logbook.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Src/show_logbook.c Sat Nov 15 19:29:44 2025 +0100 @@ -455,7 +455,7 @@ #endif uint16_t dataLength = 0; - dataLength = logbook_readSampleData(StepBackwards, 1000, depthdata,gasdata, tempdata, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tankdata, &posCoord, NULL); + dataLength = logbook_readSampleData(StepBackwards, 1000, depthdata,gasdata, tempdata, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tankdata, NULL, &posCoord, NULL, NULL); //Print Date uint8_t year = logbookHeader.dateYear; @@ -466,7 +466,7 @@ Gfx_write_label_var(hgfx, 30, 250,10, &FontT42,CLUT_GasSensor1,text); -#if defined ENABLE_GNSS_SUPPORT || defined ENABLE_GPIO_V2 +#if defined ENABLE_GNSS_INTERN || defined ENABLE_GNSS_EXTERN if((posCoord.fLat != 0.0) || (posCoord.fLon != 0.0)) { snprintf(text, 20, "%2.4f - %2.4f", posCoord.fLat, posCoord.fLon ); @@ -752,7 +752,7 @@ uint16_t decoDepthdata[1000]; uint16_t *pDecoDepthData = 0; - dataLength = logbook_readSampleData(StepBackwards, 1000, depthdata,gasdata, tempdata, NULL, NULL, NULL, NULL, NULL, NULL, NULL, decoDepthdata, NULL, NULL, NULL); + dataLength = logbook_readSampleData(StepBackwards, 1000, depthdata,gasdata, tempdata, NULL, NULL, NULL, NULL, NULL, NULL, NULL, decoDepthdata, NULL, NULL, NULL, NULL, NULL); for(int i = 0; i<dataLength; i++) { @@ -897,6 +897,7 @@ releaseFrame(17,tLOGbackground.FBStartAdress); } +#define MSG_LENGTH 30 static void show_logbook_logbook_show_log_page3(GFX_DrawCfgScreen *hgfx, uint8_t StepBackwards) { @@ -917,9 +918,9 @@ uint16_t dataLength = 0; uint16_t depthdata[1000]; uint8_t gasdata[1000]; - dataLength = logbook_readSampleData(StepBackwards, 1000, depthdata,gasdata, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + dataLength = logbook_readSampleData(StepBackwards, 1000, depthdata,gasdata, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - char msg[15]; + char msg[MSG_LENGTH]; char gas_name[15]; int j = 0; @@ -979,18 +980,18 @@ 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); + snprintf(msg, MSG_LENGTH, "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); + snprintf(msg, MSG_LENGTH, "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); + snprintf(msg, MSG_LENGTH, "G%d: %s", index + 1, gas_name); } Gfx_write_label_var(hgfx, winsmal.left, winsmal.right,winsmal.top, &FontT24,color,msg); } @@ -1047,15 +1048,15 @@ if(!isLoopMode(logbookHeader.diveMode)) - dataLength = logbook_readSampleData(StepBackwards, 1000, depthdata,gasdata, NULL, ppO2data, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + dataLength = logbook_readSampleData(StepBackwards, 1000, depthdata,gasdata, NULL, ppO2data, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); else { 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, NULL); + default: dataLength = logbook_readSampleData(StepBackwards, 1000, depthdata, gasdata, NULL, NULL, setpoint, NULL, NULL, NULL, 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, NULL); + case CCRMODE_Sensors: dataLength = logbook_readSampleData(StepBackwards, 1000, depthdata, gasdata, NULL, NULL, NULL, sensor1, sensor2, sensor3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); if(!check_data_array_empty(sensor1)) { sensorDataAvailable[0] = 1; @@ -1072,22 +1073,22 @@ { if(sensorDataAvailable[0] == 0) { - logbook_readSampleData(StepBackwards, 1000, depthdata,gasdata, NULL, sensor1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + logbook_readSampleData(StepBackwards, 1000, depthdata,gasdata, NULL, sensor1, NULL, NULL, NULL, 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, NULL); + logbook_readSampleData(StepBackwards, 1000, depthdata,gasdata, NULL, sensor2, NULL, NULL, NULL, 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, NULL); + logbook_readSampleData(StepBackwards, 1000, depthdata,gasdata, NULL, sensor3, NULL, NULL, NULL, 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, NULL); + case CCRMODE_Simulation: dataLength = logbook_readSampleData(StepBackwards, 1000, depthdata,gasdata, NULL, ppO2data, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); break; } }
--- a/Discovery/Src/simulation.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Src/simulation.c Sat Nov 15 19:29:44 2025 +0100 @@ -43,6 +43,7 @@ #include "vpm.h" #include "buehlmann.h" #include "logbook_miniLive.h" +#include "logbook.h" #include "configuration.h" @@ -111,7 +112,8 @@ stateSim.lifeData.apnea_total_max_depth_meter = 0; - memcpy(stateSim.scrubberDataDive, settingsGetPointer()->scrubberData, sizeof(stateSim.scrubberDataDive)); + SSettings *settings = settingsGetPointer(); + memcpy(stateSim.scrubberDataDive, settings->scrubberData, sizeof(stateSim.scrubberDataDive)); memset(simSensmVOffset,0,sizeof(simSensmVOffset)); if(getReplayOffset() != 0xFFFF) { @@ -244,21 +246,35 @@ pDiveState->lifeData.ascent_rate_meter_per_min = 0; } - if((pSettings->scrubTimerMode != SCRUB_TIMER_OFF) && (isLoopMode(pSettings->dive_mode)) && (pDiveState->mode == MODE_DIVE) && isLoopMode(pDiveState->diveSettings.diveMode)) - { - simScrubberTimeoutCount++; - if(simScrubberTimeoutCount >= 60) /* resolution is minutes */ - { - simScrubberTimeoutCount = 0; - if(pDiveState->scrubberDataDive[pSettings->scubberActiveId].TimerCur > MIN_SCRUBBER_TIME) - { - pDiveState->scrubberDataDive[pSettings->scubberActiveId].TimerCur--; - } - translateDate(stateUsed->lifeData.dateBinaryFormat, &pDiveState->scrubberDataDive[pSettings->scubberActiveId].lastDive); - } + if (isScrubberTimerRunning(pDiveState, pSettings)) { + simScrubberTimeoutCount++; + + if (simScrubberTimeoutCount >= 60) { + /* resolution is minutes */ + simScrubberTimeoutCount = 0; + + int16_t maxScrubberTime = INT16_MIN; + SScrubberData *longestScrubberData = NULL; + for (unsigned timerId = 0; timerId < 2; timerId++) { + if (pSettings->scrubberActiveId & (1 << timerId)) { + SScrubberData *scrubberData = &pDiveState->scrubberDataDive[timerId]; + if (scrubberData->TimerCur > MIN_SCRUBBER_TIME) { + scrubberData->TimerCur--; + } + + if (scrubberData->TimerCur > maxScrubberTime) { + maxScrubberTime = scrubberData->TimerCur; + longestScrubberData = scrubberData; + } + + translateDate(stateUsed->lifeData.dateBinaryFormat, &scrubberData->lastDive); + } + } + + logScrubberState(longestScrubberData); + } } - if(lastPressure_bar > 0) { //1 second * 60 == 1 minute, bar * 10 = meter
--- a/Discovery/Src/stm32f4xx_hal_msp_hw2.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Src/stm32f4xx_hal_msp_hw2.c Sat Nov 15 19:29:44 2025 +0100 @@ -630,18 +630,20 @@ /* USER CODE END USART3_MspInit 0 */ /* Peripheral clock enable */ - __USART3_CLK_ENABLE(); + USART_RADIO_RX_GPIO_CLK_ENABLE(); /**USART3 GPIO Configuration - PC10 ------> USART3_TX - PC11 ------> USART3_RX + PB11 ------> USART3_RX */ - GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11; + GPIO_InitStruct.Pin = USART_RADIO_RX_PIN; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_LOW; - GPIO_InitStruct.Alternate = GPIO_AF7_USART3; - HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + GPIO_InitStruct.Alternate = USART_RADIO_RX_AF; + HAL_GPIO_Init(USART_RADIO_RX_GPIO_PORT, &GPIO_InitStruct); + + HAL_NVIC_SetPriority(USART_RADIO_IRQn, 0, 1); + HAL_NVIC_EnableIRQ(USART_RADIO_IRQn); /* USER CODE BEGIN USART3_MspInit 1 */ @@ -706,7 +708,7 @@ PC10 ------> USART3_TX PC11 ------> USART3_RX */ - HAL_GPIO_DeInit(GPIOC, GPIO_PIN_10|GPIO_PIN_11); + HAL_GPIO_DeInit(USART_RADIO_RX_GPIO_PORT, USART_RADIO_RX_PIN); /* USER CODE BEGIN USART3_MspDeInit 1 */
--- a/Discovery/Src/t3.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Src/t3.c Sat Nov 15 19:29:44 2025 +0100 @@ -33,6 +33,7 @@ #include "t3.h" #include "data_exchange_main.h" +#include "settings.h" #include "decom.h" #include "gfx_fonts.h" #include "math.h" @@ -536,13 +537,13 @@ else { color = 0xff; - if((pSettings->slowExitTime != 0) && (nextstopDepthMeter == 0) && (stateUsed->lifeData.depth_meter < pSettings->last_stop_depth_meter)) + if((pSettings->slowExitTime != 0) && (nextstopDepthMeter == 0) && (stateUsed->lifeData.depth_meter < pSettings->last_stop_depth_meter) && (stateUsed->lifeData.depth_meter > 0.3)) { color = t3_drawSlowExitGraph(tXscreen, tXl1, tXr1); } if(color == 0xff) /* no slow exit => continue with common ascent graph */ { - if(stateUsed->lifeData.ascent_rate_meter_per_min > 0) /* ascentrate graph -standard mode */ + if(stateUsed->lifeData.ascent_rate_meter_per_min > 0) /* ascent rate graph -standard mode */ { if(!pSettings->FlipDisplay) { @@ -769,7 +770,7 @@ else { t3_refresh_customview(depth_meter); - requestBuzzerActivation(0); + requestBuzzerActivation(REQUEST_BUZZER_OFF); } if(stateUsed->warnings.lowBattery) t3_basics_battery_low_customview_extra(&t3r1); //t3c1); @@ -1334,14 +1335,13 @@ GFX_write_string(&FontT105,tXc1,text,1); } - if((pSettings->scrubTimerMode != SCRUB_TIMER_OFF) && isLoopMode(pSettings->dive_mode)) - { + if (isScrubberTimerEnabled(pSettings)) { snprintf(text,TEXTSIZE,"\032\002\f%c",TXT_ScrubTime); GFX_write_string(&FontT42,tXc1,text,0); textpointer = 0; text[textpointer++] = '\002'; - textpointer += printScrubberText(&text[textpointer], 10, stateUsed->scrubberDataDive, pSettings); + textpointer += printScrubberText(&text[textpointer], 10, stateUsed->scrubberDataDive, pSettings, false); GFX_write_string(&FontT105,tXc1,text,1); } } @@ -1687,7 +1687,7 @@ { GFX_write_string(&FontT48,&t3c2,text,0); } - requestBuzzerActivation(1); + requestBuzzerActivation(REQUEST_BUZZER_CONTINUOUS); } uint8_t t3_customview_disabled(uint8_t view) @@ -1996,21 +1996,46 @@ return t3_selection_customview; } -int printScrubberText(char *text, size_t size, const SScrubberData *scrubberData, SSettings *settings) +unsigned printScrubberText(char *text, size_t size, const SScrubberData scrubberData[], const SSettings *settings, bool useTwoLines) { - int16_t currentTimerMinutes = scrubberData[settings->scubberActiveId].TimerCur; - char colour = '\020'; - if (currentTimerMinutes <= 0) { - colour = '\025'; - } else if (currentTimerMinutes <= 30) { - colour = '\024'; + unsigned textIndex = 0; + for (unsigned timerId = 0; timerId < 2; timerId++) { + if (settings->scrubberActiveId & (1 << timerId)) { + const SScrubberData *currentScrubberData = &scrubberData[timerId]; + char colour = '\020'; + if (isScrubberError(currentScrubberData)) { + colour = '\025'; + } else if (isScrubberWarning(currentScrubberData)) { + colour = '\024'; + } + + if (useTwoLines) { + textIndex += snprintf(&text[textIndex], size, "\016\016"); + } + + int16_t currentTimerMinutes = currentScrubberData->TimerCur; + if (settings->scrubTimerMode == SCRUB_TIMER_MINUTES || currentTimerMinutes < 0) { + textIndex += snprintf(&text[textIndex], size, "%c%3i'", colour, currentTimerMinutes); + } else { + if (useTwoLines) { + textIndex += snprintf(&text[textIndex], size, "%c%u%%", colour, currentTimerMinutes * 100 / settings->scrubberData[timerId].TimerMax); + } else { + textIndex += snprintf(&text[textIndex], size, "%c%u\016\016%%\017", colour, currentTimerMinutes * 100 / settings->scrubberData[timerId].TimerMax); + } + } + + if (settings->scrubberActiveId == 0x03 && timerId == 0) { + /* both timers are active => print separator */ + if (useTwoLines) { + textIndex += snprintf(&text[textIndex], size, "\r\n"); + } else { + textIndex += snprintf(&text[textIndex], size, "\020|"); + } + } + } } - if (settings->scrubTimerMode == SCRUB_TIMER_MINUTES || currentTimerMinutes < 0) { - return snprintf(text, size, "%c%3i'", colour, currentTimerMinutes); - } else { - return snprintf(text, size, "%c%u\016\016%%\017", colour, currentTimerMinutes * 100 / settingsGetPointer()->scrubberData[settings->scubberActiveId].TimerMax); - } + return textIndex; } void t3_AF_updateBorderConditions()
--- a/Discovery/Src/t7.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Src/t7.c Sat Nov 15 19:29:44 2025 +0100 @@ -139,7 +139,7 @@ CVIEW_Charger, CVIEW_CcrSummary, CVIEW_Timer, -#if defined ENABLE_GPIO_V2 || defined ENABLE_GNSS_SUPPORT +#if defined ENABLE_GNSS_INTERN || defined ENABLE_GNSS_EXTERN CVIEW_Position, #endif CVIEW_END @@ -705,9 +705,9 @@ static float debounceAmbientPressure = 0; static uint8_t lastChargeStatus = 0; static float lastTemperature = 100.0; - char text[256]; - char timeSuffix; - uint8_t hours; + char text[200]; + char tmpString[20]; + uint8_t loop, textIdx; uint8_t date[3], year,month,day; uint32_t color; @@ -795,53 +795,20 @@ dateNotSet = 1; else dateNotSet = 0; -/* - if(Stime.Seconds % 2) - snprintf(text,255,"\001%02d:%02d",Stime.Hours,Stime.Minutes); - else - snprintf(text,255,"\001%02d\031:\020%02d",Stime.Hours,Stime.Minutes); - GFX_write_string(&FontT54,&t7surfaceR,text,3); -*/ -// debug version: - - if (settingsGetPointer()->amPMTime) + + + + if((dateNotSet) && (Stime.Seconds % 2 == 0)) { - if (Stime.Hours > 11) - { - timeSuffix = 'P'; - } - else - { - timeSuffix = 'A'; - } - - if (Stime.Hours % 12 == 0) - { - hours = 12; - } - else - { - hours = (Stime.Hours % 12); - } - - if(Stime.Seconds % 2) - snprintf(text,255,"\001%02d:%02d:%02d\016\016%cM\017",hours,Stime.Minutes,Stime.Seconds,timeSuffix); - else if(dateNotSet) - snprintf(text,255,"\001\031%02d:%02d:%02d\016\016%cM\017\020",hours,Stime.Minutes,Stime.Seconds,timeSuffix); - else - snprintf(text,255,"\001%02d\031:\020%02d:%02d\016\016%cM\017",hours,Stime.Minutes,Stime.Seconds,timeSuffix); - GFX_write_string(&FontT48,&t7surfaceR,text,3); + formatStringOfTime(tmpString,20,Stime,0,1); + snprintf(text,100,"\031\001%s",tmpString); } else { - if(Stime.Seconds % 2) - snprintf(text,255,"\001%02d:%02d:%02d",Stime.Hours,Stime.Minutes,Stime.Seconds); - else if(dateNotSet) - snprintf(text,255,"\001\031%02d:%02d:%02d\020",Stime.Hours,Stime.Minutes,Stime.Seconds); - else - snprintf(text,255,"\001%02d\031:\020%02d:%02d",Stime.Hours,Stime.Minutes,Stime.Seconds); - GFX_write_string(&FontT54,&t7surfaceR,text,3); + formatStringOfTime(tmpString,20,Stime,1,1); + snprintf(text,100,"\030\001%s",tmpString); } + GFX_write_string(&FontT48,&t7surfaceR,text,3); if(settingsGetPointer()->date_format == DDMMYY) { @@ -1065,6 +1032,7 @@ else { textIdx = 0; + if(isLoopMode(stateUsed->diveSettings.diveMode)) gasOffset = NUM_OFFSET_DILUENT; else @@ -1095,9 +1063,23 @@ text[textIdx++] = 10; } text[textIdx++] = 0; + if(!pSettings->FlipDisplay) + { + t7surfaceL.WindowX0 +=5; + } + else + { + t7surfaceL.WindowX1 -=2; + } GFX_write_string(&FontT48,&t7surfaceL,text,6); - - + if(!pSettings->FlipDisplay) + { + t7surfaceL.WindowX0 -=5; + } + else + { + t7surfaceL.WindowX1 +=2; + } oxygen_percentage = 100; oxygen_percentage -= stateUsed->lifeData.actualGas.nitrogen_percentage; oxygen_percentage -= stateUsed->lifeData.actualGas.helium_percentage; @@ -1121,7 +1103,7 @@ if(!pSettings->FlipDisplay) { start.y = t7surfaceL.WindowY0 + (3 * t7surfaceL.WindowLineSpacing); - start.x = t7surfaceL.WindowX0 + ((stateUsed->lifeData.actualGas.GasIdInSettings - gasOffset - 1) * 35); + start.x = t7surfaceL.WindowX0 + ((stateUsed->lifeData.actualGas.GasIdInSettings - gasOffset - 1) * 35) + 2; } else { @@ -1129,7 +1111,7 @@ start.x = t7surfaceR.WindowX0 + ((stateUsed->lifeData.actualGas.GasIdInSettings - gasOffset - 1) * 35); } - stop.x = start.x + 25; + stop.x = start.x + 29; stop.y = start.y + 52; GFX_draw_box2(&t7screen, start, stop, CLUT_Font020, 1); } @@ -1622,7 +1604,7 @@ } */ GFX_write_string(&FontT48,&t7cW,text,1); - requestBuzzerActivation(1); + requestBuzzerActivation(REQUEST_BUZZER_CONTINUOUS); } @@ -1820,7 +1802,7 @@ } bool showScrubberTime = false; - if (settings->scrubTimerMode != SCRUB_TIMER_OFF) { + if (isScrubberTimerEnabled(settings)) { numLines++; showScrubberTime = true; } @@ -1897,7 +1879,7 @@ heading[headingIndex++] = '\016'; heading[headingIndex++] = TXT_CCRmode; - data[dataIndex++] = '\t'; + data[dataIndex++] = '\002'; char *modeText; if (settings->CCR_Mode == CCRMODE_Sensors) { if (settings->fallbackToFixedSetpoint) { @@ -1925,7 +1907,7 @@ data[dataIndex++] = '\n'; data[dataIndex++] = '\r'; - data[dataIndex++] = '\t'; + data[dataIndex++] = '\002'; dataIndex += snprintf(&data[dataIndex], 10, "\020%01.2f", setpointsToShow[i]->setpoint_cbar / 100.0); if (setpointsToShow[i]->depth_meter && !(settings->autoSetpoint && i + 1 == SETPOINT_INDEX_AUTO_DECO)) { bool setpointDelayed = settings->autoSetpoint && i + 1 == SETPOINT_INDEX_AUTO_LOW && settings->delaySetpointLow; @@ -1945,7 +1927,7 @@ data[dataIndex++] = '\n'; data[dataIndex++] = '\r'; - data[dataIndex++] = '\t'; + data[dataIndex++] = '\002'; data[dataIndex++] = '\020'; dataIndex += write_gas(&data[dataIndex], diluentsToShow[i]->oxygen_percentage, diluentsToShow[i]->helium_percentage); if (diluentsToShow[i]->note.ub.deco) { @@ -1967,8 +1949,8 @@ data[dataIndex++] = '\n'; data[dataIndex++] = '\r'; - data[dataIndex++] = '\t'; - dataIndex += printScrubberText(&data[dataIndex], 10, settings->scrubberData, settings); + data[dataIndex++] = '\002'; + dataIndex += printScrubberText(&data[dataIndex], 10, settings->scrubberData, settings, false); } heading[headingIndex++] = '\017'; @@ -1983,16 +1965,19 @@ if (!settings->FlipDisplay) { t7cY0free.WindowY0 = t7cC.WindowY0 - 10; t7cY0free.WindowX0 += 10; + t7cY0free.WindowX1 = t7cC.WindowX1 - 10; t7cY0free.WindowY0 += 10; t7cY0free.WindowY1 = 355; GFX_write_string(&FontT24, &t7cY0free, heading, 1); t7cY0free.WindowX0 -= 10; t7cY0free.WindowY0 -= 10; } else { + t7cY0free.WindowX0 -= 10; t7cY0free.WindowY1 = 400; t7cY0free.WindowY1 -= 10; t7cY0free.WindowX1 -= 10; GFX_write_string(&FontT24, &t7cY0free, heading, 1); + t7cY0free.WindowX0 += 10; t7cY0free.WindowY1 += 10; t7cY0free.WindowX1 += 10; } @@ -2165,9 +2150,8 @@ { static uint8_t last_customview = CVIEW_END; - char text[256]; - char timeSuffix; - uint8_t hoursToDisplay; + char text[200]; + char tmpString[20]; #ifdef ENABLE_PSCR_MODE uint8_t showSimPPO2 = 1; #endif @@ -2431,39 +2415,8 @@ translateDate(stateRealGetPointer()->lifeData.dateBinaryFormat, &Sdate); translateTime(stateRealGetPointer()->lifeData.timeBinaryFormat, &Stime); - if (settingsGetPointer()->amPMTime) - { - if (Stime.Hours > 11) - { - timeSuffix = 'P'; - } - else - { - timeSuffix = 'A'; - } - - if (Stime.Hours % 12 == 0) - { - hoursToDisplay = 12; - } - else - { - hoursToDisplay = (Stime.Hours % 12); - } - - if(Stime.Seconds % 2) - textpointer += snprintf(&text[textpointer],100,"\030\001%02d:%02d %cM",hoursToDisplay,Stime.Minutes,timeSuffix); - else - textpointer += snprintf(&text[textpointer],100,"\030\001%02d\031:\030%02d %cM",hoursToDisplay,Stime.Minutes,timeSuffix); - } - else - { - if(Stime.Seconds % 2) - textpointer += snprintf(&text[textpointer],100,"\030\001%02d:%02d",Stime.Hours,Stime.Minutes); - else - textpointer += snprintf(&text[textpointer],100,"\030\001%02d\031:\030%02d",Stime.Hours,Stime.Minutes); - } - + formatStringOfTime(tmpString,20,Stime,1,0); + snprintf(text,100,"\030\001%s",tmpString); GFX_write_string(&FontT42, &t7cY0free, text, 2); // EAD / END @@ -2816,7 +2769,7 @@ /* ascent rate graph */ color = 0xff; - if((pSettings->slowExitTime != 0) && (nextstopDepthMeter == 0) && (stateUsed->lifeData.depth_meter < pSettings->last_stop_depth_meter)) + if((pSettings->slowExitTime != 0) && (nextstopDepthMeter == 0) && (stateUsed->lifeData.depth_meter < pSettings->last_stop_depth_meter) && (stateUsed->lifeData.depth_meter > 0.3)) { color = t7_drawSlowExitGraph(); } @@ -3233,7 +3186,7 @@ else { t7_refresh_customview(); - requestBuzzerActivation(0); + requestBuzzerActivation(REQUEST_BUZZER_OFF); } /* the frame */ @@ -3254,18 +3207,18 @@ { selection_custom_field++; } - if((selection_custom_field == LLC_ScrubberTime) && ((settingsGetPointer()->scrubTimerMode == SCRUB_TIMER_OFF) || (!isLoopMode(settingsGetPointer()->dive_mode)))) - { + SSettings *settings = settingsGetPointer(); + if (selection_custom_field == LLC_ScrubberTime && !isScrubberTimerEnabled(settings)) { selection_custom_field++; } #ifdef ENABLE_PSCR_MODE - if((selection_custom_field == LCC_SimPpo2) && (settingsGetPointer()->dive_mode != DIVEMODE_PSCR)) + if((selection_custom_field == LCC_SimPpo2) && (settings->dive_mode != DIVEMODE_PSCR)) { selection_custom_field++; } #endif #ifdef ENABLE_CO2_SUPPORT - if((selection_custom_field == LCC_CO2) && (settingsGetPointer()->co2_sensor_active == 0)) + if((selection_custom_field == LCC_CO2) && (settings->co2_sensor_active == 0)) { selection_custom_field++; } @@ -3402,7 +3355,8 @@ tinyHeaderFont = 1; headerText[2] = TXT_ScrubTime; - printScrubberText(text, TEXTSIZE, stateUsed->scrubberDataDive, pSettings); + bool useTwoLines = (pSettings->scrubberActiveId == 0x03); + textpointer = printScrubberText(text, TEXTSIZE, stateUsed->scrubberDataDive, pSettings, useTwoLines); break; #ifdef ENABLE_PSCR_MODE @@ -3537,7 +3491,7 @@ } else { - GFX_write_string(&FontT48,&t7l3,text,line); + GFX_write_string(&FontT48,&t7l3,text,line); } #else GFX_write_string(&FontT105,&t7l3,text,line); @@ -4176,7 +4130,7 @@ t7cY0free.WindowLineSpacing = 48; t7cY0free.WindowNumberOfTextLines = 6; - t7cY0free.WindowTab = 420; + t7cY0free.WindowTab = 380; // header textpointer = 0; @@ -4198,10 +4152,9 @@ text[textpointer++] = TXT_FutureTTS; text[textpointer++] = '\n'; text[textpointer++] = '\r'; - if((pSettings->scrubTimerMode != SCRUB_TIMER_OFF) && (isLoopMode(pSettings->dive_mode))) - { - text[textpointer++] = TXT_ScrubTime; - + if (isScrubberTimerEnabled(pSettings)) { + text[textpointer++] = TXT_2BYTE; + text[textpointer++] = TXT2BYTE_Scrubber; } text[textpointer++] = '\017'; text[textpointer++] = 0; @@ -4247,13 +4200,12 @@ else textpointer += snprintf(&text[textpointer],10,"\020%ih", (pDecoinfoFuture->output_time_to_surface_seconds + 59) / 3600); - if((pSettings->scrubTimerMode != SCRUB_TIMER_OFF) && (isLoopMode(pSettings->dive_mode))) - { + if (isScrubberTimerEnabled(pSettings)) { text[textpointer++] = '\n'; text[textpointer++] = '\r'; text[textpointer++] = '\t'; - textpointer += printScrubberText(&text[textpointer], 10, stateUsed->scrubberDataDive, pSettings); + textpointer += printScrubberText(&text[textpointer], 10, stateUsed->scrubberDataDive, pSettings, false); } text[textpointer++] = 0; Gfx_colorsscheme_mod(text, 0); @@ -4648,7 +4600,7 @@ } else { - memcpy (&ChargerLog[0],&ChargerLog[1],sizeof(ChargerLog) - 1); + memmove(&ChargerLog[0], &ChargerLog[1], sizeof(ChargerLog) - 1); ChargerLog[curIndex] = level; } if(curIndex > 1) /* estimate time til charging is complete */
--- a/Discovery/Src/tCCR.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Src/tCCR.c Sat Nov 15 19:29:44 2025 +0100 @@ -34,6 +34,7 @@ #include "data_exchange.h" #include "check_warning.h" #include "configuration.h" +#include "logbook.h" #include <math.h> /* Private types -------------------------------------------------------------*/ @@ -340,17 +341,30 @@ // If we are in the simulator the counter is updated in `simulator.c` if (!is_stateUsedSetToSim()) { /* decrease scrubber timer only if we are not bailed out */ - if((pSettings->scrubTimerMode != SCRUB_TIMER_OFF) && (isLoopMode(pSettings->dive_mode)) && (stateUsed->mode == MODE_DIVE) && isLoopMode(stateUsed->diveSettings.diveMode)) - { + if (isScrubberTimerRunning(stateUsed, pSettings)) { ScrubberTimeoutCount++; - if(ScrubberTimeoutCount >= 600) /* resolution is minutes */ - { + if (ScrubberTimeoutCount >= 600) { /* resolution is minutes */ ScrubberTimeoutCount = 0; - if(stateUsed->scrubberDataDive[pSettings->scubberActiveId].TimerCur > MIN_SCRUBBER_TIME) - { - stateUsedWrite->scrubberDataDive[pSettings->scubberActiveId].TimerCur--; + + int16_t maxScrubberTime = INT16_MIN; + SScrubberData *longestScrubberData = NULL; + for (unsigned timerId = 0; timerId < 2; timerId++) { + if (pSettings->scrubberActiveId & (1 << timerId)) { + SScrubberData *scrubberData = &stateUsedWrite->scrubberDataDive[timerId]; + if (scrubberData->TimerCur > MIN_SCRUBBER_TIME) { + scrubberData->TimerCur--; + } + + if (scrubberData->TimerCur > maxScrubberTime) { + maxScrubberTime = scrubberData->TimerCur; + longestScrubberData = scrubberData; + } + + translateDate(stateUsed->lifeData.dateBinaryFormat, &scrubberData->lastDive); + } } - translateDate(stateUsed->lifeData.dateBinaryFormat, &stateUsedWrite->scrubberDataDive[pSettings->scubberActiveId].lastDive); + + logScrubberState(longestScrubberData); } } }
--- a/Discovery/Src/tComm.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Src/tComm.c Sat Nov 15 19:29:44 2025 +0100 @@ -188,11 +188,10 @@ if(bluetoothActiveLastTime) { HAL_UART_AbortReceive_IT(&UartHandle); - HAL_UART_DeInit(&UartHandle); - HAL_Delay(1); - UartHandle.Init.BaudRate = 115200; /* Module will be operating at default baud rate if powered again */ - BmTmpConfig = BM_CONFIG_OFF; /* Restart configuration if powered again */ - HAL_UART_Init(&UartHandle); + HAL_UART_DeInit(&UartHandle); + HAL_Delay(1); + UartHandle.Init.BaudRate = 115200; /* Module will be operating at default baud rate if powered again */ + BmTmpConfig = BM_CONFIG_OFF; /* Restart configuration if powered again */ HAL_Delay(1); UartReady = RESET; StartListeningToUART = 1; @@ -205,8 +204,8 @@ else { bluetoothActiveLastTime = 1; - if(RequestDisconnection) - { + if(RequestDisconnection) /* at the moment disconnection does not seem to be in use. */ + { /* Instead the modul id usually powered off for disconnection */ RequestDisconnection = 0; tComm_Disconnect(); } @@ -225,6 +224,7 @@ if((UartReady == RESET) && StartListeningToUART) { StartListeningToUART = 0; + receiveStartByteUart = 0; if(HAL_UART_Receive_IT(&UartHandle, &receiveStartByteUart, 1) != HAL_OK) tComm_Error_Handler(); } @@ -328,7 +328,7 @@ #ifndef BOOTLOADER_STANDALONE if(updateSettingsAndMenuOnExit) { - check_and_correct_settings(); + check_and_correct_settings(EF_SETTINGS); createDiveSettings(); tM_rebuild_menu_after_tComm(); } @@ -453,7 +453,7 @@ #ifndef BOOTLOADER_STANDALONE void tComm_Disconnect() { - uint8_t answer; + uint8_t answer = HAL_ERROR; uint8_t retrycnt = 3; char aTxDisconnect[] ="ATH\r"; char aTxBufferEnd[10]; @@ -461,31 +461,34 @@ uint8_t sizeDisconnect = sizeof(aTxDisconnect) -1; - tComm_GetBTCmdStr(BT_CMD_EXIT_CMD, aTxBufferEnd); - HAL_UART_AbortReceive_IT(&UartHandle); - do + if (isNewDisplay()) /* disconnect for OSTC5 BT is a little bit more complicated and not implemented yet, because function is not used */ { - HAL_Delay(200); - if(HAL_UART_Transmit(&UartHandle, (uint8_t*)aTxBufferEscapeSequence, 3, UART_OPERATION_TIMEOUT)== HAL_OK) + tComm_GetBTCmdStr(BT_CMD_EXIT_CMD, aTxBufferEnd); + HAL_UART_AbortReceive_IT(&UartHandle); + do { - answer = tComm_CheckAnswerOK(); + HAL_Delay(200); + if(HAL_UART_Transmit(&UartHandle, (uint8_t*)aTxBufferEscapeSequence, 3, UART_OPERATION_TIMEOUT)== HAL_OK) + { + answer = tComm_CheckAnswerOK(); + } + retrycnt--; } - retrycnt--; - } - while((answer != HAL_OK) && (retrycnt > 0)); + while((answer != HAL_OK) && (retrycnt > 0)); - if(answer == HAL_OK) - { - answer = HAL_ERROR; - if(HAL_UART_Transmit(&UartHandle, (uint8_t*)aTxDisconnect,sizeDisconnect , UART_OPERATION_TIMEOUT)== HAL_OK) + if(answer == HAL_OK) { answer = HAL_ERROR; - if(tComm_CheckAnswerOK() == HAL_OK) + if(HAL_UART_Transmit(&UartHandle, (uint8_t*)aTxDisconnect,sizeDisconnect , UART_OPERATION_TIMEOUT)== HAL_OK) { answer = HAL_ERROR; - if(HAL_UART_Transmit(&UartHandle, (uint8_t*)aTxBufferEnd, 4, UART_OPERATION_TIMEOUT) == HAL_OK) /* exit terminal mode */ + if(tComm_CheckAnswerOK() == HAL_OK) { - answer = tComm_CheckAnswerOK(); + answer = HAL_ERROR; + if(HAL_UART_Transmit(&UartHandle, (uint8_t*)aTxBufferEnd, 4, UART_OPERATION_TIMEOUT) == HAL_OK) /* exit terminal mode */ + { + answer = tComm_CheckAnswerOK(); + } } } } @@ -1070,16 +1073,20 @@ // get model + features case 0x60: aTxBuffer[count++] = 0x00; // hardware descriptor HIGH byte - aTxBuffer[count++] = 0x3B; // hardware descriptor LOW byte // 0x3B is OSTC4 // 0x1A is OTSC3 + aTxBuffer[count++] = 0x3B; // hardware descriptor LOW byte // 0x3B is OSTC 4/5 // 0x1A is OTSC3 aTxBuffer[count++] = 0x00; // feature descriptor HIGH byte aTxBuffer[count++] = 0x00; // feature descriptor LOW byte - aTxBuffer[count++] = 0x43; // model id + if (isNewDisplay()) { + aTxBuffer[count++] = 0x44; // model id OSTC5 + } else { + aTxBuffer[count++] = 0x43; // model id OSTC4 + } aTxBuffer[count++] = prompt4D4C(receiveStartByteUart); break; // get model case 0x6A: - aTxBuffer[count++] = 0x3B; // 0x3B is OSTC4 // 0x1A is OTSC3 + aTxBuffer[count++] = 0x3B; // 0x3B is OSTC 4/5 // 0x1A is OTSC3 aTxBuffer[count++] = prompt4D4C(receiveStartByteUart); break; @@ -1179,7 +1186,7 @@ #ifndef BOOTLOADER_STANDALONE //Reset all setting case 0x78: - set_settings_to_Standard(); + set_settings_to_Standard(EF_SETTINGS); updateSettingsAndMenuOnExit = 1; aTxBuffer[count++] = prompt4D4C(receiveStartByteUart); break; @@ -1546,6 +1553,7 @@ const uint8_t id_Region1_firmware = 0xFF; const uint8_t id_RTE = 0xFE; uint8_t textpointer = 0; + uint32_t index = 0; //Get length if(HAL_UART_Receive(&UartHandle, sBuffer, 4,5000)!= HAL_OK) // 58000 @@ -1572,7 +1580,10 @@ // neu 110212 if(id == id_FONT) + { offsetTotal = 256 * 256 * 256 * (uint32_t)sBuffer[1] + 256 * 256 * (uint32_t)sBuffer[2] + 256 * (uint32_t)sBuffer[3]; + /* todo set offset depending on font version offsetTotal = 0; */ + } else offsetTotal = 256 * 256 * 256 * (uint32_t)sBuffer[0] + 256 * 256 * (uint32_t)sBuffer[1] + 256 * (uint32_t)sBuffer[2] + sBuffer[3]; @@ -1713,7 +1724,7 @@ return 0xFF; } else - //if(region == 2) + if(id == id_FONT) { uint8_t ptr = 0; ptr += gfx_number_to_string(7,0,&display_text[ptr],lengthTotal); @@ -1728,7 +1739,7 @@ } - // only non RTE !! + /* only non RTE !! (at this point RTE path already performed a return some lines above */ uint8_t* pBufferCompare = (uint8_t*)getFrame(20); ByteCompareStatus = 0; @@ -1742,14 +1753,14 @@ if(lengthCompare != length1) ByteCompareStatus = 10000; - for(int i = 0; i < length1; i++) + for(index = 0; index < length1; index++) { - if(pBuffer1[0] != pBufferCompare[0]) + if(pBuffer1[index] != pBufferCompare[index]) ByteCompareStatus++; } } else - //if(region == 2) + if(id == id_FONT) { /* upper region firmware can be larger (1MB) */ if(ext_flash_read_firmware2(0, pBufferCompare,4, 0,0) != 0xFFFFFFFF) @@ -1761,16 +1772,16 @@ ByteCompareStatus = 10000; if(offsetTotal != offsetCompare) ByteCompareStatus += 20000; - for(int i = 0; i < length1; i++) + for(index = 0; index < length1; index++) { - if(pBuffer1[0] != pBufferCompare[0]) + if(pBuffer1[index] != pBufferCompare[index]) ByteCompareStatus++; } lengthCompare = ext_flash_read_firmware2(0, 0,768000, pBufferCompare,768000); - for(int i = 0; i < length2; i++) + for(index = 0; index < length2; index++) { - if(pBuffer2[0] != pBufferCompare[0]) + if(pBuffer2[index] != pBufferCompare[index]) ByteCompareStatus++; } } @@ -2033,7 +2044,14 @@ { if(indexRef != 0) { - indexRef = 0; + if((answerOkay[0] == aRxBuffer[indexBuf])) + { + indexRef = 1; + } + else + { + indexRef = 0; + } } } indexBuf++; @@ -2245,178 +2263,169 @@ void tComm_StartBlueModConfig() { - uint8_t answer = HAL_OK; - uint8_t RxBuffer[UART_CMD_BUF_SIZE]; - uint8_t index = 0; + HAL_UART_Init(&UartHandle); - BmTmpConfig = BM_CONFIG_ECHO; - do /* flush RX buffer */ + if (isNewDisplay()) { - answer = HAL_UART_Receive(&UartHandle, (uint8_t*)&RxBuffer[index], 1, 10); - if(index < UART_CMD_BUF_SIZE) index++; - }while(answer == HAL_OK); +#ifdef ENABLE_FAST_COMM + BmTmpConfig = BM_CONFIG5_ESCAPE1; +#else + BmTmpConfig = BM_CONFIG_DONE; /* Configuration is stored in BT module => no configuration needed */ +#endif + } + else + { + BmTmpConfig = BM_CONFIG_ECHO; + } } uint8_t tComm_HandleBlueModConfig() { static uint8_t RestartModule = 1; /* used to do power off / on cycle */ static uint8_t ConfigRetryCnt = 0; /* Retry count without power cycle */ + static uint32_t cmdTick = 0; +#ifdef ENABLE_FAST_COMM + static uint32_t configTick = 0; +#endif char TxBuffer[UART_CMD_BUF_SIZE]; uint8_t CmdSize = 0; uint8_t result = HAL_OK; - memset(TxBuffer, 0, sizeof(TxBuffer)); - - switch (BmTmpConfig) + if(time_elapsed_ms(cmdTick, HAL_GetTick()) > 100) /* do config in 100ms steps */ { - case BM_CONFIG_ECHO: tComm_GetBTCmdStr (BT_CMD_ECHO, TxBuffer); - break; - case BM_CONFIG_SILENCE: tComm_GetBTCmdStr (BT_CMD_SILENCE, TxBuffer); - break; - case BM_CONFIG_ESCAPE_DELAY: tComm_GetBTCmdStr (BT_CMD_ESCAPE_DELAY, TxBuffer); - break; - case BM_CONFIG_SIGNAL_POLL: tComm_GetBTCmdStr(BT_CMD_SIGNAL_POLL, TxBuffer); - break; - case BM_CONFIG_BAUD: -#ifdef ENABLE_FAST_COMM - tComm_GetBTCmdStr(BT_CMD_BAUDRATE_460, TxBuffer); -#else - BmTmpConfig = BM_CONFIG_DONE; -#endif - break; - case BM_CONFIG_RETRY: ConfigRetryCnt--; - HAL_Delay(1); - if(ConfigRetryCnt == 0) + cmdTick = HAL_GetTick(); + memset(TxBuffer, 0, sizeof(TxBuffer)); + + switch (BmTmpConfig) + { + case BM_CONFIG_ECHO: tComm_GetBTCmdStr (BT_CMD_ECHO, TxBuffer); + break; + case BM_CONFIG_SILENCE: tComm_GetBTCmdStr (BT_CMD_SILENCE, TxBuffer); + break; + case BM_CONFIG_ESCAPE_DELAY: tComm_GetBTCmdStr (BT_CMD_ESCAPE_DELAY, TxBuffer); + break; + case BM_CONFIG_SIGNAL_POLL: tComm_GetBTCmdStr(BT_CMD_SIGNAL_POLL, TxBuffer); + break; + case BM_CONFIG_BAUD: + #ifdef ENABLE_FAST_COMM + tComm_GetBTCmdStr(BT_CMD_BAUDRATE_460, TxBuffer); + #else + BmTmpConfig = BM_CONFIG_DONE; + #endif + break; + case BM_CONFIG_RETRY: ConfigRetryCnt--; + HAL_Delay(1); + if(ConfigRetryCnt == 0) + { + MX_Bluetooth_PowerOn(); + tComm_StartBlueModConfig(); + } + break; + case BM_CONFIG_DONE: + case BM_CONFIG_OFF: + ConfigRetryCnt = 0; + RestartModule = 1; + break; + + case BM_CONFIG5_ESCAPE1: configTick = HAL_GetTick(); + BmTmpConfig++; + break; + case BM_CONFIG5_ESCAPE2: if(time_elapsed_ms(configTick, HAL_GetTick()) > 2600) { - MX_Bluetooth_PowerOn(); - tComm_StartBlueModConfig(); + configTick = HAL_GetTick(); + HAL_GPIO_WritePin(BLE_UBLOX_DSR_GPIO_PORT,BLE_UBLOX_DSR_PIN,GPIO_PIN_SET); + BmTmpConfig++; } - break; - case BM_CONFIG_DONE: - case BM_CONFIG_OFF: - ConfigRetryCnt = 0; - RestartModule = 1; - break; -#ifdef BOOTLOADER_STANDALONE /* the procedure below is just needed for the initial bluetooth module initialization */ - case BM_INIT_TRIGGER_ON: HAL_Delay(2000); - HAL_GPIO_WritePin(BLE_UBLOX_DSR_GPIO_PORT,BLE_UBLOX_DSR_PIN,GPIO_PIN_RESET); - BmTmpConfig++; - break; - case BM_INIT_TRIGGER_OFF: HAL_Delay(1); - HAL_GPIO_WritePin(BLE_UBLOX_DSR_GPIO_PORT,BLE_UBLOX_DSR_PIN,GPIO_PIN_SET); - HAL_Delay(2000); - BmTmpConfig++; - break; - case BM_INIT_ECHO: sprintf(TxBuffer,"ATE0\r"); - break; - case BM_INIT_FACTORY: sprintf(TxBuffer,"AT+UFACTORY\r"); /*Set to factory defined configuration */ - break; - case BM_INIT_MODE: sprintf(TxBuffer,"AT+UMSM=1\r"); /* start in Data mode */ - break; - case BM_INIT_BLE: sprintf(TxBuffer,"AT+UBTLE=2\r"); /* Bluetooth low energy Peripheral */ - break; - case BM_INIT_NAME: sprintf(TxBuffer,"AT+UBTLN=OSTC5-12345\r"); /* Bluetooth name */ - if(hardwareDataGetPointer()->primarySerial != 0xFFFF) /* module reinit? => restore old name */ - { - gfx_number_to_string(5,1,&TxBuffer[15],hardwareDataGetPointer()->primarySerial); - } - break; - case BM_INIT_SSP_IDO_OFF: sprintf(TxBuffer,"AT+UDSC=0,0\r"); /* Disable SPP Server on ID0 */ - break; - case BM_INIT_SSP_IDO_ON: sprintf(TxBuffer,"AT+UDSC=0,3\r"); /* SPP Server on ID0 */ - break; - case BM_INIT_SSP_ID1_OFF: sprintf(TxBuffer,"AT+UDSC=1,0\r"); /* Disable SPS Server on ID1 */ - break; - case BM_INIT_SSP_ID1_ON: sprintf(TxBuffer,"AT+UDSC=1,6\r"); /* SPS Server on ID1 */ - break; - case BM_INIT_STORE: sprintf(TxBuffer,"AT&W\r"); /* write settings into eeprom */ - break; - case BM_INIT_RESTART: sprintf(TxBuffer,"AT+CPWROFF\r"); /* reboot module */ - break; - case BM_INIT_DONE: BmTmpConfig = BM_CONFIG_ECHO; - break; -#endif - default: - break; - } - if(TxBuffer[0] != 0) /* forward command to module */ - { - CmdSize = strlen(TxBuffer); - if(HAL_UART_Transmit(&UartHandle, (uint8_t*)TxBuffer,CmdSize, 2000) == HAL_OK) + break; + case BM_CONFIG5_BAUD: if(time_elapsed_ms(configTick, HAL_GetTick()) > 1100) + { + tComm_GetBTCmdStr(BT_CMD_BAUDRATE_460, TxBuffer); + } + break; + case BM_CONFIG5_DATAMODE: tComm_GetBTCmdStr(BT_CMD_EXIT_CMD, TxBuffer); + break; + + default: + break; + } + if(TxBuffer[0] != 0) /* forward command to module */ { - 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); - HAL_Delay(1); - UartHandle.Init.BaudRate = 460800; - HAL_UART_Init(&UartHandle); - } - else if((BmTmpConfig == BM_CONFIG_BAUD) && (result == HAL_OK) && (UartHandle.Init.BaudRate == 460800)) /* This shut not happen because default speed is 115200 => update module configuration */ - { - tComm_GetBTCmdStr(BT_CMD_BAUDRATE_115, TxBuffer); - - 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); - } + CmdSize = strlen(TxBuffer); + result = HAL_UART_Transmit(&UartHandle, (uint8_t*)TxBuffer,CmdSize, 500); if(result == HAL_OK) { - BmTmpConfig++; - if(BmTmpConfig == BM_CONFIG_RETRY) - { - BmTmpConfig = BM_CONFIG_DONE; - } - } - if(BmTmpConfig == BM_CONFIG_ECHO) - { - BmTmpConfig = BM_CONFIG_DONE; - ConfigRetryCnt = 0; - RestartModule = 1; - } - } - } - else /* no command for the configuration step found => skip step */ - { - if((BmTmpConfig > BM_CONFIG_OFF) && (BmTmpConfig < BM_CONFIG_DONE)) - { - BmTmpConfig++; - } - } - if(result != HAL_OK) - { - ConfigRetryCnt++; - if(ConfigRetryCnt > 3) /* Configuration failed => switch off module */ - { - MX_Bluetooth_PowerOff(); - if(RestartModule) - { - RestartModule = 0; /* only one try */ - ConfigRetryCnt = 200; /* used for delay to startup module again */ + result = tComm_CheckAnswerOK(); - if((BmTmpConfig == BM_CONFIG_ECHO) || (BmTmpConfig == BM_INIT_ECHO)) /* the module did not answer even once => try again with alternative baud rate */ + if(((BmTmpConfig == BM_CONFIG_BAUD) || (BmTmpConfig == BM_CONFIG5_BAUD)) && (result == HAL_OK) && (UartHandle.Init.BaudRate != 460800)) /* is com already switched to fast speed? */ { HAL_UART_DeInit(&UartHandle); HAL_Delay(1); UartHandle.Init.BaudRate = 460800; HAL_UART_Init(&UartHandle); } - BmTmpConfig = BM_CONFIG_RETRY; + else if((BmTmpConfig == BM_CONFIG_BAUD) && (result == HAL_OK) && (UartHandle.Init.BaudRate == 460800)) /* This shut not happen because default speed is 115200 => update module configuration */ + { + tComm_GetBTCmdStr(BT_CMD_BAUDRATE_115, TxBuffer); + + 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) + { + if((BmTmpConfig != BM_CONFIG5_DATAMODE) && (BmTmpConfig != BM_CONFIG_DONE)) + { + BmTmpConfig++; + } + else + { + HAL_GPIO_WritePin(BLE_UBLOX_DSR_GPIO_PORT,BLE_UBLOX_DSR_PIN,GPIO_PIN_RESET); + BmTmpConfig = BM_CONFIG_DONE; + } + } } - else /* even restarting module failed => switch bluetooth off */ + } + else /* no command for the configuration step found => skip step */ + { + if((BmTmpConfig > BM_CONFIG_OFF) && (BmTmpConfig < BM_CONFIG_DONE)) { - ConfigRetryCnt = 0; - BmTmpConfig = BM_CONFIG_OFF; - settingsGetPointer()->bluetoothActive = 0; + BmTmpConfig++; + } + } + if(result != HAL_OK) + { + ConfigRetryCnt++; + if(ConfigRetryCnt > 3) /* Configuration failed => switch off module */ + { + MX_Bluetooth_PowerOff(); + if(RestartModule) + { + RestartModule = 0; /* only one try */ + ConfigRetryCnt = 200; /* used for delay to startup module again */ + + if((BmTmpConfig == BM_CONFIG_ECHO) || (BmTmpConfig == BM_INIT_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 */ + { + ConfigRetryCnt = 0; + BmTmpConfig = BM_CONFIG_OFF; + settingsGetPointer()->bluetoothActive = 0; + } } } }
--- a/Discovery/Src/tDebug.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Src/tDebug.c Sat Nov 15 19:29:44 2025 +0100 @@ -58,9 +58,12 @@ void exitDebugMode(void) { - MX_Bluetooth_PowerOff(); - settingsGetPointer()->debugModeOnStart = 0; - tD_debugModeActive = 0; + if(tD_debugModeActive) + { + MX_Bluetooth_PowerOff(); + settingsGetPointer()->debugModeOnStart = 0; + tD_debugModeActive = 0; + } }
--- a/Discovery/Src/tHome.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Src/tHome.c Sat Nov 15 19:29:44 2025 +0100 @@ -59,7 +59,13 @@ static uint16_t tHome_tick_count_field; static uint16_t tHome_tick_count_o2sens; -const uint8_t cv_changelist[] = {CVIEW_Compass, CVIEW_SummaryOfLeftCorner, CVIEW_Tissues, CVIEW_Profile, CVIEW_EADTime, CVIEW_Gaslist, CVIEW_noneOrDebug, CVIEW_Decolist, CVIEW_sensors,CVIEW_sensors_mV, CVIEW_Timer, CVIEW_END}; +const uint8_t cv_changelist[] = {CVIEW_Compass, CVIEW_SummaryOfLeftCorner, CVIEW_Tissues, + CVIEW_Profile, CVIEW_EADTime, CVIEW_Gaslist, CVIEW_noneOrDebug, + CVIEW_Decolist, CVIEW_sensors,CVIEW_sensors_mV, CVIEW_Timer, +#ifdef ENABLE_LOGGER_WINDOW + CVIEW_Logger, +#endif + CVIEW_END}; const uint8_t cv_changelist_BS[] = {CVIEW_T3_Decostop, CVIEW_sensors, CVIEW_Compass, CVIEW_T3_MaxDepth,CVIEW_T3_StopWatch, CVIEW_T3_TTS, CVIEW_T3_GasList, CVIEW_T3_ppO2andGas, CVIEW_noneOrDebug, CVIEW_T3_Navigation, CVIEW_T3_DepthData, CVIEW_T3_DecoTTS, #ifdef ENABLE_T3_PROFILE_VIEW
--- a/Discovery/Src/tInfo.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Src/tInfo.c Sat Nov 15 19:29:44 2025 +0100 @@ -38,6 +38,7 @@ #include "tInfoCompass.h" #include "tInfoSensor.h" #include "tInfoPreDive.h" +#include "tInfoLogger.h" #include "tMenu.h" #include "tMenuEdit.h" @@ -227,6 +228,12 @@ infoColor = CLUT_MenuPageGasCC; refreshInfo_PreDive(tIscreen); break; +#ifdef ENABLE_LOGGER_WINDOW + case StILOGGER: tIscreen.FBStartAdress = getFrame(14); + infoColor = CLUT_MenuPageCvOption; + refreshInfo_Logger(tIscreen); + break; +#endif default: break; @@ -256,6 +263,11 @@ exitMenuEdit_to_BackMenu(); } +void exitInfoSilent(void) /* no changes were done on info screen => just free buffer */ +{ + releaseFrame(14,tIscreen.FBStartAdress); + updateMenu(); +} void sendActionToInfo(uint8_t sendAction) { @@ -298,6 +310,32 @@ } + +void tInfo_drawPixel(int16_t x, int16_t y, uint8_t color) +{ + int8_t xoff; + int8_t yoff; + + for (xoff = -1; xoff < 2; xoff++) + { + for (yoff = -1; yoff < 2; yoff++) + { + GFX_draw_pixel(&tIscreen, x + xoff, y + yoff, color); + } + } + GFX_draw_pixel(&tIscreen, x, y, color); +} + +void tInfo_draw_colorline(point_t start, point_t stop, uint8_t color) +{ + GFX_draw_colorline(&tIscreen, start, stop, color); +} + +void t_Info_draw_circle(point_t center, uint8_t radius, int8_t color) +{ + GFX_draw_circle(&tIscreen, center, radius, color); +} + void tInfo_write_content_simple(uint16_t XleftGimpStyle, uint16_t XrightGimpStyle, uint16_t YtopGimpStyle, const tFont *Font, const char *text, uint8_t color) { GFX_DrawCfgWindow hgfx;
--- a/Discovery/Src/tInfoCompass.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Src/tInfoCompass.c Sat Nov 15 19:29:44 2025 +0100 @@ -28,34 +28,77 @@ /* Includes ------------------------------------------------------------------*/ -#include "gfx_engine.h" + #include "gfx_fonts.h" #include "tHome.h" #include "tInfo.h" #include "tInfoCompass.h" #include <string.h> +#include <math.h> + +#define PI 3.14159265358979323846 + +#define PITCH (0) +#define ROLL (1) +#define YAW (2) /* Private variables ---------------------------------------------------------*/ -uint16_t tInfoCompassTimeout = 0; -int16_t minMaxCompassDX[3][2] = { 0 }; +static uint16_t tInfoCompassTimeout = 0; +static int16_t minMaxCompassDX[3][2] = { 0 }; + +static axisIndicator_t axis[3]; +static uint8_t activeAxis = PITCH; +static uint32_t checkTick = 0; /* Exported functions --------------------------------------------------------*/ void openInfo_Compass(void) { + uint16_t angle = 0; + uint8_t axisIndex = 0; set_globalState(StICOMPASS); tInfoCompassTimeout = settingsGetPointer()->timeoutInfoCompass; tInfoCompassTimeout *= 10; + for(axisIndex = 0; axisIndex < 3; axisIndex++) + { + memset(axis[axisIndex].check,0, 360); + } + for(angle = 170; angle < 360; angle++) + { + axis[PITCH].check[angle] = 1; /* pitch only from -90 to +90 */ + } + axis[YAW].coord.x = 100; + axis[YAW].coord.y = 70; + axis[PITCH].coord.x = 100; + axis[PITCH].coord.y = 300; + axis[ROLL].coord.x = 100; + axis[ROLL].coord.y = 200; + + axis[YAW].eclipse.x = 50; + axis[YAW].eclipse.y = 50; + axis[PITCH].eclipse.x = 20; + axis[PITCH].eclipse.y = 50; + axis[ROLL].eclipse.x = 50; + axis[ROLL].eclipse.y = 20; + for(int i = 0; i<3;i ++) { minMaxCompassDX[i][0] = 999; minMaxCompassDX[i][1] = -999; } + checkTick = HAL_GetTick(); + + activeAxis = PITCH; } - +void getElipsePoint(uint16_t elipseX , int16_t elipseY, int16_t degree, int16_t *x, int16_t *y) +{ + double rad = degree * (PI / 180.0); + *x = (int16_t) (elipseX * cos(rad)); + *y = (int16_t) (elipseY * sin(rad)); +} // =============================================================================== // refreshInfo_Compass /// @brief there is only compass_DX_f, compass_DY_f, compass_DZ_f output during this mode @@ -63,6 +106,20 @@ // =============================================================================== void refreshInfo_Compass(GFX_DrawCfgScreen s) { + static int16_t cursorAngle = 0; + + int16_t angle = 0.0; + int16_t drawX = 0; + int16_t drawY = 0; + uint8_t color = 0; + point_t start; + point_t stop; + point_t center; + + int8_t offset = 0; + uint8_t axisIndex = 0; + int16_t index = 0; + uint8_t textIndex = 0; tHome_show_lost_connection_count(&s); tInfoCompassTimeout--; @@ -80,6 +137,106 @@ compassValues[1] = stateUsed->lifeData.compass_DY_f; compassValues[2] = stateUsed->lifeData.compass_DZ_f; + /* draw indicator */ + for(axisIndex = 0; axisIndex < 3; axisIndex++) + { + switch(axisIndex) + { + default: + case YAW: index = (uint16_t)(stateUsed->lifeData.compass_heading); + textIndex = snprintf(text,80,"yaw %.1f", stateUsed->lifeData.compass_heading); + + if((tInfoCompassTimeout < 50) && (activeAxis == YAW)) + { + snprintf(&text[textIndex],80,"\023\t(%i, %i)", minMaxCompassDX[YAW][0], minMaxCompassDX[YAW][1]); + } + + start.x = axis[axisIndex].coord.x - 1; + start.y = axis[axisIndex].coord.y; + stop.x = axis[axisIndex].coord.x + 1; + stop.y = axis[axisIndex].coord.y; + break; + case PITCH: index = (uint16_t)(stateUsed->lifeData.compass_pitch + 90); + textIndex = snprintf(text,80,"pitch %.1f", stateUsed->lifeData.compass_pitch); + if((tInfoCompassTimeout < 50) && (activeAxis == YAW)) + { + snprintf(&text[textIndex],80,"\023\t(%i, %i)", minMaxCompassDX[PITCH][0], minMaxCompassDX[PITCH][1]); + } + start.x = axis[axisIndex].coord.x - 30; + start.y = axis[axisIndex].coord.y; + stop.x = axis[axisIndex].coord.x + 30; + stop.y = axis[axisIndex].coord.y; + + break; + case ROLL: index = (uint16_t)(stateUsed->lifeData.compass_roll + 180); + textIndex = snprintf(text,80,"roll %.1f", stateUsed->lifeData.compass_roll); + if((tInfoCompassTimeout < 50) && (activeAxis == YAW)) + { + snprintf(&text[textIndex],80,"\023\t(%i, %i)", minMaxCompassDX[ROLL][0], minMaxCompassDX[ROLL][1]); + } + start.x = axis[axisIndex].coord.x; + start.y = axis[axisIndex].coord.y - 30; + stop.x = axis[axisIndex].coord.x; + stop.y = axis[axisIndex].coord.y +30; + break; + } + if(settingsGetPointer()->FlipDisplay) + { + start.x = 800 - start.x; + stop.x = 800 - stop.x; + start.y = 480 - start.y; + stop.y = 480 - stop.y; + } + if(activeAxis == axisIndex) /* only check one axis at a time. reason: yaw will be unstable at the beginning of calibration */ + { + for(offset = -6; offset <= 6; offset++) /* it is hard to hit every single angle and the resolution is not needed */ + { + if(( (index + offset) >= 0) && (index + offset < 360)) + { + axis[axisIndex].check[index + offset] = 1; /* => check surrounding angles as well */ + } + } + } + if(axisIndex == activeAxis) + { + color = CLUT_InfoCompass; + getElipsePoint(axis[axisIndex].eclipse.x,axis[axisIndex].eclipse.y,cursorAngle, &drawX, &drawY); + center.x = axis[axisIndex].coord.x + drawX; + center.y = axis[axisIndex].coord.y + drawY; + + t_Info_draw_circle(center, 4, CLUT_Font020); + cursorAngle += 15; + if(cursorAngle >= 360) + { + cursorAngle = 0; + } + } + else + { + color = CLUT_Font021; + } + tInfo_write_content_simple( 200, 600, 480 - axis[axisIndex].coord.y - 35 , &FontT42, text, color); + tInfo_draw_colorline(start, stop, CLUT_Font020); + for(angle = 0; angle < 360; angle = angle + 3) + { + if(axis[axisIndex].check[angle]) + { + color = CLUT_NiceGreen; + } + else + { + color = CLUT_WarningRed; + } + getElipsePoint(axis[axisIndex].eclipse.x,axis[axisIndex].eclipse.y,angle, &drawX, &drawY); + tInfo_drawPixel(axis[axisIndex].coord.x + drawX, axis[axisIndex].coord.y + drawY,color); + if((axisIndex == PITCH) && (angle == 180)) /* pitch only from -90 to +90 */ + { + break; + } + } + + } + for(int i = 0; i<3;i ++) { // do not accept zero @@ -100,18 +257,33 @@ snprintf(text,80,"Time left: %u s",(tInfoCompassTimeout+9)/10); tInfo_write_content_simple( 20,800, 25, &FontT42, text, CLUT_InfoCompass); - for(int i = 0; i<3;i ++) + + if(time_elapsed_ms(checkTick, HAL_GetTick() > 1000)) { - snprintf(text,80,"%c: %i" "\t(%i, %i)", - 'X'+i, - compassValues[i], - minMaxCompassDX[i][0], - minMaxCompassDX[i][1]); - tInfo_write_content_simple( 20,800, 96 + (i*96), &FontT48, text, CLUT_InfoCompass); + index = 0; + for(angle = 0; angle < 360; angle++) + { + if(axis[activeAxis].check[angle]) + { + index++; + } + } + if(index > 350) + { + if(activeAxis < 2) + { + activeAxis++; + } + else + { + if(tInfoCompassTimeout > 50) + { + tInfoCompassTimeout = 50; /* reduce exit time to five seconds */ + } + } + } + + + checkTick = HAL_GetTick(); } - - snprintf(text,80,"roll %.1f" "\tpitch %.1f", - stateUsed->lifeData.compass_roll, - stateUsed->lifeData.compass_pitch); - tInfo_write_content_simple( 20,800, 96 * 4, &FontT42, text, CLUT_InfoCompass); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Discovery/Src/tInfoLogger.c Sat Nov 15 19:29:44 2025 +0100 @@ -0,0 +1,170 @@ +/////////////////////////////////////////////////////////////////////////////// +/// -*- coding: UTF-8 -*- +/// +/// \file Discovery/Src/tInfoLogger.c +/// \brief Show data which is received / send through UART interface +/// \author heinrichs weikamp gmbh +/// \date 23-Feb-2015 +/// +/// \details +/// +/// $Id$ +/////////////////////////////////////////////////////////////////////////////// +/// \par Copyright (c) 2014-2018 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 <http://www.gnu.org/licenses/>. +////////////////////////////////////////////////////////////////////////////// + +/* Includes ------------------------------------------------------------------*/ + +#include "gfx_engine.h" +#include "gfx_fonts.h" +#include "tHome.h" +#include "tInfo.h" +#include "tInfoLogger.h" +#include "tMenuEdit.h" +#include "data_exchange_main.h" +#include "t7.h" + +#include <string.h> +#include <inttypes.h> + + +/* Private variables ---------------------------------------------------------*/ +static uint8_t lines[MAX_LOGGER_LINES][MAX_CHAR_PER_LINE + LINE_HEADER_BYTES]; +static uint8_t lineWriteIndex = 0; +static uint8_t lineReadIndex = 0; +static uint32_t receivedLinesCount = 0; + +static uint32_t loggerUpdateTime = 0; +static uint32_t previousGlobalState = 0; + +/* Exported functions --------------------------------------------------------*/ + + +void InfoLogger_writeLine(uint8_t* pLine,uint8_t lineLength,uint8_t direction) +{ +#ifdef ENABLE_LOGGER_WINDOW + uint8_t LogIndex = 0; + + if(!t7_customview_disabled(CVIEW_Logger)) + { + if(lineLength <= MAX_CHAR_PER_LINE) + { + memset(&lines[lineWriteIndex][0],0, (MAX_CHAR_PER_LINE + LINE_HEADER_BYTES)); + if(direction == LOG_TX_LINE) + { + lines[lineWriteIndex][LogIndex] = '\002'; /* align right */ + LogIndex++; + } + memcpy(&lines[lineWriteIndex][LogIndex],pLine,lineLength); + lineWriteIndex++; + if(lineWriteIndex == MAX_LOGGER_LINES) + { + lineWriteIndex = 0; + } + receivedLinesCount++; + } + } +#endif +} + +uint8_t InfoLogger_isUpdated() +{ + uint8_t ret = 0; + if(lineReadIndex != lineWriteIndex) + { + ret = 1; + } + return ret; +} + +void openInfo_Logger() +{ + previousGlobalState = get_globalState(); + set_globalState(StILOGGER); + + loggerUpdateTime = HAL_GetTick(); +} + +void refreshInfo_Logger(GFX_DrawCfgScreen s) +{ + uint8_t index = 0; + char text[31]; + uint8_t displayLine = 0; + uint8_t color = CLUT_Font020; + + sprintf(text,"\001%c%c", TXT_2BYTE, TXT2BYTE_Logger); + + tInfo_write_content_simple( 30, 770, ME_Y_LINE_BASE, &FontT48, text, CLUT_InfoSurface); + + + if(InfoLogger_isUpdated()) + { + loggerUpdateTime = HAL_GetTick(); + } + if(receivedLinesCount > MAX_LOGGER_LINES) + { + displayLine = MAX_LOGGER_LINES-1; + } + else + { + displayLine = lineWriteIndex; + } + + if(lineReadIndex != lineWriteIndex) /* needed for isUpdated function */ + { + lineReadIndex++; + if(lineReadIndex == MAX_LOGGER_LINES) + { + lineReadIndex = 0; + } + } + while (index < displayLine) + { + color = CLUT_Font020; + if(lines[index][0] == '\002') + { + color = CLUT_NiceGreen; + } + if(lineReadIndex == index) + { + color = CLUT_NiceBlue; + } + tInfo_write_content_simple( 30, 770, 60 + (index * 30), &FontT24, (char*)lines[index], color); + + if(lineReadIndex != lineWriteIndex) /* needed for isUpdated function */ + { + lineReadIndex++; + if(lineReadIndex == MAX_LOGGER_LINES) + { + lineReadIndex = 0; + } + } + index++; + } + if((time_elapsed_ms(loggerUpdateTime, HAL_GetTick()) > 10000)) + { + set_globalState(previousGlobalState); /* restore state which was active before log data was received */ + exitInfo(); + } +} + +void sendActionToInfoLogger(uint8_t sendAction) +{ +/* TODO: at the moment a generic return to home is used because the logger window could be opened from everywhere => implement context based return from view */ + set_globalState(previousGlobalState); /* restore state which was active before log data was received */ + exitInfoSilent(); +} +
--- a/Discovery/Src/tInfoPreDive.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Src/tInfoPreDive.c Sat Nov 15 19:29:44 2025 +0100 @@ -70,7 +70,7 @@ } else { - memcpy (&pressureHistory[0],&pressureHistory[2],sizeof(pressureHistory) - 2); + memmove(&pressureHistory[0], &pressureHistory[2], sizeof(pressureHistory) - 2); pressureHistory[pressureHistoryIndex] = newValue; } } @@ -87,7 +87,7 @@ } else { - memcpy (&temperatureHistory[0],&temperatureHistory[2],sizeof(temperatureHistory) - 2); + memmove(&temperatureHistory[0], &temperatureHistory[2], sizeof(temperatureHistory) - 2); temperatureHistory[temperatureHistoryIndex] = newValue; } }
--- a/Discovery/Src/tMenu.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Src/tMenu.c Sat Nov 15 19:29:44 2025 +0100 @@ -42,6 +42,7 @@ #include "tMenuEditSystem.h" #include "tMenuEditXtra.h" #include "tMenuEditCustom.h" +#include "tMenuEditCvOption.h" #include "tMenuGas.h" #include "tMenuHardware.h" #include "tMenuPlanner.h" @@ -51,13 +52,16 @@ #include "tMenuCustom.h" /* Private types -------------------------------------------------------------*/ -#define MAXPAGES 11 +#define MAXPAGES 12 #define CURSOR_HIGH 25 #define TAB_HEADER_HIGH 25 #define TAB_BAR_HIGH 5 #define MENU_WDW_HIGH 390 #define KEY_LABEL_HIGH 25 /* Height of the label used for the the user keys */ +#define TAB_BAR_WIDTH 50 +#define TAB_BAR_SPACING 5 + #define SLOW_UPDATE_CNT 10 /* Some content shall not be update in short intervals => add prescalar */ #define MAXLINES 6 @@ -580,6 +584,7 @@ tM_add(StMDECO); tM_add(StMHARD); tM_add(StMCustom); + tM_add(StMOption); // tM_add(StMSYS); now in both modes } else @@ -649,6 +654,9 @@ id = tMCustom_refresh(0, text, &tabPosition, subtext); tM_build_page(id, text, tabPosition, subtext); + + id = tMCvOption_refresh(0, text, &tabPosition, subtext); + tM_build_page(id, text, tabPosition, subtext); } @@ -789,7 +797,7 @@ update_content_with_new_frame(page, text, tabPosition, subtext); break; case StMDECO: - if((line == 1) || (line == 3)) // dive mode or ppO2 limits (the later for correct MOD in gaslists) + if((line == get_lineOfID(StMDECO1_OC)) || (line == get_lineOfID(StMDECO3_PPO2Max))) // dive mode or ppO2 limits (the later for correct MOD in gaslists) { tM_rebuild_pages(); menu.lineMemoryForNavigationForPage[page] = line; // fix 160623 @@ -818,7 +826,12 @@ update_content_actual_page(text, tabPosition, subtext); break; case StMSYS: - if((line == 2) || (line == 3) || (line == 6)) + if((line == get_lineOfID(StMSYS1_DateTime)) || (line == get_lineOfID(StMSYS2_English)) +#ifdef ENABLE_SETTING_PROFILES + || (line == get_lineOfID(StMSYS_Profile))) +#else + ) +#endif { tM_rebuild_pages(); menu.lineMemoryForNavigationForPage[page] = line; // fix 160623 @@ -837,6 +850,11 @@ clean_line_actual_page(); update_content_actual_page(text, tabPosition, subtext); break; + case StMOption: + tMCvOption_refresh(line, text, &tabPosition, subtext); + clean_line_actual_page(); + update_content_actual_page(text, tabPosition, subtext); + break; default: break; } @@ -864,7 +882,10 @@ if((page == 0) || (line == 0)) return; - requestBuzzerActivation(0); + if( getBuzzerActivationRequest() != REQUEST_BUZZER_ONCE) + { + requestBuzzerActivation(REQUEST_BUZZER_OFF); + } menu.pageMemoryForNavigation = page; /* new test for 3button design */ @@ -947,7 +968,7 @@ { switch(get_globalState()) { - case StMSYS: tMSystem_checkLineStatus(); + case StMOption: tMCvOption_checkLineStatus(); break; case StMXTRA: tMXtra_checkLineStatus(); break; @@ -1150,6 +1171,9 @@ case StMCustom: openEdit_Custom(line); break; + case StMOption: + openEdit_CvOption(line); + break; default: break; } @@ -1347,19 +1371,21 @@ { "", "OC", "CC", - "SP", + "", "DATA", "DECO", "", "SYS", "", "", - "SIM" + "", + "SIM", + "" }; _Bool spacing[MAXPAGES+1] = { 0, - 0, // behind OC + 1, // behind OC 0, // behind CC 1, // behind SP 1, // behind DATA @@ -1367,7 +1393,8 @@ 1, // behind DECO2 0, // behind SYS1 0, // behind SYS2 - 1, // behind SYS3 + 0, // behind SYS3 + 1, // behind SYS4 1, // behind SIM 0 }; @@ -1375,7 +1402,7 @@ if(actual_menu_content == MENU_SURFACE) { spacing[3] = 0; /* Display extra menu directly after setpoint */ - sprintf(text8max[4],"OP"); + memset(text8max[4],0,8); } pBackup = tMscreen.FBStartAdress; @@ -1386,6 +1413,7 @@ gfx_write_page_number(&tMscreen ,menu.pageCountNumber[page],menu.pageCountTotal,0); + /* Find the matching master text if a tab has no direct name e.g. SYS subtabs */ while((text8max[pageText][0] == 0) && (pageText > 1)) { pageText--; @@ -1427,9 +1455,9 @@ /* Draw color bars */ if(!settingsGetPointer()->FlipDisplay) { - pDestination += 5 * 480; + pDestination += TAB_BAR_SPACING * 480; - for(j = 60; j > 0; j--) + for(j = TAB_BAR_WIDTH; j > 0; j--) { pDestination += (390 + 26); @@ -1440,13 +1468,13 @@ pDestination += 48; } - pDestination += 5 * 480; - positionText += 70; + pDestination += TAB_BAR_SPACING * 480; + positionText += TAB_BAR_WIDTH + 2* TAB_BAR_SPACING; if(((k == 4) && (actual_menu_content != MENU_SURFACE)) || ((k == 6) && (menu.pageCountNumber[5] == 0))) { - pDestination += 70 * 480; - positionText += 70; + pDestination += (TAB_BAR_WIDTH + 2* TAB_BAR_SPACING) * 480; + positionText += TAB_BAR_WIDTH + 2* TAB_BAR_SPACING; } if(spacing[k]) @@ -1495,3 +1523,9 @@ { return isGrey ? "\031" : ""; } + + +char printCheckbox(bool isChecked) +{ + return isChecked ? '\005' : '\006'; +}
--- a/Discovery/Src/tMenuCustom.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Src/tMenuCustom.c Sat Nov 15 19:29:44 2025 +0100 @@ -39,6 +39,7 @@ #include "gfx_fonts.h" #include "tInfo.h" #include "motion.h" +#include "ostc.h" /* Exported functions --------------------------------------------------------*/ @@ -119,24 +120,21 @@ textPointer += 2; #endif -#ifdef ENABLE_GPIO_V2 if((line == 0) || (line == 5)) { - /* MotionCtrl */ - text[textPointer++] = TXT_2BYTE; - text[textPointer++] = TXT2BYTE_BUZZER; - text[textPointer++] = ' '; - text[textPointer++] = TXT_Warning; - text[textPointer++] = '\t'; - if(settingsGetPointer()->warningBuzzer) - text[textPointer++] = '\005'; - else - text[textPointer++] = '\006'; + text[textPointer++] = TXT_2BYTE; + text[textPointer++] = TXT2BYTE_FLIPDISPLAY; + text[textPointer++] = '\t'; + if(settingsGetPointer()->FlipDisplay) + text[textPointer++] = '\005'; + else + text[textPointer++] = '\006'; + text[textPointer] = 0; + } strcpy(&text[textPointer],"\n\r"); textPointer += 2; -#endif return StMCustom; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Discovery/Src/tMenuCvOption.c Sat Nov 15 19:29:44 2025 +0100 @@ -0,0 +1,106 @@ +/////////////////////////////////////////////////////////////////////////////// +/// -*- coding: UTF-8 -*- +/// +/// \file Discovery/Src/tMenuCvOption.c +/// \brief Main Template file for Menu Page System settings +/// \author heinrichs weikamp gmbh +/// \date 24-Apr-2025 +/// +/// \details +/// +/// $Id$ +/////////////////////////////////////////////////////////////////////////////// +/// \par Copyright (c) 2014-2025 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 <http://www.gnu.org/licenses/>. +////////////////////////////////////////////////////////////////////////////// + +/* Includes ------------------------------------------------------------------*/ +#include "tMenu.h" +#include "tMenuCvOption.h" +#include "tHome.h" // for enum CUSTOMVIEWS and init_t7_compass() +#include "t7.h" + +/* Private function prototypes -----------------------------------------------*/ + +/* Exported functions --------------------------------------------------------*/ + +uint32_t tMCvOption_refresh(uint8_t line, char *text, uint16_t *tab, char *subtext) +{ + SSettings *data; + uint8_t textPointer; + + data = settingsGetPointer(); + textPointer = 0; + *tab = 300; + *subtext = 0; + + resetLineMask(StMOption); + + if((line == 0) || (line == 1)) + { + text[textPointer++] = TXT_2BYTE; + text[textPointer++] = TXT2BYTE_Compass; + text[textPointer++] = '\t'; + + if(settingsGetPointer()->compassBearing != 0) + { + textPointer += snprintf(&text[textPointer], 20, "(%03u`)", settingsGetPointer()->compassBearing % 360); + } + text[textPointer] = 0; + } + nextline(text,&textPointer); + if (line == 0 || line == 2) + { + if(t7_customview_disabled(CVIEW_Timer)) + { + text[textPointer++] = '\031'; /* change text color */ + textPointer += snprintf(&text[textPointer], 21, "%c%c\t%u:%02u \016\016[m:ss]\017", TXT_2BYTE, TXT2BYTE_Timer, data->timerDurationS / 60, data->timerDurationS % 60); + text[textPointer++] = '\020'; /* restore text color */ + } + else + { + textPointer += snprintf(&text[textPointer], 21, "%c%c\t%u:%02u \016\016[m:ss]\017", TXT_2BYTE, TXT2BYTE_Timer, data->timerDurationS / 60, data->timerDurationS % 60); + } + } + nextline(text,&textPointer); + +#ifdef ENABLE_PULSE_SENSOR_BT + if (line == 0 || line == 3) + { + textPointer += snprintf(&text[textPointer], 21, "%c%c", TXT_2BYTE, TXT2BYTE_Pulse); + } + nextline(text,&textPointer); + +#endif + + return StMOption; +} +void tMCvOption_checkLineStatus(void) +{ + uint8_t localLineMask = 0; + uint8_t lineMask = getLineMask(StMOption); + + if(t7_customview_disabled(CVIEW_Timer)) + { + localLineMask |= 1 << 2; + } + + if(lineMask != localLineMask) + { + updateMenu(); + } +} + +/* Private functions ---------------------------------------------------------*/
--- a/Discovery/Src/tMenuEdit.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Src/tMenuEdit.c Sat Nov 15 19:29:44 2025 +0100 @@ -42,10 +42,14 @@ #include "tMenuEditSystem.h" #include "tMenuEditXtra.h" #include "tMenuEditCustom.h" +#include "cv_heartbeat.h" /* Private types -------------------------------------------------------------*/ #define TEXTSIZE 16 +#define IDENT_MAY_INPUT_NUM 4 /* legacy value of ident.input struct */ +#define IDENT_MAX_INPUT_TEXT 9 /* 8 data items + 0 for string operations */ + typedef struct { uint32_t pEventFunction; @@ -63,9 +67,9 @@ { char orgText[32]; char newText[32]; - uint32_t input[4]; + uint32_t input[IDENT_MAX_INPUT_TEXT]; uint16_t coord[3]; - int8_t begin[4], size[4]; + int8_t begin[IDENT_MAX_INPUT_TEXT], size[IDENT_MAX_INPUT_TEXT]; tFont *fontUsed; uint32_t callerID; uint8_t maintype; @@ -85,6 +89,7 @@ FIELD_3DIGIT, FIELD_SDIGIT, FIELD_FLOAT, + FIELD_TEXT, FIELD_END } SField; @@ -229,7 +234,7 @@ case (StMHARD3_Sensor_Detect): case (StMHARD3_Sensor_Info): refreshFct = refresh_O2Sensors; break; - case (StMHARD2_Compass & MaskFieldDigit): + case (StMOption_Compass & MaskFieldDigit): refreshFct = refresh_CompassEdit; break; case (StMXTRA_CompassHeading & MaskFieldDigit): @@ -256,6 +261,11 @@ case StMCustom3_CViewSelection5: case StMCustom3_CViewSelection6: refreshFct = CustomviewDivemode_refresh; break; +#ifdef ENABLE_PULSE_SENSOR_BT + case (StMOption_Heartbeat): refreshFct = refresh_Heartbeat; + break; +#endif + #ifdef ENABLE_MOTION_CONTROL case (StMCustom5_CViewPortCalib & MaskFieldDigit): case StMCustom5_CViewPortLayout: @@ -284,7 +294,7 @@ { reset_SettingWarning(); GFX_logoAutoOff(); - ext_flash_write_settings(0); + ext_flash_write_settings(EF_SETTINGS,0); WriteSettings = 0; } } @@ -442,7 +452,7 @@ return 1; } - if(((block + 1) < 4) && (ident[actualId].size[block+1] > 0)) + if((((block + 1) < 4) || ((ident[actualId].maintype == FIELD_TEXT) && ((block + 1) < IDENT_MAX_INPUT_TEXT))) && (ident[actualId].size[block+1] > 0)) { block++; subBlockPosition = 0; @@ -476,7 +486,7 @@ content += ident[actualId].newText[ident[actualId].begin[block] + 1]; } else - if(ident[actualId].maintype == FIELD_NUMBERS) + if((ident[actualId].maintype == FIELD_NUMBERS) || (ident[actualId].maintype == FIELD_TEXT)) content = ident[actualId].newText[ident[actualId].begin[block] + subBlockPosition]; else if((ident[actualId].maintype == FIELD_ON_OFF) || (ident[actualId].maintype == FIELD_TOGGLE)) @@ -495,7 +505,7 @@ if(event[actualevid].callerID != ident[actualId].callerID) return; - if(ident[actualId].maintype == FIELD_NUMBERS) + if((ident[actualId].maintype == FIELD_NUMBERS) || (ident[actualId].maintype == FIELD_TEXT)) { oneCharText[0] = ident[actualId].newText[ident[actualId].begin[oldblock] + oldsubblockpos]; oneCharText[1] = 0; @@ -547,18 +557,34 @@ void mark_new_digit_of_actual_id_block_and_subBlock(void) { char oneCharText[2]; + char text[10]; uint16_t positionOffset; + uint8_t index = 0; + uint8_t textPos = 0; if(event[actualevid].callerID != ident[actualId].callerID) return; - if(ident[actualId].maintype == FIELD_NUMBERS) + if((ident[actualId].maintype == FIELD_NUMBERS) || (ident[actualId].maintype == FIELD_TEXT)) { oneCharText[0] = ident[actualId].newText[ident[actualId].begin[block] + subBlockPosition]; oneCharText[1] = 0; positionOffset = GFX_return_offset(ident[actualId].fontUsed, ident[actualId].newText, ident[actualId].begin[block] + subBlockPosition); write_content( ident[actualId].coord[0] + positionOffset, ident[actualId].coord[1], ident[actualId].coord[2], ident[actualId].fontUsed, oneCharText, CLUT_MenuEditDigit); } + if(ident[actualId].maintype == FIELD_TEXT) /* letter width may change from character to character => output end of string */ + { + if(block + 1 < 8) + { + for(index = block + 1; index < 8; index++) + { + text[textPos++] = ident[actualId].newText[ident[actualId].begin[index] + 0]; + } + text[textPos] = 0; + positionOffset = GFX_return_offset(ident[actualId].fontUsed, ident[actualId].newText, ident[actualId].begin[block + 1] + subBlockPosition); + write_content( ident[actualId].coord[0] + positionOffset, ident[actualId].coord[1], ident[actualId].coord[2], ident[actualId].fontUsed, text, CLUT_MenuEditFieldSelected); + } + } } @@ -582,7 +608,7 @@ block = 0; subBlockPosition = 0; - if(ident[actualId].maintype == FIELD_NUMBERS) + if((ident[actualId].maintype == FIELD_NUMBERS) || (ident[actualId].maintype == FIELD_TEXT)) { change_CLUT_entry(CLUT_MenuEditLineSelected, CLUT_MenuEditCursor); // old stuff? hw 150916, reactivated 150923, this shows which digit will be changed now as it marks the other grey/black @@ -690,7 +716,13 @@ break; case FIELD_SELECT: write_buttonTextline(TXT2BYTE_ButtonMinus, TXT2BYTE_ButtonEnter, TXT2BYTE_ButtonPlus); + break; + case FIELD_TEXT: + write_buttonTextline(TXT2BYTE_ButtonMinus, TXT2BYTE_ButtonEnter, TXT2BYTE_ButtonPlus); + if((newContent >= 'A') && (newContent <= '_')) + ident[actualId].newText[ident[actualId].begin[block] + subBlockPosition] = newContent; + mark_new_digit_of_actual_id_block_and_subBlock(); break; } } @@ -815,6 +847,9 @@ else if((ident[actualId].maintype == FIELD_NUMBERS) && (action == ACTION_BUTTON_ENTER) && (newContent >= '0') && (newContent <= '9')) ident[actualId].newText[ident[actualId].begin[block] + subBlockPosition] = newContent; + else + if((ident[actualId].maintype == FIELD_TEXT) && (action == ACTION_BUTTON_ENTER) && (newContent >= '0') && (newContent <= '9')) + ident[actualId].newText[ident[actualId].begin[block] + subBlockPosition] = newContent; if(action == ACTION_BUTTON_ENTER) { @@ -911,6 +946,10 @@ ident[actualId].newText[ident[actualId].begin[block] + subBlockPosition] = newContent; } + if ((ident[actualId].maintype == FIELD_TEXT) && (newContent >= 'A' && newContent <= '_')) + { + ident[actualId].newText[ident[actualId].begin[block] + subBlockPosition] = newContent; + } mark_new_digit_of_actual_id_block_and_subBlock(); } @@ -950,6 +989,9 @@ } else if (ident[actualId].maintype == FIELD_NUMBERS && newContent >= '0' && newContent <= '9') { ident[actualId].newText[ident[actualId].begin[block] + subBlockPosition] = newContent; } + if ((ident[actualId].maintype == FIELD_TEXT) && (newContent >= 'A' && newContent <= '_')) { + ident[actualId].newText[ident[actualId].begin[block] + subBlockPosition] = newContent; + } mark_new_digit_of_actual_id_block_and_subBlock(); } @@ -1018,7 +1060,27 @@ *pNewValue3 = sum[2]; *pNewValue4 = sum[3]; } +void evaluateNewStringText(uint32_t editID, uint8_t *pNewString) +{ + if(editID != ident[actualId].callerID) + return; + uint8_t i, digitCount; + uint8_t digit = '_'; + + memset(pNewString, 0 , IDENT_MAX_INPUT_TEXT); + + i = 0; + while( ident[actualId].size[i] && (i < IDENT_MAX_INPUT_TEXT - 1)) + { + for(digitCount = 0; digitCount < ident[actualId].size[i]; digitCount++) + { + digit = ident[actualId].newText[ident[actualId].begin[i] + digitCount]; + } + pNewString[i] = digit; + i++; + } +} uint8_t get_id_of(uint32_t editID) { @@ -1156,7 +1218,38 @@ id = backup_id; } +void tMenuEdit_newInputText(uint32_t editID, uint8_t* ptext) +{ + uint8_t backup_id, temp_id; + uint8_t index = 0; + temp_id = get_id_of(editID); + if(temp_id == 255) + return; + + backup_id = id; + id = temp_id; + + if(editID != ident[id].callerID) + { + temp_id = 0; + while((temp_id < IDENT_MAX_INPUT_TEXT) && (editID != ident[temp_id].callerID)) + temp_id++; + if(editID != ident[temp_id].callerID) + return; + id = temp_id; + } + for(index = 0; index < IDENT_MAX_INPUT_TEXT; index++) + { + ident[id].input[index] = *ptext++; + } + create_newText_for_Id(id); + if(id <= idLast) + change_CLUT_entry((CLUT_MenuEditField0 + id), CLUT_MenuEditFieldRegular); + write_content_of_Id(id); + + id = backup_id; +} void resetEnterPressedToStateBeforeButtonAction(void) { @@ -1257,6 +1350,20 @@ } } +void create_newText_for_Id_and_field_text(int8_t localId) +{ + uint8_t i; + + i = 0; + while( ident[localId].size[i] && (i < 9)) + { + if(ident[localId].input[i]) + ident[localId].newText[ident[localId].begin[i]] = ident[localId].input[i]; + i++; + } +} + + void create_newText_for_actual_Id_and_field_select(void) { create_newText_for_Id_and_field_select(actualId); @@ -1276,6 +1383,12 @@ return; } + if( ident[localId].maintype == FIELD_TEXT) + { + create_newText_for_Id_and_field_text(localId); + return; + } + while( ident[localId].size[i] && (i < 4)) { bool isNegative = false; @@ -1443,6 +1556,66 @@ write_field_udigit_and_2digit(FIELD_SDIGIT, editID, XleftGimpStyle, XrightGimpStyle, YtopGimpStyle, Font, text, ((input_u)int1).uint32, ((input_u)int2).uint32, ((input_u)int3).uint32, ((input_u)int4).uint32); } +void write_field_text(uint32_t editID, uint16_t XleftGimpStyle, uint16_t XrightGimpStyle, uint16_t YtopGimpStyle, const tFont *Font, const char *text, uint8_t* pInput) +{ + if(id >= 9) + return; + + int8_t beginTmp; + + ident[id].maintype = FIELD_TEXT; + ident[id].subtype = FIELD_TEXT; + + ident[id].coord[0] = XleftGimpStyle; + ident[id].coord[1] = XrightGimpStyle; + ident[id].coord[2] = YtopGimpStyle; + ident[id].fontUsed = (tFont *)Font; + ident[id].callerID = editID; + + strncpy(ident[id].orgText, text, 32); + strncpy(ident[id].newText, text, 32); + ident[id].orgText[31] = 0; + ident[id].newText[31] = 0; + + for(int i=0;i < IDENT_MAX_INPUT_TEXT -1;i++) + { + ident[id].input[i] = pInput[i]; + ident[id].size[i] = 0; + } + pInput[8] = 0; + + beginTmp = 0; + for(int i=0;i < IDENT_MAX_INPUT_TEXT;i++) + { + while((ident[id].orgText[beginTmp] != '#')&& ident[id].orgText[beginTmp]) + beginTmp++; + + if(ident[id].orgText[beginTmp] == '#') + { + + ident[id].begin[i] = beginTmp; + ident[id].size[i] = 1; + beginTmp = ident[id].begin[i] + ident[id].size[i]; + } + else + break; + } + + change_CLUT_entry((CLUT_MenuEditField0 + id), CLUT_MenuEditFieldRegular); + + create_newText_for_Id(id); + + if(editID == 0) + write_content_without_Id(); + else + { + write_content_of_Id(id); + if(!tME_stop) + idLast = id; + id++; + } +} + void write_field_select(uint32_t editID, uint16_t XleftGimpStyle, uint16_t XrightGimpStyle, uint16_t YtopGimpStyle, const tFont *Font, const char *text, uint8_t int1, uint8_t int2, uint8_t int3, uint8_t int4) {
--- a/Discovery/Src/tMenuEditCustom.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Src/tMenuEditCustom.c Sat Nov 15 19:29:44 2025 +0100 @@ -40,6 +40,7 @@ #include "motion.h" #include "tMenu.h" #include "tMenuSystem.h" +#include "ostc.h" #include <math.h> @@ -56,7 +57,7 @@ void openEdit_BigScreen(void); void openEdit_MotionCtrl(void); void openEdit_ViewPort(void); -void openEdit_WarningBuz(void); +void openEdit_FlipDisplay(void); void refresh_Customviews(void); void setMenuContentStructure(); char customview_TXT2BYTE_helper(uint8_t customViewId); @@ -379,10 +380,10 @@ case 5: openEdit_ViewPort(); break; #endif -#ifdef ENABLE_GPIO_V2 - case 5: openEdit_WarningBuz(); - break; -#endif + case 5: + openEdit_FlipDisplay(); + break; + } } @@ -473,19 +474,16 @@ setEvent(StMCustom5_CViewPortControl, (uint32_t)OnAction_CViewPortControl); #endif } -void openEdit_WarningBuz(void) +void openEdit_FlipDisplay(void) { - SSettings *pSettings = settingsGetPointer(); +/* does not work like this resetEnterPressedToStateBeforeButtonAction(); */ - if(pSettings->warningBuzzer == 0) - { - pSettings->warningBuzzer = 1; - } - else - { - pSettings->warningBuzzer = 0; - } - exitMenuEdit_to_Menu_with_Menu_Update_do_not_write_settings_for_this_only(); + bool oldValue = settingsGetPointer()->FlipDisplay; + + setFlipDisplay(!oldValue); + + exitEditWithUpdate(); + exitMenuEdit_to_Home(); } char customview_TXT2BYTE_helper(uint8_t customViewId) @@ -530,6 +528,10 @@ case CVIEW_noneOrDebug: text = TXT2BYTE_DispNoneDbg; break; +#ifdef ENABLE_LOGGER_WINDOW + case CVIEW_Logger: text = TXT2BYTE_Logger; + break; +#endif default: break; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Discovery/Src/tMenuEditCvOption.c Sat Nov 15 19:29:44 2025 +0100 @@ -0,0 +1,362 @@ +/////////////////////////////////////////////////////////////////////////////// +/// -*- coding: UTF-8 -*- +/// +/// \file Discovery/Src/tMenuEditCvOption.c +/// \brief Menu for configuration depended items +/// \author heinrichs weikamp gmbh +/// \date 24-Apr-2025 +/// +/// \details +/// +/// $Id$ +/////////////////////////////////////////////////////////////////////////////// +/// \par Copyright (c) 2014-2025 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 <http://www.gnu.org/licenses/>. +////////////////////////////////////////////////////////////////////////////// + +/* Includes ------------------------------------------------------------------*/ +#include "tMenuEditCvOption.h" +#include "tMenuEdit.h" + +#include "gfx_fonts.h" +#include "ostc.h" +#include "tMenuEdit.h" +#include "tHome.h" + +#include "cv_heartbeat.h" + +/* Private function prototypes -----------------------------------------------*/ +static void openEdit_Timer(void); +void openEdit_Compass(void); + +/* Announced function prototypes -----------------------------------------------*/ +uint8_t OnAction_Compass (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); +static uint8_t OnAction_CompassDeclination(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); +uint8_t OnAction_Bearing (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); +uint8_t OnAction_BearingClear (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); +uint8_t OnAction_InertiaLevel (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); +static uint8_t OnAction_Timer(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); + +/* Exported functions --------------------------------------------------------*/ + +void openEdit_CvOption(uint8_t line) +{ + set_globalState_Menu_Line(line); + + switch(line) + { + case 1: + default: resetMenuEdit(CLUT_MenuPageHardware); + openEdit_Compass(); + break; + case 2: openEdit_Timer(); + break; +#ifdef ENABLE_PULSE_SENSOR_BT + case 3: openEdit_Heartbeat(); +#endif + break; + } +} + +/* Private functions ---------------------------------------------------------*/ + +static uint8_t OnAction_CompassDeclination(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) +{ + SSettings *settings = settingsGetPointer(); + uint8_t digitContentNew; + switch (action) { + case ACTION_BUTTON_ENTER: + + return digitContent; + case ACTION_BUTTON_ENTER_FINAL: + { + int32_t compassDeclinationDeg; + evaluateNewString(editId, (uint32_t *)&compassDeclinationDeg, NULL, NULL, NULL); + + if (compassDeclinationDeg > 99) { + compassDeclinationDeg = 99; + } else if (compassDeclinationDeg < -99) { + compassDeclinationDeg = -99; + } + + settings->compassDeclinationDeg = compassDeclinationDeg; + + tMenuEdit_newInput(editId, ((input_u)compassDeclinationDeg).uint32, 0, 0, 0); + } + + break; + case ACTION_BUTTON_NEXT: + if (digitNumber == 0) { + digitContentNew = togglePlusMinus(digitContent); + } else { + digitContentNew = digitContent + 1; + if (digitContentNew > '9') { + digitContentNew = '0'; + } + } + + return digitContentNew; + case ACTION_BUTTON_BACK: + if (digitNumber == 0) { + digitContentNew = togglePlusMinus(digitContent); + } else { + digitContentNew = digitContent - 1; + if (digitContentNew < '0') { + digitContentNew = '9'; + } + } + + return digitContentNew; + } + + return UNSPECIFIC_RETURN; +} + + +static void showCompassDeclination(SSettings *settings, bool isRefresh) +{ + char text[16]; + snprintf(text, 16, "%c%c:", TXT_2BYTE, TXT2BYTE_CompassDeclination); + write_label_var(30, 800, ME_Y_LINE6, &FontT48, text); + if (isRefresh) { + tMenuEdit_refresh_field(StMOption_Compass_Declination); + } else { + write_field_sdigit(StMOption_Compass_Declination, 500, 800, ME_Y_LINE6, &FontT48, "\034###`", settings->compassDeclinationDeg, 0, 0, 0); + } +} + + +void refresh_CompassEdit(void) +{ + SSettings *settings = settingsGetPointer(); + + uint16_t heading; + char text[32]; + uint8_t textIndex = 0; + + text[0] = '\001'; + text[1] = TXT_2BYTE; + text[2] = TXT2BYTE_Compass; + text[3] = 0; + write_topline(text); + + if(settings->compassInertia) + { + heading = (uint16_t)compass_getCompensated(); + } + else + { + heading = (uint16_t)stateUsed->lifeData.compass_heading; + } + snprintf(text,32,"\001%03i`",heading); + write_label_var( 0, 800, ME_Y_LINE1, &FontT54, text); + + tMenuEdit_refresh_field(StMOption_Compass_SetCourse); + tMenuEdit_refresh_field(StMOption_Compass_Calibrate); + tMenuEdit_refresh_field(StMOption_Compass_ResetCourse); + text[textIndex++] = TXT_2BYTE; + text[textIndex++] = TXT2BYTE_CompassInertia; + text[textIndex++] = ':'; + text[textIndex++] = ' '; + text[textIndex++] = '0' + settings->compassInertia; + + write_label_var(30, 800, ME_Y_LINE5, &FontT48, text); + + showCompassDeclination(settings, true); + + write_buttonTextline(TXT2BYTE_ButtonBack,TXT2BYTE_ButtonEnter,TXT2BYTE_ButtonNext); +} + + +void openEdit_Compass(void) +{ + SSettings *settings = settingsGetPointer(); + + char text[10]; + uint8_t textIndex = 0; + + + set_globalState(StMOption_Compass); + resetMenuEdit(CLUT_MenuPageHardware); + + text[textIndex++] = '\001'; + text[textIndex++] = TXT_2BYTE; + text[textIndex++] = TXT2BYTE_Compass; + text[textIndex++] = 0; + write_topline(text); + + text[0] = TXT_2BYTE; + text[2] = 0; + + text[1] = TXT2BYTE_SetBearing; + write_field_button(StMOption_Compass_SetCourse, 30, 800, ME_Y_LINE2, &FontT48, text); + + text[1] = TXT2BYTE_ResetBearing; + write_field_button(StMOption_Compass_ResetCourse, 30, 800, ME_Y_LINE3, &FontT48, text); + + text[1] = TXT2BYTE_CompassCalib; + write_field_button(StMOption_Compass_Calibrate, 30, 800, ME_Y_LINE4, &FontT48, text); + + text[1] = TXT2BYTE_CompassInertia; + textIndex = 2; + text[textIndex++] = ':'; + text[textIndex++] = ' '; + text[textIndex++] = '0' + settings->compassInertia; + text[textIndex++] = 0; + + write_field_button(StMOption_Compass_Inertia, 30, 800, ME_Y_LINE5, &FontT48, text); + + showCompassDeclination(settings, false); + + setEvent(StMOption_Compass_SetCourse, (uint32_t)OnAction_Bearing); + setEvent(StMOption_Compass_ResetCourse, (uint32_t)OnAction_BearingClear); + setEvent(StMOption_Compass_Calibrate, (uint32_t)OnAction_Compass); + setEvent(StMOption_Compass_Inertia, (uint32_t)OnAction_InertiaLevel); + setEvent(StMOption_Compass_Declination, (uint32_t)OnAction_CompassDeclination); + + tMenuEdit_select(StMOption_Compass_SetCourse); + + write_buttonTextline(TXT2BYTE_ButtonBack,TXT2BYTE_ButtonEnter,TXT2BYTE_ButtonNext); +} + + +uint8_t OnAction_Compass (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) +{ + calibrateCompass(); + return EXIT_TO_INFO_COMPASS; +} + + +uint8_t OnAction_Bearing (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) +{ + if((int16_t)stateUsed->lifeData.compass_heading != -1) + { + settingsGetPointer()->compassBearing = (int16_t)stateUsed->lifeData.compass_heading; + } + else + { + settingsGetPointer()->compassBearing = 0; + } + + if(settingsGetPointer()->compassBearing == 0) + settingsGetPointer()->compassBearing = 360; + return UPDATE_AND_EXIT_TO_MENU; +} + + +uint8_t OnAction_BearingClear (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) +{ + settingsGetPointer()->compassBearing = 0; + return UPDATE_AND_EXIT_TO_MENU; +} + + +uint8_t OnAction_InertiaLevel (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) +{ + uint8_t newLevel = 0; + + newLevel = settingsGetPointer()->compassInertia + 1; + if(newLevel > MAX_COMPASS_COMP) + { + newLevel = 0; + } + settingsGetPointer()->compassInertia = newLevel; + return UPDATE_DIVESETTINGS; +} + +static void openEdit_Timer(void) +{ + SSettings *settings = settingsGetPointer(); + + char text[32]; + snprintf(text, 32, "\001%c%c", TXT_2BYTE, TXT2BYTE_Timer); + write_topline(text); + + set_globalState(StMOption_Timer); + resetMenuEdit(CLUT_MenuPageCvOption); + + uint16_t yPos = ME_Y_LINE_BASE + get_globalState_Menu_Line() * ME_Y_LINE_STEP; + snprintf(text, 32, "%c%c", TXT_2BYTE, TXT2BYTE_Timer); + write_label_var(30, 299, yPos, &FontT48, text); + write_field_udigit(StMOption_Timer_Value, 300, 392, yPos, &FontT48, "#:##", settings->timerDurationS / 60, settings->timerDurationS % 60, 0, 0); + write_label_var(393, 800, yPos, &FontT48, "\016\016 [m:ss]\017"); + + write_buttonTextline(TXT2BYTE_ButtonMinus, TXT2BYTE_ButtonEnter, TXT2BYTE_ButtonPlus); + + setEvent(StMOption_Timer_Value, (uint32_t)OnAction_Timer); + startEdit(); +} +static uint8_t OnAction_Timer(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) +{ + SSettings *settings = settingsGetPointer(); + uint8_t digitContentNew; + switch (action) { + case ACTION_BUTTON_ENTER: + + return digitContent; + case ACTION_BUTTON_ENTER_FINAL: + { + uint32_t timerM; + uint32_t timerS; + evaluateNewString(editId, &timerM, &timerS, 0, 0); + if (timerM > 9) { + timerM = 9; + } + if (timerS > 59) { + timerS = 59; + } + + uint16_t timerDurationS = 60 * timerM + timerS; + + if (timerDurationS < 1) { + timerDurationS = 1; + } + + if (timerDurationS != settings->timerDurationS) { + settings->timerDurationS = timerDurationS; + + disableTimer(); + + tMenuEdit_newInput(editId, settings->timerDurationS / 60, settings->timerDurationS % 60, 0, 0); + } + + settings->cv_configuration |= (1 << CVIEW_Timer); + + return EXIT_TO_MENU; + } + case ACTION_BUTTON_NEXT: + digitContentNew = digitContent + 1; + if ((blockNumber == 1 && digitNumber == 0 && digitContentNew > '5') || digitContentNew > '9') { + digitContentNew = '0'; + } + + return digitContentNew; + case ACTION_BUTTON_BACK: + digitContentNew = digitContent - 1; + if (digitContentNew < '0') { + if (blockNumber == 1 && digitNumber == 0) { + digitContentNew = '5'; + } else { + digitContentNew = '9'; + } + } + + return digitContentNew; + } + + return EXIT_TO_MENU; +} + +
--- a/Discovery/Src/tMenuEditHardware.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Src/tMenuEditHardware.c Sat Nov 15 19:29:44 2025 +0100 @@ -43,34 +43,27 @@ #include "data_exchange_main.h" -extern void tM_build_pages(void); +//extern void tM_build_pages(void); /* Private function prototypes -----------------------------------------------*/ void openEdit_Bluetooth(void); -void openEdit_Compass(void); void openEdit_O2Sensors(void); void openEdit_Brightness(void); //void openEdit_Luftintegration(void); void openEdit_ButtonSens(void); -void openEdit_FlipDisplay(void); +void openEdit_WarningBuz(void); + /* Announced function prototypes -----------------------------------------------*/ -uint8_t OnAction_Compass (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); -uint8_t OnAction_Bearing (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); -uint8_t OnAction_BearingClear (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); -uint8_t OnAction_InertiaLevel (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); -//uint8_t OnAction_ExitHardw (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); uint8_t OnAction_Sensor1 (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); uint8_t OnAction_Sensor2 (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); uint8_t OnAction_Sensor3 (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); uint8_t OnAction_O2_Calibrate (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); -//uint8_t OnAction_O2_Source (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); uint8_t OnAction_Sensor_Info (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); uint8_t OnAction_Sensor_Detect (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); uint8_t OnAction_Button (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); uint8_t OnAction_ButtonBalance (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); uint8_t OnAction_ButtonLock (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); -// not required uint8_t OnAction_Bluetooth (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); /* Exported functions --------------------------------------------------------*/ @@ -87,26 +80,20 @@ switch(line) { case 1: - default: - openEdit_Bluetooth(); - break; - case 2: - resetMenuEdit(CLUT_MenuPageHardware); - openEdit_Compass(); - break; - case 3: - openEdit_O2Sensors(); - break; - case 4: - openEdit_Brightness(); - break; - case 5: - resetMenuEdit(CLUT_MenuPageHardware); - openEdit_ButtonSens(); - break; - case 6: - openEdit_FlipDisplay(); - break; + default: openEdit_Bluetooth(); + break; + case 2: openEdit_O2Sensors(); + break; + case 3: openEdit_Brightness(); + break; + case 4: resetMenuEdit(CLUT_MenuPageHardware); + openEdit_ButtonSens(); + break; + case 5: if(isNewDisplay()) + { + openEdit_WarningBuz(); + } + break; } } @@ -131,245 +118,24 @@ exitMenuEdit_to_Menu_with_Menu_Update_do_not_write_settings_for_this_only(); } -void openEdit_FlipDisplay(void) +void openEdit_WarningBuz(void) { -/* does not work like this resetEnterPressedToStateBeforeButtonAction(); */ - SSettings *pSettings = settingsGetPointer(); - if(pSettings->FlipDisplay == 0) - { - pSettings->FlipDisplay = 1; - } - else + if(pSettings->warningBuzzer == 0) { - pSettings->FlipDisplay = 0; - } - /* reinit all views */ - tHome_init(); - tI_init(); - tM_init(); - tMenuEdit_init(); - tInfoLog_init(); - tM_build_pages(); - GFX_build_logo_frame(); - GFX_build_hw_background_frame(); - - exitEditWithUpdate(); - exitMenuEdit_to_Home(); -} - -static uint8_t OnAction_CompassDeclination(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) -{ - SSettings *settings = settingsGetPointer(); - uint8_t digitContentNew; - switch (action) { - case ACTION_BUTTON_ENTER: - - return digitContent; - case ACTION_BUTTON_ENTER_FINAL: - { - int32_t compassDeclinationDeg; - evaluateNewString(editId, (uint32_t *)&compassDeclinationDeg, NULL, NULL, NULL); - - if (compassDeclinationDeg > 99) { - compassDeclinationDeg = 99; - } else if (compassDeclinationDeg < -99) { - compassDeclinationDeg = -99; - } - - settings->compassDeclinationDeg = compassDeclinationDeg; - - tMenuEdit_newInput(editId, ((input_u)compassDeclinationDeg).uint32, 0, 0, 0); - } - - break; - case ACTION_BUTTON_NEXT: - if (digitNumber == 0) { - digitContentNew = togglePlusMinus(digitContent); - } else { - digitContentNew = digitContent + 1; - if (digitContentNew > '9') { - digitContentNew = '0'; - } - } - - return digitContentNew; - case ACTION_BUTTON_BACK: - if (digitNumber == 0) { - digitContentNew = togglePlusMinus(digitContent); - } else { - digitContentNew = digitContent - 1; - if (digitContentNew < '0') { - digitContentNew = '9'; - } - } - - return digitContentNew; - } - - return UNSPECIFIC_RETURN; -} - - -static void showCompassDeclination(SSettings *settings, bool isRefresh) -{ - char text[16]; - snprintf(text, 16, "%c%c:", TXT_2BYTE, TXT2BYTE_CompassDeclination); - write_label_var(30, 800, ME_Y_LINE6, &FontT48, text); - if (isRefresh) { - tMenuEdit_refresh_field(StMHARD2_Compass_Declination); - } else { - write_field_sdigit(StMHARD2_Compass_Declination, 500, 800, ME_Y_LINE6, &FontT48, "\034###`", settings->compassDeclinationDeg, 0, 0, 0); - } -} - - -void refresh_CompassEdit(void) -{ - SSettings *settings = settingsGetPointer(); - - uint16_t heading; - char text[32]; - uint8_t textIndex = 0; - - text[0] = '\001'; - text[1] = TXT_2BYTE; - text[2] = TXT2BYTE_Compass; - text[3] = 0; - write_topline(text); - - if(settings->compassInertia) - { - heading = (uint16_t)compass_getCompensated(); + pSettings->warningBuzzer = 1; + requestBuzzerActivation(REQUEST_BUZZER_ONCE); } else { - heading = (uint16_t)stateUsed->lifeData.compass_heading; + pSettings->warningBuzzer = 0; + deactivateBuzzer(); } - snprintf(text,32,"\001%03i`",heading); - write_label_var( 0, 800, ME_Y_LINE1, &FontT54, text); - - tMenuEdit_refresh_field(StMHARD2_Compass_SetCourse); - tMenuEdit_refresh_field(StMHARD2_Compass_Calibrate); - tMenuEdit_refresh_field(StMHARD2_Compass_ResetCourse); - text[textIndex++] = TXT_2BYTE; - text[textIndex++] = TXT2BYTE_CompassInertia; - text[textIndex++] = ':'; - text[textIndex++] = ' '; - text[textIndex++] = '0' + settings->compassInertia; - - write_label_var(30, 800, ME_Y_LINE5, &FontT48, text); - - showCompassDeclination(settings, true); - - write_buttonTextline(TXT2BYTE_ButtonBack,TXT2BYTE_ButtonEnter,TXT2BYTE_ButtonNext); + exitMenuEdit_to_Menu_with_Menu_Update_do_not_write_settings_for_this_only(); } -void openEdit_Compass(void) -{ - SSettings *settings = settingsGetPointer(); - - char text[10]; - uint8_t textIndex = 0; - - - set_globalState(StMHARD2_Compass); - resetMenuEdit(CLUT_MenuPageHardware); - - text[textIndex++] = '\001'; - text[textIndex++] = TXT_2BYTE; - text[textIndex++] = TXT2BYTE_Compass; - text[textIndex++] = 0; - write_topline(text); - - text[0] = TXT_2BYTE; - text[2] = 0; - - text[1] = TXT2BYTE_SetBearing; - write_field_button(StMHARD2_Compass_SetCourse, 30, 800, ME_Y_LINE2, &FontT48, text); - - text[1] = TXT2BYTE_ResetBearing; - write_field_button(StMHARD2_Compass_ResetCourse, 30, 800, ME_Y_LINE3, &FontT48, text); - - text[1] = TXT2BYTE_CompassCalib; - write_field_button(StMHARD2_Compass_Calibrate, 30, 800, ME_Y_LINE4, &FontT48, text); - - text[1] = TXT2BYTE_CompassInertia; - textIndex = 2; - text[textIndex++] = ':'; - text[textIndex++] = ' '; - text[textIndex++] = '0' + settings->compassInertia; - text[textIndex++] = 0; - - write_field_button(StMHARD2_Compass_Inertia, 30, 800, ME_Y_LINE5, &FontT48, text); - - showCompassDeclination(settings, false); - - setEvent(StMHARD2_Compass_SetCourse, (uint32_t)OnAction_Bearing); - setEvent(StMHARD2_Compass_ResetCourse, (uint32_t)OnAction_BearingClear); - setEvent(StMHARD2_Compass_Calibrate, (uint32_t)OnAction_Compass); - setEvent(StMHARD2_Compass_Inertia, (uint32_t)OnAction_InertiaLevel); - setEvent(StMHARD2_Compass_Declination, (uint32_t)OnAction_CompassDeclination); - - tMenuEdit_select(StMHARD2_Compass_SetCourse); - - write_buttonTextline(TXT2BYTE_ButtonBack,TXT2BYTE_ButtonEnter,TXT2BYTE_ButtonNext); -} - - -uint8_t OnAction_Compass (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) -{ - calibrateCompass(); - return EXIT_TO_INFO_COMPASS; -} - - -uint8_t OnAction_Bearing (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) -{ - if((int16_t)stateUsed->lifeData.compass_heading != -1) - { - settingsGetPointer()->compassBearing = (int16_t)stateUsed->lifeData.compass_heading; - } - else - { - settingsGetPointer()->compassBearing = 0; - } - - if(settingsGetPointer()->compassBearing == 0) - settingsGetPointer()->compassBearing = 360; - return UPDATE_AND_EXIT_TO_MENU; -} - - -uint8_t OnAction_BearingClear (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) -{ - settingsGetPointer()->compassBearing = 0; - return UPDATE_AND_EXIT_TO_MENU; -} - - -uint8_t OnAction_InertiaLevel (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) -{ - uint8_t newLevel = 0; - - newLevel = settingsGetPointer()->compassInertia + 1; - if(newLevel > MAX_COMPASS_COMP) - { - newLevel = 0; - } - settingsGetPointer()->compassInertia = newLevel; - return UPDATE_DIVESETTINGS; -} - -/* -uint8_t OnAction_ExitHardw (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) -{ - return EXIT_TO_MENU; -} -*/ - void refresh_O2Sensors(void) { char strSensorId[20];
--- a/Discovery/Src/tMenuEditPlanner.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Src/tMenuEditPlanner.c Sat Nov 15 19:29:44 2025 +0100 @@ -396,11 +396,7 @@ resultPage = 0; pDecoinfo = simulation_decoplaner(tMplan_depth_meter, tMplan_intervall_time_minutes, tMplan_dive_time_minutes, gasChangeList); - simulation_evaluate_profil( &tMplan_pGasConsumption, - &tMplan_Summary, - tMplan_depth_meter, tMplan_dive_time_minutes, tMplan_gasConsumTravel, tMplan_gasConsumDeco, - pDecoinfo, - gasChangeList); + simulation_evaluate_profil(&tMplan_pGasConsumption[0], &tMplan_Summary, tMplan_depth_meter, tMplan_dive_time_minutes, tMplan_gasConsumTravel, tMplan_gasConsumDeco, pDecoinfo, gasChangeList); // simulation_gas_consumption(tMplan_pGasConsumption, tMplan_depth_meter, tMplan_dive_time_minutes, pDecoinfo, tMplan_gasConsumTravel, tMplan_gasConsumDeco, gasChangeList); // simulation_helper_change_points(&tMplan_Summary, tMplan_depth_meter, tMplan_dive_time_minutes, pDecoinfo, gasChangeListDepth);
--- a/Discovery/Src/tMenuEditSystem.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Src/tMenuEditSystem.c Sat Nov 15 19:29:44 2025 +0100 @@ -46,18 +46,38 @@ /*#define HAVE_DEBUG_VIEW */ static uint8_t infoPage = 0; +#ifdef ENABLE_SETTING_PROFILES +static uint32_t profileStartCrc[NUMBER_OF_PROFILES]; +static uint8_t profileActiveStart = 0; +#endif /* Private function prototypes -----------------------------------------------*/ void openEdit_DateTime(void); void openEdit_DateFormat(void); void openEdit_Language(void); void openEdit_Design(void); +#ifdef ENABLE_SETTING_PROFILES +void openEdit_Profile(void); +#endif void openEdit_Information(void); void openEdit_Reset(void); void openEdit_Maintenance(void); //void openEdit_ShowDebugInfo(void); //void openEdit_Salinity(void); +static uint32_t swapBytes(uint32_t source) +{ + uint32_t ret = 0; + + ret = ((source & 0x000000FF) << 24) + | ((source & 0x0000FF00) << 8) + | ((source & 0x00FF0000) >> 8) + | ((source & 0xFF000000) >> 24); + + return ret; +} + + /* Announced function prototypes -----------------------------------------------*/ uint8_t OnAction_Date (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); uint8_t OnAction_Time (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); @@ -81,7 +101,10 @@ uint8_t OnAction_Units (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); uint8_t OnAction_Colorscheme (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); uint8_t OnAction_DebugInfo (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); - +#ifdef ENABLE_SETTING_PROFILES +uint8_t OnAction_Profile(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); +uint8_t OnAction_SetProfile(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); +#endif uint8_t OnAction_Exit (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); uint8_t OnAction_Confirm (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); uint8_t OnAction_Maintenance (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); @@ -101,7 +124,9 @@ #ifdef SCREENTEST uint8_t OnAction_ScreenTest (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); #endif -uint8_t OnAction_Information (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); +uint8_t OnAction_Information (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); +uint8_t OnAction_FlashBootloader (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); + /* uint8_t OnAction_Salinity (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); uint8_t OnAction_TestCLog (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); @@ -109,87 +134,6 @@ /* Exported functions --------------------------------------------------------*/ -static uint8_t OnAction_Timer(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) -{ - SSettings *settings = settingsGetPointer(); - uint8_t digitContentNew; - switch (action) { - case ACTION_BUTTON_ENTER: - - return digitContent; - case ACTION_BUTTON_ENTER_FINAL: - { - uint32_t timerM; - uint32_t timerS; - evaluateNewString(editId, &timerM, &timerS, 0, 0); - if (timerM > 9) { - timerM = 9; - } - if (timerS > 59) { - timerS = 59; - } - - uint16_t timerDurationS = 60 * timerM + timerS; - - if (timerDurationS < 1) { - timerDurationS = 1; - } - - if (timerDurationS != settings->timerDurationS) { - settings->timerDurationS = timerDurationS; - - disableTimer(); - - tMenuEdit_newInput(editId, settings->timerDurationS / 60, settings->timerDurationS % 60, 0, 0); - } - - return EXIT_TO_MENU; - } - case ACTION_BUTTON_NEXT: - digitContentNew = digitContent + 1; - if ((blockNumber == 1 && digitNumber == 0 && digitContentNew > '5') || digitContentNew > '9') { - digitContentNew = '0'; - } - - return digitContentNew; - case ACTION_BUTTON_BACK: - digitContentNew = digitContent - 1; - if (digitContentNew < '0') { - if (blockNumber == 1 && digitNumber == 0) { - digitContentNew = '5'; - } else { - digitContentNew = '9'; - } - } - - return digitContentNew; - } - - return EXIT_TO_MENU; -} - - -static void openEdit_Timer(void) -{ - SSettings *settings = settingsGetPointer(); - - char text[32]; - snprintf(text, 32, "\001%c%c", TXT_2BYTE, TXT2BYTE_Timer); - write_topline(text); - - uint16_t yPos = ME_Y_LINE_BASE + get_globalState_Menu_Line() * ME_Y_LINE_STEP; - snprintf(text, 32, "%c%c", TXT_2BYTE, TXT2BYTE_Timer); - write_label_var(30, 299, yPos, &FontT48, text); - write_field_udigit(StMSYS_Timer, 300, 392, yPos, &FontT48, "#:##", settings->timerDurationS / 60, settings->timerDurationS % 60, 0, 0); - write_label_var(393, 800, yPos, &FontT48, "\016\016 [m:ss]\017"); - - write_buttonTextline(TXT2BYTE_ButtonMinus, TXT2BYTE_ButtonEnter, TXT2BYTE_ButtonPlus); - - setEvent(StMSYS_Timer, (uint32_t)OnAction_Timer); - startEdit(); -} - - void openEdit_System(uint8_t line) { set_globalState_Menu_Line(line); @@ -197,36 +141,33 @@ if(actual_menu_content == MENU_SURFACE) { - switch(line) - { - case 1: - default: - openEdit_DateTime(); - break; - case 2: - openEdit_Timer(); - break; - case 3: - openEdit_Language(); - break; - case 4: - openEdit_Design(); - break; - case 5: - openEdit_Information(); - break; - case 6: - openEdit_Reset(); - break; -/* - case 3: - openEdit_DecoFutureTTS(); - break; - case 4: - openEdit_DecoLastStop(); - break; -*/ - } + + if(line == get_lineOfID(StMSYS1_DateTime)) + { + openEdit_DateTime(); + } + else if(line == get_lineOfID(StMSYS2_English)) + { + openEdit_Language(); + } + else if(line == get_lineOfID(StMSYS3_Units)) + { + openEdit_Design(); + } + else if(line == get_lineOfID(StMSYS4_Info)) + { + openEdit_Information(); + } + else if(line == get_lineOfID(StMSYS5_ResetAll)) + { + openEdit_Reset(); + } +#ifdef ENABLE_SETTING_PROFILES + else if(line == get_lineOfID(StMSYS_Profile)) + { + openEdit_Profile(); + } +#endif } else { @@ -247,7 +188,7 @@ char formatStr[20]; SSettings *pSettings; const SFirmwareData *pFirmwareInfo; -#if defined ENABLE_GNSS_SUPPORT || defined ENABLE_GPIO_V2 +#if defined ENABLE_GNSS_INTERN || defined ENABLE_GNSS_EXTERN uint8_t localHours = 0; uint8_t localMinutes = 0; #endif @@ -285,7 +226,7 @@ write_label_fix( 20, 340, ME_Y_LINE2, &FontT42, TXT_Format); write_label_fix( 20, 340, ME_Y_LINE3, &FontT42, TXT_DateConfig); write_label_fix( 20, 790, ME_Y_LINE4, &FontT42, TXT_Format); -#if defined ENABLE_GNSS_SUPPORT || defined ENABLE_GPIO_V2 +#if defined ENABLE_GNSS_INTERN || defined ENABLE_GNSS_EXTERN write_label_var( 20, 340, ME_Y_LINE5, &FontT42, "GNSS"); snprintf(text, 32, "%c%c", TXT_2BYTE, TXT2BYTE_TIMEZONE); write_label_var( 20, 340, ME_Y_LINE6, &FontT42, text); @@ -307,7 +248,7 @@ } tMenuEdit_newButtonText(StMSYS1_FORMAT, formatStr); -#if defined ENABLE_GNSS_SUPPORT || defined ENABLE_GPIO_V2 +#if defined ENABLE_GNSS_INTERN || defined ENABLE_GNSS_EXTERN if(pStateReal->lifeData.gnssData.alive & GNSS_ALIVE_STATE_TIME) { convertUTCToLocal(pStateReal->lifeData.gnssData.DateTime.hour, pStateReal->lifeData.gnssData.DateTime.min, &localHours, &localMinutes); @@ -373,7 +314,7 @@ write_label_fix( 20, 340, ME_Y_LINE2, &FontT42, TXT_Format); write_label_fix( 20, 340, ME_Y_LINE3, &FontT42, TXT_DateConfig); write_label_fix( 20, 790, ME_Y_LINE4, &FontT42, TXT_Format); -#if defined ENABLE_GNSS_SUPPORT || defined ENABLE_GPIO_V2 +#if defined ENABLE_GNSS_INTERN || defined ENABLE_GNSS_EXTERN write_label_var( 20, 340, ME_Y_LINE5, &FontT42, "GNSS"); snprintf(text, 32, "%c%c", TXT_2BYTE, TXT2BYTE_TIMEZONE); write_label_var( 20, 340, ME_Y_LINE6, &FontT42, text); @@ -395,7 +336,7 @@ write_field_button(StMSYS1_FORMAT, 320, 790, ME_Y_LINE4, &FontT48, formatStr); -#if defined ENABLE_GNSS_SUPPORT || defined ENABLE_GPIO_V2 +#if defined ENABLE_GNSS_INTERN || defined ENABLE_GNSS_EXTERN snprintf(text, 32, "--:--"); write_field_button(StMSYS1_GNSSDT, 320, 790, ME_Y_LINE5, &FontT48, text); write_field_sdigit(StMSYS1_ZONE, 320, 780, ME_Y_LINE6, &FontT48, "UTC: ###:###", pSettings->timeZone.hours, pSettings->timeZone.minutes,0,0); @@ -405,7 +346,7 @@ setEvent(StMSYS1_Time, (uint32_t)OnAction_Time); setEvent(StMSYS1_12HR, (uint32_t)OnAction_12HR); setEvent(StMSYS1_FORMAT, (uint32_t)OnAction_Format); -#if defined ENABLE_GNSS_SUPPORT || defined ENABLE_GPIO_V2 +#if defined ENABLE_GNSS_INTERN || defined ENABLE_GNSS_EXTERN setEvent(StMSYS1_GNSSDT, (uint32_t)OnAction_SetGnss); setEvent(StMSYS1_ZONE, (uint32_t)OnAction_UTC); #endif @@ -986,10 +927,131 @@ #endif } +#ifdef ENABLE_SETTING_PROFILES +void changeActiveProfil(uint8_t newProfile) +{ + SSettings *pSettings = settingsGetPointer(); + SSettings* pOldProfile = profileGetPointer(pSettings->activeProfile); + SSettings* pNewProfile = profileGetPointer(newProfile); + uint16_t personalDiveCountBackup; + uint8_t lastDiveLogIdBackup; + uint32_t sampleStartBackup; + char customTextBackup[60]; + + if( newProfile < NUMBER_OF_PROFILES) + { + /* some data needs to be the same in all profiles => make backup before gettings the new profile */ + personalDiveCountBackup = pSettings->personalDiveCount; + lastDiveLogIdBackup = pSettings->lastDiveLogId; + sampleStartBackup = pSettings->logFlashNextSampleStartAddress; + memcpy(customTextBackup, pSettings->customtext, 60); + + + memcpy(pOldProfile,pSettings,sizeof(SSettings)); + memcpy(pSettings,pNewProfile,sizeof(SSettings)); + + set_new_settings_missing_in_ext_flash(EF_PROFILE0 + newProfile); + check_and_correct_settings(EF_PROFILE0 + newProfile); + + pSettings->personalDiveCount = personalDiveCountBackup; + pSettings->lastDiveLogId = lastDiveLogIdBackup; + pSettings->logFlashNextSampleStartAddress = sampleStartBackup; + + pSettings->firmwareVersion[0] = firmware_FirmwareData.versionFirst; + pSettings->firmwareVersion[1] = firmware_FirmwareData.versionSecond; + pSettings->firmwareVersion[2] = firmware_FirmwareData.versionThird; + pSettings->firmwareVersion[3] = firmware_FirmwareData.versionBeta; + + memcpy(pSettings->customtext, customTextBackup, 60); + + if(pOldProfile->tX_colorscheme != pSettings->tX_colorscheme) + { + GFX_use_colorscheme(pSettings->tX_colorscheme); + tHome_init_compass(); + } + } +} + +void exitMenuProfil() +{ + uint8_t index = 0; + SSettings* pProfile; + uint8_t writeFlash = 0; + uint32_t profileExitCrc; + + for(index = 0; index < NUMBER_OF_PROFILES; index++) + { + pProfile = profileGetPointer(index); + profileExitCrc = CalcFletcher32((uint32_t)pProfile, (uint32_t)pProfile + sizeof(SSettings)); + + if(profileExitCrc != profileStartCrc[index]) + { + writeFlash = 1; + break; + } + } + if(writeFlash) + { + for(index = EF_PROFILE0; index <= EF_PROFILE3; index++) + ext_flash_write_settings(index,0); + } + if(profileActiveStart != settingsGetPointer()->activeProfile) + { + createDiveSettings(); + } + exitMenuEdit(1); +} +#endif +#ifdef ENABLE_SETTING_PROFILES +void openEdit_Profile(void) +{ + char text[50]; + uint8_t index = 0; + SSettings *pSettings = settingsGetPointer(); + SSettings* pProfile; + + setBackMenu((uint32_t)exitMenuProfil,0,0); + + profileActiveStart = pSettings->activeProfile; + +/* read profiles from flash */ + for(index = EF_PROFILE0; index <= EF_PROFILE3; index++) + { + set_settings_to_Standard(index); /* this is needed because details like header version are used by the read block function */ + ext_flash_read_settings(index); /* will overwrite standard settings if reading is successfull */ + pProfile = profileGetPointer(index - EF_PROFILE0); + profileStartCrc[index - EF_PROFILE0] = CalcFletcher32((uint32_t)pProfile, (uint32_t)pProfile + sizeof(SSettings)); + set_new_settings_missing_in_ext_flash(index); + check_and_correct_settings(index); + } + + sprintf(text,"\001%c%c",TXT_2BYTE,TXT2BYTE_Profile); + write_topline(text); + + sprintf(text,"%c %c%c:",TXT_Active,TXT_2BYTE,TXT2BYTE_Profile); + write_label_var( 30, 300, ME_Y_LINE1, &FontT48, text); + sprintf(text,"%s",pSettings->profileName[pSettings->activeProfile]); + write_field_button(StMSYS_Profile, 400, 700, ME_Y_LINE1, &FontT48, text); + write_field_text(StMSYS_ProfileA, 400, 700, ME_Y_LINE3, &FontT48, "########", pSettings->profileName[0]); + write_field_text(StMSYS_ProfileB, 400, 700, ME_Y_LINE4, &FontT48, "########", pSettings->profileName[1]); + write_field_text(StMSYS_ProfileC, 400, 700, ME_Y_LINE5, &FontT48, "########", pSettings->profileName[2]); + write_field_text(StMSYS_ProfileD, 400, 700, ME_Y_LINE6, &FontT48, "########", pSettings->profileName[3]); + + setEvent(StMSYS_Profile, (uint32_t)OnAction_SetProfile); + setEvent(StMSYS_ProfileA, (uint32_t)OnAction_Profile); + setEvent(StMSYS_ProfileB, (uint32_t)OnAction_Profile); + setEvent(StMSYS_ProfileC, (uint32_t)OnAction_Profile); + setEvent(StMSYS_ProfileD, (uint32_t)OnAction_Profile); + + write_buttonTextline(TXT2BYTE_ButtonBack,TXT2BYTE_ButtonEnter,TXT2BYTE_ButtonNext); +} +#endif + void refresh_Design(void) { - char text[32]; + char text[32]; + SSettings *pSettings = settingsGetPointer(); // header text[0] = '\001'; @@ -1004,7 +1066,7 @@ text[2] = 0; write_label_var( 30, 200, ME_Y_LINE1, &FontT48, text); - if(settingsGetPointer()->nonMetricalSystem) + if(pSettings->nonMetricalSystem) { text[1] = TXT2BYTE_Units_feet; } @@ -1020,7 +1082,7 @@ text[2] = 0; write_label_var( 30, 300, ME_Y_LINE2, &FontT48, text); - text[0] = '0' + settingsGetPointer()->tX_colorscheme; + text[0] = '0' + pSettings->tX_colorscheme; text[1] = 0; write_label_var( 400, 700, ME_Y_LINE2, &FontT48, text); @@ -1081,8 +1143,103 @@ return UPDATE_DIVESETTINGS; } +#ifdef ENABLE_SETTING_PROFILES +uint8_t OnAction_SetProfile(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) +{ + SSettings *pSettings = settingsGetPointer(); + uint8_t newProfile = pSettings->activeProfile + 1; + if(newProfile == NUMBER_OF_PROFILES) + { + newProfile = 0; + } + changeActiveProfil(newProfile); + pSettings->activeProfile = newProfile; + + tMenuEdit_newButtonText(editId,(char*)pSettings->profileName[pSettings->activeProfile]); + return UNSPECIFIC_RETURN; +} + +uint8_t OnAction_Profile(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) +{ + SSettings *pSettings = settingsGetPointer(); + SSettings *pProfile; + uint8_t digitContentNew; + uint8_t profilName[9]; + uint8_t updateProfilIndex = 0; + uint8_t index = 0; + + uint8_t returnValue = UNSPECIFIC_RETURN; + + switch (editId) + { + default: + case StMSYS_ProfileA: updateProfilIndex = 0; + break; + case StMSYS_ProfileB: updateProfilIndex = 1; + break; + case StMSYS_ProfileC: updateProfilIndex = 2; + break; + case StMSYS_ProfileD: updateProfilIndex = 3; + break; + } + + switch (action) + { + case ACTION_BUTTON_ENTER: returnValue = digitContent; + break; + case ACTION_BUTTON_ENTER_FINAL: + { + evaluateNewStringText(editId, profilName); + tMenuEdit_newInputText(editId, profilName); + if(pSettings->activeProfile == updateProfilIndex) + { + tMenuEdit_newButtonText(StMSYS_Profile, (char*)profilName); + } + strcpy((char*)pSettings->profileName[updateProfilIndex],(char*)profilName); + for (index = 0; index < NUMBER_OF_PROFILES; index++) + { + pProfile = profileGetPointer(index); + strcpy((char*)pProfile->profileName[updateProfilIndex],(char*)profilName); + } + } + + break; + case ACTION_BUTTON_NEXT: + if(digitContent == 'Z') + { + digitContentNew = '_'; + } + else if (digitContent == '_') + { + digitContentNew = 'A'; + } + else + { + digitContentNew = digitContent + 1; + } + returnValue = digitContentNew; + break; + case ACTION_BUTTON_BACK: + if(digitContent == 'A') + { + digitContentNew = '_'; + } + else if (digitContent == '_') + { + digitContentNew = 'Z'; + } + else + { + digitContentNew = digitContent - 1; + } + returnValue = digitContentNew; + break; + } + return returnValue; +} +#endif /* uint8_t OnAction_Design_t7ft (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) @@ -1192,7 +1349,14 @@ text_header[1] = TXT_Information; text_header[2] = 0; - write_label_var( 20, 800, ME_Y_LINE1, &FontT42, "Dive Computer OSTC4"); + if(isNewDisplay()) + { + write_label_var( 20, 800, ME_Y_LINE1, &FontT42, "Dive Computer OSTC5"); + } + else + { + write_label_var( 20, 800, ME_Y_LINE1, &FontT42, "Dive Computer OSTC4"); + } write_label_var( 20, 800, ME_Y_LINE2, &FontT42, "Design heinrichs/weikamp"); Sdate.Year = firmwareDataGetPointer()->release_year; @@ -1468,6 +1632,8 @@ write_buttonTextline(TXT2BYTE_ButtonBack,TXT2BYTE_ButtonEnter,TXT2BYTE_ButtonNext); } +customBlockInfo_t blockInfo; + void openEdit_Maintenance(void) { char text[32]; @@ -1475,6 +1641,12 @@ SSettings *pSettings = settingsGetPointer(); SSensorDataDiveO2* pDiveO2Data = NULL; + customBlockInfo_t* pCustumBlockInfo = (customBlockInfo_t *) CUSTOM_BLOCK_INFO_ADDR; + + blockInfo.Type = swapBytes(pCustumBlockInfo->Type); + blockInfo.fletcher = swapBytes(pCustumBlockInfo->fletcher); + blockInfo.length = swapBytes(pCustumBlockInfo->length); + resetMenuEdit(CLUT_MenuPageSystem); text[0] = '\001'; @@ -1517,6 +1689,12 @@ } } + if((blockInfo.Type & 0x0000FF00)== 0x0100) + { + snprintf(text,32,"Flash Bootloader"); + write_field_button(StMSYS5_FlashBoot, 30, 800, ME_Y_LINE4, &FontT48, text); + } + #ifdef ENABLE_ANALYSE_SAMPLES text[0] = TXT_2BYTE; text[1] = TXT2BYTE_SetSampleIndex; @@ -1540,6 +1718,12 @@ setEvent(StMSYS5_SetSampleIndx, (uint32_t)OnAction_RecoverSampleIdx); #endif + if((blockInfo.Type & 0x0000FF00)== 0x0100) + { + setEvent(StMSYS5_FlashBoot, (uint32_t)OnAction_FlashBootloader); + } + + text[0] = TXT_2BYTE; text[1] = TXT2BYTE_WarnBatteryLow; @@ -1624,8 +1808,8 @@ uint8_t OnAction_ResetAll (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) { - set_settings_to_Standard(); - check_and_correct_settings(); + set_settings_to_Standard(EF_SETTINGS); + check_and_correct_settings(EF_SETTINGS); return UPDATE_AND_EXIT_TO_HOME; } @@ -1755,6 +1939,31 @@ FrameCount++; } #endif + +uint8_t OnAction_FlashBootloader (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) +{ + SHardwareData HwInfo; + customBlockInfo_t* pCustumBlockInfo = (customBlockInfo_t *) CUSTOM_BLOCK_INFO_ADDR; + customBlockInfo_t blockInfo; + uint32_t checksum; + uint8_t* pSource = (uint8_t *) 0x08100000; + + checksum = CalcFletcher32(0x08100000,0x0811FFEF); /* last nibble contains block info => exclude */ + + blockInfo.Type = swapBytes(pCustumBlockInfo->Type); + blockInfo.fletcher = swapBytes(pCustumBlockInfo->fletcher); + blockInfo.length = swapBytes(pCustumBlockInfo->length); + + if(checksum == blockInfo.fletcher) + { + memcpy (&HwInfo, hardwareDataGetPointer(), sizeof(SHardwareData)); /* create backup copy because data will be overwritten during flash erase */ + + bootloader_eraseFlashMemory(); + bootloader_programFlashMemory(pSource, blockInfo.length, &HwInfo); + } + return UNSPECIFIC_RETURN; +} + /* uint8_t OnAction_TestCLog (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) {
--- a/Discovery/Src/tMenuEditXtra.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Src/tMenuEditXtra.c Sat Nov 15 19:29:44 2025 +0100 @@ -41,6 +41,9 @@ #include "tInfoPreDive.h" +#define SCRUBBER_COUNT 2 + + /* Private function prototypes -----------------------------------------------*/ void openEdit_CompassHeading(void); void openEdit_ResetStopwatch(void); @@ -62,6 +65,7 @@ static uint8_t OnAction_ScrubberTimerMax(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); static uint8_t OnAction_ScrubberReset(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); static uint8_t OnAction_ScrubberMode(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); +static uint8_t OnAction_ScrubberActive(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); @@ -69,6 +73,7 @@ /* Exported functions --------------------------------------------------------*/ +static uint8_t scrubberMenuId = 0; void openEdit_Xtra(uint8_t line) { @@ -194,84 +199,109 @@ } -static void printScrubberResetText(char *text, SSettings *settings) +static void printScrubberResetText(char *text, SSettings *settings, uint8_t scrubberId, bool isActive) { - int16_t currentTimerMinutes = settings->scrubberData[settings->scubberActiveId].TimerCur; - char colour = '\020'; - if (currentTimerMinutes <= 0) { - colour = '\025'; - } else if (currentTimerMinutes <= 30) { - colour = '\024'; + int16_t currentTimerMinutes = settings->scrubberData[scrubberId].TimerCur; + + char *colour = ""; + if (isActive) { + if (currentTimerMinutes <= 0) { + colour = "\025"; + } else if (currentTimerMinutes <= 30) { + colour = "\024"; + } } - snprintf(text, 32, "%c\002%c%03i\016\016 %c\017", TXT_ScrubTimeReset, colour, currentTimerMinutes, TXT_Minutes); + snprintf(text, 32, "%s%c\002%s%03i\016\016 %c\017", makeGrey(!isActive), TXT_ScrubTimeReset, colour, currentTimerMinutes, TXT_Minutes); } +static void drawScrubberMenu(bool isRefresh) +{ + SSettings *settings = settingsGetPointer(); + + resetMenuContentStructure(); + + char text[32]; + snprintf(text, 32, "%c \002#%d", TXT_ScrubTime, scrubberMenuId); + if (isRefresh) { + clean_content(20, 780, ME_Y_LINE1, &FontT48); + } + write_field_button(StMXTRA_ScrubTimer, 20, 780, ME_Y_LINE1, &FontT48, text); + + bool currentScrubberIsActive = settings->scrubberActiveId & (1 << scrubberMenuId); + + snprintf(text, 32, "%c %c \002%c", TXT_ScrubTime, TXT_Active, printCheckbox(currentScrubberIsActive)); + if (isRefresh) { + clean_content(20, 780, ME_Y_LINE2, &FontT48); + } + write_field_button(StMXTRA_ScrubTimer_Active, 20, 780, ME_Y_LINE2, &FontT48, text); + + snprintf(text, 32, "%s%c\016\016(%c)\017", makeGrey(!currentScrubberIsActive), TXT_ScrubTime, TXT_Maximum); + if (isRefresh) { + clean_content(20, 340, ME_Y_LINE3, &FontT48); + } + write_label_var(20, 340, ME_Y_LINE3, &FontT48, text); + + uint16_t timerMax = settings->scrubberData[scrubberMenuId].TimerMax; + if (isRefresh) { + clean_content(610, 780, ME_Y_LINE3, &FontT48); + } + if (currentScrubberIsActive) { + snprintf(text, 32, "%s\002###\016\016 %c\017", makeGrey(!currentScrubberIsActive), TXT_Minutes); + write_field_udigit(StMXTRA_ScrubTimer_Max, 610, 780, ME_Y_LINE3, &FontT48, text, timerMax, 0, 0, 0); + } else { + snprintf(text, 32, "%s\002%03i\016\016 %c\017", makeGrey(!currentScrubberIsActive), timerMax, TXT_Minutes); + write_label_var(610, 780, ME_Y_LINE3, &FontT48, text); + } + + printScrubberResetText(text, settings, scrubberMenuId, currentScrubberIsActive); + if (isRefresh) { + clean_content(20, 780, ME_Y_LINE4, &FontT48); + } + if (currentScrubberIsActive) { + write_field_button(StMXTRA_ScrubTimer_Reset, 20, 780, ME_Y_LINE4, &FontT48, text); + } else { + write_label_var(20, 780, ME_Y_LINE4, &FontT48, text); + } + + if (settings->scrubberData[scrubberMenuId].lastDive.WeekDay != 0) { + snprintf(text, 32, "%s%c%c\002 %02d.%02d.%02d", makeGrey(!currentScrubberIsActive), TXT_2BYTE, TXT2BYTE_SimDiveTime, settings->scrubberData[scrubberMenuId].lastDive.Date, settings->scrubberData[scrubberMenuId].lastDive.Month, settings->scrubberData[scrubberMenuId].lastDive.Year); + } else { + snprintf(&text[0], 32, "%s%c%c\002 --.--.--", makeGrey(!currentScrubberIsActive), TXT_2BYTE, TXT2BYTE_SimDiveTime); + } + if (isRefresh) { + clean_content(20, 780, ME_Y_LINE5, &FontT48); + } + write_label_var(20, 780, ME_Y_LINE5, &FontT48, text); + + switch (settings->scrubTimerMode) { + case SCRUB_TIMER_MINUTES: + default: snprintf(text, 32, "%c\002%c", TXT_ScrubTimeMode, TXT_Minutes); + break; + case SCRUB_TIMER_PERCENT: snprintf(text, 32, "%c\002%c", TXT_ScrubTimeMode, TXT_Percent); + break; + } + write_field_button(StMXTRA_ScrubTimer_OP_Mode, 20, 780, ME_Y_LINE6, &FontT48, text); + + setEvent(StMXTRA_ScrubTimer, (uint32_t)OnAction_ScrubberTimerId); + setEvent(StMXTRA_ScrubTimer_Active, (uint32_t)OnAction_ScrubberActive); + setEvent(StMXTRA_ScrubTimer_Max, (uint32_t)OnAction_ScrubberTimerMax); + setEvent(StMXTRA_ScrubTimer_Reset, (uint32_t)OnAction_ScrubberReset); + setEvent(StMXTRA_ScrubTimer_OP_Mode, (uint32_t)OnAction_ScrubberMode); +} + static void openEdit_Scrubber(void) { char text[32]; - uint8_t textIndex = 0; - uint16_t localScrubTimer; - - SSettings *pSettings = settingsGetPointer(); - - localScrubTimer = pSettings->scrubberData[pSettings->scubberActiveId].TimerMax; resetMenuEdit(CLUT_MenuPageXtra); - - snprintf(&text[0], 32,"\001%c",TXT_ScrubTime); + snprintf(text, 32, "\001%c", TXT_ScrubTime); write_topline(text); - - snprintf(&text[0], 32,"%c \002#%d",TXT_ScrubTime,pSettings->scubberActiveId); - write_field_button(StMXTRA_ScrubTimer, 20, 780, ME_Y_LINE1, &FontT48, text); - - snprintf(&text[textIndex], 32,\ - "%c" - "\016\016(%c)\017" - ,TXT_ScrubTime - ,TXT_Maximum); - - write_label_var( 20, 340, ME_Y_LINE2, &FontT48, text); - snprintf(&text[textIndex], 32, "\002###\016\016 %c\017",TXT_Minutes); - - write_field_udigit(StMXTRA_ScrubTimer_Max, 610, 780, ME_Y_LINE2, &FontT48, text,localScrubTimer, 0, 0, 0); - - printScrubberResetText(text, pSettings); - write_field_button(StMXTRA_ScrubTimer_Reset, 20, 780, ME_Y_LINE3, &FontT48, text); + drawScrubberMenu(false); - if(pSettings->scrubberData[pSettings->scubberActiveId].lastDive.WeekDay != 0) - { - snprintf(&text[0], 32,"%c%c\002 %02d.%02d.%02d", TXT_2BYTE, TXT2BYTE_SimDiveTime, pSettings->scrubberData[pSettings->scubberActiveId].lastDive.Date, - pSettings->scrubberData[pSettings->scubberActiveId].lastDive.Month, - pSettings->scrubberData[pSettings->scubberActiveId].lastDive.Year); - } - else - { - snprintf(&text[0], 32,"%c%c\002 --.--.--", TXT_2BYTE, TXT2BYTE_SimDiveTime); - } - write_label_var( 20, 780, ME_Y_LINE4, &FontT48, text); - - switch(pSettings->scrubTimerMode) - { - case SCRUB_TIMER_OFF: - default: snprintf(&text[0], 32,"%c\002%c%c",TXT_ScrubTimeMode, TXT_2BYTE, TXT2BYTE_MoCtrlNone ); - break; - case SCRUB_TIMER_MINUTES: snprintf(&text[0], 32,"%c\002%c",TXT_ScrubTimeMode, TXT_Minutes ); - break; - case SCRUB_TIMER_PERCENT: snprintf(&text[0], 32,"%c\002%c",TXT_ScrubTimeMode, TXT_Percent ); - break; - } - write_field_button(StMXTRA_ScrubTimer_OP_Mode, 20, 780, ME_Y_LINE5, &FontT48, text); - - setEvent(StMXTRA_ScrubTimer, (uint32_t)OnAction_ScrubberTimerId); - setEvent(StMXTRA_ScrubTimer_Max, (uint32_t)OnAction_ScrubberTimerMax); - setEvent(StMXTRA_ScrubTimer_Reset, (uint32_t)OnAction_ScrubberReset); - setEvent(StMXTRA_ScrubTimer_OP_Mode, (uint32_t)OnAction_ScrubberMode); - - write_buttonTextline(TXT2BYTE_ButtonBack,TXT2BYTE_ButtonEnter,TXT2BYTE_ButtonNext); - + write_buttonTextline(TXT2BYTE_ButtonBack, TXT2BYTE_ButtonEnter, TXT2BYTE_ButtonNext); } static void openEdit_PSCR(void) @@ -460,40 +490,9 @@ uint8_t OnAction_ScrubberTimerId(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) { - char text[32]; - SSettings *pSettings; - pSettings = settingsGetPointer(); - - if(pSettings->scubberActiveId == 0) - { - pSettings->scubberActiveId = 1; - } - else - { - pSettings->scubberActiveId = 0; - } - - - snprintf(&text[0], 32,"%c \002#%d",TXT_ScrubTime,pSettings->scubberActiveId); - tMenuEdit_newButtonText(StMXTRA_ScrubTimer, text); + scrubberMenuId = (scrubberMenuId + 1) % SCRUBBER_COUNT; - printScrubberResetText(text, pSettings); - tMenuEdit_newButtonText(StMXTRA_ScrubTimer_Reset, text); - - tMenuEdit_newInput(StMXTRA_ScrubTimer_Max, pSettings->scrubberData[pSettings->scubberActiveId].TimerMax, 0, 0, 0); - - if(pSettings->scrubberData[pSettings->scubberActiveId].lastDive.WeekDay != 0) - { - snprintf(&text[0], 32,"%c%c\002 %02d.%02d.%02d", TXT_2BYTE, TXT2BYTE_SimDiveTime, pSettings->scrubberData[pSettings->scubberActiveId].lastDive.Date, - pSettings->scrubberData[pSettings->scubberActiveId].lastDive.Month, - pSettings->scrubberData[pSettings->scubberActiveId].lastDive.Year); - } - else - { - snprintf(&text[0], 32,"%c%c\002 --.--.--", TXT_2BYTE, TXT2BYTE_SimDiveTime); - } - clean_content( 20, 780, ME_Y_LINE4, &FontT48); - write_label_var( 20, 780, ME_Y_LINE4, &FontT48, text); + drawScrubberMenu(true); return UNSPECIFIC_RETURN; } @@ -516,10 +515,10 @@ newScrubberTime = MAX_SCRUBBER_TIME; pSettings = settingsGetPointer(); - pSettings->scrubberData[pSettings->scubberActiveId].TimerMax = newScrubberTime; - if(pSettings->scrubberData[pSettings->scubberActiveId].TimerCur > newScrubberTime) + pSettings->scrubberData[scrubberMenuId].TimerMax = newScrubberTime; + if(pSettings->scrubberData[scrubberMenuId].TimerCur > newScrubberTime) { - pSettings->scrubberData[pSettings->scubberActiveId].TimerCur = newScrubberTime; + pSettings->scrubberData[scrubberMenuId].TimerCur = newScrubberTime; } tMenuEdit_newInput(editId, newScrubberTime, 0, 0, 0); @@ -542,19 +541,11 @@ uint8_t OnAction_ScrubberReset(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) { - char text[32]; - SSettings *pSettings; - pSettings = settingsGetPointer(); - pSettings->scrubberData[pSettings->scubberActiveId].TimerCur = pSettings->scrubberData[pSettings->scubberActiveId].TimerMax; - pSettings->scrubberData[pSettings->scubberActiveId].lastDive.WeekDay = 0; /* invalidate date */ + SSettings *pSettings = settingsGetPointer(); + pSettings->scrubberData[scrubberMenuId].TimerCur = pSettings->scrubberData[scrubberMenuId].TimerMax; + pSettings->scrubberData[scrubberMenuId].lastDive.WeekDay = 0; /* invalidate date */ - printScrubberResetText(text, pSettings); - tMenuEdit_newButtonText(StMXTRA_ScrubTimer_Reset, text); - - snprintf(&text[0], 32,"%c%c\002 --.--.--", TXT_2BYTE, TXT2BYTE_SimDiveTime); - clean_content( 20, 780, ME_Y_LINE4, &FontT48); - write_label_var( 20, 780, ME_Y_LINE4, &FontT48, text); - + drawScrubberMenu(true); return UNSPECIFIC_RETURN; } @@ -566,27 +557,42 @@ SSettings *pSettings; pSettings = settingsGetPointer(); newMode = pSettings->scrubTimerMode + 1; - if(newMode >= SCRUB_TIMER_END) - { - newMode = SCRUB_TIMER_OFF; + if (newMode >= SCRUB_TIMER_END) { + newMode = SCRUB_TIMER_MINUTES; } pSettings->scrubTimerMode = newMode; - switch(pSettings->scrubTimerMode) - { - case SCRUB_TIMER_OFF: - default: snprintf(&text[0], 32,"%c\002%c%c",TXT_ScrubTimeMode, TXT_2BYTE, TXT2BYTE_MoCtrlNone ); - break; - case SCRUB_TIMER_MINUTES: snprintf(&text[0], 32,"%c\002%c",TXT_ScrubTimeMode, TXT_Minutes ); - break; - case SCRUB_TIMER_PERCENT: snprintf(&text[0], 32,"%c\002%c",TXT_ScrubTimeMode, TXT_Percent ); - break; - } + switch (pSettings->scrubTimerMode) { + case SCRUB_TIMER_MINUTES: + default: + snprintf(&text[0], 32,"%c\002%c",TXT_ScrubTimeMode, TXT_Minutes ); + + break; + case SCRUB_TIMER_PERCENT: + snprintf(&text[0], 32,"%c\002%c",TXT_ScrubTimeMode, TXT_Percent ); + + break; + } tMenuEdit_newButtonText(StMXTRA_ScrubTimer_OP_Mode, text); return UNSPECIFIC_RETURN; } +uint8_t OnAction_ScrubberActive(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) +{ + SSettings *pSettings = settingsGetPointer(); + + if (pSettings->scrubberActiveId & (1 << scrubberMenuId)) { + pSettings->scrubberActiveId &= ~(1 << scrubberMenuId); + } else { + pSettings->scrubberActiveId |= (1 << scrubberMenuId); + } + + drawScrubberMenu(true); + + return UNSPECIFIC_RETURN; +} + #ifdef ENABLE_PSCR_MODE static uint8_t OnAction_PSCRO2Drop(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) {
--- a/Discovery/Src/tMenuHardware.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Src/tMenuHardware.c Sat Nov 15 19:29:44 2025 +0100 @@ -29,6 +29,7 @@ /* Includes ------------------------------------------------------------------*/ #include "tMenu.h" #include "tMenuHardware.h" +#include "ostc.h" //#define NEXTLINE(text, textPointer) {text[(textPointer)++] = '\n'; text[textPointer++] = '\r'; text[textPointer] = 0;} // NEXTLINE(text,textPointer); @@ -75,26 +76,6 @@ if((line == 0) || (line == 2)) { - text[textPointer++] = TXT_2BYTE; - text[textPointer++] = TXT2BYTE_Compass; - text[textPointer++] = '\t'; - - if(settingsGetPointer()->compassBearing != 0) - { - textPointer += snprintf(&text[textPointer], 20, "(%03u`)", settingsGetPointer()->compassBearing % 360); - } - text[textPointer] = 0; -/* - textPointer += snprintf(&text[textPointer],20,"%i %i %i" - ,stateUsed->lifeData.compass_DX_f - ,stateUsed->lifeData.compass_DY_f - ,stateUsed->lifeData.compass_DZ_f); -*/ - } - nextline(text,&textPointer); - - if((line == 0) || (line == 3)) - { text[textPointer++] = TXT_o2Sensors; if((stateUsed->lifeData.ppO2Sensor_bar[0] != 0) || (stateUsed->lifeData.ppO2Sensor_bar[1] != 0) || (stateUsed->lifeData.ppO2Sensor_bar[2] != 0)) { @@ -118,7 +99,7 @@ } nextline(text,&textPointer); - if((line == 0) || (line == 4)) + if((line == 0) || (line == 3)) { text[textPointer++] = TXT_Brightness; text[textPointer++] = '\t'; @@ -140,7 +121,7 @@ } nextline(text,&textPointer); - if((line == 0) || (line == 5)) + if((line == 0) || (line == 4)) { text[textPointer++] = TXT_2BYTE; text[textPointer++] = TXT2BYTE_ButtonSensitivity; @@ -160,17 +141,18 @@ } nextline(text,&textPointer); - if((line == 0) || (line == 6)) + if((isNewDisplay()) && ((line == 0) || (line == 5))) { - text[textPointer++] = TXT_2BYTE; - text[textPointer++] = TXT2BYTE_FLIPDISPLAY; - text[textPointer++] = '\t'; - if(settingsGetPointer()->FlipDisplay) - text[textPointer++] = '\005'; - else - text[textPointer++] = '\006'; - text[textPointer] = 0; - nextline(text,&textPointer); + text[textPointer++] = TXT_2BYTE; + text[textPointer++] = TXT2BYTE_BUZZER; + text[textPointer++] = ' '; + text[textPointer++] = TXT_Warning; + text[textPointer++] = '\t'; + if(settingsGetPointer()->warningBuzzer) + text[textPointer++] = '\005'; + else + text[textPointer++] = '\006'; + nextline(text,&textPointer); } return StMHARD;
--- a/Discovery/Src/tMenuSystem.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Src/tMenuSystem.c Sat Nov 15 19:29:44 2025 +0100 @@ -58,7 +58,7 @@ textPointer = 0; *tab = 300; *subtext = 0; - char tmpString[15]; + char tmpString[20]; resetLineMask(StMSYS); @@ -131,40 +131,32 @@ text[textPointer++] = TXT_Date; getStringOfFormat_DDMMYY(tmpString,15); textPointer += snprintf(&text[textPointer], 40,"\016\016 %s ",tmpString); - convertStringOfDate_DDMMYY(tmpString,15,Sdate.Date, Sdate.Month, Sdate.Year); + convertStringOfDate_DDMMYY(tmpString,15,Sdate.Date, Sdate.Month, Sdate.Year); textPointer += snprintf(&text[textPointer], 40,"\017\t%s ",tmpString); - - textPointer += snprintf(&text[textPointer], 60, - "%02d:%02d:%02d" - "\n\r" - ,Stime.Hours, Stime.Minutes, Stime.Seconds - ); + formatStringOfTime(tmpString,20,Stime,0,1); + textPointer += snprintf(&text[textPointer], 60,"%s\n\r",tmpString); } else { strcpy(&text[textPointer],"\n\r"); textPointer += 2; } - - if (line == 0 || line == 2) +#ifdef ENABLE_SETTING_PROFILES + if((line == 0) || (line == 2)) + { + textPointer += snprintf(&text[textPointer], 40,"%c%c:\t%s\n\r",TXT_2BYTE,TXT2BYTE_Profile,data->profileName[data->activeProfile]); + } + else { - if(t7_customview_disabled(CVIEW_Timer)) - { - text[textPointer++] = '\031'; /* change text color */ - textPointer += snprintf(&text[textPointer], 21, "%c%c\t%u:%02u \016\016[m:ss]\017\n\r", TXT_2BYTE, TXT2BYTE_Timer, data->timerDurationS / 60, data->timerDurationS % 60); - disableLine(StMSYS_Timer); - text[textPointer++] = '\020'; /* restore text color */ - } - else - { - textPointer += snprintf(&text[textPointer], 21, "%c%c\t%u:%02u \016\016[m:ss]\017\n\r", TXT_2BYTE, TXT2BYTE_Timer, data->timerDurationS / 60, data->timerDurationS % 60); - } - } else - { - textPointer += snprintf(&text[textPointer], 3, "\n\r"); + strcpy(&text[textPointer],"\n\r"); + textPointer += 2; } - +#endif +#ifdef ENABLE_SETTING_PROFILES if((line == 0) || (line == 3)) +#else + if((line == 0) || (line == 2)) +#endif { text[textPointer++] = TXT_Language; text[textPointer++] = '\t'; @@ -178,8 +170,11 @@ strcpy(&text[textPointer],"\n\r"); textPointer += 2; } - +#ifdef ENABLE_SETTING_PROFILES if((line == 0) || (line == 4)) +#else + if((line == 0) || (line == 3)) +#endif { text[textPointer++] = TXT_2BYTE; text[textPointer++] = TXT2BYTE_Layout; @@ -252,7 +247,11 @@ textPointer += 2; } +#ifdef ENABLE_SETTING_PROFILES if((line == 0) || (line == 5)) +#else + if((line == 0) || (line == 4)) +#endif { text[textPointer++] = TXT_Information; text[textPointer++] = '\t'; @@ -267,7 +266,11 @@ strcpy(&text[textPointer],"\n\r"); textPointer += 2; +#ifdef ENABLE_SETTING_PROFILES if((line == 0) || (line == 6)) +#else + if((line == 0) || (line == 5)) +#endif { text[textPointer++] = TXT_2BYTE; text[textPointer++] = TXT2BYTE_ResetMenu; @@ -278,19 +281,6 @@ return StMSYS; } -void tMSystem_checkLineStatus(void) -{ - uint8_t localLineMask = 0; - uint8_t lineMask = getLineMask(StMSYS); - if(t7_customview_disabled(CVIEW_Timer)) - { - localLineMask |= 1 << 2; - } - if(lineMask != localLineMask) - { - updateMenu(); - } -} /* Private functions ---------------------------------------------------------*/
--- a/Discovery/Src/text_multilanguage.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Discovery/Src/text_multilanguage.c Sat Nov 15 19:29:44 2025 +0100 @@ -2005,6 +2005,18 @@ static uint8_t text_IT_Reverse[] = "Invertire"; static uint8_t text_ES_Reverse[] = "Invertir"; +static uint8_t text_EN_Pulse[] = "Heartbeat sensor (BT)"; +static uint8_t text_DE_Pulse[] = "Pulssensor (BT)"; +static uint8_t text_FR_Pulse[] = ""; +static uint8_t text_IT_Pulse[] = ""; +static uint8_t text_ES_Pulse[] = ""; + +static uint8_t text_EN_Logger[] = "Debug Messages"; +static uint8_t text_DE_Logger[] = "Logger"; +static uint8_t text_FR_Logger[] = ""; +static uint8_t text_IT_Logger[] = ""; +static uint8_t text_ES_Logger[] = ""; + /* Lookup Table -------------------------------------------------------------*/ const tText text_array[] = @@ -2319,6 +2331,8 @@ {(uint8_t)TXT2BYTE_Log, {text_EN_Log, text_DE_Log, text_FR_Log, text_IT_Log, text_ES_Log}}, {(uint8_t)TXT2BYTE_Reverse, {text_EN_Reverse, text_DE_Reverse, text_FR_Reverse, text_IT_Reverse, text_ES_Reverse}}, + {(uint8_t)TXT2BYTE_Pulse, {text_EN_Pulse, text_DE_Pulse, text_FR_Pulse, text_IT_Pulse, text_ES_Pulse}}, + {(uint8_t)TXT2BYTE_Logger, {text_EN_Logger, text_DE_Logger, text_FR_Logger, text_IT_Logger, text_ES_Logger}}, };
--- a/OtherSources/data_central_mini.c Sun Nov 02 19:30:58 2025 +0100 +++ b/OtherSources/data_central_mini.c Sat Nov 15 19:29:44 2025 +0100 @@ -111,10 +111,12 @@ uint32_t CRC_CalcBlockCRC_moreThan768000(uint32_t *buffer1, uint32_t *buffer2, uint32_t words) { - cm_t crc_model; - uint32_t word_to_do; - uint8_t byte_to_do; - int i; + cm_t crc_model; + uint32_t word_to_do; + uint8_t byte_to_do; + int i; + + uint32_t wordCnt = 0; // Values for the STM32F generator. @@ -127,10 +129,10 @@ cm_ini(&crc_model); - while (words--) + do { // The STM32F10x hardware does 32-bit words at a time!!! - if(words > (768000/4)) + if(wordCnt >= (768000/4)) word_to_do = *buffer2++; else word_to_do = *buffer1++; @@ -159,7 +161,8 @@ cm_nxt(&crc_model, byte_to_do); } - } + wordCnt++; + } while (wordCnt != words); // Return the final result.
--- a/OtherSources/firmwareEraseProgram.c Sun Nov 02 19:30:58 2025 +0100 +++ b/OtherSources/firmwareEraseProgram.c Sat Nov 15 19:29:44 2025 +0100 @@ -83,6 +83,9 @@ #define SECTOR_SIZE_128KB ((uint32_t)0x00020000) +#define FLASH_BOOT_START_ADDR ADDR_FLASH_SECTOR_0 +#define FLASH_BOOT_END_ADDR (ADDR_FLASH_SECTOR_5 - 1) + #define FLASH_FW_START_ADDR ADDR_FLASH_SECTOR_6 #define FLASH_FW_END_ADDR (ADDR_FLASH_SECTOR_12 - 1) @@ -447,6 +450,133 @@ } + +uint8_t bootloader_eraseFlashMemory(void) +{ +// HAL_StatusTypeDef answer; + /* Unlock the Flash to enable the flash control register access *************/ + HAL_FLASH_Unlock(); + + /* Erase the user Flash area + (area defined by FLASH_USER_START_ADDR and FLASH_USER_END_ADDR) ***********/ + + /* Get the 1st sector to erase */ + FirstSector = GetSector(FLASH_BOOT_START_ADDR); + /* Get the number of sector to erase from 1st sector*/ + NbOfSectors = GetSector(FLASH_BOOT_END_ADDR) - FirstSector + 1; + + /* Fill EraseInit structure*/ + EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS; + EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_1; + EraseInitStruct.Sector = FirstSector; + EraseInitStruct.NbSectors = NbOfSectors; + + /* Note: If an erase operation in Flash memory also concerns data in the data or instruction cache, + you have to make sure that these data are rewritten before they are accessed during code + execution. If this cannot be done safely, it is recommended to flush the caches by setting the + DCRST and ICRST bits in the FLASH_CR register. */ + return HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError); +} + +uint8_t bootloader_programFlashMemory(uint8_t *pBuffer1, uint32_t length1, SHardwareData* pHwInfo) +{ + HAL_StatusTypeDef answer; + + /* Program the user Flash area word by word + (area defined by FLASH_USER_START_ADDR and FLASH_USER_END_ADDR) ***********/ + + uint32_t index = 0; + Address = FLASH_BOOT_START_ADDR; + + uint8_t* pHardwareInfo = (uint8_t*) pHwInfo; + uint8_t tmp = 0; + + index = 0; + while ((Address <= FLASH_FW_END_ADDR) && (index < length1)) + { + if((Address >= HARDWAREDATA_ADDRESS) && (Address < HARDWAREDATA_ADDRESS + sizeof(SHardwareData))) + { + answer = HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, Address, *pHardwareInfo++); + } + else + { + answer = HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, Address, pBuffer1[index]); + } + if (answer == HAL_OK) + { + Address = Address + 1; + index++; + } + else + { + return answer; + } + } + /* Lock the Flash to disable the flash control register access (recommended + to protect the FLASH memory against possible unwanted operation) *********/ + HAL_FLASH_Lock(); + + /* Check if the programmed data is OK + MemoryProgramStatus = 0: data programmed correctly + MemoryProgramStatus != 0: number of words not programmed correctly ******/ + Address = FLASH_BOOT_START_ADDR; + MemoryProgramStatus = 0x0; + + index = 0; + pHardwareInfo = (uint8_t*) pHwInfo; + + while ((Address <= FLASH_FW_END_ADDR) && (index < length1)) + { + if((Address >= HARDWAREDATA_ADDRESS) && (Address < HARDWAREDATA_ADDRESS + sizeof(SHardwareData))) + { + tmp = *pHardwareInfo++; + } + else + { + tmp = pBuffer1[index]; + } + + data32 = *(__IO uint8_t*)Address; + if (data32 != tmp) + { + MemoryProgramStatus++; + } + + Address = Address + 1; + index++; + } + /* Check if there is an issue to program data */ + if (MemoryProgramStatus == 0) + { + return HAL_OK; + /* No error detected. Switch on LED3 */ + } + else + { + return 0xEE; + } +} + + +uint32_t CalcFletcher32(uint32_t startAddr, uint32_t endAddr) +{ + uint32_t fletcher = 0; + uint16_t* pData = (uint16_t*) startAddr; + uint32_t index = 0; + + uint16_t sum1 = 0; + uint16_t sum2 = 0; + for(index = startAddr; index <= endAddr; index +=2) + { + sum1 = sum1 + *pData++; + sum2 = (sum2 + sum1); + } + fletcher = (sum2 << 16) | sum1; + + return fletcher; +} + + /* Private functions ---------------------------------------------------------*/ /**
--- a/Small_CPU/Inc/GNSS.h Sun Nov 02 19:30:58 2025 +0100 +++ b/Small_CPU/Inc/GNSS.h Sat Nov 15 19:29:44 2025 +0100 @@ -101,6 +101,44 @@ GNSS_StateHandle GNSS_Handle; +typedef struct { + uint8_t header1; + uint8_t header2; + uint8_t msgClass; + uint8_t msgID; + uint16_t length; + uint8_t type; + uint8_t version; + uint8_t ref; + uint8_t leapsec; + uint16_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint8_t second; + uint8_t flags; + uint32_t nanoseconds; + uint16_t accuracy_seconds; + uint16_t reserved; + uint32_t accuracy_nano; +} __attribute__((packed)) UBX_MGA_INI_TIME_UTC_t; + +typedef struct { + uint8_t header1; + uint8_t header2; + uint8_t class_id; + uint8_t msg_id; + uint16_t length; + uint8_t type; + uint8_t version; + uint16_t reserved; + int32_t latitude; + int32_t longitude; + int32_t altitude; + uint32_t accuracy; +} __attribute__((packed)) UBX_MGA_INI_POS_LLH_t; + enum GNSSMode{Portable=0, Stationary=1, Pedestrian=2, Automotiv=3, Airbone1G=5, Airbone2G=6,Airbone4G=7,Wirst=8,Bike=9}; @@ -125,11 +163,13 @@ static const uint8_t setPowerNormal[]={0xB5,0x62,0x06,0x86,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; +/* UBX-CFG-NAV5 */ static const uint8_t setPortableMode[]={0xB5,0x62,0x06,0x24,0x24,0x00,0xFF,0xFF,0x00,0x03,0x00,0x00,0x00,0x00,0x10,0x27,0x00,0x00,0x05,0x00,0xFA,0x00,0xFA,0x00,0x64,0x00,0x5E,0x01,0x00,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; - static const uint8_t setPedestrianMode[]={0xB5,0x62,0x06,0x24,0x24,0x00,0xFF,0xFF,0x03,0x03,0x00,0x00,0x00,0x00,0x10,0x27,0x00,0x00,0x05,0x00,0xFA,0x00,0xFA,0x00,0x64,0x00,0x5E,0x01,0x00,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; static const uint8_t setConfig[]={0xB5,0x62,0x06,0x09,0x0D,0x00, 0x00,0x00,0x00,0x00, 0x18,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x01}; +/* UBX-MGA-INI-TIME_UTC */ +static const uint8_t setDateTime[] = {0xB5,0x62,0x13,0x40,0x18,0x00,0x10,0x00,0x00,0x80,0x07,0xE9,0x01,0x02,0x03,0x04,0x05,0x00,0x01,0x02,0x03,0x04,0x00,0x3C,0x00,0x00,0x00,0x00,0x00,0x00}; static const uint8_t setPortableType[]={}; void GNSS_Init(GNSS_StateHandle *GNSS, UART_HandleTypeDef *huart);
--- a/Small_CPU/Inc/externalInterface.h Sun Nov 02 19:30:58 2025 +0100 +++ b/Small_CPU/Inc/externalInterface.h Sat Nov 15 19:29:44 2025 +0100 @@ -72,7 +72,7 @@ DETECTION_CO2_2, DETECTION_CO2_3, #endif -#ifdef ENABLE_GNSS_SUPPORT +#ifdef ENABLE_GNSS_EXTERN DETECTION_GNSS_0, /* check UART channel for connected gnss sensor */ DETECTION_GNSS_1, DETECTION_GNSS_2,
--- a/Small_CPU/Inc/gpio.h Sun Nov 02 19:30:58 2025 +0100 +++ b/Small_CPU/Inc/gpio.h Sat Nov 15 19:29:44 2025 +0100 @@ -38,7 +38,7 @@ void GPIO_Power_MainCPU_ON(void); void GPIO_Power_MainCPU_OFF(void); -#ifdef ENABLE_GPIO_V2 + void GPIO_LED_RED_OFF(void); void GPIO_LED_RED_ON(void); void GPIO_LED_GREEN_OFF(void); @@ -50,11 +50,13 @@ void GPIO_GPS_BCKP_OFF(void); void GPIO_GPS_BCKP_ON(void); +uint8_t GPIO_GetVersion(void); +void GPIO_Activate_V2(void); +void GPIO_Init_V2(void); void GPIO_HandleBuzzer(); #endif #ifdef __cplusplus } -#endif #endif /* GPIO_H */
--- a/Small_CPU/Inc/rtc.h Sun Nov 02 19:30:58 2025 +0100 +++ b/Small_CPU/Inc/rtc.h Sat Nov 15 19:29:44 2025 +0100 @@ -41,6 +41,7 @@ void RTC_SetDate(RTC_DateTypeDef sdatestructure); void RTC_GetTime(RTC_TimeTypeDef* pstimestructure); +void RTC_GetDate(RTC_DateTypeDef* psdatestructure); #ifdef __cplusplus }
--- a/Small_CPU/Inc/uart.h Sun Nov 02 19:30:58 2025 +0100 +++ b/Small_CPU/Inc/uart.h Sat Nov 15 19:29:44 2025 +0100 @@ -68,7 +68,7 @@ void DigitalCO2_SendCmd(uint8_t CO2Cmd, uint8_t *cmdString, uint8_t *cmdLength); #endif -#ifdef ENABLE_GNSS_SUPPORT +#ifdef ENABLE_GNSS_EXTERN void UART_HandleGnssData(void); #endif #ifdef ENABLE_SENTINEL_MODE
--- a/Small_CPU/Inc/uartProtocol_GNSS.h Sun Nov 02 19:30:58 2025 +0100 +++ b/Small_CPU/Inc/uartProtocol_GNSS.h Sat Nov 15 19:29:44 2025 +0100 @@ -42,6 +42,8 @@ UART_GNSS_LOADCONF_1, UART_GNSS_LOADCONF_2, UART_GNSS_SETMODE_MOBILE, + UART_GNSS_SETDATE_TIME, + UART_GNSS_SET_POSITION, UART_GNSS_PWRDOWN, UART_GNSS_PWRUP, UART_GNSS_SETCONF, /* save configuration */ @@ -74,6 +76,8 @@ GNSSCMD_LOADCONF_1, GNSSCMD_LOADCONF_2, GNSSCMD_SETMOBILE, + GNSSCMD_SETDATETIME, + GNSSCMD_SET_POSITION, GNSSCMD_MODE_PWS, GNSSCMD_MODE_NORMAL, GNSSCMD_SET_CONFIG,
--- a/Small_CPU/Src/baseCPU2.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Small_CPU/Src/baseCPU2.c Sat Nov 15 19:29:44 2025 +0100 @@ -172,7 +172,7 @@ // See CPU2-RTE.ld const SFirmwareData cpu2_FirmwareData __attribute__(( section(".firmware_data") ))= { .versionFirst = 3, - .versionSecond = 4, + .versionSecond = 7, .versionThird = 0, .versionBeta = 0, @@ -180,8 +180,8 @@ .signature = "mh", .release_year = 25, - .release_month = 1, - .release_day = 18, + .release_month = 6, + .release_day = 9, .release_sub = 0, /* max 48 with trailing 0 */ @@ -285,8 +285,6 @@ HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0); MX_RTC_init(); - GPIO_LEDs_VIBRATION_Init(); - GPIO_GNSS_Init(); GPIO_new_DEBUG_Init(); // added 170322 hw initGlobals(); @@ -402,46 +400,19 @@ if (global.mode == MODE_BOOT) { GPIO_Power_MainCPU_OFF(); -#ifdef ENABLE_GPIO_V2 - GPIO_LED_GREEN_ON(); -#endif HAL_Delay(100); // for GPIO_Power_MainCPU_ON(); GPIO_Power_MainCPU_ON(); -#ifdef ENABLE_GPIO_V2 - GPIO_LED_GREEN_OFF(); - - GPIO_LED_RED_ON(); - GPIO_VIBRATION_ON(); -#endif HAL_Delay(100); -#ifdef ENABLE_GPIO_V2 - GPIO_LED_RED_OFF(); - GPIO_VIBRATION_OFF(); -#endif } -#ifdef ENABLE_GPIO_V2 - GPIO_LED_RED_OFF(); - GPIO_LED_GREEN_OFF(); - GPIO_VIBRATION_OFF(); -#endif SPI_synchronize_with_Master(); MX_DMA_Init(); MX_SPI1_Init(); SPI_Start_single_TxRx_with_Master(); /* be prepared for the first data exchange */ Scheduler_Request_sync_with_SPI(SPI_SYNC_METHOD_HARD); -#ifdef ENABLE_GPIO_V2 - // GNSS tests - GNSS_IO_init(); - GPIO_GPS_ON(); - GPIO_GPS_BCKP_ON(); - MX_USART6_UART_Init(); - GNSS_Init(&GNSS_Handle, &huart6); -#else -#ifdef ENABLE_GNSS_SUPPORT +#ifdef ENABLE_GNSS_EXTERN GNSS_Init(&GNSS_Handle, &huart1); #endif -#endif global.mode = MODE_SURFACE; break; @@ -466,8 +437,11 @@ global.no_fly_time_minutes = 0; global.lifeData.dive_time_seconds = 0; global.lifeData.dive_time_seconds_without_surface_time = 0; -#if defined ENABLE_GNSS_SUPPORT || defined ENABLE_GPIO_V2 - uartGnss_ReqPowerDown(1); +#if defined ENABLE_GNSS_INTERN + if(GPIO_GetVersion() > 0) + { + uartGnss_ReqPowerDown(1); + } #endif scheduleDiveMode(); // done now in scheduler prior to change mode: global.seconds_since_last_dive = 1; @@ -494,8 +468,11 @@ backup.no_fly_time_minutes = 0; backup.seconds_since_last_dive = 0; -#if defined ENABLE_GNSS_SUPPORT || defined ENABLE_GPIO_V2 - uartGnss_ReqPowerDown(0); +#if defined ENABLE_GNSS_INTERN + if(GPIO_GetVersion() > 0) + { + uartGnss_ReqPowerDown(0); + } #endif break; @@ -504,27 +481,43 @@ MX_SPI3_Init(); -#if defined ENABLE_GNSS_SUPPORT || defined ENABLE_GPIO_V2 - if(shutdownTick == 0) +#if defined ENABLE_GNSS_INTERN || defined ENABLE_GNSS_EXTERN + + do + { + if(GPIO_GetVersion() > 0) { - shutdownTick = HAL_GetTick(); - uartGnss_ReqPowerDown(1); + if(shutdownTick == 0) + { + shutdownTick = HAL_GetTick(); + uartGnss_ReqPowerDown(1); + } } -#ifdef ENABLE_GNSS_SUPPORT +#endif +#ifdef ENABLE_GNSS_EXTERN externalInterface_HandleUART(); #else - UART6_HandleUART(); +#ifdef ENABLE_GNSS_INTERN + if(GPIO_GetVersion() > 0) + { + UART6_HandleUART(); + } #endif - if((uartGnss_GetState() == UART_GNSS_INACTIVE) || (time_elapsed_ms(shutdownTick,HAL_GetTick()) > 3000)) +#endif +#if defined ENABLE_GNSS_INTERN || defined ENABLE_GNSS_EXTERN + if((uartGnss_GetState() == UART_GNSS_INACTIVE) || (time_elapsed_ms(shutdownTick,HAL_GetTick()) > 4000)) { global.mode = MODE_SLEEP; uartGnss_ReqPowerDown(0); /* release power down request */ + uartGnss_SetState(UART_GNSS_INACTIVE); } + #else global.mode = MODE_SLEEP; #endif - - +#if defined ENABLE_GNSS_INTERN || defined ENABLE_GNSS_EXTERN + }while (global.mode == MODE_SHUTDOWN); +#endif break; case MODE_SLEEP: @@ -533,7 +526,6 @@ externalInterface_SwitchPower33(false); if (hasExternalClock()) SystemClock_Config_HSI(); - GPIO_LEDs_VIBRATION_Init(); sleep_prepare(); while(time_elapsed_ms(shutdownTick,HAL_GetTick()) < 1000 ) /* delay shutdown till shutdown animation is finished */ @@ -542,6 +534,8 @@ } shutdownTick = 0; scheduleSleepMode(); + + /* wakeup starts here */ if (hasExternalClock()) SystemClock_Config_HSE(); EXTI_Wakeup_Button_DeInit(); @@ -560,6 +554,7 @@ externalInterface_SwitchPower33(true); } externalInterface_InitDatastruct(); + GPIO_Init_V2(); // EXTILine0_Button_DeInit(); not now, later after testing break; } @@ -888,6 +883,9 @@ } void sleep_prepare(void) { + + GPIO_InitTypeDef GPIO_InitStruct; + EXTI_Wakeup_Button_Init(); compass_sleep(); @@ -900,7 +898,12 @@ MX_SPI3_DeInit(); ADCx_DeInit(); - GPIO_InitTypeDef GPIO_InitStruct; + if(GPIO_GetVersion() > 0) + { + GPIO_LED_GREEN_OFF(); + GPIO_LED_RED_OFF(); + GPIO_VIBRATION_OFF(); + } __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); @@ -912,41 +915,41 @@ GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Pin = GPIO_PIN_All; HAL_GPIO_Init( GPIOH, &GPIO_InitStruct); + #ifdef ENABLE_SLEEP_DEBUG GPIO_InitStruct.Pin = GPIO_PIN_All ^ ( GPIO_PIN_3 | GPIO_PIN_8 | GPIO_PIN_9); /* debug */ #endif -/* +#ifdef ENABLE_GNSS_INTERN GPIO_InitStruct.Pin = GPIO_PIN_All ^ (GPS_POWER_CONTROL_PIN | GPS_BCKP_CONTROL_PIN); +#else + GPIO_InitStruct.Pin = GPIO_PIN_All; +#endif HAL_GPIO_Init( GPIOB, &GPIO_InitStruct); -*/ + GPIO_InitStruct.Pin = GPIO_PIN_All ^ ( MAINCPU_CONTROL_PIN | CHARGE_OUT_PIN | EXT33V_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 | VIBRATION_CONTROL_PIN | LED_CONTROL_PIN_RED | LED_CONTROL_PIN_GREEN); + GPIO_InitStruct.Pin = GPIO_PIN_All ^ ( GPIO_PIN_0 ); /* could be added for debug purpose: | VIBRATION_CONTROL_PIN | LED_CONTROL_PIN_RED | LED_CONTROL_PIN_GREEN */ #ifdef ENABLE_SLEEP_DEBUG GPIO_InitStruct.Pin = GPIO_PIN_All ^ ( GPIO_PIN_0 | GPIO_PIN_13 | GPIO_PIN_14); /* wake up button & debug */ #endif HAL_GPIO_Init( GPIOA, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_All; - HAL_GPIO_Init( GPIOH, &GPIO_InitStruct); + GPIO_Power_MainCPU_OFF(); - GPIO_Power_MainCPU_OFF(); -#ifdef ENABLE_GPIO_V2 - GPIO_LED_GREEN_OFF(); - GPIO_LED_RED_OFF(); - GPIO_VIBRATION_OFF(); - GPIO_GPS_BCKP_ON(); // mH : costs 100µA in sleep - beware -/* GPIO_GPS_OFF(); will be done in transition sleep => deep sleep */ - - MX_USART6_UART_DeInit(); +#ifdef ENABLE_GNSS_INTERN + if(GPIO_GetVersion() > 0) + { + GPIO_GPS_BCKP_ON(); // mH : costs 100µA in sleep - beware + /* GPIO_GPS_OFF(); will be done in transition sleep => deep sleep */ + MX_USART6_UART_DeInit(); + } #endif #ifndef ENABLE_SLEEP_DEBUG -/* +#ifndef ENABLE_GNSS_INTERN __HAL_RCC_GPIOB_CLK_DISABLE(); -*/ +#endif #endif __HAL_RCC_GPIOH_CLK_DISABLE(); }
--- a/Small_CPU/Src/compass.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Small_CPU/Src/compass.c Sat Nov 15 19:29:44 2025 +0100 @@ -86,6 +86,17 @@ int16_t compass_CZ_f; ///< calibration value +float compass_DX_min; +float compass_DX_max; + +float compass_DY_min; +float compass_DY_max; + +float compass_DZ_min; +float compass_DZ_max; + + + /// The (filtered) components of the accelerometer sensor int16_t accel_DX_f; ///< output from sensor int16_t accel_DY_f; ///< output from sensor @@ -1070,8 +1081,25 @@ // =============================================================================== void compass_calc_roll_pitch_only(void) { - float sinPhi, cosPhi; + float sinPhi, cosPhi, sinTeta, cosTeta; float Phi, Teta; + float mx_corr, my_corr; + + float offsetX, offsetY, offsetZ; + float scaleX, scaleY,scaleZ; + + float local_DX = compass_DX_f; + float local_DY = compass_DY_f; + float local_DZ = compass_DZ_f; + + + if(local_DX < compass_DX_min) compass_DX_min = local_DX; + if(local_DY < compass_DY_min) compass_DY_min = local_DY; + if(local_DZ < compass_DZ_min) compass_DZ_min = local_DZ; + + if(local_DX > compass_DX_max) compass_DX_max = local_DX; + if(local_DY > compass_DY_max) compass_DY_max = local_DY; + if(local_DZ > compass_DZ_max) compass_DZ_max = local_DZ; //---- Calculate sine and cosine of roll angle Phi ----------------------- Phi= atan2f(accel_DY_f, accel_DZ_f) ; @@ -1079,9 +1107,38 @@ sinPhi = sinf(Phi); cosPhi = cosf(Phi); - //---- calculate sin and cosine of pitch angle Theta --------------------- Teta = atanf(-(float)accel_DX_f/(accel_DY_f * sinPhi + accel_DZ_f * cosPhi)); - compass_pitch = Teta * 180.0f /PI; + compass_pitch = Teta * (180.0 / PI); + + sinTeta = sinf(Teta); + cosTeta = cosf(Teta); + + offsetX = (compass_DX_max + compass_DX_min) / 2.0; + offsetY = (compass_DY_max + compass_DY_min) / 2.0; + offsetZ = (compass_DZ_max + compass_DZ_min) / 2.0; + + scaleX = 2.0 / (compass_DX_max - compass_DX_min); + scaleY = 2.0 / (compass_DY_max - compass_DY_min); + scaleZ = 2.0 / (compass_DZ_max - compass_DZ_min); + + local_DX -= offsetX; + local_DX *= scaleX; + + local_DY -= offsetY; + local_DY *= scaleY; + + local_DZ -= offsetZ; + local_DZ *= scaleZ; + + mx_corr = local_DX * cosTeta + local_DZ * sinTeta; + my_corr = local_DX * sinPhi * sinTeta + local_DY * cosPhi - local_DZ * sinPhi * cosTeta; + + compass_heading = atan2(my_corr, mx_corr) * (180.0 / PI); + + + if (compass_heading < 0) { + compass_heading += 360.0; + } } @@ -1172,6 +1229,14 @@ g->Suuu = g->Svvv = g->Swww = 0.0; g->Suuv = g->Suuw = g->Svvu = g->Svvw = g->Swwu = g->Swwv = 0.0; compass_CX_f = compass_CY_f = compass_CZ_f = 0.0; + + compass_DX_min = 10000; + compass_DY_min = 10000; + compass_DZ_min = 10000; + + compass_DX_max = -10000; + compass_DY_max = -10000; + compass_DZ_max = -10000; }
--- a/Small_CPU/Src/externalInterface.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Small_CPU/Src/externalInterface.c Sat Nov 15 19:29:44 2025 +0100 @@ -401,7 +401,7 @@ #ifdef ENABLE_CO2_SUPPORT || ((externalAutoDetect >= DETECTION_CO2_0) && (externalAutoDetect <= DETECTION_CO2_3)) #endif -#ifdef ENABLE_GNSS_SUPPORT +#ifdef ENABLE_GNSS_EXTERN || ((externalAutoDetect >= DETECTION_GNSS_0) && (externalAutoDetect <= DETECTION_GNSS_3)) #endif @@ -672,7 +672,7 @@ { static uint8_t sensorIndex = 0; static uint8_t uartMuxChannel = 0; -#ifdef ENABLE_GNSS_SUPPORT +#ifdef ENABLE_GNSS_EXTERN static uint8_t detectionDelayCnt = 0; #endif uint8_t index = 0; @@ -829,7 +829,7 @@ case DETECTION_CO2_3: if(uartCo2_isSensorConnected()) { foundSensorMap[EXT_INTERFACE_MUX_OFFSET + activeUartChannel] = SENSOR_CO2; -#ifdef ENABLE_GNSS_SUPPORT +#ifdef ENABLE_GNSS_EXTERN externalAutoDetect = DETECTION_GNSS_0; /* only one CO2 sensor supported */ #else externalAutoDetect = DETECTION_DONE; /* only one CO2 sensor supported */ @@ -852,8 +852,8 @@ { -#if defined ENABLE_SENTINEL_MODE || defined ENABLE_GNSS_SUPPORT -#ifdef ENABLE_GNSS_SUPPORT +#if defined ENABLE_SENTINEL_MODE || defined ENABLE_GNSS_EXTERN +#ifdef ENABLE_GNSS_EXTERN externalAutoDetect = DETECTION_GNSS_0; externalInterface_SwitchUART(EXT_INTERFACE_UART_GNSS); #else @@ -867,7 +867,7 @@ } #endif -#ifdef ENABLE_GNSS_SUPPORT +#ifdef ENABLE_GNSS_EXTERN if(externalAutoDetect == DETECTION_GNSS_0) { tmpSensorMap[uartMuxChannel + EXT_INTERFACE_MUX_OFFSET] = SENSOR_NONE; @@ -1251,7 +1251,7 @@ case SENSOR_CO2: uartCo2_Control(); break; #endif -#ifdef ENABLE_GNSS_SUPPORT +#ifdef ENABLE_GNSS_EXTERN case SENSOR_GNSS: uartGnss_Control(); break; #endif
--- a/Small_CPU/Src/gpio.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Small_CPU/Src/gpio.c Sat Nov 15 19:29:44 2025 +0100 @@ -25,10 +25,12 @@ #include "gpio.h" #include "data_exchange.h" #include "scheduler.h" +#include "uart_Internal.h" +#include "GNSS.h" /* Exported variables --------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ - +static uint8_t GPIO_Version = 0; /* Private types -------------------------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/ @@ -91,7 +93,6 @@ HAL_GPIO_WritePin( GPIOC, MAINCPU_CONTROL_PIN, GPIO_PIN_RESET); } -#ifdef ENABLE_GPIO_V2 void GPIO_HandleBuzzer() { static uint32_t buzzerOnTick = 0; @@ -124,7 +125,7 @@ buzzerWasOn = 0; } } -#endif + void GPIO_Power_MainCPU_ON(void) { HAL_GPIO_WritePin( GPIOC, MAINCPU_CONTROL_PIN, GPIO_PIN_RESET); } @@ -133,7 +134,6 @@ HAL_GPIO_WritePin( GPIOC, MAINCPU_CONTROL_PIN, GPIO_PIN_SET); } -#ifdef ENABLE_GPIO_V2 void GPIO_LED_GREEN_ON(void) { HAL_GPIO_WritePin( GPIOA, LED_CONTROL_PIN_GREEN, GPIO_PIN_RESET); } @@ -173,8 +173,34 @@ void GPIO_GPS_BCKP_OFF(void) { HAL_GPIO_WritePin( GPIOB, GPS_BCKP_CONTROL_PIN, GPIO_PIN_RESET); } + +uint8_t GPIO_GetVersion() +{ + return GPIO_Version; +} + +void GPIO_Activate_V2(void) +{ + if(GPIO_Version == 0) + { + GPIO_Version = 1; + } +} + +void GPIO_Init_V2(void) +{ + if(GPIO_Version == 1) + { + GPIO_LEDs_VIBRATION_Init(); +#ifdef ENABLE_GNSS_INTERN + GNSS_IO_init(); + GPIO_GPS_ON(); + GPIO_GPS_BCKP_ON(); + MX_USART6_UART_Init(); + GNSS_Init(&GNSS_Handle, &huart6); #endif - + } +} /* Private functions ---------------------------------------------------------*/
--- a/Small_CPU/Src/rtc.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Small_CPU/Src/rtc.c Sat Nov 15 19:29:44 2025 +0100 @@ -35,6 +35,11 @@ HAL_RTC_GetTime(&RTCHandle, pstimestructure, RTC_FORMAT_BIN); } +void RTC_GetDate(RTC_DateTypeDef* psdatestructure) +{ + HAL_RTC_GetDate(&RTCHandle, psdatestructure, RTC_FORMAT_BIN); +} + void RTC_SetTime(RTC_TimeTypeDef stimestructure) {
--- a/Small_CPU/Src/scheduler.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Small_CPU/Src/scheduler.c Sat Nov 15 19:29:44 2025 +0100 @@ -342,9 +342,17 @@ { externalInterface_ExecuteCmd(global.dataSendToSlave.data.externalInterface_Cmd); } -#ifdef ENABLE_GPIO_V2 - GPIO_HandleBuzzer(); -#endif + + if(GPIO_GetVersion() < global.dataSendToSlave.displayVersion) + { + GPIO_Activate_V2(); + GPIO_Init_V2(); + } + + if(GPIO_GetVersion() > 0) + { + GPIO_HandleBuzzer(); + } #if 0 @@ -533,8 +541,11 @@ ticksdiff = time_elapsed_ms(Scheduler.tickstart,lasttick); externalInterface_HandleUART(); -#ifdef ENABLE_GPIO_V2 - UART6_HandleUART(); +#ifdef ENABLE_GNSS_INTERN + if(GPIO_GetVersion() > 0) + { + UART6_HandleUART(); + } #endif if(ticksdiff >= Scheduler.counterSPIdata100msec * 100 + 10) { @@ -838,8 +849,11 @@ } externalInterface_HandleUART(); -#ifdef ENABLE_GPIO_V2 - UART6_HandleUART(); +#ifdef ENABLE_GNSS_INTERN + if(GPIO_GetVersion() > 0) + { + UART6_HandleUART(); + } #endif /* Evaluate received data at 10 ms, 110 ms, 210 ms,... duration ~<1ms */ @@ -893,7 +907,7 @@ adc_ambient_light_sensor_get_data(); copyAmbientLightData(); -#if defined ENABLE_GNSS_SUPPORT || defined ENABLE_GPIO_V2 +#if defined ENABLE_GNSS_INTERN || defined ENABLE_GNSS_EXTERN copyGNSSdata(); #endif Scheduler.counterAmbientLight100msec++; @@ -1110,7 +1124,7 @@ global.dataSendToMaster.mode = 0; global.deviceDataSendToMaster.mode = 0; secondsCount = 0; -#ifdef ENABLE_GPIO_V2 +#ifdef ENABLE_GNSS_INTERN uint16_t deepSleepCntDwn = 21600; /* 12 hours in 2 second steps */ uint8_t deepSleep = 0; GPIO_InitTypeDef GPIO_InitStruct; @@ -1191,31 +1205,34 @@ global.mode = MODE_BOOT; } scheduleUpdateLifeData(2000); -#ifdef ENABLE_GPIO_V2 - if(deepSleepCntDwn) +#ifdef ENABLE_GNSS_INTERN + if(GPIO_GetVersion() > 0) { - deepSleepCntDwn--; - if(deepSleepCntDwn == 0) + if(deepSleepCntDwn) { - deepSleep = 1; - GPIO_GPS_OFF(); - GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; - GPIO_InitStruct.Speed = GPIO_SPEED_LOW; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Pin = GPIO_PIN_All ^ (GPS_POWER_CONTROL_PIN); - HAL_GPIO_Init( GPIOB, &GPIO_InitStruct); - uartGnss_SetState(UART_GNSS_INIT); + deepSleepCntDwn--; + if(deepSleepCntDwn == 0) + { + deepSleep = 1; + GPIO_GPS_OFF(); + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Speed = GPIO_SPEED_LOW; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pin = GPIO_PIN_All ^ (GPS_POWER_CONTROL_PIN); + HAL_GPIO_Init( GPIOB, &GPIO_InitStruct); + uartGnss_SetState(UART_GNSS_INIT); + } } - } - else - { - if((deepSleep = 1) && (global.lifeData.battery_voltage < 3.5)) /* switch off backup voltage if battery gets low */ + else { - deepSleep = 2; - GPIO_GPS_BCKP_OFF(); - GPIO_InitStruct.Pin = GPIO_PIN_All ^ (GPS_BCKP_CONTROL_PIN); - HAL_GPIO_Init( GPIOB, &GPIO_InitStruct); - __HAL_RCC_GPIOB_CLK_DISABLE(); + if((deepSleep = 1) && (global.lifeData.battery_voltage < 3.5)) /* switch off backup voltage if battery gets low */ + { + deepSleep = 2; + GPIO_GPS_BCKP_OFF(); + GPIO_InitStruct.Pin = GPIO_PIN_All ^ (GPS_BCKP_CONTROL_PIN); + HAL_GPIO_Init( GPIOB, &GPIO_InitStruct); + __HAL_RCC_GPIOB_CLK_DISABLE(); + } } } #endif @@ -1227,10 +1244,17 @@ setButtonsNow = 0; reinitGlobals(); ReInit_battery_charger_status_pins(); -#ifdef ENABLE_GPIO_V2 - if(deepSleep != 0) +#ifdef ENABLE_GNSS_INTERN + if(GPIO_GetVersion() > 0) { - GPIO_GNSS_Init(); + if(deepSleep != 0) + { + GPIO_GNSS_Init(); + } + else + { + GNSS_IO_init(); + } } #endif }
--- a/Small_CPU/Src/stm32f4xx_it_v3.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Small_CPU/Src/stm32f4xx_it_v3.c Sat Nov 15 19:29:44 2025 +0100 @@ -61,9 +61,11 @@ extern UART_HandleTypeDef huart1; extern DMA_HandleTypeDef hdma_usart1_rx; extern DMA_HandleTypeDef hdma_usart1_tx; +#ifdef ENABLE_GNSS_INTERN extern UART_HandleTypeDef huart6; extern DMA_HandleTypeDef hdma_usart6_rx; extern DMA_HandleTypeDef hdma_usart6_tx; +#endif /* Private function prototypes -----------------------------------------------*/ /* Private functions ---------------------------------------------------------*/ @@ -249,7 +251,7 @@ HAL_DMA_IRQHandler(&hdma_usart1_tx); } -#ifdef ENABLE_GPIO_V2 +#ifdef ENABLE_GNSS_INTERN void DMA2_Stream2_IRQHandler(void) { HAL_DMA_IRQHandler(&hdma_usart6_rx); @@ -327,7 +329,7 @@ HAL_UART_IRQHandler(&huart1); } -#ifdef ENABLE_GPIO_V2 +#ifdef ENABLE_GNSS_INTERN void USART6_IRQHandler(void) { HAL_UART_IRQHandler(&huart6);
--- a/Small_CPU/Src/uart.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Small_CPU/Src/uart.c Sat Nov 15 19:29:44 2025 +0100 @@ -26,9 +26,10 @@ #include "uartProtocol_GNSS.h" #include "externalInterface.h" #include "data_exchange.h" +#include "gpio.h" #include <string.h> /* memset */ -#ifdef ENABLE_GPIO_V2 +#ifdef ENABLE_GNSS_INTERN extern UART_HandleTypeDef huart6; extern sUartComCtrl Uart6Ctrl; #endif @@ -104,9 +105,11 @@ Uart1Ctrl.pTxBuffer = txBuffer; Uart1Ctrl.txBufferQueLen = 0; -#ifndef ENABLE_GPIO_V2 +#ifndef ENABLE_GNSS_INTERN +#ifdef ENABLE_GNSS_EXTERN UART_SetGnssCtrl(&Uart1Ctrl); #endif +#endif } @@ -337,10 +340,13 @@ { UART_HandleRxComplete(&Uart1Ctrl); } -#ifdef ENABLE_GPIO_V2 - if(huart == &huart6) +#ifdef ENABLE_GNSS_INTERN + if(GPIO_GetVersion() > 0) { - UART_HandleRxComplete(&Uart6Ctrl); + if(huart == &huart6) + { + UART_HandleRxComplete(&Uart6Ctrl); + } } #endif } @@ -363,10 +369,13 @@ { UART_HandleTxComplete(&Uart1Ctrl); } -#ifdef ENABLE_GPIO_V2 - if(huart == &huart6) +#ifdef ENABLE_GNSS_INTERN + if(GPIO_GetVersion() > 0) { - UART_HandleTxComplete(&Uart6Ctrl); + if(huart == &huart6) + { + UART_HandleTxComplete(&Uart6Ctrl); + } } #endif } @@ -401,11 +410,13 @@ if(sensorType == SENSOR_GNSS) { -#ifdef ENABLE_GPIO_V2 +#ifdef ENABLE_GNSS_INTERN pUartCtrl = &Uart6Ctrl; #else +#ifdef ENABLE_GNSS_EXTERN pUartCtrl = &Uart1Ctrl; #endif +#endif } else { @@ -438,7 +449,7 @@ case SENSOR_CO2: uartCo2_ProcessData(pUartCtrl->pRxBuffer[localRX]); break; #endif - #if defined ENABLE_GNSS_SUPPORT || defined ENABLE_GPIO_V2 + #if defined ENABLE_GNSS_INTERN || defined ENABLE_GNSS_EXTERN case SENSOR_GNSS: uartGnss_ProcessData(pUartCtrl->pRxBuffer[localRX]); break; #endif
--- a/Small_CPU/Src/uartProtocol_GNSS.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Small_CPU/Src/uartProtocol_GNSS.c Sat Nov 15 19:29:44 2025 +0100 @@ -26,9 +26,10 @@ #include "GNSS.h" #include "configuration.h" #include "externalInterface.h" +#include "rtc.h" -#if defined ENABLE_GNSS || defined ENABLE_GNSS_SUPPORT || defined ENABLE_GPIO_V2 +#if defined ENABLE_GNSS_INTERN || defined ENABLE_GNSS_EXTERN static uartGnssStatus_t gnssState = UART_GNSS_INIT; static gnssRequest_s activeRequest = {0,0}; @@ -88,6 +89,11 @@ { const uint8_t* pData; uint8_t txLength = 0; + RTC_TimeTypeDef time; + RTC_DateTypeDef date; + + UBX_MGA_INI_TIME_UTC_t msg_DateTime; + UBX_MGA_INI_POS_LLH_t msg_Position; switch (GnssCmd) { @@ -121,6 +127,51 @@ case GNSSCMD_SET_CONFIG: pData = setConfig; txLength = sizeof(setConfig) / sizeof(uint8_t); break; + case GNSSCMD_SETDATETIME: + RTC_GetDate(&date); + RTC_GetTime(&time); + + memset(&msg_DateTime, 0, sizeof(UBX_MGA_INI_TIME_UTC_t)); + msg_DateTime.header1 = 0xB5; + msg_DateTime.header2 = 0x62; + msg_DateTime.msgClass = 0x13; + msg_DateTime.msgID = 0x40; + msg_DateTime.length = sizeof(UBX_MGA_INI_TIME_UTC_t) - 6; + msg_DateTime.type = 0x00; + msg_DateTime.version = 0x00; + msg_DateTime.year = date.Year + 2000; + msg_DateTime.month = date.Month; + msg_DateTime.day = date.Date; + if((time.Hours - 2) < 0) + { + msg_DateTime.hour = time.Hours + 24 - 2; + } + else + { + msg_DateTime.hour = time.Hours - 2; + } + msg_DateTime.minute = time.Minutes; + msg_DateTime.second = time.Seconds; + msg_DateTime.accuracy_seconds = 60; + msg_DateTime.accuracy_nano = 0x0; + msg_DateTime.flags = 0x00; + msg_DateTime.leapsec = 0x80; + + pData = (uint8_t*)&msg_DateTime; + txLength = sizeof(msg_DateTime) / sizeof(uint8_t); + break; + case GNSSCMD_SET_POSITION: msg_Position.header1 = 0xB5; + msg_Position.header2 = 0x62; + msg_Position.class_id = 0x13; + msg_Position.msg_id = 0x40; + msg_Position.length = sizeof(UBX_MGA_INI_POS_LLH_t) - 6; + msg_Position.latitude = (int32_t) (8.98647 * 1e7); + msg_Position.longitude = (int32_t) (47.77147 * 1e7); + msg_Position.altitude = (int32_t) 40000; + msg_Position.accuracy = 100000; + pData = (uint8_t*)&msg_Position; + txLength = sizeof(msg_Position) / sizeof(uint8_t); + break; default: break; } @@ -165,9 +216,17 @@ case UART_GNSS_LOADCONF_2: UART_Gnss_SendCmd(GNSSCMD_LOADCONF_2); rxState = GNSSRX_DETECT_ACK_0; break; - case UART_GNSS_SETMODE_MOBILE: UART_Gnss_SendCmd(GNSSCMD_LOADCONF_2); + case UART_GNSS_SETMODE_MOBILE: UART_Gnss_SendCmd(GNSSCMD_SETMOBILE); rxState = GNSSRX_DETECT_ACK_0; break; + case UART_GNSS_SETDATE_TIME: UART_Gnss_SendCmd(GNSSCMD_SETDATETIME); + // rxState = GNSSRX_DETECT_ACK_0; /* aiding function will not acknoledge receiption (until config to do so) */ + gnssState = UART_GNSS_SET_POSITION; + break; + case UART_GNSS_SET_POSITION: UART_Gnss_SendCmd(GNSSCMD_SET_POSITION); + // rxState = GNSSRX_DETECT_ACK_0; /* aiding function will not acknoledge receiption (until config to do so) */ + gnssState = UART_GNSS_IDLE; + break; case UART_GNSS_PWRDOWN: UART_Gnss_SendCmd(GNSSCMD_MODE_PWS); rxState = GNSSRX_DETECT_ACK_0; break; @@ -287,12 +346,29 @@ case UART_GNSS_LOADCONF_0: case UART_GNSS_LOADCONF_1: gnssState++; break; - case UART_GNSS_LOADCONF_2: gnssState = UART_GNSS_SETMODE_MOBILE; + case UART_GNSS_LOADCONF_2: +#ifdef ENABLE_GNSS_TIME_INIT + gnssState = UART_GNSS_SETMODE_MOBILE; +#else + gnssState = UART_GNSS_SET_POSITION; +#endif break; - case UART_GNSS_SETMODE_MOBILE: rxState = GNSSRX_DETECT_ACK_0; + case UART_GNSS_SETMODE_MOBILE: +#ifdef ENABLE_GNSS_TIME_INIT + gnssState = UART_GNSS_SETDATE_TIME; +#else + rxState = GNSSRX_DETECT_ACK_0; + UART_Gnss_SendCmd(GNSSCMD_MODE_NORMAL); + gnssState = UART_GNSS_PWRUP; +#endif + break; + case UART_GNSS_SET_POSITION: rxState = GNSSRX_DETECT_ACK_0; UART_Gnss_SendCmd(GNSSCMD_MODE_NORMAL); gnssState = UART_GNSS_PWRUP; break; + case UART_GNSS_SETDATE_TIME: rxState = GNSSRX_DETECT_ACK_0; + UART_Gnss_SendCmd(GNSSCMD_MODE_NORMAL); + gnssState = UART_GNSS_PWRUP; default: break; }
--- a/Small_CPU/Src/uart_Internal.c Sun Nov 02 19:30:58 2025 +0100 +++ b/Small_CPU/Src/uart_Internal.c Sat Nov 15 19:29:44 2025 +0100 @@ -64,6 +64,56 @@ GPIO_InitStruct.Speed = GPIO_SPEED_FAST; GPIO_InitStruct.Alternate = GPIO_AF8_USART6; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); +} + +void MX_USART6_DMA_Init() { + /* DMA controller clock enable */ + __HAL_RCC_DMA2_CLK_ENABLE(); + + /* DMA interrupt init */ + /* DMA2_Stream2_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn); + /* DMA2_Stream6_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(DMA2_Stream6_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(DMA2_Stream6_IRQn); +} + + +void MX_USART6_UART_DeInit(void) +{ + HAL_DMA_Abort(&hdma_usart6_rx); + HAL_DMA_DeInit(&hdma_usart6_rx); + HAL_DMA_Abort(&hdma_usart6_tx); + HAL_DMA_DeInit(&hdma_usart6_tx); + HAL_UART_DeInit(&huart6); + //HAL_UART_DeInit(&huart6); + Uart6Ctrl.dmaRxActive = 0; + Uart6Ctrl.dmaTxActive = 0; +} + +void MX_USART6_UART_Init(void) { + huart6.Instance = USART6; + huart6.Init.BaudRate = 9600; + huart6.Init.WordLength = UART_WORDLENGTH_8B; + huart6.Init.StopBits = UART_STOPBITS_1; + huart6.Init.Parity = UART_PARITY_NONE; + huart6.Init.Mode = UART_MODE_TX_RX; + huart6.Init.HwFlowCtl = UART_HWCONTROL_NONE; + huart6.Init.OverSampling = UART_OVERSAMPLING_16; + HAL_UART_Init(&huart6); + + Uart6Ctrl.pHandle = &huart6; + Uart6Ctrl.dmaRxActive = 0; + Uart6Ctrl.dmaTxActive = 0; + Uart6Ctrl.pRxBuffer = rxBufferUart6; + Uart6Ctrl.pTxBuffer = txBufferUart6; + Uart6Ctrl.rxReadIndex = 0; + Uart6Ctrl.rxWriteIndex = 0; + Uart6Ctrl.txBufferQueLen = 0; + + UART_clearRxBuffer(&Uart6Ctrl); + UART_SetGnssCtrl(&Uart6Ctrl); /* USART6 DMA Init */ /* USART6_RX Init */ @@ -101,56 +151,6 @@ HAL_NVIC_EnableIRQ(USART6_IRQn); MX_USART6_DMA_Init(); - -} - -void MX_USART6_DMA_Init() { - /* DMA controller clock enable */ - __HAL_RCC_DMA2_CLK_ENABLE(); - - /* DMA interrupt init */ - /* DMA2_Stream2_IRQn interrupt configuration */ - HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 0, 0); - HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn); - /* DMA2_Stream6_IRQn interrupt configuration */ - HAL_NVIC_SetPriority(DMA2_Stream6_IRQn, 0, 0); - HAL_NVIC_EnableIRQ(DMA2_Stream6_IRQn); -} - - -void MX_USART6_UART_DeInit(void) -{ - HAL_DMA_Abort(&hdma_usart6_rx); - HAL_DMA_DeInit(&hdma_usart6_rx); - HAL_DMA_Abort(&hdma_usart6_tx); - HAL_DMA_DeInit(&hdma_usart6_tx); - HAL_UART_DeInit(&huart6); - HAL_UART_DeInit(&huart6); -} - -void MX_USART6_UART_Init(void) { - huart6.Instance = USART6; - huart6.Init.BaudRate = 9600; - huart6.Init.WordLength = UART_WORDLENGTH_8B; - huart6.Init.StopBits = UART_STOPBITS_1; - huart6.Init.Parity = UART_PARITY_NONE; - huart6.Init.Mode = UART_MODE_TX_RX; - huart6.Init.HwFlowCtl = UART_HWCONTROL_NONE; - huart6.Init.OverSampling = UART_OVERSAMPLING_16; - HAL_UART_Init(&huart6); - - UART_clearRxBuffer(&Uart6Ctrl); - - Uart6Ctrl.pHandle = &huart6; - Uart6Ctrl.dmaRxActive = 0; - Uart6Ctrl.dmaTxActive = 0; - Uart6Ctrl.pRxBuffer = rxBufferUart6; - Uart6Ctrl.pTxBuffer = txBufferUart6; - Uart6Ctrl.rxReadIndex = 0; - Uart6Ctrl.rxWriteIndex = 0; - Uart6Ctrl.txBufferQueLen = 0; - - UART_SetGnssCtrl(&Uart6Ctrl); } void UART6_HandleUART() @@ -163,7 +163,9 @@ uartGnssStatus_t gnssState = uartGnss_GetState(); - if(gnssState != UART_GNSS_INIT) + if(Uart6Ctrl.pHandle != 0) + { + if((gnssState != UART_GNSS_INIT) && (gnssState != UART_GNSS_PWRUP)) { UART_ReadData(SENSOR_GNSS, 0); UART_WriteData(&Uart6Ctrl); @@ -186,7 +188,7 @@ uartGnss_SetState(gnssState); } else if(((retryRequest == 0) /* timeout or error */ - && (((time_elapsed_ms(lastRequestTick,tick) > (TIMEOUT_SENSOR_ANSWER)) && (gnssState != UART_GNSS_IDLE)) /* retry if no answer after half request interval */ + && (((time_elapsed_ms(lastRequestTick,tick) > (TIMEOUT_SENSOR_ANSWER)) && (gnssState != UART_GNSS_IDLE) && (gnssState != UART_GNSS_PWRUP)) /* retry if no answer after half request interval */ || (gnssState == UART_GNSS_ERROR)))) { /* The channel switch will cause the sensor to respond with an error message. */ @@ -216,7 +218,7 @@ timeToTrigger = 0; uartGnss_Control(); } - + } }
