Files
2023-06-12 00:09:27 -03:00

163 lines
3.9 KiB
Go

package sx127x
import (
"errors"
"time"
"github.com/soypat/lora"
)
type DeviceLoRaBare struct {
DL DeviceLoRa
}
func (d *DeviceLoRaBare) Configure(c lora.Config) (err error) {
// Taken from both:
// pico-lorawan/src/lorawan.c
// pico-lorawan/lib/LoRaMac-node/src/radio/sx1276/sx1276.c
d.DL.Reset()
// Seems to take just under ~6ms. Wait 20ms.
err = d.DL.rxFSKChainCalibration(20 * time.Millisecond)
if err != nil {
return err
}
err = d.SetOpModeBare(OpSleep)
// err = d.DL.InitLoRaMode()
if err != nil {
return err
}
for _, irv := range initRegValues {
err = d.setModem(irv.modem)
if err != nil {
return err
}
err = d.DL.Write8(irv.addr, irv.val)
if err != nil {
return err
}
}
return d.setModem(modeFSK)
// Set up FIFO
// We configure so that we can use the entire 256 byte FIFO for either receive
// or transmit, but not both at the same time
d.DL.Write8(regFIFO_TX_BASE_ADDR, 0)
d.DL.Write8(regFIFO_RX_BASE_ADDR, 0)
// Bw125Cr45Sf128
d.DL.Write8(regMODEM_CONFIG_1, 0x72)
d.DL.Write8(regMODEM_CONFIG_2, 0x74)
d.DL.Write8(regMODEM_CONFIG_3, 0x00)
d.DL.setPreambleLength(8)
d.DL.setFrequency(lora.Freq169_4M)
return d.crappySetTxPower(13, false)
}
func (d *DeviceLoRaBare) crappySetTxPower(power int8, useRFO bool) (err error) {
if useRFO {
if power > 14 {
power = 14
} else if power < -1 {
power = -1
}
err = d.DL.Write8(regPA_CONFIG, 0x70|uint8(power+1))
} else {
if power > 23 {
power = 23
} else {
power = 5
}
// For RH_RF95_PA_DAC_ENABLE, manual says '+20dBm on PA_BOOST when OutputPower=0xf'
// RH_RF95_PA_DAC_ENABLE actually adds about 3dBm to all power levels. We will us it
// for 21, 22 and 23dBm
if power > 20 {
d.DL.Write8(regPA_DAC, 0x07)
power -= 3
} else {
d.DL.Write8(regPA_DAC, 0x04)
}
// RFM95/96/97/98 does not have RFO pins connected to anything. Only PA_BOOST
// pin is connected, so must use PA_BOOST
// Pout = 2 + OutputPower.
// The documentation is pretty confusing on this topic: PaSelect says the max power is 20dBm,
// but OutputPower claims it would be 17dBm.
const paSelect = 0x80
err = d.DL.Write8(regPA_CONFIG, paSelect|uint8(power-5))
}
return err
}
func (d *DeviceLoRaBare) SetOpModeBare(mode OpMode) (err error) {
return d.DL.writeMasked8(regOP_MODE, uint8(mode), 0x07)
}
func (d *DeviceLoRaBare) Send(packet []byte) (err error) {
if len(packet) > 251 {
return errors.New("too long")
}
gotmode, err := d.DL.GetOpMode()
if err != nil {
return err
}
if gotmode != OpStandby && gotmode != OpSleep {
return errors.New("not in standby or sleep before Tx")
}
err = d.DL.SetOpMode(OpStandby)
if err != nil {
return err
}
// Position at the beginning of the FIFO.
d.DL.Write8(regFIFO_ADDR_PTR, 0)
for i := range packet {
d.DL.Write8(regFIFO, packet[i])
}
d.DL.Write8(regPAYLOAD_LENGTH, uint8(len(packet)))
err = d.DL.SetOpMode(OpTx)
if err != nil {
return err
}
return d.DL.SetIRQTxDoneOnDIO0()
}
func (d *DeviceLoRaBare) HandleInterrupt() {
flags, _ := d.DL.read8(regIRQ_FLAGS)
if flags != 0 {
println("got irqs:", irqFlagsString(flags))
}
// Clear flags
d.DL.Write8(regIRQ_FLAGS, 0xff)
}
func (d *DeviceLoRaBare) Read(addr uint8) uint8 {
val, _ := d.DL.read8(addr)
return val
}
const modeFSK, modeLoRa = 0, 1
var initRegValues = []struct {
modem uint8
addr uint8
val uint8
}{
{modeFSK, regLNA, 0x23},
{modeFSK, regRXConfig, 0x1E},
{modeFSK, regRSSIConfig, 0xD2},
{modeFSK, regAFCFEI, 0x01},
{modeFSK, regPreambleDetect, 0xAA},
{modeFSK, regOsc, 0x07},
{modeFSK, regSyncConfig, 0x12},
{modeFSK, regSyncValue1, 0xC1},
{modeFSK, regSyncValue2, 0x94},
{modeFSK, regSyncValue3, 0xC1},
{modeFSK, regPacketConfig1, 0xD8},
{modeFSK, regFifoThresh, 0x8F},
{modeFSK, regImageCal, 0x02},
{modeFSK, regDIO_MAPPING_1, 0x00},
{modeFSK, regDIO_MAPPING_2, 0x30},
{modeLoRa, regDETECTION_OPTIMIZE, 0x43},
{modeLoRa, regMAX_PAYLOAD_LENGTH, 0x40},
}