12 Commits

18 changed files with 431 additions and 72 deletions

View File

@ -11,7 +11,7 @@ CFLAGS=-Wall -mmcu=$(MCU) -std=gnu99 -I $(TOOLCHAIN_PREFIX)/include -O3 -g0
LDFLAGS=-mmcu=$(MCU) -L $(TOOLCHAIN_PREFIX)/include LDFLAGS=-mmcu=$(MCU) -L $(TOOLCHAIN_PREFIX)/include
$(ARTIFACT).elf: main.o led.o time.o PontCoopScheduler.o displayDriver.o canvas.o displayTest.o $(ARTIFACT).elf: main.o led.o time.o PontCoopScheduler.o displayDriver.o canvas.o displayTest.o displayTest2.o displayTest3.o
$(CC) -o $@ $(LDFLAGS) $^ $(CC) -o $@ $(LDFLAGS) $^
$(OBJDUMP) -D $(ARTIFACT).elf > $(ARTIFACT).txt $(OBJDUMP) -D $(ARTIFACT).elf > $(ARTIFACT).txt
@ -24,7 +24,7 @@ all: $(ARTIFACT).elf
.PHONY: clean .PHONY: clean
clean: clean:
-rm -f *.o *.elf -rm -f *.o $(ARTIFACT).elf $(ARTIFACT).txt
.PHONY: upload .PHONY: upload
upload: $(ARTIFACT).elf upload: $(ARTIFACT).elf

View File

@ -7,6 +7,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <msp430g2553.h>
#include "PontCoopScheduler.h" #include "PontCoopScheduler.h"
@ -15,7 +16,7 @@ tTask tasks[MAX_NUM_OF_TASKS];
void schInit() { void schInit() {
for (uint8_t i = 0; i < MAX_NUM_OF_TASKS; i++) { for (uint16_t i = 0; i < MAX_NUM_OF_TASKS; i++) {
tasks[i].delay = 0; tasks[i].delay = 0;
tasks[i].period = 0; tasks[i].period = 0;
tasks[i].run = 0; tasks[i].run = 0;
@ -25,7 +26,7 @@ void schInit() {
} }
void schAdd(void (*exec)(void *), void *handle, uint32_t delay, uint32_t period) { void schAdd(void (*exec)(void *), void *handle, uint32_t delay, uint32_t period) {
for (uint8_t i = 0; i < MAX_NUM_OF_TASKS; i++) { for (uint16_t i = 0; i < MAX_NUM_OF_TASKS; i++) {
if (tasks[i].exec == NULL) { if (tasks[i].exec == NULL) {
tasks[i].delay = delay; tasks[i].delay = delay;
tasks[i].period = period; tasks[i].period = period;
@ -41,23 +42,34 @@ void schAdd(void (*exec)(void *), void *handle, uint32_t delay, uint32_t period)
} }
} }
/*
void schDel(void (*exec)(void *), void *handle) { void schDel(void (*exec)(void *), void *handle) {
for (uint8_t i = 0; i < MAX_NUM_OF_TASKS; i++) { for (uint16_t i = 0; i < MAX_NUM_OF_TASKS; i++) {
if ((tasks[i].exec == exec) && (tasks[i].handle == handle)) { if ((tasks[i].exec == exec) && (tasks[i].handle == handle)) {
tasks[i].exec = NULL; tasks[i].exec = NULL;
break; break;
} }
} }
} }
*/
void schExec() { void schExec() {
for (uint8_t i = 0; i < MAX_NUM_OF_TASKS; i++) { for (uint16_t i = 0; i < MAX_NUM_OF_TASKS; i++) {
// synchronize access to tasks[].run
__disable_interrupt();
if (tasks[i].exec != NULL && tasks[i].run > 0) { if (tasks[i].exec != NULL && tasks[i].run > 0) {
tasks[i].run--; tasks[i].run--;
// synchronize access to tasks[].run
// reenable interrupts before actually executing task
__enable_interrupt();
tasks[i].exec(tasks[i].handle); tasks[i].exec(tasks[i].handle);
if (tasks[i].period == 0) { if (tasks[i].period == 0) {
tasks[i].exec = NULL; tasks[i].exec = NULL;
} }
} else {
// synchronize access to tasks[].run
// reenable interrupts in case task is not yet executable
__enable_interrupt();
} }
} }
} }
@ -65,7 +77,7 @@ void schExec() {
void schUpdate() { void schUpdate() {
for (uint8_t i = 0; i < MAX_NUM_OF_TASKS; i++) { for (uint16_t i = 0; i < MAX_NUM_OF_TASKS; i++) {
if (tasks[i].exec != NULL) { if (tasks[i].exec != NULL) {
if (tasks[i].delay == 0) { if (tasks[i].delay == 0) {
tasks[i].delay = tasks[i].period; tasks[i].delay = tasks[i].period;
@ -76,13 +88,3 @@ void schUpdate() {
} }
} }
} }
uint8_t schTaskCnt() {
uint8_t cnt = 0;
for (uint8_t i = 0; i < MAX_NUM_OF_TASKS; i++) {
if (tasks[i].exec != NULL){
cnt++;
}
}
return cnt;
}

View File

@ -13,7 +13,7 @@
#define MAX_NUM_OF_TASKS 4 #define MAX_NUM_OF_TASKS 2
typedef struct { typedef struct {

View File

@ -5,27 +5,51 @@
#include "displayDriver.h" #include "displayDriver.h"
static canvas_t canvas;
static uint8_t canvasStorage[CANVAS_WIDTH * CANVAS_HEIGHT]; static uint8_t canvasStorage[CANVAS_WIDTH * CANVAS_HEIGHT];
const canvas_t canvas = {
.height = CANVAS_HEIGHT,
.width = CANVAS_WIDTH,
.size = CANVAS_WIDTH * CANVAS_HEIGHT,
.canvas = canvasStorage
};
void canvasInit() { void canvasInit() {
canvas.height = CANVAS_HEIGHT; canvasClear();
canvas.width = CANVAS_WIDTH;
canvas.size = CANVAS_HEIGHT * CANVAS_WIDTH;
canvas.canvas = canvasStorage;
// Bit7 signals need to be transfered for octet
memset(canvasStorage, 0x80, canvas.size);
displayDriverTransferCanvas(); displayDriverTransferCanvas();
} }
canvas_t *canvasGet() { void canvasClear() {
return &canvas; memset(canvas.canvas, 0x80, canvas.size);
}
void canvasSetAll(uint8_t color) {
memset(canvas.canvas, color + 0x80, canvas.size);
} }
void canvasShow() { void canvasShow() {
displayDriverTransferCanvas(); displayDriverTransferCanvas();
} }
void canvasSetPixel(uint8_t column, uint8_t row, uint8_t color) {
*((canvas.canvas) + (row * canvas.width + column)) = (color + 0x80);
}
void canvasWipeRow(uint8_t row) {
memmove(((canvas.canvas)+canvas.width), canvas.canvas, canvas.width*row);
for (uint8_t i = 10; i < canvas.width*(row+1); i++) {
*((canvas.canvas)+i) += 0x80;
}
memset(canvas.canvas, 0x80, canvas.width);
}
uint8_t canvasIsRowFilled(uint8_t row) {
uint8_t res = 1;
for (uint8_t column = 0; column < canvas.width; column++) {
if (*((canvas.canvas) + (row * canvas.width + column)) == 0) {
res = 0;
break;
}
}
return res;
}

View File

@ -5,19 +5,23 @@
#define CANVAS_WIDTH 10 #define CANVAS_WIDTH 10
#define CANVAS_HEIGHT 6 #define CANVAS_HEIGHT 11
typedef struct { typedef struct {
uint8_t width; const uint8_t width;
uint8_t height; const uint8_t height;
uint8_t size; const uint8_t size;
uint8_t *canvas; uint8_t * const canvas;
} canvas_t; } canvas_t;
void canvasInit(); void canvasInit();
canvas_t *canvasGet(); void canvasClear();
void canvasSetAll(uint8_t color);
void canvasShow(); void canvasShow();
void canvasSetPixel(uint8_t column, uint8_t row, uint8_t color);
void canvasWipeRow(uint8_t row);
uint8_t canvasIsRowFilled(uint8_t row);
extern const canvas_t canvas;
#endif // _CANVAS_H_ #endif // _CANVAS_H_

View File

@ -18,12 +18,11 @@ void displayDriverTransferCanvas() {
// wait for signal waiting for data // wait for signal waiting for data
while ((P1IN & BIT3) == 0); while ((P1IN & BIT3) == 0);
canvas_t *canvas = canvasGet(); for (uint8_t i = 0; i < canvas.size; i++) {
for (uint8_t i = 0; i < canvas->size; i++) { if ((*((canvas.canvas)+i) & 0x80) != 0) {
if ((*((canvas->canvas)+i) & 0x80) != 0) { *((canvas.canvas)+i) &= ~0x80;
*((canvas->canvas)+i) &= ~0x80;
spiSendOctet(i); spiSendOctet(i);
spiSendOctet(*((canvas->canvas)+i)); spiSendOctet(*((canvas.canvas)+i));
} }
} }
spiSendOctet(0xfe); spiSendOctet(0xfe);
@ -34,7 +33,11 @@ void displayDriverInit() {
UCB0CTL0 = UCMST; UCB0CTL0 = UCMST;
// SPI timing config // SPI timing config
UCB0CTL1 = UCSSEL_3; UCB0CTL1 = UCSSEL_3;
UCB0BR0 = 8; // Faster than 8 ends up in strange communication errors
// between the both MCUs.
// With 8 the transfer of a complete 110 pixel canvas takes
// about 720us.
UCB0BR0 = 8;
UCB0BR1 = 0; UCB0BR1 = 0;
// BIT5: UCB0CLK // BIT5: UCB0CLK

View File

@ -3,27 +3,182 @@
#include "PontCoopScheduler.h" #include "PontCoopScheduler.h"
static canvas_t *canvas; #define MAX_COLOR 0x0d
static uint8_t lastPixel = 0xff;
static uint8_t currentPixel = 0; typedef enum {
e_WIPE_LAST_COLUMN_DOWN,
e_PIXELS_UP,
e_WIPE_LAST_PIXEL_UP,
e_PIXELS_DOWN,
e_WIPE_LAST_PIXEL_DOWN,
e_ROWS_UP,
e_WIPE_LAST_ROW_UP,
e_ROWS_DOWN,
e_WIPE_LAST_ROW_DOWN,
e_COLUMNS_UP,
e_WIPE_LAST_COLUMN_UP,
e_COLUMNS_DOWN
} t_State;
void displayTestExec(void *args) { void displayTestExec(void *args) {
if (lastPixel != 0xff) { static int16_t last = 0xff;
*((canvas->canvas)+lastPixel) = 0x80; static int16_t current = 0;
static uint8_t color = 0x01;
static t_State state = e_PIXELS_UP;
switch (state) {
// wipe last column
case e_WIPE_LAST_COLUMN_DOWN:
for (uint16_t i = 0; i < canvas.height; i++) {
canvasSetPixel(last, i, 0);
}
last = 0xff;
state = e_PIXELS_UP;
// pixels up
case e_PIXELS_UP:
if (last != 0xff) {
*((canvas.canvas)+last) = 0x80;
}
last = current;
*((canvas.canvas)+current) = (color + 0x80);
current++;
if (current >= canvas.size) {
current = 0;
state = e_WIPE_LAST_PIXEL_UP;
}
break;
// wipe last pixel
case e_WIPE_LAST_PIXEL_UP:
*((canvas.canvas)+last) = 0x80;
last = 0xff;
current = canvas.size - 1;
state = e_PIXELS_DOWN;
// pixels down
case e_PIXELS_DOWN:
if (last != 0xff) {
*((canvas.canvas)+last) = 0x80;
}
last = current;
*((canvas.canvas)+current) = (color + 0x80);
current--;
if (current < 0) {
current = 0;
state = e_WIPE_LAST_PIXEL_DOWN;
}
break;
// wipe last pixel
case e_WIPE_LAST_PIXEL_DOWN:
*((canvas.canvas)+last) = 0x80;
last = 0xff;
state = e_ROWS_UP;
// rows up
case e_ROWS_UP:
if (last != 0xff) {
for (uint16_t i = 0; i < canvas.width; i++) {
canvasSetPixel(i, last, 0);
}
}
last = current;
for (uint16_t i = 0; i < canvas.width; i++) {
canvasSetPixel(i, current, color);
}
current++;
if (current >= canvas.height) {
current = 0;
state = e_WIPE_LAST_ROW_UP;
}
break;
// wipe last row
case e_WIPE_LAST_ROW_UP:
for (uint16_t i = 0; i < canvas.width; i++) {
canvasSetPixel(i, last, 0);
}
last = 0xff;
current = canvas.height - 1;
state = e_ROWS_DOWN;
// rows down
case e_ROWS_DOWN:
if (last != 0xff) {
for (uint16_t i = 0; i < canvas.width; i++) {
canvasSetPixel(i, last, 0);
}
}
last = current;
for (uint16_t i = 0; i < canvas.width; i++) {
canvasSetPixel(i, current, color);
}
current--;
if (current < 0) {
current = 0;
state = e_WIPE_LAST_ROW_DOWN;
}
break;
// wipe last row
case e_WIPE_LAST_ROW_DOWN:
for (uint16_t i = 0; i < canvas.width; i++) {
canvasSetPixel(i, last, 0);
}
last = 0xff;
state = e_COLUMNS_UP;
// columns up
case e_COLUMNS_UP:
if (last != 0xff) {
for (uint16_t i = 0; i < canvas.height; i++) {
canvasSetPixel(last, i, 0);
}
}
last = current;
for (uint16_t i = 0; i < canvas.height; i++) {
canvasSetPixel(current, i, color);
}
current++;
if (current >= canvas.width) {
current = 0;
state = e_WIPE_LAST_COLUMN_UP;
}
break;
// wipe last column
case e_WIPE_LAST_COLUMN_UP:
for (uint16_t i = 0; i < canvas.height; i++) {
canvasSetPixel(last, i, 0);
}
last = 0xff;
current = canvas.width - 1;
state = e_COLUMNS_DOWN;
// columns down
case e_COLUMNS_DOWN:
if (last != 0xff) {
for (uint16_t i = 0; i < canvas.height; i++) {
canvasSetPixel(last, i, 0);
}
}
last = current;
for (uint16_t i = 0; i < canvas.height; i++) {
canvasSetPixel(current, i, color);
}
current--;
if (current < 0) {
current = 0;
state = e_WIPE_LAST_COLUMN_DOWN;
}
break;
} }
lastPixel = currentPixel; color++;
*((canvas->canvas)+currentPixel) = 0x81; if (color > MAX_COLOR) {
currentPixel++; color = 1;
if (currentPixel >= canvas->size) {
currentPixel = 0;
} }
canvasShow(); canvasShow();
} }
void displayTestInit() { void displayTestInit() {
canvas = canvasGet();
schAdd(displayTestExec, NULL, 0, 50); schAdd(displayTestExec, NULL, 0, 50);
} }

75
displayTest2.c Normal file
View File

@ -0,0 +1,75 @@
#include <stdlib.h>
#include <string.h>
#include "canvas.h"
#include "PontCoopScheduler.h"
#include "displayTest2.h"
typedef enum { e_idle, e_start, e_fillArea, e_placeObject, e_wipeLines_7, e_wipeLines_8, e_wipeLines_9, e_wipeLines_10 } t_state;
void displayTest2Exec(void *args) {
static t_state state = e_start;
switch (state) {
case e_idle:
break;
case e_start:
state = e_fillArea;
break;
case e_fillArea:
memset((canvas.canvas)+(canvas.width*7), 0x81, canvas.width);
memset((canvas.canvas)+(canvas.width*8), 0x8d, canvas.width);
memset((canvas.canvas)+(canvas.width*9), 0x82, canvas.width);
memset((canvas.canvas)+(canvas.width*10), 0x88, canvas.width);
for (uint8_t i = 0; i < canvas.width; i++) {
if (i != 4 && i != 5) {
canvasSetPixel(i, 6, 0x05);
}
}
state = e_placeObject;
break;
case e_placeObject:
canvasSetPixel(4, 0, 0x04);
canvasSetPixel(5, 0, 0x04);
canvasSetPixel(6, 0, 0x04);
canvasSetPixel(5, 1, 0x04);
state = e_wipeLines_7;
break;
case e_wipeLines_7:
canvasWipeRow(7);
state = e_wipeLines_8;
break;
case e_wipeLines_8:
canvasWipeRow(8);
state = e_wipeLines_9;
break;
case e_wipeLines_9:
canvasWipeRow(9);
state = e_wipeLines_10;
break;
case e_wipeLines_10:
canvasWipeRow(10);
state = e_idle;
break;
default:
state = e_idle;
break;
}
canvasShow();
}
void displayTest2Init() {
schAdd(displayTest2Exec, NULL, 0, 5000);
}

11
displayTest2.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef _DISPLAY_TEST_2_H_
#define _DISPLAY_TEST_2_H_
void displayTest2Init();
void displayTest2Exec();
#endif // _DISPLAY_TEST_2_H_

78
displayTest3.c Normal file
View File

@ -0,0 +1,78 @@
#include <stdlib.h>
#include <string.h>
#include "canvas.h"
#include "PontCoopScheduler.h"
#include "displayTest3.h"
#include "led.h"
typedef enum { e_idle, e_delay, e_start, e_fillArea, e_placeObject, e_preWipeLines, e_wipeLines } t_state;
void displayTest3Exec(void *args) {
static t_state state = e_start;
static uint8_t wipeLineHelper = 0;
ledBlueToggle();
switch (state) {
case e_idle:
state = e_delay;
break;
case e_delay:
canvasClear();
state = e_start;
break;
case e_start:
state = e_fillArea;
break;
case e_fillArea:
memset((canvas.canvas)+(canvas.width*7), 0x84, canvas.width);
memset((canvas.canvas)+(canvas.width*8), 0x8d, canvas.width);
memset((canvas.canvas)+(canvas.width*9), 0x82, canvas.width);
memset((canvas.canvas)+(canvas.width*10), 0x88, canvas.width);
for (uint8_t i = 0; i < canvas.width; i++) {
if (i != 4 && i != 5) {
canvasSetPixel(i, 6, 0x05);
}
}
state = e_placeObject;
break;
case e_placeObject:
canvasSetPixel(4, 0, 0x04);
canvasSetPixel(5, 0, 0x04);
canvasSetPixel(6, 0, 0x04);
canvasSetPixel(5, 1, 0x04);
state = e_preWipeLines;
break;
case e_preWipeLines:
wipeLineHelper = 0;
state = e_wipeLines;
// no break
case e_wipeLines:
if (canvasIsRowFilled(wipeLineHelper) == 1) {
canvasWipeRow(wipeLineHelper);
}
wipeLineHelper++;
if (wipeLineHelper >= canvas.height) {
state = e_idle;
}
break;
default:
state = e_idle;
break;
}
canvasShow();
}
void displayTest3Init() {
schAdd(displayTest3Exec, NULL, 0, 1000);
}

11
displayTest3.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef _DISPLAY_TEST_3_H_
#define _DISPLAY_TEST_3_H_
void displayTest3Init();
void displayTest3Exec();
#endif // _DISPLAY_TEST_3_H_

BIN
docs/one-color.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

BIN
docs/working-transfer.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

12
led.c
View File

@ -12,6 +12,10 @@ void ledGreenOff() {
P1OUT &= ~BIT0; P1OUT &= ~BIT0;
} }
void ledGreenToggle() {
P1OUT ^= BIT0;
}
void ledBlueOn() { void ledBlueOn() {
P1OUT |= BIT1; P1OUT |= BIT1;
} }
@ -20,8 +24,12 @@ void ledBlueOff() {
P1OUT &= ~BIT1; P1OUT &= ~BIT1;
} }
void ledBlueToggle() {
P1OUT ^= BIT1;
}
void ledExec(void *args) { void ledExec(void *args) {
static int i = 0; static uint16_t i = 0;
if (i == 0) { if (i == 0) {
ledGreenOff(); ledGreenOff();
@ -41,7 +49,7 @@ void ledInit() {
ledBlueOff(); ledBlueOff();
// schAdd(ledExec, NULL, 0, 50); // schAdd(ledExec, NULL, 0, 500);
} }

2
led.h
View File

@ -4,8 +4,10 @@
void ledBlueOff(); void ledBlueOff();
void ledBlueOn(); void ledBlueOn();
void ledBlueToggle();
void ledGreenOff(); void ledGreenOff();
void ledGreenOn(); void ledGreenOn();
void ledGreenToggle();
void ledInit(); void ledInit();
void ledExec(); void ledExec();

4
main.c
View File

@ -9,6 +9,8 @@
#include "displayDriver.h" #include "displayDriver.h"
#include "canvas.h" #include "canvas.h"
#include "displayTest.h" #include "displayTest.h"
#include "displayTest2.h"
#include "displayTest3.h"
int main() { int main() {
@ -29,7 +31,7 @@ int main() {
ledInit(); ledInit();
displayDriverInit(); displayDriverInit();
canvasInit(); canvasInit();
displayTestInit(); displayTest3Init();
__enable_interrupt(); __enable_interrupt();

14
time.c
View File

@ -1,30 +1,16 @@
#include <msp430g2553.h> #include <msp430g2553.h>
#include <stdint.h>
#include "time.h" #include "time.h"
#include "PontCoopScheduler.h" #include "PontCoopScheduler.h"
volatile uint32_t timestamp;
void __attribute__ ((interrupt (TIMER0_A0_VECTOR))) ta0_isr() { void __attribute__ ((interrupt (TIMER0_A0_VECTOR))) ta0_isr() {
timestamp++;
schUpdate(); schUpdate();
} }
void timeInit() { void timeInit() {
timestamp = 0;
TACCR0 = 32; TACCR0 = 32;
TACCTL0 = CCIE; TACCTL0 = CCIE;
TACTL = MC_1 | ID_0 | TASSEL_1 | TACLR; TACTL = MC_1 | ID_0 | TASSEL_1 | TACLR;
} }
uint32_t getMillis() {
return timestamp;
}
void ms_active_delay(uint16_t delay) {
uint32_t start = timestamp;
while (start + delay > timestamp);
}

2
time.h
View File

@ -4,8 +4,6 @@
#include <stdint.h> #include <stdint.h>
void timeInit(); void timeInit();
uint32_t getMillis();
void ms_active_delay(uint16_t delay);