From b4004316071d08a39c33f7ba3d7a1bb5a5065a8f Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Fri, 19 Apr 2024 11:38:32 +0200 Subject: [PATCH] add highscore display --- display-driver/main.c | 2 +- game-ctrl/Makefile | 4 +-- game-ctrl/buttons.c | 7 +++- game-ctrl/buttons.h | 3 ++ game-ctrl/eeprom.c | 75 +++++++++++++++++++++++++++++++++++++++++ game-ctrl/eeprom.h | 13 +++++++ game-ctrl/game.c | 17 ++++++++-- game-ctrl/main.c | 2 ++ game-ctrl/spi.c | 20 +++++++---- game-ctrl/spi.h | 3 +- rgb-driver/main.S | 2 +- sound-driver/spi_init.c | 2 +- 12 files changed, 134 insertions(+), 16 deletions(-) create mode 100644 game-ctrl/eeprom.c create mode 100644 game-ctrl/eeprom.h diff --git a/display-driver/main.c b/display-driver/main.c index dd2f3b8..8d874bb 100644 --- a/display-driver/main.c +++ b/display-driver/main.c @@ -76,7 +76,7 @@ int main() { P1SEL |= BIT4 | BIT5 | BIT6 | BIT7; P1SEL2 |= BIT4 | BIT5 | BIT6 | BIT7; // most significant bit first, enable STE - UCB0CTL0 = UCSYNC | UCMSB | UCMODE_2; + UCB0CTL0 = UCCKPH | UCSYNC | UCMSB | UCMODE_2; UCB0CTL1 = 0x00; // enable RX interrupt UC0IE |= UCB0RXIE; diff --git a/game-ctrl/Makefile b/game-ctrl/Makefile index a4de91f..9282608 100644 --- a/game-ctrl/Makefile +++ b/game-ctrl/Makefile @@ -7,11 +7,11 @@ MCU=msp430g2553 CFLAGS=-Wall -mmcu=$(MCU) -std=gnu99 -I $(TOOLCHAIN_PREFIX)/include -O1 -g0 # for debugging -#CFLAGS+= -g3 -ggdb -gdwarf-2 +CFLAGS+= -g3 -ggdb -gdwarf-2 LDFLAGS=-mmcu=$(MCU) -L $(TOOLCHAIN_PREFIX)/include -$(ARTIFACT).elf: main.o spi.o scheduler.o canvas.o shapes.o game.o buttons.o myrand.o display.o sound.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 $(CC) -o $@ $(LDFLAGS) $^ $(OBJDUMP) -D $(ARTIFACT).elf > $(ARTIFACT).txt diff --git a/game-ctrl/buttons.c b/game-ctrl/buttons.c index 183caa0..c640a2e 100644 --- a/game-ctrl/buttons.c +++ b/game-ctrl/buttons.c @@ -10,6 +10,8 @@ #include "sound.h" +bool mutedFlag = true; + static uint8_t buttonsMoveLeftPressed() { static uint8_t last = 0; uint8_t current = (P2IN & BIT4); @@ -49,7 +51,6 @@ static uint8_t buttonsMoveDownPressed() { void buttonsExec(void *handle) { static uint32_t unmuteTimestamp; uint32_t currentTimestamp = getSeconds(); - static bool mutedFlag = true; if (! stoneIsValid()) { @@ -107,3 +108,7 @@ void buttonsInit() { schAdd(buttonsExec, NULL, 0, 25); } +bool isGameActive() { + return ! mutedFlag; +} + diff --git a/game-ctrl/buttons.h b/game-ctrl/buttons.h index 5b8a65e..72e9c69 100644 --- a/game-ctrl/buttons.h +++ b/game-ctrl/buttons.h @@ -1,7 +1,10 @@ #ifndef _BUTTONS_H_ #define _BUTTONS_H_ +#include + void buttonsInit(); +bool isGameActive(); #endif // _BUTTONS_H_ diff --git a/game-ctrl/eeprom.c b/game-ctrl/eeprom.c new file mode 100644 index 0000000..605cd97 --- /dev/null +++ b/game-ctrl/eeprom.c @@ -0,0 +1,75 @@ +#include +#include "eeprom.h" +#include "spi.h" + + +#define MAGIC 0xaffe +#define HIGHSCORE_ADDR 0x00 +#define DUMMY 0x00 +#define CMD_READ 0b00000011 +#define CMD_WRITE 0b00000010 +#define CMD_WRDI 0b00000100 +#define CMD_WREN 0b00000110 + + +typedef union { + uint8_t buffer[4]; + struct { + uint16_t magic; + uint16_t highScore; + } v; +} eepromBuf_t; + +eepromBuf_t buf; + +static void writeBuf() { + spiSendBegin(e_SPI_EEPROM); + spiSendOctet(CMD_WREN); + spiSendEnd(e_SPI_EEPROM); + + 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]); + spiSendEnd(e_SPI_EEPROM); +} + +static void readBuf() { + spiSendBegin(e_SPI_EEPROM); + spiSendOctet(CMD_READ); + 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(); + spiSendEnd(e_SPI_EEPROM); +} + +void eepromInit() { + readBuf(); + + if (buf.v.magic != MAGIC) { + buf.v.magic = MAGIC; + buf.v.highScore = 0; + writeBuf(); + } +} + +uint16_t eepromReadHighScore() { + return buf.v.highScore; +} + +void eepromWriteHighScore(uint16_t v) { + buf.v.highScore = v; + writeBuf(); +} + diff --git a/game-ctrl/eeprom.h b/game-ctrl/eeprom.h new file mode 100644 index 0000000..0caf393 --- /dev/null +++ b/game-ctrl/eeprom.h @@ -0,0 +1,13 @@ +#ifndef _EEPROM_H_ +#define _EEPROM_H_ + +#include + + +void eepromInit(); +uint16_t eepromReadHighScore(); +void eepromWriteHighScore(uint16_t v); + + + +#endif // _EEPROM_H_ diff --git a/game-ctrl/game.c b/game-ctrl/game.c index 688de74..fc202f1 100644 --- a/game-ctrl/game.c +++ b/game-ctrl/game.c @@ -8,6 +8,8 @@ #include "../rgb-driver/colors.h" #include "display.h" #include "sound.h" +#include "eeprom.h" +#include "buttons.h" #define GAME_CYCLE_TIME 100 @@ -35,6 +37,7 @@ void gameExec(void *handle) { static uint8_t proceedDelay; static uint8_t level; static uint16_t score; + static bool newHighScoreAchieved; // --- engine begin ------------------------------------------------------- switch (state) { @@ -44,7 +47,7 @@ void gameExec(void *handle) { soundCtrl(SOUND_START); level = 1; score = 0; - displaySetValue(score); + newHighScoreAchieved = false; phase = e_Phase_Game; state = e_NewStone; break; @@ -91,7 +94,7 @@ void gameExec(void *handle) { case e_GameOverFill: rowIndex--; - canvasFillRow(rowIndex, _red); + canvasFillRow(rowIndex, newHighScoreAchieved ? _green : _red); if (rowIndex == 0) { state = e_GameOverWipe; } @@ -121,6 +124,10 @@ void gameExec(void *handle) { 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(); @@ -131,6 +138,12 @@ void gameExec(void *handle) { soundCtrl(SOUND_FANFARE); } } + + if (isGameActive()) { + displaySetValue(score); + } else { + displaySetValue(eepromReadHighScore()); + } } void gameInit() { diff --git a/game-ctrl/main.c b/game-ctrl/main.c index c6814d2..88ff97b 100644 --- a/game-ctrl/main.c +++ b/game-ctrl/main.c @@ -12,6 +12,7 @@ #include "myrand.h" #include "spi.h" #include "display.h" +#include "eeprom.h" int main() { @@ -28,6 +29,7 @@ int main() { schInit(); spiInit(); + eepromInit(); displayInit(); myRandInit(); canvasInit(); diff --git a/game-ctrl/spi.c b/game-ctrl/spi.c index 3dc59d2..751a609 100644 --- a/game-ctrl/spi.c +++ b/game-ctrl/spi.c @@ -3,7 +3,7 @@ void spiInit() { // SPI in master mode, most significant bit first - UCB0CTL0 = UCMST | UCMSB; + UCB0CTL0 = UCCKPH | UCMST | UCMSB; // SPI timing config UCB0CTL1 = UCSSEL_3; // Faster than 8 ends up in strange communication errors @@ -19,25 +19,25 @@ void spiInit() { // BIT7: UCB0SIMO P1SEL |= BIT5 | BIT6 | BIT7; P1SEL2 |= BIT5 | BIT6 | BIT7; - P1DIR |= BIT5 | BIT7; + // P1DIR |= BIT5 | BIT7; - // Device Select Lines: 0: Canvas, 1: Display, 2: Sound - P1DIR |= BIT0 | BIT1 | BIT2; + // Device Select Lines: 0: Canvas, 1: Display, 2: Sound, 4: EEPROM + P1DIR |= BIT0 | BIT1 | BIT2 | BIT4; // Disable all of them - P1OUT |= BIT0 | BIT1 | BIT2; + P1OUT |= BIT0 | BIT1 | BIT2 | BIT4; // enable SPI module UCB0CTL1 &= ~UCSWRST; } void spiSendBegin(t_SpiDeviceSelector d) { - uint16_t bit = ((uint16_t[]){ BIT0, BIT1, BIT2 })[d]; + uint16_t bit = ((uint16_t[]){ BIT0, BIT1, BIT2, BIT4 })[d]; P1OUT &= ~bit; } void spiSendEnd(t_SpiDeviceSelector d) { while (UCB0STAT & UCBUSY); - uint16_t bit = ((uint16_t[]){ BIT0, BIT1, BIT2 })[d]; + uint16_t bit = ((uint16_t[]){ BIT0, BIT1, BIT2, BIT4 })[d]; P1OUT |= bit; } @@ -48,3 +48,9 @@ void spiSendOctet(uint8_t v) { UCB0TXBUF = v; } +uint8_t spiReceiveOctet() { + while (!(UC0IFG & UCB0RXIFG)); + uint8_t v = UCB0RXBUF; + return v; +} + diff --git a/game-ctrl/spi.h b/game-ctrl/spi.h index 9a3efaa..37f252c 100644 --- a/game-ctrl/spi.h +++ b/game-ctrl/spi.h @@ -4,12 +4,13 @@ #include -typedef enum { e_SPI_CANVAS, e_SPI_DISPLAY, e_SPI_SOUND } t_SpiDeviceSelector; +typedef enum { e_SPI_CANVAS, e_SPI_DISPLAY, e_SPI_SOUND, e_SPI_EEPROM } t_SpiDeviceSelector; void spiInit(); void spiSendBegin(t_SpiDeviceSelector d); void spiSendEnd(t_SpiDeviceSelector d); void spiSendOctet(uint8_t v); +uint8_t spiReceiveOctet(); diff --git a/rgb-driver/main.S b/rgb-driver/main.S index 70e7a83..ea03ce1 100644 --- a/rgb-driver/main.S +++ b/rgb-driver/main.S @@ -123,7 +123,7 @@ init: ;; spi configuration ;; USCI B to slave mode, enable STE and most significant bit first - mov.b #UCSYNC|UCMODE_2|UCMSB, &UCB0CTL0 + mov.b #UCCKPH|UCSYNC|UCMODE_2|UCMSB, &UCB0CTL0 mov.b #0x00, &UCB0CTL1 ;; make sure the isr will not immediately start diff --git a/sound-driver/spi_init.c b/sound-driver/spi_init.c index 4f70f12..5d831b1 100644 --- a/sound-driver/spi_init.c +++ b/sound-driver/spi_init.c @@ -18,7 +18,7 @@ void spiInit() { P1SEL2 |= BIT4 | BIT5 | BIT7; // most significant bit first, enable STE - UCB0CTL0 = UCSYNC | UCMSB | UCMODE_2; + UCB0CTL0 = UCCKPH | UCSYNC | UCMSB | UCMODE_2; UCB0CTL1 = 0x00; // enable RX interrupt