sound works

This commit is contained in:
Wolfgang Hottgenroth 2024-04-17 15:30:45 +02:00
parent d68dae167d
commit 36d3b2f735
16 changed files with 165 additions and 167 deletions

View File

@ -49,7 +49,7 @@ 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 unmuteFlag = false; static bool unmuteFlag = true;
if (! stoneIsValid()) { if (! stoneIsValid()) {
@ -61,27 +61,27 @@ void buttonsExec(void *handle) {
if (buttonsMoveLeftPressed()) { if (buttonsMoveLeftPressed()) {
stoneMoveLeft(); stoneMoveLeft();
soundCtrl(e_SOUND_STONE_MOVE_LEFT); soundCtrl(SOUND_MOTION);
buttonPressed = 1; buttonPressed = 1;
} }
if (buttonsMoveRightPressed()) { if (buttonsMoveRightPressed()) {
stoneMoveRight(); stoneMoveRight();
soundCtrl(e_SOUND_STONE_MOVE_RIGHT); soundCtrl(SOUND_MOTION);
buttonPressed = 1; buttonPressed = 1;
} }
if (buttonsRotateLeftPressed()) { if (buttonsRotateLeftPressed()) {
stoneRotateLeft(); stoneRotateLeft();
soundCtrl(e_SOUND_STONE_ROTATE_LEFT); soundCtrl(SOUND_MOTION);
buttonPressed = 1; buttonPressed = 1;
} }
if (buttonsRotateRightPressed()) { if (buttonsRotateRightPressed()) {
stoneRotateRight(); stoneRotateRight();
soundCtrl(e_SOUND_STONE_ROTATE_RIGHT); soundCtrl(SOUND_MOTION);
buttonPressed = 1; buttonPressed = 1;
} }
if (buttonsMoveDownPressed()) { if (buttonsMoveDownPressed()) {
stoneMoveDown(); stoneMoveDown();
soundCtrl(e_SOUND_STONE_MOVE_DOWN); soundCtrl(SOUND_MOTION);
buttonPressed = 1; buttonPressed = 1;
} }
@ -89,14 +89,14 @@ void buttonsExec(void *handle) {
canvasShow(); canvasShow();
if (! unmuteFlag) { if (! unmuteFlag) {
soundCtrl(e_SOUND_UNMUTE); soundCtrl(SOUND_UNMUTE);
unmuteFlag = true; unmuteFlag = true;
} }
unmuteTimestamp = currentTimestamp; unmuteTimestamp = currentTimestamp;
} }
if (unmuteFlag && (unmuteTimestamp + MUTE_DELAY < currentTimestamp)) { if (unmuteFlag && (unmuteTimestamp + MUTE_DELAY < currentTimestamp)) {
soundCtrl(e_SOUND_MUTE); soundCtrl(SOUND_MUTE);
unmuteFlag = false; unmuteFlag = false;
} }
} }

View File

@ -41,7 +41,7 @@ void gameExec(void *handle) {
// --- phase: game -------------------------------------------------------- // --- phase: game --------------------------------------------------------
case e_Start: case e_Start:
canvasClear(); canvasClear();
soundCtrl(e_SOUND_START_BACKGROUND); soundCtrl(SOUND_START);
level = 1; level = 1;
score = 0; score = 0;
displaySetValue(score); displaySetValue(score);
@ -73,7 +73,7 @@ void gameExec(void *handle) {
case e_Down: case e_Down:
if (! stoneMoveDown()) { if (! stoneMoveDown()) {
soundCtrl(e_SOUND_STONE_LOCKED); soundCtrl(SOUND_LOCK);
state = e_NewStone; state = e_NewStone;
} else { } else {
proceedDelay = delayFactor(level); proceedDelay = delayFactor(level);
@ -83,8 +83,7 @@ void gameExec(void *handle) {
// --- phase: game over --------------------------------------------------- // --- phase: game over ---------------------------------------------------
case e_GameOver: case e_GameOver:
soundCtrl(e_SOUND_STOP_BACKGROUND); soundCtrl(SOUND_GAMEOVER);
soundCtrl(e_SOUND_START_GAMEOVER);
rowIndex = CANVAS_HEIGHT; rowIndex = CANVAS_HEIGHT;
phase = e_Phase_GameOver; phase = e_Phase_GameOver;
state = e_GameOverFill; state = e_GameOverFill;
@ -110,7 +109,6 @@ void gameExec(void *handle) {
case e_GameOverDelay: case e_GameOverDelay:
gameOverDelay--; gameOverDelay--;
if (gameOverDelay == 0) { if (gameOverDelay == 0) {
soundCtrl(e_SOUND_STOP_GAMEOVER);
state = e_Start; state = e_Start;
} }
break; break;
@ -129,10 +127,13 @@ void gameExec(void *handle) {
wipeCnt += 1; wipeCnt += 1;
} }
} }
soundCtrl(e_SOUND_FANFARE_BASE + wipeCnt); if (wipeCnt != 0) {
soundCtrl(SOUND_FANFARE);
}
} }
} }
void gameInit() { void gameInit() {
schAdd(gameExec, NULL, 0, GAME_CYCLE_TIME); schAdd(gameExec, NULL, 0, GAME_CYCLE_TIME);
} }

View File

@ -1,3 +1,4 @@
#include <stdint.h>
#include "sound.h" #include "sound.h"
#include "spi.h" #include "spi.h"
@ -7,10 +8,10 @@ void soundInit() {
} }
void soundCtrl(t_SoundCmd cmd) { void soundCtrl(uint8_t cmd) {
spiSendBegin(e_SPI_SOUND); spiSendBegin(e_SPI_SOUND);
spiSendOctet((uint8_t)cmd); spiSendOctet(cmd);
spiSendEnd(e_SPI_SOUND); spiSendEnd(e_SPI_SOUND);
} }

View File

@ -1,32 +1,14 @@
#ifndef _SOUND_H_ #ifndef _SOUND_H_
#define _SOUND_H_ #define _SOUND_H_
#include <stdint.h>
#define MUTE_DELAY 30 // seconds #define MUTE_DELAY 30 // seconds
typedef enum { #include "../sound-driver/soundCodes.h"
e_SOUND_IDLE = 0,
e_SOUND_MUTE = 1,
e_SOUND_UNMUTE,
e_SOUND_START_BACKGROUND,
e_SOUND_STOP_BACKGROUND,
e_SOUND_START_GAMEOVER,
e_SOUND_STOP_GAMEOVER,
e_SOUND_SPEED_UP,
e_SOUND_FANFARE_BASE,
e_SOUND_FANFARE_1,
e_SOUND_FANFARE_2,
e_SOUND_FANFARE_3,
e_SOUND_FANFARE_4,
e_SOUND_STONE_LOCKED,
e_SOUND_STONE_MOVE_LEFT,
e_SOUND_STONE_MOVE_RIGHT,
e_SOUND_STONE_ROTATE_LEFT,
e_SOUND_STONE_ROTATE_RIGHT,
e_SOUND_STONE_MOVE_DOWN,
} t_SoundCmd;
void soundInit(); void soundInit();
void soundCtrl(t_SoundCmd cmd); void soundCtrl(uint8_t cmd);

View File

@ -4,20 +4,25 @@ OBJDUMP=$(TOOLCHAIN_PREFIX)/bin/msp430-elf-objdump
ARTIFACT=firmware ARTIFACT=firmware
MCU=msp430g2553 MCU=msp430g2553
CFLAGS=-Wall -mmcu=$(MCU) -std=gnu99 -I $(TOOLCHAIN_PREFIX)/include -O1 -g0 COMMONFLAGS=-Wall -mmcu=$(MCU) -I $(TOOLCHAIN_PREFIX)/include -O0 -g0
CFLAGS=$(COMMONFLAGS) -std=gnu99
ASFLAGS=$(COMMONFLAGS) -D__ASSEMBLER__
# 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 scheduler.o spi.o sequencer.o melody_tetris.o melody_tusch1.o ay_3_8913.o mute.o $(ARTIFACT).elf: main.o scheduler.o spi.o spi_init.o sequencer.o melody_tetris.o melody_tusch1.o ay_3_8913.o mute.o
$(CC) -o $@ $(LDFLAGS) $^ $(CC) -o $@ $(LDFLAGS) $^
$(OBJDUMP) -D $(ARTIFACT).elf > $(ARTIFACT).txt $(OBJDUMP) -D $(ARTIFACT).elf > $(ARTIFACT).txt
.c.o: .c.o:
$(CC) $(CFLAGS) -c $< $(CC) $(CFLAGS) -c $<
.S.o:
$(CC) $(ASFLAGS) -c $<
.PHONY: all .PHONY: all
all: $(ARTIFACT).elf all: $(ARTIFACT).elf

View File

@ -31,6 +31,8 @@ int main() {
__enable_interrupt(); __enable_interrupt();
// playMelodyTetris();
while (1) { while (1) {
schExec(); schExec();
} }

View File

@ -925,7 +925,8 @@ const t_tone voice3[] = {
t_melodies tetrisTheme = { t_melodies tetrisTheme = {
.melodies = { { .chip = 0, .amplitude = 8, .tones = voice1 }, { .chip = 0, .amplitude = 8, .tones = voice2 }, { .chip = 0, .amplitude = 8, .tones = voice3 } }, .melodies = { { .chip = 0, .amplitude = 8, .tones = voice1 }, { .chip = 0, .amplitude = 8, .tones = voice2 }, { .chip = 0, .amplitude = 8, .tones = voice3 } },
.numOfMelodies = 3, .numOfMelodies = 3,
.pace = 160 .pace = 160,
.slotMask = 0x01
}; };
void playMelodyTetris() { void playMelodyTetris() {

View File

@ -73,7 +73,8 @@ const t_tone tusch1voice3[] = {
t_melodies tusch1 = { t_melodies tusch1 = {
.melodies = { { .chip = 1, .amplitude = 12, .tones = tusch1voice1 }, { .chip = 1, .amplitude = 12, .tones = tusch1voice2 }, { .chip = 1, .amplitude = 12, .tones = tusch1voice3 } }, .melodies = { { .chip = 1, .amplitude = 12, .tones = tusch1voice1 }, { .chip = 1, .amplitude = 12, .tones = tusch1voice2 }, { .chip = 1, .amplitude = 12, .tones = tusch1voice3 } },
.numOfMelodies = 3, .numOfMelodies = 3,
.pace = 200 .pace = 200,
.slotMask = 0x02
}; };
void playTusch1() { void playTusch1() {

View File

@ -6,7 +6,7 @@
#define MAX_NUM_OF_TASKS 8 #define MAX_NUM_OF_TASKS 4
typedef struct { typedef struct {

View File

@ -6,8 +6,10 @@
#include "psg.h" #include "psg.h"
uint8_t slots;
void sequencerInit() { void sequencerInit() {
slots = 0;
} }
#pragma GCC diagnostic push #pragma GCC diagnostic push
@ -97,12 +99,18 @@ void sequencerExec(void *handle) {
break; break;
case e_Terminate: case e_Terminate:
schDel(melodies->taskId); schDel(melodies->taskId);
slots &= ~(melodies->slotMask);
break; break;
} }
} }
} }
uint16_t sequencerPlayMelodies(t_melodies *melodies) { void sequencerPlayMelodies(t_melodies *melodies) {
if ((slots & melodies->slotMask) != 0) {
return;
}
slots |= melodies->slotMask;
for (uint8_t i = 0; i < NUM_OF_CHANNELS; i++) { for (uint8_t i = 0; i < NUM_OF_CHANNELS; i++) {
melodies->melodies[i].idx = 0; melodies->melodies[i].idx = 0;
melodies->melodies[i].lengthCnt = 0; melodies->melodies[i].lengthCnt = 0;
@ -112,11 +120,10 @@ uint16_t sequencerPlayMelodies(t_melodies *melodies) {
melodies->quarterLength = 60000 / melodies->pace / SEQUENCER_PERIOD; // duration of a 1/4 tone in ms melodies->quarterLength = 60000 / melodies->pace / SEQUENCER_PERIOD; // duration of a 1/4 tone in ms
melodies->taskId = schAdd(sequencerExec, (void*) melodies, 0, SEQUENCER_PERIOD); melodies->taskId = schAdd(sequencerExec, (void*) melodies, 0, SEQUENCER_PERIOD);
return melodies->taskId;
} }
void sequencerStopMelodies(t_melodies *melodies) { void sequencerStopMelodies(t_melodies *melodies) {
slots &= ~(melodies->slotMask);
schDel(melodies->taskId); schDel(melodies->taskId);
} }

View File

@ -52,6 +52,7 @@ typedef struct {
#define SEQUENCER_PERIOD 4 // ms #define SEQUENCER_PERIOD 4 // ms
#define NUM_OF_CHANNELS 3 #define NUM_OF_CHANNELS 3
typedef struct { typedef struct {
uint8_t slotMask;
uint8_t taskId; uint8_t taskId;
uint16_t quarterLength; uint16_t quarterLength;
uint8_t numOfMelodies; uint8_t numOfMelodies;
@ -61,7 +62,7 @@ typedef struct {
} t_melodies; } t_melodies;
void sequencerInit(); void sequencerInit();
uint16_t sequencerPlayMelodies(t_melodies *melodies); void sequencerPlayMelodies(t_melodies *melodies);
void sequencerStopMelodies(t_melodies *melodies); void sequencerStopMelodies(t_melodies *melodies);
#endif // _SEQUENCER_H_ #endif // _SEQUENCER_H_

14
sound-driver/soundCodes.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef _SOUND_CODES_H_
#define _SOUND_CODES_H_
#define SOUND_IDLE 0x00
#define SOUND_MUTE 0x01
#define SOUND_UNMUTE 0x02
#define SOUND_START 0x04
#define SOUND_GAMEOVER 0x08
#define SOUND_FANFARE 0x10
#define SOUND_LOCK 0x20
#define SOUND_MOTION 0x40
#define SOUND_SPEED_UP 0x80
#endif // _SOUND_CODES_H_

70
sound-driver/spi.S Normal file
View File

@ -0,0 +1,70 @@
#include <msp430g2553.h>
#include "soundCodes.h"
.section ".data"
.global cmd
cmd:
.byte
.section ".text","ax",@progbits
receive_isr:
bit #UCB0RXIFG, &UC0IFG
jz receive_isr_no_data
bis UCB0RXBUF, &cmd
receive_isr_no_data:
reti
.global spiCmdHandler
spiCmdHandler:
spiCmdHandler_1:
bit #SOUND_MUTE, &cmd
jz spiCmdHandler_2
call #mute
bic #SOUND_MUTE, &cmd
spiCmdHandler_2:
bit #SOUND_UNMUTE, &cmd
jz spiCmdHandler_3
call #unMute
bic #SOUND_UNMUTE, &cmd
spiCmdHandler_3:
bit #SOUND_START, &cmd
jz spiCmdHandler_4
call #playMelodyTetris
bic #SOUND_START, &cmd
spiCmdHandler_4:
bit #SOUND_GAMEOVER, &cmd
jz spiCmdHandler_5
;; insert a call here
bic #SOUND_GAMEOVER, &cmd
spiCmdHandler_5:
bit #SOUND_FANFARE, &cmd
jz spiCmdHandler_6
call #playTusch1
bic #SOUND_FANFARE, &cmd
spiCmdHandler_6:
bit #SOUND_LOCK, &cmd
jz spiCmdHandler_7
;; insert a call here
bic #SOUND_LOCK, &cmd
spiCmdHandler_7:
bit #SOUND_MOTION, &cmd
jz spiCmdHandler_8
;; insert a call here
bic #SOUND_MOTION, &cmd
spiCmdHandler_8:
bit #SOUND_SPEED_UP, &cmd
jz spiCmdHandler_end
;; insert a call here
bic #SOUND_SPEED_UP, &cmd
spiCmdHandler_end:
ret
.section "__interrupt_vector_8","ax",@progbits
.word receive_isr
.end

View File

@ -1,118 +0,0 @@
#include <stdint.h>
#include <stddef.h>
#include <msp430g2553.h>
#include "spi.h"
#include "../game-ctrl/sound.h"
#include "scheduler.h"
#include "psg.h"
#include "mute.h"
#include "melody_tetris.h"
#include "melody_tusch1.h"
volatile t_SoundCmd cmd;
void __attribute__ ((interrupt (USCIAB0RX_VECTOR))) receive() {
if (UC0IFG & UCB0RXIFG) {
// receive an octet
cmd = UCB0RXBUF;
}
}
void spiCmdHandler(void *handle) {
t_SoundCmd cmdShadow;
__disable_interrupt();
cmdShadow = cmd;
__enable_interrupt();
/*
e_SOUND_IDLE = 0,
e_SOUND_MUTE = 1,
e_SOUND_UNMUTE,
e_SOUND_START_BACKGROUND,
e_SOUND_STOP_BACKGROUND,
e_SOUND_START_GAMEOVER,
e_SOUND_STOP_GAMEOVER,
e_SOUND_SPEED_UP,
e_SOUND_FANFARE_BASE,
e_SOUND_FANFARE_1,
e_SOUND_FANFARE_2,
e_SOUND_FANFARE_3,
e_SOUND_FANFARE_4,
e_SOUND_STONE_LOCKED,
e_SOUND_STONE_MOVE_LEFT,
e_SOUND_STONE_MOVE_RIGHT,
e_SOUND_STONE_ROTATE_LEFT,
e_SOUND_STONE_ROTATE_RIGHT,
e_SOUND_STONE_MOVE_DOWN,
*/
switch (cmdShadow) {
case e_SOUND_MUTE:
mute();
break;
case e_SOUND_UNMUTE:
unMute();
break;
case e_SOUND_START_BACKGROUND:
playMelodyTetris();
break;
case e_SOUND_STOP_BACKGROUND:
stopMelodyTetris();
break;
case e_SOUND_START_GAMEOVER:
break;
case e_SOUND_STOP_GAMEOVER:
break;
case e_SOUND_SPEED_UP:
break;
case e_SOUND_FANFARE_1:
playTusch1();
break;
case e_SOUND_FANFARE_2:
playTusch1();
break;
case e_SOUND_FANFARE_3:
playTusch1();
break;
case e_SOUND_FANFARE_4:
playTusch1();
break;
case e_SOUND_STONE_LOCKED:
break;
case e_SOUND_STONE_MOVE_DOWN:
break;
case e_SOUND_STONE_MOVE_LEFT:
break;
case e_SOUND_STONE_MOVE_RIGHT:
break;
case e_SOUND_STONE_ROTATE_LEFT:
break;
case e_SOUND_STONE_ROTATE_RIGHT:
break;
default:
break;
}
}
void spiInit() {
// SPI slave
// BIT4: UCB0STE
// BIT5: UCB0CLK
// BIT6: UCB0SOMI
// BIT7: UCB0SIMO
P1SEL |= BIT4 | BIT5 | BIT7;
P1SEL2 |= BIT4 | BIT5 | BIT7;
// most significant bit first, enable STE
UCB0CTL0 = UCSYNC | UCMSB | UCMODE_2;
UCB0CTL1 = 0x00;
// enable RX interrupt
UC0IE |= UCB0RXIE;
schAdd(spiCmdHandler, NULL, 0, 10);
}

View File

@ -3,7 +3,7 @@
void spiInit(); void spiInit();
void spiCmdHandler();
#endif // _SPI_H_ #endif // _SPI_H_

31
sound-driver/spi_init.c Normal file
View File

@ -0,0 +1,31 @@
#include <stddef.h>
#include <msp430g2553.h>
#include <stdint.h>
#include "scheduler.h"
#include "spi.h"
#include "soundCodes.h"
extern uint8_t cmd;
void spiInit() {
// SPI slave
// BIT4: UCB0STE
// BIT5: UCB0CLK
// BIT6: UCB0SOMI
// BIT7: UCB0SIMO
P1SEL |= BIT4 | BIT5 | BIT7;
P1SEL2 |= BIT4 | BIT5 | BIT7;
// most significant bit first, enable STE
UCB0CTL0 = UCSYNC | UCMSB | UCMODE_2;
UCB0CTL1 = 0x00;
// enable RX interrupt
UC0IE |= UCB0RXIE;
cmd = SOUND_IDLE;
schAdd(spiCmdHandler, NULL, 0, 100);
}