#![no_main]
#![no_std]
use cortex_m_rt::entry;
use critical_section::with;
use defmt::println;
use hal::{
clocks::Clocks,
dma::{self, Dma, DmaChannel, DmaInterrupt, DmaPeriph, DmaWriteBuf},
gpio::{Pin, PinMode, Port},
i2c::{I2c, I2cConfig, I2cSpeed, NoiseFilter},
init_globals, low_power,
pac::{self, I2C1},
setup_nvic,
};
static WRITE_BUF: [u8; 2] = [0, 0];
static mut READ_BUF: [u8; 8] = [0; 8];
const ADDR: u8 = 0x48;
const DMA_PERIPH: DmaPeriph = DmaPeriph::Dma1;
const TX_CH: DmaChannel = DmaChannel::C6;
const RX_CH: DmaChannel = DmaChannel::C7;
make_globals!((I2C, I2c<I2C1>),);
#[entry]
fn main() -> ! {
let mut cp = cortex_m::Peripherals::take().unwrap();
let mut dp = pac::Peripherals::take().unwrap();
let clock_cfg = Clocks::default();
clock_cfg.setup().unwrap();
let mut scl = Pin::new(Port::B, 6, PinMode::Alt(4));
scl.output_type(OutputType::OpenDrain);
let mut sda = Pin::new(Port::B, 7, PinMode::Alt(4));
sda.output_type(OutputType::OpenDrain);
let i2c = I2c::new(dp.I2C1, Default::default(), &clock_cfg);
let i2c_cfg = I2cConfig {
speed: I2cSpeed::Fast400K, noise_filter: NoiseFilter::Digitial(5),
..Default::default()
};
let i2c = I2c::new(dp.I2C1, i2c_cfg, &clock_cfg);
let cfg = [0b1000_0101, 0b1000_0000];
let cfg_reg = 0x1;
let conversion_reg = 0x0;
let mut dma = Dma::new(&mut dp.DMA1);
dma::mux(DMA_PERIPH, TX_CH, DmaInput::I2c1Tx);
dma::mux(DMA_PERIPH, RX_CH, DmaInput::I2c1Rx);
unsafe {
i2c.write_dma(
ADDR,
&WRITE_BUF,
false,
TX_CH,
Default::default(),
DMA_PERIPH,
);
}
let mut read_buf = [0, 0];
i2c.write(ADDR, &[cfg_reg, cfg[0], cfg[1]]).ok();
i2c.write_read(ADDR, &[conversion_reg], &mut read_buf).ok();
let reading = i16::from_be_bytes([read_buf[0], read_buf[1]]);
init_globals!((I2C, i2c),);
setup_nvic!([(DMA1_CH6, 3), (DMA2_CH7, 3),], cp);
loop {
low_power::sleep_now();
}
}
#[interrupt]
fn DMA1_CH6() {
dma::clear_interrupt(DMA_PERIPH, TX_CH, DmaInterrupt::TransferComplete);
dma::stop(DMA_PERIPH, TX_CH);
with(|cs| {
access_global!(I2C, i2c, cs);
unsafe {
i2c.read_dma(ADDR, &mut READ_BUF, RX_CH, Default::default(), DMA_PERIPH);
}
});
println!("I2C write complete; reading.");
}
#[interrupt]
fn DMA1_CH7() {
dma::clear_interrupt(DMA_PERIPH, RX_CH, DmaInterrupt::TransferComplete);
dma::stop(DMA_PERIPH, RX_CH);
let buf = unsafe { &READ_BUF };
println!("I2C data is available: {:?}", buf);
}
#[defmt::panic_handler]
fn panic() -> ! {
cortex_m::asm::udf()
}