aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2011-07-12 00:54:33 +0000
committerDimitri Sokolyuk <demon@dim13.org>2011-07-12 00:54:33 +0000
commitb4a9b392c57ca8b3f740dd3035b1f43b4ad583b4 (patch)
treeeeda7f987ad9abf16a5954ce250dc51cf0b1ac41
parent42a1324ba256967ca11fa1a81ef3d2ac3d10c491 (diff)
add clock, redesign timer, tweak stack values
-rw-r--r--kernel/Makefile2
-rw-r--r--kernel/clock.c50
-rw-r--r--kernel/cmd.c5
-rw-r--r--kernel/ctrl.c40
-rw-r--r--kernel/dmx.c34
-rw-r--r--kernel/dmx/Makefile8
-rw-r--r--kernel/heartbeat.c18
-rw-r--r--kernel/kernel.c74
-rw-r--r--kernel/kernel.h9
-rw-r--r--kernel/lcd3.c29
-rw-r--r--kernel/rgb.c23
-rw-r--r--kernel/tasks.h17
12 files changed, 209 insertions, 100 deletions
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 <bsd.subdir.mk>
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 <demon@dim13.org>
+ *
+ * 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 <inttypes.h>
+#include <avr/io.h>
+#include <stdlib.h>
+#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 <demon@dim13.org>
+ *
+ * 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 <inttypes.h>
+#include <avr/io.h>
+#include <stdio.h>
+#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 <bsd.prog.mk>
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 <inttypes.h>
#include <avr/io.h>
+#ifdef USE_DELAY
+#warning "using dalay routines"
#include <util/delay.h>
+#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