1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-01-18 12:52:44 +01:00

* NOTE: simple packet exchange using cc110x_ng seems to work now

* added TX functions to cc110x_ng driver and transceiver module
* split up cc1100_ng functions to more files
* added address asignment and request functions to driver and transceiver module
This commit is contained in:
Oliver Hahm 2010-11-26 10:23:46 +01:00
parent d378ee1930
commit 29cb64a37e
9 changed files with 432 additions and 197 deletions

View File

@ -29,5 +29,5 @@ SubDir TOP drivers cc110x_ng ;
HDRS += $(TOP)/drivers/cc110x_ng ;
Module cc110x_ng : cc1100.c cc1100-defaultSettings.c cc1100_spi.c : board_cc1100 swtimer gpioint ;
Module cc110x_ng : cc1100.c cc1100-rx.c cc1100-tx.c cc1100-defaultSettings.c cc1100_spi.c : board_cc1100 swtimer gpioint ;

View File

@ -137,19 +137,5 @@ uint8_t pa_table[] = { ///< PATABLE with available output powers
0xC3 ///< +10 dBm
}; // If PATABLE is changed in size, adjust MAX_OUTPUT_POWER definition in CC1100 interface!
static int8_t pa_table_dBm[] = { ///< Values of the PATABLE in dBm
-52,
-30,
-20,
-15,
-10,
-5,
-1,
0,
5,
7,
9,
10
};
/** @} */

View File

@ -0,0 +1,153 @@
#include <cc1100_ng.h>
#include <cc1100-internal.h>
#include <cc1100-config.h>
#include <cc1100-defaultSettings.h>
#include <cc1100_spi.h>
#include <hwtimer.h>
#include <msg.h>
#include <transceiver.h>
#include <board.h>
static uint8_t receive_packet_variable(uint8_t *rxBuffer, uint8_t length);
static uint8_t receive_packet(uint8_t *rxBuffer, uint8_t length);
rx_buffer_t cc1100_rx_buffer[RX_BUF_SIZE]; ///< RX buffer
volatile uint8_t rx_buffer_next; ///< Next packet in RX queue
void cc1100_rx_handler(void) {
uint8_t res = 0;
// Possible packet received, RX -> IDLE (0.1 us)
rflags.CAA = 0;
rflags.MAN_WOR = 0;
cc1100_statistic.packets_in++;
res = receive_packet((uint8_t*)&(cc1100_rx_buffer[rx_buffer_next].packet), sizeof(cc1100_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)
{
cc1100_statistic.packets_in_while_tx++;
return;
}
cc1100_rx_buffer[rx_buffer_next].rssi = rflags.RSSI;
cc1100_rx_buffer[rx_buffer_next].lqi = rflags.LQI;
// 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).
cc1100_spi_write_reg(CC1100_MCSM0, 0x08); // Turn off FS-Autocal
cc1100_spi_write_reg(CC1100_MCSM2, 0x07); // Configure RX_TIME (until end of packet)
cc1100_spi_strobe(CC1100_SRX);
hwtimer_wait(IDLE_TO_RX_TIME);
radio_state = RADIO_RX;
/* notify transceiver thread if any */
if (transceiver_pid) {
msg 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) {
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
cc1100_spi_strobe(CC1100_SIDLE); // Switch to IDLE (should already be)...
cc1100_spi_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)
{
cc1100_spi_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)
{
cc1100_statistic.packets_in_while_tx++;
return;
}
// No valid packet, so go back to RX/WOR as soon as possible
cc1100_switch_to_rx();
}
}
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 ((cc1100_spi_read_status(CC1100_RXBYTES) & BYTES_IN_RXFIFO)) {
LED_GREEN_TOGGLE;
// Read length byte (first byte in RX FIFO)
packetLength = cc1100_spi_read_reg(CC1100_RXFIFO);
// 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
cc1100_spi_readburst_reg(CC1100_RXFIFO, (char*)rxBuffer+1, packetLength);
// Read the 2 appended status bytes (status[0] = RSSI, status[1] = LQI)
cc1100_spi_readburst_reg(CC1100_RXFIFO, (char*)status, 2);
// Store RSSI value of packet
rflags.RSSI = status[I_RSSI];
// MSB of LQI is the CRC_OK bit
rflags.CRC = (status[I_LQI] & CRC_OK) >> 7;
if (!rflags.CRC) {
cc1100_statistic.packets_in_crc_fail++;
}
// Bit 0-6 of LQI indicates the link quality (LQI)
rflags.LQI = status[I_LQI] & LQI_EST;
return rflags.CRC;
}
/* too many bytes in FIFO */
else {
// RX FIFO get automatically flushed if return value is false
return 0;
}
}
/* no bytes in RX FIFO */
else {
LED_RED_TOGGLE;
// 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 = cc1100_spi_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;
}

View File

@ -0,0 +1,77 @@
#include <stdio.h>
#include <cc1100_ng.h>
#include <cc1100-defaultSettings.h>
#include <cc1100-internal.h>
#include <cc1100-arch.h>
#include <cc1100_spi.h>
#include <irq.h>
#include <board.h>
uint8_t cc1100_send(cc1100_packet_t *packet) {
puts("Going to send\n");
volatile uint32_t abort_count;
uint8_t size;
/* TODO: burst sending */
radio_state = RADIO_SEND_BURST;
rflags.LL_ACK = 0;
/*
* Number of bytes to send is:
* length of phy payload (packet->length)
* + size of length field (1 byte)
*/
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) {
return 0;
}
packet->phy_src = cc1100_get_address();
// Disables RX interrupt etc.
cc1100_before_send();
// But CC1100 in IDLE mode to flush the FIFO
cc1100_spi_strobe(CC1100_SIDLE);
// Flush TX FIFO to be sure it is empty
cc1100_spi_strobe(CC1100_SFTX);
// Write packet into TX FIFO
cc1100_spi_writeburst_reg(CC1100_TXFIFO, (char*) packet, size);
// Switch to TX mode
abort_count = 0;
unsigned int cpsr = disableIRQ();
cc1100_spi_strobe(CC1100_STX);
// Wait for GDO2 to be set -> sync word transmitted
while (cc1100_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 (cc1100_get_gdo2() != 0);
// Experimental - TOF Measurement
cc1100_after_send();
cc1100_statistic.raw_packets_out++;
// Store number of transmission retries
rflags.TX = 0;
// Go to mode after TX (CONST_RX -> RX, WOR -> WOR)
cc1100_switch_to_rx();
return true;
}

View File

@ -1,5 +1,3 @@
#include <stdlib.h>
#include <cc1100_ng.h>
#include <cc1100-arch.h>
#include <cc1100-config.h>
@ -7,15 +5,10 @@
#include <cc1100-internal.h>
#include <cc1100_spi.h>
#include <transceiver.h>
#include <hwtimer.h>
#include <msg.h>
//#define ENABLE_DEBUG (1)
#include <debug.h>
#include <board.h>
#define RX_BUF_SIZE (10)
/* some externals */
extern uint8_t pa_table[]; ///< PATABLE with available output powers
@ -23,22 +16,17 @@ extern uint8_t pa_table_index; ///< Current PATABLE Index
/* global variables */
rx_buffer_t cc1100_rx_buffer[RX_BUF_SIZE]; ///< RX buffer
cc1100_statistic_t cc1100_statistic;
volatile cc1100_flags rflags; ///< Radio control flags
volatile uint8_t radio_state = RADIO_UNKNOWN; ///< Radio state
static volatile uint8_t rx_buffer_next; ///< Next packet in RX queue
static uint8_t radio_address; ///< Radio address
static uint8_t radio_channel; ///< Radio channel
static int transceiver_pid; ///< the transceiver thread pid
int transceiver_pid; ///< the transceiver thread pid
/* internal function prototypes */
static uint8_t receive_packet_variable(uint8_t *rxBuffer, uint8_t length);
static uint8_t receive_packet(uint8_t *rxBuffer, uint8_t length);
static int rd_set_mode(int mode);
static void reset(void);
static void power_up_reset(void);
@ -100,84 +88,15 @@ void cc1100_gdo2_irq(void) {
cc1100_rx_handler();
}
void cc1100_rx_handler(void) {
uint8_t res = 0;
// Possible packet received, RX -> IDLE (0.1 us)
rflags.CAA = 0;
rflags.MAN_WOR = 0;
cc1100_statistic.packets_in++;
res = receive_packet((uint8_t*)&(cc1100_rx_buffer[rx_buffer_next].packet), sizeof(cc1100_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)
{
cc1100_statistic.packets_in_while_tx++;
return;
}
cc1100_rx_buffer[rx_buffer_next].rssi = rflags.RSSI;
cc1100_rx_buffer[rx_buffer_next].lqi = rflags.LQI;
// 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).
cc1100_spi_write_reg(CC1100_MCSM0, 0x08); // Turn off FS-Autocal
cc1100_spi_write_reg(CC1100_MCSM2, 0x07); // Configure RX_TIME (until end of packet)
cc1100_spi_strobe(CC1100_SRX);
hwtimer_wait(IDLE_TO_RX_TIME);
radio_state = RADIO_RX;
/* notify transceiver thread if any */
if (transceiver_pid) {
msg 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) {
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
cc1100_spi_strobe(CC1100_SIDLE); // Switch to IDLE (should already be)...
cc1100_spi_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)
{
cc1100_spi_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)
{
cc1100_statistic.packets_in_while_tx++;
return;
}
// No valid packet, so go back to RX/WOR as soon as possible
cc1100_switch_to_rx();
}
}
uint8_t cc1100_get_buffer_pos(void) {
return (rx_buffer_next-1);
}
uint8_t cc1100_set_address(radio_address_t address) {
radio_address_t cc1100_get_address() {
return radio_address;
}
radio_address_t cc1100_set_address(radio_address_t address) {
if ((address < MIN_UID) || (address > MAX_UID)) {
return 0;
}
@ -188,7 +107,7 @@ uint8_t cc1100_set_address(radio_address_t address) {
}
radio_address = id;
return 0;
return radio_address;
}
void cc1100_setup_rx_mode(void) {
@ -277,7 +196,6 @@ char* cc1100_state_to_text(uint8_t state) {
void cc1100_print_config(void) {
char buf[8];
printf("Current radio state: %s\r\n", cc1100_state_to_text(radio_state));
printf("Current MARC state: %s\r\n", cc1100_get_marc_state());
printf("Current channel number: %u\r\n", radio_channel);
@ -289,9 +207,10 @@ void switch_to_pwd(void) {
radio_state = RADIO_PWD;
}
uint8_t cc1100_set_channel(uint8_t channr) {
/*---------------------------------------------------------------------------*/
int16_t cc1100_set_channel(uint8_t channr) {
uint8_t state = cc1100_spi_read_status(CC1100_MARCSTATE) & MARC_STATE;
if (state != 1) && ((channr > MAX_CHANNR)) {
if ((state != 1) && (channr > MAX_CHANNR)) {
return 0;
}
write_register(CC1100_CHANNR, channr*10);
@ -299,72 +218,10 @@ uint8_t cc1100_set_channel(uint8_t channr) {
return radio_channel;
}
uint8_t cc1100_get_channel(void) {
int16_t cc1100_get_channel(void) {
return radio_channel;
}
/*---------------------------------------------------------------------------*/
/* Internal functions */
/*---------------------------------------------------------------------------*/
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 ((cc1100_spi_read_status(CC1100_RXBYTES) & BYTES_IN_RXFIFO)) {
LED_GREEN_TOGGLE;
// Read length byte (first byte in RX FIFO)
packetLength = cc1100_spi_read_reg(CC1100_RXFIFO);
// 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
cc1100_spi_readburst_reg(CC1100_RXFIFO, (char*)rxBuffer+1, packetLength);
// Read the 2 appended status bytes (status[0] = RSSI, status[1] = LQI)
cc1100_spi_readburst_reg(CC1100_RXFIFO, (char*)status, 2);
// Store RSSI value of packet
rflags.RSSI = status[I_RSSI];
// MSB of LQI is the CRC_OK bit
rflags.CRC = (status[I_LQI] & CRC_OK) >> 7;
if (!rflags.CRC) {
cc1100_statistic.packets_in_crc_fail++;
}
// Bit 0-6 of LQI indicates the link quality (LQI)
rflags.LQI = status[I_LQI] & LQI_EST;
return rflags.CRC;
}
/* too many bytes in FIFO */
else {
// RX FIFO get automatically flushed if return value is false
return 0;
}
}
/* no bytes in RX FIFO */
else {
LED_RED_TOGGLE;
// 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 = cc1100_spi_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;
}
/*---------------------------------------------------------------------------*/
// CC1100 reset functionality

View File

@ -6,6 +6,8 @@
#include <stdint.h>
#include <cc1100-config.h>
#define RX_BUF_SIZE (10)
#define CC1100_MAX_DATA_LENGTH (58)
#define CC1100_BROADCAST_ADDRESS (0x00) ///< CC1100 broadcast address
@ -19,6 +21,9 @@
#define MIN_OUTPUT_POWER (0) ///< Minimum output power value
#define MAX_OUTPUT_POWER (11) ///< Maximum output power value
#define PACKET_LENGTH (0x3E) ///< Packet length = 62 Bytes.
#define CC1100_SYNC_WORD_TX_TIME (90000) // loop count (max. timeout ~ 15 ms) to wait for
// sync word to be transmitted (GDO2 from low to high)
/**
* @name Defines used as state values for state machine
* @{
@ -83,10 +88,19 @@ enum radio_mode {
extern rx_buffer_t cc1100_rx_buffer[];
extern volatile uint8_t rx_buffer_next; ///< Next packet in RX queue
extern volatile uint8_t radio_state; ///< Radio state
extern cc1100_statistic_t cc1100_statistic;
int transceiver_pid; ///< the transceiver thread pid
void cc1100_init(int transceiver_pid);
void cc1100_rx_handler(void);
uint8_t cc1100_send(cc1100_packet_t *pkt);
uint8_t cc1100_get_buffer_pos(void);
void cc1100_setup_rx_mode(void);
@ -95,8 +109,11 @@ void cc1100_wakeup_from_rx(void);
void cc1100_switch_to_pwd(void);
void cc1100_disable_interrupts(void);
uint8_t cc1100_set_channel(uint8_t channr);
uint8_t cc1100_get_channel(void);
int16_t cc1100_set_channel(uint8_t channr);
int16_t cc1100_get_channel(void);
radio_address_t cc1100_set_address(radio_address_t addr);
radio_address_t cc1100_get_address(void);
void cc1100_print_config(void);
#endif

View File

@ -12,12 +12,12 @@
#define RADIO_STACK_SIZE (4096)
int transceiver_pid;
int radio_pid;
char shell_stack_buffer[SHELL_STACK_SIZE];
char radio_stack_buffer[RADIO_STACK_SIZE];
void trans_chan(char *chan);
void trans_register(char *unused);
void trans_addr(char *addr);
void trans_send(char *mesg);
msg mesg;
transceiver_command_t tcmd;
@ -25,28 +25,58 @@ transceiver_command_t tcmd;
shell_t shell;
const shell_command_t sc[] = {
{"tchan", "Set the channel for cc1100", trans_chan},
{"treg", "Register application for CC1100", trans_register},
{"taddr", "Set the address for cc1100", trans_addr},
{"tsnd", "Sends a CC1100 packet", trans_send},
{NULL, NULL, NULL}};
void trans_chan(char *chan) {
unsigned int c;
int c;
tcmd.transceivers = TRANSCEIVER_CC1100;
tcmd.data = &c;
mesg.content.ptr = (char*) &tcmd;
if (sscanf(chan, "tchan %u", &c)) {
printf("Trying to set channel %u\n", c);
if (sscanf(chan, "tchan %i", &c) > 0) {
printf("Trying to set channel %i\n", c);
mesg.type = SET_CHANNEL;
}
else {
mesg.type = GET_CHANNEL;
}
msg_send_receive(&mesg, &mesg, transceiver_pid);
printf("Got channel: %hu\n", c);
printf("Got channel: %i\n", c);
}
void trans_register(char *unused) {
transceiver_register(TRANSCEIVER_CC1100, radio_pid);
void trans_addr(char *addr) {
int a;
tcmd.transceivers = TRANSCEIVER_CC1100;
tcmd.data = &a;
mesg.content.ptr = (char*) &tcmd;
if (sscanf(addr, "taddr %i", &a) > 0) {
printf("Trying to set address %i\n", a);
mesg.type = SET_ADDRESS;
}
else {
mesg.type = GET_ADDRESS;
}
msg_send_receive(&mesg, &mesg, transceiver_pid);
printf("Got address: %i\n", a);
}
void trans_send(char *text) {
radio_packet_t p;
uint32_t response;
tcmd.transceivers = TRANSCEIVER_CC1100;
tcmd.data = &p;
p.length = 10;
p.dst = 5;
mesg.type = SND_PKT;
mesg.content.ptr = (char*) &tcmd;
msg_send_receive(&mesg, &mesg, transceiver_pid);
response = mesg.content.value;
printf("Packet send: %lu\n", response);
}
void shell_runner(void) {
@ -65,12 +95,12 @@ void radio(void) {
}
int main(void) {
thread_create(shell_stack_buffer, SHELL_STACK_SIZE, PRIORITY_MAIN-1, CREATE_STACKTEST, shell_runner, "shell");
int radio_pid;
thread_create(shell_stack_buffer, SHELL_STACK_SIZE, PRIORITY_MAIN-1, CREATE_STACKTEST, shell_runner, "shell");
radio_pid = thread_create(radio_stack_buffer, RADIO_STACK_SIZE, PRIORITY_MAIN-2, CREATE_STACKTEST, radio, "radio");
transceiver_init(TRANSCEIVER_CC1100);
transceiver_pid = transceiver_start();
extern void cc1100_set_channel(uint8_t c);
cc1100_set_channel(6);
transceiver_init(TRANSCEIVER_CC1100);
transceiver_pid = transceiver_start();
transceiver_register(TRANSCEIVER_CC1100, radio_pid);
while (1) {
// LED_GREEN_TOGGLE;

View File

@ -27,6 +27,8 @@ enum transceiver_msg_type_t {
POWERDOWN, ///< power down transceiver
GET_CHANNEL, ///< Get current channel
SET_CHANNEL, ///< Set a new channel
GET_ADDRESS, ///< Get the radio address
SET_ADDRESS, ///< Set the radio address
/* Error messages */
ENOBUFFER,

View File

@ -6,6 +6,7 @@
#include <msg.h>
#include <transceiver.h>
#include <radio/types.h>
#define PAYLOAD_SIZE (0)
@ -21,29 +22,38 @@
#define ENABLE_DEBUG (1)
#include <debug.h>
/*------------------------------------------------------------------------------------*/
/* used transceiver types */
transceiver_type_t transceivers = TRANSCEIVER_NONE;
/* registered upper layer threads */
registered_t reg[TRANSCEIVER_MAX_REGISTERED];
/* packet buffers */
radio_packet_t transceiver_buffer[TRANSCEIVER_BUFFER_SIZE];
uint8_t data_buffer[TRANSCEIVER_BUFFER_SIZE * PAYLOAD_SIZE];
uint32_t response; ///< response bytes for messages to upper layer threads
static volatile uint8_t rx_buffer_pos = 0;
static volatile uint8_t transceiver_buffer_pos = 0;
/* transceiver stack */
char transceiver_stack[TRANSCEIVER_STACK_SIZE];
/*------------------------------------------------------------------------------------*/
/* function prototypes */
static void run(void);
static void receive_packet(uint16_t type, uint8_t pos);
static void receive_cc1100_packet(radio_packet_t *trans_p);
static uint8_t send_packet(transceiver_type_t t, void *pkt);
static uint8_t get_channel(transceiver_type_t t);
static uint8_t set_channel(transceiver_type_t t, void *channel);
static int16_t get_channel(transceiver_type_t t);
static int16_t set_channel(transceiver_type_t t, void *channel);
static int16_t get_address(transceiver_type_t t);
static int16_t set_address(transceiver_type_t t, void *address);
/*------------------------------------------------------------------------------------*/
/* Transceiver init */
void transceiver_init(transceiver_type_t t) {
uint8_t i;
for (i = 0; i < TRANSCEIVER_MAX_REGISTERED; i++) {
@ -58,6 +68,7 @@ void transceiver_init(transceiver_type_t t) {
}
}
/* Start the transceiver thread */
int transceiver_start(void) {
int pid = thread_create(transceiver_stack, TRANSCEIVER_STACK_SIZE, PRIORITY_MAIN-3, CREATE_STACKTEST, run, "Transceiver");
if (pid < 0) {
@ -70,6 +81,7 @@ int transceiver_start(void) {
return pid;
}
/* Register an upper layer thread */
uint8_t transceiver_register(transceiver_type_t t, int pid) {
uint8_t i;
for (i = 0; ((reg[i].pid != pid) &&
@ -90,12 +102,19 @@ uint8_t transceiver_register(transceiver_type_t t, int pid) {
/*------------------------------------------------------------------------------------*/
/* Internal functions */
/*------------------------------------------------------------------------------------*/
/*
* @brief The main thread run, receiving and processing messages in an infinite
* loop
*/
void run(void) {
msg m;
transceiver_command_t *cmd;
while (1) {
msg_receive(&m);
/* only makes sense for messages for upper layers */
cmd = (transceiver_command_t*) m.content.ptr;
DEBUG("Transceiver: Message received\n");
switch (m.type) {
case RCV_PKT_CC1020:
@ -103,17 +122,24 @@ void run(void) {
receive_packet(m.type, m.content.value);
break;
case SND_PKT:
cmd = (transceiver_command_t*) m.content.ptr;
send_packet(cmd->transceivers, cmd->data);
response = send_packet(cmd->transceivers, cmd->data);
m.content.value = response;
msg_reply(&m, &m);
break;
case GET_CHANNEL:
cmd = (transceiver_command_t*) m.content.ptr;
*((uint8_t*) cmd->data) = get_channel(cmd->transceivers);
*((int16_t*) cmd->data) = get_channel(cmd->transceivers);
msg_reply(&m, &m);
break;
case SET_CHANNEL:
cmd = (transceiver_command_t*) m.content.ptr;
*((uint8_t*) cmd->data) = set_channel(cmd->transceivers, cmd->data);
*((int16_t*) cmd->data) = set_channel(cmd->transceivers, cmd->data);
msg_reply(&m, &m);
break;
case GET_ADDRESS:
*((int16_t*) cmd->data) = get_address(cmd->transceivers);
msg_reply(&m, &m);
break;
case SET_ADDRESS:
*((int16_t*) cmd->data) = set_address(cmd->transceivers, cmd->data);
msg_reply(&m, &m);
break;
default:
@ -123,7 +149,14 @@ void run(void) {
}
}
/*------------------------------------------------------------------------------------*/
/*
* @brief Processes a packet received by any transceiver device
*
* @param type The message type to determine which device has received the
* packet
* @param pos The current device driver's buffer position
*/
static void receive_packet(uint16_t type, uint8_t pos) {
uint8_t i = 0;
transceiver_type_t t;
@ -181,6 +214,11 @@ static void receive_packet(uint16_t type, uint8_t pos) {
}
}
/*
* @brief process packets from CC1100
*
* @param trans_p The current entry in the transceiver buffer
*/
static void receive_cc1100_packet(radio_packet_t *trans_p) {
DEBUG("Handling CC1100 packet\n");
/* disable interrupts while copying packet */
@ -199,13 +237,47 @@ static void receive_cc1100_packet(radio_packet_t *trans_p) {
trans_p->data = (uint8_t*) &(data_buffer[transceiver_buffer_pos * CC1100_MAX_DATA_LENGTH]);
}
/*------------------------------------------------------------------------------------*/
/*
* @brief Sends a radio packet to the receiver
*
* @param t The transceiver device
* @param pkt Generic pointer to the packet
*
* @return 1 on success, 0 otherwise
*/
static uint8_t send_packet(transceiver_type_t t, void *pkt) {
uint8_t res = 0;
radio_packet_t p = *((radio_packet_t*) pkt);
cc1100_packet_t cc1100_pkt;
switch (t) {
case TRANSCEIVER_CC1100:
/* TODO: prepare and send packet here */
cc1100_pkt.length = p.length;
cc1100_pkt.address = p.dst;
cc1100_pkt.flags = 0;
memcpy(cc1100_pkt.data, p.data, p.length);
res = cc1100_send(&cc1100_pkt);
break;
default:
puts("Unknown transceiver");
break;
}
return res;
}
static uint8_t set_channel(transceiver_type_t t, void *channel) {
/*------------------------------------------------------------------------------------*/
/*
* @brief Sets the radio channel for any transceiver device
*
* @param t The transceiver device
* @param channel The channel to be set
*
* @return The radio channel AFTER calling the set command, -1 on error
*/
static int16_t set_channel(transceiver_type_t t, void *channel) {
uint8_t c = *((uint8_t*) channel);
switch (t) {
case TRANSCEIVER_CC1100:
@ -215,7 +287,14 @@ static uint8_t set_channel(transceiver_type_t t, void *channel) {
}
}
static uint8_t get_channel(transceiver_type_t t) {
/*
* @brief Get the radio channel of any transceiver device
*
* @param t The transceiver device
*
* @return The current radio channel of the transceiver, -1 on error
*/
static int16_t get_channel(transceiver_type_t t) {
switch (t) {
case TRANSCEIVER_CC1100:
return cc1100_get_channel();
@ -223,3 +302,37 @@ static uint8_t get_channel(transceiver_type_t t) {
return -1;
}
}
/*------------------------------------------------------------------------------------*/
/*
* @brief Get the current address of transceiver device
*
* @param t The transciever device
*
* @return The configured address of the device, -1 on error
*/
static int16_t get_address(transceiver_type_t t) {
switch (t) {
case TRANSCEIVER_CC1100:
return cc1100_get_address();
default:
return -1;
}
}
/*
* @brief Set the address of the transceiver device
*
* @param t The transceiver device
* @param address Generic pointer to the address to set
*
* @return The new radio address of the device
*/
static int16_t set_address(transceiver_type_t t, void *address) {
radio_address_t addr = *((radio_address_t*) address);
switch (t) {
case TRANSCEIVER_CC1100:
return cc1100_set_address(addr);
default:
return -1;
}
}