# HG changeset patch # User Ideenmodellierer # Date 1667938577 -3600 # Node ID 8adf9b8fc7fa88dba2d1ffde3171bd7484107b99 # Parent c799151670d59bfc5439a4476ab9e6059123a352 Extension scrubber time: In previous version only one scrubber timer was available. After movement of scruvver timer menu menu space became available allowing to upgrade the functionality to support two scrubbers. To make it easier to identify combination ID to used scrubber the date of the last usage of the scrubber timer has been added. diff -r c799151670d5 -r 8adf9b8fc7fa Common/Inc/settings.h --- a/Common/Inc/settings.h Tue Nov 08 21:13:14 2022 +0100 +++ b/Common/Inc/settings.h Tue Nov 08 21:16:17 2022 +0100 @@ -35,6 +35,7 @@ #include "global_constants.h" // From Common/Drivers/ #include "stm32f4xx_hal.h" +#include "stm32f4xx_hal_rtc.h" #include "configuration.h" @@ -84,7 +85,7 @@ #define UART_MAX_PROTOCOL (2u) -#define FUTURE_SPARE_SIZE (28u) /* Applied for reuse of old, not used, scooter block (was 32 bytes)*/ +#define FUTURE_SPARE_SIZE (11u) /* Applied for reuse of old, not used, scooter block (was 32 bytes)*/ typedef enum { @@ -159,6 +160,13 @@ } SSetpointLine; +typedef struct +{ + uint16_t TimerMax; + uint16_t TimerCur; + RTC_DateTypeDef lastDive; +} SScrubberData; + /* SSettings * gas[0] and setpoint[0] are the special ones configurable during the dive @@ -223,6 +231,10 @@ uint8_t pscr_o2_drop; /* redefined in 0xFFFF0020 */ uint8_t co2_sensor_active; /* redefined in 0xFFFF0021 */ uint8_t ext_uart_protocol; /* redefined in 0xFFFF0022 */ + + uint8_t scubberActiveId; /* redefined in 0xFFFF0023 */ + SScrubberData scrubberData[2]; + uint8_t Future_SPARE[FUTURE_SPARE_SIZE]; /* redefined in 0xFFFF0020 (old scooter Block was 32 byte)*/ // new in 0xFFFF0006 uint8_t ppo2sensors_deactivated; @@ -276,8 +288,8 @@ uint8_t amPMTime; /* new in 0xFFFF001F */ uint8_t autoSetpoint; - uint16_t scrubTimerMax; - uint16_t scrubTimerCur; + uint16_t scrubTimerMax_Obsolete; /* have been replaced with new scrubber data format */ + uint16_t scrubTimerCur_Obsolete; /* have been replaced with new scrubber data format */ uint8_t scrubTimerMode; } SSettings; diff -r c799151670d5 -r 8adf9b8fc7fa Discovery/Inc/tStructure.h --- a/Discovery/Inc/tStructure.h Tue Nov 08 21:13:14 2022 +0100 +++ b/Discovery/Inc/tStructure.h Tue Nov 08 21:16:17 2022 +0100 @@ -199,8 +199,9 @@ #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_Reset _MB(2,4,3,2,0) -#define StMXTRA_ScrubTimer_OP_Mode _MB(2,4,3,3,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_PSCR_O2_Drop _MB(2,4,4,1,0) #define StMXTRA_PSCR_LUNG_RATIO _MB(2,4,4,2,0) diff -r c799151670d5 -r 8adf9b8fc7fa Discovery/Src/settings.c --- a/Discovery/Src/settings.c Tue Nov 08 21:13:14 2022 +0100 +++ b/Discovery/Src/settings.c Tue Nov 08 21:16:17 2022 +0100 @@ -87,7 +87,7 @@ * There might even be entries with fixed values that have no range */ const SSettings SettingsStandard = { - .header = 0xFFFF0022, + .header = 0xFFFF0023, .warning_blink_dsec = 8 * 2, .lastDiveLogId = 0, .logFlashNextSampleStartAddress = SAMPLESTART, @@ -322,8 +322,8 @@ .ppo2sensors_calibCoeff[2] = 0.0, .amPMTime = 0, .autoSetpoint = 0, - .scrubTimerMax = 0, - .scrubTimerCur = 0, + .scrubTimerMax_Obsolete = 0, + .scrubTimerCur_Obsolete = 0, .scrubTimerMode = SCRUB_TIMER_OFF, }; @@ -488,8 +488,8 @@ // no break case 0xFFFF001E: pSettings->autoSetpoint = 0; - pSettings->scrubTimerMax = 0; - pSettings->scrubTimerCur = 0; + pSettings->scrubTimerMax_Obsolete = 0; + pSettings->scrubTimerCur_Obsolete = 0; pSettings->scrubTimerMode = SCRUB_TIMER_OFF; // no break case 0xFFFF001F: @@ -502,6 +502,22 @@ case 0xFFFF0021: pSettings->ext_uart_protocol = 0; // no break; + case 0xFFFF0022: + pSettings->scubberActiveId = 0; + pSettings->scrubberData[0].TimerCur = pSettings->scrubTimerCur_Obsolete; + pSettings->scrubberData[0].TimerMax = pSettings->scrubTimerMax_Obsolete; + pSettings->scrubberData[0].lastDive.WeekDay = 0; + pSettings->scrubberData[0].lastDive.Month = 0; + pSettings->scrubberData[0].lastDive.Date = 0; + pSettings->scrubberData[0].lastDive.Year = 0; + + pSettings->scrubberData[1].TimerCur = 0; + pSettings->scrubberData[1].TimerMax = 0; + pSettings->scrubberData[1].lastDive.WeekDay = 0; + pSettings->scrubberData[1].lastDive.Month = 0; + pSettings->scrubberData[1].lastDive.Date = 0; + pSettings->scrubberData[1].lastDive.Year = 0; + // no break; default: pSettings->header = pStandard->header; break; // no break before!! @@ -1462,10 +1478,21 @@ corrections++; } - if((Settings.scrubTimerMax > MAX_SCRUBBER_TIME) || (Settings.scrubTimerCur > MAX_SCRUBBER_TIME)) + if(Settings.scubberActiveId > 1) + { + Settings.scubberActiveId = 0; + corrections++; + } + if((Settings.scrubberData[0].TimerMax > MAX_SCRUBBER_TIME) || (Settings.scrubberData[0].TimerCur > MAX_SCRUBBER_TIME)) { - Settings.scrubTimerMax = 0; - Settings.scrubTimerCur = 0; + Settings.scrubberData[0].TimerMax = 0; + Settings.scrubberData[0].TimerCur = 0; + corrections++; + } + if((Settings.scrubberData[1].TimerMax > MAX_SCRUBBER_TIME) || (Settings.scrubberData[1].TimerCur > MAX_SCRUBBER_TIME)) + { + Settings.scrubberData[1].TimerMax = 0; + Settings.scrubberData[1].TimerCur = 0; corrections++; } if(Settings.scrubTimerMode > SCRUB_TIMER_END) @@ -1490,7 +1517,7 @@ Settings.co2_sensor_active = 0; corrections++; } - if(Settings.co2_sensor_active > UART_MAX_PROTOCOL) + if(Settings.ext_uart_protocol > UART_MAX_PROTOCOL) { Settings.ext_uart_protocol = 0; corrections++; diff -r c799151670d5 -r 8adf9b8fc7fa Discovery/Src/t3.c --- a/Discovery/Src/t3.c Tue Nov 08 21:13:14 2022 +0100 +++ b/Discovery/Src/t3.c Tue Nov 08 21:16:17 2022 +0100 @@ -1301,11 +1301,11 @@ textpointer = 0; if(settingsGetPointer()->scrubTimerMode == SCRUB_TIMER_MINUTES) { - textpointer += snprintf(&text[textpointer],10,"\020\002%3u'", pSettings->scrubTimerCur); + textpointer += snprintf(&text[textpointer],10,"\020\002%3u'", pSettings->scrubberData[pSettings->scubberActiveId].TimerCur); } else { - textpointer += snprintf(&text[textpointer],20,"\020\002%u\016\016%%\017", (uint16_t)(pSettings->scrubTimerCur * 100 / pSettings->scrubTimerMax)); + textpointer += snprintf(&text[textpointer],20,"\020\002%u\016\016%%\017", (uint16_t)(pSettings->scrubberData[pSettings->scubberActiveId].TimerCur * 100 / pSettings->scrubberData[pSettings->scubberActiveId].TimerMax)); } GFX_write_string(&FontT105,tXc1,text,1); } diff -r c799151670d5 -r 8adf9b8fc7fa Discovery/Src/t7.c --- a/Discovery/Src/t7.c Tue Nov 08 21:13:14 2022 +0100 +++ b/Discovery/Src/t7.c Tue Nov 08 21:16:17 2022 +0100 @@ -2773,6 +2773,7 @@ const SDecoinfo * pDecoinfoFuture; float fCNS; float temperature; + SSettings* pSettings = settingsGetPointer(); if(stateUsed->diveSettings.deco_type.ub.standard == GF_MODE) { @@ -2813,7 +2814,7 @@ /* Average Depth */ case LLC_AverageDepth: headerText[2] = TXT_AvgDepth; - if(settingsGetPointer()->nonMetricalSystem) + if(pSettings->nonMetricalSystem) snprintf(text,TEXTSIZE,"\020%01.0f",unit_depth_float(fAverageDepthAbsolute)); else snprintf(text,TEXTSIZE,"\020%01.1f",fAverageDepthAbsolute); @@ -2828,7 +2829,7 @@ /* Stop Uhr */ case LLC_Stopwatch: headerText[2] = TXT_Stopwatch; - if(settingsGetPointer()->nonMetricalSystem) + if(pSettings->nonMetricalSystem) snprintf(text,TEXTSIZE,"\020\016\016%u:%02u\n\r%01.0f",Stopwatch.Minutes, Stopwatch.Seconds,unit_depth_float(fAverageDepth)); else snprintf(text,TEXTSIZE,"\020\016\016%u:%02u\n\r%01.1f",Stopwatch.Minutes, Stopwatch.Seconds,fAverageDepth); @@ -2839,7 +2840,7 @@ /* Ceiling */ case LLC_Ceiling: headerText[2] = TXT_Ceiling; - if((pDecoinfoStandard->output_ceiling_meter > 99.9f) || (settingsGetPointer()->nonMetricalSystem)) + if((pDecoinfoStandard->output_ceiling_meter > 99.9f) || (pSettings->nonMetricalSystem)) snprintf(text,TEXTSIZE,"\020%01.0f",unit_depth_float(pDecoinfoStandard->output_ceiling_meter)); else snprintf(text,TEXTSIZE,"\020%01.1f",pDecoinfoStandard->output_ceiling_meter); @@ -2849,9 +2850,9 @@ case LLC_FutureTTS: headerText[2] = TXT_FutureTTS; if (pDecoinfoFuture->output_time_to_surface_seconds < 1000 * 60) - snprintf(text,TEXTSIZE,"\020\016\016@+%u'\n\r" "%i' TTS",settingsGetPointer()->future_TTS, (pDecoinfoFuture->output_time_to_surface_seconds + 59) / 60); + snprintf(text,TEXTSIZE,"\020\016\016@+%u'\n\r" "%i' TTS",pSettings->future_TTS, (pDecoinfoFuture->output_time_to_surface_seconds + 59) / 60); else - snprintf(text,TEXTSIZE,"\020\016\016@+%u'\n\r" "%ih TTS",settingsGetPointer()->future_TTS, (pDecoinfoFuture->output_time_to_surface_seconds + 59) / 3600); + snprintf(text,TEXTSIZE,"\020\016\016@+%u'\n\r" "%ih TTS",pSettings->future_TTS, (pDecoinfoFuture->output_time_to_surface_seconds + 59) / 3600); tinyHeaderFont = 1; line = 1; break; @@ -2876,11 +2877,11 @@ headerText[2] = TXT_ScrubTime; if(settingsGetPointer()->scrubTimerMode == SCRUB_TIMER_MINUTES) { - snprintf(text,TEXTSIZE,"\020%3u'",settingsGetPointer()->scrubTimerCur); + snprintf(text,TEXTSIZE,"\020%3u'",pSettings->scrubberData[pSettings->scubberActiveId].TimerCur); } else { - snprintf(text,TEXTSIZE,"\020%u\016\016%%\017", (settingsGetPointer()->scrubTimerCur * 100 / settingsGetPointer()->scrubTimerMax)); + snprintf(text,TEXTSIZE,"\020%u\016\016%%\017", (pSettings->scrubberData[pSettings->scubberActiveId].TimerCur * 100 / settingsGetPointer()->scrubberData[pSettings->scubberActiveId].TimerMax)); } break; #ifdef ENABLE_PSCR_MODE @@ -3522,11 +3523,11 @@ text[textpointer++] = '\t'; if(settingsGetPointer()->scrubTimerMode == SCRUB_TIMER_MINUTES) { - textpointer += snprintf(&text[textpointer],10,"\020%3u'", pSettings->scrubTimerCur); + textpointer += snprintf(&text[textpointer],10,"\020%3u'", pSettings->scrubberData[pSettings->scubberActiveId].TimerCur); } else { - textpointer += snprintf(&text[textpointer],10,"\020%u\016\016%%\017", (pSettings->scrubTimerCur * 100 / pSettings->scrubTimerMax)); + textpointer += snprintf(&text[textpointer],10,"\020%u\016\016%%\017", (pSettings->scrubberData[pSettings->scubberActiveId].TimerCur * 100 / pSettings->scrubberData[pSettings->scubberActiveId].TimerMax)); } } text[textpointer++] = 0; diff -r c799151670d5 -r 8adf9b8fc7fa Discovery/Src/tCCR.c --- a/Discovery/Src/tCCR.c Tue Nov 08 21:13:14 2022 +0100 +++ b/Discovery/Src/tCCR.c Tue Nov 08 21:16:17 2022 +0100 @@ -337,16 +337,17 @@ } /* decrease scrubber timer only in real dive mode */ - if((pSettings->scrubTimerMode != SCRUB_TIMER_OFF) && (isLoopMode(pSettings->dive_mode)) && (stateUsed->mode == MODE_DIVE) && (stateUsed == stateRealGetPointer())) + if((pSettings->scrubTimerMode != SCRUB_TIMER_OFF) && (isLoopMode(pSettings->dive_mode)) && (stateUsed->mode == MODE_DIVE)) // && (stateUsed == stateRealGetPointer())) { ScrubberTimeoutCount++; if(ScrubberTimeoutCount >= 600) /* resolution is minutes */ { ScrubberTimeoutCount = 0; - if(pSettings->scrubTimerCur > 0) + if(pSettings->scrubberData[pSettings->scubberActiveId].TimerCur > 0) { - pSettings->scrubTimerCur--; + pSettings->scrubberData[pSettings->scubberActiveId].TimerCur--; } + translateDate(stateUsed->lifeData.dateBinaryFormat, &pSettings->scrubberData[pSettings->scubberActiveId].lastDive); } } } diff -r c799151670d5 -r 8adf9b8fc7fa Discovery/Src/tMenuEditXtra.c --- a/Discovery/Src/tMenuEditXtra.c Tue Nov 08 21:13:14 2022 +0100 +++ b/Discovery/Src/tMenuEditXtra.c Tue Nov 08 21:16:17 2022 +0100 @@ -58,7 +58,8 @@ /* Announced function prototypes -----------------------------------------------*/ uint8_t OnAction_CompassHeading (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); -static uint8_t OnAction_ScrubberTimer(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); +uint8_t OnAction_ScrubberTimerId(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); +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); #ifdef ENABLE_PSCR_MODE @@ -73,6 +74,7 @@ /* Exported functions --------------------------------------------------------*/ + void openEdit_Xtra(uint8_t line) { set_globalState_Menu_Line(line); @@ -210,33 +212,48 @@ SSettings *pSettings = settingsGetPointer(); - localScrubTimer = pSettings->scrubTimerMax; + localScrubTimer = pSettings->scrubberData[pSettings->scubberActiveId].TimerMax; resetMenuEdit(CLUT_MenuPageXtra); - snprintf(&text[textIndex], 32,"\001%c",TXT_ScrubTime); + snprintf(&text[0], 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_LINE1, &FontT48, text); + 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, 610, 780, ME_Y_LINE1, &FontT48, text,localScrubTimer, 0, 0, 0); + write_field_udigit(StMXTRA_ScrubTimer_Max, 610, 780, ME_Y_LINE2, &FontT48, text,localScrubTimer, 0, 0, 0); snprintf(&text[0], 32,\ "%c\002%03u\016\016 %c\017" ,TXT_ScrubTimeReset - ,pSettings->scrubTimerCur + ,pSettings->scrubberData[pSettings->scubberActiveId].TimerCur ,TXT_Minutes); - write_field_button(StMXTRA_ScrubTimer_Reset, 20, 780, ME_Y_LINE2, &FontT48, text); + write_field_button(StMXTRA_ScrubTimer_Reset, 20, 780, ME_Y_LINE3, &FontT48, text); + + 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) { @@ -248,9 +265,10 @@ case SCRUB_TIMER_PERCENT: snprintf(&text[0], 32,"%c\002%c",TXT_ScrubTimeMode, TXT_Percent ); break; } - write_field_button(StMXTRA_ScrubTimer_OP_Mode, 30, 780, ME_Y_LINE3, &FontT48, text); + write_field_button(StMXTRA_ScrubTimer_OP_Mode, 20, 780, ME_Y_LINE5, &FontT48, text); - setEvent(StMXTRA_ScrubTimer, (uint32_t)OnAction_ScrubberTimer); + 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); @@ -379,7 +397,52 @@ return EXIT_TO_HOME; } -static uint8_t OnAction_ScrubberTimer(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) + +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); + + snprintf(&text[0], 32,\ + "%c\002%03u\016\016 %c\017" + ,TXT_ScrubTimeReset + ,pSettings->scrubberData[pSettings->scubberActiveId].TimerCur + ,TXT_Minutes); + 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); + + return UNSPECIFIC_RETURN; +} + +static uint8_t OnAction_ScrubberTimerMax(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) { SSettings *pSettings; uint8_t digitContentNew = EXIT_TO_MENU; @@ -397,10 +460,10 @@ newScrubberTime = MAX_SCRUBBER_TIME; pSettings = settingsGetPointer(); - pSettings->scrubTimerMax = newScrubberTime; - if(pSettings->scrubTimerCur > newScrubberTime) + pSettings->scrubberData[pSettings->scubberActiveId].TimerMax = newScrubberTime; + if(pSettings->scrubberData[pSettings->scubberActiveId].TimerCur > newScrubberTime) { - pSettings->scrubTimerCur = newScrubberTime; + pSettings->scrubberData[pSettings->scubberActiveId].TimerCur = newScrubberTime; } tMenuEdit_newInput(editId, newScrubberTime, 0, 0, 0); @@ -426,16 +489,21 @@ char text[32]; SSettings *pSettings; pSettings = settingsGetPointer(); - pSettings->scrubTimerCur = pSettings->scrubTimerMax; - + pSettings->scrubberData[pSettings->scubberActiveId].TimerCur = pSettings->scrubberData[pSettings->scubberActiveId].TimerMax; + pSettings->scrubberData[pSettings->scubberActiveId].lastDive.WeekDay = 0; /* invalidate date */ snprintf(&text[0], 32,\ "%c\002%03u\016\016 %c\017" ,TXT_ScrubTimeReset - ,pSettings->scrubTimerCur + ,pSettings->scrubberData[pSettings->scubberActiveId].TimerCur ,TXT_Minutes); - tMenuEdit_refresh_field(StMXTRA_ScrubTimer_Reset); + 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); + return UNSPECIFIC_RETURN; }