Skip to content

Instantly share code, notes, and snippets.

@awonak
Last active August 21, 2022 18:15
Show Gist options
  • Save awonak/eb5192b3c8775fc4f3bd227b7bd9f48d to your computer and use it in GitHub Desktop.
Save awonak/eb5192b3c8775fc4f3bd227b7bd9f48d to your computer and use it in GitHub Desktop.
Experiment in building a EuroPi script using the Pico C/C++ SDK (https://imgur.com/a/jjSMy6P)
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "pico/stdlib.h"
#include "pico/time.h"
#include "hardware/adc.h"
#include "hardware/gpio.h"
#include "hardware/i2c.h"
#include "hardware/pwm.h"
#include "ssd1306.h"
// App constants
#define N_SAMPLES 1000
uint16_t sample_buf[N_SAMPLES];
#define K1_GPIO 27
#define K2_GPIO 28
#define CV1_GPIO 21
#define MIN_BPM 20
#define MAX_BPM 240
#define TRIGGER_DURATION 15
#define CORRECTION_OFFSET 2
#define PPQN 4
#define MINUTE 60000 // in milliseconds
// Helpers
float toFloat(uint16_t val)
{
return val;
}
// Init funcs
void setup_pwm(uint gpio)
{
gpio_set_function(gpio, GPIO_FUNC_PWM);
uint slice_num = pwm_gpio_to_slice_num(gpio);
pwm_config config = pwm_get_default_config();
pwm_init(slice_num, &config, true);
}
void setup_gpios(void)
{
// OLED Display
i2c_init(i2c0, 400000);
gpio_set_function(0, GPIO_FUNC_I2C);
gpio_set_function(1, GPIO_FUNC_I2C);
gpio_pull_up(0);
gpio_pull_up(1);
// CV Outputs
setup_pwm(CV1_GPIO);
}
void __not_in_flash_func(adc_capture)(uint16_t *buf, size_t count)
{
adc_fifo_setup(true, false, 0, false, false);
adc_run(true);
for (int i = 0; i < count; i = i + 1)
buf[i] = adc_fifo_get_blocking();
adc_run(false);
adc_fifo_drain();
}
uint16_t read_k(uint n)
{
adc_select_input(n);
adc_capture(sample_buf, N_SAMPLES);
uint64_t sum = 0;
for (int i = 0; i < N_SAMPLES; i++)
{
sum += sample_buf[i];
}
float avg = (float)sum / N_SAMPLES;
return (1 << 12) - avg; // cast back to uin16
}
uint16_t read_bpm()
{
float k1 = read_k(1) / toFloat(1 << 12);
return ((MAX_BPM - MIN_BPM) * k1) + MIN_BPM;
}
uint16_t sleep_period(uint16_t bpm)
{
return MINUTE / bpm / PPQN;
}
int main()
{
// Init device
stdio_init_all();
setup_gpios();
// Set up display
ssd1306_t disp;
disp.external_vcc = false;
ssd1306_init(&disp, 128, 32, 0x3C, i2c0);
ssd1306_clear(&disp);
// Set up ADC
adc_init();
adc_gpio_init(K1_GPIO);
adc_gpio_init(K2_GPIO);
// Main app loop
uint16_t bpm = 0;
while (1)
{
uint16_t _bpm = read_bpm();
if (_bpm != bpm)
{
bpm = _bpm;
ssd1306_clear(&disp);
char text[7];
sprintf(text, "%d BPM", bpm);
ssd1306_draw_string(&disp, 42, 8, 1, text);
sprintf(text, "%d MS", sleep_period(bpm) * 4);
ssd1306_draw_string(&disp, 42, 18, 1, text);
ssd1306_show(&disp);
}
sleep_ms(sleep_period(bpm) - (TRIGGER_DURATION + CORRECTION_OFFSET));
pwm_set_gpio_level(CV1_GPIO, (1 << 16) - 1);
sleep_ms(TRIGGER_DURATION);
pwm_set_gpio_level(CV1_GPIO, 0);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment