mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-08-18 13:43:58 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 68d4991da1 |
@@ -13,11 +13,8 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container: tinygo/tinygo-dev
|
container: tinygo/tinygo-dev
|
||||||
steps:
|
steps:
|
||||||
- name: Work around CVE-2022-24765
|
|
||||||
# We're not on a multi-user machine, so this is safe.
|
|
||||||
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v2
|
||||||
- name: TinyGo version check
|
- name: TinyGo version check
|
||||||
run: tinygo version
|
run: tinygo version
|
||||||
- name: Enforce Go Formatted Code
|
- name: Enforce Go Formatted Code
|
||||||
|
|||||||
@@ -1,80 +1,3 @@
|
|||||||
0.24.0
|
|
||||||
---
|
|
||||||
- **new devices**
|
|
||||||
- **lora**
|
|
||||||
- created shared RadioEvent
|
|
||||||
- move shared config for sx126x/sx127x to single package
|
|
||||||
- **lorawan**
|
|
||||||
- add initial LoRaWAN stack support
|
|
||||||
- Basic implementation of Lorawan Regional Settings and EU868/AU915 regions
|
|
||||||
- **qmi8658c**
|
|
||||||
- Add support for the QMI8658C sensor (#467)
|
|
||||||
- **sh1106**
|
|
||||||
- add support for SH1106 display driver
|
|
||||||
- **sx127x**
|
|
||||||
- Driver for Semtech sx127x radio modules
|
|
||||||
|
|
||||||
- **enhancements**
|
|
||||||
- **bme280**
|
|
||||||
- improve config support
|
|
||||||
- add ReadAltitude() function copied from BMP280 driver
|
|
||||||
- **buzzer**
|
|
||||||
- make all note durations float64
|
|
||||||
- no tone during rest
|
|
||||||
- **dht22**
|
|
||||||
- update DHT22 receive to use runtime/interrupt
|
|
||||||
- **gps**
|
|
||||||
- add support for GLL sentence type, add original sentence to gps errors
|
|
||||||
- improve error handling
|
|
||||||
- improve parsing and add tests to verify
|
|
||||||
- **microbitmatrix**
|
|
||||||
- add link to schema for microbit V2
|
|
||||||
- add smoke test for microbitmatrix with microbit-v2
|
|
||||||
- add support for brightness of led pixels
|
|
||||||
- harmonize v1 and v2 implementation
|
|
||||||
- move Size() to version agnostic part
|
|
||||||
- **mpu6050**
|
|
||||||
- add functions to configure clock, and scaling for accelerometer and gyroscope
|
|
||||||
- **net/http**
|
|
||||||
- add PostForm()
|
|
||||||
- **sx126x**
|
|
||||||
- add Reset() and needed pin
|
|
||||||
- move RadioController into separate file for clarity
|
|
||||||
- pre-define all errors to avoid heap allocations
|
|
||||||
- refactor to RadioController interface to more easily handle non-STM32WL boards and remove duplicated code
|
|
||||||
|
|
||||||
- **vl53l1x**
|
|
||||||
- Add getter for the effective SPAD count
|
|
||||||
- **wifinina**
|
|
||||||
- add support for http server (#480)
|
|
||||||
|
|
||||||
- **bugfixes**
|
|
||||||
- **lsm303agr**
|
|
||||||
- fix I2C address auto increment for multi data read
|
|
||||||
- **net**
|
|
||||||
- (#501) make IP.String() method return something sensible
|
|
||||||
- **mpu6050**
|
|
||||||
- return I2C error when configuring fails
|
|
||||||
- **sx126x**
|
|
||||||
- fix in SetBandwidth function
|
|
||||||
- actually set the frequency when calling SetFrequency()
|
|
||||||
- correct RX/TX pin mapping for TheThingsIndustries GNSE board
|
|
||||||
|
|
||||||
- **examples**
|
|
||||||
- **LoRaWAN**
|
|
||||||
- example with LoRaWAN AT command set implementation
|
|
||||||
- basic example
|
|
||||||
- update all remaining examples for refactored API
|
|
||||||
- **sx126x**
|
|
||||||
- fix bandwidth,tx power in lora//lora_continuous example
|
|
||||||
- **sx127x**
|
|
||||||
- rx/tx example
|
|
||||||
|
|
||||||
- **build**
|
|
||||||
- remove older format build tags
|
|
||||||
- update to actions/checkout@v3
|
|
||||||
- work around for CVE-2022-24765
|
|
||||||
|
|
||||||
0.23.0
|
0.23.0
|
||||||
---
|
---
|
||||||
- **new devices**
|
- **new devices**
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ func main() {
|
|||||||
|
|
||||||
## Currently supported devices
|
## Currently supported devices
|
||||||
|
|
||||||
The following 90 devices are supported.
|
The following 91 devices are supported.
|
||||||
|
|
||||||
| Device Name | Interface Type |
|
| Device Name | Interface Type |
|
||||||
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------|
|
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------|
|
||||||
@@ -63,6 +63,7 @@ The following 90 devices are supported.
|
|||||||
| [APA102 RGB LED](https://cdn-shop.adafruit.com/product-files/2343/APA102C.pdf) | SPI |
|
| [APA102 RGB LED](https://cdn-shop.adafruit.com/product-files/2343/APA102C.pdf) | SPI |
|
||||||
| [APDS9960 Digital proximity, ambient light, RGB and gesture sensor](https://cdn.sparkfun.com/assets/learn_tutorials/3/2/1/Avago-APDS-9960-datasheet.pdf) | I2C |
|
| [APDS9960 Digital proximity, ambient light, RGB and gesture sensor](https://cdn.sparkfun.com/assets/learn_tutorials/3/2/1/Avago-APDS-9960-datasheet.pdf) | I2C |
|
||||||
| [AT24CX 2-wire serial EEPROM](https://www.openimpulse.com/blog/wp-content/uploads/wpsc/downloadables/24C32-Datasheet.pdf) | I2C |
|
| [AT24CX 2-wire serial EEPROM](https://www.openimpulse.com/blog/wp-content/uploads/wpsc/downloadables/24C32-Datasheet.pdf) | I2C |
|
||||||
|
| [ATECCx08 cryptographic processor](https://datasheet.octopart.com/ATSAMA5D27-WLSOM1-Microchip-datasheet-149595509.pdf) | I2C |
|
||||||
| [AXP192 single Cell Li-Battery and Power System Management](https://github.com/m5stack/M5-Schematic/blob/master/Core/AXP192%20Datasheet_v1.1_en_draft_2211.pdf) | I2C |
|
| [AXP192 single Cell Li-Battery and Power System Management](https://github.com/m5stack/M5-Schematic/blob/master/Core/AXP192%20Datasheet_v1.1_en_draft_2211.pdf) | I2C |
|
||||||
| [BBC micro:bit LED matrix](https://github.com/bbcmicrobit/hardware/blob/master/SCH_BBC-Microbit_V1.3B.pdf) | GPIO |
|
| [BBC micro:bit LED matrix](https://github.com/bbcmicrobit/hardware/blob/master/SCH_BBC-Microbit_V1.3B.pdf) | GPIO |
|
||||||
| [BH1750 ambient light sensor](https://www.mouser.com/ds/2/348/bh1750fvi-e-186247.pdf) | I2C |
|
| [BH1750 ambient light sensor](https://www.mouser.com/ds/2/348/bh1750fvi-e-186247.pdf) | I2C |
|
||||||
@@ -146,7 +147,6 @@ The following 90 devices are supported.
|
|||||||
| [WS2812 RGB LED](https://cdn-shop.adafruit.com/datasheets/WS2812.pdf) | GPIO |
|
| [WS2812 RGB LED](https://cdn-shop.adafruit.com/datasheets/WS2812.pdf) | GPIO |
|
||||||
| [XPT2046 touch controller](http://grobotronics.com/images/datasheets/xpt2046-datasheet.pdf) | GPIO |
|
| [XPT2046 touch controller](http://grobotronics.com/images/datasheets/xpt2046-datasheet.pdf) | GPIO |
|
||||||
| [Semtech SX126x Lora](https://www.semtech.com/products/wireless-rf/lora-connect/sx1261) | SPI |
|
| [Semtech SX126x Lora](https://www.semtech.com/products/wireless-rf/lora-connect/sx1261) | SPI |
|
||||||
| [Semtech SX127x Lora](https://www.semtech.com/products/wireless-rf/lora-connect/sx1276) | SPI |
|
|
||||||
| [SSD1289 TFT color display](http://aitendo3.sakura.ne.jp/aitendo_data/product_img/lcd/tft2/M032C1289TP/3.2-SSD1289.pdf) | GPIO |
|
| [SSD1289 TFT color display](http://aitendo3.sakura.ne.jp/aitendo_data/product_img/lcd/tft2/M032C1289TP/3.2-SSD1289.pdf) | GPIO |
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|||||||
@@ -0,0 +1,258 @@
|
|||||||
|
// Package ateccx08 provides a driver for the ATECCx08 I2C cryptographic co-processor.
|
||||||
|
//
|
||||||
|
// Datasheet: https://datasheet.octopart.com/ATSAMA5D27-WLSOM1-Microchip-datasheet-149595509.pdf
|
||||||
|
package ateccx08 // import "tinygo.org/x/drivers/ateccx08"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"tinygo.org/x/drivers"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
maxCommandTime = (200 + 50) * time.Millisecond
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrWakeup = errors.New("error on wakeup")
|
||||||
|
ErrInvalidCRCCheck = errors.New("invalid CRC check")
|
||||||
|
ErrLockFailed = errors.New("locked failed")
|
||||||
|
)
|
||||||
|
|
||||||
|
type Device struct {
|
||||||
|
bus drivers.I2C
|
||||||
|
Address uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns ATECCx08 device for the provided I2C bus using default address.
|
||||||
|
func New(i2c drivers.I2C) *Device {
|
||||||
|
return &Device{
|
||||||
|
bus: i2c,
|
||||||
|
Address: Address,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure the ATECCx08 device.
|
||||||
|
func (d *Device) Configure() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connected returns whether ATECCx08 has been found.
|
||||||
|
func (d *Device) Connected() bool {
|
||||||
|
if err := d.Wakeup(); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
v, err := d.Version()
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return (v == ATECC508 || v == ATECC608)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wakeup the ATECC by trying to write something to address 0x00
|
||||||
|
func (d *Device) Wakeup() error {
|
||||||
|
d.bus.Tx(uint16(0x0), []byte{0x00}, nil)
|
||||||
|
time.Sleep(1500 * time.Microsecond)
|
||||||
|
d.bus.Tx(uint16(d.Address), []byte{0x00}, nil)
|
||||||
|
time.Sleep(maxCommandTime)
|
||||||
|
|
||||||
|
var status [4]byte
|
||||||
|
if err := d.readResponse(status[:]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if status[0] != StatusAfterWake {
|
||||||
|
return ErrWakeup
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sleep puts the ATECC to sleep.
|
||||||
|
func (d *Device) Sleep() {
|
||||||
|
d.bus.Tx(uint16(d.Address), []byte{0x01}, nil)
|
||||||
|
time.Sleep(time.Millisecond)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Idle puts the ATECC in idle mode.
|
||||||
|
func (d *Device) Idle() {
|
||||||
|
d.bus.Tx(uint16(d.Address), []byte{0x02}, nil)
|
||||||
|
time.Sleep(time.Millisecond)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ATECCVersion uint16
|
||||||
|
|
||||||
|
func (at ATECCVersion) String() string {
|
||||||
|
switch at {
|
||||||
|
case ATECC508:
|
||||||
|
return "ATECC508"
|
||||||
|
case ATECC608:
|
||||||
|
return "ATECC608"
|
||||||
|
case ATECCNone:
|
||||||
|
return "No ATECCx08"
|
||||||
|
default:
|
||||||
|
return "Unknown"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Version returns what version of ATECC is being used.
|
||||||
|
// Either ATECC508, ATECC608, or ATECCNone.
|
||||||
|
func (d *Device) Version() (ATECCVersion, error) {
|
||||||
|
var version [4]byte
|
||||||
|
d.Wakeup()
|
||||||
|
defer d.Idle()
|
||||||
|
|
||||||
|
d.sendCommand(cmdInfo, 0x00, 0, nil)
|
||||||
|
|
||||||
|
time.Sleep(maxCommandTime)
|
||||||
|
if err := d.readResponse(version[:]); err != nil {
|
||||||
|
return ATECCNone, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return ATECCVersion(uint16(version[2])<<8 | uint16(version[3])&0xf000), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Random returns an array of 32 byte-sized random numbers.
|
||||||
|
func (d *Device) Random() ([32]byte, error) {
|
||||||
|
var random [32]byte
|
||||||
|
d.Wakeup()
|
||||||
|
defer d.Idle()
|
||||||
|
|
||||||
|
d.sendCommand(cmdRandom, 0x00, 0, nil)
|
||||||
|
time.Sleep(23 * time.Millisecond)
|
||||||
|
|
||||||
|
err := d.readResponse(random[:])
|
||||||
|
return random, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read reads from the device memory.
|
||||||
|
func (d *Device) Read(zone, address int, data []byte) error {
|
||||||
|
d.Wakeup()
|
||||||
|
defer d.Idle()
|
||||||
|
|
||||||
|
d.sendCommand(cmdRead, byte(zone), uint16(address), nil)
|
||||||
|
time.Sleep(5 * time.Millisecond)
|
||||||
|
|
||||||
|
return d.readResponse(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsLocked checks to see if the ATECC is locked.
|
||||||
|
// Config zone (0) must be locked to generate random numbers.
|
||||||
|
func (d *Device) IsLocked() bool {
|
||||||
|
return d.IsZoneLocked(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsZoneLocked checks to see if a specific zone in the ATECC is locked.
|
||||||
|
func (d *Device) IsZoneLocked(zone int) bool {
|
||||||
|
var config [4]byte
|
||||||
|
|
||||||
|
if zone < 0 || zone > 8 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
switch zone {
|
||||||
|
case 0, 1:
|
||||||
|
if err := d.Read(0, 0x15, config[:]); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// LockConfig
|
||||||
|
loc := 3
|
||||||
|
|
||||||
|
// LockData
|
||||||
|
if zone == 1 {
|
||||||
|
loc = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
if config[loc] == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
if err := d.Read(0, 0x16, config[:]); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
slot := byte(zone<<2) | 2
|
||||||
|
|
||||||
|
if (config[0] & slot) == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lock locks a zone in the device.
|
||||||
|
// Note that you cannot unlock a device zone once locked,
|
||||||
|
// so make sure you know what you are doing!
|
||||||
|
func (d *Device) Lock(zone int) error {
|
||||||
|
var status [1]byte
|
||||||
|
d.Wakeup()
|
||||||
|
defer d.Idle()
|
||||||
|
|
||||||
|
d.sendCommand(cmdLock, byte(zone)|0x80, 0, nil)
|
||||||
|
time.Sleep(32 * time.Millisecond)
|
||||||
|
|
||||||
|
d.readResponse(status[:])
|
||||||
|
|
||||||
|
if status[0] != 0 {
|
||||||
|
return ErrLockFailed
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var cmdBuf [64]byte
|
||||||
|
|
||||||
|
func (d *Device) sendCommand(opcode, param1 byte, param2 uint16, data []byte) error {
|
||||||
|
cmdBuf[0] = 0x03
|
||||||
|
cmdBuf[1] = byte(8 + len(data) - 1)
|
||||||
|
cmdBuf[2] = opcode
|
||||||
|
cmdBuf[3] = param1
|
||||||
|
cmdBuf[4] = byte(param2 & 0xff)
|
||||||
|
cmdBuf[5] = byte(param2 >> 8)
|
||||||
|
copy(cmdBuf[6:], data)
|
||||||
|
|
||||||
|
crc := crc16(cmdBuf[1 : 6+len(data)])
|
||||||
|
cmdBuf[6+len(data)] = crc[0]
|
||||||
|
cmdBuf[6+len(data)+1] = crc[1]
|
||||||
|
|
||||||
|
if err := d.bus.Tx(uint16(d.Address), cmdBuf[:6+len(data)+2], nil); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(time.Millisecond)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Device) readResponse(data []byte) error {
|
||||||
|
var sz [1]byte
|
||||||
|
if err := d.bus.Tx(uint16(d.Address), []byte{cmdAddress}, sz[:]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
rx := make([]byte, sz[0])
|
||||||
|
if err := d.bus.Tx(uint16(d.Address), []byte{cmdAddress}, rx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
size := len(rx) - 2
|
||||||
|
payload := rx[:size]
|
||||||
|
payloaddata := rx[1:size]
|
||||||
|
payloadcrc := rx[size:]
|
||||||
|
|
||||||
|
crcCheck := crc16(payload)
|
||||||
|
if !(crcCheck[0] == payloadcrc[0] &&
|
||||||
|
crcCheck[1] == payloadcrc[1]) {
|
||||||
|
return ErrInvalidCRCCheck
|
||||||
|
}
|
||||||
|
|
||||||
|
copy(data, payloaddata)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
// from https://github.com/usbarmory/armoryctl/blob/master/atecc608/atecc608.go#L104
|
||||||
|
// thank you!
|
||||||
|
package ateccx08
|
||||||
|
|
||||||
|
const (
|
||||||
|
CRC16Poly uint16 = 0x8005
|
||||||
|
)
|
||||||
|
|
||||||
|
func crc16(data []byte) []byte {
|
||||||
|
var crc uint16
|
||||||
|
|
||||||
|
for i := 0; i < len(data); i++ {
|
||||||
|
for shift := uint8(0x01); shift > 0x00; shift <<= 1 {
|
||||||
|
// data and crc bits
|
||||||
|
var d uint8
|
||||||
|
var c uint8
|
||||||
|
|
||||||
|
if uint8(data[i])&uint8(shift) != 0 {
|
||||||
|
d = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
c = uint8(crc >> 15)
|
||||||
|
crc <<= 1
|
||||||
|
|
||||||
|
if d != c {
|
||||||
|
crc ^= CRC16Poly
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return []byte{byte(crc & 0xff), byte(crc >> 8)}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package ateccx08
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Address is default I2C address.
|
||||||
|
Address = 0x60
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ATECCNone = 0
|
||||||
|
ATECC508 = 0x5000
|
||||||
|
ATECC608 = 0x6000
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
cmdAddress = 0x03
|
||||||
|
cmdCounter = 0x24
|
||||||
|
cmdGenKey = 0x40
|
||||||
|
cmdInfo = 0x30
|
||||||
|
cmdLock = 0x17
|
||||||
|
cmdNonce = 0x16
|
||||||
|
cmdRandom = 0x1B
|
||||||
|
cmdSHA = 0x47
|
||||||
|
cmdSign = 0x41
|
||||||
|
cmdWrite = 0x12
|
||||||
|
cmdRead = 0x02
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
StatusSuccess = 0x00
|
||||||
|
StatusMiscompare = 0x01
|
||||||
|
StatusParseError = 0x03
|
||||||
|
StatusECCFault = 0x05
|
||||||
|
StatusSelfTestError = 0x07
|
||||||
|
StatusHealthTestError = 0x08
|
||||||
|
StatusExecutionError = 0x0f
|
||||||
|
StatusAfterWake = 0x11
|
||||||
|
StatusWatchdogExpire = 0xee
|
||||||
|
StatusCRCError = 0xff
|
||||||
|
)
|
||||||
@@ -6,7 +6,6 @@
|
|||||||
package bmp180 // import "tinygo.org/x/drivers/bmp180"
|
package bmp180 // import "tinygo.org/x/drivers/bmp180"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"tinygo.org/x/drivers"
|
"tinygo.org/x/drivers"
|
||||||
@@ -124,21 +123,6 @@ func (d *Device) ReadPressure() (pressure int32, err error) {
|
|||||||
return 1000 * (p + ((x1 + x2 + 3791) >> 4)), nil
|
return 1000 * (p + ((x1 + x2 + 3791) >> 4)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadAltitude returns the current altitude in meters based on the
|
|
||||||
// current barometric pressure and estimated pressure at sea level.
|
|
||||||
// Calculation is based on code from Adafruit BME280 library
|
|
||||||
//
|
|
||||||
// https://github.com/adafruit/Adafruit_BME280_Library
|
|
||||||
func (d *Device) ReadAltitude() (int32, error) {
|
|
||||||
mPa, err := d.ReadPressure()
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
atmP := float32(mPa) / 100000
|
|
||||||
|
|
||||||
return int32(44330.0 * (1.0 - math.Pow(float64(atmP/SEALEVEL_PRESSURE), 0.1903))), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// rawTemp returns the sensor's raw values of the temperature
|
// rawTemp returns the sensor's raw values of the temperature
|
||||||
func (d *Device) rawTemp() (int32, error) {
|
func (d *Device) rawTemp() (int32, error) {
|
||||||
d.bus.WriteRegister(uint8(d.Address), REG_CTRL, []byte{CMD_TEMP})
|
d.bus.WriteRegister(uint8(d.Address), REG_CTRL, []byte{CMD_TEMP})
|
||||||
|
|||||||
@@ -28,7 +28,3 @@ const (
|
|||||||
// ULTRAHIGHRESOLUTION is the highest oversampling mode of the pressure measurement.
|
// ULTRAHIGHRESOLUTION is the highest oversampling mode of the pressure measurement.
|
||||||
ULTRAHIGHRESOLUTION
|
ULTRAHIGHRESOLUTION
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
SEALEVEL_PRESSURE float32 = 1013.25 // in hPa
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"machine"
|
||||||
|
|
||||||
|
"encoding/hex"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"tinygo.org/x/drivers/ateccx08"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
println("Looking for ATECCx08...")
|
||||||
|
|
||||||
|
machine.I2C0.Configure(machine.I2CConfig{})
|
||||||
|
|
||||||
|
atecc := ateccx08.New(machine.I2C0)
|
||||||
|
atecc.Configure()
|
||||||
|
|
||||||
|
if !atecc.Connected() {
|
||||||
|
for {
|
||||||
|
println("could not connect to ATECCx08")
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
version, _ := atecc.Version()
|
||||||
|
|
||||||
|
println(version.String(), "started")
|
||||||
|
|
||||||
|
if !atecc.IsLocked() {
|
||||||
|
for i := 10; i > 0; i-- {
|
||||||
|
println(version.String(), "is not locked. Locking in", i, "seconds...")
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
}
|
||||||
|
|
||||||
|
// locks the Configuration zone... PERMANENTLY!
|
||||||
|
atecc.Lock(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
println(version.String(), "locked.")
|
||||||
|
|
||||||
|
for {
|
||||||
|
data, err := atecc.Random()
|
||||||
|
if err != nil {
|
||||||
|
println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
println(hex.EncodeToString(data[:]))
|
||||||
|
time.Sleep(500 * time.Millisecond)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"machine"
|
||||||
|
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/hex"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"tinygo.org/x/drivers/ateccx08"
|
||||||
|
)
|
||||||
|
|
||||||
|
var atecc *ateccx08.Device
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
println("Looking for ATECCx08...")
|
||||||
|
|
||||||
|
machine.I2C0.Configure(machine.I2CConfig{})
|
||||||
|
|
||||||
|
atecc = ateccx08.New(machine.I2C0)
|
||||||
|
atecc.Configure()
|
||||||
|
|
||||||
|
if !atecc.Connected() {
|
||||||
|
for {
|
||||||
|
println("could not connect to ATECCx08")
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
version, _ := atecc.Version()
|
||||||
|
|
||||||
|
println(version.String(), "started")
|
||||||
|
|
||||||
|
if !atecc.IsLocked() {
|
||||||
|
for {
|
||||||
|
println(version.String(), "is not locked. Random numbers will not actually be random.")
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var result [13]byte
|
||||||
|
for {
|
||||||
|
rand.Read(result[:])
|
||||||
|
encodedString := hex.EncodeToString(result[:])
|
||||||
|
println(encodedString)
|
||||||
|
time.Sleep(500 * time.Millisecond)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
// connects the Go crypto/rand package to the random number generation
|
||||||
|
// on the ATECCx08 cryptographic processor.
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
errNoATECC = errors.New("no ATECCx08")
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
rand.Reader = &reader{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type reader struct{}
|
||||||
|
|
||||||
|
func (r *reader) Read(b []byte) (n int, err error) {
|
||||||
|
if len(b) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if atecc == nil {
|
||||||
|
return 0, errNoATECC
|
||||||
|
}
|
||||||
|
|
||||||
|
if !atecc.IsLocked() {
|
||||||
|
panic("ATECCx08 is not locked and cannot produce random numbers!")
|
||||||
|
}
|
||||||
|
|
||||||
|
rnds, err := atecc.Random()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < len(b); i += 32 {
|
||||||
|
if i+32 > len(b) {
|
||||||
|
copy(b[i:], rnds[:(len(b)-i)])
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
copy(b[i:], rnds[:])
|
||||||
|
rnds, err = atecc.Random()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return len(b), nil
|
||||||
|
}
|
||||||
@@ -27,9 +27,6 @@ func main() {
|
|||||||
pressure, _ := sensor.ReadPressure()
|
pressure, _ := sensor.ReadPressure()
|
||||||
println("Pressure", float32(pressure)/100000, "hPa")
|
println("Pressure", float32(pressure)/100000, "hPa")
|
||||||
|
|
||||||
altitude, _ := sensor.ReadAltitude()
|
|
||||||
println("Altitude", altitude, "meters")
|
|
||||||
|
|
||||||
time.Sleep(2 * time.Second)
|
time.Sleep(2 * time.Second)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,14 +39,3 @@ Builds/flashes atcmd console application on Lora-E5 using onboard SX126x.
|
|||||||
tinygo flash -target lorae5 ./examples/lora/lorawan/atcmd/
|
tinygo flash -target lorae5 ./examples/lora/lorawan/atcmd/
|
||||||
```
|
```
|
||||||
|
|
||||||
## Joining a Public Lorawan Network
|
|
||||||
|
|
||||||
```
|
|
||||||
AT+ID=DevEui,0101010101010101
|
|
||||||
AT+ID=AppEui,0123012301230213
|
|
||||||
AT+KEY=APPKEY,AEAEAEAEAEAEAEAAEAEAEAEAEAEAAEAE
|
|
||||||
AT+LW=NET,ON
|
|
||||||
AT+JOIN
|
|
||||||
```
|
|
||||||
|
|
||||||
AT+LW=NET,(ON|OFF) command changes Lora Sync Word to connect on public network(ON) or private networks(OFF)
|
|
||||||
|
|||||||
@@ -337,17 +337,6 @@ func delay(setting string) error {
|
|||||||
|
|
||||||
func lw(setting string) error {
|
func lw(setting string) error {
|
||||||
cmd := "LW"
|
cmd := "LW"
|
||||||
|
|
||||||
param, val, hasComma := strings.Cut(setting, ",")
|
|
||||||
if hasComma {
|
|
||||||
if param == "NET" {
|
|
||||||
if val == "ON" {
|
|
||||||
lorawan.SetPublicNetwork(true)
|
|
||||||
} else {
|
|
||||||
lorawan.SetPublicNetwork(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
writeCommandOutput(cmd, setting)
|
writeCommandOutput(cmd, setting)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import (
|
|||||||
"tinygo.org/x/drivers/examples/lora/lorawan/common"
|
"tinygo.org/x/drivers/examples/lora/lorawan/common"
|
||||||
"tinygo.org/x/drivers/lora"
|
"tinygo.org/x/drivers/lora"
|
||||||
"tinygo.org/x/drivers/lora/lorawan"
|
"tinygo.org/x/drivers/lora/lorawan"
|
||||||
"tinygo.org/x/drivers/lora/lorawan/region"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// change these to test a different UART or pins if available
|
// change these to test a different UART or pins if available
|
||||||
@@ -45,8 +44,6 @@ func main() {
|
|||||||
otaa = &lorawan.Otaa{}
|
otaa = &lorawan.Otaa{}
|
||||||
lorawan.UseRadio(radio)
|
lorawan.UseRadio(radio)
|
||||||
|
|
||||||
lorawan.UseRegionSettings(region.EU868())
|
|
||||||
|
|
||||||
for {
|
for {
|
||||||
if uart.Buffered() > 0 {
|
if uart.Buffered() > 0 {
|
||||||
data, _ := uart.ReadByte()
|
data, _ := uart.ReadByte()
|
||||||
|
|||||||
@@ -33,12 +33,3 @@ tinygo flash -target pybadge -tags featherwing ./examples/lora/lorawan/basic-dem
|
|||||||
tinygo flash -target lorae5 ./examples/lora/lorawan/basic-demo
|
tinygo flash -target lorae5 ./examples/lora/lorawan/basic-demo
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Enable debugging
|
|
||||||
|
|
||||||
You can also enable some debug logs with ldflags :
|
|
||||||
|
|
||||||
```
|
|
||||||
$ tinygo build -ldflags="-X 'main.debug=true'" -target=lorae5
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,16 +2,10 @@
|
|||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
|
||||||
"tinygo.org/x/drivers/lora/lorawan"
|
|
||||||
)
|
|
||||||
|
|
||||||
// These are sample keys, so the example builds
|
// These are sample keys, so the example builds
|
||||||
// Either change here, or create a new go file and use customkeys build tag
|
// Either change here, or create a new go file and use customkeys build tag
|
||||||
func setLorawanKeys() {
|
func setLorawanKeys() {
|
||||||
otaa.SetAppEUI([]uint8{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
|
otaa.SetAppEUI([]uint8{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
|
||||||
otaa.SetDevEUI([]uint8{0xB3, 0xD5, 0x41, 0x00, 0x0A, 0xF1, 0xA4, 0x45})
|
otaa.SetDevEUI([]uint8{0xB3, 0xD5, 0x41, 0x00, 0x0A, 0xF1, 0xA4, 0x45})
|
||||||
otaa.SetAppKey([]uint8{0x12, 0x22, 0xA3, 0xFF, 0x0C, 0x7B, 0x76, 0x7B, 0x8F, 0xD3, 0x12, 0x4F, 0xCE, 0x7A, 0x32, 0x16})
|
otaa.SetAppKey([]uint8{0x12, 0x22, 0xA3, 0xFF, 0x0C, 0x7B, 0x76, 0x7B, 0x8F, 0xD3, 0x12, 0x4F, 0xCE, 0x7A, 0x32, 0x16})
|
||||||
lorawan.SetPublicNetwork(true)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,11 +9,8 @@ import (
|
|||||||
"tinygo.org/x/drivers/examples/lora/lorawan/common"
|
"tinygo.org/x/drivers/examples/lora/lorawan/common"
|
||||||
"tinygo.org/x/drivers/lora"
|
"tinygo.org/x/drivers/lora"
|
||||||
"tinygo.org/x/drivers/lora/lorawan"
|
"tinygo.org/x/drivers/lora/lorawan"
|
||||||
"tinygo.org/x/drivers/lora/lorawan/region"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var debug string
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
LORAWAN_JOIN_TIMEOUT_SEC = 180
|
LORAWAN_JOIN_TIMEOUT_SEC = 180
|
||||||
LORAWAN_RECONNECT_DELAY_SEC = 15
|
LORAWAN_RECONNECT_DELAY_SEC = 15
|
||||||
@@ -65,32 +62,33 @@ func main() {
|
|||||||
session = &lorawan.Session{}
|
session = &lorawan.Session{}
|
||||||
otaa = &lorawan.Otaa{}
|
otaa = &lorawan.Otaa{}
|
||||||
|
|
||||||
|
// Initial Lora modulation configuration
|
||||||
|
loraConf := lora.Config{
|
||||||
|
Freq: 868100000,
|
||||||
|
Bw: lora.Bandwidth_125_0,
|
||||||
|
Sf: lora.SpreadingFactor9,
|
||||||
|
Cr: lora.CodingRate4_7,
|
||||||
|
HeaderType: lora.HeaderExplicit,
|
||||||
|
Preamble: 12,
|
||||||
|
Ldr: lora.LowDataRateOptimizeOff,
|
||||||
|
Iq: lora.IQStandard,
|
||||||
|
Crc: lora.CRCOn,
|
||||||
|
SyncWord: lora.SyncPublic,
|
||||||
|
LoraTxPowerDBm: 20,
|
||||||
|
}
|
||||||
|
radio.LoraConfig(loraConf)
|
||||||
|
|
||||||
// Connect the lorawan with the Lora Radio device.
|
// Connect the lorawan with the Lora Radio device.
|
||||||
lorawan.UseRadio(radio)
|
lorawan.UseRadio(radio)
|
||||||
|
|
||||||
lorawan.UseRegionSettings(region.EU868())
|
// Configure AppEUI, DevEUI, APPKey
|
||||||
|
|
||||||
// Configure AppEUI, DevEUI, APPKey, and public/private Lorawan Network
|
|
||||||
setLorawanKeys()
|
setLorawanKeys()
|
||||||
|
|
||||||
if debug != "" {
|
|
||||||
println("main: Network joined")
|
|
||||||
println("main: DevEui, " + otaa.GetDevEUI())
|
|
||||||
println("main: AppEui, " + otaa.GetAppEUI())
|
|
||||||
println("main: DevAddr, " + otaa.GetAppKey())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to connect Lorawan network
|
// Try to connect Lorawan network
|
||||||
if err := loraConnect(); err != nil {
|
if err := loraConnect(); err != nil {
|
||||||
failMessage(err)
|
failMessage(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if debug != "" {
|
|
||||||
println("main: NetID, " + otaa.GetNetID())
|
|
||||||
println("main: NwkSKey, " + session.GetNwkSKey())
|
|
||||||
println("main: AppSKey, " + session.GetAppSKey())
|
|
||||||
println("main: Done")
|
|
||||||
}
|
|
||||||
// Try to periodicaly send an uplink sample message
|
// Try to periodicaly send an uplink sample message
|
||||||
upCount := 1
|
upCount := 1
|
||||||
for {
|
for {
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
//go:build featherwing
|
|
||||||
|
|
||||||
package common
|
|
||||||
|
|
||||||
import "machine"
|
|
||||||
|
|
||||||
var (
|
|
||||||
// We assume LoRa Featherwing module with sx127x is connected to PyBadge
|
|
||||||
rstPin = machine.D11
|
|
||||||
csPin = machine.D10
|
|
||||||
dio0Pin = machine.D6
|
|
||||||
dio1Pin = machine.D9
|
|
||||||
spi = machine.SPI0
|
|
||||||
)
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
//go:build lgt92
|
|
||||||
|
|
||||||
package common
|
|
||||||
|
|
||||||
import "machine"
|
|
||||||
|
|
||||||
var (
|
|
||||||
rstPin = machine.PB0
|
|
||||||
csPin = machine.PA15
|
|
||||||
dio0Pin = machine.PC13
|
|
||||||
dio1Pin = machine.PB10
|
|
||||||
spi = machine.SPI0
|
|
||||||
)
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
//go:build !featherwing && !lgt92 && !stm32wlx && !sx126x
|
//go:build !featherwing && !stm32wlx && !sx126x
|
||||||
|
|
||||||
package common
|
package common
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,22 @@ func SetupLora() (lora.Radio, error) {
|
|||||||
return nil, errRadioNotFound
|
return nil, errRadioNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loraConf := lora.Config{
|
||||||
|
Freq: FREQ,
|
||||||
|
Bw: lora.Bandwidth_500_0,
|
||||||
|
Sf: lora.SpreadingFactor9,
|
||||||
|
Cr: lora.CodingRate4_7,
|
||||||
|
HeaderType: lora.HeaderExplicit,
|
||||||
|
Preamble: 12,
|
||||||
|
Ldr: lora.LowDataRateOptimizeOff,
|
||||||
|
Iq: lora.IQStandard,
|
||||||
|
Crc: lora.CRCOn,
|
||||||
|
SyncWord: lora.SyncPrivate,
|
||||||
|
LoraTxPowerDBm: 20,
|
||||||
|
}
|
||||||
|
|
||||||
|
loraRadio.LoraConfig(loraConf)
|
||||||
|
|
||||||
return loraRadio, nil
|
return loraRadio, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,22 @@ func SetupLora() (lora.Radio, error) {
|
|||||||
return nil, errRadioNotFound
|
return nil, errRadioNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loraConf := lora.Config{
|
||||||
|
Freq: FREQ,
|
||||||
|
Bw: lora.Bandwidth_500_0,
|
||||||
|
Sf: lora.SpreadingFactor9,
|
||||||
|
Cr: lora.CodingRate4_7,
|
||||||
|
HeaderType: lora.HeaderExplicit,
|
||||||
|
Preamble: 12,
|
||||||
|
Ldr: lora.LowDataRateOptimizeOff,
|
||||||
|
Iq: lora.IQStandard,
|
||||||
|
Crc: lora.CRCOn,
|
||||||
|
SyncWord: lora.SyncPrivate,
|
||||||
|
LoraTxPowerDBm: 20,
|
||||||
|
}
|
||||||
|
|
||||||
|
loraRadio.LoraConfig(loraConf)
|
||||||
|
|
||||||
return loraRadio, nil
|
return loraRadio, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//go:build featherwing || lgt92
|
//go:build featherwing
|
||||||
|
|
||||||
package common
|
package common
|
||||||
|
|
||||||
@@ -18,25 +18,63 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
// We assume LoRa Featherwing module is connected to PyBadge:
|
||||||
|
rstPin = machine.D11
|
||||||
|
csPin = machine.D10
|
||||||
|
dio0Pin = machine.D6
|
||||||
|
dio1Pin = machine.D9
|
||||||
|
spi = machine.SPI0
|
||||||
loraRadio *sx127x.Device
|
loraRadio *sx127x.Device
|
||||||
)
|
)
|
||||||
|
|
||||||
// do sx127x setup here
|
// do sx127x setup here
|
||||||
func SetupLora() (lora.Radio, error) {
|
func SetupLora() (lora.Radio, error) {
|
||||||
rstPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
rstPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||||
|
csPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||||
|
dio0Pin.Configure(machine.PinConfig{Mode: machine.PinInputPullup})
|
||||||
|
dio1Pin.Configure(machine.PinConfig{Mode: machine.PinInputPullup})
|
||||||
spi.Configure(machine.SPIConfig{Frequency: 500000, Mode: 0})
|
spi.Configure(machine.SPIConfig{Frequency: 500000, Mode: 0})
|
||||||
|
|
||||||
loraRadio = sx127x.New(spi, rstPin)
|
loraRadio = sx127x.New(spi, csPin, rstPin)
|
||||||
loraRadio.SetRadioController(sx127x.NewRadioControl(csPin, dio0Pin, dio1Pin))
|
|
||||||
loraRadio.Reset()
|
loraRadio.Reset()
|
||||||
|
|
||||||
if state := loraRadio.DetectDevice(); !state {
|
if state := loraRadio.DetectDevice(); !state {
|
||||||
return nil, errRadioNotFound
|
return nil, errRadioNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Setup DIO0 interrupt Handling
|
||||||
|
if err := dio0Pin.SetInterrupt(machine.PinRising, dioIrqHandler); err != nil {
|
||||||
|
println("could not configure DIO0 pin interrupt:", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup DIO1 interrupt Handling
|
||||||
|
if err := dio1Pin.SetInterrupt(machine.PinRising, dioIrqHandler); err != nil {
|
||||||
|
println("could not configure DIO1 pin interrupt:", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare for Lora Operation
|
||||||
|
loraConf := lora.Config{
|
||||||
|
Freq: FREQ,
|
||||||
|
Bw: lora.Bandwidth_125_0,
|
||||||
|
Sf: lora.SpreadingFactor9,
|
||||||
|
Cr: lora.CodingRate4_7,
|
||||||
|
HeaderType: lora.HeaderExplicit,
|
||||||
|
Preamble: 12,
|
||||||
|
Iq: lora.IQStandard,
|
||||||
|
Crc: lora.CRCOn,
|
||||||
|
SyncWord: lora.SyncPublic,
|
||||||
|
LoraTxPowerDBm: 20,
|
||||||
|
}
|
||||||
|
|
||||||
|
loraRadio.LoraConfig(loraConf)
|
||||||
|
|
||||||
return loraRadio, nil
|
return loraRadio, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func dioIrqHandler(machine.Pin) {
|
||||||
|
loraRadio.HandleInterrupt()
|
||||||
|
}
|
||||||
|
|
||||||
func FirmwareVersion() string {
|
func FirmwareVersion() string {
|
||||||
v := loraRadio.GetVersion()
|
v := loraRadio.GetVersion()
|
||||||
return "sx127x v" + strconv.Itoa(int(v))
|
return "sx127x v" + strconv.Itoa(int(v))
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ func main() {
|
|||||||
|
|
||||||
// Prepare for Lora operation
|
// Prepare for Lora operation
|
||||||
loraConf := lora.Config{
|
loraConf := lora.Config{
|
||||||
Freq: lora.MHz_868_1,
|
Freq: FREQ,
|
||||||
Bw: lora.Bandwidth_125_0,
|
Bw: lora.Bandwidth_500_0,
|
||||||
Sf: lora.SpreadingFactor9,
|
Sf: lora.SpreadingFactor9,
|
||||||
Cr: lora.CodingRate4_7,
|
Cr: lora.CodingRate4_7,
|
||||||
HeaderType: lora.HeaderExplicit,
|
HeaderType: lora.HeaderExplicit,
|
||||||
@@ -45,7 +45,7 @@ func main() {
|
|||||||
Iq: lora.IQStandard,
|
Iq: lora.IQStandard,
|
||||||
Crc: lora.CRCOn,
|
Crc: lora.CRCOn,
|
||||||
SyncWord: lora.SyncPrivate,
|
SyncWord: lora.SyncPrivate,
|
||||||
LoraTxPowerDBm: 20,
|
LoraTxPowerDBm: 14,
|
||||||
}
|
}
|
||||||
loraRadio.LoraConfig(loraConf)
|
loraRadio.LoraConfig(loraConf)
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import (
|
|||||||
"tinygo.org/x/drivers/sx126x"
|
"tinygo.org/x/drivers/sx126x"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const FREQ = 868100000
|
||||||
|
|
||||||
const (
|
const (
|
||||||
LORA_DEFAULT_RXTIMEOUT_MS = 1000
|
LORA_DEFAULT_RXTIMEOUT_MS = 1000
|
||||||
LORA_DEFAULT_TXTIMEOUT_MS = 5000
|
LORA_DEFAULT_TXTIMEOUT_MS = 5000
|
||||||
@@ -42,8 +44,8 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
loraConf := lora.Config{
|
loraConf := lora.Config{
|
||||||
Freq: lora.MHz_868_1,
|
Freq: FREQ,
|
||||||
Bw: lora.Bandwidth_125_0,
|
Bw: lora.Bandwidth_500_0,
|
||||||
Sf: lora.SpreadingFactor9,
|
Sf: lora.SpreadingFactor9,
|
||||||
Cr: lora.CodingRate4_7,
|
Cr: lora.CodingRate4_7,
|
||||||
HeaderType: lora.HeaderExplicit,
|
HeaderType: lora.HeaderExplicit,
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import (
|
|||||||
"tinygo.org/x/drivers/sx127x"
|
"tinygo.org/x/drivers/sx127x"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const FREQ = 868100000
|
||||||
|
|
||||||
const (
|
const (
|
||||||
LORA_DEFAULT_RXTIMEOUT_MS = 1000
|
LORA_DEFAULT_RXTIMEOUT_MS = 1000
|
||||||
LORA_DEFAULT_TXTIMEOUT_MS = 5000
|
LORA_DEFAULT_TXTIMEOUT_MS = 5000
|
||||||
@@ -38,13 +40,13 @@ func main() {
|
|||||||
println("# ----------------------")
|
println("# ----------------------")
|
||||||
machine.LED.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
machine.LED.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||||
SX127X_PIN_RST.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
SX127X_PIN_RST.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||||
|
SX127X_PIN_CS.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||||
|
SX127X_PIN_DIO0.Configure(machine.PinConfig{Mode: machine.PinInputPullup})
|
||||||
|
SX127X_PIN_DIO1.Configure(machine.PinConfig{Mode: machine.PinInputPullup})
|
||||||
SX127X_SPI.Configure(machine.SPIConfig{Frequency: 500000, Mode: 0})
|
SX127X_SPI.Configure(machine.SPIConfig{Frequency: 500000, Mode: 0})
|
||||||
|
|
||||||
println("main: create and start SX127x driver")
|
println("main: create and start SX127x driver")
|
||||||
loraRadio = sx127x.New(SX127X_SPI, SX127X_PIN_RST)
|
loraRadio = sx127x.New(SX127X_SPI, SX127X_PIN_CS, SX127X_PIN_RST)
|
||||||
loraRadio.SetRadioController(sx127x.NewRadioControl(SX127X_PIN_CS, SX127X_PIN_DIO0, SX127X_PIN_DIO1))
|
|
||||||
|
|
||||||
loraRadio.Reset()
|
loraRadio.Reset()
|
||||||
state := loraRadio.DetectDevice()
|
state := loraRadio.DetectDevice()
|
||||||
if !state {
|
if !state {
|
||||||
@@ -53,10 +55,20 @@ func main() {
|
|||||||
println("main: sx127x found")
|
println("main: sx127x found")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Setup DIO0 interrupt Handling
|
||||||
|
if err := SX127X_PIN_DIO0.SetInterrupt(machine.PinRising, dioIrqHandler); err != nil {
|
||||||
|
println("could not configure DIO0 pin interrupt:", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup DIO1 interrupt Handling
|
||||||
|
if err := SX127X_PIN_DIO1.SetInterrupt(machine.PinRising, dioIrqHandler); err != nil {
|
||||||
|
println("could not configure DIO1 pin interrupt:", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
// Prepare for Lora Operation
|
// Prepare for Lora Operation
|
||||||
loraConf := lora.Config{
|
loraConf := lora.Config{
|
||||||
Freq: lora.MHz_868_1,
|
Freq: FREQ,
|
||||||
Bw: lora.Bandwidth_125_0,
|
Bw: lora.Bandwidth_500_0,
|
||||||
Sf: lora.SpreadingFactor9,
|
Sf: lora.SpreadingFactor9,
|
||||||
Cr: lora.CodingRate4_7,
|
Cr: lora.CodingRate4_7,
|
||||||
HeaderType: lora.HeaderExplicit,
|
HeaderType: lora.HeaderExplicit,
|
||||||
|
|||||||
@@ -76,10 +76,3 @@ const (
|
|||||||
SyncPublic = iota
|
SyncPublic = iota
|
||||||
SyncPrivate
|
SyncPrivate
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
MHz_868_1 = 868100000
|
|
||||||
MHz_868_5 = 868500000
|
|
||||||
MHz_916_8 = 916800000
|
|
||||||
MHz_923_3 = 923300000
|
|
||||||
)
|
|
||||||
|
|||||||
+11
-48
@@ -4,7 +4,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"tinygo.org/x/drivers/lora"
|
"tinygo.org/x/drivers/lora"
|
||||||
"tinygo.org/x/drivers/lora/lorawan/region"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -19,26 +18,18 @@ var (
|
|||||||
ErrInvalidNetIDLength = errors.New("invalid NetID length")
|
ErrInvalidNetIDLength = errors.New("invalid NetID length")
|
||||||
ErrInvalidNwkSKeyLength = errors.New("invalid NwkSKey length")
|
ErrInvalidNwkSKeyLength = errors.New("invalid NwkSKey length")
|
||||||
ErrInvalidAppSKeyLength = errors.New("invalid AppSKey length")
|
ErrInvalidAppSKeyLength = errors.New("invalid AppSKey length")
|
||||||
ErrUndefinedRegionSettings = errors.New("undefined Regionnal Settings ")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
LORA_TX_TIMEOUT = 2000
|
LORA_TX_TIMEOUT = 2000
|
||||||
LORA_RX_TIMEOUT = 10000
|
LORA_RX_TIMEOUT = 5000
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ActiveRadio lora.Radio
|
ActiveRadio lora.Radio
|
||||||
Retries = 15
|
Retries = 15
|
||||||
regionSettings region.RegionSettings
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// UseRegionSettings sets current Lorawan Regional parameters
|
|
||||||
func UseRegionSettings(rs region.RegionSettings) {
|
|
||||||
regionSettings = rs
|
|
||||||
}
|
|
||||||
|
|
||||||
// UseRadio attaches Lora radio driver to Lorawan
|
|
||||||
func UseRadio(r lora.Radio) {
|
func UseRadio(r lora.Radio) {
|
||||||
if ActiveRadio != nil {
|
if ActiveRadio != nil {
|
||||||
panic("lorawan.ActiveRadio is already set")
|
panic("lorawan.ActiveRadio is already set")
|
||||||
@@ -46,25 +37,6 @@ func UseRadio(r lora.Radio) {
|
|||||||
ActiveRadio = r
|
ActiveRadio = r
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetPublicNetwork defines Lora Sync Word according to network type (public/private)
|
|
||||||
func SetPublicNetwork(enabled bool) {
|
|
||||||
ActiveRadio.SetPublicNetwork(enabled)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ApplyChannelConfig sets current Lora modulation according to current regional settings
|
|
||||||
func applyChannelConfig(ch *region.Channel) {
|
|
||||||
ActiveRadio.SetFrequency(ch.Frequency)
|
|
||||||
ActiveRadio.SetBandwidth(ch.Bandwidth)
|
|
||||||
ActiveRadio.SetCodingRate(ch.CodingRate)
|
|
||||||
ActiveRadio.SetSpreadingFactor(ch.SpreadingFactor)
|
|
||||||
ActiveRadio.SetPreambleLength(ch.PreambleLength)
|
|
||||||
ActiveRadio.SetTxPower(ch.TxPowerDBm)
|
|
||||||
// Lorawan defaults to explicit headers
|
|
||||||
ActiveRadio.SetHeaderType(lora.HeaderExplicit)
|
|
||||||
ActiveRadio.SetCrc(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Join tries to connect Lorawan Gateway
|
|
||||||
func Join(otaa *Otaa, session *Session) error {
|
func Join(otaa *Otaa, session *Session) error {
|
||||||
var resp []uint8
|
var resp []uint8
|
||||||
|
|
||||||
@@ -72,10 +44,6 @@ func Join(otaa *Otaa, session *Session) error {
|
|||||||
return ErrNoRadioAttached
|
return ErrNoRadioAttached
|
||||||
}
|
}
|
||||||
|
|
||||||
if regionSettings == nil {
|
|
||||||
return ErrUndefinedRegionSettings
|
|
||||||
}
|
|
||||||
|
|
||||||
otaa.Init()
|
otaa.Init()
|
||||||
|
|
||||||
// Send join packet
|
// Send join packet
|
||||||
@@ -84,22 +52,24 @@ func Join(otaa *Otaa, session *Session) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare radio for Join Tx
|
ActiveRadio.SetCrc(true)
|
||||||
applyChannelConfig(regionSettings.JoinRequestChannel())
|
ActiveRadio.SetIqMode(0) // IQ Standard
|
||||||
ActiveRadio.SetIqMode(lora.IQStandard)
|
|
||||||
ActiveRadio.Tx(payload, LORA_TX_TIMEOUT)
|
ActiveRadio.Tx(payload, LORA_TX_TIMEOUT)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for JoinAccept
|
// Wait for JoinAccept
|
||||||
applyChannelConfig(regionSettings.JoinAcceptChannel())
|
ActiveRadio.SetIqMode(1) // IQ Inverted
|
||||||
ActiveRadio.SetIqMode(lora.IQInverted)
|
for i := 0; i < Retries; i++ {
|
||||||
resp, err = ActiveRadio.Rx(LORA_RX_TIMEOUT)
|
resp, err = ActiveRadio.Rx(LORA_RX_TIMEOUT)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if resp != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
if resp == nil {
|
if resp == nil {
|
||||||
return ErrNoJoinAcceptReceived
|
return ErrNoJoinAcceptReceived
|
||||||
}
|
}
|
||||||
@@ -112,20 +82,13 @@ func Join(otaa *Otaa, session *Session) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendUplink sends Lorawan Uplink message
|
|
||||||
func SendUplink(data []uint8, session *Session) error {
|
func SendUplink(data []uint8, session *Session) error {
|
||||||
|
|
||||||
if regionSettings == nil {
|
|
||||||
return ErrUndefinedRegionSettings
|
|
||||||
}
|
|
||||||
|
|
||||||
payload, err := session.GenMessage(0, []byte(data))
|
payload, err := session.GenMessage(0, []byte(data))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
ActiveRadio.SetCrc(true)
|
||||||
applyChannelConfig(regionSettings.UplinkChannel())
|
ActiveRadio.SetIqMode(0) // IQ Standard
|
||||||
ActiveRadio.SetIqMode(lora.IQStandard)
|
|
||||||
ActiveRadio.Tx(payload, LORA_TX_TIMEOUT)
|
ActiveRadio.Tx(payload, LORA_TX_TIMEOUT)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ type Otaa struct {
|
|||||||
// Initialize DevNonce
|
// Initialize DevNonce
|
||||||
func (o *Otaa) Init() {
|
func (o *Otaa) Init() {
|
||||||
o.buf = make([]uint8, 0)
|
o.buf = make([]uint8, 0)
|
||||||
|
|
||||||
o.generateDevNonce()
|
o.generateDevNonce()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,49 +0,0 @@
|
|||||||
package region
|
|
||||||
|
|
||||||
import "tinygo.org/x/drivers/lora"
|
|
||||||
|
|
||||||
const (
|
|
||||||
AU915_DEFAULT_PREAMBLE_LEN = 8
|
|
||||||
AU915_DEFAULT_TX_POWER_DBM = 20
|
|
||||||
)
|
|
||||||
|
|
||||||
type RegionSettingsAU915 struct {
|
|
||||||
joinRequestChannel *Channel
|
|
||||||
joinAcceptChannel *Channel
|
|
||||||
uplinkChannel *Channel
|
|
||||||
}
|
|
||||||
|
|
||||||
func AU915() *RegionSettingsAU915 {
|
|
||||||
return &RegionSettingsAU915{
|
|
||||||
joinRequestChannel: &Channel{lora.MHz_916_8,
|
|
||||||
lora.Bandwidth_125_0,
|
|
||||||
lora.SpreadingFactor9,
|
|
||||||
lora.CodingRate4_5,
|
|
||||||
AU915_DEFAULT_PREAMBLE_LEN,
|
|
||||||
AU915_DEFAULT_TX_POWER_DBM},
|
|
||||||
joinAcceptChannel: &Channel{lora.MHz_923_3,
|
|
||||||
lora.Bandwidth_500_0,
|
|
||||||
lora.SpreadingFactor9,
|
|
||||||
lora.CodingRate4_5,
|
|
||||||
AU915_DEFAULT_PREAMBLE_LEN,
|
|
||||||
AU915_DEFAULT_TX_POWER_DBM},
|
|
||||||
uplinkChannel: &Channel{lora.MHz_916_8,
|
|
||||||
lora.Bandwidth_125_0,
|
|
||||||
lora.SpreadingFactor9,
|
|
||||||
lora.CodingRate4_5,
|
|
||||||
AU915_DEFAULT_PREAMBLE_LEN,
|
|
||||||
AU915_DEFAULT_TX_POWER_DBM},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *RegionSettingsAU915) JoinRequestChannel() *Channel {
|
|
||||||
return r.joinRequestChannel
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *RegionSettingsAU915) JoinAcceptChannel() *Channel {
|
|
||||||
return r.joinAcceptChannel
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *RegionSettingsAU915) UplinkChannel() *Channel {
|
|
||||||
return r.uplinkChannel
|
|
||||||
}
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
package region
|
|
||||||
|
|
||||||
import "tinygo.org/x/drivers/lora"
|
|
||||||
|
|
||||||
const (
|
|
||||||
EU868_DEFAULT_PREAMBLE_LEN = 8
|
|
||||||
EU868_DEFAULT_TX_POWER_DBM = 20
|
|
||||||
)
|
|
||||||
|
|
||||||
type RegionSettingsEU868 struct {
|
|
||||||
joinRequestChannel *Channel
|
|
||||||
joinAcceptChannel *Channel
|
|
||||||
uplinkChannel *Channel
|
|
||||||
}
|
|
||||||
|
|
||||||
func EU868() *RegionSettingsEU868 {
|
|
||||||
return &RegionSettingsEU868{
|
|
||||||
joinRequestChannel: &Channel{lora.MHz_868_1,
|
|
||||||
lora.Bandwidth_125_0,
|
|
||||||
lora.SpreadingFactor9,
|
|
||||||
lora.CodingRate4_7,
|
|
||||||
EU868_DEFAULT_PREAMBLE_LEN,
|
|
||||||
EU868_DEFAULT_TX_POWER_DBM},
|
|
||||||
joinAcceptChannel: &Channel{lora.MHz_868_1,
|
|
||||||
lora.Bandwidth_125_0,
|
|
||||||
lora.SpreadingFactor9,
|
|
||||||
lora.CodingRate4_7,
|
|
||||||
EU868_DEFAULT_PREAMBLE_LEN,
|
|
||||||
EU868_DEFAULT_TX_POWER_DBM},
|
|
||||||
uplinkChannel: &Channel{lora.MHz_868_1,
|
|
||||||
lora.Bandwidth_125_0,
|
|
||||||
lora.SpreadingFactor9,
|
|
||||||
lora.CodingRate4_7,
|
|
||||||
EU868_DEFAULT_PREAMBLE_LEN,
|
|
||||||
EU868_DEFAULT_TX_POWER_DBM},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *RegionSettingsEU868) JoinRequestChannel() *Channel {
|
|
||||||
return r.joinRequestChannel
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *RegionSettingsEU868) JoinAcceptChannel() *Channel {
|
|
||||||
return r.joinAcceptChannel
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *RegionSettingsEU868) UplinkChannel() *Channel {
|
|
||||||
return r.uplinkChannel
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
package region
|
|
||||||
|
|
||||||
type Channel struct {
|
|
||||||
Frequency uint32
|
|
||||||
Bandwidth uint8
|
|
||||||
SpreadingFactor uint8
|
|
||||||
CodingRate uint8
|
|
||||||
PreambleLength uint16
|
|
||||||
TxPowerDBm int8
|
|
||||||
}
|
|
||||||
|
|
||||||
type RegionSettings interface {
|
|
||||||
JoinRequestChannel() *Channel
|
|
||||||
JoinAcceptChannel() *Channel
|
|
||||||
UplinkChannel() *Channel
|
|
||||||
}
|
|
||||||
@@ -10,10 +10,5 @@ type Radio interface {
|
|||||||
SetBandwidth(bw uint8)
|
SetBandwidth(bw uint8)
|
||||||
SetCrc(enable bool)
|
SetCrc(enable bool)
|
||||||
SetSpreadingFactor(sf uint8)
|
SetSpreadingFactor(sf uint8)
|
||||||
SetPreambleLength(plen uint16)
|
|
||||||
SetTxPower(txpow int8)
|
|
||||||
SetSyncWord(syncWord uint16)
|
|
||||||
SetPublicNetwork(enable bool)
|
|
||||||
SetHeaderType(headerType uint8)
|
|
||||||
LoraConfig(cnf Config)
|
LoraConfig(cnf Config)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-16
@@ -32,7 +32,7 @@ func (d Device) Connected() bool {
|
|||||||
|
|
||||||
// Configure sets up the device for communication.
|
// Configure sets up the device for communication.
|
||||||
func (d Device) Configure() error {
|
func (d Device) Configure() error {
|
||||||
return d.SetClockSource(CLOCK_INTERNAL)
|
return d.bus.WriteRegister(uint8(d.Address), PWR_MGMT_1, []uint8{0})
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadAcceleration reads the current acceleration from the device and returns
|
// ReadAcceleration reads the current acceleration from the device and returns
|
||||||
@@ -78,18 +78,3 @@ func (d Device) ReadRotation() (x int32, y int32, z int32) {
|
|||||||
z = int32(int16((uint16(data[4])<<8)|uint16(data[5]))) * 15625 / 2048 * 1000
|
z = int32(int16((uint16(data[4])<<8)|uint16(data[5]))) * 15625 / 2048 * 1000
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetClockSource allows the user to configure the clock source.
|
|
||||||
func (d Device) SetClockSource(source uint8) error {
|
|
||||||
return d.bus.WriteRegister(uint8(d.Address), PWR_MGMT_1, []uint8{source})
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetFullScaleGyroRange allows the user to configure the scale range for the gyroscope.
|
|
||||||
func (d Device) SetFullScaleGyroRange(rng uint8) error {
|
|
||||||
return d.bus.WriteRegister(uint8(d.Address), GYRO_CONFIG, []uint8{rng})
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetFullScaleAccelRange allows the user to configure the scale range for the accelerometer.
|
|
||||||
func (d Device) SetFullScaleAccelRange(rng uint8) error {
|
|
||||||
return d.bus.WriteRegister(uint8(d.Address), ACCEL_CONFIG, []uint8{rng})
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -98,29 +98,6 @@ const (
|
|||||||
I2C_PER3_DO = 0x66
|
I2C_PER3_DO = 0x66
|
||||||
I2C_MST_DELAY_CT = 0x67
|
I2C_MST_DELAY_CT = 0x67
|
||||||
|
|
||||||
// Clock settings
|
|
||||||
CLOCK_INTERNAL = 0x00
|
|
||||||
CLOCK_PLL_XGYRO = 0x01
|
|
||||||
CLOCK_PLL_YGYRO = 0x02
|
|
||||||
CLOCK_PLL_ZGYRO = 0x03
|
|
||||||
CLOCK_PLL_EXTERNAL_32_768_KZ = 0x04
|
|
||||||
CLOCK_PLL_EXTERNAL_19_2_MHZ = 0x05
|
|
||||||
CLOCK_RESERVED = 0x06
|
|
||||||
CLOCK_STOP = 0x07
|
|
||||||
|
|
||||||
// Accelerometer settings
|
|
||||||
AFS_RANGE_2G = 0x00
|
|
||||||
AFS_RANGE_4G = 0x01
|
|
||||||
AFS_RANGE_8G = 0x02
|
|
||||||
AFS_RANGE_16G = 0x03
|
|
||||||
|
|
||||||
// Gyroscope settings
|
|
||||||
FS_RANGE_250 = 0x00
|
|
||||||
FS_RANGE_500 = 0x01
|
|
||||||
FS_RANGE_1000 = 0x02
|
|
||||||
FS_RANGE_2000 = 0x03
|
|
||||||
|
|
||||||
// other registers
|
|
||||||
SIGNAL_PATH_RES = 0x68 // Signal path reset
|
SIGNAL_PATH_RES = 0x68 // Signal path reset
|
||||||
USER_CTRL = 0x6A // User control
|
USER_CTRL = 0x6A // User control
|
||||||
PWR_MGMT_1 = 0x6B // Power Management 1
|
PWR_MGMT_1 = 0x6B // Power Management 1
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
# SX126x LoRa Radio
|
|
||||||
|
|
||||||
The Semtech SX126x family of sub-Ghz radio transceivers come in a number of different formats.
|
|
||||||
|
|
||||||
SX126x radios have a wide continuous frequency coverage from 150 MHz to 960 MHz.
|
|
||||||
|
|
||||||
SX1261 can transmit up to +15 dBm and the SX1262 can transmit up to +22 dBm
|
|
||||||
|
|
||||||
Some development boards are specific to a particular frequency range, so for example you need a different variation of that board for EU868 vs. for AU915.
|
|
||||||
|
|
||||||
## LAMBDA62 RF module
|
|
||||||
|
|
||||||
Cost effective radio module featuring the Semtech SX1262.
|
|
||||||
|
|
||||||
## STM32 STM32WLE5JC
|
|
||||||
|
|
||||||
ST Micro STM32WLE5/E4xx is 32-bit ARM Cortex M4 processor with Semtech SX126x processor on a single die.
|
|
||||||
|
|
||||||
https://www.st.com/en/microcontrollers-microprocessors/stm32wle5jc.html
|
|
||||||
|
|
||||||
Several boards have been made using this processor.
|
|
||||||
|
|
||||||
### Wio-E5 mini
|
|
||||||
|
|
||||||
https://www.seeedstudio.com/LoRa-E5-mini-STM32WLE5JC-p-4869.html
|
|
||||||
|
|
||||||
Wio-E5 mini is a compacted-sized dev board suitable for the rapid testing and building of small-size LoRa device and application prototyping. Wio-E5 mini is embedded with and leads out full GPIOs of Wio-E5 STM32WLE5JC
|
|
||||||
+2
-21
@@ -545,7 +545,7 @@ func (d *Device) SetCodingRate(cr uint8) {
|
|||||||
// SetBandwidth() sets current Lora Bandwidth
|
// SetBandwidth() sets current Lora Bandwidth
|
||||||
// NB: Change will be applied at next RX / TX
|
// NB: Change will be applied at next RX / TX
|
||||||
func (d *Device) SetBandwidth(bw uint8) {
|
func (d *Device) SetBandwidth(bw uint8) {
|
||||||
d.loraConf.Bw = bw
|
d.loraConf.Cr = bw
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetCrc() sets current CRC mode (ON/OFF)
|
// SetCrc() sets current CRC mode (ON/OFF)
|
||||||
@@ -558,30 +558,12 @@ func (d *Device) SetCrc(enable bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetSpreadingFactor sets current Lora Spreading Factor
|
// SetSpreadingFactor setc surrent Lora Spreading Factor
|
||||||
// NB: Change will be applied at next RX / TX
|
// NB: Change will be applied at next RX / TX
|
||||||
func (d *Device) SetSpreadingFactor(sf uint8) {
|
func (d *Device) SetSpreadingFactor(sf uint8) {
|
||||||
d.loraConf.Sf = sf
|
d.loraConf.Sf = sf
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetPreambleLength sets current Lora Preamble Length
|
|
||||||
// NB: Change will be applied at next RX / TX
|
|
||||||
func (d *Device) SetPreambleLength(pl uint16) {
|
|
||||||
d.loraConf.Preamble = pl
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetTxPowerDbm sets current Lora TX Power in DBm
|
|
||||||
// NB: Change will be applied at next RX / TX
|
|
||||||
func (d *Device) SetTxPower(txpow int8) {
|
|
||||||
d.loraConf.LoraTxPowerDBm = txpow
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetHeaderType sets implicit or explicit header mode
|
|
||||||
// NB: Change will be applied at next RX / TX
|
|
||||||
func (d *Device) SetHeaderType(headerType uint8) {
|
|
||||||
d.loraConf.HeaderType = headerType
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Lora functions
|
// Lora functions
|
||||||
//
|
//
|
||||||
@@ -658,7 +640,6 @@ func (d *Device) Rx(timeoutMs uint32) ([]uint8, error) {
|
|||||||
irqVal := uint16(SX126X_IRQ_RX_DONE | SX126X_IRQ_TIMEOUT | SX126X_IRQ_CRC_ERR)
|
irqVal := uint16(SX126X_IRQ_RX_DONE | SX126X_IRQ_TIMEOUT | SX126X_IRQ_CRC_ERR)
|
||||||
d.SetStandby()
|
d.SetStandby()
|
||||||
d.SetBufferBaseAddress(0, 0)
|
d.SetBufferBaseAddress(0, 0)
|
||||||
d.SetRfFrequency(d.loraConf.Freq)
|
|
||||||
d.SetModulationParams(d.loraConf.Sf, bandwidth(d.loraConf.Bw), d.loraConf.Cr, d.loraConf.Ldr)
|
d.SetModulationParams(d.loraConf.Sf, bandwidth(d.loraConf.Bw), d.loraConf.Cr, d.loraConf.Ldr)
|
||||||
d.SetPacketParam(d.loraConf.Preamble, d.loraConf.HeaderType, d.loraConf.Crc, 0xFF, d.loraConf.Iq)
|
d.SetPacketParam(d.loraConf.Preamble, d.loraConf.HeaderType, d.loraConf.Crc, 0xFF, d.loraConf.Iq)
|
||||||
d.SetDioIrqParams(irqVal, irqVal, SX126X_IRQ_NONE, SX126X_IRQ_NONE)
|
d.SetDioIrqParams(irqVal, irqVal, SX126X_IRQ_NONE, SX126X_IRQ_NONE)
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
# SX127x LoRa Radio
|
|
||||||
|
|
||||||
This processor comes in several different packages.
|
|
||||||
|
|
||||||
## Adafruit LoRa Radio Featherwing
|
|
||||||
|
|
||||||
https://www.adafruit.com/product/3231
|
|
||||||
|
|
||||||
This is the LoRa 9x @ 900 MHz radio version, which can be used for either 868MHz or 915MHz transmission/reception - the exact radio frequency is determined when you load the software since it can be tuned around dynamically. They can easily go 2 Km line of sight using simple wire antennas, or up to 20Km with directional antennas and settings tweaks.
|
|
||||||
|
|
||||||
### Connecting
|
|
||||||
|
|
||||||
To use the LoRa Featherwing with a Pybadge/Gobadge, you need to connect some pads on the board itself. Solder some jumper wires as follows:
|
|
||||||
|
|
||||||
RST -> A
|
|
||||||
CS -> B
|
|
||||||
DIO1 -> C
|
|
||||||
IRQ -> D
|
|
||||||
|
|
||||||
You also need to connect an antenna. The easiest is to cut a small piece of wire to the correct length based on the desired frequency:
|
|
||||||
|
|
||||||
EU868 Mhz - 34.54 cm
|
|
||||||
|
|
||||||
You can also use a fancier solution such as a uFL SMA connector with matching antenna.
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
package sx127x
|
|
||||||
|
|
||||||
// SX127X radio transceiver has several pins that control NSS,
|
|
||||||
// and that are signalled when RX or TX operations are completed.
|
|
||||||
// This interface allows the creation of types that can control this
|
|
||||||
type RadioController interface {
|
|
||||||
Init() error
|
|
||||||
SetNss(state bool) error
|
|
||||||
SetupInterrupts(handler func()) error
|
|
||||||
}
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
package sx127x
|
|
||||||
|
|
||||||
import (
|
|
||||||
"machine"
|
|
||||||
)
|
|
||||||
|
|
||||||
// RadioControl for boards that are connected using normal pins.
|
|
||||||
type RadioControl struct {
|
|
||||||
nssPin, dio0Pin, dio1Pin machine.Pin
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewRadioControl(nssPin, dio0Pin, dio1Pin machine.Pin) *RadioControl {
|
|
||||||
return &RadioControl{
|
|
||||||
nssPin: nssPin,
|
|
||||||
dio0Pin: dio0Pin,
|
|
||||||
dio1Pin: dio1Pin,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetNss sets the NSS line aka chip select for SPI.
|
|
||||||
func (rc *RadioControl) SetNss(state bool) error {
|
|
||||||
rc.nssPin.Set(state)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Init() configures whatever needed for sx127x radio control
|
|
||||||
func (rc *RadioControl) Init() error {
|
|
||||||
rc.nssPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
|
||||||
rc.dio0Pin.Configure(machine.PinConfig{Mode: machine.PinInputPulldown})
|
|
||||||
rc.dio1Pin.Configure(machine.PinConfig{Mode: machine.PinInputPulldown})
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// add interrupt handlers for Radio IRQs for pins
|
|
||||||
func (rc *RadioControl) SetupInterrupts(handler func()) error {
|
|
||||||
irqHandler = handler
|
|
||||||
|
|
||||||
// Setup DIO0 interrupt Handling
|
|
||||||
if err := rc.dio0Pin.SetInterrupt(machine.PinRising, handleInterrupt); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup DIO1 interrupt Handling
|
|
||||||
if err := rc.dio1Pin.SetInterrupt(machine.PinRising, handleInterrupt); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var irqHandler func()
|
|
||||||
|
|
||||||
func handleInterrupt(machine.Pin) {
|
|
||||||
irqHandler()
|
|
||||||
}
|
|
||||||
+33
-67
@@ -21,10 +21,9 @@ const (
|
|||||||
// Device wraps an SPI connection to a SX127x device.
|
// Device wraps an SPI connection to a SX127x device.
|
||||||
type Device struct {
|
type Device struct {
|
||||||
spi drivers.SPI // SPI bus for module communication
|
spi drivers.SPI // SPI bus for module communication
|
||||||
rstPin machine.Pin // GPIO for reset
|
rstPin, csPin machine.Pin // GPIOs for reset and chip select
|
||||||
radioEventChan chan lora.RadioEvent // Channel for Receiving events
|
radioEventChan chan lora.RadioEvent // Channel for Receiving events
|
||||||
loraConf lora.Config // Current Lora configuration
|
loraConf lora.Config // Current Lora configuration
|
||||||
controller RadioController // to manage interactions with the radio
|
|
||||||
deepSleep bool // Internal Sleep state
|
deepSleep bool // Internal Sleep state
|
||||||
deviceType int // sx1261,sx1262,sx1268 (defaults sx1261)
|
deviceType int // sx1261,sx1262,sx1268 (defaults sx1261)
|
||||||
spiBuffer [SPI_BUFFER_SIZE]uint8
|
spiBuffer [SPI_BUFFER_SIZE]uint8
|
||||||
@@ -42,26 +41,16 @@ func (d *Device) GetRadioEventChan() chan lora.RadioEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new SX127x connection. The SPI bus must already be configured.
|
// New creates a new SX127x connection. The SPI bus must already be configured.
|
||||||
func New(spi machine.SPI, rstPin machine.Pin) *Device {
|
func New(spi machine.SPI, csPin machine.Pin, rstPin machine.Pin) *Device {
|
||||||
k := Device{
|
k := Device{
|
||||||
spi: spi,
|
spi: spi,
|
||||||
|
csPin: csPin,
|
||||||
rstPin: rstPin,
|
rstPin: rstPin,
|
||||||
radioEventChan: make(chan lora.RadioEvent, 10),
|
radioEventChan: make(chan lora.RadioEvent, 10),
|
||||||
}
|
}
|
||||||
return &k
|
return &k
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetRadioControl let you define the RadioController
|
|
||||||
func (d *Device) SetRadioController(rc RadioController) error {
|
|
||||||
d.controller = rc
|
|
||||||
if err := d.controller.Init(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
d.controller.SetupInterrupts(d.HandleInterrupt)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset re-initialize the sx127x device
|
// Reset re-initialize the sx127x device
|
||||||
func (d *Device) Reset() {
|
func (d *Device) Reset() {
|
||||||
d.rstPin.Low()
|
d.rstPin.Low()
|
||||||
@@ -78,21 +67,21 @@ func (d *Device) DetectDevice() bool {
|
|||||||
|
|
||||||
// ReadRegister reads register value
|
// ReadRegister reads register value
|
||||||
func (d *Device) ReadRegister(reg uint8) uint8 {
|
func (d *Device) ReadRegister(reg uint8) uint8 {
|
||||||
d.controller.SetNss(false)
|
d.csPin.Low()
|
||||||
d.spi.Tx([]byte{reg & 0x7f}, nil)
|
d.spi.Tx([]byte{reg & 0x7f}, nil)
|
||||||
var value [1]byte
|
var value [1]byte
|
||||||
d.spi.Tx(nil, value[:])
|
d.spi.Tx(nil, value[:])
|
||||||
d.controller.SetNss(true)
|
d.csPin.High()
|
||||||
return value[0]
|
return value[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteRegister writes value to register
|
// WriteRegister writes value to register
|
||||||
func (d *Device) WriteRegister(reg uint8, value uint8) uint8 {
|
func (d *Device) WriteRegister(reg uint8, value uint8) uint8 {
|
||||||
var response [1]byte
|
var response [1]byte
|
||||||
d.controller.SetNss(false)
|
d.csPin.Low()
|
||||||
d.spi.Tx([]byte{reg | 0x80}, nil)
|
d.spi.Tx([]byte{reg | 0x80}, nil)
|
||||||
d.spi.Tx([]byte{value}, response[:])
|
d.spi.Tx([]byte{value}, response[:])
|
||||||
d.controller.SetNss(true)
|
d.csPin.High()
|
||||||
return response[0]
|
return response[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,8 +134,8 @@ func (d *Device) GetBandwidth() int32 {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// SetTxPowerWithPaBoost sets the transmitter output power and may activate paBoost
|
// SetTxPower sets the transmitter output power
|
||||||
func (d *Device) SetTxPowerWithPaBoost(txPower int8, paBoost bool) {
|
func (d *Device) SetTxPower(txPower int8, paBoost bool) {
|
||||||
if !paBoost {
|
if !paBoost {
|
||||||
// RFO
|
// RFO
|
||||||
if txPower < 0 {
|
if txPower < 0 {
|
||||||
@@ -271,8 +260,8 @@ func (d *Device) SetCodingRate(cr uint8) {
|
|||||||
d.WriteRegister(SX127X_REG_MODEM_CONFIG_1, (d.ReadRegister(SX127X_REG_MODEM_CONFIG_1)&0xf1)|(cr<<1))
|
d.WriteRegister(SX127X_REG_MODEM_CONFIG_1, (d.ReadRegister(SX127X_REG_MODEM_CONFIG_1)&0xf1)|(cr<<1))
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetHeaderType set implicit or explicit mode
|
// SetImplicitHeaderModeOn Enables implicit header mode ***
|
||||||
func (d *Device) SetHeaderType(headerType uint8) {
|
func (d *Device) SetHeaderMode(headerType uint8) {
|
||||||
d.loraConf.HeaderType = headerType
|
d.loraConf.HeaderType = headerType
|
||||||
if headerType == lora.HeaderImplicit {
|
if headerType == lora.HeaderImplicit {
|
||||||
d.WriteRegister(SX127X_REG_MODEM_CONFIG_1, d.ReadRegister(SX127X_REG_MODEM_CONFIG_1)|0x01)
|
d.WriteRegister(SX127X_REG_MODEM_CONFIG_1, d.ReadRegister(SX127X_REG_MODEM_CONFIG_1)|0x01)
|
||||||
@@ -295,10 +284,13 @@ func (d *Device) SetSpreadingFactor(sf uint8) {
|
|||||||
d.WriteRegister(SX127X_REG_MODEM_CONFIG_2, newValue)
|
d.WriteRegister(SX127X_REG_MODEM_CONFIG_2, newValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetTxPower sets the transmitter output (with paBoost ON)
|
// SetTxContinuousMode enable Continuous Tx mode
|
||||||
func (d *Device) SetTxPower(txPower int8) {
|
func (d *Device) SetTxContinuousMode(val bool) {
|
||||||
d.loraConf.LoraTxPowerDBm = txPower
|
if val {
|
||||||
d.SetTxPowerWithPaBoost(txPower, true)
|
d.WriteRegister(SX127X_REG_MODEM_CONFIG_2, d.ReadRegister(SX127X_REG_MODEM_CONFIG_2)|0x08)
|
||||||
|
} else {
|
||||||
|
d.WriteRegister(SX127X_REG_MODEM_CONFIG_2, d.ReadRegister(SX127X_REG_MODEM_CONFIG_2)&0xf7)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetCrc Enable CRC generation and check on payload
|
// SetCrc Enable CRC generation and check on payload
|
||||||
@@ -312,9 +304,8 @@ func (d *Device) SetCrc(enable bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetPreambleLength defines number of preamble
|
func (d *Device) SetPreamble(pLen uint16) {
|
||||||
func (d *Device) SetPreambleLength(pLen uint16) {
|
// Sets preamble length
|
||||||
d.loraConf.Preamble = pLen
|
|
||||||
d.WriteRegister(SX127X_REG_PREAMBLE_MSB, uint8((pLen>>8)&0xFF))
|
d.WriteRegister(SX127X_REG_PREAMBLE_MSB, uint8((pLen>>8)&0xFF))
|
||||||
d.WriteRegister(SX127X_REG_PREAMBLE_LSB, uint8(pLen&0xFF))
|
d.WriteRegister(SX127X_REG_PREAMBLE_LSB, uint8(pLen&0xFF))
|
||||||
}
|
}
|
||||||
@@ -340,15 +331,6 @@ func (d *Device) SetIqMode(val uint8) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetPublicNetwork changes Sync Word to match network type
|
|
||||||
func (d *Device) SetPublicNetwork(enabled bool) {
|
|
||||||
if enabled {
|
|
||||||
d.SetSyncWord(SX127X_LORA_MAC_PUBLIC_SYNCWORD)
|
|
||||||
} else {
|
|
||||||
d.SetSyncWord(SX127X_LORA_MAC_PRIVATE_SYNCWORD)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tx sends a lora packet, (with timeout)
|
// Tx sends a lora packet, (with timeout)
|
||||||
func (d *Device) Tx(pkt []uint8, timeoutMs uint32) error {
|
func (d *Device) Tx(pkt []uint8, timeoutMs uint32) error {
|
||||||
d.SetOpModeLora()
|
d.SetOpModeLora()
|
||||||
@@ -360,15 +342,15 @@ func (d *Device) Tx(pkt []uint8, timeoutMs uint32) error {
|
|||||||
d.WriteRegister(SX127X_REG_LNA, SX127X_LNA_MAX_GAIN) // Set Low Noise Amplifier to MAX
|
d.WriteRegister(SX127X_REG_LNA, SX127X_LNA_MAX_GAIN) // Set Low Noise Amplifier to MAX
|
||||||
|
|
||||||
d.SetFrequency(d.loraConf.Freq)
|
d.SetFrequency(d.loraConf.Freq)
|
||||||
d.SetPreambleLength(d.loraConf.Preamble)
|
d.SetPreamble(d.loraConf.Preamble)
|
||||||
d.SetSyncWord(d.loraConf.SyncWord)
|
d.SetSyncWord(d.loraConf.SyncWord)
|
||||||
d.SetBandwidth(d.loraConf.Bw)
|
d.SetBandwidth(d.loraConf.Bw)
|
||||||
d.SetSpreadingFactor(d.loraConf.Sf)
|
d.SetSpreadingFactor(d.loraConf.Sf)
|
||||||
d.SetIqMode(d.loraConf.Iq)
|
d.SetIqMode(d.loraConf.Iq)
|
||||||
d.SetCodingRate(d.loraConf.Cr)
|
d.SetCodingRate(d.loraConf.Cr)
|
||||||
d.SetCrc(d.loraConf.Crc == lora.CRCOn)
|
d.SetCrc(d.loraConf.Crc == lora.CRCOn)
|
||||||
d.SetTxPower(d.loraConf.LoraTxPowerDBm)
|
d.SetTxPower(d.loraConf.LoraTxPowerDBm, true)
|
||||||
d.SetHeaderType(d.loraConf.HeaderType)
|
d.SetHeaderMode(d.loraConf.HeaderType)
|
||||||
d.SetAgcAuto(SX127X_AGC_AUTO_ON)
|
d.SetAgcAuto(SX127X_AGC_AUTO_ON)
|
||||||
|
|
||||||
// set the IRQ mapping DIO0=TxDone DIO1=NOP DIO2=NOP
|
// set the IRQ mapping DIO0=TxDone DIO1=NOP DIO2=NOP
|
||||||
@@ -416,15 +398,15 @@ func (d *Device) Rx(timeoutMs uint32) ([]uint8, error) {
|
|||||||
d.WriteRegister(SX127X_REG_LNA, SX127X_LNA_MAX_GAIN) // Set Low Noise Amplifier to MAX
|
d.WriteRegister(SX127X_REG_LNA, SX127X_LNA_MAX_GAIN) // Set Low Noise Amplifier to MAX
|
||||||
|
|
||||||
d.SetFrequency(d.loraConf.Freq)
|
d.SetFrequency(d.loraConf.Freq)
|
||||||
d.SetPreambleLength(d.loraConf.Preamble)
|
d.SetPreamble(d.loraConf.Preamble)
|
||||||
d.SetSyncWord(d.loraConf.SyncWord)
|
d.SetSyncWord(d.loraConf.SyncWord)
|
||||||
d.SetBandwidth(d.loraConf.Bw)
|
d.SetBandwidth(d.loraConf.Bw)
|
||||||
d.SetSpreadingFactor(d.loraConf.Sf)
|
d.SetSpreadingFactor(d.loraConf.Sf)
|
||||||
d.SetIqMode(d.loraConf.Iq)
|
d.SetIqMode(d.loraConf.Iq)
|
||||||
d.SetCodingRate(d.loraConf.Cr)
|
d.SetCodingRate(d.loraConf.Cr)
|
||||||
d.SetCrc(d.loraConf.Crc == lora.CRCOn)
|
d.SetCrc(d.loraConf.Crc == lora.CRCOn)
|
||||||
d.SetTxPower(d.loraConf.LoraTxPowerDBm)
|
d.SetTxPower(d.loraConf.LoraTxPowerDBm, true)
|
||||||
d.SetHeaderType(d.loraConf.HeaderType)
|
d.SetHeaderMode(d.loraConf.HeaderType)
|
||||||
d.SetAgcAuto(SX127X_AGC_AUTO_ON)
|
d.SetAgcAuto(SX127X_AGC_AUTO_ON)
|
||||||
|
|
||||||
// set the IRQ mapping DIO0=RxDone DIO1=RxTimeout DIO2=NOP
|
// set the IRQ mapping DIO0=RxDone DIO1=RxTimeout DIO2=NOP
|
||||||
@@ -433,26 +415,19 @@ func (d *Device) Rx(timeoutMs uint32) ([]uint8, error) {
|
|||||||
d.WriteRegister(SX127X_REG_IRQ_FLAGS, 0xFF)
|
d.WriteRegister(SX127X_REG_IRQ_FLAGS, 0xFF)
|
||||||
// Mask all but RxDone
|
// Mask all but RxDone
|
||||||
d.WriteRegister(SX127X_REG_IRQ_FLAGS_MASK, ^(SX127X_IRQ_LORA_RXDONE_MASK | SX127X_IRQ_LORA_RXTOUT_MASK))
|
d.WriteRegister(SX127X_REG_IRQ_FLAGS_MASK, ^(SX127X_IRQ_LORA_RXDONE_MASK | SX127X_IRQ_LORA_RXTOUT_MASK))
|
||||||
|
// Switch to RX Mode
|
||||||
|
d.SetOpMode(SX127X_OPMODE_RX_SINGLE) //
|
||||||
|
// Wait for Radio Event
|
||||||
|
|
||||||
// Get Radio Event Channel
|
|
||||||
radioCh := d.GetRadioEventChan()
|
radioCh := d.GetRadioEventChan()
|
||||||
|
|
||||||
// Single RX mode don't properly handle Timeouts on sx127x, so we use Continuous RX
|
msg := <-radioCh
|
||||||
// Go routine is a workaround to stop the Continuous RX and fire a timeout Event
|
if msg.EventType == lora.RadioEventTimeout {
|
||||||
d.SetOpMode(SX127X_OPMODE_RX)
|
return nil, nil
|
||||||
|
} else if msg.EventType != lora.RadioEventRxDone {
|
||||||
var msg lora.RadioEvent
|
|
||||||
select {
|
|
||||||
case msg = <-radioCh:
|
|
||||||
if msg.EventType != lora.RadioEventRxDone {
|
|
||||||
return nil, errors.New("Unexpected Radio Event while RX " + string(0x30+msg.EventType))
|
return nil, errors.New("Unexpected Radio Event while RX " + string(0x30+msg.EventType))
|
||||||
}
|
}
|
||||||
case <-time.After(time.Millisecond * time.Duration(timeoutMs)):
|
|
||||||
d.SetOpMode(SX127X_OPMODE_STANDBY)
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the received payload
|
|
||||||
d.WriteRegister(SX127X_REG_FIFO_RX_BASE_ADDR, 0)
|
d.WriteRegister(SX127X_REG_FIFO_RX_BASE_ADDR, 0)
|
||||||
d.WriteRegister(SX127X_REG_FIFO_ADDR_PTR, 0)
|
d.WriteRegister(SX127X_REG_FIFO_ADDR_PTR, 0)
|
||||||
|
|
||||||
@@ -465,15 +440,6 @@ func (d *Device) Rx(timeoutMs uint32) ([]uint8, error) {
|
|||||||
return d.spiBuffer[:pLen], nil
|
return d.spiBuffer[:pLen], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetTxContinuousMode enable Continuous Tx mode
|
|
||||||
func (d *Device) SetTxContinuousMode(val bool) {
|
|
||||||
if val {
|
|
||||||
d.WriteRegister(SX127X_REG_MODEM_CONFIG_2, d.ReadRegister(SX127X_REG_MODEM_CONFIG_2)|0x08)
|
|
||||||
} else {
|
|
||||||
d.WriteRegister(SX127X_REG_MODEM_CONFIG_2, d.ReadRegister(SX127X_REG_MODEM_CONFIG_2)&0xf7)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// HELPER FUNCTIONS
|
// HELPER FUNCTIONS
|
||||||
//
|
//
|
||||||
|
|||||||
+1
-1
@@ -2,4 +2,4 @@ package drivers
|
|||||||
|
|
||||||
// Version returns a user-readable string showing the version of the drivers package for support purposes.
|
// Version returns a user-readable string showing the version of the drivers package for support purposes.
|
||||||
// Update this value before release of new version of software.
|
// Update this value before release of new version of software.
|
||||||
const Version = "0.24.0"
|
const Version = "0.23.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user