#include #include "pico/stdlib.h" #include "hardware/dma.h" #include "hardware/adc.h" #include "hardware/clocks.h" #include "hardware/pwm.h" #define LED_PIN PICO_DEFAULT_LED_PIN // LED uint slice_num; #define ADC0_PIN ADC_BASE_PIN #define ADC1_PIN (ADC_BASE_PIN+1) #define ADC2_PIN (ADC_BASE_PIN+2) #define ADC_VREF 3.3f #define ADC_SAMPLE_CLKS 96 #define SAMPLE_RATE 1000 typedef enum { adc_input0, adc_input1, adc_input2, adc_input3, adc_input4, } _adc_input_t; #define RW_BUFFER_SIZE 256 int adc_dma_ch; volatile static uint8_t rw_buffer[2][RW_BUFFER_SIZE]; volatile static int write_buf_selector = 0; void adc_dma_irq_handler(void) { // 割り込みフラグクリア dma_channel_acknowledge_irq0(adc_dma_ch); write_buf_selector ^= 1; // DMA転送を再トリガー dma_channel_set_write_addr(adc_dma_ch, rw_buffer[write_buf_selector], false); dma_channel_set_trans_count(adc_dma_ch, RW_BUFFER_SIZE, true); } void pwm_irq_handler(void) { static int counter = 0; static int read_buf_selector = 1; pwm_clear_irq(slice_num); pwm_set_gpio_level(LED_PIN, (uint16_t)rw_buffer[read_buf_selector][counter++]); if(counter > RW_BUFFER_SIZE) { read_buf_selector = write_buf_selector ^ 1; counter = 0; } } int main() { stdio_init_all(); float adc_div, pwm_div; gpio_set_function(LED_PIN, GPIO_FUNC_PWM); pwm_config c = pwm_get_default_config(); pwm_div = clock_get_hz(clk_sys) / SAMPLE_RATE / RW_BUFFER_SIZE; pwm_config_set_clkdiv(&c, pwm_div); pwm_config_set_wrap(&c, RW_BUFFER_SIZE); slice_num = pwm_gpio_to_slice_num(LED_PIN); pwm_init(slice_num, &c, false); pwm_set_gpio_level(LED_PIN, 0xFF ); // PWM IRQ pwm_clear_irq(slice_num); pwm_set_irq_enabled(slice_num, true); irq_set_exclusive_handler(PWM_DEFAULT_IRQ_NUM(), pwm_irq_handler); irq_set_enabled(PWM_DEFAULT_IRQ_NUM(), true); // ADCの設定 adc_init(); adc_gpio_init(ADC0_PIN); // ADC FIFOの設定 adc_fifo_setup( true, // FIFOを有効化するならtrue true, // DREQを有効化するならtrue 1, // DREQ、IRQを発生させるFIFOエントリ数 false, // 最上位ビットをエラーフラグにするならtrue true // バイトシフトするならtrue ); // ADCクロック分周比 adc_div = (float)clock_get_hz(clk_adc) / (float)ADC_SAMPLE_CLKS / SAMPLE_RATE; adc_set_clkdiv(adc_div); printf("adc_div = %f\n", adc_div); adc_dma_ch = dma_claim_unused_channel(true); dma_channel_config dma_conf = dma_channel_get_default_config(adc_dma_ch); channel_config_set_transfer_data_size(&dma_conf, DMA_SIZE_8); channel_config_set_read_increment(&dma_conf, false); channel_config_set_write_increment(&dma_conf, true); channel_config_set_dreq(&dma_conf, DREQ_ADC); // DMAチャネル設定 dma_channel_configure( adc_dma_ch, &dma_conf, (rw_buffer[0]), // 書き込み先はRW_BUFFER &adc_hw->fifo, // 読み出し元はRW_BUFFER RW_BUFFER_SIZE, // 転送回数 false // 開始しない ); dma_channel_set_irq0_enabled(adc_dma_ch, true); irq_set_exclusive_handler(DMA_IRQ_0, adc_dma_irq_handler); irq_set_enabled(DMA_IRQ_0, true); dma_channel_start(adc_dma_ch); adc_run(true); pwm_set_enabled(slice_num, true); while (true) { tight_loop_contents(); } }