diff --git a/examples/wifinina/pins/main.go b/examples/wifinina/pins/main.go new file mode 100644 index 0000000..378a528 --- /dev/null +++ b/examples/wifinina/pins/main.go @@ -0,0 +1,91 @@ +//go:build nano_rp2040 +// +build nano_rp2040 + +// This examples shows how to control RGB LED connected to +// NINA-W102 chip on Arduino Nano RP2040 Connect board +// Built-in LED code added for API comparison + +package main + +import ( + "machine" + "time" + + "tinygo.org/x/drivers/wifinina" +) + +const ( + LED = machine.LED + + // Arduino Nano RP2040 Connect board RGB LED pins + // See https://docs.arduino.cc/static/3525d638b5c76a2d19588d6b41cd02a0/ABX00053-full-pinout.pdf + LED_R wifinina.Pin = 27 + LED_G wifinina.Pin = 25 + LED_B wifinina.Pin = 26 +) + +var ( + + // these are the default pins for the Arduino Nano-RP2040 Connect + spi = machine.NINA_SPI + + // this is the ESP chip that has the WIFININA firmware flashed on it + device *wifinina.Device +) + +func setup() { + + // Configure SPI for 8Mhz, Mode 0, MSB First + spi.Configure(machine.SPIConfig{ + Frequency: 8 * 1e6, + SDO: machine.NINA_SDO, + SDI: machine.NINA_SDI, + SCK: machine.NINA_SCK, + }) + + device = wifinina.New(spi, + machine.NINA_CS, + machine.NINA_ACK, + machine.NINA_GPIO0, + machine.NINA_RESETN) + device.Configure() + + time.Sleep(time.Second) + + LED.Configure(machine.PinConfig{Mode: machine.PinOutput}) + LED_R.Configure(wifinina.PinConfig{Mode: wifinina.PinOutput}) + LED_G.Configure(wifinina.PinConfig{Mode: wifinina.PinOutput}) + LED_B.Configure(wifinina.PinConfig{Mode: wifinina.PinOutput}) +} + +func main() { + + setup() + + LED.Low() // OFF + LED_R.High() // OFF + LED_G.High() // OFF + LED_B.High() // OFF + + go func() { + for { + LED.Low() + time.Sleep(time.Second) + LED.High() + time.Sleep(time.Second) + } + }() + + for { + LED_R.Low() // ON + time.Sleep(time.Second) + LED_R.High() // OFF + LED_G.Low() // ON + time.Sleep(time.Second) + LED_G.High() // OFF + LED_B.Low() // ON + time.Sleep(time.Second) + LED_B.High() // OFF + } + +} diff --git a/wifinina/pins.go b/wifinina/pins.go new file mode 100644 index 0000000..a1afbcb --- /dev/null +++ b/wifinina/pins.go @@ -0,0 +1,65 @@ +package wifinina + +import "errors" + +// Mimics machine package's pin control +// +// NB! These are NINA chip pins, not main unit pins. +// +// Digital pin values and modes taken from +// https://github.com/arduino/nina-fw/blob/master/arduino/cores/esp32/wiring_digital.h + +type Pin uint8 + +const ( + PinLow uint8 = iota + PinHigh +) + +type PinMode uint8 + +const ( + PinInput PinMode = iota + PinOutput + PinInputPullup +) + +type PinConfig struct { + Mode PinMode +} + +var ( + ErrPinNoDevice = errors.New("wifinina pin: device not set") +) + +var pinDevice *Device + +func pinUseDevice(d *Device) { + pinDevice = d +} + +func (p Pin) Configure(config PinConfig) error { + if pinDevice == nil { + return ErrPinNoDevice + } + return pinDevice.PinMode(uint8(p), uint8(config.Mode)) +} + +func (p Pin) Set(high bool) error { + if pinDevice == nil { + return ErrPinNoDevice + } + value := PinLow + if high { + value = PinHigh + } + return pinDevice.DigitalWrite(uint8(p), value) +} + +func (p Pin) High() error { + return p.Set(true) +} + +func (p Pin) Low() error { + return p.Set(false) +} diff --git a/wifinina/wifinina.go b/wifinina/wifinina.go index 04ed371..290f1b0 100644 --- a/wifinina/wifinina.go +++ b/wifinina/wifinina.go @@ -297,6 +297,7 @@ func New(bus drivers.SPI, csPin, ackPin, gpio0Pin, resetPin machine.Pin) *Device func (d *Device) Configure() { net.UseDriver(d.NewDriver()) + pinUseDevice(d) d.CS.Configure(machine.PinConfig{Mode: machine.PinOutput}) d.ACK.Configure(machine.PinConfig{Mode: machine.PinInput}) @@ -689,6 +690,23 @@ func (d *Device) StartScanNetworks() (uint8, error) { return d.getUint8(d.req0(CmdStartScanNetworks)) } +func (d *Device) PinMode(pin uint8, mode uint8) error { + _, err := d.req2Uint8(CmdSetPinMode, pin, mode) + return err +} + +func (d *Device) DigitalWrite(pin uint8, value uint8) error { + _, err := d.req2Uint8(CmdSetDigitalWrite, pin, value) + return err +} + +func (d *Device) AnalogWrite(pin uint8, value uint8) error { + _, err := d.req2Uint8(CmdSetAnalogWrite, pin, value) + return err +} + +// ------------- End of public device interface ---------------------------- + func (d *Device) getString(l uint8, err error) (string, error) { if err != nil { return "", err @@ -773,6 +791,14 @@ func (d *Device) reqUint8(cmd uint8, data uint8) (l uint8, err error) { return d.waitRspCmd1(cmd) } +// req2Uint8 sends a command to the device with two uint8 parameters +func (d *Device) req2Uint8(cmd, p1, p2 uint8) (l uint8, err error) { + if err := d.sendCmdPadded2(cmd, p1, p2); err != nil { + return 0, err + } + return d.waitRspCmd1(cmd) +} + // reqStr sends a command to the device with a single string parameter func (d *Device) reqStr(cmd uint8, p1 string) (uint8, error) { if err := d.sendCmdStr(cmd, p1); err != nil { @@ -834,6 +860,18 @@ func (d *Device) sendCmdPadded1(cmd uint8, data uint8) error { return nil } +func (d *Device) sendCmdPadded2(cmd, data1, data2 uint8) error { + defer d.spiChipDeselect() + if err := d.waitForChipSelect(); err != nil { + return err + } + l := d.sendCmd(cmd, 1) + l += d.sendParam8(data1, false) + l += d.sendParam8(data2, true) + d.SPI.Transfer(dummyData) + return nil +} + func (d *Device) sendCmdStr(cmd uint8, p1 string) (err error) { defer d.spiChipDeselect() if err := d.waitForChipSelect(); err != nil {