score counter

This commit is contained in:
Wolfgang Hottgenroth 2024-03-22 22:49:43 +01:00
parent a32ef8fa5b
commit 85d243551e
5 changed files with 175 additions and 35 deletions

31
display-driver/Makefile Normal file
View File

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

131
display-driver/main.c Normal file
View File

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

View File

@ -4,47 +4,23 @@
#include "spi.h" #include "spi.h"
uint16_t score;
void displayInit() { 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) { value.value = v;
score = v;
spiSendBegin(e_SPI_DISPLAY); spiSendBegin(e_SPI_DISPLAY);
spiSendOctet(0x01); spiSendOctet(value.sendBuffer[0]);
spiSendOctet(0x07); spiSendOctet(value.sendBuffer[1]);
spiSendEnd(e_SPI_DISPLAY); spiSendEnd(e_SPI_DISPLAY);
} }

View File

@ -5,7 +5,7 @@
void displayInit(); void displayInit();
void displaySetScore(uint16_t v); void displaySetValue(uint16_t v);

View File

@ -33,6 +33,7 @@ void gameExec(void *handle) {
static uint8_t rowIndex; static uint8_t rowIndex;
static uint8_t proceedDelay; static uint8_t proceedDelay;
static uint8_t level; static uint8_t level;
static uint16_t score;
// --- engine begin ------------------------------------------------------- // --- engine begin -------------------------------------------------------
switch (state) { switch (state) {
@ -40,6 +41,7 @@ void gameExec(void *handle) {
case e_Start: case e_Start:
canvasClear(); canvasClear();
level = 1; level = 1;
score = 0;
phase = e_Phase_Game; phase = e_Phase_Game;
state = e_NewStone; state = e_NewStone;
break; break;
@ -112,13 +114,13 @@ void gameExec(void *handle) {
if (phase == e_Phase_Game) { if (phase == e_Phase_Game) {
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;
displaySetValue(score);
canvasWipeRow(r); canvasWipeRow(r);
canvasShow(); canvasShow();
} }
} }
} }
displaySetScore(7);
} }
void gameInit() { void gameInit() {