aboutsummaryrefslogtreecommitdiff
path: root/examples/rp235x/src/bin/i2c_async.rs
diff options
context:
space:
mode:
Diffstat (limited to 'examples/rp235x/src/bin/i2c_async.rs')
-rw-r--r--examples/rp235x/src/bin/i2c_async.rs110
1 files changed, 110 insertions, 0 deletions
diff --git a/examples/rp235x/src/bin/i2c_async.rs b/examples/rp235x/src/bin/i2c_async.rs
new file mode 100644
index 000000000..e31cc894c
--- /dev/null
+++ b/examples/rp235x/src/bin/i2c_async.rs
@@ -0,0 +1,110 @@
1//! This example shows how to communicate asynchronous using i2c with external chips.
2//!
3//! Example written for the [`MCP23017 16-Bit I2C I/O Expander with Serial Interface`] chip.
4//! (https://www.microchip.com/en-us/product/mcp23017)
5
6#![no_std]
7#![no_main]
8
9use defmt::*;
10use embassy_executor::Spawner;
11use embassy_rp::bind_interrupts;
12use embassy_rp::i2c::{self, Config, InterruptHandler};
13use embassy_rp::peripherals::I2C1;
14use embassy_time::Timer;
15use embedded_hal_async::i2c::I2c;
16use {defmt_rtt as _, panic_probe as _};
17
18bind_interrupts!(struct Irqs {
19 I2C1_IRQ => InterruptHandler<I2C1>;
20});
21
22#[allow(dead_code)]
23mod mcp23017 {
24 pub const ADDR: u8 = 0x20; // default addr
25
26 macro_rules! mcpregs {
27 ($($name:ident : $val:expr),* $(,)?) => {
28 $(
29 pub const $name: u8 = $val;
30 )*
31
32 pub fn regname(reg: u8) -> &'static str {
33 match reg {
34 $(
35 $val => stringify!($name),
36 )*
37 _ => panic!("bad reg"),
38 }
39 }
40 }
41 }
42
43 // These are correct for IOCON.BANK=0
44 mcpregs! {
45 IODIRA: 0x00,
46 IPOLA: 0x02,
47 GPINTENA: 0x04,
48 DEFVALA: 0x06,
49 INTCONA: 0x08,
50 IOCONA: 0x0A,
51 GPPUA: 0x0C,
52 INTFA: 0x0E,
53 INTCAPA: 0x10,
54 GPIOA: 0x12,
55 OLATA: 0x14,
56 IODIRB: 0x01,
57 IPOLB: 0x03,
58 GPINTENB: 0x05,
59 DEFVALB: 0x07,
60 INTCONB: 0x09,
61 IOCONB: 0x0B,
62 GPPUB: 0x0D,
63 INTFB: 0x0F,
64 INTCAPB: 0x11,
65 GPIOB: 0x13,
66 OLATB: 0x15,
67 }
68}
69
70#[embassy_executor::main]
71async fn main(_spawner: Spawner) {
72 let p = embassy_rp::init(Default::default());
73
74 let sda = p.PIN_14;
75 let scl = p.PIN_15;
76
77 info!("set up i2c ");
78 let mut i2c = i2c::I2c::new_async(p.I2C1, scl, sda, Irqs, Config::default());
79
80 use mcp23017::*;
81
82 info!("init mcp23017 config for IxpandO");
83 // init - a outputs, b inputs
84 i2c.write(ADDR, &[IODIRA, 0x00]).await.unwrap();
85 i2c.write(ADDR, &[IODIRB, 0xff]).await.unwrap();
86 i2c.write(ADDR, &[GPPUB, 0xff]).await.unwrap(); // pullups
87
88 let mut val = 1;
89 loop {
90 let mut portb = [0];
91
92 i2c.write_read(mcp23017::ADDR, &[GPIOB], &mut portb).await.unwrap();
93 info!("portb = {:02x}", portb[0]);
94 i2c.write(mcp23017::ADDR, &[GPIOA, val | portb[0]]).await.unwrap();
95 val = val.rotate_left(1);
96
97 // get a register dump
98 info!("getting register dump");
99 let mut regs = [0; 22];
100 i2c.write_read(ADDR, &[0], &mut regs).await.unwrap();
101 // always get the regdump but only display it if portb'0 is set
102 if portb[0] & 1 != 0 {
103 for (idx, reg) in regs.into_iter().enumerate() {
104 info!("{} => {:02x}", regname(idx as u8), reg);
105 }
106 }
107
108 Timer::after_millis(100).await;
109 }
110}