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 ``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 trailing silence in buzzer tune (#10694)
### Changed
- 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 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 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 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 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)
- 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

View File

@ -32,44 +32,39 @@ struct BUZZER {
uint8_t inverted = 0; // Buzzer inverted flag (1 = (0 = On, 1 = Off))
uint8_t count = 0; // Number of buzzes
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 duration;
uint8_t state = 0;
uint8_t tune_size = 0;
uint8_t size = 0;
} Buzzer;
/*********************************************************************************************/
void BuzzerSet(uint8_t state)
{
void BuzzerSet(uint32_t state) {
if (Buzzer.inverted) {
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;
if (last_state != state) {
if (state) {
analogWrite(Pin(GPIO_BUZZER, 0), Settings.pwm_range / 2); // set 50% 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
}
// 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
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, uint32_t on, uint32_t off, uint32_t tune, uint32_t mode)
{
Buzzer.set[0] = off; // off duration in 100 mSec steps
Buzzer.set[1] = on; // on duration in 100 mSec steps
Buzzer.duration = 1; // Start buzzer on first step
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[1] = on; // On duration in 100 mSec steps
Buzzer.duration = 1; // Start buzzer on first step
Buzzer.tune_size = 0;
Buzzer.tune_reload = 0;
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;
for (uint32_t i = 0; i < 32; i++) {
if (!(tune2 & 0x80000000)) {
tune2 <<= 1; // Skip leading silence
tune2 <<= 1; // Skip leading silence
} 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;
tune1 >>= 1;
}
}
Buzzer.size = Buzzer.tune_size;
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.
if (Settings.flag4.buzzer_freq_mode) { // SetOption111 - Enable frequency output mode for buzzer
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);
AddLog(LOG_LEVEL_DEBUG, PSTR("BUZ: Count %d(%d), Time %d/%d, Tune 0x%08X(0x%08X), Size %d, Mode %d"),
count, Buzzer.count, on, off, tune, Buzzer.tune, Buzzer.tune_size, Settings.flag4.buzzer_freq_mode);
Buzzer.enable = (Buzzer.count > 0);
if (Buzzer.enable) {
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 {
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 {
TasmotaGlobal.sleep = Settings.sleep; // restore original sleep
} else {
TasmotaGlobal.sleep = Settings.sleep; // Restore original sleep
BuzzerSet(0);
}
}
void BuzzerSetStateToLed(uint32_t state)
{
void BuzzerSetStateToLed(uint32_t state) {
if (Buzzer.enable && (2 == Buzzer.mode)) {
Buzzer.state = (state != 0);
BuzzerSet(Buzzer.state);
}
}
void BuzzerBeep(uint32_t count)
{
void BuzzerBeep(uint32_t count) {
BuzzerBeep(count, 1, 1, 0, 0);
}
void BuzzerEnabledBeep(uint32_t count, uint32_t duration)
{
if (Settings.flag3.buzzer_enable) { // SetOption67 - Enable buzzer when available
void BuzzerEnabledBeep(uint32_t count, uint32_t duration) {
if (Settings.flag3.buzzer_enable) { // SetOption67 - Enable buzzer when available
BuzzerBeep(count, duration, 1, 0, 0);
}
}
/*********************************************************************************************/
bool BuzzerPinState(void)
{
bool BuzzerPinState(void) {
if (XdrvMailbox.index == AGPIO(GPIO_BUZZER_INV)) {
Buzzer.inverted = 1;
XdrvMailbox.index -= (AGPIO(GPIO_BUZZER_INV) - AGPIO(GPIO_BUZZER));
@ -145,8 +130,7 @@ bool BuzzerPinState(void)
return false;
}
void BuzzerInit(void)
{
void BuzzerInit(void) {
if (PinUsed(GPIO_BUZZER)) {
pinMode(Pin(GPIO_BUZZER), OUTPUT);
BuzzerSet(0);
@ -155,17 +139,18 @@ void BuzzerInit(void)
}
}
void BuzzerEvery100mSec(void)
{
void BuzzerEvery100mSec(void) {
if (Buzzer.enable && (Buzzer.mode != 2)) {
if (Buzzer.count) {
if (Buzzer.duration) {
Buzzer.duration--;
if (!Buzzer.duration) {
if (Buzzer.tune) {
if (Buzzer.size) {
Buzzer.size--;
Buzzer.state = Buzzer.tune & 1;
Buzzer.tune >>= 1;
} else {
Buzzer.size = Buzzer.tune_size;
Buzzer.tune = Buzzer.tune_reload;
Buzzer.count -= (Buzzer.tune_reload) ? 2 : 1;
Buzzer.state = Buzzer.count & 1;
@ -193,8 +178,7 @@ const char kBuzzerCommands[] PROGMEM = "|" // No prefix
void (* const BuzzerCommand[])(void) PROGMEM = {
&CmndBuzzer };
void CmndBuzzer(void)
{
void CmndBuzzer(void) {
// Buzzer <number of beeps>,<duration of beep in 100mS steps>,<duration of silence in 100mS steps>,<tune>
// All parameters are optional
//
@ -233,8 +217,7 @@ void CmndBuzzer(void)
* Interface
\*********************************************************************************************/
bool Xdrv24(uint8_t function)
{
bool Xdrv24(uint8_t function) {
bool result = false;
if (Buzzer.active) {