diff --git a/CMakeLists.txt b/CMakeLists.txt index 775baecf412..d952d51474e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,6 +57,7 @@ set(CORE_SRCS cores/esp32/stdlib_noniso.c cores/esp32/Stream.cpp cores/esp32/StreamString.cpp + cores/esp32/Tone.cpp cores/esp32/HWCDC.cpp cores/esp32/USB.cpp cores/esp32/USBCDC.cpp diff --git a/cores/esp32/Arduino.h b/cores/esp32/Arduino.h index b1e8f7cd7de..c8be9222b39 100644 --- a/cores/esp32/Arduino.h +++ b/cores/esp32/Arduino.h @@ -195,6 +195,10 @@ extern "C" void configTime(long gmtOffset_sec, int daylightOffset_sec, extern "C" void configTzTime(const char* tz, const char* server1, const char* server2 = nullptr, const char* server3 = nullptr); +void setToneChannel(uint8_t channel = 0); +void tone(uint8_t _pin, unsigned int frequency, unsigned long duration = 0); +void noTone(uint8_t _pin); + // WMath prototypes long random(long); #endif /* __cplusplus */ diff --git a/cores/esp32/Tone.cpp b/cores/esp32/Tone.cpp new file mode 100644 index 00000000000..ca69c10c13b --- /dev/null +++ b/cores/esp32/Tone.cpp @@ -0,0 +1,131 @@ +#include +#include "esp32-hal-ledc.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" + +static TaskHandle_t _tone_task = NULL; +static QueueHandle_t _tone_queue = NULL; +static uint8_t _channel = 0; + +typedef enum{ + TONE_START, + TONE_END, + TONE_SET_CHANNEL +} tone_cmd_t; + +typedef struct{ + tone_cmd_t tone_cmd; + uint8_t pin; + unsigned int frequency; + unsigned long duration; + uint8_t channel; +} tone_msg_t; + +static void tone_task(void*){ + tone_msg_t tone_msg; + while(1){ + xQueueReceive(_tone_queue, &tone_msg, portMAX_DELAY); + switch(tone_msg.tone_cmd){ + case TONE_START: + log_d("Task received from queue TONE_START: _pin=%d, frequency=%u Hz, duration=%u ms", tone_msg.pin, tone_msg.frequency, tone_msg.duration); + + log_d("Setup LED controll on channel %d", _channel); + // ledcSetup(_channel, tone_msg.frequency, 11); + // ledcAttachPin(tone_msg.pin, _channel); + // ledcWrite(_channel, 1024); + ledcWriteTone(_channel, tone_msg.frequency); + ledcAttachPin(tone_msg.pin, _channel); + + if(tone_msg.duration){ + delay(tone_msg.duration); + ledcDetachPin(tone_msg.pin); + ledcWriteTone(_channel, 0); + } + break; + + case TONE_END: + log_d("Task received from queue TONE_END: pin=%d", tone_msg.pin); + ledcDetachPin(tone_msg.pin); + ledcWriteTone(_channel, 0); + break; + + case TONE_SET_CHANNEL: + log_d("Task received from queue TONE_SET_CHANNEL: channel=%d", tone_msg.channel); + _channel = tone_msg.channel; + break; + + default: ; // do nothing + } // switch + } // infinite loop +} + +static int tone_init(){ + if(_tone_queue == NULL){ + log_v("Creating tone queue"); + _tone_queue = xQueueCreate(128, sizeof(tone_msg_t)); + if(_tone_queue == NULL){ + log_e("Could not create tone queue"); + return 0; // ERR + } + log_v("Tone queue created"); + } + + if(_tone_task == NULL){ + log_v("Creating tone task"); + xTaskCreate( + tone_task, // Function to implement the task + "toneTask", // Name of the task + 3500, // Stack size in words + NULL, // Task input parameter + 1, // Priority of the task + &_tone_task // Task handle. + ); + if(_tone_task == NULL){ + log_e("Could not create tone task"); + return 0; // ERR + } + log_v("Tone task created"); + } + return 1; // OK +} + +void setToneChannel(uint8_t channel){ + log_d("channel=%d", channel); + if(tone_init()){ + tone_msg_t tone_msg = { + .tone_cmd = TONE_SET_CHANNEL, + .channel = channel + }; + xQueueSend(_tone_queue, &tone_msg, portMAX_DELAY); + } +} + +void noTone(uint8_t _pin){ + log_d("noTone was called"); + if(tone_init()){ + tone_msg_t tone_msg = { + .tone_cmd = TONE_END, + .pin = _pin + }; + xQueueSend(_tone_queue, &tone_msg, portMAX_DELAY); + } +} + +// parameters: +// _pin - pin number which will output the signal +// frequency - PWM frequency in Hz +// duration - time in ms - how long will the signal be outputted. +// If not provided, or 0 you must manually call noTone to end output +void tone(uint8_t _pin, unsigned int frequency, unsigned long duration){ + log_d("_pin=%d, frequency=%u Hz, duration=%u ms", _pin, frequency, duration); + if(tone_init()){ + tone_msg_t tone_msg = { + .tone_cmd = TONE_START, + .pin = _pin, + .frequency = frequency, + .duration = duration + }; + xQueueSend(_tone_queue, &tone_msg, portMAX_DELAY); + } +}