8 Commits

22 changed files with 243 additions and 68 deletions

View File

@ -8,6 +8,7 @@
#include "shapes.h"
#include "canvas.h"
#include "sound.h"
#include "eeprom.h"
bool mutedFlag = true;
@ -84,27 +85,22 @@ void buttonsExec(void *handle) {
if (buttonsMoveLeftPressed()) {
stoneMoveLeft();
soundCtrl(SOUND_MOTION);
buttonPressed = 1;
}
if (buttonsMoveRightPressed()) {
stoneMoveRight();
soundCtrl(SOUND_MOTION);
buttonPressed = 1;
}
if (buttonsRotateLeftPressed()) {
stoneRotateLeft();
soundCtrl(SOUND_MOTION);
buttonPressed = 1;
}
if (buttonsRotateRightPressed()) {
stoneRotateRight();
soundCtrl(SOUND_MOTION);
buttonPressed = 1;
}
if (buttonsMoveDownPressed()) {
stoneMoveDown();
soundCtrl(SOUND_MOTION);
buttonPressed = 1;
}
@ -112,6 +108,7 @@ void buttonsExec(void *handle) {
canvasShow();
if (mutedFlag) {
eepromIncGameCounter();
soundCtrl(SOUND_UNMUTE);
mutedFlag = false;
}

View File

@ -7,19 +7,24 @@
#include "eeprom.h"
#include "display.h"
#include "shapes.h"
#include "sound.h"
static bool configChanged = false;
static bool muted = false;
static void configHandleFlash() {
uint8_t color = eepromReadFlashColor();
canvasFillRow(CANVAS_HEIGHT-1, color);
displaySetValue(color);
if (buttonsConfig2Pressed()) {
configChanged = true;
uint8_t color = eepromReadFlashColor() + 1;
color += 1;
if (color > _color_end) {
color = 0;
}
canvasFillRow(CANVAS_HEIGHT-1, color);
displaySetValue(color);
eepromSetFlashColor(color);
}
}
@ -33,8 +38,18 @@ static void configHandleResetHighScore() {
}
}
static void configHandleResetGameCounter() {
displaySetValue(eepromReadGameCounter());
if (buttonsConfig2Pressed()) {
configChanged = true;
eepromClearGameCounter(0);
}
}
static void configHandleBrightness() {
displaySetValue(eepromReadBrightness());
stoneDrawConfigPattern();
if (buttonsConfig2Pressed()) {
configChanged = true;
@ -43,13 +58,35 @@ static void configHandleBrightness() {
brightness = 0;
}
eepromSetBrightness(brightness);
stoneDrawConfigPattern();
}
}
void (*configHandler[])(void) = { configHandleFlash, configHandleResetHighScore, configHandleBrightness };
static void configHandleAmplitude() {
displaySetValue(eepromReadAmplitude());
if (muted) {
muted = false;
soundCtrl(SOUND_START);
soundCtrl(SOUND_UNMUTE);
}
if (buttonsConfig2Pressed()) {
configChanged = true;
uint8_t amplitude = eepromReadAmplitude() + 1;
if (amplitude > 15) {
amplitude = 0;
}
eepromSetAmplitude(amplitude);
soundCtrl(SOUND_COMMAND + SOUND_SUBCMD_AMPLITUDE + amplitude);
}
}
void (*configHandler[])(void) = {
configHandleResetHighScore,
configHandleResetGameCounter,
configHandleFlash,
configHandleBrightness,
configHandleAmplitude
};
void configExec(void *handle) {
static uint8_t configState = 0;
@ -60,7 +97,14 @@ void configExec(void *handle) {
miniCanvasClear();
canvasClear();
miniCanvasSetPixel(configState, 0, _red);
if (! muted) {
muted = true;
soundCtrl(SOUND_MUTE);
}
uint8_t row = configState / 3;
uint8_t column = configState % 3;
miniCanvasSetPixel(column, row, _red);
}
if (buttonsConfig1Pressed()) {
@ -73,13 +117,13 @@ void configExec(void *handle) {
configHandler[configState]();
if (configChanged) {
miniCanvasSetPixel(0, 2, _red);
miniCanvasSetPixel(0, 3, _red);
if (buttonsConfig4Pressed()) {
eepromCommit();
configChanged = false;
}
} else {
miniCanvasSetPixel(0, 2, _green);
miniCanvasSetPixel(0, 3, _green);
}
canvasShow();
@ -87,5 +131,5 @@ void configExec(void *handle) {
void configInit() {
schAdd(configExec, NULL, 0, 25);
schAdd(configExec, NULL, 0, 100);
}

View File

@ -1,9 +1,15 @@
#include <stdint.h>
#include <string.h>
#include <sys/param.h>
#include "eeprom.h"
#include "spi.h"
#include "scheduler.h"
#include "display.h"
#include "canvas.h"
#include "../rgb-driver/colors.h"
#define MAGIC 0xb000
#define MAGIC 0xb003
#define HIGHSCORE_ADDR 0x00
#define DUMMY 0x00
#define CMD_READ 0b00000011
@ -15,8 +21,10 @@
typedef struct {
uint16_t magic;
uint16_t highScore;
uint16_t gameCounter;
uint8_t flashColor;
uint8_t brightness;
uint8_t amplitude;
} t_configBlock;
typedef union {
@ -57,10 +65,8 @@ void eepromInit() {
readBuf();
if (buf.v.magic != MAGIC) {
memset(buf.buffer, 0, sizeof(t_configBlock));
buf.v.magic = MAGIC;
buf.v.highScore = 0;
buf.v.flashColor = 0;
buf.v.brightness = 0;
writeBuf();
}
}
@ -69,6 +75,35 @@ void eepromCommit() {
writeBuf();
}
void eepromShowValues() {
canvasClear();
canvasFillRow(0, _green);
canvasShow();
displaySetValue(buf.v.highScore);
wait(2);
canvasClear();
canvasFillRow(1, _green);
canvasShow();
displaySetValue(MIN(buf.v.gameCounter, 9999));
wait(2);
canvasClear();
canvasFillRow(2, _green);
canvasShow();
displaySetValue(buf.v.flashColor);
wait(2);
canvasClear();
canvasFillRow(3, _green);
canvasShow();
displaySetValue(buf.v.brightness);
wait(2);
canvasClear();
canvasFillRow(4, _green);
canvasShow();
displaySetValue(buf.v.amplitude);
wait(2);
}
uint16_t eepromReadHighScore() {
return buf.v.highScore;
}
@ -94,3 +129,25 @@ void eepromSetBrightness(uint8_t v) {
buf.v.brightness = v;
}
uint8_t eepromReadAmplitude() {
return buf.v.amplitude;
}
void eepromSetAmplitude(uint8_t v) {
buf.v.amplitude = v;
}
uint16_t eepromReadGameCounter() {
return buf.v.gameCounter;
}
void eepromIncGameCounter() {
buf.v.gameCounter += 1;
writeBuf();
}
void eepromClearGameCounter() {
buf.v.gameCounter = 0;
}

View File

@ -5,13 +5,19 @@
void eepromInit();
void eepromCommit();
void eepromShowValues();
uint16_t eepromReadHighScore();
void eepromSetHighScore(uint16_t v);
uint8_t eepromReadFlashColor();
void eepromSetFlashColor(uint8_t v);
uint8_t eepromReadBrightness();
void eepromSetBrightness(uint8_t v);
void eepromCommit();
uint8_t eepromReadAmplitude();
void eepromSetAmplitude(uint8_t v);
void eepromIncGameCounter();
uint16_t eepromReadGameCounter();
void eepromClearGameCounter();

View File

@ -24,13 +24,15 @@ static uint16_t delayFactor(uint16_t level) {
}
typedef enum {
e_BootWait,
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 state_t state = e_Start;
static state_t state = e_BootWait;
static uint16_t bootWaitTime = 2500 / GAME_CYCLE_TIME;
static uint8_t gameOverDelay;
static uint8_t rowIndex;
static uint16_t proceedDelay;
@ -46,6 +48,12 @@ void gameExec(void *handle) {
#endif
// --- engine begin -------------------------------------------------------
switch (state) {
case e_BootWait:
bootWaitTime -= 1;
if (bootWaitTime == 0) {
state = e_Start;
}
break;
// --- phase: game --------------------------------------------------------
case e_Start:
canvasClear();

View File

@ -14,6 +14,7 @@
#include "display.h"
#include "eeprom.h"
#include "config.h"
#include "sound.h"
int main() {
@ -34,8 +35,11 @@ int main() {
displayInit();
myRandInit();
canvasInit();
soundInit();
buttonsInit();
eepromShowValues();
if (isConfigMode()) {
configInit();
} else {

View File

@ -109,3 +109,9 @@ uint32_t getSeconds() {
return s;
}
void wait(uint8_t t) {
uint8_t startTime = getSeconds();
while (getSeconds() < (startTime + t));
}

View File

@ -32,6 +32,6 @@ void schExec();
void schUpdate();
uint8_t schTaskCnt();
uint32_t getSeconds();
void wait(uint8_t t);
#endif /* PONTCOOPSCHEDULER_H_ */

View File

@ -354,14 +354,18 @@ const orientation_t nextOrientation[5][4] = { // 5 = number of directions to mov
stone_t stone;
shape_t nextShape;
static shape_t randomNextShape() {
return ((shape_t[]){ e_I, e_O, e_T, e_Z, e_S, e_L, e_J })[myRandGet() % e_ShapeInvalid];
}
void shapesInit() {
stone.shape = e_ShapeInvalid;
nextShape = e_Z;
nextShape = randomNextShape();
}
void stoneCreate() {
stone.shape = nextShape;
nextShape = ((shape_t[]){ e_I, e_O, e_T, e_Z, e_S, e_L, e_J })[myRandGet() % e_ShapeInvalid];
nextShape = randomNextShape();
stone.orientation = e_0;
stone.x = 4;
stone.y = 0;
@ -452,6 +456,21 @@ void nextStoneDraw() {
motions[nextShape].color);
}
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);
}
uint8_t stoneDraw() {
nextStoneDraw();
@ -466,38 +485,12 @@ uint8_t stoneDraw() {
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);
stoneJustDraw(stone.x, stone.y, stone.shape);
res = 1;
}
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);

View File

@ -1,10 +1,12 @@
#include <stdint.h>
#include "sound.h"
#include "spi.h"
#include "eeprom.h"
void soundInit() {
soundCtrl(SOUND_COMMAND + SOUND_SUBCMD_AMPLITUDE + eepromReadAmplitude());
}

View File

@ -12,7 +12,7 @@ ASFLAGS=$(COMMONFLAGS) -D__ASSEMBLER__
LDFLAGS=-mmcu=$(MCU) -L $(TOOLCHAIN_PREFIX)/include
$(ARTIFACT).elf: main.o scheduler.o spi.o spi_init.o sequencer.o melody_tetris.o melody_tusch1.o psg.o mute.o melody_pling.o
$(ARTIFACT).elf: main.o scheduler.o spi.o spi_init.o sequencer.o melody_tetris.o melody_tusch1.o psg.o mute.o melody_pling.o config.o
$(CC) -o $@ $(LDFLAGS) $^
$(OBJDUMP) -D $(ARTIFACT).elf > $(ARTIFACT).txt

26
sound-driver/config.c Normal file
View File

@ -0,0 +1,26 @@
#include <stdint.h>
#include <sys/param.h>
#include "config.h"
typedef struct {
uint8_t melodyAmplitude;
uint8_t effectsAmplitude;
} config_t;
config_t config;
void configSetAmplitude(uint8_t v) {
config.melodyAmplitude = MIN(v, 15);
config.effectsAmplitude = MIN(v+4, 15);
}
uint8_t *configGetMelodyAmplitudePtr() {
return &(config.melodyAmplitude);
}
uint8_t *configGetEffectsAmplitudePtr() {
return &(config.effectsAmplitude);
}

12
sound-driver/config.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef _CONFIG_H_
#define _CONFIG_H_
#include <stdint.h>
void configSetAmplitude(uint8_t v);
uint8_t *configGetMelodyAmplitudePtr();
uint8_t *configGetEffectsAmplitudePtr();
#endif // _CONFIG_H_

View File

@ -3,6 +3,8 @@
#include "psg.h"
#include "sequencer.h"
#include "scheduler.h"
#include "config.h"
const t_tone plingVoice1[] = {
{ .octave = e_O_5, .note = e_C, .length = e_L_1_16, .legato = false, .staccato = false },
@ -18,13 +20,14 @@ const t_tone plingVoice1[] = {
};
t_melodies pling = {
.melodies = { { .amplitude = 12, .tones = plingVoice1 } },
.melodies = { { .tones = plingVoice1 } },
.numOfMelodies = 1,
.pace = 200,
.chip = 1
};
void playPling() {
pling.amplitude = configGetEffectsAmplitudePtr();
sequencerPlayMelodies(&pling);
}

View File

@ -3,6 +3,7 @@
#include "psg.h"
#include "sequencer.h"
#include "scheduler.h"
#include "config.h"
/*
@ -924,7 +925,7 @@ const t_tone voice3[] = {
#define INITIAL_PACE 160
t_melodies tetrisTheme = {
.melodies = { { .amplitude = 8, .tones = voice1 }, { .amplitude = 8, .tones = voice2 }, { .amplitude = 8, .tones = voice3 } },
.melodies = { { .tones = voice1 }, { .tones = voice2 }, { .tones = voice3 } },
.numOfMelodies = 3,
.pace = INITIAL_PACE,
.chip = 0
@ -932,6 +933,7 @@ t_melodies tetrisTheme = {
void playMelodyTetris() {
tetrisTheme.pace = INITIAL_PACE; // reset to start value each time
tetrisTheme.amplitude = configGetMelodyAmplitudePtr();
sequencerPlayMelodies(&tetrisTheme);
}

View File

@ -5,5 +5,6 @@
void playMelodyTetris();
void stopMelodyTetris();
void playMelodyTetrisFaster();
void playMelodyTetrisAmplitude(uint8_t a);
#endif // _MELODY_TETRIS_H_

View File

@ -3,7 +3,7 @@
#include "psg.h"
#include "sequencer.h"
#include "scheduler.h"
#include "melody_tetris.h"
#include "config.h"
const t_tone tusch1voice1[] = {
{ .octave = e_O_5, .note = e_C, .length = e_L_1_4, .legato = false, .staccato = true },
@ -72,15 +72,15 @@ const t_tone tusch1voice3[] = {
};
t_melodies tusch1 = {
.melodies = { { .amplitude = 12, .tones = tusch1voice1 }, { .amplitude = 12, .tones = tusch1voice2 }, { .amplitude = 12, .tones = tusch1voice3 } },
.melodies = { { .tones = tusch1voice1 }, { .tones = tusch1voice2 }, { .tones = tusch1voice3 } },
.numOfMelodies = 3,
.pace = 200,
.chip = 1
};
void playTusch1() {
tusch1.amplitude = configGetEffectsAmplitudePtr();
sequencerPlayMelodies(&tusch1);
// playMelodyTetrisFaster();
}

View File

@ -59,7 +59,7 @@ void sequencerExec(void *handle) {
if (melody->tones[melody->idx].length == e_L_EndMark) {
melody->idx = 0;
}
psgPlayTone(melodies->chip, channel, melody->amplitude, melody->tones[melody->idx].octave, melody->tones[melody->idx].note);
psgPlayTone(melodies->chip, channel, *(melodies->amplitude), melody->tones[melody->idx].octave, melody->tones[melody->idx].note);
melody->lengthCnt = (melody->tones[melody->idx].staccato) ?
(calcLength(melodies, melody->tones[melody->idx].length) / 2) :
calcLength(melodies, melody->tones[melody->idx].length);

View File

@ -44,7 +44,6 @@ typedef struct {
uint16_t idx;
uint16_t lengthCnt;
t_sequencerState state;
uint8_t amplitude;
const t_tone *tones;
} t_melody;
@ -53,6 +52,7 @@ typedef struct {
typedef struct {
uint8_t slotMask;
uint8_t chip;
uint8_t *amplitude;
uint8_t taskId;
uint16_t quarterLength;
uint8_t numOfMelodies;

View File

@ -8,7 +8,9 @@
#define SOUND_GAMEOVER 0x08
#define SOUND_FANFARE 0x10
#define SOUND_LOCK 0x20
#define SOUND_MOTION 0x40
#define SOUND_PLING 0x80
#define SOUND_PLING 0x40
#define SOUND_COMMAND 0x80
#define SOUND_SUBCMD_AMPLITUDE 0x40
#endif // _SOUND_CODES_H_

View File

@ -6,12 +6,21 @@
receive_isr:
bit #UCB0RXIFG, &UC0IFG
jz receive_isr_no_data
bit #SOUND_COMMAND, &cmd
jnz receive_isr_no_data
bis UCB0RXBUF, &cmd
receive_isr_no_data:
reti
.global spiCmdHandler
spiCmdHandler:
spiCmdHandler_0:
bit #SOUND_COMMAND, &cmd
jz spiCmdHandler_1
;; insert a call here
call #spiCommandDispatcher
mov.b #0, &cmd
ret
spiCmdHandler_1:
bit #SOUND_MUTE, &cmd
jz spiCmdHandler_2
@ -44,11 +53,6 @@ spiCmdHandler_6:
;; insert a call here
bic #SOUND_LOCK, &cmd
spiCmdHandler_7:
bit #SOUND_MOTION, &cmd
jz spiCmdHandler_8
;; insert a call here
bic #SOUND_MOTION, &cmd
spiCmdHandler_8:
bit #SOUND_PLING, &cmd
jz spiCmdHandler_end
call #playPling

View File

@ -4,9 +4,10 @@
#include "scheduler.h"
#include "spi.h"
#include "soundCodes.h"
#include "config.h"
uint8_t cmd;
volatile uint8_t cmd;
void spiInit() {
// SPI slave
@ -25,7 +26,14 @@ void spiInit() {
UC0IE |= UCB0RXIE;
cmd = SOUND_IDLE;
schAdd(spiCmdHandler, NULL, 0, 100);
schAdd(spiCmdHandler, NULL, 0, 5);
}
void spiCommandDispatcher() {
cmd &= ~SOUND_COMMAND;
if (cmd & SOUND_SUBCMD_AMPLITUDE) {
cmd &= ~SOUND_SUBCMD_AMPLITUDE;
configSetAmplitude(cmd);
}
}