diff --git a/examples/lora/sx127x/pingpong.go b/examples/lora/sx127x/pingpong.go deleted file mode 100644 index 8e10a14..0000000 --- a/examples/lora/sx127x/pingpong.go +++ /dev/null @@ -1,127 +0,0 @@ -// Receives data with LoRa. -package main - -import ( - "fmt" - "machine" - "strconv" - "strings" - - "tinygo.org/x/drivers/lora/sx127x" -) - -var loraConfig = sx127x.Config{ - Frequency: 868100000, - SpreadingFactor: 12, - Bandwidth: 125000, - CodingRate: 6, - TxPower: 17, -} - -const ( - - // Serial console - UART_TX_PIN = machine.PA9 - UART_RX_PIN = machine.PA10 - - // RFM95 SPI Connection to Bluepill - SPI_SCK_PIN = machine.PA5 - SPI_SDO_PIN = machine.PA7 - SPI_SDI_PIN = machine.PA6 - SPI_CS_PIN = machine.PB8 - SPI_RST_PIN = machine.PB9 - - // DIO RFM95 Pin connection to BluePill - DIO0_PIN = machine.PA2 - DIO0_PIN_MODE = machine.PinInputPulldown - DIO0_PIN_CHANGE = machine.PinRising - - pollDelayMs int = 1000 -) - -// configureDioInt sets up the DIO0 interrupt handler -func configureDioInt(radio *sx127x.Device) { - // Set an interrupt on this pin. - err := DIO0_PIN.SetInterrupt(DIO0_PIN_CHANGE, func(machine.Pin) { - if DIO0_PIN.Get() { - radio.CheckIrq() - } - }) - if err != nil { - println("could not configure pin interrupt:", err.Error()) - } -} - -func main() { - // Configure serial console - machine.Serial.Configure(machine.UARTConfig{TX: UART_TX_PIN, RX: UART_RX_PIN, BaudRate: 115200}) - - println("LoRa PingPong Example") - - // Prepare GPIOS (SPI + DIO) - machine.LED.Configure(machine.PinConfig{Mode: machine.PinOutput}) - SPI_CS_PIN.Configure(machine.PinConfig{Mode: machine.PinOutput}) - SPI_RST_PIN.Configure(machine.PinConfig{Mode: machine.PinOutput}) - DIO0_PIN.Configure(machine.PinConfig{Mode: machine.PinOutput}) - - machine.LED.Set(true) - - // Enable SPI - machine.SPI0.Configure(machine.SPIConfig{ - SCK: SPI_SCK_PIN, - SDO: SPI_SDO_PIN, - SDI: SPI_SDI_PIN, - Frequency: 500000, - Mode: 0}) - - // Create and Reset Lora driver - loraRadio := sx127x.New(machine.SPI0, SPI_CS_PIN, SPI_RST_PIN) - loraRadio.Reset() - - // Setup DIO0 interrupt Handling - configureDioInt(&loraRadio) - - // Configure Lora settings (modulation, SF... etc ) - var err = loraRadio.SetupLora(loraConfig) - if err != nil { - fmt.Println(err) - return - } - - // ping counter is incremented after every retransmission - pingCount := 0 - - // Send first packet without using interrupts - println("*** Send a Lora PING ") - machine.LED.Set(false) - loraRadio.TxLora([]byte("PING " + strconv.Itoa(pingCount))) - machine.LED.Set(true) - - println("*** Switch to RX Mode ") - for { - loraRadio.RxLora() - // Wait for Radio event - in := <-loraRadio.GetRadioEventChan() - - // We have a packet - if in.EventType == sx127x.EventRxDone { - data := string(in.EventData) - println("RX: ", data) - - machine.LED.Set(false) - // If it's ping, reply pong - if strings.Contains(data, "PING") { - println("Received PING, Sending PONG") - loraRadio.TxLora([]byte("PONG #" + strconv.Itoa(pingCount))) - } else if strings.Contains(data, "PONG") { - println("Received PONG, Sending PING") - loraRadio.TxLora([]byte("PING #" + strconv.Itoa(pingCount))) - } - machine.LED.Set(true) - - pingCount++ - - } - - } -} diff --git a/examples/lora/sx127x/receiver.go b/examples/lora/sx127x/receiver.go deleted file mode 100644 index 2a3b7af..0000000 --- a/examples/lora/sx127x/receiver.go +++ /dev/null @@ -1,50 +0,0 @@ -// Receives data with LoRa. -package main - -import ( - "fmt" - "machine" - - "tinygo.org/x/drivers/lora/sx127x" -) - -var loraConfig = sx127x.Config{ - Frequency: 433998500, - SpreadingFactor: 7, - Bandwidth: 125000, - CodingRate: 6, - TxPower: 17, -} - -var packet [255]byte - -func main() { - println("LoRa Receiver Example") - - // SPI settings for Feather M0 LoRa board - csPin := machine.PB1 - csPin.Configure(machine.PinConfig{Mode: machine.PinOutput}) - rstPin := machine.PB2 - rstPin.Configure(machine.PinConfig{Mode: machine.PinOutput}) - dio0Pin := machine.PB3 - dio0Pin.Configure(machine.PinConfig{Mode: machine.PinOutput}) - - machine.SPI0.Configure(machine.SPIConfig{}) - loraRadio := sx127x.New(machine.SPI0, csPin, rstPin) - var err = loraRadio.SetupLora(loraConfig) - if err != nil { - fmt.Println(err) - return - } - - println("Receiving LoRa packets...") - - for { - packetSize := loraRadio.ParsePacket(0) - if packetSize > 0 { - println("Got packet, RSSI=", loraRadio.LastPacketRSSI()) - size := loraRadio.ReadPacket(packet[:]) - println(string(packet[:size])) - } - } -} diff --git a/examples/lora/sx127x/sender.go b/examples/lora/sx127x/sender.go deleted file mode 100644 index 47bf4d1..0000000 --- a/examples/lora/sx127x/sender.go +++ /dev/null @@ -1,88 +0,0 @@ -// Sends data with LoRa. -package main - -import ( - "fmt" - "machine" - "strconv" - "time" - - "tinygo.org/x/drivers/lora/sx127x" -) - -var loraConfig = sx127x.Config{ - Frequency: 868100000, - SpreadingFactor: 12, - Bandwidth: 125000, - CodingRate: 6, - TxPower: 17, -} - -const ( - SPI_SCK_PIN = machine.PA5 - SPI_SDO_PIN = machine.PA7 - SPI_SDI_PIN = machine.PA6 - - SPI_CS_PIN = machine.PB8 - SPI_RST_PIN = machine.PB9 - DIO0_PIN = machine.PA2 - - UART_TX_PIN = machine.PA9 - UART_RX_PIN = machine.PA10 -) - -func main() { - - // Configure serial console - machine.Serial.Configure(machine.UARTConfig{TX: UART_TX_PIN, RX: UART_RX_PIN, BaudRate: 115200}) - - println("LoRa Sender Example") - - // Prepare GPIOS (SPI + DIO) - machine.LED.Configure(machine.PinConfig{Mode: machine.PinOutput}) - SPI_CS_PIN.Configure(machine.PinConfig{Mode: machine.PinOutput}) - SPI_RST_PIN.Configure(machine.PinConfig{Mode: machine.PinOutput}) - DIO0_PIN.Configure(machine.PinConfig{Mode: machine.PinOutput}) - - // Enable SPI - machine.SPI0.Configure(machine.SPIConfig{ - SCK: SPI_SCK_PIN, - SDO: SPI_SDO_PIN, - SDI: SPI_SDI_PIN, - Frequency: 500000, - Mode: 0}) - - // Create and Reset Lora driver - loraRadio := sx127x.New(machine.SPI0, SPI_CS_PIN, SPI_RST_PIN) - loraRadio.Reset() - - // Check module identification - if loraRadio.GetVersion() != 0x12 { - println("SX1276 module not found") - for { - } - } else { - println("Module version 0x12") - } - - // Configure Lora settings (modulation, SF... etc ) - var err = loraRadio.SetupLora(loraConfig) - if err != nil { - fmt.Println(err) - return - } - - // Send a Lora packet every 5 sec - println("Sending LoRa packets every 5 seconds...") - for i := 0; ; i++ { - var packet = "TinyGo LoRa Sender: " + strconv.Itoa(i) - println("Sending:", packet) - - machine.LED.Low() - time.Sleep(time.Millisecond * 150) - machine.LED.High() - - loraRadio.TxLora([]byte(packet)) - time.Sleep(5000 * time.Millisecond) - } -} diff --git a/examples/sx126x/lora_continuous/lora_continuous.go b/examples/sx126x/lora_continuous/lora_continuous.go index 97db402..4000dac 100644 --- a/examples/sx126x/lora_continuous/lora_continuous.go +++ b/examples/sx126x/lora_continuous/lora_continuous.go @@ -7,6 +7,7 @@ import ( rfswitch "tinygo.org/x/drivers/examples/sx126x/rfswitch" + "tinygo.org/x/drivers/lora" "tinygo.org/x/drivers/sx126x" ) @@ -36,17 +37,17 @@ func main() { } // Prepare for Lora operation - loraConf := sx126x.LoraConfig{ + loraConf := lora.Config{ 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, + Bw: lora.Bandwidth_500_0, + Sf: lora.SpreadingFactor9, + Cr: lora.CodingRate4_7, + HeaderType: lora.HeaderExplicit, 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, + Ldr: lora.LowDataRateOptimizeOff, + Iq: lora.IQStandard, + Crc: lora.CRCOn, + SyncWord: lora.SyncPrivate, LoraTxPowerDBm: 14, } loraRadio.LoraConfig(loraConf) diff --git a/examples/sx126x/lora_rxtx/lora_rxtx.go b/examples/sx126x/lora_rxtx/lora_rxtx.go index 7c13b93..effb940 100644 --- a/examples/sx126x/lora_rxtx/lora_rxtx.go +++ b/examples/sx126x/lora_rxtx/lora_rxtx.go @@ -11,6 +11,7 @@ import ( rfswitch "tinygo.org/x/drivers/examples/sx126x/rfswitch" + "tinygo.org/x/drivers/lora" "tinygo.org/x/drivers/sx126x" ) @@ -54,17 +55,17 @@ func main() { intr := interrupt.New(stm32.IRQ_Radio_IRQ_Busy, radioIntHandler) intr.Enable() - loraConf := sx126x.LoraConfig{ + loraConf := lora.Config{ 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, + Bw: lora.Bandwidth_500_0, + Sf: lora.SpreadingFactor9, + Cr: lora.CodingRate4_7, + HeaderType: lora.HeaderExplicit, 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, + Ldr: lora.LowDataRateOptimizeOff, + Iq: lora.IQStandard, + Crc: lora.CRCOn, + SyncWord: lora.SyncPrivate, LoraTxPowerDBm: 20, } @@ -74,20 +75,17 @@ func main() { for { tStart := time.Now() - // Blocking RX for LORA_DEFAULT_RXTIMEOUT_MS - println("Start Lora RX for 10 sec") + println("main: Receiving Lora for 10 seconds") 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)) + println("main: End Lora RX") + println("LORA TX size=", len(txmsg), " -> ", string(txmsg)) err := loraRadio.LoraTx(txmsg, LORA_DEFAULT_TXTIMEOUT_MS) if err != nil { println("TX Error:", err) diff --git a/examples/sx127x/lora_rxtx/lora_rxtx.go b/examples/sx127x/lora_rxtx/lora_rxtx.go index f2aa6b2..fb5e087 100644 --- a/examples/sx127x/lora_rxtx/lora_rxtx.go +++ b/examples/sx127x/lora_rxtx/lora_rxtx.go @@ -7,18 +7,20 @@ import ( "machine" "time" + "tinygo.org/x/drivers/lora" "tinygo.org/x/drivers/sx127x" ) +const FREQ = 868100000 + const ( LORA_DEFAULT_RXTIMEOUT_MS = 1000 LORA_DEFAULT_TXTIMEOUT_MS = 5000 - - DIO_PIN_CHANGE = machine.PinRising ) var ( loraRadio *sx127x.Device + txmsg = []byte("Hello TinyGO") // We assume the module is connected this way: SX127X_PIN_RST = machine.PB9 @@ -26,29 +28,15 @@ var ( SX127X_PIN_DIO0 = machine.PA0 SX127X_PIN_DIO1 = machine.PA1 SX127X_SPI = machine.SPI0 - - txmsg = []byte("Hello TinyGO") - - // Prepare for Lora Operation - loraConf = sx127x.LoraConfig{ - Freq: 868100000, - Bw: sx127x.SX127X_LORA_BW_125_0, - Sf: sx127x.SX127X_LORA_SF9, - Cr: sx127x.SX127X_LORA_CR_4_7, - HeaderType: sx127x.SX127X_LORA_HEADER_EXPLICIT, - Preamble: 12, - Iq: sx127x.SX127X_LORA_IQ_STANDARD, - Crc: sx127x.SX127X_LORA_CRC_ON, - SyncWord: sx127x.SX127X_LORA_MAC_PUBLIC_SYNCWORD, - LoraTxPowerDBm: 20, - } ) -func main() { - println("\n# TinyGo Driver SX127X RX/TX example") - println("# ------------------------------------") +func dioIrqHandler(machine.Pin) { + loraRadio.HandleInterrupt() +} - println("main: configuring LED/SPI/DIO/IRQ") +func main() { + println("\n# TinyGo Lora RX/TX test") + println("# ----------------------") machine.LED.Configure(machine.PinConfig{Mode: machine.PinOutput}) SX127X_PIN_RST.Configure(machine.PinConfig{Mode: machine.PinOutput}) SX127X_PIN_CS.Configure(machine.PinConfig{Mode: machine.PinOutput}) @@ -67,36 +55,34 @@ func main() { } // Setup DIO0 interrupt Handling - err := SX127X_PIN_DIO0.SetInterrupt(DIO_PIN_CHANGE, func(machine.Pin) { - if SX127X_PIN_DIO0.Get() { - loraRadio.HandleInterrupt() - } - }) - if err != nil { + if err := SX127X_PIN_DIO0.SetInterrupt(machine.PinRising, dioIrqHandler); err != nil { println("could not configure DIO0 pin interrupt:", err.Error()) } // Setup DIO1 interrupt Handling - err = SX127X_PIN_DIO1.SetInterrupt(DIO_PIN_CHANGE, func(machine.Pin) { - if SX127X_PIN_DIO1.Get() { - loraRadio.HandleInterrupt() - } - }) - if err != nil { + if err := SX127X_PIN_DIO1.SetInterrupt(machine.PinRising, dioIrqHandler); err != nil { println("could not configure DIO1 pin interrupt:", err.Error()) } - println("main: Configure lora modulation") - loraRadio.LoraConfig(loraConf) + // Prepare for Lora Operation + loraConf := lora.Config{ + Freq: FREQ, + Bw: lora.Bandwidth_500_0, + Sf: lora.SpreadingFactor9, + Cr: lora.CodingRate4_7, + HeaderType: lora.HeaderExplicit, + Preamble: 12, + Iq: lora.IQStandard, + Crc: lora.CRCOn, + SyncWord: lora.SyncPrivate, + LoraTxPowerDBm: 20, + } - // Get uint32 from RSSI - rand32 := loraRadio.RandomU32() - println("main: Get random 32bit from RSSI:", rand32) + loraRadio.LoraConfig(loraConf) var count uint for { tStart := time.Now() - machine.LED.Set(!machine.LED.Get()) println("main: Receiving Lora for 10 seconds") for int(time.Now().Sub(tStart).Seconds()) < 10 { diff --git a/lora/config.go b/lora/config.go new file mode 100644 index 0000000..fa3fe9e --- /dev/null +++ b/lora/config.go @@ -0,0 +1,78 @@ +package lora + +import "errors" + +// Config holds the LoRa configuration parameters +type Config struct { + Freq uint32 // Frequency + Cr uint8 // Coding Rate + Sf uint8 // Spread Factor + Bw uint8 // Bandwidth + Ldr uint8 // Low Data Rate + Preamble uint16 // PreambleLength + SyncWord uint16 // Sync Word + HeaderType uint8 // Header : Implicit/explicit + Crc uint8 // CRC : Yes/No + Iq uint8 // iq : Standard/inverted + LoraTxPowerDBm int8 // Tx power in Dbm +} + +var ( + ErrUndefinedLoraConf = errors.New("Undefined Lora configuration") +) + +const ( + SpreadingFactor5 = 0x05 + SpreadingFactor6 = 0x06 + SpreadingFactor7 = 0x07 + SpreadingFactor8 = 0x08 + SpreadingFactor9 = 0x09 + SpreadingFactor10 = 0x0A + SpreadingFactor11 = 0x0B + SpreadingFactor12 = 0x0C +) + +const ( + CodingRate4_5 = 0x01 // 7 0 LoRa coding rate: 4/5 + CodingRate4_6 = 0x02 // 7 0 4/6 + CodingRate4_7 = 0x03 // 7 0 4/7 + CodingRate4_8 = 0x04 // 7 0 4/8 +) + +const ( + HeaderExplicit = 0x00 // 7 0 LoRa header mode: explicit + HeaderImplicit = 0x01 // 7 0 implicit +) + +const ( + LowDataRateOptimizeOff = 0x00 // 7 0 LoRa low data rate optimization: disabled + LowDataRateOptimizeOn = 0x01 // 7 0 enabled +) + +const ( + CRCOff = 0x00 // 7 0 LoRa CRC mode: disabled + CRCOn = 0x01 // 7 0 enabled +) + +const ( + IQStandard = 0x00 // 7 0 LoRa IQ setup: standard + IQInverted = 0x01 // 7 0 inverted +) + +const ( + Bandwidth_7_8 = iota // 7.8 kHz + Bandwidth_10_4 // 10.4 kHz + Bandwidth_15_6 // 15.6 kHz + Bandwidth_20_8 // 20.8 kHz + Bandwidth_31_25 // 31.25 kHz + Bandwidth_41_7 // 41.7 kHz + Bandwidth_62_5 // 62.5 kHz + Bandwidth_125_0 // 125.0 kHz + Bandwidth_250_0 // 250.0 kHz + Bandwidth_500_0 // 500.0 kHz +) + +const ( + SyncPublic = iota + SyncPrivate +) diff --git a/sx126x/registers.go b/sx126x/registers.go index 2aa450a..19b42e1 100644 --- a/sx126x/registers.go +++ b/sx126x/registers.go @@ -206,48 +206,42 @@ const ( SX126X_PA_RAMP_3400U = 0x07 // 7 0 3400 us //SX126X_CMD_SET_MODULATION_PARAMS - SX126X_GFSK_FILTER_NONE = 0x00 // 7 0 GFSK filter: none - SX126X_GFSK_FILTER_GAUSS_0_3 = 0x08 // 7 0 Gaussian, BT = 0.3 - SX126X_GFSK_FILTER_GAUSS_0_5 = 0x09 // 7 0 Gaussian, BT = 0.5 - SX126X_GFSK_FILTER_GAUSS_0_7 = 0x0A // 7 0 Gaussian, BT = 0.7 - SX126X_GFSK_FILTER_GAUSS_1 = 0x0B // 7 0 Gaussian, BT = 1 - SX126X_GFSK_RX_BW_4_8 = 0x1F // 7 0 GFSK Rx bandwidth: 4.8 kHz - SX126X_GFSK_RX_BW_5_8 = 0x17 // 7 0 5.8 kHz - SX126X_GFSK_RX_BW_7_3 = 0x0F // 7 0 7.3 kHz - SX126X_GFSK_RX_BW_9_7 = 0x1E // 7 0 9.7 kHz - SX126X_GFSK_RX_BW_11_7 = 0x16 // 7 0 11.7 kHz - SX126X_GFSK_RX_BW_14_6 = 0x0E // 7 0 14.6 kHz - SX126X_GFSK_RX_BW_19_5 = 0x1D // 7 0 19.5 kHz - SX126X_GFSK_RX_BW_23_4 = 0x15 // 7 0 23.4 kHz - SX126X_GFSK_RX_BW_29_3 = 0x0D // 7 0 29.3 kHz - SX126X_GFSK_RX_BW_39_0 = 0x1C // 7 0 39.0 kHz - SX126X_GFSK_RX_BW_46_9 = 0x14 // 7 0 46.9 kHz - SX126X_GFSK_RX_BW_58_6 = 0x0C // 7 0 58.6 kHz - SX126X_GFSK_RX_BW_78_2 = 0x1B // 7 0 78.2 kHz - SX126X_GFSK_RX_BW_93_8 = 0x13 // 7 0 93.8 kHz - SX126X_GFSK_RX_BW_117_3 = 0x0B // 7 0 117.3 kHz - SX126X_GFSK_RX_BW_156_2 = 0x1A // 7 0 156.2 kHz - SX126X_GFSK_RX_BW_187_2 = 0x12 // 7 0 187.2 kHz - SX126X_GFSK_RX_BW_234_3 = 0x0A // 7 0 234.3 kHz - SX126X_GFSK_RX_BW_312_0 = 0x19 // 7 0 312.0 kHz - SX126X_GFSK_RX_BW_373_6 = 0x11 // 7 0 373.6 kHz - SX126X_GFSK_RX_BW_467_0 = 0x09 // 7 0 467.0 kHz - SX126X_LORA_BW_7_8 = 0x00 // 7 0 LoRa bandwidth: 7.8 kHz - SX126X_LORA_BW_10_4 = 0x08 // 7 0 10.4 kHz - SX126X_LORA_BW_15_6 = 0x01 // 7 0 15.6 kHz - SX126X_LORA_BW_20_8 = 0x09 // 7 0 20.8 kHz - SX126X_LORA_BW_31_25 = 0x02 // 7 0 31.25 kHz - SX126X_LORA_BW_41_7 = 0x0A // 7 0 41.7 kHz - SX126X_LORA_BW_62_5 = 0x03 // 7 0 62.5 kHz - SX126X_LORA_BW_125_0 = 0x04 // 7 0 125.0 kHz - SX126X_LORA_BW_250_0 = 0x05 // 7 0 250.0 kHz - SX126X_LORA_BW_500_0 = 0x06 // 7 0 500.0 kHz - SX126X_LORA_CR_4_5 = 0x01 // 7 0 LoRa coding rate: 4/5 - SX126X_LORA_CR_4_6 = 0x02 // 7 0 4/6 - SX126X_LORA_CR_4_7 = 0x03 // 7 0 4/7 - SX126X_LORA_CR_4_8 = 0x04 // 7 0 4/8 - SX126X_LORA_LOW_DATA_RATE_OPTIMIZE_OFF = 0x00 // 7 0 LoRa low data rate optimization: disabled - SX126X_LORA_LOW_DATA_RATE_OPTIMIZE_ON = 0x01 // 7 0 enabled + SX126X_GFSK_FILTER_NONE = 0x00 // 7 0 GFSK filter: none + SX126X_GFSK_FILTER_GAUSS_0_3 = 0x08 // 7 0 Gaussian, BT = 0.3 + SX126X_GFSK_FILTER_GAUSS_0_5 = 0x09 // 7 0 Gaussian, BT = 0.5 + SX126X_GFSK_FILTER_GAUSS_0_7 = 0x0A // 7 0 Gaussian, BT = 0.7 + SX126X_GFSK_FILTER_GAUSS_1 = 0x0B // 7 0 Gaussian, BT = 1 + SX126X_GFSK_RX_BW_4_8 = 0x1F // 7 0 GFSK Rx bandwidth: 4.8 kHz + SX126X_GFSK_RX_BW_5_8 = 0x17 // 7 0 5.8 kHz + SX126X_GFSK_RX_BW_7_3 = 0x0F // 7 0 7.3 kHz + SX126X_GFSK_RX_BW_9_7 = 0x1E // 7 0 9.7 kHz + SX126X_GFSK_RX_BW_11_7 = 0x16 // 7 0 11.7 kHz + SX126X_GFSK_RX_BW_14_6 = 0x0E // 7 0 14.6 kHz + SX126X_GFSK_RX_BW_19_5 = 0x1D // 7 0 19.5 kHz + SX126X_GFSK_RX_BW_23_4 = 0x15 // 7 0 23.4 kHz + SX126X_GFSK_RX_BW_29_3 = 0x0D // 7 0 29.3 kHz + SX126X_GFSK_RX_BW_39_0 = 0x1C // 7 0 39.0 kHz + SX126X_GFSK_RX_BW_46_9 = 0x14 // 7 0 46.9 kHz + SX126X_GFSK_RX_BW_58_6 = 0x0C // 7 0 58.6 kHz + SX126X_GFSK_RX_BW_78_2 = 0x1B // 7 0 78.2 kHz + SX126X_GFSK_RX_BW_93_8 = 0x13 // 7 0 93.8 kHz + SX126X_GFSK_RX_BW_117_3 = 0x0B // 7 0 117.3 kHz + SX126X_GFSK_RX_BW_156_2 = 0x1A // 7 0 156.2 kHz + SX126X_GFSK_RX_BW_187_2 = 0x12 // 7 0 187.2 kHz + SX126X_GFSK_RX_BW_234_3 = 0x0A // 7 0 234.3 kHz + SX126X_GFSK_RX_BW_312_0 = 0x19 // 7 0 312.0 kHz + SX126X_GFSK_RX_BW_373_6 = 0x11 // 7 0 373.6 kHz + SX126X_GFSK_RX_BW_467_0 = 0x09 // 7 0 467.0 kHz + SX126X_LORA_BW_7_8 = 0x00 // 7 0 LoRa bandwidth: 7.8 kHz + SX126X_LORA_BW_10_4 = 0x08 // 7 0 10.4 kHz + SX126X_LORA_BW_15_6 = 0x01 // 7 0 15.6 kHz + SX126X_LORA_BW_20_8 = 0x09 // 7 0 20.8 kHz + SX126X_LORA_BW_31_25 = 0x02 // 7 0 31.25 kHz + SX126X_LORA_BW_41_7 = 0x0A // 7 0 41.7 kHz + SX126X_LORA_BW_62_5 = 0x03 // 7 0 62.5 kHz + SX126X_LORA_BW_125_0 = 0x04 // 7 0 125.0 kHz + SX126X_LORA_BW_250_0 = 0x05 // 7 0 250.0 kHz + SX126X_LORA_BW_500_0 = 0x06 // 7 0 500.0 kHz //SX126X_CMD_SET_PACKET_PARAMS SX126X_GFSK_PREAMBLE_DETECT_OFF = 0x00 // 7 0 GFSK minimum preamble length before reception starts: detector disabled @@ -267,12 +261,6 @@ const ( SX126X_GFSK_CRC_2_BYTE_INV = 0x06 // 7 0 2 byte, inverted SX126X_GFSK_WHITENING_OFF = 0x00 // 7 0 GFSK data whitening: disabled SX126X_GFSK_WHITENING_ON = 0x01 // 7 0 enabled - SX126X_LORA_HEADER_EXPLICIT = 0x00 // 7 0 LoRa header mode: explicit - SX126X_LORA_HEADER_IMPLICIT = 0x01 // 7 0 implicit - SX126X_LORA_CRC_OFF = 0x00 // 7 0 LoRa CRC mode: disabled - SX126X_LORA_CRC_ON = 0x01 // 7 0 enabled - SX126X_LORA_IQ_STANDARD = 0x00 // 7 0 LoRa IQ setup: standard - SX126X_LORA_IQ_INVERTED = 0x01 // 7 0 inverted //SX126X_CMD_SET_CAD_PARAMS SX126X_CAD_ON_1_SYMB = 0x00 // 7 0 number of symbols used for CAD: 1 @@ -323,13 +311,4 @@ const ( SX126X_LORA_MAC_PUBLIC_SYNCWORD = 0x3444 SX126X_LORA_MAC_PRIVATE_SYNCWORD = 0x1424 - - SX126X_LORA_SF5 = 0x05 - SX126X_LORA_SF6 = 0x06 - SX126X_LORA_SF7 = 0x07 - SX126X_LORA_SF8 = 0x08 - SX126X_LORA_SF9 = 0x09 - SX126X_LORA_SF10 = 0x0A - SX126X_LORA_SF11 = 0x0B - SX126X_LORA_SF12 = 0x0C ) diff --git a/sx126x/sx126x.go b/sx126x/sx126x.go index 6537259..42d308e 100644 --- a/sx126x/sx126x.go +++ b/sx126x/sx126x.go @@ -8,6 +8,7 @@ import ( "time" "tinygo.org/x/drivers" + "tinygo.org/x/drivers/lora" ) // SX126X radio transceiver RF_IN and RF_OUT may be connected @@ -55,36 +56,17 @@ const ( type Device struct { spi drivers.SPI // SPI bus for module communication radioEventChan chan RadioEvent // Channel for Receiving events - loraConf LoraConfig // Current Lora configuration + loraConf lora.Config // Current Lora configuration rfswitch RFSwitch // RF Switch, if any deepSleep bool // Internal Sleep state deviceType int // sx1261,sx1262,sx1268 (defaults sx1261) spiBuffer [SPI_BUFFER_SIZE]uint8 } -// Config holds the LoRa configuration parameters -type LoraConfig struct { - Freq uint32 // Frequency - Cr uint8 // Coding Rate - Sf uint8 // Spread Factor - Bw uint8 // Bandwidth - Ldr uint8 // Low Data Rate - Preamble uint16 // PreambleLength - SyncWord uint16 // Sync Word - HeaderType uint8 // Header : Implicit/explicit - Crc uint8 // CRC : Yes/No - Iq uint8 // iq : Standard/inverted - LoraTxPowerDBm int8 // Tx power in Dbm -} - const ( SX126X_RTC_FREQ_IN_HZ uint32 = 64000 ) -var ( - errUndefinedLoraConf = errors.New("Undefined Lora configuration") -) - // -------------------------------------------------- // Helper functions // -------------------------------------------------- @@ -387,11 +369,11 @@ func (d *Device) SetPacketType(packetType uint8) { } // SetSyncWord defines the Sync Word to yse -func (d *Device) SetSyncWord(syncword uint16) { +func (d *Device) SetSyncWord(sw uint16) { var p [2]uint8 - d.loraConf.SyncWord = syncword - p[0] = uint8((syncword >> 8) & 0xFF) - p[1] = uint8((syncword >> 0) & 0xFF) + d.loraConf.SyncWord = sw + p[0] = uint8((d.loraConf.SyncWord >> 8) & 0xFF) + p[1] = uint8((d.loraConf.SyncWord >> 0) & 0xFF) d.WriteRegister(SX126X_REG_LORA_SYNC_WORD_MSB, p[:]) } @@ -547,9 +529,9 @@ func (d *Device) SetLoraFrequency(freq uint32) { // NB: Change will be applied at next RX / TX func (d *Device) SetLoraIqMode(mode uint8) { if mode == 0 { - d.loraConf.Iq = SX126X_LORA_IQ_STANDARD + d.loraConf.Iq = lora.IQStandard } else { - d.loraConf.Iq = SX126X_LORA_IQ_INVERTED + d.loraConf.Iq = lora.IQInverted } } @@ -569,9 +551,9 @@ func (d *Device) SetLoraBandwidth(bw uint8) { // NB: Change will be applied at next RX / TX func (d *Device) SetLoraCrc(enable bool) { if enable { - d.loraConf.Crc = SX126X_LORA_CRC_ON + d.loraConf.Crc = lora.CRCOn } else { - d.loraConf.Crc = SX126X_LORA_CRC_OFF + d.loraConf.Crc = lora.CRCOn } } @@ -587,9 +569,10 @@ func (d *Device) SetLoraSpreadingFactor(sf uint8) { // // LoraConfig() defines Lora configuration for next Lora operations -func (d *Device) LoraConfig(cnf LoraConfig) { +func (d *Device) LoraConfig(cnf lora.Config) { // Save given configuration d.loraConf = cnf + d.loraConf.SyncWord = syncword(int(cnf.SyncWord)) // Switch to standby prior to configuration changes d.SetStandby() // Clear errors, disable radio interrupts for the moment @@ -599,7 +582,7 @@ func (d *Device) LoraConfig(cnf LoraConfig) { // Define radio operation mode d.SetPacketType(SX126X_PACKET_TYPE_LORA) d.SetRfFrequency(d.loraConf.Freq) - d.SetModulationParams(d.loraConf.Sf, 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.SetTxParams(d.loraConf.LoraTxPowerDBm, SX126X_PA_RAMP_200U) d.SetSyncWord(d.loraConf.SyncWord) d.SetBufferBaseAddress(0, 0) @@ -609,7 +592,7 @@ func (d *Device) LoraConfig(cnf LoraConfig) { func (d *Device) LoraTx(pkt []uint8, timeoutMs uint32) error { if d.loraConf.Freq == 0 { - return errUndefinedLoraConf + return lora.ErrUndefinedLoraConf } if d.rfswitch != nil { err := d.rfswitch.SetRfSwitchMode(RFSWITCH_TX_HP) @@ -625,7 +608,7 @@ func (d *Device) LoraTx(pkt []uint8, timeoutMs uint32) error { d.SetTxParams(d.loraConf.LoraTxPowerDBm, SX126X_PA_RAMP_200U) d.SetBufferBaseAddress(0, 0) d.WriteBuffer(pkt) - d.SetModulationParams(d.loraConf.Sf, 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, uint8(len(pkt)), d.loraConf.Iq) d.SetDioIrqParams(irqVal, irqVal, SX126X_IRQ_NONE, SX126X_IRQ_NONE) d.SetSyncWord(d.loraConf.SyncWord) @@ -642,7 +625,7 @@ func (d *Device) LoraTx(pkt []uint8, timeoutMs uint32) error { func (d *Device) LoraRx(timeoutMs uint32) ([]uint8, error) { if d.loraConf.Freq == 0 { - return nil, errUndefinedLoraConf + return nil, lora.ErrUndefinedLoraConf } if d.rfswitch != nil { err := d.rfswitch.SetRfSwitchMode(RFSWITCH_RX) @@ -654,7 +637,7 @@ func (d *Device) LoraRx(timeoutMs uint32) ([]uint8, error) { irqVal := uint16(SX126X_IRQ_RX_DONE | SX126X_IRQ_TIMEOUT | SX126X_IRQ_CRC_ERR) d.SetStandby() d.SetBufferBaseAddress(0, 0) - d.SetModulationParams(d.loraConf.Sf, 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.SetDioIrqParams(irqVal, irqVal, SX126X_IRQ_NONE, SX126X_IRQ_NONE) d.SetRx(timeoutMsToRtcSteps(timeoutMs)) @@ -699,3 +682,37 @@ func (d *Device) HandleInterrupt() { } } + +func bandwidth(bw uint8) uint8 { + switch bw { + case lora.Bandwidth_7_8: + return SX126X_LORA_BW_7_8 + case lora.Bandwidth_10_4: + return SX126X_LORA_BW_10_4 + case lora.Bandwidth_15_6: + return SX126X_LORA_BW_15_6 + case lora.Bandwidth_20_8: + return SX126X_LORA_BW_20_8 + case lora.Bandwidth_31_25: + return SX126X_LORA_BW_31_25 + case lora.Bandwidth_41_7: + return SX126X_LORA_BW_41_7 + case lora.Bandwidth_62_5: + return SX126X_LORA_BW_62_5 + case lora.Bandwidth_125_0: + return SX126X_LORA_BW_125_0 + case lora.Bandwidth_250_0: + return SX126X_LORA_BW_250_0 + case lora.Bandwidth_500_0: + return SX126X_LORA_BW_500_0 + default: + return 0 + } +} + +func syncword(sw int) uint16 { + if sw == lora.SyncPublic { + return SX126X_LORA_MAC_PUBLIC_SYNCWORD + } + return SX126X_LORA_MAC_PRIVATE_SYNCWORD +} diff --git a/sx127x/registers.go b/sx127x/registers.go index 98a2093..903eb51 100644 --- a/sx127x/registers.go +++ b/sx127x/registers.go @@ -70,20 +70,6 @@ const ( SX127X_LNA_OFF_GAIN = uint8(0x00) SX127X_LNA_LOW_GAIN = uint8(0x20) - // Header type - SX127X_LORA_HEADER_EXPLICIT = uint8(0x00) - SX127X_LORA_HEADER_IMPLICIT = uint8(0x01) - // CRC - SX127X_LORA_CRC_OFF = uint8(0x00) - SX127X_LORA_CRC_ON = uint8(0x01) - // IQ Polarity - SX127X_LORA_IQ_STANDARD = uint8(0x00) - SX127X_LORA_IQ_INVERTED = uint8(0x01) - // Coding Rate - SX127X_LORA_CR_4_5 = uint8(0x01) - SX127X_LORA_CR_4_6 = uint8(0x02) - SX127X_LORA_CR_4_7 = uint8(0x03) - SX127X_LORA_CR_4_8 = uint8(0x04) // Bandwidth SX127X_LORA_BW_7_8 = uint8(0x00) SX127X_LORA_BW_10_4 = uint8(0x01) @@ -95,17 +81,6 @@ const ( SX127X_LORA_BW_125_0 = uint8(0x07) SX127X_LORA_BW_250_0 = uint8(0x08) SX127X_LORA_BW_500_0 = uint8(0x09) - // Spreading factor - SX127X_LORA_SF6 = uint8(0x06) - SX127X_LORA_SF7 = uint8(0x07) - SX127X_LORA_SF8 = uint8(0x08) - SX127X_LORA_SF9 = uint8(0x09) - SX127X_LORA_SF10 = uint8(0x0A) - SX127X_LORA_SF11 = uint8(0x0B) - SX127X_LORA_SF12 = uint8(0x0C) - // Optim Low DR - SX127X_LOW_DATARATE_OPTIM_OFF = uint8(0x00) - SX127X_LOW_DATARATE_OPTIM_ON = uint8(0x01) // Automatic gain control SX127X_AGC_AUTO_OFF = uint8(0x00) SX127X_AGC_AUTO_ON = uint8(0x01) diff --git a/sx127x/sx127x.go b/sx127x/sx127x.go index 342f633..76c4fbc 100644 --- a/sx127x/sx127x.go +++ b/sx127x/sx127x.go @@ -10,6 +10,7 @@ import ( "time" "tinygo.org/x/drivers" + "tinygo.org/x/drivers/lora" ) const ( @@ -38,36 +39,19 @@ type Device struct { spi drivers.SPI // SPI bus for module communication rstPin, csPin machine.Pin // GPIOs for reset and chip select radioEventChan chan RadioEvent // Channel for Receiving events - loraConf LoraConfig // Current Lora configuration + loraConf lora.Config // Current Lora configuration deepSleep bool // Internal Sleep state deviceType int // sx1261,sx1262,sx1268 (defaults sx1261) spiBuffer [SPI_BUFFER_SIZE]uint8 packetIndex uint8 // FIXME ... useless ? } -// Config holds the LoRa configuration parameters -type LoraConfig struct { - Freq uint32 // Frequency - Cr uint8 // Coding Rate - Sf uint8 // Spread Factor - Bw uint8 // Bandwidth - Ldr uint8 // Low Data Rate - Preamble uint16 // PreambleLength - SyncWord uint16 // Sync Word - HeaderType uint8 // Header : Implicit/explicit - Crc uint8 // CRC : Yes/No - Iq uint8 // iq : Standard/inverted - LoraTxPowerDBm int8 // Tx power in Dbm -} - -var ( - errUndefinedLoraConf = errors.New("Undefined Lora configuration") -) - // -------------------------------------------------- -// Channel and events +// +// Channel and events +// // -------------------------------------------------- -//NewRadioEvent() returns a new RadioEvent that can be used in the RadioChannel +// NewRadioEvent() returns a new RadioEvent that can be used in the RadioChannel func NewRadioEvent(eType int, irqStatus uint8, eData []byte) RadioEvent { r := RadioEvent{EventType: eType, IRQStatus: irqStatus, EventData: eData} return r @@ -135,7 +119,7 @@ func (d *Device) SetOpModeLora() { d.WriteRegister(SX127X_REG_OP_MODE, SX127X_OPMODE_LORA) } -//GetVersion returns hardware version of sx1276 chipset +// GetVersion returns hardware version of sx1276 chipset func (d *Device) GetVersion() uint8 { return (d.ReadRegister(SX127X_REG_VERSION)) } @@ -245,7 +229,7 @@ func (d *Device) SetAgcAuto(val uint8) { // SetLowDataRateOptimize enables Low Data Rate Optimization func (d *Device) SetLowDataRateOptim(val uint8) { - if val == SX127X_LOW_DATARATE_OPTIM_ON { + if val == lora.LowDataRateOptimizeOn { d.WriteRegister(SX127X_REG_MODEM_CONFIG_3, d.ReadRegister(SX127X_REG_MODEM_CONFIG_3)|0x08) } else { d.WriteRegister(SX127X_REG_MODEM_CONFIG_3, d.ReadRegister(SX127X_REG_MODEM_CONFIG_3)&0xf7) @@ -271,9 +255,10 @@ func (d *Device) SetHopPeriod(val uint8) { // // LoraConfig() defines Lora configuration for next Lora operations -func (d *Device) LoraConfig(cnf LoraConfig) { +func (d *Device) LoraConfig(cnf lora.Config) { // Save given configuration d.loraConf = cnf + d.loraConf.SyncWord = syncword(int(cnf.SyncWord)) } // SetLoraFrequency updates the frequency the LoRa module is using @@ -287,7 +272,7 @@ func (d *Device) SetLoraFrequency(frequency uint32) { // SetBandwidth updates the bandwidth the LoRa module is using func (d *Device) SetLoraBandwidth(bw uint8) { - d.loraConf.Bw = bw + d.loraConf.Bw = bandwidth(bw) d.WriteRegister(SX127X_REG_MODEM_CONFIG_1, (d.ReadRegister(SX127X_REG_MODEM_CONFIG_1)&0x0f)|(bw<<4)) } @@ -300,7 +285,7 @@ func (d *Device) SetLoraCodingRate(cr uint8) { // SetImplicitHeaderModeOn Enables implicit header mode *** func (d *Device) SetLoraHeaderMode(headerType uint8) { d.loraConf.HeaderType = headerType - if headerType == SX127X_LORA_HEADER_IMPLICIT { + if headerType == lora.HeaderExplicit { d.WriteRegister(SX127X_REG_MODEM_CONFIG_1, d.ReadRegister(SX127X_REG_MODEM_CONFIG_1)|0x01) } else { d.WriteRegister(SX127X_REG_MODEM_CONFIG_1, d.ReadRegister(SX127X_REG_MODEM_CONFIG_1)&0xfe) @@ -310,7 +295,7 @@ func (d *Device) SetLoraHeaderMode(headerType uint8) { // SetLoraSpreadingFactor changes spreading factor func (d *Device) SetLoraSpreadingFactor(sf uint8) { d.loraConf.Sf = sf - if sf == SX127X_LORA_SF6 { + if sf == lora.SpreadingFactor6 { d.WriteRegister(SX127X_REG_DETECTION_OPTIMIZE, 0xc5) d.WriteRegister(SX127X_REG_DETECTION_THRESHOLD, 0x0c) } else { @@ -333,10 +318,10 @@ func (d *Device) SetTxContinuousMode(val bool) { // SetLoraCrc Enable CRC generation and check on payload func (d *Device) SetLoraCrc(enable bool) { if enable { - d.loraConf.Crc = SX127X_LORA_CRC_ON + d.loraConf.Crc = lora.CRCOn d.WriteRegister(SX127X_REG_MODEM_CONFIG_2, d.ReadRegister(SX127X_REG_MODEM_CONFIG_2)|0x04) } else { - d.loraConf.Crc = SX127X_LORA_CRC_OFF + d.loraConf.Crc = lora.CRCOff d.WriteRegister(SX127X_REG_MODEM_CONFIG_2, d.ReadRegister(SX127X_REG_MODEM_CONFIG_2)&0xfb) } } @@ -347,7 +332,7 @@ func (d *Device) SetLoraPreamble(pLen uint16) { d.WriteRegister(SX127X_REG_PREAMBLE_LSB, uint8(pLen&0xFF)) } -//SetLoraSyncWord defines sync word +// SetLoraSyncWord defines sync word func (d *Device) SetLoraSyncWord(syncWord uint16) { d.loraConf.SyncWord = syncWord sw := uint8(syncWord & 0xFF) @@ -357,7 +342,7 @@ func (d *Device) SetLoraSyncWord(syncWord uint16) { // SetLoraIQMode Sets I/Q polarity configuration func (d *Device) SetLoraIqMode(val uint8) { d.loraConf.Iq = val - if val == SX127X_LORA_IQ_STANDARD { + if val == lora.IQStandard { //Set IQ to normal values d.WriteRegister(SX127X_REG_INVERTIQ, 0x27) d.WriteRegister(SX127X_REG_INVERTIQ2, 0x1D) @@ -387,7 +372,7 @@ func (d *Device) LoraTx(pkt []uint8, timeoutMs uint32) error { d.SetLoraSpreadingFactor(d.loraConf.Sf) d.SetLoraIqMode(d.loraConf.Iq) d.SetLoraCodingRate(d.loraConf.Cr) - d.SetLoraCrc(d.loraConf.Crc == SX127X_LORA_CRC_ON) + d.SetLoraCrc(d.loraConf.Crc == lora.CRCOn) d.SetTxPower(d.loraConf.LoraTxPowerDBm, true) d.SetLoraHeaderMode(d.loraConf.HeaderType) d.SetAgcAuto(SX127X_AGC_AUTO_ON) @@ -426,7 +411,7 @@ func (d *Device) LoraTx(pkt []uint8, timeoutMs uint32) error { func (d *Device) LoraRx(timeoutMs uint32) ([]uint8, error) { if d.loraConf.Freq == 0 { - return nil, errUndefinedLoraConf + return nil, lora.ErrUndefinedLoraConf } d.SetOpModeLora() @@ -444,7 +429,7 @@ func (d *Device) LoraRx(timeoutMs uint32) ([]uint8, error) { d.SetLoraSpreadingFactor(d.loraConf.Sf) // OK d.SetLoraIqMode(d.loraConf.Iq) //OK d.SetLoraCodingRate(d.loraConf.Cr) - d.SetLoraCrc(d.loraConf.Crc == SX127X_LORA_CRC_ON) + d.SetLoraCrc(d.loraConf.Crc == lora.CRCOn) d.SetTxPower(d.loraConf.LoraTxPowerDBm, true) d.SetLoraHeaderMode(d.loraConf.HeaderType) d.SetAgcAuto(SX127X_AGC_AUTO_ON) @@ -534,3 +519,37 @@ func (d *Device) HandleInterrupt() { rChan <- NewRadioEvent(RadioEventCrcError, st, nil) } } + +func bandwidth(bw uint8) uint8 { + switch bw { + case lora.Bandwidth_7_8: + return SX127X_LORA_BW_7_8 + case lora.Bandwidth_10_4: + return SX127X_LORA_BW_10_4 + case lora.Bandwidth_15_6: + return SX127X_LORA_BW_15_6 + case lora.Bandwidth_20_8: + return SX127X_LORA_BW_20_8 + case lora.Bandwidth_31_25: + return SX127X_LORA_BW_31_25 + case lora.Bandwidth_41_7: + return SX127X_LORA_BW_41_7 + case lora.Bandwidth_62_5: + return SX127X_LORA_BW_62_5 + case lora.Bandwidth_125_0: + return SX127X_LORA_BW_125_0 + case lora.Bandwidth_250_0: + return SX127X_LORA_BW_250_0 + case lora.Bandwidth_500_0: + return SX127X_LORA_BW_500_0 + default: + return 0 + } +} + +func syncword(sw int) uint16 { + if sw == lora.SyncPublic { + return SX127X_LORA_MAC_PUBLIC_SYNCWORD + } + return SX127X_LORA_MAC_PRIVATE_SYNCWORD +}