diff --git a/sound-driver/Makefile b/sound-driver/Makefile index 0f70fcb..ad4569c 100644 --- a/sound-driver/Makefile +++ b/sound-driver/Makefile @@ -7,11 +7,11 @@ MCU=msp430g2553 CFLAGS=-Wall -mmcu=$(MCU) -std=gnu99 -I $(TOOLCHAIN_PREFIX)/include -O1 -g0 # for debugging -#CFLAGS+= -g3 -ggdb -gdwarf-2 +CFLAGS+= -g3 -ggdb -gdwarf-2 LDFLAGS=-mmcu=$(MCU) -L $(TOOLCHAIN_PREFIX)/include -$(ARTIFACT).elf: main.o +$(ARTIFACT).elf: main.o scheduler.o $(CC) -o $@ $(LDFLAGS) $^ $(OBJDUMP) -D $(ARTIFACT).elf > $(ARTIFACT).txt diff --git a/sound-driver/firmware.gdb b/sound-driver/firmware.gdb new file mode 100644 index 0000000..6312fd6 --- /dev/null +++ b/sound-driver/firmware.gdb @@ -0,0 +1,2 @@ +target remote localhost:2000 +file firmware.elf diff --git a/sound-driver/main.c b/sound-driver/main.c index aa8c0f1..8c8e13a 100644 --- a/sound-driver/main.c +++ b/sound-driver/main.c @@ -2,12 +2,14 @@ #include #include +#include "notes.h" +#include "scheduler.h" + #define ADDR_DATA_REG P2OUT #define BUS_CTRL_REG P1OUT -#define BC1 BIT0 +#define BC1 BIT3 #define BDIR BIT1 -#define _CS BIT3 #define R0 0 #define R1 1 @@ -24,12 +26,6 @@ #define R14 014 #define R15 015 -inline static void BUS_OP_ENABLE_CS() { - BUS_CTRL_REG &= ~_CS; -} -inline static void BUS_OP_DISABLE_CS() { - BUS_CTRL_REG |= _CS; -} inline static void BUS_OP_NACT() { BUS_CTRL_REG &= ~(BDIR | BC1); } @@ -62,9 +58,6 @@ asm volatile ( static void writePSG(uint8_t address, uint8_t data) { // according to "State Timing" (p. 15) of datasheet - // select chip - //BUS_OP_ENABLE_CS(); - // put bus into inactive state BUS_OP_NACT(); @@ -85,16 +78,11 @@ static void writePSG(uint8_t address, uint8_t data) { // set inactive again BUS_OP_NACT(); - - // deselect chip - //BUS_OP_DISABLE_CS(); } static void writeFrequency(uint8_t channel, uint16_t frequencyCode) { - uint8_t fine = frequencyCode & 0x00ff; - uint8_t coarse = (frequencyCode >> 8) & 0x000f; - writePSG(R0 + (channel * 2), fine); - writePSG(R1 + (channel * 2), coarse); + writePSG(R0 + (channel * 2), (frequencyCode & 0x00ff)); + writePSG(R1 + (channel * 2), ((frequencyCode >> 8) & 0x000f)); } int main() { @@ -137,14 +125,12 @@ int main() { delay(); // bus control lines - // BIT0: BC1 + // BIT3: BC1 // BIT1: BDIR - // BIT3: /CS - P1DIR |= BIT0 | BIT1 | BIT3; + P1DIR |= BIT1 | BIT3; // put bus into inactive state BUS_CTRL_REG &= ~(BDIR | BC1); - BUS_CTRL_REG |= _CS; // release sound chip from reset state P1OUT |= BIT2; @@ -153,11 +139,12 @@ int main() { delay(); + schInit(); + __enable_interrupt(); - BUS_OP_ENABLE_CS(); /* // single tone @@ -191,9 +178,9 @@ int main() { /* // Akkord - writeFrequency(0, 01527); - writeFrequency(1, 01247); - writeFrequency(2, 01073); + writeFrequency(0, C5); + writeFrequency(1, E5); + writeFrequency(2, G5); writePSG(R7, 0b11111000); writePSG(R10, 03); writePSG(R11, 03); @@ -201,9 +188,9 @@ int main() { */ - BUS_OP_DISABLE_CS(); while (1) { + schExec(); } } diff --git a/sound-driver/scheduler.c b/sound-driver/scheduler.c new file mode 100644 index 0000000..90720aa --- /dev/null +++ b/sound-driver/scheduler.c @@ -0,0 +1,86 @@ +#include +#include +#include "scheduler.h" + +tTask tasks[MAX_NUM_OF_TASKS]; + + +void schInit() { + P1DIR |= BIT0; + TACCR0 = 19600; + TACCTL0 = CCIE; + TACTL = MC_1 | ID_0 | TASSEL_2 | TACLR; + + for (uint16_t i = 0; i < MAX_NUM_OF_TASKS; i++) { + tasks[i].delay = 0; + tasks[i].period = 0; + tasks[i].run = 0; + tasks[i].exec = NULL; + tasks[i].handle = NULL; + } +} + +void __attribute__ ((interrupt (TIMER0_A0_VECTOR))) schUpdate() { + P1OUT ^= BIT0; + for (uint16_t i = 0; i < MAX_NUM_OF_TASKS; i++) { + if (tasks[i].exec != NULL) { + if (tasks[i].delay == 0) { + tasks[i].delay = tasks[i].period; + tasks[i].run++; + } else { + tasks[i].delay--; + } + } + } +} + +void schAdd(void (*exec)(void *), void *handle, uint32_t delay, uint32_t period) { + for (uint16_t i = 0; i < MAX_NUM_OF_TASKS; i++) { + if (tasks[i].exec == NULL) { + tasks[i].delay = delay; + tasks[i].period = period; + if (delay == 0 && period == 0) { + tasks[i].run = 1; + } else { + tasks[i].run = 0; + } + tasks[i].exec = exec; + tasks[i].handle = handle; + break; + } + } +} + +/* +void schDel(void (*exec)(void *), void *handle) { + for (uint16_t i = 0; i < MAX_NUM_OF_TASKS; i++) { + if ((tasks[i].exec == exec) && (tasks[i].handle == handle)) { + tasks[i].exec = NULL; + break; + } + } +} +*/ + +void schExec() { + 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) { + tasks[i].run--; + // synchronize access to tasks[].run + // reenable interrupts before actually executing task + __enable_interrupt(); + tasks[i].exec(tasks[i].handle); + if (tasks[i].period == 0) { + tasks[i].exec = NULL; + } + } else { + // synchronize access to tasks[].run + // reenable interrupts in case task is not yet executable + __enable_interrupt(); + } + } +} + + diff --git a/sound-driver/scheduler.h b/sound-driver/scheduler.h new file mode 100644 index 0000000..510818e --- /dev/null +++ b/sound-driver/scheduler.h @@ -0,0 +1,29 @@ +#ifndef PONTCOOPSCHEDULER_H_ +#define PONTCOOPSCHEDULER_H_ + + +#include + + + +#define MAX_NUM_OF_TASKS 2 + + +typedef struct { + uint16_t delay; + uint16_t period; + uint8_t run; + void (*exec)(void *handle); + void *handle; +} tTask; + + +void schInit(); +void schAdd(void (*exec)(void *), void *handle, uint32_t delay, uint32_t period); +void schDel(void (*exec)(void *), void *handle); +void schExec(); +void schUpdate(); +uint8_t schTaskCnt(); + + +#endif /* PONTCOOPSCHEDULER_H_ */