Contiki 3.x
cc1120-zoul-arch.c
Go to the documentation of this file.
1 
2 /*
3  * Copyright (c) 2014, University of Southampton, Electronics and Computer Science
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  * 3. Neither the name of the Institute nor the names of its contributors
15  * may be used to endorse or promote products derived from this software
16  * without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  */
31 
32  /**
33  * \file
34  * Architecture specific CC1120 functions for the Zolertia Zoul
35  * \author
36  * Graeme Bragg <g.bragg@ecs.soton.ac.uk>
37  * Phil Basford <pjb@ecs.soton.ac.uk>
38  */
39 
40 #include "cc1120.h"
41 #include "cc1120-arch.h"
42 #include "cc1120-const.h"
43 #include "board.h"
44 
45 #include "spi-arch.h"
46 #include "dev/ioc.h"
47 #include "dev/sys-ctrl.h"
48 #include "dev/spi.h"
49 #include "dev/ssi.h"
50 #include "dev/gpio.h"
51 #include "lpm.h"
52 
53 #if PLATFORM_HAS_LEDS
54 #include "dev/leds.h"
55 #define LEDS_ON(x) leds_on(x)
56 #endif
57 
58 #include <stdio.h>
59 #include <watchdog.h>
60 
61 static uint8_t enabled;
62 
63 /* Busy Wait for time-outable waiting. */
64 #define BUSYWAIT_UNTIL(cond, max_time) \
65  do { \
66  rtimer_clock_t t0; \
67  t0 = RTIMER_NOW(); \
68  while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (max_time))); \
69  } while(0)
70 
71 #define CC1200_SPI_CLK_PORT_BASE GPIO_PORT_TO_BASE(SPI0_CLK_PORT)
72 #define CC1200_SPI_CLK_PIN_MASK GPIO_PIN_MASK(SPI0_CLK_PIN)
73 #define CC1200_SPI_MOSI_PORT_BASE GPIO_PORT_TO_BASE(SPI0_TX_PORT)
74 #define CC1200_SPI_MOSI_PIN_MASK GPIO_PIN_MASK(SPI0_TX_PIN)
75 #define CC1200_SPI_MISO_PORT_BASE GPIO_PORT_TO_BASE(SPI0_RX_PORT)
76 #define CC1200_SPI_MISO_PIN_MASK GPIO_PIN_MASK(SPI0_RX_PIN)
77 #define CC1200_SPI_CSN_PORT_BASE GPIO_PORT_TO_BASE(CC1200_SPI_CSN_PORT)
78 #define CC1200_SPI_CSN_PIN_MASK GPIO_PIN_MASK(CC1200_SPI_CSN_PIN)
79 #define CC1200_GDO0_PORT_BASE GPIO_PORT_TO_BASE(CC1200_GDO0_PORT)
80 #define CC1200_GDO0_PIN_MASK GPIO_PIN_MASK(CC1200_GDO0_PIN)
81 #define CC1200_GDO2_PORT_BASE GPIO_PORT_TO_BASE(CC1200_GDO2_PORT)
82 #define CC1200_GDO2_PIN_MASK GPIO_PIN_MASK(CC1200_GDO2_PIN)
83 #define CC1200_RESET_PORT_BASE GPIO_PORT_TO_BASE(CC1200_RESET_PORT)
84 #define CC1200_RESET_PIN_MASK GPIO_PIN_MASK(CC1200_RESET_PIN)
85 
86 #if CC1120INTDEBUG || DEBUG
87  #define PRINTFINT(...) printf(__VA_ARGS__)
88 #else
89  #define PRINTFINT(...) do {} while (0)
90 #endif
91 
92 #if CC1120_DEBUG_PINS
93 void
94 cc1120_debug_pin_cca(uint8_t val)
95 {
96  if(val == 1) {
98  } else {
100  }
101 }
102 
103 void
104 cc1120_debug_pin_rx(uint8_t val)
105 {
106  if(val == 1) {
108  } else {
110  }
111 }
112 #endif
113 
114 /* ---------------------------- Init Functions ----------------------------- */
115 /*---------------------------------------------------------------------------*/
116 void
117 cc1120_int_handler(uint8_t port, uint8_t pin)
118 {
119  PRINTFINT("\n\tInt\n");
120  /* To keep the gpio_register_callback happy */
121  cc1120_interrupt_handler();
122 }
123 
124 /*---------------------------------------------------------------------------*/
125 /**
126  * Callback to allow Low Power Modes 1 and 2.
127  * LPM Modes 1 and 2 lead to vastly increased packet latency in the network,
128  * possibly due to ISR latency
129  */
130 static bool lpm_permit_pm1(void) {
131  radio_value_t res;
132  cc1120_driver.get_value(RADIO_PARAM_POWER_MODE, &res);
133  // Allow PM{1,2} as long as the radio is not on
134  return res != RADIO_POWER_MODE_ON;
135 }
136 
137 /*---------------------------------------------------------------------------*/
138 void
139 cc1120_arch_init(void)
140 {
141  /* First leave RESET high */
142  GPIO_SOFTWARE_CONTROL(CC1200_RESET_PORT_BASE, CC1200_RESET_PIN_MASK);
143  GPIO_SET_OUTPUT(CC1200_RESET_PORT_BASE, CC1200_RESET_PIN_MASK);
144  ioc_set_over(CC1200_RESET_PORT, CC1200_RESET_PIN, IOC_OVERRIDE_OE);
145  GPIO_SET_PIN(CC1200_RESET_PORT_BASE, CC1200_RESET_PIN_MASK);
146 
147  /* Initialize CSn, enable CSn and then wait for MISO to go low*/
148  spix_cs_init(CC1200_SPI_CSN_PORT, CC1200_SPI_CSN_PIN);
149 
150  /* Initialize SPI */
151  spix_init(CC1200_SPI_INSTANCE);
152  //spix_set_mode(CC1200_SPI_INSTANCE, SSI_CR0_FRF_MOTOROLA,
153  // 0, 0, 8);
154 
155  /* Configure GPIOx */
156  GPIO_SOFTWARE_CONTROL(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
157  GPIO_SET_INPUT(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
158  ioc_set_over(CC1200_GDO0_PORT, CC1200_GDO0_PIN, IOC_OVERRIDE_DIS);
159  GPIO_SOFTWARE_CONTROL(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
160  GPIO_SET_INPUT(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
161  ioc_set_over(CC1200_GDO2_PORT, CC1200_GDO2_PIN, IOC_OVERRIDE_DIS);
162 
163  /* Leave CSn as default */
164  cc1120_arch_spi_disable();
165 
166  /* Ensure MISO is high */
167  BUSYWAIT_UNTIL(
168  GPIO_READ_PIN(CC1200_SPI_MISO_PORT_BASE, CC1200_SPI_MISO_PIN_MASK),
169  RTIMER_SECOND / 10);
170 
171 #if CC1120_DEBUG_PINS
172  /* Use ADC 2 as Channel Clear. */
176 
177  /* Use ADC 1 as RX Indicator. */
181 #endif
182 
183  // Register ourselves as an LPM periph so we can prevent going to LPM{1,2} when the radio is on
185 }
186 
187 /*---------------------------------------------------------------------------*/
188 
189 void
190 cc1120_arch_pin_init(void)
191 {
192  GPIO_SOFTWARE_CONTROL(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
193  GPIO_SET_INPUT(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
194  GPIO_DETECT_EDGE(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
195  GPIO_TRIGGER_SINGLE_EDGE(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
196 
197  GPIO_DETECT_RISING(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
198 
199  nvic_interrupt_enable(CC1200_GPIOx_VECTOR);
200  gpio_register_callback(cc1120_int_handler, CC1200_GDO0_PORT,
201  CC1200_GDO0_PIN);
202 }
203 
204 
205 /* ---------------------------- Reset Functions ---------------------------- */
206 void
207 cc1120_arch_reset(void)
208 {
209  cc1120_arch_spi_disable(); /* Assert CSn to de-select CC1120. */
210 
211 
212  GPIO_CLR_PIN(CC1200_RESET_PORT_BASE, CC1200_RESET_PIN_MASK); /* Clear !Reset pin. */
213  clock_delay_usec(CC1120_RESET_DELAY_USEC); /* Delay for a little. */
214  GPIO_SET_PIN(CC1200_RESET_PORT_BASE, CC1200_RESET_PIN_MASK); /* Assert !Reset pin. */
215 }
216 
217 
218 /* ----------------------------- SPI Functions ----------------------------- */
219 uint8_t
220 cc1120_arch_spi_enabled(void)
221 {
222  return enabled;
223 }
224 
225 void
226 cc1120_arch_spi_enable(void)
227 {
228  if(!enabled)
229  {
230  rtimer_clock_t t0 = RTIMER_NOW();
231  int i = 0;
232 
233  /* Set CSn to low (0) */
234  GPIO_CLR_PIN(CC1200_SPI_CSN_PORT_BASE, CC1200_SPI_CSN_PIN_MASK);
235 
237 
238  /* The MISO pin should go LOW before chip is fully enabled. */
239  while(GPIO_READ_PIN(CC1200_SPI_MISO_PORT_BASE, CC1200_SPI_MISO_PIN_MASK))
240  {
241  if(RTIMER_CLOCK_LT((t0 + CC1120_EN_TIMEOUT), RTIMER_NOW()) )
242  {
244  if(i == 0)
245  {
246  /* Timeout. Try a SNOP and a re-enable once. */
247  (void) cc1120_arch_spi_rw_byte(CC1120_STROBE_SNOP); /* SNOP. */
248  GPIO_SET_PIN(CC1200_SPI_CSN_PORT_BASE, CC1200_SPI_CSN_PIN_MASK); /* Disable. */
249  clock_wait(50); /* Wait. */
250  GPIO_CLR_PIN(CC1200_SPI_CSN_PORT_BASE, CC1200_SPI_CSN_PIN_MASK); /* Enable. */
251 
252  i++;
253  }
254  else
255  {
256  break;
257  }
258 
259  t0 = RTIMER_NOW(); /* Reset timeout. */
260  }
261  }
262 
263  enabled = 1;
264  }
265 }
266 
267 /*---------------------------------------------------------------------------*/
268 void
269 cc1120_arch_spi_disable(void)
270 {
271  /* Set CSn to high (1) */
272  GPIO_SET_PIN(CC1200_SPI_CSN_PORT_BASE, CC1200_SPI_CSN_PIN_MASK);
273 
274  enabled = 0;
275 }
276 
277 /*---------------------------------------------------------------------------*/
278 uint8_t
279 cc1120_arch_spi_rw_byte(uint8_t val)
280 {
281  SPI_WAITFORTx_BEFORE();
282  SPIX_BUF(CC1200_SPI_INSTANCE) = val;
283  SPIX_WAITFOREOTx(CC1200_SPI_INSTANCE);
284  SPIX_WAITFOREORx(CC1200_SPI_INSTANCE);
285  return SPIX_BUF(CC1200_SPI_INSTANCE);
286 }
287 
288 /*---------------------------------------------------------------------------*/
289 uint8_t
290 cc1120_arch_txfifo_load(uint8_t *packet, uint8_t packet_length)
291 {
292  uint8_t status, i;
293  //status = cc1120_arch_spi_rw_byte(CC1120_FIFO_ACCESS | CC1120_STANDARD_BIT | CC1120_WRITE_BIT);
294  status = cc1120_arch_spi_rw_byte(CC1120_FIFO_ACCESS | CC1120_BURST_BIT | CC1120_WRITE_BIT);
295  cc1120_arch_spi_rw_byte(packet_length);
296 
297  for(i = 0; i < packet_length; i++)
298  {
299  //cc1120_arch_spi_rw_byte(CC1120_FIFO_ACCESS | CC1120_STANDARD_BIT | CC1120_WRITE_BIT);
300  cc1120_arch_spi_rw_byte(packet[i]);
301  }
302 
303  return status;
304 }
305 
306 
307 /*---------------------------------------------------------------------------*/
308 void
309 cc1120_arch_rxfifo_read(uint8_t *packet, uint8_t packet_length)
310 {
311  uint8_t i;
312 
313  (void) cc1120_arch_spi_rw_byte(CC1120_FIFO_ACCESS | CC1120_BURST_BIT | CC1120_READ_BIT);
314 
315  for(i = 0; i < packet_length; i++)
316  {
317  //(void) cc1120_arch_spi_rw_byte(CC1120_FIFO_ACCESS | CC1120_STANDARD_BIT | CC1120_READ_BIT);
318  packet[i] = cc1120_arch_spi_rw_byte(0);
319  }
321 }
322 
323 
324 /*---------------------------------------------------------------------------*/
325 uint8_t
326 cc1120_arch_read_cca(void)
327 {
328  /*if(CC1120_GDO3_PORT(IN) & BV(CC1120_GDO3_PIN))
329  {
330  return 1;
331  }
332  else
333  {*/
334  return 0;
335  //}
336 }
337 
338 
339 /*---------------------------------------------------------------------------*/
340 uint8_t
341 cc1120_arch_read_gpio2(void)
342 {
343  return GPIO_READ_PIN(CC1200_GDO2_PORT_BASE, CC1200_GDO2_PIN_MASK);
344 }
345 
346 uint8_t
347 cc1120_arch_read_gpio3(void)
348 {
349  return 0;
350 }
351 
352 /* -------------------------- Interrupt Functions -------------------------- */
353 
354 /* On the Z1, the interrupt is shared with the ADXL345 accelerometer.
355  * The interrupt routine is handled in adcl345.c. */
356 
357 /*---------------------------------------------------------------------------*/
358 void
359 cc1120_arch_interrupt_enable(void)
360 {
361  PRINTFINT("\nInterrupt Enabled\n");
362  /* Reset interrupt trigger */
363 
364  /* Enable interrupt on the GDO0 pin */
365  GPIO_ENABLE_INTERRUPT(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
366 }
367 
368 /*---------------------------------------------------------------------------*/
369 void
370 cc1120_arch_interrupt_disable(void)
371 {
372  PRINTFINT("\nInterrupt Disabled\n");
373  /* Disable interrupt on the GDO0 pin */
374  GPIO_DISABLE_INTERRUPT(CC1200_GDO0_PORT_BASE, CC1200_GDO0_PIN_MASK);
375  /* Reset interrupt trigger */
376 
377 }
378 /*---------------------------------------------------------------------------*/
379 void
380 cc1120_arch_interrupt_acknowledge(void)
381 {
382 
383 }
384 
385 
#define GPIO_TRIGGER_SINGLE_EDGE(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to trigger an interrupt on single edge (controlled by G...
Definition: gpio.h:178
#define ADC_SENSORS_ADC2_PIN
ADC2 to PA4.
Definition: board.h:205
#define GPIO_ENABLE_INTERRUPT(PORT_BASE, PIN_MASK)
Enable interrupt triggering for pins with PIN_MASK of port with PORT_BASE.
Definition: gpio.h:202
#define GPIO_SET_INPUT(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to input.
Definition: gpio.h:93
#define GPIO_PIN_MASK(PIN)
Converts a pin number to a pin mask.
Definition: gpio.h:321
#define ADC_SENSORS_ADC1_PIN
ADC1 to PA5.
Definition: board.h:195
#define IOC_OVERRIDE_DIS
Override Disabled.
Definition: ioc.h:226
Header file for the cc2538 SPI driver, including macros for the implementation of the low-level SPI p...
#define GPIO_DETECT_EDGE(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to detect edge.
Definition: gpio.h:155
#define RTIMER_NOW()
Get the current clock time.
Definition: rtimer.h:135
#define IOC_OVERRIDE_OE
Output Enable.
Definition: ioc.h:222
void spix_init(uint8_t spi)
Initialize the SPI bus for the instance given.
Definition: spi.c:207
#define GPIO_READ_PIN(PORT_BASE, PIN_MASK)
Read pins with PIN_MASK of port with PORT_BASE.
Definition: gpio.h:148
#define GPIO_CLR_PIN(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE low.
Definition: gpio.h:114
#define GPIO_SET_PIN(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE high.
Definition: gpio.h:107
void spix_cs_init(uint8_t port, uint8_t pin)
Configure a GPIO to be the chip select pin.
Definition: spi.c:319
#define GPIO_SET_OUTPUT(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to output.
Definition: gpio.h:100
int radio_value_t
Each radio has a set of parameters that designate the current configuration and state of the radio...
Definition: radio.h:88
Header file with declarations for the I/O Control module.
#define GPIO_SOFTWARE_CONTROL(PORT_BASE, PIN_MASK)
Configure the pin to be software controlled with PIN_MASK of port with PORT_BASE. ...
Definition: gpio.h:259
void watchdog_periodic(void)
Writes the WDT clear sequence.
Definition: watchdog.c:64
#define GPIO_PORT_TO_BASE(PORT)
Converts a port number to the port base address.
Definition: gpio.h:329
Header file for the cc2538 System Control driver.
Header file for the cc2538 Synchronous Serial Interface.
#define GPIO_DETECT_RISING(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to trigger an interrupt on rising edge.
Definition: gpio.h:186
void lpm_register_peripheral(lpm_periph_permit_pm1_func_t permit_pm1_func)
Register a peripheral function which will get called by the LPM module to get 'permission' to drop to...
static bool lpm_permit_pm1(void)
Callback to allow Low Power Modes 1 and 2.
void nvic_interrupt_enable(uint32_t intr)
Enables interrupt intr.
Definition: nvic.c:64
void clock_wait(clock_time_t t)
Wait for a given number of ticks.
Definition: clock.c:162
#define GPIO_DISABLE_INTERRUPT(PORT_BASE, PIN_MASK)
Disable interrupt triggering for pins with PIN_MASK of port with PORT_BASE.
Definition: gpio.h:210
void ioc_set_over(uint8_t port, uint8_t pin, uint8_t over)
Set Port:Pin override function.
Definition: ioc.c:54
void gpio_register_callback(gpio_callback_t f, uint8_t port, uint8_t pin)
Register GPIO callback.
Definition: gpio.c:56
void clock_delay_usec(uint16_t dt)
Delay a given number of microseconds.
Definition: clock.c:94
#define ADC_SENSORS_PORT
ADC GPIO control port.
Definition: board.h:192