Moved the cc2520 driver into its own dev/cc2520 module

This commit is contained in:
Adam Dunkels 2013-11-28 14:59:10 +01:00
parent 837a697dc8
commit c9efe3c3c4
7 changed files with 7 additions and 7 deletions

832
dev/cc2520/cc2520.c Normal file
View file

@ -0,0 +1,832 @@
/*
* Copyright (c) 2011, Swedish Institute of Computer Science
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*/
/*
* This code is almost device independent and should be easy to port.
*/
#include "contiki.h"
#include "dev/spi.h"
#include "dev/cc2520/cc2520.h"
#include "dev/cc2520/cc2520_const.h"
#include "net/packetbuf.h"
#include "net/rime/rimestats.h"
#include "net/netstack.h"
#include <string.h>
#ifndef CC2520_CONF_AUTOACK
#define CC2520_CONF_AUTOACK 0
#endif /* CC2520_CONF_AUTOACK */
#define WITH_SEND_CCA 1
#define FOOTER_LEN 2
#define FOOTER1_CRC_OK 0x80
#define FOOTER1_CORRELATION 0x7f
#include <stdio.h>
#define DEBUG 0
#if DEBUG
#define PRINTF(...) printf(__VA_ARGS__)
#else
#define PRINTF(...) do {} while (0)
#endif
#if 0 && DEBUG
#include "dev/leds.h"
#define LEDS_ON(x) leds_on(x)
#define LEDS_OFF(x) leds_off(x)
#else
#define LEDS_ON(x)
#define LEDS_OFF(x)
#endif
void cc2520_arch_init(void);
/* XXX hack: these will be made as Chameleon packet attributes */
rtimer_clock_t cc2520_time_of_arrival, cc2520_time_of_departure;
int cc2520_authority_level_of_sender;
int cc2520_packets_seen, cc2520_packets_read;
#define BUSYWAIT_UNTIL(cond, max_time) \
do { \
rtimer_clock_t t0; \
t0 = RTIMER_NOW(); \
while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (max_time))); \
} while(0)
volatile uint8_t cc2520_sfd_counter;
volatile uint16_t cc2520_sfd_start_time;
volatile uint16_t cc2520_sfd_end_time;
static volatile uint16_t last_packet_timestamp;
/*---------------------------------------------------------------------------*/
PROCESS(cc2520_process, "CC2520 driver");
/*---------------------------------------------------------------------------*/
int cc2520_on(void);
int cc2520_off(void);
static int cc2520_read(void *buf, unsigned short bufsize);
static int cc2520_prepare(const void *data, unsigned short len);
static int cc2520_transmit(unsigned short len);
static int cc2520_send(const void *data, unsigned short len);
static int cc2520_receiving_packet(void);
static int pending_packet(void);
static int cc2520_cca(void);
/* static int detected_energy(void); */
signed char cc2520_last_rssi;
uint8_t cc2520_last_correlation;
const struct radio_driver cc2520_driver =
{
cc2520_init,
cc2520_prepare,
cc2520_transmit,
cc2520_send,
cc2520_read,
/* cc2520_set_channel, */
/* detected_energy, */
cc2520_cca,
cc2520_receiving_packet,
pending_packet,
cc2520_on,
cc2520_off,
};
static uint8_t receive_on;
static int channel;
/*---------------------------------------------------------------------------*/
static void
getrxdata(void *buf, int len)
{
CC2520_READ_FIFO_BUF(buf, len);
}
static void
getrxbyte(uint8_t *byte)
{
CC2520_READ_FIFO_BYTE(*byte);
}
static void
flushrx(void)
{
uint8_t dummy;
CC2520_READ_FIFO_BYTE(dummy);
CC2520_STROBE(CC2520_INS_SFLUSHRX);
CC2520_STROBE(CC2520_INS_SFLUSHRX);
}
/*---------------------------------------------------------------------------*/
static void
strobe(uint8_t regname)
{
CC2520_STROBE(regname);
}
/*---------------------------------------------------------------------------*/
static unsigned int
status(void)
{
uint8_t status;
CC2520_GET_STATUS(status);
return status;
}
/*---------------------------------------------------------------------------*/
static uint8_t locked, lock_on, lock_off;
static void
on(void)
{
CC2520_ENABLE_FIFOP_INT();
strobe(CC2520_INS_SRXON);
BUSYWAIT_UNTIL(status() & (BV(CC2520_XOSC16M_STABLE)), RTIMER_SECOND / 100);
ENERGEST_ON(ENERGEST_TYPE_LISTEN);
receive_on = 1;
}
static void
off(void)
{
/* PRINTF("off\n");*/
receive_on = 0;
/* Wait for transmission to end before turning radio off. */
BUSYWAIT_UNTIL(!(status() & BV(CC2520_TX_ACTIVE)), RTIMER_SECOND / 10);
ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
strobe(CC2520_INS_SRFOFF);
CC2520_DISABLE_FIFOP_INT();
if(!CC2520_FIFOP_IS_1) {
flushrx();
}
}
/*---------------------------------------------------------------------------*/
#define GET_LOCK() locked++
static void RELEASE_LOCK(void) {
if(locked == 1) {
if(lock_on) {
on();
lock_on = 0;
}
if(lock_off) {
off();
lock_off = 0;
}
}
locked--;
}
/*---------------------------------------------------------------------------*/
static uint8_t
getreg(uint16_t regname)
{
uint8_t reg;
CC2520_READ_REG(regname, reg);
return reg;
}
/*---------------------------------------------------------------------------*/
static void
setreg(uint16_t regname, uint8_t value)
{
CC2520_WRITE_REG(regname, value);
}
/*---------------------------------------------------------------------------*/
static void
set_txpower(uint8_t power)
{
setreg(CC2520_TXPOWER, power);
}
/*---------------------------------------------------------------------------*/
#define AUTOCRC (1 << 6)
#define AUTOACK (1 << 5)
#define FRAME_MAX_VERSION ((1 << 3) | (1 << 2))
#define FRAME_FILTER_ENABLE (1 << 0)
#define CORR_THR(n) (((n) & 0x1f) << 6)
#define FIFOP_THR(n) ((n) & 0x7f)
/*---------------------------------------------------------------------------*/
int
cc2520_init(void)
{
{
int s = splhigh();
cc2520_arch_init(); /* Initalize ports and SPI. */
CC2520_DISABLE_FIFOP_INT();
CC2520_FIFOP_INT_INIT();
splx(s);
}
SET_VREG_INACTIVE();
clock_delay(250);
/* Turn on voltage regulator and reset. */
SET_VREG_ACTIVE();
clock_delay(250);
SET_RESET_ACTIVE();
clock_delay(127);
SET_RESET_INACTIVE();
clock_delay(125);
/* Turn on the crystal oscillator. */
strobe(CC2520_INS_SXOSCON);
clock_delay(125);
BUSYWAIT_UNTIL(status() & (BV(CC2520_XOSC16M_STABLE)), RTIMER_SECOND / 100);
/* Change default values as recommended in the data sheet, */
/* correlation threshold = 20, RX bandpass filter = 1.3uA.*/
setreg(CC2520_TXCTRL, 0x94);
setreg(CC2520_TXPOWER, 0x13); // Output power 1 dBm
/*
valeurs de TXPOWER
0x03 -> -18 dBm
0x2C -> -7 dBm
0x88 -> -4 dBm
0x81 -> -2 dBm
0x32 -> 0 dBm
0x13 -> 1 dBm
0x32 -> 0 dBm
0x13 -> 1 dBm
0xAB -> 2 dBm
0xF2 -> 3 dBm
0xF7 -> 5 dBm
*/
setreg(CC2520_CCACTRL0, 0xF8); // CCA treshold -80dBm
// Recommended RX settings
setreg(CC2520_MDMCTRL0, 0x84); // Controls modem
setreg(CC2520_MDMCTRL1, 0x14); // Controls modem
setreg(CC2520_RXCTRL, 0x3F); // Adjust currents in RX related analog modules
setreg(CC2520_FSCTRL, 0x5A); // Adjust currents in synthesizer.
setreg(CC2520_FSCAL1, 0x2B); // Adjust currents in VCO
setreg(CC2520_AGCCTRL1, 0x11); // Adjust target value for AGC control loop
setreg(CC2520_AGCCTRL2, 0xEB);
// Disable external clock
setreg(CC2520_EXTCLOCK, 0x00);
// Tune ADC performance
setreg(CC2520_ADCTEST0, 0x10);
setreg(CC2520_ADCTEST1, 0x0E);
setreg(CC2520_ADCTEST2, 0x03);
/* Set auto CRC on frame. */
#if CC2520_CONF_AUTOACK
setreg(CC2520_FRMCTRL0, AUTOCRC | AUTOACK);
setreg(CC2520_FRMFILT0, FRAME_MAX_VERSION|FRAME_FILTER_ENABLE);
#else
/* setreg(CC2520_FRMCTRL0, 0x60); */
setreg(CC2520_FRMCTRL0, AUTOCRC);
/* Disable filter on @ (remove if you want to address specific wismote) */
setreg(CC2520_FRMFILT0, 0x00);
#endif /* CC2520_CONF_AUTOACK */
/* SET_RXENMASK_ON_TX */
setreg(CC2520_FRMCTRL1, 1);
/* Set FIFOP threshold to maximum .*/
setreg(CC2520_FIFOPCTRL, FIFOP_THR(0x7F));
cc2520_set_pan_addr(0xffff, 0x0000, NULL);
cc2520_set_channel(26);
flushrx();
process_start(&cc2520_process, NULL);
return 1;
}
/*---------------------------------------------------------------------------*/
static int
cc2520_transmit(unsigned short payload_len)
{
int i, txpower;
GET_LOCK();
txpower = 0;
if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) {
/* Remember the current transmission power */
txpower = cc2520_get_txpower();
/* Set the specified transmission power */
set_txpower(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) - 1);
}
/* The TX FIFO can only hold one packet. Make sure to not overrun
* FIFO by waiting for transmission to start here and synchronizing
* with the CC2520_TX_ACTIVE check in cc2520_send.
*
* Note that we may have to wait up to 320 us (20 symbols) before
* transmission starts.
*/
#ifndef CC2520_CONF_SYMBOL_LOOP_COUNT
#error CC2520_CONF_SYMBOL_LOOP_COUNT needs to be set!!!
#else
#define LOOP_20_SYMBOLS CC2520_CONF_SYMBOL_LOOP_COUNT
#endif
#if WITH_SEND_CCA
strobe(CC2520_INS_SRXON);
BUSYWAIT_UNTIL(status() & BV(CC2520_RSSI_VALID) , RTIMER_SECOND / 10);
strobe(CC2520_INS_STXONCCA);
#else /* WITH_SEND_CCA */
strobe(CC2520_INS_STXON);
#endif /* WITH_SEND_CCA */
for(i = LOOP_20_SYMBOLS; i > 0; i--) {
if(CC2520_SFD_IS_1) {
{
rtimer_clock_t sfd_timestamp;
sfd_timestamp = cc2520_sfd_start_time;
if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
PACKETBUF_ATTR_PACKET_TYPE_TIMESTAMP) {
/* Write timestamp to last two bytes of packet in TXFIFO. */
CC2520_WRITE_RAM(&sfd_timestamp, CC2520RAM_TXFIFO + payload_len - 1, 2);
}
}
if(!(status() & BV(CC2520_TX_ACTIVE))) {
/* SFD went high but we are not transmitting. This means that
we just started receiving a packet, so we drop the
transmission. */
RELEASE_LOCK();
return RADIO_TX_COLLISION;
}
if(receive_on) {
ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
}
ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
/* We wait until transmission has ended so that we get an
accurate measurement of the transmission time.*/
//BUSYWAIT_UNTIL(getreg(CC2520_EXCFLAG0) & TX_FRM_DONE , RTIMER_SECOND / 100);
BUSYWAIT_UNTIL(!(status() & BV(CC2520_TX_ACTIVE)), RTIMER_SECOND / 10);
#ifdef ENERGEST_CONF_LEVELDEVICE_LEVELS
ENERGEST_OFF_LEVEL(ENERGEST_TYPE_TRANSMIT,cc2520_get_txpower());
#endif
ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
if(receive_on) {
ENERGEST_ON(ENERGEST_TYPE_LISTEN);
} else {
/* We need to explicitly turn off the radio,
* since STXON[CCA] -> TX_ACTIVE -> RX_ACTIVE */
off();
}
if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) {
/* Restore the transmission power */
set_txpower(txpower & 0xff);
}
RELEASE_LOCK();
return RADIO_TX_OK;
}
}
/* If we are using WITH_SEND_CCA, we get here if the packet wasn't
transmitted because of other channel activity. */
RIMESTATS_ADD(contentiondrop);
PRINTF("cc2520: do_send() transmission never started\n");
if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) {
/* Restore the transmission power */
set_txpower(txpower & 0xff);
}
RELEASE_LOCK();
return RADIO_TX_COLLISION;
}
/*---------------------------------------------------------------------------*/
static int
cc2520_prepare(const void *payload, unsigned short payload_len)
{
uint8_t total_len;
GET_LOCK();
PRINTF("cc2520: sending %d bytes\n", payload_len);
/*int i;
for(i = 0; i < payload_len;i++)
printf("%x",((uint8_t *) payload)[i]);
printf("\n");*/
RIMESTATS_ADD(lltx);
/* Wait for any previous transmission to finish. */
/* while(status() & BV(CC2520_TX_ACTIVE));*/
/* Write packet to TX FIFO. */
strobe(CC2520_INS_SFLUSHTX);
total_len = payload_len + FOOTER_LEN;
CC2520_WRITE_FIFO_BUF(&total_len, 1);
CC2520_WRITE_FIFO_BUF(payload, payload_len);
RELEASE_LOCK();
return 0;
}
/*---------------------------------------------------------------------------*/
static int
cc2520_send(const void *payload, unsigned short payload_len)
{
cc2520_prepare(payload, payload_len);
return cc2520_transmit(payload_len);
}
/*---------------------------------------------------------------------------*/
int
cc2520_off(void)
{
/* Don't do anything if we are already turned off. */
if(receive_on == 0) {
return 1;
}
/* If we are called when the driver is locked, we indicate that the
radio should be turned off when the lock is unlocked. */
if(locked) {
/* printf("Off when locked (%d)\n", locked);*/
lock_off = 1;
return 1;
}
GET_LOCK();
/* If we are currently receiving a packet (indicated by SFD == 1),
we don't actually switch the radio off now, but signal that the
driver should switch off the radio once the packet has been
received and processed, by setting the 'lock_off' variable. */
if(status() & BV(CC2520_TX_ACTIVE)) {
lock_off = 1;
} else {
off();
}
RELEASE_LOCK();
return 1;
}
/*---------------------------------------------------------------------------*/
int
cc2520_on(void)
{
if(receive_on) {
return 1;
}
if(locked) {
lock_on = 1;
return 1;
}
GET_LOCK();
on();
RELEASE_LOCK();
return 1;
}
/*---------------------------------------------------------------------------*/
int
cc2520_get_channel(void)
{
return channel;
}
/*---------------------------------------------------------------------------*/
int
cc2520_set_channel(int c)
{
uint16_t f;
GET_LOCK();
/*
* Subtract the base channel (11), multiply by 5, which is the
* channel spacing. 357 is 2405-2048 and 0x4000 is LOCK_THR = 1.
*/
channel = c;
f = MIN_CHANNEL + ((channel - MIN_CHANNEL) * CHANNEL_SPACING);
/*
* Writing RAM requires crystal oscillator to be stable.
*/
BUSYWAIT_UNTIL((status() & (BV(CC2520_XOSC16M_STABLE))), RTIMER_SECOND / 10);
/* Wait for any transmission to end. */
BUSYWAIT_UNTIL(!(status() & BV(CC2520_TX_ACTIVE)), RTIMER_SECOND / 10);
/* Define radio channel (between 11 and 25) */
setreg(CC2520_FREQCTRL, f);
/* If we are in receive mode, we issue an SRXON command to ensure
that the VCO is calibrated. */
if(receive_on) {
strobe(CC2520_INS_SRXON);
}
RELEASE_LOCK();
return 1;
}
/*---------------------------------------------------------------------------*/
void
cc2520_set_pan_addr(unsigned pan,
unsigned addr,
const uint8_t *ieee_addr)
{
uint8_t tmp[2];
GET_LOCK();
/*
* Writing RAM requires crystal oscillator to be stable.
*/
BUSYWAIT_UNTIL(status() & (BV(CC2520_XOSC16M_STABLE)), RTIMER_SECOND / 10);
tmp[0] = pan & 0xff;
tmp[1] = pan >> 8;
CC2520_WRITE_RAM(&tmp, CC2520RAM_PANID, 2);
tmp[0] = addr & 0xff;
tmp[1] = addr >> 8;
CC2520_WRITE_RAM(&tmp, CC2520RAM_SHORTADDR, 2);
if(ieee_addr != NULL) {
int f;
uint8_t tmp_addr[8];
// LSB first, MSB last for 802.15.4 addresses in CC2520
for (f = 0; f < 8; f++) {
tmp_addr[7 - f] = ieee_addr[f];
}
CC2520_WRITE_RAM(tmp_addr, CC2520RAM_IEEEADDR, 8);
}
RELEASE_LOCK();
}
/*---------------------------------------------------------------------------*/
/*
* Interrupt leaves frame intact in FIFO.
*/
int
cc2520_interrupt(void)
{
CC2520_CLEAR_FIFOP_INT();
process_poll(&cc2520_process);
last_packet_timestamp = cc2520_sfd_start_time;
cc2520_packets_seen++;
return 1;
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(cc2520_process, ev, data)
{
int len;
PROCESS_BEGIN();
PRINTF("cc2520_process: started\n");
while(1) {
PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
PRINTF("cc2520_process: calling receiver callback\n");
packetbuf_clear();
packetbuf_set_attr(PACKETBUF_ATTR_TIMESTAMP, last_packet_timestamp);
len = cc2520_read(packetbuf_dataptr(), PACKETBUF_SIZE);
packetbuf_set_datalen(len);
NETSTACK_RDC.input();
/* flushrx(); */
}
PROCESS_END();
}
/*---------------------------------------------------------------------------*/
static int
cc2520_read(void *buf, unsigned short bufsize)
{
uint8_t footer[2];
uint8_t len;
if(!CC2520_FIFOP_IS_1) {
return 0;
}
GET_LOCK();
cc2520_packets_read++;
getrxbyte(&len);
if(len > CC2520_MAX_PACKET_LEN) {
/* Oops, we must be out of sync. */
flushrx();
RIMESTATS_ADD(badsynch);
RELEASE_LOCK();
return 0;
}
if(len <= FOOTER_LEN) {
flushrx();
RIMESTATS_ADD(tooshort);
RELEASE_LOCK();
return 0;
}
if(len - FOOTER_LEN > bufsize) {
flushrx();
RIMESTATS_ADD(toolong);
RELEASE_LOCK();
return 0;
}
getrxdata(buf, len - FOOTER_LEN);
getrxdata(footer, FOOTER_LEN);
if(footer[1] & FOOTER1_CRC_OK) {
cc2520_last_rssi = footer[0];
cc2520_last_correlation = footer[1] & FOOTER1_CORRELATION;
packetbuf_set_attr(PACKETBUF_ATTR_RSSI, cc2520_last_rssi);
packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, cc2520_last_correlation);
RIMESTATS_ADD(llrx);
} else {
RIMESTATS_ADD(badcrc);
len = FOOTER_LEN;
}
if(CC2520_FIFOP_IS_1) {
if(!CC2520_FIFO_IS_1) {
/* Clean up in case of FIFO overflow! This happens for every
* full length frame and is signaled by FIFOP = 1 and FIFO =
* 0. */
flushrx();
} else {
/* Another packet has been received and needs attention. */
process_poll(&cc2520_process);
}
}
RELEASE_LOCK();
if(len < FOOTER_LEN) {
return 0;
}
return len - FOOTER_LEN;
}
/*---------------------------------------------------------------------------*/
void
cc2520_set_txpower(uint8_t power)
{
GET_LOCK();
set_txpower(power);
RELEASE_LOCK();
}
/*---------------------------------------------------------------------------*/
int
cc2520_get_txpower(void)
{
uint8_t power;
GET_LOCK();
power = getreg(CC2520_TXPOWER);
RELEASE_LOCK();
return power;
}
/*---------------------------------------------------------------------------*/
int
cc2520_rssi(void)
{
int rssi;
int radio_was_off = 0;
if(locked) {
return 0;
}
GET_LOCK();
if(!receive_on) {
radio_was_off = 1;
cc2520_on();
}
BUSYWAIT_UNTIL(status() & BV(CC2520_RSSI_VALID), RTIMER_SECOND / 100);
rssi = (int)((signed char)getreg(CC2520_RSSI));
if(radio_was_off) {
cc2520_off();
}
RELEASE_LOCK();
return rssi;
}
/*---------------------------------------------------------------------------*/
/*
static int
detected_energy(void)
{
return cc2520_rssi();
}
*/
/*---------------------------------------------------------------------------*/
int
cc2520_cca_valid(void)
{
int valid;
if(locked) {
return 1;
}
GET_LOCK();
valid = !!(status() & BV(CC2520_RSSI_VALID));
RELEASE_LOCK();
return valid;
}
/*---------------------------------------------------------------------------*/
static int
cc2520_cca(void)
{
int cca;
int radio_was_off = 0;
/* If the radio is locked by an underlying thread (because we are
being invoked through an interrupt), we preted that the coast is
clear (i.e., no packet is currently being transmitted by a
neighbor). */
if(locked) {
return 1;
}
GET_LOCK();
if(!receive_on) {
radio_was_off = 1;
cc2520_on();
}
/* Make sure that the radio really got turned on. */
if(!receive_on) {
RELEASE_LOCK();
if(radio_was_off) {
cc2520_off();
}
return 1;
}
BUSYWAIT_UNTIL(status() & BV(CC2520_RSSI_VALID), RTIMER_SECOND / 100);
cca = CC2520_CCA_IS_1;
if(radio_was_off) {
cc2520_off();
}
RELEASE_LOCK();
return cca;
}
/*---------------------------------------------------------------------------*/
int
cc2520_receiving_packet(void)
{
return CC2520_SFD_IS_1;
}
/*---------------------------------------------------------------------------*/
static int
pending_packet(void)
{
return CC2520_FIFOP_IS_1;
}
/*---------------------------------------------------------------------------*/
void
cc2520_set_cca_threshold(int value)
{
GET_LOCK();
setreg(CC2520_CCACTRL0, value & 0xff);
RELEASE_LOCK();
}
/*---------------------------------------------------------------------------*/

198
dev/cc2520/cc2520.h Normal file
View file

@ -0,0 +1,198 @@
/*
* Copyright (c) 2011, Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*/
/**
* \file
* CC2520 driver header file
* \author
* Adam Dunkels <adam@sics.se>
* Joakim Eriksson <joakime@sics.se>
*/
#ifndef CC2520_H_
#define CC2520_H_
#include "contiki.h"
#include "dev/spi.h"
#include "dev/radio.h"
#include "dev/cc2520/cc2520_const.h"
int cc2520_init(void);
#define CC2520_MAX_PACKET_LEN 127
int cc2520_set_channel(int channel);
int cc2520_get_channel(void);
void cc2520_set_pan_addr(unsigned pan,
unsigned addr,
const uint8_t *ieee_addr);
extern signed char cc2520_last_rssi;
extern uint8_t cc2520_last_correlation;
int cc2520_rssi(void);
extern const struct radio_driver cc2520_driver;
/**
* \param power Between 1 and 31.
*/
void cc2520_set_txpower(uint8_t power);
int cc2520_get_txpower(void);
#define CC2520_TXPOWER_MAX 31
#define CC2520_TXPOWER_MIN 0
/**
* Interrupt function, called from the simple-cc2520-arch driver.
*
*/
int cc2520_interrupt(void);
/* XXX hack: these will be made as Chameleon packet attributes */
extern rtimer_clock_t cc2520_time_of_arrival,
cc2520_time_of_departure;
extern int cc2520_authority_level_of_sender;
int cc2520_on(void);
int cc2520_off(void);
void cc2520_set_cca_threshold(int value);
/************************************************************************/
/* Additional SPI Macros for the CC2520 */
/************************************************************************/
/* Send a strobe to the CC2520 */
#define CC2520_STROBE(s) \
do { \
CC2520_SPI_ENABLE(); \
SPI_WRITE(s); \
CC2520_SPI_DISABLE(); \
} while (0)
/* Write to a register in the CC2520 */
/* Note: the SPI_WRITE(0) seems to be needed for getting the */
/* write reg working on the Z1 / MSP430X platform */
#define CC2520_WRITE_REG(adr,data) \
do { \
CC2520_SPI_ENABLE(); \
SPI_WRITE_FAST(CC2520_INS_MEMWR | ((adr>>8)&0xFF)); \
SPI_WRITE_FAST(adr & 0xff); \
SPI_WRITE_FAST((uint8_t) data); \
SPI_WAITFORTx_ENDED(); \
CC2520_SPI_DISABLE(); \
} while(0)
/* Read a register in the CC2520 */
#define CC2520_READ_REG(adr,data) \
do { \
CC2520_SPI_ENABLE(); \
SPI_WRITE((CC2520_INS_MEMRD | ((adr>>8)&0xFF))); \
SPI_WRITE((adr & 0xFF)); \
SPI_READ(data); \
CC2520_SPI_DISABLE(); \
} while(0)
#define CC2520_READ_FIFO_BYTE(data) \
do { \
CC2520_SPI_ENABLE(); \
SPI_WRITE(CC2520_INS_RXBUF); \
(void)SPI_RXBUF; \
SPI_READ(data); \
clock_delay(1); \
CC2520_SPI_DISABLE(); \
} while(0)
#define CC2520_READ_FIFO_BUF(buffer,count) \
do { \
uint8_t i; \
CC2520_SPI_ENABLE(); \
SPI_WRITE(CC2520_INS_RXBUF); \
(void)SPI_RXBUF; \
for(i = 0; i < (count); i++) { \
SPI_READ(((uint8_t *)(buffer))[i]); \
} \
clock_delay(1); \
CC2520_SPI_DISABLE(); \
} while(0)
#define CC2520_WRITE_FIFO_BUF(buffer,count) \
do { \
uint8_t i; \
CC2520_SPI_ENABLE(); \
SPI_WRITE_FAST(CC2520_INS_TXBUF); \
for(i = 0; i < (count); i++) { \
SPI_WRITE_FAST(((uint8_t *)(buffer))[i]); \
SPI_WAITFORTxREADY(); \
} \
SPI_WAITFORTx_ENDED(); \
CC2520_SPI_DISABLE(); \
} while(0)
/* Write to RAM in the CC2520 */
#define CC2520_WRITE_RAM(buffer,adr,count) \
do { \
uint8_t i; \
CC2520_SPI_ENABLE(); \
SPI_WRITE_FAST(CC2520_INS_MEMWR | (((adr)>>8) & 0xFF)); \
SPI_WRITE_FAST(((adr) & 0xFF)); \
for(i = 0; i < (count); i++) { \
SPI_WRITE_FAST(((uint8_t*)(buffer))[i]); \
} \
SPI_WAITFORTx_ENDED(); \
CC2520_SPI_DISABLE(); \
} while(0)
/* Read from RAM in the CC2520 */
#define CC2520_READ_RAM(buffer,adr,count) \
do { \
uint8_t i; \
CC2520_SPI_ENABLE(); \
SPI_WRITE(CC2520_INS_MEMRD | (((adr)>>8) & 0xFF)); \
SPI_WRITE(((adr) & 0xFF)); \
SPI_RXBUF; \
for(i = 0; i < (count); i++) { \
SPI_READ(((uint8_t*)(buffer))[i]); \
} \
CC2520_SPI_DISABLE(); \
} while(0)
/* Read status of the CC2520 */
#define CC2520_GET_STATUS(s) \
do { \
CC2520_SPI_ENABLE(); \
SPI_WRITE(CC2520_INS_SNOP); \
s = SPI_RXBUF; \
CC2520_SPI_DISABLE(); \
} while (0)
#endif /* CC2520_H_ */

216
dev/cc2520/cc2520_const.h Normal file
View file

@ -0,0 +1,216 @@
/*
* Copyright (c) 2011, Swedish Institute of Computer Science
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#ifndef CC2520_CONST_H
#define CC2520_CONST_H
/*
* All constants are from the Chipcon cc2520 Data Sheet that at one
* point in time could be found at
* http://www.chipcon.com/files/cc2520_Data_Sheet_1_4.pdf
*
* The page numbers below refer to pages in this document.
*/
/* Page 27. */
enum cc2520_status_byte {
CC2520_XOSC16M_STABLE = 7,
CC2520_RSSI_VALID = 6,
CC2520_EXCEPTION_CHA = 5,
CC2520_EXCEPTION_CHB = 4,
CC2520_DPU_H = 3,
CC2520_DPU_L = 2,
CC2520_TX_ACTIVE = 1,
CC2520_RX_ACTIVE = 0,
};
#define TX_FRM_DONE 0x02
#define RX_FRM_DONE 0x01
#define RX_FRM_ABORTED 0x20
#define RX_FRM_UNDERFLOW 0x20
/* Page 27. */
enum cc2520_memory_size {
CC2520_RAM_SIZE = 640,
CC2520_FIFO_SIZE = 128,
};
/* Page 29. */
enum cc2520_address {
CC2520RAM_TXFIFO = 0x100,
CC2520RAM_RXFIFO = 0x180,
CC2520RAM_IEEEADDR = 0x3EA,
CC2520RAM_PANID = 0x3F2,
CC2520RAM_SHORTADDR = 0x3F4,
};
// IEEE 802.15.4 defined constants (2.4 GHz logical channels)
#define MIN_CHANNEL 11 // 2405 MHz
#define MAX_CHANNEL 26 // 2480 MHz
#define CHANNEL_SPACING 5 // MHz
// FREG definitions (BSET/BCLR supported)
#define CC2520_FRMFILT0 0x000
#define CC2520_FRMFILT1 0x001
#define CC2520_SRCMATCH 0x002
#define CC2520_SRCSHORTEN0 0x004
#define CC2520_SRCSHORTEN1 0x005
#define CC2520_SRCSHORTEN2 0x006
#define CC2520_SRCEXTEN0 0x008
#define CC2520_SRCEXTEN1 0x009
#define CC2520_SRCEXTEN2 0x00A
#define CC2520_FRMCTRL0 0x00C
#define CC2520_FRMCTRL1 0x00D
#define CC2520_RXENABLE0 0x00E
#define CC2520_RXENABLE1 0x00F
#define CC2520_EXCFLAG0 0x010
#define CC2520_EXCFLAG1 0x011
#define CC2520_EXCFLAG2 0x012
#define CC2520_EXCMASKA0 0x014
#define CC2520_EXCMASKA1 0x015
#define CC2520_EXCMASKA2 0x016
#define CC2520_EXCMASKB0 0x018
#define CC2520_EXCMASKB1 0x019
#define CC2520_EXCMASKB2 0x01A
#define CC2520_EXCBINDX0 0x01C
#define CC2520_EXCBINDX1 0x01D
#define CC2520_EXCBINDY0 0x01E
#define CC2520_EXCBINDY1 0x01F
#define CC2520_GPIOCTRL0 0x020
#define CC2520_GPIOCTRL1 0x021
#define CC2520_GPIOCTRL2 0x022
#define CC2520_GPIOCTRL3 0x023
#define CC2520_GPIOCTRL4 0x024
#define CC2520_GPIOCTRL5 0x025
#define CC2520_GPIOPOLARITY 0x026
#define CC2520_GPIOCTRL 0x028
#define CC2520_DPUCON 0x02A
#define CC2520_DPUSTAT 0x02C
#define CC2520_FREQCTRL 0x02E
#define CC2520_FREQTUNE 0x02F
#define CC2520_TXPOWER 0x030
#define CC2520_TXCTRL 0x031
#define CC2520_FSMSTAT0 0x032
#define CC2520_FSMSTAT1 0x033
#define CC2520_FIFOPCTRL 0x034
#define CC2520_FSMCTRL 0x035
#define CC2520_CCACTRL0 0x036
#define CC2520_CCACTRL1 0x037
#define CC2520_RSSI 0x038
#define CC2520_RSSISTAT 0x039
#define CC2520_TXFIFO_BUF 0x03A
#define CC2520_RXFIRST 0x03C
#define CC2520_RXFIFOCNT 0x03E
#define CC2520_TXFIFOCNT 0x03F
// SREG definitions (BSET/BCLR unsupported)
#define CC2520_CHIPID 0x040
#define CC2520_VERSION 0x042
#define CC2520_EXTCLOCK 0x044
#define CC2520_MDMCTRL0 0x046
#define CC2520_MDMCTRL1 0x047
#define CC2520_FREQEST 0x048
#define CC2520_RXCTRL 0x04A
#define CC2520_FSCTRL 0x04C
#define CC2520_FSCAL0 0x04E
#define CC2520_FSCAL1 0x04F
#define CC2520_FSCAL2 0x050
#define CC2520_FSCAL3 0x051
#define CC2520_AGCCTRL0 0x052
#define CC2520_AGCCTRL1 0x053
#define CC2520_AGCCTRL2 0x054
#define CC2520_AGCCTRL3 0x055
#define CC2520_ADCTEST0 0x056
#define CC2520_ADCTEST1 0x057
#define CC2520_ADCTEST2 0x058
#define CC2520_MDMTEST0 0x05A
#define CC2520_MDMTEST1 0x05B
#define CC2520_DACTEST0 0x05C
#define CC2520_DACTEST1 0x05D
#define CC2520_ATEST 0x05E
#define CC2520_DACTEST2 0x05F
#define CC2520_PTEST0 0x060
#define CC2520_PTEST1 0x061
#define CC2520_RESERVED 0x062
#define CC2520_DPUBIST 0x07A
#define CC2520_ACTBIST 0x07C
#define CC2520_RAMBIST 0x07E
// Instruction implementation
#define CC2520_INS_SNOP 0x00
#define CC2520_INS_IBUFLD 0x02
#define CC2520_INS_SIBUFEX 0x03
#define CC2520_INS_SSAMPLECCA 0x04
#define CC2520_INS_SRES 0x0F
#define CC2520_INS_MEMRD 0x10
#define CC2520_INS_MEMWR 0x20
#define CC2520_INS_RXBUF 0x30
#define CC2520_INS_RXBUFCP 0x38
#define CC2520_INS_RXBUFMOV 0x32
#define CC2520_INS_TXBUF 0x3A
#define CC2520_INS_TXBUFCP 0x3E
#define CC2520_INS_RANDOM 0x3C
#define CC2520_INS_SXOSCON 0x40
#define CC2520_INS_STXCAL 0x41
#define CC2520_INS_SRXON 0x42
#define CC2520_INS_STXON 0x43
#define CC2520_INS_STXONCCA 0x44
#define CC2520_INS_SRFOFF 0x45
#define CC2520_INS_SXOSCOFF 0x46
#define CC2520_INS_SFLUSHRX 0x47
#define CC2520_INS_SFLUSHTX 0x48
#define CC2520_INS_SACK 0x49
#define CC2520_INS_SACKPEND 0x4A
#define CC2520_INS_SNACK 0x4B
#define CC2520_INS_SRXMASKBITSET 0x4C
#define CC2520_INS_SRXMASKBITCLR 0x4D
#define CC2520_INS_RXMASKAND 0x4E
#define CC2520_INS_RXMASKOR 0x4F
#define CC2520_INS_MEMCP 0x50
#define CC2520_INS_MEMCPR 0x52
#define CC2520_INS_MEMXCP 0x54
#define CC2520_INS_MEMXWR 0x56
#define CC2520_INS_BCLR 0x58
#define CC2520_INS_BSET 0x59
#define CC2520_INS_CTR 0x60
#define CC2520_INS_CBCMAC 0x64
#define CC2520_INS_UCBCMAC 0x66
#define CC2520_INS_CCM 0x68
#define CC2520_INS_UCCM 0x6A
#define CC2520_INS_ECB 0x70
#define CC2520_INS_ECBO 0x72
#define CC2520_INS_ECBX 0x74
#define CC2520_INS_ECBXO 0x76
#define CC2520_INS_INC 0x78
#define CC2520_INS_ABORT 0x7F
#define CC2520_INS_REGRD 0x80
#define CC2520_INS_REGWR 0xC0
#endif /* CC2520_CONST_H */