Contiki 3.x
cc1120-arch-z1.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 Z1
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 
44 #include "dev/spi.h"
45 #include "dev/leds.h"
46 
47 #include "isr_compat.h"
48 #include <stdio.h>
49 #include <watchdog.h>
50 
51 #define LEDS_ON(x) leds_on(x)
52 
53 static uint8_t enabled;
54 
55 /* Busy Wait for time-outable waiting. */
56 #define BUSYWAIT_UNTIL(cond, max_time) \
57  do { \
58  rtimer_clock_t t0; \
59  t0 = RTIMER_NOW(); \
60  while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (max_time))); \
61  } while(0)
62 
63 
64 /* ---------------------------- Init Functions ----------------------------- */
65 /*---------------------------------------------------------------------------*/
66 
67 void
68 cc1120_arch_init(void)
69 {
70  /* Configure pins. This may have already been done but func is repeat-execution safe. */
71  cc1120_arch_pin_init();
72 
73  /* Init SPI. May have already done but we need to ensure SPI is configured. On Z1 this is done in main. */
74  //spi_init();
75 
76  /* Setup GPIO pins. All are Inputs for now. */
77  CC1120_GDO0_PORT(SEL) &= ~BV(CC1120_GDO0_PIN);
78  CC1120_GDO0_PORT(DIR) &= ~BV(CC1120_GDO0_PIN);
79  CC1120_GDO0_PORT(REN) |= BV(CC1120_GDO0_PIN);
80  CC1120_GDO0_PORT(OUT) &= ~BV(CC1120_GDO0_PIN);
81 
82  /* Set CC1120 to a rising edge interrupt. */
83  CC1120_GDO0_PORT(IES) &= ~BV(CC1120_GDO0_PIN);
84 
85 //#ifdef CC1120_GPIO2_FUNC
86 // CC1120_GDO2_PORT(SEL) &= ~BV(CC1120_GDO2_PIN);
87 // CC1120_GDO2_PORT(DIR) &= ~BV(CC1120_GDO2_PIN);
88 //#endif
89 
90 
91  CC1120_GDO3_PORT(SEL) &= ~BV(CC1120_GDO3_PIN);
92  CC1120_GDO3_PORT(DIR) &= ~BV(CC1120_GDO3_PIN);
93  CC1120_GDO3_PORT(REN) |= BV(CC1120_GDO3_PIN);
94  CC1120_GDO3_PORT(OUT) &= ~BV(CC1120_GDO3_PIN);
95 
96 }
97 
98 /*---------------------------------------------------------------------------*/
99 
100 void
101 cc1120_arch_pin_init(void)
102 {
103  /* Turn off CC2420. */
104  CC2420_PWR_PORT(DIR) |= BV(CC2420_PWR_PIN);
105  CC2420_PWR_PORT(OUT) &= ~BV(CC2420_PWR_PIN);
106  CC2420_CSN_PORT(DIR) |= BV(CC2420_CSN_PIN);
107  CC2420_CSN_PORT(OUT) |= BV(CC2420_CSN_PIN);
108  CC2420_RESET_PORT(DIR) |= BV(CC2420_RESET_PIN);
109  CC2420_RESET_PORT(OUT) |= BV(CC2420_RESET_PIN);
110 
111  /* Setup !RESET and CSn pins. */
112  CC1120_SPI_CSN_PORT(DIR) |= BV(CC1120_SPI_CSN_PIN); /* Set CSn pin to Output. */
113  CC1120_SPI_CSN_PORT(SEL) &= ~BV(CC1120_SPI_CSN_PIN); /* Set CSn pin to GPIO mode. */
114  CC1120_SPI_CSN_PORT(OUT) |= BV(CC1120_SPI_CSN_PIN); /* Set CSn high to de-select radio. */
115  enabled = 0;
116 
117  CC1120_RESET_PORT(DIR) |= BV(CC1120_RESET_PIN); /* Set !Reset pin to Output. */
118  CC1120_RESET_PORT(SEL) &= ~BV(CC1120_RESET_PIN); /* Set !Reset pin to GPIO mode. */
119  CC1120_RESET_PORT(OUT) |= BV(CC1120_RESET_PIN); /* Set !Reset high to ensure radio does not hog SPI. */
120 }
121 
122 
123 /* ---------------------------- Reset Functions ---------------------------- */
124 void
125 cc1120_arch_reset(void)
126 {
127  CC1120_SPI_CSN_PORT(OUT) |= BV(CC1120_SPI_CSN_PIN); /* Assert CSn to de-select CC1120. */
128  CC1120_RESET_PORT(OUT) &= ~BV(CC1120_RESET_PIN); /* Clear !Reset pin. */
129  clock_delay_usec(CC1120_RESET_DELAY_USEC); /* Delay for a little. */
130  CC1120_RESET_PORT(OUT) |= BV(CC1120_RESET_PIN); /* Assert !Reset pin. */
131 }
132 
133 
134 /* ----------------------------- SPI Functions ----------------------------- */
135 uint8_t
136 cc1120_arch_spi_enabled(void)
137 {
138  return enabled;
139 }
140 
141 void
142 cc1120_arch_spi_enable(void)
143 {
144  if(!enabled)
145  {
146  rtimer_clock_t t0 = RTIMER_NOW();
147  int i = 0;
148 
149  /* Set CSn to low to select CC1120 */
150  CC1120_SPI_CSN_PORT(OUT) &= ~BV(CC1120_SPI_CSN_PIN);
151 
153 
154  /* The MISO pin should go LOW before chip is fully enabled. */
155  while(CC1120_SPI_MISO_PORT(IN) & BV(CC1120_SPI_MISO_PIN))
156  {
157  if(RTIMER_CLOCK_LT((t0 + CC1120_EN_TIMEOUT), RTIMER_NOW()) )
158  {
160  if(i == 0)
161  {
162  /* Timeout. Try a SNOP and a re-enable once. */
163  (void) cc1120_arch_spi_rw_byte(CC1120_STROBE_SNOP); /* SNOP. */
164  CC1120_SPI_CSN_PORT(OUT) |= BV(CC1120_SPI_CSN_PIN); /* Disable. */
165  clock_wait(50); /* Wait. */
166  CC1120_SPI_CSN_PORT(OUT) &= ~BV(CC1120_SPI_CSN_PIN); /* Enable. */
167 
168  i++;
169  }
170  else
171  {
172  break;
173  }
174 
175  t0 = RTIMER_NOW(); /* Reset timeout. */
176  }
177  }
178 
179  enabled = 1;
180  }
181 }
182 
183 /*---------------------------------------------------------------------------*/
184 void
185 cc1120_arch_spi_disable(void)
186 {
187  if(enabled)
188  {
189  /* Set CSn to high (1) */
190  CC1120_SPI_CSN_PORT(OUT) |= BV(CC1120_SPI_CSN_PIN);
191 
192  enabled = 0;
193  }
194 }
195 
196 /*---------------------------------------------------------------------------*/
197 uint8_t
198 cc1120_arch_spi_rw_byte(uint8_t val)
199 {
200  SPI_WAITFORTx_BEFORE();
201  SPI_TXBUF = val;
202  //SPI_WAITFOREOTx(); /* Causes SPI hanging when used with burst read/write. */
203  SPI_WAITFOREORx();
204  return SPI_RXBUF;
205 }
206 
207 /*---------------------------------------------------------------------------*/
208 uint8_t
209 cc1120_arch_txfifo_load(uint8_t *packet, uint8_t packet_length)
210 {
211  uint8_t status, i;
212  //status = cc1120_arch_spi_rw_byte(CC1120_FIFO_ACCESS | CC1120_STANDARD_BIT | CC1120_WRITE_BIT);
213  status = cc1120_arch_spi_rw_byte(CC1120_FIFO_ACCESS | CC1120_BURST_BIT | CC1120_WRITE_BIT);
214  cc1120_arch_spi_rw_byte(packet_length);
215 
216  for(i = 0; i < packet_length; i++)
217  {
218  //cc1120_arch_spi_rw_byte(CC1120_FIFO_ACCESS | CC1120_STANDARD_BIT | CC1120_WRITE_BIT);
219  cc1120_arch_spi_rw_byte(packet[i]);
220  }
221 
222  return status;
223 }
224 
225 
226 /*---------------------------------------------------------------------------*/
227 void
228 cc1120_arch_rxfifo_read(uint8_t *packet, uint8_t packet_length)
229 {
230  uint8_t i;
231 
232  (void) cc1120_arch_spi_rw_byte(CC1120_FIFO_ACCESS | CC1120_BURST_BIT | CC1120_READ_BIT);
233 
234  for(i = 0; i < packet_length; i++)
235  {
236  //(void) cc1120_arch_spi_rw_byte(CC1120_FIFO_ACCESS | CC1120_STANDARD_BIT | CC1120_READ_BIT);
237  packet[i] = cc1120_arch_spi_rw_byte(0);
238  }
240 }
241 
242 
243 /*---------------------------------------------------------------------------*/
244 uint8_t
245 cc1120_arch_read_cca(void)
246 {
247  /*if(CC1120_GDO3_PORT(IN) & BV(CC1120_GDO3_PIN))
248  {
249  return 1;
250  }
251  else
252  {*/
253  return 0;
254  //}
255 }
256 
257 
258 /*---------------------------------------------------------------------------*/
259 uint8_t
260 cc1120_arch_read_gpio2(void)
261 {
262  if(CC1120_GDO3_PORT(IN) & BV(CC1120_GDO3_PIN))
263  {
264  return 1;
265  }
266  else
267  {
268  return 0;
269  }
270 }
271 
272 uint8_t
273 cc1120_arch_read_gpio3(void)
274 {
275  if(CC1120_GDO3_PORT(IN) & BV(CC1120_GDO3_PIN))
276  {
277  return 1;
278  }
279  else
280  {
281  return 0;
282  }
283 }
284 
285 /* -------------------------- Interrupt Functions -------------------------- */
286 
287 /* On the Z1, the interrupt is shared with the ADXL345 accelerometer.
288  * The interrupt routine is handled in adcl345.c. */
289 
290 /*---------------------------------------------------------------------------*/
291 void
292 cc1120_arch_interrupt_enable(void)
293 {
294  /* Reset interrupt trigger */
295  CC1120_GDO0_PORT(IFG) &= ~BV(CC1120_GDO0_PIN);
296  /* Enable interrupt on the GDO0 pin */
297  CC1120_GDO0_PORT(IE) |= BV(CC1120_GDO0_PIN);
298 }
299 
300 /*---------------------------------------------------------------------------*/
301 void
302 cc1120_arch_interrupt_disable(void)
303 {
304  /* Disable interrupt on the GDO0 pin */
305  CC1120_GDO0_PORT(IE) &= ~BV(CC1120_GDO0_PIN);
306  /* Reset interrupt trigger */
307  CC1120_GDO0_PORT(IFG) &= ~BV(CC1120_GDO0_PIN);
308 }
309 /*---------------------------------------------------------------------------*/
310 void
311 cc1120_arch_interrupt_acknowledge(void)
312 {
313  /* Disable interrupt on the GDO0 pin */
314  CC1120_GDO0_PORT(IE) &= ~BV(CC1120_GDO0_PIN);
315  /* Reset interrupt trigger */
316  CC1120_GDO0_PORT(IFG) &= ~BV(CC1120_GDO0_PIN);
317  /* Enable interrupt on the GDO0 pin */
318  CC1120_GDO0_PORT(IE) |= BV(CC1120_GDO0_PIN);
319 }
320 
321 
#define RTIMER_NOW()
Get the current clock time.
Definition: rtimer.h:135
void watchdog_periodic(void)
Writes the WDT clear sequence.
Definition: watchdog.c:64
void clock_wait(clock_time_t t)
Wait for a given number of ticks.
Definition: clock.c:162
void clock_delay_usec(uint16_t dt)
Delay a given number of microseconds.
Definition: clock.c:94