1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

coding conventions for drivers

This commit is contained in:
Oliver Hahm 2013-06-21 22:36:48 +02:00
parent 201f593641
commit e2130fbd47
26 changed files with 2467 additions and 2150 deletions

View File

@ -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;
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;
}
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;
// 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);
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;
}
if(timespan > 1000000) {
collisions_per_sec = (collision_count * 1000000) / (double) timespan;
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(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 (protocol == 0)
{
return RADIO_INVALID_PARAM; // Not allowed, protocol id must be greater zero
}
if(timespan > 5000000) {
collision_state = COLLISION_STATE_INITIAL;
}
}
cc1100_phy_mutex_lock(); // Lock radio for exclusive access
/* 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;
}
// 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;
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 */
cc1100_cs_init(); // Initialize carrier sensing
if(protocol == 0) {
return RADIO_INVALID_PARAM; /* Not allowed, protocol id must be greater zero */
}
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++;
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;
}

View File

@ -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 */
};
/** @} */

View File

@ -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

View File

@ -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

View File

@ -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;
/*---------------------------------------------------------------------------*/

View File

@ -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;
}
/** @} */

View File

@ -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!

View File

@ -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++;
/* 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;
}
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;
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
/* 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;
}
/* 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;
}
// No valid packet, so go back to RX/WOR as soon as possible
cc110x_switch_to_rx();
}
/* 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);
// Read data from RX FIFO and store in rxBuffer
if (packetLength <= length)
{
// Put length byte at first position in RX Buffer
rxBuffer[0] = packetLength;
/* 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 the rest of the packet
//cc110x_readburst_reg(CC1100_RXFIFO, (char*)rxBuffer+1, packetLength);
cc110x_read_fifo((char*) rxBuffer + 1, 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 2 appended status bytes (status[0] = RSSI, status[1] = LQI)
cc110x_readburst_reg(CC1100_RXFIFO, (char*)status, 2);
/* Read the rest of the packet */
//cc110x_readburst_reg(CC1100_RXFIFO, (char*)rxBuffer+1, packetLength);
cc110x_read_fifo((char *) rxBuffer + 1, packetLength);
// Store RSSI value of packet
rflags._RSSI = status[I_RSSI];
/* Read the 2 appended status bytes (status[0] = RSSI, status[1] = LQI) */
cc110x_readburst_reg(CC1100_RXFIFO, (char *)status, 2);
// MSB of LQI is the CRC_OK bit
rflags.CRC_STATE = (status[I_LQI] & CRC_OK) >> 7;
if (!rflags.CRC_STATE) {
/* 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) {
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;
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;
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

View File

@ -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;
}
}
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 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);
/* 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;
}

View File

@ -1,3 +1,19 @@
/**
* Basic functionality of cc110x driver
*
* Copyright (C) 2013 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-arch.h>
#include <cc110x-config.h>
@ -34,107 +50,119 @@ static void reset(void);
static void power_up_reset(void);
static void write_register(uint8_t r, uint8_t value);
/*---------------------------------------------------------------------------*/
// Radio Driver API
/*---------------------------------------------------------------------------*/
void cc110x_init(int tpid) {
/*---------------------------------------------------------------------------*
* Radio Driver API *
*---------------------------------------------------------------------------*/
void cc110x_init(int tpid)
{
transceiver_pid = tpid;
DEBUG("Transceiver PID: %i\n", transceiver_pid);
rx_buffer_next = 0;
rx_buffer_next = 0;
#ifdef MODULE_CC110X_SPI
/* Initialize SPI */
cc110x_spi_init();
cc110x_spi_init();
#endif
/* Load driver & reset */
power_up_reset();
/* Load driver & reset */
power_up_reset();
/* Write configuration to configuration registers */
cc110x_writeburst_reg(0x00, cc110x_conf, CC1100_CONF_SIZE);
/* Write PATABLE (power settings) */
cc110x_write_reg(CC1100_PATABLE, pa_table[pa_table_index]);
/* Write PATABLE (power settings) */
cc110x_write_reg(CC1100_PATABLE, pa_table[pa_table_index]);
/* Initialize Radio Flags */
rflags._RSSI = 0x00;
rflags.LL_ACK = 0;
rflags.CAA = 0;
rflags.CRC_STATE = 0;
rflags.SEQ = 0;
rflags.MAN_WOR = 0;
rflags.KT_RES_ERR = 0;
rflags.TX = 0;
rflags.WOR_RST = 0;
/* Initialize Radio Flags */
rflags._RSSI = 0x00;
rflags.LL_ACK = 0;
rflags.CAA = 0;
rflags.CRC_STATE = 0;
rflags.SEQ = 0;
rflags.MAN_WOR = 0;
rflags.KT_RES_ERR = 0;
rflags.TX = 0;
rflags.WOR_RST = 0;
/* Set default channel number */
/* Set default channel number */
#ifdef MODULE_CONFIG
cc110x_set_config_channel(sysconfig.radio_channel);
cc110x_set_config_channel(sysconfig.radio_channel);
#else
cc110x_set_channel(CC1100_DEFAULT_CHANNR);
#endif
DEBUG("CC1100 initialized and set to channel %i\n", radio_channel);
// Switch to desired mode (WOR or RX)
rd_set_mode(RADIO_MODE_ON);
/* Switch to desired mode (WOR or RX) */
rd_set_mode(RADIO_MODE_ON);
#ifdef DBG_IGNORE
cc110x_init_ignore();
#endif
}
void cc110x_disable_interrupts(void) {
cc110x_gdo2_disable();
cc110x_gdo0_disable();
void cc110x_disable_interrupts(void)
{
cc110x_gdo2_disable();
cc110x_gdo0_disable();
}
void cc110x_gdo0_irq(void) {
// Air was not free -> Clear CCA flag
rflags.CAA = false;
// Disable carrier sense detection (GDO0 interrupt)
cc110x_gdo0_disable();
void cc110x_gdo0_irq(void)
{
/* Air was not free -> Clear CCA flag */
rflags.CAA = false;
/* Disable carrier sense detection (GDO0 interrupt) */
cc110x_gdo0_disable();
}
void cc110x_gdo2_irq(void) {
cc110x_rx_handler();
void cc110x_gdo2_irq(void)
{
cc110x_rx_handler();
}
uint8_t cc110x_get_buffer_pos(void) {
return (rx_buffer_next-1);
uint8_t cc110x_get_buffer_pos(void)
{
return (rx_buffer_next - 1);
}
radio_address_t cc110x_get_address() {
radio_address_t cc110x_get_address()
{
return radio_address;
}
radio_address_t cc110x_set_address(radio_address_t address) {
if ((address < MIN_UID) || (address > MAX_UID)) {
return 0;
}
radio_address_t cc110x_set_address(radio_address_t address)
{
if((address < MIN_UID) || (address > MAX_UID)) {
return 0;
}
uint8_t id = (uint8_t) address;
if (radio_state != RADIO_UNKNOWN) {
write_register(CC1100_ADDR, id);
}
uint8_t id = (uint8_t) address;
radio_address = id;
return radio_address;
if(radio_state != RADIO_UNKNOWN) {
write_register(CC1100_ADDR, id);
}
radio_address = id;
return radio_address;
}
#ifdef MODULE_CONFIG
radio_address_t cc110x_set_config_address(radio_address_t address) {
radio_address_t cc110x_set_config_address(radio_address_t address)
{
radio_address_t a = cc110x_set_address(address);
if (a) {
if(a) {
sysconfig.radio_address = a;
}
config_save();
return a;
}
#endif
void cc110x_set_monitor(uint8_t mode) {
if (mode) {
void cc110x_set_monitor(uint8_t mode)
{
if(mode) {
write_register(CC1100_PKTCTRL1, (0x04));
}
else {
@ -142,199 +170,259 @@ void cc110x_set_monitor(uint8_t mode) {
}
}
void cc110x_setup_rx_mode(void) {
// Stay in RX mode until end of packet
cc110x_write_reg(CC1100_MCSM2, 0x07);
cc110x_switch_to_rx();
void cc110x_setup_rx_mode(void)
{
/* Stay in RX mode until end of packet */
cc110x_write_reg(CC1100_MCSM2, 0x07);
cc110x_switch_to_rx();
}
void cc110x_switch_to_rx(void) {
radio_state = RADIO_RX;
cc110x_strobe(CC1100_SRX);
void cc110x_switch_to_rx(void)
{
radio_state = RADIO_RX;
cc110x_strobe(CC1100_SRX);
}
void cc110x_wakeup_from_rx(void) {
if (radio_state != RADIO_RX) {
void cc110x_wakeup_from_rx(void)
{
if(radio_state != RADIO_RX) {
return;
}
DEBUG("CC1100 going to idle\n");
cc110x_strobe(CC1100_SIDLE);
radio_state = RADIO_IDLE;
cc110x_strobe(CC1100_SIDLE);
radio_state = RADIO_IDLE;
}
char* cc110x_get_marc_state(void) {
uint8_t state;
char *cc110x_get_marc_state(void)
{
uint8_t state;
// Save old radio state
uint8_t old_state = radio_state;
/* Save old radio state */
uint8_t old_state = radio_state;
// Read content of status register
state = cc110x_read_status(CC1100_MARCSTATE) & MARC_STATE;
/* Read content of status register */
state = cc110x_read_status(CC1100_MARCSTATE) & MARC_STATE;
// Make sure in IDLE state.
// Only goes to IDLE if state was RX/WOR
cc110x_wakeup_from_rx();
/* Make sure in IDLE state.
* Only goes to IDLE if state was RX/WOR */
cc110x_wakeup_from_rx();
// Have to put radio back to WOR/RX if old radio state
// was WOR/RX, otherwise no action is necessary
if (old_state == RADIO_WOR || old_state == RADIO_RX) {
cc110x_switch_to_rx();
}
/* Have to put radio back to WOR/RX if old radio state
* was WOR/RX, otherwise no action is necessary */
if(old_state == RADIO_WOR || old_state == RADIO_RX) {
cc110x_switch_to_rx();
}
switch (state)
{
// Note: it is not possible to read back the SLEEP or XOFF state numbers
// because setting CSn low will make the chip enter the IDLE mode from the
// SLEEP (0) or XOFF (2) states.
case 1: return "IDLE";
case 3: case 4: case 5: return "MANCAL";
case 6: case 7: return "FS_WAKEUP";
case 8: case 12: return "CALIBRATE";
case 9: case 10: case 11: return "SETTLING";
case 13: case 14: case 15: return "RX";
case 16: return "TXRX_SETTLING";
case 17: return "RXFIFO_OVERFLOW";
case 18: return "FSTXON";
case 19: case 20: return "TX";
case 21: return "RXTX_SETTLING";
case 22: return "TXFIFO_UNDERFLOW";
default: return "UNKNOWN";
}
switch(state) {
/* Note: it is not possible to read back the SLEEP or XOFF state numbers
* because setting CSn low will make the chip enter the IDLE mode from the
* SLEEP (0) or XOFF (2) states. */
case 1:
return "IDLE";
case 3:
case 4:
case 5:
return "MANCAL";
case 6:
case 7:
return "FS_WAKEUP";
case 8:
case 12:
return "CALIBRATE";
case 9:
case 10:
case 11:
return "SETTLING";
case 13:
case 14:
case 15:
return "RX";
case 16:
return "TXRX_SETTLING";
case 17:
return "RXFIFO_OVERFLOW";
case 18:
return "FSTXON";
case 19:
case 20:
return "TX";
case 21:
return "RXTX_SETTLING";
case 22:
return "TXFIFO_UNDERFLOW";
default:
return "UNKNOWN";
}
}
char* cc110x_state_to_text(uint8_t state) {
switch (state)
{
case RADIO_UNKNOWN:
return "Unknown";
case RADIO_AIR_FREE_WAITING:
return "CS";
case RADIO_WOR:
return "WOR";
case RADIO_IDLE:
return "IDLE";
case RADIO_SEND_BURST:
return "TX BURST";
case RADIO_RX:
return "RX";
case RADIO_SEND_ACK:
return "TX ACK";
case RADIO_PWD:
return "PWD";
default:
return "unknown";
}
char *cc110x_state_to_text(uint8_t state)
{
switch(state) {
case RADIO_UNKNOWN:
return "Unknown";
case RADIO_AIR_FREE_WAITING:
return "CS";
case RADIO_WOR:
return "WOR";
case RADIO_IDLE:
return "IDLE";
case RADIO_SEND_BURST:
return "TX BURST";
case RADIO_RX:
return "RX";
case RADIO_SEND_ACK:
return "TX ACK";
case RADIO_PWD:
return "PWD";
default:
return "unknown";
}
}
void cc110x_print_config(void) {
printf("Current radio state: %s\r\n", cc110x_state_to_text(radio_state));
printf("Current MARC state: %s\r\n", cc110x_get_marc_state());
printf("Current channel number: %u\r\n", radio_channel);
void cc110x_print_config(void)
{
printf("Current radio state: %s\r\n", cc110x_state_to_text(radio_state));
printf("Current MARC state: %s\r\n", cc110x_get_marc_state());
printf("Current channel number: %u\r\n", radio_channel);
}
void cc110x_switch_to_pwd(void) {
void cc110x_switch_to_pwd(void)
{
DEBUG("[cc110x_ng] switching to powerdown\n");
cc110x_wakeup_from_rx();
cc110x_strobe(CC1100_SPWD);
radio_state = RADIO_PWD;
cc110x_strobe(CC1100_SPWD);
radio_state = RADIO_PWD;
}
/*---------------------------------------------------------------------------*/
int16_t cc110x_set_channel(uint8_t channr) {
uint8_t state = cc110x_read_status(CC1100_MARCSTATE) & MARC_STATE;
if ((state != 1) && (channr > MAX_CHANNR)) {
int16_t cc110x_set_channel(uint8_t channr)
{
uint8_t state = cc110x_read_status(CC1100_MARCSTATE) & MARC_STATE;
if((state != 1) && (channr > MAX_CHANNR)) {
return -1;
}
write_register(CC1100_CHANNR, channr*10);
radio_channel = channr;
return radio_channel;
write_register(CC1100_CHANNR, channr * 10);
radio_channel = channr;
return radio_channel;
}
#ifdef MODULE_CONFIG
int16_t cc110x_set_config_channel(uint8_t channr) {
int16_t cc110x_set_config_channel(uint8_t channr)
{
int16_t c = cc110x_set_channel(channr);
if (c) {
if(c) {
sysconfig.radio_channel = c;
}
config_save();
return c;
}
#endif
int16_t cc110x_get_channel(void) {
int16_t cc110x_get_channel(void)
{
return radio_channel;
}
/*---------------------------------------------------------------------------*/
// CC1100 reset functionality
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------
* CC1100 reset functionality
*---------------------------------------------------------------------------*/
static void reset(void) {
cc110x_wakeup_from_rx();
static void reset(void)
{
cc110x_wakeup_from_rx();
#ifdef MODULE_CC110x_SPI
cc110x_spi_select();
cc110x_spi_select();
#endif
cc110x_strobe(CC1100_SRES);
hwtimer_wait(RTIMER_TICKS(100));
cc110x_strobe(CC1100_SRES);
hwtimer_wait(RTIMER_TICKS(100));
}
static void power_up_reset(void) {
static void power_up_reset(void)
{
#ifdef MODULE_CC110x_SPI
cc110x_spi_unselect();
cc110x_spi_cs();
cc110x_spi_unselect();
cc110x_spi_unselect();
cc110x_spi_cs();
cc110x_spi_unselect();
#endif
hwtimer_wait(RESET_WAIT_TIME);
reset();
radio_state = RADIO_IDLE;
hwtimer_wait(RESET_WAIT_TIME);
reset();
radio_state = RADIO_IDLE;
}
static void write_register(uint8_t r, uint8_t value) {
// Save old radio state
uint8_t old_state = radio_state;
/* Wake up from WOR/RX (if in WOR/RX, else no effect) */
cc110x_wakeup_from_rx();
cc110x_write_reg(r, value);
static void write_register(uint8_t r, uint8_t value)
{
/* Save old radio state */
uint8_t old_state = radio_state;
// Have to put radio back to WOR/RX if old radio state
// was WOR/RX, otherwise no action is necessary
if ((old_state == RADIO_WOR) || (old_state == RADIO_RX)) {
cc110x_switch_to_rx();
}
/* Wake up from WOR/RX (if in WOR/RX, else no effect) */
cc110x_wakeup_from_rx();
cc110x_write_reg(r, value);
/* Have to put radio back to WOR/RX if old radio state
* was WOR/RX, otherwise no action is necessary */
if((old_state == RADIO_WOR) || (old_state == RADIO_RX)) {
cc110x_switch_to_rx();
}
}
static int rd_set_mode(int mode) {
int result;
// Get current radio mode
if ((radio_state == RADIO_UNKNOWN) || (radio_state == RADIO_PWD)) {
result = RADIO_MODE_OFF;
}
else {
result = RADIO_MODE_ON;
}
static int rd_set_mode(int mode)
{
int result;
switch (mode) {
case RADIO_MODE_ON:
/* Get current radio mode */
if((radio_state == RADIO_UNKNOWN) || (radio_state == RADIO_PWD)) {
result = RADIO_MODE_OFF;
}
else {
result = RADIO_MODE_ON;
}
switch(mode) {
case RADIO_MODE_ON:
DEBUG("Enabling rx mode\n");
cc110x_init_interrupts(); // Enable interrupts
cc110x_setup_rx_mode(); // Set chip to desired mode
break;
case RADIO_MODE_OFF:
cc110x_disable_interrupts(); // Disable interrupts
cc110x_switch_to_pwd(); // Set chip to power down mode
break;
case RADIO_MODE_GET:
// do nothing, just return current mode
default:
// do nothing
break;
}
cc110x_init_interrupts(); /* Enable interrupts */
cc110x_setup_rx_mode(); /* Set chip to desired mode */
break;
// Return previous mode
return result;
case RADIO_MODE_OFF:
cc110x_disable_interrupts(); /* Disable interrupts */
cc110x_switch_to_pwd(); /* Set chip to power down mode */
break;
case RADIO_MODE_GET:
/* do nothing, just return current mode */
default:
/* do nothing */
break;
}
/* Return previous mode */
return result;
}

View File

@ -1,3 +1,19 @@
/**
* Configuration parameters for the cc110x radio chip
*
* 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>
* @}
*/
#ifndef CC1100_CONFIG_H
#define CC1100_CONFIG_H
@ -6,91 +22,90 @@
/** CC1100 register configuration */
typedef struct {
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;
} cc110x_reg_t;
/** CC1100 radio configuration */
typedef struct {
cc110x_reg_t reg_cfg; ///< CC1100 register configuration
uint8_t pa_power; ///< Output power setting
cc110x_reg_t reg_cfg; ///< CC1100 register configuration
uint8_t pa_power; ///< Output power setting
} cc110x_cfg_t;
/**
* @brief Radio Control Flags
*/
typedef struct
{
uint32_t TOF; ///< Time of flight of the last packet and last ACK
typedef struct {
uint32_t TOF; ///< Time of flight of the last packet and last ACK
timex_t TOA; ///< Time of packet arriveal
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
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
} cc110x_flags;
/**
* @brief Statistic interface for debugging
*/
typedef struct cc110x_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_broadcast;
uint32_t raw_packets_out;
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_broadcast;
uint32_t raw_packets_out;
uint32_t acks_send;
uint32_t rx_buffer_max;
uint32_t watch_dog_resets;
} cc110x_statistic_t;
#endif

View File

@ -1,28 +1,19 @@
/******************************************************************************
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
*******************************************************************************/
/**
* Driver internal constants for 110x chip configuration
*
* Copyright (C) 2008 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>
* @}
*/
#ifndef CC1100_INTERNAL_H
#define CC1100_INTERNAL_H

View File

@ -3,9 +3,8 @@
* @ingroup dev_cc110x_ng
* @brief Access to CC110X registers
*
* @author Freie Uniersität Berlin, Computer Systems & Telematics, RIOT
* @author Oliver Hahm <oliver.hahm@fu-berlin.de
* version $Revision$
* @author INRIA
* @author Oliver Hahm <oliver.hahm@inria.fr>
*
*/
@ -39,7 +38,7 @@ void cc110x_readburst_reg(uint8_t addr, char *buffer, uint8_t count);
*
* @param buffer Buffer to store read data
* @param count Size of data to be read
*
*
* @note: Calls cc110x_readburst_reg if not dedicated fifo read command
* available
*/

View File

@ -1,3 +1,19 @@
/**
* Data structures and variables for the cc110x driver interface
*
* 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>
* @}
*/
#ifndef CC1100_H
#define CC1100_H
@ -65,13 +81,15 @@ 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)) {
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[CC1100_MAX_DATA_LENGTH]; ///< Data (high layer protocol)
} cc110x_packet_t;
typedef struct __attribute__((packed))
{
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[CC1100_MAX_DATA_LENGTH]; ///< Data (high layer protocol)
}
cc110x_packet_t;
typedef struct {
uint8_t rssi;
@ -80,12 +98,12 @@ typedef struct {
} rx_buffer_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
};
extern rx_buffer_t cc110x_rx_buffer[];
extern rx_buffer_t cc110x_rx_buffer[];
extern volatile uint8_t rx_buffer_next; ///< Next packet in RX queue

View File

@ -58,76 +58,87 @@ and the mailinglist (subscription via web site)
#define NOBYTE 0xFF
uint8_t cc110x_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;
uint8_t cc110x_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;
}
void cc110x_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);
void cc110x_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);
}
void cc110x_read_fifo(char *buffer, uint8_t count) {
cc110x_readburst_reg(CC1100_RXFIFO, buffer,count);
void cc110x_read_fifo(char *buffer, uint8_t count)
{
cc110x_readburst_reg(CC1100_RXFIFO, buffer, count);
}
void cc110x_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);
void cc110x_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);
}
uint8_t cc110x_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 cc110x_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 cc110x_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 cc110x_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 cc110x_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 cc110x_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;
}
/** @} */

View File

@ -1,5 +1,5 @@
#ifndef ADC_H
#define ADC_H
#define ADC_H
#include <stdint.h>

View File

@ -20,8 +20,8 @@
#endif
/* These functions are defined in asmfunc.S */
void Copy_al2un (unsigned char *dst, const unsigned long *src, int count); /* Copy aligned to unaligned. */
void Copy_un2al (unsigned long *dst, const unsigned char *src, int count); /* Copy unaligned to aligned. */
void Copy_al2un(unsigned char *dst, const unsigned long *src, int count); /* Copy aligned to unaligned. */
void Copy_un2al(unsigned long *dst, const unsigned char *src, int count); /* Copy unaligned to aligned. */
/* Status of Disk Functions */
@ -29,22 +29,22 @@ typedef unsigned char DSTATUS;
/* Results of Disk Functions */
typedef enum {
RES_OK = 0, /* 0: Successful */
RES_ERROR, /* 1: R/W Error */
RES_WRPRT, /* 2: Write Protected */
RES_NOTRDY, /* 3: Not Ready */
RES_PARERR /* 4: Invalid Parameter */
RES_OK = 0, /* 0: Successful */
RES_ERROR, /* 1: R/W Error */
RES_WRPRT, /* 2: Write Protected */
RES_NOTRDY, /* 3: Not Ready */
RES_PARERR /* 4: Invalid Parameter */
} DRESULT;
/*---------------------------------------*/
/* Prototypes for disk control functions */
DSTATUS disk_initialize (unsigned char);
DSTATUS disk_status (unsigned char);
DRESULT disk_read (unsigned char, unsigned char*, unsigned long, unsigned char);
DRESULT disk_write (unsigned char, const unsigned char*, unsigned long, unsigned char);
DRESULT disk_ioctl (unsigned char, unsigned char, void*);
DSTATUS disk_initialize(unsigned char);
DSTATUS disk_status(unsigned char);
DRESULT disk_read(unsigned char, unsigned char *, unsigned long, unsigned char);
DRESULT disk_write(unsigned char, const unsigned char *, unsigned long, unsigned char);
DRESULT disk_ioctl(unsigned char, unsigned char, void *);
@ -90,18 +90,18 @@ DRESULT disk_ioctl (unsigned char, unsigned char, void*);
/* Prototypes for each physical disk functions */
DSTATUS NAND_initialize (void);
DSTATUS NAND_status (void);
DRESULT NAND_read (unsigned char*, unsigned long, unsigned char);
DRESULT NAND_write (const unsigned char*, unsigned long, unsigned char);
DRESULT NAND_ioctl (unsigned char, void*);
DSTATUS NAND_initialize(void);
DSTATUS NAND_status(void);
DRESULT NAND_read(unsigned char *, unsigned long, unsigned char);
DRESULT NAND_write(const unsigned char *, unsigned long, unsigned char);
DRESULT NAND_ioctl(unsigned char, void *);
DSTATUS MCI_initialize (void);
DSTATUS MCI_status (void);
DRESULT MCI_read (unsigned char*, unsigned long, unsigned char);
DRESULT MCI_write (const unsigned char*, unsigned long, unsigned char);
DRESULT MCI_ioctl (unsigned char, void*);
void MCI_timerproc (void);
DSTATUS MCI_initialize(void);
DSTATUS MCI_status(void);
DRESULT MCI_read(unsigned char *, unsigned long, unsigned char);
DRESULT MCI_write(const unsigned char *, unsigned long, unsigned char);
DRESULT MCI_ioctl(unsigned char, void *);
void MCI_timerproc(void);
#endif

View File

@ -1,5 +1,5 @@
#ifndef FLASHROM_H
#define FLASHROM_H
#define FLASHROM_H
#include <stdint.h>
#include <stddef.h>

View File

@ -1,5 +1,5 @@
#ifndef __LTC4150_H
#define __LTC4150_H
#define __LTC4150_H
#include <ltc4150_arch.h>

View File

@ -25,7 +25,7 @@ and the mailinglist (subscription via web site)
*******************************************************************************/
#ifndef __LTC4150_ARCH_H
#define __LTC4150_ARCH_H
#define __LTC4150_ARCH_H
/**
* @defgroup ltc4150 LTC4150 Coulomb Counter
@ -53,7 +53,7 @@ void ltc4150_disable_int(void);
/** board specific ltc4150 interrupt enable */
void ltc4150_enable_int(void);
/** board specific synchronization of ltc4150 */
void ltc4150_sync_blocking(void);
void ltc4150_sync_blocking(void);
/** board specific ltc4150 initialization */
void ltc4150_arch_init(void);

View File

@ -56,13 +56,13 @@ void rtc_disable(void);
* @brief Sets the current time in broken down format directly from to RTC
* @param[in] localt Pointer to structure with time to set
*/
void rtc_set_localtime(struct tm* localt);
void rtc_set_localtime(struct tm *localt);
/**
* @brief Returns the current time in broken down format directly from the RTC
* @param[out] localt Pointer to structure to receive time
*/
void rtc_get_localtime(struct tm* localt);
void rtc_get_localtime(struct tm *localt);
extern int rtc_second_pid;

View File

@ -44,7 +44,7 @@ and the mailinglist (subscription via web site)
#define SHT11_NO_ACK (0)
#define SHT11_ACK (1)
//adr command r/w
//adr command r/w
#define SHT11_STATUS_REG_W (0x06) //000 0011 0
#define SHT11_STATUS_REG_R (0x07) //000 0011 1
#define SHT11_MEASURE_TEMP (0x03) //000 0001 1
@ -60,20 +60,20 @@ and the mailinglist (subscription via web site)
#define SHT11_MEASURE_TIMEOUT (1000)
/**
* @brief sht11 measureable data
* @brief sht11 measureable data
*/
typedef struct {
float temperature; /**< temperature value */
float relhum; /**< linear relative humidity */
float relhum_temp; /**< temperature compensated relative humidity */
float temperature; /**< temperature value */
float relhum; /**< linear relative humidity */
float relhum_temp; /**< temperature compensated relative humidity */
} sht11_val_t;
/**
* @brief SHT11 modes that can be measured
*/
typedef enum {
TEMPERATURE = 1,
HUMIDITY = 2
TEMPERATURE = 1,
HUMIDITY = 2
} sht11_mode_t;
/**
@ -98,7 +98,7 @@ uint8_t sht11_read_sensor(sht11_val_t *value, sht11_mode_t mode);
/**
* @brief Write status register
*
*
* @param p_value The value to write
*
* @return 1 on success, 0 otherwise

View File

@ -46,51 +46,63 @@ static unsigned int last_int_time;
static unsigned int last_int_duration;
static unsigned int start_time;
static double __attribute__((__no_instrument_function__)) int_to_coulomb(int ints) {
static double __attribute__((__no_instrument_function__)) int_to_coulomb(int ints)
{
return ((double)ints) / (_GFH * _R_SENSE);
}
static double __attribute__((__no_instrument_function__)) coulomb_to_mA(double coulomb){
static double __attribute__((__no_instrument_function__)) coulomb_to_mA(double coulomb)
{
return (coulomb * 1000) / 3600;
}
static double mAh_to_Joule(double mAh) {
static double mAh_to_Joule(double mAh)
{
return (SUPPLY_VOLTAGE * mAh * 3600);
}
uint32_t ltc4150_get_last_int_duration_us(void) {
uint32_t ltc4150_get_last_int_duration_us(void)
{
return HWTIMER_TICKS_TO_US(last_int_duration);
}
double ltc4150_get_current_mA(void) {
return 1000000000/(ltc4150_get_last_int_duration_us()*(_GFH * _R_SENSE));
double ltc4150_get_current_mA(void)
{
return 1000000000 / (ltc4150_get_last_int_duration_us() * (_GFH * _R_SENSE));
}
double __attribute__((__no_instrument_function__)) ltc4150_get_total_mAh(void) {
double __attribute__((__no_instrument_function__)) ltc4150_get_total_mAh(void)
{
return coulomb_to_mA(int_to_coulomb(int_count));
}
double ltc4150_get_total_Joule(void) {
double ltc4150_get_total_Joule(void)
{
return mAh_to_Joule(ltc4150_get_total_mAh());
}
double ltc4150_get_avg_mA(void) {
return (int_to_coulomb(int_count)*1000000000)/HWTIMER_TICKS_TO_US(last_int_time - start_time);
double ltc4150_get_avg_mA(void)
{
return (int_to_coulomb(int_count) * 1000000000) / HWTIMER_TICKS_TO_US(last_int_time - start_time);
}
int ltc4150_get_interval(void) {
int ltc4150_get_interval(void)
{
return HWTIMER_TICKS_TO_US(last_int_time - start_time);
}
unsigned long __attribute__((__no_instrument_function__)) ltc4150_get_intcount(void) {
unsigned long __attribute__((__no_instrument_function__)) ltc4150_get_intcount(void)
{
return int_count;
}
void ltc4150_init(void) {
void ltc4150_init(void)
{
ltc4150_arch_init();
}
void ltc4150_start(void) {
void ltc4150_start(void)
{
ltc4150_disable_int();
int_count = 0;
uint32_t now = hwtimer_now();
@ -100,17 +112,20 @@ void ltc4150_start(void) {
ltc4150_enable_int();
}
void ltc4150_stop(void) {
void ltc4150_stop(void)
{
ltc4150_disable_int();
}
void __attribute__((__no_instrument_function__)) ltc4150_interrupt(void)
{
uint32_t now = hwtimer_now();
if (now >= last_int_time) {
if(now >= last_int_time) {
last_int_duration = now - last_int_time;
} else {
last_int_duration = (0-1) - last_int_time + now + 1;
}
else {
last_int_duration = (0 - 1) - last_int_time + now + 1;
}
last_int_time = now;

View File

@ -53,7 +53,7 @@ float sht11_temperature_offset;
/**
* @brief Perform measurement
*
*
* @param p_value Measured value (14 or 12 bit -> 2 bytes)
* @param p_checksum Checksum of measurement
* @param mode The requestested measurement mode: temperature or humidity
@ -62,7 +62,7 @@ float sht11_temperature_offset;
*/
static uint8_t measure(uint8_t *p_value, uint8_t *p_checksum, uint8_t mode);
/**
/**
* @brief Write one byte
*
* @param value The value to write
@ -91,7 +91,7 @@ static void connection_reset(void);
static void transmission_start(void);
/**
* @brief Toggle the clock line
* @brief Toggle the clock line
*/
static inline void clk_signal(void);
@ -99,7 +99,8 @@ static inline void clk_signal(void);
mutex_t sht11_mutex;
/*---------------------------------------------------------------------------*/
static inline void clk_signal(void) {
static inline void clk_signal(void)
{
SHT11_SCK_HIGH;
hwtimer_wait(SHT11_CLK_WAIT);
SHT11_SCK_LOW;
@ -109,246 +110,264 @@ static inline void clk_signal(void) {
/*---------------------------------------------------------------------------*/
static uint8_t write_byte(uint8_t value)
{
uint8_t i;
uint8_t ack;
uint8_t i;
uint8_t ack;
SHT11_DATA_OUT;
/* send value bit by bit to sht11 */
for (i = 0; i < 8; i++) {
if (value & BIT7) {
SHT11_DATA_HIGH;
for(i = 0; i < 8; i++) {
if(value & BIT7) {
SHT11_DATA_HIGH;
hwtimer_wait(SHT11_DATA_WAIT);
} else {
SHT11_DATA_LOW;
}
else {
SHT11_DATA_LOW;
hwtimer_wait(SHT11_DATA_WAIT);
}
}
/* trigger clock signal */
clk_signal();
/* shift value to write next bit */
value = value << 1;
}
value = value << 1;
}
/* wait for ack */
SHT11_DATA_IN;
SHT11_DATA_IN;
hwtimer_wait(SHT11_CLK_WAIT);
ack = SHT11_DATA;
ack = SHT11_DATA;
clk_signal();
return ack;
return ack;
}
/*---------------------------------------------------------------------------*/
static uint8_t read_byte (uint8_t ack)
static uint8_t read_byte(uint8_t ack)
{
uint8_t i;
uint8_t value = 0;
uint8_t i;
uint8_t value = 0;
SHT11_DATA_IN;
SHT11_DATA_IN;
hwtimer_wait(SHT11_DATA_WAIT);
/* read value bit by bit */
for (i = 0; i < 8; i++) {
value = value << 1;
SHT11_SCK_HIGH;
for(i = 0; i < 8; i++) {
value = value << 1;
SHT11_SCK_HIGH;
hwtimer_wait(SHT11_CLK_WAIT);
if (SHT11_DATA) {
if(SHT11_DATA) {
/* increase data by one when DATA is high */
value++;
}
SHT11_SCK_LOW;
SHT11_SCK_LOW;
hwtimer_wait(SHT11_CLK_WAIT);
}
}
/* send ack if necessary */
SHT11_DATA_OUT;
if (ack) {
SHT11_DATA_LOW;
SHT11_DATA_OUT;
if(ack) {
SHT11_DATA_LOW;
hwtimer_wait(SHT11_DATA_WAIT);
} else {
SHT11_DATA_HIGH;
}
else {
SHT11_DATA_HIGH;
hwtimer_wait(SHT11_DATA_WAIT);
}
}
clk_signal();
/* release data line */
SHT11_DATA_IN;
SHT11_DATA_IN;
return value;
return value;
}
/*---------------------------------------------------------------------------*/
static void transmission_start(void)
{
/* _____ ________
DATA: |_______|
___ ___
SCK : ___| |___| |______
*/
SHT11_DATA_OUT;
DATA: |_______|
___ ___
SCK : ___| |___| |______
*/
SHT11_DATA_OUT;
/* set initial state */
SHT11_DATA_HIGH;
SHT11_DATA_HIGH;
hwtimer_wait(SHT11_DATA_WAIT);
SHT11_SCK_LOW;
SHT11_SCK_LOW;
hwtimer_wait(SHT11_CLK_WAIT);
SHT11_SCK_HIGH;
SHT11_SCK_HIGH;
hwtimer_wait(SHT11_CLK_WAIT);
SHT11_DATA_LOW;
SHT11_DATA_LOW;
hwtimer_wait(SHT11_DATA_WAIT);
SHT11_SCK_LOW;
SHT11_SCK_LOW;
hwtimer_wait(SHT11_CLK_WAIT);
SHT11_SCK_HIGH;
SHT11_SCK_HIGH;
hwtimer_wait(SHT11_CLK_WAIT);
SHT11_DATA_HIGH;
SHT11_DATA_HIGH;
hwtimer_wait(SHT11_DATA_WAIT);
SHT11_SCK_LOW;
SHT11_SCK_LOW;
hwtimer_wait(SHT11_CLK_WAIT);
}
/*---------------------------------------------------------------------------*/
static void connection_reset(void)
{
/* _____________________________________________________ ____
DATA: |_______|
_ _ _ _ _ _ _ _ _ ___ ___
SCK : __| |__| |__| |__| |__| |__| |__| |__| |__| |______| |___| |__
*/
/* _____________________________________________________ ____
DATA: |_______|
_ _ _ _ _ _ _ _ _ ___ ___
SCK : __| |__| |__| |__| |__| |__| |__| |__| |__| |______| |___| |__
*/
uint8_t i;
SHT11_DATA_HIGH;
SHT11_DATA_HIGH;
hwtimer_wait(SHT11_DATA_WAIT);
SHT11_SCK_LOW;
hwtimer_wait(SHT11_CLK_WAIT);
for (i = 0; i < 9; i++) {
for(i = 0; i < 9; i++) {
clk_signal();
}
transmission_start();
}
transmission_start();
}
/*---------------------------------------------------------------------------*/
static uint8_t measure(uint8_t *p_value, uint8_t *p_checksum, uint8_t mode)
{
uint8_t error = 0;
uint8_t ack = 1;
uint16_t i;
uint8_t error = 0;
uint8_t ack = 1;
uint16_t i;
transmission_start();
error = write_byte(mode);
error = write_byte(mode);
hwtimer_wait(HWTIMER_TICKS(1000));
/* wait untile sensor has finished measurement or timeout */
for (i = 0; (i < SHT11_MEASURE_TIMEOUT) && (!error); i++) {
ack = SHT11_DATA;
for(i = 0; (i < SHT11_MEASURE_TIMEOUT) && (!error); i++) {
ack = SHT11_DATA;
if (!ack) {
break;
if(!ack) {
break;
}
hwtimer_wait(HWTIMER_TICKS(1000));
}
error += ack;
}
error += ack;
/* read MSB */
*(p_value + 1) = read_byte(SHT11_ACK);
*(p_value + 1) = read_byte(SHT11_ACK);
/* read LSB */
*(p_value) = read_byte(SHT11_ACK);
*(p_value) = read_byte(SHT11_ACK);
/* read checksum */
*p_checksum = read_byte(SHT11_NO_ACK);
return (!error);
return (!error);
}
/*---------------------------------------------------------------------------*/
void sht11_init(void) {
sht11_temperature_offset = 0;
mutex_init(&sht11_mutex);
SHT11_INIT;
void sht11_init(void)
{
sht11_temperature_offset = 0;
mutex_init(&sht11_mutex);
SHT11_INIT;
hwtimer_wait(11 * HWTIMER_TICKS(1000));
}
/*---------------------------------------------------------------------------*/
uint8_t sht11_read_status(uint8_t *p_value, uint8_t *p_checksum) {
uint8_t error = 0;
uint8_t sht11_read_status(uint8_t *p_value, uint8_t *p_checksum)
{
uint8_t error = 0;
transmission_start();
error |= write_byte(SHT11_STATUS_REG_R);
*p_value = read_byte(SHT11_ACK);
*p_checksum = read_byte(SHT11_NO_ACK);
return (!error);
transmission_start();
error |= write_byte(SHT11_STATUS_REG_R);
*p_value = read_byte(SHT11_ACK);
*p_checksum = read_byte(SHT11_NO_ACK);
return (!error);
}
/*---------------------------------------------------------------------------*/
uint8_t sht11_write_status(uint8_t *p_value) {
uint8_t error = 0;
uint8_t sht11_write_status(uint8_t *p_value)
{
uint8_t error = 0;
transmission_start();
error += write_byte(SHT11_STATUS_REG_W);
error += write_byte(*p_value);
return (!error);
transmission_start();
error += write_byte(SHT11_STATUS_REG_W);
error += write_byte(*p_value);
return (!error);
}
/*---------------------------------------------------------------------------*/
uint8_t sht11_read_sensor(sht11_val_t *value, sht11_mode_t mode) {
uint8_t error = 0;
uint8_t checksum;
uint16_t humi_int, temp_int;
uint8_t sht11_read_sensor(sht11_val_t *value, sht11_mode_t mode)
{
uint8_t error = 0;
uint8_t checksum;
uint16_t humi_int, temp_int;
/* Temperature arithmetic where S0(T) is read value
/* Temperature arithmetic where S0(T) is read value
* T = D1 + D2 * S0(T) */
const float D1 = -39.6;
const float D2 = 0.01;
const float D1 = -39.6;
const float D2 = 0.01;
/* Arithmetic for linear humdity where S0(RH) is read value
/* Arithmetic for linear humdity where S0(RH) is read value
* HL = C1 + C2 * S0(RH) + C3 * SO(RH)^2 */
const float C1 = -4.0;
const float C2 = +0.0405;
const float C3 = -0.0000028;
const float C1 = -4.0;
const float C2 = +0.0405;
const float C3 = -0.0000028;
/* Arithmetic for temperature compesated relative humdity
/* Arithmetic for temperature compesated relative humdity
* HT = (T-25) * ( T1 + T2 * SO(RH) ) + HL */
const float T1 = +0.01;
const float T2 = +0.00008;
const float T1 = +0.01;
const float T2 = +0.00008;
/* check for valid buffer */
if (value == NULL) {
if(value == NULL) {
return 0;
}
value->temperature = 0;
value->relhum = 0;
value->relhum_temp = 0;
value->temperature = 0;
value->relhum = 0;
value->relhum_temp = 0;
mutex_lock(&sht11_mutex);
connection_reset();
mutex_lock(&sht11_mutex);
connection_reset();
/* measure humidity */
if (mode & HUMIDITY) {
error += (!measure((uint8_t*) &humi_int, &checksum, SHT11_MEASURE_HUMI));
}
if(mode & HUMIDITY) {
error += (!measure((uint8_t *) &humi_int, &checksum, SHT11_MEASURE_HUMI));
}
/* measure temperature */
if (mode & TEMPERATURE) {
error += (!measure((uint8_t*) &temp_int, &checksum, SHT11_MEASURE_TEMP));
}
if(mode & TEMPERATURE) {
error += (!measure((uint8_t *) &temp_int, &checksum, SHT11_MEASURE_TEMP));
}
/* break on error */
if (error != 0) {
connection_reset();
mutex_unlock(&sht11_mutex,0);
return 0;
}
if(error != 0) {
connection_reset();
mutex_unlock(&sht11_mutex, 0);
return 0;
}
if (mode & TEMPERATURE) {
value->temperature = D1 + (D2 * ((float) temp_int)) + sht11_temperature_offset;
}
if (mode & HUMIDITY) {
value->relhum = C1 + (C2 * ((float) humi_int)) + (C3 * ((float) humi_int) * ((float) humi_int));
if(mode & TEMPERATURE) {
value->temperature = D1 + (D2 * ((float) temp_int)) + sht11_temperature_offset;
}
if (mode & TEMPERATURE) {
value->relhum_temp = (value->temperature - 25) * (T1 + (T2 * (float) humi_int)) + value->relhum;
}
}
mutex_unlock(&sht11_mutex,0);
return 1;
if(mode & HUMIDITY) {
value->relhum = C1 + (C2 * ((float) humi_int)) + (C3 * ((float) humi_int) * ((float) humi_int));
if(mode & TEMPERATURE) {
value->relhum_temp = (value->temperature - 25) * (T1 + (T2 * (float) humi_int)) + value->relhum;
}
}
mutex_unlock(&sht11_mutex, 0);
return 1;
}
/** @} */