Exemple #1
0
extern void init_i2s(const i2s_config *cfg, const i2s_instance *inst,
                     i2s_sample_callback *callback)
{
    uint32_t base = inst->i2si_base_address;

    // Just handle one case for now.
    assert(cfg->i2sc_sample_frequency == 44100);
    assert(cfg->i2sc_mode             == I2SM_MASTER_TX);
    assert(cfg->i2sc_standard         == I2SS_LSB);
    assert(cfg->i2sc_data_format      == I2SF_16);
    assert(cfg->i2sc_mclk_output      == I2SM_ENABLED);
    assert(cfg->i2sc_cpol             == I2SC_CPOL_HIGH);
    assert(cfg->i2sc_clock_source     == I2SC_PLL);
    assert(cfg->i2sc_full_duplex      == false);
    
    switch (base) {

    case SPI2_BASE:
        spi2_callback = callback;
        spi2_left_right = I2SC_LEFT;
        break;

    case SPI3_BASE:
        spi3_callback = callback;
        spi3_left_right = I2SC_LEFT;
        break;

    default:
        assert(false && "i2s: unknown bad address");
    }

    // Enable clock.
    rcc_periph_clock_enable(RCC_SPI2);

    // Enable GPIO pins.
    size_t pin_count = 3 + !!cfg->i2sc_mclk_output + !!cfg->i2sc_full_duplex;
    gpio_init_pins(cfg->i2sc_gpio_pins, pin_count);

    // Enable interrupt.
    nvic_enable_irq(NVIC_SPI2_IRQ);

    SPI_I2SCFGR(base)  = 0;

    RCC_PLLI2SCFGR     = PLLI2S_N_VALUE << RCC_PLLI2SCFGR_PLLI2SN_SHIFT
                       | PLLI2S_R_VALUE << RCC_PLLI2SCFGR_PLLI2SR_SHIFT;

    SPI_I2SPR(base)    = SPI_I2SPR_MCKOE
                       | I2SPR_ODD_VALUE
                       | I2SPR_I2SDIV_VALUE;
    
    SPI_I2SCFGR(base)  = SPI_I2SCFGR_I2SMOD
                       | SPI_I2SCFGR_I2SCFG_MASTER_TRANSMIT
                         << SPI_I2SCFGR_I2SCFG_LSB
                       | SPI_I2SCFGR_I2SSTD_I2S_PHILIPS
                         << SPI_I2SCFGR_I2SSTD_LSB
                       | SPI_I2SCFGR_CKPOL
                       | SPI_I2SCFGR_DATLEN_16BIT
                         << SPI_I2SCFGR_DATLEN_LSB;

    SPI_CR2(base)     |= SPI_CR2_TXEIE;

    // Start the I2S PLL.
    RCC_CR |= RCC_CR_PLLI2SON;

    // Enable I2S.
    SPI_I2SCFGR(base) |= SPI_I2SCFGR_I2SE;
}
Exemple #2
0
void codecInit(void)
{
    memset(adcBuffer, 0xaa, sizeof(adcBuffer));

    // I2S2 alternate function mapping
    gpio_mode_setup(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO12 | GPIO13 | GPIO14 | GPIO15);
    gpio_set_af(GPIOB, GPIO_AF5, GPIO12 | GPIO13 | GPIO15);
    gpio_set_af(GPIOB, GPIO_AF6, GPIO14); // I2S2ext_SD (I2S receive)
    gpio_mode_setup(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO6);
    gpio_set_af(GPIOC, GPIO_AF5, GPIO6); // MCLK
    gpio_set_output_options(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_25MHZ, GPIO12 | GPIO13 | GPIO15);
    gpio_set_output_options(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_100MHZ, GPIO6);

    // Set up SPI1
    spi_reset(SPI1);

    spi_init_master(SPI1, SPI_CR1_BAUDRATE_FPCLK_DIV_256, SPI_CR1_CPOL_CLK_TO_1_WHEN_IDLE,
            SPI_CR1_CPHA_CLK_TRANSITION_2, SPI_CR1_DFF_16BIT, SPI_CR1_MSBFIRST);
    spi_set_nss_high(SPI1);
    spi_enable_software_slave_management(SPI1);
    spi_enable(SPI1);

    // SPI1 alternate function mapping, set CSB signal high output
    gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO5 | GPIO7);
    gpio_set_af(GPIOA, GPIO_AF5, GPIO5 | GPIO7);
    gpio_set(GPIOA, GPIO4);
    gpio_mode_setup(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO4);

    codecConfig();

    // Set up I2S for 48kHz 16-bit stereo.
    // The input to the PLLI2S is 1MHz. Division factors are from
    // table 126 in the data sheet.
    //
    // This gives us 1.536MHz SCLK = 16 bits * 2 channels * 48000 Hz
    // and 12.288 MHz MCLK = 256 * 48000 Hz.
    // With this PLL configuration the actual sampling frequency
    // is nominally 47991 Hz.

    spi_reset(SPI2);

    RCC_PLLI2SCFGR = (3 << 28) | (258 << 6);
    RCC_CR |= RCC_CR_PLLI2SON;
    while (!(RCC_CR & RCC_CR_PLLI2SRDY));

    const unsigned i2sdiv = 3;
    SPI_I2SPR(SPI2) = SPI_I2SPR_MCKOE | SPI_I2SPR_ODD | i2sdiv;
    SPI_I2SCFGR(SPI2) |= SPI_I2SCFGR_I2SMOD | SPI_I2SCFGR_I2SE |
            (SPI_I2SCFGR_I2SCFG_MASTER_TRANSMIT << SPI_I2SCFGR_I2SCFG_LSB);
    SPI_I2SCFGR(I2S2_EXT_BASE) = SPI_I2SCFGR_I2SMOD | SPI_I2SCFGR_I2SE |
            (SPI_I2SCFGR_I2SCFG_SLAVE_RECEIVE << SPI_I2SCFGR_I2SCFG_LSB);

    // Configure the DMA engine to stream data to the DAC.
    dma_stream_reset(DMA1, DAC_DMA_STREAM);
    dma_set_peripheral_address(DMA1, DAC_DMA_STREAM, (intptr_t)&SPI_DR(SPI2));
    dma_set_memory_address(DMA1, DAC_DMA_STREAM, (intptr_t)dacBuffer[0]);
    dma_set_memory_address_1(DMA1, DAC_DMA_STREAM, (intptr_t)dacBuffer[1]);
    dma_set_number_of_data(DMA1, DAC_DMA_STREAM, BUFFER_SAMPLES);
    dma_channel_select(DMA1, DAC_DMA_STREAM, DAC_DMA_CHANNEL);
    dma_set_transfer_mode(DMA1, DAC_DMA_STREAM, DMA_SxCR_DIR_MEM_TO_PERIPHERAL);
    dma_set_memory_size(DMA1, DAC_DMA_STREAM, DMA_SxCR_MSIZE_16BIT);
    dma_set_peripheral_size(DMA1, DAC_DMA_STREAM, DMA_SxCR_PSIZE_16BIT);
    dma_enable_memory_increment_mode(DMA1, DAC_DMA_STREAM);
    dma_enable_double_buffer_mode(DMA1, DAC_DMA_STREAM);
    dma_enable_stream(DMA1, DAC_DMA_STREAM);

    // Configure the DMA engine to stream data from the ADC.
    dma_stream_reset(DMA1, ADC_DMA_STREAM);
    dma_set_peripheral_address(DMA1, ADC_DMA_STREAM, (intptr_t)&SPI_DR(I2S2_EXT_BASE));
    dma_set_memory_address(DMA1, ADC_DMA_STREAM, (intptr_t)adcBuffer[0]);
    dma_set_memory_address_1(DMA1, ADC_DMA_STREAM, (intptr_t)adcBuffer[1]);
    dma_set_number_of_data(DMA1, ADC_DMA_STREAM, BUFFER_SAMPLES);
    dma_channel_select(DMA1, ADC_DMA_STREAM, ADC_DMA_CHANNEL);
    dma_set_transfer_mode(DMA1, ADC_DMA_STREAM, DMA_SxCR_DIR_PERIPHERAL_TO_MEM);
    dma_set_memory_size(DMA1, ADC_DMA_STREAM, DMA_SxCR_MSIZE_16BIT);
    dma_set_peripheral_size(DMA1, ADC_DMA_STREAM, DMA_SxCR_PSIZE_16BIT);
    dma_enable_memory_increment_mode(DMA1, ADC_DMA_STREAM);
    dma_enable_double_buffer_mode(DMA1, ADC_DMA_STREAM);
    dma_enable_stream(DMA1, ADC_DMA_STREAM);

    dma_enable_transfer_complete_interrupt(DMA1, ADC_DMA_STREAM);
    nvic_enable_irq(NVIC_DMA1_STREAM3_IRQ);
    nvic_set_priority(NVIC_DMA1_STREAM3_IRQ, 0x80); // 0 is most urgent

    // Start transmitting data
    spi_enable_rx_dma(I2S2_EXT_BASE);
    spi_enable_tx_dma(SPI2);
}