coding conventions for drivers

dev/timer
Oliver Hahm 10 years ago
parent 201f593641
commit e2130fbd47

@ -66,162 +66,195 @@ volatile static int cs_hwtimer_id = -1;
volatile static int cs_timeout_flag = 0;
/*---------------------------------------------------------------------------*/
static void cs_timeout_cb(void* ptr)
static void cs_timeout_cb(void *ptr)
{
cs_timeout_flag = 1;
cs_timeout_flag = 1;
}
/*---------------------------------------------------------------------------*/
int cc1100_send_csmaca(radio_address_t address, protocol_t protocol, int priority, char *payload, int payload_len)
{
uint16_t min_window_size;
uint16_t max_window_size;
uint16_t difs;
uint16_t slottime;
switch (priority)
{
case PRIORITY_ALARM:
min_window_size = PRIO_ALARM_MIN_WINDOW_SIZE;
max_window_size = PRIO_ALARM_MAX_WINDOW_SIZE;
difs = PRIO_ALARM_DIFS;
slottime = PRIO_ALARM_SLOTTIME;
break;
case PRIORITY_WARNING:
min_window_size = PRIO_WARN_MIN_WINDOW_SIZE;
max_window_size = PRIO_WARN_MAX_WINDOW_SIZE;
difs = PRIO_WARN_DIFS;
slottime = PRIO_WARN_SLOTTIME;
break;
default:
min_window_size = PRIO_DATA_MIN_WINDOW_SIZE;
max_window_size = PRIO_DATA_MAX_WINDOW_SIZE;
difs = PRIO_DATA_DIFS;
slottime = PRIO_DATA_SLOTTIME;
}
// Calculate collisions per second
if (collision_state == COLLISION_STATE_INITIAL) {
timex_t now;
vtimer_now(&now);
collision_measurement_start = now.microseconds;
collision_count = 0;
collisions_per_sec = 0;
collision_state = COLLISION_STATE_MEASURE;
} else if (collision_state == COLLISION_STATE_MEASURE) {
timex_t now;
vtimer_now(&now);
uint64_t timespan = now.microseconds - collision_measurement_start;
if (timespan > 1000000) {
collisions_per_sec = (collision_count * 1000000) / (double) timespan;
if (collisions_per_sec > 0.5 && collisions_per_sec <= 2.2) {
timex_t now;
vtimer_now(&now);
collision_measurement_start = now.microseconds;
collision_state = COLLISION_STATE_KEEP;
} else if (collisions_per_sec > 2.2) {
timex_t now;
vtimer_now(&now);
collision_measurement_start = now.microseconds;
collision_state = COLLISION_STATE_KEEP;
} else {
collision_state = COLLISION_STATE_INITIAL;
}
}
} else if (collision_state == COLLISION_STATE_KEEP) {
timex_t now;
vtimer_now(&now);
uint16_t min_window_size;
uint16_t max_window_size;
uint16_t difs;
uint16_t slottime;
switch(priority) {
case PRIORITY_ALARM:
min_window_size = PRIO_ALARM_MIN_WINDOW_SIZE;
max_window_size = PRIO_ALARM_MAX_WINDOW_SIZE;
difs = PRIO_ALARM_DIFS;
slottime = PRIO_ALARM_SLOTTIME;
break;
case PRIORITY_WARNING:
min_window_size = PRIO_WARN_MIN_WINDOW_SIZE;
max_window_size = PRIO_WARN_MAX_WINDOW_SIZE;
difs = PRIO_WARN_DIFS;
slottime = PRIO_WARN_SLOTTIME;
break;
default:
min_window_size = PRIO_DATA_MIN_WINDOW_SIZE;
max_window_size = PRIO_DATA_MAX_WINDOW_SIZE;
difs = PRIO_DATA_DIFS;
slottime = PRIO_DATA_SLOTTIME;
}
/* Calculate collisions per second */
if(collision_state == COLLISION_STATE_INITIAL) {
timex_t now;
vtimer_now(&now);
collision_measurement_start = now.microseconds;
collision_count = 0;
collisions_per_sec = 0;
collision_state = COLLISION_STATE_MEASURE;
}
else if(collision_state == COLLISION_STATE_MEASURE) {
timex_t now;
vtimer_now(&now);
uint64_t timespan = now.microseconds - collision_measurement_start;
if (timespan > 5000000) {
collision_state = COLLISION_STATE_INITIAL;
}
}
// Adjust initial window size according to collision rate
if (collisions_per_sec > 0.5 && collisions_per_sec <= 2.2) {
min_window_size *= 2;
} else if (collisions_per_sec > 2.2) {
min_window_size *= 4;
}
uint16_t windowSize = min_window_size; // Start with window size of PRIO_XXX_MIN_WINDOW_SIZE
uint16_t backoff = 0; // Backoff between 1 and windowSize
uint32_t total; // Holds the total wait time before send try
uint32_t cs_timeout; // Current carrier sense timeout value
if (protocol == 0)
{
return RADIO_INVALID_PARAM; // Not allowed, protocol id must be greater zero
}
cc1100_phy_mutex_lock(); // Lock radio for exclusive access
// Get carrier sense timeout based on overall error rate till now
send_csmaca_calls++;
int fail_percentage = (send_csmaca_calls_cs_timeout * 100) / send_csmaca_calls;
if (fail_percentage == 0) fail_percentage = 1;
cs_timeout = CARRIER_SENSE_TIMEOUT / fail_percentage;
if (cs_timeout < CARRIER_SENSE_TIMEOUT_MIN) cs_timeout = CARRIER_SENSE_TIMEOUT_MIN;
cc1100_cs_init(); // Initialize carrier sensing
window:
if (backoff != 0) goto cycle; // If backoff was 0
windowSize *= 2; // ...double the current window size
if (windowSize > max_window_size)
{
windowSize = max_window_size; // This is the maximum size allowed
}
backoff = rand() % windowSize; // ...and choose new backoff
if (backoff < 0) backoff *= -1;
backoff += (uint16_t) 1;
cycle:
cs_timeout_flag = 0; // Carrier sense timeout flag
cs_hwtimer_id = hwtimer_set(cs_timeout, // Set hwtimer to set CS timeout flag
cs_timeout_cb, NULL);
while (cc1100_cs_read()) // Wait until air is free
{
if (cs_timeout_flag)
{
send_csmaca_calls_cs_timeout++;
if(timespan > 1000000) {
collisions_per_sec = (collision_count * 1000000) / (double) timespan;
if(collisions_per_sec > 0.5 && collisions_per_sec <= 2.2) {
timex_t now;
vtimer_now(&now);
collision_measurement_start = now.microseconds;
collision_state = COLLISION_STATE_KEEP;
}
else if(collisions_per_sec > 2.2) {
timex_t now;
vtimer_now(&now);
collision_measurement_start = now.microseconds;
collision_state = COLLISION_STATE_KEEP;
}
else {
collision_state = COLLISION_STATE_INITIAL;
}
}
}
else if(collision_state == COLLISION_STATE_KEEP) {
timex_t now;
vtimer_now(&now);
uint64_t timespan = now.microseconds - collision_measurement_start;
if(timespan > 5000000) {
collision_state = COLLISION_STATE_INITIAL;
}
}
/* Adjust initial window size according to collision rate */
if(collisions_per_sec > 0.5 && collisions_per_sec <= 2.2) {
min_window_size *= 2;
}
else if(collisions_per_sec > 2.2) {
min_window_size *= 4;
}
uint16_t windowSize = min_window_size; /* Start with window size of PRIO_XXX_MIN_WINDOW_SIZE */
uint16_t backoff = 0; /* Backoff between 1 and windowSize */
uint32_t total; /* Holds the total wait time before send try */
uint32_t cs_timeout; /* Current carrier sense timeout value */
if(protocol == 0) {
return RADIO_INVALID_PARAM; /* Not allowed, protocol id must be greater zero */
}
cc1100_phy_mutex_lock(); /* Lock radio for exclusive access */
/* Get carrier sense timeout based on overall error rate till now */
send_csmaca_calls++;
int fail_percentage = (send_csmaca_calls_cs_timeout * 100) / send_csmaca_calls;
if(fail_percentage == 0) {
fail_percentage = 1;
}
cs_timeout = CARRIER_SENSE_TIMEOUT / fail_percentage;
if(cs_timeout < CARRIER_SENSE_TIMEOUT_MIN) {
cs_timeout = CARRIER_SENSE_TIMEOUT_MIN;
}
cc1100_cs_init(); /* Initialize carrier sensing */
window:
if(backoff != 0) {
goto cycle; /* If backoff was 0 */
}
windowSize *= 2; /* ...double the current window size */
if(windowSize > max_window_size) {
windowSize = max_window_size; /* This is the maximum size allowed */
}
backoff = rand() % windowSize; /* ...and choose new backoff */
if(backoff < 0) {
backoff *= -1;
}
backoff += (uint16_t) 1;
cycle:
cs_timeout_flag = 0; /* Carrier sense timeout flag */
cs_hwtimer_id = hwtimer_set(cs_timeout, /* Set hwtimer to set CS timeout flag */
cs_timeout_cb, NULL);
while(cc1100_cs_read()) { /* Wait until air is free */
if(cs_timeout_flag) {
send_csmaca_calls_cs_timeout++;
#ifndef CSMACA_MAC_AGGRESSIVE_MODE
cc1100_phy_mutex_unlock();
cc1100_go_after_tx(); // Go from RX to default mode
return RADIO_CS_TIMEOUT; // Return immediately
cc1100_phy_mutex_unlock();
cc1100_go_after_tx(); /* Go from RX to default mode */
return RADIO_CS_TIMEOUT; /* Return immediately */
#endif
#ifdef CSMACA_MAC_AGGRESSIVE_MODE
goto send; // Send anyway
goto send; /* Send anyway */
#endif
}
}
hwtimer_remove(cs_hwtimer_id); // Remove hwtimer
cc1100_cs_write_cca(1); // Air is free now
cc1100_cs_set_enabled(true);
if (cc1100_cs_read()) goto window; // GDO0 triggers on rising edge, so
// test once after interrupt is enabled
if (backoff > 0) backoff--; // Decrement backoff counter
total = slottime; // Calculate total wait time
total *= (uint32_t)backoff; // Slot vector set
total += difs; // ...and standard DIFS wait time
cs_timeout_flag = 0; // Carrier sense timeout flag
cs_hwtimer_id = hwtimer_set(total, // Set hwtimer to set CS timeout flag
cs_timeout_cb, NULL);
while (!cs_timeout_flag
|| !cc1100_cs_read_cca()) // Wait until timeout is finished
{
if (cc1100_cs_read_cca() == 0) // Is the air still free?
{
hwtimer_remove(cs_hwtimer_id);
goto window; // No. Go back to new wait period.
}
}
cc1100_cs_set_enabled(false);
}
}
hwtimer_remove(cs_hwtimer_id); /* Remove hwtimer */
cc1100_cs_write_cca(1); /* Air is free now */
cc1100_cs_set_enabled(true);
if(cc1100_cs_read()) {
goto window; /* GDO0 triggers on rising edge, so */
}
/* test once after interrupt is enabled */
if(backoff > 0) {
backoff--; /* Decrement backoff counter */
}
total = slottime; /* Calculate total wait time */
total *= (uint32_t)backoff; /* Slot vector set */
total += difs; /* ...and standard DIFS wait time */
cs_timeout_flag = 0; /* Carrier sense timeout flag */
cs_hwtimer_id = hwtimer_set(total, /* Set hwtimer to set CS timeout flag */
cs_timeout_cb, NULL);
while(!cs_timeout_flag
|| !cc1100_cs_read_cca()) { /* Wait until timeout is finished */
if(cc1100_cs_read_cca() == 0) { /* Is the air still free? */
hwtimer_remove(cs_hwtimer_id);
goto window; /* No. Go back to new wait period. */
}
}
cc1100_cs_set_enabled(false);
#ifdef CSMACA_MAC_AGGRESSIVE_MODE
send:
send:
#endif
int res = cc1100_send(address, protocol, priority, payload, payload_len);
if (res < 0) {
collision_count++;
}
return res;
int res = cc1100_send(address, protocol, priority, payload, payload_len);
if(res < 0) {
collision_count++;
}
return res;
}

@ -76,49 +76,49 @@ and the mailinglist (subscription via web site)
* 24 | 240 | 917.61
*/
// 400 kbps, MSK, X-tal: 26 MHz (Chip Revision F)
/* 400 kbps, MSK, X-tal: 26 MHz (Chip Revision F) */
char cc1100_conf[] = {
0x06, // IOCFG2
0x2E, // IOCFG1
0x0E, // IOCFG0
0x0F, // FIFOTHR
0x9B, // SYNC1
0xAD, // SYNC0
0x3D, // PKTLEN (maximum value of packet length byte = 61)
0x06, // PKTCTRL1
0x45, // PKTCTRL0 (variable packet length)
0xFF, // ADDR
CC1100_DEFAULT_CHANNR*10, // CHANNR
0x0B, // FSCTRL1
0x00, // FSCTRL0
0x21, // FREQ2
0x71, // FREQ1
0x7A, // FREQ0
0x2D, // MDMCFG4
0xF8, // MDMCFG3
0x73, // MDMCFG2
0x42, // MDMCFG1
0xF8, // MDMCFG0
0x00, // DEVIATN
0x07, // MCSM2
0x03, // MCSM1
0x18, // MCSM0
0x1D, // FOCCFG
0x1C, // BSCFG
0xC0, // AGCCTRL2
0x49, // AGCCTRL1, (old value was 0x49 -> made carrier sense less sensitive!)
// 0x47 - 7 dB above MAGN_TARGET setting
0xB2, // AGCCTRL0
0x87, // WOREVT1
0x6B, // WOREVT0
0xF8, // WORCTRL
0xB6, // FREND1
0x10, // FREND0
0xEA, // FSCAL3
0x2A, // FSCAL2
0x00, // FSCAL1
0x1F, // FSCAL0
0x00 // padding to 4 bytes
0x06, /* IOCFG2 */
0x2E, /* IOCFG1 */
0x0E, /* IOCFG0 */
0x0F, /* FIFOTHR */
0x9B, /* SYNC1 */
0xAD, /* SYNC0 */
0x3D, /* PKTLEN (maximum value of packet length byte = 61) */
0x06, /* PKTCTRL1 */
0x45, /* PKTCTRL0 (variable packet length) */
0xFF, /* ADDR */
CC1100_DEFAULT_CHANNR * 10, /* CHANNR */
0x0B, /* FSCTRL1 */
0x00, /* FSCTRL0 */
0x21, /* FREQ2 */
0x71, /* FREQ1 */
0x7A, /* FREQ0 */
0x2D, /* MDMCFG4 */
0xF8, /* MDMCFG3 */
0x73, /* MDMCFG2 */
0x42, /* MDMCFG1 */
0xF8, /* MDMCFG0 */
0x00, /* DEVIATN */
0x07, /* MCSM2 */
0x03, /* MCSM1 */
0x18, /* MCSM0 */
0x1D, /* FOCCFG */
0x1C, /* BSCFG */
0xC0, /* AGCCTRL2 */
0x49, /* AGCCTRL1, (old value was 0x49 -> made carrier sense less sensitive!)
* 0x47 - 7 dB above MAGN_TARGET setting */
0xB2, /* AGCCTRL0 */
0x87, /* WOREVT1 */
0x6B, /* WOREVT0 */
0xF8, /* WORCTRL */
0xB6, /* FREND1 */
0x10, /* FREND0 */
0xEA, /* FSCAL3 */
0x2A, /* FSCAL2 */
0x00, /* FSCAL1 */
0x1F, /* FSCAL0 */
0x00 /* padding to 4 bytes */
};
/** @} */

@ -66,7 +66,7 @@ and the mailinglist (subscription via web site)
// Define default radio mode to constant RX if no
// project specific setting is available.
#ifndef CC1100_RADIO_MODE
#define CC1100_RADIO_MODE CC1100_MODE_CONSTANT_RX
#define CC1100_RADIO_MODE CC1100_MODE_CONSTANT_RX
#endif
/// CC1100 radio interface

File diff suppressed because it is too large Load Diff

@ -70,107 +70,106 @@ and the mailinglist (subscription via web site)
/** CC1100 register configuration */
typedef struct cc1100_reg {
uint8_t IOCFG2;
uint8_t IOCFG1;
uint8_t IOCFG0;
uint8_t FIFOTHR;
uint8_t SYNC1;
uint8_t SYNC0;
uint8_t PKTLEN;
uint8_t PKTCTRL1;
uint8_t PKTCTRL0;
uint8_t ADDR;
uint8_t CHANNR;
uint8_t FSCTRL1;
uint8_t FSCTRL0;
uint8_t FREQ2;
uint8_t FREQ1;
uint8_t FREQ0;
uint8_t MDMCFG4;
uint8_t MDMCFG3;
uint8_t MDMCFG2;
uint8_t MDMCFG1;
uint8_t MDMCFG0;
uint8_t DEVIATN;
uint8_t MCSM2;
uint8_t MCSM1;
uint8_t MCSM0;
uint8_t FOCCFG;
uint8_t BSCFG;
uint8_t AGCCTRL2;
uint8_t AGCCTRL1;
uint8_t AGCCTRL0;
uint8_t WOREVT1;
uint8_t WOREVT0;
uint8_t WORCTRL;
uint8_t FREND1;
uint8_t FREND0;
uint8_t FSCAL3;
uint8_t FSCAL2;
uint8_t FSCAL1;
uint8_t FSCAL0;
uint8_t IOCFG2;
uint8_t IOCFG1;
uint8_t IOCFG0;
uint8_t FIFOTHR;
uint8_t SYNC1;
uint8_t SYNC0;
uint8_t PKTLEN;
uint8_t PKTCTRL1;
uint8_t PKTCTRL0;
uint8_t ADDR;
uint8_t CHANNR;
uint8_t FSCTRL1;
uint8_t FSCTRL0;
uint8_t FREQ2;
uint8_t FREQ1;
uint8_t FREQ0;
uint8_t MDMCFG4;
uint8_t MDMCFG3;
uint8_t MDMCFG2;
uint8_t MDMCFG1;
uint8_t MDMCFG0;
uint8_t DEVIATN;
uint8_t MCSM2;
uint8_t MCSM1;
uint8_t MCSM0;
uint8_t FOCCFG;
uint8_t BSCFG;
uint8_t AGCCTRL2;
uint8_t AGCCTRL1;
uint8_t AGCCTRL0;
uint8_t WOREVT1;
uint8_t WOREVT0;
uint8_t WORCTRL;
uint8_t FREND1;
uint8_t FREND0;
uint8_t FSCAL3;
uint8_t FSCAL2;
uint8_t FSCAL1;
uint8_t FSCAL0;
} cc1100_reg_t;
/** CC1100 radio configuration */
typedef struct cc1100_cfg_t {
cc1100_reg_t reg_cfg; ///< CC1100 register configuration
uint8_t pa_power; ///< Output power setting
cc1100_reg_t reg_cfg; ///< CC1100 register configuration
uint8_t pa_power; ///< Output power setting
} cc1100_cfg_t;
/**
* @brief Radio Control Flags
*/
typedef struct cc1100_flags
{
uint32_t TOF; ///< Time of flight of the last packet and last ACK
uint32_t TCP; ///< Time to compute packet
unsigned RPS : 16; ///< Raw packets sent to transmit last packet
unsigned RETC : 8; ///< Retransmission count of last send packet
unsigned RSSI : 8; ///< The RSSI value of last received packet
unsigned RSSI_SEND : 8; ///< The RSSI value of the last send unicast packet of this node
unsigned LQI : 8; ///< The LQI value of the last received packet
unsigned LL_ACK : 1; ///< Is set if Link-Level ACK is received, otherwise 0 (reset on new burst)
unsigned CAA : 1; ///< The status of the air (1 = air free, 0 = air not free)
unsigned CRC_STATE : 1; ///< The CRC status of last received packet (1 = OK, 0 = not OK)
unsigned SEQ : 1; ///< Sequence number (toggles between 0 and 1)
unsigned MAN_WOR : 1; ///< Manual WOR set (for randomized WOR times => no synch)
unsigned KT_RES_ERR : 1; ///< A hwtimer resource error has occurred (no free timers available)
unsigned TX : 1; ///< State machine TX lock, only ACKs will be received
unsigned WOR_RST : 1; ///< Reset CC1100 real time clock (WOR) on next WOR strobe
typedef struct cc1100_flags {
uint32_t TOF; ///< Time of flight of the last packet and last ACK
uint32_t TCP; ///< Time to compute packet
unsigned RPS : 16; ///< Raw packets sent to transmit last packet
unsigned RETC : 8; ///< Retransmission count of last send packet
unsigned RSSI : 8; ///< The RSSI value of last received packet
unsigned RSSI_SEND : 8; ///< The RSSI value of the last send unicast packet of this node
unsigned LQI : 8; ///< The LQI value of the last received packet
unsigned LL_ACK : 1; ///< Is set if Link-Level ACK is received, otherwise 0 (reset on new burst)
unsigned CAA : 1; ///< The status of the air (1 = air free, 0 = air not free)
unsigned CRC_STATE : 1; ///< The CRC status of last received packet (1 = OK, 0 = not OK)
unsigned SEQ : 1; ///< Sequence number (toggles between 0 and 1)
unsigned MAN_WOR : 1; ///< Manual WOR set (for randomized WOR times => no synch)
unsigned KT_RES_ERR : 1; ///< A hwtimer resource error has occurred (no free timers available)
unsigned TX : 1; ///< State machine TX lock, only ACKs will be received
unsigned WOR_RST : 1; ///< Reset CC1100 real time clock (WOR) on next WOR strobe
} cc1100_flags;
/**
* @brief Statistic interface for debugging
*/
typedef struct cc1100_statistic {
uint32_t packets_in;
uint32_t packets_in_crc_fail;
uint32_t packets_in_while_tx;
uint32_t packets_in_dups;
uint32_t packets_in_up;
uint32_t packets_out;
uint32_t packets_out_acked;
uint32_t packets_out_broadcast;
uint32_t raw_packets_out;
uint32_t raw_packets_out_acked;
uint32_t acks_send;
uint32_t rx_buffer_max;
uint32_t watch_dog_resets;
uint32_t packets_in;
uint32_t packets_in_crc_fail;
uint32_t packets_in_while_tx;
uint32_t packets_in_dups;
uint32_t packets_in_up;
uint32_t packets_out;
uint32_t packets_out_acked;
uint32_t packets_out_broadcast;
uint32_t raw_packets_out;
uint32_t raw_packets_out_acked;
uint32_t acks_send;
uint32_t rx_buffer_max;
uint32_t watch_dog_resets;
} cc1100_statistic_t;
enum radio_mode {
RADIO_MODE_GET = -1, ///< leave mode unchanged
RADIO_MODE_OFF = 0, ///< turn radio off
RADIO_MODE_ON = 1 ///< turn radio on
RADIO_MODE_GET = -1, ///< leave mode unchanged
RADIO_MODE_OFF = 0, ///< turn radio off
RADIO_MODE_ON = 1 ///< turn radio on
};
enum radio_result {
RADIO_PAYLOAD_TOO_LONG = -1, ///< payload too long
RADIO_WRONG_MODE = -2, ///< operation not supported in current mode
RADIO_ADDR_OUT_OF_RANGE = -3, ///< address out of range
RADIO_OP_FAILED = -4, ///< operation failed
RADIO_CS_TIMEOUT = -5, ///< Carrier Sense timeout: air was never free
RADIO_INVALID_PARAM = -6 ///< Invalid parameters passed to radio
RADIO_PAYLOAD_TOO_LONG = -1, ///< payload too long
RADIO_WRONG_MODE = -2, ///< operation not supported in current mode
RADIO_ADDR_OUT_OF_RANGE = -3, ///< address out of range
RADIO_OP_FAILED = -4, ///< operation failed
RADIO_CS_TIMEOUT = -5, ///< Carrier Sense timeout: air was never free
RADIO_INVALID_PARAM = -6 ///< Invalid parameters passed to radio
};
/* ------------------------------------------------------------------------- */
@ -207,7 +206,7 @@ void cc1100_set_idle(void);
*
* @return Textual representation of radio mode.
*/
char* cc1100_mode_to_text(uint8_t mode);
char *cc1100_mode_to_text(uint8_t mode);
/**
* @brief Convert radio state to textual representation.
@ -216,21 +215,21 @@ char* cc1100_mode_to_text(uint8_t mode);
*
* @return Textual representation of radio state.
*/
char* cc1100_state_to_text(uint8_t state);
char *cc1100_state_to_text(uint8_t state);
/**
* @brief Convert current output power to textual representation.
*
* @return Textual representation of current output power in dBm.
*/
char* cc1100_get_output_power(char* buf);
char *cc1100_get_output_power(char *buf);
/**
* @brief Read out main radio control FSM state.
*
* @return Textual representation of current main radio control FSM state.
*/
char* cc1100_get_marc_state(void);
char *cc1100_get_marc_state(void);
/**
* @brief hwtimer wrapper function.

File diff suppressed because it is too large Load Diff

@ -75,23 +75,21 @@ Notes:
\li Identification is increased is used to scan duplicates. It must be increased
for each new packet and kept for packet retransmissions.
*/
typedef struct __attribute__ ((packed)) cc1100_packet_layer0_t
{
uint8_t length; ///< Length of the packet (without length byte)
uint8_t address; ///< Destination address
uint8_t phy_src; ///< Source address (physical source)
uint8_t flags; ///< Flags
uint8_t data[MAX_DATA_LENGTH]; ///< Data (high layer protocol)
typedef struct __attribute__((packed)) cc1100_packet_layer0_t {
uint8_t length; ///< Length of the packet (without length byte)
uint8_t address; ///< Destination address
uint8_t phy_src; ///< Source address (physical source)
uint8_t flags; ///< Flags
uint8_t data[MAX_DATA_LENGTH]; ///< Data (high layer protocol)
} cc1100_packet_layer0_t;
typedef struct cc1100_wor_config_t
{
uint16_t rx_interval; ///< RX polling interval in milliseconds
float rx_time_ms; ///< WOR_RX_TIME in milliseconds
uint8_t rx_time_reg; ///< WOR_RX_TIME (CC1100 "MCSM2.RX_TIME" register value)
uint8_t wor_evt_0; ///< CC1100 WOREVT0 register value
uint8_t wor_evt_1; ///< CC1100 WOREVT1 register value
uint8_t wor_ctrl; ///< CC1100 WORCTRL register value
typedef struct cc1100_wor_config_t {
uint16_t rx_interval; ///< RX polling interval in milliseconds
float rx_time_ms; ///< WOR_RX_TIME in milliseconds
uint8_t rx_time_reg; ///< WOR_RX_TIME (CC1100 "MCSM2.RX_TIME" register value)
uint8_t wor_evt_0; ///< CC1100 WOREVT0 register value
uint8_t wor_evt_1; ///< CC1100 WOREVT1 register value
uint8_t wor_ctrl; ///< CC1100 WORCTRL register value
} cc1100_wor_config_t;
/*---------------------------------------------------------------------------*/

@ -59,78 +59,82 @@ and the mailinglist (subscription via web site)
uint8_t
cc1100_spi_writeburst_reg(uint8_t addr, char *src, uint8_t count)
{
int i = 0;
unsigned int cpsr = disableIRQ();
cc110x_spi_select();
cc110x_txrx(addr | CC1100_WRITE_BURST);
while (i < count) {
cc110x_txrx(src[i]);
i++;
}
cc110x_spi_unselect();
restoreIRQ(cpsr);
return count;
int i = 0;
unsigned int cpsr = disableIRQ();
cc110x_spi_select();
cc110x_txrx(addr | CC1100_WRITE_BURST);
while(i < count) {
cc110x_txrx(src[i]);
i++;
}
cc110x_spi_unselect();
restoreIRQ(cpsr);
return count;
}
void
cc1100_spi_readburst_reg(uint8_t addr, char *buffer, uint8_t count)
{
int i = 0;
unsigned int cpsr = disableIRQ();
cc110x_spi_select();
cc110x_txrx(addr | CC1100_READ_BURST);
while (i < count) {
buffer[i] = cc110x_txrx(NOBYTE);
i++;
}
cc110x_spi_unselect();
restoreIRQ(cpsr);
int i = 0;
unsigned int cpsr = disableIRQ();
cc110x_spi_select();
cc110x_txrx(addr | CC1100_READ_BURST);
while(i < count) {
buffer[i] = cc110x_txrx(NOBYTE);
i++;
}
cc110x_spi_unselect();
restoreIRQ(cpsr);
}
void
cc1100_spi_write_reg(uint8_t addr, uint8_t value)
{
unsigned int cpsr = disableIRQ();
cc110x_spi_select();
cc110x_txrx(addr);
cc110x_txrx(value);
cc110x_spi_unselect();
restoreIRQ(cpsr);
unsigned int cpsr = disableIRQ();
cc110x_spi_select();
cc110x_txrx(addr);
cc110x_txrx(value);
cc110x_spi_unselect();
restoreIRQ(cpsr);
}
uint8_t cc1100_spi_read_reg(uint8_t addr)
{
uint8_t result;
unsigned int cpsr = disableIRQ();
cc110x_spi_select();
cc110x_txrx(addr | CC1100_READ_SINGLE);
result = cc110x_txrx(NOBYTE);
cc110x_spi_unselect();
restoreIRQ(cpsr);
return result;
uint8_t result;
unsigned int cpsr = disableIRQ();
cc110x_spi_select();
cc110x_txrx(addr | CC1100_READ_SINGLE);
result = cc110x_txrx(NOBYTE);
cc110x_spi_unselect();
restoreIRQ(cpsr);
return result;
}
uint8_t cc1100_spi_read_status(uint8_t addr)
{
uint8_t result;
unsigned int cpsr = disableIRQ();
cc110x_spi_select();
cc110x_txrx(addr | CC1100_READ_BURST);
result = cc110x_txrx(NOBYTE);
cc110x_spi_unselect();
restoreIRQ(cpsr);
return result;
uint8_t result;
unsigned int cpsr = disableIRQ();
cc110x_spi_select();
cc110x_txrx(addr | CC1100_READ_BURST);
result = cc110x_txrx(NOBYTE);
cc110x_spi_unselect();
restoreIRQ(cpsr);
return result;
}
uint8_t cc1100_spi_strobe(uint8_t c)
{
uint8_t result;
unsigned int cpsr = disableIRQ();
cc110x_spi_select();
result = cc110x_txrx(c);
cc110x_spi_unselect();
restoreIRQ(cpsr);
return result;
uint8_t result;
unsigned int cpsr = disableIRQ();
cc110x_spi_select();
result = cc110x_txrx(c);
cc110x_spi_unselect();
restoreIRQ(cpsr);
return result;
}
/** @} */

@ -1,28 +1,12 @@
/******************************************************************************
Copyright 2008, Freie Universitaet Berlin (FUB). All rights reserved.
These sources were developed at the Freie Universitaet Berlin, Computer Systems
and Telematics group (http://cst.mi.fu-berlin.de).
-------------------------------------------------------------------------------
This file is part of RIOT.
This program is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
RIOT is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program. If not, see http://www.gnu.org/licenses/ .
--------------------------------------------------------------------------------
For further information and questions please use the web site
http://scatterweb.mi.fu-berlin.de
and the mailinglist (subscription via web site)
scatterweb@lists.spline.inf.fu-berlin.de
*******************************************************************************/
/**
* Default configuration for the cc110x chip
*
* Copyright (C) 2013 INRIA
*
* This file subject to the terms and conditions of the GNU Lesser General
* Public License. See the file LICENSE in the top level directory for more
* details.
*/
/**
* @ingroup dev_cc110x
@ -34,9 +18,10 @@ and the mailinglist (subscription via web site)
* @brief TI Chipcon CC110x default settings
*
* @author Freie Universität Berlin, Computer Systems & Telematics
* @author INRIA
* @author Thomas Hillebrandt <hillebra@inf.fu-berlin.de>
* @author Heiko Will <hwill@inf.fu-berlin.de>
* @version $Revision: 2058 $
* @author Oliver Hahm <oliver.hahm@inria.fr>
*
* @note $Id: cc110x-defaultSettings.c 2058 2010-03-31 08:59:31Z hillebra $
*/
@ -78,63 +63,63 @@ and the mailinglist (subscription via web site)
// 400 kbps, MSK, X-tal: 26 MHz (Chip Revision F)
char cc110x_conf[] = {
0x06, // IOCFG2
0x2E, // IOCFG1
0x0E, // IOCFG0
0x0F, // FIFOTHR
0x9B, // SYNC1
0xAD, // SYNC0
0x3D, // PKTLEN (maximum value of packet length byte = 61)
0x06, // PKTCTRL1
0x45, // PKTCTRL0 (variable packet length)
0xFF, // ADDR
CC1100_DEFAULT_CHANNR*10, // CHANNR
0x0B, // FSCTRL1
0x00, // FSCTRL0
0x21, // FREQ2
0x71, // FREQ1
0x7A, // FREQ0
0x2D, // MDMCFG4
0xF8, // MDMCFG3
0x73, // MDMCFG2
0x42, // MDMCFG1
0xF8, // MDMCFG0
0x00, // DEVIATN
0x07, // MCSM2
0x03, // MCSM1
0x18, // MCSM0
0x1D, // FOCCFG
0x1C, // BSCFG
0xC0, // AGCCTRL2
0x49, // AGCCTRL1, (old value was 0x49 -> made carrier sense less sensitive!)
// 0x47 - 7 dB above MAGN_TARGET setting
0xB2, // AGCCTRL0
0x87, // WOREVT1
0x6B, // WOREVT0
0xF8, // WORCTRL
0xB6, // FREND1
0x10, // FREND0
0xEA, // FSCAL3
0x2A, // FSCAL2
0x00, // FSCAL1
0x1F, // FSCAL0
0x00 // padding to 4 bytes
0x06, // IOCFG2
0x2E, // IOCFG1
0x0E, // IOCFG0
0x0F, // FIFOTHR
0x9B, // SYNC1
0xAD, // SYNC0
0x3D, // PKTLEN (maximum value of packet length byte = 61)
0x06, // PKTCTRL1
0x45, // PKTCTRL0 (variable packet length)
0xFF, // ADDR
CC1100_DEFAULT_CHANNR * 10, // CHANNR
0x0B, // FSCTRL1
0x00, // FSCTRL0
0x21, // FREQ2
0x71, // FREQ1
0x7A, // FREQ0
0x2D, // MDMCFG4
0xF8, // MDMCFG3
0x73, // MDMCFG2
0x42, // MDMCFG1
0xF8, // MDMCFG0
0x00, // DEVIATN
0x07, // MCSM2
0x03, // MCSM1
0x18, // MCSM0
0x1D, // FOCCFG
0x1C, // BSCFG
0xC0, // AGCCTRL2
0x49, // AGCCTRL1, (old value was 0x49 -> made carrier sense less sensitive!)
// 0x47 - 7 dB above MAGN_TARGET setting
0xB2, // AGCCTRL0
0x87, // WOREVT1
0x6B, // WOREVT0
0xF8, // WORCTRL
0xB6, // FREND1
0x10, // FREND0
0xEA, // FSCAL3
0x2A, // FSCAL2
0x00, // FSCAL1
0x1F, // FSCAL0
0x00 // padding to 4 bytes
};
uint8_t pa_table_index = PATABLE; ///< Current PATABLE Index
uint8_t pa_table[] = { ///< PATABLE with available output powers
0x00, ///< -52 dBm
0x03, ///< -30 dBm
0x0D, ///< -20 dBm
0x1C, ///< -15 dBm
0x34, ///< -10 dBm
0x57, ///< - 5 dBm
0x3F, ///< - 1 dBm
0x8E, ///< 0 dBm
0x85, ///< + 5 dBm
0xCC, ///< + 7 dBm
0xC6, ///< + 9 dBm
0xC3 ///< +10 dBm
0x00, ///< -52 dBm
0x03, ///< -30 dBm
0x0D, ///< -20 dBm
0x1C, ///< -15 dBm
0x34, ///< -10 dBm
0x57, ///< - 5 dBm
0x3F, ///< - 1 dBm
0x8E, ///< 0 dBm
0x85, ///< + 5 dBm
0xCC, ///< + 7 dBm
0xC6, ///< + 9 dBm
0xC3 ///< +10 dBm
}; // If PATABLE is changed in size, adjust MAX_OUTPUT_POWER definition in CC1100 interface!

@ -1,3 +1,20 @@
/**
* Functions for packet reception on cc110x
*
* Copyright (C) 2009 Freie Universität Berlin
* Copyright (C) 2013 INRIA
*
* This file subject to the terms and conditions of the GNU Lesser General
* Public License. See the file LICENSE in the top level directory for more
* details.
*
* @ingroup dev_cc110x_ng
* @{
* @file
* @author Oliver Hahm <oliver.hahm@inria.fr>
* @}
*/
#include <cc110x_ng.h>
#include <cc110x-internal.h>
#include <cc110x-config.h>
@ -27,174 +44,186 @@ static uint8_t receive_packet(uint8_t *rxBuffer, uint8_t length);
rx_buffer_t cc110x_rx_buffer[RX_BUF_SIZE]; ///< RX buffer
volatile uint8_t rx_buffer_next; ///< Next packet in RX queue
void cc110x_rx_handler(void) {
void cc110x_rx_handler(void)
{
uint8_t res = 0;
// Possible packet received, RX -> IDLE (0.1 us)
rflags.CAA = 0;
rflags.MAN_WOR = 0;
cc110x_statistic.packets_in++;
res = receive_packet((uint8_t*)&(cc110x_rx_buffer[rx_buffer_next].packet), sizeof(cc110x_packet_t));
if (res) {
// If we are sending a burst, don't accept packets.
// Only ACKs are processed (for stopping the burst).
// Same if state machine is in TX lock.
if (radio_state == RADIO_SEND_BURST || rflags.TX)
{
cc110x_statistic.packets_in_while_tx++;
return;
}
/* Possible packet received, RX -> IDLE (0.1 us) */
rflags.CAA = 0;
rflags.MAN_WOR = 0;
cc110x_statistic.packets_in++;
res = receive_packet((uint8_t *)&(cc110x_rx_buffer[rx_buffer_next].packet), sizeof(cc110x_packet_t));
if(res) {
/* If we are sending a burst, don't accept packets.
* Only ACKs are processed (for stopping the burst).
* Same if state machine is in TX lock. */
if(radio_state == RADIO_SEND_BURST || rflags.TX) {
cc110x_statistic.packets_in_while_tx++;
return;
}
cc110x_rx_buffer[rx_buffer_next].rssi = rflags._RSSI;
cc110x_rx_buffer[rx_buffer_next].lqi = rflags._LQI;
cc110x_strobe(CC1100_SFRX); // ...for flushing the RX FIFO
cc110x_strobe(CC1100_SFRX); /* ...for flushing the RX FIFO */
// Valid packet. After a wake-up, the radio should be in IDLE.
// So put CC1100 to RX for WOR_TIMEOUT (have to manually put
// the radio back to sleep/WOR).
//cc110x_spi_write_reg(CC1100_MCSM0, 0x08); // Turn off FS-Autocal
cc110x_write_reg(CC1100_MCSM2, 0x07); // Configure RX_TIME (until end of packet)
/* Valid packet. After a wake-up, the radio should be in IDLE.
* So put CC1100 to RX for WOR_TIMEOUT (have to manually put
* the radio back to sleep/WOR). */
//cc110x_spi_write_reg(CC1100_MCSM0, 0x08); /* Turn off FS-Autocal */
cc110x_write_reg(CC1100_MCSM2, 0x07); /* Configure RX_TIME (until end of packet) */
cc110x_strobe(CC1100_SRX);
hwtimer_wait(IDLE_TO_RX_TIME);
radio_state = RADIO_RX;
#ifdef DBG_IGNORE
if (is_ignored(cc110x_rx_buffer[rx_buffer_next].packet.phy_src)) {
if(is_ignored(cc110x_rx_buffer[rx_buffer_next].packet.phy_src)) {
LED_RED_TOGGLE;
return;
}
#endif
/* notify transceiver thread if any */
if (transceiver_pid) {
msg_t m;
if(transceiver_pid) {
msg_t m;
m.type = (uint16_t) RCV_PKT_CC1100;
m.content.value = rx_buffer_next;
msg_send_int(&m, transceiver_pid);
}
/* shift to next buffer element */
if (++rx_buffer_next == RX_BUF_SIZE) {
if(++rx_buffer_next == RX_BUF_SIZE) {
rx_buffer_next = 0;
}
return;
}
else
{
// No ACK received so TOF is unpredictable
rflags.TOF = 0;
// CRC false or RX buffer full -> clear RX FIFO in both cases
cc110x_strobe(CC1100_SIDLE); // Switch to IDLE (should already be)...
cc110x_strobe(CC1100_SFRX); // ...for flushing the RX FIFO
// If packet interrupted this nodes send call,
// don't change anything after this point.
if (radio_state == RADIO_AIR_FREE_WAITING)
{
cc110x_strobe(CC1100_SRX);
hwtimer_wait(IDLE_TO_RX_TIME);
return;
}
// If currently sending, exit here (don't go to RX/WOR)
if (radio_state == RADIO_SEND_BURST)
{
cc110x_statistic.packets_in_while_tx++;
return;
}
// No valid packet, so go back to RX/WOR as soon as possible
cc110x_switch_to_rx();
}
else {
/* No ACK received so TOF is unpredictable */
rflags.TOF = 0;
/* CRC false or RX buffer full -> clear RX FIFO in both cases */
cc110x_strobe(CC1100_SIDLE); /* Switch to IDLE (should already be)... */
cc110x_strobe(CC1100_SFRX); /* ...for flushing the RX FIFO */
/* If packet interrupted this nodes send call,
* don't change anything after this point. */
if(radio_state == RADIO_AIR_FREE_WAITING) {
cc110x_strobe(CC1100_SRX);
hwtimer_wait(IDLE_TO_RX_TIME);
return;
}
/* If currently sending, exit here (don't go to RX/WOR) */
if(radio_state == RADIO_SEND_BURST) {
cc110x_statistic.packets_in_while_tx++;
return;
}
/* No valid packet, so go back to RX/WOR as soon as possible */
cc110x_switch_to_rx();
}
}
static uint8_t receive_packet_variable(uint8_t *rxBuffer, uint8_t length) {
uint8_t status[2];
uint8_t packetLength = 0;
static uint8_t receive_packet_variable(uint8_t *rxBuffer, uint8_t length)
{
uint8_t status[2];
uint8_t packetLength = 0;
/* Any bytes available in RX FIFO? */
if((cc110x_read_status(CC1100_RXBYTES) & BYTES_IN_RXFIFO)) {
/* Read length byte (first byte in RX FIFO) */
cc110x_read_fifo((char *) &packetLength, 1);
/* Any bytes available in RX FIFO? */
if ((cc110x_read_status(CC1100_RXBYTES) & BYTES_IN_RXFIFO)) {
// Read length byte (first byte in RX FIFO)
cc110x_read_fifo((char*) &packetLength, 1);
// Read data from RX FIFO and store in rxBuffer
if (packetLength <= length)
{
// Put length byte at first position in RX Buffer
rxBuffer[0] = packetLength;
/* Read data from RX FIFO and store in rxBuffer */
if(packetLength <= length) {
/* Put length byte at first position in RX Buffer */
rxBuffer[0] = packetLength;
// Read the rest of the packet
//cc110x_readburst_reg(CC1100_RXFIFO, (char*)rxBuffer+1, packetLength);
cc110x_read_fifo((char*) rxBuffer + 1, packetLength);
/* Read the rest of the packet */
//cc110x_readburst_reg(CC1100_RXFIFO, (char*)rxBuffer+1, packetLength);
cc110x_read_fifo((char *) rxBuffer + 1, packetLength);
// Read the 2 appended status bytes (status[0] = RSSI, status[1] = LQI)
cc110x_readburst_reg(CC1100_RXFIFO, (char*)status, 2);
/* Read the 2 appended status bytes (status[0] = RSSI, status[1] = LQI) */
cc110x_readburst_reg(CC1100_RXFIFO, (char *)status, 2);
// Store RSSI value of packet
rflags._RSSI = status[I_RSSI];
/* Store RSSI value of packet */
rflags._RSSI = status[I_RSSI];
// MSB of LQI is the CRC_OK bit
rflags.CRC_STATE = (status[I_LQI] & CRC_OK) >> 7;
if (!rflags.CRC_STATE) {
/* MSB of LQI is the CRC_OK bit */
rflags.CRC_STATE = (status[I_LQI] & CRC_OK) >> 7;
if(!rflags.CRC_STATE) {
cc110x_statistic.packets_in_crc_fail++;
}
// Bit 0-6 of LQI indicates the link quality (LQI)
rflags._LQI = status[I_LQI] & LQI_EST;
/* Bit 0-6 of LQI indicates the link quality (LQI) */
rflags._LQI = status[I_LQI] & LQI_EST;
return rflags.CRC_STATE;
return rflags.CRC_STATE;
}
/* too many bytes in FIFO */
else {
// RX FIFO get automatically flushed if return value is false
else {
/* RX FIFO get automatically flushed if return value is false */
return 0;
}
}
}
/* no bytes in RX FIFO */
else {
// RX FIFO get automatically flushed if return value is false
return 0;
}
else {
/* RX FIFO get automatically flushed if return value is false */
return 0;
}
}
static uint8_t receive_packet(uint8_t *rxBuffer, uint8_t length) {
uint8_t pkt_len_cfg = cc110x_read_reg(CC1100_PKTCTRL0) & PKT_LENGTH_CONFIG;
if (pkt_len_cfg == VARIABLE_PKTLEN)
{
return receive_packet_variable(rxBuffer, length);
}
// Fixed packet length not supported.
// RX FIFO get automatically flushed if return value is false
return 0;
static uint8_t receive_packet(uint8_t *rxBuffer, uint8_t length)
{
uint8_t pkt_len_cfg = cc110x_read_reg(CC1100_PKTCTRL0) & PKT_LENGTH_CONFIG;
if(pkt_len_cfg == VARIABLE_PKTLEN) {
return receive_packet_variable(rxBuffer, length);
}
/* Fixed packet length not supported. */
/* RX FIFO get automatically flushed if return value is false */
return 0;
}
#ifdef DBG_IGNORE
void cc110x_init_ignore(void) {
memset(ignored_addr, 0, IGN_MAX*sizeof(radio_address_t));
void cc110x_init_ignore(void)
{
memset(ignored_addr, 0, IGN_MAX * sizeof(radio_address_t));
}
uint8_t cc110x_add_ignored(radio_address_t addr) {
uint8_t i = 0;
while ((i < IGN_MAX) && ignored_addr[i++]) {
printf("i: %hu\n", i);
}
if (i > IGN_MAX) {
return 0;
}
ignored_addr[i-1] = addr;
return 1;
uint8_t cc110x_add_ignored(radio_address_t addr)
{
uint8_t i = 0;
while((i < IGN_MAX) && ignored_addr[i++]) {
printf("i: %hu\n", i);
}
if(i > IGN_MAX) {
return 0;
}
ignored_addr[i - 1] = addr;
return 1;
}
static uint8_t is_ignored(radio_address_t addr) {
static uint8_t is_ignored(radio_address_t addr)
{
uint8_t i;
for (i = 0; i < IGN_MAX; i++) {
if (ignored_addr[i] == addr) {
for(i = 0; i < IGN_MAX; i++) {
if(ignored_addr[i] == addr) {
return 1;
}
}
return 0;
}
#endif

@ -1,3 +1,20 @@
/**
* Functions for packet transmission on cc110x
*
* Copyright (C) 2009 Freie Universität Berlin
* Copyright (C) 2013 INRIA
*
* This file subject to the terms and conditions of the GNU Lesser General
* Public License. See the file LICENSE in the top level directory for more
* details.
*
* @ingroup dev_cc110x_ng
* @{
* @file
* @author Oliver Hahm <oliver.hahm@inria.fr>
* @}
*/
#include <stdio.h>
#include <cc110x_ng.h>
@ -11,12 +28,13 @@
#include <board.h>
uint8_t cc110x_send(cc110x_packet_t *packet) {
volatile uint32_t abort_count;
uint8_t cc110x_send(cc110x_packet_t *packet)
{
volatile uint32_t abort_count;
uint8_t size;
/* TODO: burst sending */
radio_state = RADIO_SEND_BURST;
rflags.LL_ACK = 0;
radio_state = RADIO_SEND_BURST;
rflags.LL_ACK = 0;
/*
* Number of bytes to send is:
@ -25,54 +43,58 @@ uint8_t cc110x_send(cc110x_packet_t *packet) {
*/
size = packet->length + 1;
// The number of bytes to be transmitted must be smaller
// or equal to PACKET_LENGTH (62 bytes). So the receiver
// can put the whole packet in its RX-FIFO (with appended
// packet status bytes).
if (size > PACKET_LENGTH) {
/* The number of bytes to be transmitted must be smaller
* or equal to PACKET_LENGTH (62 bytes). So the receiver
* can put the whole packet in its RX-FIFO (with appended
* packet status bytes).*/
if(size > PACKET_LENGTH) {
return 0;
}
packet->phy_src = cc110x_get_address();
// Disables RX interrupt etc.
cc110x_before_send();
/* Disables RX interrupt etc. */
cc110x_before_send();
// But CC1100 in IDLE mode to flush the FIFO
/* But CC1100 in IDLE mode to flush the FIFO */
cc110x_strobe(CC1100_SIDLE);
// Flush TX FIFO to be sure it is empty
/* Flush TX FIFO to be sure it is empty */
cc110x_strobe(CC1100_SFTX);
// Write packet into TX FIFO
cc110x_writeburst_reg(CC1100_TXFIFO, (char*) packet, size);
// Switch to TX mode
/* Write packet into TX FIFO */
cc110x_writeburst_reg(CC1100_TXFIFO, (char *) packet, size);
/* Switch to TX mode */
abort_count = 0;
unsigned int cpsr = disableIRQ();
cc110x_strobe(CC1100_STX);
// Wait for GDO2 to be set -> sync word transmitted
while (cc110x_get_gdo2() == 0) {
abort_count++;
if (abort_count > CC1100_SYNC_WORD_TX_TIME) {
// Abort waiting. CC1100 maybe in wrong mode
// e.g. sending preambles for always
puts("[CC1100 TX] fatal error\n");
break;
}
/* Wait for GDO2 to be set -> sync word transmitted */
while(cc110x_get_gdo2() == 0) {
abort_count++;
if(abort_count > CC1100_SYNC_WORD_TX_TIME) {
/* Abort waiting. CC1100 maybe in wrong mode */
/* e.g. sending preambles for always */
puts("[CC1100 TX] fatal error\n");
break;
}
}
restoreIRQ(cpsr);
// Wait for GDO2 to be cleared -> end of packet
while (cc110x_get_gdo2() != 0);
//LED_GREEN_TOGGLE;
// Experimental - TOF Measurement
/* Wait for GDO2 to be cleared -> end of packet */
while(cc110x_get_gdo2() != 0);
/* Experimental - TOF Measurement */
cc110x_after_send();
cc110x_statistic.raw_packets_out++;
// Store number of transmission retries
rflags.TX = 0;
/* Store number of transmission retries */
rflags.TX = 0;
// Go to mode after TX (CONST_RX -> RX, WOR -> WOR)
cc110x_switch_to_rx();
/* Go to mode after TX (CONST_RX -> RX, WOR -> WOR) */
cc110x_switch_to_rx();
return true;
return true;
}

@ -1,3 +1,19 @@
/**
* Basic functionality of cc110x driver
*
* Copyright (C) 2013 Freie Universität Berlin
* Copyright (C) 2013 INRIA
*