stm32f4xx-hal 0.14.0

Peripheral access API for STM32F4 series microcontrollers
Documentation
//! # I2S transfer example
//!
//! This application show I2s transfer usage for audio output. WARNING! This example generates very
//! loud sine tones (full scale), so turn down the volume before running this example.
//!
//! # Hardware required
//!
//! * a STM32F411 based board
//! * I2S DAC, eg PCM5102 from TI
//!
//! # Hardware Wiring
//!
//! The wiring assume using a PCM5102 module that can be found on Aliexpress, ebay, Amazon...
//!
//! ## Stm32
//!
//! | stm32 | PCM5102 |
//! |-------|---------|
//! | pa4   | LCK     |
//! | pc10  | BCK     |
//! | pc12  | DIN     |
//!
//!
//! ## PCM5102 module
//!
//! | Pin   | Connected to    |
//! |-------|-----------------|
//! | BCK   | pc10            |
//! | DIN   | pc12            |
//! | LCK   | pa4             |
//! | GND   | Gnd             |
//! | VIN   | +3V3            |
//! | FLT   | Gnd or +3V3     |
//! | DEMP  | Gnd             |
//! | XSMT  | +3V3            |
//! | A3V3  |                 |
//! | AGND  | audio out gnd   |
//! | ROUT  | audio out left  |
//! | LROUT | audio out right |
//!
//! Notes: on the module (not the chip) A3V3 is connected to VIN and AGND is connected to GND
//!
//!
//! Expected behavior: two different sine tone.

#![no_std]
#![no_main]

use cortex_m_rt::entry;

use rtt_target::{rprintln, rtt_init_print};

use stm32f4xx_hal::gpio::NoPin;
use stm32f4xx_hal::i2s::stm32_i2s_v12x::transfer::*;
use stm32f4xx_hal::i2s::I2s;
use stm32f4xx_hal::nb::block;
use stm32f4xx_hal::pac::Peripherals;
use stm32f4xx_hal::prelude::*;

const SAMPLE_RATE: u32 = 48_000;

/// A sine wave spanning 64 samples
///
/// With a sample rate of 48 kHz, this produces a 750 Hz tone.
const SINE_750: [i16; 64] = [
    0, 3211, 6392, 9511, 12539, 15446, 18204, 20787, 23169, 25329, 27244, 28897, 30272, 31356,
    32137, 32609, 32767, 32609, 32137, 31356, 30272, 28897, 27244, 25329, 23169, 20787, 18204,
    15446, 12539, 9511, 6392, 3211, 0, -3211, -6392, -9511, -12539, -15446, -18204, -20787, -23169,
    -25329, -27244, -28897, -30272, -31356, -32137, -32609, -32767, -32609, -32137, -31356, -30272,
    -28897, -27244, -25329, -23169, -20787, -18204, -15446, -12539, -9511, -6392, -3211,
];

/// A sine wave spanning 128 samples
///
/// With a sample rate of 48 kHz, this produces a 375 Hz tone.
const SINE_375: [i16; 128] = [
    0, 1607, 3211, 4807, 6392, 7961, 9511, 11038, 12539, 14009, 15446, 16845, 18204, 19519, 20787,
    22004, 23169, 24278, 25329, 26318, 27244, 28105, 28897, 29621, 30272, 30851, 31356, 31785,
    32137, 32412, 32609, 32727, 32767, 32727, 32609, 32412, 32137, 31785, 31356, 30851, 30272,
    29621, 28897, 28105, 27244, 26318, 25329, 24278, 23169, 22004, 20787, 19519, 18204, 16845,
    15446, 14009, 12539, 11038, 9511, 7961, 6392, 4807, 3211, 1607, 0, -1607, -3211, -4807, -6392,
    -7961, -9511, -11038, -12539, -14009, -15446, -16845, -18204, -19519, -20787, -22004, -23169,
    -24278, -25329, -26318, -27244, -28105, -28897, -29621, -30272, -30851, -31356, -31785, -32137,
    -32412, -32609, -32727, -32767, -32727, -32609, -32412, -32137, -31785, -31356, -30851, -30272,
    -29621, -28897, -28105, -27244, -26318, -25329, -24278, -23169, -22004, -20787, -19519, -18204,
    -16845, -15446, -14009, -12539, -11038, -9511, -7961, -6392, -4807, -3211, -1607,
];

#[entry]
fn main() -> ! {
    rtt_init_print!();
    let dp = Peripherals::take().unwrap();

    let gpioa = dp.GPIOA.split();
    let gpioc = dp.GPIOC.split();

    let rcc = dp.RCC.constrain();
    // The 61440 kHz frequency can be divided to get exactly 48 kHz sample rate even when
    // generating master clock
    let clocks = rcc
        .cfgr
        .use_hse(8u32.MHz())
        .sysclk(96.MHz())
        .i2s_clk(61440.kHz())
        .freeze();

    let i2s_pins = (gpioa.pa4, gpioc.pc10, NoPin, gpioc.pc12);
    let i2s = I2s::new(dp.SPI3, i2s_pins, &clocks);
    let i2s_config = I2sTransferConfig::new_master()
        .transmit()
        .standard(Philips)
        .data_format(Data32Channel32)
        .request_frequency(SAMPLE_RATE);
    let mut i2s_transfer = I2sTransfer::new(i2s, i2s_config);
    rprintln!("Actual sample rate is {}", i2s_transfer.sample_rate());

    let sine_375_1sec = SINE_375
        .iter()
        .map(|&x| {
            let x = (x as i32) << 16;
            (x, x)
        })
        .cycle()
        .take(SAMPLE_RATE as usize);
    let sine_750_1sec = SINE_750
        .iter()
        .map(|&x| {
            let x = (x as i32) << 16;
            (x, x)
        })
        .cycle()
        .take(SAMPLE_RATE as usize);

    loop {
        // Play 375.1 Hz using non blocking api
        for sample in sine_375_1sec.clone() {
            block!(i2s_transfer.write(sample)).ok();
        }
        // Play 750 Hz using blocking api
        i2s_transfer.write_iter(sine_750_1sec.clone());
    }
}

use core::panic::PanicInfo;
#[inline(never)]
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
    rprintln!("{}", info);
    loop {} // You might need a compiler fence in here.
}