aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/examples/i2c-target/main.go
diff options
context:
space:
mode:
authorKenneth Bell <[email protected]>2023-03-25 16:27:54 +0000
committerRon Evans <[email protected]>2023-04-04 09:36:42 +0200
commitad3e9e1a776855a0844909054578d987593cd095 (patch)
tree5b0c7203c073d3625bbfc2fa0bd208dab50d0553 /src/examples/i2c-target/main.go
parente0385e48d09907c028f5f5926a2523c62757474a (diff)
downloadtinygo-ad3e9e1a776855a0844909054578d987593cd095.tar.gz
tinygo-ad3e9e1a776855a0844909054578d987593cd095.zip
i2c: implement target mode for rp2040 and nrf
Diffstat (limited to 'src/examples/i2c-target/main.go')
-rw-r--r--src/examples/i2c-target/main.go130
1 files changed, 130 insertions, 0 deletions
diff --git a/src/examples/i2c-target/main.go b/src/examples/i2c-target/main.go
new file mode 100644
index 000000000..cd984ba3c
--- /dev/null
+++ b/src/examples/i2c-target/main.go
@@ -0,0 +1,130 @@
+// Example demonstrating I2C controller / target comms.
+//
+// To use this example, physically connect I2C0 and I2C1.
+// I2C0 will be used as the controller and I2C1 used as
+// the target.
+//
+// In this example, the target implements a simple memory
+// map, with the controller able to read and write the
+// memory.
+
+package main
+
+import (
+ "machine"
+ "time"
+)
+
+const (
+ targetAddress = 0x11
+ maxTxSize = 16
+)
+
+func main() {
+ // Delay to enable USB monitor time to attach
+ time.Sleep(3 * time.Second)
+
+ // Controller uses default I2C pins and controller
+ // mode is default
+ err := controller.Configure(machine.I2CConfig{})
+ if err != nil {
+ panic("failed to config I2C0 as controller")
+ }
+
+ // Target uses alternate pins and target mode is
+ // explicit
+ err = target.Configure(machine.I2CConfig{
+ Mode: machine.I2CModeTarget,
+ SCL: TARGET_SCL,
+ SDA: TARGET_SDA,
+ })
+ if err != nil {
+ panic("failed to config I2C1 as target")
+ }
+
+ // Put welcome message directly into target memory
+ copy(mem[0:], []byte("Hello World!"))
+ err = target.Listen(targetAddress)
+ if err != nil {
+ panic("failed to listen as I2C target")
+ }
+
+ // Start the target
+ go targetMain()
+
+ // Read welcome message from target over I2C
+ buf := make([]byte, 12)
+ err = controller.Tx(targetAddress, []byte{0}, buf)
+ if err != nil {
+ println("failed to read welcome message over I2C")
+ panic(err)
+ }
+ println("message from target:", string(buf))
+
+ // Write (1,2,3) to the target starting at memory address 3
+ println("writing (1,2,3) @ 0x3")
+ err = controller.Tx(targetAddress, []byte{3, 1, 2, 3}, nil)
+ if err != nil {
+ println("failed to write to I2C target")
+ panic(err)
+ }
+
+ time.Sleep(100 * time.Millisecond) // Wait for target to process write
+ println("mem:", mem[0], mem[1], mem[2], mem[3], mem[4], mem[5])
+
+ // Read memory address 4 from target, which should be the value 2
+ buf = make([]byte, 1)
+ err = controller.Tx(targetAddress, []byte{4}, buf[:1])
+ if err != nil {
+ println("failed to read from I2C target")
+ panic(err)
+ }
+
+ if buf[0] != 2 {
+ panic("read incorrect value from I2C target")
+ }
+
+ println("all done!")
+ for {
+ time.Sleep(1 * time.Second)
+ }
+}
+
+// -- target ---
+
+var (
+ mem [256]byte
+)
+
+// targetMain implements the 'main loop' for an I2C target
+func targetMain() {
+ buf := make([]byte, maxTxSize)
+ var ptr uint8
+
+ for {
+ evt, n, err := target.WaitForEvent(buf)
+ if err != nil {
+ panic(err)
+ }
+
+ switch evt {
+ case machine.I2CReceive:
+ if n > 0 {
+ ptr = buf[0]
+ }
+
+ for o := 1; o < n; o++ {
+ mem[ptr] = buf[o]
+ ptr++
+ }
+
+ case machine.I2CRequest:
+ target.Reply(mem[ptr:256])
+
+ case machine.I2CFinish:
+ // nothing to do
+
+ default:
+ }
+ }
+}