forked from ps2/subg_rfspy
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathradio.c
268 lines (230 loc) · 7.14 KB
/
radio.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
#include <stdint.h>
#include "hardware.h"
#include "serial.h"
#include "commands.h"
#include "delay.h"
#include "timer.h"
#define MAX_PACKET_LEN 192
volatile uint8_t __xdata radio_tx_buf[MAX_PACKET_LEN];
volatile uint8_t radio_tx_buf_len = 0;
volatile uint8_t radio_tx_buf_idx = 0;
volatile uint8_t __xdata radio_rx_buf[MAX_PACKET_LEN];
volatile uint8_t radio_rx_buf_len = 0;
volatile uint8_t packet_count = 1;
volatile uint8_t underflow_count = 0;
void configure_radio()
{
/* RF settings SoC: CC1110 */
SYNC1 = 0xFF; // sync word, high byte
SYNC0 = 0x00; // sync word, low byte
PKTLEN = 0xFF; // packet length
PKTCTRL1 = 0x00; // packet automation control
PKTCTRL0 = 0x00; // packet automation control
ADDR = 0x00;
// CHANNR: See the locale-specific section below
FSCTRL1 = 0x06; // frequency synthesizer control
FSCTRL0 = 0x00;
// FREQ0/FREQ1/FREQ2: See the locale-specific section below
MDMCFG4 = 0x99; // 150.5 kHz rx filter bandwidth. Narrower can improve range,
// but then freq must be dialed in more tightly, which does not
// allow for variation we see with pump in free space vs on body.
MDMCFG3 = 0x66; // modem configuration
MDMCFG2 = 0x33; // modem configuration
MDMCFG1 = 0x61; // modem configuration
MDMCFG0 = 0x7E; // modem configuration
DEVIATN = 0x15; // modem deviation setting
MCSM2 = 0x07;
MCSM1 = 0x30;
MCSM0 = 0x18; // main radio control state machine configuration
FOCCFG = 0x17; // frequency offset compensation configuration BSCFG = 0x6C;
FREND1 = 0xB6; // front end tx configuration
FREND0 = 0x11; // front end tx configuration
FSCAL3 = 0xE9; // frequency synthesizer calibration
FSCAL2 = 0x2A; // frequency synthesizer calibration
FSCAL1 = 0x00; // frequency synthesizer calibration
FSCAL0 = 0x1F; // frequency synthesizer calibration
TEST1 = 0x31; // various test settings
TEST0 = 0x09; // various test settings
PA_TABLE0 = 0x00; // needs to be explicitly set!
// PA_TABLE1: See the locale-specific section below
AGCCTRL2 = 0x07; // 0x03 to 0x07 - default: 0x03
AGCCTRL1 = 0x00; // 0x00 - default: 0x40
AGCCTRL0 = 0x91; // 0x91 or 0x92 - default: 0x91
#if US_RADIO_LOCALE
FREQ2 = 0x26; // 916.541MHz is midpoint between freq of pump in free space,
FREQ1 = 0x30; // and pump held close to the body.
FREQ0 = 0x70; //
CHANNR = 0x02; // channel number
PA_TABLE1 = 0xC0; // pa power setting 10 dBm
#else
FREQ2 = 0x24; // frequency control word, high byte
FREQ1 = 0x2E; // frequency control word, middle byte
FREQ0 = 0x38; // frequency control word, low byte
CHANNR = 0x00; // channel number
PA_TABLE1 = 0xC2; // Max configurable power output at this frequency is 0xC2
#endif
IEN2 |= IEN2_RFIE;
RFTXRXIE = 1;
}
void rftxrx_isr(void) __interrupt RFTXRX_VECTOR {
uint8_t d_byte;
if (MARCSTATE==MARC_STATE_RX) {
d_byte = RFD;
if (radio_rx_buf_len == 0) {
radio_rx_buf[0] = RSSI;
if (radio_rx_buf[0] == 0) {
radio_rx_buf[0] = 1; // Prevent RSSI of 0 from triggering end-of-packet
}
radio_rx_buf[1] = packet_count;
packet_count++;
radio_rx_buf_len = 2;
}
if (packet_count == 0) {
packet_count = 1;
}
if (radio_rx_buf_len < MAX_PACKET_LEN) {
radio_rx_buf[radio_rx_buf_len] = d_byte;
radio_rx_buf_len++;
} else {
// Overflow
}
if (d_byte == 0) {
RFST = RFST_SIDLE;
while(MARCSTATE!=MARC_STATE_IDLE);
}
}
else if (MARCSTATE==MARC_STATE_TX) {
if (radio_tx_buf_len > radio_tx_buf_idx) {
d_byte = radio_tx_buf[radio_tx_buf_idx++];
RFD = d_byte;
} else {
RFD = 0;
underflow_count++;
// We wait a few counts to make sure the radio has sent the last bytes
// before turning it off.
if (underflow_count == 2) {
RFST = RFST_SIDLE;
}
}
}
}
void rf_isr(void) __interrupt RF_VECTOR {
S1CON &= ~0x03; // Clear CPU interrupt flag
if(RFIF & 0x80) // TX underflow
{
// Underflow
RFST = RFST_SIDLE;
RFIF &= ~0x80; // Clear module interrupt flag
}
else if(RFIF & 0x40) // RX overflow
{
RFIF &= ~0x40; // Clear module interrupt flag
}
else if(RFIF & 0x20) // RX timeout
{
RFIF &= ~0x20; // Clear module interrupt flag
}
// Use ”else if” to check and handle other RFIF flags
}
void send_packet_from_serial(uint8_t channel, uint8_t repeat_count, uint8_t delay_ms) {
uint8_t s_byte;
radio_tx_buf_len = 0;
radio_tx_buf_idx = 0;
underflow_count = 0;
RFST = RFST_SIDLE;
while(MARCSTATE!=MARC_STATE_IDLE);
CHANNR = channel;
BLUE_LED = 1;
while (1) {
s_byte = serial_rx_byte();
if (radio_tx_buf_len == (MAX_PACKET_LEN - 1)) {
s_byte = 0;
}
radio_tx_buf[radio_tx_buf_len++] = s_byte;
if (s_byte == 0) {
break;
}
if (radio_tx_buf_len == 2) {
// Turn on radio
RFST = RFST_STX;
}
}
// wait for sending to finish
while(MARCSTATE!=MARC_STATE_IDLE);
while(repeat_count > 0) {
// Reset idx to beginning of buffer
radio_tx_buf_idx = 0;
underflow_count = 0;
// delay
if (delay_ms > 0) {
delay(delay_ms);
}
// Turn on radio (interrupts should start again)
RFST = RFST_STX;
while(MARCSTATE!=MARC_STATE_TX);
// wait for sending to finish
while(MARCSTATE!=MARC_STATE_IDLE);
repeat_count--;
}
BLUE_LED = 0;
}
void resend_from_tx_buf(uint8_t channel) {
RFST = RFST_SIDLE;
while(MARCSTATE!=MARC_STATE_IDLE);
CHANNR = channel;
// Reset idx to beginning of buffer
radio_tx_buf_idx = 0;
underflow_count = 0;
// Turn on radio (interrupts should start again)
RFST = RFST_STX;
while(MARCSTATE!=MARC_STATE_TX);
// wait for sending to finish
while(MARCSTATE!=MARC_STATE_IDLE);
}
uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms) {
uint8_t read_idx = 0;
uint8_t d_byte = 0;
uint8_t rval = 0;
reset_timer();
RFST = RFST_SIDLE;
while(MARCSTATE!=MARC_STATE_IDLE);
CHANNR = channel;
radio_rx_buf_len = 0;
RFST = RFST_SRX;
while(MARCSTATE!=MARC_STATE_RX);
while(1) {
// Waiting for isr to put radio bytes into radio_rx_buf
if (radio_rx_buf_len > read_idx) {
GREEN_LED = 1;
if (read_idx == 0 && radio_rx_buf_len > 2 && radio_rx_buf[2] == 0) {
rval = ERROR_ZERO_DATA;
break;
}
d_byte = radio_rx_buf[read_idx];
serial_tx_byte(d_byte);
read_idx++;
if (read_idx > 1 && read_idx == radio_rx_buf_len && d_byte == 0) {
// End of packet.
break;
}
}
if (timeout_ms > 0 && timerCounter > timeout_ms && radio_rx_buf_len == 0) {
rval = ERROR_RX_TIMEOUT;
break;
}
#ifndef TI_DONGLE
#else
#endif
// Also going to watch serial in case the client wants to interrupt rx
if (SERIAL_DATA_AVAILABLE) {
// Received a byte from uart while waiting for radio packet
// We will interrupt the RX and go handle the command.
interrupting_cmd = serial_rx_byte();
rval = ERROR_CMD_INTERRUPTED;
break;
}
}
RFST = RFST_SIDLE;
GREEN_LED = 0;
return rval;
}