Code: Select all
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/adc.h"
#include "hardware/gpio.h"
#include "hardware/i2c.h"
#include "ssd1306.h"
#define ENCODER_PIN1 16
#define ENCODER_PIN2 17
#define ENCODER_BUTTON 18
#define POTENTIOMETER_PIN 26
#define SPEAKER_PIN 2
#define I2C_PORT i2c_default
#define OLED_ADDR 0x3C
#define OLED_WIDTH 128
#define OLED_HEIGHT 64
#define NUM_WAVETABLES 256
// Описание wav файлов, хранящих таблицы волны
const char* wav_files[NUM_WAVETABLES] =
{
// ... описание путей к файлам
};
// Индекс выбранной таблицы волнового синтеза
uint8_t wave_table_index = 0;
// Функция выбора волновой таблицы
void select_wave_table()
{
ssd1306_clear_display();
ssd1306_draw_string(OLED_WIDTH/2 - 30, OLED_HEIGHT/2 - 10, "Select Table:");
ssd1306_update_display();
uint8_t selected_table = wave_table_index;
while (1)
{
// Отрисовка списка таблиц
ssd1306_clear_display();
for (uint8_t i = 0; i < NUM_WAVETABLES; i++)
{
char str[5];
snprintf(str, sizeof(str), "%d", i+1);
ssd1306_draw_string(0, i*10, str);
if (i == selected_table)
{
ssd1306_draw_string(10, i*10, wav_files[i]);
} else
{
ssd1306_draw_string(10, i*10, wav_files[i]);
}
}
ssd1306_update_display();
// Обработка вращения энкодера и нажатия на кнопку
int8_t enc0 = gpio_get(ENCODER_PIN1);
int8_t enc1 = gpio_get(ENCODER_PIN2);
if ((enc0 == 0) && (enc1 == 1))
{
selected_table = (selected_table + 1) % NUM_WAVETABLES;
while (gpio_get(ENCODER_PIN2) != 0) {sleep_us(100);} // ожидание отжатия кнопки
}
if ((enc0 == 1) && (enc1 == 0)) {
selected_table = (selected_table + NUM_WAVETABLES - 1) % NUM_WAVETABLES;
while (gpio_get(ENCODER_PIN1) != 0) {sleep_us(100);} // ожидание отжатия кнопки
}
if (gpio_get(ENCODER_BUTTON) == 0)
{
wave_table_index = selected_table;
return;
}
}
}
int main()
{
stdio_init_all();
// Инициализация GPIO
gpio_init(ENCODER_PIN1);
gpio_init(ENCODER_PIN2);
gpio_init(ENCODER_BUTTON);
gpio_pull_up(ENCODER_BUTTON);
gpio_set_dir(SPEAKER_PIN, GPIO_OUT);
// Инициализация ADC
adc_init();
adc_gpio_init(POTENTIOMETER_PIN);
adc_select_input(0);
// Инициализация I2C и OLED
i2c_init(I2C_PORT, 1000000);
gpio_set_function(8, GPIO_FUNC_I2C);
gpio_set_function(9, GPIO_FUNC_I2C);
gpio_pull_up(8);
gpio_pull_up(9);
ssd1306_init(I2C_PORT, OLED_ADDR, OLED_WIDTH, OLED_HEIGHT);
while(1)
{
// Чтение показаний с потенциометра
uint16_t pot_value = adc_read();
// Масштабирование показаний в диапазон [0, NUM_WAVETABLES-1]
uint8_t selected_wavetable = (pot_value * NUM_WAVETABLES) / 65536;
// Переключение между выводом осциллограммы и выбором таблицы волны
int8_t enc0 = gpio_get(ENCODER_PIN1);
int8_t enc1 = gpio_get(ENCODER_PIN2);
if ((enc0 == 0) && (enc1 == 1))
{
ssd1306_clear_display(); //'ssd1306_clear_display' was not declared in this scope ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
ssd1306_draw_string(OLED_WIDTH/2 - 25, OLED_HEIGHT/2 - 10, "Waveform:");
ssd1306_update_display();
while ((gpio_get(ENCODER_PIN2) != 0) && (gpio_get(ENCODER_BUTTON) != 0))
{
// Отрисовка осциллограммы выбранной таблицы волны
float* waveform = read_wavetable(wav_files[wave_table_index]);
for (int i = 0; i < OLED_WIDTH; i++)
{
uint8_t sample = (uint8_t)(map(waveform[(i * 512) / OLED_WIDTH], -1.0f, 1.0f, 0, OLED_HEIGHT-1));
ssd1306_draw_pixel(i, sample);
}
ssd1306_update_display();
}
} else if ((enc0 == 1) && (enc1 == 0))
{
select_wave_table();
}
// Воспроизведение выбранной таблицы волны на динамике
float* wavetable = read_wavetable(wav_files[selected_wavetable]);
for (int i = 0; i < 512; i++)
{
float sample = wavetable[i];
uint8_t output_sample = (uint8_t)(map(sample, -1.0f, 1.0f, 0, 255));
gpio_put(SPEAKER_PIN, output_sample);
sleep_us(1000);
}
}
}