forked from ExpressLRS/ExpressLRS
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFHSS.cpp
More file actions
169 lines (146 loc) · 5.46 KB
/
FHSS.cpp
File metadata and controls
169 lines (146 loc) · 5.46 KB
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#include "FHSS.h"
uint8_t volatile FHSSptr = 0;
uint8_t FHSSsequence[256] = {0};
//uint8_t NumOfFHSSfrequencies = 20;
int32_t FreqCorrection = 0;
void ICACHE_RAM_ATTR FHSSsetCurrIndex(uint8_t value)
{ // set the current index of the FHSS pointer
FHSSptr = value;
}
uint8_t ICACHE_RAM_ATTR FHSSgetCurrIndex()
{ // get the current index of the FHSS pointer
return FHSSptr;
}
uint32_t ICACHE_RAM_ATTR GetInitialFreq()
{
return FHSSfreqs[0] - FreqCorrection;
}
uint32_t ICACHE_RAM_ATTR FHSSgetCurrFreq()
{
return FHSSfreqs[FHSSsequence[FHSSptr]] - FreqCorrection;
}
uint32_t ICACHE_RAM_ATTR FHSSgetNextFreq()
{
FHSSptr++;
return FHSSgetCurrFreq();
}
// Set all of the flags in the array to true, except for the first one
// which corresponds to the sync channel and is never available for normal
// allocation.
void resetIsAvailable(uint8_t *array)
{
// channel 0 is the sync channel and is never considered available
array[0] = 0;
// all other entires to 1
for (unsigned int i = 1; i < NR_FHSS_ENTRIES; i++)
array[i] = 1;
}
/**
Requirements:
1. 0 every n hops
2. No two repeated channels
3. Equal occurance of each (or as even as possible) of each channel
4. Pesudorandom
Approach:
Initialise an array of flags indicating which channels have not yet been assigned and a counter of how many channels are available
Iterate over the FHSSsequence array using index
if index is a multiple of SYNC_INTERVAL assign the sync channel index (0)
otherwise, generate a random number between 0 and the number of channels left to be assigned
find the index of the nth remaining channel
if the index is a repeat, generate a new random number
if the index is not a repeat, assing it to the FHSSsequence array, clear the availability flag and decrement the available count
if there are no available channels left, reset the flags array and the count
*/
void FHSSrandomiseFHSSsequence()
{
#ifdef Regulatory_Domain_AU_915
Serial.println("Setting 915MHz Mode");
#elif defined Regulatory_Domain_FCC_915
Serial.println("Setting 915MHz Mode");
#elif defined Regulatory_Domain_EU_868
Serial.println("Setting 868MHz Mode");
#elif defined Regulatory_Domain_AU_433
Serial.println("Setting 433MHz EU Mode");
#elif defined Regulatory_Domain_EU_433
Serial.println("Setting 433MHz EU Mode");
#elif defined Regulatory_Domain_ISM_2400
Serial.println("Setting 2400MHz Mode");
#else
#error No regulatory domain defined, please define one in common.h
#endif
Serial.print("Number of FHSS frequencies =");
Serial.println(NR_FHSS_ENTRIES);
long macSeed = ((long)UID[2] << 24) + ((long)UID[3] << 16) + ((long)UID[4] << 8) + UID[5];
rngSeed(macSeed);
uint8_t isAvailable[NR_FHSS_ENTRIES];
resetIsAvailable(isAvailable);
// Fill the FHSSsequence with channel indices
// The 0 index is special - the 'sync' channel. The sync channel appears every
// syncInterval hops. The other channels are randomly distributed between the
// sync channels
const int SYNC_INTERVAL = NR_FHSS_ENTRIES -1;
int nLeft = NR_FHSS_ENTRIES - 1; // how many channels are left to be allocated. Does not include the sync channel
unsigned int prev = 0; // needed to prevent repeats of the same index
// for each slot in the sequence table
for (int i = 0; i < NR_SEQUENCE_ENTRIES; i++)
{
if (i % SYNC_INTERVAL == 0)
{
// assign sync channel 0
FHSSsequence[i] = 0;
prev = 0;
}
else
{
// pick one of the available channels. May need to loop to avoid repeats
unsigned int index;
do
{
int c = rngN(nLeft); // returnc 0<c<nLeft
// find the c'th entry in the isAvailable array
// can skip 0 as that's the sync channel and is never available for normal allocation
index = 1;
int found = 0;
while (index < NR_FHSS_ENTRIES)
{
if (isAvailable[index])
{
if (found == c)
break;
found++;
}
index++;
}
if (index == NR_FHSS_ENTRIES)
{
// This should never happen
Serial.print("FAILED to find the available entry!\n");
// What to do? We don't want to hang as that will stop us getting to the wifi hotspot
// Use the sync channel
index = 0;
break;
}
} while (index == prev); // can't use index if it repeats the previous value
FHSSsequence[i] = index; // assign the value to the sequence array
isAvailable[index] = 0; // clear the flag
prev = index; // remember for next iteration
nLeft--; // reduce the count of available channels
if (nLeft == 0)
{
// we've assigned all of the channels, so reset for next cycle
resetIsAvailable(isAvailable);
nLeft = NR_FHSS_ENTRIES - 1;
}
}
Serial.print(FHSSsequence[i]);
if ((i + 1) % 10 == 0)
{
Serial.println();
}
else
{
Serial.print(" ");
}
} // for each element in FHSSsequence
Serial.println();
}