//#define PICO #ifdef PICO #include #include #include "FreeRTOS.h" #include "task.h" #else #include #include #include #include #include #define PICO_DEFAULT_LED_PIN 0 #define GPIO_OUT 1 #define GPIO_IN 0 #endif #include #include "log.h" #include "jobs.h" #include "gpio.h" #define ALARM_BASE_FREQ 2000 // auditive frequency human range: [20; 20000] hertz #define ALARM_PERIOD_MS 500 #define PI 3.14 /** * Oscillator for passive buzzer hardware. * * It generates desired `freq_hz` for `duration_ms`. * * NOTE: `sleep_us` method does not impact FreeRTOS engine * since, the scheduler started on two cores (RP2350). The behavior may differs * on one core. Update the FreeRTOS tick freq and implement `pdUS_TO_TICKS` if needed. */ void gen_freq(gpio* g, size_t freq_hz, size_t duration_ms) { if (!freq_hz) { gpio_set_state(g, 0); return; } float period = (1.0 / freq_hz) * 1000000; // signal period in micro seconds size_t duty_period = period / 2; // working period = period / 2 size_t nb_period = duration_ms * 1000 / period; // number of period to play debug("freq_hz = (%ld), period_us = (%.2f), duty_period_us = (%ld), nb_period = (%ld)", freq_hz, period, duty_period, nb_period); for (size_t i = 0; i < nb_period; i++) { gpio_set_state(g, true); _sleep_us(duty_period); gpio_set_state(g, false); _sleep_us(duty_period); } } void run_alarm(void *const params) { for(;;) { debug("running alarm..."); float sin_val; int tone_val; const size_t duration_ms = ALARM_PERIOD_MS / 36; for (size_t i = 0; i < 360; i+=10) { sin_val = sinf(i * (PI / 180)); tone_val = ALARM_BASE_FREQ + sin_val * (ALARM_BASE_FREQ / 10); gen_freq(GPIOS[2], tone_val, duration_ms); } } } /* Initialize the main FreeRTOS task */ void init_rtos_main(TaskParam *params) { #ifdef PICO BaseType_t res = xTaskCreate(check_btn_state, "main", configMINIMAL_STACK_SIZE, (void *const)params, configMAX_PRIORITIES - 1U, NULL); if (res != pdPASS) { blink_failed(GPIOS[0]->pin, 500); } #endif } /** * A program to run alarm on button pushed. * * To activate the alarm, push the button. Same for desactivation. * The alarm is launched in a separate task and controlled by * the main task (which holds the push button logic). * * Hardware: * - 1x Passive Buzzer * - 1x Push button * - 1 NPN transistor for signal amplification * - 1x 1k ohm resistor (NPN collector) * - 2x 10k ohm resistor * * You can run the application in "DEBUG" mode using: * `make run-debug name=buzzer` * The FreeRTOS engine is replaced by threads. */ int main() { init_gpio(); AppState as; init_app_state(&as); TaskParam params = (TaskParam) { .s = &as, .f = run_alarm, }; #ifdef PICO init_rtos_main(¶ms); #else check_btn_state(¶ms); #endif #ifdef PICO vTaskStartScheduler(); #endif blink_failed(PICO_DEFAULT_LED_PIN, 200); }