i2c: implement target mode for rp2040 and nrf

This commit is contained in:
Kenneth Bell
2023-03-25 16:27:54 +00:00
committed by Ron Evans
parent e0385e48d0
commit ad3e9e1a77
9 changed files with 479 additions and 27 deletions
+130
View File
@@ -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:
}
}
}
@@ -0,0 +1,15 @@
//go:build feather_nrf52840
package main
import "machine"
const (
TARGET_SCL = machine.A5
TARGET_SDA = machine.A4
)
var (
controller = machine.I2C0
target = machine.I2C1
)
@@ -0,0 +1,15 @@
//go:build rp2040
package main
import "machine"
const (
TARGET_SCL = machine.GPIO25
TARGET_SDA = machine.GPIO24
)
var (
controller = machine.I2C1
target = machine.I2C0
)