From 85d243551ee727225d6004d047874ecaec69d424 Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Fri, 22 Mar 2024 22:49:43 +0100 Subject: [PATCH] score counter --- display-driver/Makefile | 31 ++++++++++ display-driver/main.c | 131 ++++++++++++++++++++++++++++++++++++++++ game-ctrl/display.c | 40 +++--------- game-ctrl/display.h | 2 +- game-ctrl/game.c | 6 +- 5 files changed, 175 insertions(+), 35 deletions(-) create mode 100644 display-driver/Makefile create mode 100644 display-driver/main.c diff --git a/display-driver/Makefile b/display-driver/Makefile new file mode 100644 index 0000000..0f70fcb --- /dev/null +++ b/display-driver/Makefile @@ -0,0 +1,31 @@ +TOOLCHAIN_PREFIX=/opt/msp430-gcc +CC=$(TOOLCHAIN_PREFIX)/bin/msp430-elf-gcc +OBJDUMP=$(TOOLCHAIN_PREFIX)/bin/msp430-elf-objdump + +ARTIFACT=firmware +MCU=msp430g2553 +CFLAGS=-Wall -mmcu=$(MCU) -std=gnu99 -I $(TOOLCHAIN_PREFIX)/include -O1 -g0 + +# for debugging +#CFLAGS+= -g3 -ggdb -gdwarf-2 + +LDFLAGS=-mmcu=$(MCU) -L $(TOOLCHAIN_PREFIX)/include + +$(ARTIFACT).elf: main.o + $(CC) -o $@ $(LDFLAGS) $^ + $(OBJDUMP) -D $(ARTIFACT).elf > $(ARTIFACT).txt + +.c.o: + $(CC) $(CFLAGS) -c $< + + +.PHONY: all +all: $(ARTIFACT).elf + +.PHONY: clean +clean: + -rm -f *.o $(ARTIFACT).elf $(ARTIFACT).txt + +.PHONY: upload +upload: $(ARTIFACT).elf + mspdebug rf2500 "prog $(ARTIFACT).elf" diff --git a/display-driver/main.c b/display-driver/main.c new file mode 100644 index 0000000..dd2f3b8 --- /dev/null +++ b/display-driver/main.c @@ -0,0 +1,131 @@ +#include +#include +#include + + +const uint8_t patterns[] = { + 0b00111111, // 0 + 0b00000110, // 1 + 0b01011011, // 2 + 0b01001111, // 3 + 0b01100110, // 4 + 0b01101101, // 5 + 0b01111101, // 6 + 0b00100111, // 7 + 0b01111111, // 8 + 0b01101111, // 9 +}; + + + +volatile union { + uint16_t value; + uint8_t receiveBuffer[2]; +} value; + + +static void delay() { + asm volatile ( + "push r12\n" + "mov.w #1000, r12\n" + "loop:\n" + "dec.w r12\n" + "jnz loop\n" + "pop r12\n" + ); +} + + +void __attribute__ ((interrupt (USCIAB0RX_VECTOR))) receive() { + static uint8_t octetNumber = 0; + if (UC0IFG & UCB0RXIFG) { + value.receiveBuffer[octetNumber] = UCB0RXBUF; + octetNumber++; + if (octetNumber > 1) { + octetNumber = 0; + } + } +} + +// mask 0x0f: digit value +// mask 0x10: set dp +// mask 0x20: digit off +static void setDigit(uint16_t bit, uint8_t value) { + P1OUT |= (BIT0 | BIT1 | BIT2 | BIT3); + P2OUT = ((value & 0x20) ? 0 : patterns[value & 0x0f]) | ((value & 0x10) ? 0x80 : 0x00); + P1OUT &= ~bit; +} + + +int main() { + WDTCTL = WDTPW | WDTHOLD; + + __disable_interrupt(); + + // highest possible system clock + DCOCTL = DCO0 | DCO1 | DCO2; + BCSCTL1 = XT2OFF | RSEL0 | RSEL1 | RSEL2 | RSEL3; + BCSCTL2 = 0; + BCSCTL3 = 0; + + // SPI slave + // BIT4: UCB0STE + // BIT5: UCB0CLK + // BIT6: UCB0SOMI + // BIT7: UCB0SIMO + P1SEL |= BIT4 | BIT5 | BIT6 | BIT7; + P1SEL2 |= BIT4 | BIT5 | BIT6 | BIT7; + // most significant bit first, enable STE + UCB0CTL0 = UCSYNC | UCMSB | UCMODE_2; + UCB0CTL1 = 0x00; + // enable RX interrupt + UC0IE |= UCB0RXIE; + + // digit driver + P1DIR |= BIT0 | BIT1 | BIT2 | BIT3; + P1SEL &= ~(BIT0 | BIT1 | BIT2 | BIT3); + P1SEL2 &= ~(BIT0 | BIT1 | BIT2 | BIT3); + + // segment driver + P2DIR = 0xff; + P2SEL = 0x00; + P2SEL2 = 0x00; + + // all digits off + P1OUT |= (BIT0 | BIT1 | BIT2 | BIT3); + + // all segments off + P2OUT &= ~(BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7); + + // reset value to 0 + value.value = 0; + + __enable_interrupt(); + + while (1) { + __disable_interrupt(); + uint16_t shadowValue = value.value; + __enable_interrupt(); + + uint8_t digit0 = shadowValue % 10; + uint8_t digit1 = (shadowValue / 10) % 10; + uint8_t digit2 = (shadowValue / 100) % 10; + uint8_t digit3 = (shadowValue / 1000) % 10; + + digit1 += (!((digit3 & 0x0f) | (digit2 & 0x0f) | (digit1 & 0x0f))) ? 0x20 : 0x00; + digit2 += (!((digit3 & 0x0f) | (digit2 & 0x0f))) ? 0x20 : 0x00; + digit3 += (!(digit3 & 0x0f)) ? 0x20 : 0x00; + + setDigit(BIT0, digit0); + delay(); + + setDigit(BIT1, digit1); + delay(); + + setDigit(BIT2, digit2); + delay(); + + setDigit(BIT3, digit3); + delay(); + } +} diff --git a/game-ctrl/display.c b/game-ctrl/display.c index 66695f0..2dc316a 100644 --- a/game-ctrl/display.c +++ b/game-ctrl/display.c @@ -4,47 +4,23 @@ #include "spi.h" -uint16_t score; - void displayInit() { - score = 0; - - spiSendBegin(e_SPI_DISPLAY); - - // display test off - spiSendOctet(0x0f); - spiSendOctet(0x01); - - // BCD decode for all digits - spiSendOctet(0x09); - spiSendOctet(0xff); - - // scan limit to digits 0-3 - spiSendOctet(0x0b); - spiSendOctet(0x03); - - // intensity - spiSendOctet(0x0a); - spiSendOctet(0x0f); - - - // normal operation - spiSendOctet(0x0C); - spiSendOctet(0x01); - - spiSendEnd(e_SPI_DISPLAY); } +void displaySetValue(uint16_t v) { + union { + uint16_t value; + uint8_t sendBuffer[2]; + } value; -void displaySetScore(uint16_t v) { - score = v; + value.value = v; spiSendBegin(e_SPI_DISPLAY); - spiSendOctet(0x01); - spiSendOctet(0x07); + spiSendOctet(value.sendBuffer[0]); + spiSendOctet(value.sendBuffer[1]); spiSendEnd(e_SPI_DISPLAY); } diff --git a/game-ctrl/display.h b/game-ctrl/display.h index e2c2af5..34316c7 100644 --- a/game-ctrl/display.h +++ b/game-ctrl/display.h @@ -5,7 +5,7 @@ void displayInit(); -void displaySetScore(uint16_t v); +void displaySetValue(uint16_t v); diff --git a/game-ctrl/game.c b/game-ctrl/game.c index e8e6b9b..4b266aa 100644 --- a/game-ctrl/game.c +++ b/game-ctrl/game.c @@ -33,6 +33,7 @@ void gameExec(void *handle) { static uint8_t rowIndex; static uint8_t proceedDelay; static uint8_t level; + static uint16_t score; // --- engine begin ------------------------------------------------------- switch (state) { @@ -40,6 +41,7 @@ void gameExec(void *handle) { case e_Start: canvasClear(); level = 1; + score = 0; phase = e_Phase_Game; state = e_NewStone; break; @@ -112,13 +114,13 @@ void gameExec(void *handle) { if (phase == e_Phase_Game) { for (uint8_t r = 0; r < CANVAS_HEIGHT; r++) { if (canvasIsRowFilled(r)) { + score += level; + displaySetValue(score); canvasWipeRow(r); canvasShow(); } } } - - displaySetScore(7); } void gameInit() {