add barebones

This commit is contained in:
soypat
2023-05-25 15:15:48 -03:00
parent 41e514150d
commit c20a7a3d40
9 changed files with 298 additions and 45 deletions
+112
View File
@@ -0,0 +1,112 @@
package sx127x
import (
"errors"
"github.com/soypat/lora"
)
type DeviceLoRaBare struct {
DL DeviceLoRa
}
func (d *DeviceLoRaBare) Configure(c lora.Config) (err error) {
err = d.DL.InitLoRaMode()
if err != nil {
return err
}
err = d.DL.SetOpMode(OpSleep)
if err != nil {
return err
}
// 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) 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
}
+4 -5
View File
@@ -53,7 +53,7 @@ func _() {
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{
var __reg_map = [0x4d+1]string{
0: __reg_name[0:5],
1: __reg_name[5:13],
6: __reg_name[13:21],
@@ -98,13 +98,12 @@ var __reg_map = map[regstr]string{
}
func (i regstr) valid() bool {
_, ok := __reg_map[i]
return ok
return i >= 0 && i < regstr(len(__reg_map))-1 && __reg_map[i] != ""
}
func (i regstr) String() string {
if str, ok := __reg_map[i]; ok {
return str
if i.valid() {
return __reg_map[i]
}
return "regstr(" + strconv.FormatInt(int64(i), 10) + ")"
}
+33 -13
View File
@@ -82,7 +82,7 @@ func DefaultConfig(freq lora.Frequency) lora.Config {
return lora.Config{
Frequency: freq,
SpreadFactor: lora.SF7,
Bandwidth: 125 * lora.KiloHertz,
Bandwidth: 125 * lora.Kilohertz,
CodingRate: lora.CR4_5,
PreambleLength: 8,
HeaderType: lora.HeaderExplicit,
@@ -118,6 +118,25 @@ var (
errImplicitPacketTooLarge = errors.New("packet length exceeds MaxImplicitPayloadLength")
)
func (d *DeviceLoRa) InitLoRaMode() (err error) {
d.Reset()
if !d.IsConnected() {
return ErrNotDetected
}
// We need to be in sleep mode to set LoRa mode if in FSK/OOK.
d.Write8(regOP_MODE, opmSLEEP) // No need to check error, do it in SetOpmode.
if !d.IsConnected() {
return ErrNotDetected
}
err = d.SetOpMode(OpSleep)
if err != nil {
return err
}
time.Sleep(15 * time.Millisecond) // Wait for sleep to take effect.
d.Write8(regIRQ_FLAGS, 0xff) // Clear interrupts
return nil
}
func (d *DeviceLoRa) Configure(cfg lora.Config) (err error) {
switch {
case cfg.SpreadFactor < lora.SF6 || cfg.SpreadFactor > lora.SF12:
@@ -128,7 +147,7 @@ func (d *DeviceLoRa) Configure(cfg lora.Config) (err error) {
err = errPreambleTooShort
case cfg.CodingRate < lora.CR4_5 || cfg.CodingRate > lora.CR4_8:
err = errBadCodingRate
case cfg.Frequency < 175*lora.MegaHertz && cfg.Bandwidth > 125*lora.KiloHertz:
case cfg.Frequency < 175*lora.Megahertz && cfg.Bandwidth > 125*lora.Kilohertz:
err = errUnsupportedBandwidth
case cfg.HeaderType != lora.HeaderImplicit && cfg.HeaderType != lora.HeaderExplicit:
err = errors.New("bad header type")
@@ -140,17 +159,10 @@ func (d *DeviceLoRa) Configure(cfg lora.Config) (err error) {
if err != nil {
return err
}
d.Reset()
// We need to be in sleep mode to set LoRa mode if in FSK/OOK.
d.Write8(regOP_MODE, opmSLEEP) // No need to check error, do it in SetOpmode.
if !d.IsConnected() {
return ErrNotDetected
}
err = d.SetOpMode(OpSleep)
err = d.InitLoRaMode()
if err != nil {
return err
}
time.Sleep(15 * time.Millisecond) // Wait for sleep to take effect.
err = d.setFrequency(cfg.Frequency)
if err != nil {
return err
@@ -313,6 +325,7 @@ func (d *DeviceLoRa) Tx(packet []byte) (err error) {
return err
}
if opmode != OpStandby && opmode != OpSleep {
// TODO: remove this once validated.
println("unexpected opmode before Tx:", opmode.String())
err = d.SetOpMode(OpSleep)
if err != nil {
@@ -570,7 +583,7 @@ func (d *DeviceLoRa) clearIRQ(toClear uint8) error {
if err != nil {
return err
}
time.Sleep(500 * time.Millisecond)
time.Sleep(1 * time.Millisecond)
reg, _ := d.read8(regIRQ_FLAGS)
if reg&toClear != 0 {
return errIRQNotCleared
@@ -808,12 +821,17 @@ func paBoostPowReg(txPow int8) (OutputPower uint8) {
}
// SetOCP defines Overload Current Protection configuration. It receives
// the max current (Imax) in milliamperes.
// the max current (Imax) in milliamperes. Set with mA=0 to disable OCP.
func (d *DeviceLoRa) SetOCP(mA uint8) error {
const ocpEnabledMask = 1 << 5
return d.Write8(regOCP, ocpEnabledMask|(0x1F&ocpTrim(mA)))
if mA == 0 {
return d.writeMasked8(regOCP, ocpEnabledMask, 0)
}
return d.Write8(regOCP, ocpEnabledMask|ocpTrim(mA))
}
// ocpTrim returns the register value for the Overload Current Protection.
// It ensures a max error of 10mA (see tests).
func ocpTrim(imax uint8) uint8 {
if imax < 45 {
imax = 45 // Absolute minimum is 45mA.
@@ -972,7 +990,9 @@ func (d *DeviceLoRa) Write8(addr, value byte) error {
}
func (d *DeviceLoRa) csEnable(b bool) {
time.Sleep(100 * time.Nanosecond) // 100ns is the minimum CS de-assertion time page 22.
d.cs(!b)
time.Sleep(30 * time.Nanosecond) // 30ns is the minimum CS assertion time for setups.
}
//go:inline