application: new way on playing songs

now always plays right after the end of a song/message instead of waiting fixed times.
announces the actual time instead of waiting for the 3 minutes mark.
plays songs and comical messages in an endless loop.
plays a message when the door is opened.
This commit is contained in:
King Kévin 2020-11-06 10:00:46 +01:00
parent a100716cfc
commit 557c8777b1
2 changed files with 125 additions and 66 deletions

View File

@ -11,8 +11,10 @@ Next, a display has been added to show the time spent in the water room.
This would put some pressure on the user to not spend too much time on the loo and hold up the queue.
Finally, it has been connected to the speakers.
A welcome message would greed the new comer, followed by a pleasant music.
After three minutes, a comical message would encourage the slow rider to hurry up.
A welcome message would greed the new comer, followed by a (random) pleasant music.
Then the time passed inside is announced, followed by a (random) comical message.
And the loop continues with another song.
Once you exit the place, a short (random) message is played.
board
=====

View File

@ -1,4 +1,4 @@
/** STM32F1 application example
/** dachboden klo-assistant firmware
* @file
* @author King Kévin <kingkevin@cuvoodoo.info>
* @copyright SPDX-License-Identifier: GPL-3.0-or-later
@ -130,14 +130,29 @@ enum mp3_commands_t {
MP3_CMD_QUERY_FLDR_COUNT = 0x4f,
};
/** which song group we are currently playing */
static enum playing_state_t {
PLAYING_STATE_OFF, /**< playing any song or track */
PLAYING_STATE_INTRO, /**< playing the welcome message */
PLAYING_STATE_SONG, /**< playing any song */
PLAYING_STATE_TIMER_INTRO, /**< playing the time announcement intro */
PLAYING_STATE_TIMER_MINUTES, /**< playing the number of minutes */
PLAYING_STATE_TIMER_MINUTE, /**< playing the minute announcement */
PLAYING_STATE_TIMER_SECONDS, /**< playing the number of seconds */
PLAYING_STATE_TIMER_OUTRO, /**< playing the timer announcement closing word */
PLAYING_STATE_TALK, /**< playing any talk track */
PLAYING_STATE_EXIT, /**< playing any exit message */
} playing_state = PLAYING_STATE_OFF; /**< which song group we are currently playing */
/** RTC timestamps when the last MP3 response track finished has been received */
static uint32_t last_finished = 0;
/** number of possible music tracks */
#define MUSIC_TRACKS 19
/** if a music track has been played */
static bool music_played = false;
#define MUSIC_TRACKS 24
/** number of possible exit message tracks */
#define EXIT_TRACKS 18
/** number of possible talk tracks */
#define TALK_TRACKS 27
/** if a talk track has been played */
static bool talk_played = false;
size_t putc(char c)
{
@ -193,6 +208,53 @@ static void command_reset(void* argument);
*/
static void command_bootloader(void* argument);
/** send command to MP3 playes
* @param[in] cmd command to send
* @param[in] data argument for command (such as track number)
*/
static void mp3_command(enum mp3_commands_t cmd, uint16_t data)
{
puts("MP3 command: ");
switch (cmd) {
case MP3_CMD_PLAY:
puts("play");
break;
case MP3_CMD_NEXT_SONG:
puts("next");
break;
case MP3_CMD_STOP_PLAY:
puts("stop");
break;
case MP3_CMD_PLAY_FOLDER_FILE:
puts("playing ");
const uint8_t folder = data >> 8;
const uint8_t track = data & 0xff;
printf("%02u/%03u", folder, track);
if (0 == folder) {
puts(" (invalid input folder 0)");
}
if (0 == track) {
puts(" (invalid input track 0");
}
break;
case MP3_CMD_SET_VOLUME:
printf("set volume to %u", data);
break;
case MP3_CMD_RESET:
puts("reset");
break;
default:
printf("%+02x");
break;
}
putc('\n');
uint8_t command[] = {0x7e, 0xff, 0x06, cmd, 0x01, data >> 8, data, 0xef}; // command template (with feedback)
for (uint8_t i = 0; i < LENGTH(command); i++) {
usart_send_blocking(USART(MP3_UART), command[i]);
}
}
/** process response received from MP3 player
* @return if a valid response has been received
*/
@ -251,6 +313,55 @@ static bool mp3_response(void)
break;
case 0x3d:
puts("track finished");
if ((rtc_get_counter_val() - last_finished) < 2) {
const uint16_t time_passed = (rtc_get_counter_val() - timer_door_closed) / RTC_TICKS_SECOND; // how many seconds have passed since door has been closed
switch (playing_state) {
case PLAYING_STATE_INTRO: // the welcome message finished
mp3_command(MP3_CMD_PLAY_FOLDER_FILE, (2 << 8) + (rtc_get_counter_val() % MUSIC_TRACKS) + 1); // play random music track
playing_state = PLAYING_STATE_SONG; // remember we are playong a song (for the first time)
break;
case PLAYING_STATE_SONG: // the song finished
mp3_command(MP3_CMD_PLAY_FOLDER_FILE, (5 << 8) + 65); // play time announcement
playing_state = PLAYING_STATE_TIMER_INTRO; // remember we are playing the timer announcement
break;
case PLAYING_STATE_TIMER_INTRO: // the time intro finished
if (0 == (time_passed / 60)) {
mp3_command(MP3_CMD_PLAY_FOLDER_FILE, (5 << 8) + 60); // play number of minutes announcement
} else {
mp3_command(MP3_CMD_PLAY_FOLDER_FILE, (5 << 8) + (time_passed / 60)); // play number of minutes announcement
}
playing_state = PLAYING_STATE_TIMER_MINUTES; // remember we are playing the number of minutes
break;
case PLAYING_STATE_TIMER_MINUTES: // the minutes announcement finished
mp3_command(MP3_CMD_PLAY_FOLDER_FILE, (5 << 8) + 62); // play minute announcement
playing_state = PLAYING_STATE_TIMER_MINUTE; // remember we are playing the minute announcement
break;
case PLAYING_STATE_TIMER_MINUTE: // the minute announcement finished
if (0 == (time_passed % 60)) {
mp3_command(MP3_CMD_PLAY_FOLDER_FILE, (5 << 8) + 60); // play number of seconds announcement
} else {
mp3_command(MP3_CMD_PLAY_FOLDER_FILE, (5 << 8) + (time_passed % 60)); // play number of seconds announcement
}
playing_state = PLAYING_STATE_TIMER_SECONDS; // remember we are playing the number of seconds
break;
case PLAYING_STATE_TIMER_SECONDS: // the number of seconds finished
mp3_command(MP3_CMD_PLAY_FOLDER_FILE, (5 << 8) + 64); // play time outro announcement
playing_state = PLAYING_STATE_TIMER_OUTRO; // remember we are playing the timer outro announcement
break;
case PLAYING_STATE_TIMER_OUTRO: // the timer outro announcement finished
mp3_command(MP3_CMD_PLAY_FOLDER_FILE, (3 << 8) + (rtc_get_counter_val() % TALK_TRACKS) + 1); // play random talk track
playing_state = PLAYING_STATE_TALK; // remember we are playing the talk track
break;
case PLAYING_STATE_TALK: // the talk track finished
mp3_command(MP3_CMD_PLAY_FOLDER_FILE, (2 << 8) + (rtc_get_counter_val() % MUSIC_TRACKS) + 1); // play random music track
playing_state = PLAYING_STATE_SONG; // remember we are playing a song (again)
break;
default:
playing_state = PLAYING_STATE_OFF; // we won't play anything else
break;
}
}
last_finished = rtc_get_counter_val(); // remember last time we received the ack
break;
case 0x40:
puts("error");
@ -269,52 +380,6 @@ static bool mp3_response(void)
mp3_rx_len = 0; // reset message
return true;
}
/** send command to MP3 playes
* @param[in] cmd command to send
* @param[in] data argument for command (such as track number)
*/
static void mp3_command(enum mp3_commands_t cmd, uint16_t data)
{
puts("MP3 command: ");
switch (cmd) {
case MP3_CMD_PLAY:
puts("play");
break;
case MP3_CMD_NEXT_SONG:
puts("next");
break;
case MP3_CMD_STOP_PLAY:
puts("stop");
break;
case MP3_CMD_PLAY_FOLDER_FILE:
puts("playing ");
const uint8_t folder = data >> 8;
const uint8_t track = data & 0xff;
printf("%02u/%03u", folder, track);
if (0 == folder) {
puts(" (invalid input folder 0)");
}
if (0 == track) {
puts(" (invalid input track 0");
}
break;
case MP3_CMD_SET_VOLUME:
printf("set volume to %u", data);
break;
case MP3_CMD_RESET:
puts("reset");
break;
default:
printf("%+02x");
break;
}
putc('\n');
uint8_t command[] = {0x7e, 0xff, 0x06, cmd, 0x01, data >> 8, data, 0xef}; // command template (with feedback)
for (uint8_t i = 0; i < LENGTH(command); i++) {
usart_send_blocking(USART(MP3_UART), command[i]);
}
}
/** play MP3
* @param[in] argument no argument required
@ -725,14 +790,6 @@ void main(void)
if (timer_door_closed && 0 == ((rtc_get_counter_val() - timer_door_closed) % (RTC_TICKS_SECOND / 4))) { // 1/4 second has passed since since door closed
const uint16_t time_passed = (rtc_get_counter_val() - timer_door_closed) / RTC_TICKS_SECOND; // how many seconds have passed since door has been closed
led_tm1637_time(time_passed / 60, time_passed % 60); // show time passed
if (!music_played && time_passed > 10) { // start playing song after the welcome message has been played
mp3_command(MP3_CMD_PLAY_FOLDER_FILE, (2 << 8) + (rtc_get_counter_val() % MUSIC_TRACKS) + 1); // play random music track
music_played = true; // remember we have played the music
}
if (!talk_played && time_passed >= 3 * 60) { // start playing talk track after 3 minutes
mp3_command(MP3_CMD_PLAY_FOLDER_FILE, (3 << 8) + (rtc_get_counter_val() % TALK_TRACKS) + 1); // play random talk track
talk_played = true; // remember we played the talk track
}
}
}
if (door_flag) { // door switch state changed
@ -743,21 +800,21 @@ void main(void)
if (closed && 0 == timer_door_closed) { // door has been closed
puts("door closed\n");
timer_door_closed = rtc_get_counter_val(); // remember when the door has been closed
music_played = false; // the music has not been played yet
talk_played = false; // the talk has not been played
leds_sign(true); // show on the sign that the toilet is occupied
led_tm1637_time(0, 0); // start showing time on display
led_tm1637_on(); // ensure the display is on
mp3_command(MP3_CMD_PLAY_FOLDER_FILE, (1 << 8) + 1); // play welcome track
playing_state = PLAYING_STATE_INTRO; // remember we are playing the welcome message
} else if (!closed && timer_door_closed) { // door has been opened
puts("door opened\n");
timer_door_closed = 0; // remember door is now open
leds_sign(false); // show on sign the toilet is free
led_tm1637_off(); // stop showing time
mp3_command(MP3_CMD_STOP_PLAY, 0); // stop playing
mp3_command(MP3_CMD_PLAY_FOLDER_FILE, (4 << 8) + (rtc_get_counter_val() % EXIT_TRACKS) + 1); // play random exit message track
playing_state = PLAYING_STATE_EXIT; // we are playing the exit track
}
}
if (mp3_rx_flag) { // data from MP3 player
if (mp3_rx_flag) { // data from MP3 player received
mp3_response(); // check for response
mp3_rx_flag = false; // clear flag
action = true; // action has been performed