ukkonooa and frequency slider

This commit is contained in:
2026-01-13 14:49:35 +02:00
parent c767b541be
commit a2871a193b
11 changed files with 335 additions and 56 deletions

6
.clangd Normal file
View File

@@ -0,0 +1,6 @@
CompileFlags:
Remove: [
'-fstrict-volatile-bitfields',
'-fno-tree-switch-conversion',
'-fno-shrink-wrap'
]

View File

@@ -1,2 +1,3 @@
idf_component_register(SRCS "esp-pwm.c"
INCLUDE_DIRS ".")
idf_component_register(SRCS "esp-pwm.c" "buzzer.c" "un.c" "freq_slider.c"
INCLUDE_DIRS "." "./headers"
)

84
main/buzzer.c Normal file
View File

@@ -0,0 +1,84 @@
#include <math.h>
#include <stdint.h>
#include "driver/ledc.h"
#include "esp_clk_tree.h"
#include "esp_err.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h" // IWYU pragma: keep
#include "freertos/task.h"
#include "hal/ledc_types.h"
#include "soc/clk_tree_defs.h"
#include "buzzer.h"
static const char* TAG = "BUZZER_C";
const uint32_t init_buzzer_freq = 2731;
void buzzer_init(const uint32_t frequency) {
uint32_t clk_freq = 0;
ESP_ERROR_CHECK(esp_clk_tree_src_get_freq_hz(
SOC_MOD_CLK_RC_FAST, ESP_CLK_TREE_SRC_FREQ_PRECISION_EXACT, &clk_freq));
uint32_t duty_resolution =
ledc_find_suitable_duty_resolution(clk_freq, frequency);
if (duty_resolution == 0) {
ESP_LOGE(TAG, "Could not determine optimal duty resolution.\n");
return;
}
ledc_timer_config_t ledc_config = {.speed_mode = LEDC_LOW_SPEED_MODE,
.timer_num = LEDC_TIMER_0,
.freq_hz = frequency,
.duty_resolution = duty_resolution,
.clk_cfg = LEDC_USE_RC_FAST_CLK};
ESP_ERROR_CHECK(ledc_timer_config(&ledc_config));
ledc_channel_config_t ledc_ch_config = {
.gpio_num = 9,
.speed_mode = LEDC_LOW_SPEED_MODE,
.channel = LEDC_CHANNEL_0,
.timer_sel = LEDC_TIMER_0,
.duty = (uint32_t)(pow(2, duty_resolution) / 2),
// .hpoint = ((uint32_t) pow(2, duty_resolution)) - 1,
.hpoint = 0,
.sleep_mode = LEDC_SLEEP_MODE_KEEP_ALIVE,
.flags.output_invert = false};
ESP_ERROR_CHECK(ledc_channel_config(&ledc_ch_config));
}
uint32_t modify_frequency(int amount) {
uint32_t freq = ledc_get_freq(LEDC_LOW_SPEED_MODE, LEDC_TIMER_0) + amount;
if (freq < 10) {
freq = 10;
}
buzzer_pause();
ESP_ERROR_CHECK(ledc_set_freq(LEDC_LOW_SPEED_MODE, LEDC_TIMER_0, freq));
buzzer_resume();
return freq;
}
uint32_t reset_frequency() {
ESP_ERROR_CHECK(
ledc_set_freq(LEDC_LOW_SPEED_MODE, LEDC_TIMER_0, init_buzzer_freq));
return init_buzzer_freq;
}
void set_frequency(const uint32_t freq) {
ESP_ERROR_CHECK(ledc_set_freq(LEDC_LOW_SPEED_MODE, LEDC_TIMER_0, freq));
}
void buzzer_pause() {
ESP_ERROR_CHECK(ledc_timer_pause(LEDC_LOW_SPEED_MODE, LEDC_TIMER_0));
}
void buzzer_reset() {
ESP_ERROR_CHECK(ledc_timer_rst(LEDC_LOW_SPEED_MODE, LEDC_TIMER_0));
}
void buzzer_resume() {
ESP_ERROR_CHECK(ledc_timer_resume(LEDC_LOW_SPEED_MODE, LEDC_TIMER_0));
}

View File

@@ -1,55 +1,34 @@
#include <stdio.h>
#include <math.h>
#include <stdint.h>
#include "driver/ledc.h"
#include "hal/ledc_types.h"
#include "soc/clk_tree_defs.h"
#include "esp_clk_tree.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/FreeRTOS.h" // IWYU pragma: keep
#include "freertos/projdefs.h"
#include "freertos/task.h"
const char* TAG = "MAIN_CPP";
#include "freq_slider.h"
#include "un.h"
extern const uint32_t init_buzzer_freq;
const char* TAG = "MAIN_C";
void app_main() {
ESP_LOGI(TAG, "BOOT\n");
ESP_LOGI(TAG, "BOOT");
const uint32_t timer_freq = 2731;
// Only enable one task at a time.
uint32_t clk_freq = 0;
ESP_ERROR_CHECK(esp_clk_tree_src_get_freq_hz(SOC_MOD_CLK_RC_FAST, ESP_CLK_TREE_SRC_FREQ_PRECISION_EXACT, &clk_freq));
// if (xTaskCreate(freq_slider_task, "freq_slider_task", 4096, NULL, tskIDLE_PRIORITY,
// NULL) == pdFALSE) {
// ESP_LOGE(TAG, "Failed to create freq_slider_task.");
// }
uint32_t duty_resolution = ledc_find_suitable_duty_resolution(clk_freq, timer_freq);
if (duty_resolution == 0) {
ESP_LOGE(TAG, "Could not determine optimal duty resolution.\n");
return;
if (xTaskCreate(un_task, "un_task", 4096, NULL, tskIDLE_PRIORITY,
NULL) == pdFALSE) {
ESP_LOGE(TAG, "Failed to create un_task.");
}
ledc_timer_config_t ledc_config = {
.speed_mode = LEDC_LOW_SPEED_MODE,
.timer_num = LEDC_TIMER_0,
.freq_hz = timer_freq,
.duty_resolution = duty_resolution,
.clk_cfg = LEDC_USE_RC_FAST_CLK
};
ESP_ERROR_CHECK(ledc_timer_config(&ledc_config));
ledc_channel_config_t ledc_ch_config = {
.gpio_num = 9,
.speed_mode = LEDC_LOW_SPEED_MODE,
.channel = LEDC_CHANNEL_0,
.timer_sel = LEDC_TIMER_0,
.duty = (uint32_t) (pow(2, duty_resolution) / 2),
// .hpoint = ((uint32_t) pow(2, duty_resolution)) - 1,
.hpoint = 0,
.sleep_mode = LEDC_SLEEP_MODE_KEEP_ALIVE,
.flags.output_invert = false
};
ESP_ERROR_CHECK(ledc_channel_config(&ledc_ch_config));
while (true) {
vTaskDelay(10000);
vTaskDelay(pdMS_TO_TICKS(10000));
}
}

40
main/freq_slider.c Normal file
View File

@@ -0,0 +1,40 @@
#include <stdbool.h>
#include "driver/usb_serial_jtag.h"
#include "portmacro.h"
#include "esp_log.h"
#include "buzzer.h"
#include "arraylen.h"
extern const uint32_t init_buzzer_freq;
static const char* TAG = "FREQ_SLIDER_C";
void freq_slider_task(void* param) {
buzzer_init(init_buzzer_freq);
usb_serial_jtag_driver_config_t jtag_config = {.rx_buffer_size = 1024,
.tx_buffer_size = 1024};
ESP_ERROR_CHECK(usb_serial_jtag_driver_install(&jtag_config));
int modify_amount = 10;
char buf[4] = {0};
while (true) {
int read_count = usb_serial_jtag_read_bytes(buf, ARRAY_LEN(buf) - 1, portMAX_DELAY);
buf[read_count + 1] = '\0';
switch (buf[0]) {
case 'q':
ESP_LOGI(TAG, "Increasing frequency. New frequency: %d", modify_frequency(modify_amount));
break;
case 'a':
ESP_LOGI(TAG, "Decreasing frequency. New frequency: %d", modify_frequency(-modify_amount));
modify_frequency(-modify_amount);
break;
case '1':
reset_frequency();
break;
}
}
}

6
main/headers/arraylen.h Normal file
View File

@@ -0,0 +1,6 @@
#ifndef ARRAY_LEN_H_
#define ARRAY_LEN_H_
#define ARRAY_LEN(arr) (sizeof(arr) / sizeof(arr[0]))
#endif // ARRAY_LEN_H_

14
main/headers/buzzer.h Normal file
View File

@@ -0,0 +1,14 @@
#ifndef BUZZER_H_
#define BUZZER_H_
#include <stdint.h>
void buzzer_init(const uint32_t frequency);
uint32_t modify_frequency(int amount);
uint32_t reset_frequency();
void set_frequency(const uint32_t freq);
void buzzer_pause();
void buzzer_reset();
void buzzer_resume();
#endif // BUZZER_H_

View File

@@ -0,0 +1,6 @@
#ifndef FREQ_SLIDER_H_
#define FREQ_SLIDER_H_
void freq_slider_task(void* param);
#endif // FREQ_SLIDER_H_

23
main/headers/un.h Normal file
View File

@@ -0,0 +1,23 @@
#ifndef UN_H_
#define UN_H_
#include <stdint.h>
// https://mixbutton.com/music-tools/frequency-and-pitch/music-note-to-frequency-chart
// Octave 2
// typedef enum { P = -1, C = 65, D = 73, E = 82, F = 87, G = 98 } NoteFreq;
// Octave 4
typedef enum { P = -1, C = 262, D = 294, E = 330, F = 349, G = 392 } NoteFreq;
typedef struct {
NoteFreq note;
uint32_t length;
} Note;
const char* NoteFreqToStr(NoteFreq note);
void play_note(Note* note);
void un_task(void* param);
#endif // UN_H_

122
main/un.c Normal file
View File

@@ -0,0 +1,122 @@
#include <stdint.h>
#include "esp_log.h"
#include "driver/usb_serial_jtag.h"
#include "freertos/FreeRTOS.h" // IWYU pragma: keep
#include "freertos/task.h"
#include "un.h"
#include "buzzer.h"
#include "arraylen.h"
extern const uint32_t init_buzzer_freq;
static const char* TAG = "UN_C";
const char* NoteFreqToStr(NoteFreq note) {
switch (note) {
case C:
return "C";
case D:
return "D";
case E:
return "E";
case F:
return "F";
case G:
return "G";
case P:
return "P";
default:
return "INVALID NOTEFREQ";
}
}
void play_note(Note* note) {
ESP_LOGI(TAG, "Playing note: %s %d", NoteFreqToStr(note->note),
note->length);
if (note->note != P) {
set_frequency(note->note);
buzzer_resume();
}
vTaskDelay(pdMS_TO_TICKS(note->length));
buzzer_pause();
}
void un_task(void* param) {
usb_serial_jtag_driver_config_t jtag_config = {.rx_buffer_size = 1024,
.tx_buffer_size = 1024};
ESP_ERROR_CHECK(usb_serial_jtag_driver_install(&jtag_config));
buzzer_init(init_buzzer_freq);
const uint32_t quarter = 250;
const uint32_t half = 500;
const uint32_t whole = 1000;
// clang-format off
Note sequence[] = {
{.note = C, .length = quarter},
{.note = C, .length = quarter},
{.note = C, .length = quarter},
{.note = E, .length = quarter},
{.note = D, .length = quarter},
{.note = D, .length = quarter},
{.note = D, .length = quarter},
{.note = F, .length = quarter},
{.note = E, .length = quarter},
{.note = E, .length = quarter},
{.note = D, .length = quarter},
{.note = D, .length = quarter},
{.note = C, .length = half},
{.note = P, .length = half},
{.note = E, .length = quarter},
{.note = E, .length = quarter},
{.note = E, .length = quarter},
{.note = E, .length = quarter},
{.note = G, .length = half},
{.note = F, .length = half},
{.note = D, .length = quarter},
{.note = D, .length = quarter},
{.note = D, .length = quarter},
{.note = D, .length = quarter},
{.note = F, .length = half},
{.note = E, .length = half},
{.note = C, .length = quarter},
{.note = C, .length = quarter},
{.note = C, .length = quarter},
{.note = E, .length = quarter},
{.note = D, .length = quarter},
{.note = D, .length = quarter},
{.note = D, .length = quarter},
{.note = F, .length = quarter},
{.note = E, .length = quarter},
{.note = E, .length = quarter},
{.note = D, .length = quarter},
{.note = D, .length = quarter},
{.note = C, .length = whole},
};
// clang-format on
char* buf[4] = {0};
buzzer_pause();
while (true) {
ESP_LOGI(TAG, "Press any button to play");
usb_serial_jtag_read_bytes(buf, ARRAY_LEN(buf) - 1, portMAX_DELAY);
for (size_t i = 0; i < ARRAY_LEN(sequence); i++) {
play_note(&sequence[i]);
}
}
}

View File

@@ -501,7 +501,9 @@ CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT=y
# CONFIG_BOOTLOADER_FACTORY_RESET is not set
# CONFIG_BOOTLOADER_APP_TEST is not set
CONFIG_BOOTLOADER_REGION_PROTECTION_ENABLE=y
# CONFIG_BOOTLOADER_WDT_ENABLE is not set
CONFIG_BOOTLOADER_WDT_ENABLE=y
# CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE is not set
CONFIG_BOOTLOADER_WDT_TIME_MS=9000
# CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP is not set
# CONFIG_BOOTLOADER_SKIP_VALIDATE_ON_POWER_ON is not set
# CONFIG_BOOTLOADER_SKIP_VALIDATE_ALWAYS is not set
@@ -672,6 +674,7 @@ CONFIG_COMPILER_ORPHAN_SECTIONS_WARNING=y
#
# CONFIG_APPTRACE_DEST_JTAG is not set
CONFIG_APPTRACE_DEST_NONE=y
# CONFIG_APPTRACE_DEST_UART0 is not set
# CONFIG_APPTRACE_DEST_UART1 is not set
# CONFIG_APPTRACE_DEST_UART2 is not set
CONFIG_APPTRACE_DEST_UART_NONE=y
@@ -1278,17 +1281,14 @@ CONFIG_ESP_MAIN_TASK_AFFINITY_CPU0=y
# CONFIG_ESP_MAIN_TASK_AFFINITY_NO_AFFINITY is not set
CONFIG_ESP_MAIN_TASK_AFFINITY=0x0
CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE=2048
CONFIG_ESP_CONSOLE_UART_DEFAULT=y
# CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG is not set
# CONFIG_ESP_CONSOLE_UART_DEFAULT is not set
CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y
# CONFIG_ESP_CONSOLE_UART_CUSTOM is not set
# CONFIG_ESP_CONSOLE_NONE is not set
# CONFIG_ESP_CONSOLE_SECONDARY_NONE is not set
CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG=y
CONFIG_ESP_CONSOLE_SECONDARY_NONE=y
CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED=y
CONFIG_ESP_CONSOLE_UART=y
CONFIG_ESP_CONSOLE_UART_NUM=0
CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM=0
CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200
CONFIG_ESP_CONSOLE_UART_NUM=-1
CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM=3
CONFIG_ESP_INT_WDT=y
CONFIG_ESP_INT_WDT_TIMEOUT_MS=300
CONFIG_ESP_TASK_WDT_EN=y
@@ -2281,13 +2281,11 @@ CONFIG_ESP_SYSTEM_PM_POWER_DOWN_CPU=y
CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32
CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2304
CONFIG_MAIN_TASK_STACK_SIZE=3584
CONFIG_CONSOLE_UART_DEFAULT=y
# CONFIG_CONSOLE_UART_DEFAULT is not set
# CONFIG_CONSOLE_UART_CUSTOM is not set
# CONFIG_CONSOLE_UART_NONE is not set
# CONFIG_ESP_CONSOLE_UART_NONE is not set
CONFIG_CONSOLE_UART=y
CONFIG_CONSOLE_UART_NUM=0
CONFIG_CONSOLE_UART_BAUDRATE=115200
CONFIG_CONSOLE_UART_NUM=-1
CONFIG_INT_WDT=y
CONFIG_INT_WDT_TIMEOUT_MS=300
CONFIG_TASK_WDT=y