Mercurial > public > ostc4
view Discovery/Src/show_logbook.c @ 688:8c92f7743e14 Betatest
Added sanity check for temperature and pressure values:
It happens from time to time at the debug hardware (electronic without housing) that pressure or temperature are in an invalid range . To avoid side effects a sanity check has been added.
author | Ideenmodellierer |
---|---|
date | Fri, 05 Aug 2022 15:13:29 +0200 |
parents | 1b995079c045 |
children | aa6006975e76 |
line wrap: on
line source
/////////////////////////////////////////////////////////////////////////////// /// -*- coding: UTF-8 -*- /// /// \file Discovery/Src/show_logbook.c /// \brief show_logbook_logbook_show_log_page1 / /// \author Heinrichs Weikamp gmbh /// \date 07-July-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/>. ////////////////////////////////////////////////////////////////////////////// #include "base.h" #include "logbook.h" #include "gfx_colors.h" #include "gfx_engine.h" #include "gfx_fonts.h" #include "show_logbook.h" #include "unit.h" #include "configuration.h" #include "logbook_miniLive.h" #include "text_multilanguage.h" #include <stdint.h> #include <stdio.h> #include <stdlib.h> // for abs() #define LOG_BORDER_OFFSET (50u) /* text offset from left / right display to text start/end */ /* Private variables ---------------------------------------------------------*/ static GFX_DrawCfgScreen tLOGscreen; static GFX_DrawCfgScreen tLOGbackground; static void print_gas_name(char* output,uint8_t lengh,uint8_t oxygen,uint8_t helium); static int16_t get_colour(int16_t color); static uint8_t active_log_page = 1; static uint8_t active_log_offset = 0; /* Overview */ static void show_logbook_logbook_show_log_page1(GFX_DrawCfgScreen *hgfx, uint8_t StepBackwards); /* Temperature */ static void show_logbook_logbook_show_log_page2(GFX_DrawCfgScreen *hgfx, uint8_t StepBackwards); /* Gas List */ static void show_logbook_logbook_show_log_page3(GFX_DrawCfgScreen *hgfx, uint8_t StepBackwards); /* ppO2 */ static void show_logbook_logbook_show_log_page4(GFX_DrawCfgScreen *hgfx, uint8_t StepBackwards); static inline uint32_t MaxU32LOG(uint32_t a, uint32_t b) { return((a>b)?a:b); } /** ****************************************************************************** * @brief GFX write label. / print coordinate system & depth graph * @author Peter Ryser * @version V0.0.1 * @date 07-July-2014 ****************************************************************************** * * @param hgfx: * @param window: WindowGimpStyle * @param mode: different modes depending witch page uses the function * @param dataLength: * @param depthdata: * @param colordata: 1 * @retval None */ static void show_logbook_draw_depth_graph(GFX_DrawCfgScreen *hgfx, uint8_t StepBackwards, SWindowGimpStyle* window, short mode, uint16_t dataLength, uint16_t* depthdata, uint8_t * colordata, uint16_t * decostopdata) { SLogbookHeader logbookHeader; SWindowGimpStyle wintemp = *window; SWindowGimpStyle winsmal; logbook_getHeader(StepBackwards, &logbookHeader); int divetime = logbookHeader.diveTimeMinutes; int maxDepth = logbookHeader.maxDepth/100; int16_t saveBottom = wintemp.bottom; int16_t saveTop = 0 - wintemp.top; //*** Horisontal (depth) *************************************************** //--- calc depth lines and labels -- int vscale = 0; int vstep = 0; vstep = maxDepth / 5; vscale = vstep * 5; if(vscale < maxDepth) { vstep += 1; vscale += 5; } /* if(vscale < for(int i=1; i <= 20; i++) { vscale = i * 25; vstep = i * 5; if( vscale > maxDepth) break; } */ //--- print depth labels --- winsmal.left = wintemp.left - 48; winsmal.top = wintemp.top - 3; winsmal.right = wintemp.left -1; winsmal.bottom = winsmal.top + 16; if(settingsGetPointer()->nonMetricalSystem) { Gfx_write_label_var(hgfx, winsmal.left, winsmal.right,winsmal.top, &FontT24,CLUT_GasSensor1,"[ft]"); } else { Gfx_write_label_var(hgfx, winsmal.left, winsmal.right,winsmal.top, &FontT24,CLUT_GasSensor1,"[m]"); } // winsmal.left = wintemp.left - 48; char msg[10]; float deltaline = ((float)(wintemp.bottom - wintemp.top))/5; for(int i = 1; i<=5; i++) { winsmal.top = wintemp.top + deltaline * i - 14; winsmal.bottom = winsmal.top + 16; // winsmal.right = wintemp.left - 2; snprintf(msg,10,"%i",unit_depth_integer(i * vstep)); Gfx_write_label_var(hgfx, winsmal.left, winsmal.right,winsmal.top, &FontT24,CLUT_GasSensor1,msg); } //vertical (Time) ******************************************************************* //--- calc time lines and labels -- int timestep = 0; int lines = 0; for(int i=1; i <= 60; i++) { timestep = i * 5; lines = divetime/timestep; if(lines < 7) { break; } } //*** print coordinate system grit *** int winwidth = wintemp.right - wintemp.left; float vdeltaline = ((float)(winwidth * timestep))/divetime; GFX_draw_Grid( &tLOGbackground,wintemp, 0, vdeltaline, 5,0, CLUT_LogbookGrid); //--- print time labels --- winsmal.left = wintemp.left; winsmal.top = wintemp.top - 40; winsmal.right = winsmal.left + 60; winsmal.bottom = winsmal.top + 16; Gfx_write_label_var(hgfx, winsmal.left, winsmal.right,winsmal.top, &FontT24,CLUT_GasSensor1,"min"); for(int i = 1; i<=lines; i++) { winsmal.left= wintemp.left + vdeltaline * i - 15; winsmal.right = winsmal.left + 30; snprintf(msg,10,"%3i",i * timestep); Gfx_write_label_var(hgfx, winsmal.left, winsmal.right,winsmal.top, &FontT24,CLUT_GasSensor1,msg); } winsmal.left = wintemp.left;// - 9; winsmal.top = wintemp.top - 40; winsmal.right = winsmal.left + 60; //--- print depth graph --- //adapt window int winhight = wintemp.bottom - wintemp.top; int newhight = (winhight * maxDepth)/vscale; wintemp.bottom = wintemp.top + newhight; //wintemp.fontcolor = LOGBOOK_GRAPH_DEPTH; int datamax = 0; for(int i=0;i<dataLength;i++) { if(depthdata[i]>datamax) datamax = depthdata[i]; } if(decostopdata) { if(dataLength <= 1000) { uint8_t colortemp[1000]; for(int i = 0; i<dataLength; i++) { if(decostopdata[i] > depthdata[i]) { colortemp[i] = CLUT_WarningRed; } else { colortemp[i] = CLUT_NiceGreen; } } GFX_graph_print(hgfx,&wintemp,saveTop,1,0,datamax, decostopdata,dataLength, 0, colortemp); } else GFX_graph_print(hgfx,&wintemp,saveTop,1,0,datamax, decostopdata,dataLength, CLUT_NiceGreen, NULL); } if(settingsGetPointer()->FlipDisplay) { winsmal.right = 800 - wintemp.left; winsmal.left = 800 - wintemp.right; winsmal.bottom = wintemp.bottom; winsmal.top = wintemp.top; } else { winsmal.right = wintemp.right; winsmal.left = wintemp.left; winsmal.bottom = wintemp.bottom; winsmal.top = wintemp.top; } switch(mode) { case 0: GFX_graph_print(hgfx,&winsmal,0,1,0,datamax, depthdata,dataLength,CLUT_GasSensor1, NULL); break; case 1: GFX_graph_print(hgfx,&winsmal,saveBottom,1,0,datamax, depthdata,dataLength,CLUT_GasSensor0,colordata); break; case 2: if(*colordata) GFX_graph_print(hgfx,&winsmal,0,1,0,datamax, depthdata,dataLength,CLUT_GasSensor0,colordata); else GFX_graph_print(hgfx,&winsmal,0,1,0,datamax, depthdata,dataLength,CLUT_GasSensor1, NULL); } } /** ****************************************************************************** * @brief scaleAdapt * @author heinrichs weikamp gmbh * @version V0.0.1 * @date 29-Nov-2016 ****************************************************************************** * * @param ... * @retval *OutputStepOfScale, *OutputMaxValueOnScale, *OutputTop, *OutputBottom * fit to multiples of 1�C (data format is 1/10�C) */ static void scaleAdapt( int InputTop, int InputBottom, int16_t *OutputMinValue, int16_t *OutputMaxValue, int *OutputTop, int *OutputBottom, uint16_t *OutputStepOfScale, int16_t *OutputMaxValueOnScale) { // uint16_t oldScale; uint16_t newScale; // uint16_t diff_newScale; // int16_t oldMaxOnScale; int16_t newMaxOnScale; // int16_t diff_newMaxOnScale; _Bool negativeMaxValue = 0; // float oldRange; float newRange; float sizeOfScreen; // float InputTopValue; // float InputBottomValue; float screenToRangeRatio; float diffOutMaxToMaxOnScale; float diffOutMinToMaxOnScale; int positonOutputMaxValue; int positonOutputMinValue; // scale // oldScale = *OutputStepOfScale; newScale = *OutputStepOfScale + 9; newScale /= 10; newScale *= 10; // diff_newScale = newScale - *OutputStepOfScale; // oldRange = 5 * oldScale; newRange = 5 * newScale; *OutputStepOfScale = newScale; // MaxValueOnScale // oldMaxOnScale = *OutputMaxValueOnScale; if(OutputMaxValueOnScale < 0) { negativeMaxValue = 1; newMaxOnScale = 0 - *OutputMaxValueOnScale; } else { negativeMaxValue = 0; newMaxOnScale = *OutputMaxValueOnScale; } newMaxOnScale += 9; newMaxOnScale /= 10; newMaxOnScale *= 10; if(negativeMaxValue) { // diff_newMaxOnScale = newMaxOnScale + *OutputMaxValueOnScale; *OutputMaxValueOnScale = 0 - newMaxOnScale; } else { // diff_newMaxOnScale = newMaxOnScale - *OutputMaxValueOnScale; *OutputMaxValueOnScale = newMaxOnScale; } // new coordinates sizeOfScreen = 1 + InputBottom - InputTop; // InputTopValue = *OutputMaxValueOnScale; // InputBottomValue = InputTopValue + (6 * *OutputStepOfScale); screenToRangeRatio = sizeOfScreen / newRange; diffOutMaxToMaxOnScale = abs(*OutputMaxValueOnScale) - abs(*OutputMaxValue); // diffOutMinToMax = abs(*OutputMinValue - *OutputMaxValue); diffOutMinToMaxOnScale = abs(*OutputMaxValueOnScale - *OutputMinValue); positonOutputMaxValue = (int)(diffOutMaxToMaxOnScale * screenToRangeRatio); positonOutputMaxValue += *OutputTop; positonOutputMinValue = (int)(diffOutMinToMaxOnScale * screenToRangeRatio); positonOutputMinValue += *OutputTop; // positonOutputMinValue = (int)(diffOutMinToMax * screenToRangeRatio); // positonOutputMinValue += positonOutputMaxValue; *OutputTop = positonOutputMaxValue; *OutputBottom = positonOutputMinValue; } /** ****************************************************************************** * @brief scaleHelper * @author heinrichs weikamp gmbh * @version V0.0.1 * @date 13-Oct-2016 ****************************************************************************** * * @param hgfx: * @retval None * pixel 50 oben * pixel 439 unten * pixel 390 gesamt h�he * for temperature, input is �C * 10 */ static void scaleHelper( uint16_t InputDataLength, int16_t *InputDataArray, int InputTop, int InputBottom, int16_t *OutputMinValue, int16_t *OutputMaxValue, int *OutputTop, int *OutputBottom, uint16_t *OutputStepOfScale, int16_t *OutputMaxValueOnScale) { int32_t datamin = INT16_MAX; // 32 bit for delta calculation ( delta is unsigned -> value can be 2x INT16_MAX) int32_t datamax = INT16_MIN; uint16_t deltaMinMax = 1; // uint16_t deltaMinMaxUsed = 1; // uint16_t digits = 1; // uint16_t scaler = 1; uint32_t step = 1; const int sizeOfScreen = InputBottom - InputTop; float pixel2range = 1.0; // min, max, deltaMinMax, OutputMinValue, OutputMaxValue for(uint16_t i = 0; i < InputDataLength; i++) { if(InputDataArray[i] > datamax) datamax = InputDataArray[i]; if(InputDataArray[i] < datamin) datamin = InputDataArray[i]; } deltaMinMax = (uint16_t)(datamax - datamin); *OutputMinValue = (int16_t)datamin; *OutputMaxValue = (int16_t)datamax; // step step = deltaMinMax / 5; while(deltaMinMax > (step * 5)) { step += 1; } pixel2range = ((float)sizeOfScreen) / (step * 5); *OutputStepOfScale = (uint16_t)step; *OutputMaxValueOnScale = *OutputMaxValue; *OutputTop = InputTop; *OutputBottom = ((int)(pixel2range * deltaMinMax)) + *OutputTop; } /** ****************************************************************************** * @brief show_logbook_logbook_show_log_page1 / * @author Peter Ryser * @version V0.0.1 * @date 07-July-2014 ****************************************************************************** * * @param hgfx: * @retval None */ static void show_logbook_logbook_show_log_page1(GFX_DrawCfgScreen *hgfx,uint8_t StepBackwards) { SWindowGimpStyle wintemp; SWindowGimpStyle winsmal; wintemp.left = LOG_BORDER_OFFSET; wintemp.right = 799 - wintemp.left; wintemp.top = LOG_BORDER_OFFSET; wintemp.bottom = 479 - 40; char timeSuffix; uint8_t hoursToDisplay; SLogbookHeader logbookHeader; logbook_getHeader(StepBackwards ,&logbookHeader); uint16_t depthdata[1000] = { 0 }; uint8_t gasdata[1000] = { 0 }; int16_t tempdata[1000] = { 0 }; uint16_t tankdata[1000] = { 0 }; #ifdef ENABLE_BOTTLE_SENSOR uint16_t bottlePressureStart = 0; uint16_t bottlePressureEnd = 0; uint16_t loop = 0; #endif uint16_t dataLength = 0; dataLength = logbook_readSampleData(StepBackwards, 1000, depthdata,gasdata, tempdata, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tankdata,NULL); //Print Date uint8_t year = logbookHeader.dateYear; uint8_t month = logbookHeader.dateMonth; uint8_t day = logbookHeader.dateDay; char text[40]; snprintf(text, 20, "20%02i-%02i-%02i", year, month, day); Gfx_write_label_var(hgfx, 30, 250,10, &FontT42,CLUT_GasSensor1,text); // Print logbook number with offset if(settingsGetPointer()->logbookOffset) { int32_t logNumber; logNumber = settingsGetPointer()->logbookOffset - StepBackwards; if(logNumber < 0) logNumber = 0; else if(logNumber > 9999) logNumber = 9999; snprintf(text,20,"#%ld",logNumber); Gfx_write_label_var(hgfx, 300, 590,10, &FontT42,CLUT_GasSensor1,text); } //Print time uint8_t minute = logbookHeader.timeMinute; if (settingsGetPointer()->amPMTime) { if (logbookHeader.timeHour > 11) { timeSuffix = 'P'; } else { timeSuffix = 'A'; } if (logbookHeader.timeHour % 12 == 0) { hoursToDisplay = 12; } else { hoursToDisplay = (logbookHeader.timeHour % 12); } snprintf(text,20,"\002%02i:%02i %cM",hoursToDisplay,minute,timeSuffix); } else { hoursToDisplay = logbookHeader.timeHour; snprintf(text,20,"\002%02i:%02i",hoursToDisplay,minute); } Gfx_write_label_var(hgfx, 600, wintemp.right,10, &FontT42,CLUT_GasSensor1,text); //Print Dive Mode (OC/CCR/...) switch(logbookHeader.diveMode) { case DIVEMODE_OC: snprintf(text,20,"%c",TXT_OpenCircuit); break; case DIVEMODE_CCR: snprintf(text,20,"%c",TXT_ClosedCircuit); break; case DIVEMODE_Gauge: snprintf(text,20,"%c",TXT_Gauge); break; case DIVEMODE_Apnea: snprintf(text,20,"%c",TXT_Apnoe); break; case DIVEMODE_PSCR: snprintf(text,20,"%c",TXT_PSClosedCircuit); break; } Gfx_write_label_var(hgfx, 30, 250,60, &FontT42,CLUT_GasSensor4,text); // Decomodel if(logbookHeader.diveMode <= DIVEMODE_CCR) { switch(logbookHeader.decoModel) { case GF_MODE: snprintf(text,20,"\002GF%u/%u",logbookHeader.gfLow_or_Vpm_conservatism,logbookHeader.gfHigh); break; case VPM_MODE: snprintf(text,20,"\002VPM +%u",logbookHeader.gfLow_or_Vpm_conservatism); break; default: snprintf(text,20," "); /* no information to be displayed */ break; } Gfx_write_label_var(hgfx, 500, wintemp.right,60, &FontT42,CLUT_GasSensor1,text); } //Write Dive Time int minutes = logbookHeader.diveTimeMinutes; int seconds = logbookHeader.diveTimeSeconds; int hours = minutes/60; minutes -= hours * 60; snprintf(text,20,"%02i:%02i:%02i",hours,minutes,seconds); Gfx_write_label_var(hgfx, 30, 250,360, &FontT42,CLUT_GasSensor1,text); Gfx_write_label_var(hgfx, 200, 250,360, &FontT42,CLUT_GasSensor4,"s"); // Max Depth int maxdepth =logbookHeader.maxDepth/100; int maxdepth_dcm = logbookHeader.maxDepth/10 - maxdepth * 10; int top = 150; if(settingsGetPointer()->nonMetricalSystem) { float maxDepthFeet = 0; maxDepthFeet = unit_depth_float(((float)logbookHeader.maxDepth)/100); snprintf(text,20,"%.0f",maxDepthFeet); } else { snprintf(text,20,"%i.%i",maxdepth,maxdepth_dcm); } Gfx_write_label_var(hgfx, 30, 250,top, &FontT42,CLUT_GasSensor1,text); winsmal.left = 30; winsmal.top = top -3; winsmal.bottom = winsmal.top + FontT42.height; if(maxdepth < 10) { winsmal.left = 137; } else if(maxdepth < 100) { winsmal.left = 151; } else { winsmal.left = 147; } winsmal.right = winsmal.left + 50; Gfx_write_label_var(hgfx, winsmal.left, winsmal.right,top, &FontT24,CLUT_GasSensor4,"max"); snprintf(text,3,"%c%c" , unit_depth_char1() , unit_depth_char2() ); Gfx_write_label_var(hgfx, winsmal.left - 37, 250,top, &FontT42,CLUT_GasSensor4,text); // Average Depth int avrdepth =logbookHeader.averageDepth_mbar/100; int avrdepth_dcm = logbookHeader.averageDepth_mbar/10 - avrdepth * 10; top = 200; if(settingsGetPointer()->nonMetricalSystem) { float avgDepthFeet = 0; avgDepthFeet = unit_depth_float(((float)logbookHeader.averageDepth_mbar)/100); snprintf(text,20,"%.0f",avgDepthFeet); } else { snprintf(text,20,"%i.%i",avrdepth,avrdepth_dcm); } Gfx_write_label_var(hgfx, 30, 250,top, &FontT42,CLUT_GasSensor1,text); winsmal.left = 30; winsmal.top = top -3; winsmal.bottom = winsmal.top + FontT42.height; /* put avg behind previous string */ if(avrdepth < 10) { winsmal.left = 137 ; } else if(avrdepth < 100) { winsmal.left = 151; } else { winsmal.left = 147; } winsmal.right = winsmal.left + 50; Gfx_write_label_var(hgfx, winsmal.left, winsmal.right,winsmal.top, &FontT24,CLUT_GasSensor4,"avg"); snprintf(text,3,"%c%c" , unit_depth_char1() , unit_depth_char2() ); Gfx_write_label_var(hgfx, winsmal.left - 37, 250,top, &FontT42,CLUT_GasSensor4,text); // Temperature top+= 50; float temp_Temperature; uint16_t start; temp_Temperature = ((float)logbookHeader.minTemp)/10; snprintf(text,20,"%.1f",unit_temperature_float(temp_Temperature)); Gfx_write_label_var(hgfx, 30, 250,top, &FontT42,CLUT_GasSensor1,text); if(settingsGetPointer()->nonMetricalSystem) start = 121; else if((logbookHeader.minTemp >= 0) && (logbookHeader.minTemp < 10)) start = 100; else if((logbookHeader.minTemp >= -10) && (logbookHeader.minTemp < 100)) start = 114; else start = 121; text[0] = '\140'; if(settingsGetPointer()->nonMetricalSystem) text[1] = 'F'; else text[1] = 'C'; text[2] = 0; Gfx_write_label_var(hgfx, start, 300,top, &FontT42,CLUT_GasSensor4,text); // CNS snprintf(text,20,"CNS: %i %%",logbookHeader.maxCNS); Gfx_write_label_var(hgfx, 30, 250,440, &FontT42,CLUT_GasSensor1,text); // Surface Pressure // snprintf(text,20,"\001%i\016\016 mbar",logbookHeader.surfacePressure_mbar); // Gfx_write_label_var(hgfx,300,500,750, &FontT42,CLUT_GasSensor1,text); // snprintf(text,40,"%i\016\016 mbar\017 (%i\016\016 m\017)",logbookHeader.surfacePressure_mbar, unit_SeaLevelRelation_integer(logbookHeader.surfacePressure_mbar)); snprintf(text,40,"%i\016\016 hPa\017",logbookHeader.surfacePressure_mbar); Gfx_write_label_var(hgfx,320,600,440, &FontT42,CLUT_GasSensor1,text); /* show symbol in case log entry is marked for usage in profile custom view */ snprintf(text,10,"\002>"); if(StepBackwards == getReplayOffset()) { Gfx_write_label_var(hgfx,750,799,440, &FontT42,CLUT_GasSensor1,text); } else { Gfx_write_label_var(hgfx,750,799,440, &FontT42,CLUT_MenuTopBackground,text); } /* Show tank info */ #ifdef ENABLE_BOTTLE_SENSOR for(loop = 0; loop < dataLength; loop++) { if((bottlePressureStart == 0) && (tankdata[loop] != 0)) /* find first pressure value */ { bottlePressureStart = tankdata[loop]; } if((tankdata[loop] != 0)) /* store last pressure value */ { bottlePressureEnd = tankdata[loop]; } } if(bottlePressureStart != 0) { snprintf(text,40,"\002%i | %i\016\016 Bar\017",bottlePressureStart,bottlePressureEnd); Gfx_write_label_var(hgfx,450,wintemp.right,440, &FontT42,CLUT_GasSensor1,text); } #endif //--- print coordinate system & depth graph with gaschanges --- wintemp.left = 330; wintemp.top = 160; wintemp.bottom -= 40; show_logbook_draw_depth_graph(hgfx, StepBackwards, &wintemp, 1, dataLength, depthdata, gasdata, NULL); } static void show_logbook_logbook_show_log_page2(GFX_DrawCfgScreen *hgfx, uint8_t StepBackwards) { //*** Page2: Depth and Temperature **** SWindowGimpStyle wintemp; SWindowGimpStyle winsmal; wintemp.left = 50; wintemp.right = 799 - wintemp.left; wintemp.top = 50; wintemp.bottom = 479 - 40; SLogbookHeader logbookHeader; logbook_getHeader(StepBackwards,&logbookHeader); uint16_t dataLength = 0; uint16_t depthdata[1000]; uint8_t gasdata[1000]; int16_t tempdata[1000]; 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); for(int i = 0; i<dataLength; i++) { if(decoDepthdata[i] >= 300) { pDecoDepthData = decoDepthdata; break; } } //--- print coordinate system & depth graph --- show_logbook_draw_depth_graph(hgfx, StepBackwards, &wintemp, 0, dataLength, depthdata, gasdata, pDecoDepthData); //*** Temperature ************************************************* //--- print temperature labels --- // input maxtmpline, tmpstep, deltaline winsmal.left = wintemp.right +6; winsmal.top = wintemp.top - 3; winsmal.right = wintemp.right + 30; winsmal.bottom = winsmal.top + 16; if(settingsGetPointer()->nonMetricalSystem) { Gfx_write_label_var(hgfx, winsmal.left, winsmal.right,winsmal.top, &FontT24,CLUT_LogbookTemperature,"[F]"); } else { Gfx_write_label_var(hgfx, winsmal.left, winsmal.right,winsmal.top, &FontT24,CLUT_LogbookTemperature,"[C]"); } int16_t minVal = 0; int16_t maxVal = 0; int newTop = 0; int newBottom = 0; uint16_t step = 0; int16_t maxValTop = 0; int16_t tmp = 0; scaleHelper(dataLength, tempdata, wintemp.top, wintemp.bottom, &minVal, &maxVal, &newTop, &newBottom, &step, &maxValTop); // newTop is wintemp.top scaleAdapt( wintemp.top, wintemp.bottom, &minVal, &maxVal, &newTop, &newBottom, &step, &maxValTop); // temperature in 1/10 �C int deltaline = (1 + wintemp.bottom - wintemp.top)/5; char msg[15]; /* temperature is provided in centi scaling => convert */ maxValTop /= 10; step /= 10; tmp = maxValTop; for(int i = 1; i<=5; i++) { tmp -= step; winsmal.top = wintemp.top + deltaline * i - 14; winsmal.bottom = winsmal.top + 16; snprintf(msg,15,"%2i",unit_temperature_integer(tmp)); Gfx_write_label_var(hgfx, winsmal.left, winsmal.right,winsmal.top, &FontT24,CLUT_LogbookTemperature,msg); } //--- print temperature graph --- // input tempdata[i], maxtmpline, mintmpline, maxTmp, minTmp, deltaline, wintemp.top, dataLength, datamax, //adapt window wintemp.bottom = newBottom; wintemp.top = newTop; GFX_graph_print(hgfx,&wintemp,0,1,maxVal,minVal, (uint16_t *)tempdata,dataLength,CLUT_LogbookTemperature, NULL); } static void build_logbook_test(uint8_t page, uint8_t StepBackwards) { uint32_t lastScreen,lastBackground; lastScreen = tLOGscreen.FBStartAdress; lastBackground = tLOGbackground.FBStartAdress; tLOGscreen.FBStartAdress = getFrame(16); tLOGscreen.ImageHeight = 480; tLOGscreen.ImageWidth = 800; tLOGscreen.LayerIndex = 1; tLOGbackground.FBStartAdress = getFrame(17); tLOGbackground.ImageHeight = 480; tLOGbackground.ImageWidth = 800; tLOGbackground.LayerIndex = 0; switch(page) { case 1: show_logbook_logbook_show_log_page1(&tLOGscreen,StepBackwards); break; case 2: show_logbook_logbook_show_log_page2(&tLOGscreen,StepBackwards); break; case 3: show_logbook_logbook_show_log_page3(&tLOGscreen,StepBackwards); break; case 4: show_logbook_logbook_show_log_page4(&tLOGscreen,StepBackwards); break; } releaseFrame(16,lastScreen); releaseFrame(17,lastBackground); } void show_logbook_test(_Bool firstPage, uint8_t StepBackwards) { if(firstPage) { active_log_page = 1; active_log_offset = StepBackwards; } else { active_log_page++; if(active_log_page > 4) { active_log_page = 1; } } build_logbook_test(active_log_page,StepBackwards); // GFX_ResetLayer(TOP_LAYER); // GFX_ResetLayer(BACKGRD_LAYER); set_globalState(StILOGSHOW); GFX_SetFramesTopBottom(tLOGscreen.FBStartAdress, tLOGbackground.FBStartAdress,480); } void show_logbook_exit(void) { releaseFrame(16,tLOGscreen.FBStartAdress); releaseFrame(17,tLOGbackground.FBStartAdress); } static void show_logbook_logbook_show_log_page3(GFX_DrawCfgScreen *hgfx, uint8_t StepBackwards) { SWindowGimpStyle wintemp; SWindowGimpStyle winsmal; uint8_t gasWasUsed[NUM_GASES * 2]; int16_t index = 0; uint8_t loopMode = 0; wintemp.left = 50; wintemp.right = 799 - wintemp.left; wintemp.top = 50; wintemp.bottom = 479 - 40; SLogbookHeader logbookHeader; logbook_getHeader(StepBackwards, &logbookHeader); 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); char msg[15]; char gas_name[15]; int j = 0; loopMode = isLoopMode(logbookHeader.diveMode); /* check if gas was used, independent from its active state */ for(index = 0; index < NUM_GASES * 2; index++) { gasWasUsed[index] = 0; } for(index = 0; index < dataLength; index++) { if(loopMode) { if(gasdata[index] < NUM_GASES) /* the log entry starts with a ID in range 1..4 independend if diluent is used at start */ { gasdata[index] += NUM_GASES; } else { loopMode = 0; /* after the first gas change, no matter if diluent or bailout, the correct ID will be stored */ } } if(gasdata[index] > 0) { gasWasUsed[gasdata[index]-1] = 1; /* The ID stored in the samples is starting with 1 (array[0] = gasID1) */ } else { gasWasUsed[0] = 1; } } //--- print coordinate system & depth graph with gaschanges --- show_logbook_draw_depth_graph(hgfx, StepBackwards, &wintemp, 1, dataLength, depthdata, gasdata, NULL); //--- print gas list --- winsmal.left = wintemp.right - 190; winsmal.right = winsmal.left + 150; loopMode = isLoopMode(logbookHeader.diveMode); for(index = (2 * NUM_GASES) -1; index >= 0; index--) { if(gasWasUsed[index]) { j++; if(j > 5) /* limit number of gases displayed to 5 */ { break; } winsmal.top = wintemp.bottom - 5 - j * 26 ; winsmal.bottom = winsmal.top + 21 ; uint8_t color = get_colour(index); if(loopMode) { if(index < NUM_GASES) /* Switch to Bailout is not covered by log gas list */ { snprintf(gas_name,15,"Bailout"); snprintf(msg,15,"G%d: %s",index +1, gas_name); } else { print_gas_name(gas_name,15,logbookHeader.gasordil[index-NUM_GASES].oxygen_percentage,logbookHeader.gasordil[index-NUM_GASES].helium_percentage); snprintf(msg,15,"D%d: %s",index +1 - NUM_GASES, gas_name); } } else { print_gas_name(gas_name,15,logbookHeader.gasordil[index].oxygen_percentage,logbookHeader.gasordil[index].helium_percentage); snprintf(msg,15,"G%d: %s",index +1, gas_name); } Gfx_write_label_var(hgfx, winsmal.left, winsmal.right,winsmal.top, &FontT24,color,msg); } } //--- define buttons --- /*if(*ghost_char_logfile_oxydata) button_start_single_action(surf1_menu_logbook_current_page, surf1_menu_logbook_show_log_page4, surf1_menu_logbook_show_log_next); else button_start_single_action(surf1_menu_logbook_current_page, surf1_menu_logbook_show_log_page1, surf1_menu_logbook_show_log_next); */ } static uint8_t check_data_array_empty(uint16_t* pdata) { uint8_t ret = 0; uint8_t index = 0; uint8_t emptyCnt = 0; for (index=0; index < 10; index++) /* read the first 10 data points. If all are 0 then the array is rated as empty */ { if(*(pdata+index) == 0) { emptyCnt++; } } if(emptyCnt == 10) { ret = 1; } return ret; } static void show_logbook_logbook_show_log_page4(GFX_DrawCfgScreen *hgfx, uint8_t StepBackwards) { SWindowGimpStyle wintemp; SWindowGimpStyle winsmal; wintemp.left = 50; wintemp.right = 799 - wintemp.left; wintemp.top = 50; wintemp.bottom = 479 - 40; uint8_t color = 0; SLogbookHeader logbookHeader; logbook_getHeader(StepBackwards, &logbookHeader); uint16_t dataLength = 0; uint16_t depthdata[1000]; uint8_t gasdata[1000]; uint16_t ppO2data[1000]; uint16_t sensor2[1000]; uint16_t sensor3[1000]; uint16_t *setpoint = ppO2data; uint16_t *sensor1 = ppO2data; uint8_t sensorDataAvailable[] = {0,0,0}; if(!isLoopMode(logbookHeader.diveMode)) dataLength = logbook_readSampleData(StepBackwards, 1000, depthdata,gasdata, NULL, ppO2data, 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); break; case CCRMODE_Sensors: dataLength = logbook_readSampleData(StepBackwards, 1000, depthdata, gasdata, NULL, NULL, NULL, sensor1, sensor2, sensor3, NULL, NULL, NULL, NULL, NULL); if(!check_data_array_empty(sensor1)) { sensorDataAvailable[0] = 1; } if(!check_data_array_empty(sensor2)) { sensorDataAvailable[1] = 1; } if(!check_data_array_empty(sensor3)) { sensorDataAvailable[2] = 1; } if((logbookHeader.diveMode == DIVEMODE_PSCR) && (sensorDataAvailable[0] + sensorDataAvailable[1] + sensorDataAvailable[2] != 3)) /*insert sim data if not all three sensors are in use*/ { if(sensorDataAvailable[0] == 0) { logbook_readSampleData(StepBackwards, 1000, depthdata,gasdata, NULL, sensor1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); sensorDataAvailable[0] = 1; } else if(sensorDataAvailable[1] == 0) { logbook_readSampleData(StepBackwards, 1000, depthdata,gasdata, NULL, sensor2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); sensorDataAvailable[1] = 1; } else if(sensorDataAvailable[2] == 0) { logbook_readSampleData(StepBackwards, 1000, depthdata,gasdata, NULL, sensor3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); sensorDataAvailable[2] = 1; } } break; case CCRMODE_Simulation: dataLength = logbook_readSampleData(StepBackwards, 1000, depthdata,gasdata, NULL, ppO2data, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); break; } } //--- print coordinate system & depth graph with bailout--- show_logbook_draw_depth_graph(hgfx, StepBackwards, &wintemp, 0, dataLength, depthdata, gasdata, NULL); //*** Desciption at bottom of page *************************** winsmal.top = wintemp.bottom +2 ; winsmal.bottom = winsmal.top + 16; /*if(strcmp( (char*)ghost_char_logfile_text_oc_ccr,"ccr/bailout") == 0) { winsmal.left = wintemp.left + 2; winsmal.right = winsmal.left + 55; oled_write(OVERLAY, &winsmal,"CCR -",false,true); winsmal.left = winsmal.right; winsmal.right = winsmal.left + 90; //winsmal.fontcolor = oled_get_colour(15); oled_write(OVERLAY, &winsmal,"bailout",false,true); } else*/ { winsmal.left = wintemp.left + 2; winsmal.right = winsmal.left + 55; color = CLUT_GasSensor1;//LOGBOOK_GRAPH_DEPTH; Gfx_write_label_var(hgfx, winsmal.left, winsmal.right,winsmal.top, &FontT24,color,"depth"); } winsmal.left = 799 - 67;//wintemp.right -67; winsmal.right = winsmal.left;// + 45; color = CLUT_LogbookTemperature; if(!isLoopMode(logbookHeader.diveMode)) { Gfx_write_label_var(hgfx, winsmal.left, winsmal.right,winsmal.top, &FontT24,color,"\002PP O2"); } else { switch(logbookHeader.CCRmode) { case CCRMODE_FixedSetpoint: default: Gfx_write_label_var(hgfx, winsmal.left, winsmal.right,winsmal.top, &FontT24,color,"\002SETPOINT"); break; case CCRMODE_Sensors: Gfx_write_label_var(hgfx, winsmal.left, winsmal.right,winsmal.top, &FontT24,color,"\002SENSORS"); break; case CCRMODE_Simulation: Gfx_write_label_var(hgfx, winsmal.left, winsmal.right,winsmal.top, &FontT24,color,"\002SIM PPO2"); break; } } //*** PP O2 **************************************************** //calc lines and labels int datamax = 0; int datamin = 10000; for(int i=1;i<dataLength;i++) { if(ppO2data[i]>datamax) datamax = ppO2data[i]; if(ppO2data[i]<datamin) datamin = ppO2data[i]; } if(isLoopMode(logbookHeader.diveMode) && (logbookHeader.CCRmode == CCRMODE_Sensors)) { for(int i=1;i<dataLength;i++) { if(sensor2[i]>datamax) datamax = sensor2[i]; if(sensor2[i]<datamin) datamin = sensor2[i]; if(sensor3[i]>datamax) datamax = sensor3[i]; if(sensor3[i]<datamin) datamin = sensor3[i]; } } float maxoxy = ((float)datamax)/100; float minoxy = ((float)datamin)/100; float oxystep = 0.5; float maxoxyline = 2.5; //--- print PP O2 labels ---- winsmal.left = wintemp.right + 2; winsmal.top = wintemp.top ; winsmal.right = wintemp.right + 30; winsmal.bottom = winsmal.top + 16; //winsmal.font = ft_tiny + ft_SLIM; color = CLUT_LogbookTemperature;// = LOGBOOK_GRAPH_TEMP; Gfx_write_label_var(hgfx, winsmal.left, winsmal.right,winsmal.top, &FontT24,color,"bar"); int deltaline = (wintemp.bottom - wintemp.top)/5; char msg[4]; float oxy = maxoxyline; for(int i = 1; i<=5; i++) { oxy -= oxystep; if(oxy < 0) break; winsmal.top = wintemp.top + deltaline * i - 8; winsmal.bottom = winsmal.top + 16; snprintf(msg,4,"%1.1f",oxy); Gfx_write_label_var(hgfx, winsmal.left, winsmal.right,winsmal.top, &FontT24,color,msg); //oled_write(OVERLAY, &winsmal,msg,false,true); } //--- print PP O2 graph --- //Adapt window float ftmp = ((maxoxyline - minoxy) * deltaline) /oxystep + wintemp.top; wintemp.bottom = ftmp; if((ftmp - (int)ftmp) >= 0.5f) wintemp.bottom++; ftmp = wintemp.top + ((maxoxyline - maxoxy) * deltaline) /oxystep; wintemp.top = ftmp; if((ftmp - (int)ftmp) >= 0.5f) wintemp.top++; wintemp.top = MaxU32LOG(wintemp.top ,0); if(wintemp.top < wintemp.bottom) { if(isLoopMode(logbookHeader.diveMode) && (logbookHeader.CCRmode == CCRMODE_Sensors)) { if(sensorDataAvailable[0]) { GFX_graph_print(hgfx,&wintemp,0,1,datamax,datamin, ppO2data,dataLength,CLUT_GasSensor2, NULL); } if(sensorDataAvailable[1]) { GFX_graph_print(hgfx,&wintemp,0,1,datamax,datamin, sensor2,dataLength,CLUT_GasSensor3, NULL); } if(sensorDataAvailable[2]) { GFX_graph_print(hgfx,&wintemp,0,1,datamax,datamin, sensor3,dataLength,CLUT_GasSensor4, NULL); } } else GFX_graph_print(hgfx,&wintemp,0,1,datamax,datamin, ppO2data,dataLength,CLUT_LogbookTemperature, NULL); } else { point_t startPoint, stopPoint; startPoint.x = wintemp.left; stopPoint.x = wintemp.right; stopPoint.y = startPoint.y = 479 - wintemp.top; GFX_draw_colorline(hgfx, startPoint, stopPoint, CLUT_LogbookTemperature); } //--- define buttons --- //button_start_single_action(surf1_menu_logbook_current_page, surf1_menu_logbook_show_log_page1, surf1_menu_logbook_show_log_next); } static void print_gas_name(char* output,uint8_t length,uint8_t oxygen,uint8_t helium) { if(helium == 0) { if(oxygen == 21) snprintf(output, length, "Air"); else if(oxygen == 100) snprintf(output, length, "Oxy"); else snprintf(output, length, "NX%i",oxygen); } else { if((oxygen + helium) == 100) snprintf(output, length, "HX%i",oxygen); else snprintf(output, length, "TMX%i/%i", oxygen, helium); } } static int16_t get_colour(int16_t color) { return CLUT_GasSensor1 + color; } uint8_t getActiveLogPage() { return active_log_page; } void updateReplayIncdicator(GFX_DrawCfgScreen *hgfx) { build_logbook_test(1,active_log_offset); GFX_SetFramesTopBottom(tLOGscreen.FBStartAdress, tLOGbackground.FBStartAdress,480); }