8 Commits

Author SHA1 Message Date
ccd395d6ab config 2024-05-18 20:09:21 +02:00
eb75e31577 different flash 2024-05-18 12:08:18 +02:00
ba4248ff24 flash 2024-05-17 16:08:10 +02:00
2cc5a6a4f3 changes 2024-05-05 21:48:20 +02:00
5c86d55458 dark mode 2024-05-05 17:24:29 +02:00
b9e5813223 flash 2024-05-04 12:58:02 +02:00
1b4a93d9e1 types bigger 2024-05-04 11:35:29 +02:00
30d50dcc5e seems to work but some unpleasant delays 2024-05-04 11:31:27 +02:00
11 changed files with 210 additions and 56 deletions

View File

@ -11,7 +11,7 @@ CFLAGS=-Wall -mmcu=$(MCU) -std=gnu99 -I $(TOOLCHAIN_PREFIX)/include -O1 -g0
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

View File

@ -20,6 +20,14 @@ static uint8_t buttonsMoveLeftPressed() {
return res;
}
bool isConfigMode() {
return (P2IN & BIT4);
}
bool buttonsConfig1Pressed() {
return buttonsMoveLeftPressed();
}
static uint8_t buttonsMoveRightPressed() {
static uint8_t last = 0;
uint8_t current = (P2IN & BIT0);
@ -28,6 +36,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 +48,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,6 +60,11 @@ static uint8_t buttonsRotateRightPressed() {
return res;
}
bool buttonsConfig3Pressed() {
return buttonsRotateRightPressed();
}
static uint8_t buttonsMoveDownPressed() {
return P2IN & BIT2;
}
@ -104,7 +125,9 @@ void buttonsExec(void *handle) {
void buttonsInit() {
P2DIR &= ~(BIT0|BIT1|BIT2|BIT3|BIT4);
}
void buttonsStart() {
schAdd(buttonsExec, NULL, 0, 25);
}

View File

@ -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_

65
game-ctrl/config.c Normal file
View File

@ -0,0 +1,65 @@
#include <stddef.h>
#include "config.h"
#include "canvas.h"
#include "../rgb-driver/colors.h"
#include "scheduler.h"
#include "buttons.h"
#include "eeprom.h"
typedef enum { e_Config_Flash, e_Config_ResetHighscore, e_Config_End } t_ConfigState;
static bool configChanged = false;
static void configHandleFlash() {
canvasSetPixel(0, 1, eepromReadFlashColor());
if (buttonsConfig2Pressed()) {
configChanged = true;
uint8_t color = eepromReadFlashColor() + 1;
if (color == _color_end) {
color = 0;
}
eepromSetFlashColor(color);
}
}
static void configHandleResetHighScore() {
}
void (*configHandler[])(void) = { configHandleFlash, configHandleResetHighScore };
void configExec(void *handle) {
static t_ConfigState configState = e_Config_Flash;
if (buttonsConfig1Pressed()) {
configState += 1;
if (configState == e_Config_End) {
configState = e_Config_Flash;
}
canvasClear();
canvasSetPixel(configState, 0, _red);
}
configHandler[configState]();
if (configChanged) {
canvasSetPixel(0, 2, _red);
if (buttonsConfig4Pressed()) {
eepromCommit();
configChanged = false;
}
} else {
canvasSetPixel(0, 2, _green);
}
canvasShow();
}
void configInit() {
schAdd(configExec, NULL, 0, 25);
}

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

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

View File

@ -3,7 +3,7 @@
#include "spi.h"
#define MAGIC 0xaffe
#define MAGIC 0xafff
#define HIGHSCORE_ADDR 0x00
#define DUMMY 0x00
#define CMD_READ 0b00000011
@ -12,12 +12,15 @@
#define CMD_WREN 0b00000110
typedef struct {
uint16_t magic;
uint16_t highScore;
uint8_t flashColor;
} t_configBlock;
typedef union {
uint8_t buffer[4];
struct {
uint16_t magic;
uint16_t highScore;
} v;
t_configBlock v;
uint8_t buffer[sizeof(t_configBlock)];
} eepromBuf_t;
eepromBuf_t buf;
@ -30,10 +33,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 +45,10 @@ static void readBuf() {
spiReceiveOctet();
spiSendOctet(HIGHSCORE_ADDR);
spiReceiveOctet();
spiSendOctet(DUMMY);
buf.buffer[0] = spiReceiveOctet();
spiSendOctet(DUMMY);
buf.buffer[1] = spiReceiveOctet();
spiSendOctet(DUMMY);
buf.buffer[2] = spiReceiveOctet();
spiSendOctet(DUMMY);
buf.buffer[3] = spiReceiveOctet();
for (uint8_t i = 0; i < sizeof(t_configBlock); i++) {
spiSendOctet(DUMMY);
buf.buffer[i] = spiReceiveOctet();
}
spiSendEnd(e_SPI_EEPROM);
}
@ -60,16 +58,29 @@ void eepromInit() {
if (buf.v.magic != MAGIC) {
buf.v.magic = MAGIC;
buf.v.highScore = 0;
buf.v.flashColor = 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;
}

View File

@ -6,7 +6,10 @@
void eepromInit();
uint16_t eepromReadHighScore();
void eepromWriteHighScore(uint16_t v);
void eepromSetHighScore(uint16_t v);
uint8_t eepromReadFlashColor();
void eepromSetFlashColor(uint8_t v);
void eepromCommit();

View File

@ -1,3 +1,5 @@
// #define STATE_DEBUGGING
#include "stddef.h"
#include "stdint.h"
@ -12,17 +14,18 @@
#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_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;
@ -30,14 +33,17 @@ void gameExec(void *handle) {
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;
bool wipedLines = false;
static uint8_t clearCheckCnt;
#ifdef STATE_DEBUGGING
displaySetValue(state);
#endif
// --- engine begin -------------------------------------------------------
switch (state) {
// --- phase: game --------------------------------------------------------
@ -64,7 +70,6 @@ void gameExec(void *handle) {
case e_DownDelay:
proceedDelay--;
if (proceedDelay == 0) {
rowIndex = 0;
state = e_Down;
}
break;
@ -73,42 +78,64 @@ void gameExec(void *handle) {
if (! stoneMoveDown()) {
soundCtrl(SOUND_LOCK);
stoneLock();
state = e_ClearRows;
state = e_ClearRowInit;
} else {
proceedDelay = delayFactor(level);
state = e_DownDelay;
}
break;
case e_ClearRows:
// clear filled lines
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;
// --- 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;
if (wipedLines) {
soundCtrl(SOUND_PLING);
}
case e_ClearRowFlash:
canvasFillRow(clearCheckCnt, eepromReadFlashColor());
state = e_ClearRowFlashDelay;
break;
if (wipedLines && (filledLines > 0) && ((filledLines % 10) == 0)) {
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_NewStone;
state = e_ClearRowNext;
break;
// --- phase: game over ---------------------------------------------------
@ -146,11 +173,13 @@ void gameExec(void *handle) {
canvasShow();
#ifndef STATE_DEBUGGING
if (isGameActive()) {
displaySetValue(score);
} else {
displaySetValue(eepromReadHighScore());
}
#endif
}
void gameInit() {

View File

@ -13,6 +13,7 @@
#include "spi.h"
#include "display.h"
#include "eeprom.h"
#include "config.h"
int main() {
@ -33,11 +34,16 @@ int main() {
displayInit();
myRandInit();
canvasInit();
shapesInit();
gameInit();
buttonsInit();
if (isConfigMode()) {
configInit();
} else {
shapesInit();
gameInit();
buttonsStart();
}
__enable_interrupt();
while (1) {

View File

@ -1,6 +1,6 @@
#include "colors.h"
#define DIMM_FACTOR 3
#define DIMM_FACTOR 5
.section ".rodata","a"
;; color definitions according to
;; https://learn.sparkfun.com/tutorials/lilypad-protosnap-plus-activity-guide/3-custom-color-mixing
@ -8,7 +8,7 @@ colors:
.global colors
;; red, green, blue, padding
off:
.byte 0x00, 0x00, 0x00, 0
.byte 0x00, 0x00, 0x00, 0 ;; off
blue:
.byte 0x00>>DIMM_FACTOR, 0x00>>DIMM_FACTOR, 0xff>>DIMM_FACTOR, 0
green:
@ -35,4 +35,6 @@ white:
.byte 0xff>>DIMM_FACTOR, 0xff>>DIMM_FACTOR, 0xff>>DIMM_FACTOR, 0
red:
.byte 0xff>>DIMM_FACTOR, 0x00>>DIMM_FACTOR, 0x00>>DIMM_FACTOR, 0
flash:
.byte 0xff, 0xff, 0xff, 0

View File

@ -16,7 +16,8 @@
#define _yellow 0x0b
#define _white 0x0c
#define _red 0x0d
#define _flash 0x0e
#define _color_end 0x0f
#endif