Select Git revision
solution.c 2.63 KiB
#include "pico/stdlib.h"
#include "hardware/pwm.h"
#include "hardware/clocks.h"
#define BUZZER_PIN 18 // This is both the buzzer and audio jack (just in case you have anything to plug into it)
#define BUTTON_1_PIN 20
#define BUTTON_2_PIN 21
#define BUTTON_3_PIN 22
#define FREQ_1 261.6256f
#define FREQ_2 293.6648f
#define FREQ_3 329.6276f
/**
* A method for playing a note on the speaker.
* @param frequency Frequency of the note in Hz.
*/
void playNote(float frequency) {
uint pwmSlice = pwm_gpio_to_slice_num(BUZZER_PIN);
uint32_t wrap = clock_get_hz(clk_sys) / frequency;
float clkdiv = 1.0f;
while (wrap > 65535) {
wrap = wrap / 2;
clkdiv = clkdiv * 2;
}
// Setting the clkdiv and wrap
pwm_set_clkdiv(pwmSlice, clkdiv);
pwm_set_wrap(pwmSlice, wrap);
// Setting the volume to maximum (having maximum oscillation)
uint32_t dutyCycle = wrap / 2;
pwm_set_chan_level(pwmSlice, PWM_CHAN_A, dutyCycle);
pwm_set_enabled(pwmSlice, true);
}
/**
* A method for silencing the speaker.
*/
void playNothing() {
uint pwmSlice = pwm_gpio_to_slice_num(BUZZER_PIN);
pwm_set_enabled(pwmSlice, false);
}
/**
* A method for handling GPIO events.
* @param gpio GPIO Number.
* @param event_mask Which events will cause an interrupt. See gpio_irq_level for details.
*/
void handleEvent(uint gpio, uint32_t event_mask) {
// Making keys play frequencies
if (event_mask == GPIO_IRQ_EDGE_FALL) {
if (gpio == BUTTON_1_PIN) {
playNote(FREQ_1);
}
if (gpio == BUTTON_2_PIN) {
playNote(FREQ_2);
}
if (gpio == BUTTON_3_PIN) {
playNote(FREQ_3);
}
}
// Making releasing a button make it silent
if (event_mask == GPIO_IRQ_EDGE_RISE) {
playNothing();
}
}
int main() {
stdio_init_all();
// Setting up the buzzer
gpio_set_function(BUZZER_PIN, GPIO_FUNC_PWM);
// Linking the buttons to the event handler
gpio_set_irq_enabled_with_callback(BUTTON_1_PIN, GPIO_IRQ_EDGE_FALL, true, &handleEvent);
gpio_set_irq_enabled_with_callback(BUTTON_2_PIN, GPIO_IRQ_EDGE_FALL, true, &handleEvent);
gpio_set_irq_enabled_with_callback(BUTTON_3_PIN, GPIO_IRQ_EDGE_FALL, true, &handleEvent);
gpio_set_irq_enabled_with_callback(BUTTON_1_PIN, GPIO_IRQ_EDGE_RISE, true, &handleEvent);
gpio_set_irq_enabled_with_callback(BUTTON_2_PIN, GPIO_IRQ_EDGE_RISE, true, &handleEvent);
gpio_set_irq_enabled_with_callback(BUTTON_3_PIN, GPIO_IRQ_EDGE_RISE, true, &handleEvent);
// Main Program Loop
while (true) {
tight_loop_contents();
}
return 0; // This will never be reached
}