2024-06-06 17:05:17 +02:00
|
|
|
#include <stddef.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include "scheduler.h"
|
|
|
|
#include "sequencer.h"
|
|
|
|
#include "psg.h"
|
|
|
|
|
|
|
|
|
|
|
|
const uint32_t CYCLE_TIME = 5; // ms
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
ACTION_RESULT_STAY,
|
|
|
|
ACTION_RESULT_NEXT,
|
|
|
|
ACTION_RESULT_REPEAT,
|
|
|
|
ACTION_RESULT_END
|
|
|
|
} actionResult_t;
|
|
|
|
|
2024-06-11 21:24:54 +02:00
|
|
|
uint16_t taskId;
|
2024-06-06 17:05:17 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static actionResult_t _wait(uint32_t wait) {
|
|
|
|
static bool running = false;
|
|
|
|
static uint32_t counter = 0;
|
|
|
|
|
|
|
|
actionResult_t res;
|
|
|
|
if (! running) {
|
2024-06-11 21:24:54 +02:00
|
|
|
running = true;
|
2024-06-06 17:05:17 +02:00
|
|
|
counter = wait;
|
|
|
|
res = ACTION_RESULT_STAY;
|
|
|
|
} else {
|
|
|
|
if (counter == 0) {
|
|
|
|
running = false;
|
|
|
|
res = ACTION_RESULT_NEXT;
|
|
|
|
} else {
|
|
|
|
counter -= 1;
|
|
|
|
res = ACTION_RESULT_STAY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
static actionResult_t _change_sound(uint16_t frequency_a, uint8_t volume_a, uint16_t frequency_b, uint8_t volume_b) {
|
|
|
|
// set frequency_a and volume_a to generator 0
|
2024-06-11 21:24:54 +02:00
|
|
|
psgPlayFrequency(0, 0, volume_a, frequency_a);
|
2024-06-06 17:05:17 +02:00
|
|
|
// set frequency_b and volume_b to generator 1
|
2024-06-11 21:24:54 +02:00
|
|
|
psgPlayFrequency(1, 0, volume_b, frequency_b);
|
2024-06-06 17:05:17 +02:00
|
|
|
return ACTION_RESULT_NEXT;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool _change_volume(uint8_t volume_a, uint8_t volume_b) {
|
|
|
|
// set volume_a to generator 0
|
2024-06-11 21:24:54 +02:00
|
|
|
psgAmplitude(0, 0, volume_a);
|
2024-06-06 17:05:17 +02:00
|
|
|
// set volume_b to generator 1
|
2024-06-11 21:24:54 +02:00
|
|
|
psgAmplitude(1, 0, volume_b);
|
2024-06-06 17:05:17 +02:00
|
|
|
return ACTION_RESULT_NEXT;
|
|
|
|
}
|
|
|
|
|
2024-06-11 21:24:54 +02:00
|
|
|
void sequencerExec(void *handle) {
|
|
|
|
sequencerAction_t *seq = (sequencerAction_t*) handle;
|
|
|
|
|
|
|
|
static uint16_t seqIdx = 0;
|
|
|
|
|
|
|
|
sequencerAction_t *action = seq + seqIdx;
|
|
|
|
|
|
|
|
actionResult_t res;
|
|
|
|
switch (action->type) {
|
|
|
|
case SA_WAIT:
|
|
|
|
res = _wait(action->u.wait);
|
|
|
|
break;
|
|
|
|
case SA_REPEAT:
|
|
|
|
res = ACTION_RESULT_REPEAT;
|
|
|
|
break;
|
|
|
|
case SA_END:
|
|
|
|
res = ACTION_RESULT_END;
|
|
|
|
break;
|
|
|
|
case SA_CHANGE_SOUND:
|
|
|
|
res = _change_sound(
|
|
|
|
action->u.cs.frequency_a,
|
|
|
|
action->u.cs.volume_a,
|
|
|
|
action->u.cs.frequency_b,
|
|
|
|
action->u.cs.volume_b);
|
|
|
|
break;
|
|
|
|
case SA_CHANGE_VOLUME:
|
|
|
|
res = _change_volume(
|
|
|
|
action->u.cs.volume_a,
|
|
|
|
action->u.cs.volume_b);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (res) {
|
|
|
|
case ACTION_RESULT_NEXT:
|
|
|
|
seqIdx += 1;
|
|
|
|
break;
|
|
|
|
case ACTION_RESULT_REPEAT:
|
|
|
|
seqIdx = 0;
|
|
|
|
break;
|
|
|
|
case ACTION_RESULT_STAY:
|
|
|
|
break;
|
|
|
|
case ACTION_RESULT_END:
|
|
|
|
schDel(taskId);
|
|
|
|
break;
|
|
|
|
}
|
2024-06-06 17:05:17 +02:00
|
|
|
}
|
|
|
|
|
2024-06-11 21:24:54 +02:00
|
|
|
void sequencerStart(const sequencerAction_t *sequence) {
|
|
|
|
taskId = schAdd(sequencerExec, (void*) sequence, 0, CYCLE_TIME);
|
2024-06-06 17:05:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void sequencerInit() {
|
|
|
|
}
|
|
|
|
|
2024-06-11 21:24:54 +02:00
|
|
|
|