up to three melodies will be played by one sequencer instance
This commit is contained in:
@ -2,7 +2,8 @@
|
|||||||
#include "psg.h"
|
#include "psg.h"
|
||||||
#include "sequencer.h"
|
#include "sequencer.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* most simple Tetris from https://de.wikipedia.org/wiki/Korobeiniki
|
||||||
const t_tone notes[] = {
|
const t_tone notes[] = {
|
||||||
{ .octave = e_O_3, .note = e_G, .length = e_L_1_4, .legato = false, .staccato = false },
|
{ .octave = e_O_3, .note = e_G, .length = e_L_1_4, .legato = false, .staccato = false },
|
||||||
{ .octave = e_O_3, .note = e_D, .length = e_L_1_8, .legato = false, .staccato = false },
|
{ .octave = e_O_3, .note = e_D, .length = e_L_1_8, .legato = false, .staccato = false },
|
||||||
@ -70,8 +71,12 @@ const t_tone notes[] = {
|
|||||||
|
|
||||||
{ .octave = e_O_Null, .note = e_Null, .length = e_L_EndMark, .legato = false, .staccato = false },
|
{ .octave = e_O_Null, .note = e_Null, .length = e_L_EndMark, .legato = false, .staccato = false },
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* drei-stimmiges theme from https://www.gamemusicthemes.com/sheetmusic/gameboy/tetris/themea/Tetris_-_Theme_A_by_Gori_Fater.pdf
|
||||||
|
*/
|
||||||
const t_tone tetris1[] = {
|
const t_tone tetris1[] = {
|
||||||
// -------
|
// -------
|
||||||
{ .octave = e_O_5, .note = e_E, .length = e_L_1_4, .legato = false, .staccato = false },
|
{ .octave = e_O_5, .note = e_E, .length = e_L_1_4, .legato = false, .staccato = false },
|
||||||
@ -692,38 +697,16 @@ const t_tone tetris3[] = {
|
|||||||
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
|
{ .octave = e_O_3, .note = e_E, .length = e_L_1_8, .legato = false, .staccato = false },
|
||||||
};
|
};
|
||||||
|
|
||||||
t_melody melody = {
|
|
||||||
.pace = 4,
|
|
||||||
.amplitude = 3,
|
|
||||||
.channel = 0,
|
|
||||||
.tones = notes
|
|
||||||
};
|
|
||||||
|
|
||||||
|
t_melodies tetrisTheme = {
|
||||||
t_melody melodyTetris1 = {
|
.melodies = { { .amplitude = 3, .tones = tetris1 }, { .amplitude = 3, .tones = tetris2 }, { .amplitude = 3, .tones = tetris3 } },
|
||||||
.pace = 4,
|
.numOfMelodies = 3,
|
||||||
.amplitude = 3,
|
.pace = 4
|
||||||
.channel = 0,
|
|
||||||
.tones = tetris1
|
|
||||||
};
|
|
||||||
t_melody melodyTetris2 = {
|
|
||||||
.pace = 4,
|
|
||||||
.amplitude = 3,
|
|
||||||
.channel = 1,
|
|
||||||
.tones = tetris2
|
|
||||||
};
|
|
||||||
t_melody melodyTetris3 = {
|
|
||||||
.pace = 4,
|
|
||||||
.amplitude = 3,
|
|
||||||
.channel = 1,
|
|
||||||
.tones = tetris3
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void melodyInit() {
|
void melodyInit() {
|
||||||
sequencerPlayMelody(&melodyTetris1);
|
sequencerPlayMelodies(&tetrisTheme);
|
||||||
sequencerPlayMelody(&melodyTetris2);
|
|
||||||
sequencerPlayMelody(&melodyTetris3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include <sys/param.h>
|
||||||
#include "sequencer.h"
|
#include "sequencer.h"
|
||||||
#include "scheduler.h"
|
#include "scheduler.h"
|
||||||
#include "psg.h"
|
#include "psg.h"
|
||||||
@ -8,53 +9,59 @@ void sequencerInit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void sequencerExec(void *handle) {
|
void sequencerExec(void *handle) {
|
||||||
t_melody *melody = (t_melody*) handle;
|
t_melodies *melodies = (t_melodies*) handle;
|
||||||
|
|
||||||
switch (melody->state) {
|
for (uint8_t channel = 0; channel < MAX(NUM_OF_CHANNELS, melodies->numOfMelodies); channel++) {
|
||||||
case e_Init:
|
t_melody *melody = &(melodies->melodies[channel]);
|
||||||
psgAmplitude(melody->channel, melody->amplitude);
|
|
||||||
melody->state = e_PlayTone;
|
switch (melody->state) {
|
||||||
break;
|
case e_Init:
|
||||||
case e_PlayTone:
|
psgAmplitude(channel, melody->amplitude);
|
||||||
if (melody->tones[melody->idx].length == e_L_EndMark) {
|
melody->state = e_PlayTone;
|
||||||
melody->idx = 0;
|
break;
|
||||||
}
|
case e_PlayTone:
|
||||||
psgPlayTone(melody->channel, melody->tones[melody->idx].octave, melody->tones[melody->idx].note);
|
if (melody->tones[melody->idx].length == e_L_EndMark) {
|
||||||
melody->lengthCnt = (melody->tones[melody->idx].staccato) ? (melody->tones[melody->idx].length / 2) : melody->tones[melody->idx].length;
|
melody->idx = 0;
|
||||||
melody->state = e_HoldTone;
|
}
|
||||||
break;
|
psgPlayTone(channel, melody->tones[melody->idx].octave, melody->tones[melody->idx].note);
|
||||||
case e_HoldTone:
|
melody->lengthCnt = (melody->tones[melody->idx].staccato) ? (melody->tones[melody->idx].length / 2) : melody->tones[melody->idx].length;
|
||||||
melody->lengthCnt -= 1;
|
melody->state = e_HoldTone;
|
||||||
if (melody->lengthCnt == 0) {
|
break;
|
||||||
melody->state = (melody->tones[melody->idx].staccato) ? e_StaccatoBreak : e_SeparateTone;
|
case e_HoldTone:
|
||||||
}
|
melody->lengthCnt -= 1;
|
||||||
break;
|
if (melody->lengthCnt == 0) {
|
||||||
case e_StaccatoBreak:
|
melody->state = (melody->tones[melody->idx].staccato) ? e_StaccatoBreak : e_SeparateTone;
|
||||||
psgPlayTone(melody->channel, e_O_Null, e_Pause);
|
}
|
||||||
melody->lengthCnt = melody->tones[melody->idx].length / 2;
|
break;
|
||||||
melody->state = e_HoldStaccatoBreak;
|
case e_StaccatoBreak:
|
||||||
break;
|
psgPlayTone(channel, e_O_Null, e_Pause);
|
||||||
case e_HoldStaccatoBreak:
|
melody->lengthCnt = melody->tones[melody->idx].length / 2;
|
||||||
melody->lengthCnt -= 1;
|
melody->state = e_HoldStaccatoBreak;
|
||||||
if (melody->lengthCnt == 0) {
|
break;
|
||||||
melody->state = e_SeparateTone;
|
case e_HoldStaccatoBreak:
|
||||||
}
|
melody->lengthCnt -= 1;
|
||||||
break;
|
if (melody->lengthCnt == 0) {
|
||||||
case e_SeparateTone:
|
melody->state = e_SeparateTone;
|
||||||
if (! (melody->tones[melody->idx].legato)) {
|
}
|
||||||
psgPlayTone(melody->channel, e_O_Null, e_Pause);
|
break;
|
||||||
}
|
case e_SeparateTone:
|
||||||
melody->idx += 1;
|
if (! (melody->tones[melody->idx].legato)) {
|
||||||
melody->state = e_PlayTone;
|
psgPlayTone(channel, e_O_Null, e_Pause);
|
||||||
break;
|
}
|
||||||
|
melody->idx += 1;
|
||||||
|
melody->state = e_PlayTone;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t sequencerPlayMelody(t_melody *melody) {
|
uint16_t sequencerPlayMelodies(t_melodies *melodies) {
|
||||||
melody->idx = 0;
|
for (uint8_t i = 0; i < NUM_OF_CHANNELS; i++) {
|
||||||
melody->lengthCnt = 0;
|
melodies->melodies[i].idx = 0;
|
||||||
melody->state = e_Init;
|
melodies->melodies[i].lengthCnt = 0;
|
||||||
|
melodies->melodies[i].state = e_Init;
|
||||||
|
}
|
||||||
|
|
||||||
return schAdd(sequencerExec, (void*) melody, 0, melody->pace);
|
return schAdd(sequencerExec, (void*) melodies, 0, melodies->pace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,14 +37,20 @@ typedef struct {
|
|||||||
uint16_t idx;
|
uint16_t idx;
|
||||||
uint8_t lengthCnt;
|
uint8_t lengthCnt;
|
||||||
t_sequencerState state;
|
t_sequencerState state;
|
||||||
uint8_t pace;
|
|
||||||
uint8_t amplitude;
|
uint8_t amplitude;
|
||||||
uint8_t channel;
|
|
||||||
const t_tone *tones;
|
const t_tone *tones;
|
||||||
} t_melody;
|
} t_melody;
|
||||||
|
|
||||||
|
#define NUM_OF_CHANNELS 3
|
||||||
|
typedef struct {
|
||||||
|
uint8_t numOfMelodies;
|
||||||
|
uint8_t pace;
|
||||||
|
t_melody melodies[NUM_OF_CHANNELS];
|
||||||
|
} t_melodies;
|
||||||
|
|
||||||
void sequencerInit();
|
void sequencerInit();
|
||||||
uint16_t sequencerPlayMelody(t_melody *melody);
|
uint16_t sequencerPlayMelody(t_melody *melody);
|
||||||
|
uint16_t sequencerPlayMelodies(t_melodies *melodies);
|
||||||
|
|
||||||
|
|
||||||
#endif // _SEQUENCER_H_
|
#endif // _SEQUENCER_H_
|
||||||
|
Reference in New Issue
Block a user