add highscore display

This commit is contained in:
Wolfgang Hottgenroth 2024-04-19 11:38:32 +02:00
parent 7933aa46ae
commit b400431607
12 changed files with 134 additions and 16 deletions

View File

@ -76,7 +76,7 @@ int main() {
P1SEL |= BIT4 | BIT5 | BIT6 | BIT7; P1SEL |= BIT4 | BIT5 | BIT6 | BIT7;
P1SEL2 |= BIT4 | BIT5 | BIT6 | BIT7; P1SEL2 |= BIT4 | BIT5 | BIT6 | BIT7;
// most significant bit first, enable STE // most significant bit first, enable STE
UCB0CTL0 = UCSYNC | UCMSB | UCMODE_2; UCB0CTL0 = UCCKPH | UCSYNC | UCMSB | UCMODE_2;
UCB0CTL1 = 0x00; UCB0CTL1 = 0x00;
// enable RX interrupt // enable RX interrupt
UC0IE |= UCB0RXIE; UC0IE |= UCB0RXIE;

View File

@ -7,11 +7,11 @@ MCU=msp430g2553
CFLAGS=-Wall -mmcu=$(MCU) -std=gnu99 -I $(TOOLCHAIN_PREFIX)/include -O1 -g0 CFLAGS=-Wall -mmcu=$(MCU) -std=gnu99 -I $(TOOLCHAIN_PREFIX)/include -O1 -g0
# for debugging # for debugging
#CFLAGS+= -g3 -ggdb -gdwarf-2 CFLAGS+= -g3 -ggdb -gdwarf-2
LDFLAGS=-mmcu=$(MCU) -L $(TOOLCHAIN_PREFIX)/include 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) $^ $(CC) -o $@ $(LDFLAGS) $^
$(OBJDUMP) -D $(ARTIFACT).elf > $(ARTIFACT).txt $(OBJDUMP) -D $(ARTIFACT).elf > $(ARTIFACT).txt

View File

@ -10,6 +10,8 @@
#include "sound.h" #include "sound.h"
bool mutedFlag = true;
static uint8_t buttonsMoveLeftPressed() { static uint8_t buttonsMoveLeftPressed() {
static uint8_t last = 0; static uint8_t last = 0;
uint8_t current = (P2IN & BIT4); uint8_t current = (P2IN & BIT4);
@ -49,7 +51,6 @@ static uint8_t buttonsMoveDownPressed() {
void buttonsExec(void *handle) { void buttonsExec(void *handle) {
static uint32_t unmuteTimestamp; static uint32_t unmuteTimestamp;
uint32_t currentTimestamp = getSeconds(); uint32_t currentTimestamp = getSeconds();
static bool mutedFlag = true;
if (! stoneIsValid()) { if (! stoneIsValid()) {
@ -107,3 +108,7 @@ void buttonsInit() {
schAdd(buttonsExec, NULL, 0, 25); schAdd(buttonsExec, NULL, 0, 25);
} }
bool isGameActive() {
return ! mutedFlag;
}

View File

@ -1,7 +1,10 @@
#ifndef _BUTTONS_H_ #ifndef _BUTTONS_H_
#define _BUTTONS_H_ #define _BUTTONS_H_
#include <stdbool.h>
void buttonsInit(); void buttonsInit();
bool isGameActive();
#endif // _BUTTONS_H_ #endif // _BUTTONS_H_

75
game-ctrl/eeprom.c Normal file
View File

@ -0,0 +1,75 @@
#include <stdint.h>
#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();
}

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

@ -0,0 +1,13 @@
#ifndef _EEPROM_H_
#define _EEPROM_H_
#include <stdint.h>
void eepromInit();
uint16_t eepromReadHighScore();
void eepromWriteHighScore(uint16_t v);
#endif // _EEPROM_H_

View File

@ -8,6 +8,8 @@
#include "../rgb-driver/colors.h" #include "../rgb-driver/colors.h"
#include "display.h" #include "display.h"
#include "sound.h" #include "sound.h"
#include "eeprom.h"
#include "buttons.h"
#define GAME_CYCLE_TIME 100 #define GAME_CYCLE_TIME 100
@ -35,6 +37,7 @@ void gameExec(void *handle) {
static uint8_t proceedDelay; static uint8_t proceedDelay;
static uint8_t level; static uint8_t level;
static uint16_t score; static uint16_t score;
static bool newHighScoreAchieved;
// --- engine begin ------------------------------------------------------- // --- engine begin -------------------------------------------------------
switch (state) { switch (state) {
@ -44,7 +47,7 @@ void gameExec(void *handle) {
soundCtrl(SOUND_START); soundCtrl(SOUND_START);
level = 1; level = 1;
score = 0; score = 0;
displaySetValue(score); newHighScoreAchieved = false;
phase = e_Phase_Game; phase = e_Phase_Game;
state = e_NewStone; state = e_NewStone;
break; break;
@ -91,7 +94,7 @@ void gameExec(void *handle) {
case e_GameOverFill: case e_GameOverFill:
rowIndex--; rowIndex--;
canvasFillRow(rowIndex, _red); canvasFillRow(rowIndex, newHighScoreAchieved ? _green : _red);
if (rowIndex == 0) { if (rowIndex == 0) {
state = e_GameOverWipe; state = e_GameOverWipe;
} }
@ -121,6 +124,10 @@ void gameExec(void *handle) {
for (uint8_t r = 0; r < CANVAS_HEIGHT; r++) { for (uint8_t r = 0; r < CANVAS_HEIGHT; r++) {
if (canvasIsRowFilled(r)) { if (canvasIsRowFilled(r)) {
score += level; score += level;
if (score > eepromReadHighScore()) {
newHighScoreAchieved = true;
eepromWriteHighScore(score);
}
displaySetValue(score); displaySetValue(score);
canvasWipeRow(r); canvasWipeRow(r);
canvasShow(); canvasShow();
@ -131,6 +138,12 @@ void gameExec(void *handle) {
soundCtrl(SOUND_FANFARE); soundCtrl(SOUND_FANFARE);
} }
} }
if (isGameActive()) {
displaySetValue(score);
} else {
displaySetValue(eepromReadHighScore());
}
} }
void gameInit() { void gameInit() {

View File

@ -12,6 +12,7 @@
#include "myrand.h" #include "myrand.h"
#include "spi.h" #include "spi.h"
#include "display.h" #include "display.h"
#include "eeprom.h"
int main() { int main() {
@ -28,6 +29,7 @@ int main() {
schInit(); schInit();
spiInit(); spiInit();
eepromInit();
displayInit(); displayInit();
myRandInit(); myRandInit();
canvasInit(); canvasInit();

View File

@ -3,7 +3,7 @@
void spiInit() { void spiInit() {
// SPI in master mode, most significant bit first // SPI in master mode, most significant bit first
UCB0CTL0 = UCMST | UCMSB; UCB0CTL0 = UCCKPH | UCMST | UCMSB;
// SPI timing config // SPI timing config
UCB0CTL1 = UCSSEL_3; UCB0CTL1 = UCSSEL_3;
// Faster than 8 ends up in strange communication errors // Faster than 8 ends up in strange communication errors
@ -19,25 +19,25 @@ void spiInit() {
// BIT7: UCB0SIMO // BIT7: UCB0SIMO
P1SEL |= BIT5 | BIT6 | BIT7; P1SEL |= BIT5 | BIT6 | BIT7;
P1SEL2 |= BIT5 | BIT6 | BIT7; P1SEL2 |= BIT5 | BIT6 | BIT7;
P1DIR |= BIT5 | BIT7; // P1DIR |= BIT5 | BIT7;
// Device Select Lines: 0: Canvas, 1: Display, 2: Sound // Device Select Lines: 0: Canvas, 1: Display, 2: Sound, 4: EEPROM
P1DIR |= BIT0 | BIT1 | BIT2; P1DIR |= BIT0 | BIT1 | BIT2 | BIT4;
// Disable all of them // Disable all of them
P1OUT |= BIT0 | BIT1 | BIT2; P1OUT |= BIT0 | BIT1 | BIT2 | BIT4;
// enable SPI module // enable SPI module
UCB0CTL1 &= ~UCSWRST; UCB0CTL1 &= ~UCSWRST;
} }
void spiSendBegin(t_SpiDeviceSelector d) { 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; P1OUT &= ~bit;
} }
void spiSendEnd(t_SpiDeviceSelector d) { void spiSendEnd(t_SpiDeviceSelector d) {
while (UCB0STAT & UCBUSY); while (UCB0STAT & UCBUSY);
uint16_t bit = ((uint16_t[]){ BIT0, BIT1, BIT2 })[d]; uint16_t bit = ((uint16_t[]){ BIT0, BIT1, BIT2, BIT4 })[d];
P1OUT |= bit; P1OUT |= bit;
} }
@ -48,3 +48,9 @@ void spiSendOctet(uint8_t v) {
UCB0TXBUF = v; UCB0TXBUF = v;
} }
uint8_t spiReceiveOctet() {
while (!(UC0IFG & UCB0RXIFG));
uint8_t v = UCB0RXBUF;
return v;
}

View File

@ -4,12 +4,13 @@
#include <stdint.h> #include <stdint.h>
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 spiInit();
void spiSendBegin(t_SpiDeviceSelector d); void spiSendBegin(t_SpiDeviceSelector d);
void spiSendEnd(t_SpiDeviceSelector d); void spiSendEnd(t_SpiDeviceSelector d);
void spiSendOctet(uint8_t v); void spiSendOctet(uint8_t v);
uint8_t spiReceiveOctet();

View File

@ -123,7 +123,7 @@ init:
;; spi configuration ;; spi configuration
;; USCI B to slave mode, enable STE and most significant bit first ;; 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 mov.b #0x00, &UCB0CTL1
;; make sure the isr will not immediately start ;; make sure the isr will not immediately start

View File

@ -18,7 +18,7 @@ void spiInit() {
P1SEL2 |= BIT4 | BIT5 | BIT7; P1SEL2 |= BIT4 | BIT5 | BIT7;
// most significant bit first, enable STE // most significant bit first, enable STE
UCB0CTL0 = UCSYNC | UCMSB | UCMODE_2; UCB0CTL0 = UCCKPH | UCSYNC | UCMSB | UCMODE_2;
UCB0CTL1 = 0x00; UCB0CTL1 = 0x00;
// enable RX interrupt // enable RX interrupt