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:
parent
a100716cfc
commit
557c8777b1
|
@ -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.
|
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.
|
Finally, it has been connected to the speakers.
|
||||||
A welcome message would greed the new comer, followed by a pleasant music.
|
A welcome message would greed the new comer, followed by a (random) pleasant music.
|
||||||
After three minutes, a comical message would encourage the slow rider to hurry up.
|
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
|
board
|
||||||
=====
|
=====
|
||||||
|
|
185
application.c
185
application.c
|
@ -1,4 +1,4 @@
|
||||||
/** STM32F1 application example
|
/** dachboden klo-assistant firmware
|
||||||
* @file
|
* @file
|
||||||
* @author King Kévin <kingkevin@cuvoodoo.info>
|
* @author King Kévin <kingkevin@cuvoodoo.info>
|
||||||
* @copyright SPDX-License-Identifier: GPL-3.0-or-later
|
* @copyright SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
@ -130,14 +130,29 @@ enum mp3_commands_t {
|
||||||
MP3_CMD_QUERY_FLDR_COUNT = 0x4f,
|
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 */
|
/** number of possible music tracks */
|
||||||
#define MUSIC_TRACKS 19
|
#define MUSIC_TRACKS 24
|
||||||
/** if a music track has been played */
|
/** number of possible exit message tracks */
|
||||||
static bool music_played = false;
|
#define EXIT_TRACKS 18
|
||||||
/** number of possible talk tracks */
|
/** number of possible talk tracks */
|
||||||
#define TALK_TRACKS 27
|
#define TALK_TRACKS 27
|
||||||
/** if a talk track has been played */
|
|
||||||
static bool talk_played = false;
|
|
||||||
|
|
||||||
size_t putc(char c)
|
size_t putc(char c)
|
||||||
{
|
{
|
||||||
|
@ -193,6 +208,53 @@ static void command_reset(void* argument);
|
||||||
*/
|
*/
|
||||||
static void command_bootloader(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
|
/** process response received from MP3 player
|
||||||
* @return if a valid response has been received
|
* @return if a valid response has been received
|
||||||
*/
|
*/
|
||||||
|
@ -251,6 +313,55 @@ static bool mp3_response(void)
|
||||||
break;
|
break;
|
||||||
case 0x3d:
|
case 0x3d:
|
||||||
puts("track finished");
|
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;
|
break;
|
||||||
case 0x40:
|
case 0x40:
|
||||||
puts("error");
|
puts("error");
|
||||||
|
@ -269,52 +380,6 @@ static bool mp3_response(void)
|
||||||
mp3_rx_len = 0; // reset message
|
mp3_rx_len = 0; // reset message
|
||||||
return true;
|
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
|
/** play MP3
|
||||||
* @param[in] argument no argument required
|
* @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
|
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
|
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
|
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
|
if (door_flag) { // door switch state changed
|
||||||
|
@ -743,21 +800,21 @@ void main(void)
|
||||||
if (closed && 0 == timer_door_closed) { // door has been closed
|
if (closed && 0 == timer_door_closed) { // door has been closed
|
||||||
puts("door closed\n");
|
puts("door closed\n");
|
||||||
timer_door_closed = rtc_get_counter_val(); // remember when the door has been closed
|
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
|
leds_sign(true); // show on the sign that the toilet is occupied
|
||||||
led_tm1637_time(0, 0); // start showing time on display
|
led_tm1637_time(0, 0); // start showing time on display
|
||||||
led_tm1637_on(); // ensure the display is on
|
led_tm1637_on(); // ensure the display is on
|
||||||
mp3_command(MP3_CMD_PLAY_FOLDER_FILE, (1 << 8) + 1); // play welcome track
|
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
|
} else if (!closed && timer_door_closed) { // door has been opened
|
||||||
puts("door opened\n");
|
puts("door opened\n");
|
||||||
timer_door_closed = 0; // remember door is now open
|
timer_door_closed = 0; // remember door is now open
|
||||||
leds_sign(false); // show on sign the toilet is free
|
leds_sign(false); // show on sign the toilet is free
|
||||||
led_tm1637_off(); // stop showing time
|
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_response(); // check for response
|
||||||
mp3_rx_flag = false; // clear flag
|
mp3_rx_flag = false; // clear flag
|
||||||
action = true; // action has been performed
|
action = true; // action has been performed
|
||||||
|
|
Loading…
Reference in New Issue