mirror of
https://github.com/opentx/opentx.git
synced 2025-07-22 07:45:14 +03:00
Simu for V4. First draft of rotary encoders use in menus
This commit is contained in:
parent
8faf304b14
commit
352b04302a
18 changed files with 904 additions and 178 deletions
35
src/Makefile
35
src/Makefile
|
@ -48,6 +48,19 @@ HELI = NO
|
|||
# Values = YES, NO
|
||||
TEMPLATES = YES
|
||||
|
||||
# Enable navigation with Pots / Rotary encoders
|
||||
# Values = NO
|
||||
# POT1 (only POT1 available for fields modification),
|
||||
# POT2 (menus scroll),
|
||||
# POT3 (cursor down/up),
|
||||
# POTS (POT1, POT2, POT3),
|
||||
# RE1 (Rotary encoder 1, on V3/V4 boards)
|
||||
ifeq ($(PCB), V4)
|
||||
NAVIGATION = RE1
|
||||
else
|
||||
NAVIGATION = POTS
|
||||
endif
|
||||
|
||||
# gruvin: BEEPER. Values = BUZZER, BUZZER_MOD or SPEAKER
|
||||
# (without a mod, BUZZER can make PPM jack output switch from output to input at random)
|
||||
# SPEAKER mode actually works on the stock radio, using the stock beeper. Sort of sound OK(ish).
|
||||
|
@ -122,7 +135,7 @@ endif
|
|||
|
||||
# Disk IO support (PCB V2+ only)
|
||||
ifneq ($(PCB), STD)
|
||||
CPPSRC += time.cpp
|
||||
CPPSRC += gtime.cpp
|
||||
CPPSRC += rtc.cpp
|
||||
CPPSRC += ff.cpp
|
||||
CPPSRC += diskio.cpp
|
||||
|
@ -178,6 +191,21 @@ CPPDEFS = -DF_CPU=$(F_CPU)UL
|
|||
# NOTE: PCB version now overrides all the earlier individual settings
|
||||
# These individual settings work only for PCB=STD
|
||||
|
||||
# If POT1/POTS/RE1 is used for fields modification
|
||||
ifeq ($(NAVIGATION), POT1)
|
||||
CPPDEFS += -DNAVIGATION_POT1
|
||||
endif
|
||||
ifeq ($(NAVIGATION), POT2)
|
||||
CPPDEFS += -DNAVIGATION_POT2
|
||||
endif
|
||||
ifeq ($(NAVIGATION), POT3)
|
||||
CPPDEFS += -DNAVIGATION_POT3
|
||||
endif
|
||||
ifeq ($(NAVIGATION), POTS)
|
||||
CPPDEFS += -DNAVIGATION_POT1 -DNAVIGATION_POT2 -DNAVIGATION_POT3
|
||||
endif
|
||||
|
||||
|
||||
ifeq ($(PCB), STD)
|
||||
# STD PCB, so ...
|
||||
|
||||
|
@ -232,6 +260,11 @@ ifeq ($(PCB), STD)
|
|||
endif
|
||||
|
||||
else
|
||||
|
||||
ifeq ($(NAVIGATION), RE1)
|
||||
CPPDEFS += -DNAVIGATION_RE1
|
||||
endif
|
||||
|
||||
# not PCB=STD, so ...
|
||||
CPPSRC += frsky.cpp
|
||||
CPPDEFS += -DPCBV3 -DFRSKY -DFRSKY_HUB
|
||||
|
|
|
@ -26,11 +26,9 @@
|
|||
/* are platform dependent. */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#include <avr/io.h>
|
||||
#include "gruvin9x.h"
|
||||
#include "diskio.h"
|
||||
|
||||
|
||||
/* Definitions for MMC/SDC command */
|
||||
#define CMD0 (0) /* GO_IDLE_STATE */
|
||||
#define CMD1 (1) /* SEND_OP_COND (MMC) */
|
||||
|
@ -59,8 +57,13 @@
|
|||
|
||||
/* Port Controls (Platform dependent) */
|
||||
// GCC optimisation should result in a single CBI/SBI instructions here
|
||||
#if defined (PCBV4)
|
||||
# define CS_LOW() PORTB &= ~0x01 /* MMC CS = L */
|
||||
# define CS_HIGH() PORTB |= 0x01 /* MMC CS = H */
|
||||
#else
|
||||
# define CS_LOW() PORTB &= ~0x10 /* MMC CS = L */
|
||||
# define CS_HIGH() PORTB |= 0x10 /* MMC CS = H */
|
||||
#endif
|
||||
|
||||
#define SOCKPORT PINB /* Socket contact port */
|
||||
#define SOCKWP 0x00 // not implemented /* Write protect switch */
|
||||
|
@ -175,7 +178,9 @@ static
|
|||
void power_on (void)
|
||||
{
|
||||
// PORTE &= ~0x80; // Socket power on
|
||||
#ifndef SIMU
|
||||
for (Timer1 = 2; Timer1; ); // Wait for 20ms
|
||||
#endif
|
||||
//PORTB = 0b10110101; // Enable drivers
|
||||
//DDRB = 0b11000111;
|
||||
|
||||
|
|
|
@ -121,7 +121,6 @@ public:
|
|||
uint8_t getDbl() { return m_dblcnt; }
|
||||
};
|
||||
|
||||
|
||||
Key keys[NUM_KEYS];
|
||||
void Key::input(bool val, EnumKeys enuk)
|
||||
{
|
||||
|
@ -214,10 +213,6 @@ bool keyState(EnumKeys enuk)
|
|||
|
||||
case SW_Trainer: return PINB & (1<<INP_B_Trainer);
|
||||
|
||||
case SW_RE1: return (~PIND & 0b00100000);
|
||||
|
||||
case SW_RE2: return (~PIND & 0b00010000);
|
||||
|
||||
default:;
|
||||
}
|
||||
#else
|
||||
|
@ -306,6 +301,10 @@ void per10ms()
|
|||
*/
|
||||
|
||||
# if defined (PCBV4)
|
||||
|
||||
keys[BTN_RE1].input(~PIND & 0b00100000, BTN_RE1);
|
||||
keys[BTN_RE2].input(~PIND & 0b00010000, BTN_RE2);
|
||||
|
||||
uint8_t tin = ~PINL;
|
||||
uint8_t in;
|
||||
in = (tin & 0x0f) << 3;
|
||||
|
@ -343,6 +342,7 @@ void per10ms()
|
|||
keys[enuk].input(in & (1<<i),(EnumKeys)enuk);
|
||||
++enuk;
|
||||
}
|
||||
|
||||
// End User buttons
|
||||
|
||||
// Trim switches ...
|
||||
|
|
3
src/ff.h
3
src/ff.h
|
@ -42,6 +42,7 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "inttypes.h"
|
||||
#include "integer.h" /* Basic integer types */
|
||||
#include "ffconf.h" /* FatFs configuration options */
|
||||
|
||||
|
@ -473,7 +474,7 @@ TCHAR* f_gets (TCHAR*, int, FIL*); /* Get a string from the file */
|
|||
|
||||
/* RTC function */
|
||||
#if !_FS_READONLY
|
||||
extern DWORD get_fattime (void); /* Returns 32-bit packed date and time */
|
||||
extern uint32_t get_fattime (void); /* Returns 32-bit packed date and time */
|
||||
#endif
|
||||
|
||||
/* Unicode support functions */
|
||||
|
|
|
@ -439,14 +439,14 @@ bool RlcFile::copy(uint8_t i_fileDst, uint8_t i_fileSrc)
|
|||
if (m_currBlk && (fri=EeFsGetLink(m_currBlk)))
|
||||
EeFsSetLink(m_currBlk, 0);
|
||||
|
||||
if (fri) EeFsFree(fri); //chain in
|
||||
|
||||
eeFs.files[FILE_TMP].size = m_pos;
|
||||
EFile::swap(m_fileId, FILE_TMP);
|
||||
|
||||
if (fri) EeFsFree(fri); //chain in
|
||||
|
||||
assert(!m_write_step);
|
||||
|
||||
s_sync_write = false;
|
||||
// s_sync_write is set to false in swap();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -488,7 +488,7 @@ void FrskyData::set(uint8_t value)
|
|||
|
||||
// TODO not here!
|
||||
#if defined (PCBV3)
|
||||
char g_logFilename[21]; // "/G9XLOGS/M00_000.TXT\0" max required length = 21
|
||||
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;
|
||||
|
|
|
@ -256,8 +256,8 @@ void menuProcTime(uint8_t event)
|
|||
|
||||
int8_t sub = m_posVert - 1; // vertical position (1 = page counter, top/right)
|
||||
uint8_t subSub = m_posHorz; // horizontal position
|
||||
static struct tm t;
|
||||
struct tm *at = &t;
|
||||
static struct gtm t;
|
||||
struct gtm *at = &t;
|
||||
|
||||
switch(event)
|
||||
{
|
||||
|
@ -266,7 +266,7 @@ void menuProcTime(uint8_t event)
|
|||
killEvents(event);
|
||||
break;
|
||||
case EVT_KEY_FIRST(KEY_MENU):
|
||||
if (sub >= 0 && !s_editMode) // set the date and time into RTC chip
|
||||
if (sub >= 0 && s_editMode<=0) // set the date and time into RTC chip
|
||||
{
|
||||
g_ms100 = 0; // start of next second begins now
|
||||
g_unixTime = mktime(&t); // update local timestamp and get wday calculated
|
||||
|
@ -286,7 +286,7 @@ void menuProcTime(uint8_t event)
|
|||
break;
|
||||
}
|
||||
|
||||
if (!s_editMode) filltm(&g_unixTime, &t);
|
||||
if (s_editMode<=0) filltm(&g_unixTime, &t);
|
||||
|
||||
lcd_putc(FW*10+2, FH*2, '-'); lcd_putc(FW*13, FH*2, '-');
|
||||
lcd_putc(FW*10+1, FH*4, ':'); lcd_putc(FW*13-1, FH*4, ':');
|
||||
|
@ -299,7 +299,7 @@ void menuProcTime(uint8_t event)
|
|||
|
||||
for(uint8_t j=0; j<3;j++) // 3 settings each for date and time (YMD and HMS)
|
||||
{
|
||||
uint8_t attr = (sub==i && subSub==j) ? (s_editMode ? BLINK : INVERS) : 0;
|
||||
uint8_t attr = (sub==i && subSub==j) ? (s_editMode>0 ? BLINK : INVERS) : 0;
|
||||
switch(i)
|
||||
{
|
||||
case 0: // DATE
|
||||
|
@ -307,15 +307,15 @@ void menuProcTime(uint8_t event)
|
|||
{
|
||||
case 0:
|
||||
lcd_outdezAtt(FW*10+2, y, at->tm_year+1900, attr);
|
||||
if(attr && (s_editMode || p1valdiff)) at->tm_year = checkIncDec( event, at->tm_year, 110, 200, 0);
|
||||
if(attr && (s_editMode>0 || p1valdiff)) at->tm_year = checkIncDec( event, at->tm_year, 110, 200, 0);
|
||||
break;
|
||||
case 1:
|
||||
lcd_outdezNAtt(FW*13, y, at->tm_mon+1, attr|LEADING0, 2);
|
||||
if(attr && (s_editMode || p1valdiff)) at->tm_mon = checkIncDec( event, at->tm_mon, 0, 11, 0);
|
||||
if(attr && (s_editMode>0 || p1valdiff)) at->tm_mon = checkIncDec( event, at->tm_mon, 0, 11, 0);
|
||||
break;
|
||||
case 2:
|
||||
lcd_outdezNAtt(FW*16-2, y, at->tm_mday, attr|LEADING0, 2);
|
||||
if(attr && (s_editMode || p1valdiff)) at->tm_mday = checkIncDec( event, at->tm_mday, 1, 31, 0);
|
||||
if(attr && (s_editMode>0 || p1valdiff)) at->tm_mday = checkIncDec( event, at->tm_mday, 1, 31, 0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -325,15 +325,15 @@ void menuProcTime(uint8_t event)
|
|||
{
|
||||
case 0:
|
||||
lcd_outdezNAtt(FW*10+1, y, at->tm_hour, attr|LEADING0, 2);
|
||||
if(attr && (s_editMode || p1valdiff)) at->tm_hour = checkIncDec( event, at->tm_hour, 0, 23, 0);
|
||||
if(attr && (s_editMode>0 || p1valdiff)) at->tm_hour = checkIncDec( event, at->tm_hour, 0, 23, 0);
|
||||
break;
|
||||
case 1:
|
||||
lcd_outdezNAtt(FW*13-1, y, at->tm_min, attr|LEADING0, 2);
|
||||
if(attr && (s_editMode || p1valdiff)) at->tm_min = checkIncDec( event, at->tm_min, 0, 59, 0);
|
||||
if(attr && (s_editMode>0 || p1valdiff)) at->tm_min = checkIncDec( event, at->tm_min, 0, 59, 0);
|
||||
break;
|
||||
case 2:
|
||||
lcd_outdezNAtt(FW*16-2, y, at->tm_sec, attr|LEADING0, 2);
|
||||
if(attr && (s_editMode || p1valdiff)) at->tm_sec = checkIncDec( event, at->tm_sec, 0, 59, 0);
|
||||
if(attr && (s_editMode>0 || p1valdiff)) at->tm_sec = checkIncDec( event, at->tm_sec, 0, 59, 0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -363,7 +363,7 @@ void menuProcTrainer(uint8_t event)
|
|||
|
||||
sub--;
|
||||
y = 2*FH;
|
||||
blink = s_editMode ? BLINK : INVERS ;
|
||||
blink = (s_editMode>0) ? BLINK : INVERS ;
|
||||
|
||||
for (uint8_t i=0; i<4; i++) {
|
||||
uint8_t chan = pgm_read_byte(chout_ar+g_eeGeneral.templateSetup*4+i); // G: Issue 30.
|
||||
|
@ -374,17 +374,17 @@ void menuProcTrainer(uint8_t event)
|
|||
|
||||
edit = (sub==i && subSub==0);
|
||||
lcd_putsnAtt(4*FW, y, PSTR("off += :=")+3*td->mode, 3, edit ? blink : 0);
|
||||
if (edit && s_editMode)
|
||||
if (edit && s_editMode>0)
|
||||
CHECK_INCDEC_GENVAR(event, td->mode, 0, 2);
|
||||
|
||||
edit = (sub==i && subSub==1);
|
||||
lcd_outdezAtt(11*FW, y, td->studWeight, edit ? blink : 0);
|
||||
if (edit && s_editMode)
|
||||
if (edit && s_editMode>0)
|
||||
CHECK_INCDEC_GENVAR(event, td->studWeight, -100, 100);
|
||||
|
||||
edit = (sub==i && subSub==2);
|
||||
lcd_putsnAtt(12*FW, y, PSTR("ch1ch2ch3ch4")+3*td->srcChn, 3, edit ? blink : 0);
|
||||
if (edit && s_editMode)
|
||||
if (edit && s_editMode>0)
|
||||
CHECK_INCDEC_GENVAR(event, td->srcChn, 0, 3);
|
||||
|
||||
edit = (sub==i && subSub==3);
|
||||
|
@ -455,7 +455,7 @@ void menuProcDiagKeys(uint8_t event)
|
|||
for(uint8_t i=0; i<2; i++) {
|
||||
uint8_t y = i*FH + FH;
|
||||
lcd_putsn_P(14*FW, y, PSTR("RE1RE2")+3*i, 3);
|
||||
lcd_outdezNAtt(18*FW, y, g_rotenc[i], LEFT|(keyState((EnumKeys)(SW_RE1+i)) ? INVERS : 0));
|
||||
lcd_outdezNAtt(18*FW, y, g_rotenc[i], LEFT|(keyState((EnumKeys)(BTN_RE1+i)) ? INVERS : 0));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -25,11 +25,6 @@
|
|||
|
||||
// MM/SD card Disk IO Support
|
||||
#if defined (PCBV3)
|
||||
#include "integer.h"
|
||||
#include "time.h"
|
||||
#include "rtc.h"
|
||||
#include "ff.h"
|
||||
#include "diskio.h"
|
||||
time_t g_unixTime; // Global date/time register, incremented each second in per10ms()
|
||||
#endif
|
||||
|
||||
|
@ -816,7 +811,7 @@ void getADC_bandgap()
|
|||
{
|
||||
#if defined(PCBSTD)
|
||||
ADMUX=0x1E|ADC_VREF_TYPE; // Switch MUX to internal 1.22V reference
|
||||
_delay_us(5); // short delay to stabilise reference voltage
|
||||
_delay_us(7); // short delay to stabilise reference voltage
|
||||
ADCSRA|=0x40;
|
||||
while ((ADCSRA & 0x10)==0);
|
||||
ADCSRA|=0x10; // grab a sample
|
||||
|
@ -864,7 +859,6 @@ uint16_t g_LightOffCounter;
|
|||
uint8_t beepAgain = 0;
|
||||
uint8_t beepAgainOrig = 0;
|
||||
uint8_t beepOn = false;
|
||||
int16_t p1val;
|
||||
|
||||
inline bool checkSlaveMode()
|
||||
{
|
||||
|
@ -1695,18 +1689,6 @@ void perMain()
|
|||
else
|
||||
BACKLIGHT_OFF;
|
||||
|
||||
////////////////
|
||||
// G: TODO This shouldn't be in perMain(). It should be in the same place
|
||||
// all the other ADC samples happen
|
||||
static int16_t p1valprev;
|
||||
p1valdiff = (p1val-calibratedStick[6])/32;
|
||||
if(p1valdiff) {
|
||||
p1valdiff = (p1valprev-calibratedStick[6])/2;
|
||||
p1val = calibratedStick[6];
|
||||
}
|
||||
p1valprev = calibratedStick[6];
|
||||
/////////////////
|
||||
|
||||
g_menuStack[g_menuStackPtr](evt);
|
||||
refreshDisplay();
|
||||
|
||||
|
@ -2028,30 +2010,6 @@ ISR(TIMER3_CAPT_vect) // G: High frequency noise can cause stack overflo with IS
|
|||
#endif
|
||||
}
|
||||
|
||||
#if defined (PCBV3)
|
||||
/*---------------------------------------------------------*/
|
||||
/* User Provided Date/Time Function for FatFs module */
|
||||
/*---------------------------------------------------------*/
|
||||
/* This is a real time clock service to be called from */
|
||||
/* FatFs module. Any valid time must be returned even if */
|
||||
/* the system does not support a real time clock. */
|
||||
/* This is not required in read-only configuration. */
|
||||
|
||||
uint32_t get_fattime(void)
|
||||
{
|
||||
struct tm t;
|
||||
filltm(&g_unixTime, &t); // create a struct tm date/time structure from global unix time stamp
|
||||
|
||||
/* Pack date and time into a DWORD variable */
|
||||
return ((DWORD)(t.tm_year - 80) << 25)
|
||||
| ((uint32_t)(t.tm_mon+1) << 21)
|
||||
| ((uint32_t)t.tm_mday << 16)
|
||||
| ((uint32_t)t.tm_hour << 11)
|
||||
| ((uint32_t)t.tm_min << 5)
|
||||
| ((uint32_t)t.tm_sec >> 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
extern uint16_t g_timeMain;
|
||||
|
||||
/*
|
||||
|
@ -2089,6 +2047,29 @@ uint16_t DEBUG2 = 0;
|
|||
|
||||
#endif
|
||||
|
||||
#if defined (PCBV3)
|
||||
/*---------------------------------------------------------*/
|
||||
/* User Provided Date/Time Function for FatFs module */
|
||||
/*---------------------------------------------------------*/
|
||||
/* This is a real time clock service to be called from */
|
||||
/* FatFs module. Any valid time must be returned even if */
|
||||
/* the system does not support a real time clock. */
|
||||
/* This is not required in read-only configuration. */
|
||||
|
||||
uint32_t get_fattime(void) // TODO why not in ff.cpp?
|
||||
{
|
||||
struct gtm t;
|
||||
filltm(&g_unixTime, &t); // create a struct tm date/time structure from global unix time stamp
|
||||
|
||||
/* Pack date and time into a DWORD variable */
|
||||
return ((DWORD)(t.tm_year - 80) << 25)
|
||||
| ((uint32_t)(t.tm_mon+1) << 21)
|
||||
| ((uint32_t)t.tm_mday << 16)
|
||||
| ((uint32_t)t.tm_hour << 11)
|
||||
| ((uint32_t)t.tm_min << 5)
|
||||
| ((uint32_t)t.tm_sec >> 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
void instantTrim()
|
||||
{
|
||||
|
@ -2145,6 +2126,11 @@ void moveTrimsToOffsets() // copy state of 3 primary to subtrim
|
|||
#if defined (PCBV4)
|
||||
// Rotary encoder interrupts
|
||||
volatile uint8_t g_rotenc[2] = {0};
|
||||
#endif
|
||||
|
||||
#ifndef SIMU
|
||||
|
||||
#if defined (PCBV4)
|
||||
ISR(INT2_vect)
|
||||
{
|
||||
uint8_t input = PIND & 0b00001100;
|
||||
|
@ -2168,8 +2154,6 @@ ISR(INT6_vect)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifndef SIMU
|
||||
|
||||
extern unsigned char __bss_end ;
|
||||
|
||||
uint16_t stack_free()
|
||||
|
@ -2295,13 +2279,13 @@ int main(void)
|
|||
}
|
||||
}
|
||||
|
||||
sei(); // interrupts needed for eeReadAll function (soon).
|
||||
|
||||
g_menuStack[0] = menuMainView;
|
||||
g_menuStack[1] = menuProcModelSelect;
|
||||
|
||||
lcdSetRefVolt(25);
|
||||
|
||||
sei(); // interrupts needed for FRSKY_Init and eeReadAll.
|
||||
|
||||
#if defined (FRSKY)
|
||||
FRSKY_Init();
|
||||
#endif
|
||||
|
@ -2341,7 +2325,7 @@ int main(void)
|
|||
#if defined (PCBV3)
|
||||
// Initialise global unix timestamp with current time from RTC chip on SD card interface
|
||||
RTC rtc;
|
||||
struct tm utm;
|
||||
struct gtm utm;
|
||||
rtc_gettime(&rtc);
|
||||
utm.tm_year = rtc.year - 1900;
|
||||
utm.tm_mon = rtc.month - 1;
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
#if defined(PCBV3)
|
||||
#include "ff.h"
|
||||
#include "time.h"
|
||||
#include "gtime.h"
|
||||
#endif
|
||||
|
||||
#ifdef SIMU
|
||||
|
@ -280,6 +280,10 @@ enum EnumKeys {
|
|||
TRM_RV_UP ,
|
||||
TRM_RH_DWN ,
|
||||
TRM_RH_UP ,
|
||||
#ifdef PCBV4
|
||||
BTN_RE1,
|
||||
BTN_RE2,
|
||||
#endif
|
||||
//SW_NC ,
|
||||
//SW_ON ,
|
||||
SW_ThrCt ,
|
||||
|
@ -291,8 +295,8 @@ enum EnumKeys {
|
|||
SW_AileDR ,
|
||||
SW_Gear ,
|
||||
SW_Trainer,
|
||||
SW_RE1,
|
||||
SW_RE2
|
||||
NUM_KEYS = SW_ThrCt
|
||||
|
||||
};
|
||||
|
||||
#define CURVE_BASE 7
|
||||
|
@ -376,7 +380,6 @@ enum EnumKeys {
|
|||
#define THRCHK_DEADBAND 16
|
||||
#define SPLASH_TIMEOUT (4*100) //400 msec - 4 seconds
|
||||
|
||||
#define NUM_KEYS TRM_RH_UP+1
|
||||
#define TRM_BASE TRM_LH_DWN
|
||||
|
||||
//#define _MSK_KEY_FIRST (_MSK_KEY_REPT|0x20)
|
||||
|
@ -732,7 +735,7 @@ extern char userDataDisplayBuf[TELEM_SCREEN_BUFFER_SIZE]; // text buffer for frs
|
|||
#endif
|
||||
|
||||
#if defined (PCBV3)
|
||||
extern char g_logFilename[21]; // pers.cpp::resetTelemetry()
|
||||
extern char g_logFilename[22]; // pers.cpp::resetTelemetry()
|
||||
extern FATFS FATFS_Obj; // pers.cpp::resetTelemetry()
|
||||
extern FIL g_oLogFile; // pers.cpp::resetTelemetry()
|
||||
#endif
|
||||
|
|
485
src/gtime.cpp
Normal file
485
src/gtime.cpp
Normal file
|
@ -0,0 +1,485 @@
|
|||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
*
|
||||
* gruvin9x is based on code named er9x by
|
||||
* Author - Erez Raviv <erezraviv@gmail.com>, which is in turn
|
||||
* was based on the original (and ongoing) project by Thomas Husterer,
|
||||
* th9x -- http://code.google.com/p/th9x/
|
||||
*
|
||||
* 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 "gtime.h"
|
||||
|
||||
#define LEAP_SECONDS_POSSIBLE 0
|
||||
|
||||
/* Shift A right by B bits portably, by dividing A by 2**B and
|
||||
truncating towards minus infinity. A and B should be free of side
|
||||
effects, and B should be in the range 0 <= B <= INT_BITS - 2, where
|
||||
INT_BITS is the number of useful bits in an int. GNU code can
|
||||
assume that INT_BITS is at least 32.
|
||||
|
||||
ISO C99 says that A >> B is implementation-defined if A < 0. Some
|
||||
implementations (e.g., UNICOS 9.0 on a Cray Y-MP EL) don't shift
|
||||
right in the usual way when A < 0, so SHR falls back on division if
|
||||
ordinary A >> B doesn't seem to be the usual signed shift. */
|
||||
#define SHR(a, b) \
|
||||
(-1 >> 1 == -1 \
|
||||
? (a) >> (b) \
|
||||
: (a) / (1 << (b)) - ((a) % (1 << (b)) < 0))
|
||||
|
||||
/* The extra casts in the following macros work around compiler bugs,
|
||||
e.g., in Cray C 5.0.3.0. */
|
||||
|
||||
/* True if the arithmetic type T is an integer type. bool counts as
|
||||
an integer. */
|
||||
#define TYPE_IS_INTEGER(t) ((t) 1.5 == 1)
|
||||
|
||||
/* True if negative values of the signed integer type T use two's
|
||||
complement, ones' complement, or signed magnitude representation,
|
||||
respectively. Much GNU code assumes two's complement, but some
|
||||
people like to be portable to all possible C hosts. */
|
||||
#define TYPE_TWOS_COMPLEMENT(t) ((t) ~ (t) 0 == (t) -1)
|
||||
#define TYPE_ONES_COMPLEMENT(t) ((t) ~ (t) 0 == 0)
|
||||
#define TYPE_SIGNED_MAGNITUDE(t) ((t) ~ (t) 0 < (t) -1)
|
||||
|
||||
/* True if the arithmetic type T is signed. */
|
||||
#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
|
||||
|
||||
/* The maximum and minimum values for the integer type T. These
|
||||
macros have undefined behavior if T is signed and has padding bits.
|
||||
If this is a problem for you, please let us know how to fix it for
|
||||
your host. */
|
||||
#define TYPE_MINIMUM(t) \
|
||||
((t) (! TYPE_SIGNED (t) \
|
||||
? (t) 0 \
|
||||
: TYPE_SIGNED_MAGNITUDE (t) \
|
||||
? ~ (t) 0 \
|
||||
: ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1)))
|
||||
#define TYPE_MAXIMUM(t) \
|
||||
((t) (! TYPE_SIGNED (t) \
|
||||
? (t) -1 \
|
||||
: ~ (~ (t) 0 << (sizeof (t) * CHAR_BIT - 1))))
|
||||
|
||||
#ifndef TIME_T_MIN
|
||||
# define TIME_T_MIN TYPE_MINIMUM (time_t)
|
||||
#endif
|
||||
#ifndef TIME_T_MAX
|
||||
# define TIME_T_MAX TYPE_MAXIMUM (time_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 (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
|
||||
diagnostic on some hosts. */
|
||||
|
||||
#define EPOCH_YEAR 1970
|
||||
#define TM_YEAR_BASE 1900
|
||||
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
|
||||
leapyear (long int year)
|
||||
{
|
||||
/* Don't add YEAR to TM_YEAR_BASE, as that might overflow.
|
||||
Also, work even if YEAR is negative. */
|
||||
return
|
||||
((year & 3) == 0
|
||||
&& (year % 100 != 0
|
||||
|| ((year / 100) & 3) == (- (TM_YEAR_BASE / 100) & 3)));
|
||||
}
|
||||
|
||||
const unsigned short int __mon_yday[2][13] =
|
||||
{
|
||||
/* Normal years. */
|
||||
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
|
||||
/* Leap years. */
|
||||
{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
|
||||
};
|
||||
|
||||
/* Compute the `struct tm' representation of *T,
|
||||
offset OFFSET seconds east of UTC,
|
||||
and store year, yday, mon, mday, wday, hour, min, sec into *TP.
|
||||
Return nonzero if successful. */
|
||||
int
|
||||
__offtime (
|
||||
time_t *t,
|
||||
long int offset,
|
||||
struct gtm *tp)
|
||||
{
|
||||
long int days, rem, y;
|
||||
const unsigned short int *ip;
|
||||
|
||||
days = *t / SECS_PER_DAY;
|
||||
rem = *t % SECS_PER_DAY;
|
||||
rem += offset;
|
||||
while (rem < 0)
|
||||
{
|
||||
rem += SECS_PER_DAY;
|
||||
--days;
|
||||
}
|
||||
while (rem >= SECS_PER_DAY)
|
||||
{
|
||||
rem -= SECS_PER_DAY;
|
||||
++days;
|
||||
}
|
||||
tp->tm_hour = rem / SECS_PER_HOUR;
|
||||
rem %= SECS_PER_HOUR;
|
||||
tp->tm_min = rem / 60;
|
||||
tp->tm_sec = rem % 60;
|
||||
/* January 1, 1970 was a Thursday. */
|
||||
tp->tm_wday = (4 + days) % 7;
|
||||
if (tp->tm_wday < 0)
|
||||
tp->tm_wday += 7;
|
||||
y = 1970;
|
||||
|
||||
#define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
|
||||
#define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
|
||||
|
||||
while (days < 0 || days >= (leapyear (y) ? 366 : 365))
|
||||
{
|
||||
/* Guess a corrected year, assuming 365 days per year. */
|
||||
long int yg = y + days / 365 - (days % 365 < 0);
|
||||
|
||||
/* Adjust DAYS and Y to match the guessed year. */
|
||||
days -= ((yg - y) * 365
|
||||
+ LEAPS_THRU_END_OF (yg - 1)
|
||||
- LEAPS_THRU_END_OF (y - 1));
|
||||
y = yg;
|
||||
}
|
||||
tp->tm_year = y - 1900;
|
||||
if (tp->tm_year != y - 1900)
|
||||
{
|
||||
/* The year cannot be represented due to overflow. */
|
||||
// __set_errno (EOVERFLOW);
|
||||
return 0;
|
||||
}
|
||||
tp->tm_yday = days;
|
||||
ip = __mon_yday[leapyear(y)];
|
||||
for (y = 11; days < (long int) ip[y]; --y)
|
||||
continue;
|
||||
days -= ip[y];
|
||||
tp->tm_mon = y;
|
||||
tp->tm_mday = days + 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* time_r function implementations */
|
||||
// G: No time zones in our implementation so just do the converion from time_t to struct tm
|
||||
struct gtm *
|
||||
__localtime_r (time_t * t, struct gtm * tp)
|
||||
{
|
||||
__offtime(t, 0, tp);
|
||||
return tp;
|
||||
}
|
||||
|
||||
|
||||
/* Return an integer value measuring (YEAR1-YDAY1 HOUR1:MIN1:SEC1) -
|
||||
(YEAR0-YDAY0 HOUR0:MIN0:SEC0) in seconds, assuming that the clocks
|
||||
were not adjusted between the time stamps.
|
||||
|
||||
The YEAR values uses the same numbering as TP->tm_year. Values
|
||||
need not be in the usual range. However, YEAR1 must not be less
|
||||
than 2 * INT_MIN or greater than 2 * INT_MAX.
|
||||
|
||||
The result may overflow. It is the caller's responsibility to
|
||||
detect overflow. */
|
||||
|
||||
static inline time_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)
|
||||
{
|
||||
verify (C99_integer_division, -1 / 2 == 0);
|
||||
verify (long_int_year_and_yday_are_wide_enough,
|
||||
INT_MAX <= LONG_MAX / 2 || TIME_T_MAX <= UINT_MAX);
|
||||
|
||||
/* Compute intervening leap days correctly even if year is negative.
|
||||
Take care to avoid integer overflow here. */
|
||||
int a4 = SHR (year1, 2) + SHR (TM_YEAR_BASE, 2) - ! (year1 & 3);
|
||||
int b4 = SHR (year0, 2) + SHR (TM_YEAR_BASE, 2) - ! (year0 & 3);
|
||||
int a100 = a4 / 25 - (a4 % 25 < 0);
|
||||
int b100 = b4 / 25 - (b4 % 25 < 0);
|
||||
int a400 = SHR (a100, 2);
|
||||
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
|
||||
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;
|
||||
return seconds;
|
||||
}
|
||||
|
||||
/* Return a time_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
|
||||
guess_time_tm (long int year, long int yday, int hour, int min, int sec,
|
||||
time_t *t, struct gtm *tp)
|
||||
{
|
||||
if (tp)
|
||||
{
|
||||
time_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))
|
||||
return t1;
|
||||
}
|
||||
|
||||
/* Overflow occurred one way or another. Return the nearest result
|
||||
that is actually in range, except don't report a zero difference
|
||||
if the actual difference is nonzero, as that would cause a false
|
||||
match; and don't oscillate between two values, as that would
|
||||
confuse the spring-forward gap detector. */
|
||||
return (*t < TIME_T_MIDPOINT
|
||||
? (*t <= TIME_T_MIN + 1 ? *t + 1 : TIME_T_MIN)
|
||||
: (TIME_T_MAX - 1 <= *t ? *t - 1 : TIME_T_MAX));
|
||||
}
|
||||
|
||||
/* Use CONVERT to convert *T to a broken down time in *TP.
|
||||
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)
|
||||
{
|
||||
struct gtm *r = convert (t, tp);
|
||||
|
||||
if (!r && *t)
|
||||
{
|
||||
time_t bad = *t;
|
||||
time_t ok = 0;
|
||||
|
||||
/* BAD is a known unconvertible time_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
|
||||
? bad + ((ok - bad) >> 1)
|
||||
: ok + ((bad - ok) >> 1));
|
||||
r = convert (t, tp);
|
||||
if (r)
|
||||
ok = mid;
|
||||
else
|
||||
bad = mid;
|
||||
}
|
||||
|
||||
if (!r && ok)
|
||||
{
|
||||
/* The last conversion attempt failed;
|
||||
revert to the most recent successful attempt. */
|
||||
*t = ok;
|
||||
r = convert (t, tp);
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Convert *TP to a time_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
|
||||
__mktime_internal (struct gtm *tp,
|
||||
struct gtm *(*convert) (time_t *, struct gtm *),
|
||||
time_t *offset)
|
||||
{
|
||||
time_t t, gt, t0, t1, t2;
|
||||
struct gtm tm;
|
||||
|
||||
/* The maximum number of probes (calls to CONVERT) should be enough
|
||||
to handle any combinations of time zone rule changes, solar time,
|
||||
leap seconds, and oscillations around a spring-forward gap.
|
||||
POSIX.1 prohibits leap seconds, but some hosts have them anyway. */
|
||||
int remaining_probes = 6;
|
||||
|
||||
/* Time requested. Copy it in case CONVERT modifies *TP; this can
|
||||
occur if TP is localtime's returned value and CONVERT is localtime. */
|
||||
int sec = tp->tm_sec;
|
||||
int min = tp->tm_min;
|
||||
int hour = tp->tm_hour;
|
||||
int mday = tp->tm_mday;
|
||||
int mon = tp->tm_mon;
|
||||
int year_requested = tp->tm_year;
|
||||
|
||||
/* Ensure that mon is in range, and set year accordingly. */
|
||||
int mon_remainder = mon % 12;
|
||||
int negative_mon_remainder = mon_remainder < 0;
|
||||
int mon_years = mon / 12 - negative_mon_remainder;
|
||||
long int lyear_requested = year_requested;
|
||||
long int year = lyear_requested + mon_years;
|
||||
|
||||
/* The other values need not be in range:
|
||||
the remaining code handles minor overflows correctly,
|
||||
assuming int and time_t arithmetic wraps around.
|
||||
Major overflows are caught at the end. */
|
||||
|
||||
/* Calculate day of year from year, month, and day of month.
|
||||
The result need not be in range. */
|
||||
int mon_yday = ((__mon_yday[leapyear (year)]
|
||||
[mon_remainder + 12 * negative_mon_remainder])
|
||||
- 1);
|
||||
long int lmday = mday;
|
||||
long int yday = mon_yday + lmday;
|
||||
|
||||
time_t guessed_offset = *offset;
|
||||
|
||||
int sec_requested = sec;
|
||||
|
||||
/*
|
||||
if (LEAP_SECONDS_POSSIBLE)
|
||||
{
|
||||
// Handle out-of-range seconds specially,
|
||||
// since ydhms_tm_diff assumes every minute has 60 seconds.
|
||||
if (sec < 0)
|
||||
sec = 0;
|
||||
if (59 < sec)
|
||||
sec = 59;
|
||||
}
|
||||
*/
|
||||
|
||||
/* Invert CONVERT by probing. First assume the same offset as last
|
||||
time. */
|
||||
|
||||
t0 = ydhms_diff (year, yday, hour, min, sec,
|
||||
EPOCH_YEAR - TM_YEAR_BASE, 0, 0, 0, - guessed_offset);
|
||||
|
||||
if (TIME_T_MAX / INT_MAX / 366 / 24 / 60 / 60 < 3)
|
||||
{
|
||||
/* time_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
|
||||
that is bounded by a small value. */
|
||||
|
||||
/* Approximate log base 2 of the number of time units per
|
||||
biennium. A biennium is 2 years; use this unit instead of
|
||||
years to avoid integer overflow. For example, 2 average
|
||||
Gregorian years are 2 * 365.2425 * 24 * 60 * 60 seconds,
|
||||
which is 63113904 seconds, and rint (log2 (63113904)) is
|
||||
26. */
|
||||
int ALOG2_SECONDS_PER_BIENNIUM = 26;
|
||||
int ALOG2_MINUTES_PER_BIENNIUM = 20;
|
||||
int ALOG2_HOURS_PER_BIENNIUM = 14;
|
||||
int ALOG2_DAYS_PER_BIENNIUM = 10;
|
||||
int LOG2_YEARS_PER_BIENNIUM = 1;
|
||||
|
||||
int approx_requested_biennia =
|
||||
(SHR (year_requested, LOG2_YEARS_PER_BIENNIUM)
|
||||
- SHR (EPOCH_YEAR - TM_YEAR_BASE, LOG2_YEARS_PER_BIENNIUM)
|
||||
+ SHR (mday, ALOG2_DAYS_PER_BIENNIUM)
|
||||
+ SHR (hour, ALOG2_HOURS_PER_BIENNIUM)
|
||||
+ SHR (min, ALOG2_MINUTES_PER_BIENNIUM)
|
||||
+ (LEAP_SECONDS_POSSIBLE
|
||||
? 0
|
||||
: SHR (sec, ALOG2_SECONDS_PER_BIENNIUM)));
|
||||
|
||||
int approx_biennia = SHR (t0, ALOG2_SECONDS_PER_BIENNIUM);
|
||||
int diff = approx_biennia - approx_requested_biennia;
|
||||
int abs_diff = diff < 0 ? - diff : diff;
|
||||
|
||||
/* IRIX 4.0.5 cc miscalculates TIME_T_MIN / 3: it erroneously
|
||||
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 =
|
||||
(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;
|
||||
approx_biennia = SHR (repaired_t0, ALOG2_SECONDS_PER_BIENNIUM);
|
||||
diff = approx_biennia - approx_requested_biennia;
|
||||
abs_diff = diff < 0 ? - diff : diff;
|
||||
if (overflow_threshold < abs_diff)
|
||||
return -1;
|
||||
guessed_offset += repaired_t0 - t0;
|
||||
t0 = repaired_t0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Repeatedly use the error to improve the guess. */
|
||||
|
||||
for (t = t1 = t2 = t0;
|
||||
(gt = guess_time_tm (year, yday, hour, min, sec, &t,
|
||||
ranged_convert (convert, &t, &tm)),
|
||||
t != gt);
|
||||
t1 = t2, t2 = t, t = gt)
|
||||
if (t == t1 && t != t2)
|
||||
goto offset_found;
|
||||
else if (--remaining_probes == 0)
|
||||
return -1;
|
||||
|
||||
offset_found:
|
||||
*offset = guessed_offset + t - t0;
|
||||
|
||||
if (LEAP_SECONDS_POSSIBLE && sec_requested != tm.tm_sec)
|
||||
{
|
||||
/* Adjust time to reflect the tm_sec requested, not the normalized value.
|
||||
Also, repair any damage from a false match due to a leap second. */
|
||||
int sec_adjustment = (sec == 0 && tm.tm_sec == 60) - sec;
|
||||
t1 = t + sec_requested;
|
||||
t2 = t1 + sec_adjustment;
|
||||
if (((t1 < t) != (sec_requested < 0))
|
||||
| ((t2 < t1) != (sec_adjustment < 0))
|
||||
| ! convert (&t2, &tm))
|
||||
return -1;
|
||||
t = t2;
|
||||
}
|
||||
|
||||
*tp = tm;
|
||||
return t;
|
||||
}
|
||||
|
||||
/* Convert *TP to a time_t value. */
|
||||
time_t
|
||||
mktime (struct gtm *tp)
|
||||
{
|
||||
// no time zone stuff. Just do the math ;)
|
||||
static time_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)
|
||||
{
|
||||
return __offtime(t, 0, tp);
|
||||
}
|
||||
|
55
src/gtime.h
Normal file
55
src/gtime.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
*
|
||||
* gruvin9x is based on code named er9x by
|
||||
* Author - Erez Raviv <erezraviv@gmail.com>, which is in turn
|
||||
* was based on the original (and ongoing) project by Thomas Husterer,
|
||||
* th9x -- http://code.google.com/p/th9x/
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef g9x_time_h
|
||||
#define g9x_time_h
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#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;
|
||||
|
||||
struct gtm
|
||||
{
|
||||
int8_t tm_sec; /* Seconds. [0-60] (1 leap second) */
|
||||
int8_t tm_min; /* Minutes. [0-59] */
|
||||
int8_t tm_hour; /* Hours. [0-23] */
|
||||
int8_t tm_mday; /* Day. [1-31] */
|
||||
int8_t tm_mon; /* Month. [0-11] */
|
||||
int8_t tm_year; /* Year - 1900. Limited to the year 2115. Oh no! :P */
|
||||
int8_t tm_wday; /* Day of week. [0-6] */
|
||||
int16_t tm_yday; /* Day of year. [0-365] Needed internally for calculations */
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
#endif
|
||||
|
154
src/menus.cpp
154
src/menus.cpp
|
@ -27,11 +27,11 @@
|
|||
int16_t calibratedStick[NUM_STICKS+NUM_POTS];
|
||||
int16_t ex_chans[NUM_CHNOUT]; // Outputs + intermidiates
|
||||
uint8_t s_pgOfs;
|
||||
uint8_t s_editMode;
|
||||
int8_t s_editMode;
|
||||
uint8_t s_noHi;
|
||||
uint8_t s_noScroll;
|
||||
|
||||
int16_t g_chans512[NUM_CHNOUT];
|
||||
int16_t g_chans512[NUM_CHNOUT]; // TODO not here!
|
||||
|
||||
void menu_lcd_onoff( uint8_t x,uint8_t y, uint8_t value, uint8_t mode )
|
||||
{
|
||||
|
@ -50,7 +50,10 @@ void DisplayScreenIndex(uint8_t index, uint8_t count, uint8_t attr)
|
|||
lcd_outdezAtt(1+128-FW*(count>9 ? 3 : 2),0,index+1,attr);
|
||||
}
|
||||
|
||||
#if defined(NAVIGATION_POT1) || defined(NAVIGATION_RE1)
|
||||
int16_t p1valdiff;
|
||||
#endif
|
||||
|
||||
int8_t checkIncDec_Ret;
|
||||
int16_t checkIncDec(uint8_t event, int16_t val, int16_t i_min, int16_t i_max, uint8_t i_flags)
|
||||
{
|
||||
|
@ -63,7 +66,7 @@ int16_t checkIncDec(uint8_t event, int16_t val, int16_t i_min, int16_t i_max, ui
|
|||
kmi=hlp;
|
||||
event=EVT_KEY_FIRST(EVT_KEY_MASK & event);
|
||||
}
|
||||
if(event==EVT_KEY_FIRST(kpl) || event== EVT_KEY_REPT(kpl) || (s_editMode && (event==EVT_KEY_FIRST(KEY_UP) || event== EVT_KEY_REPT(KEY_UP))) ) {
|
||||
if(event==EVT_KEY_FIRST(kpl) || event== EVT_KEY_REPT(kpl) || (s_editMode>0 && (event==EVT_KEY_FIRST(KEY_UP) || event== EVT_KEY_REPT(KEY_UP))) ) {
|
||||
newval++;
|
||||
#if defined (BEEPSPKR)
|
||||
beepKeySpkr(BEEP_KEY_UP_FREQ);
|
||||
|
@ -71,7 +74,7 @@ int16_t checkIncDec(uint8_t event, int16_t val, int16_t i_min, int16_t i_max, ui
|
|||
beepKey();
|
||||
#endif
|
||||
kother=kmi;
|
||||
}else if(event==EVT_KEY_FIRST(kmi) || event== EVT_KEY_REPT(kmi) || (s_editMode && (event==EVT_KEY_FIRST(KEY_DOWN) || event== EVT_KEY_REPT(KEY_DOWN))) ) {
|
||||
}else if(event==EVT_KEY_FIRST(kmi) || event== EVT_KEY_REPT(kmi) || (s_editMode>0 && (event==EVT_KEY_FIRST(KEY_DOWN) || event== EVT_KEY_REPT(KEY_DOWN))) ) {
|
||||
newval--;
|
||||
#if defined (BEEPSPKR)
|
||||
beepKeySpkr(BEEP_KEY_DOWN_FREQ);
|
||||
|
@ -86,13 +89,15 @@ int16_t checkIncDec(uint8_t event, int16_t val, int16_t i_min, int16_t i_max, ui
|
|||
killEvents(kpl);
|
||||
}
|
||||
if(i_min==0 && i_max==1 && event==EVT_KEY_FIRST(KEY_MENU)) {
|
||||
s_editMode = false;
|
||||
s_editMode = 0;
|
||||
newval=!val;
|
||||
killEvents(event);
|
||||
}
|
||||
|
||||
#if defined(NAVIGATION_POT1) || defined (NAVIGATION_RE1)
|
||||
//change values based on P1
|
||||
newval -= p1valdiff;
|
||||
#endif
|
||||
|
||||
if(newval > i_max)
|
||||
{
|
||||
|
@ -155,29 +160,92 @@ bool check_submenu_simple(uint8_t event, uint8_t maxrow)
|
|||
return check_simple(event, 0, 0, 0, maxrow);
|
||||
}
|
||||
|
||||
#define SCROLL_TH 64
|
||||
#define SCROLL_POT1_TH 32
|
||||
|
||||
#define MAXCOL(row) (horTab ? pgm_read_byte(horTab+min(row, horTabMax)) : (const uint8_t)0)
|
||||
#define INC(val,max) if(val<max) {val++;} else {val=0;}
|
||||
#define DEC(val,max) if(val>0 ) {val--;} else {val=max;}
|
||||
bool check(uint8_t event, uint8_t curr, MenuFuncP *menuTab, uint8_t menuTabSize, prog_uint8_t *horTab, uint8_t horTabMax, uint8_t maxrow)
|
||||
{
|
||||
#ifdef NAVIGATION_RE1
|
||||
// check rotary encoder 1 if changed -> cursor down/up
|
||||
static int16_t re1valprev;
|
||||
p1valdiff = 0;
|
||||
int8_t scrollRE = re1valprev - g_rotenc[0];
|
||||
if (scrollRE) {
|
||||
re1valprev = g_rotenc[0];
|
||||
if (s_editMode > 0) {
|
||||
p1valdiff = scrollRE;
|
||||
scrollRE = 0;
|
||||
}
|
||||
}
|
||||
if (event == EVT_KEY_FIRST(BTN_RE1)) {
|
||||
scrollRE = 0;
|
||||
if (s_editMode++ > 0) s_editMode = 0;
|
||||
if (s_editMode > 0 && m_posVert == 0) s_editMode = -1;
|
||||
}
|
||||
#else
|
||||
#define scrollRE 0
|
||||
#endif
|
||||
|
||||
#ifdef NAVIGATION_POT1
|
||||
// check pot 1 - if changed -> scroll values
|
||||
static int16_t p1valprev;
|
||||
p1valdiff = (p1valprev-calibratedStick[6]) / SCROLL_POT1_TH;
|
||||
if (p1valdiff) p1valprev = calibratedStick[6];
|
||||
#endif
|
||||
|
||||
#ifdef NAVIGATION_POT2
|
||||
// check pot 2 - if changed -> scroll menu
|
||||
static int16_t p2valprev;
|
||||
int8_t scrollLR = (p2valprev-calibratedStick[4]) / SCROLL_TH;
|
||||
if (scrollLR) p2valprev = calibratedStick[4];
|
||||
#else
|
||||
#define scrollLR 0
|
||||
#endif
|
||||
|
||||
#ifdef NAVIGATION_POT3
|
||||
// check pot 3 if changed -> cursor down/up
|
||||
static int16_t p3valprev;
|
||||
int8_t scrollUD = (p3valprev-calibratedStick[5]) / SCROLL_TH;
|
||||
if (scrollUD) p3valprev = calibratedStick[5];
|
||||
#else
|
||||
#define scrollUD 0
|
||||
#endif
|
||||
|
||||
if(scrollLR || scrollUD || p1valdiff) g_LightOffCounter = g_eeGeneral.lightAutoOff*500; // on keypress turn the light on 5*100
|
||||
|
||||
if (menuTab) {
|
||||
uint8_t attr = 0;
|
||||
|
||||
if (m_posVert==0 && !s_noScroll) {
|
||||
attr = INVERS;
|
||||
switch(event)
|
||||
{
|
||||
|
||||
int8_t cc = curr;
|
||||
|
||||
if (scrollLR || (scrollRE && s_editMode < 0)) {
|
||||
cc = limit((int8_t)0, (int8_t)(curr - scrollLR - scrollRE), (int8_t)(menuTabSize-1));
|
||||
}
|
||||
|
||||
switch(event) {
|
||||
case EVT_KEY_FIRST(KEY_LEFT):
|
||||
if (curr > 0)
|
||||
chainMenu((MenuFuncP)pgm_read_adr(&menuTab[curr-1]));
|
||||
cc = curr - 1;
|
||||
else
|
||||
chainMenu((MenuFuncP)pgm_read_adr(&menuTab[menuTabSize-1]));
|
||||
return false;
|
||||
cc = menuTabSize-1;
|
||||
break;
|
||||
|
||||
case EVT_KEY_FIRST(KEY_RIGHT):
|
||||
if (curr < (menuTabSize-1))
|
||||
chainMenu((MenuFuncP)pgm_read_adr(&menuTab[curr+1]));
|
||||
cc = curr + 1;
|
||||
else
|
||||
chainMenu((MenuFuncP)pgm_read_adr(&menuTab[0]));
|
||||
cc = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (cc != curr) {
|
||||
chainMenu((MenuFuncP)pgm_read_adr(&menuTab[cc]));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -188,23 +256,67 @@ bool check(uint8_t event, uint8_t curr, MenuFuncP *menuTab, uint8_t menuTabSize,
|
|||
theFile.DisplayProgressBar(menuTab ? lcd_lastPos-2*FW-((curr+1)/10*FWNUM)-2 : 20*FW+1);
|
||||
|
||||
uint8_t maxcol = MAXCOL(m_posVert);
|
||||
|
||||
if (s_editMode<=0) {
|
||||
if (scrollUD) {
|
||||
m_posVert = limit((int8_t)0, (int8_t)(m_posVert - scrollUD), (int8_t)maxrow);
|
||||
m_posHorz = min(m_posHorz, MAXCOL(m_posVert));
|
||||
BLINK_SYNC;
|
||||
}
|
||||
|
||||
if (scrollLR && m_posVert>0) {
|
||||
m_posHorz = limit((int8_t)0, (int8_t)(m_posHorz - scrollLR), (int8_t)maxcol);
|
||||
BLINK_SYNC;
|
||||
}
|
||||
|
||||
#ifdef NAVIGATION_RE1
|
||||
while (scrollRE) {
|
||||
if (scrollRE > 0) {
|
||||
--scrollRE;
|
||||
if (++m_posHorz > MAXCOL(m_posVert)) {
|
||||
m_posHorz = 0;
|
||||
if (++m_posVert > maxrow) {
|
||||
m_posVert = maxrow;
|
||||
m_posHorz = MAXCOL(m_posVert);
|
||||
scrollRE = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
++scrollRE;
|
||||
if (m_posHorz-- == 0) {
|
||||
if (m_posVert-- == 0) {
|
||||
m_posVert = 0;
|
||||
m_posHorz = 0;
|
||||
scrollRE = 0;
|
||||
}
|
||||
else {
|
||||
m_posHorz = MAXCOL(m_posVert);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
switch(event)
|
||||
{
|
||||
case EVT_ENTRY:
|
||||
minit();
|
||||
s_editMode = false;
|
||||
s_editMode = -1;
|
||||
break;
|
||||
case EVT_KEY_FIRST(KEY_MENU):
|
||||
if (maxcol > 0)
|
||||
s_editMode = !s_editMode;
|
||||
s_editMode = (s_editMode<=0);
|
||||
break;
|
||||
case EVT_KEY_LONG(KEY_EXIT):
|
||||
s_editMode = false;
|
||||
s_editMode = 0;
|
||||
popMenu();
|
||||
break;
|
||||
case EVT_KEY_BREAK(KEY_EXIT):
|
||||
if(s_editMode) {
|
||||
s_editMode = false;
|
||||
if(s_editMode>0) {
|
||||
s_editMode = 0;
|
||||
break;
|
||||
}
|
||||
if(m_posVert==0 || !menuTab) {
|
||||
|
@ -219,7 +331,7 @@ bool check(uint8_t event, uint8_t curr, MenuFuncP *menuTab, uint8_t menuTabSize,
|
|||
case EVT_KEY_REPT(KEY_RIGHT): //inc
|
||||
if(m_posHorz==maxcol) break;
|
||||
case EVT_KEY_FIRST(KEY_RIGHT)://inc
|
||||
if(!horTab || s_editMode)break;
|
||||
if(!horTab || s_editMode>0)break;
|
||||
INC(m_posHorz,maxcol);
|
||||
BLINK_SYNC;
|
||||
break;
|
||||
|
@ -227,7 +339,7 @@ bool check(uint8_t event, uint8_t curr, MenuFuncP *menuTab, uint8_t menuTabSize,
|
|||
case EVT_KEY_REPT(KEY_LEFT): //dec
|
||||
if(m_posHorz==0) break;
|
||||
case EVT_KEY_FIRST(KEY_LEFT)://dec
|
||||
if(!horTab || s_editMode)break;
|
||||
if(!horTab || s_editMode>0)break;
|
||||
DEC(m_posHorz,maxcol);
|
||||
BLINK_SYNC;
|
||||
break;
|
||||
|
@ -235,7 +347,7 @@ bool check(uint8_t event, uint8_t curr, MenuFuncP *menuTab, uint8_t menuTabSize,
|
|||
case EVT_KEY_REPT(KEY_DOWN): //inc
|
||||
if(m_posVert==maxrow) break;
|
||||
case EVT_KEY_FIRST(KEY_DOWN): //inc
|
||||
if(s_editMode)break;
|
||||
if(s_editMode>0)break;
|
||||
do {
|
||||
INC(m_posVert,maxrow);
|
||||
} while(MAXCOL(m_posVert) == (uint8_t)-1);
|
||||
|
@ -246,7 +358,7 @@ bool check(uint8_t event, uint8_t curr, MenuFuncP *menuTab, uint8_t menuTabSize,
|
|||
case EVT_KEY_REPT(KEY_UP): //dec
|
||||
if(m_posVert==0) break;
|
||||
case EVT_KEY_FIRST(KEY_UP): //dec
|
||||
if(s_editMode)break;
|
||||
if(s_editMode>0)break;
|
||||
do {
|
||||
DEC(m_posVert,maxrow);
|
||||
} while(MAXCOL(m_posVert) == (uint8_t)-1);
|
||||
|
|
|
@ -69,9 +69,14 @@ void menuProcModelSelect(uint8_t event);
|
|||
void menuProcStatistic(uint8_t event);
|
||||
void menuProcStatistic2(uint8_t event);
|
||||
|
||||
#if defined(NAVIGATION_POT1) || defined(NAVIGATION_RE1)
|
||||
extern int16_t p1valdiff;
|
||||
#else
|
||||
#define p1valdiff 0
|
||||
#endif
|
||||
|
||||
extern int8_t checkIncDec_Ret; // global helper vars
|
||||
extern uint8_t s_editMode; // global editmode
|
||||
extern int8_t s_editMode; // global editmode
|
||||
|
||||
int16_t checkIncDec(uint8_t event, int16_t i_pval, int16_t i_min, int16_t i_max, uint8_t i_flags);
|
||||
int8_t checkIncDecModel(uint8_t event, int8_t i_val, int8_t i_min, int8_t i_max);
|
||||
|
|
|
@ -345,7 +345,7 @@ void menuProcModelSelect(uint8_t event)
|
|||
void EditName(uint8_t x, uint8_t y, char *name, uint8_t size, uint8_t event, bool active, uint8_t & cur)
|
||||
{
|
||||
if (active) {
|
||||
if (s_editMode) {
|
||||
if (s_editMode>0) {
|
||||
switch(event) {
|
||||
case EVT_KEY_BREAK(KEY_LEFT):
|
||||
if (cur>0) cur--;
|
||||
|
@ -360,8 +360,8 @@ void EditName(uint8_t x, uint8_t y, char *name, uint8_t size, uint8_t event, boo
|
|||
}
|
||||
}
|
||||
|
||||
lcd_putsnAtt(x, y, name, size, ZCHAR | (active ? (s_editMode ? 0 : INVERS) : 0));
|
||||
if (active && s_editMode) {
|
||||
lcd_putsnAtt(x, y, name, size, ZCHAR | (active ? ((s_editMode>0) ? 0 : INVERS) : 0));
|
||||
if (active && s_editMode>0) {
|
||||
char c = name[cur];
|
||||
char v = c;
|
||||
if (p1valdiff || event==EVT_KEY_FIRST(KEY_DOWN) || event==EVT_KEY_FIRST(KEY_UP)
|
||||
|
@ -402,12 +402,12 @@ void menuProcModel(uint8_t event)
|
|||
for (uint8_t i=0; i<2; i++, timer=&g_model.timer2) {
|
||||
if (s_pgOfs<subN) {
|
||||
lcd_putsnAtt(0*FW, y, PSTR("Timer1Timer2")+6*i, 6, 0);
|
||||
putsTmrMode(PARAM_OFS, y, timer->mode, sub==subN && m_posHorz==0 ? (s_editMode ? BLINK : INVERS) : 0);
|
||||
putsTmrMode(PARAM_OFS, y, timer->mode, sub==subN && m_posHorz==0 ? ((s_editMode>0) ? BLINK : INVERS) : 0);
|
||||
putsTime(14*FW-3, y, timer->val,
|
||||
(sub==subN && m_posHorz==1 ? (s_editMode ? BLINK : INVERS):0),
|
||||
(sub==subN && m_posHorz==2 ? (s_editMode ? BLINK : INVERS):0) );
|
||||
lcd_putsnAtt(19*FW, y, PSTR("\x7e\x7f")+1-timer->dir,1,sub==subN && m_posHorz==3 ? (s_editMode ? BLINK : INVERS) : 0);
|
||||
if (sub==subN && (s_editMode || p1valdiff)) {
|
||||
(sub==subN && m_posHorz==1 ? ((s_editMode>0) ? BLINK : INVERS):0),
|
||||
(sub==subN && m_posHorz==2 ? ((s_editMode>0) ? BLINK : INVERS):0) );
|
||||
lcd_putsnAtt(19*FW, y, PSTR("\x7e\x7f")+1-timer->dir,1,sub==subN && m_posHorz==3 ? ((s_editMode>0) ? BLINK : INVERS) : 0);
|
||||
if (sub==subN && (s_editMode>0 || p1valdiff)) {
|
||||
switch (m_posHorz) {
|
||||
case 0:
|
||||
CHECK_INCDEC_MODELVAR(event, timer->mode, -(13+2*MAX_SWITCH),(13+2*MAX_SWITCH));
|
||||
|
@ -461,7 +461,7 @@ void menuProcModel(uint8_t event)
|
|||
lcd_puts_P( 0, y, PSTR("T-Trim"));
|
||||
menu_lcd_onoff(PARAM_OFS, y, g_model.thrTrim, sub==subN && m_posHorz==0) ;
|
||||
lcd_putsnAtt(PARAM_OFS+4*FW, y, PSTR("LinearExp ")+6*g_model.thrExpo,6,(sub==subN && m_posHorz==1) ? INVERS : 0);
|
||||
if (sub==subN && (s_editMode || p1valdiff)) {
|
||||
if (sub==subN && (s_editMode>0 || p1valdiff)) {
|
||||
switch (m_posHorz) {
|
||||
case 0:
|
||||
CHECK_INCDEC_MODELVAR(event,g_model.thrTrim,0,1);
|
||||
|
@ -480,7 +480,7 @@ void menuProcModel(uint8_t event)
|
|||
if(sub==subN){
|
||||
if((event==EVT_KEY_FIRST(KEY_MENU)) || p1valdiff) {
|
||||
killEvents(event);
|
||||
s_editMode = false;
|
||||
s_editMode = 0;
|
||||
g_model.beepANACenter ^= (1<<m_posHorz);
|
||||
STORE_MODELVARS;
|
||||
}
|
||||
|
@ -491,16 +491,16 @@ void menuProcModel(uint8_t event)
|
|||
if(s_pgOfs<subN) {
|
||||
lcd_puts_P(0, y, PSTR("Proto"));
|
||||
lcd_putsnAtt(PARAM_OFS, y, PSTR(PROT_STR)+PROT_STR_LEN*g_model.protocol,PROT_STR_LEN,
|
||||
(sub==subN && m_posHorz==0 ? (s_editMode ? BLINK : INVERS):0));
|
||||
(sub==subN && m_posHorz==0 ? (s_editMode>0 ? BLINK : INVERS):0));
|
||||
if(!g_model.protocol) {
|
||||
lcd_putsnAtt(PARAM_OFS+4*FW, y, PSTR("4CH 6CH 8CH 10CH12CH14CH16CH")+4*(g_model.ppmNCH+2),4,(sub==subN && m_posHorz==1 ? (s_editMode ? BLINK : INVERS):0));
|
||||
lcd_putsnAtt(PARAM_OFS+4*FW, y, PSTR("4CH 6CH 8CH 10CH12CH14CH16CH")+4*(g_model.ppmNCH+2),4,(sub==subN && m_posHorz==1 ? ((s_editMode>0) ? BLINK : INVERS):0));
|
||||
lcd_putsAtt(PARAM_OFS+11*FW, y, PSTR("u"),0);
|
||||
lcd_outdezAtt(PARAM_OFS+11*FW, y, (g_model.ppmDelay*50)+300, (sub==subN && m_posHorz==2 ? (s_editMode ? BLINK : INVERS):0));
|
||||
lcd_outdezAtt(PARAM_OFS+11*FW, y, (g_model.ppmDelay*50)+300, (sub==subN && m_posHorz==2 ? ((s_editMode>0) ? BLINK : INVERS):0));
|
||||
}
|
||||
else if (sub==subN) {
|
||||
m_posHorz = 0;
|
||||
}
|
||||
if (sub==subN && (s_editMode || p1valdiff || !g_model.protocol)) {
|
||||
if (sub==subN && (s_editMode>0 || p1valdiff || !g_model.protocol)) {
|
||||
switch (m_posHorz) {
|
||||
case 0:
|
||||
CHECK_INCDEC_MODELVAR(event,g_model.protocol,0,PROT_MAX);
|
||||
|
@ -521,8 +521,8 @@ void menuProcModel(uint8_t event)
|
|||
lcd_puts_P(0, y, PSTR("PPM frame"));
|
||||
lcd_puts_P(PARAM_OFS+3*FW, y, PSTR("ms"));
|
||||
lcd_outdezAtt(PARAM_OFS, y, (int16_t)g_model.ppmFrameLength*5 + 225, ((sub==subN && m_posHorz==0) ? INVERS:0) | PREC1|LEFT);
|
||||
lcd_putsnAtt(PARAM_OFS+6*FW, y, PSTR("POSNEG")+3*g_model.pulsePol,3,(sub==subN && m_posHorz==1 ? (s_editMode ? BLINK : INVERS):0));
|
||||
if(sub==subN && (s_editMode || p1valdiff)) {
|
||||
lcd_putsnAtt(PARAM_OFS+6*FW, y, PSTR("POSNEG")+3*g_model.pulsePol,3,(sub==subN && m_posHorz==1 ? ((s_editMode>0) ? BLINK : INVERS):0));
|
||||
if(sub==subN && (s_editMode>0 || p1valdiff)) {
|
||||
switch (m_posHorz) {
|
||||
case 0:
|
||||
CHECK_INCDEC_MODELVAR(event, g_model.ppmFrameLength, -20, 20);
|
||||
|
@ -570,13 +570,13 @@ void menuProcPhaseOne(uint8_t event)
|
|||
if (v > TRIM_EXTENDED_MAX) {
|
||||
uint8_t p = v - TRIM_EXTENDED_MAX - 1;
|
||||
if (p >= s_currIdx) p++;
|
||||
lcd_putcAtt((10+t)*FW, y, '0'+p, (attr && m_posHorz==t) ? (s_editMode ? BLINK : INVERS) : 0);
|
||||
lcd_putcAtt((10+t)*FW, y, '0'+p, (attr && m_posHorz==t) ? ((s_editMode>0) ? BLINK : INVERS) : 0);
|
||||
}
|
||||
else {
|
||||
v = TRIM_EXTENDED_MAX;
|
||||
putsChnLetter((10+t)*FW, y, t+1, (attr && m_posHorz==t) ? (s_editMode ? BLINK : INVERS) : 0);
|
||||
putsChnLetter((10+t)*FW, y, t+1, (attr && m_posHorz==t) ? ((s_editMode>0) ? BLINK : INVERS) : 0);
|
||||
}
|
||||
if (attr && m_posHorz==t && (s_editMode || p1valdiff)) {
|
||||
if (attr && m_posHorz==t && ((s_editMode>0) || p1valdiff)) {
|
||||
v = checkIncDec(event, v, TRIM_EXTENDED_MAX, TRIM_EXTENDED_MAX+MAX_PHASES-1, EE_MODEL);
|
||||
if (checkIncDec_Ret) {
|
||||
if (v == TRIM_EXTENDED_MAX) v = 0;
|
||||
|
@ -763,10 +763,10 @@ void menuProcCurveOne(uint8_t event)
|
|||
autoThrStep = 0;
|
||||
break;
|
||||
case EVT_KEY_FIRST(KEY_MENU):
|
||||
if (!s_editMode) {
|
||||
if (s_editMode<=0) {
|
||||
switch (m_posHorz) {
|
||||
case 0:
|
||||
s_editMode = true;
|
||||
s_editMode = 1;
|
||||
break;
|
||||
case 1:
|
||||
if (++dfltCrv > 4)
|
||||
|
@ -787,9 +787,9 @@ void menuProcCurveOne(uint8_t event)
|
|||
if (autoThrStep) {
|
||||
autoThrStep = 0;
|
||||
}
|
||||
else if (s_editMode) {
|
||||
else if (s_editMode>0) {
|
||||
m_posHorz = 0;
|
||||
s_editMode = false;
|
||||
s_editMode = 0;
|
||||
}
|
||||
else {
|
||||
popMenu();
|
||||
|
@ -801,7 +801,7 @@ void menuProcCurveOne(uint8_t event)
|
|||
break;
|
||||
case EVT_KEY_REPT(KEY_RIGHT):
|
||||
case EVT_KEY_FIRST(KEY_RIGHT):
|
||||
if (!autoThrStep && m_posHorz<(s_editMode ? points-1 : ((g_menuStack[g_menuStackPtr-1] == menuProcExpoOne && IS_THROTTLE(expoaddress(s_currIdx)->chn)) ? 2 : 1))) m_posHorz++;
|
||||
if (!autoThrStep && m_posHorz<((s_editMode>0) ? points-1 : ((g_menuStack[g_menuStackPtr-1] == menuProcExpoOne && IS_THROTTLE(expoaddress(s_currIdx)->chn)) ? 2 : 1))) m_posHorz++;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -813,14 +813,14 @@ void menuProcCurveOne(uint8_t event)
|
|||
else {
|
||||
x = 4*FW; y = (i+1) * FH;
|
||||
}
|
||||
uint8_t attr = (s_editMode && m_posHorz == i) ? INVERS : 0;
|
||||
uint8_t attr = (s_editMode>0 && m_posHorz==i) ? INVERS : 0;
|
||||
lcd_outdezAtt(x, y, crv[i], attr);
|
||||
}
|
||||
|
||||
lcd_puts_P(0*FW, 7*FH, PSTR("MODE"));
|
||||
lcd_putsnAtt(5*FW-2, 7*FH, PSTR("EDIT ""PRSET""A.THR")+5*(!s_editMode)*m_posHorz, 5, s_editMode || autoThrStep ? 0 : INVERS);
|
||||
lcd_putsnAtt(5*FW-2, 7*FH, PSTR("EDIT ""PRSET""A.THR")+5*(s_editMode<=0)*m_posHorz, 5, s_editMode>0 || autoThrStep ? 0 : INVERS);
|
||||
|
||||
if (s_editMode || autoThrStep) {
|
||||
if (s_editMode>0 || autoThrStep) {
|
||||
for (uint8_t i=0; i<points; i++) {
|
||||
uint8_t xx = X0-1-WCHART+i*WCHART/(points/2);
|
||||
uint8_t yy = (DISPLAY_H-1) - (100 + crv[i]) * (DISPLAY_H-1) / 200;
|
||||
|
@ -1478,8 +1478,8 @@ void menuProcLimits(uint8_t event)
|
|||
putsChn(0,y,k+1,0);
|
||||
lcd_putcAtt(12*FW+FW/2, y, (swVal[k] ? 127 : 126),0); //'<' : '>'
|
||||
for (uint8_t j=0; j<4; j++) {
|
||||
uint8_t attr = ((sub==k && m_posHorz==j) ? (s_editMode ? BLINK : INVERS) : 0);
|
||||
uint8_t active = (attr && (s_editMode || p1valdiff)) ;
|
||||
uint8_t attr = ((sub==k && m_posHorz==j) ? ((s_editMode>0) ? BLINK : INVERS) : 0);
|
||||
uint8_t active = (attr && (s_editMode>0 || p1valdiff)) ;
|
||||
switch(j)
|
||||
{
|
||||
case 0:
|
||||
|
@ -1490,7 +1490,7 @@ void menuProcLimits(uint8_t event)
|
|||
else if (attr && event==EVT_KEY_LONG(KEY_MENU)) {
|
||||
int16_t zero = g_chans512[k];
|
||||
ld->offset = (ld->revert) ? -zero : zero;
|
||||
s_editMode = false;
|
||||
s_editMode = 0;
|
||||
STORE_MODELVARS;
|
||||
}
|
||||
break;
|
||||
|
@ -1583,7 +1583,7 @@ void menuProcCustomSwitches(uint8_t event)
|
|||
y=(i+1)*FH;
|
||||
k=i+s_pgOfs;
|
||||
if(k==NUM_CSW) break;
|
||||
uint8_t attr = (sub==k ? (s_editMode ? BLINK : INVERS) : 0);
|
||||
uint8_t attr = (sub==k ? ((s_editMode>0) ? BLINK : INVERS) : 0);
|
||||
CustomSwData &cs = g_model.customSw[k];
|
||||
|
||||
//write SW names here
|
||||
|
@ -1614,7 +1614,7 @@ void menuProcCustomSwitches(uint8_t event)
|
|||
putsChnRaw( 17*FW, y, cs.v2 ,m_posHorz==2 ? attr : 0);
|
||||
}
|
||||
|
||||
if((s_editMode || p1valdiff) && attr)
|
||||
if((s_editMode>0 || p1valdiff) && attr)
|
||||
switch (m_posHorz) {
|
||||
case 0:
|
||||
CHECK_INCDEC_MODELVAR( event, cs.func, 0,CS_MAXF);
|
||||
|
@ -1671,8 +1671,8 @@ void menuProcFunctionSwitches(uint8_t event)
|
|||
if(k==NUM_CHNOUT) break;
|
||||
FuncSwData *sd = &g_model.funcSw[k];
|
||||
for (uint8_t j=0; j<2; j++) {
|
||||
uint8_t attr = ((sub==k && m_posHorz==j) ? (s_editMode ? BLINK : INVERS) : 0);
|
||||
uint8_t active = (attr && (s_editMode || p1valdiff));
|
||||
uint8_t attr = ((sub==k && m_posHorz==j) ? ((s_editMode>0) ? BLINK : INVERS) : 0);
|
||||
uint8_t active = (attr && (s_editMode>0 || p1valdiff));
|
||||
switch (j) {
|
||||
case 0:
|
||||
putsSwitches(1*FW, y, sd->swtch, attr);
|
||||
|
@ -1710,8 +1710,8 @@ void menuProcSafetySwitches(uint8_t event)
|
|||
SafetySwData *sd = &g_model.safetySw[k];
|
||||
putsChn(0,y,k+1,0);
|
||||
for(uint8_t j=0; j<=2;j++){
|
||||
uint8_t attr = ((m_posVert-1==k && m_posHorz==j) ? (s_editMode ? BLINK : INVERS) : 0);
|
||||
uint8_t active = (attr && (s_editMode || p1valdiff));
|
||||
uint8_t attr = ((m_posVert-1==k && m_posHorz==j) ? ((s_editMode>0) ? BLINK : INVERS) : 0);
|
||||
uint8_t active = (attr && (s_editMode>0 || p1valdiff));
|
||||
switch(j)
|
||||
{
|
||||
case 0:
|
||||
|
@ -1745,11 +1745,11 @@ void menuProcTelemetry(uint8_t event)
|
|||
case EVT_KEY_BREAK(KEY_UP):
|
||||
case EVT_KEY_BREAK(KEY_LEFT):
|
||||
case EVT_KEY_BREAK(KEY_RIGHT):
|
||||
if(s_editMode) // only fr-sky alarm fields have an edit mode
|
||||
if (s_editMode>0) // only fr-sky alarm fields have an edit mode
|
||||
FRSKY_setModelAlarms(); // update Fr-Sky module when edit mode exited
|
||||
}
|
||||
|
||||
blink = s_editMode ? BLINK : INVERS ;
|
||||
blink = (s_editMode>0) ? BLINK : INVERS ;
|
||||
uint8_t subN = 1;
|
||||
uint8_t t;
|
||||
int16_t val;
|
||||
|
@ -1767,7 +1767,7 @@ void menuProcTelemetry(uint8_t event)
|
|||
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);
|
||||
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 || p1valdiff)) {
|
||||
if (sub==subN && (s_editMode>0 || p1valdiff)) {
|
||||
if (m_posHorz == 0)
|
||||
g_model.frsky.channels[i].ratio = checkIncDec(event, g_model.frsky.channels[i].ratio, 0, 255, EE_MODEL);
|
||||
else
|
||||
|
@ -1792,8 +1792,8 @@ void menuProcTelemetry(uint8_t event)
|
|||
putsTelemetry(8*FW, y, val, g_model.frsky.channels[i].type, (sub==subN && m_posHorz==0 ? 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 || 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 || p1valdiff)) g_model.frsky.channels[i].barMax = checkIncDec(event, g_model.frsky.channels[i].barMax, 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);
|
||||
}
|
||||
subN++;
|
||||
|
||||
|
@ -1806,7 +1806,7 @@ void menuProcTelemetry(uint8_t event)
|
|||
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);
|
||||
|
||||
if(sub==subN && (s_editMode || p1valdiff)) {
|
||||
if(sub==subN && (s_editMode>0 || p1valdiff)) {
|
||||
switch (m_posHorz) {
|
||||
case 0:
|
||||
t = ALARM_LEVEL(i, j);
|
||||
|
|
16
src/rtc.cpp
16
src/rtc.cpp
|
@ -22,19 +22,23 @@
|
|||
/*--------------------------------------------------------------------------*/
|
||||
/* RTC controls */
|
||||
|
||||
#include <avr/io.h>
|
||||
#include <string.h>
|
||||
#include "rtc.h"
|
||||
|
||||
|
||||
#include "gruvin9x.h"
|
||||
|
||||
#if defined (PCBV4)
|
||||
#define SCL_LOW() DDRD |= 0x01 /* SCL = LOW */
|
||||
#define SCL_HIGH() DDRD &= ~0x01 /* SCL = High-Z */
|
||||
#define SCL_VAL ((PIND & 0x01) ? 1 : 0) /* SCL input level */
|
||||
#define SDA_LOW() DDRD |= 0x02 /* SDA = LOW */
|
||||
#define SDA_HIGH() DDRD &= ~0x02 /* SDA = High-Z */
|
||||
#define SDA_VAL ((PIND & 0x02) ? 1 : 0) /* SDA input level */
|
||||
#else // PCBV3
|
||||
#define SCL_LOW() DDRB |= 0x20 /* SCL = LOW */
|
||||
#define SCL_HIGH() DDRB &= ~0x20 /* SCL = High-Z */
|
||||
#define SCL_VAL ((PINB & 0x20) ? 1 : 0) /* SCL input level */
|
||||
#define SDA_LOW() DDRB |= 0x40 /* SDA = LOW */
|
||||
#define SDA_HIGH() DDRB &= ~0x40 /* SDA = High-Z */
|
||||
#define SDA_VAL ((PINB & 0x40) ? 1 : 0) /* SDA input level */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*-------------------------------------------------*/
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include "gruvin9x.h"
|
||||
#include "menus.h"
|
||||
|
||||
volatile unsigned char pinb=0, pinc=0xff, pind, pine=0xff, ping=0xff;
|
||||
volatile unsigned char pinb=0, pinc=0xff, pind, pine=0xff, ping=0xff, pinj=0xff, pinl=0;
|
||||
unsigned char portb, dummyport;
|
||||
const char *eepromFile = "eeprom.bin";
|
||||
|
||||
|
|
|
@ -39,6 +39,9 @@ typedef const int8_t prog_int8_t;
|
|||
|
||||
extern sem_t eeprom_write_sem;
|
||||
|
||||
#define loop_until_bit_is_set( port, bitnum) \
|
||||
while ( 0/*! ( (port) & (1 << (bitnum)) )*/ ) ;
|
||||
|
||||
#define PROGMEM
|
||||
#define pgm_read_byte(address_short) (*(uint8_t*)(address_short))
|
||||
#define pgm_read_word(address_short) (*(uint16_t*)(address_short))
|
||||
|
@ -70,6 +73,8 @@ extern sem_t eeprom_write_sem;
|
|||
#define PIND ~pind
|
||||
#define PINE ~pine
|
||||
#define PING ~ping
|
||||
#define PINJ ~pinj
|
||||
#define PINL ~pinl
|
||||
#define EEMEM
|
||||
|
||||
#define UCSR0B dummyport
|
||||
|
@ -79,8 +84,38 @@ extern sem_t eeprom_write_sem;
|
|||
#define DDE0 dummyport
|
||||
#define PORTE0 dummyport
|
||||
#define RXCIE0 dummyport
|
||||
#define OCR0A dummyport
|
||||
|
||||
extern volatile unsigned char pinb,pinc,pind,pine,ping;
|
||||
#define SPDR dummyport
|
||||
#define SPSR dummyport
|
||||
#define SPIF dummyport
|
||||
#define SPCR dummyport
|
||||
|
||||
#define OUT_B_LIGHT 7
|
||||
#define INP_E_ElevDR 2
|
||||
#define INP_E_Trainer 5
|
||||
#define INP_E_Gear 4
|
||||
#define INP_C_ThrCt 6
|
||||
#define INP_C_AileDR 7
|
||||
#define INP_E_ID2 6
|
||||
|
||||
#define INP_B_KEY_LFT 6
|
||||
#define INP_B_KEY_RGT 5
|
||||
#define INP_B_KEY_UP 4
|
||||
#define INP_B_KEY_DWN 3
|
||||
#define INP_B_KEY_EXT 2
|
||||
#define INP_B_KEY_MEN 1
|
||||
|
||||
#define INP_P_SPARE6 7
|
||||
#define INP_P_SPARE5 6
|
||||
#define INP_P_KEY_EXT 5
|
||||
#define INP_P_KEY_MEN 4
|
||||
#define INP_P_KEY_LFT 3
|
||||
#define INP_P_KEY_RGT 2
|
||||
#define INP_P_KEY_UP 1
|
||||
#define INP_P_KEY_DWN 0
|
||||
|
||||
extern volatile unsigned char pinb,pinc,pind,pine,ping,pinj,pinl;
|
||||
extern unsigned char portb,dummyport;
|
||||
|
||||
void InitEepromThread();
|
||||
|
|
28
src/simu.cpp
28
src/simu.cpp
|
@ -269,21 +269,25 @@ void Gruvin9xSim::refreshDiplay()
|
|||
|
||||
if(hasFocus()) {
|
||||
static FXuint keys1[]={
|
||||
KEY_Return, INP_B_KEY_MEN,
|
||||
KEY_Page_Up, INP_B_KEY_MEN,
|
||||
KEY_KP_1, INP_B_KEY_MEN,
|
||||
KEY_Page_Down, INP_B_KEY_EXT,
|
||||
KEY_BackSpace, INP_B_KEY_EXT,
|
||||
KEY_KP_0, INP_B_KEY_EXT,
|
||||
KEY_Down, INP_B_KEY_DWN,
|
||||
KEY_Up, INP_B_KEY_UP,
|
||||
KEY_Right, INP_B_KEY_RGT,
|
||||
KEY_Left, INP_B_KEY_LFT
|
||||
KEY_Return, INP_B_KEY_MEN, INP_P_KEY_MEN,
|
||||
KEY_Page_Up, INP_B_KEY_MEN, INP_P_KEY_MEN,
|
||||
KEY_KP_1, INP_B_KEY_MEN, INP_P_KEY_MEN,
|
||||
KEY_Page_Down, INP_B_KEY_EXT, INP_P_KEY_EXT,
|
||||
KEY_BackSpace, INP_B_KEY_EXT, INP_P_KEY_EXT,
|
||||
KEY_KP_0, INP_B_KEY_EXT, INP_P_KEY_EXT,
|
||||
KEY_Down, INP_B_KEY_DWN, INP_P_KEY_DWN,
|
||||
KEY_Up, INP_B_KEY_UP, INP_P_KEY_UP,
|
||||
KEY_Right, INP_B_KEY_RGT, INP_P_KEY_RGT,
|
||||
KEY_Left, INP_B_KEY_LFT, INP_P_KEY_LFT
|
||||
};
|
||||
|
||||
pinb &= ~ 0x7e;
|
||||
for(unsigned i=0; i<DIM(keys1);i+=2){
|
||||
if(getApp()->getKeyState(keys1[i])) pinb |= (1<<keys1[i+1]);
|
||||
pinl &= ~ 0x3f; // for v4
|
||||
for(unsigned i=0; i<DIM(keys1);i+=3) {
|
||||
if (getApp()->getKeyState(keys1[i])) {
|
||||
pinb |= (1<<keys1[i+1]);
|
||||
pinl |= (1<<keys1[i+2]);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue