sx126x: Driver for Semtech sx126x radio modules and optional RF Switch.

This first version of the driver has been tested with STM32WL SoC,
	which embeddeds SX1262 radio on the same die.
This commit is contained in:
Olivier Fauchon
2021-03-21 01:13:13 +01:00
committed by Ron Evans
parent 43899e1330
commit b6c750ccd1
10 changed files with 1460 additions and 1 deletions
@@ -0,0 +1,80 @@
package main
// This example will periodically enable Continuous "Preamble" and "Wave" modes on 868.1 Mhz
import (
"machine"
"time"
rfswitch "tinygo.org/x/drivers/examples/sx126x/rfswitch"
"tinygo.org/x/drivers/sx126x"
)
const FREQ = 868100000
var (
loraRadio *sx126x.Device
)
func main() {
println("\n# TinyGo Lora continuous Wave/Preamble test")
println("# -----------------------------------------")
machine.LED.Configure(machine.PinConfig{Mode: machine.PinOutput})
// Create the driver
loraRadio = sx126x.New(machine.SPI3)
loraRadio.SetDeviceType(sx126x.DEVICE_TYPE_SX1262)
// Create RF Switch
var radioSwitch rfswitch.CustomSwitch
loraRadio.SetRfSwitch(radioSwitch)
state := loraRadio.DetectDevice()
if !state {
panic("sx126x not detected. ")
}
// Prepare for Lora operation
loraConf := sx126x.LoraConfig{
Freq: FREQ,
Bw: sx126x.SX126X_LORA_BW_500_0,
Sf: sx126x.SX126X_LORA_SF9,
Cr: sx126x.SX126X_LORA_CR_4_7,
HeaderType: sx126x.SX126X_LORA_HEADER_EXPLICIT,
Preamble: 12,
Ldr: sx126x.SX126X_LORA_LOW_DATA_RATE_OPTIMIZE_OFF,
Iq: sx126x.SX126X_LORA_IQ_STANDARD,
Crc: sx126x.SX126X_LORA_CRC_ON,
SyncWord: sx126x.SX126X_LORA_MAC_PRIVATE_SYNCWORD,
LoraTxPowerDBm: 14,
}
loraRadio.LoraConfig(loraConf)
// Although LoraConfig has already configured most of Lora settings,
// the following lines are still required to enable Continuous Preamble/Wave
loraRadio.SetPacketType(sx126x.SX126X_PACKET_TYPE_LORA)
loraRadio.SetRfFrequency(loraConf.Freq)
loraRadio.SetModulationParams(loraConf.Sf, loraConf.Bw, loraConf.Cr, loraConf.Ldr)
loraRadio.SetTxParams(loraConf.LoraTxPowerDBm, sx126x.SX126X_PA_RAMP_200U)
for {
println("2 seconds in Continuous Preamble")
loraRadio.SetStandby()
loraRadio.SetTxContinuousPreamble()
time.Sleep(2 * time.Second)
println("Continuous Preamble Stopped")
loraRadio.SetStandby()
time.Sleep(10 * time.Second)
println("2 seconds in Continuous Wave")
loraRadio.SetTxContinuousWave()
time.Sleep(2 * time.Second)
println(" Continuous Wave Stopped")
loraRadio.SetStandby()
time.Sleep(60 * time.Second)
}
}
+98
View File
@@ -0,0 +1,98 @@
package main
// In this example, a Lora packet will be sent every 10s
// module will be in RX mode between two transmissions
import (
"device/stm32"
"machine"
"runtime/interrupt"
"time"
rfswitch "tinygo.org/x/drivers/examples/sx126x/rfswitch"
"tinygo.org/x/drivers/sx126x"
)
const FREQ = 868100000
const (
LORA_DEFAULT_RXTIMEOUT_MS = 1000
LORA_DEFAULT_TXTIMEOUT_MS = 5000
)
var (
loraRadio *sx126x.Device
txmsg = []byte("Hello TinyGO")
)
// radioIntHandler will take care of radio interrupts
func radioIntHandler(intr interrupt.Interrupt) {
loraRadio.HandleInterrupt()
}
func main() {
println("\n# TinyGo Lora RX/TX test")
println("# ----------------------")
machine.LED.Configure(machine.PinConfig{Mode: machine.PinOutput})
// Create the driver
loraRadio = sx126x.New(machine.SPI3)
loraRadio.SetDeviceType(sx126x.DEVICE_TYPE_SX1262)
// Create RF Switch
var radioSwitch rfswitch.CustomSwitch
loraRadio.SetRfSwitch(radioSwitch)
// Detect the device
state := loraRadio.DetectDevice()
if !state {
panic("sx126x not detected.")
}
// Add interrupt handler for Radio IRQs
intr := interrupt.New(stm32.IRQ_Radio_IRQ_Busy, radioIntHandler)
intr.Enable()
loraConf := sx126x.LoraConfig{
Freq: FREQ,
Bw: sx126x.SX126X_LORA_BW_500_0,
Sf: sx126x.SX126X_LORA_SF9,
Cr: sx126x.SX126X_LORA_CR_4_7,
HeaderType: sx126x.SX126X_LORA_HEADER_EXPLICIT,
Preamble: 12,
Ldr: sx126x.SX126X_LORA_LOW_DATA_RATE_OPTIMIZE_OFF,
Iq: sx126x.SX126X_LORA_IQ_STANDARD,
Crc: sx126x.SX126X_LORA_CRC_ON,
SyncWord: sx126x.SX126X_LORA_MAC_PRIVATE_SYNCWORD,
LoraTxPowerDBm: 20,
}
loraRadio.LoraConfig(loraConf)
var count uint
for {
tStart := time.Now()
// Blocking RX for LORA_DEFAULT_RXTIMEOUT_MS
println("Start Lora RX for 10 sec")
for int(time.Now().Sub(tStart).Seconds()) < 10 {
buf, err := loraRadio.LoraRx(LORA_DEFAULT_RXTIMEOUT_MS)
if err != nil {
println("RX Error: ", err)
} else if buf != nil {
println("Packet Received: len=", len(buf), string(buf))
}
}
println("END Lora RX")
println("LORA TX size=", len(txmsg))
err := loraRadio.LoraTx(txmsg, LORA_DEFAULT_TXTIMEOUT_MS)
if err != nil {
println("TX Error:", err)
}
count++
}
}
+61
View File
@@ -0,0 +1,61 @@
//go:build gnse
// +build gnse
/*
Generic Node Sensor Edition
RFSwitch
Disable Switch : PB8=OFF PA0=OFF PA1=OFF
Enable RX : PB8=ON PA0=ON PA1=OFF
Enable TX RFO LP : PB8=ON PA0=ON PA1=ON
Enable TX RFO HP : PB8=ON PA0=OFF PA1=ON
*/
package rfswitch
import (
"machine"
"tinygo.org/x/drivers/sx126x"
)
type CustomSwitch struct {
}
var (
rfstate int
)
func (s CustomSwitch) InitRFSwitch() {
machine.RF_FE_CTRL1.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.RF_FE_CTRL2.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.RF_FE_CTRL3.Configure(machine.PinConfig{Mode: machine.PinOutput})
rfstate = -1 //Unknown
}
func (s CustomSwitch) SetRfSwitchMode(mode int) error {
if mode == rfstate {
return nil
}
switch mode {
case sx126x.RFSWITCH_TX_HP:
machine.RF_FE_CTRL1.Set(false)
machine.RF_FE_CTRL2.Set(true)
machine.RF_FE_CTRL3.Set(true)
case sx126x.RFSWITCH_TX_LP:
machine.RF_FE_CTRL1.Set(true)
machine.RF_FE_CTRL2.Set(true)
machine.RF_FE_CTRL3.Set(true)
case sx126x.RFSWITCH_RX:
machine.RF_FE_CTRL1.Set(true)
machine.RF_FE_CTRL2.Set(false)
machine.RF_FE_CTRL3.Set(true)
}
rfstate = mode
return nil
}
+43
View File
@@ -0,0 +1,43 @@
//go:build lorae5
// +build lorae5
package radio
/*
/!\ LoRa-E5 module ONLY transmits through RFO_HP:
Receive: PA4=1, PA5=0
Transmit(high output power, SMPS mode): PA4=0, PA5=1
*/
import (
"errors"
"machine"
"tinygo.org/x/drivers/sx126x"
)
type CustomSwitch struct {
}
func (s CustomSwitch) InitRFSwitch() {
machine.PA4.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.PB5.Configure(machine.PinConfig{Mode: machine.PinOutput})
}
func (s CustomSwitch) SetRfSwitchMode(mode int) error {
switch mode {
case sx126x.RFSWITCH_RX:
machine.PA4.Set(true)
machine.PB5.Set(false)
case sx126x.RFSWITCH_TX_LP:
errors.New("RFSWITCH_TX_LP not supported ")
case sx126x.RFSWITCH_TX_HP:
machine.PA4.Set(false)
machine.PB5.Set(true)
}
return nil
}
+55
View File
@@ -0,0 +1,55 @@
//go:build nucleowl55jc
// +build nucleowl55jc
/*
Nucleo WL55JC1
RFSwitch
+-----------+---------+------------+------------+
| | FE_CTRL1 | FE_CTRL2 | FE_CTRL3 |
| | (PC4) | (PC5) | (PC3) |
+-----------+----------+-----------+------------+
| TX_HP | LOW | HIGH | HIGH |
| TX_LP | HIGH | HIGH | HIGH |
| RX | HIGH | LOW | HIGH |
+-----------+----------+-----------+------------+
*/
package rfswitch
import (
"machine"
"tinygo.org/x/drivers/sx126x"
)
type CustomSwitch struct {
}
func (s CustomSwitch) InitRFSwitch() {
machine.PC4.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.PC5.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.PC3.Configure(machine.PinConfig{Mode: machine.PinOutput})
}
func (s CustomSwitch) SetRfSwitchMode(mode int) error {
switch mode {
case sx126x.RFSWITCH_TX_HP:
machine.PC4.Set(false)
machine.PC5.Set(true)
machine.PC3.Set(true)
case sx126x.RFSWITCH_TX_LP:
machine.PC4.Set(true)
machine.PC5.Set(true)
machine.PC3.Set(true)
case sx126x.RFSWITCH_RX:
machine.PC4.Set(true)
machine.PC5.Set(false)
machine.PC3.Set(true)
}
return nil
}