From 87dd379c89dbe9b63dd3ab0f20f002a20d789c47 Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Wed, 2 Nov 2011 02:54:40 +0000 Subject: major update: lot of bugfixes, lot of changes - let compiler handle stack pointer arithmetic: switch to 16bit - improve update(): deadline depends on incremental release - resolve timing issues, new time convertion macros - major simplification of scheduler, most of garbage removed - new overflow interrupt for cycle counter, resolves also timing problems - simplify pwm generation, lookup tables are deferred, switch to 4bit - add blocking on shared values - remove garbage in lcd module and some bugfixes - add alternative reboot command to uart command interpreter - KISS --- kernel/clock.c | 33 +++++---- kernel/color.h | 90 ++++++++++++++++++++++++ kernel/ctrl.c | 6 +- kernel/dmx.c | 30 ++++---- kernel/dmx/Makefile | 10 ++- kernel/factor.h | 35 ++++++++++ kernel/factor10000.h | 35 ++++++++++ kernel/heartbeat.c | 14 ++-- kernel/kernel.c | 190 +++++++++++++++++++++++++-------------------------- kernel/kernel.h | 65 ++++++++++++++---- kernel/lcd3.c | 90 +++--------------------- kernel/rgb.c | 188 ++++++++------------------------------------------ kernel/stack.h | 3 - kernel/tasks.h | 16 ++--- kernel/uart.c | 1 + 15 files changed, 400 insertions(+), 406 deletions(-) create mode 100644 kernel/color.h create mode 100644 kernel/factor.h create mode 100644 kernel/factor10000.h (limited to 'kernel') diff --git a/kernel/clock.c b/kernel/clock.c index c098481..790391e 100644 --- a/kernel/clock.c +++ b/kernel/clock.c @@ -17,6 +17,7 @@ #include #include +#include #include #include "kernel.h" #include "tasks.h" @@ -24,27 +25,31 @@ void clock(void *arg) { - struct clockarg *a = arg; + struct lcdarg *a = arg; + uint8_t d, h, m, s; - a->s = a->m = a->h = a->d = 0; + d = h = m = s = 0; - update(0, SEC(1)); + update(0, SEC(500)); for (;;) { - a->s += 1; - if (a->s == 60) { - a->s = 0; - a->m += 1; + s += 1; + if (s == 60) { + s = 0; + m += 1; } - if (a->m == 60) { - a->m = 0; - a->h += 1; + if (m == 60) { + m = 0; + h += 1; } - if (a->h == 24) { - a->h = 0; - a->d += 1; + if (h == 24) { + h = 0; + d += 1; } - sleep(HARD, SEC(1)); + sprintf(a->first, "%8lx", now()); + sprintf(a->second, "%4d:%.2d:%.2d:%.2d", d, h, m, s); + + update(SEC(1), MSEC(500)); } } diff --git a/kernel/color.h b/kernel/color.h new file mode 100644 index 0000000..b208377 --- /dev/null +++ b/kernel/color.h @@ -0,0 +1,90 @@ +#ifndef __COLOR_H +#define __COLOR_H + +struct color { + uint8_t color, r, g, b; +} color[] PROGMEM = { + { 10, 0xff, 0x38, 0x00 }, + { 11, 0xff, 0x47, 0x00 }, + { 12, 0xff, 0x53, 0x00 }, + { 13, 0xff, 0x5d, 0x00 }, + { 14, 0xff, 0x65, 0x00 }, + { 15, 0xff, 0x6d, 0x00 }, + { 16, 0xff, 0x73, 0x00 }, + { 17, 0xff, 0x79, 0x00 }, + { 18, 0xff, 0x7e, 0x00 }, + { 19, 0xff, 0x83, 0x00 }, + { 20, 0xff, 0x89, 0x12 }, + { 21, 0xff, 0x8e, 0x21 }, + { 22, 0xff, 0x93, 0x2c }, + { 23, 0xff, 0x98, 0x36 }, + { 24, 0xff, 0x9d, 0x3f }, + { 25, 0xff, 0xa1, 0x48 }, + { 26, 0xff, 0xa5, 0x4f }, + { 27, 0xff, 0xa9, 0x57 }, + { 28, 0xff, 0xad, 0x5e }, + { 29, 0xff, 0xb1, 0x65 }, + { 30, 0xff, 0xb4, 0x6b }, + { 31, 0xff, 0xb8, 0x72 }, + { 32, 0xff, 0xbb, 0x78 }, + { 33, 0xff, 0xbe, 0x7e }, + { 34, 0xff, 0xc1, 0x84 }, + { 35, 0xff, 0xc4, 0x89 }, + { 36, 0xff, 0xc7, 0x8f }, + { 37, 0xff, 0xc9, 0x94 }, + { 38, 0xff, 0xcc, 0x99 }, + { 39, 0xff, 0xce, 0x9f }, + { 40, 0xff, 0xd1, 0xa3 }, + { 41, 0xff, 0xd3, 0xa8 }, + { 42, 0xff, 0xd5, 0xad }, + { 43, 0xff, 0xd7, 0xb1 }, + { 44, 0xff, 0xd9, 0xb6 }, + { 45, 0xff, 0xdb, 0xba }, + { 46, 0xff, 0xdd, 0xbe }, + { 47, 0xff, 0xdf, 0xc2 }, + { 48, 0xff, 0xe1, 0xc6 }, + { 49, 0xff, 0xe3, 0xca }, + { 50, 0xff, 0xe4, 0xce }, + { 51, 0xff, 0xe6, 0xd2 }, + { 52, 0xff, 0xe8, 0xd5 }, + { 53, 0xff, 0xe9, 0xd9 }, + { 54, 0xff, 0xeb, 0xdc }, + { 55, 0xff, 0xec, 0xe0 }, + { 56, 0xff, 0xee, 0xe3 }, + { 57, 0xff, 0xef, 0xe6 }, + { 58, 0xff, 0xf0, 0xe9 }, + { 59, 0xff, 0xf2, 0xec }, + { 60, 0xff, 0xf3, 0xef }, + { 61, 0xff, 0xf4, 0xf2 }, + { 62, 0xff, 0xf5, 0xf5 }, + { 63, 0xff, 0xf6, 0xf8 }, + { 64, 0xff, 0xf8, 0xfb }, + { 65, 0xff, 0xf9, 0xfd }, + { 66, 0xfe, 0xf9, 0xff }, + { 67, 0xfc, 0xf7, 0xff }, + { 68, 0xf9, 0xf6, 0xff }, + { 69, 0xf7, 0xf5, 0xff }, + { 70, 0xf5, 0xf3, 0xff }, + { 71, 0xf3, 0xf2, 0xff }, + { 72, 0xf0, 0xf1, 0xff }, + { 73, 0xef, 0xf0, 0xff }, + { 74, 0xed, 0xef, 0xff }, + { 75, 0xeb, 0xee, 0xff }, + { 76, 0xe9, 0xed, 0xff }, + { 77, 0xe7, 0xec, 0xff }, + { 78, 0xe6, 0xeb, 0xff }, + { 79, 0xe4, 0xea, 0xff }, + { 80, 0xe3, 0xe9, 0xff }, + { 81, 0xe1, 0xe8, 0xff }, + { 82, 0xe0, 0xe7, 0xff }, + { 83, 0xde, 0xe6, 0xff }, + { 84, 0xdd, 0xe6, 0xff }, + { 85, 0xdc, 0xe5, 0xff }, + { 86, 0xda, 0xe4, 0xff }, + { 87, 0xd9, 0xe3, 0xff }, + { 88, 0xd8, 0xe3, 0xff }, + { 89, 0xd7, 0xe2, 0xff }, + { 90, 0xd6, 0xe1, 0xff }, +}; + +#endif diff --git a/kernel/ctrl.c b/kernel/ctrl.c index 3becb49..720002e 100644 --- a/kernel/ctrl.c +++ b/kernel/ctrl.c @@ -26,15 +26,15 @@ ctrl(void *arg) { struct ctrlarg *a = arg; - update(0, MSEC(500)); + update(now(), MSEC(500)); for (;;) { - sprintf(a->lcd->first, "the time is now:"); + sprintf(a->lcd->first, "%8lx", now()); sprintf(a->lcd->second, "%4d:%.2d:%.2d:%.2d", a->clock->d, a->clock->h, a->clock->m, a->clock->s); - sleep(SOFT, MSEC(500)); + update(MSEC(500), MSEC(750)); } } diff --git a/kernel/dmx.c b/kernel/dmx.c index 504ffaf..4b30f1e 100644 --- a/kernel/dmx.c +++ b/kernel/dmx.c @@ -20,17 +20,15 @@ #include "kernel.h" #include "tasks.h" -/* globals */ -uint8_t red, green, blue; -struct rgbarg rgbargs = { &red, &green, &blue }; +struct rgbarg rgbargs; + struct pwmarg pwmargs[] = { - { &red, PB2 }, - { &green, PB3 }, - { &blue, PB4 } + { &rgbargs.r, PB2, &rgbargs.m }, + { &rgbargs.g, PB3, &rgbargs.m }, + { &rgbargs.b, PB4, &rgbargs.m } }; + struct lcdarg lcdarg; -struct clockarg clockarg; -struct ctrlarg ctrlarg = { &lcdarg, &clockarg }; int main() @@ -38,26 +36,26 @@ main() init(STACK); init_uart(); - semaphore(0, 1); - - exec(heartbeat, STACK, 0); // 48 +#if 1 + exec(heartbeat, STACK, 0); /* stack 48 */ +#endif #if 1 exec(rgb, STACK + 16, &rgbargs); exec(pwm, STACK, &pwmargs[0]); exec(pwm, STACK, &pwmargs[1]); exec(pwm, STACK, &pwmargs[2]); +#endif + #if 0 exec(cmd, STACK, &rgbargs); #endif + #if 1 exec(lcd, STACK, &lcdarg); - exec(clock, STACK, &clockarg); - exec(ctrl, STACK + 8, &ctrlarg); + exec(clock, STACK, &lcdarg); #endif -#endif - - for (;;); /* idle task */ + idle(); return 0; } diff --git a/kernel/dmx/Makefile b/kernel/dmx/Makefile index 051b5b2..72cbd27 100644 --- a/kernel/dmx/Makefile +++ b/kernel/dmx/Makefile @@ -2,15 +2,19 @@ MCU= atmega8 F_CPU= 16000000 -PRESCALE= 8 +#F_CPU= 14745600 +#PRESCALE= 1 # res 62.5nsec cycle 4msec +PRESCALE= 8 # res 0.5usec cycle 32.7msec +#PRESCALE= 64 # res 4usec cycle 262msec +#PRESCALE= 256 # res 16msec cycle 1 sec +#PRESCALE= 1024 # res 64msec cycle 4 sec STACK= 48 TASKS= 8 SEMAPHORES= 8 BAUD= 9600 PROG= dmx -SRCS= dmx.c heartbeat.c rgb.c hsv.c \ - clock.c lcd3.c ctrl.c uart.c +SRCS= dmx.c heartbeat.c rgb.c hsv.c clock.c lcd3.c uart.c NOMAN= .include diff --git a/kernel/factor.h b/kernel/factor.h new file mode 100644 index 0000000..a3b118b --- /dev/null +++ b/kernel/factor.h @@ -0,0 +1,35 @@ +/* 1/sqrt(2) timing scala in usec */ +uint16_t factor[256] PROGMEM = { + 30, 30, 31, 31, 32, 32, 33, 34, + 34, 35, 35, 36, 37, 37, 38, 39, + 39, 40, 41, 41, 42, 43, 44, 44, + 45, 46, 47, 48, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 68, + 69, 70, 71, 72, 74, 75, 76, 78, + 79, 80, 82, 83, 85, 86, 88, 89, + 91, 92, 94, 96, 97, 99, 101, 103, + 104, 106, 108, 110, 112, 114, 116, 118, + 120, 122, 124, 126, 129, 131, 133, 136, + 138, 140, 143, 145, 148, 150, 153, 156, + 158, 161, 164, 167, 170, 173, 176, 179, + 182, 185, 189, 192, 195, 199, 202, 206, + 209, 213, 217, 220, 224, 228, 232, 236, + 240, 245, 249, 253, 258, 262, 267, 272, + 276, 281, 286, 291, 296, 301, 307, 312, + 317, 323, 329, 334, 340, 346, 352, 358, + 365, 371, 378, 384, 391, 398, 405, 412, + 419, 426, 434, 441, 449, 457, 465, 473, + 481, 490, 498, 507, 516, 525, 534, 544, + 553, 563, 573, 583, 593, 603, 614, 625, + 635, 647, 658, 669, 681, 693, 705, 717, + 730, 743, 756, 769, 782, 796, 810, 824, + 839, 853, 868, 883, 899, 915, 931, 947, + 963, 980, 997, 1015, 1033, 1051, 1069, 1088, + 1107, 1126, 1146, 1166, 1186, 1207, 1228, 1250, + 1271, 1294, 1316, 1339, 1363, 1386, 1411, 1435, + 1460, 1486, 1512, 1538, 1565, 1593, 1621, 1649, + 1678, 1707, 1737, 1767, 1798, 1830, 1862, 1894, + 1927, 1961, 1995, 2030, 2066, 2102, 2138, 2176, + 2214, 2253, 2292, 2332, 2373, 2414, 2457, 2500, +}; diff --git a/kernel/factor10000.h b/kernel/factor10000.h new file mode 100644 index 0000000..2985026 --- /dev/null +++ b/kernel/factor10000.h @@ -0,0 +1,35 @@ +#ifndef __FACTOR_H +#define __FACTOR_H + +/* octave: round(sqrt(2).^(0:(1/16):16) * 10000 / 256)(2:end) */ + +uint16_t factor[256] PROGMEM = { + 40, 41, 42, 43, 44, 44, 45, 46, 47, 49, + 50, 51, 52, 53, 54, 55, 56, 58, 59, 60, + 62, 63, 64, 66, 67, 69, 70, 72, 73, 75, + 76, 78, 80, 82, 83, 85, 87, 89, 91, 93, + 95, 97, 99, 101, 104, 106, 108, 110, 113, 115, + 118, 120, 123, 126, 129, 131, 134, 137, 140, 143, + 146, 150, 153, 156, 160, 163, 167, 170, 174, 178, + 182, 186, 190, 194, 198, 203, 207, 212, 216, 221, + 226, 231, 236, 241, 246, 252, 257, 263, 269, 274, + 280, 287, 293, 299, 306, 313, 319, 326, 333, 341, + 348, 356, 364, 372, 380, 388, 397, 405, 414, 423, + 432, 442, 452, 462, 472, 482, 492, 503, 514, 526, + 537, 549, 561, 573, 586, 599, 612, 625, 639, 653, + 667, 682, 696, 712, 727, 743, 760, 776, 793, 811, + 828, 846, 865, 884, 903, 923, 943, 964, 985, 1007, + 1029, 1051, 1074, 1098, 1122, 1146, 1171, 1197, 1223, 1250, + 1277, 1305, 1334, 1363, 1393, 1423, 1455, 1487, 1519, 1552, + 1586, 1621, 1657, 1693, 1730, 1768, 1806, 1846, 1886, 1928, + 1970, 2013, 2057, 2102, 2148, 2195, 2243, 2293, 2343, 2394, + 2446, 2500, 2555, 2611, 2668, 2726, 2786, 2847, 2909, 2973, + 3038, 3105, 3173, 3242, 3313, 3386, 3460, 3536, 3613, 3692, + 3773, 3856, 3940, 4026, 4114, 4204, 4297, 4391, 4487, 4585, + 4685, 4788, 4893, 5000, 5109, 5221, 5336, 5453, 5572, 5694, + 5819, 5946, 6076, 6209, 6345, 6484, 6626, 6771, 6920, 7071, + 7226, 7384, 7546, 7711, 7880, 8052, 8229, 8409, 8593, 8781, + 8974, 9170, 9371, 9576, 9786, 10000 +}; + +#endif diff --git a/kernel/heartbeat.c b/kernel/heartbeat.c index b562d26..7ae97ae 100644 --- a/kernel/heartbeat.c +++ b/kernel/heartbeat.c @@ -20,7 +20,7 @@ #include "kernel.h" #include "tasks.h" -#define PIN PB0 +#define PIN PB0 void heartbeat(void *arg) @@ -30,19 +30,21 @@ heartbeat(void *arg) DDRB |= _BV(PIN); PORTB &= ~_BV(PIN); - update(0, MSEC(750)); +#define DL MSEC(5) + + update(now(), DL); for (;;) { PORTB |= _BV(PIN); - sleep(SOFT, MSEC(100)); + update(MSEC(100), DL); PORTB &= ~_BV(PIN); - sleep(SOFT, MSEC(50)); + update(MSEC(50), DL); PORTB |= _BV(PIN); - sleep(SOFT, MSEC(100)); + update(MSEC(100), DL); PORTB &= ~_BV(PIN); - sleep(SOFT, MSEC(500)); + update(MSEC(500), DL); } } diff --git a/kernel/kernel.c b/kernel/kernel.c index 5060687..bf8fee9 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -25,22 +25,20 @@ #include "kernel.h" #include "stack.h" -enum { TERMINATED, RUNQ, TIMEQ, WAITQOFFSET }; +enum State { TERMINATED, RUNQ, TIMEQ, WAITQOFFSET }; #define LO8(x) ((uint8_t)((uint16_t)(x))) #define HI8(x) ((uint8_t)((uint16_t)(x) >> 8)) #define SCHEDULE TIMER1_COMPA_vect #define DISTANCE(from, to) ((int32_t)((to) - (from))) -#define EPOCH 0x3FFFFFFFUL /* XXX */ -#define EPS (LATENCY / PRESCALE + 1) /* XXX */ +#define EPOCH (INT32_MAX >> 1) #define NOW(hi, lo) (((uint32_t)(hi) << 0x10) | (lo)) struct task { - uint8_t spl; - uint8_t sph; + uint8_t state; + uint16_t sp; /* stack pointer */ uint32_t release; uint32_t deadline; - uint8_t state; }; struct kernel { @@ -52,28 +50,24 @@ struct kernel { uint16_t cycles; } kernel; -ISR(SCHEDULE, ISR_NAKED) +ISR(TIMER1_OVF_vect) +{ + ++kernel.cycles; +} + +ISR(TIMER1_COMPA_vect, ISR_NAKED) { struct task *t; struct task *rtr; uint32_t now; uint32_t nexthit; - int32_t timeleft; PUSH_ALL(); - TIMSK &= ~_BV(OCIE1A); /* turn off output compare 1A */ - - if (bit_is_set(TIFR, TOV1)) { - TIFR |= _BV(TOV1); /* reset flag */ - ++kernel.cycles; - } - now = NOW(kernel.cycles, TCNT1); - nexthit = now + EPOCH; + nexthit = EPOCH + now; /* update idle task */ - kernel.task->release = now; kernel.task->deadline = nexthit; rtr = kernel.task; @@ -81,66 +75,49 @@ ISR(SCHEDULE, ISR_NAKED) for (t = &kernel.task[1]; t <= kernel.last; t++) { /* release tasks from time-wait-queue */ if (t->state == TIMEQ) { - if (DISTANCE(now, t->release) < 0) + if (DISTANCE(t->release, now) > 0) t->state = RUNQ; else if (DISTANCE(t->release, nexthit) > 0) nexthit = t->release; } /* find next task to run */ - if (t->state == RUNQ && \ - DISTANCE(t->deadline, rtr->deadline) > 0) - rtr = t; - } - - if (kernel.running != rtr) { - /* switch task */ - kernel.running->spl = SPL; - kernel.running->sph = SPH; - SPL = rtr->spl; - SPH = rtr->sph; - kernel.running = rtr; + if (t->state == RUNQ) { + if (DISTANCE(t->deadline, rtr->deadline) > 0) + rtr = t; + } } - now = NOW(kernel.cycles, TCNT1); - timeleft = DISTANCE(now, nexthit); - - if (timeleft < EPS) - timeleft = EPS; - - timeleft += TCNT1; - - if (timeleft < 0xFFFF) - OCR1A = timeleft; - else if (TCNT1 > 0xFFFF - EPS) - OCR1A = EPS; - else - OCR1A = 0; - - TIMSK |= _BV(OCIE1A); + /* switch task */ + kernel.running->sp = SP; + SP = rtr->sp; + kernel.running = rtr; + OCR1A = (uint16_t)nexthit; + POP_ALL(); - reti(); } void init(int stack) { + cli(); + /* Set up timer 1 */ - TCNT1 = 0; /* reset counter 1 */ - TCCR1A = 0; /* normal operation */ - TCCR1B = TIMER_FLAGS; - TIMSK = _BV(OCIE1A); + TCNT1 = 0; /* reset timer */ + TCCR1A = 0; /* normal operation */ + TCCR1B = TIMER_FLAGS; /* prescale */ + TIMSK = (_BV(OCIE1A) | _BV(TOIE1)); /* enable interrupts */ + kernel.cycles = 0; kernel.freemem = (void *)(RAMEND - stack); kernel.last = kernel.task; kernel.running = kernel.task; - kernel.cycles = 0; /* Initialize idle task (task 0) */ - kernel.running->release = 0; kernel.running->deadline = EPOCH; + kernel.running->state = RUNQ; sei(); } @@ -150,7 +127,7 @@ exec(void (*fun)(void *), uint16_t stack, void *args) { struct task *t; uint8_t *sp; - int i; + uint8_t i; cli(); @@ -158,27 +135,25 @@ exec(void (*fun)(void *), uint16_t stack, void *args) kernel.freemem -= stack; /* initialize stack */ - *sp-- = LO8(fun); /* store PC(lo) */ - *sp-- = HI8(fun); /* store PC(hi) */ + *sp-- = LO8(fun); /* PC(lo) */ + *sp-- = HI8(fun); /* PC(hi) */ - for (i = 0; i < 25; i++) - *sp-- = 0; /* store r1-r0, SREG, r2-r23 */ + for (i = 0; i < 25; i++) /* r1, r0, SREG, r2-r23 */ + *sp-- = 0; + + *sp-- = LO8(args); /* r24 */ + *sp-- = HI8(args); /* r25 */ - /* Save args in r24-25 (input arguments stored in these registers) */ - *sp-- = LO8(args); - *sp-- = HI8(args); - - for (i = 0; i < 6; i++) - *sp-- = 0; /* store r26-r31 */ + for (i = 0; i < 6; i++) /* r26-r31 */ + *sp-- = 0; t = ++kernel.last; t->release = 0; t->deadline = EPOCH; - t->state = RUNQ; + t->state = TIMEQ; - t->spl = LO8(sp); /* store stack pointer */ - t->sph = HI8(sp); + t->sp = (uint16_t)sp; /* SP */ SCHEDULE(); } @@ -201,44 +176,42 @@ wait(uint8_t sema) if (kernel.semaphore[sema] == 0) { kernel.running->state = WAITQOFFSET + sema; SCHEDULE(); - } else + } else { --kernel.semaphore[sema]; - - sei(); + sei(); + } } void signal(uint8_t sema) { - struct task *t; - struct task *rtr; + struct task *t, *rtr; cli(); rtr = kernel.task; for (t = &kernel.task[1]; t <= kernel.last; t++) { - if (t->state == WAITQOFFSET + sema && \ - DISTANCE(t->deadline, rtr->deadline) > 0) - rtr = t; + if (t->state == WAITQOFFSET + sema) + if (DISTANCE(t->deadline, rtr->deadline) > 0) + rtr = t; } if (rtr != kernel.task) { rtr->state = RUNQ; SCHEDULE(); - } else + } else { ++kernel.semaphore[sema]; - - sei(); + sei(); + } } void -update(uint32_t release, uint32_t deadline) +set(uint32_t release, uint32_t deadline) { cli(); - if (DISTANCE(NOW(kernel.cycles, TCNT1), release) > 0) - kernel.running->state = TIMEQ; + kernel.running->state = TIMEQ; kernel.running->release = release; kernel.running->deadline = deadline; @@ -246,41 +219,51 @@ update(uint32_t release, uint32_t deadline) } void -sleep(uint8_t type, uint32_t delay) +update(uint32_t release, uint32_t deadline) { cli(); kernel.running->state = TIMEQ; - kernel.running->release += delay; - switch (type) { - case SOFT: - if (DISTANCE(kernel.running->deadline, kernel.running->release) > 0) - kernel.running->deadline += delay; - break; - case HARD: - kernel.running->deadline = kernel.running->release; - break; - } + kernel.running->release += release; + kernel.running->deadline = kernel.running->release + deadline; SCHEDULE(); } - + uint32_t deadline(void) { - return kernel.running->deadline; + uint32_t ret; + + cli(); + ret = kernel.running->deadline; + sei(); + + return ret; } uint32_t release(void) { - return kernel.running->release; + uint32_t ret; + + cli(); + ret = kernel.running->release; + sei(); + + return ret; } uint32_t now(void) { - return NOW(kernel.cycles, TCNT1); + uint32_t ret; + + cli(); + ret = NOW(kernel.cycles, TCNT1); + sei(); + + return ret; } void @@ -296,5 +279,18 @@ suspend(void) uint8_t running(void) { - return kernel.running - kernel.task; + uint8_t ret; + + cli(); + ret = kernel.running - kernel.task; + sei(); + + return ret; +} + +void +idle(void) +{ + for (;;) + asm volatile ("nop"); } diff --git a/kernel/kernel.h b/kernel/kernel.h index 2a96b6b..cadef22 100644 --- a/kernel/kernel.h +++ b/kernel/kernel.h @@ -19,47 +19,77 @@ #define __KERNEL_H #ifndef TASKS -#warning "TASKS not set, fallback to default" +#warning TASKS not set, fallback to default #define TASKS 8 #endif #ifndef SEMAPHORES -#warning "SEMAPHORES not set, fallback to default" +#warning SEMAPHORES not set, fallback to default #define SEMAPHORES 8 #endif #ifndef STACK -#warning "STACK not set, fallback to default" +#warning STACK not set, fallback to default #define STACK 64 #endif #ifndef F_CPU -#warning "F_CPU not set, fallback to default" -#define F_CPU 1000000 +#warning F_CPU not set, fallback to default +#define F_CPU 16000000 #endif #ifndef PRESCALE -#warning "PRESCALE not set, fallback to default" +#warning PRESCALE not set, fallback to default #define PRESCALE 1 #endif #if (PRESCALE == 1) -#define TIMER_FLAGS _BV(CS10) +#define TIMER_FLAGS (_BV(CS10)) #elif (PRESCALE == 8) -#define TIMER_FLAGS _BV(CS11) +#define TIMER_FLAGS (_BV(CS11)) #elif (PRESCALE == 64) #define TIMER_FLAGS (_BV(CS11) | _BV(CS10)) #elif (PRESCALE == 256) -#define TIMER_FLAGS _BV(CS12) +#define TIMER_FLAGS (_BV(CS12)) #elif (PRESCALE == 1024) #define TIMER_FLAGS (_BV(CS12) | _BV(CS10)) #else -#warning "invalid PRESCALE value" +#error invalid PRESCALE value #endif -#define SEC(T) ((uint32_t)(T) * (F_CPU / PRESCALE)) -#define MSEC(T) ((uint32_t)(T) * ((F_CPU / 1000) / PRESCALE)) -#define USEC(T) ((uint32_t)(T) * ((F_CPU / 1000000) / PRESCALE)) +#define MHz ((F_CPU / 1000000) / PRESCALE) +#define kHz ((F_CPU / 1000) / PRESCALE) +#define Hz (F_CPU / PRESCALE) + +#if (!MHz) +#error MHz value too small, adjust PRESCALE and/or F_CPU +#endif + +#if (!kHz) +#error kHz value too small, adjust PRESCALE and/or F_CPU +#endif + +#if (!Hz) +#error Hz value too small, adjust PRESCALE and/or F_CPU +#endif + +#define USECMAX (INT32_MAX / MHz) +#define MSECMAX (INT32_MAX / kHz) +#define SECMAX (INT32_MAX / Hz) + +#define USEC(T) ((uint32_t)(T) * MHz) +#define MSEC(T) ((uint32_t)(T) * kHz) +#define SEC(T) ((uint32_t)(T) * Hz) + +#define SEC6(T) ((uint32_t)(T) * ((F_CPU / 1000000) / PRESCALE)) +#define SEC5(T) ((uint32_t)(T) * ((F_CPU / 100000) / PRESCALE)) +#define SEC4(T) ((uint32_t)(T) * ((F_CPU / 10000) / PRESCALE)) +#define SEC3(T) ((uint32_t)(T) * ((F_CPU / 1000) / PRESCALE)) +#define SEC2(T) ((uint32_t)(T) * ((F_CPU / 100) / PRESCALE)) +#define SEC1(T) ((uint32_t)(T) * ((F_CPU / 10) / PRESCALE)) +#define SEC0(T) ((uint32_t)(T) * ((F_CPU / 1) / PRESCALE)) + +/* __BEGIN_DECLS */ void init(int stack); void exec(void (*fun)(void *), uint16_t stack, void *args); @@ -69,13 +99,18 @@ void wait(uint8_t semnbr); void signal(uint8_t semnbr); void suspend(void); +void set(uint32_t release, uint32_t deadline); void update(uint32_t release, uint32_t deadline); -enum { SOFT, HARD }; -void sleep(uint8_t, uint32_t); +enum Sleep { SOFT, HARD }; +enum Critical { ON, OFF }; +void sleep(enum Sleep, uint32_t); uint32_t now(void); uint32_t release(void); uint32_t deadline(void); uint8_t running(void); +void idle(void); + +/* __END_DECLS */ #endif diff --git a/kernel/lcd3.c b/kernel/lcd3.c index 848dee9..b7bbb10 100644 --- a/kernel/lcd3.c +++ b/kernel/lcd3.c @@ -19,10 +19,7 @@ #include #include -#ifdef USE_DELAY -#warning "using dalay routines" #include -#endif #include "kernel.h" #include "tasks.h" @@ -39,10 +36,10 @@ #define BLINK _BV(0) #define CURSOR_OR_DISPLAY_SHIFT _BV(4) -#define SHIFT_CURS_LEFT (0x00 << 2) -#define SHIFT_CURS_RIGHT (0x01 << 2) -#define SHIFT_DISP_LEFT (0x10 << 2) -#define SHIFT_DISP_RIGHT (0x11 << 2) +#define SHIFT_CURS_LEFT 0 +#define SHIFT_CURS_RIGHT _BV(2) +#define SHIFT_DISP_LEFT _BV(3) +#define SHIFT_DISP_RIGHT (_BV(2) | _BV(3)) #define FUNCTION_SET _BV(5) #define DATA_LENGTH_8BIT _BV(4) /* on 8 / off 4 bit */ @@ -54,20 +51,15 @@ #define SET_DDRAM_ADDRESS _BV(7) #define BUSY_FLAG _BV(7) -/* 3-wire interface with 74HC164 */ +/* 3-wire interface to HD44780 throuth 74HC164 */ #define PORT PORTD #define PORTDIR DDRD -#define DATA PD5 -#define CLOCK PD6 -#define E PD7 +#define DATA PD5 +#define CLOCK PD6 +#define E PD7 -#ifdef USE_DELAY #define write_cmd(x, delay) do { write_byte((x), 0); _delay_us(delay); } while (0) #define write_data(x) do { write_byte((x), 1); _delay_us(43); } while (0) -#else -#define write_cmd(x, delay) do { write_byte((x), 0); sleep(SOFT, USEC(delay)); } while (0) -#define write_data(x) do { write_byte((x), 1); sleep(SOFT, USEC(43)); } while (0) -#endif #define move(line, row) do { write_cmd(SET_DDRAM_ADDRESS | ((line) << 6) | (row), 39); } while (0) #define clear() do { write_cmd(CLEAR_DISPLAY, 1530); } while (0) #define home() do { write_cmd(RETURN_HOME, 1530); } while (0) @@ -84,7 +76,7 @@ write_byte(uint8_t byte, uint8_t rs) uint8_t i; for (i = 0; i < 8; i++) { - setif(byte & (0b10000000 >> i), PORT, DATA); /* MSF */ + setif(byte & (0x80 >> i), PORT, DATA); /* MSF */ strobe(PORT, CLOCK); } setif(rs, PORT, DATA); @@ -106,66 +98,6 @@ mvputch(uint8_t line, uint8_t row, char ch) write_data(ch); } -#if 0 -static char * -itoa(int32_t n) -{ - static char buf[12]; - char *s = &buf[11]; - uint32_t sign, u = n; - - *s = '\0'; - - if ((sign = (n < 0))) - u = ~u + 1; - - do - *--s = '0' + (u % 10); - while ((u /= 10) > 0); - - if (sign) - *--s = '-'; - - while (s != buf) - *--s = ' '; - - return s; -} - -static char hex[] = "0123456789ABCDEF"; - -static char * -itohex16(uint16_t x) -{ - static char buf[5]; - char *s = &buf[4]; - uint8_t i; - - *s = '\0'; - - for (i = 0; i < 16; i += 4) - *--s = hex[(x >> i) & 0x0f]; - - return s; -} - - -static char * -itohex32(uint32_t x) -{ - static char buf[9]; - char *s = &buf[8]; - uint8_t i; - - *s = '\0'; - - for (i = 0; i < 32; i += 4) - *--s = hex[(x >> i) & 0x0f]; - - return s; -} -#endif - void lcd(void *arg) { @@ -174,7 +106,7 @@ lcd(void *arg) PORTDIR |= (_BV(DATA) | _BV(CLOCK) | _BV(E)); /* task init: wait >40ms */ - update(MSEC(40), MSEC(500)); + update(now() + MSEC(40), MSEC(500)); /* 8 bit, 2 line, 5x8 font */ write_cmd(FUNCTION_SET | DATA_LENGTH_8BIT | TWO_LINES, 39); @@ -197,6 +129,6 @@ lcd(void *arg) for (;;) { mvputs(0, 0, a->first); mvputs(1, 0, a->second); - sleep(SOFT, MSEC(40)); /* 25 Hz */ + update(MSEC(40), MSEC(40)); /* 25Hz */ } } diff --git a/kernel/rgb.c b/kernel/rgb.c index 4a963c7..5684456 100644 --- a/kernel/rgb.c +++ b/kernel/rgb.c @@ -17,169 +17,36 @@ #include #include -#include +#include #include "kernel.h" #include "tasks.h" void hsv(uint8_t *, uint8_t *, uint8_t *, uint16_t, uint8_t, uint8_t); -/* 1/sqrt(2) timing scala in usec */ -uint16_t factor[] PROGMEM = { - 30, 30, 31, 31, 32, 32, 33, 34, - 34, 35, 35, 36, 37, 37, 38, 39, - 39, 40, 41, 41, 42, 43, 44, 44, - 45, 46, 47, 48, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 68, - 69, 70, 71, 72, 74, 75, 76, 78, - 79, 80, 82, 83, 85, 86, 88, 89, - 91, 92, 94, 96, 97, 99, 101, 103, - 104, 106, 108, 110, 112, 114, 116, 118, - 120, 122, 124, 126, 129, 131, 133, 136, - 138, 140, 143, 145, 148, 150, 153, 156, - 158, 161, 164, 167, 170, 173, 176, 179, - 182, 185, 189, 192, 195, 199, 202, 206, - 209, 213, 217, 220, 224, 228, 232, 236, - 240, 245, 249, 253, 258, 262, 267, 272, - 276, 281, 286, 291, 296, 301, 307, 312, - 317, 323, 329, 334, 340, 346, 352, 358, - 365, 371, 378, 384, 391, 398, 405, 412, - 419, 426, 434, 441, 449, 457, 465, 473, - 481, 490, 498, 507, 516, 525, 534, 544, - 553, 563, 573, 583, 593, 603, 614, 625, - 635, 647, 658, 669, 681, 693, 705, 717, - 730, 743, 756, 769, 782, 796, 810, 824, - 839, 853, 868, 883, 899, 915, 931, 947, - 963, 980, 997, 1015, 1033, 1051, 1069, 1088, - 1107, 1126, 1146, 1166, 1186, 1207, 1228, 1250, - 1271, 1294, 1316, 1339, 1363, 1386, 1411, 1435, - 1460, 1486, 1512, 1538, 1565, 1593, 1621, 1649, - 1678, 1707, 1737, 1767, 1798, 1830, 1862, 1894, - 1927, 1961, 1995, 2030, 2066, 2102, 2138, 2176, - 2214, 2253, 2292, 2332, 2373, 2414, 2457, 2500, -}; - -struct bb { - uint8_t color, r, g, b; -} bb[] PROGMEM = { - { 10, 0xff, 0x38, 0x00 }, - { 11, 0xff, 0x47, 0x00 }, - { 12, 0xff, 0x53, 0x00 }, - { 13, 0xff, 0x5d, 0x00 }, - { 14, 0xff, 0x65, 0x00 }, - { 15, 0xff, 0x6d, 0x00 }, - { 16, 0xff, 0x73, 0x00 }, - { 17, 0xff, 0x79, 0x00 }, - { 18, 0xff, 0x7e, 0x00 }, - { 19, 0xff, 0x83, 0x00 }, - { 20, 0xff, 0x89, 0x12 }, - { 21, 0xff, 0x8e, 0x21 }, - { 22, 0xff, 0x93, 0x2c }, - { 23, 0xff, 0x98, 0x36 }, - { 24, 0xff, 0x9d, 0x3f }, - { 25, 0xff, 0xa1, 0x48 }, - { 26, 0xff, 0xa5, 0x4f }, - { 27, 0xff, 0xa9, 0x57 }, - { 28, 0xff, 0xad, 0x5e }, - { 29, 0xff, 0xb1, 0x65 }, - { 30, 0xff, 0xb4, 0x6b }, - { 31, 0xff, 0xb8, 0x72 }, - { 32, 0xff, 0xbb, 0x78 }, - { 33, 0xff, 0xbe, 0x7e }, - { 34, 0xff, 0xc1, 0x84 }, - { 35, 0xff, 0xc4, 0x89 }, - { 36, 0xff, 0xc7, 0x8f }, - { 37, 0xff, 0xc9, 0x94 }, - { 38, 0xff, 0xcc, 0x99 }, - { 39, 0xff, 0xce, 0x9f }, - { 40, 0xff, 0xd1, 0xa3 }, - { 41, 0xff, 0xd3, 0xa8 }, - { 42, 0xff, 0xd5, 0xad }, - { 43, 0xff, 0xd7, 0xb1 }, - { 44, 0xff, 0xd9, 0xb6 }, - { 45, 0xff, 0xdb, 0xba }, - { 46, 0xff, 0xdd, 0xbe }, - { 47, 0xff, 0xdf, 0xc2 }, - { 48, 0xff, 0xe1, 0xc6 }, - { 49, 0xff, 0xe3, 0xca }, - { 50, 0xff, 0xe4, 0xce }, - { 51, 0xff, 0xe6, 0xd2 }, - { 52, 0xff, 0xe8, 0xd5 }, - { 53, 0xff, 0xe9, 0xd9 }, - { 54, 0xff, 0xeb, 0xdc }, - { 55, 0xff, 0xec, 0xe0 }, - { 56, 0xff, 0xee, 0xe3 }, - { 57, 0xff, 0xef, 0xe6 }, - { 58, 0xff, 0xf0, 0xe9 }, - { 59, 0xff, 0xf2, 0xec }, - { 60, 0xff, 0xf3, 0xef }, - { 61, 0xff, 0xf4, 0xf2 }, - { 62, 0xff, 0xf5, 0xf5 }, - { 63, 0xff, 0xf6, 0xf8 }, - { 64, 0xff, 0xf8, 0xfb }, - { 65, 0xff, 0xf9, 0xfd }, - { 66, 0xfe, 0xf9, 0xff }, - { 67, 0xfc, 0xf7, 0xff }, - { 68, 0xf9, 0xf6, 0xff }, - { 69, 0xf7, 0xf5, 0xff }, - { 70, 0xf5, 0xf3, 0xff }, - { 71, 0xf3, 0xf2, 0xff }, - { 72, 0xf0, 0xf1, 0xff }, - { 73, 0xef, 0xf0, 0xff }, - { 74, 0xed, 0xef, 0xff }, - { 75, 0xeb, 0xee, 0xff }, - { 76, 0xe9, 0xed, 0xff }, - { 77, 0xe7, 0xec, 0xff }, - { 78, 0xe6, 0xeb, 0xff }, - { 79, 0xe4, 0xea, 0xff }, - { 80, 0xe3, 0xe9, 0xff }, - { 81, 0xe1, 0xe8, 0xff }, - { 82, 0xe0, 0xe7, 0xff }, - { 83, 0xde, 0xe6, 0xff }, - { 84, 0xdd, 0xe6, 0xff }, - { 85, 0xdc, 0xe5, 0xff }, - { 86, 0xda, 0xe4, 0xff }, - { 87, 0xd9, 0xe3, 0xff }, - { 88, 0xd8, 0xe3, 0xff }, - { 89, 0xd7, 0xe2, 0xff }, - { 90, 0xd6, 0xe1, 0xff }, -}; - void rgb(void *arg) { struct rgbarg *a = (struct rgbarg *)arg; uint16_t i = 0; - uint8_t v; + uint8_t r, g, b; + + cli(); + a->m = 255 >> 4; + sei(); - update(0, MSEC(370)); + update(now(), MSEC(500)); for (;;) { -#if 1 i = (i + 1) % 360; - #if 0 - v = i % 120; - v = (v < 60) ? 255 - 2 * v : 15 + 2 * v; - #else - v = 255; - #endif + hsv(&r, &g, &b, i, 255, 255); - hsv(a->r, a->g, a->b, i, 255, v); - sleep(SOFT, MSEC(83)); -#else - i = (i + 1) % 162; - if (i > 80) - v = 161 - i; - else - v = i; - //wait(0); - *a->r = pgm_read_byte(&bb[v].r); - *a->g = pgm_read_byte(&bb[v].g); - *a->b = pgm_read_byte(&bb[v].b); - //signal(0); + cli(); + a->r = r >> 4; + a->g = g >> 4; + a->b = b >> 4; + sei(); - sleep(SOFT, MSEC(370)); -#endif + update(MSEC(500), MSEC(500)); } } @@ -187,29 +54,32 @@ void pwm(void *arg) { struct pwmarg *a = (struct pwmarg *)arg; - uint16_t on, off, maxval;; - uint32_t n = now(); + uint16_t maxval, on, off; DDRB |= _BV(a->pin); PORTB &= ~_BV(a->pin); - maxval = pgm_read_word(&factor[255]); - update(n, n + USEC(maxval)); +#define DL MSEC(1) + + cli(); + maxval = *a->mval; + sei(); + update(now(), DL); for (;;) { - //wait(0); - on = pgm_read_word(&factor[*a->value]); - //signal(0); - off = maxval - on; + cli(); + on = *a->value; + sei(); - if (*a->value > 0) { + if (on) { PORTB |= _BV(a->pin); - sleep(HARD, USEC(on)); + update(MSEC(on), DL); } - if (*a->value < 255) { + off = maxval - on; + if (off) { PORTB &= ~_BV(a->pin); - sleep(HARD, USEC(off)); + update(MSEC(off), DL); } } } diff --git a/kernel/stack.h b/kernel/stack.h index 0f44954..b53c870 100644 --- a/kernel/stack.h +++ b/kernel/stack.h @@ -18,9 +18,6 @@ #ifndef __STACK_H #define __STACK_H -/* average latency in cycles */ -#define LATENCY 72 - /* 68 cycles */ #define PUSH_ALL() asm volatile ( \ "push r1 \n" \ diff --git a/kernel/tasks.h b/kernel/tasks.h index f6030b3..9fb27da 100644 --- a/kernel/tasks.h +++ b/kernel/tasks.h @@ -42,12 +42,16 @@ #endif struct rgbarg { - uint8_t *r, *g, *b; + uint8_t r; + uint8_t g; + uint8_t b; + uint8_t m; }; struct pwmarg { uint8_t *value; uint8_t pin; + uint8_t *mval; }; struct adcarg { @@ -62,19 +66,10 @@ struct lcdarg { uint8_t x, y; }; -struct clockarg { - uint8_t d, h, m, s; -}; - struct ppmarg { uint16_t *value; }; -struct ctrlarg { - struct lcdarg *lcd; - struct clockarg *clock; -}; - void init_uart(void); int uart_getchar(void); int uart_putchar(char); @@ -87,6 +82,5 @@ void adc(void *); void ppm(void *); void cmd(void *); void clock(void *); -void ctrl(void *); #endif diff --git a/kernel/uart.c b/kernel/uart.c index 0d64d50..defd552 100644 --- a/kernel/uart.c +++ b/kernel/uart.c @@ -84,6 +84,7 @@ ISR(SIG_UART_RECV) switch (c) { case 'R': /* reboot */ + case '-': /* reboot */ wdt_enable(WDTO_15MS); break; case 'D': /* dump */ -- cgit v1.2.3