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
+81
View File
@@ -0,0 +1,81 @@
package main
import (
"machine"
"time"
"github.com/soypat/lora"
"github.com/soypat/lora/sx127x"
)
const (
pinCS0 = machine.GPIO27
pinCS1 = machine.GPIO28
pinRST0 = machine.GPIO29
pinRST1 = machine.GPIO29
pinMOSI = machine.GPIO3
pinMISO = machine.GPIO4
pinSCK = machine.GPIO6
pinDIO0 = machine.GPIO7
)
var (
dev0, dev1 *sx127x.DeviceLoRaBare
cfg lora.Config
)
func main() {
time.Sleep(1500 * time.Millisecond)
println("program start")
var err error
setup()
defer println("program end")
packet := []byte("hello LoRa")
go func() {
var last bool
for {
time.Sleep(time.Millisecond * 10)
got := pinDIO0.Get()
if got != last {
println("DIO0 switch: ", got)
last = got
}
}
}()
for {
err = dev0.Configure(cfg)
for err == nil { // Tx Loop
println("transmitting packet")
err = dev0.Send(packet)
time.Sleep(10 * time.Second)
dev0.HandleInterrupt()
}
if err != nil {
println("got error: ", err.Error())
}
time.Sleep(time.Second)
}
}
func setup() {
var bus = machine.SPI0
err := bus.Configure(machine.SPIConfig{
Frequency: 10_000,
SCK: pinSCK,
SDO: pinMOSI,
SDI: pinMISO,
})
if err != nil {
panic(err.Error())
}
pinCS0.Configure(machine.PinConfig{Mode: machine.PinOutput})
pinCS1.Configure(machine.PinConfig{Mode: machine.PinOutput})
pinRST0.Configure(machine.PinConfig{Mode: machine.PinOutput})
pinRST1.Configure(machine.PinConfig{Mode: machine.PinOutput})
dev0 = &sx127x.DeviceLoRaBare{DL: *sx127x.NewLoRa(bus, pinCS0.Set, pinRST0.Set)}
pinDIO0.Configure(machine.PinConfig{Mode: machine.PinInputPulldown})
// dev1 = sx127x.NewLoRa(bus, pinCS1.Set, pinRST1.Set)
cfg = sx127x.DefaultConfig(lora.Freq433_0M)
cfg.TxPower = 10
}
+49 -17
View File
@@ -5,6 +5,7 @@ import (
"machine"
"time"
"github.com/soypat/lora"
"github.com/soypat/lora/sx127x"
)
@@ -20,6 +21,7 @@ const (
var (
dev0, dev1 *sx127x.DeviceLoRa
cfg lora.Config
)
func main() {
@@ -28,24 +30,20 @@ func main() {
var err error
setup()
defer println("program end")
var reg, fifo [256]byte
dev0.Reset()
if !dev0.IsConnected() {
panic("not connected")
packet := []byte("hello LoRa")
for {
err = dev0.Configure(cfg)
dev0.SetOCP(45)
for err == nil { // Tx Loop
println("transmitting packet")
err = dev0.Tx(packet)
time.Sleep(5 * time.Second)
}
if err != nil {
println("got error: ", err.Error())
}
time.Sleep(time.Second)
}
dev0.Write8(1, 0)
time.Sleep(100 * time.Millisecond)
// dev0.SetOpMode(sx127x.OpSleep)
err = dev0.SetOpMode(sx127x.OpSleep)
if err != nil {
panic(err.Error())
}
time.Sleep(100 * time.Millisecond)
err = dev0.FullStatus(fifo[:], reg[:])
if err != nil {
panic(err.Error())
}
fmt.Printf("reg: %v\n\nfifo: %v\n", reg[:], fifo[:])
}
func setup() {
@@ -65,4 +63,38 @@ func setup() {
pinRST1.Configure(machine.PinConfig{Mode: machine.PinOutput})
dev0 = sx127x.NewLoRa(bus, pinCS0.Set, pinRST0.Set)
dev1 = sx127x.NewLoRa(bus, pinCS1.Set, pinRST1.Set)
cfg = sx127x.DefaultConfig(lora.Freq433_0M)
cfg.TxPower = 10
}
func _() {
var err error
var reg, fifo [256]byte
dev0.Reset()
if !dev0.IsConnected() {
panic("not connected")
}
dev0.Write8(1, 0)
time.Sleep(100 * time.Millisecond)
// dev0.SetOpMode(sx127x.OpSleep)
err = dev0.SetOpMode(sx127x.OpSleep)
if err != nil {
panic(err.Error())
}
time.Sleep(100 * time.Millisecond)
err = dev0.FullStatus(fifo[:], reg[:])
if err != nil {
panic(err.Error())
}
fmt.Printf("precomreg: %v\n", reg[:0x7d+1])
err = dev0.Configure(cfg)
if err != nil {
panic(err.Error())
}
err = dev0.FullStatus(fifo[:], reg[:])
if err != nil {
panic(err.Error())
}
fmt.Printf("poscomreg: %v\n", reg[:0x7d+1])
}
+17 -6
View File
@@ -78,7 +78,7 @@ func (cfg *Config) TimeOnAir(payloadLength int) time.Duration {
Npayload += 8 + int64(cfg.PreambleLength) + 5
// Calculate LoRa Transmission Parameter Relationship page 28.
chipsPerSymbol := cfg.SpreadFactor.ChipsPerSymbol() // chips per symbol.
return time.Second * time.Duration(Npayload*chipsPerSymbol) /
return time.Second * time.Duration(Npayload*int64(chipsPerSymbol)) /
time.Duration(cfg.Bandwidth.Hertz())
}
@@ -127,6 +127,10 @@ const (
SF12
)
// ChipsPerSymbol returns the number of chips in a symbol. A chip is a subdivision
// of a symbol in the frequency domain rather than the time domain, which is why
// the units of this value is Hz, not Duration. A chip tells tells where to start
// the frequency sweep for a symbol.
func (sf SpreadFactor) ChipsPerSymbol() int64 {
return 1 << sf
}
@@ -139,17 +143,24 @@ type Frequency int64
func (f Frequency) Hertz() int64 { return int64(f) }
// Common frequency units.
//
// To count the number of units in a Frequency, divide:
//
// // How many hertz in a kilohertz?
// kiloHertz := lora.Kilohertz
// fmt.Print(int64(kiloHertz/lora.Hertz)) // prints 1000 (1000 hertz in a kilohertz)
const (
Hertz Frequency = 1
KiloHertz Frequency = 1000 * Hertz
MegaHertz Frequency = 1000 * KiloHertz
Kilohertz Frequency = 1000 * Hertz
Megahertz Frequency = 1000 * Kilohertz
)
// Common LoRa bandwidths
const (
BW125k = 125 * KiloHertz
BW250k = 250 * KiloHertz
BW500k = 500 * KiloHertz
BW125k = 125 * Kilohertz
BW250k = 250 * Kilohertz
BW500k = 500 * Kilohertz
)
// Common LoRa frequencies
+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
-2
View File
@@ -1,2 +0,0 @@
reg: [0 129 26 11 0 91 108 208 17 79 9 43 32 0 128 0 0 0 0 0 0 0 0 0 16 0 0 0 0 114 112 100 0 8 1 255 0 0 4 0 0 0 0 0 0 80 20 69 85 195 5 39 28 10 3 10 66 18 82 29 0 175 0 0 0 0 18 36 45 0 3 0 4 35 0 9 5 132 50 43 20 0 0 14 0 0 0 15 224 0 12 240 8 0 92 120 0 28 14 91 204 0 1 80 0 0 0 0 0 0 0 11 208 0 20 0 0 0 0 0 0 0 0 0 0 0 0 0 163 129 26 11 0 82 108 128 0 79 9 43 32 1 128 0 0 0 0 0 0 0 0 0 16 0 0 0 0 114 112 100 0 8 1 255 0 0 4 0 0 0 0 0 0 80 20 69 85 195 5 39 28 10 3 10 66 18 82 29 0 175 0 0 0 0 18 36 45 0 3 0 4 35 0 9 5 132 50 43 20 0 0 14 0 0 0 15 224 0 12 240 8 0 92 120 0 28 14 91 204 0 1 80 0 0 0 0 0 0 0 11 208 0 20 0 0 0 0 0 0 0 0 0 0 0 0 0]
fifo: [163 212 34 103 43 163 162 194 15 31 155 17 44 8 136 1 152 66 0 204 205 45 52 129 55 232 38 2 233 0 205 141 138 194 211 72 34 254 80 131 164 179 98 177 25 17 250 209 170 176 18 11 137 101 233 32 88 96 9 232 169 42 244 236 176 88 48 20 199 144 21 192 39 113 15 249 24 16 23 41 198 225 128 216 50 233 197 76 64 16 32 227 218 124 59 69 144 89 90 50 228 225 29 26 156 138 51 2 132 165 236 186 238 70 142 162 30 68 168 217 242 217 100 247 126 118 145 53 154 6 109 219 144 196 139 217 243 4 138 90 123 236 233 35 254 117 108 247 185 70 126 20 175 41 110 213 61 158 226 249 154 61 252 175 179 83 39 10 25 223 75 103 166 179 39 73 223 24 148 53 225 233 251 150 214 66 158 31 175 165 23 205 246 181 140 229 125 189 47 205 30 252 150 233 93 121 115 103 180 171 122 206 54 130 234 217 156 123 137 182 4 194 213 239 206 175 189 123 133 77 38 202 83 61 158 178 66 209 210 0 180 70 231 101 62 53 81 30 170 244 237 216 82 80 195 0]
-2
View File
@@ -1,2 +0,0 @@
reg: [0 129 18 10 21 0 148 72 144 72 9 42 32 2 0 0 36 10 5 5 0 0 0 0 10 5 0 0 5 0 130 65 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 128 64 20 137 18 10 1 1 1 0 0 0 1 0 8 0 128 64 0 0 1 0 0 0 128 64 0 0 128 9 128 64 168 32 69 9 164 82 164 82 82 41 0 0 0 0 0 0 128 64 0 82 0 41 128 0 64 32 0 41 64 64 41 32 148 32 36 129 132 10 0 82 72 128 0 128 9 42 32 9 0 0 65 0 0 0 0 0 0 0 16 0 0 0 0 66 64 68 40 137 0 64 64 64 0 0 0 0 0 0 0 128 128 42 32 0 72 72 0 9 0 42 16 72 0 0 72 128 128 64 0 129 18 0 0 132 0 0 0 0 9 42 0 0 72 0 0 0 0 66 0 0 0 0 16 0 0 0 0 128 128 66 64 32 128 16 0 132 0 0 0 128 128 0 33 128 132 66 132 16 64 64 72 0 0 72 66 64 72 0 33 160 144 0]
fifo: [36 16 64 64 64 64 34 41 8 0 0 0 0 68 2 16 66 16 72 10 41 68 64 0 0 0 0 0 1 36 16 0 0 0 64 72 36 4 18 0 0 0 0 0 0 0 0 18 18 21 9 36 64 0 0 0 66 72 34 32 0 0 0 0 0 0 8 34 73 68 66 66 17 0 0 0 0 0 0 64 16 5 2 20 64 64 0 0 0 0 18 10 18 69 18 32 0 64 64 17 82 66 9 17 82 42 9 17 144 64 0 0 16 64 80 34 0 0 0 0 0 0 65 20 9 32 21 32 34 84 81 16 2 0 0 0 0 0 0 16 16 81 20 41 9 8 0 0 0 0 0 0 0 0 0 36 66 18 10 0 0 0 0 18 72 80 136 0 0 0 0 64 136 17 32 74 36 73 17 0 0 0 0 0 74 69 64 81 80 34 0 0 0 1 2 65 64 0 0 0 2 0 9 144 40 18 0 0 0 0 0 2 64 2 9 74 33 65 16 32 0 0 0 64 17 68 17 4 64 16 68 81 2 5 36 0 0 0 0 0 64 36 4 32 68 65 32 136 74 18 34 73 4 0 0 0]
+2
View File
@@ -0,0 +1,2 @@
precomreg: [0 129 0 0 0 0 108 128 0 79 9 43 32 0 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 114 112 100 0 8 1 255 0 0 4 0 0 0 0 0 0 0 0 0 0 195 0 39 0 0 0 10 0 18 0 29 0 0 0 0 0 0 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
poscomreg: [0 129 0 0 0 0 108 83 44 240 9 43 32 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 114 119 255 0 8 1 255 0 0 4 0 0 0 0 0 0 0 0 0 0 195 0 39 0 0 0 10 0 52 0 29 0 0 0 0 0 0 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]