1
0
Fork 0
mirror of https://github.com/opentx/opentx.git synced 2025-07-23 16:25:16 +03:00

Logs and Telemetry decorrelated. Telemetry helpers. Possibility to reset the altitude. Flash optimizations.

This commit is contained in:
bsongis 2012-01-09 18:52:22 +00:00
parent 9e0fd2a3d2
commit a6e6a2dd12
17 changed files with 342 additions and 322 deletions

View file

@ -97,6 +97,10 @@ FRSKY_HUB = YES
# Values = YES, NO # Values = YES, NO
WS_HOW_HIGH = YES WS_HOW_HIGH = YES
# SDCARD Logs
# Values = YES, NO
LOGS = YES
# PXX (FrSky PCM) protocol # PXX (FrSky PCM) protocol
PXX = NO PXX = NO
@ -216,6 +220,7 @@ ifeq ($(NAVIGATION), POTS)
CPPDEFS += -DNAVIGATION_POT1 -DNAVIGATION_POT2 -DNAVIGATION_POT3 CPPDEFS += -DNAVIGATION_POT1 -DNAVIGATION_POT2 -DNAVIGATION_POT3
endif endif
MODS =
ifeq ($(PCB), STD) ifeq ($(PCB), STD)
# STD PCB, so ... # STD PCB, so ...
@ -286,8 +291,13 @@ else
ifeq ($(PCB), V3) ifeq ($(PCB), V3)
CPPDEFS += -DBEEPSPKR CPPDEFS += -DBEEPSPKR
endif endif
ifeq ($(LOGS), YES)
CPPSRC += logs.cpp
CPPDEFS += -DLOGS
MODS += L
endif
ifeq ($(PCB), V4) ifeq ($(PCB), V4)
CPPDEFS += -DPCBV4 CPPDEFS += -DPCBV4
# Temporary hack to get stock beeper working for testing, etc ... make BEEPER=BUZZER_MOD # Temporary hack to get stock beeper working for testing, etc ... make BEEPER=BUZZER_MOD
# TODO should not be needed / tested here in V4 # TODO should not be needed / tested here in V4
ifeq ($(BEEPER), BUZZER_MOD) ifeq ($(BEEPER), BUZZER_MOD)

View file

@ -19,8 +19,6 @@
*/ */
#include "gruvin9x.h" #include "gruvin9x.h"
#include "frsky.h"
#include "ff.h" // TODO
// Enumerate FrSky packet codes // Enumerate FrSky packet codes
#define LINKPKT 0xfe #define LINKPKT 0xfe
@ -57,6 +55,7 @@ struct FrskyAlarm frskyAlarms[4];
#if defined(FRSKY_HUB) || defined(WS_HOW_HIGH) #if defined(FRSKY_HUB) || defined(WS_HOW_HIGH)
FrskyHubData frskyHubData; FrskyHubData frskyHubData;
int16_t baroAltitudeOffset = 0;
#endif #endif
void frskyPushValue(uint8_t *&ptr, uint8_t value) void frskyPushValue(uint8_t *&ptr, uint8_t value)
@ -500,100 +499,12 @@ void FrskyData::set(uint8_t value)
min = 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() void resetTelemetry()
{ {
memset(frskyTelemetry, 0, sizeof(frskyTelemetry)); memset(frskyTelemetry, 0, sizeof(frskyTelemetry));
memset(frskyRSSI, 0, sizeof(frskyRSSI)); memset(frskyRSSI, 0, sizeof(frskyRSSI));
#if defined(FRSKY_HUB) || defined(WS_HOW_HIGH)
#if defined (PCBV3) baroAltitudeOffset = -frskyHubData.baroAltitude;
// 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.
#endif #endif
} }

View file

@ -76,12 +76,18 @@ struct FrskyHubData {
int16_t accelY; // 1/256th gram (-8g ~ +8g) int16_t accelY; // 1/256th gram (-8g ~ +8g)
int16_t accelZ; // 1/256th gram (-8g ~ +8g) int16_t accelZ; // 1/256th gram (-8g ~ +8g)
}; };
extern FrskyHubData frskyHubData;
#elif defined(WS_HOW_HIGH) #elif defined(WS_HOW_HIGH)
struct FrskyHubData { struct FrskyHubData {
uint16_t baroAltitude; // 0..9,999 meters uint16_t baroAltitude; // 0..9,999 meters
}; };
#endif
#if defined(FRSKY_HUB) || defined(WS_HOW_HIGH)
extern FrskyHubData frskyHubData; extern FrskyHubData frskyHubData;
extern int16_t baroAltitudeOffset;
#endif #endif
// Global Fr-Sky telemetry data variables // Global Fr-Sky telemetry data variables

View file

@ -25,7 +25,7 @@
// MM/SD card Disk IO Support // MM/SD card Disk IO Support
#if defined (PCBV3) #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 #endif
/* /*
@ -1194,7 +1194,7 @@ uint16_t active_functions = 0; // current max = 16 functions
void evalFunctions() void evalFunctions()
{ {
assert(sizeof(active_functions)*8 >= FUNC_LAST); assert(sizeof(active_functions)*8 > FUNC_MAX);
for (uint8_t i=0; i<NUM_FSW; i++) { for (uint8_t i=0; i<NUM_FSW; i++) {
FuncSwData *sd = &g_model.funcSw[i]; FuncSwData *sd = &g_model.funcSw[i];
@ -1590,65 +1590,11 @@ void perMain()
if (trimsCheckTimer > 0) if (trimsCheckTimer > 0)
trimsCheckTimer -= 1; trimsCheckTimer -= 1;
#if defined (FRSKY) #if defined (LOGS)
doLogs();
/***** TEST CODE - Fr-Sky SD/MMC card / User Data experiments *****/ #endif
#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(FRSKY) and defined(DISPLAY_USER_DATA)
char userDataRxBuffer[21]; // Temp buffer used to collect fr-sky 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, // retrieve bytes from user data buffer and insert into display string,
@ -1672,14 +1618,6 @@ void perMain()
f_putc(userDataRxBuffer[byt], &g_oLogFile); f_putc(userDataRxBuffer[byt], &g_oLogFile);
} }
////////////////
#endif
/***** END TEST CODE - Fr-Sky User Data experiments *****/
// PCBV3
#endif
// FRSKY
#endif #endif
lcd_clear(); lcd_clear();

View file

@ -304,7 +304,12 @@ enum EnumKeys {
#define CSWITCH_STR "---- v>ofs v<ofs |v|>ofs|v|<ofsAND OR XOR ""v1==v2 ""v1!=v2 ""v1>v2 ""v1<v2 ""v1>=v2 ""v1<=v2 " #define CSWITCH_STR "---- v>ofs v<ofs |v|>ofs|v|<ofsAND OR XOR ""v1==v2 ""v1!=v2 ""v1>v2 ""v1<v2 ""v1>=v2 ""v1<=v2 "
#define CSW_LEN_FUNC 7 #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 FSW_LEN_FUNC 14
#define SWASH_TYPE_STR "--- ""120 ""120X ""140 ""90 " #define SWASH_TYPE_STR "--- ""120 ""120X ""140 ""90 "
@ -553,6 +558,7 @@ extern uint8_t s_eeDirtyMsk;
#define FORCEINLINE inline __attribute__ ((always_inline)) #define FORCEINLINE inline __attribute__ ((always_inline))
#endif #endif
/// liefert Betrag des Arguments /// liefert Betrag des Arguments
template<class t> FORCEINLINE t abs(t a){ return a>0?a:-a; } template<class t> FORCEINLINE t abs(t a){ return a>0?a:-a; }
/// liefert das Minimum der Argumente /// liefert das Minimum der Argumente
@ -608,13 +614,12 @@ extern inline uint16_t get_tmr10ms()
#define TMR_VAROFS 16 #define TMR_VAROFS 16
#define SUB_MODE_V 1
#define SUB_MODE_H 2
#define SUB_MODE_H_DBL 3
void setupPulses(); void setupPulses();
void initTemplates(); #ifdef LOGS
extern void startLogs();
extern void doLogs();
#endif
#include "lcd.h" #include "lcd.h"
extern const char stamp1[]; extern const char stamp1[];
@ -714,7 +719,7 @@ inline void _beepSpkr(uint8_t d, uint8_t f)
#if defined (PCBV3) #if defined (PCBV3)
#include "rtc.h" #include "rtc.h"
extern void disk_timerproc(void); 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 extern uint8_t g_ms100; // defined in drivers.cpp
#endif #endif

View file

@ -73,17 +73,17 @@
: ~ (~ (t) 0 << (sizeof (t) * CHAR_BIT - 1)))) : ~ (~ (t) 0 << (sizeof (t) * CHAR_BIT - 1))))
#ifndef TIME_T_MIN #ifndef TIME_T_MIN
# define TIME_T_MIN TYPE_MINIMUM (time_t) # define TIME_T_MIN TYPE_MINIMUM (gtime_t)
#endif #endif
#ifndef TIME_T_MAX #ifndef TIME_T_MAX
# define TIME_T_MAX TYPE_MAXIMUM (time_t) # define TIME_T_MAX TYPE_MAXIMUM (gtime_t)
#endif #endif
#define TIME_T_MIDPOINT (SHR (TIME_T_MIN + TIME_T_MAX, 1) + 1) #define TIME_T_MIDPOINT (SHR (TIME_T_MIN + TIME_T_MAX, 1) + 1)
/* Verify a requirement at compile-time (unlike assert, which is runtime). */ /* Verify a requirement at compile-time (unlike assert, which is runtime). */
#define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; } #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)); verify (twos_complement_arithmetic, TYPE_TWOS_COMPLEMENT (int));
/* The code also assumes that signed integer overflow silently wraps /* The code also assumes that signed integer overflow silently wraps
around, but this assumption can't be stated without causing a 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_HOUR 3600ul
#define SECS_PER_DAY 86400ul #define SECS_PER_DAY 86400ul
#define EOVERFLOW 0
/* Return 1 if YEAR + TM_YEAR_BASE is a leap year. */ /* Return 1 if YEAR + TM_YEAR_BASE is a leap year. */
static inline int static inline int
@ -123,7 +122,7 @@ const unsigned short int __mon_yday[2][13] =
Return nonzero if successful. */ Return nonzero if successful. */
int int
__offtime ( __offtime (
time_t *t, gtime_t *t,
long int offset, long int offset,
struct gtm *tp) struct gtm *tp)
{ {
@ -138,7 +137,7 @@ __offtime (
rem += SECS_PER_DAY; rem += SECS_PER_DAY;
--days; --days;
} }
while (rem >= SECS_PER_DAY) while (rem >= (long int)SECS_PER_DAY)
{ {
rem -= SECS_PER_DAY; rem -= SECS_PER_DAY;
++days; ++days;
@ -185,9 +184,9 @@ __offtime (
} }
/* time_r function implementations */ /* 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 * struct gtm *
__localtime_r (time_t * t, struct gtm * tp) __localtime_r (gtime_t * t, struct gtm * tp)
{ {
__offtime(t, 0, tp); __offtime(t, 0, tp);
return 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 The result may overflow. It is the caller's responsibility to
detect overflow. */ detect overflow. */
static inline time_t static inline gtime_t
ydhms_diff (long int year1, long int yday1, int hour1, int min1, int sec1, ydhms_diff (long int year1, long int yday1, int hour1, int min1, int sec1,
int year0, int yday0, int hour0, int min0, int sec0) 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 b400 = SHR (b100, 2);
int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400); 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. */ occur here. */
time_t tyear1 = year1; gtime_t tyear1 = year1;
time_t years = tyear1 - year0; gtime_t years = tyear1 - year0;
time_t days = 365 * years + yday1 - yday0 + intervening_leap_days; gtime_t days = 365 * years + yday1 - yday0 + intervening_leap_days;
time_t hours = 24 * days + hour1 - hour0; gtime_t hours = 24 * days + hour1 - hour0;
time_t minutes = 60 * hours + min1 - min0; gtime_t minutes = 60 * hours + min1 - min0;
time_t seconds = 60 * minutes + sec1 - sec0; gtime_t seconds = 60 * minutes + sec1 - sec0;
return seconds; 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 assuming that *T corresponds to *TP and that no clock adjustments
occurred between *TP and the desired time. occurred between *TP and the desired time.
If TP is null, return a value not equal to *T; this avoids false matches. 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 If overflow occurs, yield the minimal or maximal value, except do not
yield a value equal to *T. */ 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, 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) 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_year, tp->tm_yday,
tp->tm_hour, tp->tm_min, tp->tm_sec); tp->tm_hour, tp->tm_min, tp->tm_sec);
time_t t1 = *t + d; gtime_t t1 = *t + d;
if ((t1 < *t) == (TYPE_SIGNED (time_t) ? d < 0 : TIME_T_MAX / 2 < d)) if ((t1 < *t) == (TYPE_SIGNED (gtime_t) ? d < 0 : TIME_T_MAX / 2 < d))
return t1; 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 If *T is out of range for conversion, adjust it so that
it is the nearest in-range value and then convert that. */ it is the nearest in-range value and then convert that. */
static struct gtm * static struct gtm *
ranged_convert (struct gtm *(*convert) (time_t *, struct gtm *), ranged_convert (struct gtm *(*convert) (gtime_t *, struct gtm *),
time_t *t, struct gtm *tp) gtime_t *t, struct gtm *tp)
{ {
struct gtm *r = convert (t, tp); struct gtm *r = convert (t, tp);
if (!r && *t) if (!r && *t)
{ {
time_t bad = *t; gtime_t bad = *t;
time_t ok = 0; 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 Use binary search to narrow the range between BAD and OK until
they differ by 1. */ they differ by 1. */
while (bad != ok + (bad < 0 ? -1 : 1)) while (bad != ok + (bad < 0 ? -1 : 1))
{ {
time_t mid = *t = (bad < 0 gtime_t mid = *t = (bad < 0
? bad + ((ok - bad) >> 1) ? bad + ((ok - bad) >> 1)
: ok + ((bad - ok) >> 1)); : ok + ((bad - ok) >> 1));
r = convert (t, tp); r = convert (t, tp);
@ -305,18 +304,18 @@ ranged_convert (struct gtm *(*convert) (time_t *, struct gtm *),
return r; 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. the monotonic and mostly-unit-linear conversion function CONVERT.
Use *OFFSET to keep track of a guess at the offset of the result, 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. compared to what the result would be for UTC without leap seconds.
If *OFFSET's guess is correct, only one CONVERT call is needed. If *OFFSET's guess is correct, only one CONVERT call is needed.
This function is external because it is used also by timegm.c. */ This function is external because it is used also by timegm.c. */
time_t gtime_t
__mktime_internal (struct gtm *tp, __mktime_internal (struct gtm *tp,
struct gtm *(*convert) (time_t *, struct gtm *), struct gtm *(*convert) (gtime_t *, struct gtm *),
time_t *offset) gtime_t *offset)
{ {
time_t t, gt, t0, t1, t2; gtime_t t, gt, t0, t1, t2;
struct gtm tm; struct gtm tm;
/* The maximum number of probes (calls to CONVERT) should be enough /* 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 other values need not be in range:
the remaining code handles minor overflows correctly, 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. */ Major overflows are caught at the end. */
/* Calculate day of year from year, month, and day of month. /* 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 lmday = mday;
long int yday = mon_yday + lmday; long int yday = mon_yday + lmday;
time_t guessed_offset = *offset; gtime_t guessed_offset = *offset;
int sec_requested = sec; int sec_requested = sec;
@ -378,7 +377,7 @@ __mktime_internal (struct gtm *tp,
if (TIME_T_MAX / INT_MAX / 366 / 24 / 60 / 60 < 3) 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 for major overflows. A gross check suffices, since if t0
has overflowed, it is off by a multiple of TIME_T_MAX - has overflowed, it is off by a multiple of TIME_T_MAX -
TIME_T_MIN + 1. So ignore any component of the difference 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 gives a positive value of 715827882. Setting a variable
first then doing math on it seems to work. first then doing math on it seems to work.
(ghazi@caip.rutgers.edu) */ (ghazi@caip.rutgers.edu) */
time_t time_t_max = TIME_T_MAX; gtime_t time_t_max = TIME_T_MAX;
time_t time_t_min = TIME_T_MIN; gtime_t time_t_min = TIME_T_MIN;
time_t overflow_threshold = gtime_t overflow_threshold =
(time_t_max / 3 - time_t_min / 3) >> ALOG2_SECONDS_PER_BIENNIUM; (time_t_max / 3 - time_t_min / 3) >> ALOG2_SECONDS_PER_BIENNIUM;
if (overflow_threshold < abs_diff) if (overflow_threshold < abs_diff)
{ {
/* Overflow occurred. Try repairing it; this might work if /* Overflow occurred. Try repairing it; this might work if
the time zone offset is enough to undo the overflow. */ 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); approx_biennia = SHR (repaired_t0, ALOG2_SECONDS_PER_BIENNIUM);
diff = approx_biennia - approx_requested_biennia; diff = approx_biennia - approx_requested_biennia;
abs_diff = diff < 0 ? - diff : diff; abs_diff = diff < 0 ? - diff : diff;
@ -467,18 +466,18 @@ __mktime_internal (struct gtm *tp,
return t; return t;
} }
/* Convert *TP to a time_t value. */ /* Convert *TP to a gtime_t value. */
time_t gtime_t
mktime (struct gtm *tp) mktime (struct gtm *tp)
{ {
// no time zone stuff. Just do the math ;) // 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); return __mktime_internal (tp, __localtime_r, &localtime_offset);
} }
/* Fill a (struct tm) TP* from a given time_t time stamp */ /* Fill a (struct tm) TP* from a given gtime_t time stamp */
time_t gtime_t
filltm(time_t *t, struct gtm *tp) filltm(gtime_t *t, struct gtm *tp)
{ {
return __offtime(t, 0, tp); return __offtime(t, 0, tp);
} }

View file

@ -23,16 +23,12 @@
#define g9x_time_h #define g9x_time_h
#include <inttypes.h> #include <inttypes.h>
#include <limits.h>
#undef CHAR_BIT
#define CHAR_BIT 8 #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 struct gtm
{ {
@ -48,8 +44,8 @@ struct gtm
extern const unsigned short int __mon_yday[2][13]; extern const unsigned short int __mon_yday[2][13];
extern time_t mktime(struct gtm *tp); extern gtime_t mktime(struct gtm *tp);
extern time_t filltm(time_t *t, struct gtm *tp); extern gtime_t filltm(gtime_t *t, struct gtm *tp);
#endif #endif

View file

@ -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) 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); 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 #ifdef FRSKY
// TODO move this into frsky.cpp // 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*/) { if (unit == 0/*v*/) {
putsVolts(x, y, val, att); putsVolts(x, y, val, att);

View file

@ -99,7 +99,8 @@ extern void putsTime(uint8_t x,uint8_t y, int16_t tme, uint8_t att, uint8_t att2
#ifdef FRSKY #ifdef FRSKY
// TODO move this into frsky.h // 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 #endif
extern void lcd_plot(unsigned char x, unsigned char y, uint8_t att=0); extern void lcd_plot(unsigned char x, unsigned char y, uint8_t att=0);

158
src/logs.cpp Normal file
View file

@ -0,0 +1,158 @@
/*
* Authors (alphabetical order)
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
*
* Original contributors
* - Philip Moss Adapted first frsky functions from jeti.cpp code by
* - Karl Szmutny <shadow@privy.de>
* 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;
}
}

View file

@ -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) void menuMainView(uint8_t event)
{ {
static uint8_t switchView = 255;
static bool instantTrimSwLock; static bool instantTrimSwLock;
static bool trim2OfsSwLock; static bool trim2OfsSwLock;
uint8_t view = (switchView == 255 ? g_eeGeneral.view : switchView); uint8_t view = g_eeGeneral.view;
#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_base = view & 0x0f; uint8_t view_base = view & 0x0f;
switch(event) switch(event)
@ -111,7 +111,6 @@ void menuMainView(uint8_t event)
break; break;
case EVT_KEY_BREAK(KEY_RIGHT): case EVT_KEY_BREAK(KEY_RIGHT):
case EVT_KEY_BREAK(KEY_LEFT): case EVT_KEY_BREAK(KEY_LEFT):
if (switchView != 255) break;
#if defined(FRSKY) #if defined(FRSKY)
#if defined(FRSKY_HUB) && defined(WS_HOW_HIGH) #if defined(FRSKY_HUB) && defined(WS_HOW_HIGH)
tabViews[e_telemetry] = (g_model.frsky.usrProto == 0 ? 2 : (g_model.frsky.usrProto == 1 ? 4 : 3)); 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); killEvents(event);
break; break;
case EVT_KEY_BREAK(KEY_UP): case EVT_KEY_BREAK(KEY_UP):
if (switchView != 255) break;
g_eeGeneral.view = view+1; g_eeGeneral.view = view+1;
if(g_eeGeneral.view>=MAX_VIEWS) g_eeGeneral.view=0; if(g_eeGeneral.view>=MAX_VIEWS) g_eeGeneral.view=0;
eeDirty(EE_GENERAL); eeDirty(EE_GENERAL);
beepKey(); beepKey();
break; break;
case EVT_KEY_BREAK(KEY_DOWN): case EVT_KEY_BREAK(KEY_DOWN):
if (switchView != 255) break;
if(view>0) if(view>0)
g_eeGeneral.view = view - 1; g_eeGeneral.view = view - 1;
else else
@ -165,21 +162,19 @@ void menuMainView(uint8_t event)
case EVT_KEY_FIRST(KEY_EXIT): case EVT_KEY_FIRST(KEY_EXIT):
if(s_timerState==TMR_BEEPING) { if(s_timerState==TMR_BEEPING) {
s_timerState = TMR_STOPPED; s_timerState = TMR_STOPPED;
beepKey();
} }
else if (view == e_timer2) { else if (view == e_timer2) {
resetTimer2(); resetTimer2();
beepKey();
} }
#ifdef FRSKY #ifdef FRSKY
else if (view == e_telemetry) { else if (view_base == e_telemetry) {
resetTelemetry(); resetTelemetry();
beepKey();
} }
#endif #endif
else { else {
resetTimer1(); resetTimer1();
} }
beepKey();
break; break;
case EVT_KEY_LONG(KEY_EXIT): case EVT_KEY_LONG(KEY_EXIT):
resetTimer1(); resetTimer1();
@ -348,7 +343,7 @@ void menuMainView(uint8_t event)
static bool alarmRaised[2]; static bool alarmRaised[2];
if (frskyStreaming) { if (frskyStreaming) {
uint8_t y0, x0, val, blink; uint8_t y0, x0, blink;
if (!displayCount) { if (!displayCount) {
for (int i=0; i<2; i++) { for (int i=0; i<2; i++) {
staticTelemetry[i] = frskyTelemetry[i].value; staticTelemetry[i] = frskyTelemetry[i].value;
@ -366,12 +361,9 @@ void menuMainView(uint8_t event)
lcd_puts_P(x0, 3*FH, PSTR("A :")); lcd_puts_P(x0, 3*FH, PSTR("A :"));
lcd_putc(x0+FW, 3*FH, '1'+i); lcd_putc(x0+FW, 3*FH, '1'+i);
x0 += 3*FW; x0 += 3*FW;
val = ((uint16_t)staticTelemetry[i]+g_model.frsky.channels[i].offset)*g_model.frsky.channels[i].ratio / 255; putsTelemetryChannel(x0, 2*FH, i, staticTelemetry[i], blink|DBLSIZE|LEFT);
putsTelemetry(x0, 2*FH, val, g_model.frsky.channels[i].type, blink|DBLSIZE|LEFT); putsTelemetryChannel(x0+FW, 4*FH, i, frskyTelemetry[i].min, 0);
val = ((int16_t)frskyTelemetry[i].min+g_model.frsky.channels[i].offset)*g_model.frsky.channels[i].ratio / 255; putsTelemetryChannel(x0+3*FW, 4*FH, i, frskyTelemetry[i].max, LEFT);
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);
x0 = 11*FW-2; x0 = 11*FW-2;
} }
} }
@ -423,10 +415,7 @@ void menuMainView(uint8_t event)
} }
#ifdef WS_HOW_HIGH #ifdef WS_HOW_HIGH
else if (g_model.frsky.usrProto == PROTO_WS_HOW_HIGH && view == e_telemetry+2*ALTERNATE_VIEW) { else if (g_model.frsky.usrProto == PROTO_WS_HOW_HIGH && view == e_telemetry+2*ALTERNATE_VIEW) {
lcd_puts_P(0, 4*FH, PSTR("Alt:")); displayAltitudeLine(0, 4*FH, DBLSIZE);
uint16_t value = frskyHubData.baroAltitude;
lcd_outdezAtt(4*FW, 3*FH, (value * 32) / 105, DBLSIZE|LEFT);
lcd_putc(lcd_lastPos, 4*FH, 'm') ;
} }
#endif #endif
#ifdef FRSKY_HUB #ifdef FRSKY_HUB
@ -514,13 +503,10 @@ void menuMainView(uint8_t event)
lcd_puts_P(0, y, PSTR("Volts:")); lcd_puts_P(0, y, PSTR("Volts:"));
lcd_outdezNAtt(lcd_lastPos, y, frskyHubData.volts, LEFT); lcd_outdezNAtt(lcd_lastPos, y, frskyHubData.volts, LEFT);
lcd_putc(lcd_lastPos, y, 'V'); lcd_putc(lcd_lastPos, y, 'V');
y = 2*FH; 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; y += 2*FH;
// Acceleromter // Acceleromter
@ -548,8 +534,7 @@ void menuMainView(uint8_t event)
blink = (alarmRaised[i] ? INVERS+BLINK : 0)|LEFT; blink = (alarmRaised[i] ? INVERS+BLINK : 0)|LEFT;
lcd_puts_P(x0, y0, PSTR("A :")); lcd_puts_P(x0, y0, PSTR("A :"));
lcd_putc(x0+FW, y0, '1'+i); 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; putsTelemetryChannel(x0+3*FW, y0, i, staticTelemetry[i], blink);
putsTelemetry(x0+3*FW, y0, val, g_model.frsky.channels[i].type, blink);
x0 = 13*FW-3; x0 = 13*FW-3;
} }
} }

View file

@ -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); 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); 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) 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 defined(FRSKY)
if (cs.v1 > NUM_XCHNRAW-NUM_TELEMETRY) if (cs.v1 > NUM_XCHNRAW-NUM_TELEMETRY) {
lcd_outdezAtt( 20*FW, y, 125+cs.v2 ,m_posHorz==2 ? attr : 0); 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 else
#endif #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) else if(cstate == CS_VBOOL)
{ {
putsSwitches(13*FW, y, cs.v1 ,m_posHorz==1 ? attr : 0); putsSwitches(13*FW, y, cs.v1 ,m_posHorz==1 ? attr : 0);
putsSwitches(17*FW, y, cs.v2 ,m_posHorz==2 ? 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 else // cstate == CS_COMP
{ {
@ -1607,46 +1615,23 @@ void menuProcCustomSwitches(uint8_t event)
putsChnRaw( 17*FW, y, cs.v2 ,m_posHorz==2 ? attr : 0); 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) { switch (m_posHorz) {
case 0: case 0:
CHECK_INCDEC_MODELVAR( event, cs.func, 0,CS_MAXF); CHECK_INCDEC_MODELVAR( event, cs.func, 0,CS_MAXF);
if(cstate != CS_STATE(cs.func)) if (cstate != CS_STATE(cs.func)) {
{ cs.v1 = 0;
cs.v1 = 0; cs.v2 = 0;
cs.v2 = 0;
} }
break; break;
case 1: case 1:
switch (cstate) { CHECK_INCDEC_MODELVAR(event, cs.v1, v1_min, v1_max);
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;
}
break; break;
case 2: case 2:
switch (cstate) { CHECK_INCDEC_MODELVAR( event, cs.v2, v2_min, v2_max);
case (CS_VOFS): break;
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;
}
} }
}
} }
} }
@ -1677,7 +1662,7 @@ void menuProcFunctionSwitches(uint8_t event)
if (sd->swtch) { if (sd->swtch) {
lcd_putsnAtt(5*FW, y, PSTR(FSWITCH_STR)+FSW_LEN_FUNC*sd->func, FSW_LEN_FUNC, attr); lcd_putsnAtt(5*FW, y, PSTR(FSWITCH_STR)+FSW_LEN_FUNC*sd->func, FSW_LEN_FUNC, attr);
if (active) { if (active) {
CHECK_INCDEC_MODELVAR( event, sd->func, 0, FUNC_LAST); CHECK_INCDEC_MODELVAR( event, sd->func, 0, FUNC_MAX-1);
} }
} }
else if (attr) { else if (attr) {
@ -1749,7 +1734,6 @@ void menuProcTelemetry(uint8_t event)
blink = (s_editMode>0) ? BLINK : INVERS ; blink = (s_editMode>0) ? BLINK : INVERS ;
uint8_t subN = 1; uint8_t subN = 1;
uint8_t t; uint8_t t;
int16_t val;
for (int i=0; i<2; i++) { for (int i=0; i<2; i++) {
if(s_pgOfs<subN) { if(s_pgOfs<subN) {
@ -1762,7 +1746,7 @@ void menuProcTelemetry(uint8_t event)
if(s_pgOfs<subN) { if(s_pgOfs<subN) {
y=(subN-s_pgOfs)*FH; y=(subN-s_pgOfs)*FH;
lcd_putsAtt(4, y, PSTR("Max"), 0); lcd_putsAtt(4, y, PSTR("Max"), 0);
putsTelemetry(8*FW, y, g_model.frsky.channels[i].ratio, g_model.frsky.channels[i].type, (sub==subN && m_posHorz==0 ? blink:0)|NO_UNIT|LEFT); putsTelemetryValue(8*FW, y, g_model.frsky.channels[i].ratio, g_model.frsky.channels[i].type, (sub==subN && m_posHorz==0 ? blink:0)|NO_UNIT|LEFT);
lcd_putsnAtt(lcd_lastPos, y, PSTR("v-")+g_model.frsky.channels[i].type, 1, (sub==subN && m_posHorz==1 ? blink:0)); lcd_putsnAtt(lcd_lastPos, y, PSTR("v-")+g_model.frsky.channels[i].type, 1, (sub==subN && m_posHorz==1 ? blink:0));
if (sub==subN && (s_editMode>0 || p1valdiff)) { if (sub==subN && (s_editMode>0 || p1valdiff)) {
if (m_posHorz == 0) if (m_posHorz == 0)
@ -1776,8 +1760,7 @@ void menuProcTelemetry(uint8_t event)
if(s_pgOfs<subN) { if(s_pgOfs<subN) {
y=(subN-s_pgOfs)*FH; y=(subN-s_pgOfs)*FH;
lcd_putsAtt(4, y, PSTR("Calib"), 0); lcd_putsAtt(4, y, PSTR("Calib"), 0);
val = ((int16_t)frskyTelemetry[i].value+g_model.frsky.channels[i].offset)*g_model.frsky.channels[i].ratio / 255; putsTelemetryChannel(8*FW, y, i, frskyTelemetry[i].value, (sub==subN ? blink:0)|LEFT);
putsTelemetry(8*FW, y, val, g_model.frsky.channels[i].type, (sub==subN ? blink:0)|LEFT);
if(sub==subN) CHECK_INCDEC_MODELVAR(event, g_model.frsky.channels[i].offset, -127, 127); if(sub==subN) CHECK_INCDEC_MODELVAR(event, g_model.frsky.channels[i].offset, -127, 127);
} }
subN++; subN++;
@ -1785,10 +1768,8 @@ void menuProcTelemetry(uint8_t event)
if(s_pgOfs<subN) { if(s_pgOfs<subN) {
y=(subN-s_pgOfs)*FH; y=(subN-s_pgOfs)*FH;
lcd_puts_P(4, y, PSTR("Bar")); lcd_puts_P(4, y, PSTR("Bar"));
val = ((int16_t)g_model.frsky.channels[i].barMin+g_model.frsky.channels[i].offset)*g_model.frsky.channels[i].ratio / 255; putsTelemetryChannel(8*FW, y, i, g_model.frsky.channels[i].barMin, (sub==subN && m_posHorz==0 ? blink:0)|LEFT);
putsTelemetry(8*FW, y, val, g_model.frsky.channels[i].type, (sub==subN && m_posHorz==0 ? blink:0)|LEFT); putsTelemetryChannel(13*FW, y, i, g_model.frsky.channels[i].barMax, (sub==subN && m_posHorz==1 ? blink:0)|LEFT);
val = ((int16_t)g_model.frsky.channels[i].barMax+g_model.frsky.channels[i].offset)*g_model.frsky.channels[i].ratio / 255;
putsTelemetry(13*FW, y, val, g_model.frsky.channels[i].type, (sub==subN && m_posHorz==1 ? blink:0)|LEFT);
if(sub==subN && m_posHorz==0 && (s_editMode>0 || p1valdiff)) g_model.frsky.channels[i].barMin = checkIncDec(event, g_model.frsky.channels[i].barMin, 0, 255, EE_MODEL); if(sub==subN && m_posHorz==0 && (s_editMode>0 || 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); 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_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(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)); 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; putsTelemetryChannel(14*FW, y, i, g_model.frsky.channels[i].alarms_value[j], (sub==subN && m_posHorz==2 ? blink:0) | LEFT);
putsTelemetry(14*FW, y, alarmValue, g_model.frsky.channels[i].type, (sub==subN && m_posHorz==2 ? blink:0) | LEFT);
if(sub==subN && (s_editMode>0 || p1valdiff)) { if(sub==subN && (s_editMode>0 || p1valdiff)) {
switch (m_posHorz) { switch (m_posHorz) {

View file

@ -158,15 +158,20 @@ PACK(typedef struct t_SafetySwData { // Safety Switches data
int8_t val; int8_t val;
}) SafetySwData; }) SafetySwData;
#define FUNC_TRAINER 1 enum Functions {
#define FUNC_TRAINER_RUD 2 FUNC_NONE,
#define FUNC_TRAINER_ELE 3 FUNC_TRAINER,
#define FUNC_TRAINER_THR 4 FUNC_TRAINER_RUD,
#define FUNC_TRAINER_AIL 5 FUNC_TRAINER_ELE,
#define FUNC_INSTANT_TRIM 6 FUNC_TRAINER_THR,
#define FUNC_TRIMS_2_OFS 7 FUNC_TRAINER_AIL,
#define FUNC_VIEW_TELEMETRY 8 FUNC_INSTANT_TRIM,
#define FUNC_LAST 8 FUNC_TRIMS_2_OFS,
#ifdef LOGS
FUNC_LOGS,
#endif
FUNC_MAX
};
PACK(typedef struct t_FuncSwData { // Function Switches data PACK(typedef struct t_FuncSwData { // Function Switches data
int8_t swtch; //input 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_value[2]; // 0.1V steps EG. 6.6 Volts = 66. 25.1V = 251, etc.
uint8_t alarms_level:4; uint8_t alarms_level:4;
uint8_t alarms_greater:2; // 0=LT(<), 1=GT(>) uint8_t alarms_greater:2; // 0=LT(<), 1=GT(>)
uint8_t spare:2; uint8_t multiplier:2; // 0=no multiplier, 1=*2 multiplier
int8_t barMin; // minimum for bar display uint8_t barMin; // minimum for bar display
uint8_t barMax; // ditto for max display (would usually = ratio) uint8_t barMax; // ditto for max display (would usually = ratio)
}) FrSkyChannelData; }) FrSkyChannelData;

View file

@ -299,6 +299,9 @@ void eeLoadModel(uint8_t id)
#ifdef FRSKY #ifdef FRSKY
resetTelemetry(); resetTelemetry();
FRSKY_setModelAlarms(); FRSKY_setModelAlarms();
#endif
#ifdef LOGS
startLogs();
#endif #endif
} }
} }

View file

@ -48,9 +48,9 @@
static static
void iic_delay (void) void iic_delay (void)
{ {
int n; #ifndef SIMU
for (int n = 4; n; n--) PINB;
for (n = 4; n; n--) PINB; #endif
} }

View file

@ -123,6 +123,9 @@ void *main_thread(void *)
while (main_thread_running) { while (main_thread_running) {
perMain(); perMain();
frskyHubData.baroAltitude = 500;
sleep(1/*ms*/); sleep(1/*ms*/);
} }
#ifdef SIMU_EXCEPTIONS #ifdef SIMU_EXCEPTIONS

View file

@ -296,9 +296,19 @@ void Gruvin9xSim::refreshDiplay()
#else #else
static FXuint keys2[]={KEY_F8, KEY_F7, KEY_F4, KEY_F3, KEY_F6, KEY_F5, KEY_F1, KEY_F2 }; static FXuint keys2[]={KEY_F8, KEY_F7, KEY_F4, KEY_F3, KEY_F6, KEY_F5, KEY_F1, KEY_F2 };
#endif #endif
#ifdef PCBV4
pinj = 0;
#else
pind = 0; pind = 0;
#endif
for(unsigned i=0; i<DIM(keys2);i++){ for(unsigned i=0; i<DIM(keys2);i++){
if(getApp()->getKeyState(keys2[i])) pind |= (1<<i); if(getApp()->getKeyState(keys2[i])) {
#ifdef PCBV4
pinj |= (1<<i);
#else
pind |= (1<<i);
#endif
}
} }
struct SwitchKey { struct SwitchKey {