From 557c8777b1ec95cdec0c53d4117cf8a9b1bdb476 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?King=20K=C3=A9vin?= Date: Fri, 6 Nov 2020 10:00:46 +0100 Subject: [PATCH] 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. --- README.md | 6 +- application.c | 185 +++++++++++++++++++++++++++++++++----------------- 2 files changed, 125 insertions(+), 66 deletions(-) diff --git a/README.md b/README.md index eeedd60..87f9f42 100644 --- a/README.md +++ b/README.md @@ -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 ===== diff --git a/application.c b/application.c index 1c9be82..91c6cda 100644 --- a/application.c +++ b/application.c @@ -1,4 +1,4 @@ -/** STM32F1 application example +/** dachboden klo-assistant firmware * @file * @author King Kévin * @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