add debugging stuff

This commit is contained in:
soypat
2023-05-22 00:41:59 -03:00
parent 3b92ee60dc
commit 06c18d75cd
8 changed files with 456 additions and 49 deletions
+3 -1
View File
@@ -1,2 +1,4 @@
# lora
LoRa protocol for TinyGo- based on tinygo-org/drivers.
High quality LoRa library and drivers for the Go language.
+64
View File
@@ -0,0 +1,64 @@
//go:build tinygo
package main
import (
"context"
"io"
"machine"
"time"
"github.com/soypat/lora"
"github.com/soypat/lora/sx127x"
)
var (
SX127X_SPI = machine.SPI0
)
const (
SX127X_PIN_RST = machine.GP16
// SPI definition for SX127x
SX127X_PIN_SCK = machine.GP2
SX127X_PIN_TX = machine.GP3
SX127X_PIN_RX = machine.GP4
SX127X_PIN_CS = machine.GP5
)
func main() {
time.Sleep(500 * time.Millisecond)
defer println("program end")
SX127X_PIN_RST.Configure(machine.PinConfig{Mode: machine.PinOutput})
SX127X_PIN_CS.Configure(machine.PinConfig{Mode: machine.PinOutput})
err := SX127X_SPI.Configure(machine.SPIConfig{
Frequency: 100000,
SCK: SX127X_PIN_SCK,
SDO: SX127X_PIN_TX,
SDI: SX127X_PIN_RX,
})
if err != nil {
panic(err.Error())
}
dev := sx127x.NewLoRa(SX127X_SPI, SX127X_PIN_CS.Set, SX127X_PIN_RST.Set)
// Replace with your frequency:
err = dev.Configure(sx127x.DefaultConfig(lora.Freq433_0M))
if err != nil {
panic(err.Error())
}
println("config success; receiving messages")
var rx [256]byte
// This blocks forever reading messages received.
ctx := context.Background()
err = dev.RxContinuous(ctx, func(r io.Reader) (_ error) {
n, err := r.Read(rx[:])
if err != nil {
return err
}
println("received LoRa:", string(rx[:n]))
return nil
})
if err != nil {
panic(err)
}
}
+1 -19
View File
@@ -40,16 +40,7 @@ func main() {
panic(err.Error())
}
dev := sx127x.NewLoRa(SX127X_SPI, SX127X_PIN_CS.Set, SX127X_PIN_RST.Set)
err = dev.Configure(lora.Config{
Bandwidth: lora.BW125k,
Frequency: lora.Freq433_0M,
CodingRate: lora.CR4_5,
SpreadFactor: lora.SF7,
HeaderType: lora.HeaderExplicit,
TxPower: 0,
CRC: true,
PreambleLength: 12,
})
err = dev.Configure(sx127x.DefaultConfig(lora.Freq433_0M))
if err != nil {
panic(err.Error())
}
@@ -57,7 +48,6 @@ func main() {
randomU32, _ := dev.RandomU32()
myName := fmt.Sprintf("user-%x", randomU32%0xffff)
println("config success; sending messages as ", myName)
var rx [256]byte
packet := []byte(myName + " says hello!")
for {
err = dev.Tx(packet)
@@ -67,13 +57,5 @@ func main() {
print(".")
}
time.Sleep(2 * time.Second)
for i := 0; i < 6; i++ {
n, err := dev.RxSingle(rx[:])
if err != nil {
println("rx error:", err.Error())
continue
}
println("got message: ", string(rx[:n]))
}
}
}
+29 -5
View File
@@ -2,10 +2,15 @@ package lora
import "time"
// Config is the generic configuration struct for a LoRa modem/radio that provides
// the most common configuration parameters needed to set up a channel with another
// radio using same parameters.
type Config struct {
// Bandwidth relates to data rate of communication. Double the bandwidth means
// double the data rate, which implies faster communications and less energy usage.
Bandwidth Frequency
// Frequency is the carrier frequency of the radio, a.k.a center frequency.
// It must match the modem's working frequency to ensure proper functioning.
Frequency Frequency
// Length of the preamble preceding the header. Can be arbitrarily long.
// Longer preambles ensure more robust communications but can lead to congestion.
@@ -14,11 +19,13 @@ type Config struct {
// than the expected packet preamble length on the SX1278.
PreambleLength uint16
HeaderType HeaderType
CodingRate CodingRate
SpreadFactor SpreadFactor
SyncWord uint8
TxPower int8 // Tx Power in dBm.
CRC bool
// Must be set when working with implicit headers.
MaxImplicitPayloadLength uint8
CodingRate CodingRate
SpreadFactor SpreadFactor
SyncWord uint8
TxPower int8 // Tx Power in dBm.
CRC bool
// Low data rate optimisation flag. The use of this flag is mandated when
// the symbol duration exceeds 16ms. Increases reliability at high spreading factors.
LDRO bool
@@ -75,6 +82,10 @@ func (cfg *Config) TimeOnAir(payloadLength int) time.Duration {
time.Duration(cfg.Bandwidth.Hertz())
}
// HeaderType defines the presence of a header in the LoRa packet.
// An explicit header means that the packet contains a header with a length
// field. An implicit header means that the packet does not contain a header
// and the length is implicitly known, i.e. agreed upon between two modems in advance.
type HeaderType uint8
const (
@@ -82,6 +93,10 @@ const (
HeaderImplicit HeaderType = 1
)
// CodingRate defines the error correction scheme used by the LoRa modem.
// Higher coding rates imply more robust communications at the expense of
// less data throughput. A CR of 4/5 means that for every 4 bits of data,
// 1 bit of error correction is added to the total transmitted bits.
type CodingRate uint8
const (
@@ -95,8 +110,13 @@ const (
CR4_8 CodingRate = 4
)
// SpreadFactor defines the number of chips per symbol. Higher spread factors
// imply longer transmission times but more robust communications.
// The number of chips per symbol is 2^SF, so a spread factor of 8 takes twice
// as long to transmit a symbol as a spread factor of 7.
type SpreadFactor uint8
// Common spread factors. Decide the number of chips per symbol.
const (
SF6 SpreadFactor = iota + 6
SF7
@@ -111,6 +131,10 @@ func (sf SpreadFactor) ChipsPerSymbol() int64 {
return 1 << sf
}
// Frequency defines the center frequency of the LoRa channel. The center frequency
// serves to avoid interference from other channels and has minimal effect on
// the data rate. The frequency in Config must match the modem's working frequency
// or the modem may fail to transmit or receive packets or even be damaged.
type Frequency int64
func (f Frequency) Hertz() int64 { return int64(f) }
+93 -1
View File
@@ -1,6 +1,11 @@
package sx127x
import "github.com/soypat/lora"
import (
"bytes"
"fmt"
"github.com/soypat/lora"
)
const (
// 32MHz frequency for crystal oscillator is typical.
@@ -9,6 +14,56 @@ const (
fSTEP = fXOSC / (1 << 19)
)
type irqFlagPos uint8
const (
irqPosCADDetected irqFlagPos = iota
irqPosFHSSChange
irqPosCADDone
irqPosTxDone
irqPosValidHeader
irqPosPayloadCRC
irqPosRxDone
irqPosRxTimeout
)
func (pos irqFlagPos) String() (str string) {
switch pos {
case irqPosCADDetected:
str = "CADDetected"
case irqPosFHSSChange:
str = "FHSSChange"
case irqPosCADDone:
str = "CADDone"
case irqPosTxDone:
str = "TxDone"
case irqPosValidHeader:
str = "ValidHeader"
case irqPosPayloadCRC:
str = "CRCError"
case irqPosRxDone:
str = "RxDone"
case irqPosRxTimeout:
str = "RxTimeout"
default:
str = "UnknownIRQ"
}
return str
}
func irqFlagsString(irqFlags uint8) (str string) {
if irqFlags == 0 {
return "[]"
}
str = "["
for i := irqFlagPos(0); i < 8; i++ {
if irqFlags&(1<<i) != 0 {
str += i.String() + ","
}
}
return str + "]"
}
const (
// registers
regFIFO = 0x00
@@ -58,6 +113,7 @@ const (
expectedVersion = 0x12
// Bits masking the corresponding IRQs from the radio
irqRXTOUT_MASK uint8 = 0x80
irqRXDONE_MASK uint8 = 0x40
irqCRCERR_MASK uint8 = 0x20
@@ -193,3 +249,39 @@ func (op OpMode) String() (s string) {
}
return s
}
func (d *DeviceLoRa) statusString() string {
irq, _ := d.read8(regIRQ_FLAGS)
opmode, err := d.GetOpMode()
return fmt.Sprintf("opmode: %s; operr=%v; irq: %08b=%s;%s", opmode.String(), err, irq, irqFlagsString(irq), d.debugRegString())
}
func (d *DeviceLoRa) wrapErr(err error) error {
if err == nil {
return nil
}
return fmt.Errorf("stat=%s: %w", d.statusString(), err)
}
func (d *DeviceLoRa) debugForEachTouchedReg(fn func(addr, mask, read, write uint8)) {
for addr := uint8(0); addr < debugBufSize; addr++ {
mask := d.debugMask[addr]
read := d.debugRead[addr]
write := d.debugWrite[addr]
fn(addr, mask, read, write)
}
}
func (d *DeviceLoRa) debugRegString() string {
var buf bytes.Buffer
d.debugForEachTouchedReg(func(addr, mask, read, write uint8) {
rm := read & mask
wm := write & mask
if rm == wm {
return
}
regstr := regstr(addr).String()
fmt.Fprintf(&buf, "0x%02X(%s): mask=%08b, read=0x%0x, write=0x%0x\n", addr, regstr, mask, read, write)
})
return buf.String()
}
+48
View File
@@ -0,0 +1,48 @@
package sx127x
type regstr uint8
const (
// registers
_FIFO regstr = 0x00
_OP_MODE regstr = 0x01
_FRF_MSB regstr = 0x06
_FRF_MID regstr = 0x07
_FRF_LSB regstr = 0x08
_PA_CONFIG regstr = 0x09
_PA_RAMP regstr = 0x0a
_OCP regstr = 0x0b
_LNA regstr = 0x0c
_FIFO_ADDR_PTR regstr = 0x0d
_FIFO_TX_BASE_ADDR regstr = 0x0e
_FIFO_RX_BASE_ADDR regstr = 0x0f
_FIFO_RX_CURRENT_ADDR regstr = 0x10
_IRQ_FLAGS_MASK regstr = 0x11
_IRQ_FLAGS regstr = 0x12
_RX_NB_BYTES regstr = 0x13
_PKT_SNR_VALUE regstr = 0x19
_PKT_RSSI_VALUE regstr = 0x1a
_RSSI_VALUE regstr = 0x1b
_MODEM_CONFIG_1 regstr = 0x1d
_MODEM_CONFIG_2 regstr = 0x1e
_SYMB_TIMEOUT_LSB regstr = 0x1f
_PREAMBLE_MSB regstr = 0x20
_PREAMBLE_LSB regstr = 0x21
_PAYLOAD_LENGTH regstr = 0x22
_MAX_PAYLOAD_LENGTH regstr = 0x23
_HOP_PERIOD regstr = 0x24
_MODEM_CONFIG_3 regstr = 0x26
_FREQ_ERROR_MSB regstr = 0x28
_FREQ_ERROR_MID regstr = 0x29
_FREQ_ERROR_LSB regstr = 0x2a
_RSSI_WIDEBAND regstr = 0x2c
_DETECTION_OPTIMIZE regstr = 0x31
_INVERTIQ regstr = 0x33
_DETECTION_THRESHOLD regstr = 0x37
_SYNC_WORD regstr = 0x39
_INVERTIQ2 regstr = 0x3b
_DIO_MAPPING_1 regstr = 0x40
_DIO_MAPPING_2 regstr = 0x41
_VERSION regstr = 0x42
_PA_DAC regstr = 0x4d
)
+105
View File
@@ -0,0 +1,105 @@
// Code generated by "stringer -type _reg ./sx127x/"; DO NOT EDIT.
package sx127x
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[_FIFO-0]
_ = x[_OP_MODE-1]
_ = x[_FRF_MSB-6]
_ = x[_FRF_MID-7]
_ = x[_FRF_LSB-8]
_ = x[_PA_CONFIG-9]
_ = x[_PA_RAMP-10]
_ = x[_OCP-11]
_ = x[_LNA-12]
_ = x[_FIFO_ADDR_PTR-13]
_ = x[_FIFO_TX_BASE_ADDR-14]
_ = x[_FIFO_RX_BASE_ADDR-15]
_ = x[_FIFO_RX_CURRENT_ADDR-16]
_ = x[_IRQ_FLAGS_MASK-17]
_ = x[_IRQ_FLAGS-18]
_ = x[_RX_NB_BYTES-19]
_ = x[_PKT_SNR_VALUE-25]
_ = x[_PKT_RSSI_VALUE-26]
_ = x[_RSSI_VALUE-27]
_ = x[_MODEM_CONFIG_1-29]
_ = x[_MODEM_CONFIG_2-30]
_ = x[_SYMB_TIMEOUT_LSB-31]
_ = x[_PREAMBLE_MSB-32]
_ = x[_PREAMBLE_LSB-33]
_ = x[_PAYLOAD_LENGTH-34]
_ = x[_MAX_PAYLOAD_LENGTH-35]
_ = x[_HOP_PERIOD-36]
_ = x[_MODEM_CONFIG_3-38]
_ = x[_FREQ_ERROR_MSB-40]
_ = x[_FREQ_ERROR_MID-41]
_ = x[_FREQ_ERROR_LSB-42]
_ = x[_RSSI_WIDEBAND-44]
_ = x[_DETECTION_OPTIMIZE-49]
_ = x[_INVERTIQ-51]
_ = x[_DETECTION_THRESHOLD-55]
_ = x[_SYNC_WORD-57]
_ = x[_INVERTIQ2-59]
_ = x[_DIO_MAPPING_1-64]
_ = x[_DIO_MAPPING_2-65]
_ = x[_VERSION-66]
_ = x[_PA_DAC-77]
}
const __reg_name = "_FIFO_OP_MODE_FRF_MSB_FRF_MID_FRF_LSB_PA_CONFIG_PA_RAMP_OCP_LNA_FIFO_ADDR_PTR_FIFO_TX_BASE_ADDR_FIFO_RX_BASE_ADDR_FIFO_RX_CURRENT_ADDR_IRQ_FLAGS_MASK_IRQ_FLAGS_RX_NB_BYTES_PKT_SNR_VALUE_PKT_RSSI_VALUE_RSSI_VALUE_MODEM_CONFIG_1_MODEM_CONFIG_2_SYMB_TIMEOUT_LSB_PREAMBLE_MSB_PREAMBLE_LSB_PAYLOAD_LENGTH_MAX_PAYLOAD_LENGTH_HOP_PERIOD_MODEM_CONFIG_3_FREQ_ERROR_MSB_FREQ_ERROR_MID_FREQ_ERROR_LSB_RSSI_WIDEBAND_DETECTION_OPTIMIZE_INVERTIQ_DETECTION_THRESHOLD_SYNC_WORD_INVERTIQ2_DIO_MAPPING_1_DIO_MAPPING_2_VERSION_PA_DAC"
var __reg_map = map[regstr]string{
0: __reg_name[0:5],
1: __reg_name[5:13],
6: __reg_name[13:21],
7: __reg_name[21:29],
8: __reg_name[29:37],
9: __reg_name[37:47],
10: __reg_name[47:55],
11: __reg_name[55:59],
12: __reg_name[59:63],
13: __reg_name[63:77],
14: __reg_name[77:95],
15: __reg_name[95:113],
16: __reg_name[113:134],
17: __reg_name[134:149],
18: __reg_name[149:159],
19: __reg_name[159:171],
25: __reg_name[171:185],
26: __reg_name[185:200],
27: __reg_name[200:211],
29: __reg_name[211:226],
30: __reg_name[226:241],
31: __reg_name[241:258],
32: __reg_name[258:271],
33: __reg_name[271:284],
34: __reg_name[284:299],
35: __reg_name[299:318],
36: __reg_name[318:329],
38: __reg_name[329:344],
40: __reg_name[344:359],
41: __reg_name[359:374],
42: __reg_name[374:389],
44: __reg_name[389:403],
49: __reg_name[403:422],
51: __reg_name[422:431],
55: __reg_name[431:451],
57: __reg_name[451:461],
59: __reg_name[461:471],
64: __reg_name[471:485],
65: __reg_name[485:499],
66: __reg_name[499:507],
77: __reg_name[507:514],
}
func (i regstr) String() string {
if str, ok := __reg_map[i]; ok {
return str
}
return "_reg(" + strconv.FormatInt(int64(i), 10) + ")"
}
+113 -23
View File
@@ -46,6 +46,7 @@ import (
"context"
"encoding/binary"
"errors"
"fmt"
"io"
"runtime"
"time"
@@ -64,30 +65,56 @@ type SPI interface {
Tx(writeBuffer, readBuffer []byte) error
}
const debugBufSize = 255
type DeviceLoRa struct {
rst PinOutput
cs PinOutput
bus SPI
headerType lora.HeaderType
// onNoPacket is called while waiting for a packet to be received in a tight loop.
onNoPacket func()
// Debugging buffers.
debugRead, debugWrite, debugMask [debugBufSize]byte
}
func DefaultConfig(freq lora.Frequency) lora.Config {
return lora.Config{
Frequency: freq,
SpreadFactor: lora.SF7,
Bandwidth: 125 * lora.KiloHertz,
CodingRate: lora.CR4_5,
PreambleLength: 12,
HeaderType: lora.HeaderExplicit,
MaxImplicitPayloadLength: 0, // No need to be set when working with explicit headers.
CRC: true,
SyncWord: publicSyncword,
TxPower: 0,
LDRO: false,
IQInversion: false,
}
}
// NewLoRa returns a new SX127x device. It performs no I/O operations.
// The caller should call Configure before using the device.
func NewLoRa(bus SPI, cs, reset PinOutput) *DeviceLoRa {
d := DeviceLoRa{bus: bus, cs: cs, rst: reset}
d := DeviceLoRa{bus: bus, cs: cs, rst: reset, onNoPacket: runtime.Gosched}
return &d
}
var (
errBadSpread = errors.New("bad spread factor")
errSF6Implicit = errors.New("SF6 can only be used with implicit header type") // Page 30: Implicit Header Mode.
errPreambleTooShort = errors.New("preamble length too short")
ErrNotDetected = errors.New("sx127x not detected")
errBadMode = errors.New("bad mode: sx127x in FSK/OOK mode, not LoRa or viceversa")
errBadCodingRate = errors.New("bad coding rate")
errUnsupportedBandwidth = errors.New("bandwidth too high for frequency around 169MHz")
errIRQNotCleared = errors.New("IRQs not cleared")
ErrDeviceBusy = errors.New("device busy")
ErrCRC = errors.New("crc error")
ErrRxTimeout = errors.New("rx timeout")
errBadSpread = errors.New("bad spread factor")
errSF6Implicit = errors.New("SF6 can only be used with implicit header type") // Page 30: Implicit Header Mode.
errPreambleTooShort = errors.New("preamble length too short")
ErrNotDetected = errors.New("sx127x not detected")
errBadMode = errors.New("bad mode: sx127x in FSK/OOK mode, not LoRa or viceversa")
errBadCodingRate = errors.New("bad coding rate")
errUnsupportedBandwidth = errors.New("bandwidth too high for frequency around 169MHz")
errIRQNotCleared = errors.New("IRQs not cleared")
ErrDeviceBusy = errors.New("device busy")
ErrCRC = errors.New("crc error")
ErrRxTimeout = errors.New("rx timeout")
errImplicitPacketTooLarge = errors.New("packet length exceeds MaxImplicitPayloadLength")
)
func (d *DeviceLoRa) Configure(cfg lora.Config) (err error) {
@@ -104,6 +131,8 @@ func (d *DeviceLoRa) Configure(cfg lora.Config) (err error) {
err = errUnsupportedBandwidth
case cfg.HeaderType != lora.HeaderImplicit && cfg.HeaderType != lora.HeaderExplicit:
err = errors.New("bad header type")
case cfg.HeaderType == lora.HeaderImplicit && cfg.MaxImplicitPayloadLength == 0:
err = errors.New("MaxImplicitPayloadLength parameter must be set when working with implicit headers")
case cfg.TxPower > 20:
err = errors.New("bad tx power")
}
@@ -161,6 +190,9 @@ func (d *DeviceLoRa) Configure(cfg lora.Config) (err error) {
if err != nil {
return err
}
if isImplicit {
d.setMaxPayloadLength(cfg.MaxImplicitPayloadLength)
}
err = d.enableIQInversion(cfg.IQInversion)
if err != nil {
return err
@@ -169,16 +201,25 @@ func (d *DeviceLoRa) Configure(cfg lora.Config) (err error) {
if err != nil {
return err
}
err = d.enableLowDataRateOptimization(cfg.LDRO)
if err != nil {
return err
}
err = d.SetSymbolTimeout(1023) // Set timeout to max value.
if err != nil {
return err
}
const rxStart = 128
d.write8(regFIFO_TX_BASE_ADDR, 0)
d.write8(regFIFO_RX_BASE_ADDR, rxStart)
d.setHopPeriod(0)
// Go insto standby mode to write to FIFO related registers.
err = d.SetOpMode(OpStandby)
if err != nil {
return err
}
d.write8(regFIFO_TX_BASE_ADDR, 0)
d.write8(regFIFO_RX_BASE_ADDR, 0)
d.write8(regFIFO_ADDR_PTR, 0)
d.headerType = cfg.HeaderType
return d.SetOpMode(OpStandby)
return d.SetOpMode(OpSleep) // Return to sleep mode to conserve power.
}
func (d *DeviceLoRa) Reset() {
@@ -211,7 +252,7 @@ func (d *DeviceLoRa) SetOpMode(mode OpMode) error {
}
got, err := d.GetOpMode()
if err != nil {
return err
return d.wrapErr(err)
}
if got != mode {
return errors.New("tried to set opmode " + mode.String() + ", got " + got.String())
@@ -347,15 +388,21 @@ func (d *DeviceLoRa) RxSingle(dst []byte) (uint8, error) {
// Loop until Rx received or timeout IRQ.
var irq uint8
for irq&(irqRXDONE_MASK|irqRXTOUT_MASK) == 0 {
runtime.Gosched() // Yield to scheduler.
for {
irq, err = d.read8(regIRQ_FLAGS)
if err != nil {
return 0, err
}
if irq&(irqRXDONE_MASK|irqRXTOUT_MASK) != 0 {
break
}
d.onNoPacket()
}
// Check for payload integrity and timeout interrupt.
if irq&irqCRCERR_MASK != 0 {
if d.headerType == lora.HeaderImplicit {
return 0, errImplicitPacketTooLarge
}
return 0, ErrCRC
} else if irq&irqRXTOUT_MASK != 0 {
return 0, ErrRxTimeout
@@ -406,17 +453,34 @@ func (d *DeviceLoRa) RxContinuous(ctx context.Context, fn rxCallback) error {
// Loop until Rx received or timeout IRQ.
var irq uint8
count := 0
defer func() {
println("RxContinuous looped", count, "times")
}()
for ctx.Err() == nil {
runtime.Gosched() // Yield to scheduler.
irq, err = d.read8(regIRQ_FLAGS)
if err != nil {
return err
}
if irq&irqRXDONE_MASK != 0 {
nbBytes, _ := d.read8(regRX_NB_BYTES)
if nbBytes == 0 {
return fmt.Errorf("received packet with 0 bytes;irq=%08b; stat=%s", irq, d.statusString())
}
err = d.gotRxContinous(fn)
if err != nil {
return err
}
} else {
d.onNoPacket()
}
count++
op, err = d.GetOpMode()
if err != nil {
return err
} else if op != OpRx {
return errors.New("unexpected op mode change during RxContinuous to " +
op.String() + " with irqs:" + irqFlagsString(irq))
}
}
return ctx.Err()
@@ -597,6 +661,9 @@ func (d *DeviceLoRa) ReadConfig() (cfg lora.Config, err error) {
cfg.SyncWord = sync
// Read Frequency.
err = d.read(regFRF_MSB, buf[:3])
if err != nil {
return cfg, err
}
freq := uint64(buf[0])<<16 | uint64(buf[1])<<8 | uint64(buf[2])
cfg.Frequency = lora.Frequency((freq * 15625) >> 8)
// Read IQ inversion.
@@ -617,6 +684,13 @@ func (d *DeviceLoRa) setPreambleLength(pLen uint16) error {
return d.write8(regPREAMBLE_LSB, buf[1])
}
func (d *DeviceLoRa) setMaxPayloadLength(plen uint8) error {
if plen == 0 {
return io.ErrShortBuffer
}
return d.write8(regPAYLOAD_LENGTH, plen)
}
func (d *DeviceLoRa) enableTxContinuousMode(enable bool) error {
return d.writeMasked8(regMODEM_CONFIG_2, 1<<3, b2u8(enable)<<3)
}
@@ -729,7 +803,7 @@ func (d *DeviceLoRa) enableLowFrequencyMode(b bool) error {
// enableCRC enables/disables CRC generation and checking.
func (d *DeviceLoRa) enableCRC(b bool) error {
const crcMask = 1 << 2
const crcMask = 0b11 << 2
return d.writeMasked8(regMODEM_CONFIG_2, crcMask, b2u8(b)<<2)
}
@@ -768,9 +842,14 @@ func (d *DeviceLoRa) writeMasked8(addr uint8, mask, value byte) error {
if err != nil {
return err
}
existing &^= mask // remove mask bits from register value.
existing |= mask & value // add value's bits as masked.
return d.write8(addr, existing)
err = d.write8(addr, existing)
if debugBufSize > 0 {
d.debugMask[addr] = mask
}
return err
}
func (d *DeviceLoRa) read8(addr byte) (byte, error) {
@@ -779,6 +858,9 @@ func (d *DeviceLoRa) read8(addr byte) (byte, error) {
d.csEnable(true)
err := d.bus.Tx(writeBuf, readBuf)
d.csEnable(false)
if debugBufSize > 0 {
d.debugRead[addr] = readBuf[1]
}
return readBuf[1], err
}
@@ -788,6 +870,11 @@ func (d *DeviceLoRa) write8(addr, value byte) error {
d.csEnable(true)
err := d.bus.Tx(writeBuf, readBuf)
d.csEnable(false)
if debugBufSize > 0 {
d.debugWrite[addr] = value
d.debugMask[addr] = 0xFF
d.read8(addr) // refresh address value.
}
return err
}
@@ -834,7 +921,7 @@ func (d *DeviceLoRa) readerToLastPacket() (_ *fifoReader, err error) {
runtime.Gosched()
}
if irqFlags&mustBeUnset != 0 {
return nil, errors.New("timeout waiting for IRQ before reading packet")
return nil, errors.New("timeout waiting for IRQ before reading packet:" + irqFlagsString(irqFlags))
}
// We now know that the packet has been received succesfully. Proceed to read.
@@ -846,6 +933,9 @@ func (d *DeviceLoRa) readerToLastPacket() (_ *fifoReader, err error) {
if err != nil {
return nil, err
}
if numBytes == 0 {
return nil, errors.New("readerToNextPacket called with RX_NB_BYTES=0")
}
err = d.write8(regFIFO_ADDR_PTR, curraddr)
if err != nil {
return nil, err