diff --git a/Makefile b/Makefile index 268d820c..6ad6ac88 100644 --- a/Makefile +++ b/Makefile @@ -42,6 +42,10 @@ smoketest-tinygo: @md5sum test.hex $(TINYGO) build -o test.uf2 -size=short -target=nano-rp2040 ./examples/advertisement @md5sum test.hex + $(TINYGO) build -o test.uf2 -size=short -target=feather-m4 -tags="ninafw ninafw_featherwing_init" ./examples/advertisement + @md5sum test.hex + $(TINYGO) build -o test.uf2 -size=short -target=pybadge ./examples/advertisement + @md5sum test.hex smoketest-linux: # Test on Linux. diff --git a/README.md b/README.md index ba40fde2..67f22a58 100644 --- a/README.md +++ b/README.md @@ -284,6 +284,10 @@ For example, this command can be used to compile and flash an Arduino Nano RP204 tinygo flash -target nano-rp2040 ./examples/heartrate +When using the AirLift WiFi Featherwing with one of Adafruit's feather boards, you can use `ninafw ninafw_featherwing_init` build tags to set up the hardware using the default pins. Make sure to [connect the solder pads on the underside of the board](https://learn.adafruit.com/adafruit-airlift-featherwing-esp32-wifi-co-processor-featherwing/pinouts#spi-and-control-pins-3029450) in order to enable BLE support (see "Optional Control Pins" section). + +To use ninafw with other boards, you will need to use the `ninafw` build tag as well as configure the pins and UART for communicating with the ESP32 module by configuring the `AdapterConfig` package variable before calling `DefaultAdapter.Enable()`. See [`adapter_ninafw-featherwing.go`](adapter_ninafw-featherwing.go) for an example of setting the hardware configuration options. + If you want more information about the `nina-fw` firmware, or want to add support for other ESP32-equipped boards, please see https://github.com/arduino/nina-fw ## API stability diff --git a/adapter_ninafw-featherwing.go b/adapter_ninafw-featherwing.go new file mode 100644 index 00000000..7dee7d12 --- /dev/null +++ b/adapter_ninafw-featherwing.go @@ -0,0 +1,22 @@ +//go:build ninafw && ninafw_featherwing_init + +package bluetooth + +import ( + "machine" +) + +func init() { + AdapterConfig = NINAConfig{ + UART: machine.DefaultUART, + CS: machine.D13, + ACK: machine.D11, + GPIO0: machine.D10, + RESETN: machine.D12, + CTS: machine.D11, // same as ACK + RTS: machine.D10, // same as GPIO0 + BaudRate: 115200, + ResetInverted: true, + SoftFlowControl: true, + } +} diff --git a/adapter_ninafw-machine.go b/adapter_ninafw-machine.go new file mode 100644 index 00000000..1434be59 --- /dev/null +++ b/adapter_ninafw-machine.go @@ -0,0 +1,22 @@ +//go:build ninafw && ninafw_machine_init + +package bluetooth + +import ( + "machine" +) + +func init() { + AdapterConfig = NINAConfig{ + UART: machine.UART_NINA, + CS: machine.NINA_CS, + ACK: machine.NINA_ACK, + GPIO0: machine.NINA_GPIO0, + RESETN: machine.NINA_RESETN, + CTS: machine.NINA_CTS, + RTS: machine.NINA_RTS, + BaudRate: machine.NINA_BAUDRATE, + ResetInverted: machine.NINA_RESET_INVERTED, + SoftFlowControl: machine.NINA_SOFT_FLOWCONTROL, + } +} diff --git a/adapter_ninafw.go b/adapter_ninafw.go index 688e5687..78605f71 100644 --- a/adapter_ninafw.go +++ b/adapter_ninafw.go @@ -11,6 +11,29 @@ import ( const maxConnections = 1 +// NINAConfig encapsulates the hardware options for the NINA firmware +type NINAConfig struct { + UART *machine.UART + + CS machine.Pin + ACK machine.Pin + GPIO0 machine.Pin + RESETN machine.Pin + + TX machine.Pin + RX machine.Pin + CTS machine.Pin + RTS machine.Pin + + BaudRate uint32 + ResetInverted bool + SoftFlowControl bool +} + +// AdapterConfig is used to set the hardware options for the NINA adapter prior +// to calling DefaultAdapter.Enable() +var AdapterConfig NINAConfig + // Adapter represents the UART connection to the NINA fw. type Adapter struct { hci *hci @@ -40,37 +63,37 @@ var DefaultAdapter = &Adapter{ // Bluetooth-related calls (unless otherwise indicated). func (a *Adapter) Enable() error { // reset the NINA in BLE mode - machine.NINA_CS.Configure(machine.PinConfig{Mode: machine.PinOutput}) - machine.NINA_CS.Low() + AdapterConfig.CS.Configure(machine.PinConfig{Mode: machine.PinOutput}) + AdapterConfig.CS.Low() - if machine.NINA_RESET_INVERTED { + if AdapterConfig.ResetInverted { resetNINAInverted() } else { resetNINA() } // serial port for nina chip - uart := machine.UART_NINA + uart := AdapterConfig.UART cfg := machine.UARTConfig{ - TX: machine.NINA_TX, - RX: machine.NINA_RX, - BaudRate: machine.NINA_BAUDRATE, + TX: AdapterConfig.TX, + RX: AdapterConfig.RX, + BaudRate: AdapterConfig.BaudRate, } - if !machine.NINA_SOFT_FLOWCONTROL { - cfg.CTS = machine.NINA_CTS - cfg.RTS = machine.NINA_RTS + if !AdapterConfig.SoftFlowControl { + cfg.CTS = AdapterConfig.CTS + cfg.RTS = AdapterConfig.RTS } uart.Configure(cfg) a.hci, a.att = newBLEStack(uart) - if machine.NINA_SOFT_FLOWCONTROL { - a.hci.softRTS = machine.NINA_RTS + if AdapterConfig.SoftFlowControl { + a.hci.softRTS = AdapterConfig.RTS a.hci.softRTS.Configure(machine.PinConfig{Mode: machine.PinOutput}) a.hci.softRTS.High() - a.hci.softCTS = machine.NINA_CTS - machine.NINA_CTS.Configure(machine.PinConfig{Mode: machine.PinInput}) + a.hci.softCTS = AdapterConfig.CTS + AdapterConfig.CTS.Configure(machine.PinConfig{Mode: machine.PinInput}) } a.hci.start() @@ -133,20 +156,20 @@ func makeNINAAddress(mac MAC) [6]uint8 { } func resetNINA() { - machine.NINA_RESETN.Configure(machine.PinConfig{Mode: machine.PinOutput}) + AdapterConfig.RESETN.Configure(machine.PinConfig{Mode: machine.PinOutput}) - machine.NINA_RESETN.High() + AdapterConfig.RESETN.High() time.Sleep(100 * time.Millisecond) - machine.NINA_RESETN.Low() + AdapterConfig.RESETN.Low() time.Sleep(1000 * time.Millisecond) } func resetNINAInverted() { - machine.NINA_RESETN.Configure(machine.PinConfig{Mode: machine.PinOutput}) + AdapterConfig.RESETN.Configure(machine.PinConfig{Mode: machine.PinOutput}) - machine.NINA_RESETN.Low() + AdapterConfig.RESETN.Low() time.Sleep(100 * time.Millisecond) - machine.NINA_RESETN.High() + AdapterConfig.RESETN.High() time.Sleep(1000 * time.Millisecond) }