[sky9x] RTC Clock on FAT (not tested)

[gruvin9x] RTC Menu redesigned
[stock] ~50bytes flash saved
This commit is contained in:
bsongis
2012-10-01 19:58:10 +00:00
parent 18f06e8395
commit 002447dbb5
18 changed files with 855 additions and 810 deletions
+4 -475
View File
@@ -31,488 +31,17 @@
*
*/
#include "ff.h"
#include "fattime.h"
#include "integer.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 (gtime_t)
#endif
#ifndef TIME_T_MAX
# define TIME_T_MAX TYPE_MAXIMUM (gtime_t)
#endif
#define TIME_T_MIDPOINT (SHR (TIME_T_MIN + TIME_T_MAX, 1) + 1)
/* Verify a requirement at compile-time (unlike assert, which is runtime). */
#define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; }
verify (gtime_t_is_integer, TYPE_IS_INTEGER (gtime_t));
verify (twos_complement_arithmetic, TYPE_TWOS_COMPLEMENT (int));
/* The code also assumes that signed integer overflow silently wraps
around, but this assumption can't be stated without causing a
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
/* 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 (
gtime_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 >= (long int)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 gtime_t to struct tm
struct gtm *
__localtime_r (gtime_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 gtime_t
ydhms_diff (long int year1, long int yday1, int hour1, int min1, int sec1,
int year0, int yday0, int hour0, int min0, int sec0)
{
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 gtime_t precision. Overflow might
occur here. */
gtime_t tyear1 = year1;
gtime_t years = tyear1 - year0;
gtime_t days = 365 * years + yday1 - yday0 + intervening_leap_days;
gtime_t hours = 24 * days + hour1 - hour0;
gtime_t minutes = 60 * hours + min1 - min0;
gtime_t seconds = 60 * minutes + sec1 - sec0;
return seconds;
}
/* Return a gtime_t value corresponding to (YEAR-YDAY HOUR:MIN:SEC),
assuming that *T corresponds to *TP and that no clock adjustments
occurred between *TP and the desired time.
If TP is null, return a value not equal to *T; this avoids false matches.
If overflow occurs, yield the minimal or maximal value, except do not
yield a value equal to *T. */
static gtime_t
guess_time_tm (long int year, long int yday, int hour, int min, int sec,
gtime_t *t, struct gtm *tp)
{
if (tp)
{
gtime_t d = ydhms_diff (year, yday, hour, min, sec,
tp->tm_year, tp->tm_yday,
tp->tm_hour, tp->tm_min, tp->tm_sec);
gtime_t t1 = *t + d;
if ((t1 < *t) == (TYPE_SIGNED (gtime_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) (gtime_t *, struct gtm *),
gtime_t *t, struct gtm *tp)
{
struct gtm *r = convert (t, tp);
if (!r && *t)
{
gtime_t bad = *t;
gtime_t ok = 0;
/* BAD is a known unconvertible gtime_t, and OK is a known good one.
Use binary search to narrow the range between BAD and OK until
they differ by 1. */
while (bad != ok + (bad < 0 ? -1 : 1))
{
gtime_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 gtime_t value, inverting
the monotonic and mostly-unit-linear conversion function CONVERT.
Use *OFFSET to keep track of a guess at the offset of the result,
compared to what the result would be for UTC without leap seconds.
If *OFFSET's guess is correct, only one CONVERT call is needed.
This function is external because it is used also by timegm.c. */
gtime_t
__mktime_internal (struct gtm *tp,
struct gtm *(*convert) (gtime_t *, struct gtm *),
gtime_t *offset)
{
gtime_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 gtime_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;
gtime_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)
{
/* gtime_t isn't large enough to rule out overflows, so check
for major overflows. A gross check suffices, since if t0
has overflowed, it is off by a multiple of TIME_T_MAX -
TIME_T_MIN + 1. So ignore any component of the difference
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) */
gtime_t time_t_max = TIME_T_MAX;
gtime_t time_t_min = TIME_T_MIN;
gtime_t overflow_threshold =
(time_t_max / 3 - time_t_min / 3) >> ALOG2_SECONDS_PER_BIENNIUM;
if (overflow_threshold < abs_diff)
{
/* Overflow occurred. Try repairing it; this might work if
the time zone offset is enough to undo the overflow. */
gtime_t repaired_t0 = -1 - t0;
approx_biennia = SHR (repaired_t0, ALOG2_SECONDS_PER_BIENNIUM);
diff = approx_biennia - approx_requested_biennia;
abs_diff = diff < 0 ? - diff : diff;
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 gtime_t value. */
gtime_t
gmktime (struct gtm *tp)
{
// no time zone stuff. Just do the math ;)
static gtime_t localtime_offset;
return __mktime_internal (tp, __localtime_r, &localtime_offset);
}
/* Fill a (struct tm) TP* from a given gtime_t time stamp */
gtime_t
filltm(gtime_t *t, struct gtm *tp)
{
return __offtime(t, 0, tp);
}
/*---------------------------------------------------------*/
/* 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. */
gtime_t g_unixTime; // Global date/time register, incremented each second in per10ms()
#include "../rtc.h"
DWORD get_fattime(void)
{
struct gtm t;
filltm(&g_unixTime, &t); // create a struct tm date/time structure from global unix time stamp
gettime(&t);
/* Pack date and time into a DWORD variable */
return ((DWORD)(t.tm_year - 80) << 25)
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)
+6 -4
View File
@@ -464,9 +464,9 @@ endif
ifeq ($(PCB), ARM)
# ARM, so ...
OPT = 2
CPPDEFS += -DPCBARM -DAUDIO -DHAPTIC -DPXX -DDSM2 -DDSM2_PPM -DROTARY_ENCODERS=1
CPPDEFS += -DPCBARM -DAUDIO -DHAPTIC -DRTCLOCK -DPXX -DDSM2 -DDSM2_PPM -DROTARY_ENCODERS=1
EXTRAINCDIRS += ersky9x CoOS/kernel CoOS/portable
BOARDSRC = board_ersky9x.cpp
BOARDSRC = board_ersky9x.cpp
SRC += ersky9x/core_cm3.c ersky9x/board_lowlevel.c ersky9x/crt.c ersky9x/vectors_sam3s.c
SRC += CoOS/kernel/core.c CoOS/kernel/hook.c CoOS/kernel/task.c CoOS/kernel/event.c CoOS/kernel/time.c CoOS/kernel/timer.c CoOS/kernel/flag.c CoOS/kernel/mutex.c CoOS/kernel/serviceReq.c CoOS/portable/GCC/port.c CoOS/portable/arch.c
SRC += ersky9x/usb/device/core/USBD_UDP.c ersky9x/usb/device/core/USBDDriver.c ersky9x/usb/device/core/USBDCallbacks.c
@@ -476,6 +476,7 @@ ifeq ($(PCB), ARM)
SRC += ersky9x/MEDSdcard.c
EEPROMSRC = eeprom_arm.cpp
PULSESSRC = pulses_arm.cpp
CPPSRC += rtc.cpp ersky9x/rtc_driver.cpp
CPPSRC += ersky9x/audio.cpp haptic.cpp
CPPSRC += ersky9x/sound_driver.cpp ersky9x/haptic_driver.cpp ersky9x/sdcard_driver.cpp ersky9x/massstorage.cpp
@@ -506,8 +507,9 @@ ifeq ($(PCB), V4)
CPPSRC += stock/audio.cpp haptic.cpp
ifeq ($(SDCARD), YES)
CPPSRC += FatFs/fattime.c gruvin9x/rtc.cpp gruvin9x/diskio.cpp
EXTRABOARDSRC += FatFs/ff.c FatFs/option/ccsbcs.c
CPPDEFS += -DRTCLOCK
CPPSRC += rtc.cpp gruvin9x/rtc_driver.cpp gruvin9x/diskio.cpp
EXTRABOARDSRC += FatFs/ff.c FatFs/fattime.c FatFs/option/ccsbcs.c
endif
ifeq ($(VOICE), YES)
+2
View File
@@ -792,6 +792,8 @@ void board_init()
alawInit();
rtc_init();
eeprom_init();
init_rotary_encoder();
+2 -16
View File
@@ -33,10 +33,6 @@
#include "open9x.h"
#ifdef SDCARD
uint8_t g_ms100 = 0; // global to allow time set function to reset to zero
#endif
#ifndef SIMU
inline void board_init()
{
@@ -76,19 +72,9 @@ inline void board_init()
TCCR0B = (1<<WGM02) | (0b011 << CS00);
TCCR0A = (0b01<<WGM00);
#if defined(SDCARD)
#if defined(RTCLOCK)
// Initialise global unix timestamp with current time from RTC chip on SD card interface
RTC rtc = {0,0,0,0,0,0,0};
struct gtm utm;
rtc_gettime(&rtc);
utm.tm_year = rtc.year - 1900;
utm.tm_mon = rtc.month - 1;
utm.tm_mday = rtc.mday;
utm.tm_hour = rtc.hour;
utm.tm_min = rtc.min;
utm.tm_sec = rtc.sec;
utm.tm_wday = rtc.wday - 1;
g_unixTime = gmktime(&utm);
rtc_init();
#endif
/***************************************************/
+2 -20
View File
@@ -31,26 +31,8 @@
*
*/
#ifndef RTC_H
#define RTC_H
#ifndef board_gruvin9x_h
#define board_gruvin9x_h
#include "../FatFs/integer.h"
typedef struct {
WORD year; /* 2000..2099 */
BYTE month; /* 1..12 */
BYTE mday; /* 1.. 31 */
BYTE wday; /* 1..7 */
BYTE hour; /* 0..23 */
BYTE min; /* 0..59 */
BYTE sec; /* 0..59 */
} RTC;
int iic_write (BYTE, UINT, UINT, const void*); /* Write to IIC device */
int iic_read (BYTE, UINT, UINT, void*); /* Read from IIC device */
int rtc_init (void); /* Initialize RTC */
int rtc_gettime (RTC*); /* Get time */
int rtc_settime (const RTC*); /* Set time */
#endif
+2 -2
View File
@@ -161,10 +161,10 @@ void per10ms()
Tenms |= 1 ; // 10 mS has passed
#endif
#if defined (PCBV4) && defined(SDCARD)
#if defined(RTCLOCK)
/* Update gloabal Date/Time every 100 per10ms cycles */
if (++g_ms100 == 100) {
g_unixTime++; // inc global unix timestamp one second
g_rtcTime++; // inc global unix timestamp one second
g_ms100 = 0;
}
#endif
+8 -8
View File
@@ -1303,6 +1303,8 @@ DSTATUS disk_status (
/* Read Sector(s) */
/*-----------------------------------------------------------------------*/
uint32_t dma_sd_buffer[512/4];
DRESULT disk_read (
BYTE drv, /* Physical drive nmuber (0) */
BYTE *buff, /* Pointer to the data buffer to store read data */
@@ -1311,16 +1313,15 @@ DRESULT disk_read (
)
{
uint32_t result ;
BYTE copy[512];
if (drv || !count) return RES_PARERR;
if ( sd_card_ready() == 0 ) return RES_NOTRDY;
do {
result = sd_read_block( sector, (uint32_t *)copy) ;
result = sd_read_block(sector, dma_sd_buffer) ;
if (result) {
memcpy(buff, copy, 512);
memcpy(buff, dma_sd_buffer, 512);
sector += 1 ;
buff += 512 ;
count -= 1 ;
@@ -1355,7 +1356,6 @@ DRESULT disk_write (
)
{
uint32_t result ;
BYTE copy[512];
if (drv || !count) return RES_PARERR;
@@ -1367,13 +1367,13 @@ DRESULT disk_write (
while (1) {
memcpy(copy, buff, 512);
memcpy(dma_sd_buffer, buff, 512);
result = sd_write_block( sector, ( uint32_t *)copy ) ;
result = sd_write_block(sector, dma_sd_buffer) ;
sd_read_block( sector, ( uint32_t *)copy ) ;
sd_read_block(sector, dma_sd_buffer) ;
if (!memcmp(copy, buff, 512))
if (!memcmp(dma_sd_buffer, buff, 512))
break;
else {
TRACE_ERROR("Block %d ko SR=%.2X\r\n", sector, HSMCI->HSMCI_SR);
+61
View File
@@ -0,0 +1,61 @@
/*
* Authors (alphabetical order)
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Jean-Pierre Parisy
* - Karl Szmutny <shadow@privy.de>
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* open9x is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and 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 "../open9x.h"
struct t_i2cTime
{
uint8_t setCode ;
uint8_t Time[7] ;
} I2CTime ;
void rtc_settime(struct gtm * t)
{
g_rtcTime = gmktime(t); // update local timestamp and get wday calculated
g_ms100 = 0; // start of next second begins now
I2CTime.setCode = 0x74 ; // Tiny SET TIME CODE command
I2CTime.Time[0] = t->tm_sec ;
I2CTime.Time[1] = t->tm_min ;
I2CTime.Time[2] = t->tm_hour ;
I2CTime.Time[3] = t->tm_mday ;
I2CTime.Time[4] = t->tm_mon+1 ;
I2CTime.Time[5] = (uint8_t) (t->tm_year+1900) ;
I2CTime.Time[6] = (t->tm_year+1900) >> 8 ;
write_coprocessor( (uint8_t *) &I2CTime, 8 ) ;
}
void rtc_init()
{
read_coprocessor();
}
+14 -15
View File
@@ -227,7 +227,7 @@ void init_twi()
NVIC_EnableIRQ(TWI0_IRQn) ;
setVolume(2) ;
}
extern t_time Time;
static int8_t Volume_required ;
static uint8_t Volume_read_pending ;
static uint8_t CoProc_read_pending ;
@@ -413,25 +413,24 @@ extern "C" void TWI0_IRQHandler()
{
Coproc_valid = 1 ;
Coproc_read = Co_proc_status[0] ;
if ( Coproc_read & 0x80 ) // Bootloader
{
if ( Coproc_read & 0x80 ) {
// Bootloader
CoProc_appgo_pending = 1 ; // Action application
}
else
{ // Got data from tiny app
else {
// Got data from tiny app
// Set the date and time
t_time *p = &Time ;
p->second = Co_proc_status[1] ;
p->minute = Co_proc_status[2] ;
p->hour = Co_proc_status[3] ;
p->date= Co_proc_status[4] ;
p->month = Co_proc_status[5] ;
p->year = Co_proc_status[6] + ( Co_proc_status[7] << 8 ) ;
struct gtm utm;
utm.tm_sec = Co_proc_status[1] ;
utm.tm_min = Co_proc_status[2] ;
utm.tm_hour = Co_proc_status[3] ;
utm.tm_mday = Co_proc_status[4] ;
utm.tm_mon = Co_proc_status[5] - 1;
utm.tm_year = (Co_proc_status[6] + ( Co_proc_status[7] << 8 )) - 1900;
g_rtcTime = gmktime(&utm);
}
TWI0->TWI_PTCR = TWI_PTCR_RXTDIS ; // Stop transfers
if ( TWI0->TWI_SR & TWI_SR_RXRDY )
{
if ( TWI0->TWI_SR & TWI_SR_RXRDY ) {
(void) TWI0->TWI_RHR ; // Discard any rubbish data
}
}
+111 -145
View File
@@ -37,19 +37,8 @@ const pm_uchar sticks[] PROGMEM = {
#include "sticks.lbm"
};
#if defined(PCBARM)
struct t_i2cTime
{
uint8_t setCode ;
uint8_t Time[7] ;
} I2CTime ;
#endif
enum EnumTabDiag {
e_Setup,
#if (defined(PCBV4) && defined(SDCARD)) || defined(PCBARM)
e_FrskyTime,
#endif
#if defined(SDCARD)
e_Sd,
#endif
@@ -57,13 +46,13 @@ enum EnumTabDiag {
e_Vers,
e_Keys,
e_Ana,
#if defined(PCBARM)
e_Hardware,
#endif
e_Calib
};
void menuProcSetup(uint8_t event);
#if (defined(PCBV4) && defined(SDCARD)) || defined (PCBARM)
void menuProcTime(uint8_t event);
#endif
#if defined(SDCARD)
void menuProcSd(uint8_t event);
#endif
@@ -71,13 +60,11 @@ void menuProcTrainer(uint8_t event);
void menuProcDiagVers(uint8_t event);
void menuProcDiagKeys(uint8_t event);
void menuProcDiagAna(uint8_t event);
void menuProcHardware(uint8_t event);
void menuProcDiagCalib(uint8_t event);
const MenuFuncP_PROGMEM menuTabDiag[] PROGMEM = {
menuProcSetup,
#if (defined(PCBV4) && defined(SDCARD)) || defined (PCBARM)
menuProcTime,
#endif
#if defined(SDCARD)
menuProcSd,
#endif
@@ -85,6 +72,9 @@ const MenuFuncP_PROGMEM menuTabDiag[] PROGMEM = {
menuProcDiagVers,
menuProcDiagKeys,
menuProcDiagAna,
#if defined(PCBARM)
menuProcHardware,
#endif
menuProcDiagCalib
};
@@ -108,6 +98,9 @@ void displaySlider(uint8_t x, uint8_t y, uint8_t value, uint8_t attr)
#endif
enum menuProcSetupItems {
#if defined(RTCLOCK)
ITEM_SETUP_RTC,
#endif
ITEM_SETUP_BEEPER_MODE,
ITEM_SETUP_BEEPER_LENGTH,
#if defined(AUDIO)
@@ -122,7 +115,6 @@ enum menuProcSetupItems {
ITEM_SETUP_HAPTIC_STRENGTH,
#endif
#if defined(PCBARM)
ITEM_SETUP_OPTREX_DISPLAY,
ITEM_SETUP_BRIGHTNESS,
#endif
ITEM_SETUP_CONTRAST,
@@ -155,12 +147,18 @@ enum menuProcSetupItems {
ITEM_SETUP_GPSFORMAT,
#endif
ITEM_SETUP_RX_CHANNEL_ORD,
ITEM_SETUP_STICK_MODE_LABELS,
ITEM_SETUP_STICK_MODE,
ITEM_SETUP_MAX
};
void menuProcSetup(uint8_t event)
{
#ifdef RTCLOCK
#define RTC_ZEROS 5,
#else
#define RTC_ZEROS
#endif
#ifdef AUDIO
#define AUDIO_ZEROS 0,
#else
@@ -187,7 +185,7 @@ void menuProcSetup(uint8_t event)
#define FRSKY_ZEROS
#endif
#ifdef PCBARM
#define ARM_ZEROS 0, 0, 0, 0,
#define ARM_ZEROS 0, 0, 0,
#else
#define ARM_ZEROS
#endif
@@ -202,10 +200,14 @@ void menuProcSetup(uint8_t event)
#define ROTARY_ENCODERS_ZEROS
#endif
MENU(STR_MENURADIOSETUP, menuTabDiag, e_Setup, ITEM_SETUP_MAX+2, {0, 0, AUDIO_ZEROS VOICE_ZEROS HAPTIC_ZEROS ARM_ZEROS BLUETOOTH_ZEROS ROTARY_ENCODERS_ZEROS 0, 0, 0, 0, 0, 0, 0, 0, 0, SPLASH_ZEROS 0, 0, 0, 0, FRSKY_ZEROS 0, (uint8_t)-1, 1});
MENU(STR_MENURADIOSETUP, menuTabDiag, e_Setup, ITEM_SETUP_MAX+1, {0, RTC_ZEROS 0, 0, AUDIO_ZEROS VOICE_ZEROS HAPTIC_ZEROS ARM_ZEROS BLUETOOTH_ZEROS ROTARY_ENCODERS_ZEROS 0, 0, 0, 0, 0, 0, 0, 0, 0, SPLASH_ZEROS 0, 0, 0, 0, FRSKY_ZEROS 0, (uint8_t)-1, 1});
uint8_t sub = m_posVert - 1;
#if defined(RTCLOCK)
static struct gtm t;
#endif
for (uint8_t i=0; i<7; i++) {
uint8_t y = 1*FH + i*FH;
uint8_t k = i+s_pgOfs;
@@ -213,6 +215,57 @@ void menuProcSetup(uint8_t event)
uint8_t attr = (sub == k ? blink : 0);
switch(k) {
#if defined(RTCLOCK)
case ITEM_SETUP_RTC:
lcd_putsLeft(y, PSTR("Time"));
lcd_putc(FW*7+6, y, '-'); lcd_putc(FW*10+4, y, '-');
lcd_putc(FW*15+5, y, ':'); lcd_putc(FW*18+3, y, ':');
for (uint8_t j=0; j<6; j++) { // 3 settings each for date and time (YMD and HMS)
uint8_t rowattr = (m_posHorz==j) ? attr : 0;
switch (j) {
case 0:
lcd_outdezAtt(FW*7+6, y, t.tm_year+1900, rowattr);
if (rowattr && (s_editMode>0 || p1valdiff)) t.tm_year = checkIncDec(event, t.tm_year, 112, 200, 0);
break;
case 1:
lcd_outdezNAtt(FW*10+4, y, t.tm_mon+1, rowattr|LEADING0, 2);
if (rowattr && (s_editMode>0 || p1valdiff)) t.tm_mon = checkIncDec(event, t.tm_mon, 0, 11, 0);
break;
case 2:
{
int16_t year = 1900 + t.tm_year;
int8_t dlim = (((((year%4==0) && (year %100!=0)) || (year%400==0)) && (t.tm_mon==1)) ? 1 : 0);
int8_t dmon[] = {31,28,31,30,31,30,31,31,30,31,30,31}; // TODO in flash
dlim += dmon[t.tm_mon];
lcd_outdezNAtt(FW*13+2, y, t.tm_mday, rowattr|LEADING0, 2);
if (rowattr && (s_editMode>0 || p1valdiff)) t.tm_mday = checkIncDec(event, t.tm_mday, 1, dlim, 0);
break;
}
case 3:
lcd_outdezNAtt(FW*15+5, y, t.tm_hour, rowattr|LEADING0, 2);
if (rowattr && (s_editMode>0 || p1valdiff)) t.tm_hour = checkIncDec( event, t.tm_hour, 0, 23, 0);
break;
case 4:
lcd_outdezNAtt(FW*18+3, y, t.tm_min, rowattr|LEADING0, 2);
if (rowattr && (s_editMode>0 || p1valdiff)) t.tm_min = checkIncDec( event, t.tm_min, 0, 59, 0);
break;
case 5:
lcd_outdezNAtt(FW*21+2, y, t.tm_sec, rowattr|LEADING0, 2);
if (rowattr && (s_editMode>0 || p1valdiff)) t.tm_sec = checkIncDec( event, t.tm_sec, 0, 59, 0);
break;
}
}
if (attr && s_editMode<=0 && event == EVT_KEY_FIRST(KEY_MENU)) {
// set the date and time into RTC chip
rtc_settime(&t);
}
else if (sub!=ITEM_SETUP_RTC || s_editMode<=0) {
gettime(&t);
}
break;
#endif
case ITEM_SETUP_BEEPER_MODE:
g_eeGeneral.beeperMode = selectMenuItem(GENERAL_PARAM_OFS, y, STR_BEEPERMODE, STR_VBEEPMODE, g_eeGeneral.beeperMode, -2, 1, attr, event);
#if defined(FRSKY)
@@ -278,10 +331,6 @@ void menuProcSetup(uint8_t event)
#endif
#if defined(PCBARM)
case ITEM_SETUP_OPTREX_DISPLAY:
g_eeGeneral.optrexDisplay = onoffMenuItem( g_eeGeneral.optrexDisplay, GENERAL_PARAM_OFS, y, STR_OPTREX_DISPLAY, attr, event );
break;
case ITEM_SETUP_BRIGHTNESS:
lcd_putsLeft(y, STR_BRIGHTNESS);
lcd_outdezAtt(GENERAL_PARAM_OFS, y, 100-g_eeGeneral.backlightBright, attr|LEFT) ;
@@ -421,17 +470,18 @@ void menuProcSetup(uint8_t event)
lcd_putsLeft( y,STR_RXCHANNELORD);// RAET->AETR
for (uint8_t i=1; i<=4; i++)
putsChnLetter(GENERAL_PARAM_OFS - FW + i*FW, y, channel_order(i), attr);
if(attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.templateSetup, 0, 23);
if (attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.templateSetup, 0, 23);
break;
case ITEM_SETUP_STICK_MODE_LABELS:
lcd_putsLeft(y, STR_MODE);
for (uint8_t i=0; i<4; i++) lcd_img((6+4*i)*FW, y, sticks, i, 0);
break;
case ITEM_SETUP_STICK_MODE:
lcd_puts( 1*FW, y, STR_MODE);
for(uint8_t i=0; i<4; i++) lcd_img((6+4*i)*FW, y, sticks,i,0);
if((y+=FH)>7*FH) return;
lcd_putcAtt( 3*FW, y, '1'+g_eeGeneral.stickMode,(sub==k+1) ? (s_editMode>0 ? BLINK|INVERS : INVERS) : 0);
for(uint8_t i=0; i<4; i++) putsChnRaw( (6+4*i)*FW, y, pgm_read_byte(modn12x3 + 4*g_eeGeneral.stickMode + i), 0);
if (sub==k+1 && s_editMode>0) {
lcd_putcAtt(2*FW, y, '1'+g_eeGeneral.stickMode, attr);
for (uint8_t i=0; i<4; i++) putsChnRaw( (6+4*i)*FW, y, pgm_read_byte(modn12x3 + 4*g_eeGeneral.stickMode + i), 0);
if (attr && s_editMode>0) {
CHECK_INCDEC_GENVAR(event, g_eeGeneral.stickMode, 0, 3);
}
else if (stickMode != g_eeGeneral.stickMode) {
@@ -446,119 +496,6 @@ void menuProcSetup(uint8_t event)
}
}
#if (defined(PCBV4) && defined(SDCARD)) || defined(PCBARM)
// SD card interface contains Real-Time-Clock chip
void menuProcTime(uint8_t event)
{
MENU(STR_MENUDATEANDTIME, menuTabDiag, e_FrskyTime, 3, {0, 2/*, 2*/});
int8_t sub = m_posVert - 1; // vertical position (1 = page counter, top/right)
uint8_t subSub = m_posHorz; // horizontal position
static struct gtm t;
struct gtm *at = &t;
switch(event)
{
case EVT_KEY_LONG(KEY_MENU):
// get data time from RTC chip (may not implement)
killEvents(event);
break;
case EVT_KEY_FIRST(KEY_MENU):
if (sub >= 0 && s_editMode<=0) // set the date and time into RTC chip
{
#if (defined(PCBV4) && defined(SDCARD))
g_unixTime = gmktime(&t); // update local timestamp and get wday calculated
g_ms100 = 0; // start of next second begins now
RTC rtc;
rtc.year = t.tm_year + 1900;
rtc.month = t.tm_mon + 1;
rtc.mday = t.tm_mday;
rtc.hour = t.tm_hour;
rtc.min = t.tm_min;
rtc.sec = t.tm_sec;
rtc.wday = t.tm_wday + 1;
rtc_settime(&rtc);
#else
I2CTime.setCode = 0x74 ; // Tiny SET TIME CODE command
I2CTime.Time[0] = t.tm_sec ;
I2CTime.Time[1] = t.tm_min ;
I2CTime.Time[2] = t.tm_hour ;
I2CTime.Time[3] = t.tm_mday ;
I2CTime.Time[4] = t.tm_mon+1 ;
I2CTime.Time[5] = (uint8_t) (t.tm_year+1900) ;
I2CTime.Time[6] = (t.tm_year+1900) >> 8 ;
write_coprocessor( (uint8_t *) &I2CTime, 8 ) ;
#endif
}
break;
}
#if (defined(PCBV4) && defined(SDCARD))
if (s_editMode<=0) filltm(&g_unixTime, &t);
#endif
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, ':');
for(uint8_t i=0; i<2; i++) // 2 rows, date then time
{
uint8_t y=(i*2+2)*FH;
lcd_putsiAtt(0, y, STR_DATETIME, i, 0);
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>0 ? BLINK|INVERS : INVERS) : 0;
switch(i)
{
case 0: // DATE
switch(j)
{
case 0:
lcd_outdezAtt(FW*10+2, y, at->tm_year+1900, attr);
if(attr && (s_editMode>0 || p1valdiff)) at->tm_year = checkIncDec( event, at->tm_year, 112, 200, 0);
break;
case 1:
lcd_outdezNAtt(FW*13, y, at->tm_mon+1, attr|LEADING0, 2);
if(attr && (s_editMode>0 || p1valdiff)) at->tm_mon = checkIncDec( event, at->tm_mon, 0, 11, 0);
break;
case 2:
int16_t year=1900 + at->tm_year;
int8_t dlim = (((((year%4==0) && (year %100!=0)) || (year%400==0)) && (at->tm_mon==1)) ? 1 : 0);
int8_t dmon[]={31,28,31,30,31,30,31,31,30,31,30,31};
dlim+=dmon[at->tm_mon];
lcd_outdezNAtt(FW*16-2, y, at->tm_mday, attr|LEADING0, 2);
if(attr && (s_editMode>0 || p1valdiff)) at->tm_mday = checkIncDec( event, at->tm_mday, 1, dlim, 0);
break;
}
break;
case 1:
switch (j)
{
case 0:
lcd_outdezNAtt(FW*10+1, y, at->tm_hour, attr|LEADING0, 2);
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>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>0 || p1valdiff)) at->tm_sec = checkIncDec( event, at->tm_sec, 0, 59, 0);
break;
}
break;
}
}
}
}
#endif
#if defined(PCBARM)
extern uint32_t sdAvailableAudioFiles; // TODO move that!
#endif
@@ -1005,6 +942,35 @@ void menuProcDiagAna(uint8_t event)
}
#if defined(PCBARM)
enum menuProcHwItems {
ITEM_SETUP_HW_OPTREX_DISPLAY,
ITEM_SETUP_HW_MAX
};
#define GENERAL_HW_PARAM_OFS (2+(15*FW))
void menuProcHardware(uint8_t event)
{
MENU(PSTR("Hardware"), menuTabDiag, e_Hardware, ITEM_SETUP_HW_MAX+1, {0, 0});
uint8_t sub = m_posVert - 1;
for (uint8_t i=0; i<7; i++) {
uint8_t y = 1*FH + i*FH;
uint8_t k = i+s_pgOfs;
uint8_t blink = ((s_editMode>0) ? BLINK|INVERS : INVERS);
uint8_t attr = (sub == k ? blink : 0);
switch(k) {
case ITEM_SETUP_HW_OPTREX_DISPLAY:
// TODO remove STR_OPTREX_DISPLAY + translations here
g_eeGeneral.optrexDisplay = selectMenuItem(GENERAL_HW_PARAM_OFS, y, PSTR("LCD"), PSTR("\006NormalOptrex"), g_eeGeneral.optrexDisplay, 0, 1, attr, event);
break;
}
}
}
#endif
void menuProcDiagCalib(uint8_t event)
{
SIMPLE_MENU(STR_MENUCALIBRATION, menuTabDiag, e_Calib, 1);
@@ -36,7 +36,17 @@
/* RTC controls */
#include "../open9x.h"
#include "rtc.h"
#include "../FatFs/integer.h"
typedef struct {
WORD year; /* 2000..2099 */
BYTE month; /* 1..12 */
BYTE mday; /* 1.. 31 */
BYTE wday; /* 1..7 */
BYTE hour; /* 0..23 */
BYTE min; /* 0..59 */
BYTE sec; /* 0..59 */
} RTC;
#define SCL_LOW() DDRD |= 0x01 /* SCL = LOW */
#define SCL_HIGH() DDRD &= ~0x01 /* SCL = High-Z */
@@ -224,11 +234,10 @@ int iic_write (
/* RTC functions */
int rtc_gettime (RTC *rtc)
int g9x_rtc_gettime (RTC *rtc)
{
BYTE buf[8];
if (!iic_read(0xD0, 0, 7, buf)) return 0;
rtc->sec = (buf[0] & 0x0F) + ((buf[0] >> 4) & 7) * 10;
@@ -242,15 +251,10 @@ int rtc_gettime (RTC *rtc)
return 1;
}
int rtc_settime (const RTC *rtc)
int g9x_rtc_settime (const RTC *rtc)
{
BYTE buf[8];
buf[0] = rtc->sec / 10 * 16 + rtc->sec % 10;
buf[1] = rtc->min / 10 * 16 + rtc->min % 10;
buf[2] = rtc->hour / 10 * 16 + rtc->hour % 10;
@@ -264,14 +268,45 @@ int rtc_settime (const RTC *rtc)
int rtc_init (void)
void rtc_gettime(struct gtm * utm)
{
RTC rtc = {0,0,0,0,0,0,0};
g9x_rtc_gettime(&rtc);
utm->tm_year = rtc.year - 1900;
utm->tm_mon = rtc.month - 1;
utm->tm_mday = rtc.mday;
utm->tm_hour = rtc.hour;
utm->tm_min = rtc.min;
utm->tm_sec = rtc.sec;
utm->tm_wday = rtc.wday - 1;
}
void rtc_settime(struct gtm * t)
{
g_rtcTime = gmktime(t); // update local timestamp and get wday calculated
g_ms100 = 0; // start of next second begins now
RTC rtc;
rtc.year = t->tm_year + 1900;
rtc.month = t->tm_mon + 1;
rtc.mday = t->tm_mday;
rtc.hour = t->tm_hour;
rtc.min = t->tm_min;
rtc.sec = t->tm_sec;
rtc.wday = t->tm_wday + 1;
g9x_rtc_settime(&rtc);
}
void rtc_init (void)
{
BYTE buf[8]; /* RTC R/W buffer */
UINT adr;
/* Read RTC registers */
if (!iic_read(0xD0, 0, 8, buf)) return 0; /* IIC error */
if (!iic_read(0xD0, 0, 8, buf)) return; /* IIC error */
if (buf[7] & 0x20) { /* When data has been volatiled, set default time */
/* Clear nv-ram. Reg[8..63] */
@@ -282,6 +317,9 @@ int rtc_init (void)
buf[4] = 1; buf[5] = 1; buf[6] = 8;
iic_write(0x0D, 0, 8, buf);
}
return 1;
struct gtm utm;
rtc_gettime(&utm);
g_rtcTime = gmktime(&utm);
}
+13 -27
View File
@@ -92,7 +92,7 @@ const pm_char * openLogs()
}
if (f_size(&g_oLogFile) == 0) {
#if defined(PCBV4)
#if defined(RTCLOCK)
f_puts("Date,Time,", &g_oLogFile);
#endif
@@ -151,21 +151,18 @@ void writeLogs()
}
}
#if defined(PCBV4)
static struct gtm t;
struct gtm *at = &t;
filltm(&g_unixTime, &t);
f_printf(&g_oLogFile, "%4d-%02d-%02d,", at->tm_year+1900, at->tm_mon+1, at->tm_mday);
f_printf(&g_oLogFile, "%02d:%02d:%02d,", at->tm_hour, at->tm_min, at->tm_sec);
#if defined(RTCLOCK)
struct gtm utm;
gettime(&utm);
f_printf(&g_oLogFile, "%4d-%02d-%02d,%02d:%02d:%02d,", utm.tm_year+1900, utm.tm_mon+1, utm.tm_mday, utm.tm_hour, utm.tm_min, utm.tm_sec);
#endif
#if defined(FRSKY)
f_printf(&g_oLogFile, "%d,", frskyStreaming);
f_printf(&g_oLogFile, "%d,", frskyData.rssi[0].value);
f_printf(&g_oLogFile, "%d,", frskyData.rssi[1].value);
f_printf(&g_oLogFile, "%d,", frskyData.analog[0].value);
f_printf(&g_oLogFile, "%d,", frskyData.analog[1].value);
f_printf(&g_oLogFile, "%d,%d,%d,", frskyStreaming, frskyData.rssi[0].value, frskyData.rssi[1].value);
for (uint8_t i=0; i<2; i++) {
int16_t converted_value = applyChannelRatio(i, frskyData.analog[i].value);
f_printf(&g_oLogFile, "%d.%02d,", converted_value/100, converted_value%100);
}
#endif
#if defined(FRSKY_HUB)
@@ -180,14 +177,11 @@ void writeLogs()
f_printf(&g_oLogFile, "%d.%d,", frskyData.hub.gpsSpeed_bp, frskyData.hub.gpsSpeed_ap);
f_printf(&g_oLogFile, "%03d.%d,", frskyData.hub.gpsAltitude_bp, frskyData.hub.gpsAltitude_ap);
f_printf(&g_oLogFile, "%d.%d,", frskyData.hub.baroAltitude_bp, frskyData.hub.baroAltitude_ap);
f_printf(&g_oLogFile, "%d,", frskyData.hub.temperature1);
f_printf(&g_oLogFile, "%d,", frskyData.hub.temperature2);
f_printf(&g_oLogFile, "%d,%d,", frskyData.hub.temperature1, frskyData.hub.temperature2);
f_printf(&g_oLogFile, "%d,", frskyData.hub.rpm);
f_printf(&g_oLogFile, "%d,", frskyData.hub.fuelLevel);
f_printf(&g_oLogFile, "%d,", frskyData.hub.volts);
f_printf(&g_oLogFile, "%d,", frskyData.hub.accelX);
f_printf(&g_oLogFile, "%d,", frskyData.hub.accelY);
f_printf(&g_oLogFile, "%d,", frskyData.hub.accelZ);
f_printf(&g_oLogFile, "%d,%d,%d,", frskyData.hub.accelX, frskyData.hub.accelY, frskyData.hub.accelZ);
}
#endif
@@ -201,15 +195,7 @@ void writeLogs()
f_printf(&g_oLogFile, "%d,", calibratedStick[i]);
}
f_printf(&g_oLogFile, "%d,", keyState(SW_ThrCt));
f_printf(&g_oLogFile, "%d,", keyState(SW_RuddDR));
f_printf(&g_oLogFile, "%d,", keyState(SW_ElevDR));
f_printf(&g_oLogFile, "%d,", keyState(SW_ID0));
f_printf(&g_oLogFile, "%d,", keyState(SW_ID1));
f_printf(&g_oLogFile, "%d,", keyState(SW_ID2));
f_printf(&g_oLogFile, "%d,", keyState(SW_AileDR));
f_printf(&g_oLogFile, "%d,", keyState(SW_Gear));
if (f_printf(&g_oLogFile, "%d\n", keyState(SW_Trainer)) < 0 && !error_displayed) {
if (f_printf(&g_oLogFile, "%d,%d,%d,%d,%d,%d,%d,%d,%d\n", keyState(SW_ThrCt), keyState(SW_RuddDR), keyState(SW_ElevDR), keyState(SW_ID0), keyState(SW_ID1), keyState(SW_ID2), keyState(SW_AileDR), keyState(SW_Gear), keyState(SW_Trainer)) < 0 && !error_displayed) {
error_displayed = STR_SDCARD_ERROR;
s_global_warning = STR_SDCARD_ERROR;
}
+1 -1
View File
@@ -238,7 +238,7 @@ extern uint8_t s_menu_offset;
extern bool s_menu_more;
const char * displayMenu(uint8_t event);
#define STATUS_LINE_LENGTH 22
#define STATUS_LINE_LENGTH 32
extern char statusLineMsg[STATUS_LINE_LENGTH];
void showStatusLine();
void drawStatusLine();
+1 -3
View File
@@ -35,7 +35,7 @@
#if defined(PCBARM)
#define MIXER_STACK_SIZE 500
#define MENUS_STACK_SIZE 2000
#define MENUS_STACK_SIZE 2500
#define AUDIO_STACK_SIZE 500
#define BT_STACK_SIZE 500
#define DEBUG_STACK_SIZE 500
@@ -87,8 +87,6 @@ ModelData g_model;
#if !defined(PCBARM)
uint8_t g_tmr1Latency_max;
uint8_t g_tmr1Latency_min;
#else
t_time Time;
#endif
uint8_t unexpectedShutdown = 0;
+4 -16
View File
@@ -52,6 +52,8 @@
#if defined(PCBARM)
#include "board_ersky9x.h"
#elif defined(PCBV4)
#include "board_gruvin9x.h"
#endif
#if defined(SIMU)
@@ -904,19 +906,6 @@ extern void deleteExpoMix(uint8_t expo, uint8_t idx);
extern void incSubtrim(uint8_t idx, int16_t inc);
extern void instantTrim();
extern void moveTrimsToOffsets();
#if defined(PCBARM)
typedef struct
{
unsigned char second; //enter the current time, date, month, and year
unsigned char minute;
unsigned char hour;
unsigned char date;
unsigned char month;
unsigned int year;
} t_time ;
extern t_time Time ;
#endif
#if defined(PCBARM)
#define ACTIVE_EXPOS_TYPE uint32_t
@@ -1084,9 +1073,8 @@ enum AUDIO_SOUNDS {
#include "sdcard.h"
#endif
#if defined(PCBV4)
#include "gruvin9x/rtc.h"
extern uint8_t g_ms100; // global to allow time set function to reset to zero
#if defined(RTCLOCK)
#include "rtc.h"
#endif
// Re-useable byte array to save having multiple buffers
+507
View File
@@ -0,0 +1,507 @@
/*
* Authors (alphabetical order)
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Jean-Pierre Parisy
* - Karl Szmutny <shadow@privy.de>
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* open9x is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and 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 <limits.h>
#include "open9x.h"
extern void rtcdriver_settime(struct gtm * t);
#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 (gtime_t)
#endif
#ifndef TIME_T_MAX
# define TIME_T_MAX TYPE_MAXIMUM (gtime_t)
#endif
#define TIME_T_MIDPOINT (SHR (TIME_T_MIN + TIME_T_MAX, 1) + 1)
/* Verify a requirement at compile-time (unlike assert, which is runtime). */
#define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; }
verify (gtime_t_is_integer, TYPE_IS_INTEGER (gtime_t));
verify (twos_complement_arithmetic, TYPE_TWOS_COMPLEMENT (int));
/* The code also assumes that signed integer overflow silently wraps
around, but this assumption can't be stated without causing a
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
/* 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 (
gtime_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 >= (long int)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 gtime_t to struct tm
struct gtm *
__localtime_r (gtime_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 gtime_t
ydhms_diff (long int year1, long int yday1, int hour1, int min1, int sec1,
int year0, int yday0, int hour0, int min0, int sec0)
{
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 gtime_t precision. Overflow might
occur here. */
gtime_t tyear1 = year1;
gtime_t years = tyear1 - year0;
gtime_t days = 365 * years + yday1 - yday0 + intervening_leap_days;
gtime_t hours = 24 * days + hour1 - hour0;
gtime_t minutes = 60 * hours + min1 - min0;
gtime_t seconds = 60 * minutes + sec1 - sec0;
return seconds;
}
/* Return a gtime_t value corresponding to (YEAR-YDAY HOUR:MIN:SEC),
assuming that *T corresponds to *TP and that no clock adjustments
occurred between *TP and the desired time.
If TP is null, return a value not equal to *T; this avoids false matches.
If overflow occurs, yield the minimal or maximal value, except do not
yield a value equal to *T. */
static gtime_t
guess_time_tm (long int year, long int yday, int hour, int min, int sec,
gtime_t *t, struct gtm *tp)
{
if (tp)
{
gtime_t d = ydhms_diff (year, yday, hour, min, sec,
tp->tm_year, tp->tm_yday,
tp->tm_hour, tp->tm_min, tp->tm_sec);
gtime_t t1 = *t + d;
if ((t1 < *t) == (TYPE_SIGNED (gtime_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) (gtime_t *, struct gtm *),
gtime_t *t, struct gtm *tp)
{
struct gtm *r = convert (t, tp);
if (!r && *t)
{
gtime_t bad = *t;
gtime_t ok = 0;
/* BAD is a known unconvertible gtime_t, and OK is a known good one.
Use binary search to narrow the range between BAD and OK until
they differ by 1. */
while (bad != ok + (bad < 0 ? -1 : 1))
{
gtime_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 gtime_t value, inverting
the monotonic and mostly-unit-linear conversion function CONVERT.
Use *OFFSET to keep track of a guess at the offset of the result,
compared to what the result would be for UTC without leap seconds.
If *OFFSET's guess is correct, only one CONVERT call is needed.
This function is external because it is used also by timegm.c. */
gtime_t
__mktime_internal (struct gtm *tp,
struct gtm *(*convert) (gtime_t *, struct gtm *),
gtime_t *offset)
{
gtime_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 gtime_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;
gtime_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)
{
/* gtime_t isn't large enough to rule out overflows, so check
for major overflows. A gross check suffices, since if t0
has overflowed, it is off by a multiple of TIME_T_MAX -
TIME_T_MIN + 1. So ignore any component of the difference
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) */
gtime_t time_t_max = TIME_T_MAX;
gtime_t time_t_min = TIME_T_MIN;
gtime_t overflow_threshold =
(time_t_max / 3 - time_t_min / 3) >> ALOG2_SECONDS_PER_BIENNIUM;
if (overflow_threshold < abs_diff)
{
/* Overflow occurred. Try repairing it; this might work if
the time zone offset is enough to undo the overflow. */
gtime_t repaired_t0 = -1 - t0;
approx_biennia = SHR (repaired_t0, ALOG2_SECONDS_PER_BIENNIUM);
diff = approx_biennia - approx_requested_biennia;
abs_diff = diff < 0 ? - diff : diff;
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 gtime_t value. */
gtime_t
gmktime (struct gtm *tp)
{
// no time zone stuff. Just do the math ;)
static gtime_t localtime_offset;
return __mktime_internal (tp, __localtime_r, &localtime_offset);
}
/* Fill a (struct tm) TP* from a given gtime_t time stamp */
gtime_t
filltm(gtime_t *t, struct gtm *tp)
{
return __offtime(t, 0, tp);
}
gtime_t g_rtcTime;
uint8_t g_ms100 = 0; // global to allow time set function to reset to zero
void gettime(struct gtm * tm)
{
filltm(&g_rtcTime, tm); // create a struct tm date/time structure from global unix time stamp
}
+67 -65
View File
@@ -1,65 +1,67 @@
/*
* Authors (alphabetical order)
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Jean-Pierre Parisy
* - Karl Szmutny <shadow@privy.de>
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* open9x is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and 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 fattime_h
#define fattime_h
#include <inttypes.h>
#include <limits.h>
#undef CHAR_BIT
#define CHAR_BIT 8
typedef long int gtime_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 gtime_t gmktime(struct gtm *tp);
extern gtime_t filltm(gtime_t *t, struct gtm *tp);
extern gtime_t g_unixTime; // Global date/time register, incremented each second in per10ms()
#endif
/*
* Authors (alphabetical order)
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Jean-Pierre Parisy
* - Karl Szmutny <shadow@privy.de>
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* open9x is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and 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 RTC_H
#define RTC_H
#include <inttypes.h>
typedef long int gtime_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 gtime_t g_rtcTime;
extern uint8_t g_ms100; // global to allow time set function to reset to zero
#ifdef __cplusplus
extern "C" {
#endif
extern void rtc_init();
extern void rtc_settime(struct gtm * tm);
extern void gettime(struct gtm * tm);
extern gtime_t gmktime (struct gtm *tm);
#ifdef __cplusplus
}
#endif
#endif
-1
View File
@@ -35,7 +35,6 @@
#define sdcard_h
#include "FatFs/ff.h"
#include "FatFs/fattime.h"
#ifdef SIMU
#define MODELS_PATH "."