mirror of
https://git.planet-casio.com/Lephenixnoir/gint.git
synced 2024-12-29 13:03: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
|
||||||
modules-gint = core keyboard mmu mpu rtc screen timer \
|
modules-gint = core keyboard mmu mpu rtc screen timer \
|
||||||
bopti display gray tales
|
bopti display gray tales
|
||||||
modules-libc = setjmp string stdio
|
modules-libc = setjmp string stdio stdlib
|
||||||
|
|
||||||
# Targets
|
# Targets
|
||||||
target-g1a = gintdemo.g1a
|
target-g1a = gintdemo.g1a
|
||||||
|
|
6
TODO
6
TODO
|
@ -10,9 +10,11 @@
|
||||||
|
|
||||||
|
|
||||||
@ possibility of vram overflow with text
|
@ possibility of vram overflow with text
|
||||||
|
@ garbage displayed as year in the clock, possibly during edition (could not
|
||||||
|
reproduce)
|
||||||
|
|
||||||
+ bitmap blending modes
|
+ 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
|
+ partial transparency
|
||||||
+ gint vs. ML with 248x124 at (-60, -28)
|
+ gint vs. ML with 248x124 at (-60, -28)
|
||||||
+ call exit handlers
|
+ call exit handlers
|
||||||
|
@ -23,7 +25,7 @@
|
||||||
- full rtc driver (time)
|
- full rtc driver (time)
|
||||||
- callbacks and complete user API
|
- callbacks and complete user API
|
||||||
|
|
||||||
~ shadowy rectangle effect for Shift + Alpha + Left + Down
|
~ packed bit fields
|
||||||
~ exhaustive save for setjmp()
|
~ exhaustive save for setjmp()
|
||||||
~ registers that need to be saved when configuring gint
|
~ registers that need to be saved when configuring gint
|
||||||
~ possible bug when -O2'ing __attribute__((interrupt_handler))
|
~ 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);
|
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()
|
printf_test()
|
||||||
Tests formatting functions.
|
Tests formatting functions.
|
||||||
|
@ -534,7 +508,7 @@ int main(void)
|
||||||
test_tales();
|
test_tales();
|
||||||
break;
|
break;
|
||||||
case 0x0105:
|
case 0x0105:
|
||||||
// test_rtc();
|
test_rtc();
|
||||||
break;
|
break;
|
||||||
case 0x0106:
|
case 0x0106:
|
||||||
// test_printf();
|
// 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)
|
while(1)
|
||||||
{
|
{
|
||||||
multigetkey(keys, 4, 1);
|
|
||||||
if(keys[0] == KEY_EXIT && keys[1] == KEY_NONE) break;
|
|
||||||
|
|
||||||
dclear();
|
dclear();
|
||||||
locate(1, 1, "Keyboard driver");
|
locate(1, 1, "Keyboard driver");
|
||||||
locate(8, 3, "Pressed keys:");
|
locate(8, 3, "Pressed keys:");
|
||||||
|
@ -78,5 +75,8 @@ void test_keyboard(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
dupdate();
|
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
|
struct mod_tmu
|
||||||
{
|
{
|
||||||
// Timer constant register.
|
unsigned int TCOR; // Timer constant register.
|
||||||
unsigned int TCOR;
|
unsigned int TCNT; // Timer counter.
|
||||||
// Timer counter.
|
|
||||||
unsigned int TCNT;
|
|
||||||
|
|
||||||
// Timer control register.
|
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
unsigned short WORD;
|
unsigned short WORD;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
unsigned :7;
|
unsigned :7;
|
||||||
// Underflow flag.
|
unsigned UNF :1; // Underflow flag.
|
||||||
unsigned UNF :1;
|
|
||||||
unsigned :2;
|
unsigned :2;
|
||||||
// Underflow interrupt enable.
|
unsigned UNIE :1; // Underflow interrupt enable.
|
||||||
unsigned UNIE :1;
|
unsigned CKEG :2; // Clock edge (SH7705 only).
|
||||||
// Clock edge, reserved on SH7305.
|
unsigned TPSC :3; // Timer prescaler.
|
||||||
unsigned CKEG :2;
|
|
||||||
// Timer prescaler.
|
|
||||||
unsigned TPSC :3;
|
|
||||||
};
|
};
|
||||||
} TCR;
|
} TCR; // Timer control register.
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
timer_get()
|
timer_get()
|
||||||
Returns the timer and TSTR register addresses.
|
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
|
#endif // _INTERNALS_TIMER_H
|
||||||
|
|
|
@ -9,6 +9,43 @@
|
||||||
#ifndef _RTC_H
|
#ifndef _RTC_H
|
||||||
#define _RTC_H 1
|
#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.
|
// Callback API.
|
||||||
//---
|
//---
|
||||||
|
|
|
@ -10,12 +10,33 @@
|
||||||
#ifndef _STDLIB_H
|
#ifndef _STDLIB_H
|
||||||
#define _STDLIB_H 1
|
#define _STDLIB_H 1
|
||||||
|
|
||||||
|
//---
|
||||||
|
// Common definitions.
|
||||||
|
//---
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
// Common exit codes.
|
// Common exit codes.
|
||||||
#define EXIT_SUCCESS 1
|
#define EXIT_SUCCESS 1
|
||||||
#define EXIT_FAILURE 0
|
#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);
|
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);
|
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()
|
free()
|
||||||
Frees a memory block allocated with malloc().
|
Frees a memory block allocated by malloc(), calloc() or realloc().
|
||||||
*/
|
*/
|
||||||
void free(void *ptr);
|
void free(void *ptr);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//---
|
||||||
|
// Random number generation.
|
||||||
|
//---
|
||||||
|
|
||||||
|
/*
|
||||||
|
int rand(void)
|
||||||
|
*/
|
||||||
|
|
||||||
//---
|
//---
|
||||||
// Integer arithmetic.
|
// Integer arithmetic.
|
||||||
//---
|
//---
|
||||||
|
@ -73,8 +114,26 @@ void free(void *ptr);
|
||||||
*/
|
*/
|
||||||
int abs(int x);
|
int abs(int x);
|
||||||
// Use a macro instead, when possible.
|
// 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
|
#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.bottom = top + ((y + height > 64) ? (64 - y) : height);
|
||||||
command.left = ((x < 0) ? (left - x) : left) >> 5;
|
command.left = ((x < 0) ? (left - x) : left) >> 5;
|
||||||
actual_width = (x + width > 128) ? (128 - x) : width;
|
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;
|
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.bottom = top + ((y + height > 64) ? (64 - y) : height);
|
||||||
command.left = ((x < 0) ? (left - x) : left) >> 5;
|
command.left = ((x < 0) ? (left - x) : left) >> 5;
|
||||||
actual_width = (x + width > 128) ? (128 - x) : width;
|
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;
|
command.op = bopti_op_gray;
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,10 @@ extern unsigned int
|
||||||
static int exit_code = EXIT_SUCCESS;
|
static int exit_code = EXIT_SUCCESS;
|
||||||
static jmp_buf env;
|
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.
|
// Remember to flush and close opened streams.
|
||||||
|
|
||||||
|
// Calling exit handlers.
|
||||||
|
while(atexit_index > 0) (*atexit_handlers[--atexit_index])();
|
||||||
|
|
||||||
// Un-initializing everything.
|
// Un-initializing everything.
|
||||||
fini();
|
fini();
|
||||||
gint_quit();
|
gint_quit();
|
||||||
|
@ -76,6 +83,10 @@ int start(void)
|
||||||
return exit_code;
|
return exit_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
init()
|
||||||
|
Calls the constructors.
|
||||||
|
*/
|
||||||
static void init(void)
|
static void init(void)
|
||||||
{
|
{
|
||||||
extern void
|
extern void
|
||||||
|
@ -83,7 +94,6 @@ static void init(void)
|
||||||
(*ectors)(void);
|
(*ectors)(void);
|
||||||
void (**func)(void) = &bctors;
|
void (**func)(void) = &bctors;
|
||||||
|
|
||||||
// Calling the constructors.
|
|
||||||
while(func < &ectors)
|
while(func < &ectors)
|
||||||
{
|
{
|
||||||
(*(*func))();
|
(*(*func))();
|
||||||
|
@ -91,6 +101,10 @@ static void init(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
fini()
|
||||||
|
Calls the destructors.
|
||||||
|
*/
|
||||||
static void fini(void)
|
static void fini(void)
|
||||||
{
|
{
|
||||||
extern void
|
extern void
|
||||||
|
@ -98,7 +112,6 @@ static void fini(void)
|
||||||
(*edtors)(void);
|
(*edtors)(void);
|
||||||
void (**func)(void) = &bdtors;
|
void (**func)(void) = &bdtors;
|
||||||
|
|
||||||
// Calling the destructors.
|
|
||||||
while(func < &edtors)
|
while(func < &edtors)
|
||||||
{
|
{
|
||||||
(*(*func))();
|
(*(*func))();
|
||||||
|
@ -112,10 +125,13 @@ static void fini(void)
|
||||||
abort()
|
abort()
|
||||||
Immediately ends the program without invoking the exit handlers.
|
Immediately ends the program without invoking the exit handlers.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void abort(void)
|
void abort(void)
|
||||||
{
|
{
|
||||||
exit_code = EXIT_FAILURE;
|
exit_code = EXIT_FAILURE;
|
||||||
|
|
||||||
|
// Avoiding any exit handler call.
|
||||||
|
atexit_index = 0;
|
||||||
|
|
||||||
longjmp(env, 1);
|
longjmp(env, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,10 +145,21 @@ void abort(void)
|
||||||
of achieving this goal while minimizing interaction with the operating
|
of achieving this goal while minimizing interaction with the operating
|
||||||
system.
|
system.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void exit(int status)
|
void exit(int status)
|
||||||
{
|
{
|
||||||
exit_code = status;
|
exit_code = status;
|
||||||
longjmp(env, 1);
|
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.
|
Internal buffer.
|
||||||
|
|
||||||
Using a buffer *really* simplifies everything. But it also has
|
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
|
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
|
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
|
The Format structure handles everything in a format: data type, value,
|
||||||
given value, including alternative forms, alignment and digit numbers.
|
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,
|
Other options are handled by The FormatFlags enumeration. See the
|
||||||
a number of integer and decimal digits, and additional flags.
|
description of functions __printf() for further description on option
|
||||||
|
precedence and influence.
|
||||||
The FormatFlags enumeration handles the various flags that can be added
|
|
||||||
to a printf()-family format.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
enum FormatFlags
|
enum FormatFlags
|
||||||
{
|
{
|
||||||
// Option '#' specifies alternatives forms, mainly '0' and '0x'
|
// Alternatives forms add '0' and '0x' prefixes in octal and
|
||||||
// prefixes in integer display.
|
// hexadecimal bases. (#)
|
||||||
Alternative = 1,
|
Alternative = 1,
|
||||||
// Under specific conditions, zero-padding may be used instead of
|
// Under specific conditions, zero-padding may be used instead of
|
||||||
// whitespace-padding.
|
// whitespace-padding. (0)
|
||||||
ZeroPadded = 2,
|
ZeroPadded = 2,
|
||||||
// Left alignment specifies that additional spaces should be added
|
// Left alignment specifies that additional spaces should be added
|
||||||
// after the value.
|
// after the value instead of before. (-)
|
||||||
LeftAlign = 4,
|
LeftAlign = 4,
|
||||||
// In numeric display, this forces a blank sign to be written before
|
// In numeric display, this forces a blank sign to be written before
|
||||||
// positive values.
|
// positive values. ( )
|
||||||
BlankSign = 8,
|
BlankSign = 8,
|
||||||
// In numeric display, this forces an explicit sign in all cases. This
|
// In numeric display, this forces an explicit sign in all cases. This
|
||||||
// option overrides BlankSign (see __printf() description for further
|
// option overrides BlankSign. (+)
|
||||||
// information on option precedence and influence).
|
|
||||||
ForceSign = 16
|
ForceSign = 16
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -72,7 +71,7 @@ struct Format
|
||||||
{
|
{
|
||||||
// Signed int with formats %c, %d and %i.
|
// Signed int with formats %c, %d and %i.
|
||||||
signed int _int;
|
signed int _int;
|
||||||
// Insigned int with formats %o, %u, %x and %X.
|
// Unsigned int with formats %o, %u, %x and %X.
|
||||||
unsigned int _unsigned;
|
unsigned int _unsigned;
|
||||||
// Double with formats %f, %F, %e, %E, %g and %G.
|
// Double with formats %f, %F, %e, %E, %g and %G.
|
||||||
// double _double;
|
// double _double;
|
||||||
|
@ -364,8 +363,7 @@ static void get_spacing(struct Format format, int *begin_spaces, int *sign,
|
||||||
__printf()
|
__printf()
|
||||||
|
|
||||||
Basic buffered formatted printing function. Fully-featured, so that
|
Basic buffered formatted printing function. Fully-featured, so that
|
||||||
ant call to a printf()-family function can be translated into a
|
any call to a printf()-family function can be performed by __printf().
|
||||||
__printf() call.
|
|
||||||
|
|
||||||
It always returns the number of characters of the theoretic formatted
|
It always returns the number of characters of the theoretic formatted
|
||||||
output. The real output may be limited in size by the given size
|
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
|
argument handling (because flag effects depend on format type, which
|
||||||
is unknown when the flags are read). Also, length modifiers 'hh' is
|
is unknown when the flags are read). Also, length modifiers 'hh' is
|
||||||
stored as 'i' to simplify structure handling. 'll' is not supported.
|
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.
|
Generic information on options precedence and influence.
|
||||||
- Influences of integer part and mantissa digit numbers depend on
|
- Number of characters and precision represent different lengths
|
||||||
the type of data that is being displayed.
|
depending on the data type.
|
||||||
- Option '#' doesn't contend with any other.
|
- '#' is independent.
|
||||||
- Option '+' overrides options ' '.
|
- '+' overrides ' '.
|
||||||
- In integer display, option '0' translates spaces to zeros, but
|
- In integer display, '0' replaces spaces to zeros, only if no
|
||||||
only if no decimal digit number is specified.
|
precision (decimal digit number) is specified.
|
||||||
The option '-' also overrides it, forcing whitespaces to be
|
- '-' also overrides it, forcing whitespaces to be written at the end.
|
||||||
written at the end of the format.
|
|
||||||
|
|
||||||
Limit of function.
|
Limits of function.
|
||||||
- Internal buffer size (should be customizable with a -D option
|
- Internal buffer size (there should be a loop to allow larger data).
|
||||||
when compiling).
|
- Precision values (format %a.b) are limited to 127.
|
||||||
- Precision values (format %a.b) are written on 8 bits, therefore
|
|
||||||
limited to 127.
|
|
||||||
|
|
||||||
Unsupported features.
|
Unsupported features.
|
||||||
- Flag character ''' (single quote) for thousands grouping
|
- ''' (single quote) (thousands grouping)
|
||||||
- Flag character 'I', that outputs locale's digits (glibc 2.2)
|
- 'I' (outputs locale's digits (glibc 2.2))
|
||||||
- Length modifiers 'll' and 'q' (libc 5 and 4.4 BSD)
|
- Length modifiers 'll' and 'q' (libc 5 and 4.4 BSD)
|
||||||
- This is not really a feature but incorrect characters in
|
- This is not really a feature but incorrect characters in formats are
|
||||||
formats are ignored and don't invalidate the format.
|
ignored and don't invalidate the format.
|
||||||
*/
|
*/
|
||||||
int __printf(size_t size, const char *string, va_list args)
|
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)
|
if(!size || size > __stdio_buffer_size)
|
||||||
size = __stdio_buffer_size;
|
size = __stdio_buffer_size;
|
||||||
|
|
||||||
// Initializing character() working values.
|
// Initializing character() variables.
|
||||||
written = 0;
|
written = 0;
|
||||||
total = 0;
|
total = 0;
|
||||||
max = size;
|
max = size;
|
||||||
|
@ -437,8 +432,7 @@ int __printf(size_t size, const char *string, va_list args)
|
||||||
format = get_format(&string);
|
format = get_format(&string);
|
||||||
if(!format.type) break;
|
if(!format.type) break;
|
||||||
|
|
||||||
/*
|
/* Some debugging...
|
||||||
// Displaying an information message.
|
|
||||||
printf(
|
printf(
|
||||||
"Format found :%s%c%c, options %d, and %d.%d "
|
"Format found :%s%c%c, options %d, and %d.%d "
|
||||||
"digits\n",
|
"digits\n",
|
||||||
|
@ -448,8 +442,7 @@ int __printf(size_t size, const char *string, va_list args)
|
||||||
format.flags,
|
format.flags,
|
||||||
format.digits,
|
format.digits,
|
||||||
format.mantissa
|
format.mantissa
|
||||||
);
|
); */
|
||||||
*/
|
|
||||||
|
|
||||||
switch(format.type)
|
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);
|
format._int = va_arg(args, signed int);
|
||||||
|
|
||||||
// Reducing value depending on format size.
|
// Reducing value depending on format size.
|
||||||
switch(format.size)
|
if(format.size == 'h') format._int &= 0x0000ffff;
|
||||||
{
|
if(format.size == 'i') format._int &= 0x000000ff;
|
||||||
case 'h':
|
|
||||||
format._int &= 0x0000ffff;
|
|
||||||
break;
|
|
||||||
case 'i':
|
|
||||||
format._int &= 0x000000ff;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
format_di(format);
|
format_di(format);
|
||||||
break;
|
break;
|
||||||
|
@ -877,7 +863,7 @@ void format_p(struct Format format)
|
||||||
|
|
||||||
unsigned int x = format._unsigned;
|
unsigned int x = format._unsigned;
|
||||||
int bspaces, zeros, digits = 0, espaces;
|
int bspaces, zeros, digits = 0, espaces;
|
||||||
int c;
|
int c, i;
|
||||||
|
|
||||||
digits = x ? 10 : 5;
|
digits = x ? 10 : 5;
|
||||||
get_spacing(format, &bspaces, NULL, &zeros, digits, &espaces);
|
get_spacing(format, &bspaces, NULL, &zeros, digits, &espaces);
|
||||||
|
@ -889,7 +875,7 @@ void format_p(struct Format format)
|
||||||
{
|
{
|
||||||
character('0');
|
character('0');
|
||||||
character('x');
|
character('x');
|
||||||
while(x)
|
for(i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
c = x >> 28;
|
c = x >> 28;
|
||||||
c += '0' + 39 * (c > 9);
|
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 <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
calloc()
|
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()
|
timer_get()
|
||||||
Returns the timer and TSTR register addresses.
|
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.
|
// Using SH7705 information for SH-3-based MPUs.
|
||||||
if(isSH3())
|
if(isSH3())
|
||||||
{
|
{
|
||||||
if(tstr) *tstr = (unsigned char *)0xfffffe92;
|
if(tstr) *tstr = (volatile unsigned char *)0xfffffe92;
|
||||||
if(tmu) *tmu = (struct mod_tmu *)0xfffffe94;
|
if(tmu) *tmu = (volatile struct mod_tmu *)
|
||||||
|
(0xfffffe94 + 12 * timer);
|
||||||
}
|
}
|
||||||
// Assuming SH7305 by default.
|
// Assuming SH7305 by default.
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(tstr) *tstr = (unsigned char *)0xa4490004;
|
if(tstr) *tstr = (volatile unsigned char *)0xa4490004;
|
||||||
if(tmu) *tmu = (struct mod_tmu *)0xa4490008;
|
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)
|
void timer_interrupt(int timer)
|
||||||
{
|
{
|
||||||
struct mod_tmu *tmu;
|
volatile struct mod_tmu *tmu;
|
||||||
timer_get(timer, &tmu, NULL);
|
timer_get(timer, &tmu, NULL);
|
||||||
|
|
||||||
// Resetting the interrupt flag.
|
// Resetting the interrupt flag.
|
||||||
(*tmu).TCR.UNF = 0;
|
tmu->TCR.UNF = 0;
|
||||||
|
|
||||||
// Calling the callback function.
|
// Calling the callback function.
|
||||||
if(timers[timer].callback) timers[timer].callback();
|
if(timers[timer].callback) timers[timer].callback();
|
||||||
|
|
|
@ -8,14 +8,14 @@
|
||||||
*/
|
*/
|
||||||
void timer_reload(int timer, int new_delay)
|
void timer_reload(int timer, int new_delay)
|
||||||
{
|
{
|
||||||
struct mod_tmu *tmu;
|
volatile struct mod_tmu *tmu;
|
||||||
unsigned char *tstr;
|
volatile unsigned char *tstr;
|
||||||
int byte = (1 << timer);
|
int byte = (1 << timer);
|
||||||
timer_get(timer, &tmu, &tstr);
|
timer_get(timer, &tmu, &tstr);
|
||||||
|
|
||||||
// Setting the constant and the delay.
|
// Setting the constant and the delay.
|
||||||
(*tmu).TCOR = new_delay;
|
tmu->TCOR = new_delay;
|
||||||
(*tmu).TCNT = new_delay;
|
tmu->TCNT = new_delay;
|
||||||
|
|
||||||
// Starting the timer.
|
// Starting the timer.
|
||||||
*tstr |= byte;
|
*tstr |= byte;
|
||||||
|
|
|
@ -8,31 +8,28 @@
|
||||||
void timer_start(int timer, int delay, int prescaler, void (*callback)(void),
|
void timer_start(int timer, int delay, int prescaler, void (*callback)(void),
|
||||||
int repeats)
|
int repeats)
|
||||||
{
|
{
|
||||||
// Getting the timer address. Using a byte to alter TSTR.
|
volatile struct mod_tmu *tmu;
|
||||||
struct mod_tmu *tmu;
|
volatile unsigned char *tstr;
|
||||||
unsigned char *tstr;
|
|
||||||
int byte = (1 << timer);
|
int byte = (1 << timer);
|
||||||
|
|
||||||
timer_get(timer, &tmu, &tstr);
|
timer_get(timer, &tmu, &tstr);
|
||||||
|
|
||||||
// Setting the constant register.
|
// Loading the counter, the constant and the prescaler/
|
||||||
(*tmu).TCOR = delay;
|
tmu->TCOR = delay;
|
||||||
// Loading the delay in the counter.
|
tmu->TCNT = delay;
|
||||||
(*tmu).TCNT = delay;
|
tmu->TCR.TPSC = prescaler;
|
||||||
|
|
||||||
// Resetting underflow flag.
|
// Resetting underflow flag and enabling interruptions.
|
||||||
(*tmu).TCR.UNF = 0;
|
tmu->TCR.UNF = 0;
|
||||||
// Enabling interruptions on underflow.
|
tmu->TCR.UNIE = 1;
|
||||||
(*tmu).TCR.UNIE = 1;
|
|
||||||
// Counting on rising edge. On SH7305 these two bits are reserved but
|
// Counting on rising edge (ignored on SH7305).
|
||||||
// writing 0 is ignored.
|
tmu->TCR.CKEG = 0;
|
||||||
(*tmu).TCR.CKEG = 0;
|
|
||||||
// Setting the prescaler.
|
|
||||||
(*tmu).TCR.TPSC = prescaler;
|
|
||||||
|
|
||||||
// Loading the structure information.
|
// Loading the structure information.
|
||||||
timers[timer].callback = callback;
|
timers[timer].callback = callback;
|
||||||
timers[timer].repeats = repeats;
|
timers[timer].repeats = repeats;
|
||||||
|
|
||||||
// Starting the timer and returning.
|
// Starting the timer.
|
||||||
*tstr |= byte;
|
*tstr |= byte;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,11 +10,9 @@
|
||||||
*/
|
*/
|
||||||
void timer_stop(int timer)
|
void timer_stop(int timer)
|
||||||
{
|
{
|
||||||
// Getting TSTR address and the corresponding byte.
|
volatile unsigned char *tstr;
|
||||||
unsigned char *tstr;
|
|
||||||
int byte = (1 << timer);
|
int byte = (1 << timer);
|
||||||
timer_get(timer, NULL, &tstr);
|
|
||||||
|
|
||||||
// Stopping the timer.
|
timer_get(timer, NULL, &tstr);
|
||||||
*tstr &= ~byte;
|
*tstr &= ~byte;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue