UoS³ Flight Computer Firmware
 All Data Structures Files Functions Groups Pages
cc1125.c
1 
2 #include "cc1125.h"
3 #include "cc112x_spi.h"
4 #include "inttypes.h"
5 
6 #include "../firmware.h"
7 
8 #define CC_XO_FREQ 38400000
9 
10 #include <stdlib.h>
11 #include <stdio.h>
12 
13 
14 
15 /* Pins: GPIO0_RADIO_RX / GPIO0_RADIO_TX */
16 bool cc1125_pollGPIO(uint8_t gpio_pin)
17 {
18  return GPIO_read(gpio_pin);
19 }
20 
21 /*******************************************************************************
22 * @fn radio_set_rxbw_param
23 *
24 * @brief Sets the RX bandwidth. Will overwrite the input value with the
25 * actual value. Call only when in 'idle' state.
26 *
27 * @param radio_id - select the radio to use
28 * *rxbw - pointer to the requested RX bandwidth (Hz)
29 *
30 * @return 0 - changed sucessfully; 1 - error, freq not set
31 */
32 uint8_t radio_set_rxbw_param(uint8_t radio_id, uint32_t *rxbw){ //, uint32_t *symrate){
33 
34 
35  uint8_t d_fact[4];
36  uint8_t i,sm;
37  uint32_t err, sm_err;
38  int32_t bw[4];
39 
40  // first try with cic = 20
41  d_fact[0] = (uint8_t)((uint32_t)CC_XO_FREQ/(*rxbw)/8/20);
42  d_fact[1] = (uint8_t)(d_fact[0]+1);
43 
44  // also try with cic = 32
45  d_fact[2] = (uint8_t)((uint32_t)CC_XO_FREQ/(*rxbw)/8/32);
46  d_fact[3] = (uint8_t)(d_fact[2]+1);
47 
48  //set limits
49  for (i = 0; i < 4; i++){
50  if (d_fact[i] < 1)
51  d_fact[i] = 1;
52  if (d_fact[i] > 44)
53  d_fact[i] = 44;
54  }
55 
56  //work back to get the actual BWs
57  bw[0] = (int32_t)CC_XO_FREQ/d_fact[0]/8/20;
58  bw[1] = (int32_t)CC_XO_FREQ/d_fact[1]/8/20;
59  bw[2] = (int32_t)CC_XO_FREQ/d_fact[2]/8/32;
60  bw[3] = (int32_t)CC_XO_FREQ/d_fact[3]/8/32;
61 
62 
63  sm_err = 1<<30;
64  sm = 0;
65  for (i = 0; i < 4; i++){
66  err = (uint32_t)abs(bw[0]-(int32_t)(*rxbw));
67  if (err < sm_err){
68  sm_err = err;
69  sm = i;
70  }
71  }
72 
73  uint8_t reg = 0;
74 
75  // set ADC_CIC_DECFACT to 20 (0) or 32 (1)
76  if (sm <= 1)
77  reg = (0<<6);
78  else
79  reg = (1<<6);
80 
81  reg = (uint8_t)(reg | (d_fact[sm] & 0x3F));
82 
83  cc112xSpiWriteReg(radio_id, CC112X_CHAN_BW, &reg);
84 
85  *rxbw = (uint32_t)bw[sm];
86 
87 /*
88  char buff[30];
89  snprintf(buff, 30, "\n\n%02x\n\n",(reg & 0xFF) );
90  UART_puts(UART_CAMERA, buff);
91 
92  */
93 
94  return 0;
95 
96 }
97 
98 
99 /*******************************************************************************
100 * @fn radio_set_fsk_param
101 *
102 * @brief Sets the FSK symbol rate and deviation to the requested values.
103 * Will overwrite the input value with the actual value. Call only
104 * when in 'idle' state
105 *
106 * @param radio_id - select the radio to use
107 * *symbol_rate - pointer to the requested symbol rate (/sec)
108 * *deviation - pointer to the requested deviation (Hz)
109 *
110 * @return 0 - changed sucessfully; 1 - error, freq not set
111 */
112 uint8_t radio_set_fsk_param(uint8_t radio_id, uint32_t *symbol_rate, uint32_t *deviation){
113 
114  // deviation
115  uint64_t d,d1;
116  uint8_t m,e;
117 
118  d = ((uint64_t)(*deviation) * (1<<24))/CC_XO_FREQ;
119 
120  d1 = d >> 8;
121 
122  if (d1 < 2){
123  e = 0;
124  m = (uint8_t)(((uint64_t)(*deviation) * (1<<23))/CC_XO_FREQ);
125  }else{
126  e = 0;
127  while(d1){
128  d1 = d1 >> 1;
129  e++;
130  }
131  e--;
132  m = (uint8_t)(((((uint64_t)(*deviation) * (1<<24))/CC_XO_FREQ) >> e) - 256);
133  }
134  if (e > 7)
135  return 1;
136 
137  //symbol rate
138  uint64_t s,s1;
139  uint32_t ms;
140  uint8_t es;
141 
142  s = ((uint64_t)(*symbol_rate) * ((uint64_t)1<<39))/((uint64_t)CC_XO_FREQ);
143  s1 = s >> 20;
144 
145  if (s1 < 2){
146  es = 0;
147  ms = (uint32_t)(((uint64_t)(*symbol_rate) * ((uint64_t)1<<38))/((uint64_t)CC_XO_FREQ));
148  }
149  else{
150  es = 0;
151  while(s1){
152  s1 = s1 >> 1;
153  es++;
154  }
155  es--;
156  ms = (uint32_t)(((((uint64_t)(*symbol_rate) * ((uint64_t)1<<39))/((uint64_t)CC_XO_FREQ)) >> es) - ((uint64_t)1<<20));
157  }
158  if (es > 15)
159  return 1;
160 
161 
162 
163  // work back to calculate the actual values
164  if (e == 0)
165  *deviation = (uint32_t)(((uint64_t)CC_XO_FREQ * m ) >> 23);
166  else
167  *deviation = (uint32_t)((CC_XO_FREQ * (256+(uint64_t)m) ) >> (24-e));
168 
169  if (es == 0)
170  *symbol_rate = (uint32_t)((((uint64_t)CC_XO_FREQ) * ms ) >> 38);
171  else
172  *symbol_rate = (uint32_t)((((uint64_t)CC_XO_FREQ) * ((1<<20)+(uint64_t)ms) ) >> (39-es));
173 
174 
175  uint8_t writebyte;
176  writebyte = (uint8_t)(ms & 0xFF);
177  cc112xSpiWriteReg(radio_id, CC112X_SYMBOL_RATE0, &writebyte);
178  writebyte = (uint8_t)((ms>>8) & 0xFF);
179  cc112xSpiWriteReg(radio_id, CC112X_SYMBOL_RATE1, &writebyte);
180  writebyte = (uint8_t)(((ms>>16) & 0x0F) | ((es<<4) & 0xF0));
181  cc112xSpiWriteReg(radio_id, CC112X_SYMBOL_RATE2, &writebyte);
182 
183  cc112xSpiWriteReg(radio_id, CC112X_DEVIATION_M , &m);
184  writebyte = (uint8_t)((e & 0x07) | (0 << 3) | (0<<6)); // (0<<3) - FSK mode
185  cc112xSpiWriteReg(radio_id, CC112X_MODCFG_DEV_E , &writebyte);
186 
187 
188  return 0;
189 
190 }
191 
192 
193 /*******************************************************************************
194 * @fn radio_set_pwr_f
195 *
196 * @brief Sets the power to the requested floating point value in dBm. Will
197 * overwrite the input value with the actual value. Call only when
198 * in 'idle' state
199 *
200 * @param radio_id - select the radio to use
201 * *pwr - pointer to the requested power (dBm)
202 * *reg_value - used for reading back the register value, useful for
203 * cal'ing the output
204 *
205 * @return 0 - changed sucessfully; 1 - error, freq not set
206 */
207 uint8_t radio_set_pwr_f(uint8_t radio_id, double *pwr, uint8_t *reg_value){
208 
209  if ((*pwr < -11) || (*pwr > 15))
210  return 1;
211 
212  double p;
213  p = (2*(*pwr+18))-1;
214 
215  uint32_t pwr_reg = (uint32_t)p;
216 
217  if (pwr_reg < 3)
218  pwr_reg = 3;
219  pwr_reg = pwr_reg & 0x3F;
220 
221  // work back to calculate the actual freq
222  p = radio_pwr_reg_to_dbm((uint8_t)pwr_reg);
223 
224  *pwr = p;
225  *reg_value = (uint8_t)pwr_reg;
226 
227  //now write to CC112X
228  //cc112xSpiWriteReg(radio_id, CC112X_PA_CFG2, (1<<6) | pwr_reg, 1);
229  uint8_t writebyte;
230  writebyte = (uint8_t)((1<<6) | pwr_reg);
231  cc112xSpiWriteReg(radio_id, CC112X_PA_CFG2, &writebyte);
232 
233  return 0;
234 
235 }
236 
237 /*******************************************************************************
238 * @fn radio_pwr_reg_to_dbm
239 *
240 * @brief Converts the 0x03 - 0x3f power register value to a dBm value.
241 * Note: this is approximate, and also depends on output circuitry
242 *
243 * @param reg_value - the value to set to the register
244 *
245 * @return power value (dBm)
246 */
247 double radio_pwr_reg_to_dbm(uint8_t reg_value){
248  return ((double)reg_value+1)/2-18;;
249 
250 }
251 
252 /*******************************************************************************
253 * @fn radio_set_pwr_reg
254 *
255 * @brief Sets the power to the requested register value. Allowable range
256 * 0x03 - 0x3F
257 *
258 * @param radio_id - select the radio to use
259 * reg_value - the value to set to the register
260 *
261 * @return 0 - changed sucessfully; 1 - error, power not set
262 */
263 uint8_t radio_set_pwr_reg(uint8_t radio_id, uint8_t reg_value){
264 
265  if ((reg_value < 3) || (reg_value > 0x3F))
266  return 1;
267 
268 
269  uint8_t writebyte;
270  writebyte = (uint8_t)((1<<6) | (reg_value&0x3F));
271  cc112xSpiWriteReg(radio_id, CC112X_PA_CFG2, &writebyte);
272 
273  return 0;
274 
275 }
276 
277 /*******************************************************************************
278 * @fn radio_set_freq_f
279 *
280 * @brief Sets the frequency to the requested floating point value. Will
281 * overwrite the input value with the actual value. Call only when
282 * in 'idle' state
283 *
284 * @param radio_id - select the radio to use
285 * *freq - pointer to the requested frequency
286 *
287 * @return 0 - changed sucessfully; 1 - error, freq not set
288 */
289 uint8_t radio_set_freq_f(uint8_t radio_id, double *freq){
290 
291  uint8_t div, bandsel;
292  if ((*freq >= 136.7) && (*freq <= 160)){
293  div = 24;
294  bandsel = 11; }
295  else if ((*freq >= 164) && (*freq <= 192)){
296  div = 20;
297  bandsel = 10; }
298  else if ((*freq >= 205) && (*freq <= 240)){
299  div = 16;
300  bandsel = 8; }
301  else if ((*freq >= 273.3) && (*freq <= 320)){
302  div = 12;
303  bandsel = 6; }
304  else if ((*freq >= 410) && (*freq <= 480)){
305  div = 8;
306  bandsel = 4; }
307  else if ((*freq >= 820) && (*freq <= 960)){
308  div = 4;
309  bandsel = 2; }
310  else
311  return 1;
312 
313  double f;
314  f = div * ((*freq)*1000000) * 65536 / CC_XO_FREQ;
315 
316  uint32_t freq_reg = (uint32_t)f;
317 
318  // work back to calculate the actual freq
319  f = (double)freq_reg*CC_XO_FREQ;
320  f = f / div;
321  f = f / 65536;
322 
323  *freq = f/1000000;
324 
325 
326  //now write to CC112X
327  uint8_t writebyte;
328  writebyte = freq_reg & 0xFF;
329  cc112xSpiWriteReg(radio_id, CC112X_FREQ0, &writebyte);
330  writebyte = (freq_reg >> 8) & 0xFF;
331  cc112xSpiWriteReg(radio_id, CC112X_FREQ1, &writebyte);
332  writebyte = (freq_reg >> 16) & 0xFF;
333  cc112xSpiWriteReg(radio_id, CC112X_FREQ2, &writebyte);
334  writebyte = 0x10 | bandsel;
335  cc112xSpiWriteReg(radio_id, CC112X_FS_CFG, &writebyte);
336 
337 
338  return 0;
339 
340 }
341 
342 
343 /*******************************************************************************
344 * @fn radio_reset_config
345 *
346 * @brief Resets the requested radio and writes the default config for that
347 * radio
348 *
349 * @param none
350 *
351 * @return none
352 */
353 void radio_reset_config(uint8_t radio_id, const registerSetting_t *cfg, uint16_t len){
354 
355  SPI_cmd(radio_id, CC112X_SRES);
356  uint8_t writeByte;
357  for(uint16_t i = 0; i < len; i++) {
358  writeByte = cfg[i].data;
359  cc112xSpiWriteReg(radio_id, cfg[i].addr, &writeByte);
360  }
361 }
362 
363 
364 
365 /*******************************************************************************
366 * @fn manualCalibration
367 *
368 * @brief Calibrates radio according to CC112x errata
369 *
370 * @param none
371 *
372 * @return none
373 */
374 #define VCDAC_START_OFFSET 2
375 #define FS_VCO2_INDEX 0
376 #define FS_VCO4_INDEX 1
377 #define FS_CHP_INDEX 2
378 void manualCalibration(uint8_t radio_id) {
379 
380  uint8_t original_fs_cal2;
381  uint8_t calResults_for_vcdac_start_high[3];
382  uint8_t calResults_for_vcdac_start_mid[3];
383  uint8_t marcstate;
384  uint8_t writeByte;
385 
386  // 1) Set VCO cap-array to 0 (FS_VCO2 = 0x00)
387  writeByte = 0x00;
388  cc112xSpiWriteReg(radio_id, CC112X_FS_VCO2, &writeByte);
389 
390  // 2) Start with high VCDAC (original VCDAC_START + 2):
391  cc112xSpiReadReg(radio_id, CC112X_FS_CAL2, &original_fs_cal2);
392  writeByte = (uint8_t)(original_fs_cal2 + VCDAC_START_OFFSET);
393  cc112xSpiWriteReg(radio_id, CC112X_FS_CAL2, &writeByte);
394 
395  // 3) Calibrate and wait for calibration to be done
396  // (radio back in IDLE state)
397  SPI_cmd(radio_id, CC112X_SCAL);
398 
399  do {
400  cc112xSpiReadReg(radio_id, CC112X_MARCSTATE, &marcstate);
401  } while (marcstate != 0x41);
402 
403  // 4) Read FS_VCO2, FS_VCO4 and FS_CHP register obtained with
404  // high VCDAC_START value
405  cc112xSpiReadReg(radio_id, CC112X_FS_VCO2,
406  &calResults_for_vcdac_start_high[FS_VCO2_INDEX]);
407  cc112xSpiReadReg(radio_id, CC112X_FS_VCO4,
408  &calResults_for_vcdac_start_high[FS_VCO4_INDEX]);
409  cc112xSpiReadReg(radio_id, CC112X_FS_CHP,
410  &calResults_for_vcdac_start_high[FS_CHP_INDEX]);
411 
412  // 5) Set VCO cap-array to 0 (FS_VCO2 = 0x00)
413  writeByte = 0x00;
414  cc112xSpiWriteReg(radio_id, CC112X_FS_VCO2, &writeByte);
415 
416  // 6) Continue with mid VCDAC (original VCDAC_START):
417  writeByte = original_fs_cal2;
418  cc112xSpiWriteReg(radio_id, CC112X_FS_CAL2, &writeByte);
419 
420  // 7) Calibrate and wait for calibration to be done
421  // (radio back in IDLE state)
422 
423  SPI_cmd(radio_id, CC112X_SCAL);
424 
425  do {
426  cc112xSpiReadReg(radio_id, CC112X_MARCSTATE, &marcstate);
427  } while (marcstate != 0x41);
428 
429  // 8) Read FS_VCO2, FS_VCO4 and FS_CHP register obtained
430  // with mid VCDAC_START value
431  cc112xSpiReadReg(radio_id, CC112X_FS_VCO2,
432  &calResults_for_vcdac_start_mid[FS_VCO2_INDEX]);
433  cc112xSpiReadReg(radio_id, CC112X_FS_VCO4,
434  &calResults_for_vcdac_start_mid[FS_VCO4_INDEX]);
435  cc112xSpiReadReg(radio_id, CC112X_FS_CHP,
436  &calResults_for_vcdac_start_mid[FS_CHP_INDEX]);
437 
438  // 9) Write back highest FS_VCO2 and corresponding FS_VCO
439  // and FS_CHP result
440 
441  if (calResults_for_vcdac_start_high[FS_VCO2_INDEX] >
442  calResults_for_vcdac_start_mid[FS_VCO2_INDEX]) {
443  writeByte = calResults_for_vcdac_start_high[FS_VCO2_INDEX];
444  cc112xSpiWriteReg(radio_id, CC112X_FS_VCO2, &writeByte);
445  writeByte = calResults_for_vcdac_start_high[FS_VCO4_INDEX];
446  cc112xSpiWriteReg(radio_id, CC112X_FS_VCO4, &writeByte);
447  writeByte = calResults_for_vcdac_start_high[FS_CHP_INDEX];
448  cc112xSpiWriteReg(radio_id, CC112X_FS_CHP, &writeByte);
449  } else {
450  writeByte = calResults_for_vcdac_start_mid[FS_VCO2_INDEX];
451  cc112xSpiWriteReg(radio_id, CC112X_FS_VCO2, &writeByte);
452  writeByte = calResults_for_vcdac_start_mid[FS_VCO4_INDEX];
453  cc112xSpiWriteReg(radio_id, CC112X_FS_VCO4, &writeByte);
454  writeByte = calResults_for_vcdac_start_mid[FS_CHP_INDEX];
455  cc112xSpiWriteReg(radio_id, CC112X_FS_CHP, &writeByte);
456  }
457 }
uint8_t SPI_cmd(uint8_t spi_num, uint8_t cmd)
Definition: spi.c:15
bool GPIO_read(uint8_t gpio_num)
Definition: gpio.c:29