This repository has been archived by the owner on Sep 15, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathlongfi.c
334 lines (303 loc) · 9.12 KB
/
longfi.c
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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
#include "board.h"
#include "longfiP.h"
#include <string.h>
uint16_t BufferSize = BUFFER_SIZE;
uint8_t Buffer[BUFFER_SIZE];
int16_t RssiValue = 0;
int8_t SnrValue = 0;
static LongFiInternal_t internal;
LongFi_t
longfi_new_handle(BoardBindings_t * bindings,
Radio_t * radio,
LongFiConfig_t config,
union LongFiAuthCallbacks auth_cb_set)
{
LongFi_t handle = {.radio = radio,
.config = config,
.bindings = bindings,
.auth_cb = auth_cb_set,
.lfc = {
.seq = 0,
.cfg =
{
.cb_data = NULL,
.oui = config.oui,
.did = config.device_id,
.key = auth_cb_set.preshared_key,
.key_len = 16,
},
}};
return handle;
}
void
longfi_init(LongFi_t * handle)
{
// store pointer to internal context for callback definitions
bindings = handle->bindings;
switch
LORA_SPREADING_FACTOR
{
case 10:
internal.spreading_factor = 3;
break;
case 9:
internal.spreading_factor = 2;
break;
case 8:
internal.spreading_factor = 1;
break;
case 7:
internal.spreading_factor = 0;
break;
default:
internal.spreading_factor = 2;
}
// configure sx1276 radio events with local helium functions
internal.radio_events.TxDone = OnTxDone;
internal.radio_events.RxDone = OnRxDone;
internal.radio_events.TxTimeout = OnTxTimeout;
internal.radio_events.RxTimeout = OnRxTimeout;
internal.radio_events.RxError = OnRxError;
// this function calls TimerInits and handle->radio->IoIrqInit, which are
// implemented here
handle->radio->Init(&internal.radio_events);
// sleep the radio and wait for a send or receive call
handle->radio->Sleep();
}
void
longfi_set_buf(LongFi_t * handle, uint8_t * buffer, size_t buffer_len)
{
internal.buffer = buffer;
internal.buffer_len = (buffer != NULL) ? buffer_len : 0;
}
void
longfi_rx(LongFi_t * handle)
{
handle->radio->Rx(0);
}
#define MIN(x, y) \
({ \
typeof(x) _x = (x); \
typeof(y) _y = (y); \
(void)(&_x == &_y); \
_x < _y ? _x : _y; \
})
// number of bytes in a fragment
size_t
payload_bytes_in_single_fragment_packet()
{
return payload_per_fragment[internal.spreading_factor]
- sizeof(packet_header_t);
}
// number of bytes in a fragment
size_t
payload_bytes_in_first_fragment_of_many()
{
return payload_per_fragment[internal.spreading_factor]
- sizeof(packet_header_multiple_fragments_t);
}
// number of bytes in a fragment
size_t
payload_bytes_in_subsequent_fragments()
{
return payload_per_fragment[internal.spreading_factor]
- sizeof(fragment_header_t);
}
void
longfi_rf_test(LongFi_t * handle)
{
uint8_t dummy_data = 0xAB;
handle->radio->SetTxConfig(MODEM_LORA,
TX_OUTPUT_POWER,
0,
LORA_BANDWIDTH,
LORA_SPREADING_FACTOR,
LORA_CODINGRATE,
LORA_PREAMBLE_LENGTH,
LORA_FIX_LENGTH_PAYLOAD_ON,
true,
0,
0,
LORA_IQ_INVERSION_ON,
3000);
handle->radio->SetChannel(910000000);
handle->radio->Send(&dummy_data, (uint8_t)sizeof(dummy_data));
}
uint32_t
longfi_get_random(LongFi_t * handle)
{
return handle->radio->Random();
}
void
_send_random(LongFi_t * handle, uint8_t * data, size_t len)
{
uint32_t frequency;
// bool free_to_transmit = false;
// while (!free_to_transmit)
// {
uint32_t random = (*bindings->get_random_bits)(4);
frequency = uplink_channel_map[random % LONGFI_NUM_UPLINK_CHANNELS];
// free_to_transmit =
// handle->radio->IsChannelFree(MODEM_LORA, frequency, -65, 0);
// }
handle->radio->SetTxConfig(MODEM_LORA,
TX_OUTPUT_POWER,
0,
LORA_BANDWIDTH,
LORA_SPREADING_FACTOR,
LORA_CODINGRATE,
LORA_PREAMBLE_LENGTH,
LORA_FIX_LENGTH_PAYLOAD_ON,
true,
0,
0,
LORA_IQ_INVERSION_ON,
3000);
handle->radio->SetChannel(frequency);
handle->radio->Send(data, len);
}
#include <stdio.h>
void
longfi_send(LongFi_t * handle, const uint8_t * data, size_t len)
{
size_t output_length = BUFFER_SIZE;
lfc_transmit(&handle->lfc, data, len, &Buffer[0], &output_length);
internal.tx_len = output_length;
internal.tx_cnt = output_length;
_send_random(handle, Buffer, output_length);
}
RxPacket_t
longfi_get_rx(__attribute__((unused)) LongFi_t * handle)
{
RxPacket_t rx = {
.buf = internal.buffer,
.len = internal.rx_len,
.rssi = RssiValue,
.snr = SnrValue,
};
internal.buffer = NULL;
internal.buffer_len = 0;
return rx;
}
ClientEvent_t
longfi_handle_event(LongFi_t * handle, RfEvent_t event)
{
internal.cur_event = InternalEvent_None;
switch (event)
{
case RFE_DIO0:
(*(internal.dio_irq_handles[0]))();
break;
case RFE_DIO1:
// SX126x library only has the one handle, so fire it even fore DIO1
(*(internal.dio_irq_handles[0]))();
break;
case RFE_DIO2:
(*internal.dio_irq_handles[2])();
break;
case RFE_DIO3:
(*internal.dio_irq_handles[3])();
break;
case RFE_DIO4:
(*internal.dio_irq_handles[4])();
break;
case RFE_DIO5:
(*internal.dio_irq_handles[5])();
break;
case RFE_Timer1:
// TODO: needs to dispatch the callback stashed from TimerInit
break;
case RFE_Timer2:
// TODO: needs to dispatch the callback stashed from TimerInit
break;
case RFE_Timer3:
// TODO: needs to dispatch the callback stashed from TimerInit
break;
default:
break;
}
return _handle_internal_event(handle);
}
ClientEvent_t
_handle_internal_event(LongFi_t * handle)
{
switch (internal.cur_event)
{
case InternalEvent_None:
return ClientEvent_None;
break;
case InternalEvent_TxDone:
// if all the tx data is sent, we're done!
if (internal.tx_len == internal.tx_cnt)
{
// sleep when done transmitting
handle->radio->Sleep();
return ClientEvent_TxDone;
}
// else we are sending another fragment
else
{
uint8_t len = MIN(payload_per_fragment[internal.spreading_factor],
internal.tx_len - internal.tx_cnt);
_send_random(handle, &Buffer[internal.tx_cnt], len);
internal.tx_cnt += len;
return ClientEvent_None;
}
break;
case InternalEvent_RxDone:
// could trigger pending Tx'es here
return ClientEvent_Rx;
break;
case InternalEvent_TxTimeout:
// potential internal retry logic
break;
case InternalEvent_RxTimeout:
// potential internal retry logic
break;
case InternalEvent_RxError:
// potential internal retry logic
break;
default:
break;
}
return ClientEvent_None;
}
// each sx12xx board definition must invoke this
void
IoIrqInit(IrqHandler * irq_handlers[NUM_IRQ_HANDLES])
{
for (uint32_t i = 0; i < NUM_IRQ_HANDLES; i++)
{
internal.dio_irq_handles[i] = irq_handlers[i];
}
}
void
OnTxDone(void)
{
internal.cur_event = InternalEvent_TxDone;
}
void
OnRxDone(uint8_t * payload, uint16_t size, int16_t rssi, int8_t snr)
{
internal.cur_event = InternalEvent_RxDone;
uint8_t rx_len = (uint8_t)MIN((size_t)size, internal.buffer_len);
internal.rx_len = rx_len;
memmove(internal.buffer, payload, rx_len);
RssiValue = rssi;
SnrValue = snr;
}
void
OnTxTimeout(void)
{
internal.cur_event = InternalEvent_TxTimeout;
}
void
OnRxTimeout(void)
{
internal.cur_event = InternalEvent_RxTimeout;
}
void
OnRxError(void)
{
internal.cur_event = InternalEvent_RxTimeout;
}