Prusa-Firmware/Firmware/sound.cpp

218 lines
5.7 KiB
C++

#include <Arduino.h>
#include "backlight.h"
#include "eeprom.h"
#include "fastio.h"
#include "pins.h"
#include "sound.h"
#include "system_timer.h"
#include "Timer.h"
//eSOUND_MODE eSoundMode=e_SOUND_MODE_LOUD;
// nema vyznam, pokud se bude volat Sound_Init (tzn. poc. hodnota je v EEPROM)
// !?! eSOUND_MODE eSoundMode; v ultraldc.cpp :: cd_settings_menu() se takto jevi jako lokalni promenna
eSOUND_MODE eSoundMode; //=e_SOUND_MODE_DEFAULT;
static void Sound_SaveMode(void);
static void Sound_DoSound_Echo(void);
static void Sound_DoSound_Prompt(void);
static void Sound_DoSound_Alert(bool bOnce);
static void Sound_DoSound_Encoder_Move(void);
static void Sound_DoSound_Blind_Alert(void);
void Sound_Init(void)
{
SET_OUTPUT(BEEPER);
eSoundMode = static_cast<eSOUND_MODE>(eeprom_init_default_byte((uint8_t*)EEPROM_SOUND_MODE, e_SOUND_MODE_DEFAULT));
}
void Sound_SaveMode(void)
{
eeprom_update_byte_notify((uint8_t*)EEPROM_SOUND_MODE,(uint8_t)eSoundMode);
}
void Sound_CycleState(void)
{
switch(eSoundMode)
{
case e_SOUND_MODE_LOUD:
eSoundMode=e_SOUND_MODE_ONCE;
break;
case e_SOUND_MODE_ONCE:
eSoundMode=e_SOUND_MODE_SILENT;
break;
case e_SOUND_MODE_SILENT:
eSoundMode=e_SOUND_MODE_BLIND;
break;
case e_SOUND_MODE_BLIND:
eSoundMode=e_SOUND_MODE_LOUD;
break;
default:
eSoundMode=e_SOUND_MODE_LOUD;
}
Sound_SaveMode();
}
//if critical is true then silend and once mode is ignored
void __attribute__((noinline)) Sound_MakeCustom(uint16_t ms,uint16_t tone_,bool critical){
if (critical || eSoundMode != e_SOUND_MODE_SILENT) {
if(!tone_) {
WRITE(BEEPER, HIGH);
_delay(ms);
WRITE(BEEPER, LOW);
} else {
_tone(BEEPER, tone_);
_delay(ms);
_noTone(BEEPER);
}
}
}
void Sound_MakeSound(eSOUND_TYPE eSoundType)
{
switch(eSoundMode)
{
case e_SOUND_MODE_LOUD:
if(eSoundType==e_SOUND_TYPE_ButtonEcho)
Sound_DoSound_Echo();
if(eSoundType==e_SOUND_TYPE_StandardPrompt)
Sound_DoSound_Prompt();
if(eSoundType==e_SOUND_TYPE_StandardAlert)
Sound_DoSound_Alert(false);
break;
case e_SOUND_MODE_ONCE:
if(eSoundType==e_SOUND_TYPE_ButtonEcho)
Sound_DoSound_Echo();
if(eSoundType==e_SOUND_TYPE_StandardPrompt)
Sound_DoSound_Prompt();
if(eSoundType==e_SOUND_TYPE_StandardAlert)
Sound_DoSound_Alert(true);
break;
case e_SOUND_MODE_SILENT:
if(eSoundType==e_SOUND_TYPE_StandardAlert)
Sound_DoSound_Alert(true);
break;
case e_SOUND_MODE_BLIND:
if(eSoundType==e_SOUND_TYPE_ButtonEcho)
Sound_DoSound_Echo();
if(eSoundType==e_SOUND_TYPE_StandardPrompt)
Sound_DoSound_Prompt();
if(eSoundType==e_SOUND_TYPE_StandardAlert)
Sound_DoSound_Alert(false);
if(eSoundType==e_SOUND_TYPE_EncoderMove)
Sound_DoSound_Encoder_Move();
if(eSoundType==e_SOUND_TYPE_BlindAlert)
Sound_DoSound_Blind_Alert();
break;
default:
break;
}
}
static void Sound_DoSound_Blind_Alert(void)
{
backlight_wake(1);
uint8_t nI;
for(nI=0; nI<20; nI++)
{
WRITE(BEEPER,HIGH);
delayMicroseconds(94);
WRITE(BEEPER,LOW);
delayMicroseconds(94);
}
}
static void Sound_DoSound_Encoder_Move(void)
{
uint8_t nI;
for(nI=0;nI<5;nI++)
{
WRITE(BEEPER,HIGH);
delayMicroseconds(75);
WRITE(BEEPER,LOW);
delayMicroseconds(75);
}
}
static void Sound_DoSound_Echo(void)
{
uint8_t nI;
for(nI=0;nI<10;nI++)
{
WRITE(BEEPER,HIGH);
delayMicroseconds(100);
WRITE(BEEPER,LOW);
delayMicroseconds(100);
}
}
static void Sound_DoSound_Prompt(void)
{
backlight_wake(2);
WRITE(BEEPER,HIGH);
_delay_ms(500);
WRITE(BEEPER,LOW);
}
static void Sound_DoSound_Alert(bool bOnce)
{
uint8_t nI,nMax;
nMax=bOnce?1:3;
for(nI=0;nI<nMax;nI++)
{
WRITE(BEEPER,HIGH);
delayMicroseconds(200);
WRITE(BEEPER,LOW);
delayMicroseconds(500);
}
}
static int16_t constexpr CONTINOUS_BEEP_PERIOD = 2000; // in ms
static ShortTimer beep_timer; // Timer to keep track of continous beeping
static bool bFirst; // true if the first beep has occurred, e_SOUND_MODE_ONCE
/// @brief Handles sound when waiting for user input
/// the function must be non-blocking. It is up to the caller
/// to call this function repeatedly.
/// Make sure to call sound_wait_for_user_reset() when the user has clicked the knob
/// Loud - should continuously beep
/// Silent - should be silent
/// Once - should beep once
/// Assist/Blind - as loud with beep and click on knob rotation and press
void sound_wait_for_user() {
#if BEEPER > 0
if (eSoundMode == e_SOUND_MODE_SILENT) return;
// Handle case where only one beep is needed
if (eSoundMode == e_SOUND_MODE_ONCE) {
if (bFirst) return;
Sound_MakeCustom(80, 0, false);
bFirst = true;
}
// Handle case where there should be continous beeps
if (beep_timer.expired_cont(CONTINOUS_BEEP_PERIOD)) {
beep_timer.start();
if (eSoundMode == e_SOUND_MODE_LOUD) {
Sound_MakeCustom(80, 0, false);
} else {
// Assist (lower volume sound)
Sound_MakeSound(e_SOUND_TYPE_ButtonEcho);
}
}
#endif // BEEPER > 0
}
/// @brief Resets the global state of sound_wait_for_user()
void sound_wait_for_user_reset()
{
beep_timer.stop();
bFirst = false;
}