From f639d800125d343c0b326b2898ee7b04d67de3d0 Mon Sep 17 00:00:00 2001 From: deadprogram Date: Sat, 6 Jan 2024 19:07:18 +0100 Subject: [PATCH] ninafw: add support for software RTS/CTS flow control for boards where hardware support is not available Signed-off-by: deadprogram --- adapter_ninafw.go | 27 +++++++++++++++++++++------ hci_ninafw.go | 46 ++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 63 insertions(+), 10 deletions(-) diff --git a/adapter_ninafw.go b/adapter_ninafw.go index 7ff3c05..c246b2c 100644 --- a/adapter_ninafw.go +++ b/adapter_ninafw.go @@ -41,7 +41,6 @@ var DefaultAdapter = &Adapter{ func (a *Adapter) Enable() error { // reset the NINA in BLE mode machine.NINA_CS.Configure(machine.PinConfig{Mode: machine.PinOutput}) - machine.NINA_RESETN.Configure(machine.PinConfig{Mode: machine.PinOutput}) machine.NINA_CS.Low() if machine.NINA_RESET_INVERTED { @@ -51,16 +50,28 @@ func (a *Adapter) Enable() error { } // serial port for nina chip - uart := machine.UART1 - uart.Configure(machine.UARTConfig{ + uart := machine.UART_NINA + cfg := machine.UARTConfig{ TX: machine.NINA_TX, RX: machine.NINA_RX, BaudRate: machine.NINA_BAUDRATE, - CTS: machine.NINA_CTS, - RTS: machine.NINA_RTS, - }) + } + if !machine.NINA_SOFT_FLOWCONTROL { + cfg.CTS = machine.NINA_CTS + cfg.RTS = machine.NINA_RTS + } + + uart.Configure(cfg) a.hci, a.att = newBLEStack(uart) + if machine.NINA_SOFT_FLOWCONTROL { + a.hci.softRTS = machine.NINA_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.start() @@ -122,6 +133,8 @@ func makeNINAAddress(mac MAC) [6]uint8 { } func resetNINA() { + machine.NINA_RESETN.Configure(machine.PinConfig{Mode: machine.PinOutput}) + machine.NINA_RESETN.High() time.Sleep(100 * time.Millisecond) machine.NINA_RESETN.Low() @@ -129,6 +142,8 @@ func resetNINA() { } func resetNINAInverted() { + machine.NINA_RESETN.Configure(machine.PinConfig{Mode: machine.PinOutput}) + machine.NINA_RESETN.Low() time.Sleep(100 * time.Millisecond) machine.NINA_RESETN.High() diff --git a/hci_ninafw.go b/hci_ninafw.go index 4b1db95..7952e8a 100644 --- a/hci_ninafw.go +++ b/hci_ninafw.go @@ -117,6 +117,8 @@ type leConnectData struct { type hci struct { uart *machine.UART + softCTS machine.Pin + softRTS machine.Pin att *att buf []byte address [6]byte @@ -129,12 +131,21 @@ type hci struct { } func newHCI(uart *machine.UART) *hci { - return &hci{uart: uart, - buf: make([]byte, 256), + return &hci{ + uart: uart, + softCTS: machine.NoPin, + softRTS: machine.NoPin, + buf: make([]byte, 256), } } func (h *hci) start() error { + if h.softRTS != machine.NoPin { + h.softRTS.Low() + + defer h.softRTS.High() + } + for h.uart.Buffered() > 0 { h.uart.ReadByte() } @@ -151,6 +162,12 @@ func (h *hci) reset() error { } func (h *hci) poll() error { + if h.softRTS != machine.NoPin { + h.softRTS.Low() + + defer h.softRTS.High() + } + i := 0 for h.uart.Buffered() > 0 { data, _ := h.uart.ReadByte() @@ -322,7 +339,7 @@ func (h *hci) sendCommandWithParams(opcode uint16, params []byte) error { h.buf[3] = byte(len(params)) copy(h.buf[4:], params) - if _, err := h.uart.Write(h.buf[:4+len(params)]); err != nil { + if _, err := h.write(h.buf[:4+len(params)]); err != nil { return err } @@ -356,13 +373,34 @@ func (h *hci) sendAclPkt(handle uint16, cid uint8, data []byte) error { println("hci send acl data", handle, cid, hex.EncodeToString(h.buf[:9+len(data)])) } - if _, err := h.uart.Write(h.buf[:9+len(data)]); err != nil { + if _, err := h.write(h.buf[:9+len(data)]); err != nil { return err } return nil } +const writeAttempts = 200 + +func (h *hci) write(buf []byte) (int, error) { + if h.softCTS != machine.NoPin { + retries := writeAttempts + for h.softCTS.Get() { + retries-- + if retries == 0 { + return 0, ErrHCITimeout + } + } + } + + n, err := h.uart.Write(buf) + if err != nil { + return 0, err + } + + return n, nil +} + type aclDataHeader struct { handle uint16 dlen uint16