summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy@goop.org>2022-09-28 09:35:19 -0700
committerJeremy Fitzhardinge <jeremy@goop.org>2022-10-01 13:43:37 -0700
commit1ee4bb22deb19e93a7c68e04875889e3e4e31c29 (patch)
tree9ad2db208382396a964e6de0b6afa273b0424f5e
parent5e2c52ee5b6fcc5b50589fd2590657e3f1083bff (diff)
downloadembassy-1ee4bb22deb19e93a7c68e04875889e3e4e31c29.zip
embassy-rp i2c: async (non-blocking) example
Simple example exercising an mcp23017 GPIO expander, configured on RP2040 GPIOs 14+15 (i2c1) with 8 inputs and 8 outputs. Input bit 0 controls whether to display a mcp23017 register dump.
-rw-r--r--examples/rp/src/bin/i2c_async.rs102
1 files changed, 102 insertions, 0 deletions
diff --git a/examples/rp/src/bin/i2c_async.rs b/examples/rp/src/bin/i2c_async.rs
new file mode 100644
index 00000000..d1a2e3cd
--- /dev/null
+++ b/examples/rp/src/bin/i2c_async.rs
@@ -0,0 +1,102 @@
+#![no_std]
+#![no_main]
+#![feature(type_alias_impl_trait)]
+
+use defmt::*;
+use embassy_executor::Spawner;
+use embassy_rp::i2c::{self, Config};
+use embassy_rp::interrupt;
+use embassy_time::{Duration, Timer};
+use embedded_hal_async::i2c::I2c;
+use {defmt_rtt as _, panic_probe as _};
+
+#[allow(dead_code)]
+mod mcp23017 {
+ pub const ADDR: u8 = 0x20; // default addr
+
+ macro_rules! mcpregs {
+ ($($name:ident : $val:expr),* $(,)?) => {
+ $(
+ pub const $name: u8 = $val;
+ )*
+
+ pub fn regname(reg: u8) -> &'static str {
+ match reg {
+ $(
+ $val => stringify!($name),
+ )*
+ _ => panic!("bad reg"),
+ }
+ }
+ }
+ }
+
+ // These are correct for IOCON.BANK=0
+ mcpregs! {
+ IODIRA: 0x00,
+ IPOLA: 0x02,
+ GPINTENA: 0x04,
+ DEFVALA: 0x06,
+ INTCONA: 0x08,
+ IOCONA: 0x0A,
+ GPPUA: 0x0C,
+ INTFA: 0x0E,
+ INTCAPA: 0x10,
+ GPIOA: 0x12,
+ OLATA: 0x14,
+ IODIRB: 0x01,
+ IPOLB: 0x03,
+ GPINTENB: 0x05,
+ DEFVALB: 0x07,
+ INTCONB: 0x09,
+ IOCONB: 0x0B,
+ GPPUB: 0x0D,
+ INTFB: 0x0F,
+ INTCAPB: 0x11,
+ GPIOB: 0x13,
+ OLATB: 0x15,
+ }
+}
+
+#[embassy_executor::main]
+async fn main(_spawner: Spawner) {
+ let p = embassy_rp::init(Default::default());
+
+ let sda = p.PIN_14;
+ let scl = p.PIN_15;
+ let irq = interrupt::take!(I2C1_IRQ);
+
+ info!("set up i2c ");
+ let mut i2c = i2c::I2c::new_async(p.I2C1, scl, sda, irq, Config::default());
+
+ use mcp23017::*;
+
+ info!("init mcp23017 config for IxpandO");
+ // init - a outputs, b inputs
+ i2c.write(ADDR, &[IODIRA, 0x00]).await.unwrap();
+ i2c.write(ADDR, &[IODIRB, 0xff]).await.unwrap();
+ i2c.write(ADDR, &[GPPUB, 0xff]).await.unwrap(); // pullups
+
+ let mut val = 1;
+ loop {
+ let mut portb = [0];
+
+ i2c.write_read(mcp23017::ADDR, &[GPIOB], &mut portb).await.unwrap();
+ info!("portb = {:02x}", portb[0]);
+ i2c.write(mcp23017::ADDR, &[GPIOA, val | portb[0]]).await.unwrap();
+ val = val.rotate_left(1);
+
+ // get a register dump
+ info!("getting register dump");
+ let mut regs = [0; 22];
+ i2c.write_read(ADDR, &[0], &mut regs).await.unwrap();
+ // always get the regdump but only display it if portb'0 is set
+ if portb[0] & 1 != 0 {
+ for (idx, reg) in regs.into_iter().enumerate() {
+ info!("{} => {:02x}", regname(idx as u8), reg);
+ }
+ }
+
+ Timer::after(Duration::from_millis(100)).await;
+ }
+}