Support trailing silence in buzzer tune

Support trailing silence in buzzer tune (#10694)
This commit is contained in:
Theo Arends 2021-01-27 16:09:56 +01:00
parent 64d1455bf6
commit f083233b09
3 changed files with 41 additions and 56 deletions

View File

@ -9,6 +9,7 @@ All notable changes to this project will be documented in this file.
- Commands ``ChannelRemap``, ``MultiPWM``, ``AlexaCTRange``, ``PowerOnFade``, ``PWMCT``, ``WhiteBlend``, ``VirtualCT`` as synonyms for ``SetOption37, 68, 82, 91, 92, 105 and 106`` respectively - Commands ``ChannelRemap``, ``MultiPWM``, ``AlexaCTRange``, ``PowerOnFade``, ``PWMCT``, ``WhiteBlend``, ``VirtualCT`` as synonyms for ``SetOption37, 68, 82, 91, 92, 105 and 106`` respectively
- Commands ``ZbNameKey``, ``ZbDeviceTopic``, ``ZbNoPrefix``, ``ZbEndpointSuffix``, ``ZbNoAutoBind``, ``ZbNameTopic`` as synonyms for ``SetOption83, 89, 100, 101, 110 and 112`` respectively - Commands ``ZbNameKey``, ``ZbDeviceTopic``, ``ZbNoPrefix``, ``ZbEndpointSuffix``, ``ZbNoAutoBind``, ``ZbNameTopic`` as synonyms for ``SetOption83, 89, 100, 101, 110 and 112`` respectively
- Support for ESP32 ``Module 5`` Wireless Tag Eth01 (#9496) - Support for ESP32 ``Module 5`` Wireless Tag Eth01 (#9496)
- Support trailing silence in buzzer tune (#10694)
### Changed ### Changed
- Maximum chars in ``AddLog_P`` logging restored from 128 to 700 (MAX_LOGSZ) to solve broken error messages - Maximum chars in ``AddLog_P`` logging restored from 128 to 700 (MAX_LOGSZ) to solve broken error messages

View File

@ -85,11 +85,12 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota
- Support for 24/26/32/34 bit RFID Wiegand interface (D0/D1) by Sigurd Leuther [#3647](https://github.com/arendst/Tasmota/issues/3647) - Support for 24/26/32/34 bit RFID Wiegand interface (D0/D1) by Sigurd Leuther [#3647](https://github.com/arendst/Tasmota/issues/3647)
- Support for SM2135 current selection using GPIO ``SM2135 DAT`` index [#10634](https://github.com/arendst/Tasmota/issues/10634) - Support for SM2135 current selection using GPIO ``SM2135 DAT`` index [#10634](https://github.com/arendst/Tasmota/issues/10634)
- Support for Sugar Valley NeoPool Controller by Norbert Richter [#10637](https://github.com/arendst/Tasmota/issues/10637) - Support for Sugar Valley NeoPool Controller by Norbert Richter [#10637](https://github.com/arendst/Tasmota/issues/10637)
- Support rotary encoder on Shelly Dimmer [#10407](https://github.com/arendst/Tasmota/issues/10407#issuecomment-756240920)
- Support character `#` to be replaced by `space`-character in command ``Publish`` topic [#10258](https://github.com/arendst/Tasmota/issues/10258)
- Support for ESP32 ``Module 3`` Odroid Go 16MB binary tasmota32-odroidgo.bin [#8630](https://github.com/arendst/Tasmota/issues/8630) - Support for ESP32 ``Module 3`` Odroid Go 16MB binary tasmota32-odroidgo.bin [#8630](https://github.com/arendst/Tasmota/issues/8630)
- Support for ESP32 ``Module 5`` Wireless Tag Eth01 [#9496](https://github.com/arendst/Tasmota/issues/9496) - Support for ESP32 ``Module 5`` Wireless Tag Eth01 [#9496](https://github.com/arendst/Tasmota/issues/9496)
- Support for ESP32 ``Module 7`` M5stack core2 16MB binary tasmota32-core2.bin [#10635](https://github.com/arendst/Tasmota/issues/10635) - Support for ESP32 ``Module 7`` M5stack core2 16MB binary tasmota32-core2.bin [#10635](https://github.com/arendst/Tasmota/issues/10635)
- Support rotary encoder on Shelly Dimmer [#10407](https://github.com/arendst/Tasmota/issues/10407#issuecomment-756240920)
- Support character `#` to be replaced by `space`-character in command ``Publish`` topic [#10258](https://github.com/arendst/Tasmota/issues/10258)
- Support trailing silence in buzzer tune [#10694](https://github.com/arendst/Tasmota/issues/10694)
- Rule trigger string comparisons for EndsWith ``$>``, StartsWith ``$<`` and Contains ``$|`` [#10538](https://github.com/arendst/Tasmota/issues/10538) - Rule trigger string comparisons for EndsWith ``$>``, StartsWith ``$<`` and Contains ``$|`` [#10538](https://github.com/arendst/Tasmota/issues/10538)
- SPI display driver SSD1331 Color oled by Jeroen Vermeulen [#10376](https://github.com/arendst/Tasmota/issues/10376) - SPI display driver SSD1331 Color oled by Jeroen Vermeulen [#10376](https://github.com/arendst/Tasmota/issues/10376)
- Compile time option ``USE_MQTT_TLS_DROP_OLD_FINGERPRINT`` to drop old (less secure) TLS fingerprint - Compile time option ``USE_MQTT_TLS_DROP_OLD_FINGERPRINT`` to drop old (less secure) TLS fingerprint

View File

@ -32,44 +32,39 @@ struct BUZZER {
uint8_t inverted = 0; // Buzzer inverted flag (1 = (0 = On, 1 = Off)) uint8_t inverted = 0; // Buzzer inverted flag (1 = (0 = On, 1 = Off))
uint8_t count = 0; // Number of buzzes uint8_t count = 0; // Number of buzzes
uint8_t mode = 0; // Buzzer mode (0 = regular, 1 = infinite, 2 = follow LED) uint8_t mode = 0; // Buzzer mode (0 = regular, 1 = infinite, 2 = follow LED)
uint8_t freq_mode = 0; // Output mode (0 = regular, 1 = using frequency output)
uint8_t set[2]; uint8_t set[2];
uint8_t duration; uint8_t duration;
uint8_t state = 0; uint8_t state = 0;
uint8_t tune_size = 0;
uint8_t size = 0;
} Buzzer; } Buzzer;
/*********************************************************************************************/ /*********************************************************************************************/
void BuzzerSet(uint8_t state) void BuzzerSet(uint32_t state) {
{
if (Buzzer.inverted) { if (Buzzer.inverted) {
state = !state; state = !state;
} }
if (Buzzer.freq_mode == 1) { if (Settings.flag4.buzzer_freq_mode) { // SetOption111 - Enable frequency output mode for buzzer
static uint8_t last_state = 0; static uint8_t last_state = 0;
if (last_state != state) { if (last_state != state) {
if (state) { // Set 50% duty cycle for frequency output
analogWrite(Pin(GPIO_BUZZER, 0), Settings.pwm_range / 2); // set 50% duty cycle for frequency output // Set 0% (or 100% for inverted PWM) duty cycle which turns off frequency output either way
} analogWrite(Pin(GPIO_BUZZER), (state) ? Settings.pwm_range / 2 : 0); // set duty cycle for frequency output
else {
analogWrite(Pin(GPIO_BUZZER, 0), 0); // set 0% (or 100% for inverted PWM) duty cycle which turns off frequency output either way
}
last_state = state; last_state = state;
} }
} else {
DigitalWrite(GPIO_BUZZER, 0, state); // Buzzer On/Off
} }
else {
DigitalWrite(GPIO_BUZZER, 0, state); // Buzzer On/Off
}
} }
//void BuzzerBeep(uint32_t count = 1, uint32_t on = 1, uint32_t off = 1, uint32_t tune = 0, uint32_t mode = 0); //void BuzzerBeep(uint32_t count = 1, uint32_t on = 1, uint32_t off = 1, uint32_t tune = 0, uint32_t mode = 0);
void BuzzerBeep(uint32_t count, uint32_t on, uint32_t off, uint32_t tune, uint32_t mode) void BuzzerBeep(uint32_t count, uint32_t on, uint32_t off, uint32_t tune, uint32_t mode) {
{ Buzzer.set[0] = off; // Off duration in 100 mSec steps
Buzzer.set[0] = off; // off duration in 100 mSec steps Buzzer.set[1] = on; // On duration in 100 mSec steps
Buzzer.set[1] = on; // on duration in 100 mSec steps Buzzer.duration = 1; // Start buzzer on first step
Buzzer.duration = 1; // Start buzzer on first step Buzzer.tune_size = 0;
Buzzer.tune_reload = 0; Buzzer.tune_reload = 0;
Buzzer.mode = mode; Buzzer.mode = mode;
@ -78,65 +73,55 @@ void BuzzerBeep(uint32_t count, uint32_t on, uint32_t off, uint32_t tune, uint32
uint32_t tune2 = tune; uint32_t tune2 = tune;
for (uint32_t i = 0; i < 32; i++) { for (uint32_t i = 0; i < 32; i++) {
if (!(tune2 & 0x80000000)) { if (!(tune2 & 0x80000000)) {
tune2 <<= 1; // Skip leading silence tune2 <<= 1; // Skip leading silence
} else { } else {
Buzzer.tune_reload <<= 1; // Add swapped tune Buzzer.tune_size++; // Allow trailing silence
Buzzer.tune_reload <<= 1; // Add swapped tune
Buzzer.tune_reload |= tune1 & 1; Buzzer.tune_reload |= tune1 & 1;
tune1 >>= 1; tune1 >>= 1;
} }
} }
Buzzer.size = Buzzer.tune_size;
Buzzer.tune = Buzzer.tune_reload; Buzzer.tune = Buzzer.tune_reload;
} }
Buzzer.count = count * 2; // Start buzzer Buzzer.count = count * 2; // Start buzzer
// We can use PWM mode for buzzer output if enabled. AddLog(LOG_LEVEL_DEBUG, PSTR("BUZ: Count %d(%d), Time %d/%d, Tune 0x%08X(0x%08X), Size %d, Mode %d"),
if (Settings.flag4.buzzer_freq_mode) { // SetOption111 - Enable frequency output mode for buzzer count, Buzzer.count, on, off, tune, Buzzer.tune, Buzzer.tune_size, Settings.flag4.buzzer_freq_mode);
Buzzer.freq_mode = 1;
}
else {
Buzzer.freq_mode = 0;
}
AddLog(LOG_LEVEL_DEBUG, PSTR("BUZ: %d(%d),%d,%d,0x%08X(0x%08X),%d"), count, Buzzer.count, on, off, tune, Buzzer.tune, Buzzer.freq_mode);
Buzzer.enable = (Buzzer.count > 0); Buzzer.enable = (Buzzer.count > 0);
if (Buzzer.enable) { if (Buzzer.enable) {
if (Settings.sleep > PWM_MAX_SLEEP) { if (Settings.sleep > PWM_MAX_SLEEP) {
TasmotaGlobal.sleep = PWM_MAX_SLEEP; // set a maxumum value of 10 milliseconds to ensure that buzzer periods are a bit more accurate TasmotaGlobal.sleep = PWM_MAX_SLEEP; // Set a maxumum value of 10 milliseconds to ensure that buzzer periods are a bit more accurate
} else { } else {
TasmotaGlobal.sleep = Settings.sleep; // or keep the current sleep if it's lower than 10 TasmotaGlobal.sleep = Settings.sleep; // Or keep the current sleep if it's lower than 10
} }
} } else {
else { TasmotaGlobal.sleep = Settings.sleep; // Restore original sleep
TasmotaGlobal.sleep = Settings.sleep; // restore original sleep
BuzzerSet(0); BuzzerSet(0);
} }
} }
void BuzzerSetStateToLed(uint32_t state) void BuzzerSetStateToLed(uint32_t state) {
{
if (Buzzer.enable && (2 == Buzzer.mode)) { if (Buzzer.enable && (2 == Buzzer.mode)) {
Buzzer.state = (state != 0); Buzzer.state = (state != 0);
BuzzerSet(Buzzer.state); BuzzerSet(Buzzer.state);
} }
} }
void BuzzerBeep(uint32_t count) void BuzzerBeep(uint32_t count) {
{
BuzzerBeep(count, 1, 1, 0, 0); BuzzerBeep(count, 1, 1, 0, 0);
} }
void BuzzerEnabledBeep(uint32_t count, uint32_t duration) void BuzzerEnabledBeep(uint32_t count, uint32_t duration) {
{ if (Settings.flag3.buzzer_enable) { // SetOption67 - Enable buzzer when available
if (Settings.flag3.buzzer_enable) { // SetOption67 - Enable buzzer when available
BuzzerBeep(count, duration, 1, 0, 0); BuzzerBeep(count, duration, 1, 0, 0);
} }
} }
/*********************************************************************************************/ /*********************************************************************************************/
bool BuzzerPinState(void) bool BuzzerPinState(void) {
{
if (XdrvMailbox.index == AGPIO(GPIO_BUZZER_INV)) { if (XdrvMailbox.index == AGPIO(GPIO_BUZZER_INV)) {
Buzzer.inverted = 1; Buzzer.inverted = 1;
XdrvMailbox.index -= (AGPIO(GPIO_BUZZER_INV) - AGPIO(GPIO_BUZZER)); XdrvMailbox.index -= (AGPIO(GPIO_BUZZER_INV) - AGPIO(GPIO_BUZZER));
@ -145,8 +130,7 @@ bool BuzzerPinState(void)
return false; return false;
} }
void BuzzerInit(void) void BuzzerInit(void) {
{
if (PinUsed(GPIO_BUZZER)) { if (PinUsed(GPIO_BUZZER)) {
pinMode(Pin(GPIO_BUZZER), OUTPUT); pinMode(Pin(GPIO_BUZZER), OUTPUT);
BuzzerSet(0); BuzzerSet(0);
@ -155,17 +139,18 @@ void BuzzerInit(void)
} }
} }
void BuzzerEvery100mSec(void) void BuzzerEvery100mSec(void) {
{
if (Buzzer.enable && (Buzzer.mode != 2)) { if (Buzzer.enable && (Buzzer.mode != 2)) {
if (Buzzer.count) { if (Buzzer.count) {
if (Buzzer.duration) { if (Buzzer.duration) {
Buzzer.duration--; Buzzer.duration--;
if (!Buzzer.duration) { if (!Buzzer.duration) {
if (Buzzer.tune) { if (Buzzer.size) {
Buzzer.size--;
Buzzer.state = Buzzer.tune & 1; Buzzer.state = Buzzer.tune & 1;
Buzzer.tune >>= 1; Buzzer.tune >>= 1;
} else { } else {
Buzzer.size = Buzzer.tune_size;
Buzzer.tune = Buzzer.tune_reload; Buzzer.tune = Buzzer.tune_reload;
Buzzer.count -= (Buzzer.tune_reload) ? 2 : 1; Buzzer.count -= (Buzzer.tune_reload) ? 2 : 1;
Buzzer.state = Buzzer.count & 1; Buzzer.state = Buzzer.count & 1;
@ -193,8 +178,7 @@ const char kBuzzerCommands[] PROGMEM = "|" // No prefix
void (* const BuzzerCommand[])(void) PROGMEM = { void (* const BuzzerCommand[])(void) PROGMEM = {
&CmndBuzzer }; &CmndBuzzer };
void CmndBuzzer(void) void CmndBuzzer(void) {
{
// Buzzer <number of beeps>,<duration of beep in 100mS steps>,<duration of silence in 100mS steps>,<tune> // Buzzer <number of beeps>,<duration of beep in 100mS steps>,<duration of silence in 100mS steps>,<tune>
// All parameters are optional // All parameters are optional
// //
@ -233,8 +217,7 @@ void CmndBuzzer(void)
* Interface * Interface
\*********************************************************************************************/ \*********************************************************************************************/
bool Xdrv24(uint8_t function) bool Xdrv24(uint8_t function) {
{
bool result = false; bool result = false;
if (Buzzer.active) { if (Buzzer.active) {