changeset 776:45b8f3c2acce

Add support for a configurable compass declination in a range of -99 to 99 degrees. This allows the displayed compass reading to be configured to take into account the compass declination (difference between the measured magnetic North direction and the actual geographical North direction) that has different values for different locations around the globe. See https://magnetic-declination.com/ for more information. (mikeller)
author heinrichsweikamp
date Thu, 18 May 2023 09:49:17 +0200
parents 46c6d2380d4e
children 74253a41cf80
files Common/Inc/data_central.h Common/Inc/settings.h Discovery/Inc/base.h Discovery/Inc/crcmodel.h Discovery/Inc/tMenuEdit.h Discovery/Inc/tStructure.h Discovery/Inc/text_multilanguage.h Discovery/Src/base.c Discovery/Src/data_central.c Discovery/Src/data_exchange_main.c Discovery/Src/settings.c Discovery/Src/t7.c Discovery/Src/tMenuEdit.c Discovery/Src/tMenuEditHardware.c Discovery/Src/tMenuEditXtra.c Discovery/Src/text_multilanguage.c
diffstat 16 files changed, 271 insertions(+), 61 deletions(-) [+]
line wrap: on
line diff
--- a/Common/Inc/data_central.h	Thu May 11 12:13:03 2023 +0200
+++ b/Common/Inc/data_central.h	Thu May 18 09:49:17 2023 +0200
@@ -28,6 +28,7 @@
 #define DATA_CENTRAL_H
 
 #include <stdint.h>
+#include <stdbool.h>
 
 #include "settings.h"
 #include "stm32f4xx_hal.h"
@@ -502,5 +503,6 @@
 
 uint8_t isLoopMode(uint8_t Mode);
 
+bool isCompassCalibrated(void);
 void setCompassHeading(uint16_t heading);
 #endif // DATA_CENTRAL_H
--- a/Common/Inc/settings.h	Thu May 11 12:13:03 2023 +0200
+++ b/Common/Inc/settings.h	Thu May 18 09:49:17 2023 +0200
@@ -86,7 +86,7 @@
 
 #define UART_MAX_PROTOCOL		(2u)
 
-#define FUTURE_SPARE_SIZE		(4u)		/* Applied for reuse of old, not used, scooter block (was 32 bytes)*/
+#define FUTURE_SPARE_SIZE		(3u)		/* Applied for reuse of old, not used, scooter block (was 32 bytes)*/
 
 typedef enum
 {
@@ -237,6 +237,7 @@
 	SScrubberData scrubberData[2];
 	uint8_t ext_sensor_map[5];
 	uint8_t buttonLockActive;										/* redefined in 0xFFFF0025 */
+	int8_t compassDeclinationDeg;										/* redefined in 0xFFFF0026 */
 	uint8_t Future_SPARE[FUTURE_SPARE_SIZE];					/* redefined in 0xFFFF0020 (old scooter Block was 32 byte)*/
 	// new in 0xFFFF0006
 	uint8_t ppo2sensors_deactivated;
--- a/Discovery/Inc/base.h	Thu May 11 12:13:03 2023 +0200
+++ b/Discovery/Inc/base.h	Thu May 18 09:49:17 2023 +0200
@@ -109,6 +109,7 @@
 void get_globalStateList(SStateList *output);
 void set_globalState_Menu_Page(uint8_t page);
 void set_globalState_Menu_Line(uint8_t line);
+uint8_t get_globalState_Menu_Line(void);
 void get_idSpecificStateList(uint32_t id, SStateList *output);
 void delayMicros(uint32_t micros);
 void get_RTC_DateTime(RTC_DateTypeDef * sdatestructureget, RTC_TimeTypeDef * stimestructureget);
--- a/Discovery/Inc/crcmodel.h	Thu May 11 12:13:03 2023 +0200
+++ b/Discovery/Inc/crcmodel.h	Thu May 18 09:49:17 2023 +0200
@@ -112,8 +112,9 @@
 
 #ifndef DONE_STYLE
 
+#include <stdbool.h>
+
 typedef unsigned long   ulong;
-typedef unsigned        bool;
 typedef unsigned char * p_ubyte_;
 
 #ifndef TRUE
--- a/Discovery/Inc/tMenuEdit.h	Thu May 11 12:13:03 2023 +0200
+++ b/Discovery/Inc/tMenuEdit.h	Thu May 18 09:49:17 2023 +0200
@@ -50,6 +50,11 @@
 #define UPDATE_AND_EXIT_TO_MENU 	(255)
 #define UNSPECIFIC_RETURN			(254)
 
+typedef union {
+    uint32_t uint32;
+    int32_t int32;
+} input_u;
+
 void sendActionToMenuEdit(uint8_t sendAction);
 
 void tMenuEdit_init(void);
@@ -75,7 +80,7 @@
 void write_field_2digit(uint32_t editID, uint16_t XleftGimpStyle, uint16_t XrightGimpStyle, uint16_t YtopGimpStyle, const tFont *Font, const char *text, uint32_t int1,  uint32_t int2,  uint32_t int3,  uint32_t int4);
 void write_field_3digit(uint32_t editID, uint16_t XleftGimpStyle, uint16_t XrightGimpStyle, uint16_t YtopGimpStyle, const tFont *Font, const char *text, uint32_t int1,  uint32_t int2,  uint32_t int3,  uint32_t int4);
 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);
-/*void write_field_sdigit(uint32_t editID, uint16_t XleftGimpStyle, uint16_t XrightGimpStyle, uint16_t YtopGimpStyle, const tFont *Font, const char *text, int32_t int1,  int32_t int2,  int32_t int3,  int32_t int4);*/
+void write_field_sdigit(uint32_t editID, uint16_t XleftGimpStyle, uint16_t XrightGimpStyle, uint16_t YtopGimpStyle, const tFont *Font, const char *text, int32_t int1, int32_t int2, int32_t int3, int32_t int4);
 void write_field_button(uint32_t editID, uint16_t XleftGimpStyle, uint16_t XrightGimpStyle, uint16_t YtopGimpStyle, const tFont *Font, const char *text);
 void write_field_symbol(uint32_t editID, uint16_t XleftGimpStyle, uint16_t XrightGimpStyle, uint16_t YtopGimpStyle, const tFont *Font, const char *text, uint8_t int1);
 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);
--- a/Discovery/Inc/tStructure.h	Thu May 11 12:13:03 2023 +0200
+++ b/Discovery/Inc/tStructure.h	Thu May 18 09:49:17 2023 +0200
@@ -266,6 +266,7 @@
 #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)
 
--- a/Discovery/Inc/text_multilanguage.h	Thu May 11 12:13:03 2023 +0200
+++ b/Discovery/Inc/text_multilanguage.h	Thu May 18 09:49:17 2023 +0200
@@ -211,6 +211,7 @@
 		TXT2BYTE_SpecialDiveGasMenuCCR,
 		TXT2BYTE_CompassCalib,
 		TXT2BYTE_CompassInertia,
+		TXT2BYTE_CompassDeclination,
 		TXT2BYTE_UseSensor,
 		TXT2BYTE_AutomaticSP,
 		/* */
--- a/Discovery/Src/base.c	Thu May 11 12:13:03 2023 +0200
+++ b/Discovery/Src/base.c	Thu May 18 09:49:17 2023 +0200
@@ -1051,6 +1051,12 @@
 }
 
 
+uint8_t get_globalState_Menu_Line(void)
+{
+    return (globalStateID & ~MaskLineFieldDigit) >> 16;
+}
+
+
 void set_globalState(uint32_t newID)
 {
     globalStateID = newID;
--- a/Discovery/Src/data_central.c	Thu May 11 12:13:03 2023 +0200
+++ b/Discovery/Src/data_central.c	Thu May 18 09:49:17 2023 +0200
@@ -861,6 +861,13 @@
 	return retVal;
 }
 
+
+bool isCompassCalibrated(void)
+{
+    return stateUsed->lifeData.compass_heading != -1;
+}
+
+
 void setCompassHeading(uint16_t heading)
 {
 
--- a/Discovery/Src/data_exchange_main.c	Thu May 11 12:13:03 2023 +0200
+++ b/Discovery/Src/data_exchange_main.c	Thu May 18 09:49:17 2023 +0200
@@ -1096,11 +1096,19 @@
 		pStateReal->lifeData.surface_time_seconds = (int32_t)dataIn.data[dataIn.boolTimeData].surfacetime_seconds;
 
 		pStateReal->lifeData.compass_heading = dataIn.data[dataIn.boolCompassData].compass_heading;
-		if(settingsGetPointer()->FlipDisplay) /* consider that diver is targeting into the opposite direction */
-		{
-			pStateReal->lifeData.compass_heading -= 180.0;
-			if (pStateReal->lifeData.compass_heading < 0) pStateReal->lifeData.compass_heading +=360.0;
-		}
+        if (pStateReal->lifeData.compass_heading != -1) {
+            if (pSettings->FlipDisplay) { /* consider that diver is targeting into the opposite direction */
+                pStateReal->lifeData.compass_heading -= 180.0;
+            }
+
+            if (pSettings->compassDeclinationDeg != 0) {
+                pStateReal->lifeData.compass_heading = pStateReal->lifeData.compass_heading + pSettings->compassDeclinationDeg - 360.0;
+            }
+
+            while (pStateReal->lifeData.compass_heading < 0) {
+                pStateReal->lifeData.compass_heading += 360.0;
+            }
+        }
 
 		pStateReal->lifeData.compass_roll = dataIn.data[dataIn.boolCompassData].compass_roll;
 		pStateReal->lifeData.compass_pitch = dataIn.data[dataIn.boolCompassData].compass_pitch;
--- a/Discovery/Src/settings.c	Thu May 11 12:13:03 2023 +0200
+++ b/Discovery/Src/settings.c	Thu May 18 09:49:17 2023 +0200
@@ -89,7 +89,7 @@
  * There might even be entries with fixed values that have no range
  */
 const SSettings SettingsStandard = {
-    .header = 0xFFFF0025,
+    .header = 0xFFFF0026,
     .warning_blink_dsec = 8 * 2,
     .lastDiveLogId = 0,
     .logFlashNextSampleStartAddress = SAMPLESTART,
@@ -332,7 +332,8 @@
 	.ext_sensor_map[2] = SENSOR_OPTIC,
 	.ext_sensor_map[3] = SENSOR_NONE,
 	.ext_sensor_map[4] = SENSOR_NONE,
-	.buttonLockActive = 0
+	.buttonLockActive = 0,
+    .compassDeclinationDeg = 0,
 };
 
 /* Private function prototypes -----------------------------------------------*/
@@ -534,6 +535,10 @@
     	// no break;
     case 0xFFFF0024: pSettings->buttonLockActive = 0;
     	// no break;
+    case 0xFFFF0025:
+        pSettings->compassDeclinationDeg = pStandard->compassDeclinationDeg;
+
+    	// no break;
     default:
         pSettings->header = pStandard->header;
         break; // no break before!!
@@ -1578,6 +1583,16 @@
         corrections++;
     }
 
+    if (Settings.compassDeclinationDeg > 99) {
+        Settings.compassDeclinationDeg = 99;
+
+        corrections++;
+    } else if (Settings.compassDeclinationDeg < -99) {
+        Settings.compassDeclinationDeg = -99;
+
+        corrections++;
+    }
+
     if(corrections)
     {
     	settingsWarning = 1;
--- a/Discovery/Src/t7.c	Thu May 11 12:13:03 2023 +0200
+++ b/Discovery/Src/t7.c	Thu May 18 09:49:17 2023 +0200
@@ -1762,12 +1762,6 @@
 }
 
 
-bool isCompassCalibrated(void)
-{
-    return stateUsed->lifeData.compass_heading != -1;
-}
-
-
 static void t7_CcrSummary(SSettings *settings)
 {
     unsigned numLines = 1; // CCR Mode
--- a/Discovery/Src/tMenuEdit.c	Thu May 11 12:13:03 2023 +0200
+++ b/Discovery/Src/tMenuEdit.c	Thu May 18 09:49:17 2023 +0200
@@ -27,6 +27,8 @@
 //////////////////////////////////////////////////////////////////////////////
 
 /* Includes ------------------------------------------------------------------*/
+#include <stdlib.h>
+
 #include "tMenuEdit.h"
 
 #include "externLogbookFlash.h"
@@ -60,7 +62,7 @@
 {
     char orgText[32];
     char newText[32];
-    uint16_t input[4];
+    uint32_t input[4];
     uint16_t coord[3];
     int8_t begin[4], size[4];
     tFont *fontUsed;
@@ -80,6 +82,7 @@
     FIELD_UDIGIT,
     FIELD_2DIGIT,
     FIELD_3DIGIT,
+    FIELD_SDIGIT,
     FIELD_FLOAT,
     FIELD_END
 } SField;
@@ -616,15 +619,15 @@
     case FIELD_NUMBERS:
         write_buttonTextline(TXT2BYTE_ButtonMinus,TXT2BYTE_ButtonEnter,TXT2BYTE_ButtonPlus);
 
-        if(ident[id].subtype == FIELD_UDIGIT)
-        {
+        switch (ident[id].subtype) {
+        case FIELD_UDIGIT:
             if((newContent >= '0') && (newContent <= '9'))
                 ident[id].newText[ident[id].begin[block] + subBlockPosition] = newContent;
 
             mark_new_digit_of_actual_id_block_and_subBlock();
-        }
-        else if(ident[id].subtype == FIELD_3DIGIT)
-        {
+
+            break;
+        case FIELD_3DIGIT:
             if((newContent >= '0') && (newContent <= '0'+200))
             {
                 split_Content_to_Digit_helper( newContent, &digit100, &digit10, &digit1);
@@ -633,15 +636,25 @@
                 ident[id].newText[ident[id].begin[block] + 2] = '0' + digit1;
                 mark_new_3digit_of_actual_id_block();
             }
-        }
-        else // FIELD_2DIGIT
-        {
+
+            break;
+        case FIELD_2DIGIT:
             if((newContent >= '0') && (newContent <= '0'+99))
             {
                 ident[id].newText[ident[id].begin[block]] = '0' + (newContent - '0')/10;
                 ident[id].newText[ident[id].begin[block] + 1] = '0' + ((newContent - '0') - (10*((newContent - '0')/10)));
                 mark_new_2digit_of_actual_id_block();
             }
+
+            break;
+        case FIELD_SDIGIT:
+            if ((subBlockPosition == 0 && (newContent == '+' || newContent == '-')) || (subBlockPosition > 0 && newContent >= '0' && newContent <= '9')) {
+                ident[id].newText[ident[id].begin[block] + subBlockPosition] = newContent;
+            }
+
+            mark_new_digit_of_actual_id_block_and_subBlock();
+
+            break;
         }
         break;
     case FIELD_BUTTON:
@@ -758,6 +771,10 @@
     {
         ident[id].newText[ident[id].begin[block] + 0] = '0' + (newContent - '0')/10;
         ident[id].newText[ident[id].begin[block] + 1] = '0' + ((newContent - '0') - (10*((newContent - '0')/10)));
+    } else if (ident[id].maintype == FIELD_NUMBERS && ident[id].subtype == FIELD_SDIGIT && action == ACTION_BUTTON_ENTER && subBlockPosition == 0) {
+        if (newContent == '+' || newContent == '-') {
+            ident[id].newText[ident[id].begin[block] + subBlockPosition] = newContent;
+        }
     }
     else
     if((ident[id].maintype == FIELD_NUMBERS) && (action == ACTION_BUTTON_ENTER) && (newContent >= '0') && (newContent <= '9'))
@@ -813,6 +830,15 @@
     return CopyContent;
 }
 
+
+static void checkUpdateSDigit(uint8_t newContent)
+{
+    if ((subBlockPosition == 0 && (newContent == '+' || newContent == '-')) || (subBlockPosition > 0 && newContent >= '0' && newContent <= '9')) {
+        ident[id].newText[ident[id].begin[block] + subBlockPosition] = newContent;
+    }
+}
+
+
 void upMenuEditFieldDigit(void)
 {
     uint8_t newContent;
@@ -843,8 +869,11 @@
         return;
     }
 
-    if((ident[id].maintype == FIELD_NUMBERS) && (newContent >= '0') && (newContent <= '9'))
+    if (ident[id].maintype == FIELD_NUMBERS && ident[id].subtype == FIELD_SDIGIT) {
+        checkUpdateSDigit(newContent);
+    } else if (ident[id].maintype == FIELD_NUMBERS && newContent >= '0' && newContent <= '9') {
         ident[id].newText[ident[id].begin[block] + subBlockPosition] = newContent;
+    }
 
     mark_new_digit_of_actual_id_block_and_subBlock();
 }
@@ -880,8 +909,11 @@
         return;
     }
 
-    if((ident[id].maintype == FIELD_NUMBERS) && (newContent >= '0') && (newContent <= '9'))
+    if (ident[id].maintype == FIELD_NUMBERS && ident[id].subtype == FIELD_SDIGIT) {
+        checkUpdateSDigit(newContent);
+    } else if (ident[id].maintype == FIELD_NUMBERS && newContent >= '0' && newContent <= '9') {
         ident[id].newText[ident[id].begin[block] + subBlockPosition] = newContent;
+    }
 
     mark_new_digit_of_actual_id_block_and_subBlock();
 }
@@ -892,6 +924,8 @@
     if(editID != ident[id].callerID)
         return;
 
+    bool isSigned = ident[id].maintype == FIELD_NUMBERS && ident[id].subtype == FIELD_SDIGIT;
+
     uint8_t i, digitCount, digit;
     uint32_t sum[4], multiplier;
 
@@ -905,25 +939,41 @@
         for(digitCount = 1; digitCount < ident[id].size[i]; digitCount++)
             multiplier *= 10;
 
+        bool isNegative = false;
         for(digitCount = 0; digitCount < ident[id].size[i]; digitCount++)
         {
             digit = ident[id].newText[ident[id].begin[i] + digitCount];
 
-            if(digit > '0')
-                digit -= '0';
-            else
-                digit = 0;
+            if (isSigned && digitCount == 0) {
+                if (digit == '-') {
+                    isNegative = true;
+                }
+            } else {
+                if(digit > '0')
+                    digit -= '0';
+                else
+                    digit = 0;
 
-            if(digit > 9)
-                digit = 9;
+                if(digit > 9)
+                    digit = 9;
 
-            sum[i] += digit * multiplier;
+                sum[i] += digit * multiplier;
+            }
 
             if(multiplier >= 10)
                 multiplier /= 10;
             else
                 multiplier = 0;
         }
+
+        if (isSigned) {
+            int32_t value = sum[i];
+            if (isNegative) {
+                value = -value;
+            }
+            sum[i] = ((input_u)value).uint32;
+        }
+
         i++;
     }
 
@@ -1180,13 +1230,24 @@
         return;
     }
 
+    bool isSigned = ident[id].maintype == FIELD_NUMBERS && ident[id].subtype == FIELD_SDIGIT;
+
     uint8_t i, digitCount;
     uint32_t remainder, digit, divider;
 
     i = 0;
     while( ident[id].size[i] && (i < 4))
     {
-        remainder = ident[id].input[i];
+        bool isNegative = false;
+        if (isSigned) {
+            int32_t value = ((input_u)ident[id].input[i]).int32;
+            if (value < 0) {
+                isNegative = true;
+            }
+            remainder = abs(value);
+        } else {
+            remainder = ident[id].input[i];
+        }
         divider = 1;
 
         for(digitCount = 1; digitCount < ident[id].size[i]; digitCount++)
@@ -1194,13 +1255,18 @@
 
         for(digitCount = 0; digitCount < ident[id].size[i]; digitCount++)
         {
-            digit = remainder	/ divider;
-            remainder -= digit * divider;
+            if (isSigned && digitCount == 0) {
+                ident[id].newText[ident[id].begin[i] + digitCount] = isNegative ? '-' : '+';
+            } else {
+                digit = remainder	/ divider;
+                remainder -= digit * divider;
+                if(digit < 10)
+                    ident[id].newText[ident[id].begin[i] + digitCount] = digit + '0';
+                else
+                    ident[id].newText[ident[id].begin[i] + digitCount] = 'x';
+            }
+
             divider /= 10;
-            if(digit < 10)
-                ident[id].newText[ident[id].begin[i] + digitCount] = digit + '0';
-            else
-                ident[id].newText[ident[id].begin[i] + digitCount] = 'x';
         }
         i++;
     }
@@ -1310,11 +1376,12 @@
     write_field_udigit_and_2digit(FIELD_3DIGIT, editID,XleftGimpStyle,XrightGimpStyle,YtopGimpStyle,Font,text,int1,int2,int3,int4);
 }
 
-/*
-void write_field_sdigit(uint32_t editID, uint16_t XleftGimpStyle, uint16_t XrightGimpStyle, uint16_t YtopGimpStyle, const tFont *Font, const char *text, int32_t int1,  int32_t int2,  int32_t int3,  int32_t int4)
+
+void write_field_sdigit(uint32_t editID, uint16_t XleftGimpStyle, uint16_t XrightGimpStyle, uint16_t YtopGimpStyle, const tFont *Font, const char *text, int32_t int1, int32_t int2, int32_t int3, int32_t int4)
 {
+    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_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/tMenuEditHardware.c	Thu May 11 12:13:03 2023 +0200
+++ b/Discovery/Src/tMenuEditHardware.c	Thu May 18 09:49:17 2023 +0200
@@ -159,8 +159,87 @@
     exitMenuEdit_to_Home();
 }
 
+
+static uint8_t togglePlusMinus(uint8_t input)
+{
+    if (input == '+') {
+        return '-';
+    } else {
+        return '+';
+    }
+}
+
+
+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;
@@ -171,7 +250,7 @@
     text[3] = 0;
     write_topline(text);
 
-    if(settingsGetPointer()->compassInertia)
+    if(settings->compassInertia)
     {
     	heading = (uint16_t)compass_getCompensated();
     }
@@ -189,16 +268,20 @@
     text[textIndex++] = TXT2BYTE_CompassInertia;
     text[textIndex++] = ':';
     text[textIndex++] = ' ';
-    text[textIndex++] = '0' + settingsGetPointer()->compassInertia;
+    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;
 
@@ -214,24 +297,28 @@
     text[1] = TXT2BYTE_SetBearing;
     write_field_button(StMHARD2_Compass_SetCourse,	 30, 800, ME_Y_LINE2,  &FontT48, text);
 
-    text[1] = TXT2BYTE_CompassCalib;
-    write_field_button(StMHARD2_Compass_Calibrate,	 30, 800, ME_Y_LINE3,  &FontT48, text);
+    text[1] = TXT2BYTE_ResetBearing;
+    write_field_button(StMHARD2_Compass_ResetCourse, 30, 800, ME_Y_LINE3,  &FontT48, text);
 
-    text[1] = TXT2BYTE_ResetBearing;
-    write_field_button(StMHARD2_Compass_ResetCourse, 30, 800, ME_Y_LINE4,  &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' + settingsGetPointer()->compassInertia;
+    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_ResetCourse,	(uint32_t)OnAction_BearingClear);
     setEvent(StMHARD2_Compass_Inertia,	(uint32_t)OnAction_InertiaLevel);
+    setEvent(StMHARD2_Compass_Declination, (uint32_t)OnAction_CompassDeclination);
 
     write_buttonTextline(TXT2BYTE_ButtonBack,TXT2BYTE_ButtonEnter,TXT2BYTE_ButtonNext);
 }
--- a/Discovery/Src/tMenuEditXtra.c	Thu May 11 12:13:03 2023 +0200
+++ b/Discovery/Src/tMenuEditXtra.c	Thu May 18 09:49:17 2023 +0200
@@ -377,17 +377,24 @@
 }
 
 
-static void drawCompassHeadingMenu(bool doInitialise)
+static void drawCompassHeadingMenu(bool isRefresh)
 {
+    SSettings *settings = settingsGetPointer();
+
     char text[32];
     snprintf(text, 32, "\001%c%c", TXT_2BYTE, TXT2BYTE_CompassHeading);
     write_topline(text);
 
-    uint16_t heading = (uint16_t)stateUsed->lifeData.compass_heading;
+    uint16_t heading;
+    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);
 
-    if (doInitialise) {
+    if (!isRefresh) {
         snprintf(text, 32, "%c%c", TXT_2BYTE, TXT2BYTE_Set);
         write_field_button(StMXTRA_CompassHeading, 20, 800, ME_Y_LINE2, &FontT48, text);
     } else {
@@ -397,7 +404,7 @@
     bool headingIsSet = stateUsed->diveSettings.compassHeading;
     snprintf(text, 32, "%s%c%c", makeGrey(!headingIsSet), TXT_2BYTE, TXT2BYTE_Clear);
     if (headingIsSet) {
-        if (doInitialise) {
+        if (!isRefresh) {
             write_field_button(StMXTRA_CompassHeadingClear, 20, 800, ME_Y_LINE3, &FontT48, text);
         } else {
             tMenuEdit_refresh_field(StMXTRA_CompassHeadingClear);
@@ -406,11 +413,11 @@
         write_label_var(20, 800, ME_Y_LINE3, &FontT48, text);
     }
 
-    int16_t compassBearing = settingsGetPointer()->compassBearing;
+    int16_t compassBearing = settings->compassBearing;
     bool canSetBearing = compassBearing && compassBearing != stateUsed->diveSettings.compassHeading;
     snprintf(text, 32, "%s%c%c (%03u`)", makeGrey(!canSetBearing), TXT_2BYTE, TXT2BYTE_Reset, compassBearing);
     if (canSetBearing) {
-        if (doInitialise) {
+        if (!isRefresh) {
             write_field_button(StMXTRA_CompassHeadingReset, 20, 800, ME_Y_LINE4, &FontT48, text);
         } else {
             tMenuEdit_refresh_field(StMXTRA_CompassHeadingReset);
@@ -419,7 +426,7 @@
         write_label_var(20, 800, ME_Y_LINE4, &FontT48, text);
     }
 
-    if (doInitialise) {
+    if (!isRefresh) {
         setEvent(StMXTRA_CompassHeading, (uint32_t)OnAction_CompassHeading);
         setEvent(StMXTRA_CompassHeadingClear, (uint32_t)OnAction_CompassHeadingClear);
         setEvent(StMXTRA_CompassHeadingReset, (uint32_t)OnAction_CompassHeadingReset);
@@ -431,7 +438,7 @@
 
 void refresh_CompassHeading(void)
 {
-    drawCompassHeadingMenu(false);
+    drawCompassHeadingMenu(true);
 }
 
 
@@ -454,7 +461,7 @@
 
 void openEdit_CompassHeading(void)
 {
-    drawCompassHeadingMenu(true);
+    drawCompassHeadingMenu(false);
 }
 
 
--- a/Discovery/Src/text_multilanguage.c	Thu May 11 12:13:03 2023 +0200
+++ b/Discovery/Src/text_multilanguage.c	Thu May 18 09:49:17 2023 +0200
@@ -182,6 +182,12 @@
 static uint8_t text_IT_CompassInertia[] = "";
 static uint8_t text_ES_CompassInertia[] = "";
 
+static uint8_t text_EN_CompassDeclination[] = "Compass declination";
+static uint8_t text_DE_CompassDeclination[] = "Kompass Deklination";
+static uint8_t text_FR_CompassDeclination[] = "Déclinaison";
+static uint8_t text_IT_CompassDeclination[] = "Ddeclinazione";
+static uint8_t text_ES_CompassDeclination[] = "Declinación";
+
 
 // Menu SYS1 and Customview header
 static uint8_t text_EN_Compass[] = "Compass";
@@ -1982,6 +1988,7 @@
     {(uint8_t)TXT2BYTE_SpecialDiveGasMenuCCR,{text_EN_SpecialDiveGasMenuCCR, text_DE_SpecialDiveGasMenuCCR, text_FR_SpecialDiveGasMenuCCR, text_IT_SpecialDiveGasMenuCCR, text_ES_SpecialDiveGasMenuCCR}},
     {(uint8_t)TXT2BYTE_CompassCalib, 	{text_EN_CompassCalib, text_DE_CompassCalib, text_FR_CompassCalib, text_IT_CompassCalib, text_ES_CompassCalib}},
 	{(uint8_t)TXT2BYTE_CompassInertia,	{text_EN_CompassInertia, text_DE_CompassInertia, text_FR_CompassInertia, text_IT_CompassInertia, text_ES_CompassInertia}},
+	{(uint8_t)TXT2BYTE_CompassDeclination,	{text_EN_CompassDeclination, text_DE_CompassDeclination, text_FR_CompassDeclination, text_IT_CompassDeclination, text_ES_CompassDeclination}},
 	{(uint8_t)TXT2BYTE_UseSensor,		{text_EN_UseSensor, text_DE_UseSensor, text_FR_UseSensor, text_IT_UseSensor, text_ES_UseSensor}},
 	{(uint8_t)TXT2BYTE_AutomaticSP,		{text_EN_AutomaticSP, text_DE_AutomaticSP, text_FR_AutomaticSP, text_IT_AutomaticSP, text_ES_AutomaticSP}},
     {(uint8_t)TXT2BYTE_WarnDecoMissed,  {text_EN_WarnDecoMissed, text_DE_WarnDecoMissed, text_FR_WarnDecoMissed, text_IT_WarnDecoMissed, text_ES_WarnDecoMissed}},