aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2012-01-02 10:03:37 +0000
committerDimitri Sokolyuk <demon@dim13.org>2012-01-02 10:03:37 +0000
commit775ca7a6b283339019783af24c4c424cdb0cebd1 (patch)
tree8ccbd8d995db3c3774eab3e0d19250c71db7cca9
parent4d04ef80160fe748e746549b022854d88e55e188 (diff)
time sharing
-rw-r--r--kernel/Makefile.inc7
-rw-r--r--kernel/adc.c16
-rw-r--r--kernel/clock.c31
-rw-r--r--kernel/dmx.c61
-rw-r--r--kernel/dmx/Makefile12
-rw-r--r--kernel/heartbeat.c1
-rw-r--r--kernel/kernel.c189
-rw-r--r--kernel/kernel.h23
-rw-r--r--kernel/lcd3.c113
-rw-r--r--kernel/ppm.c1
-rw-r--r--kernel/rgb.c22
-rw-r--r--kernel/tasks.h18
-rw-r--r--kernel/uart.c109
13 files changed, 285 insertions, 318 deletions
diff --git a/kernel/Makefile.inc b/kernel/Makefile.inc
index 1ecf7e2..ca57693 100644
--- a/kernel/Makefile.inc
+++ b/kernel/Makefile.inc
@@ -9,9 +9,10 @@ OBJCOPY= avr-objcopy
OBJDUMP= avr-objdump
SIZE= avr-size
-CFLAGS= -Wall -Os -mmcu=${MCU} \
- -DF_CPU=${F_CPU} -DPRESCALE=${PRESCALE} -DBAUD=${BAUD} \
- -DSTACK=${STACK} -DTASKS=${TASKS} -DSEMAPHORES=${SEMAPHORES}
+CFLAGS= -mmcu=${MCU} -Wall -Os \
+ -DF_CPU=${F_CPU} -DPRESCALE=${PRESCALE} \
+ -DBAUD=${BAUD} -DSTACK=${STACK} -DTASKS=${TASKS} \
+ -DSEMAPHORES=${SEMAPHORES} -DPRIORITIES=${PRIORITIES}
LDFLAGS= -mmcu=${MCU} -Wl,-Map,${PROG}.map
.SUFFIXES: .lst .hex .bin .srec .ehex .ebin .esrec
diff --git a/kernel/adc.c b/kernel/adc.c
index 5c7a35b..76c9c0d 100644
--- a/kernel/adc.c
+++ b/kernel/adc.c
@@ -16,13 +16,14 @@
*/
#include <stdint.h>
+#include <stdio.h>
#include <avr/io.h>
#include <avr/interrupt.h>
+#include <avr/cpufunc.h>
#include "kernel.h"
#include "tasks.h"
#define MUXMASK 0x07
-#define DL MSEC(20)
void
adc(void *arg)
@@ -33,14 +34,17 @@ adc(void *arg)
ADCSRA |= (_BV(ADEN) | ADC_FLAGS);
for (;;) {
- if (bit_is_clear(ADCSRA, ADSC)) {
+ for (i = 0; i < ADCCHANNELS; i++) {
+ ADMUX = i & MUXMASK;
+ ADCSRA |= _BV(ADSC);
+ loop_until_bit_is_clear(ADCSRA, ADSC);
//cli();
a->value[i] = ADCW;
//sei();
- i = (i + 1) % ADCCHANNELS;
- ADMUX = i;
- ADCSRA |= _BV(ADSC);
}
- sleep(MSEC(500 / ADCCHANNELS));
+ wait(0);
+ fprintf(stderr, "\n%8lx%8x", now(), a->value[0]);
+ signal(0);
+ sleep(MSEC(100));
}
}
diff --git a/kernel/clock.c b/kernel/clock.c
index 4515d55..b96ac74 100644
--- a/kernel/clock.c
+++ b/kernel/clock.c
@@ -16,6 +16,7 @@
*/
#include <stdint.h>
+#include <stdio.h>
#include <avr/io.h>
#include <stdio.h>
#include <stdlib.h>
@@ -25,29 +26,21 @@
void
clock(void *arg)
{
- struct clockarg *a = arg;
- uint8_t d, h, m, s;
+ uint8_t d, h, m, s, ds;
- d = h = m = s = 0;
+ d = h = m = s = ds = 0;
for (;;) {
- s += 1;
- if (s == 60) {
- s = 0;
- m += 1;
- }
- if (m == 60) {
- m = 0;
- h += 1;
- }
- if (h == 24) {
- h = 0;
- d += 1;
- }
+ ++ds;
+ if (ds == 10) { ds = 0; ++s; }
+ if (s == 60) { s = 0; ++m; }
+ if (m == 60) { m = 0; ++h; }
+ if (h == 24) { h = 0; ++d; }
- sprintf(a->lcd->first, "%8lx%8x", now(), a->adc->value[0]);
- sprintf(a->lcd->second, "%4d:%.2d:%.2d:%.2d", d, h, m, s);
+ wait(0);
+ fprintf(stderr, "\r%4d:%.2d:%.2d:%.2d.%1d ", d, h, m, s, ds);
+ signal(0);
- sleep(SEC(1));
+ sleep(SEC1(1));
}
}
diff --git a/kernel/dmx.c b/kernel/dmx.c
index d2827e7..49ff3fd 100644
--- a/kernel/dmx.c
+++ b/kernel/dmx.c
@@ -16,65 +16,46 @@
*/
#include <stdint.h>
+#include <stdio.h>
#include <string.h>
#include <avr/io.h>
#include <avr/cpufunc.h>
+#include <avr/sleep.h>
#include "kernel.h"
#include "tasks.h"
-struct adcarg adcarg;
+enum { RT, High, Low };
+struct adcarg adcarg;
struct ppmarg ppmarg = { adcarg.value };
-
-struct lcdarg lcdarg;
-
-struct clockarg clockarg = { &lcdarg, &adcarg };
-
struct rgbarg rgbargs = { 0, 0, 0, &adcarg.value[0] };
-
struct pwmarg pwmargs[] = {
- { &rgbargs.r, PB2 },
- { &rgbargs.g, PB3 },
- { &rgbargs.b, PB4 }
+ { &rgbargs.r, PB2, 1 },
+ { &rgbargs.g, PB3, 2 },
+ { &rgbargs.b, PB4, 3 }
};
int
main()
{
- init(STACK - 6); /* 42 */
- init_uart();
-
-#define LOW 0
-#define MID 0
-#define HIGH 0
-
-#if 1
- exec(heartbeat, NULL, STACK - 10, LOW); /* 38 */
-#endif
-
-#if 1
- exec(rgb, &rgbargs, STACK + 24, MID); /* 72 */
- exec(pwm, &pwmargs[0], STACK, HIGH); /* 48 */
- exec(pwm, &pwmargs[1], STACK, HIGH); /* 48 */
- exec(pwm, &pwmargs[2], STACK, HIGH); /* 48 */
- exec(adc, &adcarg, STACK - 6, LOW); /* 42 */
-#endif
-
-#if 1
- exec(lcd, &lcdarg, STACK, LOW); /* 48 */
- exec(clock, &clockarg, STACK + 24, LOW); /* 72 */
-#endif
-
-#if 0
- exec(cmd, &rgbargs, STACK, LOW); /* 48 */
-#endif
-
+ uart_init();
+ lcd_init();
+ init(48);
+
+ exec(heartbeat, NULL, 48, Low);
+ exec(rgb, &rgbargs, 72, High);
+ exec(pwm, &pwmargs[0], 56, RT);
+ exec(pwm, &pwmargs[1], 56, RT);
+ exec(pwm, &pwmargs[2], 56, RT);
+ exec(adc, &adcarg, 96, Low);
+ exec(clock, NULL, 96, Low);
#if 0
- exec(ppm, &ppmarg, STACK, LOW); /* 48 */
+ exec(cmd, &rgbargs, 48);
+ exec(ppm, &ppmarg, 48);
#endif
for (;;)
- _NOP();
+ sleep_mode();
return 0;
}
diff --git a/kernel/dmx/Makefile b/kernel/dmx/Makefile
index 654dee9..f65a6b7 100644
--- a/kernel/dmx/Makefile
+++ b/kernel/dmx/Makefile
@@ -3,14 +3,16 @@
MCU= atmega8
F_CPU= 16000000
#F_CPU= 14745600
-#PRESCALE= 1 # res 62.5nsec cycle 4msec
-PRESCALE= 8 # res 0.5usec cycle 32.7msec
+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= 9 # +1 idle
-SEMAPHORES= 4
+#STACK= 48
+STACK= 80
+TASKS= 11 # +1 idle
+SEMAPHORES= 6
+PRIORITIES= 4
BAUD= 9600
PROG= dmx
diff --git a/kernel/heartbeat.c b/kernel/heartbeat.c
index 7540ddc..fb5947a 100644
--- a/kernel/heartbeat.c
+++ b/kernel/heartbeat.c
@@ -16,6 +16,7 @@
*/
#include <stdint.h>
+#include <stdio.h>
#include <avr/io.h>
#include "kernel.h"
#include "tasks.h"
diff --git a/kernel/kernel.c b/kernel/kernel.c
index dc29f57..7d2d6c2 100644
--- a/kernel/kernel.c
+++ b/kernel/kernel.c
@@ -27,10 +27,9 @@
#include "stack.h"
#include "queue.h"
-#define DEBUG 1
-#define NPRIO 2
+#define DEBUG 0
-enum State { TERMINATED, RTR, RUNQ, SLEEPING, WAITING };
+enum State { TERMINATED, RUNQ, TIMEQ, WAITQ, SIGNAL };
#define LO8(x) ((uint8_t)((uint16_t)(x)))
#define HI8(x) ((uint8_t)((uint16_t)(x) >> 8))
@@ -44,14 +43,15 @@ struct task {
uint16_t sp; /* stack pointer */
uint8_t state;
uint8_t prio;
- SIMPLEQ_ENTRY(task) link;
+ uint8_t sema;
+ TAILQ_ENTRY(task) link;
};
struct kernel {
- SIMPLEQ_HEAD(, task) runq[NPRIO];
- struct task *last; /* last allocated task */
+ TAILQ_HEAD(queue, task) runq[PRIORITIES], timeq, waitq[SEMAPHORES];
+ struct task task[1 + TASKS];
+ struct task *nextfree;
struct task *current;
- struct task task[TASKS + 1];
uint16_t cycles;
uint8_t *freemem;
uint8_t semaphore[SEMAPHORES];
@@ -64,62 +64,90 @@ ISR(TIMER1_OVF_vect)
ISR(TIMER1_COMPA_vect, ISR_NAKED)
{
- struct task *tp;
+ struct task *tp, *tmp;
int32_t dist;
uint32_t now;
uint16_t nexthit;
uint8_t prio;
- /* save context */
PUSH_ALL();
-
now = NOW(kernel.cycles, TCNT1);
#if DEBUG
PORTB ^= _BV(PB1); /* DEBUG */
#endif
- /* save stack pointer and drop task from run-queue */
kernel.current->sp = SP;
- if (kernel.current->state == RUNQ)
- kernel.current->state = RTR;
- SIMPLEQ_REMOVE_HEAD(&kernel.runq[kernel.current->prio], link);
+ TAILQ_REMOVE(&kernel.runq[kernel.current->prio], kernel.current, link);
nexthit = 0xffff;
- prio = 0;
-
- /* walk through tasks and assemble run-queue */
- for (tp = &kernel.task[1]; tp <= kernel.last; tp++) {
- if (tp->state == SLEEPING) {
- dist = DISTANCE(now, tp->release);
- if (dist <= 0)
- tp->state = RTR;
- else if (dist < nexthit)
- nexthit = dist;
- }
- if (tp->state == RTR) {
- /* find highest priority */
- if (tp->prio > prio)
- prio = tp->prio;
- /* put task on queue */
- SIMPLEQ_INSERT_TAIL(&kernel.runq[tp->prio], tp, link);
+
+ /* release waiting tasks */
+ TAILQ_FOREACH_SAFE(tp, &kernel.timeq, link, tmp) {
+ dist = DISTANCE(now, tp->release);
+ if (dist <= 0) {
tp->state = RUNQ;
- }
+ TAILQ_REMOVE(&kernel.timeq, tp, link);
+ TAILQ_INSERT_TAIL(&kernel.runq[tp->prio], tp, link);
+ } else if (dist < nexthit)
+ nexthit = dist;
+ else
+ break;
}
- /* idle if all queues empty */
- if (prio == 0 && SIMPLEQ_EMPTY(&kernel.runq[prio])) {
- SIMPLEQ_INSERT_TAIL(&kernel.runq[prio], kernel.task, link);
- kernel.task->state = RUNQ;
+again:
+ switch (kernel.current->state) {
+ case RUNQ:
+ TAILQ_INSERT_TAIL(&kernel.runq[kernel.current->prio], kernel.current, link);
+ break;
+ case TIMEQ:
+ TAILQ_FOREACH(tp, &kernel.timeq, link)
+ if (DISTANCE(kernel.current->release, tp->release) > 0)
+ break;
+
+ if (tp)
+ TAILQ_INSERT_BEFORE(tp, kernel.current, link);
+ else
+ TAILQ_INSERT_TAIL(&kernel.timeq, kernel.current, link);
+ break;
+ case WAITQ:
+ if (kernel.semaphore[kernel.current->sema] == 0) {
+ /* occupy semaphore */
+ kernel.semaphore[kernel.current->sema] = 1;
+ kernel.current->state = RUNQ;
+ goto again; /* put current task back on runq */
+ } else
+ TAILQ_INSERT_TAIL(&kernel.waitq[kernel.current->sema], kernel.current, link);
+ break;
+ case SIGNAL:
+ tp = TAILQ_FIRST(&kernel.waitq[kernel.current->sema]);
+ if (tp) {
+ tp->state = RUNQ;
+ TAILQ_REMOVE(&kernel.waitq[kernel.current->sema], tp, link);
+ TAILQ_INSERT_TAIL(&kernel.runq[tp->prio], tp, link);
+ /* occupy semaphore */
+ kernel.semaphore[kernel.current->sema] = 1;
+ } else
+ kernel.semaphore[kernel.current->sema] = 0;
+
+ kernel.current->state = RUNQ;
+ goto again; /* put current task back on runq */
+ default:
+ break;
}
- /* pick highest priority and restore stack pointer */
- kernel.current = SIMPLEQ_FIRST(&kernel.runq[prio]);
+ for (prio = 0; prio < PRIORITIES - 1; prio++)
+ if (!TAILQ_EMPTY(&kernel.runq[prio]))
+ break;
+
+ if (TAILQ_EMPTY(&kernel.runq[prio]))
+ TAILQ_INSERT_TAIL(&kernel.runq[prio], &kernel.task[0], link);
+
+ kernel.current = TAILQ_FIRST(&kernel.runq[prio]);
SP = kernel.current->sp;
OCR1A = (uint16_t)(now + nexthit);
- /* restore context */
POP_ALL();
reti();
}
@@ -127,7 +155,7 @@ ISR(TIMER1_COMPA_vect, ISR_NAKED)
void
init(uint8_t stack)
{
- uint8_t prio;
+ uint8_t i;
cli();
@@ -142,19 +170,22 @@ init(uint8_t stack)
DDRB |= _BV(PB1); /* DEBUG */
#endif
- for (prio = 0; prio < NPRIO; prio++)
- SIMPLEQ_INIT(&kernel.runq[prio]);
+ memset(&kernel, 0, sizeof(kernel));
- kernel.cycles = 0;
- kernel.freemem = (void *)(RAMEND - stack);
- kernel.task->release = 0;
- kernel.task->prio = 0;
- kernel.task->state = RUNQ;
- SIMPLEQ_INSERT_TAIL(&kernel.runq[0], kernel.task, link);
+ for (i = 0; i < PRIORITIES; i++)
+ TAILQ_INIT(&kernel.runq[i]);
+ TAILQ_INIT(&kernel.timeq);
+ for (i = 0; i < SEMAPHORES; i++)
+ TAILQ_INIT(&kernel.waitq[i]);
- kernel.last = kernel.task;
- kernel.current = kernel.task;
+ kernel.nextfree = &kernel.task[1];
+ kernel.freemem = (void *)(RAMEND - stack);
+ kernel.current = &kernel.task[0];
+ kernel.current->state = TERMINATED;
+ kernel.current->prio = PRIORITIES - 1;
+ kernel.current->release = 0;
+ TAILQ_INSERT_TAIL(&kernel.runq[PRIORITIES - 1], &kernel.task[0], link);
sei();
}
@@ -183,70 +214,37 @@ exec(void (*fun)(void *), void *args, uint8_t stack, uint8_t prio)
sp -= 6;
memset(sp, 0, 6); /* r26-r31 */
- t = ++kernel.last;
-
- t->release = 0;
-
- if (prio >= NPRIO)
- prio = NPRIO - 1;
+ t = kernel.nextfree++;
+ t->release = NOW(kernel.cycles, TCNT1);
t->prio = prio;
-
- t->state = RTR;
-
+ t->sema = 0;
t->sp = (uint16_t)sp; /* SP */
+ t->state = TIMEQ;
+ TAILQ_INSERT_TAIL(&kernel.timeq, t, link);
SCHEDULE();
}
-#if 0
-void
-semaphore(uint8_t sema, uint8_t val)
-{
- cli();
-
- kernel.semaphore[sema] = val;
-
- sei();
-}
-
void
wait(uint8_t sema)
{
cli();
- if (kernel.semaphore[sema] == 0) {
- kernel.running->state = WAITQ + sema;
- SCHEDULE();
- } else {
- --kernel.semaphore[sema];
- sei();
- }
+ kernel.current->sema = sema;
+ kernel.current->state = WAITQ;
+
+ SCHEDULE();
}
void
signal(uint8_t sema)
{
- struct task *t, *rtr;
-
cli();
- rtr = kernel.task;
-
- for (t = &kernel.task[1]; t <= kernel.last; t++) {
- if (t->state == WAITQ + sema)
- if (DISTANCE(t->deadline, rtr->deadline) > 0)
- rtr = t;
- }
+ kernel.current->state = SIGNAL;
- if (rtr != kernel.task) {
- rtr->state = RUNQ;
- SCHEDULE();
- } else {
- ++kernel.semaphore[sema];
- sei();
- }
+ SCHEDULE();
}
-#endif
void
sleep(uint32_t ticks)
@@ -254,7 +252,7 @@ sleep(uint32_t ticks)
cli();
kernel.current->release += ticks;
- kernel.current->state = SLEEPING;
+ kernel.current->state = TIMEQ;
SCHEDULE();
}
@@ -271,6 +269,7 @@ suspend(void)
cli();
kernel.current->state = TERMINATED;
+
SCHEDULE();
}
diff --git a/kernel/kernel.h b/kernel/kernel.h
index bf64b39..172fad7 100644
--- a/kernel/kernel.h
+++ b/kernel/kernel.h
@@ -19,27 +19,32 @@
#define __KERNEL_H
#ifndef TASKS
-#warning TASKS not set, fallback to default
+#warning TASKS not set, fallback to default: 8
#define TASKS 8
#endif
+#ifndef PRIORITIES
+#warning PRIORITIES not set, fallback to default: 2
+#define PRIORITIES 2
+#endif
+
#ifndef SEMAPHORES
-#warning SEMAPHORES not set, fallback to default
-#define SEMAPHORES 8
+#warning SEMAPHORES not set, fallback to default: 4
+#define SEMAPHORES 4
#endif
#ifndef STACK
-#warning STACK not set, fallback to default
+#warning STACK not set, fallback to default: 64
#define STACK 64
#endif
#ifndef F_CPU
-#warning F_CPU not set, fallback to default
+#warning F_CPU not set, fallback to default: 16MHz
#define F_CPU 16000000
#endif
#ifndef PRESCALE
-#warning PRESCALE not set, fallback to default
+#warning PRESCALE not set, fallback to default: 1
#define PRESCALE 1
#endif
@@ -93,10 +98,10 @@
void init(uint8_t stack);
void exec(void (*fun)(void *), void *args, uint8_t stack, uint8_t prio);
-void semaphore(uint8_t semnbr, uint8_t initVal);
-void wait(uint8_t semnbr);
-void signal(uint8_t semnbr);
+void wait(uint8_t sema);
+void signal(uint8_t sema);
+
void suspend(void);
void sleep(uint32_t ticks);
diff --git a/kernel/lcd3.c b/kernel/lcd3.c
index e12a408..6bbb847 100644
--- a/kernel/lcd3.c
+++ b/kernel/lcd3.c
@@ -18,12 +18,15 @@
#define USE_DELAY
#include <stdint.h>
+#include <stdio.h>
#include <avr/io.h>
#include <avr/cpufunc.h>
#include <util/delay.h>
#include "kernel.h"
#include "tasks.h"
+FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, NULL, _FDEV_SETUP_WRITE);
+
#define CLEAR_DISPLAY _BV(0)
#define RETURN_HOME _BV(1)
@@ -47,7 +50,6 @@
#define TWO_LINES _BV(3) /* on 2 / off 1 line */
#define BIG_FONT _BV(2) /* on 5x10 / off 5x7 */
-
#define SET_CGRAM_ADDRESS _BV(6)
#define SET_DDRAM_ADDRESS _BV(7)
#define BUSY_FLAG _BV(7)
@@ -59,47 +61,15 @@
#define CLOCK PD6
#define E PD7
-#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)
-
-#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)
-
-
-/* recomended cycle 1us: 450ns on, 450ns off.
- * this is beyond our resolution */
-#define wait_short() do { \
- _NOP(); \
-} while (0)
-
-#define strobe(port, bit) do { \
- port |= _BV(bit); \
- wait_short(); \
- port &= ~_BV(bit); \
-} while (0)
-
-#define setif(cond, port, bit) do { \
- if (cond) \
- port |= _BV(bit); \
- else \
- port &= ~_BV(bit); \
-} while (0)
+/* recomended cycle: 450ns on, 450ns off. this is beyond our resolution */
+#define strobe(port, bit) do { port |= _BV(bit); _NOP(); port &= ~_BV(bit); } while (0)
+#define setif(cond, port, bit) do { if (cond) (port) |= _BV(bit); else (port) &= ~_BV(bit); } while (0)
+#define write_data(x) do { write_byte((x), 1); _delay_us(43); } while (0)
+#define _write_cmd(x, delay) do { write_byte((x), 0); _delay_us(delay); } while (0)
+#define write_cmd(x) _write_cmd((x), 39)
+#define move(line, row) _write_cmd(SET_DDRAM_ADDRESS | ((line) << 6) | (row), 39)
+#define clear() _write_cmd(CLEAR_DISPLAY, 1530)
+#define home() _write_cmd(RETURN_HOME, 1530)
static void
write_byte(uint8_t byte, uint8_t rs)
@@ -107,59 +77,60 @@ write_byte(uint8_t byte, uint8_t rs)
uint8_t i;
for (i = 0; i < 8; i++) {
- setif(byte & (0x80 >> i), PORT, DATA); /* MSF */
+ setif(byte & (0x80 >> i), PORT, DATA); /* MSF */
strobe(PORT, CLOCK);
}
+
setif(rs, PORT, DATA);
strobe(PORT, E);
}
-static void
-mvputs(uint8_t line, uint8_t row, char *s)
-{
- move(line, row);
- while (*s)
- write_data(*(s++));
-}
-
-static void
-mvputch(uint8_t line, uint8_t row, char ch)
-{
- move(line, row);
- write_data(ch);
-}
-
void
-lcd(void *arg)
+lcd_init(void)
{
- struct lcdarg *a = (struct lcdarg *)arg;
-
PORTDIR |= (_BV(DATA) | _BV(CLOCK) | _BV(E));
/* task init: wait >40ms */
- sleep(MSEC(40));
+ _delay_ms(40);
/* 8 bit, 2 line, 5x8 font */
- write_cmd(FUNCTION_SET | DATA_LENGTH_8BIT | TWO_LINES, 39);
+ write_cmd(FUNCTION_SET | DATA_LENGTH_8BIT | TWO_LINES);
/* no BUSY_FLAG until now */
/* display on, cursor off, cursor blink off */
- write_cmd(ON_OFF_CONTROL | DISPLAY_ON, 39);
+ write_cmd(ON_OFF_CONTROL | DISPLAY_ON);
/* clear display */
clear();
/* entry mode */
- write_cmd(ENTRY_MODE_SET | INC_DDRAM, 39);
+ write_cmd(ENTRY_MODE_SET | INC_DDRAM);
home();
- *a->first = '\0';
- *a->second = '\0';
+ stderr = &lcd_stream;
+}
- for (;;) {
- mvputs(0, 0, a->first);
- mvputs(1, 0, a->second);
- sleep(MSEC(40));
+int
+lcd_putchar(char c, FILE *fd)
+{
+ switch (c) {
+ case '\b': /* XXX */
+ clear();
+ /* FALLTHROUGH */
+ case '\r':
+ home();
+ break;
+ case '\n':
+ move(1, 0);
+ break;
+ case '\t':
+ c = ' ';
+ /* FALLTHROUGH */
+ default:
+ write_data(c);
+ break;
}
+
+ return 0;
}
diff --git a/kernel/ppm.c b/kernel/ppm.c
index 51dc0e5..3d22ac1 100644
--- a/kernel/ppm.c
+++ b/kernel/ppm.c
@@ -16,6 +16,7 @@
*/
#include <stdint.h>
+#include <stdio.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include "kernel.h"
diff --git a/kernel/rgb.c b/kernel/rgb.c
index ae5e119..0cf9a96 100644
--- a/kernel/rgb.c
+++ b/kernel/rgb.c
@@ -16,6 +16,7 @@
*/
#include <stdint.h>
+#include <stdio.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include "kernel.h"
@@ -32,12 +33,21 @@ rgb(void *arg)
for (;;) {
i = (i + 1) % 360;
- hsv(&r, &g, &b, i, v, v);
+ //hsv(&r, &g, &b, i, v, v);
+ hsv(&r, &g, &b, i, 255, 255);
- //cli();
+ wait(1);
a->r = r;
+ signal(1);
+
+ wait(2);
a->g = g;
+ signal(2);
+
+ wait(3);
a->b = b;
+ signal(3);
+
v = *a->v >> 2; /* 10bit to 8bit */
//sei();
@@ -55,17 +65,21 @@ pwm(void *arg)
DDRB |= _BV(a->pin);
PORTB &= ~_BV(a->pin);
+#define DIV (UINT8_MAX >> 1)
+
for (;;) {
//cli();
+ wait(a->sema);
v = *a->value;
+ signal(a->sema);
//sei();
- if ((on = SEC2(v) / INT8_MAX)) {
+ if ((on = SEC2(v) / DIV)) {
PORTB |= _BV(a->pin);
sleep(on);
}
- if ((off = SEC2(UINT8_MAX - v) / INT8_MAX)) {
+ if ((off = SEC2(UINT8_MAX - v) / DIV)) {
PORTB &= ~_BV(a->pin);
sleep(off);
}
diff --git a/kernel/tasks.h b/kernel/tasks.h
index d89a8c3..98b637a 100644
--- a/kernel/tasks.h
+++ b/kernel/tasks.h
@@ -51,20 +51,14 @@ struct rgbarg {
struct pwmarg {
uint8_t *value;
uint8_t pin;
+ uint8_t sema;
};
struct adcarg {
uint16_t value[ADCCHANNELS];
};
-struct lcdarg {
- char first[18];
- char second[18];
- uint8_t x, y;
-};
-
struct clockarg {
- struct lcdarg *lcd;
struct adcarg *adc;
};
@@ -72,14 +66,16 @@ struct ppmarg {
uint16_t *value;
};
-void init_uart(void);
-int uart_getchar(void);
-int uart_putchar(char);
+void uart_init(void);
+int uart_getchar(FILE *);
+int uart_putchar(char, FILE *);
+
+void lcd_init(void);
+int lcd_putchar(char, FILE *);
void heartbeat(void *);
void rgb(void *);
void pwm(void *);
-void lcd(void *);
void adc(void *);
void ppm(void *);
void cmd(void *);
diff --git a/kernel/uart.c b/kernel/uart.c
index e3df551..8407113 100644
--- a/kernel/uart.c
+++ b/kernel/uart.c
@@ -31,69 +31,25 @@
#include "kernel.h"
#include "tasks.h"
-int
-uart_putchar(char c)
-{
- if (c == '\n')
- uart_putchar('\r');
- loop_until_bit_is_set(UCSRA, UDRE);
- UDR = c;
-
- return 0;
-}
-
-int
-uart_getchar(void)
-{
- char c;
-
-#if 0 /* BLOCKING */
- loop_until_bit_is_set(UCSRA, RXC);
-#else
- if (bit_is_clear(UCSRA, RXC))
- return 0;
-#endif
-
- if (bit_is_set(UCSRA, FE))
- return -2; /* EOF */
- if (bit_is_set(UCSRA, DOR))
- return -1; /* ERR */
- c = UDR;
-
- uart_putchar(c); /* ECHO */
-
- switch (c) {
- case '\r':
- c = '\n';
- break;
- case '\t':
- c = ' ';
- break;
- default:
- break;
- }
-
- return c;
-}
+FILE uart_stream = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);
#ifdef USE_RXCIE
ISR(SIG_UART_RECV)
{
- uint8_t c = UDR;
- uint8_t *p = 0;
+ uint8_t c, *p;
- switch (c) {
+ switch ((c = UDR)) {
+ case 'Z': /* zero */
+ for (p = (uint8_t *)RAMSTART; p <= (uint8_t *)RAMEND; p++)
+ *p = 'A';
+ /* FALLTHROUGH */
case 'R': /* reboot */
case '-': /* reboot */
wdt_enable(WDTO_15MS);
break;
case 'D': /* dump */
- while (p <= (uint8_t *)RAMEND)
- uart_putchar(*p++);
- break;
- case 'N': /* zero */
- while (p <= (uint8_t *)RAMEND)
- *p++ = 0xFF;
+ for (p = (uint8_t *)0; p <= (uint8_t *)RAMEND; p++)
+ uart_putchar(*p, NULL);
break;
case 'T':
UCSRB |= _BV(UDRIE);
@@ -105,7 +61,7 @@ ISR(SIG_UART_RECV)
case '\n':
break;
default:
- uart_putchar('?');
+ uart_putchar('?', NULL);
break;
}
}
@@ -119,7 +75,7 @@ ISR(SIG_UART_DATA)
#endif
void
-init_uart(void)
+uart_init(void)
{
UCSRB = _BV(RXEN) | _BV(TXEN);
#ifdef USE_RXCIE
@@ -128,4 +84,47 @@ init_uart(void)
UBRRH = UBRRH_VALUE;
UBRRL = UBRRL_VALUE;
UCSRA &= ~_BV(U2X);
+
+ stdin = &uart_stream;
+ stdout = &uart_stream;
+}
+
+int
+uart_putchar(char c, FILE *fd)
+{
+ if (c == '\n')
+ uart_putchar('\r', fd);
+ loop_until_bit_is_set(UCSRA, UDRE);
+ UDR = c;
+
+ return 0;
+}
+
+int
+uart_getchar(FILE *fd)
+{
+ char c;
+
+ loop_until_bit_is_set(UCSRA, RXC);
+
+ if (bit_is_set(UCSRA, FE))
+ return -2; /* EOF */
+ if (bit_is_set(UCSRA, DOR))
+ return -1; /* ERR */
+
+ c = UDR;
+ uart_putchar(c, fd); /* ECHO */
+
+ switch (c) {
+ case '\r':
+ c = '\n';
+ break;
+ case '\t':
+ c = ' ';
+ break;
+ default:
+ break;
+ }
+
+ return c;
}