diff options
Diffstat (limited to 'lora')
| -rw-r--r-- | lora/helpers.go | 52 | ||||
| -rw-r--r-- | lora/stuff.go | 84 |
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 +} |
