sound.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. #include "sound.h"
  2. #include <stdio.h>
  3. #include "freertos/FreeRTOS.h"
  4. #include "freertos/task.h"
  5. //#include "driver/gpio.h"
  6. #include "esp_log.h"
  7. #include "sdkconfig.h"
  8. #include "driver/dac.h"
  9. #include "math.h"
  10. #include "config.h"
  11. #include "mqtt.h"
  12. #ifdef SOUND_ENABLED
  13. #define DAC_CHANNEL 1
  14. #define DAC_PIN GPIO_NUM_25 // GPIO pin for DAC output GPIO25=Channel 1
  15. #define TONE_FREQ 440 // Frequency of the tone in Hz
  16. #define TONE_DURATION 1000 // Duration of the tone in ms
  17. #define QUIET_DURATION 1000 // Duration of the quiet period in ms
  18. // Internal variable used to control the actual sound state
  19. static bool soundEnabled = false;
  20. static bool alarmMasterEnabled = true; // Master control, default ON
  21. static void play_tone(int frequency, float duration, int quietDuration, bool override) {
  22. int semitones = 0;
  23. int t_freq = frequency * pow(2.0, semitones / 12.0);
  24. int8_t cw_offset = 0;
  25. dac_cw_config_t cosineConf = {DAC_CHANNEL_1, DAC_CW_SCALE_8, DAC_CW_PHASE_0, t_freq, cw_offset};
  26. if (frequency == 0) {
  27. dac_output_disable(DAC_CHANNEL_1);
  28. } else {
  29. dac_cw_generator_config(&cosineConf);
  30. dac_output_enable(DAC_CHANNEL_1);
  31. }
  32. // Loop with 50mS loops until the duration is complete
  33. for(int i = 0; i < duration; i+=50) {
  34. vTaskDelay(pdMS_TO_TICKS(50));
  35. if( soundEnabled == false && override == false ) {
  36. break;
  37. }
  38. }
  39. dac_output_disable(DAC_CHANNEL_1);
  40. }
  41. static void setupSound() {
  42. int8_t cw_offset = 0;
  43. dac_cw_config_t cosineConf = {DAC_CHANNEL_1, DAC_CW_SCALE_8, DAC_CW_PHASE_0, 440, cw_offset};
  44. dac_output_disable(DAC_CHANNEL_1);
  45. dac_cw_generator_config(&cosineConf);
  46. dac_cw_generator_enable();
  47. dac_output_disable(DAC_CHANNEL_1);
  48. ESP_LOGI("SOUND", "Sound setup");
  49. }
  50. static void sound_task(void *pvParameters) {
  51. ESP_LOGI("SOUND", "Sound task starts....");
  52. setupSound();
  53. while (1) {
  54. vTaskDelay(pdMS_TO_TICKS(1000));
  55. if( soundEnabled ) {
  56. play_tone(TONE_FREQ, TONE_DURATION, QUIET_DURATION, false);
  57. }
  58. }
  59. }
  60. void initSound() {
  61. xTaskCreate(sound_task, "sound_task", 2048, NULL, 10, NULL);
  62. ESP_LOGI("SOUND", "Sound initialized");
  63. }
  64. // FreeRTOS Task: Handles the test beep asynchronously
  65. static void alarm_test_task(void *pvParameters) {
  66. play_tone(TONE_FREQ, TONE_DURATION, QUIET_DURATION, true);
  67. vTaskDelete(NULL); // Delete task after completion
  68. }
  69. // Function to enable/disable the notification sound (called by door sensor)
  70. void enableNotificationSound(bool enable) {
  71. if (!alarmMasterEnabled) {
  72. // If master is OFF, sound should always be OFF
  73. enable = false;
  74. }
  75. if (soundEnabled != enable) { // Only send MQTT if there's a change
  76. ESP_LOGI("SOUND", "Notification sound %s", enable ? "enabled" : "disabled");
  77. char mqtt_s[50];
  78. char value_s[10];
  79. sprintf(mqtt_s, "kitchen/fridge/doorAlarm");
  80. sprintf(value_s, "%s", enable ? "active" : "inactive");
  81. sendMQTTMessage(mqtt_s, value_s);
  82. soundEnabled = enable; // Update state AFTER sending message
  83. }
  84. }
  85. // Master control for the alarm system (called by Home Assistant)
  86. void alarmMasterControl(alarmState_t state) {
  87. switch (state) {
  88. case ALARM_OFF:
  89. alarmMasterEnabled = false; // Master disables alarm
  90. enableNotificationSound(false); // Ensure sound is OFF
  91. break;
  92. case ALARM_ON:
  93. alarmMasterEnabled = true; // Master enables alarm
  94. break;
  95. case ALARM_TEST:
  96. // Create a background task for the test beep, even if master is OFF
  97. xTaskCreate(alarm_test_task, "alarm_test_task", 2048, NULL, 5, NULL);
  98. break;
  99. }
  100. }
  101. #else
  102. void initSound() {};
  103. void enableNotificationSound(bool enable) {};
  104. void alarmMasterControl(alarmState_t state) {};
  105. #endif