From a6e6a2dd12abe411c78130aa8c6681b6e4f7c6a2 Mon Sep 17 00:00:00 2001 From: bsongis Date: Mon, 9 Jan 2012 18:52:22 +0000 Subject: [PATCH] Logs and Telemetry decorrelated. Telemetry helpers. Possibility to reset the altitude. Flash optimizations. --- src/Makefile | 12 +++- src/frsky.cpp | 95 +------------------------- src/frsky.h | 8 ++- src/gruvin9x.cpp | 74 ++------------------- src/gruvin9x.h | 19 ++++-- src/gtime.cpp | 91 +++++++++++++------------ src/gtime.h | 14 ++-- src/lcd.cpp | 14 +++- src/lcd.h | 3 +- src/logs.cpp | 158 ++++++++++++++++++++++++++++++++++++++++++++ src/main_views.cpp | 53 ++++++--------- src/model_menus.cpp | 72 ++++++++------------ src/myeeprom.h | 27 +++++--- src/pers.cpp | 3 + src/rtc.cpp | 6 +- src/simpgmspace.cpp | 3 + src/simu.cpp | 12 +++- 17 files changed, 342 insertions(+), 322 deletions(-) create mode 100644 src/logs.cpp diff --git a/src/Makefile b/src/Makefile index cdc0d3a96..b8f98eade 100644 --- a/src/Makefile +++ b/src/Makefile @@ -97,6 +97,10 @@ FRSKY_HUB = YES # Values = YES, NO WS_HOW_HIGH = YES +# SDCARD Logs +# Values = YES, NO +LOGS = YES + # PXX (FrSky PCM) protocol PXX = NO @@ -216,6 +220,7 @@ ifeq ($(NAVIGATION), POTS) CPPDEFS += -DNAVIGATION_POT1 -DNAVIGATION_POT2 -DNAVIGATION_POT3 endif +MODS = ifeq ($(PCB), STD) # STD PCB, so ... @@ -286,8 +291,13 @@ else ifeq ($(PCB), V3) CPPDEFS += -DBEEPSPKR endif + ifeq ($(LOGS), YES) + CPPSRC += logs.cpp + CPPDEFS += -DLOGS + MODS += L + endif ifeq ($(PCB), V4) - CPPDEFS += -DPCBV4 + CPPDEFS += -DPCBV4 # Temporary hack to get stock beeper working for testing, etc ... make BEEPER=BUZZER_MOD # TODO should not be needed / tested here in V4 ifeq ($(BEEPER), BUZZER_MOD) diff --git a/src/frsky.cpp b/src/frsky.cpp index bbec40c1a..d3f4d8787 100644 --- a/src/frsky.cpp +++ b/src/frsky.cpp @@ -19,8 +19,6 @@ */ #include "gruvin9x.h" -#include "frsky.h" -#include "ff.h" // TODO // Enumerate FrSky packet codes #define LINKPKT 0xfe @@ -57,6 +55,7 @@ struct FrskyAlarm frskyAlarms[4]; #if defined(FRSKY_HUB) || defined(WS_HOW_HIGH) FrskyHubData frskyHubData; +int16_t baroAltitudeOffset = 0; #endif void frskyPushValue(uint8_t *&ptr, uint8_t value) @@ -500,100 +499,12 @@ void FrskyData::set(uint8_t value) min = value; } -// TODO not here! -#if defined (PCBV3) -char g_logFilename[22]; // "/G9XLOGS/M00_000.TXT\0" max required length = 21 -// These global so we can close any open file from anywhere -FATFS FATFS_Obj; -FIL g_oLogFile; -#endif - void resetTelemetry() { memset(frskyTelemetry, 0, sizeof(frskyTelemetry)); memset(frskyRSSI, 0, sizeof(frskyRSSI)); - -#if defined (PCBV3) - - // Determine and set log file filename - - FRESULT result; - - // close any file left open. E.G. Changing models with log switch still on. - if (g_oLogFile.fs) f_close(&g_oLogFile); - - strcpy(g_logFilename, "/G9XLOGS/M00_000.TXT"); - - uint8_t num = g_eeGeneral.currModel + 1; - char *n = &g_logFilename[11]; - *n = (char)((num % 10) + '0'); - *(--n) = (char)((num / 10) + '0'); - - result = f_mount(0, &FATFS_Obj); - if (result!=FR_OK) - { - strcpy(g_logFilename, "FILE SYSTEM ERROR"); - } - else - { - // Skip over any existing log files ... _000, _001, etc. (or find first gap in numbering) - while (1) - { - result = f_open(&g_oLogFile, g_logFilename, FA_OPEN_EXISTING | FA_READ); - - if (result == FR_OK) - { - f_close(&g_oLogFile); - - // bump log file counter (file extension) - n = &g_logFilename[15]; - if (++*n > '9') - { - *n='0'; - n--; - if (++*n > '9') - { - *n='0'; - n--; - if (++*n > '9') - { - *n='0'; - break; // Wow. We looped back around past 999 to 000! abort loop - } - } - } - } - else if (result == FR_NO_PATH) - { - if (f_mkdir("/G9XLOGS") != FR_OK) - { - result = FR_NO_PATH; - break; - } - else - continue; - } - else - break; - } - - switch (result) - { - case FR_NO_PATH: - strcpy(g_logFilename, "Check /G9XLOGS folder"); - break; - case FR_NOT_READY: - strcpy(g_logFilename, "DATA CARD NOT PRESENT"); - break; - - default: - break; - } - } - - // g_logFilename should now be set appropriately. - +#if defined(FRSKY_HUB) || defined(WS_HOW_HIGH) + baroAltitudeOffset = -frskyHubData.baroAltitude; #endif - } diff --git a/src/frsky.h b/src/frsky.h index a5b2ffbdb..fe4eca039 100644 --- a/src/frsky.h +++ b/src/frsky.h @@ -76,12 +76,18 @@ struct FrskyHubData { int16_t accelY; // 1/256th gram (-8g ~ +8g) int16_t accelZ; // 1/256th gram (-8g ~ +8g) }; -extern FrskyHubData frskyHubData; + #elif defined(WS_HOW_HIGH) + struct FrskyHubData { uint16_t baroAltitude; // 0..9,999 meters }; + +#endif + +#if defined(FRSKY_HUB) || defined(WS_HOW_HIGH) extern FrskyHubData frskyHubData; +extern int16_t baroAltitudeOffset; #endif // Global Fr-Sky telemetry data variables diff --git a/src/gruvin9x.cpp b/src/gruvin9x.cpp index 2928763e8..1bd47a005 100644 --- a/src/gruvin9x.cpp +++ b/src/gruvin9x.cpp @@ -25,7 +25,7 @@ // MM/SD card Disk IO Support #if defined (PCBV3) -time_t g_unixTime; // Global date/time register, incremented each second in per10ms() +gtime_t g_unixTime; // Global date/time register, incremented each second in per10ms() #endif /* @@ -1194,7 +1194,7 @@ uint16_t active_functions = 0; // current max = 16 functions void evalFunctions() { - assert(sizeof(active_functions)*8 >= FUNC_LAST); + assert(sizeof(active_functions)*8 > FUNC_MAX); for (uint8_t i=0; i 0) trimsCheckTimer -= 1; -#if defined (FRSKY) - -/***** TEST CODE - Fr-Sky SD/MMC card / User Data experiments *****/ - -#if defined (PCBV3) - - /* Use light switch (on) to open telemtry test log file */ - static FRESULT result; - - static int8_t testLogOpen = 0; - - if(getSwitch(g_eeGeneral.lightSw,0)) - { - // while(1); // Test WDT - if ((testLogOpen==0) // if we know we haven't started logging ... - || ((testLogOpen==1) && !g_oLogFile.fs)) // ... or we thought we had, but the file got closed - { - result = f_mount(0, &FATFS_Obj); - if (result!=FR_OK) - { - testLogOpen = -1; - beepAgain = result - 1; - beepKey(); - } - else - { - // create new log file using filename set up in pers.cpp::resetTelemetry() - result = f_open(&g_oLogFile, g_logFilename, FA_OPEN_ALWAYS | FA_WRITE); - if (result!=FR_OK) - { - testLogOpen = -2; - beepAgain = result - 1; - beepKey(); - } - else - { - f_lseek(&g_oLogFile, g_oLogFile.fsize); // append - - testLogOpen = 1; - beepWarn2(); - } - } - } - } - else - { - if (testLogOpen==1) - { - f_close(&g_oLogFile); - beepWarn2(); - } - testLogOpen = 0; - } - - -#ifdef DISPLAY_USER_DATA - //////////////// - // Write raw user data into on-screen display line buffer +#if defined (LOGS) + doLogs(); +#endif +#if defined(FRSKY) and defined(DISPLAY_USER_DATA) char userDataRxBuffer[21]; // Temp buffer used to collect fr-sky user data // retrieve bytes from user data buffer and insert into display string, @@ -1672,14 +1618,6 @@ void perMain() f_putc(userDataRxBuffer[byt], &g_oLogFile); } - //////////////// -#endif - -/***** END TEST CODE - Fr-Sky User Data experiments *****/ - -// PCBV3 -#endif -// FRSKY #endif lcd_clear(); diff --git a/src/gruvin9x.h b/src/gruvin9x.h index af8cb9865..948dac53a 100644 --- a/src/gruvin9x.h +++ b/src/gruvin9x.h @@ -304,7 +304,12 @@ enum EnumKeys { #define CSWITCH_STR "---- v>ofs vofs|v|v2 ""v1=v2 ""v1<=v2 " #define CSW_LEN_FUNC 7 -#define FSWITCH_STR "---- ""Trainer ""Trainer RUD ""Trainer ELE ""Trainer THR ""Trainer AIL ""Instant Trim ""Trims2Offsets ""Telemetry View" +#ifdef LOGS +#define LOGS_STR "SDCARD Logs " +#else +#define LOGS_STR +#endif +#define FSWITCH_STR "---- ""Trainer ""Trainer RUD ""Trainer ELE ""Trainer THR ""Trainer AIL ""Instant Trim ""Trims2Offsets "LOGS_STR #define FSW_LEN_FUNC 14 #define SWASH_TYPE_STR "--- ""120 ""120X ""140 ""90 " @@ -553,6 +558,7 @@ extern uint8_t s_eeDirtyMsk; #define FORCEINLINE inline __attribute__ ((always_inline)) #endif + /// liefert Betrag des Arguments template FORCEINLINE t abs(t a){ return a>0?a:-a; } /// liefert das Minimum der Argumente @@ -608,13 +614,12 @@ extern inline uint16_t get_tmr10ms() #define TMR_VAROFS 16 -#define SUB_MODE_V 1 -#define SUB_MODE_H 2 -#define SUB_MODE_H_DBL 3 - void setupPulses(); -void initTemplates(); +#ifdef LOGS +extern void startLogs(); +extern void doLogs(); +#endif #include "lcd.h" extern const char stamp1[]; @@ -714,7 +719,7 @@ inline void _beepSpkr(uint8_t d, uint8_t f) #if defined (PCBV3) #include "rtc.h" extern void disk_timerproc(void); -extern time_t g_unixTime; // global unix timestamp -- hold current time in seconds since 1970-01-01 00:00:00 +extern gtime_t g_unixTime; // global unix timestamp -- hold current time in seconds since 1970-01-01 00:00:00 extern uint8_t g_ms100; // defined in drivers.cpp #endif diff --git a/src/gtime.cpp b/src/gtime.cpp index ccb460a3e..4225d33c0 100644 --- a/src/gtime.cpp +++ b/src/gtime.cpp @@ -73,17 +73,17 @@ : ~ (~ (t) 0 << (sizeof (t) * CHAR_BIT - 1)))) #ifndef TIME_T_MIN -# define TIME_T_MIN TYPE_MINIMUM (time_t) +# define TIME_T_MIN TYPE_MINIMUM (gtime_t) #endif #ifndef TIME_T_MAX -# define TIME_T_MAX TYPE_MAXIMUM (time_t) +# define TIME_T_MAX TYPE_MAXIMUM (gtime_t) #endif #define TIME_T_MIDPOINT (SHR (TIME_T_MIN + TIME_T_MAX, 1) + 1) /* Verify a requirement at compile-time (unlike assert, which is runtime). */ #define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; } -verify (time_t_is_integer, TYPE_IS_INTEGER (time_t)); +verify (gtime_t_is_integer, TYPE_IS_INTEGER (gtime_t)); verify (twos_complement_arithmetic, TYPE_TWOS_COMPLEMENT (int)); /* The code also assumes that signed integer overflow silently wraps around, but this assumption can't be stated without causing a @@ -95,7 +95,6 @@ verify (base_year_is_a_multiple_of_100, TM_YEAR_BASE % 100 == 0); #define SECS_PER_HOUR 3600ul #define SECS_PER_DAY 86400ul -#define EOVERFLOW 0 /* Return 1 if YEAR + TM_YEAR_BASE is a leap year. */ static inline int @@ -123,7 +122,7 @@ const unsigned short int __mon_yday[2][13] = Return nonzero if successful. */ int __offtime ( - time_t *t, + gtime_t *t, long int offset, struct gtm *tp) { @@ -138,7 +137,7 @@ __offtime ( rem += SECS_PER_DAY; --days; } - while (rem >= SECS_PER_DAY) + while (rem >= (long int)SECS_PER_DAY) { rem -= SECS_PER_DAY; ++days; @@ -185,9 +184,9 @@ __offtime ( } /* time_r function implementations */ -// G: No time zones in our implementation so just do the converion from time_t to struct tm +// G: No time zones in our implementation so just do the converion from gtime_t to struct tm struct gtm * -__localtime_r (time_t * t, struct gtm * tp) +__localtime_r (gtime_t * t, struct gtm * tp) { __offtime(t, 0, tp); return tp; @@ -205,7 +204,7 @@ __localtime_r (time_t * t, struct gtm * tp) The result may overflow. It is the caller's responsibility to detect overflow. */ -static inline time_t +static inline gtime_t ydhms_diff (long int year1, long int yday1, int hour1, int min1, int sec1, int year0, int yday0, int hour0, int min0, int sec0) { @@ -223,34 +222,34 @@ ydhms_diff (long int year1, long int yday1, int hour1, int min1, int sec1, int b400 = SHR (b100, 2); int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400); - /* Compute the desired time in time_t precision. Overflow might + /* Compute the desired time in gtime_t precision. Overflow might occur here. */ - time_t tyear1 = year1; - time_t years = tyear1 - year0; - time_t days = 365 * years + yday1 - yday0 + intervening_leap_days; - time_t hours = 24 * days + hour1 - hour0; - time_t minutes = 60 * hours + min1 - min0; - time_t seconds = 60 * minutes + sec1 - sec0; + gtime_t tyear1 = year1; + gtime_t years = tyear1 - year0; + gtime_t days = 365 * years + yday1 - yday0 + intervening_leap_days; + gtime_t hours = 24 * days + hour1 - hour0; + gtime_t minutes = 60 * hours + min1 - min0; + gtime_t seconds = 60 * minutes + sec1 - sec0; return seconds; } -/* Return a time_t value corresponding to (YEAR-YDAY HOUR:MIN:SEC), +/* Return a gtime_t value corresponding to (YEAR-YDAY HOUR:MIN:SEC), assuming that *T corresponds to *TP and that no clock adjustments occurred between *TP and the desired time. If TP is null, return a value not equal to *T; this avoids false matches. If overflow occurs, yield the minimal or maximal value, except do not yield a value equal to *T. */ -static time_t +static gtime_t guess_time_tm (long int year, long int yday, int hour, int min, int sec, - time_t *t, struct gtm *tp) + gtime_t *t, struct gtm *tp) { if (tp) { - time_t d = ydhms_diff (year, yday, hour, min, sec, + gtime_t d = ydhms_diff (year, yday, hour, min, sec, tp->tm_year, tp->tm_yday, tp->tm_hour, tp->tm_min, tp->tm_sec); - time_t t1 = *t + d; - if ((t1 < *t) == (TYPE_SIGNED (time_t) ? d < 0 : TIME_T_MAX / 2 < d)) + gtime_t t1 = *t + d; + if ((t1 < *t) == (TYPE_SIGNED (gtime_t) ? d < 0 : TIME_T_MAX / 2 < d)) return t1; } @@ -268,22 +267,22 @@ guess_time_tm (long int year, long int yday, int hour, int min, int sec, If *T is out of range for conversion, adjust it so that it is the nearest in-range value and then convert that. */ static struct gtm * -ranged_convert (struct gtm *(*convert) (time_t *, struct gtm *), - time_t *t, struct gtm *tp) +ranged_convert (struct gtm *(*convert) (gtime_t *, struct gtm *), + gtime_t *t, struct gtm *tp) { struct gtm *r = convert (t, tp); if (!r && *t) { - time_t bad = *t; - time_t ok = 0; + gtime_t bad = *t; + gtime_t ok = 0; - /* BAD is a known unconvertible time_t, and OK is a known good one. + /* BAD is a known unconvertible gtime_t, and OK is a known good one. Use binary search to narrow the range between BAD and OK until they differ by 1. */ while (bad != ok + (bad < 0 ? -1 : 1)) { - time_t mid = *t = (bad < 0 + gtime_t mid = *t = (bad < 0 ? bad + ((ok - bad) >> 1) : ok + ((bad - ok) >> 1)); r = convert (t, tp); @@ -305,18 +304,18 @@ ranged_convert (struct gtm *(*convert) (time_t *, struct gtm *), return r; } -/* Convert *TP to a time_t value, inverting +/* Convert *TP to a gtime_t value, inverting the monotonic and mostly-unit-linear conversion function CONVERT. Use *OFFSET to keep track of a guess at the offset of the result, compared to what the result would be for UTC without leap seconds. If *OFFSET's guess is correct, only one CONVERT call is needed. This function is external because it is used also by timegm.c. */ -time_t +gtime_t __mktime_internal (struct gtm *tp, - struct gtm *(*convert) (time_t *, struct gtm *), - time_t *offset) + struct gtm *(*convert) (gtime_t *, struct gtm *), + gtime_t *offset) { - time_t t, gt, t0, t1, t2; + gtime_t t, gt, t0, t1, t2; struct gtm tm; /* The maximum number of probes (calls to CONVERT) should be enough @@ -343,7 +342,7 @@ __mktime_internal (struct gtm *tp, /* The other values need not be in range: the remaining code handles minor overflows correctly, - assuming int and time_t arithmetic wraps around. + assuming int and gtime_t arithmetic wraps around. Major overflows are caught at the end. */ /* Calculate day of year from year, month, and day of month. @@ -354,7 +353,7 @@ __mktime_internal (struct gtm *tp, long int lmday = mday; long int yday = mon_yday + lmday; - time_t guessed_offset = *offset; + gtime_t guessed_offset = *offset; int sec_requested = sec; @@ -378,7 +377,7 @@ __mktime_internal (struct gtm *tp, if (TIME_T_MAX / INT_MAX / 366 / 24 / 60 / 60 < 3) { - /* time_t isn't large enough to rule out overflows, so check + /* gtime_t isn't large enough to rule out overflows, so check for major overflows. A gross check suffices, since if t0 has overflowed, it is off by a multiple of TIME_T_MAX - TIME_T_MIN + 1. So ignore any component of the difference @@ -414,16 +413,16 @@ __mktime_internal (struct gtm *tp, gives a positive value of 715827882. Setting a variable first then doing math on it seems to work. (ghazi@caip.rutgers.edu) */ - time_t time_t_max = TIME_T_MAX; - time_t time_t_min = TIME_T_MIN; - time_t overflow_threshold = + gtime_t time_t_max = TIME_T_MAX; + gtime_t time_t_min = TIME_T_MIN; + gtime_t overflow_threshold = (time_t_max / 3 - time_t_min / 3) >> ALOG2_SECONDS_PER_BIENNIUM; if (overflow_threshold < abs_diff) { /* Overflow occurred. Try repairing it; this might work if the time zone offset is enough to undo the overflow. */ - time_t repaired_t0 = -1 - t0; + gtime_t repaired_t0 = -1 - t0; approx_biennia = SHR (repaired_t0, ALOG2_SECONDS_PER_BIENNIUM); diff = approx_biennia - approx_requested_biennia; abs_diff = diff < 0 ? - diff : diff; @@ -467,18 +466,18 @@ __mktime_internal (struct gtm *tp, return t; } -/* Convert *TP to a time_t value. */ -time_t +/* Convert *TP to a gtime_t value. */ +gtime_t mktime (struct gtm *tp) { // no time zone stuff. Just do the math ;) - static time_t localtime_offset; + static gtime_t localtime_offset; return __mktime_internal (tp, __localtime_r, &localtime_offset); } -/* Fill a (struct tm) TP* from a given time_t time stamp */ -time_t -filltm(time_t *t, struct gtm *tp) +/* Fill a (struct tm) TP* from a given gtime_t time stamp */ +gtime_t +filltm(gtime_t *t, struct gtm *tp) { return __offtime(t, 0, tp); } diff --git a/src/gtime.h b/src/gtime.h index 4c9313db9..f8021db58 100644 --- a/src/gtime.h +++ b/src/gtime.h @@ -23,16 +23,12 @@ #define g9x_time_h #include +#include +#undef CHAR_BIT #define CHAR_BIT 8 -#define INT_MAX 32767 -#define INT_MIN -32767 -#define LONG_MAX 0x7FFFFFFFL -#define LONG_MIN ((long) 0x80000000L) -#define UINT_MAX 0xFFFFU/0xFFFFFFFFUL -#define ULONG_MAX 0xFFFFFFFFUL -typedef long int time_t; +typedef long int gtime_t; struct gtm { @@ -48,8 +44,8 @@ struct gtm extern const unsigned short int __mon_yday[2][13]; -extern time_t mktime(struct gtm *tp); -extern time_t filltm(time_t *t, struct gtm *tp); +extern gtime_t mktime(struct gtm *tp); +extern gtime_t filltm(gtime_t *t, struct gtm *tp); #endif diff --git a/src/lcd.cpp b/src/lcd.cpp index e5eceda9e..d1e864432 100644 --- a/src/lcd.cpp +++ b/src/lcd.cpp @@ -387,7 +387,7 @@ void putsTime(uint8_t x,uint8_t y,int16_t tme,uint8_t att,uint8_t att2) void putsVolts(uint8_t x, uint8_t y, uint16_t volts, uint8_t att) { - lcd_outdezAtt(x, y, (int16_t)volts, att|PREC1|UNSIGN); + lcd_outdezAtt(x, y, (int16_t)volts, att | ((att&PREC2)==PREC2 ? 0 : PREC1)); if (~att & NO_UNIT) lcd_putcAtt(lcd_lastPos, y, 'v', att); } @@ -492,7 +492,17 @@ void putsTmrMode(uint8_t x, uint8_t y, int8_t mode, uint8_t att) #ifdef FRSKY // TODO move this into frsky.cpp -void putsTelemetry(uint8_t x, uint8_t y, uint8_t val, uint8_t unit, uint8_t att) +void putsTelemetryChannel(uint8_t x, uint8_t y, uint8_t channel, uint8_t val, uint8_t att) +{ + int16_t converted_value = ((int16_t)val+g_model.frsky.channels[channel].offset)*g_model.frsky.channels[channel].ratio / 255; + if (g_model.frsky.channels[channel].type == 0 && converted_value < 100) { + att |= PREC2; + converted_value = ((int16_t)val+g_model.frsky.channels[channel].offset)*g_model.frsky.channels[channel].ratio*10 / 255; + } + putsTelemetryValue(x, y, converted_value, g_model.frsky.channels[channel].type, att); +} + +void putsTelemetryValue(uint8_t x, uint8_t y, int16_t val, uint8_t unit, uint8_t att) { if (unit == 0/*v*/) { putsVolts(x, y, val, att); diff --git a/src/lcd.h b/src/lcd.h index 213fd8f44..d022687e1 100644 --- a/src/lcd.h +++ b/src/lcd.h @@ -99,7 +99,8 @@ extern void putsTime(uint8_t x,uint8_t y, int16_t tme, uint8_t att, uint8_t att2 #ifdef FRSKY // TODO move this into frsky.h -extern void putsTelemetry(uint8_t x, uint8_t y, uint8_t val, uint8_t unit, uint8_t att); +void putsTelemetryChannel(uint8_t x, uint8_t y, uint8_t channel, uint8_t val, uint8_t att); +void putsTelemetryValue(uint8_t x, uint8_t y, int16_t val, uint8_t unit, uint8_t att); #endif extern void lcd_plot(unsigned char x, unsigned char y, uint8_t att=0); diff --git a/src/logs.cpp b/src/logs.cpp new file mode 100644 index 000000000..f9907157c --- /dev/null +++ b/src/logs.cpp @@ -0,0 +1,158 @@ +/* + * Authors (alphabetical order) + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * + * Original contributors + * - Philip Moss Adapted first frsky functions from jeti.cpp code by + * - Karl Szmutny + + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * 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. + * + */ + +#include "gruvin9x.h" +#include "ff.h" + +// "/G9XLOGS/M00_000.TXT\0" max required length = 21 +char g_logFilename[22]; + +// These global so we can close any open file from anywhere +FATFS FATFS_Obj; +FIL g_oLogFile; +int8_t g_logState = 0; // 0=closed, >0=opened, <0=error + +void startLogs() +{ + // Determine and set log file filename + FRESULT result; + + // close any file left open. E.G. Changing models with log switch still on. + if (g_oLogFile.fs) f_close(&g_oLogFile); + g_logState = 0; + + strcpy_P(g_logFilename, PSTR("/G9XLOGS/M00_000.TXT")); + + uint8_t num = g_eeGeneral.currModel + 1; + char *n = &g_logFilename[11]; + *n = (char)((num % 10) + '0'); + *(--n) = (char)((num / 10) + '0'); + + result = f_mount(0, &FATFS_Obj); + if (result!=FR_OK) + { + strcpy_P(g_logFilename, PSTR("FILE SYSTEM ERROR")); + g_logState = -result; + return; + } + + // Skip over any existing log files ... _000, _001, etc. (or find first gap in numbering) + while (1) + { + result = f_open(&g_oLogFile, g_logFilename, FA_OPEN_EXISTING | FA_READ); + if (result == FR_OK) + { + f_close(&g_oLogFile); + + // bump log file counter (file extension) + n = &g_logFilename[15]; + if (++*n > '9') + { + *n='0'; + n--; + if (++*n > '9') + { + *n='0'; + n--; + if (++*n > '9') + { + *n='0'; + break; // Wow. We looped back around past 999 to 000! abort loop + } + } + } + } + else if (result == FR_NO_FILE /*TODO check this code*/) + { + break; + } + else if (result == FR_NO_PATH) + { + if (f_mkdir("/G9XLOGS") != FR_OK) + { + strcpy_P(g_logFilename, PSTR("Check /G9XLOGS folder")); + g_logState = -result; + return; + } + } + else + { + g_logState = -result; + if (result == FR_NOT_READY) + strcpy_P(g_logFilename, PSTR("DATA CARD NOT PRESENT")); + else + strcpy_P(g_logFilename, PSTR("DATA CARD ERROR")); + return; + } + } + + // g_logFilename should now be set appropriately. +} + +// TODO FORCEINLINE this function +void doLogs() +{ + FRESULT result; + + if (isFunctionActive(FUNC_LOGS)) + { + if (g_logState==0) + { + result = f_mount(0, &FATFS_Obj); + if (result != FR_OK) + { + g_logState = -result; + beepAgain = result - 1; + beepKey(); + } + else + { + // create new log file using filename set up in startLogs() + result = f_open(&g_oLogFile, g_logFilename, FA_OPEN_ALWAYS | FA_WRITE); + if (result != FR_OK) + { + g_logState = -result; + beepAgain = result - 1; + beepKey(); + } + else + { + f_lseek(&g_oLogFile, g_oLogFile.fsize); // append + g_logState = 1; + beepWarn2(); + } + } + } + + if (g_logState>0) + { + // TODO here we write logs + } + } + else if (g_logState > 0) + { + f_close(&g_oLogFile); + beepWarn2(); + g_logState = 0; + } +} + + + diff --git a/src/main_views.cpp b/src/main_views.cpp index 352e016dc..05d397ec1 100644 --- a/src/main_views.cpp +++ b/src/main_views.cpp @@ -81,20 +81,20 @@ void doMainScreenGrphics() } } +void displayAltitudeLine(uint8_t x, uint8_t y, uint8_t flags) +{ + lcd_puts_P(x, y, PSTR("Alt:")); + uint16_t value = frskyHubData.baroAltitude + baroAltitudeOffset; + lcd_outdezAtt(lcd_lastPos, (flags & DBLSIZE) ? y-FH : y, value, flags|LEFT|UNSIGN); + lcd_putc(lcd_lastPos, y, 'm') ; +} + void menuMainView(uint8_t event) { - static uint8_t switchView = 255; static bool instantTrimSwLock; static bool trim2OfsSwLock; - uint8_t view = (switchView == 255 ? g_eeGeneral.view : switchView); - -#ifdef FRSKY - bool telemViewSw = isFunctionActive(FUNC_VIEW_TELEMETRY); - if (switchView == 255 && telemViewSw) { view = switchView = e_telemetry + ALTERNATE_VIEW; } - if (switchView != 255 && !telemViewSw) { view = g_eeGeneral.view; switchView = 255; } -#endif - + uint8_t view = g_eeGeneral.view; uint8_t view_base = view & 0x0f; switch(event) @@ -111,7 +111,6 @@ void menuMainView(uint8_t event) break; case EVT_KEY_BREAK(KEY_RIGHT): case EVT_KEY_BREAK(KEY_LEFT): - if (switchView != 255) break; #if defined(FRSKY) #if defined(FRSKY_HUB) && defined(WS_HOW_HIGH) tabViews[e_telemetry] = (g_model.frsky.usrProto == 0 ? 2 : (g_model.frsky.usrProto == 1 ? 4 : 3)); @@ -134,14 +133,12 @@ void menuMainView(uint8_t event) killEvents(event); break; case EVT_KEY_BREAK(KEY_UP): - if (switchView != 255) break; g_eeGeneral.view = view+1; if(g_eeGeneral.view>=MAX_VIEWS) g_eeGeneral.view=0; eeDirty(EE_GENERAL); beepKey(); break; case EVT_KEY_BREAK(KEY_DOWN): - if (switchView != 255) break; if(view>0) g_eeGeneral.view = view - 1; else @@ -165,21 +162,19 @@ void menuMainView(uint8_t event) case EVT_KEY_FIRST(KEY_EXIT): if(s_timerState==TMR_BEEPING) { s_timerState = TMR_STOPPED; - beepKey(); } else if (view == e_timer2) { resetTimer2(); - beepKey(); } #ifdef FRSKY - else if (view == e_telemetry) { + else if (view_base == e_telemetry) { resetTelemetry(); - beepKey(); } #endif else { resetTimer1(); } + beepKey(); break; case EVT_KEY_LONG(KEY_EXIT): resetTimer1(); @@ -348,7 +343,7 @@ void menuMainView(uint8_t event) static bool alarmRaised[2]; if (frskyStreaming) { - uint8_t y0, x0, val, blink; + uint8_t y0, x0, blink; if (!displayCount) { for (int i=0; i<2; i++) { staticTelemetry[i] = frskyTelemetry[i].value; @@ -366,12 +361,9 @@ void menuMainView(uint8_t event) lcd_puts_P(x0, 3*FH, PSTR("A :")); lcd_putc(x0+FW, 3*FH, '1'+i); x0 += 3*FW; - val = ((uint16_t)staticTelemetry[i]+g_model.frsky.channels[i].offset)*g_model.frsky.channels[i].ratio / 255; - putsTelemetry(x0, 2*FH, val, g_model.frsky.channels[i].type, blink|DBLSIZE|LEFT); - val = ((int16_t)frskyTelemetry[i].min+g_model.frsky.channels[i].offset)*g_model.frsky.channels[i].ratio / 255; - putsTelemetry(x0+FW, 4*FH, val, g_model.frsky.channels[i].type, 0); - val = ((int16_t)frskyTelemetry[i].max+g_model.frsky.channels[i].offset)*g_model.frsky.channels[i].ratio / 255; - putsTelemetry(x0+3*FW, 4*FH, val, g_model.frsky.channels[i].type, LEFT); + putsTelemetryChannel(x0, 2*FH, i, staticTelemetry[i], blink|DBLSIZE|LEFT); + putsTelemetryChannel(x0+FW, 4*FH, i, frskyTelemetry[i].min, 0); + putsTelemetryChannel(x0+3*FW, 4*FH, i, frskyTelemetry[i].max, LEFT); x0 = 11*FW-2; } } @@ -423,10 +415,7 @@ void menuMainView(uint8_t event) } #ifdef WS_HOW_HIGH else if (g_model.frsky.usrProto == PROTO_WS_HOW_HIGH && view == e_telemetry+2*ALTERNATE_VIEW) { - lcd_puts_P(0, 4*FH, PSTR("Alt:")); - uint16_t value = frskyHubData.baroAltitude; - lcd_outdezAtt(4*FW, 3*FH, (value * 32) / 105, DBLSIZE|LEFT); - lcd_putc(lcd_lastPos, 4*FH, 'm') ; + displayAltitudeLine(0, 4*FH, DBLSIZE); } #endif #ifdef FRSKY_HUB @@ -514,13 +503,10 @@ void menuMainView(uint8_t event) lcd_puts_P(0, y, PSTR("Volts:")); lcd_outdezNAtt(lcd_lastPos, y, frskyHubData.volts, LEFT); lcd_putc(lcd_lastPos, y, 'V'); - y = 2*FH; - // Altitude (barometric) - lcd_puts_P(12*FW, y, PSTR("Alt:")); - lcd_outdezNAtt(lcd_lastPos, y, frskyHubData.baroAltitude, LEFT|UNSIGN); - lcd_putc(lcd_lastPos, y, 'm'); + // Altitude (barometric) + displayAltitudeLine(12*FW, y, 0); y += 2*FH; // Acceleromter @@ -548,8 +534,7 @@ void menuMainView(uint8_t event) blink = (alarmRaised[i] ? INVERS+BLINK : 0)|LEFT; lcd_puts_P(x0, y0, PSTR("A :")); lcd_putc(x0+FW, y0, '1'+i); - val = ((int16_t)staticTelemetry[i]+g_model.frsky.channels[i].offset)*g_model.frsky.channels[i].ratio / 255; - putsTelemetry(x0+3*FW, y0, val, g_model.frsky.channels[i].type, blink); + putsTelemetryChannel(x0+3*FW, y0, i, staticTelemetry[i], blink); x0 = 13*FW-3; } } diff --git a/src/model_menus.cpp b/src/model_menus.cpp index e29af2cdb..3e2bc8a15 100644 --- a/src/model_menus.cpp +++ b/src/model_menus.cpp @@ -1585,21 +1585,29 @@ void menuProcCustomSwitches(uint8_t event) lcd_putsnAtt( 4*FW - 1, y, PSTR(CSWITCH_STR)+CSW_LEN_FUNC*cs.func,CSW_LEN_FUNC,m_posHorz==0 ? attr : 0); uint8_t cstate = CS_STATE(cs.func); + int8_t v1_min=0, v1_max=NUM_XCHNRAW, v2_min=0, v2_max=NUM_XCHNRAW; if(cstate == CS_VOFS) { - putsChnRaw( 12*FW, y, cs.v1 ,m_posHorz==1 ? attr : 0); + putsChnRaw(12*FW, y, cs.v1, m_posHorz==1 ? attr : 0); #if defined(FRSKY) - if (cs.v1 > NUM_XCHNRAW-NUM_TELEMETRY) - lcd_outdezAtt( 20*FW, y, 125+cs.v2 ,m_posHorz==2 ? attr : 0); + if (cs.v1 > NUM_XCHNRAW-NUM_TELEMETRY) { + putsTelemetryChannel(20*FW, y, cs.v1+NUM_TELEMETRY-NUM_XCHNRAW-1, 128+cs.v2, m_posHorz==2 ? attr : 0); + v2_min = -128; v2_max = 127; + } else #endif - lcd_outdezAtt( 20*FW, y, cs.v2 ,m_posHorz==2 ? attr : 0); + { + lcd_outdezAtt( 20*FW, y, cs.v2 ,m_posHorz==2 ? attr : 0); + v2_min = -125; v2_max = 125; + } } else if(cstate == CS_VBOOL) { putsSwitches(13*FW, y, cs.v1 ,m_posHorz==1 ? attr : 0); putsSwitches(17*FW, y, cs.v2 ,m_posHorz==2 ? attr : 0); + v1_min = -MAX_SWITCH; v1_max = MAX_SWITCH; + v2_min = -MAX_SWITCH; v2_max = MAX_SWITCH; } else // cstate == CS_COMP { @@ -1607,46 +1615,23 @@ void menuProcCustomSwitches(uint8_t event) putsChnRaw( 17*FW, y, cs.v2 ,m_posHorz==2 ? attr : 0); } - if((s_editMode>0 || p1valdiff) && attr) + if ((s_editMode>0 || p1valdiff) && attr) { switch (m_posHorz) { case 0: CHECK_INCDEC_MODELVAR( event, cs.func, 0,CS_MAXF); - if(cstate != CS_STATE(cs.func)) - { - cs.v1 = 0; - cs.v2 = 0; + if (cstate != CS_STATE(cs.func)) { + cs.v1 = 0; + cs.v2 = 0; } break; case 1: - switch (cstate) { - case (CS_VOFS): - CHECK_INCDEC_MODELVAR( event, cs.v1, 0,NUM_XCHNRAW); - break; - case (CS_VBOOL): - CHECK_INCDEC_MODELVAR( event, cs.v1, -MAX_SWITCH,MAX_SWITCH); - break; - case (CS_VCOMP): - CHECK_INCDEC_MODELVAR( event, cs.v1, 0,NUM_XCHNRAW); - break; - default: - break; - } + CHECK_INCDEC_MODELVAR(event, cs.v1, v1_min, v1_max); break; case 2: - switch (cstate) { - case (CS_VOFS): - CHECK_INCDEC_MODELVAR( event, cs.v2, -125,125); - break; - case (CS_VBOOL): - CHECK_INCDEC_MODELVAR( event, cs.v2, -MAX_SWITCH,MAX_SWITCH); - break; - case (CS_VCOMP): - CHECK_INCDEC_MODELVAR( event, cs.v2, 0,NUM_XCHNRAW); - break; - default: - break; - } + CHECK_INCDEC_MODELVAR( event, cs.v2, v2_min, v2_max); + break; } + } } } @@ -1677,7 +1662,7 @@ void menuProcFunctionSwitches(uint8_t event) if (sd->swtch) { lcd_putsnAtt(5*FW, y, PSTR(FSWITCH_STR)+FSW_LEN_FUNC*sd->func, FSW_LEN_FUNC, attr); if (active) { - CHECK_INCDEC_MODELVAR( event, sd->func, 0, FUNC_LAST); + CHECK_INCDEC_MODELVAR( event, sd->func, 0, FUNC_MAX-1); } } else if (attr) { @@ -1749,7 +1734,6 @@ void menuProcTelemetry(uint8_t event) blink = (s_editMode>0) ? BLINK : INVERS ; uint8_t subN = 1; uint8_t t; - int16_t val; for (int i=0; i<2; i++) { if(s_pgOfs0 || p1valdiff)) { if (m_posHorz == 0) @@ -1776,8 +1760,7 @@ void menuProcTelemetry(uint8_t event) if(s_pgOfs0 || p1valdiff)) g_model.frsky.channels[i].barMin = checkIncDec(event, g_model.frsky.channels[i].barMin, 0, 255, EE_MODEL); if(sub==subN && m_posHorz==1 && (s_editMode>0 || p1valdiff)) g_model.frsky.channels[i].barMax = checkIncDec(event, g_model.frsky.channels[i].barMax, 0, 255, EE_MODEL); } @@ -1800,8 +1781,7 @@ void menuProcTelemetry(uint8_t event) lcd_putsAtt(4, y, PSTR("Alarm"), 0); lcd_putsnAtt(8*FW, y, PSTR("---YelOrgRed")+3*ALARM_LEVEL(i, j),3,(sub==subN && m_posHorz==0 ? blink:0)); lcd_putsnAtt(12*FW, y, PSTR("<>")+ALARM_GREATER(i, j),1,(sub==subN && m_posHorz==1 ? blink:0)); - uint8_t alarmValue = ((uint16_t)g_model.frsky.channels[i].alarms_value[j] * g_model.frsky.channels[i].ratio) / 255; - putsTelemetry(14*FW, y, alarmValue, g_model.frsky.channels[i].type, (sub==subN && m_posHorz==2 ? blink:0) | LEFT); + putsTelemetryChannel(14*FW, y, i, g_model.frsky.channels[i].alarms_value[j], (sub==subN && m_posHorz==2 ? blink:0) | LEFT); if(sub==subN && (s_editMode>0 || p1valdiff)) { switch (m_posHorz) { diff --git a/src/myeeprom.h b/src/myeeprom.h index 0af43caa5..cbf004f1b 100644 --- a/src/myeeprom.h +++ b/src/myeeprom.h @@ -158,15 +158,20 @@ PACK(typedef struct t_SafetySwData { // Safety Switches data int8_t val; }) SafetySwData; -#define FUNC_TRAINER 1 -#define FUNC_TRAINER_RUD 2 -#define FUNC_TRAINER_ELE 3 -#define FUNC_TRAINER_THR 4 -#define FUNC_TRAINER_AIL 5 -#define FUNC_INSTANT_TRIM 6 -#define FUNC_TRIMS_2_OFS 7 -#define FUNC_VIEW_TELEMETRY 8 -#define FUNC_LAST 8 +enum Functions { + FUNC_NONE, + FUNC_TRAINER, + FUNC_TRAINER_RUD, + FUNC_TRAINER_ELE, + FUNC_TRAINER_THR, + FUNC_TRAINER_AIL, + FUNC_INSTANT_TRIM, + FUNC_TRIMS_2_OFS, +#ifdef LOGS + FUNC_LOGS, +#endif + FUNC_MAX +}; PACK(typedef struct t_FuncSwData { // Function Switches data int8_t swtch; //input @@ -180,8 +185,8 @@ PACK(typedef struct t_FrSkyChannelData { uint8_t alarms_value[2]; // 0.1V steps EG. 6.6 Volts = 66. 25.1V = 251, etc. uint8_t alarms_level:4; uint8_t alarms_greater:2; // 0=LT(<), 1=GT(>) - uint8_t spare:2; - int8_t barMin; // minimum for bar display + uint8_t multiplier:2; // 0=no multiplier, 1=*2 multiplier + uint8_t barMin; // minimum for bar display uint8_t barMax; // ditto for max display (would usually = ratio) }) FrSkyChannelData; diff --git a/src/pers.cpp b/src/pers.cpp index 0413fab2b..5312f3dd5 100644 --- a/src/pers.cpp +++ b/src/pers.cpp @@ -299,6 +299,9 @@ void eeLoadModel(uint8_t id) #ifdef FRSKY resetTelemetry(); FRSKY_setModelAlarms(); +#endif +#ifdef LOGS + startLogs(); #endif } } diff --git a/src/rtc.cpp b/src/rtc.cpp index 479e493b8..91e28daa6 100644 --- a/src/rtc.cpp +++ b/src/rtc.cpp @@ -48,9 +48,9 @@ static void iic_delay (void) { - int n; - - for (n = 4; n; n--) PINB; +#ifndef SIMU + for (int n = 4; n; n--) PINB; +#endif } diff --git a/src/simpgmspace.cpp b/src/simpgmspace.cpp index 2e99a9e28..ad91b811d 100644 --- a/src/simpgmspace.cpp +++ b/src/simpgmspace.cpp @@ -123,6 +123,9 @@ void *main_thread(void *) while (main_thread_running) { perMain(); + + frskyHubData.baroAltitude = 500; + sleep(1/*ms*/); } #ifdef SIMU_EXCEPTIONS diff --git a/src/simu.cpp b/src/simu.cpp index c8261e654..7d187128f 100644 --- a/src/simu.cpp +++ b/src/simu.cpp @@ -296,9 +296,19 @@ void Gruvin9xSim::refreshDiplay() #else static FXuint keys2[]={KEY_F8, KEY_F7, KEY_F4, KEY_F3, KEY_F6, KEY_F5, KEY_F1, KEY_F2 }; #endif +#ifdef PCBV4 + pinj = 0; +#else pind = 0; +#endif for(unsigned i=0; igetKeyState(keys2[i])) pind |= (1<getKeyState(keys2[i])) { +#ifdef PCBV4 + pinj |= (1<