Compare commits
20 Commits
sound_tuni
...
configmode
Author | SHA1 | Date | |
---|---|---|---|
d9769c6b28 | |||
d9fd18d799 | |||
7894359f30 | |||
4cb0a10617 | |||
a92a3beb96 | |||
ccd395d6ab | |||
eb75e31577 | |||
ba4248ff24 | |||
2cc5a6a4f3 | |||
5c86d55458 | |||
b9e5813223 | |||
1b4a93d9e1 | |||
30d50dcc5e | |||
1607dc62dd | |||
78df7eee66 | |||
09fe302e63
|
|||
d28e62fdd3
|
|||
01d4fe3f85
|
|||
5de2761fde | |||
1f807cdb7c |
BIN
docs/IMG_4941.jpg
Normal file
BIN
docs/IMG_4941.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 603 KiB |
BIN
docs/IMG_4958.jpeg
Normal file
BIN
docs/IMG_4958.jpeg
Normal file
Binary file not shown.
After Width: | Height: | Size: 262 KiB |
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 48 KiB |
BIN
docs/sound-driver-2.png
Normal file
BIN
docs/sound-driver-2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 183 KiB |
@ -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 spi.o scheduler.o canvas.o shapes.o game.o buttons.o myrand.o display.o sound.o eeprom.o
|
||||
$(ARTIFACT).elf: main.o spi.o scheduler.o canvas.o shapes.o game.o buttons.o myrand.o display.o sound.o eeprom.o config.o
|
||||
$(CC) -o $@ $(LDFLAGS) $^
|
||||
$(OBJDUMP) -D $(ARTIFACT).elf > $(ARTIFACT).txt
|
||||
|
||||
|
@ -20,6 +20,10 @@ static uint8_t buttonsMoveLeftPressed() {
|
||||
return res;
|
||||
}
|
||||
|
||||
bool buttonsConfig1Pressed() {
|
||||
return buttonsMoveLeftPressed();
|
||||
}
|
||||
|
||||
static uint8_t buttonsMoveRightPressed() {
|
||||
static uint8_t last = 0;
|
||||
uint8_t current = (P2IN & BIT0);
|
||||
@ -28,6 +32,10 @@ static uint8_t buttonsMoveRightPressed() {
|
||||
return res;
|
||||
}
|
||||
|
||||
bool buttonsConfig4Pressed() {
|
||||
return buttonsMoveRightPressed();
|
||||
}
|
||||
|
||||
static uint8_t buttonsRotateLeftPressed() {
|
||||
static uint8_t last = 0;
|
||||
uint8_t current = (P2IN & BIT3);
|
||||
@ -36,6 +44,10 @@ static uint8_t buttonsRotateLeftPressed() {
|
||||
return res;
|
||||
}
|
||||
|
||||
bool buttonsConfig2Pressed() {
|
||||
return buttonsRotateLeftPressed();
|
||||
}
|
||||
|
||||
static uint8_t buttonsRotateRightPressed() {
|
||||
static uint8_t last = 0;
|
||||
uint8_t current = (P2IN & BIT1);
|
||||
@ -44,10 +56,20 @@ static uint8_t buttonsRotateRightPressed() {
|
||||
return res;
|
||||
}
|
||||
|
||||
bool buttonsConfig3Pressed() {
|
||||
return buttonsRotateRightPressed();
|
||||
}
|
||||
|
||||
|
||||
static uint8_t buttonsMoveDownPressed() {
|
||||
return P2IN & BIT2;
|
||||
}
|
||||
|
||||
bool isConfigMode() {
|
||||
return (P2IN & BIT2);
|
||||
}
|
||||
|
||||
|
||||
void buttonsExec(void *handle) {
|
||||
static uint32_t unmuteTimestamp;
|
||||
uint32_t currentTimestamp = getSeconds();
|
||||
@ -104,7 +126,9 @@ void buttonsExec(void *handle) {
|
||||
|
||||
void buttonsInit() {
|
||||
P2DIR &= ~(BIT0|BIT1|BIT2|BIT3|BIT4);
|
||||
}
|
||||
|
||||
void buttonsStart() {
|
||||
schAdd(buttonsExec, NULL, 0, 25);
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,13 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
void buttonsInit();
|
||||
void buttonsStart();
|
||||
bool isGameActive();
|
||||
bool isConfigMode();
|
||||
bool buttonsConfig1Pressed();
|
||||
bool buttonsConfig2Pressed();
|
||||
bool buttonsConfig3Pressed();
|
||||
bool buttonsConfig4Pressed();
|
||||
|
||||
|
||||
#endif // _BUTTONS_H_
|
||||
|
@ -5,6 +5,8 @@
|
||||
|
||||
#include "canvas.h"
|
||||
#include "spi.h"
|
||||
#include "eeprom.h"
|
||||
#include "../rgb-driver/colors.h"
|
||||
|
||||
|
||||
static uint8_t canvasStorage[CANVAS_WIDTH * CANVAS_HEIGHT];
|
||||
@ -22,6 +24,8 @@ const canvas_t miniCanvas = {
|
||||
};
|
||||
|
||||
void canvasShow() {
|
||||
uint8_t brightness_offset = _brightness_offset * eepromReadBrightness();
|
||||
|
||||
// wait for signal waiting for data
|
||||
while (!(P1IN & BIT3));
|
||||
|
||||
@ -31,14 +35,14 @@ void canvasShow() {
|
||||
if ((*((canvas.canvas)+i) & 0x80) != 0) {
|
||||
*((canvas.canvas)+i) &= ~0x80;
|
||||
spiSendOctet(i);
|
||||
spiSendOctet(*((canvas.canvas)+i));
|
||||
spiSendOctet((*((canvas.canvas)+i) == 0) ? 0 : (*((canvas.canvas)+i) + brightness_offset));
|
||||
}
|
||||
}
|
||||
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((*((miniCanvas.canvas)+i) == 0) ? 0 : (*((miniCanvas.canvas)+i) + brightness_offset));
|
||||
}
|
||||
}
|
||||
spiSendOctet(0xfe);
|
||||
|
91
game-ctrl/config.c
Normal file
91
game-ctrl/config.c
Normal file
@ -0,0 +1,91 @@
|
||||
#include <stddef.h>
|
||||
#include "config.h"
|
||||
#include "canvas.h"
|
||||
#include "../rgb-driver/colors.h"
|
||||
#include "scheduler.h"
|
||||
#include "buttons.h"
|
||||
#include "eeprom.h"
|
||||
#include "display.h"
|
||||
#include "shapes.h"
|
||||
|
||||
|
||||
static bool configChanged = false;
|
||||
|
||||
static void configHandleFlash() {
|
||||
if (buttonsConfig2Pressed()) {
|
||||
configChanged = true;
|
||||
uint8_t color = eepromReadFlashColor() + 1;
|
||||
if (color > _color_end) {
|
||||
color = 0;
|
||||
}
|
||||
canvasFillRow(CANVAS_HEIGHT-1, color);
|
||||
displaySetValue(color);
|
||||
eepromSetFlashColor(color);
|
||||
}
|
||||
}
|
||||
|
||||
static void configHandleResetHighScore() {
|
||||
displaySetValue(eepromReadHighScore());
|
||||
|
||||
if (buttonsConfig2Pressed()) {
|
||||
configChanged = true;
|
||||
eepromSetHighScore(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void configHandleBrightness() {
|
||||
displaySetValue(eepromReadBrightness());
|
||||
|
||||
if (buttonsConfig2Pressed()) {
|
||||
configChanged = true;
|
||||
uint8_t brightness = eepromReadBrightness() + 1;
|
||||
if (brightness > _brightness_shifts) {
|
||||
brightness = 0;
|
||||
}
|
||||
eepromSetBrightness(brightness);
|
||||
|
||||
stoneDrawConfigPattern();
|
||||
}
|
||||
}
|
||||
|
||||
void (*configHandler[])(void) = { configHandleFlash, configHandleResetHighScore, configHandleBrightness };
|
||||
|
||||
|
||||
void configExec(void *handle) {
|
||||
static uint8_t configState = 0;
|
||||
static uint8_t lastConfigState = 255;
|
||||
|
||||
if (configState != lastConfigState) {
|
||||
lastConfigState = configState;
|
||||
|
||||
miniCanvasClear();
|
||||
canvasClear();
|
||||
miniCanvasSetPixel(configState, 0, _red);
|
||||
}
|
||||
|
||||
if (buttonsConfig1Pressed()) {
|
||||
configState += 1;
|
||||
if (configState >= sizeof(configHandler) / sizeof(configHandler[0])) {
|
||||
configState = 0;
|
||||
}
|
||||
}
|
||||
|
||||
configHandler[configState]();
|
||||
|
||||
if (configChanged) {
|
||||
miniCanvasSetPixel(0, 2, _red);
|
||||
if (buttonsConfig4Pressed()) {
|
||||
eepromCommit();
|
||||
configChanged = false;
|
||||
}
|
||||
} else {
|
||||
miniCanvasSetPixel(0, 2, _green);
|
||||
}
|
||||
|
||||
canvasShow();
|
||||
}
|
||||
|
||||
|
||||
void configInit() {
|
||||
schAdd(configExec, NULL, 0, 25);
|
||||
}
|
8
game-ctrl/config.h
Normal file
8
game-ctrl/config.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef _CONFIG_H_
|
||||
#define _CONFIG_H_
|
||||
|
||||
|
||||
void configInit();
|
||||
|
||||
|
||||
#endif // _CONFIG_H_
|
@ -3,7 +3,7 @@
|
||||
#include "spi.h"
|
||||
|
||||
|
||||
#define MAGIC 0xaffe
|
||||
#define MAGIC 0xb000
|
||||
#define HIGHSCORE_ADDR 0x00
|
||||
#define DUMMY 0x00
|
||||
#define CMD_READ 0b00000011
|
||||
@ -12,12 +12,16 @@
|
||||
#define CMD_WREN 0b00000110
|
||||
|
||||
|
||||
typedef union {
|
||||
uint8_t buffer[4];
|
||||
struct {
|
||||
typedef struct {
|
||||
uint16_t magic;
|
||||
uint16_t highScore;
|
||||
} v;
|
||||
uint8_t flashColor;
|
||||
uint8_t brightness;
|
||||
} t_configBlock;
|
||||
|
||||
typedef union {
|
||||
t_configBlock v;
|
||||
uint8_t buffer[sizeof(t_configBlock)];
|
||||
} eepromBuf_t;
|
||||
|
||||
eepromBuf_t buf;
|
||||
@ -30,10 +34,9 @@ static void writeBuf() {
|
||||
spiSendBegin(e_SPI_EEPROM);
|
||||
spiSendOctet(CMD_WRITE);
|
||||
spiSendOctet(HIGHSCORE_ADDR);
|
||||
spiSendOctet(buf.buffer[0]);
|
||||
spiSendOctet(buf.buffer[1]);
|
||||
spiSendOctet(buf.buffer[2]);
|
||||
spiSendOctet(buf.buffer[3]);
|
||||
for (uint8_t i = 0; i < sizeof(t_configBlock); i++) {
|
||||
spiSendOctet(buf.buffer[i]);
|
||||
}
|
||||
spiSendEnd(e_SPI_EEPROM);
|
||||
}
|
||||
|
||||
@ -43,14 +46,10 @@ static void readBuf() {
|
||||
spiReceiveOctet();
|
||||
spiSendOctet(HIGHSCORE_ADDR);
|
||||
spiReceiveOctet();
|
||||
for (uint8_t i = 0; i < sizeof(t_configBlock); i++) {
|
||||
spiSendOctet(DUMMY);
|
||||
buf.buffer[0] = spiReceiveOctet();
|
||||
spiSendOctet(DUMMY);
|
||||
buf.buffer[1] = spiReceiveOctet();
|
||||
spiSendOctet(DUMMY);
|
||||
buf.buffer[2] = spiReceiveOctet();
|
||||
spiSendOctet(DUMMY);
|
||||
buf.buffer[3] = spiReceiveOctet();
|
||||
buf.buffer[i] = spiReceiveOctet();
|
||||
}
|
||||
spiSendEnd(e_SPI_EEPROM);
|
||||
}
|
||||
|
||||
@ -60,16 +59,38 @@ void eepromInit() {
|
||||
if (buf.v.magic != MAGIC) {
|
||||
buf.v.magic = MAGIC;
|
||||
buf.v.highScore = 0;
|
||||
buf.v.flashColor = 0;
|
||||
buf.v.brightness = 0;
|
||||
writeBuf();
|
||||
}
|
||||
}
|
||||
|
||||
void eepromCommit() {
|
||||
writeBuf();
|
||||
}
|
||||
|
||||
uint16_t eepromReadHighScore() {
|
||||
return buf.v.highScore;
|
||||
}
|
||||
|
||||
void eepromWriteHighScore(uint16_t v) {
|
||||
void eepromSetHighScore(uint16_t v) {
|
||||
buf.v.highScore = v;
|
||||
writeBuf();
|
||||
}
|
||||
|
||||
uint8_t eepromReadFlashColor() {
|
||||
return buf.v.flashColor;
|
||||
}
|
||||
|
||||
void eepromSetFlashColor(uint8_t v) {
|
||||
buf.v.flashColor = v;
|
||||
}
|
||||
|
||||
uint8_t eepromReadBrightness() {
|
||||
return buf.v.brightness;
|
||||
}
|
||||
|
||||
void eepromSetBrightness(uint8_t v) {
|
||||
buf.v.brightness = v;
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,12 @@
|
||||
|
||||
void eepromInit();
|
||||
uint16_t eepromReadHighScore();
|
||||
void eepromWriteHighScore(uint16_t v);
|
||||
void eepromSetHighScore(uint16_t v);
|
||||
uint8_t eepromReadFlashColor();
|
||||
void eepromSetFlashColor(uint8_t v);
|
||||
uint8_t eepromReadBrightness();
|
||||
void eepromSetBrightness(uint8_t v);
|
||||
void eepromCommit();
|
||||
|
||||
|
||||
|
||||
|
121
game-ctrl/game.c
121
game-ctrl/game.c
@ -1,3 +1,5 @@
|
||||
// #define STATE_DEBUGGING
|
||||
|
||||
#include "stddef.h"
|
||||
#include "stdint.h"
|
||||
|
||||
@ -12,35 +14,36 @@
|
||||
#include "buttons.h"
|
||||
|
||||
|
||||
#define GAME_CYCLE_TIME 50
|
||||
#define GAME_CYCLE_TIME 10
|
||||
#define GAMEOVER_DELAY 10
|
||||
#define MAX_LEVEL 20
|
||||
#define MAX_LEVEL 100
|
||||
|
||||
|
||||
static uint8_t delayFactor(uint8_t level) {
|
||||
static uint16_t delayFactor(uint16_t level) {
|
||||
return MAX_LEVEL + 1 - level;
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
e_Phase_Game, e_Phase_GameOver
|
||||
} phase_t;
|
||||
|
||||
typedef enum {
|
||||
e_Start, e_NewStone, e_Down, e_DownDelay, e_ClearRows,
|
||||
e_Start, e_NewStone, e_Down, e_DownDelay,
|
||||
e_ClearRowInit, e_ClearRowNext, e_ClearRowCheck, e_ClearRowFlash, e_ClearRowFlashDelay, e_ClearRowWipe,
|
||||
e_GameOver, e_GameOverFill, e_GameOverWipe, e_GameOverDelay
|
||||
} state_t;
|
||||
|
||||
void gameExec(void *handle) {
|
||||
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 proceedDelay;
|
||||
static uint16_t level;
|
||||
static uint16_t filledLines;
|
||||
static uint16_t score;
|
||||
static bool newHighScoreAchieved;
|
||||
|
||||
static uint8_t clearCheckCnt;
|
||||
|
||||
#ifdef STATE_DEBUGGING
|
||||
displaySetValue(state);
|
||||
#endif
|
||||
// --- engine begin -------------------------------------------------------
|
||||
switch (state) {
|
||||
// --- phase: game --------------------------------------------------------
|
||||
@ -51,7 +54,6 @@ void gameExec(void *handle) {
|
||||
filledLines = 0;
|
||||
score = 0;
|
||||
newHighScoreAchieved = false;
|
||||
phase = e_Phase_Game;
|
||||
state = e_NewStone;
|
||||
break;
|
||||
|
||||
@ -68,30 +70,78 @@ void gameExec(void *handle) {
|
||||
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()) {
|
||||
soundCtrl(SOUND_LOCK);
|
||||
state = e_NewStone;
|
||||
stoneLock();
|
||||
state = e_ClearRowInit;
|
||||
} else {
|
||||
proceedDelay = delayFactor(level);
|
||||
state = e_DownDelay;
|
||||
}
|
||||
break;
|
||||
|
||||
// --- phase: clear rows --------------------------------------------------
|
||||
case e_ClearRowInit:
|
||||
clearCheckCnt = 0;
|
||||
state = e_ClearRowCheck;
|
||||
break;
|
||||
|
||||
case e_ClearRowNext:
|
||||
if (clearCheckCnt >= CANVAS_HEIGHT) {
|
||||
state = e_NewStone;
|
||||
} else {
|
||||
clearCheckCnt += 1;
|
||||
state = e_ClearRowCheck;
|
||||
}
|
||||
break;
|
||||
|
||||
case e_ClearRowCheck:
|
||||
if (canvasIsRowFilled(clearCheckCnt)) {
|
||||
score += level;
|
||||
if (score > eepromReadHighScore()) {
|
||||
newHighScoreAchieved = true;
|
||||
eepromSetHighScore(score);
|
||||
eepromCommit();
|
||||
}
|
||||
state = e_ClearRowFlash;
|
||||
} else {
|
||||
state = e_ClearRowNext;
|
||||
}
|
||||
break;
|
||||
|
||||
case e_ClearRowFlash:
|
||||
canvasFillRow(clearCheckCnt, eepromReadFlashColor());
|
||||
state = e_ClearRowFlashDelay;
|
||||
break;
|
||||
|
||||
case e_ClearRowFlashDelay:
|
||||
state = e_ClearRowWipe;
|
||||
break;
|
||||
|
||||
case e_ClearRowWipe:
|
||||
canvasWipeRow(clearCheckCnt);
|
||||
filledLines += 1;
|
||||
|
||||
if ((filledLines > 0) && ((filledLines % 10) == 0)) {
|
||||
if (level < MAX_LEVEL) {
|
||||
level += 1;
|
||||
}
|
||||
soundCtrl(SOUND_FANFARE);
|
||||
} else {
|
||||
soundCtrl(SOUND_PLING);
|
||||
}
|
||||
state = e_ClearRowNext;
|
||||
break;
|
||||
|
||||
// --- phase: game over ---------------------------------------------------
|
||||
case e_GameOver:
|
||||
soundCtrl(SOUND_GAMEOVER);
|
||||
rowIndex = CANVAS_HEIGHT;
|
||||
phase = e_Phase_GameOver;
|
||||
state = e_GameOverFill;
|
||||
break;
|
||||
|
||||
@ -121,42 +171,15 @@ void gameExec(void *handle) {
|
||||
}
|
||||
// --- engine end ---------------------------------------------------------
|
||||
|
||||
bool wipedLines = false;
|
||||
canvasShow();
|
||||
if (phase == e_Phase_Game) {
|
||||
for (uint8_t r = 0; r < CANVAS_HEIGHT; r++) {
|
||||
if (canvasIsRowFilled(r)) {
|
||||
score += level;
|
||||
if (score > eepromReadHighScore()) {
|
||||
newHighScoreAchieved = true;
|
||||
eepromWriteHighScore(score);
|
||||
}
|
||||
displaySetValue(score);
|
||||
canvasWipeRow(r);
|
||||
canvasShow();
|
||||
wipedLines = true;
|
||||
filledLines += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (wipedLines) {
|
||||
soundCtrl(SOUND_PLING);
|
||||
}
|
||||
|
||||
if (wipedLines && (filledLines > 0) && ((filledLines % 10) == 0)) {
|
||||
if (level < MAX_LEVEL) {
|
||||
level += 1;
|
||||
}
|
||||
soundCtrl(SOUND_FANFARE);
|
||||
}
|
||||
|
||||
|
||||
#ifndef STATE_DEBUGGING
|
||||
if (isGameActive()) {
|
||||
displaySetValue(score);
|
||||
} else {
|
||||
displaySetValue(eepromReadHighScore());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void gameInit() {
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "spi.h"
|
||||
#include "display.h"
|
||||
#include "eeprom.h"
|
||||
#include "config.h"
|
||||
|
||||
|
||||
int main() {
|
||||
@ -33,10 +34,15 @@ int main() {
|
||||
displayInit();
|
||||
myRandInit();
|
||||
canvasInit();
|
||||
buttonsInit();
|
||||
|
||||
if (isConfigMode()) {
|
||||
configInit();
|
||||
} else {
|
||||
shapesInit();
|
||||
gameInit();
|
||||
buttonsInit();
|
||||
buttonsStart();
|
||||
}
|
||||
|
||||
__enable_interrupt();
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "shapes.h"
|
||||
#include "myrand.h"
|
||||
@ -19,6 +20,7 @@ typedef struct {
|
||||
orientation_t orientation;
|
||||
uint8_t x; // column
|
||||
uint8_t y; // row
|
||||
bool locked;
|
||||
} stone_t;
|
||||
|
||||
typedef struct {
|
||||
@ -363,6 +365,11 @@ void stoneCreate() {
|
||||
stone.orientation = e_0;
|
||||
stone.x = 4;
|
||||
stone.y = 0;
|
||||
stone.locked = false;
|
||||
}
|
||||
|
||||
void stoneLock() {
|
||||
stone.locked = true;
|
||||
}
|
||||
|
||||
uint8_t stoneIsValid() {
|
||||
@ -376,6 +383,12 @@ static uint8_t move(direction_t direction) {
|
||||
if (motions[stone.shape].nullRotation && (direction == e_RotateLeft || direction == e_RotateRight)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// if the stone is already locked, do nothing
|
||||
if (stone.locked) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 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) &&
|
||||
@ -470,6 +483,31 @@ uint8_t stoneDraw() {
|
||||
return res;
|
||||
}
|
||||
|
||||
static void stoneJustDraw(uint8_t x, uint8_t y, shape_t shape) {
|
||||
canvasSetPixel(x + motions[shape].draw[0].x,
|
||||
y + motions[shape].draw[0].y,
|
||||
motions[shape].color);
|
||||
canvasSetPixel(x + motions[shape].draw[1].x,
|
||||
y + motions[shape].draw[1].y,
|
||||
motions[shape].color);
|
||||
canvasSetPixel(x + motions[shape].draw[2].x,
|
||||
y + motions[shape].draw[2].y,
|
||||
motions[shape].color);
|
||||
canvasSetPixel(x + motions[shape].draw[3].x,
|
||||
y + motions[shape].draw[3].y,
|
||||
motions[shape].color);
|
||||
}
|
||||
|
||||
void stoneDrawConfigPattern() {
|
||||
stoneJustDraw(1, 0, e_I);
|
||||
stoneJustDraw(3, 4, e_O);
|
||||
stoneJustDraw(4, 7, e_T);
|
||||
stoneJustDraw(5, 10, e_Z);
|
||||
stoneJustDraw(1, 12, e_S);
|
||||
stoneJustDraw(5, 15, e_L);
|
||||
stoneJustDraw(1, 17, e_J);
|
||||
}
|
||||
|
||||
uint8_t stoneMoveDown() {
|
||||
return move(e_MoveDown);
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
void shapesInit();
|
||||
void stoneCreate();
|
||||
void stoneLock();
|
||||
uint8_t stoneIsValid();
|
||||
uint8_t stoneDraw();
|
||||
uint8_t stoneMoveDown();
|
||||
@ -13,5 +14,6 @@ uint8_t stoneMoveRight();
|
||||
uint8_t stoneRotateLeft();
|
||||
uint8_t stoneRotateRight();
|
||||
|
||||
void stoneDrawConfigPattern();
|
||||
|
||||
#endif // _SHAPES_H_
|
||||
|
10
readme.md
10
readme.md
@ -2,6 +2,14 @@
|
||||
|
||||

|
||||
|
||||
Update Amplifier (separate input circuitry per PSG, it appears, that a silent PSG has a DC level on its output which is summarized to the AC output of the working PSG, so two input circuits with individual couping capacitor):
|
||||
|
||||

|
||||
|
||||
Update of the power switch of the amplifier (at appears, that the small transistor couldn't deliver enough current):
|
||||
|
||||

|
||||
|
||||
This Tetris implementation consists of a hardware and a software (running on that hardware).
|
||||
|
||||
The hardware utilizes four MSP430 microcontrollers for 1.) the game play, 2.) the play ground canvas, 3.) the score display and 4.) the sound effects.
|
||||
@ -54,7 +62,7 @@ An amplifier following the proposal of the AY-3-8913 datasheet is implemented us
|
||||
The clock generator proposed by the AY-3-8913 does not work reliably, so an alternative design from "The Art of Electronics" has been used.
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
|
@ -1,38 +1,55 @@
|
||||
#include "colors.h"
|
||||
|
||||
#define DIMM_FACTOR 3
|
||||
.section ".rodata","a"
|
||||
;; color definitions according to
|
||||
;; https://learn.sparkfun.com/tutorials/lilypad-protosnap-plus-activity-guide/3-custom-color-mixing
|
||||
colors:
|
||||
.global colors
|
||||
;; red, green, blue, padding
|
||||
off:
|
||||
.byte 0x00, 0x00, 0x00, 0
|
||||
blue:
|
||||
.byte 0x00>>DIMM_FACTOR, 0x00>>DIMM_FACTOR, 0xff>>DIMM_FACTOR, 0
|
||||
green:
|
||||
.byte 0x00>>DIMM_FACTOR, 0xff>>DIMM_FACTOR, 0x00>>DIMM_FACTOR, 0
|
||||
orange:
|
||||
.byte 0xff>>DIMM_FACTOR, 0x80>>DIMM_FACTOR, 0x00>>DIMM_FACTOR, 0
|
||||
rose:
|
||||
.byte 0xff>>DIMM_FACTOR, 0x00>>DIMM_FACTOR, 0x80>>DIMM_FACTOR, 0
|
||||
magenta:
|
||||
.byte 0xff>>DIMM_FACTOR, 0x00>>DIMM_FACTOR, 0xff>>DIMM_FACTOR, 0
|
||||
violet:
|
||||
.byte 0x80>>DIMM_FACTOR, 0x00>>DIMM_FACTOR, 0xff>>DIMM_FACTOR, 0
|
||||
azure:
|
||||
.byte 0x00>>DIMM_FACTOR, 0x80>>DIMM_FACTOR, 0xff>>DIMM_FACTOR, 0
|
||||
cyan:
|
||||
.byte 0x00>>DIMM_FACTOR, 0xff>>DIMM_FACTOR, 0xff>>DIMM_FACTOR, 0
|
||||
springgreen:
|
||||
.byte 0x00>>DIMM_FACTOR, 0xff>>DIMM_FACTOR, 0x80>>DIMM_FACTOR, 0
|
||||
chartreuse:
|
||||
.byte 0x80>>DIMM_FACTOR, 0xff>>DIMM_FACTOR, 0x00>>DIMM_FACTOR, 0
|
||||
yellow:
|
||||
.byte 0xff>>DIMM_FACTOR, 0xff>>DIMM_FACTOR, 0x00>>DIMM_FACTOR, 0
|
||||
white:
|
||||
.byte 0xff>>DIMM_FACTOR, 0xff>>DIMM_FACTOR, 0xff>>DIMM_FACTOR, 0
|
||||
red:
|
||||
.byte 0xff>>DIMM_FACTOR, 0x00>>DIMM_FACTOR, 0x00>>DIMM_FACTOR, 0
|
||||
.byte 0x00, 0x00, 0x00, 0 ;; off
|
||||
|
||||
.byte 0x00>>5, 0x00>>5, 0xff>>5, 0 ;; blue
|
||||
.byte 0x00>>5, 0xff>>5, 0x00>>5, 0 ;; green
|
||||
.byte 0xff>>5, 0x80>>5, 0x00>>5, 0 ;; orange
|
||||
.byte 0x80>>5, 0x00>>5, 0xff>>5, 0 ;; violet
|
||||
.byte 0x00>>5, 0xff>>5, 0xff>>5, 0 ;; cyan
|
||||
.byte 0xff>>5, 0xff>>5, 0x00>>5, 0 ;; yellow
|
||||
.byte 0xff>>5, 0x00>>5, 0x00>>5, 0 ;; red
|
||||
.byte 0xff>>5, 0xff>>5, 0xff>>5, 0 ;; white
|
||||
|
||||
.byte 0x00>>4, 0x00>>4, 0xff>>4, 0 ;; blue
|
||||
.byte 0x00>>4, 0xff>>4, 0x00>>4, 0 ;; green
|
||||
.byte 0xff>>4, 0x80>>4, 0x00>>4, 0 ;; orange
|
||||
.byte 0x80>>4, 0x00>>4, 0xff>>4, 0 ;; violet
|
||||
.byte 0x00>>4, 0xff>>4, 0xff>>4, 0 ;; cyan
|
||||
.byte 0xff>>4, 0xff>>4, 0x00>>4, 0 ;; yellow
|
||||
.byte 0xff>>4, 0x00>>4, 0x00>>4, 0 ;; red
|
||||
.byte 0xff>>4, 0xff>>4, 0xff>>4, 0 ;; white
|
||||
|
||||
.byte 0x00>>3, 0x00>>3, 0xff>>3, 0 ;; blue
|
||||
.byte 0x00>>3, 0xff>>3, 0x00>>3, 0 ;; green
|
||||
.byte 0xff>>3, 0x80>>3, 0x00>>3, 0 ;; orange
|
||||
.byte 0x80>>3, 0x00>>3, 0xff>>3, 0 ;; violet
|
||||
.byte 0x00>>3, 0xff>>3, 0xff>>3, 0 ;; cyan
|
||||
.byte 0xff>>3, 0xff>>3, 0x00>>3, 0 ;; yellow
|
||||
.byte 0xff>>3, 0x00>>3, 0x00>>3, 0 ;; red
|
||||
.byte 0xff>>3, 0xff>>3, 0xff>>3, 0 ;; white
|
||||
|
||||
.byte 0x00>>2, 0x00>>2, 0xff>>2, 0 ;; blue
|
||||
.byte 0x00>>2, 0xff>>2, 0x00>>2, 0 ;; green
|
||||
.byte 0xff>>2, 0x80>>2, 0x00>>2, 0 ;; orange
|
||||
.byte 0x80>>2, 0x00>>2, 0xff>>2, 0 ;; violet
|
||||
.byte 0x00>>2, 0xff>>2, 0xff>>2, 0 ;; cyan
|
||||
.byte 0xff>>2, 0xff>>2, 0x00>>2, 0 ;; yellow
|
||||
.byte 0xff>>2, 0x00>>2, 0x00>>2, 0 ;; red
|
||||
.byte 0xff>>2, 0xff>>2, 0xff>>2, 0 ;; white
|
||||
|
||||
.byte 0x00>>1, 0x00>>1, 0xff>>1, 0 ;; blue
|
||||
.byte 0x00>>1, 0xff>>1, 0x00>>1, 0 ;; green
|
||||
.byte 0xff>>1, 0x80>>1, 0x00>>1, 0 ;; orange
|
||||
.byte 0x80>>1, 0x00>>1, 0xff>>1, 0 ;; violet
|
||||
.byte 0x00>>1, 0xff>>1, 0xff>>1, 0 ;; cyan
|
||||
.byte 0xff>>1, 0xff>>1, 0x00>>1, 0 ;; yellow
|
||||
.byte 0xff>>1, 0x00>>1, 0x00>>1, 0 ;; red
|
||||
.byte 0xff>>1, 0xff>>1, 0xff>>1, 0 ;; white
|
||||
|
||||
|
@ -2,21 +2,20 @@
|
||||
#define _COLORS_H_
|
||||
|
||||
|
||||
#define _off 0x00
|
||||
#define _blue 0x01
|
||||
#define _green 0x02
|
||||
#define _orange 0x03
|
||||
#define _rose 0x04
|
||||
#define _magenta 0x05
|
||||
#define _violet 0x06
|
||||
#define _azure 0x07
|
||||
#define _cyan 0x08
|
||||
#define _springgreen 0x09
|
||||
#define _chartreuse 0x0a
|
||||
#define _yellow 0x0b
|
||||
#define _white 0x0c
|
||||
#define _red 0x0d
|
||||
#define _off 0
|
||||
|
||||
#define _blue 1
|
||||
#define _green 2
|
||||
#define _orange 3
|
||||
#define _violet 4
|
||||
#define _cyan 5
|
||||
#define _yellow 6
|
||||
#define _red 7
|
||||
#define _white 8
|
||||
|
||||
#define _brightness_offset 8
|
||||
#define _brightness_shifts 5
|
||||
#define _color_end (_brightness_offset * _brightness_shifts)
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -9,41 +9,17 @@ const t_tone plingVoice1[] = {
|
||||
{ .octave = e_O_5, .note = e_Cis, .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_Dis, .length = e_L_1_16, .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_E, .length = e_L_1_8, .legato = false, .staccato = false },
|
||||
|
||||
{ .octave = e_O_Null, .note = e_Null, .length = e_L_SyncMark,.legato = false, .staccato = false },
|
||||
{ .octave = e_O_Null, .note = e_Null, .length = e_L_StopMark,.legato = false, .staccato = false },
|
||||
|
||||
{ .octave = e_O_Null, .note = e_Null, .length = e_L_EndMark, .legato = false, .staccato = false },
|
||||
};
|
||||
const t_tone plingVoice2[] = {
|
||||
{ .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_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_5, .note = e_Gis, .length = e_L_1_4, .legato = false, .staccato = false },
|
||||
|
||||
{ .octave = e_O_Null, .note = e_Null, .length = e_L_SyncMark,.legato = false, .staccato = false },
|
||||
{ .octave = e_O_Null, .note = e_Null, .length = e_L_HoldMark,.legato = false, .staccato = false },
|
||||
|
||||
{ .octave = e_O_Null, .note = e_Null, .length = e_L_EndMark, .legato = false, .staccato = false },
|
||||
};
|
||||
const t_tone plingVoice3[] = {
|
||||
{ .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_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_5, .note = e_H, .length = e_L_1_4, .legato = false, .staccato = false },
|
||||
|
||||
{ .octave = e_O_Null, .note = e_Null, .length = e_L_SyncMark,.legato = false, .staccato = false },
|
||||
{ .octave = e_O_Null, .note = e_Null, .length = e_L_HoldMark,.legato = false, .staccato = false },
|
||||
|
||||
{ .octave = e_O_Null, .note = e_Null, .length = e_L_EndMark, .legato = false, .staccato = false },
|
||||
};
|
||||
|
||||
t_melodies pling = {
|
||||
.melodies = { { .amplitude = 12, .tones = plingVoice1 }, { .amplitude = 12, .tones = plingVoice2 }, { .amplitude = 12, .tones = plingVoice3 } },
|
||||
.numOfMelodies = 3,
|
||||
.melodies = { { .amplitude = 12, .tones = plingVoice1 } },
|
||||
.numOfMelodies = 1,
|
||||
.pace = 200,
|
||||
.chip = 1
|
||||
};
|
||||
|
@ -8,15 +8,15 @@ void muteInit() {
|
||||
P1DIR |= BIT6;
|
||||
|
||||
// initially, mute
|
||||
P1OUT |= BIT6;
|
||||
}
|
||||
|
||||
void mute() {
|
||||
P1OUT |= BIT6;
|
||||
}
|
||||
|
||||
void unMute() {
|
||||
P1OUT &= ~BIT6;
|
||||
}
|
||||
|
||||
void mute() {
|
||||
P1OUT &= ~BIT6;
|
||||
}
|
||||
|
||||
void unMute() {
|
||||
P1OUT |= BIT6;
|
||||
}
|
||||
|
||||
|
||||
|
@ -96,9 +96,11 @@ void sequencerExec(void *handle) {
|
||||
melody->state = e_PlayTone;
|
||||
break;
|
||||
case e_Hold:
|
||||
psgPlayTone(melodies->chip, channel, 0, e_O_Null, e_Pause);
|
||||
break;
|
||||
case e_Terminate:
|
||||
schDel(melodies->taskId);
|
||||
psgPlayTone(melodies->chip, channel, 0, e_O_Null, e_Pause);
|
||||
slots &= ~(melodies->slotMask);
|
||||
break;
|
||||
}
|
||||
|
Reference in New Issue
Block a user