From 1f223f807fdd440dcaeb6aec571c66ce8ce9009c Mon Sep 17 00:00:00 2001 From: lephe Date: Tue, 2 Aug 2016 07:51:44 +0200 Subject: [PATCH] Added an RTC test (clock), image part drawing and a few standard functions (stdlib, time). --- Makefile | 2 +- TODO | 6 +- demo/gintdemo.c | 28 +--- demo/resources/opt_rtc.bmp | Bin 0 -> 20474 bytes demo/resources/rtc_segments.bmp | Bin 0 -> 6962 bytes demo/test_keyboard.c | 6 +- demo/test_rtc.c | 262 ++++++++++++++++++++++++++++++++ gintdemo.g1a | Bin 37666 -> 42194 bytes include/internals/rtc.h | 118 ++++++++++++++ include/internals/timer.h | 24 ++- include/rtc.h | 37 +++++ include/stdlib.h | 63 +++++++- include/time.h | 85 +++++++++++ libc.a | Bin 12430 -> 15700 bytes libgint.a | Bin 72922 -> 73134 bytes src/bopti/dimage_part.c | 2 +- src/bopti/gimage_part.c | 2 +- src/core/crt0.c | 35 ++++- src/rtc/rtc_getTime.c | 53 +++++++ src/rtc/rtc_setTime.c | 31 ++++ src/stdio/stdio_format.c | 94 +++++------- src/stdlib/abs.c | 7 - src/stdlib/calloc.c | 1 + src/stdlib/stdlib_abs.c | 13 ++ src/stdlib/stdlib_div.c | 29 ++++ src/stdlib/stdlib_rand.c | 14 ++ src/time/mktime.c | 93 ++++++++++++ src/time/time_misc.c | 20 +++ src/timer/timer_get.c | 16 +- src/timer/timer_interrupt.c | 4 +- src/timer/timer_reload.c | 8 +- src/timer/timer_start.c | 31 ++-- src/timer/timer_stop.c | 6 +- 33 files changed, 938 insertions(+), 152 deletions(-) create mode 100644 demo/resources/opt_rtc.bmp create mode 100644 demo/resources/rtc_segments.bmp create mode 100644 demo/test_rtc.c create mode 100644 include/internals/rtc.h create mode 100644 include/time.h create mode 100644 src/rtc/rtc_getTime.c create mode 100644 src/rtc/rtc_setTime.c delete mode 100644 src/stdlib/abs.c create mode 100644 src/stdlib/stdlib_abs.c create mode 100644 src/stdlib/stdlib_div.c create mode 100644 src/stdlib/stdlib_rand.c create mode 100644 src/time/mktime.c create mode 100644 src/time/time_misc.c diff --git a/Makefile b/Makefile index 0607f44..d6d809c 100644 --- a/Makefile +++ b/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 diff --git a/TODO b/TODO index f830f93..56f0be3 100644 --- a/TODO +++ b/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)) diff --git a/demo/gintdemo.c b/demo/gintdemo.c index 19f097b..8e4249f 100644 --- a/demo/gintdemo.c +++ b/demo/gintdemo.c @@ -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(); diff --git a/demo/resources/opt_rtc.bmp b/demo/resources/opt_rtc.bmp new file mode 100644 index 0000000000000000000000000000000000000000..7fdd7641babf2196187112d263c9cbe484278547 GIT binary patch literal 20474 zcmeI0L2e{P6hsHMEZJ}oE-)Kb2#IsBW5cZHvT#~aR;zvYg zWqW3%`TX-=zkIqpe`NhFKY!-u$NYTr>4&W0nScKsKNlg(=bwK4{R!Xt`R!`_``oh@ zURT!LuKU;N8*IoS*Hhi15Hv0g5T^&+z;Z`So9d6)k68et#!*&!y&-;k1d1w_(C-?( zaZ^h$Y&HykSBWqWSx0L_8`_4mr(krq2pErsp-Z1N=-dOG#OWw(iqo|t z+Qt+*oWqkTam@loJzX*7=;EebB94K_2;k`YRCD;#jSeTD0`IBe>75RLdI=xkRc;_( z*vWm5e&y?S@1WuCYb0n~8X(S%fg5;@+8zS+uX)pf%>ta#56!9#tgT0f8b+ZsVBMm3 zaci7SDQWXs+seQMjSm|0P;}a(AwcYuh8~Ian7RV&X>eZy2Vk$!FepxTWbG4nLt{%i z(qdx^+Z+)c=N|6qCGnWTk78|$j%+|_k3qnoXBym#?L5QS;ySgYZs0XujE`R;*r0%5Q{#4;#ipUD9;X02 zJ#A%dA?=bYerib#n+@nv!Ja-0+U&n>a2jA_06jwwMcFhs1q{k|ihB*%oDOR9o?+9k z*?2&U;s)zcdm2oM>j0P$SF92P4~4-4464}%K-(OxZN$;FnbofX7?hHTJf;NE^(Z!Q ziu1AP>kmAnzMed?E{r7AJe0L6iVqE;1K6yNClrNs?LoP?9-VqN8@kQT7D-w1PH}K|6S@%tsX>((5K$~r)VYGa@=d+tl)JS+y&IUeqOCi-1hc^_ep3R? z#skK~zC&#Ktf9@Dm}7Jg3TE*D!{5z4ir$nGS5tUe2ahu}Z3DYdGVmVlz3^nc@wd?M<=%(eyZagm8kYu$vjw<;-B^kEi&Q*3Y((D7`;=#1Z>piAz({x2T8+r)hg#ReF(4I1ZAbXuYzfTu@MD0v!A z&zM4Oa4N88^)SMzf0OF8jQj5rU6bj7TpDYz9Hx~GFZ6=>a#eT-!t7>%VyM4-sm7^|Ya}&LOG;ng;W9B)F*t#LIC0^U;0`t)yYl z$6fdJVK5Gm+N>g28!}?*DxgOS=!P*0RWXa`Y8=Df+J3Nwqao8CwRzQ@QbM*1)%Qjk z0`S-=XwQmUAz}}mdvxvBxdL{vknGxkVXR~|4-krh6jV=-Rs%L01f~GPHm20F($K37 z+8Qub>7ZDk4G^6XCDKjM5e%-xG3>2v9{r)+03DvLZ38wGJ+=vKQyIWcbg4m=7!XnH zkq&^F)Lywd*^a2tz-X+*F|=(}Y-<3fgl02$b<`=bQ-abf4R~x2&>&qK7`esmpsNmHw>Xq)^LuLO_d0~Vgb(m4 zH;^yu2ob;)6ab#!sZzPN7E;FjeWG9z}tE;{oSy?|eg_ z=XUIyCKAlkILe?XZlM818X%^jdyJ2fx^WExMwH_}e|zT}JozEeZ*eH7`7Jb@zrFJf cUdSQf@6u7=E=Pm<|HFp!w|Bn5*Et0K0nW?|&j0`b literal 0 HcmV?d00001 diff --git a/demo/resources/rtc_segments.bmp b/demo/resources/rtc_segments.bmp new file mode 100644 index 0000000000000000000000000000000000000000..958d83f9ba49ca4adb3c46724481bb3d7786f6d9 GIT binary patch literal 6962 zcmc)FF^*J03`Nm~l#m3$E?B}OL?o<(i~xz1vAe+C|y;`|!F@9}#ZzgL%cab7Mz-^cw;{+Wof%zM(DowmGP zZHW11&)|sKC-R!-UIcdgeUSYo{S{u18Z@j7BoE zL*!K)AOb_woHXM!udv?}t&LolH{R55at3*byov)vV2GNNW}M~~_IskWk?ZotoBB=8 zAP(jH_8)22&9|0LX!+MZ z;i-{68yODuzjKC#BH$AzY@D-Yq7Fnr1VkVsr+I~;PP@A^EEECHIAP40YPwonfH}c*Y4E=WLm%0}&7b5y;4CUSX)y?(Pf=MZhyo*f?j)L>-8L2#7#N zPV)*wopyI;SSSLXal*zqTPEs21VlgtGIE+%80xgUJHtW|@Qf2S&e<|i2O=N>B9IZG zUUA65D%YSox)s`<8evXMu6?LEx)pSDPmM4q!MwuqTT!WI-H@Cq?G$MFn9X@@Nq!|a PY@C1jt<8I0?!<;)xdY_V literal 0 HcmV?d00001 diff --git a/demo/test_keyboard.c b/demo/test_keyboard.c index a10a78d..ab90268 100644 --- a/demo/test_keyboard.c +++ b/demo/test_keyboard.c @@ -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; } } diff --git a/demo/test_rtc.c b/demo/test_rtc.c new file mode 100644 index 0000000..93a15c6 --- /dev/null +++ b/demo/test_rtc.c @@ -0,0 +1,262 @@ +#include "gintdemo.h" +#include +#include +#include + +#include +#include + +/* + 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 +#include + +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); +} diff --git a/gintdemo.g1a b/gintdemo.g1a index 6c2964ec9ba281226d817f4a1339312627a1ad4e..ead9e3896ecfa1fd26cd34036cb168240568ae0e 100644 GIT binary patch delta 8052 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 kdcT2LW?b>aSoP_ZF19Z61Ku7w6wz| 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 +#include // 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 diff --git a/include/time.h b/include/time.h new file mode 100644 index 0000000..2fd712a --- /dev/null +++ b/include/time.h @@ -0,0 +1,85 @@ +//--- +// +// standard library module: time +// +// Provides time manipulation and representation functions. +// +//--- + +#ifndef _TIME_H +#define _TIME_H 1 + +#include + +//--- +// 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 diff --git a/libc.a b/libc.a index c7e02abb4ba3f0129ce97a9dcfcc19916c50204e..b460e143f5afada1697270d43ba9f14e3aa6c039 100644 GIT binary patch delta 1886 zcmZ`)|4&<06hH4vzwv!EVR6PpXH3YJDD~X;UQ3DdBinT#Br+ZXe{e7c z{)j4-(brK`W$b)#OaZ?t!R;pbj6_66U>iK7iFq;`n@}R7gSwBpP~EsYOE>8Q`g@ic zeLu@guhHyTZVe9|1W~N_Qov+ia|7zKjH@Wg?X2vCpM8Zj>1Zat=AB%6@`vfx?#fEm zrQL}?r#QWhtYp~|ALT{TtK^>TOu}DiN$*IEmyGUC?%9HzIh8$fgD*)8?EjAI4sBeM zl=!LbxykpLrFX{G=caI632a;|Q{n;g+Q!_-G{3-x)|U*S7XoB%bb)m(hmN|I1JW;G zbj~F!W=zgQQ}e9kn}0|mm7UMe4Bfmn)3;sG7nWKDw`WW26#D<^`@6d161(zB9343~%%&>7Hof>R04(WhFCA3aVbU^@gPiPw21PJuz=Z{nliKGISHY z{d}j3T&(J0PLR#2enupRrG1Q@yd=HMJyPQ2Giko?i*RDi*(z*_S3XhV(e)T#(L#<^ zcXgV7wI~~H&Nf?{rOo2~c%FH1`hnafc*}dty?G0N_L!H1{$!W1Rf9Z+Jc=AacJ?Q` zskc*SpZ;ikn;$%%Sg+1C?BaN?q%@Iqwr3zqEuq>YoZand@TKbj6|EF#?;!f6tk+9| ztg9uCb4o+=ES8Pt;*oq`D)jcS$rHjfE$)y)^(PMpMCsO-Zg4#Tl8@6-$hZ3|JkE zLatg%$*0ylRipD0CI{0-cB~Eqb}%fG10|B%j9QiMh7PJrx2F+bhF!{t`LU^#^{6o) z#MaJ;*$jrZ{COsDJkSML9x0vN&6{q_)i1~{&@L#%c{XKrp4qG!F9G?yXg`@Twv+2z zF;hl<&zG2PH6#n4r)w=Hs(qR5V4jlq3LJ(2`izs@9LaqjH5+n@^ssz;`Z^=58+;iF zu(j=TcwlcH4K#zp#|f`74$8d~|Ht4S*?k&s6Io6s<&ACs_xmV43B%O1rImkDrB68MLgdowZ$I*qB zb@~m}$SKm`X^`=G+oe75V5R$LrMF+eGkXwPV?d~UQA1?Sux<<$aE=cRV3%E$>>3Ax zXp>v$J+0sOMrV`BB&rO#n=?FXrB);!Z|5{slQ=P;hQA$^QdL9IqE%C!iJ10igFhAy zJ5W^XLaN&xQC~QbmGak?qQ~bLYFgxwnb#x QE+(>5zOR^m$$uK>UtbQmJ^%m! delta 601 zcmcao)t5LyD$UH&+{nXCgR_Qi*WR#$=y)rMaS59dN_|{R{&A6a8 z?@~tvkUp1idA&qRL&D_j%N-fjEWNDBmpU^0S#(Y;U`n=0w$(Y2p!}SHO|#>_d=0y% zT179DvPJK+$pT8AthH%}Z`MwZQxcc2aO7s-)Oj8H&y)L!fzF9LrTuKFmqY(QQSju> z-Mnt!&uh|2F}S2D!qbRQ#W7KbmV@buy%GzL++(YmdOuPyj3|0&M8=!jmqYhP|A)~33wWL=Ob$>L6L_NF!<{>MZD2~nWwu(D eB%{qGs(h@lSePs*F0px`mMbF6Kmx3K+ROl9!mca; diff --git a/libgint.a b/libgint.a index a2df03caa0932906d809ec77923a699940f0a8b9..ce45882548005403801e4a9a3bc8e91a326127a9 100644 GIT binary patch delta 4782 zcma)933O9c8vgHlNwd5>IX(iDN4Z0a~POW7Uj)Y#SYekazH`b%4k&v+p-J_BUqS-Xv+8& z;D1q020-5EDA^AK5DK#e30rJ#9+IA5qjq?Fs zAdXmiiSRF%0_^z)U|;VL6dno`V6RgEe?16rRRvzYfCm()cPydg-SNYrSjmq(3+C!nskD!s$|tzCB7LSHD+MSl*as#T0%?8 zN@|x>tS!Me#QBQq+G2lARA$B`sgWsEu{Ky%;;-Udm2m?2qcsOIcT4U^c(1fv7OJYQ zSVvrx;T_WS#$FlHV3W*AgUyC_$Z~O$Oe}IZU3TWE3{i2PuPZWDtWSYod_r*&-e}F%k{W-kEZJC#<;huw;>zk0e{prKJ+C;g z(q=L_T(JY_#!bl?wA1du-|ZdeOv)jrjRqGf0dhbA(hgBK6q(JM4*HD9tZ5e&DlQ_f zHCl*pvdS11bx6*uf@X)iUfP9~+z337uvt(5t`hj5C7g3?&0<@bu&4t8DyZLjj_UwF86x_xl zhko?zY#Y7kjL}B~lk{m(TPDl3XJ%2InV)9{w)oPwOR5HPD4!I)#C7NkZ0Xc}t{-fo zJ%cl^3TTQf6@8#6@5Aq^Y)C}POnhzs2CV0Z@>GJ5pZG{KXK* z>ov}B>=cl0kVbZv-#Q&hnmj*>Oo8W3#1+qzAc*UG1o&iuen4O+1fb>n?g5aqJV|o^ zeOl+-iKA`zi(bb zg;_8+N8li`&?Aa>XIhs^MSNH0|dTx`>OcS_!K-$p!9Y^V)GZX zsUlg%d+;y~)oMvx!jXk~=G{j}#z)}63mUad|6^0)%<4^#)ZjA z5hO%8NJ#oZw%xY9wl{3YZJ*jMwHFncgPQdNj)LuU_(c1>ChE%V9Sv7**J-|y2b9J1 z^p3uT8NtIVwm-eq)QH{LUs*RQpe&qujva6ZCd;k?KaF zaE<$c+5tuGjFfTui%^e(HQlICT`vtSo+154diU+XbkV^_(4l`%nj7p5WIyJz(Cc*{oTmsnzV&xHY=4r^vFdZ*AY2zK8o(_eFE;omTqttzFT}VNdFvR;CW3$7f~EfHOBXGgIe!WG{r zI`O9E7CW_(AZ|kZ$9b|%ba4*N)ncIZIAbW21 zmpOA3OTJ%nE3#z{xv-b~5UJzpA0ykix$m&{#}+ODGwUXM3ZDevx|JIdME4UVm-8$P-1DL_C(0TR*J6(<)hG<>G{o$MP?qKETe93$dxLY2jFS!3^>k z=I;bX?LocWXQl`?Gl2C zyOkYD%+dNMDSd$>`jZzk7q>+cdc!-kz98S7a3px4dT`YWEmO4XYf4uzTyT?&PPyzj zWzu-mg?Be*dkx`Rr8hQ^*J{a)U~i8kCpYVG%IjOxR?%IzOu43~H>a_D!)Q}3%YA5y z%3c37<>GUVdAl>vX8hPAQdEa`Klgx|92W_{)e*8C_~o()X-b}xjh-P}U`21@yieG2 z{uQ=dH^qwf;G^$b(J7qQYq6shWYK@V_5~i-Fw<>)p;S}W+k>Xn7gq(XSzfC;EGn|# zmR*~fw_fZ+dbd6HZyfEPSV!(EJoo!UpT(`U)r0*M!aCIj``iIZ6cj_*mz3THjh&vnZW2|C9;b29>>JtMoL2P z#n<*wI*)5;zu4cVXR4S+TJI?sI!Zl^skx097`oNVJp_zLo}l&KVMgI)TK{Gf>%I9y zkHE`?rtz4FSeQ7R3W-f@JTifa9RC$j^9;T0QA>&sM$vkQ-7Z|k`1X1k-)RZk>=b$u zGzZ#R;*Xf9y-8;>69^Od>}o>d=Kk=PRjfgmFrE?yxp0zy<&Y7T0^!9YPzki@a24aj z_I+~Zjmt%}c2EQe6uXMaZuaI=2Ajh%C=VobnCsvBXq{uw4VGx-MzgYil}zUtb}*mm sn$z^?IL$io3Kv>nhHOXktLex~>zoeZA&IJxC-g-2GHt#lLW-pS0_pOoWB>pF delta 3694 zcmb_fdvH|M8UN0`yPM6E&9d2hvrS+(OLjvI`^sh?sALxzhoKN2wH1{n*^m&)P>3Oe znz4y6l@V;pnlJ5kGKhc@oz?;5R-^brLA1(i5vs_PhEyzLEiIulDvV6ey?5{K-Of_^ z!!z?c=R4o)eCP3$!Jv$TN9Od5(E>hjtmkhwaS^@rZ4B)Fj16*_cUl7fkkVe5(Acj^TWxX=^ zaUlG7^V*(RcMmkjTGxn;Fv4tLv0gVrSfeW;+K!b!k9FYQ(y6{L1%vt-iV+$DK!6YbL-l@;}o^3@@?Za2Q2KSOKv`n&;Q zBA+m*FPen4MF(}VL&08bBRbg#LnTXawB!e9EanD_bp@GGaJZy$a!+hk``Tu?mYlnm zOnFMysJjtPd*#@*7dol6si1wX9;YM>DGNp>6-R@thO%qccnc!5ZgRF!0@ zWOkBGN%GY)N)z|Szk&O=N!v-=!YXgoCdTI5bL|05a_Y&cAJK^oXg(($4qNx0Zz!+w z0*MxW_G3s^d{PlDg#2X18L15oZqmdyikv-HLxU&yQ{@p#TlG(9PH-ZXba6|>6nm;fva%>!r@x>lv*QR&bHPwV^&pg_@&0~9Ls z5I~Va{|=y7p|{fUOO(!bfJqAdER9K_p9d&aXgXn|Lhl8btk8c1Fe&sas(@an7p1~K zpqjuT0JF%alLdGmfK!x?0PuL;G=#Trx9ix?sB|uFE3=bT*tmtmGi3&C7v)9pQkh+% z=w3KDoMA4~()EEOILmA&5p?xB$=A5q?9|>xH{t-^yQE6TienwcbLJ}b@ihxmxPsC& z=NV6pF5RK0+blG?)-l3UUC(fYNW(H#ZNUkz&0dg~ z<_Ly)Z7TWLeqI<_V8|MS6Amu1Y0?%LALa!1?#pamDlgGp!wJUwHZWO?eLtH}GkD=( zOEm2y_?t1p3HJ7wT7?sKc6^?WJSfCFr{$|$^1?@JztLqe{?S{RaVZ%3@5+v8!-hbH zv8B!;ys`VNpTJN}jfT>>kD%`OsSWqIJ6U39Q=b zVy=&2-{?jLy0D~`!^=A(hWi2Xl!RCXpvUu(M@bhpuC$Yfa5XyUJ+%0cQ>uCVXVic@ z4mlYT$LsT*JR17UAYw?RDc7%%u=d_=>0a<5uY7~6kQ!})H!ze3Zy zyO{D|J$f53{qHW857+0;58Og``}h@4J|7O< zAYH|Q-QNzgoJSqJyjPx3*ozUGB7R)#swJ-{x(#Fz_U`K|fJo|FX~bb}fB79@X$+RWFBLYBbQ!@S&@gs-w`>V9eK(FeQ+jLml3nBqdWF6eZ7C5^YE*WM`|7c zpI?k~^j?K_?bMWez5bjY<-8ty$*3~8`tnhh8sv)7?+c+}9zS}UiG*1C TEl_82Ish>RNAEC@_t^geP4juQ diff --git a/src/bopti/dimage_part.c b/src/bopti/dimage_part.c index d4ce26d..00d1977 100644 --- a/src/bopti/dimage_part.c +++ b/src/bopti/dimage_part.c @@ -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; diff --git a/src/bopti/gimage_part.c b/src/bopti/gimage_part.c index 391c43b..abeb1b5 100644 --- a/src/bopti/gimage_part.c +++ b/src/bopti/gimage_part.c @@ -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; diff --git a/src/core/crt0.c b/src/core/crt0.c index 1643e05..ab92620 100644 --- a/src/core/crt0.c +++ b/src/core/crt0.c @@ -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; +} + diff --git a/src/rtc/rtc_getTime.c b/src/rtc/rtc_getTime.c new file mode 100644 index 0000000..2874d70 --- /dev/null +++ b/src/rtc/rtc_getTime.c @@ -0,0 +1,53 @@ +#include +#include +#include + +/* + 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; +} diff --git a/src/rtc/rtc_setTime.c b/src/rtc/rtc_setTime.c new file mode 100644 index 0000000..b00bcf5 --- /dev/null +++ b/src/rtc/rtc_setTime.c @@ -0,0 +1,31 @@ +#include +#include +#include + +/* + 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; +} diff --git a/src/stdio/stdio_format.c b/src/stdio/stdio_format.c index d1f10c7..c7db02f 100644 --- a/src/stdio/stdio_format.c +++ b/src/stdio/stdio_format.c @@ -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); diff --git a/src/stdlib/abs.c b/src/stdlib/abs.c deleted file mode 100644 index 3a10e8f..0000000 --- a/src/stdlib/abs.c +++ /dev/null @@ -1,7 +0,0 @@ -#include -#undef abs - -int abs(int x) -{ - return (x < 0) ? (-x) : (x); -} diff --git a/src/stdlib/calloc.c b/src/stdlib/calloc.c index 9c8421a..e1b9ac9 100644 --- a/src/stdlib/calloc.c +++ b/src/stdlib/calloc.c @@ -1,4 +1,5 @@ #include +#include /* calloc() diff --git a/src/stdlib/stdlib_abs.c b/src/stdlib/stdlib_abs.c new file mode 100644 index 0000000..3e4c4f8 --- /dev/null +++ b/src/stdlib/stdlib_abs.c @@ -0,0 +1,13 @@ +#include +#undef abs +#undef labs + +int abs(int x) +{ + return (x < 0) ? (-x) : x; +} + +long labs(long x) +{ + return (x < 0) ? (-x) : x; +} diff --git a/src/stdlib/stdlib_div.c b/src/stdlib/stdlib_div.c new file mode 100644 index 0000000..77f22a1 --- /dev/null +++ b/src/stdlib/stdlib_div.c @@ -0,0 +1,29 @@ +#include + +/* + 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; +} diff --git a/src/stdlib/stdlib_rand.c b/src/stdlib/stdlib_rand.c new file mode 100644 index 0000000..d5c17a6 --- /dev/null +++ b/src/stdlib/stdlib_rand.c @@ -0,0 +1,14 @@ +#include + +static unsigned int seed = 1; + +void srand(unsigned int new_seed) +{ + seed = new_seed; +} + +int rand(void) +{ + seed = seed * 1103515245 + 12345; + return seed & 0x7fffffff; +} diff --git a/src/time/mktime.c b/src/time/mktime.c new file mode 100644 index 0000000..e29b212 --- /dev/null +++ b/src/time/mktime.c @@ -0,0 +1,93 @@ +#include + +/* + 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; +} diff --git a/src/time/time_misc.c b/src/time/time_misc.c new file mode 100644 index 0000000..c3d21d6 --- /dev/null +++ b/src/time/time_misc.c @@ -0,0 +1,20 @@ +#include + +/* + 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); +} diff --git a/src/timer/timer_get.c b/src/timer/timer_get.c index 0d4b5cb..9174164 100644 --- a/src/timer/timer_get.c +++ b/src/timer/timer_get.c @@ -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; } diff --git a/src/timer/timer_interrupt.c b/src/timer/timer_interrupt.c index aea22bf..7dd91e4 100644 --- a/src/timer/timer_interrupt.c +++ b/src/timer/timer_interrupt.c @@ -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(); diff --git a/src/timer/timer_reload.c b/src/timer/timer_reload.c index 3b725e0..8cc047e 100644 --- a/src/timer/timer_reload.c +++ b/src/timer/timer_reload.c @@ -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; diff --git a/src/timer/timer_start.c b/src/timer/timer_start.c index c320edf..6b7aa1e 100644 --- a/src/timer/timer_start.c +++ b/src/timer/timer_start.c @@ -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; } diff --git a/src/timer/timer_stop.c b/src/timer/timer_stop.c index 8d8d860..083c4a4 100644 --- a/src/timer/timer_stop.c +++ b/src/timer/timer_stop.c @@ -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; }