본문 바로가기

RaspberryPi/W55RP20

[W55RP20-4032] I2S MEMS MIC(ICS-43434) 테스트

 

네트웍크 스피커에 연결 될수 있는 네트웍 마이크를 제작 하기 위해 MEMS MIC(ICS-43434) 를 테스트 해보자.

마이크는 기존에 제작 해 두었던 ICS-43434 모듈을  이용하였다.

 

 

MIC신호는 I2S로 입력 받고 스피커로 출력 할 수 있다.

스위치1 을 누르는 동안 마이크 신호를 스피커로 출력하고, 스위치 2를 누르면 볼륨 조절 하는 아주 간단한 예제를 테스트 해보자.

#include <stdio.h>
#include <math.h>
#include "pico/stdlib.h"
#include "pico/audio_i2s.h"
#include "hardware/pio.h"        
#include "audio_mic_rx.pio.h" 

#define BUTTON_PIN        2
#define BUTTON_PIN2       28
#define AMP_I2S_DATA_PIN  10
#define AMP_I2S_CK_PIN    11 
#define AMP_I2S_WS_PIN    12 

#define I2S_DATA_PIN      16
#define I2S_CK_PIN        18 
#define I2S_WS_PIN        19 

#define SAMPLE_RATE 480000

int main() {
    stdio_init_all();
    
    gpio_init(BUTTON_PIN);
    gpio_set_dir(BUTTON_PIN, GPIO_IN);
    gpio_pull_up(BUTTON_PIN);

    gpio_init(BUTTON_PIN2);
    gpio_set_dir(BUTTON_PIN2, GPIO_IN);
    gpio_pull_up(BUTTON_PIN2);

    printf("Starting Fixed I2S Mic to Amp Passthrough...\n");

    PIO pio_rx = pio1;
    uint sm_rx = pio_claim_unused_sm(pio_rx, true);
    uint offset_rx = pio_add_program(pio_rx, &i2s_rx_program);
    i2s_rx_program_init(pio_rx, sm_rx, offset_rx, MIC_I2S_DATA_PIN, MIC_I2S_CLOCK_BASE, SAMPLE_RATE);

    audio_format_t audio_format = {
        .sample_freq = SAMPLE_RATE,
        .format = AUDIO_BUFFER_FORMAT_PCM_S16,
        .channel_count = 2,
    };

    struct audio_buffer_format producer_format = {
        .format = &audio_format,
        .sample_stride = 4 
    };

    struct audio_i2s_config config = {
        .data_pin = I2S_DATA_PIN,
        .clock_pin_base = I2S_CLOCK_PIN_BASE,
        .dma_channel = 0,
        .pio_sm = 0,
    };


    const audio_format_t *output_format = audio_i2s_setup(&audio_format, &config);
    if (!output_format) {
        panic("PicoAudio: Unable to open I2S audio device.\n");
    }


    audio_buffer_pool_t *producer_pool = audio_new_producer_pool(&producer_format, 3, 256);
    if (!producer_pool) {
        panic("PicoAudio: Failed to create buffer pool.\n");
    }

    bool connection_ok = audio_i2s_connect(producer_pool);
    if (!connection_ok) {
        panic("PicoAudio: Unable to connect to I2S device.\n");
    }
    audio_i2s_set_enabled(true);

    float volume = 0.5f; 
    bool btn2_last_state = true;

    while (true) {
        struct audio_buffer *buffer = take_audio_buffer(producer_pool, true);
        int16_t *samples = (int16_t *)buffer->buffer->bytes;
        
        for (uint i = 0; i < buffer->max_sample_count; i++) {
            uint32_t packet = pio_sm_get_blocking(pio_rx, sm_rx);
            
            int16_t left = (int16_t)(packet >> 16);
            int16_t right = (int16_t)(packet & 0xFFFF);

            if (gpio_get(BUTTON_PIN) == 0) {
                samples[i * 2 + 0] = (int16_t)(left * volume);  
                samples[i * 2 + 1] = (int16_t)(right * volume); 
            } else {
                samples[i * 2 + 0] = 0;
                samples[i * 2 + 1] = 0;
            }
        }
        
        buffer->sample_count = buffer->max_sample_count;
        give_audio_buffer(producer_pool, buffer);

        bool btn2_state = gpio_get(BUTTON_PIN2);
        if (btn2_state == 0 && btn2_last_state == true) {
            volume += 0.2f;
            if (volume > 1.0f) {
                volume = 0.0f;
            }
        }
        btn2_last_state = btn2_state;
    }

    return 0;
}