2 * Copyright Droids Corporation (2008)
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * Author : Julien LE GUEN - jlg@jleguen.info
25 #include <aversive/wait.h>
26 #include <aversive/error.h>
31 #include <cc2420_arch.h>
32 #include <cc2420_config.h>
35 #define SLAVE_SELECT() spi_slave_select(g_slave_adr)
36 #define SLAVE_DESELECT() spi_slave_deselect(g_slave_adr)
39 #define SLAVE_SELECT() PORTC &= 0xFE
40 #define SLAVE_DESELECT() PORTC |= 0x01
43 volatile static uint8_t g_slave_adr;
49 uint8_t cc2420_get_status(void)
53 tmp = spi_send_and_receive_byte(SNOP);
59 * Write to a strobe register
62 uint8_t cc2420_strobe_register(uint8_t reg)
66 tmp = spi_send_and_receive_byte(reg);
72 * Read a two-bytes register
74 uint16_t cc2420_read_register(uint8_t reg)
78 /* Send address and READ action */
79 spi_send_byte(REG_BIT | READ_BIT | (reg & REG_MASK));
80 /* Just send nothing (0x00) and read the value back (MSB first) */
81 value = spi_receive_byte();
82 value = (value<<8) | spi_receive_byte();
88 * Write to a two-bytes register
90 void cc2420_write_register(uint8_t reg, uint16_t value)
93 /* Send address and WRITE action */
94 spi_send_byte(REG_BIT | WRITE_BIT | (reg & REG_MASK));
95 /* Send the value, ignore the status byte in return */
96 spi_send_byte((uint8_t)((value & 0xFF00)>>8));
97 spi_send_byte((uint8_t)(value & 0x00FF));
102 * Write the contents of a buffer to TXFIFO
103 * Returns last read status byte
105 uint8_t cc2420_write_txfifo(uint8_t *buffer, uint8_t length)
110 /* Flush the FIFO - don't need the status byte */
111 //spi_send_byte(SFLUSHTX);
112 /* TXFIFO Register address */
113 NOTICE(E_CC2420, "Writing %d bytes to TXFIFO at address 0x%x", length, REG_BIT | WRITE_BIT | TXFIFO);
114 spi_send_byte(REG_BIT | WRITE_BIT | TXFIFO);
116 for(i = 0; i < length; i++)
118 /* We may need the status byte at any time
119 * For instance, to detect TXFIFO underflow */
120 status = spi_send_and_receive_byte(buffer[i]);
127 * Write the contents of a buffer to RXFIFO
128 * Returns last read status byte
130 uint8_t cc2420_write_rxfifo(uint8_t *buffer, uint8_t length)
135 /* Flush the FIFO - don't need the status byte */
136 spi_send_byte(SFLUSHRX);
137 /* RXFIFO Register address */
138 spi_send_byte(REG_BIT | WRITE_BIT | RXFIFO);
140 for(i = 0; i < length; i++)
142 /* We may need the status byte at any time
143 * For instance, to detect TXFIFO underflow */
144 status = spi_send_and_receive_byte(buffer[i]);
151 * Read the contents of RXFIFO into a buffer
153 void cc2420_read_rxfifo(uint8_t *buffer, uint8_t length)
157 /* RXFIFO Register address */
158 spi_send_byte(REG_BIT | READ_BIT | RXFIFO);
160 for(i = 0; i < length; i++)
162 buffer[i] = spi_receive_byte();
167 /* XXX Ca fait de la merde dans le coin la... */
170 * Write to a RAM address one or several byte(s)
171 * /!\ This is NOT foolproof, you have to be sure of the
172 * address you write to, and the length of your buffer
174 void cc2420_write_ram(uint16_t addr, uint8_t *buffer, uint16_t length)
178 /* Forge the address */
179 spi_send_byte(RAM_BIT | (addr & RAM_MASK));
180 spi_send_byte((((addr>>1) & BANK_MASK) | RAM_READ_WRITE));
182 for(i = 0; i < length; i++)
184 spi_send_byte((uint8_t)buffer[i]);
190 * Read from RAM. Same warning.
192 void cc2420_read_ram(uint16_t addr, uint8_t *buffer, uint16_t length)
196 /* Forge the address */
197 spi_send_byte((RAM_BIT | (addr & RAM_MASK)));
198 spi_send_byte((((addr>>1) & BANK_MASK) | RAM_READ));
199 /* Receive the data */
200 for(i = 0; i < length; i++)
202 buffer[i] = spi_receive_byte();
210 * Initialize ports and starts-up the chip
212 void cc2420_init(void)
214 NOTICE(E_CC2420, "Initialization");
215 /* Check and start SPI module */
216 if (spi_get_mode() == SPI_MODE_UNINIT)
218 g_slave_adr = spi_register_ss_line(&CC2420_SS_PORT, CC2420_SS_PIN);
219 spi_init(SPI_MODE_MASTER, SPI_FORMAT_0, SPI_CLK_RATE_2);
222 NOTICE(E_CC2420, "Registered slave line: %d", g_slave_adr);
224 /* Configure all IO ports in input */
225 DDR(CC2420_FIFO_PORT) &= ~(_BV(CC2420_FIFO_PIN));
226 DDR(CC2420_FIFOP_PORT) &= ~(_BV(CC2420_FIFOP_PIN));
227 DDR(CC2420_CCA_PORT) &= ~(_BV(CC2420_CCA_PIN));
228 DDR(CC2420_SFD_PORT) &= ~(_BV(CC2420_SFD_PIN));
230 CC2420_SS_DDR = 0x01;
232 /* Enable on-chip voltage regulator */
233 #ifdef CC2420_VREG_ENABLE
234 NOTICE(E_CC2420, "Enable on-chip voltage regulator");
235 DDR(CC2420_VREG_EN_PORT) |= _BV(CC2420_VREG_EN_PIN);
236 CC2420_VREG_EN_PORT |= _BV(CC2420_VREG_EN_PIN);
241 #ifdef CC2420_RESET_ENABLE
242 NOTICE(E_CC2420, "Reset radio chip");
243 DDR(CC2420_RESET_PORT) |= _BV(CC2420_RESET_PIN);
244 CC2420_RESET_PORT &= ~(_BV(CC2420_RESET_PIN));
246 CC2420_RESET_PORT |= _BV(CC2420_RESET_PIN);
251 /* Start the oscillator */
252 NOTICE(E_CC2420, "Start the oscillator");
254 /* Select the CC2420 SS line */
256 spi_send_byte(SXOSCON);
257 /* Release SS line */
260 /* Wait for stability */
261 while(!CC2420_STATUS_CHECK(XOSC16M_STABLE))
264 NOTICE(E_CC2420, "Init done");