63 Commits

Author SHA1 Message Date
97dc6ede70 dreistimmig 2024-03-29 11:15:38 +01:00
a4563cd393 third melody 2024-03-29 00:39:21 +01:00
b435396d67 other melody 2024-03-29 00:28:15 +01:00
38ea1a7fdb register name 2024-03-28 17:05:35 +01:00
6632630303 register names 2024-03-28 17:03:56 +01:00
fdb524c8d4 separate SPI 2024-03-28 16:53:19 +01:00
2c3bccd147 fix wrong initial state 2024-03-28 16:53:08 +01:00
ee98ba12a3 spi separated 2024-03-28 16:48:29 +01:00
33242a09c1 docs 2024-03-28 16:25:16 +01:00
2097280f2b add docs 2024-03-28 16:07:50 +01:00
70b3b25a9d Merge branch 'main' of gitea.hottis.de:wn/tetris 2024-03-26 23:22:06 +01:00
5e1e9dfa92 sequencer init state 2024-03-26 23:21:24 +01:00
f397d0737b docs 2024-03-26 23:15:56 +01:00
1c2414463b sounds good 2024-03-26 23:13:59 +01:00
2e629f12aa sequencer states 2024-03-26 22:12:46 +01:00
9989a52c38 legato 2024-03-26 21:05:48 +01:00
73d2bbc730 tetris melody 2024-03-26 16:56:46 +01:00
5e2f120432 Tonleiter is running 2024-03-26 16:47:42 +01:00
152f171c66 sequencer 2024-03-26 15:58:45 +01:00
9ddb747f16 refactored 2024-03-26 15:05:39 +01:00
bd11d12620 psg and notes 2024-03-26 14:43:02 +01:00
e5c6669284 notes refactored 2024-03-26 13:30:42 +01:00
202e91bfb6 playsommething 2024-03-26 12:23:44 +01:00
48c83f0b2d scheduler added, tuned for 1ms 2024-03-26 10:44:23 +01:00
d8e34ec209 note definitions 2024-03-25 23:13:33 +01:00
5a491140c7 register numbering is octal! 2024-03-25 22:11:15 +01:00
aaf709b0c9 begin sound driver 2024-03-25 13:28:33 +01:00
32bb08696f score reset 2024-03-22 23:03:31 +01:00
85d243551e score counter 2024-03-22 22:49:43 +01:00
a32ef8fa5b prepare display 2024-03-22 18:38:30 +01:00
10a09e3ad3 game over 2024-03-22 12:00:23 +01:00
611c56b329 game over 2024-03-22 11:59:28 +01:00
5b1dfde819 updated schematics 2024-03-21 21:14:05 +01:00
1cc4785ddb refactor SPI handling and introduce SPI CS, forgotten files 2024-03-21 20:55:41 +01:00
9acd56b79b refactor SPI handling and introduce SPI CS 2024-03-21 20:55:26 +01:00
474fce2278 mini canvas 2024-03-21 19:30:40 +01:00
8597a9f736 schematics 2024-03-21 16:02:24 +01:00
da21fac130 motion definition 2024-03-21 15:40:16 +01:00
5f9fab5f2c more to the center 2024-03-21 15:28:36 +01:00
f524a08687 introduce next shape 2024-03-21 12:24:12 +01:00
5c03232855 wipe full lines 2024-03-21 11:58:42 +01:00
f69c5bc59e random is working 2024-03-21 11:34:20 +01:00
50486f6ec0 adc for random number generation not yet working 2024-03-20 21:56:19 +01:00
8c995f66ff J done 2024-03-20 21:00:22 +01:00
ebe958ac49 start of J 2024-03-20 17:35:31 +01:00
fadb80c362 L done 2024-03-20 17:05:13 +01:00
d1e13dc16a S done 2024-03-20 15:19:26 +01:00
90a9294da6 Z done 2024-03-20 14:48:25 +01:00
cfc06ddb2d placeholders for all stones 2024-03-20 13:54:57 +01:00
5e5c616bde T done 2024-03-20 13:48:06 +01:00
2ca1d2e4ad T, move right fixed 2024-03-19 22:18:42 +01:00
a28cdcf6af T, move left fixed 2024-03-19 21:19:34 +01:00
7f6d027d1a fix T, rotate left 2024-03-19 18:14:03 +01:00
97b1d19da8 T 2024-03-19 17:42:25 +01:00
8b2f18415d buttons 2024-03-19 16:46:52 +01:00
5615c80e8f all leds 2024-03-19 14:57:41 +01:00
a68f74559f refactoring 2024-03-18 20:50:10 +01:00
326d0f66b0 remove unused code 2024-03-18 13:01:23 +01:00
feed11f977 change 2024-03-18 12:54:23 +01:00
fd3df973ec code beautifying 2024-03-18 12:51:57 +01:00
58ae9a641a move displayTests to disabled folder 2024-03-18 12:18:18 +01:00
e0aae175b0 debug option in Makefile separated 2024-03-15 23:27:10 +01:00
7e4285f280 move down, left, right for T done 2024-03-15 14:23:19 +01:00
58 changed files with 2142 additions and 312 deletions

4
.gitignore vendored
View File

@ -1,3 +1,5 @@
*.o
firmware.*
firmware.txt
firmware.elf
firmware.map

31
display-driver/Makefile Normal file
View File

@ -0,0 +1,31 @@
TOOLCHAIN_PREFIX=/opt/msp430-gcc
CC=$(TOOLCHAIN_PREFIX)/bin/msp430-elf-gcc
OBJDUMP=$(TOOLCHAIN_PREFIX)/bin/msp430-elf-objdump
ARTIFACT=firmware
MCU=msp430g2553
CFLAGS=-Wall -mmcu=$(MCU) -std=gnu99 -I $(TOOLCHAIN_PREFIX)/include -O1 -g0
# for debugging
#CFLAGS+= -g3 -ggdb -gdwarf-2
LDFLAGS=-mmcu=$(MCU) -L $(TOOLCHAIN_PREFIX)/include
$(ARTIFACT).elf: main.o
$(CC) -o $@ $(LDFLAGS) $^
$(OBJDUMP) -D $(ARTIFACT).elf > $(ARTIFACT).txt
.c.o:
$(CC) $(CFLAGS) -c $<
.PHONY: all
all: $(ARTIFACT).elf
.PHONY: clean
clean:
-rm -f *.o $(ARTIFACT).elf $(ARTIFACT).txt
.PHONY: upload
upload: $(ARTIFACT).elf
mspdebug rf2500 "prog $(ARTIFACT).elf"

Binary file not shown.

Binary file not shown.

131
display-driver/main.c Normal file
View File

@ -0,0 +1,131 @@
#include <msp430g2553.h>
#include <stdint.h>
#include <stdlib.h>
const uint8_t patterns[] = {
0b00111111, // 0
0b00000110, // 1
0b01011011, // 2
0b01001111, // 3
0b01100110, // 4
0b01101101, // 5
0b01111101, // 6
0b00100111, // 7
0b01111111, // 8
0b01101111, // 9
};
volatile union {
uint16_t value;
uint8_t receiveBuffer[2];
} value;
static void delay() {
asm volatile (
"push r12\n"
"mov.w #1000, r12\n"
"loop:\n"
"dec.w r12\n"
"jnz loop\n"
"pop r12\n"
);
}
void __attribute__ ((interrupt (USCIAB0RX_VECTOR))) receive() {
static uint8_t octetNumber = 0;
if (UC0IFG & UCB0RXIFG) {
value.receiveBuffer[octetNumber] = UCB0RXBUF;
octetNumber++;
if (octetNumber > 1) {
octetNumber = 0;
}
}
}
// mask 0x0f: digit value
// mask 0x10: set dp
// mask 0x20: digit off
static void setDigit(uint16_t bit, uint8_t value) {
P1OUT |= (BIT0 | BIT1 | BIT2 | BIT3);
P2OUT = ((value & 0x20) ? 0 : patterns[value & 0x0f]) | ((value & 0x10) ? 0x80 : 0x00);
P1OUT &= ~bit;
}
int main() {
WDTCTL = WDTPW | WDTHOLD;
__disable_interrupt();
// highest possible system clock
DCOCTL = DCO0 | DCO1 | DCO2;
BCSCTL1 = XT2OFF | RSEL0 | RSEL1 | RSEL2 | RSEL3;
BCSCTL2 = 0;
BCSCTL3 = 0;
// SPI slave
// BIT4: UCB0STE
// BIT5: UCB0CLK
// BIT6: UCB0SOMI
// BIT7: UCB0SIMO
P1SEL |= BIT4 | BIT5 | BIT6 | BIT7;
P1SEL2 |= BIT4 | BIT5 | BIT6 | BIT7;
// most significant bit first, enable STE
UCB0CTL0 = UCSYNC | UCMSB | UCMODE_2;
UCB0CTL1 = 0x00;
// enable RX interrupt
UC0IE |= UCB0RXIE;
// digit driver
P1DIR |= BIT0 | BIT1 | BIT2 | BIT3;
P1SEL &= ~(BIT0 | BIT1 | BIT2 | BIT3);
P1SEL2 &= ~(BIT0 | BIT1 | BIT2 | BIT3);
// segment driver
P2DIR = 0xff;
P2SEL = 0x00;
P2SEL2 = 0x00;
// all digits off
P1OUT |= (BIT0 | BIT1 | BIT2 | BIT3);
// all segments off
P2OUT &= ~(BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7);
// reset value to 0
value.value = 0;
__enable_interrupt();
while (1) {
__disable_interrupt();
uint16_t shadowValue = value.value;
__enable_interrupt();
uint8_t digit0 = shadowValue % 10;
uint8_t digit1 = (shadowValue / 10) % 10;
uint8_t digit2 = (shadowValue / 100) % 10;
uint8_t digit3 = (shadowValue / 1000) % 10;
digit1 += (!((digit3 & 0x0f) | (digit2 & 0x0f) | (digit1 & 0x0f))) ? 0x20 : 0x00;
digit2 += (!((digit3 & 0x0f) | (digit2 & 0x0f))) ? 0x20 : 0x00;
digit3 += (!(digit3 & 0x0f)) ? 0x20 : 0x00;
setDigit(BIT0, digit0);
delay();
setDigit(BIT1, digit1);
delay();
setDigit(BIT2, digit2);
delay();
setDigit(BIT3, digit3);
delay();
}
}

BIN
docs/schematics.pdf Executable file

Binary file not shown.

View File

@ -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 led.o time.o PontCoopScheduler.o displayDriver.o canvas.o shapes.o game.o buttons.o
$(ARTIFACT).elf: main.o spi.o scheduler.o canvas.o shapes.o game.o buttons.o myrand.o display.o
$(CC) -o $@ $(LDFLAGS) $^
$(OBJDUMP) -D $(ARTIFACT).elf > $(ARTIFACT).txt

View File

@ -1,59 +1,47 @@
#include "stddef.h"
#include "stdint.h"
#include <stddef.h>
#include <stdint.h>
#include <msp430g2553.h>
#include "buttons.h"
#include "PontCoopScheduler.h"
#include "scheduler.h"
#include "shapes.h"
#include "canvas.h"
#include "led.h"
// TEST CODE
uint16_t counter;
static uint8_t buttonsMoveLeftPressed() {
// -----------------------
// TEST CODE
//if (counter == 95) {
// ledGreenToggle();
// return 1;
//}
// -----------------------
return 0;
static uint8_t last = 0;
uint8_t current = (P2IN & BIT4);
uint8_t res = (current != 0) && (current != last);
last = current;
return res;
}
static uint8_t buttonsMoveRightPressed() {
// -----------------------
// TEST CODE
if (counter == 95) {
ledGreenToggle();
return 1;
}
// -----------------------
return 0;
static uint8_t last = 0;
uint8_t current = (P2IN & BIT0);
uint8_t res = (current != 0) && (current != last);
last = current;
return res;
}
static uint8_t buttonsRotateLeftPressed() {
return 0;
static uint8_t last = 0;
uint8_t current = (P2IN & BIT3);
uint8_t res = (current != 0) && (current != last);
last = current;
return res;
}
static uint8_t buttonsRotateRightPressed() {
// -----------------------
// TEST CODE
if (counter == 35) {
ledGreenToggle();
return 1;
}
// -----------------------
// -----------------------
// TEST CODE
if (counter == 45) {
ledGreenToggle();
return 1;
}
// -----------------------
return 0;
static uint8_t last = 0;
uint8_t current = (P2IN & BIT1);
uint8_t res = (current != 0) && (current != last);
last = current;
return res;
}
static uint8_t buttonsMoveDownPressed() {
return P2IN & BIT2;
}
void buttonsExec(void *handle) {
@ -62,9 +50,6 @@ void buttonsExec(void *handle) {
return;
}
// TEST CODE
counter++;
uint8_t buttonPressed = 0;
if (buttonsMoveLeftPressed()) {
@ -83,6 +68,10 @@ void buttonsExec(void *handle) {
stoneRotateRight();
buttonPressed = 1;
}
if (buttonsMoveDownPressed()) {
stoneMoveDown();
buttonPressed = 1;
}
if (buttonPressed == 1) {
canvasShow();
@ -90,9 +79,8 @@ void buttonsExec(void *handle) {
}
void buttonsInit() {
// TEST CODE
counter = 0;
P2DIR &= ~(BIT0|BIT1|BIT2|BIT3|BIT4);
schAdd(buttonsExec, NULL, 0, 100);
schAdd(buttonsExec, NULL, 0, 25);
}

View File

@ -1,39 +1,80 @@
#include <string.h>
#include <stdint.h>
#include <msp430g2553.h>
#include "canvas.h"
#include "displayDriver.h"
#include "spi.h"
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
};
static uint8_t miniCanvasStorage[MINI_CANVAS_WIDTH * MINI_CANVAS_HEIGHT];
const canvas_t miniCanvas = {
.height = MINI_CANVAS_HEIGHT,
.width = MINI_CANVAS_WIDTH,
.canvas = miniCanvasStorage
};
void canvasShow() {
// wait for signal waiting for data
while (!(P1IN & BIT3));
spiSendBegin(e_SPI_CANVAS);
for (uint8_t i = 0; i < (CANVAS_WIDTH*CANVAS_HEIGHT); i++) {
if ((*((canvas.canvas)+i) & 0x80) != 0) {
*((canvas.canvas)+i) &= ~0x80;
spiSendOctet(i);
spiSendOctet(*((canvas.canvas)+i));
}
}
for (uint8_t i = 0; i < (MINI_CANVAS_WIDTH*MINI_CANVAS_HEIGHT); i++) {
if ((*((miniCanvas.canvas)+i) & 0x80) != 0) {
*((miniCanvas.canvas)+i) &= ~0x80;
spiSendOctet(i + (CANVAS_HEIGHT*CANVAS_WIDTH));
spiSendOctet(*((miniCanvas.canvas)+i));
}
}
spiSendOctet(0xfe);
spiSendEnd(e_SPI_CANVAS);
}
void canvasInit() {
// P1.3 is signal line
P1DIR &= ~BIT3;
canvasClear();
displayDriverTransferCanvas();
miniCanvasClear();
canvasShow();
}
void canvasClear() {
memset(canvas.canvas, 0x80, canvas.size);
memset(canvas.canvas, 0x80, CANVAS_WIDTH*CANVAS_HEIGHT);
}
void canvasSetAll(uint8_t color) {
memset(canvas.canvas, color + 0x80, canvas.size);
void miniCanvasClear() {
memset(miniCanvas.canvas, 0x80, MINI_CANVAS_WIDTH*MINI_CANVAS_HEIGHT);
}
void canvasShow() {
displayDriverTransferCanvas();
}
//void canvasSetAll(uint8_t color) {
// memset(canvas.canvas, color + 0x80, CANVAS_WIDTH*CANVAS_HEIGHT);
//}
void canvasSetPixel(uint8_t column, uint8_t row, uint8_t color) {
*((canvas.canvas) + (row * canvas.width + column)) = (color + 0x80);
}
void miniCanvasSetPixel(uint8_t column, uint8_t row, uint8_t color) {
*((miniCanvas.canvas) + (row * miniCanvas.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++) {
@ -42,6 +83,13 @@ void canvasWipeRow(uint8_t row) {
memset(canvas.canvas, 0x80, canvas.width);
}
void canvasFillRow(uint8_t row, uint8_t color) {
for (uint8_t c = 0; c < canvas.width; c++) {
canvasSetPixel(c, row, color);
}
}
uint8_t canvasIsRowFilled(uint8_t row) {
uint8_t res = 1;
for (uint8_t column = 0; column < canvas.width; column++) {

View File

@ -3,9 +3,10 @@
#include <stdint.h>
// Definition of CANVAS_WIDTH and CANVAS_HEIGHT
// imported from rgb-driver
#include "../rgb-driver/canvasSize.h"
#define CANVAS_WIDTH 10
#define CANVAS_HEIGHT 11
typedef struct {
const uint8_t width;
@ -16,13 +17,14 @@ typedef struct {
void canvasInit();
void canvasClear();
void canvasSetAll(uint8_t color);
void miniCanvasClear();
//void canvasSetAll(uint8_t color);
void canvasShow();
void canvasSetPixel(uint8_t column, uint8_t row, uint8_t color);
void miniCanvasSetPixel(uint8_t column, uint8_t row, uint8_t color);
uint8_t canvasIsPixelFree(uint8_t column, uint8_t row);
void canvasWipeRow(uint8_t row);
void canvasFillRow(uint8_t row, uint8_t color);
uint8_t canvasIsRowFilled(uint8_t row);
extern const canvas_t canvas;
#endif // _CANVAS_H_

View File

@ -1,6 +1,6 @@
#include "led.h"
#include <msp430g2553.h>
#include "PontCoopScheduler.h"
#include "scheduler.h"
#include <stdlib.h>

26
game-ctrl/display.c Normal file
View File

@ -0,0 +1,26 @@
#include <stdint.h>
#include "display.h"
#include "spi.h"
void displayInit() {
}
void displaySetValue(uint16_t v) {
union {
uint16_t value;
uint8_t sendBuffer[2];
} value;
value.value = v;
spiSendBegin(e_SPI_DISPLAY);
spiSendOctet(value.sendBuffer[0]);
spiSendOctet(value.sendBuffer[1]);
spiSendEnd(e_SPI_DISPLAY);
}

13
game-ctrl/display.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef _DISPLAY_H_
#define _DISPLAY_H_
#include <stdint.h>
void displayInit();
void displaySetValue(uint16_t v);
#endif // _DISPLAY_H_

View File

@ -1,57 +0,0 @@
#include "displayDriver.h"
#include "led.h"
#include "canvas.h"
#include <msp430g2553.h>
#include <stdlib.h>
#include <stdint.h>
inline static void spiSendOctet(uint8_t v) {
// wait for TX buffer empty
while (!(UC0IFG & UCB0TXIFG));
// load octet into TX buffer
UCB0TXBUF = v;
}
void displayDriverTransferCanvas() {
// wait for signal waiting for data
while ((P1IN & BIT3) == 0);
for (uint8_t i = 0; i < canvas.size; i++) {
if ((*((canvas.canvas)+i) & 0x80) != 0) {
*((canvas.canvas)+i) &= ~0x80;
spiSendOctet(i);
spiSendOctet(*((canvas.canvas)+i));
}
}
spiSendOctet(0xfe);
}
void displayDriverInit() {
// SPI in master mode
UCB0CTL0 = UCMST;
// SPI timing config
UCB0CTL1 = UCSSEL_3;
// 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;
// BIT5: UCB0CLK
// BIT6: UCB0SOMI
// BIT7: UCB0SIMO
P1SEL |= BIT5 | BIT6 | BIT7;
P1SEL2 |= BIT5 | BIT6 | BIT7;
P1DIR |= BIT5 | BIT7;
// P1.3 is signal line
P1DIR &= ~BIT3;
// enable SPI module
UCB0CTL1 &= ~UCSWRST;
}

View File

@ -1,9 +0,0 @@
#ifndef _DISPLAY_DRIVER_H_
#define _DISPLAY_DRIVER_H_
void displayDriverInit();
void displayDriverTransferCanvas();
#endif // _DISPLAY_DRIVER_H_

Binary file not shown.

2
game-ctrl/firmware.gdb Normal file
View File

@ -0,0 +1,2 @@
target remote localhost:2000
file firmware.elf

View File

@ -2,66 +2,128 @@
#include "stdint.h"
#include "game.h"
#include "PontCoopScheduler.h"
#include "scheduler.h"
#include "shapes.h"
#include "canvas.h"
#include "../rgb-driver/colors.h"
#include "display.h"
typedef enum { e_idle, e_start, e_newStone, e_down, e_gameOver, e_delay } state_t;
#define GAME_CYCLE_TIME 100
#define GAMEOVER_DELAY 10
static uint8_t delayFactor(uint8_t level) {
return 11 - level;
}
typedef enum {
e_Phase_Game, e_Phase_GameOver
} phase_t;
typedef enum {
e_Start, e_NewStone, e_Down, e_DownDelay, e_ClearRows,
e_GameOver, e_GameOverFill, e_GameOverWipe, e_GameOverDelay
} state_t;
void gameExec(void *handle) {
static state_t state = e_start;
static uint8_t delay;
static phase_t phase;
static state_t state = e_Start;
static uint8_t gameOverDelay;
static uint8_t rowIndex;
static uint8_t proceedDelay;
static uint8_t level;
static uint16_t score;
// --- engine begin -------------------------------------------------------
switch (state) {
case e_idle:
break;
case e_start:
// --- phase: game --------------------------------------------------------
case e_Start:
canvasClear();
state = e_newStone;
level = 1;
score = 0;
displaySetValue(score);
phase = e_Phase_Game;
state = e_NewStone;
break;
case e_newStone:
case e_NewStone:
stoneCreate();
if (stoneDraw()) {
state = e_down;
proceedDelay = delayFactor(level);
state = e_DownDelay;
} else {
state = e_gameOver;
state = e_GameOver;
}
break;
case e_down:
case e_DownDelay:
proceedDelay--;
if (proceedDelay == 0) {
rowIndex = 0;
state = e_ClearRows;
}
break;
case e_ClearRows:
state = e_Down;
break;
case e_Down:
if (! stoneMoveDown()) {
state = e_newStone;
state = e_NewStone;
} else {
proceedDelay = delayFactor(level);
state = e_DownDelay;
}
break;
case e_gameOver:
for (uint8_t c = 0; c < canvas.width; c++) {
canvasSetPixel(c, 0, 0x0d);
canvasSetPixel(c, canvas.height-1, 0x0d);
}
for (uint8_t r = 0; r < canvas.height; r++) {
canvasSetPixel(0, r, 0x0d);
canvasSetPixel(canvas.width-1, r, 0x0d);
}
delay = 10;
state = e_delay;
// --- phase: game over ---------------------------------------------------
case e_GameOver:
rowIndex = CANVAS_HEIGHT;
phase = e_Phase_GameOver;
state = e_GameOverFill;
break;
case e_delay:
delay--;
if (delay == 0) {
state = e_start;
case e_GameOverFill:
rowIndex--;
canvasFillRow(rowIndex, _red);
if (rowIndex == 0) {
state = e_GameOverWipe;
}
break;
case e_GameOverWipe:
canvasWipeRow(rowIndex);
rowIndex++;
if (rowIndex == CANVAS_HEIGHT) {
gameOverDelay = GAMEOVER_DELAY;
state = e_GameOverDelay;
}
break;
case e_GameOverDelay:
gameOverDelay--;
if (gameOverDelay == 0) {
state = e_Start;
}
break;
}
// --- engine end ---------------------------------------------------------
canvasShow();
if (phase == e_Phase_Game) {
for (uint8_t r = 0; r < CANVAS_HEIGHT; r++) {
if (canvasIsRowFilled(r)) {
score += level;
displaySetValue(score);
canvasWipeRow(r);
canvasShow();
}
}
}
}
void gameInit() {
schAdd(gameExec, NULL, 0, 1000);
schAdd(gameExec, NULL, 0, GAME_CYCLE_TIME);
}

View File

@ -4,13 +4,14 @@
#include <stdbool.h>
#include "time.h"
#include "PontCoopScheduler.h"
#include "led.h"
#include "displayDriver.h"
#include "scheduler.h"
#include "canvas.h"
#include "game.h"
#include "buttons.h"
#include "shapes.h"
#include "myrand.h"
#include "spi.h"
#include "display.h"
int main() {
@ -24,11 +25,11 @@ int main() {
BCSCTL2 = 0;
BCSCTL3 = 0;
timeInit();
schInit();
ledInit();
displayDriverInit();
spiInit();
displayInit();
myRandInit();
canvasInit();
shapesInit();

26
game-ctrl/myrand.c Normal file
View File

@ -0,0 +1,26 @@
#include <stdint.h>
#include <msp430g2553.h>
#include "myrand.h"
void myRandInit() {
ADC10CTL1 = INCH_10;
ADC10CTL0 = SREF_1 | ADC10SHT_1 | REFON | ADC10ON;
}
uint16_t myRandGet() {
uint16_t res = 0;
for (uint8_t i = 0; i < 16; i++) {
ADC10CTL0 |= ENC | ADC10SC;
while ((ADC10CTL1 & ADC10BUSY));
res <<= 1;
res |= ADC10MEM & 0x0001;
}
return res;
}

8
game-ctrl/myrand.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef _MYRAND_H_
#define _MYRAND_H_
void myRandInit();
uint16_t myRandGet();
#endif // _MYRAND_H_

View File

@ -1,21 +1,23 @@
/*
* PontCoopScheduler.c
*
* Created on: 29.08.2016
* Originally created on: 29.08.2016
* Author: wn
*/
#include <stdlib.h>
#include <msp430g2553.h>
#include "PontCoopScheduler.h"
#include "scheduler.h"
tTask tasks[MAX_NUM_OF_TASKS];
void schInit() {
TACCR0 = 32;
TACCTL0 = CCIE;
TACTL = MC_1 | ID_0 | TASSEL_1 | TACLR;
for (uint16_t i = 0; i < MAX_NUM_OF_TASKS; i++) {
tasks[i].delay = 0;
tasks[i].period = 0;
@ -25,6 +27,19 @@ void schInit() {
}
}
void __attribute__ ((interrupt (TIMER0_A0_VECTOR))) schUpdate() {
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) {
@ -75,16 +90,3 @@ void schExec() {
}
void schUpdate() {
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--;
}
}
}
}

View File

@ -1,7 +1,9 @@
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include "shapes.h"
#include "myrand.h"
#include "canvas.h"
#include "../rgb-driver/colors.h"
@ -42,7 +44,7 @@ typedef struct {
motion_t motion[5][4];
} motionTable_t;
const motionTable_t motions[2] = { // 2 = number of implemented stones
const motionTable_t motions[7] = { // size = number of implemented stones
{ // I
.color = _cyan,
.nullRotation = 0,
@ -120,13 +122,223 @@ const motionTable_t motions[2] = { // 2 = number of implemented stones
},
{
// rotate right
{ .set = { {-2, 1}, {-1, 1}, { 1, 1}, { 1, 1} }, .reset = { { 0, 0}, { 0, 2}, { 0, 3}, { 0, 3} }, .offset = {-2, 1} }, // 0
{ .set = { { 1,-1}, { 1, 1}, { 1, 2}, { 1, 2} }, .reset = { { 0, 0}, { 2, 0}, { 3, 0}, { 3, 0} }, .offset = { 1,-1} }, // 90
{ .set = { {-2, 1}, {-1, 1}, { 1, 1}, { 1, 1} }, .reset = { { 0, 0}, { 0, 2}, { 0, 3}, { 0, 3} }, .offset = {-2, 1} }, // 180
{ .set = { { 1,-1}, { 1, 1}, { 1, 2}, { 1, 2} }, .reset = { { 0, 0}, { 2, 0}, { 3, 0}, { 3, 0} }, .offset = { 1,-1} }, // 270
{ .set = { { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0} }, .reset = { { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0} }, .offset = { 0, 0} }, // 0
{ .set = { { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0} }, .reset = { { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0} }, .offset = { 0, 0} }, // 90
{ .set = { { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0} }, .reset = { { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0} }, .offset = { 0, 0} }, // 180
{ .set = { { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0} }, .reset = { { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0} }, .offset = { 0, 0} }, // 270
},
}
},
{ // T
.color = _violet,
.nullRotation = 0,
.draw = { { 0, 0}, { 1, 0}, { 2, 0}, { 1, 1} },
.motion = {
{
// move down
{ .set = { { 0, 1}, { 2, 1}, { 1, 2}, { 1, 2} }, .reset = { { 0, 0}, { 1, 0}, { 2, 0}, { 2, 0} }, .offset = { 0, 1} }, // 0
{ .set = { { 0, 2}, { 1, 3}, { 1, 3}, { 1, 3} }, .reset = { { 1, 0}, { 0, 1}, { 0, 1}, { 0, 1} }, .offset = { 0, 1} }, // 90
{ .set = { { 0, 2}, { 1, 2}, { 2, 2}, { 2, 2} }, .reset = { { 1, 0}, { 0, 1}, { 2, 1}, { 2, 1} }, .offset = { 0, 1} }, // 180
{ .set = { { 0, 3}, { 1, 2}, { 1, 2}, { 1, 2} }, .reset = { { 0, 0}, { 1, 1}, { 1, 1}, { 1, 1} }, .offset = { 0, 1} }, // 270
},
{
// move left
{ .set = { {-1, 0}, { 0, 1}, { 0, 1}, { 0, 1} }, .reset = { { 1, 1}, { 2, 0}, { 2, 0}, { 2, 0} }, .offset = {-1, 0} }, // 0
{ .set = { { 0, 0}, {-1, 1}, { 0, 2}, { 0, 2} }, .reset = { { 1, 0}, { 1, 1}, { 1, 2}, { 1, 2} }, .offset = {-1, 0} }, // 90
{ .set = { {-1, 1}, { 0, 0}, { 0, 0}, { 0, 0} }, .reset = { { 1, 0}, { 2, 1}, { 2, 1}, { 2, 1} }, .offset = {-1, 0} }, // 180
{ .set = { {-1, 0}, {-1, 1}, {-1, 2}, {-1, 2} }, .reset = { { 0, 0}, { 0, 2}, { 1, 1}, { 1, 1} }, .offset = {-1, 0} }, // 270
},
{
// move right
{ .set = { { 3, 0}, { 2, 1}, { 2, 1}, { 2, 1} }, .reset = { { 0, 0}, { 1, 1}, { 1, 1}, { 1, 1} }, .offset = { 1, 0} }, // 0
{ .set = { { 2, 0}, { 2, 1}, { 2, 2}, { 2, 2} }, .reset = { { 0, 1}, { 1, 0}, { 1, 2}, { 1, 2} }, .offset = { 1, 0} }, // 90
{ .set = { { 3, 1}, { 2, 0}, { 2, 0}, { 2, 0} }, .reset = { { 0, 0}, { 0, 1}, { 1, 0}, { 1, 0} }, .offset = { 1, 0} }, // 180
{ .set = { { 1, 0}, { 1, 2}, { 2, 1}, { 2, 1} }, .reset = { { 0, 0}, { 0, 1}, { 0, 2}, { 0, 2} }, .offset = { 1, 0} }, // 270
},
{
// rotate left
{ .set = { { 1,-1}, { 1,-1}, { 1,-1}, { 1,-1} }, .reset = { { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0} }, .offset = { 1,-1} }, // 0
{ .set = { { 2, 1}, { 2, 1}, { 2, 1}, { 2, 1} }, .reset = { { 1, 0}, { 1, 0}, { 1, 0}, { 1, 0} }, .offset = { 0, 1} }, // 90
{ .set = { { 1, 2}, { 1, 2}, { 1, 2}, { 1, 2} }, .reset = { { 2, 1}, { 2, 1}, { 2, 1}, { 2, 1} }, .offset = { 0, 0} }, // 180
{ .set = { {-1, 1}, {-1, 1}, {-1, 1}, {-1, 1} }, .reset = { { 0, 2}, { 0, 2}, { 0, 2}, { 0, 2} }, .offset = {-1, 0} }, // 270
},
{
// rotate right
{ .set = { { 1,-1}, { 1,-1}, { 1,-1}, { 1,-1} }, .reset = { { 2, 0}, { 2, 0}, { 2, 0}, { 2, 0} }, .offset = { 0,-1} }, // 0
{ .set = { { 2, 1}, { 2, 1}, { 2, 1}, { 2, 1} }, .reset = { { 1, 2}, { 1, 2}, { 1, 2}, { 1, 2} }, .offset = { 0, 0} }, // 90
{ .set = { { 1, 2}, { 1, 2}, { 1, 2}, { 1, 2} }, .reset = { { 0, 1}, { 0, 1}, { 0, 1}, { 0, 1} }, .offset = { 1, 0} }, // 180
{ .set = { {-1, 1}, {-1, 1}, {-1, 1}, {-1, 1} }, .reset = { { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0} }, .offset = {-1, 1} }, // 270
},
}
},
{ // Z
.color = _red,
.nullRotation = 0,
.draw = { { 0, 0}, { 1, 0}, { 1, 1}, { 2, 1} },
.motion = {
{
// move down
{ .set = { { 0, 1}, { 1, 2}, { 2, 2}, { 2, 2} }, .reset = { { 0, 0}, { 1, 0}, { 2, 1}, { 2, 1} }, .offset = { 0, 1} }, // 0
{ .set = { { 1, 2}, { 0, 3}, { 0, 3}, { 0, 3} }, .reset = { { 1, 0}, { 0, 1}, { 0, 1}, { 0, 1} }, .offset = { 0, 1} }, // 90
{ .set = { { 0, 1}, { 1, 2}, { 2, 2}, { 2, 2} }, .reset = { { 0, 0}, { 1, 0}, { 2, 1}, { 2, 1} }, .offset = { 0, 1} }, // 180
{ .set = { { 1, 2}, { 0, 3}, { 0, 3}, { 0, 3} }, .reset = { { 1, 0}, { 0, 1}, { 0, 1}, { 0, 1} }, .offset = { 0, 1} }, // 270
},
{
// move left
{ .set = { {-1, 0}, { 0, 1}, { 0, 1}, { 0, 1} }, .reset = { { 1, 0}, { 2, 1}, { 2, 1}, { 2, 1} }, .offset = {-1, 0} }, // 0
{ .set = { {-1, 1}, {-1, 2}, { 0, 0}, { 0, 0} }, .reset = { { 1, 0}, { 1, 1}, { 0, 2}, { 0, 2} }, .offset = {-1, 0} }, // 90
{ .set = { {-1, 0}, { 0, 1}, { 0, 1}, { 0, 1} }, .reset = { { 1, 0}, { 2, 1}, { 2, 1}, { 2, 1} }, .offset = {-1, 0} }, // 180
{ .set = { {-1, 1}, {-1, 2}, { 0, 0}, { 0, 0} }, .reset = { { 1, 0}, { 1, 1}, { 0, 2}, { 0, 2} }, .offset = {-1, 0} }, // 270
},
{
// move right
{ .set = { { 3, 1}, { 2, 0}, { 2, 0}, { 2, 0} }, .reset = { { 0, 0}, { 1, 1}, { 1, 1}, { 1, 1} }, .offset = { 1, 0} }, // 0
{ .set = { { 2, 0}, { 2, 1}, { 1, 2}, { 1, 2} }, .reset = { { 0, 1}, { 0, 2}, { 1, 0}, { 1, 0} }, .offset = { 1, 0} }, // 90
{ .set = { { 3, 1}, { 2, 0}, { 2, 0}, { 2, 0} }, .reset = { { 0, 0}, { 1, 1}, { 1, 1}, { 1, 1} }, .offset = { 1, 0} }, // 180
{ .set = { { 2, 0}, { 2, 1}, { 1, 2}, { 1, 2} }, .reset = { { 0, 1}, { 0, 2}, { 1, 0}, { 1, 0} }, .offset = { 1, 0} }, // 270
},
{
// rotate left
{ .set = { { 1,-1}, { 0, 1}, { 0, 1}, { 0, 1} }, .reset = { { 2, 1}, { 1, 1}, { 1, 1}, { 1, 1} }, .offset = { 0,-1} }, // 0
{ .set = { { 0, 0}, { 2, 1}, { 2, 1}, { 2, 1} }, .reset = { { 0, 2}, { 0, 1}, { 0, 1}, { 0, 1} }, .offset = { 0, 0} }, // 90
{ .set = { { 1,-1}, { 0, 1}, { 0, 1}, { 0, 1} }, .reset = { { 2, 1}, { 1, 1}, { 1, 1}, { 1, 1} }, .offset = { 0,-1} }, // 180
{ .set = { { 0, 0}, { 2, 1}, { 2, 1}, { 2, 1} }, .reset = { { 0, 2}, { 0, 1}, { 0, 1}, { 0, 1} }, .offset = { 0, 0} }, // 270
},
{
// rotate right
{ .set = { { 1,-1}, { 0, 1}, { 0, 1}, { 0, 1} }, .reset = { { 2, 1}, { 1, 1}, { 1, 1}, { 1, 1} }, .offset = { 0,-1} }, // 0
{ .set = { { 0, 0}, { 2, 1}, { 2, 1}, { 2, 1} }, .reset = { { 0, 2}, { 0, 1}, { 0, 1}, { 0, 1} }, .offset = { 0, 0} }, // 90
{ .set = { { 1,-1}, { 0, 1}, { 0, 1}, { 0, 1} }, .reset = { { 2, 1}, { 1, 1}, { 1, 1}, { 1, 1} }, .offset = { 0,-1} }, // 180
{ .set = { { 0, 0}, { 2, 1}, { 2, 1}, { 2, 1} }, .reset = { { 0, 2}, { 0, 1}, { 0, 1}, { 0, 1} }, .offset = { 0, 0} }, // 270
},
}
},
{ // S
.color = _green,
.nullRotation = 0,
.draw = { { 0, 1}, { 1, 1}, { 1, 0}, { 2, 0} },
.motion = {
{
// move down
{ .set = { { 0, 2}, { 1, 2}, { 2, 1}, { 2, 1} }, .reset = { { 0, 1}, { 1, 0}, { 2, 0}, { 2, 0} }, .offset = { 0, 1} }, // 0
{ .set = { { 0, 2}, { 1, 3}, { 1, 3}, { 1, 3} }, .reset = { { 0, 0}, { 1, 1}, { 1, 1}, { 1, 1} }, .offset = { 0, 1} }, // 90
{ .set = { { 0, 2}, { 1, 2}, { 2, 1}, { 2, 1} }, .reset = { { 0, 1}, { 1, 0}, { 2, 0}, { 2, 0} }, .offset = { 0, 1} }, // 180
{ .set = { { 0, 2}, { 1, 3}, { 1, 3}, { 1, 3} }, .reset = { { 0, 0}, { 1, 1}, { 1, 1}, { 1, 1} }, .offset = { 0, 1} }, // 270
},
{
// move left
{ .set = { { 0, 0}, {-1, 1}, {-1, 1}, {-1, 1} }, .reset = { { 2, 0}, { 1, 1}, { 1, 1}, { 1, 1} }, .offset = {-1, 0} }, // 0
{ .set = { {-1, 0}, {-1, 1}, { 0, 2}, { 0, 2} }, .reset = { { 0, 0}, { 1, 1}, { 1, 2}, { 1, 2} }, .offset = {-1, 0} }, // 90
{ .set = { { 0, 0}, {-1, 1}, {-1, 1}, {-1, 1} }, .reset = { { 2, 0}, { 1, 1}, { 1, 1}, { 1, 1} }, .offset = {-1, 0} }, // 180
{ .set = { {-1, 0}, {-1, 1}, { 0, 2}, { 0, 2} }, .reset = { { 0, 0}, { 1, 1}, { 1, 2}, { 1, 2} }, .offset = {-1, 0} }, // 270
},
{
// move right
{ .set = { { 2, 1}, { 3, 0}, { 3, 0}, { 3, 0} }, .reset = { { 1, 0}, { 0, 1}, { 0, 1}, { 0, 1} }, .offset = { 1, 0} }, // 0
{ .set = { { 1, 0}, { 2, 1}, { 2, 2}, { 2, 2} }, .reset = { { 0, 0}, { 0, 1}, { 1, 2}, { 1, 2} }, .offset = { 1, 0} }, // 90
{ .set = { { 2, 1}, { 3, 0}, { 3, 0}, { 3, 0} }, .reset = { { 1, 0}, { 0, 1}, { 0, 1}, { 0, 1} }, .offset = { 1, 0} }, // 180
{ .set = { { 1, 0}, { 2, 1}, { 2, 2}, { 2, 2} }, .reset = { { 0, 0}, { 0, 1}, { 1, 2}, { 1, 2} }, .offset = { 1, 0} }, // 270
},
{
// rotate left
{ .set = { { 0, 0}, { 0,-1}, { 0,-1}, { 0,-1} }, .reset = { { 0, 1}, { 2, 0}, { 2, 0}, { 2, 0} }, .offset = { 0,-1} }, // 0
{ .set = { { 1, 0}, { 2, 0}, { 2, 0}, { 2, 0} }, .reset = { { 0, 0}, { 1, 2}, { 1, 2}, { 1, 2} }, .offset = { 0, 0} }, // 90
{ .set = { { 0, 0}, { 0,-1}, { 0,-1}, { 0,-1} }, .reset = { { 0, 1}, { 2, 0}, { 2, 0}, { 2, 0} }, .offset = { 0,-1} }, // 180
{ .set = { { 1, 0}, { 2, 0}, { 2, 0}, { 2, 0} }, .reset = { { 0, 0}, { 1, 2}, { 1, 2}, { 1, 2} }, .offset = { 0, 0} }, // 270
},
{
// rotate right
{ .set = { { 0, 0}, { 0,-1}, { 0,-1}, { 0,-1} }, .reset = { { 0, 1}, { 2, 0}, { 2, 0}, { 2, 0} }, .offset = { 0,-1} }, // 0
{ .set = { { 1, 0}, { 2, 0}, { 2, 0}, { 2, 0} }, .reset = { { 0, 0}, { 1, 2}, { 1, 2}, { 1, 2} }, .offset = { 0, 0} }, // 90
{ .set = { { 0, 0}, { 0,-1}, { 0,-1}, { 0,-1} }, .reset = { { 0, 1}, { 2, 0}, { 2, 0}, { 2, 0} }, .offset = { 0,-1} }, // 180
{ .set = { { 1, 0}, { 2, 0}, { 2, 0}, { 2, 0} }, .reset = { { 0, 0}, { 1, 2}, { 1, 2}, { 1, 2} }, .offset = { 0, 0} }, // 270
},
}
},
{ // L
.color = _orange,
.nullRotation = 0,
.draw = { { 0, 0}, { 0, 1}, { 0, 2}, { 1, 2} },
.motion = {
{
// move down
{ .set = { { 0, 3}, { 1, 3}, { 1, 3}, { 1, 3} }, .reset = { { 0, 0}, { 1, 2}, { 1, 2}, { 1, 2} }, .offset = { 0, 1} }, // 0
{ .set = { { 1, 1}, { 2, 1}, { 0, 2}, { 0, 2} }, .reset = { { 0, 0}, { 1, 0}, { 2, 0}, { 2, 0} }, .offset = { 0, 1} }, // 90
{ .set = { { 0, 1}, { 1, 3}, { 1, 3}, { 1, 3} }, .reset = { { 0, 0}, { 1, 0}, { 1, 0}, { 1, 0} }, .offset = { 0, 1} }, // 180
{ .set = { { 0, 2}, { 1, 2}, { 2, 2}, { 2, 2} }, .reset = { { 2, 0}, { 0, 1}, { 1, 1}, { 1, 1} }, .offset = { 0, 1} }, // 270
},
{
// move left
{ .set = { {-1, 0}, {-1, 1}, {-1, 2}, {-1, 2} }, .reset = { { 0, 0}, { 0, 1}, { 1, 2}, { 0, 0} }, .offset = {-1, 0} }, // 0
{ .set = { {-1, 0}, {-1, 1}, {-1, 1}, {-1, 1} }, .reset = { { 0, 1}, { 2, 0}, { 2, 0}, { 2, 0} }, .offset = {-1, 0} }, // 90
{ .set = { { 0, 1}, { 0, 2}, {-1, 0}, {-1, 0} }, .reset = { { 1, 0}, { 1, 1}, { 1, 2}, { 1, 2} }, .offset = {-1, 0} }, // 180
{ .set = { {-1, 1}, { 1, 0}, { 1, 0}, { 1, 0} }, .reset = { { 2, 0}, { 2, 1}, { 2, 1}, { 2, 1} }, .offset = {-1, 0} }, // 270
},
{
// move right
{ .set = { { 1, 0}, { 1, 1}, { 2, 2}, { 2, 2} }, .reset = { { 0, 0}, { 0, 1}, { 0, 2}, { 0, 2} }, .offset = { 1, 0} }, // 0
{ .set = { { 1, 1}, { 3, 0}, { 3, 0}, { 3, 0} }, .reset = { { 0, 0}, { 0, 1}, { 0, 1}, { 0, 1} }, .offset = { 1, 0} }, // 90
{ .set = { { 2, 0}, { 2, 1}, { 2, 2}, { 2, 2} }, .reset = { { 0, 0}, { 1, 1}, { 1, 2}, { 1, 2} }, .offset = { 1, 0} }, // 180
{ .set = { { 3, 0}, { 3, 1}, { 3, 1}, { 3, 1} }, .reset = { { 0, 1}, { 2, 0}, { 2, 0}, { 2, 0} }, .offset = { 1, 0} }, // 270
},
{
// rotate left
{ .set = { {-1, 2}, {-2, 2}, {-2, 2}, {-2, 2} }, .reset = { { 0, 0}, { 1, 2}, { 1, 2}, { 1, 2} }, .offset = {-2, 1} }, // 0
{ .set = { { 0,-1}, { 0,-2}, { 0,-2}, { 0,-2} }, .reset = { { 0, 1}, { 2, 0}, { 2, 0}, { 2, 0} }, .offset = { 0,-2} }, // 90
{ .set = { { 2, 0}, { 3, 0}, { 3, 0}, { 3, 0} }, .reset = { { 0, 0}, { 1, 2}, { 1, 2}, { 1, 2} }, .offset = { 1, 0} }, // 180
{ .set = { { 2, 2}, { 2, 3}, { 2, 3}, { 2, 3} }, .reset = { { 0, 1}, { 2, 0}, { 2, 0}, { 2, 0} }, .offset = { 1, 1} }, // 270
},
{
// rotate right
{ .set = { { 0, 3}, { 2, 2}, { 2, 2}, { 2, 2} }, .reset = { { 0, 0}, { 0, 1}, { 0, 1}, { 0, 1} }, .offset = { 0, 2} }, // 0
{ .set = { {-1, 0}, { 0, 2}, { 0, 2}, { 0, 2} }, .reset = { { 1, 0}, { 2, 0}, { 2, 0}, { 2, 0} }, .offset = {-1, 0} }, // 90
{ .set = { {-1, 0}, { 1,-1}, { 1,-1}, { 1,-1} }, .reset = { { 1, 1}, { 1, 2}, { 1, 2}, { 1, 2} }, .offset = {-1,-1} }, // 180
{ .set = { { 2,-1}, { 3, 1}, { 3, 1}, { 3, 1} }, .reset = { { 0, 1}, { 1, 1}, { 1, 1}, { 1, 1} }, .offset = { 2,-1} }, // 270
},
}
},
{ // J
.color = _blue,
.nullRotation = 0,
.draw = { { 0, 2}, { 1, 0}, { 1, 1}, { 1, 2} },
.motion = {
{
// move down
{ .set = { { 0, 3}, { 1, 3}, { 1, 3}, { 1, 3} }, .reset = { { 0, 2}, { 1, 0}, { 1, 0}, { 1, 0} }, .offset = { 0, 1} }, // 0
{ .set = { { 0, 2}, { 1, 2}, { 2, 2}, { 2, 2} }, .reset = { { 0, 0}, { 1, 1}, { 2, 1}, { 2, 1} }, .offset = { 0, 1} }, // 90
{ .set = { { 0, 3}, { 1, 1}, { 1, 1}, { 1, 1} }, .reset = { { 0, 0}, { 1, 0}, { 1, 0}, { 1, 0} }, .offset = { 0, 1} }, // 180
{ .set = { { 0, 1}, { 1, 1}, { 2, 2}, { 2, 2} }, .reset = { { 0, 0}, { 1, 0}, { 2, 0}, { 2, 0} }, .offset = { 0, 1} }, // 270
},
{
// move left
{ .set = { { 0, 0}, { 0, 1}, {-1, 2}, {-1, 2} }, .reset = { { 1, 0}, { 1, 1}, { 1, 2}, { 1, 2} }, .offset = {-1, 0} }, // 0
{ .set = { {-1, 0}, {-1, 1}, {-1, 1}, {-1, 1} }, .reset = { { 0, 0}, { 2, 1}, { 2, 1}, { 2, 1} }, .offset = {-1, 0} }, // 90
{ .set = { {-1, 0}, {-1, 1}, {-1, 2}, {-1, 2} }, .reset = { { 1, 0}, { 0, 1}, { 0, 2}, { 0, 2} }, .offset = {-1, 0} }, // 180
{ .set = { {-1, 0}, { 1, 1}, { 1, 1}, { 1, 1} }, .reset = { { 2, 0}, { 2, 1}, { 2, 1}, { 2, 1} }, .offset = {-1, 0} }, // 270
},
{
// move right
{ .set = { { 2, 0}, { 2, 1}, { 2, 2}, { 2, 2} }, .reset = { { 1, 0}, { 1, 1}, { 0, 2}, { 0, 2} }, .offset = { 1, 0} }, // 0
{ .set = { { 1, 0}, { 3, 1}, { 3, 1}, { 3, 1} }, .reset = { { 0, 0}, { 0, 1}, { 0, 1}, { 0, 1} }, .offset = { 1, 0} }, // 90
{ .set = { { 1, 1}, { 1, 2}, { 2, 0}, { 2, 0} }, .reset = { { 0, 0}, { 0, 1}, { 0, 2}, { 0, 2} }, .offset = { 1, 0} }, // 180
{ .set = { { 3, 0}, { 3, 1}, { 3, 1}, { 3, 1} }, .reset = { { 0, 0}, { 2, 1}, { 2, 1}, { 2, 1} }, .offset = { 1, 0} }, // 270
},
{
// rotate left
{ .set = { { 1, 3}, {-1, 2}, {-1, 2}, {-1, 2} }, .reset = { { 1, 0}, { 1, 1}, { 0, 0}, { 0, 0} }, .offset = {-1, 2} }, // 0
{ .set = { {-1, 1}, { 0,-1}, { 0,-1}, { 0,-1} }, .reset = { { 1, 1}, { 2, 1}, { 2, 1}, { 2, 1} }, .offset = {-1,-1} }, // 90
{ .set = { { 2, 0}, { 0,-1}, { 0,-1}, { 0,-1} }, .reset = { { 0, 1}, { 0, 2}, { 0, 2}, { 0, 2} }, .offset = { 0,-1} }, // 180
{ .set = { { 2, 2}, { 3, 0}, { 3, 0}, { 3, 0} }, .reset = { { 0, 0}, { 1, 0}, { 1, 0}, { 1, 0} }, .offset = { 2, 0} }, // 270
},
{
// rotate right
{ .set = { { 2, 2}, { 3, 2}, { 3, 2}, { 3, 2} }, .reset = { { 1, 0}, { 0, 2}, { 0, 2}, { 0, 2} }, .offset = { 1, 1} }, // 0
{ .set = { { 0, 2}, { 0, 3}, { 0, 3}, { 0, 3} }, .reset = { { 0, 0}, { 2, 1}, { 2, 1}, { 2, 1} }, .offset = { 0, 1} }, // 90
{ .set = { {-1, 0}, {-2, 0}, {-2, 0}, {-2, 0} }, .reset = { { 1, 0}, { 0, 2}, { 0, 2}, { 0, 2} }, .offset = {-2, 0} }, // 180
{ .set = { { 2,-1}, { 2,-2}, { 2,-2}, { 2,-2} }, .reset = { { 0, 0}, { 2, 1}, { 2, 1}, { 2, 1} }, .offset = { 1,-2} }, // 270
},
}
},
};
const orientation_t nextOrientation[5][4] = { // 5 = number of directions to move, 4 = number of orientation a stone can have
@ -138,20 +350,18 @@ const orientation_t nextOrientation[5][4] = { // 5 = number of directions to mov
};
stone_t stone;
shape_t nextShape;
void shapesInit() {
stone.shape = e_ShapeInvalid;
nextShape = e_Z;
}
void stoneCreate() {
static uint8_t cnt = 0;
stone.shape = ((shape_t[]){ e_I, e_O, e_T, e_Z, e_S, e_L, e_J })[cnt];
cnt++;
if (cnt > 1) {
cnt = 0;
}
stone.shape = nextShape;
nextShape = ((shape_t[]){ e_I, e_O, e_T, e_Z, e_S, e_L, e_J })[myRandGet() % e_ShapeInvalid];
stone.orientation = e_0;
stone.x = 5;
stone.x = 4;
stone.y = 0;
}
@ -161,39 +371,100 @@ uint8_t stoneIsValid() {
// all of them return 1 in case of success and 0 in case of error
static uint8_t move(direction_t direction) {
// if this is a rotation and the shape is marked with nullRotation (just the O), do nothing
// and return success
if (motions[stone.shape].nullRotation && (direction == e_RotateLeft || direction == e_RotateRight)) {
return 1;
}
if (canvasIsPixelFree(stone.x + motions[stone.shape].motion[direction][stone.orientation].set[0].x, stone.y + motions[stone.shape].motion[direction][stone.orientation].set[0].y) &&
canvasIsPixelFree(stone.x + motions[stone.shape].motion[direction][stone.orientation].set[1].x, stone.y + motions[stone.shape].motion[direction][stone.orientation].set[1].y) &&
canvasIsPixelFree(stone.x + motions[stone.shape].motion[direction][stone.orientation].set[2].x, stone.y + motions[stone.shape].motion[direction][stone.orientation].set[2].y) &&
canvasIsPixelFree(stone.x + motions[stone.shape].motion[direction][stone.orientation].set[3].x, stone.y + motions[stone.shape].motion[direction][stone.orientation].set[3].y)) {
canvasSetPixel(stone.x + motions[stone.shape].motion[direction][stone.orientation].reset[0].x, stone.y + motions[stone.shape].motion[direction][stone.orientation].reset[0].y, _off);
canvasSetPixel(stone.x + motions[stone.shape].motion[direction][stone.orientation].reset[1].x, stone.y + motions[stone.shape].motion[direction][stone.orientation].reset[1].y, _off);
canvasSetPixel(stone.x + motions[stone.shape].motion[direction][stone.orientation].reset[2].x, stone.y + motions[stone.shape].motion[direction][stone.orientation].reset[2].y, _off);
canvasSetPixel(stone.x + motions[stone.shape].motion[direction][stone.orientation].reset[3].x, stone.y + motions[stone.shape].motion[direction][stone.orientation].reset[3].y, _off);
canvasSetPixel(stone.x + motions[stone.shape].motion[direction][stone.orientation].set[0].x, stone.y + motions[stone.shape].motion[direction][stone.orientation].set[0].y, motions[stone.shape].color);
canvasSetPixel(stone.x + motions[stone.shape].motion[direction][stone.orientation].set[1].x, stone.y + motions[stone.shape].motion[direction][stone.orientation].set[1].y, motions[stone.shape].color);
canvasSetPixel(stone.x + motions[stone.shape].motion[direction][stone.orientation].set[2].x, stone.y + motions[stone.shape].motion[direction][stone.orientation].set[2].y, motions[stone.shape].color);
canvasSetPixel(stone.x + motions[stone.shape].motion[direction][stone.orientation].set[3].x, stone.y + motions[stone.shape].motion[direction][stone.orientation].set[3].y, motions[stone.shape].color);
// check whether the pixels to move to are free
if (canvasIsPixelFree(stone.x + motions[stone.shape].motion[direction][stone.orientation].set[0].x,
stone.y + motions[stone.shape].motion[direction][stone.orientation].set[0].y) &&
canvasIsPixelFree(stone.x + motions[stone.shape].motion[direction][stone.orientation].set[1].x,
stone.y + motions[stone.shape].motion[direction][stone.orientation].set[1].y) &&
canvasIsPixelFree(stone.x + motions[stone.shape].motion[direction][stone.orientation].set[2].x,
stone.y + motions[stone.shape].motion[direction][stone.orientation].set[2].y) &&
canvasIsPixelFree(stone.x + motions[stone.shape].motion[direction][stone.orientation].set[3].x,
stone.y + motions[stone.shape].motion[direction][stone.orientation].set[3].y)) {
// if so, reset the pixels the shape moves away from
canvasSetPixel(stone.x + motions[stone.shape].motion[direction][stone.orientation].reset[0].x,
stone.y + motions[stone.shape].motion[direction][stone.orientation].reset[0].y,
_off);
canvasSetPixel(stone.x + motions[stone.shape].motion[direction][stone.orientation].reset[1].x,
stone.y + motions[stone.shape].motion[direction][stone.orientation].reset[1].y,
_off);
canvasSetPixel(stone.x + motions[stone.shape].motion[direction][stone.orientation].reset[2].x,
stone.y + motions[stone.shape].motion[direction][stone.orientation].reset[2].y,
_off);
canvasSetPixel(stone.x + motions[stone.shape].motion[direction][stone.orientation].reset[3].x,
stone.y + motions[stone.shape].motion[direction][stone.orientation].reset[3].y,
_off);
// and set the pixels the shape moves to to the shape's color
canvasSetPixel(stone.x + motions[stone.shape].motion[direction][stone.orientation].set[0].x,
stone.y + motions[stone.shape].motion[direction][stone.orientation].set[0].y,
motions[stone.shape].color);
canvasSetPixel(stone.x + motions[stone.shape].motion[direction][stone.orientation].set[1].x,
stone.y + motions[stone.shape].motion[direction][stone.orientation].set[1].y,
motions[stone.shape].color);
canvasSetPixel(stone.x + motions[stone.shape].motion[direction][stone.orientation].set[2].x,
stone.y + motions[stone.shape].motion[direction][stone.orientation].set[2].y,
motions[stone.shape].color);
canvasSetPixel(stone.x + motions[stone.shape].motion[direction][stone.orientation].set[3].x,
stone.y + motions[stone.shape].motion[direction][stone.orientation].set[3].y,
motions[stone.shape].color);
// set the new origin of the shape
stone.x += motions[stone.shape].motion[direction][stone.orientation].offset.x;
stone.y += motions[stone.shape].motion[direction][stone.orientation].offset.y;
stone.orientation = (nextOrientation[direction][stone.orientation] == e_Keep) ? stone.orientation : nextOrientation[direction][stone.orientation];
// set the new orientation of the shape, if required
stone.orientation = (nextOrientation[direction][stone.orientation] == e_Keep) ?
stone.orientation :
nextOrientation[direction][stone.orientation];
return 1;
}
return 0;
}
void nextStoneDraw() {
miniCanvasClear();
miniCanvasSetPixel(motions[nextShape].draw[0].x,
motions[nextShape].draw[0].y,
motions[nextShape].color);
miniCanvasSetPixel(motions[nextShape].draw[1].x,
motions[nextShape].draw[1].y,
motions[nextShape].color);
miniCanvasSetPixel(motions[nextShape].draw[2].x,
motions[nextShape].draw[2].y,
motions[nextShape].color);
miniCanvasSetPixel(motions[nextShape].draw[3].x,
motions[nextShape].draw[3].y,
motions[nextShape].color);
}
uint8_t stoneDraw() {
nextStoneDraw();
uint8_t res = 0;
if (canvasIsPixelFree(stone.x + motions[stone.shape].draw[0].x, stone.y + motions[stone.shape].draw[0].y) &&
canvasIsPixelFree(stone.x + motions[stone.shape].draw[1].x, stone.y + motions[stone.shape].draw[1].y) &&
canvasIsPixelFree(stone.x + motions[stone.shape].draw[2].x, stone.y + motions[stone.shape].draw[2].y) &&
canvasIsPixelFree(stone.x + motions[stone.shape].draw[3].x, stone.y + motions[stone.shape].draw[3].y)) {
canvasSetPixel(stone.x + motions[stone.shape].draw[0].x, stone.y + motions[stone.shape].draw[0].y, motions[stone.shape].color);
canvasSetPixel(stone.x + motions[stone.shape].draw[1].x, stone.y + motions[stone.shape].draw[1].y, motions[stone.shape].color);
canvasSetPixel(stone.x + motions[stone.shape].draw[2].x, stone.y + motions[stone.shape].draw[2].y, motions[stone.shape].color);
canvasSetPixel(stone.x + motions[stone.shape].draw[3].x, stone.y + motions[stone.shape].draw[3].y, motions[stone.shape].color);
// check if the pixels the shape should be drawn at are free
if (canvasIsPixelFree(stone.x + motions[stone.shape].draw[0].x,
stone.y + motions[stone.shape].draw[0].y) &&
canvasIsPixelFree(stone.x + motions[stone.shape].draw[1].x,
stone.y + motions[stone.shape].draw[1].y) &&
canvasIsPixelFree(stone.x + motions[stone.shape].draw[2].x,
stone.y + motions[stone.shape].draw[2].y) &&
canvasIsPixelFree(stone.x + motions[stone.shape].draw[3].x,
stone.y + motions[stone.shape].draw[3].y)) {
// if so, draw the shape
canvasSetPixel(stone.x + motions[stone.shape].draw[0].x,
stone.y + motions[stone.shape].draw[0].y,
motions[stone.shape].color);
canvasSetPixel(stone.x + motions[stone.shape].draw[1].x,
stone.y + motions[stone.shape].draw[1].y,
motions[stone.shape].color);
canvasSetPixel(stone.x + motions[stone.shape].draw[2].x,
stone.y + motions[stone.shape].draw[2].y,
motions[stone.shape].color);
canvasSetPixel(stone.x + motions[stone.shape].draw[3].x,
stone.y + motions[stone.shape].draw[3].y,
motions[stone.shape].color);
res = 1;
}
return res;

50
game-ctrl/spi.c Normal file
View File

@ -0,0 +1,50 @@
#include <msp430g2553.h>
#include "spi.h"
void spiInit() {
// SPI in master mode, most significant bit first
UCB0CTL0 = UCMST | UCMSB;
// SPI timing config
UCB0CTL1 = UCSSEL_3;
// 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.
// 8 was still too fast and caused problems.
UCB0BR0 = 16;
UCB0BR1 = 0;
// BIT5: UCB0CLK
// BIT6: UCB0SOMI
// BIT7: UCB0SIMO
P1SEL |= BIT5 | BIT6 | BIT7;
P1SEL2 |= BIT5 | BIT6 | BIT7;
P1DIR |= BIT5 | BIT7;
// Device Select Lines: 0: Canvas, 1: Display, 2: Sound
P1DIR |= BIT0 | BIT1 | BIT2;
// Disable all of them
P1OUT |= BIT0 | BIT1 | BIT2;
// enable SPI module
UCB0CTL1 &= ~UCSWRST;
}
void spiSendBegin(t_SpiDeviceSelector d) {
uint16_t bit = ((uint16_t[]){ BIT0, BIT1, BIT2 })[d];
P1OUT &= ~bit;
}
void spiSendEnd(t_SpiDeviceSelector d) {
while (UCB0STAT & UCBUSY);
uint16_t bit = ((uint16_t[]){ BIT0, BIT1, BIT2 })[d];
P1OUT |= bit;
}
void spiSendOctet(uint8_t v) {
// wait for TX buffer empty
while (!(UC0IFG & UCB0TXIFG));
// load octet into TX buffer
UCB0TXBUF = v;
}

16
game-ctrl/spi.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef _SPI_H_
#define _SPI_H_
#include <stdint.h>
typedef enum { e_SPI_CANVAS, e_SPI_DISPLAY, e_SPI_SOUND } t_SpiDeviceSelector;
void spiInit();
void spiSendBegin(t_SpiDeviceSelector d);
void spiSendEnd(t_SpiDeviceSelector d);
void spiSendOctet(uint8_t v);
#endif // _SPI_H_

View File

@ -1,16 +0,0 @@
#include <msp430g2553.h>
#include "time.h"
#include "PontCoopScheduler.h"
void __attribute__ ((interrupt (TIMER0_A0_VECTOR))) ta0_isr() {
schUpdate();
}
void timeInit() {
TACCR0 = 32;
TACCTL0 = CCIE;
TACTL = MC_1 | ID_0 | TASSEL_1 | TACLR;
}

View File

@ -1,10 +0,0 @@
#ifndef TIME_H_
#define TIME_H_
#include <stdint.h>
void timeInit();
#endif /* TIME_H_ */

View File

@ -4,7 +4,8 @@ OBJDUMP=$(TOOLCHAIN_PREFIX)/bin/msp430-elf-objdump
MCU=msp430g2553
ARTIFACT=firmware
COMMON=-Wall -mmcu=$(MCU) -std=gnu99 -I $(TOOLCHAIN_PREFIX)/include -Os -g0 -fdata-sections -ffunction-sections -ggdb -gdwarf-2
COMMON=-Wall -mmcu=$(MCU) -std=gnu99 -I $(TOOLCHAIN_PREFIX)/include -Os -g0 -fdata-sections -ffunction-sections
#COMMON+= -ggdb -gdwarf-2 # debug
CFLAGS=$(COMMON)
ASFLAGS=$(COMMON) -D__ASSEMBLER__

10
rgb-driver/canvasSize.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef _CANVAS_SIZE_H_
#define _CANVAS_SIZE_H_
#define CANVAS_WIDTH 10
#define CANVAS_HEIGHT 20
#define MINI_CANVAS_WIDTH 3
#define MINI_CANVAS_HEIGHT 4
#endif // _CANVAS_SIZE_H_

View File

@ -1,5 +1,7 @@
#include <msp430g2553.h>
#include "colors.h"
#include "canvasSize.h"
#define PC r0
#define SP r1
@ -59,13 +61,11 @@
.section ".data"
screendata:
.rept 110 ;; number of leds in hardward
.rept (CANVAS_HEIGHT*CANVAS_WIDTH) + (MINI_CANVAS_HEIGHT*MINI_CANVAS_WIDTH) ;; number of leds in hardward
.byte 0
.endr
screendataend:
.byte 0xff
data_forward_pointer:
.word 0
;; .text is the name of the section, it is a hint for the linker to
@ -96,11 +96,12 @@ init:
;; BIT3: Signal waiting for data
mov.b #BIT0|BIT1|BIT2|BIT3, &P1DIR
mov.b #0,&P1OUT
;; BIT4: spi, UCB0STE
;; BIT5: spi, UCB0CLK
;; BIT6: spi, UCB0SOMI
;; BIT7: spi, UCB0SIMO
mov.b #BIT5|BIT6|BIT7, &P1SEL
mov.b #BIT5|BIT6|BIT7, &P1SEL2
mov.b #BIT4|BIT5|BIT6|BIT7, &P1SEL
mov.b #BIT4|BIT5|BIT6|BIT7, &P1SEL2
;; BIT4: long pulse
;; BIT1: short pulse
mov.b #BIT1|BIT4,&P2DIR
@ -121,8 +122,8 @@ init:
mov.w #OUTMOD_7,&TA1CCTL2
;; spi configuration
;; USCI B to slave mode
mov.b #UCSYNC, &UCB0CTL0
;; USCI B to slave mode, enable STE and most significant bit first
mov.b #UCSYNC|UCMODE_2|UCMSB, &UCB0CTL0
mov.b #0x00, &UCB0CTL1
;; make sure the isr will not immediately start
@ -136,70 +137,20 @@ init:
;; ----------------------------------------------------
mainloop:
call #forwardscreen_init
call #resetscreen
mainloop_draw:
call #drawscreen
;; signal waiting for data
set_signal_waiting_for_data
;call #forwardscreen
;call #wait
call #receivedata
;; data has been received, clear signal
clear_signal_waiting_for_data
jmp mainloop_draw
;; ----------------------------------------------------
wait:
push r11
push r12
mov.w #0x0040, r11
wait_continue_1:
mov.w #0xffff, r12
wait_continue_2:
dec.w r12
jnz wait_continue_2
dec.w r11
jnz wait_continue_1
pop r12
pop r11
ret
;; ----------------------------------------------------
forwardscreen_init:
mov.w #screendata, &data_forward_pointer
ret
;; ----------------------------------------------------
forwardscreen:
push r8
push r10
mov.w #screendataend, r8
mov.w data_forward_pointer, r10
mov.b #_off, @r10
inc.w r10
mov.b #_blue, @r10
cmp.w r10, r8
jnz forwardscreen_done
mov.w #screendata, r10
forwardscreen_done:
mov.w r10, data_forward_pointer
pop r10
pop r8
ret
;; ----------------------------------------------------
resetscreen:
push r7
@ -231,11 +182,6 @@ receivedata_wait_for_control_octet:
;; get control or address octet from buffer register
mov.b UCB0RXBUF, r9
;; check whether value == 0xff (wait for the whole
;; set of data to fill the screendata)
cmp.b #0xff, r9
;; receive all data
jz receivedata_wait_for_all_data
;; check whether value == 0xfe (no more data)
cmp.b #0xfe, r9
;; no more data
@ -253,10 +199,6 @@ receivedata_wait_for_octet:
;; next address/control octet
jmp receivedata_wait_for_control_octet
receivedata_wait_for_all_data:
;; this is a bit dangerous, if the application controller
;; sends too few data, we are in a dead lock
receivedata_end:
pop r10
pop r9

31
sound-driver/Makefile Normal file
View File

@ -0,0 +1,31 @@
TOOLCHAIN_PREFIX=/opt/msp430-gcc
CC=$(TOOLCHAIN_PREFIX)/bin/msp430-elf-gcc
OBJDUMP=$(TOOLCHAIN_PREFIX)/bin/msp430-elf-objdump
ARTIFACT=firmware
MCU=msp430g2553
CFLAGS=-Wall -mmcu=$(MCU) -std=gnu99 -I $(TOOLCHAIN_PREFIX)/include -O1 -g0
# for debugging
CFLAGS+= -g3 -ggdb -gdwarf-2
LDFLAGS=-mmcu=$(MCU) -L $(TOOLCHAIN_PREFIX)/include
$(ARTIFACT).elf: main.o scheduler.o spi.o psg.o sequencer.o melody.o
$(CC) -o $@ $(LDFLAGS) $^
$(OBJDUMP) -D $(ARTIFACT).elf > $(ARTIFACT).txt
.c.o:
$(CC) $(CFLAGS) -c $<
.PHONY: all
all: $(ARTIFACT).elf
.PHONY: clean
clean:
-rm -f *.o $(ARTIFACT).elf $(ARTIFACT).txt
.PHONY: upload
upload: $(ARTIFACT).elf
mspdebug rf2500 "prog $(ARTIFACT).elf"

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

BIN
sound-driver/docs/Registers.pdf Executable file

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,2 @@
target remote localhost:2000
file firmware.elf

37
sound-driver/main.c Normal file
View File

@ -0,0 +1,37 @@
#include <msp430g2553.h>
#include <stdint.h>
#include <stdlib.h>
#include "spi.h"
#include "psg.h"
#include "scheduler.h"
#include "sequencer.h"
#include "melody.h"
int main() {
WDTCTL = WDTPW | WDTHOLD;
__disable_interrupt();
// highest possible system clock
DCOCTL = DCO0 | DCO1 | DCO2;
BCSCTL1 = XT2OFF | RSEL0 | RSEL1 | RSEL2 | RSEL3;
BCSCTL2 = 0;
BCSCTL3 = 0;
schInit();
spiInit();
psgInit();
sequencerInit();
__enable_interrupt();
melodyInit();
while (1) {
schExec();
}
}

729
sound-driver/melody.c Normal file
View File

@ -0,0 +1,729 @@
#include <stdbool.h>
#include "psg.h"
#include "sequencer.h"
const t_tone notes[] = {
{ .octave = e_O_3, .note = e_G, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_D, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_Es, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_F, .length = e_L_1_4, .legato = false, .staccato = false },
// Triller
{ .octave = e_O_3, .note = e_Es, .length = e_L_1_32, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_F, .length = e_L_1_32, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_Es, .length = e_L_1_32, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_F, .length = e_L_1_32, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_D, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_C, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_C, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_Es, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_G, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_F, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_Es, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_D, .length = e_L_1_4, .legato = true , .staccato = false },
{ .octave = e_O_3, .note = e_D, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_Es, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_F, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_G, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_Es, .length = e_L_1_4, .legato = false, .staccato = true },
{ .octave = e_O_3, .note = e_C, .length = e_L_1_4, .legato = false, .staccato = true },
{ .octave = e_O_3, .note = e_C, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_Null, .note = e_Pause, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_Null, .note = e_Pause, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_F, .length = e_L_1_8, .legato = true , .staccato = false },
{ .octave = e_O_3, .note = e_F, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_As, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_C, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_B, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_As, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_G, .length = e_L_1_4, .legato = true , .staccato = false },
{ .octave = e_O_3, .note = e_G, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_Es, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_G, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_F, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_Es, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_D, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_D, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_Es, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_F, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_G, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_Es, .length = e_L_1_4, .legato = false, .staccato = true },
{ .octave = e_O_3, .note = e_C, .length = e_L_1_4, .legato = false, .staccato = true },
{ .octave = e_O_3, .note = e_C, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_Null, .note = e_Pause, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_Null, .note = e_Null, .length = e_L_EndMark, .legato = false, .staccato = false },
};
const t_tone tetris1[] = {
// -------
{ .octave = e_O_5, .note = e_E, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_H, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_C, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_D, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_E, .length = e_L_1_16, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_D, .length = e_L_1_16, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_C, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_H, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_A, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_C, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_E, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_D, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_C, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_H, .length = e_L_1_4, .legato = true, .staccato = false }, // diese und die naechste zusammen: ein punktiertes Viertel
{ .octave = e_O_4, .note = e_H, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_C, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_D, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_E, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_C, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_A, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_A, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_Null, .note = e_Pause, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_D, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_F, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_A, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_G, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_F, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_E, .length = e_L_1_4, .legato = true, .staccato = false }, // punktiert
{ .octave = e_O_5, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_C, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_E, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_D, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_C, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_H, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_H, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_C, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_D, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_E, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_C, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_A, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_A, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_Null, .note = e_Pause, .length = e_L_1_4, .legato = false, .staccato = false },
// -------
{ .octave = e_O_5, .note = e_E, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_H, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_C, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_D, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_E, .length = e_L_1_16, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_D, .length = e_L_1_16, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_C, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_H, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_A, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_C, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_E, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_D, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_C, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_H, .length = e_L_1_4, .legato = true, .staccato = false }, // diese und die naechste zusammen: ein punktiertes Viertel
{ .octave = e_O_4, .note = e_H, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_C, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_D, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_E, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_C, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_A, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_A, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_Null, .note = e_Pause, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_D, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_F, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_A, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_G, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_F, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_E, .length = e_L_1_4, .legato = true, .staccato = false }, // punktiert
{ .octave = e_O_5, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_C, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_E, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_D, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_C, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_H, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_H, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_C, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_D, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_E, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_C, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_A, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_A, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_Null, .note = e_Pause, .length = e_L_1_4, .legato = false, .staccato = false },
// -------
{ .octave = e_O_4, .note = e_E, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_C, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_D, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_H, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_C, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_A, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_Gis, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_H, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_E, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_C, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_D, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_H, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_C, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_E, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_A, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_Gis, .length = e_L_1, .legato = false, .staccato = false },
// -------
{ .octave = e_O_4, .note = e_E, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_C, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_D, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_H, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_C, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_A, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_Gis, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_H, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_E, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_C, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_D, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_H, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_C, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_E, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_A, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_Gis, .length = e_L_1, .legato = false, .staccato = false },
};
const t_tone tetris2[] = {
// -------
{ .octave = e_O_4, .note = e_H, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_H, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_Null, .note = e_Pause, .length = e_L_1_16, .legato = false, .staccato = false },
{ .octave = e_O_Null, .note = e_Pause, .length = e_L_1_16, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_E, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_C, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_H, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_H, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_C, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_A, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_A, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_E, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_Null, .note = e_Pause, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_F, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_C, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_C, .length = e_L_1_16, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_C, .length = e_L_1_16, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_H, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_G, .length = e_L_1_4, .legato = true, .staccato = false }, // punktiert
{ .octave = e_O_4, .note = e_G, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_G, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_A, .length = e_L_1_16, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_G, .length = e_L_1_16, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_F, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_H, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_C, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_E, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_E, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_Null, .note = e_Pause, .length = e_L_1_4, .legato = false, .staccato = false },
// -------
{ .octave = e_O_4, .note = e_H, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_H, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_Null, .note = e_Pause, .length = e_L_1_16, .legato = false, .staccato = false },
{ .octave = e_O_Null, .note = e_Pause, .length = e_L_1_16, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_E, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_C, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_H, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_H, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_C, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_A, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_A, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_E, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_Null, .note = e_Pause, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_F, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_C, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_C, .length = e_L_1_16, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_C, .length = e_L_1_16, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_H, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_G, .length = e_L_1_4, .legato = true, .staccato = false }, // punktiert
{ .octave = e_O_4, .note = e_G, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_G, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_A, .length = e_L_1_16, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_G, .length = e_L_1_16, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_F, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_H, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_5, .note = e_C, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_E, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_E, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_Null, .note = e_Pause, .length = e_L_1_4, .legato = false, .staccato = false },
// -------
{ .octave = e_O_4, .note = e_C, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_A, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_H, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_Gis, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_A, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_D, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_D, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_G, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_C, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_A, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_H, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_Gis, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_A, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_C, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1, .legato = false, .staccato = false },
// -------
{ .octave = e_O_4, .note = e_C, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_A, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_H, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_Gis, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_A, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_D, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_D, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_G, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_4, .note = e_C, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_A, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_H, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_Gis, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_A, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_C, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_2, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1, .legato = false, .staccato = false },
};
const t_tone tetris3[] = {
// -------
{ .octave = e_O_2, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_H, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_C, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_D, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_D, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_Null, .note = e_Pause, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_D, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_Null, .note = e_Pause, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_D, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_F, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_C, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_C, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_Null, .note = e_Pause, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_C, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_C, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_G, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_Null, .note = e_Pause, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_G, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_H, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_H, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_Null, .note = e_Pause, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_H, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_Null, .note = e_Pause, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_Null, .note = e_Pause, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_Null, .note = e_Pause, .length = e_L_1_4, .legato = false, .staccato = false },
// -------
{ .octave = e_O_2, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_H, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_C, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_D, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_D, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_Null, .note = e_Pause, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_D, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_Null, .note = e_Pause, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_D, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_F, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_C, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_C, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_Null, .note = e_Pause, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_C, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_C, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_G, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_Null, .note = e_Pause, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_G, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_H, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_H, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_Null, .note = e_Pause, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_H, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_Null, .note = e_Pause, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_Null, .note = e_Pause, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_4, .legato = false, .staccato = false },
{ .octave = e_O_Null, .note = e_Pause, .length = e_L_1_4, .legato = false, .staccato = false },
// -------
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
// -------
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_A, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_2, .note = e_Gis, .length = e_L_1_8, .legato = false, .staccato = false },
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
};
t_melody melody = {
.pace = 4,
.amplitude = 3,
.channel = 0,
.tones = notes
};
t_melody melodyTetris1 = {
.pace = 4,
.amplitude = 3,
.channel = 0,
.tones = tetris1
};
t_melody melodyTetris2 = {
.pace = 4,
.amplitude = 3,
.channel = 1,
.tones = tetris2
};
t_melody melodyTetris3 = {
.pace = 4,
.amplitude = 3,
.channel = 1,
.tones = tetris3
};
void melodyInit() {
sequencerPlayMelody(&melodyTetris1);
sequencerPlayMelody(&melodyTetris2);
sequencerPlayMelody(&melodyTetris3);
}

8
sound-driver/melody.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef _MELODY_H_
#define _MELODY_H_
void melodyInit();
#endif // _MELODY_H_

163
sound-driver/psg.c Normal file
View File

@ -0,0 +1,163 @@
#include <msp430g2553.h>
#include <stdint.h>
#include <stdlib.h>
#include "psg.h"
#include "scheduler.h"
const uint16_t frequencyCodes[8][12] = {
// C, Cis, D, Dis, E, F, Fis, G, Gis, A, Ais, H
{ 06535, 06234, 05747, 05474, 05233, 05002, 04563, 04353, 04153, 03762, 03600, 03424 }, // Octave 1
{ 03256, 03116, 02764, 02636, 02515, 02401, 02271, 02165, 02065, 01771, 01700, 01612 }, // Octave 2
{ 01527, 01447, 01372, 01317, 01247, 01201, 01135, 01073, 01033, 00774, 00740, 00705 }, // Octave 3
{ 00654, 00624, 00575, 00550, 00523, 00500, 00456, 00435, 00415, 00376, 00360, 00342 }, // Octave 4
{ 00326, 00312, 00276, 00264, 00252, 00240, 00227, 00217, 00207, 00177, 00170, 00161 }, // Octave 5
{ 00153, 00145, 00137, 00132, 00125, 00120, 00114, 00107, 00103, 00100, 00074, 00071 }, // Octave 6
{ 00065, 00062, 00060, 00055, 00052, 00050, 00046, 00044, 00042, 00040, 00036, 00034 }, // Octave 7
{ 00033, 00031, 00030, 00026, 00025, 00024, 00023, 00022, 00021, 00020, 00017, 00016 } // Octave 8
};
#define ADDR_DATA_REG P2OUT
#define BUS_CTRL_REG P1OUT
#define BC1 BIT3
#define BDIR BIT1
#define R0 0
#define CHANNEL_A_TONE_PERIOD_FINE_REG R0
#define R1 1
#define CHANNEL_A_TONE_PERIOD_COARSE_REG R1
#define R2 2
#define CHANNEL_B_TONE_PERIOD_FINE_REG R2
#define R3 3
#define CHANNEL_B_TONE_PERIOD_COARSE_REG R3
#define R4 4
#define CHANNEL_C_TONE_PERIOD_FINE_REG R4
#define R5 5
#define CHANNEL_C_TONE_PERIOD_COARSE_REG R5
#define R6 6
#define NOISE_PERIOD_REG R6
#define R7 7
#define _ENABLE_REG R7
#define R10 010
#define CHANNEL_A_AMPLITUDE_REG R10
#define R11 011
#define CHANNEL_B_AMPLITUDE_REG R11
#define R12 012
#define CHANNEL_C_AMPLITUDE_REG R12
#define R13 013
#define ENVELOPE_PERIOD_FINE_REG R13
#define R14 014
#define ENVELOPE_PERIOD_COARSE_REG R13
#define R15 015
#define ENVELOPE_SHAPE_REG R15
uint8_t psgShadowRegisters[14];
inline static void BUS_OP_NACT() {
BUS_CTRL_REG &= ~(BDIR | BC1);
}
inline static void BUS_OP_INTAK() {
BUS_CTRL_REG |= BDIR | BC1;
}
inline static void BUS_OP_DWS() {
BUS_CTRL_REG |= BDIR;
BUS_CTRL_REG &= ~BC1;
}
static void delay() {
asm volatile (
"push r12\n"
"mov.w #5, r12\n"
"loop:\n"
"dec.w r12\n"
"jnz loop\n"
"pop r12\n"
);
}
uint8_t psgReadShadow(uint8_t address) {
return psgShadowRegisters[address];
}
void psgWrite(uint8_t address, uint8_t data) {
psgShadowRegisters[address] = data;
// according to "State Timing" (p. 15) of datasheet
// put bus into inactive state
BUS_OP_NACT();
// put address on bus
ADDR_DATA_REG = address;
// address latch mode
BUS_OP_INTAK();
// latch address
BUS_OP_NACT();
// put data on bus
ADDR_DATA_REG = data;
// set write to psg
BUS_OP_DWS();
// set inactive again
BUS_OP_NACT();
}
void psgWriteFrequency(uint8_t channel, uint16_t frequencyCode) {
psgWrite(CHANNEL_A_TONE_PERIOD_FINE_REG + (channel * 2), (frequencyCode & 0x00ff));
psgWrite(CHANNEL_A_TONE_PERIOD_COARSE_REG + (channel * 2), ((frequencyCode >> 8) & 0x000f));
}
void psgPlayTone(uint8_t channel, t_octave octave, t_note note) {
if (note == e_Pause) {
psgWrite(_ENABLE_REG, psgReadShadow(_ENABLE_REG) | (1 << channel));
} else {
psgWrite(_ENABLE_REG, psgReadShadow(_ENABLE_REG) & ~(1 << channel));
psgWriteFrequency(channel, frequencyCodes[octave][note]);
}
}
void psgAmplitude(uint8_t channel, uint8_t volume) {
psgWrite(CHANNEL_A_AMPLITUDE_REG + channel, volume);
}
void psgInit() {
// address/data bus
P2DIR = 0xff;
P2SEL = 0;
P2SEL2 = 0;
// sound chip reset
// BIT2: /RST
P1DIR |= BIT2;
// put sound chip into reset state
P1OUT &= ~BIT2;
delay();
delay();
delay();
// bus control lines
// BIT3: BC1
// BIT1: BDIR
P1DIR |= BIT1 | BIT3;
// put bus into inactive state
BUS_CTRL_REG &= ~(BDIR | BC1);
// release sound chip from reset state
P1OUT |= BIT2;
delay();
delay();
delay();
// disable everything
psgWrite(_ENABLE_REG, 0xff);
}

52
sound-driver/psg.h Normal file
View File

@ -0,0 +1,52 @@
#ifndef _PSG_H_
#define _PSG_H_
#include <stdint.h>
typedef enum {
e_O_1 = 0,
e_O_2,
e_O_3,
e_O_4,
e_O_5,
e_O_6,
e_O_7,
e_O_8,
e_O_Null
} t_octave;
typedef enum {
e_C = 0,
e_Cis,
e_D,
e_Dis,
e_E,
e_F,
e_Fis,
e_G,
e_Gis,
e_A,
e_Ais,
e_H,
e_Pause,
e_Null
} t_note;
#define e_Es e_Dis
#define e_As e_Gis
#define e_B e_Ais
void psgInit();
void psgPlayTone(uint8_t channel, t_octave octave, t_note note);
void psgAmplitude(uint8_t channel, uint8_t volume);
// low level
void psgWriteFrequency(uint8_t channel, uint16_t frequencyCode);
// very low level
void psgWrite(uint8_t address, uint8_t data);
uint8_t psgReadShadow(uint8_t address);
#endif // _PSG_H_

92
sound-driver/scheduler.c Normal file
View File

@ -0,0 +1,92 @@
#include <stdlib.h>
#include <msp430g2553.h>
#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--;
}
}
}
}
uint16_t schAdd(void (*exec)(void *), void *handle, uint32_t delay, uint32_t period) {
uint16_t taskId = 0xffff;
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;
taskId = i;
break;
}
}
return taskId;
}
/*
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 schDel(uint16_t taskId) {
tasks[taskId].exec = NULL;
}
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();
}
}
}

28
sound-driver/scheduler.h Normal file
View File

@ -0,0 +1,28 @@
#ifndef PONTCOOPSCHEDULER_H_
#define PONTCOOPSCHEDULER_H_
#include <stdint.h>
#define MAX_NUM_OF_TASKS 8
typedef struct {
uint16_t delay;
uint16_t period;
uint8_t run;
void (*exec)(void *handle);
void *handle;
} tTask;
void schInit();
uint16_t schAdd(void (*exec)(void *), void *handle, uint32_t delay, uint32_t period);
// void schDel(void (*exec)(void *), void *handle);
void schDel(uint16_t taskId);
void schExec();
#endif /* PONTCOOPSCHEDULER_H_ */

60
sound-driver/sequencer.c Normal file
View File

@ -0,0 +1,60 @@
#include "sequencer.h"
#include "scheduler.h"
#include "psg.h"
void sequencerInit() {
}
void sequencerExec(void *handle) {
t_melody *melody = (t_melody*) handle;
switch (melody->state) {
case e_Init:
psgAmplitude(melody->channel, melody->amplitude);
melody->state = e_PlayTone;
break;
case e_PlayTone:
if (melody->tones[melody->idx].length == e_L_EndMark) {
melody->idx = 0;
}
psgPlayTone(melody->channel, melody->tones[melody->idx].octave, melody->tones[melody->idx].note);
melody->lengthCnt = (melody->tones[melody->idx].staccato) ? (melody->tones[melody->idx].length / 2) : melody->tones[melody->idx].length;
melody->state = e_HoldTone;
break;
case e_HoldTone:
melody->lengthCnt -= 1;
if (melody->lengthCnt == 0) {
melody->state = (melody->tones[melody->idx].staccato) ? e_StaccatoBreak : e_SeparateTone;
}
break;
case e_StaccatoBreak:
psgPlayTone(melody->channel, e_O_Null, e_Pause);
melody->lengthCnt = melody->tones[melody->idx].length / 2;
melody->state = e_HoldStaccatoBreak;
break;
case e_HoldStaccatoBreak:
melody->lengthCnt -= 1;
if (melody->lengthCnt == 0) {
melody->state = e_SeparateTone;
}
break;
case e_SeparateTone:
if (! (melody->tones[melody->idx].legato)) {
psgPlayTone(melody->channel, e_O_Null, e_Pause);
}
melody->idx += 1;
melody->state = e_PlayTone;
break;
}
}
uint16_t sequencerPlayMelody(t_melody *melody) {
melody->idx = 0;
melody->lengthCnt = 0;
melody->state = e_Init;
return schAdd(sequencerExec, (void*) melody, 0, melody->pace);
}

50
sound-driver/sequencer.h Normal file
View File

@ -0,0 +1,50 @@
#ifndef _SEQUENCER_H_
#define _SEQUENCER_H_
#include <stdint.h>
#include <stdbool.h>
#include "psg.h"
typedef enum {
e_L_EndMark = 0,
e_L_1 = 320,
e_L_1_2 = 160,
e_L_1_4 = 80,
e_L_1_8 = 40,
e_L_1_16 = 20,
e_L_1_32 = 10,
} t_noteLength;
typedef struct {
t_octave octave;
t_note note;
t_noteLength length;
bool legato;
bool staccato;
} t_tone;
typedef enum {
e_Init,
e_PlayTone,
e_HoldTone,
e_StaccatoBreak,
e_HoldStaccatoBreak,
e_SeparateTone
} t_sequencerState;
typedef struct {
uint16_t idx;
uint8_t lengthCnt;
t_sequencerState state;
uint8_t pace;
uint8_t amplitude;
uint8_t channel;
const t_tone *tones;
} t_melody;
void sequencerInit();
uint16_t sequencerPlayMelody(t_melody *melody);
#endif // _SEQUENCER_H_

29
sound-driver/spi.c Normal file
View File

@ -0,0 +1,29 @@
#include <msp430g2553.h>
#include "spi.h"
void __attribute__ ((interrupt (USCIAB0RX_VECTOR))) receive() {
if (UC0IFG & UCB0RXIFG) {
// receive an octet
}
}
void spiInit() {
// SPI slave
// BIT4: UCB0STE
// BIT5: UCB0CLK
// BIT6: UCB0SOMI
// BIT7: UCB0SIMO
P1SEL |= BIT4 | BIT5 | BIT6 | BIT7;
P1SEL2 |= BIT4 | BIT5 | BIT6 | BIT7;
// most significant bit first, enable STE
UCB0CTL0 = UCSYNC | UCMSB | UCMODE_2;
UCB0CTL1 = 0x00;
// enable RX interrupt
UC0IE |= UCB0RXIE;
}

9
sound-driver/spi.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef _SPI_H_
#define _SPI_H_
void spiInit();
#endif // _SPI_H_