123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- #include "sound.h"
- #include <stdio.h>
- #include "freertos/FreeRTOS.h"
- #include "freertos/task.h"
- //#include "driver/gpio.h"
- #include "esp_log.h"
- #include "sdkconfig.h"
- #include "driver/dac.h"
- #include "math.h"
- #include "config.h"
- #include "mqtt.h"
- #ifdef SOUND_ENABLED
- #define DAC_CHANNEL 1
- #define DAC_PIN GPIO_NUM_25 // GPIO pin for DAC output GPIO25=Channel 1
- #define TONE_FREQ 440 // Frequency of the tone in Hz
- #define TONE_DURATION 1000 // Duration of the tone in ms
- #define QUIET_DURATION 1000 // Duration of the quiet period in ms
- // Internal variable used to control the actual sound state
- static bool soundEnabled = false;
- static bool alarmMasterEnabled = true; // Master control, default ON
- static void play_tone(int frequency, float duration, int quietDuration, bool override) {
- int semitones = 0;
- int t_freq = frequency * pow(2.0, semitones / 12.0);
- int8_t cw_offset = 0;
- dac_cw_config_t cosineConf = {DAC_CHANNEL_1, DAC_CW_SCALE_8, DAC_CW_PHASE_0, t_freq, cw_offset};
- if (frequency == 0) {
- dac_output_disable(DAC_CHANNEL_1);
- } else {
- dac_cw_generator_config(&cosineConf);
- dac_output_enable(DAC_CHANNEL_1);
- }
- // Loop with 50mS loops until the duration is complete
- for(int i = 0; i < duration; i+=50) {
- vTaskDelay(pdMS_TO_TICKS(50));
- if( soundEnabled == false && override == false ) {
- break;
- }
- }
- dac_output_disable(DAC_CHANNEL_1);
- }
- static void setupSound() {
- int8_t cw_offset = 0;
- dac_cw_config_t cosineConf = {DAC_CHANNEL_1, DAC_CW_SCALE_8, DAC_CW_PHASE_0, 440, cw_offset};
- dac_output_disable(DAC_CHANNEL_1);
- dac_cw_generator_config(&cosineConf);
- dac_cw_generator_enable();
- dac_output_disable(DAC_CHANNEL_1);
- ESP_LOGI("SOUND", "Sound setup");
- }
- static void sound_task(void *pvParameters) {
- ESP_LOGI("SOUND", "Sound task starts....");
- setupSound();
- while (1) {
- vTaskDelay(pdMS_TO_TICKS(1000));
- if( soundEnabled ) {
- play_tone(TONE_FREQ, TONE_DURATION, QUIET_DURATION, false);
- }
- }
- }
- void initSound() {
- xTaskCreate(sound_task, "sound_task", 2048, NULL, 10, NULL);
- ESP_LOGI("SOUND", "Sound initialized");
- }
- // FreeRTOS Task: Handles the test beep asynchronously
- static void alarm_test_task(void *pvParameters) {
- play_tone(TONE_FREQ, TONE_DURATION, QUIET_DURATION, true);
- vTaskDelete(NULL); // Delete task after completion
- }
- // Function to enable/disable the notification sound (called by door sensor)
- void enableNotificationSound(bool enable) {
- if (!alarmMasterEnabled) {
- // If master is OFF, sound should always be OFF
- enable = false;
- }
- if (soundEnabled != enable) { // Only send MQTT if there's a change
- ESP_LOGI("SOUND", "Notification sound %s", enable ? "enabled" : "disabled");
- char mqtt_s[50];
- char value_s[10];
- sprintf(mqtt_s, "kitchen/fridge/doorAlarm");
- sprintf(value_s, "%s", enable ? "active" : "inactive");
- sendMQTTMessage(mqtt_s, value_s);
- soundEnabled = enable; // Update state AFTER sending message
- }
- }
- // Master control for the alarm system (called by Home Assistant)
- void alarmMasterControl(alarmState_t state) {
- switch (state) {
- case ALARM_OFF:
- alarmMasterEnabled = false; // Master disables alarm
- enableNotificationSound(false); // Ensure sound is OFF
- break;
- case ALARM_ON:
- alarmMasterEnabled = true; // Master enables alarm
- break;
- case ALARM_TEST:
- // Create a background task for the test beep, even if master is OFF
- xTaskCreate(alarm_test_task, "alarm_test_task", 2048, NULL, 5, NULL);
- break;
- }
- }
- #else
- void initSound() {};
- void enableNotificationSound(bool enable) {};
- void alarmMasterControl(alarmState_t state) {};
- #endif
|