attempt RxSingle routine

This commit is contained in:
soypat
2023-05-21 00:57:43 -03:00
parent 0df54699a6
commit 3d2821d0b6
2 changed files with 121 additions and 27 deletions
+21 -14
View File
@@ -51,20 +51,27 @@ func main() {
if err != nil {
panic(err.Error())
}
println("config success")
for {
rssiRead, err := dev.EstimateReadFromRSSIPeriod(time.Second)
if err != nil {
panic(err.Error())
}
println("rssiRead:", rssiRead.String())
}
tstart := time.Now()
var rng [4]byte
err = dev.RandomRead(rng[:], 0)
if err != nil {
panic(err.Error())
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)
if err != nil {
println("got error transmitting:", err.Error())
} else {
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]))
}
}
fmt.Printf("random bytes: %b\nelapsed:%s\n", rng, time.Since(tstart).String())
}
+100 -13
View File
@@ -84,6 +84,9 @@ var (
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")
)
func (d *DeviceLoRa) Configure(cfg lora.Config) (err error) {
@@ -250,6 +253,7 @@ func (d *DeviceLoRa) EnableAutoGainControl(b bool) error {
return d.writeMasked8(regMODEM_CONFIG_3, agcMask, b2u8(b)<<2)
}
// Tx sends packet over LoRa network and blocks until packet is done sending.
func (d *DeviceLoRa) Tx(packet []byte) (err error) {
if len(packet) > 255 {
return errors.New("packet too long")
@@ -291,18 +295,19 @@ func (d *DeviceLoRa) Tx(packet []byte) (err error) {
if err != nil {
return err
}
counts := 0
var reg uint8
for {
counts++
reg, err = d.read8(regIRQ_FLAGS)
if reg&irqTXDONE_MASK != 0 || err != nil {
if err != nil {
return err
}
break
}
var irq uint8
for irq&irqTXDONE_MASK == 0 {
runtime.Gosched() // Yield to scheduler.
irq, err = d.read8(regIRQ_FLAGS)
if err != nil {
d.SetOpMode(OpSleep) // Back to sleep in case of error.
return err
}
}
// Go back to sleep to be able to write to static registers.
err = d.SetOpMode(OpSleep)
if err != nil {
return err
}
err = d.clearIRQ(irqTXDONE_MASK)
if err != nil {
@@ -311,6 +316,84 @@ func (d *DeviceLoRa) Tx(packet []byte) (err error) {
return nil
}
func (d *DeviceLoRa) RxSingle(dst []byte) (uint8, error) {
op, err := d.GetOpMode()
switch {
case err != nil:
// err already set
case len(dst) < 255:
err = io.ErrShortBuffer
case op == OpTx || op == OpRx || op == OpRxSingle:
err = ErrDeviceBusy // Device is currently transmitting or receiving.
}
if err != nil {
return 0, err
}
// Reset packet pointers.
const fifoAddr = 0
err = d.prepareForRx(fifoAddr)
if err != nil {
return 0, err
}
// Begin looking for packets immediately until first one found (RxSingle mode).
err = d.SetOpMode(OpRxSingle)
if err != nil {
return 0, err
}
defer d.SetOpMode(OpSleep) // Ensure Sleep Mode on exit.
// Loop until Rx received or timeout IRQ.
var irq uint8
for irq&(irqRXDONE_MASK|irqRXTOUT_MASK) == 0 {
runtime.Gosched() // Yield to scheduler.
irq, err = d.read8(regIRQ_FLAGS)
if err != nil {
return 0, err
}
}
// Check for payload integrity and timeout interrupt.
if irq&irqCRCERR_MASK != 0 {
return 0, ErrCRC
} else if irq&irqRXTOUT_MASK != 0 {
return 0, ErrRxTimeout
}
// TODO(soypat): This should already be in standby mode according to datasheet.
// remove once confirmed it does not affect behaviour. Needed to read FIFO addr.
err = d.SetOpMode(OpStandby)
if err != nil {
return 0, err
}
// Ready to read packet! Rewrite FifoAddrPtr just in case...
d.write8(regFIFO_ADDR_PTR, fifoAddr)
nbBytes, err := d.read8(regRX_NB_BYTES)
if err != nil {
return 0, err
}
for i := uint8(0); i < nbBytes; i++ {
dst[i], err = d.read8(regFIFO)
if err != nil {
return i, err
}
}
return nbBytes, nil
}
func (d *DeviceLoRa) prepareForRx(fifoAddr uint8) (err error) {
err = d.SetOpMode(OpStandby) // Standby mode needed so that FIFO can be written/read.
if err != nil {
return err
}
err = d.clearIRQ(irqRXDONE_MASK | irqHEADER_MASK | irqCRCERR_MASK | irqRXTOUT_MASK)
if err != nil {
return err
}
err = d.write8(regFIFO_RX_BASE_ADDR, fifoAddr)
if err != nil {
return err
}
return d.write8(regFIFO_ADDR_PTR, fifoAddr)
}
// clearIRQ clears IRQ bits indicated by toClear:
// - bit 0: CAD detected interrupt
// - bit 1: FHSS change channel interrupt
@@ -325,8 +408,10 @@ func (d *DeviceLoRa) clearIRQ(toClear uint8) error {
if err != nil {
return err
}
time.Sleep(500 * time.Millisecond)
reg, _ := d.read8(regIRQ_FLAGS)
if reg&toClear != 0 {
println(reg, toClear)
return errIRQNotCleared
}
return nil
@@ -347,6 +432,8 @@ func (d *DeviceLoRa) RandomU32() (rnd uint32, err error) {
// The period between RSSI reads is readFromRSSIPeriod. A higher readFromRSSIPeriod
// will typically result in higher entropy in the random data. 10ms is a reasonable period.
// This method will take approximately readFromRSSIPeriod*len(dst)*8 + 50ms to complete.
//
// See EstimateReadFromRSSIPeriod method.
func (d *DeviceLoRa) RandomRead(dst []byte, readFromRSSIPeriod time.Duration) error {
// Disable ALL irqs
err := d.clearIRQ(0xff)
@@ -596,8 +683,8 @@ func (d *DeviceLoRa) enableCRC(b bool) error {
//
// Timeout = timeoutSymbols * Ts (where Ts is the symbol period)
func (d *DeviceLoRa) setTimeoutInSymbols(symbTimeout uint16) (err error) {
if symbTimeout > 0x3FF {
return errors.New("timeout value too large")
if symbTimeout > 0x3FF || symbTimeout < 4 {
return errors.New("symbol timeout must be in range 4..1023")
}
err = d.writeMasked8(regMODEM_CONFIG_2, 0b11, byte(symbTimeout>>8))
if err != nil {