aboutsummaryrefslogtreecommitdiff
path: root/lora/stuff.go
blob: 1cee21ac557a984aef257a62dd4b12b501761abf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
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
}