From b4a9b392c57ca8b3f740dd3035b1f43b4ad583b4 Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Tue, 12 Jul 2011 00:54:33 +0000 Subject: add clock, redesign timer, tweak stack values --- kernel/Makefile | 2 +- kernel/clock.c | 50 ++++++++++++++++++++++++++++++++++++ kernel/cmd.c | 5 +--- kernel/ctrl.c | 40 +++++++++++++++++++++++++++++ kernel/dmx.c | 34 ++++++++++++++++-------- kernel/dmx/Makefile | 8 +++--- kernel/heartbeat.c | 18 +++++++------ kernel/kernel.c | 74 +++++++++++++++++++---------------------------------- kernel/kernel.h | 9 +++---- kernel/lcd3.c | 29 +++++++++++++++------ kernel/rgb.c | 23 +++++++++-------- kernel/tasks.h | 17 +++++++++--- 12 files changed, 209 insertions(+), 100 deletions(-) create mode 100644 kernel/clock.c create mode 100644 kernel/ctrl.c diff --git a/kernel/Makefile b/kernel/Makefile index fac49e2..2482984 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -1,5 +1,5 @@ # $Id$ -SUBDIR= remix16 dmx +SUBDIR= dmx .include diff --git a/kernel/clock.c b/kernel/clock.c new file mode 100644 index 0000000..c098481 --- /dev/null +++ b/kernel/clock.c @@ -0,0 +1,50 @@ +/* $Id$ */ +/* + * Copyright (c) 2011 Dimitri Sokolyuk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include "kernel.h" +#include "tasks.h" + +void +clock(void *arg) +{ + struct clockarg *a = arg; + + a->s = a->m = a->h = a->d = 0; + + update(0, SEC(1)); + + for (;;) { + a->s += 1; + if (a->s == 60) { + a->s = 0; + a->m += 1; + } + if (a->m == 60) { + a->m = 0; + a->h += 1; + } + if (a->h == 24) { + a->h = 0; + a->d += 1; + } + + sleep(HARD, SEC(1)); + } +} diff --git a/kernel/cmd.c b/kernel/cmd.c index 0174817..89d7a5f 100644 --- a/kernel/cmd.c +++ b/kernel/cmd.c @@ -34,8 +34,6 @@ void cmd(void *arg) { struct rgbarg *a = arg; - uint32_t d = deadline(); - uint32_t r = release(); char c; int val; char buf[10], *s; @@ -63,7 +61,6 @@ cmd(void *arg) } } - d = r += MSEC(10); - update(r, d); + snore(MSEC(10)); } } diff --git a/kernel/ctrl.c b/kernel/ctrl.c new file mode 100644 index 0000000..3becb49 --- /dev/null +++ b/kernel/ctrl.c @@ -0,0 +1,40 @@ +/* $Id$ */ +/* + * Copyright (c) 2011 Dimitri Sokolyuk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include "kernel.h" +#include "tasks.h" + +void +ctrl(void *arg) +{ + struct ctrlarg *a = arg; + + update(0, MSEC(500)); + + for (;;) { + sprintf(a->lcd->first, "the time is 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)); + } +} diff --git a/kernel/dmx.c b/kernel/dmx.c index 412db9b..7b17e6a 100644 --- a/kernel/dmx.c +++ b/kernel/dmx.c @@ -20,30 +20,42 @@ #include "kernel.h" #include "tasks.h" +/* globals */ uint8_t red, green, blue; - struct rgbarg rgbargs = { &red, &green, &blue }; struct pwmarg pwmargs[] = { { &red, PB2 }, { &green, PB3 }, { &blue, PB4 } }; +struct lcdarg lcdarg; +struct clockarg clockarg; +struct ctrlarg ctrlarg = { &lcdarg, &clockarg }; int main() { - init(STACK); + init(36); +#if 0 semaphore(0, 1); - - task(heartbeat, STACK, USEC(0), MSEC(750), 0); - task(rgb, STACK, USEC(10), MSEC(10), &rgbargs); - task(pwm, STACK, USEC(20), USEC(2500), &pwmargs[0]); - task(pwm, STACK, USEC(30), USEC(2500), &pwmargs[1]); - task(pwm, STACK, USEC(50), USEC(2500), &pwmargs[2]); - task(cmd, STACK, USEC(70), MSEC(10), &rgbargs); - - for (;;); +#endif + task(heartbeat, STACK, 0); + + task(rgb, STACK + 8, &rgbargs); + task(pwm, STACK, &pwmargs[0]); + task(pwm, STACK, &pwmargs[1]); + task(pwm, STACK, &pwmargs[2]); +#if 0 + task(cmd, STACK, &rgbargs); +#endif +#if 1 + task(lcd, STACK, &lcdarg); + task(clock, STACK, &clockarg); + task(ctrl, STACK, &ctrlarg); +#endif + + for (;;); /* idle task */ return 0; } diff --git a/kernel/dmx/Makefile b/kernel/dmx/Makefile index a77e610..c81afce 100644 --- a/kernel/dmx/Makefile +++ b/kernel/dmx/Makefile @@ -3,14 +3,16 @@ MCU= atmega8 F_CPU= 16000000 PRESCALE= 8 -STACK= 64 +#STACK= 64 +STACK= 48 +#STACK= 56 TASKS= 8 SEMAPHORES= 8 BAUD= 9600 -USE_2X= 1 PROG= dmx -SRCS= dmx.c uart.c heartbeat.c rgb.c hsv.c cmd.c +SRCS= dmx.c heartbeat.c rgb.c hsv.c \ + clock.c lcd3.c ctrl.c NOMAN= .include diff --git a/kernel/heartbeat.c b/kernel/heartbeat.c index 64f3182..b562d26 100644 --- a/kernel/heartbeat.c +++ b/kernel/heartbeat.c @@ -30,17 +30,19 @@ heartbeat(void *arg) DDRB |= _BV(PIN); PORTB &= ~_BV(PIN); + update(0, MSEC(750)); + for (;;) { - PORTB ^= _BV(PIN); - snooze(MSEC(100)); + PORTB |= _BV(PIN); + sleep(SOFT, MSEC(100)); - PORTB ^= _BV(PIN); - snooze(MSEC(50)); + PORTB &= ~_BV(PIN); + sleep(SOFT, MSEC(50)); - PORTB ^= _BV(PIN); - snooze(MSEC(100)); + PORTB |= _BV(PIN); + sleep(SOFT, MSEC(100)); - PORTB ^= _BV(PIN); - period(MSEC(750)); + PORTB &= ~_BV(PIN); + sleep(SOFT, MSEC(500)); } } diff --git a/kernel/kernel.c b/kernel/kernel.c index 8492425..84aac28 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -32,7 +32,7 @@ enum { TERMINATED, RUNQ, TIMEQ, WAITQOFFSET }; #define SCHEDULE TIMER1_COMPA_vect #define DISTANCE(from, to) ((int32_t)((to) - (from))) #define EPOCH 0x3FFFFFFFUL /* XXX */ -#define EPS (LATENCY / PRESCALE + 1) /* XXX */ +#define EPS 2 * (LATENCY / PRESCALE + 1) /* XXX */ #define NOW(hi, lo) (((uint32_t)(hi) << 0x10) | (lo)) struct task { @@ -40,14 +40,11 @@ struct task { uint8_t sph; uint32_t release; uint32_t deadline; - uint32_t period; uint8_t state; }; struct kernel { struct task *running; - struct task *idle; - struct task *first; struct task *last; struct task task[TASKS + 1]; uint8_t semaphore[SEMAPHORES]; @@ -76,12 +73,12 @@ ISR(SCHEDULE, ISR_NAKED) nexthit = now + EPOCH; /* update idle task */ - kernel.idle->release = now; - kernel.idle->deadline = nexthit; + kernel.task->release = now; + kernel.task->deadline = nexthit; - rtr = kernel.idle; + rtr = kernel.task; - for (t = kernel.first; t <= kernel.last; t++) { + 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) @@ -137,10 +134,8 @@ init(int idlestack) TIMSK = _BV(OCIE1A); kernel.freemem = (void *)(RAMEND - idlestack); - kernel.idle = &kernel.task[0]; - kernel.first = &kernel.task[1]; - kernel.last = kernel.idle; - kernel.running = kernel.idle; + kernel.last = kernel.task; + kernel.running = kernel.task; kernel.cycles = 0; /* Initialize idle task (task 0) */ @@ -151,7 +146,7 @@ init(int idlestack) } void -task(void (*fun)(void *), uint16_t stack, uint32_t release, uint32_t deadline, void *args) +task(void (*fun)(void *), uint16_t stack, void *args) { struct task *t; uint8_t *sp; @@ -178,10 +173,9 @@ task(void (*fun)(void *), uint16_t stack, uint32_t release, uint32_t deadline, v t = ++kernel.last; - t->release = release; - t->deadline = deadline + release; - t->period = deadline; - t->state = TIMEQ; + t->release = 0; + t->deadline = EPOCH; + t->state = RUNQ; t->spl = LO8(sp); /* store stack pointer */ t->sph = HI8(sp); @@ -221,15 +215,15 @@ signal(uint8_t sema) cli(); - rtr = kernel.idle; + rtr = kernel.task; - for (t = kernel.first; t <= kernel.last; t++) { + for (t = &kernel.task[1]; t <= kernel.last; t++) { if (t->state == WAITQOFFSET + sema && \ DISTANCE(t->deadline, rtr->deadline) > 0) rtr = t; } - if (rtr != kernel.idle) { + if (rtr != kernel.task) { rtr->state = RUNQ; SCHEDULE(); } else @@ -243,7 +237,8 @@ update(uint32_t release, uint32_t deadline) { cli(); - kernel.running->state = TIMEQ; + if (DISTANCE(NOW(kernel.cycles, TCNT1), release) > 0) + kernel.running->state = TIMEQ; kernel.running->release = release; kernel.running->deadline = deadline; @@ -251,34 +246,25 @@ update(uint32_t release, uint32_t deadline) } void -snooze(uint32_t delay) +sleep(uint8_t type, uint32_t delay) { cli(); kernel.running->state = TIMEQ; kernel.running->release += delay; - - while (DISTANCE(kernel.running->deadline, kernel.running->release) > 0) - kernel.running->deadline += kernel.running->period; - - SCHEDULE(); -} - -void -period(uint32_t t) -{ - cli(); - - if (t) - kernel.running->period = t; - - kernel.running->state = TIMEQ; - kernel.running->release = kernel.running->deadline; - kernel.running->deadline += kernel.running->period; + 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; + } SCHEDULE(); } - + uint32_t deadline(void) { @@ -306,9 +292,3 @@ suspend(void) SCHEDULE(); } - -uint8_t -running(void) -{ - return kernel.running - kernel.idle; -} diff --git a/kernel/kernel.h b/kernel/kernel.h index b32c589..2c412d4 100644 --- a/kernel/kernel.h +++ b/kernel/kernel.h @@ -62,20 +62,19 @@ #define USEC(T) ((uint32_t)(T) * ((F_CPU / 1000000) / PRESCALE)) void init(int idlestack); -void task(void (*fun)(void *), uint16_t stacksize, uint32_t release, uint32_t deadline, void *args); +void task(void (*fun)(void *), uint16_t stack, void *args); void semaphore(uint8_t semnbr, uint8_t initVal); void wait(uint8_t semnbr); void signal(uint8_t semnbr); +void suspend(void); void update(uint32_t release, uint32_t deadline); -void snooze(uint32_t delay); -void period(uint32_t t); -void suspend(void); +enum { SOFT, HARD }; +void sleep(uint8_t, uint32_t); uint32_t now(void); uint32_t release(void); uint32_t deadline(void); -uint8_t running(void); #endif diff --git a/kernel/lcd3.c b/kernel/lcd3.c index 89edc94..848dee9 100644 --- a/kernel/lcd3.c +++ b/kernel/lcd3.c @@ -15,9 +15,14 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#define USE_DELAY + #include #include +#ifdef USE_DELAY +#warning "using dalay routines" #include +#endif #include "kernel.h" #include "tasks.h" @@ -56,10 +61,13 @@ #define CLOCK PD6 #define E PD7 -#define write_cmd(x, delay) do { write_byte((x), 0); snooze(USEC(delay)); } while (0) -#define write_data(x) do { write_byte((x), 1); snooze(USEC(43)); } while (0) -//#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) +#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) @@ -98,6 +106,7 @@ mvputch(uint8_t line, uint8_t row, char ch) write_data(ch); } +#if 0 static char * itoa(int32_t n) { @@ -155,6 +164,7 @@ itohex32(uint32_t x) return s; } +#endif void lcd(void *arg) @@ -164,7 +174,7 @@ lcd(void *arg) PORTDIR |= (_BV(DATA) | _BV(CLOCK) | _BV(E)); /* task init: wait >40ms */ - snooze(MSEC(40)); + update(MSEC(40), MSEC(500)); /* 8 bit, 2 line, 5x8 font */ write_cmd(FUNCTION_SET | DATA_LENGTH_8BIT | TWO_LINES, 39); @@ -181,9 +191,12 @@ lcd(void *arg) home(); + *a->first = '\0'; + *a->second = '\0'; + for (;;) { - mvputs(0, 0, itoa(a->adc[0])); - mvputs(1, 0, itoa(a->adc[1])); - period(MSEC(50)); + mvputs(0, 0, a->first); + mvputs(1, 0, a->second); + sleep(SOFT, MSEC(40)); /* 25 Hz */ } } diff --git a/kernel/rgb.c b/kernel/rgb.c index 794d266..c149eb1 100644 --- a/kernel/rgb.c +++ b/kernel/rgb.c @@ -152,8 +152,10 @@ rgb(void *arg) uint16_t i = 0; uint8_t v; + update(0, MSEC(370)); + for (;;) { -#if 0 +#if 1 i = (i + 1) % 360; #if 0 v = i % 120; @@ -163,8 +165,8 @@ rgb(void *arg) #endif hsv(a->r, a->g, a->b, i, 255, v); - period(MSEC(83)); -#endif + sleep(SOFT, MSEC(83)); +#else i = (i + 1) % 162; if (i > 80) v = 161 - i; @@ -173,7 +175,9 @@ rgb(void *arg) *a->r = pgm_read_byte(&bb[v].r); *a->g = pgm_read_byte(&bb[v].g); *a->b = pgm_read_byte(&bb[v].b); - period(MSEC(370)); + + sleep(SOFT, MSEC(370)); +#endif } } @@ -182,27 +186,26 @@ pwm(void *arg) { struct pwmarg *a = (struct pwmarg *)arg; uint16_t on, off, maxval;; - uint32_t d = deadline(); - uint32_t r = release(); + uint32_t n = now(); DDRB |= _BV(a->pin); PORTB &= ~_BV(a->pin); maxval = pgm_read_word(&factor[255]); + update(n, n + USEC(maxval)); + for (;;) { on = pgm_read_word(&factor[*a->value]); off = maxval - on; if (*a->value > 0) { PORTB |= _BV(a->pin); - r = d += USEC(on); - update(r, d); + sleep(HARD, USEC(on)); } if (*a->value < 255) { PORTB &= ~_BV(a->pin); - r = d += USEC(off); - update(r, d); + sleep(HARD, USEC(off)); } } } diff --git a/kernel/tasks.h b/kernel/tasks.h index 020bb08..831c31c 100644 --- a/kernel/tasks.h +++ b/kernel/tasks.h @@ -57,15 +57,24 @@ struct adcarg { }; struct lcdarg { - char *first; - char *second; - uint16_t *adc; + char first[17]; + char second[17]; + 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); @@ -77,5 +86,7 @@ void lcd(void *); void adc(void *); void ppm(void *); void cmd(void *); +void clock(void *); +void ctrl(void *); #endif -- cgit v1.2.3