diff Discovery/Src/t3.c @ 38:5f11787b4f42

include in ostc4 repository
author heinrichsweikamp
date Sat, 28 Apr 2018 11:52:34 +0200
parents
children cc8e24374b83
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discovery/Src/t3.c	Sat Apr 28 11:52:34 2018 +0200
@@ -0,0 +1,1275 @@
+///////////////////////////////////////////////////////////////////////////////
+/// -*- coding: UTF-8 -*-
+///
+/// \file   Discovery/Src/t3.c
+/// \brief  Main Template file for dive mode special scree t3
+/// \author Heinrichs Weikamp gmbh
+/// \date   10-Nov-2014
+///
+/// \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 "t3.h"
+
+#include "data_exchange_main.h"
+#include "decom.h"
+#include "gfx_fonts.h"
+#include "math.h"
+#include "tHome.h"
+#include "timer.h"
+#include "unit.h"
+
+//* Importend function prototypes ---------------------------------------------*/
+extern uint8_t write_gas(char *text, uint8_t oxygen, uint8_t helium);
+
+/* Exported variables --------------------------------------------------------*/
+
+const uint16_t BigFontSeperationLeftRight = 399;
+const uint16_t BigFontSeperationTopBottom = 240;
+
+/* Private variables ---------------------------------------------------------*/
+GFX_DrawCfgScreen	t3screen;
+GFX_DrawCfgWindow	t3l1;
+GFX_DrawCfgWindow	t3r1;
+GFX_DrawCfgWindow	t3c1;
+GFX_DrawCfgWindow	t3c2;
+
+extern float depthLastCall[9];
+extern uint8_t idDepthLastCall;
+extern float temperatureLastCall[3];
+extern uint8_t idTemperatureLastCall;
+
+uint8_t t3_selection_customview = 0;
+
+/* TEM HAS TO MOVE TO GLOBAL--------------------------------------------------*/
+
+/* Private types -------------------------------------------------------------*/
+#define TEXTSIZE 16
+
+const uint8_t t3_customviewsStandard[] =
+{
+    CVIEW_T3_Decostop,
+    CVIEW_sensors,
+    CVIEW_Compass,
+    CVIEW_T3_MaxDepth,
+    CVIEW_T3_StopWatch,
+    CVIEW_T3_TTS,
+    CVIEW_T3_ppO2andGas,
+    CVIEW_T3_END
+};
+
+const uint8_t t3_customviewsScooter[] =
+{
+    CVIEW_Scooter,
+    CVIEW_Compass,
+
+    CVIEW_T3_Decostop,
+    CVIEW_T3_MaxDepth,
+    CVIEW_T3_StopWatch,
+    CVIEW_T3_TTS,
+    CVIEW_T3_ppO2andGas,
+
+    CVIEW_T3_END
+};
+
+const uint8_t *t3_customviews = t3_customviewsStandard;
+
+/* Private function prototypes -----------------------------------------------*/
+void t3_refresh_divemode(void);
+
+uint8_t t3_test_customview_warnings(void);
+void t3_refresh_customview(float depth);
+void t3_basics_compass(GFX_DrawCfgScreen *tXscreen, uint16_t ActualHeading, uint16_t UserSetHeading);
+
+/* Exported functions --------------------------------------------------------*/
+
+void t3_init(void)
+{
+    if(getLicence() == LICENCEBONEX)
+    {
+        t3_customviews = t3_customviewsScooter;
+    }
+
+    t3_selection_customview = t3_customviews[0];
+
+    t3screen.FBStartAdress = 0;
+    t3screen.ImageHeight = 480;
+    t3screen.ImageWidth = 800;
+    t3screen.LayerIndex = 1;
+
+    t3l1.Image = &t3screen;
+    t3l1.WindowNumberOfTextLines = 2;
+    t3l1.WindowLineSpacing = 19; // Abstand von Y0
+    t3l1.WindowTab = 100;
+    t3l1.WindowX0 = 0;
+    t3l1.WindowX1 = BigFontSeperationLeftRight - 5;
+    t3l1.WindowY0 = BigFontSeperationTopBottom + 5;
+    t3l1.WindowY1 = 479;
+
+    t3r1.Image = &t3screen;
+    t3r1.WindowNumberOfTextLines = t3l1.WindowNumberOfTextLines;
+    t3r1.WindowLineSpacing = t3l1.WindowLineSpacing;
+    t3r1.WindowTab = t3l1.WindowTab;
+    t3r1.WindowX0 = BigFontSeperationLeftRight + 5;
+    t3r1.WindowX1 = 799;
+    t3r1.WindowY0 = t3l1.WindowY0;
+    t3r1.WindowY1 = t3l1.WindowY1;
+
+    t3c1.Image = &t3screen;
+    t3c1.WindowNumberOfTextLines = 2;
+    t3c1.WindowLineSpacing = t3l1.WindowLineSpacing;
+    t3c1.WindowX0 = 0;
+    t3c1.WindowX1 = 799;
+    t3c1.WindowY0 = 0;
+    t3c1.WindowY1 = BigFontSeperationTopBottom - 5;
+
+    t3c2.Image = &t3screen;
+    t3c2.WindowNumberOfTextLines = 3;
+    t3c2.WindowLineSpacing = 58;
+    t3c2.WindowX0 = 370;
+    t3c2.WindowX1 = 799;
+    t3c2.WindowY0 = 0;
+    t3c2.WindowY1 = BigFontSeperationTopBottom - 5;
+    t3c2.WindowTab = 600;
+}
+
+
+void t3_refresh(void)
+{
+    SStateList status;
+    get_globalStateList(&status);
+
+    if(stateUsed->mode != MODE_DIVE)
+    {
+        settingsGetPointer()->design = 7;
+        return;
+    }
+
+    if(status.base != BaseHome)
+        return;
+
+    t3screen.FBStartAdress = getFrame(24);
+    t3_refresh_divemode();
+    GFX_SetFramesTopBottom(t3screen.FBStartAdress, NULL,480);
+    releaseAllFramesExcept(24,t3screen.FBStartAdress);
+}
+
+
+/* Private functions ---------------------------------------------------------*/
+
+float t3_basics_lines_depth_and_divetime(GFX_DrawCfgScreen *tXscreen, GFX_DrawCfgWindow* tXl1, GFX_DrawCfgWindow* tXr1, uint8_t mode)
+{
+    char text[512];
+    uint8_t color;
+    uint8_t depthChangeRate;
+    uint8_t depthChangeAscent;
+    point_t start, stop, startZeroLine;
+
+    start.x = 0;
+    stop.x = 799;
+    stop.y = start.y = BigFontSeperationTopBottom;
+    GFX_draw_line(tXscreen, start, stop, CLUT_Font020);
+
+    start.y = BigFontSeperationTopBottom;
+    stop.y = 479;
+    stop.x = start.x = BigFontSeperationLeftRight;
+    GFX_draw_line(tXscreen, start, stop, CLUT_Font020);
+
+
+    /* depth */
+    float depth = 0;
+    float depthThisCall = unit_depth_float(stateUsed->lifeData.depth_meter);
+    if(is_stateUsedSetToSim())
+    {
+        depth = (depthThisCall + depthLastCall[0] + depthLastCall[1] + depthLastCall[2] + depthLastCall[3] + depthLastCall[4] + depthLastCall[5] + depthLastCall[6] + depthLastCall[7] + depthLastCall[8]) / 10.0f;
+
+        idDepthLastCall++;
+        if(idDepthLastCall >= 9)
+            idDepthLastCall = 0;
+        depthLastCall[idDepthLastCall] = depthThisCall;
+    }
+    else
+    {
+        depth = (depthThisCall + depthLastCall[0] + depthLastCall[1] + depthLastCall[2]) / 4.0f;
+
+        idDepthLastCall++;
+        if(idDepthLastCall >= 3)
+            idDepthLastCall = 0;
+        depthLastCall[idDepthLastCall] = depthThisCall;
+    }
+
+    if(depth <= 0.3f)
+        depth = 0;
+
+    if(settingsGetPointer()->nonMetricalSystem)
+        snprintf(text,TEXTSIZE,"\032\f[feet]");
+    else
+        snprintf(text,TEXTSIZE,"\032\f%c",TXT_Depth);
+    GFX_write_string(&FontT42,tXl1,text,0);
+
+    if(			((mode == DIVEMODE_Apnea) && ((stateUsed->lifeData.ascent_rate_meter_per_min > 4) || (stateUsed->lifeData.ascent_rate_meter_per_min < -4 )))
+            || 	((mode != DIVEMODE_Apnea) && ((stateUsed->lifeData.ascent_rate_meter_per_min > 8) || (stateUsed->lifeData.ascent_rate_meter_per_min < -10)))
+        )
+    {
+        snprintf(text,TEXTSIZE,"\f\002%.0f %c%c/min  "
+            , unit_depth_float(stateUsed->lifeData.ascent_rate_meter_per_min)
+            , unit_depth_char1()
+            , unit_depth_char2()
+        );
+        GFX_write_string(&FontT42,tXl1,text,0);
+    }
+
+    if( depth < 100)
+        snprintf(text,TEXTSIZE,"\020\003\016%01.1f",depth);
+    else
+        snprintf(text,TEXTSIZE,"\020\003\016%01.0f",depth);
+
+    t3_basics_colorscheme_mod(text);
+    GFX_write_string(&FontT105,tXl1,text,1);
+
+
+    /* ascentrate graph */
+    if(mode == DIVEMODE_Apnea)
+    {
+        /* ascentrate graph - apnea mode */
+        if(stateUsed->lifeData.ascent_rate_meter_per_min > 0)
+        {
+            depthChangeAscent = 1;
+            if(stateUsed->lifeData.ascent_rate_meter_per_min < 200)
+                depthChangeRate = (uint8_t)stateUsed->lifeData.ascent_rate_meter_per_min;
+            else
+                depthChangeRate = 200;
+        }
+        else
+        {
+            depthChangeAscent = 0;
+            if(stateUsed->lifeData.ascent_rate_meter_per_min > -200)
+                depthChangeRate = (uint8_t)(0 - stateUsed->lifeData.ascent_rate_meter_per_min);
+            else
+                depthChangeRate = 200;
+        }
+        start.y = tXl1->WindowY0 - 1;
+        for(int i = 0; i<5;i++)
+        {
+            start.y += 40;
+            stop.y = start.y;
+            start.x = tXl1->WindowX1 - 1;
+            stop.x = start.x - 17;
+
+            if(depthChangeRate <= 6)
+            {
+                if(i == 2)
+                {
+                    startZeroLine.y = start.y;
+                    stop.x = start.x - 34;
+                }
+            }
+            else
+            {
+                if(((i == 1) && depthChangeAscent) || ((i == 3) && !depthChangeAscent))
+                {
+                    startZeroLine.y = start.y;
+                    stop.x = start.x - 34;
+                }
+            }
+            GFX_draw_line(tXscreen, start, stop, 0);
+        }
+        // new thick bar design Sept. 2015
+        if((stateUsed->lifeData.ascent_rate_meter_per_min > 4) || (stateUsed->lifeData.ascent_rate_meter_per_min < -4))
+        {
+            start.y = startZeroLine.y;
+
+            if(depthChangeAscent)
+            {
+                color = CLUT_EverythingOkayGreen;
+                start.y += 7; // starte etwas weiter oben
+                stop.y = start.y + (uint16_t)(depthChangeRate * 4) - 9; // - x; // wegen der Liniendicke
+                if(stop.y > 475)
+                    stop.y = 475;
+            }
+            else
+            {
+                color = CLUT_Font023;
+                start.y -= 7;
+                stop.y = start.y - (uint16_t)(depthChangeRate * 4) + 9;
+                if(stop.y <= tXl1->WindowY0)
+                    stop.y = tXl1->WindowY0 + 1;
+            }
+            stop.x = start.x = tXl1->WindowX1 - 8;
+            GFX_draw_thick_line(12,tXscreen, start, stop, color);
+        }
+    }
+    else
+    {
+        /* ascentrate graph -standard mode */
+        if(stateUsed->lifeData.ascent_rate_meter_per_min > 0)
+        {
+            start.y = tXl1->WindowY0 - 1;
+            for(int i = 0; i<4;i++)
+            {
+                start.y += 5*8;
+                stop.y = start.y;
+                start.x = tXl1->WindowX1 - 1;
+                stop.x = start.x - 17;
+                GFX_draw_line(tXscreen, start, stop, 0);
+            }
+            // new thick bar design Sept. 2015
+            start.x = tXl1->WindowX1 - 3 - 5;
+            stop.x = start.x;
+            start.y = tXl1->WindowY0 - 1;
+            stop.y = start.y + (uint16_t)(stateUsed->lifeData.ascent_rate_meter_per_min * 8);
+            stop.y -= 3; // wegen der Liniendicke von 12 anstelle von 9
+            if(stop.y >= 470)
+                stop.y = 470;
+            start.y += 7; // starte etwas weiter oben
+            if(stateUsed->lifeData.ascent_rate_meter_per_min <= 10)
+                color = CLUT_EverythingOkayGreen;
+            else
+            if(stateUsed->lifeData.ascent_rate_meter_per_min <= 15)
+                color = CLUT_WarningYellow;
+            else
+                color = CLUT_WarningRed;
+
+            GFX_draw_thick_line(12,tXscreen, start, stop, color);
+        }
+    }
+
+    // divetime
+    if(mode == DIVEMODE_Apnea)
+    {
+        if(stateUsed->lifeData.counterSecondsShallowDepth)
+        {
+            SDivetime SurfaceBreakTime = {0,0,0,0};
+
+            SurfaceBreakTime.Total = stateUsed->lifeData.counterSecondsShallowDepth;
+            SurfaceBreakTime.Minutes = SurfaceBreakTime.Total / 60;
+            SurfaceBreakTime.Seconds = SurfaceBreakTime.Total - (SurfaceBreakTime.Minutes * 60);
+
+            snprintf(text,TEXTSIZE,"\032\f\002%c%c", TXT_2BYTE,TXT2BYTE_ApneaSurface);
+            GFX_write_string(&FontT42,tXr1,text,0);
+
+            snprintf(text,TEXTSIZE,"\020\003\016\002%u:%02u",SurfaceBreakTime.Minutes, SurfaceBreakTime.Seconds);
+        }
+        else
+        {
+            SDivetime Divetime = {0,0,0, 0};
+
+            Divetime.Total = stateUsed->lifeData.dive_time_seconds;
+            Divetime.Minutes = Divetime.Total / 60;
+            Divetime.Seconds = Divetime.Total - ( Divetime.Minutes * 60 );
+
+            snprintf(text,TEXTSIZE,"\032\f\002%c",TXT_Divetime);
+            GFX_write_string(&FontT42,tXr1,text,0);
+
+            if(Divetime.Minutes < 100)
+                snprintf(text,TEXTSIZE,"\020\003\016\002%u:%02u",Divetime.Minutes, Divetime.Seconds);
+            else
+                snprintf(text,TEXTSIZE,"\020\003\016\002%u'",Divetime.Minutes);
+        }
+    }
+    else
+    {
+        SDivetime Divetime = {0,0,0, 0};
+
+        Divetime.Total = stateUsed->lifeData.dive_time_seconds_without_surface_time;
+        Divetime.Minutes = Divetime.Total / 60;
+        Divetime.Seconds = Divetime.Total - ( Divetime.Minutes * 60 );
+
+        snprintf(text,TEXTSIZE,"\032\f\002%c",TXT_Divetime);
+        GFX_write_string(&FontT42,tXr1,text,0);
+
+        if(Divetime.Minutes < 100)
+            snprintf(text,TEXTSIZE,"\020\003\016\002%u:%02u",Divetime.Minutes, Divetime.Seconds);
+        else
+            snprintf(text,TEXTSIZE,"\020\003\016\002%u'",Divetime.Minutes);
+    }
+    t3_basics_colorscheme_mod(text);
+    GFX_write_string(&FontT105,tXr1,text,1);
+
+    return depth;
+}
+
+
+void t3_refresh_divemode(void)
+{
+    uint8_t  customview_warnings = 0;
+    float depth_meter = 0.0;
+
+    // everything like lines, depth, ascent graph and divetime
+    depth_meter = t3_basics_lines_depth_and_divetime(&t3screen, &t3l1, &t3r1, 0); // 0 could be stateUsed->diveSettings.diveMode for CCR specials
+
+    // customview
+    if(stateUsed->warnings.numWarnings)
+        customview_warnings = t3_test_customview_warnings();
+
+    if(customview_warnings && warning_count_high_time)
+        t3_basics_show_customview_warnings(&t3c1);
+    else
+        t3_refresh_customview(depth_meter);
+
+    if(stateUsed->warnings.lowBattery)
+        t3_basics_battery_low_customview_extra(&t3c1);
+}
+
+
+void t3_basics_battery_low_customview_extra(GFX_DrawCfgWindow* tXc1)
+{
+    char TextC1[256];
+
+    TextC1[0] = '\002';
+    TextC1[1] = '\f';
+    TextC1[2] = '\025';
+    TextC1[3] = '3';
+    TextC1[4] = '1';
+    TextC1[5] = '1';
+    TextC1[6] = '1';
+    TextC1[7] = '1';
+    TextC1[8] = '1';
+    TextC1[9] = '1';
+    TextC1[10] = '1';
+    TextC1[11] = '1';
+    TextC1[12] = '1';
+    TextC1[13] = '1';
+    TextC1[14] = '0';
+    TextC1[15] = 0;
+
+    if(!warning_count_high_time)
+        TextC1[4] = '2';
+
+    GFX_write_string(&Batt24,tXc1,TextC1,0);
+}
+
+
+void t3_basics_battery_scooter_customview_extra(GFX_DrawCfgWindow* tXc1)
+{
+    char TextC1[256];
+
+    TextC1[0] = '\001';
+    TextC1[1] = '\f';
+    TextC1[2] = '\032';
+    TextC1[3] = '3';
+    TextC1[4] = '1';
+    TextC1[5] = '1';
+    TextC1[6] = '1';
+    TextC1[7] = '1';
+    TextC1[8] = '1';
+    TextC1[9] = '1';
+    TextC1[10] = '1';
+    TextC1[11] = '1';
+    TextC1[12] = '1';
+    TextC1[13] = '1';
+    TextC1[14] = '0';
+    TextC1[15] = 0;
+
+    for(int i=1;i<=10;i++)
+    {
+        if(	stateUsed_scooterRemainingBattCapacity()  > (9 * i))
+            TextC1[i+3] += 1;
+    }
+
+    if(stateUsed_scooterRemainingBattCapacity() < 10)
+        TextC1[2] = '\025';
+
+    if(!warning_count_high_time)
+        TextC1[4] = '2';
+
+    if(stateUsed->lifeData.scooterAgeInMilliSeconds > 1500)
+        TextC1[2] = '\031';
+
+    GFX_write_string(&Batt24,tXc1,TextC1,0);
+}
+
+
+void t3_refresh_customview(float depth)
+{
+    if((t3_selection_customview == CVIEW_sensors) &&(stateUsed->diveSettings.ccrOption == 0))
+        t3_change_customview();
+
+    SDiveState * pDiveState;
+
+    if(stateUsed == stateRealGetPointer())
+        pDiveState = stateRealGetPointerWrite();
+    else
+        pDiveState = stateSimGetPointerWrite();
+
+    t3_basics_refresh_customview(depth, t3_selection_customview, &t3screen, &t3c1, &t3c2, pDiveState->diveSettings.diveMode);
+}
+
+
+void t3_basics_refresh_apnoeRight(float depth, uint8_t tX_selection_customview, GFX_DrawCfgScreen *tXscreen, GFX_DrawCfgWindow* tXc1, GFX_DrawCfgWindow* tXc2, uint8_t mode)
+{
+    char text[512];
+    uint16_t textpointer = 0;
+
+    // CVIEW_T3_Temperature
+    float temperatureThisCall;
+    float temperature;
+
+    SDivetime TotalDivetime = {0,0,0,0};
+    SDivetime LastDivetime = {0,0,0,0};
+
+    uint16_t tempWinX0;
+    uint16_t tempWinY0;
+
+    tempWinX0 = tXc1->WindowX0;
+    tempWinY0 = tXc1->WindowY0;
+
+    tXc1->WindowX0 = 440; // rechte Seite
+
+    switch(tX_selection_customview)
+    {
+    case CVIEW_T3_Temperature:
+        snprintf(text,TEXTSIZE,"\032\f%c",TXT_Temperature);
+        GFX_write_string(&FontT42,tXc1,text,0);
+
+        // mean value
+        temperatureThisCall = unit_temperature_float(stateUsed->lifeData.temperature_celsius);
+        temperature = (temperatureThisCall + temperatureLastCall[0] + temperatureLastCall[1] + temperatureLastCall[2]) / 4.0f;
+        idTemperatureLastCall++;
+        if(idTemperatureLastCall >= 3)
+            idTemperatureLastCall = 0;
+        temperatureLastCall[idTemperatureLastCall] = temperatureThisCall;
+        textpointer = snprintf(text,TEXTSIZE,"\020\003\016%01.0f\016\016\140",temperature); // "\016\016%01.1f `" + C or F
+        if(settingsGetPointer()->nonMetricalSystem == 0)
+            text[textpointer++] = 'C';
+        else
+            text[textpointer++] = 'F';
+        text[textpointer++] = 0;
+        t3_basics_colorscheme_mod(text);
+        GFX_write_string(&FontT105,tXc1,text,1);
+        break;
+
+    case CVIEW_T3_ApnoeSurfaceInfo:
+        snprintf(text,TEXTSIZE,"\032\f%c",TXT_Divetime);
+        GFX_write_string(&FontT42,tXc1,text,0);
+
+        TotalDivetime.Total = stateUsed->lifeData.dive_time_seconds_without_surface_time;
+        TotalDivetime.Minutes = TotalDivetime.Total / 60;
+        TotalDivetime.Seconds = TotalDivetime.Total - ( TotalDivetime.Minutes * 60 );
+
+        LastDivetime.Total = stateUsed->lifeData.apnea_last_dive_time_seconds;
+        LastDivetime.Minutes = LastDivetime.Total / 60;
+        LastDivetime.Seconds = LastDivetime.Total - ( LastDivetime.Minutes * 60 );
+
+        tXc1->WindowY0 = 100; // obere Zeile
+
+        snprintf(text,TEXTSIZE,"\020\016%u:%02u",LastDivetime.Minutes, LastDivetime.Seconds);
+        t3_basics_colorscheme_mod(text);
+        GFX_write_string(&FontT105,tXc1,text,0);
+
+        snprintf(text,TEXTSIZE,"\032\002%c%c",TXT_2BYTE, TXT2BYTE_ApneaLast);
+        GFX_write_string(&FontT42,tXc1,text,0);
+
+        tXc1->WindowY0 = tempWinY0; // wieder unten
+
+        snprintf(text,TEXTSIZE,"\020\016%u:%02u",TotalDivetime.Minutes, TotalDivetime.Seconds);
+        t3_basics_colorscheme_mod(text);
+        GFX_write_string(&FontT105,tXc1,text,0);
+
+        snprintf(text,TEXTSIZE,"\032\002%c%c",TXT_2BYTE, TXT2BYTE_ApneaTotal);
+        GFX_write_string(&FontT42,tXc1,text,0);
+        break;
+    }
+
+    tXc1->WindowX0 = tempWinX0;
+    tXc1->WindowY0 = tempWinY0;
+
+}
+
+
+void t3_basics_refresh_customview(float depth, uint8_t tX_selection_customview, GFX_DrawCfgScreen *tXscreen, GFX_DrawCfgWindow* tXc1, GFX_DrawCfgWindow* tXc2, uint8_t mode)
+{
+    char text[512];
+    uint16_t textpointer = 0;
+
+    // CVIEW_T3_Decostop and CVIEW_T3_TTS
+    const SDecoinfo * pDecoinfo;
+    if(stateUsed->diveSettings.deco_type.ub.standard == GF_MODE)
+        pDecoinfo = &stateUsed->decolistBuehlmann;
+    else
+        pDecoinfo = &stateUsed->decolistVPM;
+
+    // CVIEW_T3_Decostop
+    uint16_t 	nextstopLengthSeconds = 0;
+    uint8_t 	nextstopDepthMeter = 0;
+    SDivetime SafetyStopTime = {0,0,0,0};
+
+    // CVIEW_T3_ppO2andGas
+    uint8_t oxygen_percentage = 0;
+    float scooterSpeed;
+
+    // CVIEW_T3_Temperature
+    float temperatureThisCall;
+    float temperature;
+
+    // CVIEW_T3_GasList
+    float fPpO2limitHigh, fPpO2limitLow, fPpO2ofGasAtThisDepth;
+    const SGasLine * pGasLine;
+    uint8_t oxygen, helium;
+    uint8_t lineNumber;
+
+    // CVIEW_T3_StopWatch
+    SDivetime Stopwatch = {0,0,0,0};
+    float fAverageDepth, fAverageDepthAbsolute;
+
+
+    uint16_t tempWinX0;
+    uint16_t tempWinY0;
+    uint16_t tempWinC2X0;
+    uint16_t tempWinC2Tab;
+
+    tempWinX0 = tXc1->WindowX0;
+    tempWinY0 = tXc1->WindowY0;
+    tempWinC2X0  = tXc2->WindowX0;
+    tempWinC2Tab = tXc2->WindowTab;
+
+    switch(tX_selection_customview)
+    {
+    case CVIEW_Scooter:
+        snprintf(text,TEXTSIZE,"\032\fScooter");
+        GFX_write_string(&FontT42,tXc1,text,0);
+
+        t3_basics_battery_scooter_customview_extra(tXc1);
+
+        scooterSpeed = stateUsed->lifeData.scooterDrehzahl * 80 / 3300;
+
+        snprintf(text,100,"\030\003%.1f",scooterSpeed);
+        if(stateUsed->lifeData.scooterAgeInMilliSeconds > 1500)
+            text[0] = '\031';
+        GFX_write_string(&FontT105,tXc1,text,0);
+        break;
+
+
+    case CVIEW_T3_ApnoeSurfaceInfo:
+        snprintf(text,TEXTSIZE,"\032\f%c",TXT_MaxDepth);
+        GFX_write_string(&FontT42,tXc1,text,0);
+
+        tXc1->WindowY0 = 100; // obere Zeile
+
+        snprintf(text,TEXTSIZE,"\020\016%01.1f",unit_depth_float(stateUsed->lifeData.apnea_last_max_depth_meter));
+        t3_basics_colorscheme_mod(text);
+        GFX_write_string(&FontT105,tXc1,text,0);
+
+        tXc1->WindowY0 = tempWinY0; // wieder unten
+
+        snprintf(text,TEXTSIZE,"\020\016%01.1f",unit_depth_float(stateUsed->lifeData.apnea_total_max_depth_meter));
+        t3_basics_colorscheme_mod(text);
+        GFX_write_string(&FontT105,tXc1,text,0);
+        break;
+
+    case CVIEW_T3_StopWatch:
+        Stopwatch.Total = timer_Stopwatch_GetTime();
+        Stopwatch.Minutes = Stopwatch.Total / 60;
+        Stopwatch.Seconds = Stopwatch.Total - ( Stopwatch.Minutes * 60 );
+        fAverageDepth = timer_Stopwatch_GetAvarageDepth_Meter();
+        fAverageDepthAbsolute = stateUsed->lifeData.average_depth_meter;
+
+        snprintf(text,TEXTSIZE,"\032\f%c",TXT_AvgDepth);
+        GFX_write_string(&FontT42,tXc1,text,0);
+        snprintf(text,TEXTSIZE,"\030\003\016%01.1f",unit_depth_float(fAverageDepthAbsolute));
+        GFX_write_string(&FontT105,tXc1,text,0);
+
+        tempWinX0 = tXc1->WindowX0;
+        tempWinY0 = tXc1->WindowY0;
+        tXc1->WindowX0 = 480;
+//			snprintf(text,TEXTSIZE,"\032\f%c%c - %c",TXT_2BYTE, TXT2BYTE_Clock, TXT_AvgDepth);
+        snprintf(text,TEXTSIZE,"\032\f%c", TXT_Stopwatch);
+        GFX_write_string(&FontT42,tXc1,text,0);
+        snprintf(text,TEXTSIZE,"\030\016%01.1f",unit_depth_float(fAverageDepth));
+        GFX_write_string(&FontT105,tXc1,text,0);
+        tXc1->WindowY0 = 100;
+        snprintf(text,TEXTSIZE,"\030%u:\016\016%02u",Stopwatch.Minutes, Stopwatch.Seconds);
+        GFX_write_string(&FontT105,tXc1,text,0);
+        tXc1->WindowX0 = tempWinX0;
+        tXc1->WindowY0 = tempWinY0;
+        break;
+
+    case CVIEW_T3_GasList:
+        snprintf(text,TEXTSIZE,"\032\f%c%c",TXT_2BYTE, TXT2BYTE_Gaslist);
+        GFX_write_string(&FontT42,tXc1,text,0);
+
+        textpointer = 0;
+        tempWinC2X0 = tXc2->WindowX0;
+        tempWinC2Tab = tXc2->WindowTab;
+
+        tXc2->WindowX0 = 0;
+        tXc2->WindowTab = 800/2;
+
+        pGasLine = settingsGetPointer()->gas;
+        if(actualLeftMaxDepth(stateUsed))
+            fPpO2limitHigh = (float)(settingsGetPointer()->ppO2_max_deco) / 100;
+        else
+            fPpO2limitHigh = (float)(settingsGetPointer()->ppO2_max_std) / 100;
+        fPpO2limitLow = (float)(settingsGetPointer()->ppO2_min) / 100;
+        for(int gasId=1;gasId<=NUM_GASES;gasId++)
+        {
+            textpointer = 0;
+            lineNumber = gasId;
+            if(gasId > 3)
+            {
+                text[textpointer++] = '\t';
+                lineNumber = gasId - 3;
+            }
+            fPpO2ofGasAtThisDepth = (stateUsed->lifeData.pressure_ambient_bar - WATER_VAPOUR_PRESSURE) * pGasLine[gasId].oxygen_percentage / 100;
+            if(pGasLine[gasId].note.ub.active == 0)
+                strcpy(&text[textpointer++],"\021");
+            else if((fPpO2ofGasAtThisDepth > fPpO2limitHigh) || (fPpO2ofGasAtThisDepth < fPpO2limitLow))
+                strcpy(&text[textpointer++],"\025");
+            else
+                strcpy(&text[textpointer++],"\030");
+
+            text[textpointer++] = ' ';
+            oxygen = pGasLine[gasId].oxygen_percentage;
+            helium = pGasLine[gasId].helium_percentage;
+            textpointer += write_gas(&text[textpointer], oxygen, helium);
+            GFX_write_string(&FontT42, tXc2, text, lineNumber);
+        }
+        break;
+
+    case CVIEW_T3_Temperature:
+        snprintf(text,TEXTSIZE,"\032\f%c",TXT_Temperature);
+        GFX_write_string(&FontT42,tXc1,text,0);
+        // mean value
+        temperatureThisCall = unit_temperature_float(stateUsed->lifeData.temperature_celsius);
+        temperature = (temperatureThisCall + temperatureLastCall[0] + temperatureLastCall[1] + temperatureLastCall[2]) / 4.0f;
+        idTemperatureLastCall++;
+        if(idTemperatureLastCall >= 3)
+            idTemperatureLastCall = 0;
+        temperatureLastCall[idTemperatureLastCall] = temperatureThisCall;
+        textpointer = snprintf(text,TEXTSIZE,"\030\003\016%01.1f \140",temperature); // "\016\016%01.1f `" + C or F
+        if(settingsGetPointer()->nonMetricalSystem == 0)
+            text[textpointer++] = 'C';
+        else
+            text[textpointer++] = 'F';
+        text[textpointer++] = 0;
+        GFX_write_string(&FontT105,tXc1,text,0);
+        break;
+
+    case CVIEW_Compass:
+        snprintf(text,TEXTSIZE,"\032\f%c%c",TXT_2BYTE, TXT2BYTE_Compass);
+        GFX_write_string(&FontT42,tXc1,text,0);
+        snprintf(text,100,"\030\003%03i`",(uint16_t)stateUsed->lifeData.compass_heading);
+        GFX_write_string(&FontT105,tXc1,text,0);
+        t3_basics_compass(tXscreen, (uint16_t)stateUsed->lifeData.compass_heading, stateUsed->diveSettings.compassHeading);
+        break;
+
+    case CVIEW_T3_Decostop:
+    default:
+        // decostop
+        if(pDecoinfo->output_time_to_surface_seconds)
+        {
+            tHome_findNextStop(pDecoinfo->output_stop_length_seconds, &nextstopDepthMeter, &nextstopLengthSeconds);
+        }
+        else
+        {
+            nextstopDepthMeter = 0;
+            nextstopLengthSeconds = 0;
+        }
+
+        SafetyStopTime.Total = timer_Safetystop_GetCountDown();
+        SafetyStopTime.Minutes = SafetyStopTime.Total / 60;
+        SafetyStopTime.Seconds = SafetyStopTime.Total - (SafetyStopTime.Minutes * 60);
+
+        if(nextstopDepthMeter)
+        {
+            snprintf(text,TEXTSIZE,"\032\f%c",TXT_Decostop);
+            GFX_write_string(&FontT42,tXc1,text,0);
+
+            textpointer = 0;
+            snprintf(&text[textpointer],TEXTSIZE,"\020\003%u%c%c %u'"
+            , unit_depth_integer(nextstopDepthMeter)
+            , unit_depth_char1_T105()
+            , unit_depth_char2_T105()
+            , (nextstopLengthSeconds+59)/60);
+//	old without feet hw 170703			snprintf(&text[textpointer],TEXTSIZE,"\020\003%um %u'",nextstopDepthMeter,(nextstopLengthSeconds+59)/60);
+            t3_basics_colorscheme_mod(text);
+            GFX_write_string(&FontT105,tXc1,text,1);
+        }
+        else if(SafetyStopTime.Total && (depth > timer_Safetystop_GetDepthUpperLimit()))
+        {
+            textpointer = 0;
+            snprintf(&text[textpointer],TEXTSIZE,"\032\f%c%c",TXT_2BYTE,TXT2BYTE_SafetyStop2);
+            GFX_write_string(&FontT42,tXc1,text,0);
+
+            textpointer = 0;
+            snprintf(&text[textpointer],TEXTSIZE,"\020\003\016%u:%02u",SafetyStopTime.Minutes,SafetyStopTime.Seconds);
+            t3_basics_colorscheme_mod(text);
+            GFX_write_string(&FontT105,tXc1,text,1);
+        }
+        else // NDL
+        {
+            snprintf(text,TEXTSIZE,"\032\f%c",TXT_Nullzeit);
+            GFX_write_string(&FontT42,tXc1,text,0);
+            if(pDecoinfo->output_ndl_seconds < 1000 * 60)
+                snprintf(text,TEXTSIZE,"\020\003%i'",pDecoinfo->output_ndl_seconds/60);
+            else
+                snprintf(text,TEXTSIZE,"\020\003%ih",pDecoinfo->output_ndl_seconds/3600);
+            t3_basics_colorscheme_mod(text);
+            GFX_write_string(&FontT105,tXc1,text,1);
+        }
+        break;
+
+    case CVIEW_sensors:
+        snprintf(text,TEXTSIZE,"\032\f%c%c",TXT_2BYTE,TXT2BYTE_O2monitor);
+        GFX_write_string(&FontT42,tXc1,text,0);
+
+        for(int i=0;i<3;i++)
+        {
+            textpointer = 0;
+            text[textpointer++] = '\030';
+            if(i==1)
+                text[textpointer++] = '\001';
+            else if(i==2)
+                text[textpointer++] = '\002';
+            if(stateUsed->diveSettings.ppo2sensors_deactivated & (1<<i))
+            {
+                text[textpointer++] = '\031';
+                text[textpointer++] = ' ';
+                text[textpointer++] = '-';
+                text[textpointer++] = ' ';
+            }
+            else
+            {
+                if(stateUsed->warnings.sensorOutOfBounds[i])
+                    text[textpointer++] = '\025';
+                textpointer += snprintf(&text[textpointer],TEXTSIZE,"%.1f",stateUsed->lifeData.ppO2Sensor_bar[i]);
+            }
+            GFX_write_string(&FontT144,tXc1,text,1);
+        }
+        break;
+
+    case CVIEW_T3_MaxDepth:
+        snprintf(text,TEXTSIZE,"\032\f%c",TXT_MaxDepth);
+        GFX_write_string(&FontT42,tXc1,text,0);
+        snprintf(text,TEXTSIZE,"\020\003\016%01.1f",unit_depth_float(stateUsed->lifeData.max_depth_meter));
+        t3_basics_colorscheme_mod(text);
+        GFX_write_string(&FontT105,tXc1,text,1);
+        break;
+
+    case CVIEW_T3_TTS:
+        snprintf(text,TEXTSIZE,"\032\f%c",TXT_TTS);
+        GFX_write_string(&FontT42,tXc1,text,0);
+        if(pDecoinfo->output_time_to_surface_seconds)
+        {
+            if(pDecoinfo->output_time_to_surface_seconds < 1000 * 60)
+                snprintf(text,TEXTSIZE,"\020\003\002%i'",(pDecoinfo->output_time_to_surface_seconds + 30)/ 60);
+            else
+                snprintf(text,TEXTSIZE,"\020\003\002%ih",pDecoinfo->output_time_to_surface_seconds / 3600);
+            t3_basics_colorscheme_mod(text);
+            GFX_write_string(&FontT105,tXc1,text,1);
+        }
+        break;
+
+    case CVIEW_T3_ppO2andGas:
+        snprintf(text,TEXTSIZE,"\032\f%c",TXT_ppO2);
+        GFX_write_string(&FontT42,tXc1,text,0);
+        snprintf(text,TEXTSIZE,"\020\003%01.2f",stateUsed->lifeData.ppO2);
+        t3_basics_colorscheme_mod(text);
+        GFX_write_string(&FontT105,tXc1,text,1);
+
+        textpointer = 0;
+        text[textpointer++] = '\020';
+        text[textpointer++] = '\003';
+        oxygen_percentage = 100;
+        oxygen_percentage -= stateUsed->lifeData.actualGas.nitrogen_percentage;
+        oxygen_percentage -= stateUsed->lifeData.actualGas.helium_percentage;
+        text[textpointer++] = '\002';
+        tHome_gas_writer(oxygen_percentage,stateUsed->lifeData.actualGas.helium_percentage,&text[textpointer]);
+        //textpointer = snprintf(&text[textpointer],TEXTSIZE,"\020\002%02u/%02u",oxygen_percentage, stateUsed->lifeData.actualGas.helium_percentage);
+        t3_basics_colorscheme_mod(text);
+        GFX_write_string(&FontT48,tXc1,text,1);
+        break;
+    }
+    tXc1->WindowX0 = tempWinX0;
+    tXc1->WindowY0 = tempWinY0;
+    tXc2->WindowX0 = tempWinC2X0;
+    tXc2->WindowTab = tempWinC2Tab;
+}
+
+
+uint8_t t3_test_customview_warnings(void)
+{
+    uint8_t count = 0;
+
+    count = 0;
+    count += stateUsed->warnings.decoMissed;
+    count += stateUsed->warnings.ppO2Low;
+    count += stateUsed->warnings.ppO2High;
+    //count += stateUsed->warnings.lowBattery;
+    count += stateUsed->warnings.sensorLinkLost;
+    count += stateUsed->warnings.fallback;
+
+    return count;
+}
+
+//void t3_show_customview_warnings(GFX_DrawCfgScreen *tXscreen, GFX_DrawCfgWindow* tXl1, GFX_DrawCfgWindow* tXr1, uint8_t mode)
+void t3_basics_show_customview_warnings(GFX_DrawCfgWindow* tXc1)
+{
+    char text[256], textMain[256];
+    uint8_t textpointer, textpointerMain, lineFree, more;
+
+    snprintf(text,TEXTSIZE,"\025\f%c",TXT_Warning);
+    GFX_write_string(&FontT42,&t3c1,text,0);
+
+    lineFree = 1;
+    more = 0;
+
+    textpointerMain = 0;
+    textMain[textpointerMain++] = '\025';
+    textMain[textpointerMain++] = '\003';
+
+    textpointer = 0;
+
+    text[textpointer++] = '\021';
+    text[textpointer++] = TXT_2BYTE;
+    text[textpointer++] = TXT2BYTE_WarnDecoMissed;
+    if(stateUsed->warnings.decoMissed)
+    {
+        text[textpointer - 3] =  '\025';
+        if(lineFree)
+        {
+            textMain[textpointerMain++] = TXT_2BYTE;
+            textMain[textpointerMain++] = text[textpointer - 1];
+            textMain[textpointerMain] = 0;
+            lineFree--;
+        }
+        else
+        {
+            more++;
+        }
+    }
+
+    text[textpointer++] = '\t';
+    text[textpointer++] = '\021';
+    text[textpointer++] = TXT_2BYTE;
+    text[textpointer++] = TXT2BYTE_WarnPPO2Low;
+    if(stateUsed->warnings.ppO2Low)
+    {
+        text[textpointer - 3] =  '\025';
+        if(lineFree)
+        {
+            textMain[textpointerMain++] = TXT_2BYTE;
+            textMain[textpointerMain++] = text[textpointer - 1];
+            textMain[textpointerMain] = 0;
+            lineFree--;
+        }
+        else
+        {
+            more++;
+        }
+    }
+
+    text[textpointer++] = '\n';
+    text[textpointer++] = '\r';
+    text[textpointer++] = '\021';
+    text[textpointer++] = TXT_2BYTE;
+    text[textpointer++] = TXT2BYTE_WarnPPO2High;
+    if(stateUsed->warnings.ppO2High)
+    {
+        text[textpointer - 3] =  '\025';
+        if(lineFree)
+        {
+            textMain[textpointerMain++] = TXT_2BYTE;
+            textMain[textpointerMain++] = text[textpointer - 1];
+            textMain[textpointerMain] = 0;
+            lineFree--;
+        }
+        else
+        {
+            more++;
+        }
+    }
+
+    text[textpointer++] = '\t';
+    text[textpointer++] = '\021';
+    text[textpointer++] = TXT_2BYTE;
+    text[textpointer++] = TXT2BYTE_WarnFallback;
+    if(stateUsed->warnings.fallback)
+    {
+        text[textpointer - 3] =  '\025';
+        if(lineFree)
+        {
+            textMain[textpointerMain++] = TXT_2BYTE;
+            textMain[textpointerMain++] = text[textpointer - 1];
+            textMain[textpointerMain] = 0;
+            lineFree--;
+        }
+        else
+        {
+            more++;
+        }
+    }
+
+    text[textpointer++] = '\n';
+    text[textpointer++] = '\r';
+    text[textpointer++] = '\021';
+    text[textpointer++] = TXT_2BYTE;
+    text[textpointer++] = TXT2BYTE_WarnSensorLinkLost;
+    if(stateUsed->warnings.sensorLinkLost)
+    {
+        text[textpointer - 3] =  '\025';
+        if(lineFree)
+        {
+            textMain[textpointerMain++] = TXT_2BYTE;
+            textMain[textpointerMain++] = text[textpointer - 1];
+            textMain[textpointerMain] = 0;
+            lineFree--;
+        }
+        else
+        {
+            more++;
+        }
+    }
+
+/*
+    text[textpointer++] = '\t';
+    text[textpointer++] = '\021';
+    text[textpointer++] = TXT_2BYTE;
+    text[textpointer++] = TXT2BYTE_WarnBatteryLow;
+    if(stateUsed->warnings.lowBattery)
+    {
+        text[textpointer - 3] =  '\025';
+        if(lineFree)
+        {
+            textMain[textpointerMain++] = TXT_2BYTE;
+            textMain[textpointerMain++] = text[textpointer - 1];
+            textMain[textpointerMain] = 0;
+            lineFree--;
+        }
+        else
+        {
+            more++;
+        }
+    }
+*/
+    text[textpointer] = 0;
+/*
+    if(more)
+    {
+        text[textpointer++] = '\002';
+        text[textpointer++] = '+';
+        if(more < 10)
+            text[textpointer++] = '0' + more;
+        else
+            text[textpointer++] = 'X';
+        text[textpointer] = 0;
+    }
+*/
+    GFX_write_string(&FontT48,&t3c1,textMain,1);
+    if(more)
+    {
+        GFX_write_string(&FontT48,&t3c2,text,1);
+    }
+}
+
+
+void t3_change_customview(void)
+{
+    t3_basics_change_customview(&t3_selection_customview, t3_customviews);
+}
+
+
+void t3_basics_change_customview(uint8_t *tX_selection_customview, const uint8_t *tX_customviews)
+{
+    const SDecoinfo * pDecoinfo;
+    if(stateUsed->diveSettings.deco_type.ub.standard == GF_MODE)
+        pDecoinfo = &stateUsed->decolistBuehlmann;
+    else
+        pDecoinfo = &stateUsed->decolistVPM;
+
+    const uint8_t *pViews;
+    pViews = tX_customviews;
+
+    while((*pViews != CVIEW_T3_END) && (*pViews != *tX_selection_customview))
+        {pViews++;}
+
+    if(*pViews < CVIEW_T3_END)
+        pViews++;
+
+    if((*pViews == CVIEW_T3_TTS) && !pDecoinfo->output_time_to_surface_seconds)
+        pViews++;
+
+    if(*pViews == CVIEW_T3_END)
+    {
+        *tX_selection_customview = tX_customviews[0];
+    }
+    else
+        *tX_selection_customview = *pViews;
+}
+
+
+void t3_basics_colorscheme_mod(char *text)
+{
+    if((text[0] == '\020') && !GFX_is_colorschemeDiveStandard())
+    {
+        text[0] = '\027';
+    }
+}
+
+
+point_t t3_compass_circle(uint8_t id, uint16_t degree)
+{
+    float fCos, fSin;
+    const float piMult =  ((2 * 3.14159) / 360);
+//	const int radius[4] = {95,105,115,60};
+    const int radius[4] = {85,95,105,90};
+    const point_t offset = {.x = 600, .y = 116};
+
+    static point_t r[4][360] = { 0 };
+
+    if(r[0][0].y == 0)
+    {
+        for(int i=0;i<360;i++)
+        {
+            fCos = cos(i * piMult);
+            fSin = sin(i * piMult);
+            for(int j=0;j<4;j++)
+            {
+                r[j][i].x = offset.x + (int)(fSin * radius[j]);
+                r[j][i].y = offset.y + (int)(fCos * radius[j]);
+            }
+        }
+    }
+    if(id > 3) id = 0;
+    if(degree > 359) degree = 0;
+    return r[id][degree];
+}
+
+
+void t3_basics_compass(GFX_DrawCfgScreen *tXscreen, uint16_t ActualHeading, uint16_t UserSetHeading)
+{
+    uint16_t LineHeading;
+    point_t center;
+    static int32_t LastHeading = 0;
+    int32_t newHeading = 0;
+    int32_t diff = 0;
+    int32_t diff2 = 0;
+
+    int32_t diffAbs = 0;
+    int32_t diffAbs2 = 0;
+
+    newHeading = ActualHeading;
+
+    diff = newHeading - LastHeading;
+
+    if(newHeading < LastHeading)
+        diff2 = newHeading + 360 - LastHeading;
+    else
+        diff2 = newHeading - 360 - LastHeading;
+
+    diffAbs = diff;
+    if(diffAbs < 0)
+        diffAbs *= -1;
+
+    diffAbs2 = diff2;
+    if(diffAbs2 < 0)
+        diffAbs2 *= -1;
+
+    if(diffAbs <= diffAbs2)
+        newHeading = LastHeading + (diff / 2);
+    else
+        newHeading = LastHeading + (diff2 / 2);
+
+    if(newHeading < 0)
+        newHeading += 360;
+    else
+    if(newHeading >= 360)
+        newHeading -= 360;
+
+    LastHeading = newHeading;
+    ActualHeading = newHeading;
+
+    if (ActualHeading < 90)
+        ActualHeading += 360;
+
+    while(ActualHeading > 359) ActualHeading -= 360;
+
+    LineHeading = 360 - ActualHeading;
+    GFX_draw_thick_line(9,tXscreen, t3_compass_circle(0,LineHeading),  t3_compass_circle(2,LineHeading), CLUT_Font030); // North
+    LineHeading += 90;
+    if(LineHeading > 359) LineHeading -= 360;
+    GFX_draw_thick_line(9,tXscreen, t3_compass_circle(1,LineHeading),  t3_compass_circle(2,LineHeading), CLUT_Font031); // Maintick
+    LineHeading += 90;
+    if(LineHeading > 359) LineHeading -= 360;
+    GFX_draw_thick_line(9,tXscreen, t3_compass_circle(1,LineHeading),  t3_compass_circle(2,LineHeading), CLUT_Font031);
+    LineHeading += 90;
+    if(LineHeading > 359) LineHeading -= 360;
+    GFX_draw_thick_line(9,tXscreen, t3_compass_circle(1,LineHeading),  t3_compass_circle(2,LineHeading), CLUT_Font031);
+
+    LineHeading = 360 - ActualHeading;
+    LineHeading += 45;
+    if(LineHeading > 359) LineHeading -= 360;
+    GFX_draw_thick_line(5,tXscreen, t3_compass_circle(1,LineHeading),  t3_compass_circle(2,LineHeading), CLUT_Font031); // Subtick
+    LineHeading += 90;
+    if(LineHeading > 359) LineHeading -= 360;
+    GFX_draw_thick_line(5,tXscreen, t3_compass_circle(1,LineHeading),  t3_compass_circle(2,LineHeading), CLUT_Font031);
+    LineHeading += 90;
+    if(LineHeading > 359) LineHeading -= 360;
+    GFX_draw_thick_line(5,tXscreen, t3_compass_circle(1,LineHeading),  t3_compass_circle(2,LineHeading), CLUT_Font031);
+    LineHeading += 90;
+    if(LineHeading > 359) LineHeading -= 360;
+    GFX_draw_thick_line(5,tXscreen, t3_compass_circle(1,LineHeading),  t3_compass_circle(2,LineHeading), CLUT_Font031);
+
+    LineHeading = 360 - ActualHeading;
+    LineHeading += 22;
+    if(LineHeading > 359) LineHeading -= 360;
+    GFX_draw_thick_line(3,tXscreen, t3_compass_circle(1,LineHeading),  t3_compass_circle(2,LineHeading), CLUT_Font031); // Subtick
+    LineHeading += 45;
+    if(LineHeading > 359) LineHeading -= 360;
+    GFX_draw_thick_line(3,tXscreen, t3_compass_circle(1,LineHeading),  t3_compass_circle(2,LineHeading), CLUT_Font031);
+    LineHeading += 45;
+    if(LineHeading > 359) LineHeading -= 360;
+    GFX_draw_thick_line(3,tXscreen, t3_compass_circle(1,LineHeading),  t3_compass_circle(2,LineHeading), CLUT_Font031);
+    LineHeading += 45;
+    if(LineHeading > 359) LineHeading -= 360;
+    GFX_draw_thick_line(3,tXscreen, t3_compass_circle(1,LineHeading),  t3_compass_circle(2,LineHeading), CLUT_Font031);
+    LineHeading += 45;
+    if(LineHeading > 359) LineHeading -= 360;
+    GFX_draw_thick_line(3,tXscreen, t3_compass_circle(1,LineHeading),  t3_compass_circle(2,LineHeading), CLUT_Font031); // Subtick
+    LineHeading += 45;
+    if(LineHeading > 359) LineHeading -= 360;
+    GFX_draw_thick_line(3,tXscreen, t3_compass_circle(1,LineHeading),  t3_compass_circle(2,LineHeading), CLUT_Font031);
+    LineHeading += 45;
+    if(LineHeading > 359) LineHeading -= 360;
+    GFX_draw_thick_line(3,tXscreen, t3_compass_circle(1,LineHeading),  t3_compass_circle(2,LineHeading), CLUT_Font031);
+    LineHeading += 45;
+    if(LineHeading > 359) LineHeading -= 360;
+    GFX_draw_thick_line(3,tXscreen, t3_compass_circle(1,LineHeading),  t3_compass_circle(2,LineHeading), CLUT_Font031);
+
+    if(UserSetHeading)
+    {
+        LineHeading = UserSetHeading + 360 - ActualHeading;
+        if(LineHeading > 359) LineHeading -= 360;
+        GFX_draw_thick_line(9,tXscreen, t3_compass_circle(3,LineHeading),  t3_compass_circle(2,LineHeading), CLUT_CompassUserHeadingTick);
+
+        // R�ckpeilung, User Back Heading
+        LineHeading = UserSetHeading + 360 + 180 - ActualHeading;
+        if(LineHeading > 359) LineHeading -= 360;
+        if(LineHeading > 359) LineHeading -= 360;
+        GFX_draw_thick_line(9,tXscreen, t3_compass_circle(3,LineHeading),  t3_compass_circle(2,LineHeading), CLUT_CompassUserBackHeadingTick);
+    }
+
+    center.x = 600;
+    center.y = 116;
+    GFX_draw_circle(tXscreen, center, 106, CLUT_Font030);
+    GFX_draw_circle(tXscreen, center, 107, CLUT_Font030);
+    GFX_draw_circle(tXscreen, center, 108, CLUT_Font030);
+}