You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
122 lines
4.1 KiB
122 lines
4.1 KiB
#include "music.h"
|
|
#include "FreeRTOS.h"
|
|
#include "task.h"
|
|
#include <stdbool.h>
|
|
|
|
bool playing;
|
|
uint16_t pitches[110];
|
|
|
|
uint8_t tonegens[MAX_TONEGENS] = { 0, 0, 0, 0, 0, 0 };
|
|
uint8_t channelOut[MAX_TONEGENS] = { 0, 0, 0, 0, 0, 0 };
|
|
|
|
void MusicStop(void) {
|
|
playing = false;
|
|
for (int i = 0; i < MAX_TONEGENS; i++) {
|
|
// disable PWM
|
|
tonegens[i] = 0;
|
|
channelOut[i] = 0;
|
|
}
|
|
}
|
|
|
|
RET_CODE MusicPlay(Track *track) {
|
|
MusicStop();
|
|
uint8_t *melody = track->begin;
|
|
uint32_t melodySize = track->size;
|
|
playing = true;
|
|
TickType_t xLastWakeTime;
|
|
|
|
xLastWakeTime = xTaskGetTickCount();
|
|
if (melody[0] != 'P' || melody[1] != 't')
|
|
{
|
|
MusicStop();
|
|
return WRONG_HEADER;
|
|
}
|
|
for (int i = melody[2]; i < melodySize; i++) {
|
|
if (playing == true)
|
|
{
|
|
//melody[2] stores the length of header
|
|
/* If the high-order bit of the byte is 0, it is a command to delay for a while until
|
|
the next note change. The other 7 bits and the 8 bits of the following byte are
|
|
interpreted as a 15-bit big-endian integer that is the number of milliseconds to
|
|
wait before processing the next command. For example, 07 D0
|
|
would cause a delay of 0x07d0 = 2000 decimal millisconds, or 2 seconds. Any tones
|
|
that were playing before the delay command will continue to play.*/
|
|
if ((melody[i] >> 7) == 0) {
|
|
uint32_t delay = (melody[i] << 8) + melody[i + 1];
|
|
vTaskDelayUntil(&xLastWakeTime, delay);
|
|
i++;
|
|
}
|
|
else {
|
|
switch (melody[i] >> 4) {
|
|
case 0xF || 0xE : {
|
|
MusicStop();
|
|
return OK;
|
|
}
|
|
case 0x8 : {
|
|
// 8t Stop playing the note on tone generator t
|
|
uint8_t generator = melody[i] & 0x0F;
|
|
tonegens[generator] = 0;
|
|
break;
|
|
}
|
|
/* 9t nn [vv]
|
|
Start playing note nn on tone generator t, replacing any previous note.
|
|
Generators are numbered starting with 0. The note numbers are the MIDI
|
|
numbers for the chromatic scale, with decimal 69 being Middle A (440 Hz).
|
|
If the -v option was given, the third byte specifies the note volume.*/
|
|
case 0x9 : {
|
|
uint8_t generator = melody[i] & 0x0F;
|
|
tonegens[generator] = pitches[melody[i + 1]];
|
|
i++;
|
|
break;
|
|
}
|
|
/* Ct ii Change tone generator t to play instrument ii from now on. This will only
|
|
be generated if the -i option was given.*/
|
|
case 0xC : {
|
|
//not impemented
|
|
i++;
|
|
break;
|
|
}
|
|
default: {
|
|
MusicStop();
|
|
return WRONG_BYTE;
|
|
}
|
|
}
|
|
}
|
|
|
|
//placeholder (тут так и было, хз)
|
|
for (uint8_t i = 0; i < MAX_TONEGENS; i++) {
|
|
channelOut[i] = 0;
|
|
}
|
|
|
|
uint8_t activeChannels = 0;
|
|
uint8_t currentChannel = 0;
|
|
for (uint8_t i = 0; i < MAX_TONEGENS; i++) {
|
|
if (tonegens[i] && (activeChannels < MAX_CHANNELS)) {
|
|
activeChannels++;
|
|
channelOut[currentChannel++] = tonegens[i];
|
|
}
|
|
}
|
|
|
|
for (uint8_t i = 0; i < MAX_CHANNELS; i++) {
|
|
channelOut[i] = 0;
|
|
}
|
|
/*
|
|
for (auto i = 0; i < channels.size(); i++) {
|
|
channels[i].PWM_SetFrequency(channelOut[i] ? channelOut[i] : Periph::Timer::PWM_MAX);
|
|
}
|
|
*/
|
|
} else {
|
|
MusicStop();
|
|
return STOPPED;
|
|
}
|
|
}
|
|
return OUT_OF_LOOP;
|
|
}
|
|
|
|
/*
|
|
MusicPlayer() {
|
|
for (auto &channel : channels)
|
|
channel.PWM_Init();
|
|
channels[1].PWM_SetParam(1000, 250);
|
|
}*/
|