github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/examples/i2c-target/main.go (about) 1 // Example demonstrating I2C controller / target comms. 2 // 3 // To use this example, physically connect I2C0 and I2C1. 4 // I2C0 will be used as the controller and I2C1 used as 5 // the target. 6 // 7 // In this example, the target implements a simple memory 8 // map, with the controller able to read and write the 9 // memory. 10 11 package main 12 13 import ( 14 "machine" 15 "time" 16 ) 17 18 const ( 19 targetAddress = 0x11 20 maxTxSize = 16 21 ) 22 23 func main() { 24 // Delay to enable USB monitor time to attach 25 time.Sleep(3 * time.Second) 26 27 // Controller uses default I2C pins and controller 28 // mode is default 29 err := controller.Configure(machine.I2CConfig{}) 30 if err != nil { 31 panic("failed to config I2C0 as controller") 32 } 33 34 // Target uses alternate pins and target mode is 35 // explicit 36 err = target.Configure(machine.I2CConfig{ 37 Mode: machine.I2CModeTarget, 38 SCL: TARGET_SCL, 39 SDA: TARGET_SDA, 40 }) 41 if err != nil { 42 panic("failed to config I2C1 as target") 43 } 44 45 // Put welcome message directly into target memory 46 copy(mem[0:], []byte("Hello World!")) 47 err = target.Listen(targetAddress) 48 if err != nil { 49 panic("failed to listen as I2C target") 50 } 51 52 // Start the target 53 go targetMain() 54 55 // Read welcome message from target over I2C 56 buf := make([]byte, 12) 57 err = controller.Tx(targetAddress, []byte{0}, buf) 58 if err != nil { 59 println("failed to read welcome message over I2C") 60 panic(err) 61 } 62 println("message from target:", string(buf)) 63 64 // Write (1,2,3) to the target starting at memory address 3 65 println("writing (1,2,3) @ 0x3") 66 err = controller.Tx(targetAddress, []byte{3, 1, 2, 3}, nil) 67 if err != nil { 68 println("failed to write to I2C target") 69 panic(err) 70 } 71 72 time.Sleep(100 * time.Millisecond) // Wait for target to process write 73 println("mem:", mem[0], mem[1], mem[2], mem[3], mem[4], mem[5]) 74 75 // Read memory address 4 from target, which should be the value 2 76 buf = make([]byte, 1) 77 err = controller.Tx(targetAddress, []byte{4}, buf[:1]) 78 if err != nil { 79 println("failed to read from I2C target") 80 panic(err) 81 } 82 83 if buf[0] != 2 { 84 panic("read incorrect value from I2C target") 85 } 86 87 println("all done!") 88 for { 89 time.Sleep(1 * time.Second) 90 } 91 } 92 93 // -- target --- 94 95 var ( 96 mem [256]byte 97 ) 98 99 // targetMain implements the 'main loop' for an I2C target 100 func targetMain() { 101 buf := make([]byte, maxTxSize) 102 var ptr uint8 103 104 for { 105 evt, n, err := target.WaitForEvent(buf) 106 if err != nil { 107 panic(err) 108 } 109 110 switch evt { 111 case machine.I2CReceive: 112 if n > 0 { 113 ptr = buf[0] 114 } 115 116 for o := 1; o < n; o++ { 117 mem[ptr] = buf[o] 118 ptr++ 119 } 120 121 case machine.I2CRequest: 122 target.Reply(mem[ptr:256]) 123 124 case machine.I2CFinish: 125 // nothing to do 126 127 default: 128 } 129 } 130 }