legato
This commit is contained in:
@ -1,84 +1,97 @@
|
|||||||
|
#include <stdbool.h>
|
||||||
#include "psg.h"
|
#include "psg.h"
|
||||||
#include "sequencer.h"
|
#include "sequencer.h"
|
||||||
|
|
||||||
|
|
||||||
const t_tone notes[] = {
|
const t_tone notes[] = {
|
||||||
{ .octave = e_O_2, .note = e_G, .length = e_L_1_2 },
|
{ .octave = e_O_3, .note = e_G, .length = e_L_1_4, .legato = false },
|
||||||
{ .octave = e_O_2, .note = e_D, .length = e_L_1_4 },
|
{ .octave = e_O_3, .note = e_D, .length = e_L_1_8, .legato = false },
|
||||||
{ .octave = e_O_2, .note = e_Dis, .length = e_L_1_4 },
|
{ .octave = e_O_3, .note = e_Dis, .length = e_L_1_8, .legato = false },
|
||||||
|
|
||||||
{ .octave = e_O_2, .note = e_F, .length = e_L_1_2 },
|
{ .octave = e_O_3, .note = e_F, .length = e_L_1_4, .legato = false },
|
||||||
{ .octave = e_O_2, .note = e_Dis, .length = e_L_1_4 },
|
{ .octave = e_O_3, .note = e_Dis, .length = e_L_1_8, .legato = false },
|
||||||
{ .octave = e_O_2, .note = e_D, .length = e_L_1_4},
|
{ .octave = e_O_3, .note = e_D, .length = e_L_1_8, .legato = false },
|
||||||
|
|
||||||
{ .octave = e_O_2, .note = e_C, .length = e_L_1_2},
|
{ .octave = e_O_3, .note = e_C, .length = e_L_1_4, .legato = false },
|
||||||
{ .octave = e_O_2, .note = e_C, .length = e_L_1_4},
|
{ .octave = e_O_3, .note = e_C, .length = e_L_1_8, .legato = false },
|
||||||
{ .octave = e_O_2, .note = e_Dis, .length = e_L_1_4},
|
{ .octave = e_O_3, .note = e_Dis, .length = e_L_1_8, .legato = false },
|
||||||
|
|
||||||
{ .octave = e_O_2, .note = e_G, .length = e_L_1_2},
|
{ .octave = e_O_3, .note = e_G, .length = e_L_1_4, .legato = false },
|
||||||
{ .octave = e_O_2, .note = e_F, .length = e_L_1_4},
|
{ .octave = e_O_3, .note = e_F, .length = e_L_1_8, .legato = false },
|
||||||
{ .octave = e_O_2, .note = e_Dis, .length = e_L_1_4},
|
{ .octave = e_O_3, .note = e_Dis, .length = e_L_1_8, .legato = false },
|
||||||
|
|
||||||
{ .octave = e_O_2, .note = e_D, .length = e_L_1_2},
|
{ .octave = e_O_3, .note = e_D, .length = e_L_1_4, .legato = true },
|
||||||
{ .octave = e_O_2, .note = e_D, .length = e_L_1_4},
|
{ .octave = e_O_3, .note = e_D, .length = e_L_1_8, .legato = false },
|
||||||
{ .octave = e_O_2, .note = e_Dis, .length = e_L_1_4},
|
{ .octave = e_O_3, .note = e_Dis, .length = e_L_1_8, .legato = false },
|
||||||
|
|
||||||
{ .octave = e_O_2, .note = e_F, .length = e_L_1_2},
|
{ .octave = e_O_3, .note = e_F, .length = e_L_1_4, .legato = false },
|
||||||
{ .octave = e_O_2, .note = e_G, .length = e_L_1_2},
|
{ .octave = e_O_3, .note = e_G, .length = e_L_1_4, .legato = false },
|
||||||
|
|
||||||
{ .octave = e_O_2, .note = e_Dis, .length = e_L_1_2},
|
{ .octave = e_O_3, .note = e_Dis, .length = e_L_1_8, .legato = true },
|
||||||
{ .octave = e_O_2, .note = e_C, .length = e_L_1_2},
|
{ .octave = e_O_3, .note = e_Dis, .length = e_L_1_16, .legato = false },
|
||||||
|
{ .octave = e_O_Null, .note = e_Pause, .length = e_L_1_16, .legato = false },
|
||||||
|
{ .octave = e_O_3, .note = e_C, .length = e_L_1_8, .legato = true },
|
||||||
|
{ .octave = e_O_3, .note = e_C, .length = e_L_1_16, .legato = false },
|
||||||
|
{ .octave = e_O_Null, .note = e_Pause, .length = e_L_1_16, .legato = false },
|
||||||
|
|
||||||
{ .octave = e_O_2, .note = e_C, .length = e_L_1_2},
|
{ .octave = e_O_3, .note = e_C, .length = e_L_1_4, .legato = false },
|
||||||
|
{ .octave = e_O_Null, .note = e_Pause, .length = e_L_1_4, .legato = false },
|
||||||
|
|
||||||
{ .octave = e_O_2, .note = e_F, .length = e_L_1_4},
|
|
||||||
{ .octave = e_O_2, .note = e_F, .length = e_L_1_4},
|
|
||||||
{ .octave = e_O_2, .note = e_Gis, .length = e_L_1_4},
|
|
||||||
|
|
||||||
{ .octave = e_O_3, .note = e_C, .length = e_L_1_2},
|
{ .octave = e_O_Null, .note = e_Pause, .length = e_L_1_8, .legato = false },
|
||||||
{ .octave = e_O_2, .note = e_Ais, .length = e_L_1_4},
|
{ .octave = e_O_3, .note = e_F, .length = e_L_1_8, .legato = true },
|
||||||
{ .octave = e_O_2, .note = e_Gis, .length = e_L_1_4},
|
{ .octave = e_O_3, .note = e_F, .length = e_L_1_8, .legato = false },
|
||||||
|
{ .octave = e_O_3, .note = e_Gis, .length = e_L_1_8, .legato = false },
|
||||||
|
|
||||||
{ .octave = e_O_2, .note = e_G, .length = e_L_1_2},
|
{ .octave = e_O_4, .note = e_C, .length = e_L_1_4, .legato = false },
|
||||||
{ .octave = e_O_2, .note = e_G, .length = e_L_1_4},
|
{ .octave = e_O_3, .note = e_Ais, .length = e_L_1_8, .legato = false },
|
||||||
{ .octave = e_O_2, .note = e_Dis, .length = e_L_1_4},
|
{ .octave = e_O_3, .note = e_Gis, .length = e_L_1_8, .legato = false },
|
||||||
|
|
||||||
{ .octave = e_O_2, .note = e_G, .length = e_L_1_2},
|
{ .octave = e_O_3, .note = e_G, .length = e_L_1_4, .legato = true },
|
||||||
{ .octave = e_O_2, .note = e_F, .length = e_L_1_4},
|
{ .octave = e_O_3, .note = e_G, .length = e_L_1_8, .legato = false },
|
||||||
{ .octave = e_O_2, .note = e_Dis, .length = e_L_1_4},
|
{ .octave = e_O_3, .note = e_Dis, .length = e_L_1_8, .legato = false },
|
||||||
|
|
||||||
{ .octave = e_O_2, .note = e_D, .length = e_L_1_2},
|
{ .octave = e_O_3, .note = e_G, .length = e_L_1_4, .legato = false },
|
||||||
{ .octave = e_O_2, .note = e_D, .length = e_L_1_4},
|
{ .octave = e_O_3, .note = e_F, .length = e_L_1_8, .legato = false },
|
||||||
{ .octave = e_O_2, .note = e_Dis, .length = e_L_1_4},
|
{ .octave = e_O_3, .note = e_Dis, .length = e_L_1_8, .legato = false },
|
||||||
|
|
||||||
{ .octave = e_O_2, .note = e_F, .length = e_L_1_2},
|
{ .octave = e_O_3, .note = e_D, .length = e_L_1_4, .legato = false },
|
||||||
{ .octave = e_O_2, .note = e_G, .length = e_L_1_2},
|
{ .octave = e_O_3, .note = e_D, .length = e_L_1_8, .legato = false },
|
||||||
|
{ .octave = e_O_3, .note = e_Dis, .length = e_L_1_8, .legato = false },
|
||||||
|
|
||||||
{ .octave = e_O_2, .note = e_Dis, .length = e_L_1_2},
|
{ .octave = e_O_3, .note = e_F, .length = e_L_1_4, .legato = false },
|
||||||
{ .octave = e_O_2, .note = e_C, .length = e_L_1_2},
|
{ .octave = e_O_3, .note = e_G, .length = e_L_1_4, .legato = false },
|
||||||
|
|
||||||
{ .octave = e_O_2, .note = e_C, .length = e_L_1_2},
|
{ .octave = e_O_3, .note = e_Dis, .length = e_L_1_8, .legato = true },
|
||||||
|
{ .octave = e_O_3, .note = e_Dis, .length = e_L_1_16, .legato = false },
|
||||||
|
{ .octave = e_O_Null, .note = e_Pause, .length = e_L_1_16, .legato = false },
|
||||||
|
{ .octave = e_O_3, .note = e_C, .length = e_L_1_8, .legato = true },
|
||||||
|
{ .octave = e_O_3, .note = e_C, .length = e_L_1_16, .legato = false },
|
||||||
|
{ .octave = e_O_Null, .note = e_Pause, .length = e_L_1_16, .legato = false },
|
||||||
|
|
||||||
{ .octave = e_O_2, .note = e_C, .length = e_L_EndMark },
|
{ .octave = e_O_3, .note = e_C, .length = e_L_1_4, .legato = false },
|
||||||
|
{ .octave = e_O_Null, .note = e_Pause, .length = e_L_1_4, .legato = false },
|
||||||
|
|
||||||
|
{ .octave = e_O_Null, .note = e_Null, .length = e_L_EndMark, .legato = false },
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
const t_tone ladder[16] = {
|
const t_tone ladder[16] = {
|
||||||
{ .octave = e_O_2, .note = e_C, .length = e_L_1_4 },
|
|
||||||
{ .octave = e_O_2, .note = e_D, .length = e_L_1_4 },
|
|
||||||
{ .octave = e_O_2, .note = e_E, .length = e_L_1_4 },
|
|
||||||
{ .octave = e_O_2, .note = e_F, .length = e_L_1_4 },
|
|
||||||
{ .octave = e_O_2, .note = e_G, .length = e_L_1_4 },
|
|
||||||
{ .octave = e_O_2, .note = e_A, .length = e_L_1_4 },
|
|
||||||
{ .octave = e_O_2, .note = e_H, .length = e_L_1_4 },
|
|
||||||
{ .octave = e_O_3, .note = e_C, .length = e_L_1_4 },
|
{ .octave = e_O_3, .note = e_C, .length = e_L_1_4 },
|
||||||
{ .octave = e_O_2, .note = e_H, .length = e_L_1_4 },
|
{ .octave = e_O_3, .note = e_D, .length = e_L_1_4 },
|
||||||
{ .octave = e_O_2, .note = e_A, .length = e_L_1_4 },
|
{ .octave = e_O_3, .note = e_E, .length = e_L_1_4 },
|
||||||
{ .octave = e_O_2, .note = e_G, .length = e_L_1_4 },
|
{ .octave = e_O_3, .note = e_F, .length = e_L_1_4 },
|
||||||
{ .octave = e_O_2, .note = e_F, .length = e_L_1_4 },
|
{ .octave = e_O_3, .note = e_G, .length = e_L_1_4 },
|
||||||
{ .octave = e_O_2, .note = e_E, .length = e_L_1_4 },
|
{ .octave = e_O_3, .note = e_A, .length = e_L_1_4 },
|
||||||
{ .octave = e_O_2, .note = e_D, .length = e_L_1_4 },
|
{ .octave = e_O_3, .note = e_H, .length = e_L_1_4 },
|
||||||
{ .octave = e_O_2, .note = e_H, .length = e_L_EndMark },
|
{ .octave = e_O_4, .note = e_C, .length = e_L_1_4 },
|
||||||
|
{ .octave = e_O_3, .note = e_H, .length = e_L_1_4 },
|
||||||
|
{ .octave = e_O_3, .note = e_A, .length = e_L_1_4 },
|
||||||
|
{ .octave = e_O_3, .note = e_G, .length = e_L_1_4 },
|
||||||
|
{ .octave = e_O_3, .note = e_F, .length = e_L_1_4 },
|
||||||
|
{ .octave = e_O_3, .note = e_E, .length = e_L_1_4 },
|
||||||
|
{ .octave = e_O_3, .note = e_D, .length = e_L_1_4 },
|
||||||
|
{ .octave = e_O_3, .note = e_H, .length = e_L_EndMark },
|
||||||
};
|
};
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -39,6 +39,8 @@ const uint16_t frequencyCodes[8][12] = {
|
|||||||
#define R14 014
|
#define R14 014
|
||||||
#define R15 015
|
#define R15 015
|
||||||
|
|
||||||
|
uint8_t psgShadowRegisters[14];
|
||||||
|
|
||||||
inline static void BUS_OP_NACT() {
|
inline static void BUS_OP_NACT() {
|
||||||
BUS_CTRL_REG &= ~(BDIR | BC1);
|
BUS_CTRL_REG &= ~(BDIR | BC1);
|
||||||
}
|
}
|
||||||
@ -61,7 +63,13 @@ asm volatile (
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t psgReadShadow(uint8_t address) {
|
||||||
|
return psgShadowRegisters[address];
|
||||||
|
}
|
||||||
|
|
||||||
void psgWrite(uint8_t address, uint8_t data) {
|
void psgWrite(uint8_t address, uint8_t data) {
|
||||||
|
psgShadowRegisters[address] = data;
|
||||||
|
|
||||||
// according to "State Timing" (p. 15) of datasheet
|
// according to "State Timing" (p. 15) of datasheet
|
||||||
|
|
||||||
// put bus into inactive state
|
// put bus into inactive state
|
||||||
@ -92,7 +100,12 @@ void psgWriteFrequency(uint8_t channel, uint16_t frequencyCode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void psgPlayTone(uint8_t channel, t_octave octave, t_note note) {
|
void psgPlayTone(uint8_t channel, t_octave octave, t_note note) {
|
||||||
|
if (note == e_Pause) {
|
||||||
|
psgWrite(R7, psgReadShadow(R7) | (1 << channel));
|
||||||
|
} else {
|
||||||
|
psgWrite(R7, psgReadShadow(R7) & ~(1 << channel));
|
||||||
psgWriteFrequency(channel, frequencyCodes[octave][note]);
|
psgWriteFrequency(channel, frequencyCodes[octave][note]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void playSomething(void *handle) {
|
void playSomething(void *handle) {
|
||||||
|
@ -11,7 +11,8 @@ typedef enum {
|
|||||||
e_O_5,
|
e_O_5,
|
||||||
e_O_6,
|
e_O_6,
|
||||||
e_O_7,
|
e_O_7,
|
||||||
e_O_8
|
e_O_8,
|
||||||
|
e_O_Null
|
||||||
} t_octave;
|
} t_octave;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -26,7 +27,9 @@ typedef enum {
|
|||||||
e_Gis,
|
e_Gis,
|
||||||
e_A,
|
e_A,
|
||||||
e_Ais,
|
e_Ais,
|
||||||
e_H
|
e_H,
|
||||||
|
e_Pause,
|
||||||
|
e_Null
|
||||||
} t_note;
|
} t_note;
|
||||||
|
|
||||||
|
|
||||||
@ -34,5 +37,6 @@ void psgInit();
|
|||||||
void psgPlayTone(uint8_t channel, t_octave octave, t_note note);
|
void psgPlayTone(uint8_t channel, t_octave octave, t_note note);
|
||||||
void psgWriteFrequency(uint8_t channel, uint16_t frequencyCode);
|
void psgWriteFrequency(uint8_t channel, uint16_t frequencyCode);
|
||||||
void psgWrite(uint8_t address, uint8_t data);
|
void psgWrite(uint8_t address, uint8_t data);
|
||||||
|
uint8_t psgReadShadow(uint8_t address);
|
||||||
|
|
||||||
#endif // _PSG_H_
|
#endif // _PSG_H_
|
||||||
|
@ -9,7 +9,8 @@ void sequencerInit() {
|
|||||||
void sequencerExec(void *handle) {
|
void sequencerExec(void *handle) {
|
||||||
t_melody *melody = (t_melody*) handle;
|
t_melody *melody = (t_melody*) handle;
|
||||||
|
|
||||||
if (melody->lengthCnt == 0) {
|
switch (melody->state) {
|
||||||
|
case 0:
|
||||||
if (melody->tones[melody->idx].length == e_L_EndMark) {
|
if (melody->tones[melody->idx].length == e_L_EndMark) {
|
||||||
melody->idx = 0;
|
melody->idx = 0;
|
||||||
}
|
}
|
||||||
@ -17,16 +18,29 @@ void sequencerExec(void *handle) {
|
|||||||
psgPlayTone(melody->channel, melody->tones[melody->idx].octave, melody->tones[melody->idx].note);
|
psgPlayTone(melody->channel, melody->tones[melody->idx].octave, melody->tones[melody->idx].note);
|
||||||
|
|
||||||
melody->lengthCnt = melody->tones[melody->idx].length;
|
melody->lengthCnt = melody->tones[melody->idx].length;
|
||||||
melody->idx += 1;
|
melody->state = 1;
|
||||||
}
|
break;
|
||||||
|
case 1:
|
||||||
melody->lengthCnt -= 1;
|
melody->lengthCnt -= 1;
|
||||||
|
if (melody->lengthCnt == 0) {
|
||||||
|
melody->state = 2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (! (melody->tones[melody->idx].legato)) {
|
||||||
|
psgPlayTone(melody->channel, e_O_Null, e_Pause);
|
||||||
|
}
|
||||||
|
melody->idx += 1;
|
||||||
|
melody->state = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t sequencerPlayMelody(t_melody *melody) {
|
uint8_t sequencerPlayMelody(t_melody *melody) {
|
||||||
melody->idx = 0;
|
melody->idx = 0;
|
||||||
melody->lengthCnt = 0;
|
melody->lengthCnt = 0;
|
||||||
schAdd(sequencerExec, (void*) melody, 0, 25);
|
melody->state = 0;
|
||||||
|
schAdd(sequencerExec, (void*) melody, 0, 10);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include "psg.h"
|
#include "psg.h"
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -18,11 +19,13 @@ typedef struct {
|
|||||||
t_octave octave;
|
t_octave octave;
|
||||||
t_note note;
|
t_note note;
|
||||||
t_noteLength length;
|
t_noteLength length;
|
||||||
|
bool legato;
|
||||||
} t_tone;
|
} t_tone;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint16_t idx;
|
uint16_t idx;
|
||||||
uint8_t lengthCnt;
|
uint8_t lengthCnt;
|
||||||
|
uint8_t state;
|
||||||
uint8_t channel;
|
uint8_t channel;
|
||||||
const t_tone *tones;
|
const t_tone *tones;
|
||||||
} t_melody;
|
} t_melody;
|
||||||
|
Reference in New Issue
Block a user