const HasLowFrequencyCrystal = true
const (
D0 = P0_25 // UART TX
D1 = P0_24 // UART RX
D2 = P0_10 // NFC2
D3 = P1_15 // LED1
D4 = P1_10 // LED2
D5 = P1_08
D6 = P0_07
D7 = P1_02 // Button
D8 = P0_16 // NeoPixel
D9 = P0_26
D10 = P0_27
D11 = P0_06
D12 = P0_08
D13 = P1_09
D14 = P0_04 // A0
D15 = P0_05 // A1
D16 = P0_30 // A2
D17 = P0_28 // A3
D18 = P0_02 // A4
D19 = P0_03 // A5
D20 = P0_29 // Battery
D21 = P0_31 // AREF
D22 = P0_12 // I2C SDA
D23 = P0_11 // I2C SCL
D24 = P0_15 // SPI MISO
D25 = P0_13 // SPI MOSI
D26 = P0_14 // SPI SCK
D27 = P0_19 // QSPI CLK
D28 = P0_20 // QSPI CS
D29 = P0_17 // QSPI Data 0
D30 = P0_22 // QSPI Data 1
D31 = P0_23 // QSPI Data 2
D32 = P0_21 // QSPI Data 3
D33 = P0_09 // NFC1 (test point on bottom of board)
)
GPIO Pins
const (
A0 = D14
A1 = D15
A2 = D16
A3 = D17
A4 = D18
A5 = D19
A6 = D20 // Battery
A7 = D21 // ARef
)
Analog Pins
const (
LED = D3
LED1 = LED
LED2 = D4
NEOPIXEL = D8
BUTTON = D7
QSPI_SCK = D27
QSPI_CS = D28
QSPI_DATA0 = D29
QSPI_DATA1 = D30
QSPI_DATA2 = D31
QSPI_DATA3 = D32
)
const (
UART_RX_PIN = D0
UART_TX_PIN = D1
)
UART0 pins (logical UART1)
const (
SDA_PIN = D22 // I2C0 external
SCL_PIN = D23 // I2C0 external
)
I2C pins
const (
SPI0_SCK_PIN = D26 // SCK
SPI0_SDO_PIN = D25 // SDO
SPI0_SDI_PIN = D24 // SDI
)
SPI pins
const (
TWI_FREQ_100KHZ = 100000
TWI_FREQ_400KHZ = 400000
)
TWI_FREQ is the I2C bus speed. Normally either 100 kHz, or 400 kHz for high-speed bus.
const NoPin = Pin(0xff)
NoPin explicitly indicates “not a pin”. Use this pin if you want to leave one of the pins in a peripheral unconfigured (if supported by the hardware).
const (
PinInput PinMode = (nrf.GPIO_PIN_CNF_DIR_Input << nrf.GPIO_PIN_CNF_DIR_Pos) | (nrf.GPIO_PIN_CNF_INPUT_Connect << nrf.GPIO_PIN_CNF_INPUT_Pos)
PinInputPullup PinMode = PinInput | (nrf.GPIO_PIN_CNF_PULL_Pullup << nrf.GPIO_PIN_CNF_PULL_Pos)
PinInputPulldown PinMode = PinInput | (nrf.GPIO_PIN_CNF_PULL_Pulldown << nrf.GPIO_PIN_CNF_PULL_Pos)
PinOutput PinMode = (nrf.GPIO_PIN_CNF_DIR_Output << nrf.GPIO_PIN_CNF_DIR_Pos) | (nrf.GPIO_PIN_CNF_INPUT_Disconnect << nrf.GPIO_PIN_CNF_INPUT_Pos)
)
const (
PinRising PinChange = nrf.GPIOTE_CONFIG_POLARITY_LoToHi
PinFalling PinChange = nrf.GPIOTE_CONFIG_POLARITY_HiToLo
PinToggle PinChange = nrf.GPIOTE_CONFIG_POLARITY_Toggle
)
Pin change interrupt constants for SetInterrupt.
const (
P0_00 Pin = 0
P0_01 Pin = 1
P0_02 Pin = 2
P0_03 Pin = 3
P0_04 Pin = 4
P0_05 Pin = 5
P0_06 Pin = 6
P0_07 Pin = 7
P0_08 Pin = 8
P0_09 Pin = 9
P0_10 Pin = 10
P0_11 Pin = 11
P0_12 Pin = 12
P0_13 Pin = 13
P0_14 Pin = 14
P0_15 Pin = 15
P0_16 Pin = 16
P0_17 Pin = 17
P0_18 Pin = 18
P0_19 Pin = 19
P0_20 Pin = 20
P0_21 Pin = 21
P0_22 Pin = 22
P0_23 Pin = 23
P0_24 Pin = 24
P0_25 Pin = 25
P0_26 Pin = 26
P0_27 Pin = 27
P0_28 Pin = 28
P0_29 Pin = 29
P0_30 Pin = 30
P0_31 Pin = 31
P1_00 Pin = 32
P1_01 Pin = 33
P1_02 Pin = 34
P1_03 Pin = 35
P1_04 Pin = 36
P1_05 Pin = 37
P1_06 Pin = 38
P1_07 Pin = 39
P1_08 Pin = 40
P1_09 Pin = 41
P1_10 Pin = 42
P1_11 Pin = 43
P1_12 Pin = 44
P1_13 Pin = 45
P1_14 Pin = 46
P1_15 Pin = 47
)
Hardware pins
const (
DFU_MAGIC_SERIAL_ONLY_RESET = 0x4e
DFU_MAGIC_UF2_RESET = 0x57
DFU_MAGIC_OTA_RESET = 0xA8
)
var (
UART0 = USB
)
UART0 is the USB device
var (
ErrInvalidInputPin = errors.New("machine: invalid input pin")
ErrInvalidOutputPin = errors.New("machine: invalid output pin")
ErrInvalidClockPin = errors.New("machine: invalid clock pin")
ErrInvalidDataPin = errors.New("machine: invalid data pin")
ErrNoPinChangeChannel = errors.New("machine: no channel available for pin interrupt")
)
var (
ErrTxInvalidSliceSize = errors.New("SPI write and read slices must be same size")
)
var (
// NRF_UART0 is the hardware UART on the NRF SoC.
NRF_UART0 = UART{Buffer: NewRingBuffer()}
)
UART
var (
I2C0 = I2C{Bus: nrf.TWI0}
I2C1 = I2C{Bus: nrf.TWI1}
)
There are 2 I2C interfaces on the NRF.
var (
SPI0 = SPI{Bus: nrf.SPI0}
SPI1 = SPI{Bus: nrf.SPI1}
)
There are 2 SPI interfaces on the NRF5x.
var (
USB = USBCDC{Buffer: NewRingBuffer()}
usbEndpointDescriptors [8]usbDeviceDescriptor
udd_ep_in_cache_buffer [7][128]uint8
udd_ep_out_cache_buffer [7][128]uint8
sendOnEP0DATADONE struct {
ptr *byte
count int
}
isEndpointHalt = false
isRemoteWakeUpEnabled = false
endPoints = []uint32{usb_ENDPOINT_TYPE_CONTROL,
(usb_ENDPOINT_TYPE_INTERRUPT | usbEndpointIn),
(usb_ENDPOINT_TYPE_BULK | usbEndpointOut),
(usb_ENDPOINT_TYPE_BULK | usbEndpointIn)}
usbConfiguration uint8
usbSetInterface uint8
usbLineInfo = cdcLineInfo{115200, 0x00, 0x00, 0x08, 0x00}
epinen uint32
epouten uint32
easyDMABusy volatile.Register8
epout0data_setlinecoding bool
)
func CPUFrequency() uint32
func EnterOTABootloader()
EnterOTABootloader resets the chip into the bootloader so that it can be flashed via an OTA update
func EnterSerialBootloader()
EnterSerialBootloader resets the chip into the serial bootloader. After reset, it can be flashed using serial/nrfutil.
func EnterUF2Bootloader()
EnterUF2Bootloader resets the chip into the UF2 bootloader. After reset, it can be flashed via nrfutil or by copying a UF2 file to the mass storage device
func InitADC()
InitADC initializes the registers needed for ADC.
func InitPWM()
InitPWM initializes the registers needed for PWM.
func NewACMFunctionalDescriptor(subtype, d0 uint8) ACMFunctionalDescriptor
NewACMFunctionalDescriptor returns a new USB ACMFunctionalDescriptor.
func NewCDCCSInterfaceDescriptor(subtype, d0, d1 uint8) CDCCSInterfaceDescriptor
NewCDCCSInterfaceDescriptor returns a new USB CDCCSInterfaceDescriptor.
func NewCDCDescriptor(i IADDescriptor, c InterfaceDescriptor,
h CDCCSInterfaceDescriptor,
cm ACMFunctionalDescriptor,
fd CDCCSInterfaceDescriptor,
callm CMFunctionalDescriptor,
ci EndpointDescriptor,
di InterfaceDescriptor,
outp EndpointDescriptor,
inp EndpointDescriptor) CDCDescriptor
func NewCMFunctionalDescriptor(subtype, d0, d1 uint8) CMFunctionalDescriptor
NewCMFunctionalDescriptor returns a new USB CMFunctionalDescriptor.
func NewConfigDescriptor(totalLength uint16, interfaces uint8) ConfigDescriptor
NewConfigDescriptor returns a new USB ConfigDescriptor.
func NewDeviceDescriptor(class, subClass, proto, packetSize0 uint8, vid, pid, version uint16, im, ip, is, configs uint8) DeviceDescriptor
NewDeviceDescriptor returns a USB DeviceDescriptor.
func NewEndpointDescriptor(addr, attr uint8, packetSize uint16, interval uint8) EndpointDescriptor
NewEndpointDescriptor returns a new USB EndpointDescriptor.
func NewIADDescriptor(firstInterface, count, class, subClass, protocol uint8) IADDescriptor
NewIADDescriptor returns a new USB IADDescriptor.
func NewInterfaceDescriptor(n, numEndpoints, class, subClass, protocol uint8) InterfaceDescriptor
NewInterfaceDescriptor returns a new USB InterfaceDescriptor.
func NewRingBuffer() *RingBuffer
NewRingBuffer returns a new ring buffer.
type ACMFunctionalDescriptor struct {
len uint8
dtype uint8 // 0x24
subtype uint8 // 1
bmCapabilities uint8
}
ACMFunctionalDescriptor is a Abstract Control Model (ACM) USB descriptor.
func (d ACMFunctionalDescriptor) Bytes() []byte
Bytes returns the ACMFunctionalDescriptor data.
type ADC struct {
Pin Pin
}
func (a ADC) Configure() error
Configure configures an ADC pin to be able to read analog data.
func (a ADC) Get() uint16
Get returns the current value of a ADC pin in the range 0..0xffff.
type CDCCSInterfaceDescriptor struct {
len uint8 // 5
dtype uint8 // 0x24
subtype uint8
d0 uint8
d1 uint8
}
CDCCSInterfaceDescriptor is a CDC CS interface descriptor.
func (d CDCCSInterfaceDescriptor) Bytes() []byte
Bytes returns CDCCSInterfaceDescriptor data.
type CDCDescriptor struct {
// IAD
iad IADDescriptor // Only needed on compound device
// Control
cif InterfaceDescriptor
header CDCCSInterfaceDescriptor
// CDC control
controlManagement ACMFunctionalDescriptor // ACM
functionalDescriptor CDCCSInterfaceDescriptor // CDC_UNION
callManagement CMFunctionalDescriptor // Call Management
cifin EndpointDescriptor
// CDC Data
dif InterfaceDescriptor
in EndpointDescriptor
out EndpointDescriptor
}
CDCDescriptor is the Communication Device Class (CDC) descriptor.
func (d CDCDescriptor) Bytes() []byte
Bytes returns CDCDescriptor data.
type CMFunctionalDescriptor struct {
bFunctionLength uint8
bDescriptorType uint8 // 0x24
bDescriptorSubtype uint8 // 1
bmCapabilities uint8
bDataInterface uint8
}
CMFunctionalDescriptor is the functional descriptor general format.
func (d CMFunctionalDescriptor) Bytes() []byte
Bytes returns the CMFunctionalDescriptor data.
type ConfigDescriptor struct {
bLength uint8 // 9
bDescriptorType uint8 // 2
wTotalLength uint16 // total length
bNumInterfaces uint8
bConfigurationValue uint8
iConfiguration uint8
bmAttributes uint8
bMaxPower uint8
}
ConfigDescriptor implements the standard USB configuration descriptor.
Table 9-10. Standard Configuration Descriptor bLength, bDescriptorType, wTotalLength, bNumInterfaces, bConfigurationValue, iConfiguration bmAttributes, bMaxPower
func (d ConfigDescriptor) Bytes() []byte
Bytes returns ConfigDescriptor data.
type DeviceDescriptor struct {
bLength uint8 // 18
bDescriptorType uint8 // 1 USB_DEVICE_DESCRIPTOR_TYPE
bcdUSB uint16 // 0x200
bDeviceClass uint8
bDeviceSubClass uint8
bDeviceProtocol uint8
bMaxPacketSize0 uint8 // Packet 0
idVendor uint16
idProduct uint16
bcdDevice uint16 // 0x100
iManufacturer uint8
iProduct uint8
iSerialNumber uint8
bNumConfigurations uint8
}
DeviceDescriptor implements the USB standard device descriptor.
Table 9-8. Standard Device Descriptor bLength, bDescriptorType, bcdUSB, bDeviceClass, bDeviceSubClass, bDeviceProtocol, bMaxPacketSize0, idVendor, idProduct, bcdDevice, iManufacturer, iProduct, iSerialNumber, bNumConfigurations */
func (d DeviceDescriptor) Bytes() []byte
Bytes returns DeviceDescriptor data
type EndpointDescriptor struct {
bLength uint8 // 7
bDescriptorType uint8 // 5
bEndpointAddress uint8
bmAttributes uint8
wMaxPacketSize uint16
bInterval uint8
}
EndpointDescriptor implements the standard USB endpoint descriptor.
Table 9-13. Standard Endpoint Descriptor bLength, bDescriptorType, bEndpointAddress, bmAttributes, wMaxPacketSize, bInterval
func (d EndpointDescriptor) Bytes() []byte
Bytes returns EndpointDescriptor data.
type I2C struct {
Bus *nrf.TWI_Type
}
I2C on the NRF.
func (i2c I2C) Configure(config I2CConfig)
Configure is intended to setup the I2C interface.
func (i2c I2C) ReadRegister(address uint8, register uint8, data []byte) error
ReadRegister transmits the register, restarts the connection as a read operation, and reads the response.
Many I2C-compatible devices are organized in terms of registers. This method is a shortcut to easily read such registers. Also, it only works for devices with 7-bit addresses, which is the vast majority.
func (i2c I2C) Tx(addr uint16, w, r []byte) error
Tx does a single I2C transaction at the specified address. It clocks out the given address, writes the bytes in w, reads back len® bytes and stores them in r, and generates a stop condition on the bus.
func (i2c I2C) WriteRegister(address uint8, register uint8, data []byte) error
WriteRegister transmits first the register and then the data to the peripheral device.
Many I2C-compatible devices are organized in terms of registers. This method is a shortcut to easily write to such registers. Also, it only works for devices with 7-bit addresses, which is the vast majority.
type I2CConfig struct {
Frequency uint32
SCL Pin
SDA Pin
}
I2CConfig is used to store config info for I2C.
type IADDescriptor struct {
bLength uint8 // 8
bDescriptorType uint8 // 11
bFirstInterface uint8
bInterfaceCount uint8
bFunctionClass uint8
bFunctionSubClass uint8
bFunctionProtocol uint8
iFunction uint8
}
IADDescriptor is an Interface Association Descriptor, which is used to bind 2 interfaces together in CDC composite device.
Standard Interface Association Descriptor: bLength, bDescriptorType, bFirstInterface, bInterfaceCount, bFunctionClass, bFunctionSubClass, bFunctionProtocol, iFunction
func (d IADDescriptor) Bytes() []byte
Bytes returns IADDescriptor data.
type InterfaceDescriptor struct {
bLength uint8 // 9
bDescriptorType uint8 // 4
bInterfaceNumber uint8
bAlternateSetting uint8
bNumEndpoints uint8
bInterfaceClass uint8
bInterfaceSubClass uint8
bInterfaceProtocol uint8
iInterface uint8
}
InterfaceDescriptor implements the standard USB interface descriptor.
Table 9-12. Standard Interface Descriptor bLength, bDescriptorType, bInterfaceNumber, bAlternateSetting, bNumEndpoints, bInterfaceClass, bInterfaceSubClass, bInterfaceProtocol, iInterface
func (d InterfaceDescriptor) Bytes() []byte
Bytes returns InterfaceDescriptor data.
type MSCDescriptor struct {
msc InterfaceDescriptor
in EndpointDescriptor
out EndpointDescriptor
}
MSCDescriptor is not used yet.
type PWM struct {
Pin Pin
}
func (pwm PWM) Configure()
Configure configures a PWM pin for output.
func (pwm PWM) Set(value uint16)
Set turns on the duty cycle for a PWM pin using the provided value.
type Pin uint8
Pin is a single pin on a chip, which may be connected to other hardware devices. It can either be used directly as GPIO pin or it can be used in other peripherals like ADC, I2C, etc.
func (p Pin) Configure(config PinConfig)
Configure this pin with the given configuration.
func (p Pin) Get() bool
Get returns the current value of a GPIO pin.
func (p Pin) High()
High sets this GPIO pin to high, assuming it has been configured as an output pin. It is hardware dependent (and often undefined) what happens if you set a pin to high that is not configured as an output pin.
func (p Pin) Low()
Low sets this GPIO pin to low, assuming it has been configured as an output pin. It is hardware dependent (and often undefined) what happens if you set a pin to low that is not configured as an output pin.
func (p Pin) PortMaskClear() (*uint32, uint32)
Return the register and mask to disable a given port. This can be used to implement bit-banged drivers.
func (p Pin) PortMaskSet() (*uint32, uint32)
Return the register and mask to enable a given GPIO pin. This can be used to implement bit-banged drivers.
func (p Pin) Set(high bool)
Set the pin to high or low. Warning: only use this on an output pin!
func (p Pin) SetInterrupt(change PinChange, callback func(Pin)) error
SetInterrupt sets an interrupt to be executed when a particular pin changes state.
This call will replace a previously set callback on this pin. You can pass a nil func to unset the pin change interrupt. If you do so, the change parameter is ignored and can be set to any value (such as 0).
type PinChange uint8
type PinConfig struct {
Mode PinMode
}
type PinMode uint8
type RingBuffer struct {
rxbuffer [bufferSize]volatile.Register8
head volatile.Register8
tail volatile.Register8
}
RingBuffer is ring buffer implementation inspired by post at https://www.embeddedrelated.com/showthread/comp.arch.embedded/77084-1.php
func (rb *RingBuffer) Clear()
Clear resets the head and tail pointer to zero.
func (rb *RingBuffer) Get() (byte, bool)
Get returns a byte from the buffer. If the buffer is empty, the method will return a false as the second value.
func (rb *RingBuffer) Put(val byte) bool
Put stores a byte in the buffer. If the buffer is already full, the method will return false.
func (rb *RingBuffer) Used() uint8
Used returns how many bytes in buffer have been used.
type SPI struct {
Bus *nrf.SPI_Type
}
SPI on the NRF.
func (spi SPI) Configure(config SPIConfig)
Configure is intended to setup the SPI interface.
func (spi SPI) Transfer(w byte) (byte, error)
Transfer writes/reads a single byte using the SPI interface.
func (spi SPI) Tx(w, r []byte) error
Tx handles read/write operation for SPI interface. Since SPI is a syncronous write/read interface, there must always be the same number of bytes written as bytes read. The Tx method knows about this, and offers a few different ways of calling it.
This form sends the bytes in tx buffer, putting the resulting bytes read into the rx buffer. Note that the tx and rx buffers must be the same size:
spi.Tx(tx, rx)
This form sends the tx buffer, ignoring the result. Useful for sending “commands” that return zeros until all the bytes in the command packet have been received:
spi.Tx(tx, nil)
This form sends zeros, putting the result into the rx buffer. Good for reading a “result packet”:
spi.Tx(nil, rx)
type SPIConfig struct {
Frequency uint32
SCK Pin
SDO Pin
SDI Pin
LSBFirst bool
Mode uint8
}
SPIConfig is used to store config info for SPI.
type UART struct {
Buffer *RingBuffer
}
UART on the NRF.
func (uart UART) Buffered() int
Buffered returns the number of bytes currently stored in the RX buffer.
func (uart UART) Configure(config UARTConfig)
Configure the UART.
func (uart UART) Read(data []byte) (n int, err error)
Read from the RX buffer.
func (uart UART) ReadByte() (byte, error)
ReadByte reads a single byte from the RX buffer. If there is no data in the buffer, returns an error.
func (uart UART) Receive(data byte)
Receive handles adding data to the UART’s data buffer. Usually called by the IRQ handler for a machine.
func (uart UART) SetBaudRate(br uint32)
SetBaudRate sets the communication speed for the UART.
func (uart UART) Write(data []byte) (n int, err error)
Write data to the UART.
func (uart UART) WriteByte(c byte) error
WriteByte writes a byte of data to the UART.
type UARTConfig struct {
BaudRate uint32
TX Pin
RX Pin
}
type USBCDC struct {
Buffer *RingBuffer
interrupt interrupt.Interrupt
}
USBCDC is the USB CDC aka serial over USB interface on the nRF52840
func (usbcdc USBCDC) Buffered() int
Buffered returns the number of bytes currently stored in the RX buffer.
func (usbcdc *USBCDC) Configure(config UARTConfig)
Configure the USB CDC interface. The config is here for compatibility with the UART interface.
func (usbcdc USBCDC) DTR() bool
func (usbcdc USBCDC) RTS() bool
func (usbcdc USBCDC) Read(data []byte) (n int, err error)
Read from the RX buffer.
func (usbcdc USBCDC) ReadByte() (byte, error)
ReadByte reads a single byte from the RX buffer. If there is no data in the buffer, returns an error.
func (usbcdc USBCDC) Receive(data byte)
Receive handles adding data to the UART’s data buffer. Usually called by the IRQ handler for a machine.
func (usbcdc USBCDC) Write(data []byte) (n int, err error)
Write data to the USBCDC.
func (usbcdc USBCDC) WriteByte(c byte) error
WriteByte writes a byte of data to the USB CDC interface.