diff --git a/sx127x/barebones.go b/sx127x/barebones.go index 2ef4912..fed2583 100644 --- a/sx127x/barebones.go +++ b/sx127x/barebones.go @@ -2,6 +2,7 @@ package sx127x import ( "errors" + "time" "github.com/soypat/lora" ) @@ -11,14 +12,18 @@ type DeviceLoRaBare struct { } func (d *DeviceLoRaBare) Configure(c lora.Config) (err error) { - err = d.DL.InitLoRaMode() + 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.DL.SetOpMode(OpSleep) + err = d.SetOpModeBare(OpSleep) + // err = d.DL.InitLoRaMode() 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 @@ -69,6 +74,10 @@ func (d *DeviceLoRaBare) crappySetTxPower(power int8, useRFO bool) (err error) { 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") diff --git a/sx127x/sx127x.go b/sx127x/sx127x.go index b7c5a7a..a0033d3 100644 --- a/sx127x/sx127x.go +++ b/sx127x/sx127x.go @@ -82,7 +82,7 @@ func DefaultConfig(freq lora.Frequency) lora.Config { return lora.Config{ Frequency: freq, SpreadFactor: lora.SF7, - Bandwidth: 125 * lora.Kilohertz, + Bandwidth: lora.BW125k, CodingRate: lora.CR4_5, PreambleLength: 8, HeaderType: lora.HeaderExplicit, @@ -110,7 +110,7 @@ var ( errBadMode = errors.New("bad op mode: sx127x in FSK/OOK mode, not LoRa or viceversa") errSharedMode = errors.New("bad op mode: sx127x in shared access mode") errBadCodingRate = errors.New("bad coding rate") - errUnsupportedBandwidth = errors.New("bandwidth too high for frequency around 169MHz") + errUnsupportedBandwidth = errors.New("unsupported bandwidth") errIRQNotCleared = errors.New("IRQs not cleared") ErrDeviceBusy = errors.New("device busy") ErrCRC = errors.New("crc error") @@ -147,7 +147,8 @@ 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 || + (cfg.Bandwidth > 500*lora.Kilohertz): // according to a famous library 500kHz is limit? todo: check this. err = errUnsupportedBandwidth case cfg.HeaderType != lora.HeaderImplicit && cfg.HeaderType != lora.HeaderExplicit: err = errors.New("bad header type") @@ -239,11 +240,11 @@ func (d *DeviceLoRa) Configure(cfg lora.Config) (err error) { func (d *DeviceLoRa) Reset() { d.rst(true) - time.Sleep(200 * time.Millisecond) + time.Sleep(6 * time.Millisecond) d.rst(false) - time.Sleep(200 * time.Millisecond) + time.Sleep(1 * time.Millisecond) d.rst(true) - time.Sleep(200 * time.Millisecond) + time.Sleep(6 * time.Millisecond) } // IsConnected reads the version register and checks if it matches the expected value. @@ -1110,3 +1111,62 @@ func (f *fifoReader) readInternal(buf []byte) (_ uint8, err error) { f.leftToRead -= toRead return toRead, nil } + +func (d *DeviceLoRa) rxFSKChainCalibration(timeout time.Duration) error { + deadline := time.Now().Add(timeout) + // Store configuration subject to change. + cfg, err := d.ReadConfig() + if err != nil { + return err + } + paCfgInitVal, err := d.read8(regPA_CONFIG) + if err != nil { + return err + } + d.Write8(regPA_CONFIG, 0x00) // Cut PA just in case. + + // Launch Rx chain calibration for LF band + err = d.imageCal(deadline) + if err != nil { + return err + } + // Launch calibration in HF band. + err = d.setFrequency(lora.Freq868_1M) + if err != nil { + return err + } + err = d.imageCal(deadline) + if err != nil { + return err + } + // Restore initial configuration. + err = d.Write8(regPA_CONFIG, paCfgInitVal) + if err != nil { + return err + } + return d.setFrequency(cfg.Frequency) +} + +func (d *DeviceLoRa) imageCal(deadline time.Time) error { + const imageCalStart, imageCalMask = 0x40, 0xBF + err := d.writeMasked8(regImageCal, imageCalMask, imageCalStart) + if err != nil { + return err + } + + for time.Now().Before(deadline) { + const imageCalRunning = 0x20 + got, err := d.read8(regImageCal) + if err != nil { + return err + } + if got&imageCalRunning != imageCalRunning { + break + } + runtime.Gosched() + } + if !time.Now().Before(deadline) { + return errors.New("imageCal timeout") + } + return nil +}