mirror of
https://git.planet-casio.com/Lephenixnoir/gint.git
synced 2024-12-28 04:23:36 +01:00
Added an RTC test (clock), image part drawing and a few standard functions (stdlib, time).
This commit is contained in:
parent
c63d7b812e
commit
1f223f807f
33 changed files with 938 additions and 152 deletions
2
Makefile
2
Makefile
|
@ -14,7 +14,7 @@
|
|||
# Modules
|
||||
modules-gint = core keyboard mmu mpu rtc screen timer \
|
||||
bopti display gray tales
|
||||
modules-libc = setjmp string stdio
|
||||
modules-libc = setjmp string stdio stdlib
|
||||
|
||||
# Targets
|
||||
target-g1a = gintdemo.g1a
|
||||
|
|
6
TODO
6
TODO
|
@ -10,9 +10,11 @@
|
|||
|
||||
|
||||
@ possibility of vram overflow with text
|
||||
@ garbage displayed as year in the clock, possibly during edition (could not
|
||||
reproduce)
|
||||
|
||||
+ bitmap blending modes
|
||||
+ have timers use structures from 7705.h and 7305.h
|
||||
+ minimize use of 7705.h and 7305.h; use local structures instead
|
||||
+ partial transparency
|
||||
+ gint vs. ML with 248x124 at (-60, -28)
|
||||
+ call exit handlers
|
||||
|
@ -23,7 +25,7 @@
|
|||
- full rtc driver (time)
|
||||
- callbacks and complete user API
|
||||
|
||||
~ shadowy rectangle effect for Shift + Alpha + Left + Down
|
||||
~ packed bit fields
|
||||
~ exhaustive save for setjmp()
|
||||
~ registers that need to be saved when configuring gint
|
||||
~ possible bug when -O2'ing __attribute__((interrupt_handler))
|
||||
|
|
|
@ -33,32 +33,6 @@ void print(int x, int y, const char *format, ...)
|
|||
locate(x, y, __stdio_buffer);
|
||||
}
|
||||
|
||||
/*
|
||||
text_test()
|
||||
Renders text.
|
||||
|
||||
void text_test(void)
|
||||
{
|
||||
extern Font res_font_modern_start;
|
||||
Font *font = &res_font_modern_start;
|
||||
|
||||
text_configure(font);
|
||||
|
||||
dclear();
|
||||
|
||||
dtext(" !\"#$%&'()*+,-./", 10, 10);
|
||||
dtext("0123456789:;<=>?", 10, 16);
|
||||
dtext("@ABCDEFGHIJKLMNO", 10, 22);
|
||||
dtext("PQRSTUVWXYZ[\\]^_", 10, 28);
|
||||
dtext("`abcdefghijklmno", 10, 34);
|
||||
dtext("pqrstuvwxyz{|}~", 10, 40);
|
||||
|
||||
dupdate();
|
||||
|
||||
while(getkey() != KEY_EXIT);
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
printf_test()
|
||||
Tests formatting functions.
|
||||
|
@ -534,7 +508,7 @@ int main(void)
|
|||
test_tales();
|
||||
break;
|
||||
case 0x0105:
|
||||
// test_rtc();
|
||||
test_rtc();
|
||||
break;
|
||||
case 0x0106:
|
||||
// test_printf();
|
||||
|
|
BIN
demo/resources/opt_rtc.bmp
Normal file
BIN
demo/resources/opt_rtc.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
BIN
demo/resources/rtc_segments.bmp
Normal file
BIN
demo/resources/rtc_segments.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.8 KiB |
|
@ -62,9 +62,6 @@ void test_keyboard(void)
|
|||
|
||||
while(1)
|
||||
{
|
||||
multigetkey(keys, 4, 1);
|
||||
if(keys[0] == KEY_EXIT && keys[1] == KEY_NONE) break;
|
||||
|
||||
dclear();
|
||||
locate(1, 1, "Keyboard driver");
|
||||
locate(8, 3, "Pressed keys:");
|
||||
|
@ -78,5 +75,8 @@ void test_keyboard(void)
|
|||
}
|
||||
|
||||
dupdate();
|
||||
|
||||
multigetkey(keys, 4, 1);
|
||||
if(keys[0] == KEY_EXIT && keys[1] == KEY_NONE) break;
|
||||
}
|
||||
}
|
||||
|
|
262
demo/test_rtc.c
Normal file
262
demo/test_rtc.c
Normal file
|
@ -0,0 +1,262 @@
|
|||
#include "gintdemo.h"
|
||||
#include <display.h>
|
||||
#include <rtc.h>
|
||||
#include <keyboard.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/*
|
||||
test_rtc()
|
||||
Just a clock. Of course using all this RTCTime conversion and this / 10
|
||||
is awfully un-optimized, but it's a test case so it's made to check the
|
||||
values in the structure are correct.
|
||||
*/
|
||||
|
||||
#include <internals/rtc.h>
|
||||
#include <mpu.h>
|
||||
|
||||
static void draw(struct RTCTime time)
|
||||
{
|
||||
extern Image res_rtc_segments_start;
|
||||
|
||||
const char *days[7] = {
|
||||
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
|
||||
}, *months[12] = {
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
|
||||
"Oct", "Nov", "Dec"
|
||||
};
|
||||
int x[6] = { 20, 33, 52, 65, 84, 97 };
|
||||
int digits[6];
|
||||
int i;
|
||||
|
||||
digits[0] = time.hours / 10;
|
||||
digits[1] = time.hours % 10;
|
||||
digits[2] = time.minutes / 10;
|
||||
digits[3] = time.minutes % 10;
|
||||
digits[4] = time.seconds / 10;
|
||||
digits[5] = time.seconds % 10;
|
||||
|
||||
// Drawing digits.
|
||||
for(i = 0; i < 6; i++) dimage_part(x[i], 8, &res_rtc_segments_start,
|
||||
12 * digits[i], 0, 11, 19);
|
||||
// Drawing ':' between pairs of digits.
|
||||
for(i = 0; i < 16; i++) dpixel(47 + 32 * (i >= 8) + (i & 1),
|
||||
14 + 5 * !!(i & 4) + !!(i & 2), Color_Black);
|
||||
|
||||
// This should print time.year + 1900 but for the sake of this demo we
|
||||
// have tweaked the field so that it already contains time.year + 1900.
|
||||
print(4, 6, "%s %s %02d %4d", days[time.week_day],
|
||||
months[time.month], time.month_day, time.year);
|
||||
}
|
||||
|
||||
static void callback(void)
|
||||
{
|
||||
extern Image res_opt_rtc_start;
|
||||
struct RTCTime time = rtc_getTime();
|
||||
time.year += 1900;
|
||||
|
||||
dclear();
|
||||
draw(time);
|
||||
dimage_part(0, 56, &res_opt_rtc_start, 0, 0, 19, 8);
|
||||
dupdate();
|
||||
}
|
||||
|
||||
static void set_region(struct RTCTime *time, int region, int value)
|
||||
{
|
||||
switch(region)
|
||||
{
|
||||
case 0:
|
||||
time->hours = 10 * value + (time->hours % 10);
|
||||
break;
|
||||
case 1:
|
||||
time->hours = time->hours - (time->hours % 10) + value;
|
||||
break;
|
||||
case 2:
|
||||
time->minutes = 10 * value + (time->minutes % 10);
|
||||
break;
|
||||
case 3:
|
||||
time->minutes = time->minutes - (time->minutes % 10) + value;
|
||||
break;
|
||||
case 4:
|
||||
time->seconds = 10 * value + (time->seconds % 10);
|
||||
break;
|
||||
case 5:
|
||||
time->seconds = time->seconds - (time->seconds % 10) + value;
|
||||
break;
|
||||
case 6:
|
||||
time->week_day = value;
|
||||
break;
|
||||
case 7:
|
||||
time->month = value;
|
||||
break;
|
||||
case 8:
|
||||
time->month_day = 10 * value + (time->month_day % 10);
|
||||
break;
|
||||
case 9:
|
||||
time->month_day = time->month_day - (time->month_day % 10)
|
||||
+ value;
|
||||
break;
|
||||
case 10:
|
||||
time->year = 1000 * value + (time->year % 1000);
|
||||
break;
|
||||
case 11:
|
||||
time->year = time->year - (time->year % 1000) + 100 * value
|
||||
+ (time->year % 100);
|
||||
break;
|
||||
case 12:
|
||||
time->year = time->year - (time->year % 100) + 10 * value
|
||||
+ (time->year % 10);
|
||||
break;
|
||||
case 13:
|
||||
time->year = time->year - (time->year % 10) + value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void set(void)
|
||||
{
|
||||
extern Image res_opt_rtc_start;
|
||||
Image *opt = &res_opt_rtc_start;
|
||||
|
||||
struct {
|
||||
int x, y;
|
||||
int w, h;
|
||||
} regions[] = {
|
||||
{ 19, 7, 13, 21 }, { 32, 7, 13, 21 }, { 51, 7, 13, 21 },
|
||||
{ 64, 7, 13, 21 }, { 83, 7, 13, 21 }, { 96, 7, 13, 21 },
|
||||
{ 18, 39, 19, 9 }, { 42, 39, 19, 9 }, { 66, 39, 7, 9 },
|
||||
{ 72, 39, 7, 9 }, { 84, 39, 7, 9 }, { 90, 39, 7, 9 },
|
||||
{ 96, 39, 7, 9 }, { 102, 39, 7, 9 },
|
||||
};
|
||||
struct RTCTime time = rtc_getTime();
|
||||
int region_count = 14;
|
||||
int n = 0, slide = 0, key, leave;
|
||||
|
||||
time.year += 1900;
|
||||
|
||||
while(1)
|
||||
{
|
||||
dclear();
|
||||
draw(time);
|
||||
dreverse_area(regions[n].x, regions[n].y, regions[n].x
|
||||
+ regions[n].w - 1, regions[n].y + regions[n].h - 1);
|
||||
|
||||
if(n == 6) dimage_part(0, 56, opt, 0, 9 * (1 + slide), 128, 8);
|
||||
if(n == 7) dimage_part(0, 56, opt, 0, 9 * (3 + slide), 128, 8);
|
||||
else dimage_part(0, 56, opt, 22 + 22 * (n == region_count - 1),
|
||||
0, 19, 8);
|
||||
|
||||
dupdate();
|
||||
|
||||
do
|
||||
{
|
||||
leave = 1;
|
||||
key = getkey();
|
||||
if(key == KEY_EXIT) return;
|
||||
|
||||
else if(key == KEY_F1 || key == KEY_EXE)
|
||||
{
|
||||
n++;
|
||||
slide = 0;
|
||||
if(n == region_count)
|
||||
{
|
||||
time.year -= 1900;
|
||||
rtc_setTime(time);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
else if(key == KEY_F6)
|
||||
{
|
||||
if(n == 6) slide = (slide + 1) % 2;
|
||||
if(n == 7) slide = (slide + 1) % 3;
|
||||
}
|
||||
|
||||
else if((key & 0x0f) == 9) // Other F-keys
|
||||
{
|
||||
int k = 7 - (key >> 4); // Number of F-key
|
||||
|
||||
if(n == 7)
|
||||
{
|
||||
int month = k + 4 * slide - 1;
|
||||
set_region(&time, n, month);
|
||||
n++;
|
||||
slide = 0;
|
||||
}
|
||||
|
||||
else if(n == 6 && (slide != 1 || k != 5))
|
||||
{
|
||||
int day = k + 4 * slide - 1;
|
||||
set_region(&time, n, day);
|
||||
n++;
|
||||
slide = 0;
|
||||
}
|
||||
|
||||
else leave = 0;
|
||||
}
|
||||
|
||||
else if(isdigit(keychar(key))) // Numbers
|
||||
{
|
||||
int val = keychar(key) - '0';
|
||||
int ok = 1;
|
||||
|
||||
if(n == 0) ok = (val <= 2);
|
||||
if(n == 1)
|
||||
{
|
||||
int max = time.hours >= 20 ? 3 : 9;
|
||||
ok = (val <= max);
|
||||
}
|
||||
if(n == 2 || n == 4) ok = (val <= 5);
|
||||
if(n == 8) ok = (val <= 3);
|
||||
if(n == 9)
|
||||
{
|
||||
int max = time.month_day >= 30 ? 1 : 9;
|
||||
ok = (val <= max);
|
||||
}
|
||||
|
||||
if(ok)
|
||||
{
|
||||
set_region(&time, n, val);
|
||||
n++;
|
||||
if(n == region_count)
|
||||
{
|
||||
time.year -= 1900;
|
||||
rtc_setTime(time);
|
||||
return;
|
||||
}
|
||||
slide = 0;
|
||||
}
|
||||
else leave = 0;
|
||||
}
|
||||
|
||||
else leave = 0;
|
||||
} while(!leave);
|
||||
}
|
||||
|
||||
while(getkey() != KEY_EXIT);
|
||||
}
|
||||
|
||||
void test_rtc(void)
|
||||
{
|
||||
int key;
|
||||
|
||||
rtc_setCallback(callback, RTCFreq_1Hz);
|
||||
callback();
|
||||
|
||||
while(1)
|
||||
{
|
||||
key = getkey();
|
||||
|
||||
if(key == KEY_EXIT) break;
|
||||
if(key == KEY_F1)
|
||||
{
|
||||
rtc_setCallback(NULL, RTCFreq_1Hz);
|
||||
set();
|
||||
callback();
|
||||
rtc_setCallback(callback, RTCFreq_1Hz);
|
||||
}
|
||||
}
|
||||
|
||||
rtc_setCallback(NULL, RTCFreq_1Hz);
|
||||
}
|
BIN
gintdemo.g1a
BIN
gintdemo.g1a
Binary file not shown.
118
include/internals/rtc.h
Normal file
118
include/internals/rtc.h
Normal file
|
@ -0,0 +1,118 @@
|
|||
#ifndef _INTERNALS_RTC_H
|
||||
#define _INTERNALS_RTC_H 1
|
||||
|
||||
/*
|
||||
struct mod_rtc
|
||||
This structure describes the arrangement of RTC register in the memory.
|
||||
Curious thing, on SH7705, registers RYRAR and RCR3 are at a completely
|
||||
different address than the other ones. This module does not use these
|
||||
registers, so they were not included in the structure.
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
|
||||
struct mod_rtc
|
||||
{
|
||||
unsigned char const R64CNT;
|
||||
unsigned char _1;
|
||||
|
||||
union {
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned :1;
|
||||
unsigned TENS :3;
|
||||
unsigned ONES :4;
|
||||
};
|
||||
} RSECCNT;
|
||||
unsigned char _2;
|
||||
|
||||
union {
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned :1;
|
||||
unsigned TENS :3;
|
||||
unsigned ONES :4;
|
||||
};
|
||||
} RMINCNT;
|
||||
unsigned char _3;
|
||||
|
||||
union {
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned :2;
|
||||
unsigned TENS :2;
|
||||
unsigned ONES :4;
|
||||
};
|
||||
} RHRCNT;
|
||||
unsigned char _4;
|
||||
|
||||
// 0 = Sunday, 1 = Monday, ..., 6 = Saturday, 7 = prohibited setting.
|
||||
unsigned char RWKCNT;
|
||||
unsigned char _5;
|
||||
|
||||
union {
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned :2;
|
||||
unsigned TENS :2;
|
||||
unsigned ONES :4;
|
||||
};
|
||||
} RDAYCNT;
|
||||
unsigned char _6;
|
||||
|
||||
union {
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned :3;
|
||||
unsigned TENS :1;
|
||||
unsigned ONES :4;
|
||||
};
|
||||
} RMONCNT;
|
||||
unsigned char _7;
|
||||
|
||||
union {
|
||||
unsigned short WORD;
|
||||
struct {
|
||||
unsigned THOUSANDS :4;
|
||||
unsigned HUNDREDS :4;
|
||||
unsigned TENS :4;
|
||||
unsigned ONES :4;
|
||||
};
|
||||
} RYRCNT;
|
||||
unsigned char _8[12];
|
||||
|
||||
union {
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned CF :1;
|
||||
unsigned :2;
|
||||
unsigned CIE :1;
|
||||
unsigned AIE :1;
|
||||
unsigned :2;
|
||||
unsigned AF :1;
|
||||
};
|
||||
} RCR1;
|
||||
unsigned char _9;
|
||||
|
||||
union {
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned PEF :1;
|
||||
unsigned PES :3;
|
||||
unsigned :1;
|
||||
unsigned ADJ :1;
|
||||
unsigned RESET :1;
|
||||
unsigned START :1;
|
||||
};
|
||||
} RCR2;
|
||||
} __attribute__((packed));
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
/*
|
||||
We don't need to access the registers in a complicated way like the
|
||||
function of the timer module. Let's make it simple.
|
||||
*/
|
||||
#define RTC_SH7705 ((volatile struct mod_rtc *)0xfffffec0)
|
||||
#define RTC_SH7305 ((volatile struct mod_rtc *)0xa413fec0)
|
||||
|
||||
#endif // _INTERNALS_RTC_H
|
|
@ -20,35 +20,29 @@ extern struct Timer timers[3];
|
|||
*/
|
||||
struct mod_tmu
|
||||
{
|
||||
// Timer constant register.
|
||||
unsigned int TCOR;
|
||||
// Timer counter.
|
||||
unsigned int TCNT;
|
||||
unsigned int TCOR; // Timer constant register.
|
||||
unsigned int TCNT; // Timer counter.
|
||||
|
||||
// Timer control register.
|
||||
union
|
||||
{
|
||||
unsigned short WORD;
|
||||
struct
|
||||
{
|
||||
unsigned :7;
|
||||
// Underflow flag.
|
||||
unsigned UNF :1;
|
||||
unsigned UNF :1; // Underflow flag.
|
||||
unsigned :2;
|
||||
// Underflow interrupt enable.
|
||||
unsigned UNIE :1;
|
||||
// Clock edge, reserved on SH7305.
|
||||
unsigned CKEG :2;
|
||||
// Timer prescaler.
|
||||
unsigned TPSC :3;
|
||||
unsigned UNIE :1; // Underflow interrupt enable.
|
||||
unsigned CKEG :2; // Clock edge (SH7705 only).
|
||||
unsigned TPSC :3; // Timer prescaler.
|
||||
};
|
||||
} TCR;
|
||||
} TCR; // Timer control register.
|
||||
};
|
||||
|
||||
/*
|
||||
timer_get()
|
||||
Returns the timer and TSTR register addresses.
|
||||
*/
|
||||
void timer_get(int timer, struct mod_tmu **tmu, unsigned char **tstr);
|
||||
void timer_get(int timer, volatile struct mod_tmu **tmu,
|
||||
volatile unsigned char **tstr);
|
||||
|
||||
#endif // _INTERNALS_TIMER_H
|
||||
|
|
|
@ -9,6 +9,43 @@
|
|||
#ifndef _RTC_H
|
||||
#define _RTC_H 1
|
||||
|
||||
//---
|
||||
// Time access.
|
||||
//---
|
||||
|
||||
/*
|
||||
struct RTCTime
|
||||
Defines a point in time. This structure *is* the standard struct tm to
|
||||
avoid useless data copy in the interface between this module and the
|
||||
standard time module.
|
||||
*/
|
||||
struct RTCTime
|
||||
{
|
||||
int seconds; // Seconds in range 0-59
|
||||
int minutes; // Minutes in range 0-59
|
||||
int hours; // Hours in range 0-23
|
||||
int month_day; // Day of month in range 1-31
|
||||
int month; // Month in range 0-11
|
||||
int year; // Number of years since 1900
|
||||
int week_day; // Day of week in range 0(Sunday)-6(Saturday).
|
||||
int year_day; // Day of the year in range 0-365.
|
||||
int daylight_saving; // As far as I known the RTC does not use DST.
|
||||
};
|
||||
|
||||
/*
|
||||
rtc_getTime()
|
||||
Reads the current time from the RTC.
|
||||
*/
|
||||
struct RTCTime rtc_getTime(void);
|
||||
|
||||
/*
|
||||
rtc_setTime()
|
||||
Sets the time in the RTC registers.
|
||||
*/
|
||||
void rtc_setTime(struct RTCTime time);
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Callback API.
|
||||
//---
|
||||
|
|
|
@ -10,12 +10,33 @@
|
|||
#ifndef _STDLIB_H
|
||||
#define _STDLIB_H 1
|
||||
|
||||
//---
|
||||
// Common definitions.
|
||||
//---
|
||||
|
||||
#include <stddef.h>
|
||||
#include <limits.h>
|
||||
|
||||
// Common exit codes.
|
||||
#define EXIT_SUCCESS 1
|
||||
#define EXIT_FAILURE 0
|
||||
|
||||
// Number of atexit() registrations guaranteed.
|
||||
#define ATEXIT_MAX 16
|
||||
|
||||
// Maximum value returned by rand().
|
||||
#define RAND_MAX INT_MAX
|
||||
|
||||
// Integer division result.
|
||||
typedef struct
|
||||
{
|
||||
int quot, rem;
|
||||
} div_t;
|
||||
typedef struct
|
||||
{
|
||||
long quot, rem;
|
||||
} ldiv_t;
|
||||
|
||||
|
||||
|
||||
//---
|
||||
|
@ -35,6 +56,12 @@ void abort(void);
|
|||
*/
|
||||
void exit(int status);
|
||||
|
||||
/*
|
||||
atexit()
|
||||
Registers a function to be called at normal program termination.
|
||||
*/
|
||||
int atexit(void (*function)(void));
|
||||
|
||||
|
||||
|
||||
//---
|
||||
|
@ -55,14 +82,28 @@ void *malloc(size_t size);
|
|||
*/
|
||||
void *calloc(size_t n, size_t size);
|
||||
|
||||
/*
|
||||
realloc()
|
||||
Reallocates a memory block and moves its data.
|
||||
*/
|
||||
void *realloc(void *ptr, size_t size);
|
||||
|
||||
/*
|
||||
free()
|
||||
Frees a memory block allocated with malloc().
|
||||
Frees a memory block allocated by malloc(), calloc() or realloc().
|
||||
*/
|
||||
void free(void *ptr);
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Random number generation.
|
||||
//---
|
||||
|
||||
/*
|
||||
int rand(void)
|
||||
*/
|
||||
|
||||
//---
|
||||
// Integer arithmetic.
|
||||
//---
|
||||
|
@ -73,8 +114,26 @@ void free(void *ptr);
|
|||
*/
|
||||
int abs(int x);
|
||||
// Use a macro instead, when possible.
|
||||
#define abs(x) ((x) < 0 ? -(x) : (x))
|
||||
#define abs(x) ((x) < 0 ? -(x) : (x))
|
||||
|
||||
/*
|
||||
labs()
|
||||
Returns the absolute value of a long integer.
|
||||
*/
|
||||
long labs(long x);
|
||||
// Use a macro instead.
|
||||
#define labs(x) ((x) < 0 ? -(x) : (x))
|
||||
|
||||
/*
|
||||
div()
|
||||
Computes the integer division of numerator by denominator.
|
||||
*/
|
||||
div_t div(int numerator, int denominator);
|
||||
|
||||
/*
|
||||
ldiv()
|
||||
Computes the integer division of two long integers.
|
||||
*/
|
||||
ldiv_t ldiv(long numerator, long denominator);
|
||||
|
||||
#endif // _STDLIB_H
|
||||
|
|
85
include/time.h
Normal file
85
include/time.h
Normal file
|
@ -0,0 +1,85 @@
|
|||
//---
|
||||
//
|
||||
// standard library module: time
|
||||
//
|
||||
// Provides time manipulation and representation functions.
|
||||
//
|
||||
//---
|
||||
|
||||
#ifndef _TIME_H
|
||||
#define _TIME_H 1
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
//---
|
||||
// Some related types.
|
||||
//---
|
||||
|
||||
/*
|
||||
struct tm
|
||||
Represents a point in time and gives some date information.
|
||||
*/
|
||||
struct tm
|
||||
{
|
||||
int tm_sec; // Seconds in range 0-59
|
||||
int tm_min; // Minutes in range 0-59
|
||||
int tm_hour; // Hours in range 0-23
|
||||
int tm_mday; // Day of month in range 1-31
|
||||
int tm_mon; // Month in range 0-11
|
||||
int tm_year; // Number of years since 1900
|
||||
int tm_wday; // Day of week in range 0(Sunday)-6(Saturday).
|
||||
int tm_yday; // Day of the year in range 0-365.
|
||||
int tm_isdst; // Always -1 (not available).
|
||||
};
|
||||
|
||||
/*
|
||||
clock_t
|
||||
Only used by clock().
|
||||
*/
|
||||
typedef signed int clock_t;
|
||||
|
||||
/*
|
||||
time_t
|
||||
Number of seconds elapsed since 1970-01-01 00:00:00.
|
||||
*/
|
||||
typedef signed int time_t;
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Time access.
|
||||
//---
|
||||
|
||||
/*
|
||||
clock()
|
||||
Should return elapsed CPU time since beginning of program execution.
|
||||
This is currently not implemented and returns -1.
|
||||
*/
|
||||
clock_t clock(void);
|
||||
|
||||
/*
|
||||
difftime()
|
||||
Returns the number of seconds between the given points.
|
||||
*/
|
||||
double difftime(time_t end, time_t beginning);
|
||||
// But this macro should do.
|
||||
#define difftime(end, beginning) ((double)((end) - (beginning)))
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Time representation.
|
||||
//---
|
||||
|
||||
//---
|
||||
//
|
||||
//---
|
||||
|
||||
/*
|
||||
mktime()
|
||||
Computes fields tm_wday and tm_yday using the other fields. Member
|
||||
structures outside their range are normalized and tm_isdst is set.
|
||||
*/
|
||||
time_t mktime(struct tm *time);
|
||||
|
||||
#endif // _TIME_H
|
BIN
libc.a
BIN
libc.a
Binary file not shown.
BIN
libgint.a
BIN
libgint.a
Binary file not shown.
|
@ -38,7 +38,7 @@ void dimage_part(int x, int y, struct Image *img, int left, int top,
|
|||
command.bottom = top + ((y + height > 64) ? (64 - y) : height);
|
||||
command.left = ((x < 0) ? (left - x) : left) >> 5;
|
||||
actual_width = (x + width > 128) ? (128 - x) : width;
|
||||
command.right = left + ((actual_width + 31) >> 5) - 1;
|
||||
command.right = ((left + actual_width + 31) >> 5) - 1;
|
||||
|
||||
command.op = bopti_op_mono;
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ void gimage_part(int x, int y, struct Image *img, int left, int top,
|
|||
command.bottom = top + ((y + height > 64) ? (64 - y) : height);
|
||||
command.left = ((x < 0) ? (left - x) : left) >> 5;
|
||||
actual_width = (x + width > 128) ? (128 - x) : width;
|
||||
command.right = left + ((actual_width + 31) >> 5) - 1;
|
||||
command.right = ((left + actual_width + 31) >> 5) - 1;
|
||||
|
||||
command.op = bopti_op_gray;
|
||||
|
||||
|
|
|
@ -23,6 +23,10 @@ extern unsigned int
|
|||
static int exit_code = EXIT_SUCCESS;
|
||||
static jmp_buf env;
|
||||
|
||||
// Exit handlers.
|
||||
void (*atexit_handlers[ATEXIT_MAX])(void);
|
||||
int atexit_index = 0;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
@ -69,6 +73,9 @@ int start(void)
|
|||
|
||||
// Remember to flush and close opened streams.
|
||||
|
||||
// Calling exit handlers.
|
||||
while(atexit_index > 0) (*atexit_handlers[--atexit_index])();
|
||||
|
||||
// Un-initializing everything.
|
||||
fini();
|
||||
gint_quit();
|
||||
|
@ -76,6 +83,10 @@ int start(void)
|
|||
return exit_code;
|
||||
}
|
||||
|
||||
/*
|
||||
init()
|
||||
Calls the constructors.
|
||||
*/
|
||||
static void init(void)
|
||||
{
|
||||
extern void
|
||||
|
@ -83,7 +94,6 @@ static void init(void)
|
|||
(*ectors)(void);
|
||||
void (**func)(void) = &bctors;
|
||||
|
||||
// Calling the constructors.
|
||||
while(func < &ectors)
|
||||
{
|
||||
(*(*func))();
|
||||
|
@ -91,6 +101,10 @@ static void init(void)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
fini()
|
||||
Calls the destructors.
|
||||
*/
|
||||
static void fini(void)
|
||||
{
|
||||
extern void
|
||||
|
@ -98,7 +112,6 @@ static void fini(void)
|
|||
(*edtors)(void);
|
||||
void (**func)(void) = &bdtors;
|
||||
|
||||
// Calling the destructors.
|
||||
while(func < &edtors)
|
||||
{
|
||||
(*(*func))();
|
||||
|
@ -112,10 +125,13 @@ static void fini(void)
|
|||
abort()
|
||||
Immediately ends the program without invoking the exit handlers.
|
||||
*/
|
||||
|
||||
void abort(void)
|
||||
{
|
||||
exit_code = EXIT_FAILURE;
|
||||
|
||||
// Avoiding any exit handler call.
|
||||
atexit_index = 0;
|
||||
|
||||
longjmp(env, 1);
|
||||
}
|
||||
|
||||
|
@ -129,10 +145,21 @@ void abort(void)
|
|||
of achieving this goal while minimizing interaction with the operating
|
||||
system.
|
||||
*/
|
||||
|
||||
void exit(int status)
|
||||
{
|
||||
exit_code = status;
|
||||
longjmp(env, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
atexit()
|
||||
Registers a function to be called at normal program termination.
|
||||
*/
|
||||
int atexit(void (*function)(void))
|
||||
{
|
||||
if(atexit_index >= ATEXIT_MAX) return 1;
|
||||
|
||||
atexit_handlers[atexit_index++] = function;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
53
src/rtc/rtc_getTime.c
Normal file
53
src/rtc/rtc_getTime.c
Normal file
|
@ -0,0 +1,53 @@
|
|||
#include <internals/rtc.h>
|
||||
#include <rtc.h>
|
||||
#include <mpu.h>
|
||||
|
||||
/*
|
||||
integer()
|
||||
Converts a BCD value to an integer.
|
||||
*/
|
||||
static int integer8(int bcd)
|
||||
{
|
||||
return (bcd & 0x0f) + 10 * (bcd >> 4);
|
||||
}
|
||||
static int integer16(int bcd)
|
||||
{
|
||||
return (bcd & 0xf) + 10 * ((bcd >> 4) & 0xf) + 100 * ((bcd >> 8) & 0xf)
|
||||
+ 1000 * (bcd >> 12);
|
||||
}
|
||||
|
||||
static int year_day(int year, int year_bcd, int month, int month_day)
|
||||
{
|
||||
int days_in_month[12] = {
|
||||
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
int leap;
|
||||
int hundreds = integer8(year_bcd >> 8);
|
||||
int day, i;
|
||||
|
||||
leap = !(year & 3); // Take multiples of 4
|
||||
if(!((year_bcd >> 8) & 0xf)) leap = 0; // Remove multiples of 100
|
||||
if(!(hundreds & 3)) leap = 1; // Take multiples of 400
|
||||
|
||||
day = leap && (month > 2);
|
||||
for(i = 0; i < month - 1; i++) day += days_in_month[i];
|
||||
return day + month_day - 1;
|
||||
}
|
||||
|
||||
struct RTCTime rtc_getTime(void)
|
||||
{
|
||||
volatile struct mod_rtc *rtc = isSH3() ? RTC_SH7705 : RTC_SH7305;
|
||||
struct RTCTime time;
|
||||
|
||||
time.seconds = integer8(rtc->RSECCNT.BYTE);
|
||||
time.minutes = integer8(rtc->RMINCNT.BYTE);
|
||||
time.hours = integer8(rtc->RHRCNT.BYTE);
|
||||
time.month_day = integer8(rtc->RDAYCNT.BYTE);
|
||||
time.month = integer8(rtc->RMONCNT.BYTE);
|
||||
time.year = integer16(rtc->RYRCNT.WORD) - 1900;
|
||||
time.week_day = rtc->RWKCNT;
|
||||
time.year_day = year_day(time.year + 1900, rtc->RYRCNT.WORD,
|
||||
time.month, time.month_day);
|
||||
|
||||
time.daylight_saving = 0;
|
||||
return time;
|
||||
}
|
31
src/rtc/rtc_setTime.c
Normal file
31
src/rtc/rtc_setTime.c
Normal file
|
@ -0,0 +1,31 @@
|
|||
#include <internals/rtc.h>
|
||||
#include <rtc.h>
|
||||
#include <mpu.h>
|
||||
|
||||
/*
|
||||
bcd()
|
||||
Converts an integer to a BCD value.
|
||||
*/
|
||||
static int bcd8(int integer)
|
||||
{
|
||||
integer %= 100;
|
||||
return ((integer / 10) << 4) | (integer % 10);
|
||||
}
|
||||
static int bcd16(int integer)
|
||||
{
|
||||
integer %= 10000;
|
||||
return (bcd8(integer / 100) << 8) | bcd8(integer % 100);
|
||||
}
|
||||
|
||||
void rtc_setTime(struct RTCTime time)
|
||||
{
|
||||
volatile struct mod_rtc *rtc = isSH3() ? RTC_SH7705 : RTC_SH7305;
|
||||
|
||||
rtc->RSECCNT.BYTE = bcd8(time.seconds);
|
||||
rtc->RMINCNT.BYTE = bcd8(time.minutes);
|
||||
rtc->RHRCNT.BYTE = bcd8(time.hours);
|
||||
rtc->RDAYCNT.BYTE = bcd8(time.month_day);
|
||||
rtc->RMONCNT.BYTE = bcd8(time.month);
|
||||
rtc->RYRCNT.WORD = bcd16(time.year + 1900);
|
||||
rtc->RWKCNT = time.week_day < 7 ? time.week_day : 0;
|
||||
}
|
|
@ -9,7 +9,7 @@
|
|||
Internal buffer.
|
||||
|
||||
Using a buffer *really* simplifies everything. But it also has
|
||||
disadvantages, such a memory loss and limited output size.
|
||||
disadvantages, such as some memory loss and limited output size.
|
||||
|
||||
So, in case we find a possibility to get rid of this buffer, we will
|
||||
just have to change function character(), which is for now the only
|
||||
|
@ -20,35 +20,34 @@ char __stdio_buffer[__stdio_buffer_size];
|
|||
|
||||
|
||||
/*
|
||||
Format composed types.
|
||||
Composed types for format definition.
|
||||
|
||||
Format structure handles everything in a format, from data type to
|
||||
given value, including alternative forms, alignment and digit numbers.
|
||||
The Format structure handles everything in a format: data type, value,
|
||||
alternative forms, alignment and character number, precision... there
|
||||
are mainly a data type (altered by a size option), a value to print
|
||||
and a number of characters.
|
||||
|
||||
A format is made of a data type, which can be altered by a size option,
|
||||
a number of integer and decimal digits, and additional flags.
|
||||
|
||||
The FormatFlags enumeration handles the various flags that can be added
|
||||
to a printf()-family format.
|
||||
Other options are handled by The FormatFlags enumeration. See the
|
||||
description of functions __printf() for further description on option
|
||||
precedence and influence.
|
||||
*/
|
||||
|
||||
enum FormatFlags
|
||||
{
|
||||
// Option '#' specifies alternatives forms, mainly '0' and '0x'
|
||||
// prefixes in integer display.
|
||||
// Alternatives forms add '0' and '0x' prefixes in octal and
|
||||
// hexadecimal bases. (#)
|
||||
Alternative = 1,
|
||||
// Under specific conditions, zero-padding may be used instead of
|
||||
// whitespace-padding.
|
||||
// whitespace-padding. (0)
|
||||
ZeroPadded = 2,
|
||||
// Left alignment specifies that additional spaces should be added
|
||||
// after the value.
|
||||
// after the value instead of before. (-)
|
||||
LeftAlign = 4,
|
||||
// In numeric display, this forces a blank sign to be written before
|
||||
// positive values.
|
||||
// positive values. ( )
|
||||
BlankSign = 8,
|
||||
// In numeric display, this forces an explicit sign in all cases. This
|
||||
// option overrides BlankSign (see __printf() description for further
|
||||
// information on option precedence and influence).
|
||||
// option overrides BlankSign. (+)
|
||||
ForceSign = 16
|
||||
};
|
||||
|
||||
|
@ -72,7 +71,7 @@ struct Format
|
|||
{
|
||||
// Signed int with formats %c, %d and %i.
|
||||
signed int _int;
|
||||
// Insigned int with formats %o, %u, %x and %X.
|
||||
// Unsigned int with formats %o, %u, %x and %X.
|
||||
unsigned int _unsigned;
|
||||
// Double with formats %f, %F, %e, %E, %g and %G.
|
||||
// double _double;
|
||||
|
@ -364,8 +363,7 @@ static void get_spacing(struct Format format, int *begin_spaces, int *sign,
|
|||
__printf()
|
||||
|
||||
Basic buffered formatted printing function. Fully-featured, so that
|
||||
ant call to a printf()-family function can be translated into a
|
||||
__printf() call.
|
||||
any call to a printf()-family function can be performed by __printf().
|
||||
|
||||
It always returns the number of characters of the theoretic formatted
|
||||
output. The real output may be limited in size by the given size
|
||||
|
@ -376,30 +374,27 @@ static void get_spacing(struct Format format, int *begin_spaces, int *sign,
|
|||
argument handling (because flag effects depend on format type, which
|
||||
is unknown when the flags are read). Also, length modifiers 'hh' is
|
||||
stored as 'i' to simplify structure handling. 'll' is not supported.
|
||||
Format '%LF' is allowed by C99 and therefore supported.
|
||||
Support for format '%lf' (C99) is planned.
|
||||
|
||||
Generic information on options precedence and influence.
|
||||
- Influences of integer part and mantissa digit numbers depend on
|
||||
the type of data that is being displayed.
|
||||
- Option '#' doesn't contend with any other.
|
||||
- Option '+' overrides options ' '.
|
||||
- In integer display, option '0' translates spaces to zeros, but
|
||||
only if no decimal digit number is specified.
|
||||
The option '-' also overrides it, forcing whitespaces to be
|
||||
written at the end of the format.
|
||||
- Number of characters and precision represent different lengths
|
||||
depending on the data type.
|
||||
- '#' is independent.
|
||||
- '+' overrides ' '.
|
||||
- In integer display, '0' replaces spaces to zeros, only if no
|
||||
precision (decimal digit number) is specified.
|
||||
- '-' also overrides it, forcing whitespaces to be written at the end.
|
||||
|
||||
Limit of function.
|
||||
- Internal buffer size (should be customizable with a -D option
|
||||
when compiling).
|
||||
- Precision values (format %a.b) are written on 8 bits, therefore
|
||||
limited to 127.
|
||||
Limits of function.
|
||||
- Internal buffer size (there should be a loop to allow larger data).
|
||||
- Precision values (format %a.b) are limited to 127.
|
||||
|
||||
Unsupported features.
|
||||
- Flag character ''' (single quote) for thousands grouping
|
||||
- Flag character 'I', that outputs locale's digits (glibc 2.2)
|
||||
- Length modifiers 'll' and 'q' (libc 5 and 4.4 BSD)
|
||||
- This is not really a feature but incorrect characters in
|
||||
formats are ignored and don't invalidate the format.
|
||||
- ''' (single quote) (thousands grouping)
|
||||
- 'I' (outputs locale's digits (glibc 2.2))
|
||||
- Length modifiers 'll' and 'q' (libc 5 and 4.4 BSD)
|
||||
- This is not really a feature but incorrect characters in formats are
|
||||
ignored and don't invalidate the format.
|
||||
*/
|
||||
int __printf(size_t size, const char *string, va_list args)
|
||||
{
|
||||
|
@ -409,7 +404,7 @@ int __printf(size_t size, const char *string, va_list args)
|
|||
if(!size || size > __stdio_buffer_size)
|
||||
size = __stdio_buffer_size;
|
||||
|
||||
// Initializing character() working values.
|
||||
// Initializing character() variables.
|
||||
written = 0;
|
||||
total = 0;
|
||||
max = size;
|
||||
|
@ -437,8 +432,7 @@ int __printf(size_t size, const char *string, va_list args)
|
|||
format = get_format(&string);
|
||||
if(!format.type) break;
|
||||
|
||||
/*
|
||||
// Displaying an information message.
|
||||
/* Some debugging...
|
||||
printf(
|
||||
"Format found :%s%c%c, options %d, and %d.%d "
|
||||
"digits\n",
|
||||
|
@ -448,8 +442,7 @@ int __printf(size_t size, const char *string, va_list args)
|
|||
format.flags,
|
||||
format.digits,
|
||||
format.mantissa
|
||||
);
|
||||
*/
|
||||
); */
|
||||
|
||||
switch(format.type)
|
||||
{
|
||||
|
@ -459,15 +452,8 @@ int __printf(size_t size, const char *string, va_list args)
|
|||
format._int = va_arg(args, signed int);
|
||||
|
||||
// Reducing value depending on format size.
|
||||
switch(format.size)
|
||||
{
|
||||
case 'h':
|
||||
format._int &= 0x0000ffff;
|
||||
break;
|
||||
case 'i':
|
||||
format._int &= 0x000000ff;
|
||||
break;
|
||||
}
|
||||
if(format.size == 'h') format._int &= 0x0000ffff;
|
||||
if(format.size == 'i') format._int &= 0x000000ff;
|
||||
|
||||
format_di(format);
|
||||
break;
|
||||
|
@ -877,7 +863,7 @@ void format_p(struct Format format)
|
|||
|
||||
unsigned int x = format._unsigned;
|
||||
int bspaces, zeros, digits = 0, espaces;
|
||||
int c;
|
||||
int c, i;
|
||||
|
||||
digits = x ? 10 : 5;
|
||||
get_spacing(format, &bspaces, NULL, &zeros, digits, &espaces);
|
||||
|
@ -889,7 +875,7 @@ void format_p(struct Format format)
|
|||
{
|
||||
character('0');
|
||||
character('x');
|
||||
while(x)
|
||||
for(i = 0; i < 8; i++)
|
||||
{
|
||||
c = x >> 28;
|
||||
c += '0' + 39 * (c > 9);
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
#include <stdlib.h>
|
||||
#undef abs
|
||||
|
||||
int abs(int x)
|
||||
{
|
||||
return (x < 0) ? (-x) : (x);
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
calloc()
|
||||
|
|
13
src/stdlib/stdlib_abs.c
Normal file
13
src/stdlib/stdlib_abs.c
Normal file
|
@ -0,0 +1,13 @@
|
|||
#include <stdlib.h>
|
||||
#undef abs
|
||||
#undef labs
|
||||
|
||||
int abs(int x)
|
||||
{
|
||||
return (x < 0) ? (-x) : x;
|
||||
}
|
||||
|
||||
long labs(long x)
|
||||
{
|
||||
return (x < 0) ? (-x) : x;
|
||||
}
|
29
src/stdlib/stdlib_div.c
Normal file
29
src/stdlib/stdlib_div.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
div()
|
||||
Computes the integer division of numerator by denominator.
|
||||
*/
|
||||
div_t div(int numerator, int denominator)
|
||||
{
|
||||
div_t result;
|
||||
|
||||
result.quot = numerator / denominator;
|
||||
result.rem = numerator - result.quot * denominator;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
ldiv()
|
||||
Computes the integer division of two long integers.
|
||||
*/
|
||||
ldiv_t ldiv(long numerator, long denominator)
|
||||
{
|
||||
ldiv_t result;
|
||||
|
||||
result.quot = numerator / denominator;
|
||||
result.rem = numerator - result.quot * denominator;
|
||||
|
||||
return result;
|
||||
}
|
14
src/stdlib/stdlib_rand.c
Normal file
14
src/stdlib/stdlib_rand.c
Normal file
|
@ -0,0 +1,14 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
static unsigned int seed = 1;
|
||||
|
||||
void srand(unsigned int new_seed)
|
||||
{
|
||||
seed = new_seed;
|
||||
}
|
||||
|
||||
int rand(void)
|
||||
{
|
||||
seed = seed * 1103515245 + 12345;
|
||||
return seed & 0x7fffffff;
|
||||
}
|
93
src/time/mktime.c
Normal file
93
src/time/mktime.c
Normal file
|
@ -0,0 +1,93 @@
|
|||
#include <time.h>
|
||||
|
||||
/*
|
||||
isLeap()
|
||||
Determines whether the given year is a leap year.
|
||||
*/
|
||||
int isLeap(int year)
|
||||
{
|
||||
int leap = !(year & 3); // Take multiples of 4
|
||||
if(!(year % 100)) leap = 0; // Remove multiples of 100
|
||||
if(!(year % 400)) leap = 1; // Take multiples of 400
|
||||
|
||||
return leap;
|
||||
}
|
||||
|
||||
/*
|
||||
daysInMonth()
|
||||
Returns number of days for the given month (between 0 and 11) and year.
|
||||
*/
|
||||
int daysInMonth(int month, int year)
|
||||
{
|
||||
int days[12] = {
|
||||
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
|
||||
};
|
||||
|
||||
if(month != 1) return days[month];
|
||||
return days[month] + isLeap(year);
|
||||
}
|
||||
|
||||
/*
|
||||
mktime()
|
||||
Computes fields tm_wday and tm_yday using the other fields. Member
|
||||
structures outside their range are normalized and tm_isdst is set.
|
||||
*/
|
||||
time_t mktime(struct tm *time)
|
||||
{
|
||||
int first, leaps, yr;
|
||||
int days, i;
|
||||
time_t elapsed;
|
||||
|
||||
// Normalizing time.
|
||||
time->tm_min += (time->tm_sec / 60);
|
||||
time->tm_hour += (time->tm_min / 60);
|
||||
time->tm_mday += (time->tm_hour / 24);
|
||||
time->tm_sec %= 60;
|
||||
time->tm_min %= 60;
|
||||
time->tm_hour %= 24;
|
||||
|
||||
// Normalizing date.
|
||||
days = daysInMonth(time->tm_mon, time->tm_year + 1900);
|
||||
while(time->tm_mday >= days)
|
||||
{
|
||||
time->tm_mday -= days;
|
||||
if(++time->tm_mon == 12)
|
||||
{
|
||||
time->tm_mon = 0;
|
||||
time->tm_year++;
|
||||
}
|
||||
days = daysInMonth(time->tm_mon, time->tm_year + 1900);
|
||||
}
|
||||
|
||||
// Setting the year day.
|
||||
days = 0;
|
||||
for(i = 0; i < time->tm_mon; i++)
|
||||
days += daysInMonth(i, time->tm_year + 1900);
|
||||
time->tm_yday = days + time->tm_mday;
|
||||
|
||||
// Setting the week day. The calendar is periodic over 400 years and
|
||||
// 1601-01-01 was a Monday.
|
||||
|
||||
// Years completely elapsed since last 400n + 1 year (1601-2001-etc).
|
||||
yr = (time->tm_year + 1900 - 1) % 400;
|
||||
// Leap years in these yr years.
|
||||
leaps = (yr / 4) - (yr >= 100) - (yr >= 200) - (yr >= 300);
|
||||
// Days completely elapsed since last 400n + 1 year, 01-01.
|
||||
days = 365 * yr + leaps + time->tm_yday;
|
||||
// Current day of week (1 means Monday 1601-01-01).
|
||||
time->tm_wday = (1 + days) % 7;
|
||||
|
||||
// This RTC does not seem to have any DST feature.
|
||||
time->tm_isdst = 0;
|
||||
|
||||
if(time->tm_year + 1900 < 1970) return (time_t)-1;
|
||||
|
||||
// 134774 is the number of days between 1601-01-01 and 1970-01-01. Thus
|
||||
// days become the number of days elapsed since 1970-01-01.
|
||||
days -= 134774;
|
||||
// days may become negative, so add the calendar period.
|
||||
if(days < 0) days += 146097;
|
||||
|
||||
return (24 * 3600) * days + 3600 * time->tm_hour + 60 * time->tm_min +
|
||||
time->tm_sec;
|
||||
}
|
20
src/time/time_misc.c
Normal file
20
src/time/time_misc.c
Normal file
|
@ -0,0 +1,20 @@
|
|||
#include <time.h>
|
||||
|
||||
/*
|
||||
clock()
|
||||
Should return elapsed CPU time since beginning of program execution.
|
||||
This is currently not implemented and returns -1.
|
||||
*/
|
||||
clock_t clock(void)
|
||||
{
|
||||
return (clock_t)-1;
|
||||
}
|
||||
|
||||
/*
|
||||
difftime()
|
||||
Returns the number of seconds between the given points.
|
||||
*/
|
||||
double difftime(time_t end, time_t beginning)
|
||||
{
|
||||
return (double)(end - beginning);
|
||||
}
|
|
@ -5,21 +5,21 @@
|
|||
timer_get()
|
||||
Returns the timer and TSTR register addresses.
|
||||
*/
|
||||
void timer_get(int timer, struct mod_tmu **tmu, unsigned char **tstr)
|
||||
void timer_get(int timer, volatile struct mod_tmu **tmu,
|
||||
volatile unsigned char **tstr)
|
||||
{
|
||||
// Using SH7705 information for SH-3-based MPUs.
|
||||
if(isSH3())
|
||||
{
|
||||
if(tstr) *tstr = (unsigned char *)0xfffffe92;
|
||||
if(tmu) *tmu = (struct mod_tmu *)0xfffffe94;
|
||||
if(tstr) *tstr = (volatile unsigned char *)0xfffffe92;
|
||||
if(tmu) *tmu = (volatile struct mod_tmu *)
|
||||
(0xfffffe94 + 12 * timer);
|
||||
}
|
||||
// Assuming SH7305 by default.
|
||||
else
|
||||
{
|
||||
if(tstr) *tstr = (unsigned char *)0xa4490004;
|
||||
if(tmu) *tmu = (struct mod_tmu *)0xa4490008;
|
||||
if(tstr) *tstr = (volatile unsigned char *)0xa4490004;
|
||||
if(tmu) *tmu = (volatile struct mod_tmu *)
|
||||
(0xa4490008 + 12 * timer);
|
||||
}
|
||||
|
||||
// Shifting tmu value to get to the timer-nth timer in the unit.
|
||||
if(tmu) *tmu += timer;
|
||||
}
|
||||
|
|
|
@ -11,11 +11,11 @@ struct Timer timers[3] = { { NULL, 0 }, { NULL, 0 }, { NULL, 0 } };
|
|||
*/
|
||||
void timer_interrupt(int timer)
|
||||
{
|
||||
struct mod_tmu *tmu;
|
||||
volatile struct mod_tmu *tmu;
|
||||
timer_get(timer, &tmu, NULL);
|
||||
|
||||
// Resetting the interrupt flag.
|
||||
(*tmu).TCR.UNF = 0;
|
||||
tmu->TCR.UNF = 0;
|
||||
|
||||
// Calling the callback function.
|
||||
if(timers[timer].callback) timers[timer].callback();
|
||||
|
|
|
@ -8,14 +8,14 @@
|
|||
*/
|
||||
void timer_reload(int timer, int new_delay)
|
||||
{
|
||||
struct mod_tmu *tmu;
|
||||
unsigned char *tstr;
|
||||
volatile struct mod_tmu *tmu;
|
||||
volatile unsigned char *tstr;
|
||||
int byte = (1 << timer);
|
||||
timer_get(timer, &tmu, &tstr);
|
||||
|
||||
// Setting the constant and the delay.
|
||||
(*tmu).TCOR = new_delay;
|
||||
(*tmu).TCNT = new_delay;
|
||||
tmu->TCOR = new_delay;
|
||||
tmu->TCNT = new_delay;
|
||||
|
||||
// Starting the timer.
|
||||
*tstr |= byte;
|
||||
|
|
|
@ -8,31 +8,28 @@
|
|||
void timer_start(int timer, int delay, int prescaler, void (*callback)(void),
|
||||
int repeats)
|
||||
{
|
||||
// Getting the timer address. Using a byte to alter TSTR.
|
||||
struct mod_tmu *tmu;
|
||||
unsigned char *tstr;
|
||||
volatile struct mod_tmu *tmu;
|
||||
volatile unsigned char *tstr;
|
||||
int byte = (1 << timer);
|
||||
|
||||
timer_get(timer, &tmu, &tstr);
|
||||
|
||||
// Setting the constant register.
|
||||
(*tmu).TCOR = delay;
|
||||
// Loading the delay in the counter.
|
||||
(*tmu).TCNT = delay;
|
||||
// Loading the counter, the constant and the prescaler/
|
||||
tmu->TCOR = delay;
|
||||
tmu->TCNT = delay;
|
||||
tmu->TCR.TPSC = prescaler;
|
||||
|
||||
// Resetting underflow flag.
|
||||
(*tmu).TCR.UNF = 0;
|
||||
// Enabling interruptions on underflow.
|
||||
(*tmu).TCR.UNIE = 1;
|
||||
// Counting on rising edge. On SH7305 these two bits are reserved but
|
||||
// writing 0 is ignored.
|
||||
(*tmu).TCR.CKEG = 0;
|
||||
// Setting the prescaler.
|
||||
(*tmu).TCR.TPSC = prescaler;
|
||||
// Resetting underflow flag and enabling interruptions.
|
||||
tmu->TCR.UNF = 0;
|
||||
tmu->TCR.UNIE = 1;
|
||||
|
||||
// Counting on rising edge (ignored on SH7305).
|
||||
tmu->TCR.CKEG = 0;
|
||||
|
||||
// Loading the structure information.
|
||||
timers[timer].callback = callback;
|
||||
timers[timer].repeats = repeats;
|
||||
|
||||
// Starting the timer and returning.
|
||||
// Starting the timer.
|
||||
*tstr |= byte;
|
||||
}
|
||||
|
|
|
@ -10,11 +10,9 @@
|
|||
*/
|
||||
void timer_stop(int timer)
|
||||
{
|
||||
// Getting TSTR address and the corresponding byte.
|
||||
unsigned char *tstr;
|
||||
volatile unsigned char *tstr;
|
||||
int byte = (1 << timer);
|
||||
timer_get(timer, NULL, &tstr);
|
||||
|
||||
// Stopping the timer.
|
||||
timer_get(timer, NULL, &tstr);
|
||||
*tstr &= ~byte;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue