aboutsummaryrefslogtreecommitdiff
path: root/lora
diff options
context:
space:
mode:
authorSmoke <[email protected]>2024-01-19 10:51:52 -1000
committerSmoke <[email protected]>2024-01-19 10:51:52 -1000
commit70bb2c77356d349165ba46ea98f8346284c2e44e (patch)
tree7a1f858ca12386f7bd9478550e29bf3c1af109b5 /lora
parent320bb2e1e7dfe5092ea1f6b65a9c6e53e58ce387 (diff)
updates
Diffstat (limited to 'lora')
-rw-r--r--lora/helpers.go52
-rw-r--r--lora/stuff.go84
2 files changed, 136 insertions, 0 deletions
diff --git a/lora/helpers.go b/lora/helpers.go
new file mode 100644
index 0000000..c843cc3
--- /dev/null
+++ b/lora/helpers.go
@@ -0,0 +1,52 @@
+package lora
+
+import "fmt"
+
+// translated from https://sensing-labs.com/f-a-q/a-good-radio-level/
+
+// Define signal quality and diagnostic notes.
+type signalQuality string
+type diagnosticNote string
+
+const (
+ Good signalQuality = "GOOD"
+ Fair signalQuality = "FAIR"
+ Bad signalQuality = "BAD"
+)
+
+// getSignalQuality determines the signal quality based on RSSI and SNR.
+func getSignalQuality(rssi, snr float64) signalQuality {
+ // Define the boundaries for GOOD signal quality
+ if snr >= -7 && rssi >= -115 {
+ return Good
+ }
+ // Define the boundaries for FAIR signal quality
+ if snr >= -15 && rssi >= -126 {
+ return Fair
+ }
+ // If none of the above conditions are met, signal is BAD
+ return Bad
+}
+
+// getDiagnosticNotes provides recommendations based on RSSI and SNR values.
+func getDiagnosticNotes(rssi, snr float64) diagnosticNote {
+ if rssi >= -115 && snr >= -7 {
+ return "RF level is optimal to get a good reception reliability."
+ } else if rssi >= -126 && snr >= -15 {
+ return "RF level is not optimal but must be sufficient. Try to improve your device position if possible. You will have to monitor the stability of the RF level."
+ } else {
+ return "NOISY environment. Try to put device out of electromagnetic sources."
+ }
+}
+
+func Demo() {
+ // Example usage
+ rssi := -120.0 // RSSI value
+ snr := -10.0 // SNR value
+
+ quality := getSignalQuality(rssi, snr)
+ notes := getDiagnosticNotes(rssi, snr)
+
+ fmt.Printf("The signal quality is %s.\n", quality)
+ fmt.Printf("Diagnostic Notes: %s\n", notes)
+}
diff --git a/lora/stuff.go b/lora/stuff.go
new file mode 100644
index 0000000..1cee21a
--- /dev/null
+++ b/lora/stuff.go
@@ -0,0 +1,84 @@
+// Package loraradio provides functionality to determine values for a LoRa radio link,
+// including maximum data rate and link budget while accounting for receiver sensitivity.
+package lora
+
+import (
+ "fmt"
+ "math"
+)
+
+// TODO: needs cleanup. lots of gpt generated code
+
+// MaxDataRate calculates the maximum data rate for a LoRa radio link based on the provided parameters.
+func MaxDataRate(bandwidth, spreadingFactor, codeRate float64) float64 {
+ // Assuming the LoRa modulation's data rate equation:
+ // Data Rate = BW / (2^SF) * CR
+ // where SF is the spreading factor, BW is the bandwidth in Hz, and CR is the code rate.
+ return (bandwidth / math.Pow(2, spreadingFactor)) * codeRate * spreadingFactor
+}
+
+// Simplified link budget calculation per the Semtech calculator
+func LinkBudget(rxSensitivity, transmitPower float64) float64 {
+ return transmitPower - rxSensitivity
+}
+
+// SensitivityParams holds the parameters used for sensitivity calculations.
+type SensitivityParams struct {
+ Bandwidth float64 // in Hz
+ ImplementationL float64 // Implementation loss in dB, typically 1-3 dB
+ SpreadingFactor int // LoRa Spreading Factor
+}
+
+// SpreadingFactorData holds the data for each spreading factor.
+type SpreadingFactorData struct {
+ SF int
+ ChipsPerSymbol int
+ DemodulatorSNR float64
+}
+
+var SpreadingFactors = []SpreadingFactorData{
+ {SF: 5, ChipsPerSymbol: 32, DemodulatorSNR: -2.5},
+ {SF: 6, ChipsPerSymbol: 64, DemodulatorSNR: -5},
+ {SF: 7, ChipsPerSymbol: 128, DemodulatorSNR: -7.5},
+ {SF: 8, ChipsPerSymbol: 256, DemodulatorSNR: -10},
+ {SF: 9, ChipsPerSymbol: 512, DemodulatorSNR: -12.5},
+ {SF: 10, ChipsPerSymbol: 1024, DemodulatorSNR: -15},
+ {SF: 11, ChipsPerSymbol: 2048, DemodulatorSNR: -17.5},
+ {SF: 12, ChipsPerSymbol: 4096, DemodulatorSNR: -20},
+}
+
+// CalculateSensitivity calculates the LoRa receiver sensitivity based on the provided parameters.
+func CalculateSensitivity(params SensitivityParams, spreadingFactors []SpreadingFactorData) (float64, error) {
+ if params.Bandwidth <= 0 {
+ return 0, fmt.Errorf("bandwidth must be greater than 0")
+ }
+
+ // Find the SNR for the given spreading factor from the provided data.
+ var snr float64
+ found := false
+ for _, sfData := range spreadingFactors {
+ if sfData.SF == params.SpreadingFactor {
+ snr = sfData.DemodulatorSNR
+ found = true
+ break
+ }
+ }
+ if !found {
+ return 0, fmt.Errorf("spreading factor data not found for SF=%d", params.SpreadingFactor)
+ }
+
+ // Thermal noise in dBm for the given bandwidth at room temperature (290K).
+ thermalNoise := -174.0 // dBm/Hz
+
+ // Noise figure in dBm for the given bandwidth.
+ noiseFigure := thermalNoise + 10*math.Log10(params.Bandwidth)
+
+ // Receiver sensitivity calculation in dBm.
+ sensitivity := noiseFigure + snr + params.ImplementationL
+
+ return sensitivity, nil
+}
+func SNR(spreadingFactor int) float64 {
+ result := (float64(spreadingFactor) - 4) * -2.5
+ return result * 100 / 100
+}