1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/drivers/cc2420/cc2420_tx.c
2014-02-24 16:15:19 +01:00

125 lines
3.6 KiB
C

/**
* cc2420_rx.c - Implementation of transmitting cc2420 functions.
* Copyright (C) 2013 Milan Babel <babel@inf.fu-berlin.de>
*
* This source code is licensed under the GNU Lesser General Public License,
* Version 2. See the file LICENSE for more details.
*/
#include <stdio.h>
#include "cc2420.h"
#include "cc2420_spi.h"
#include "cc2420_settings.h"
#include "cc2420_arch.h"
#include "ieee802154_frame.h"
#include "irq.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
static void cc2420_gen_pkt(uint8_t *buf, cc2420_packet_t *packet);
static uint8_t sequenz_nr;
int16_t cc2420_send(cc2420_packet_t *packet)
{
volatile uint32_t abort_count = 0;
/* Set missing frame information */
packet->frame.fcf.frame_ver = 0;
if (packet->frame.src_pan_id == packet->frame.dest_pan_id) {
packet->frame.fcf.panid_comp = 1;
}
else {
packet->frame.fcf.panid_comp = 0;
}
if (packet->frame.fcf.src_addr_m == 2) {
packet->frame.src_addr[0] = (uint8_t)(cc2420_get_address() >> 8);
packet->frame.src_addr[1] = (uint8_t)(cc2420_get_address() & 0xFF);
}
else if (packet->frame.fcf.src_addr_m == 3) {
packet->frame.src_addr[0] = (uint8_t)(cc2420_get_address_long() >> 56);
packet->frame.src_addr[1] = (uint8_t)(cc2420_get_address_long() >> 48);
packet->frame.src_addr[2] = (uint8_t)(cc2420_get_address_long() >> 40);
packet->frame.src_addr[3] = (uint8_t)(cc2420_get_address_long() >> 32);
packet->frame.src_addr[4] = (uint8_t)(cc2420_get_address_long() >> 24);
packet->frame.src_addr[5] = (uint8_t)(cc2420_get_address_long() >> 16);
packet->frame.src_addr[6] = (uint8_t)(cc2420_get_address_long() >> 8);
packet->frame.src_addr[7] = (uint8_t)(cc2420_get_address_long() & 0xFF);
}
packet->frame.src_pan_id = cc2420_get_pan();
packet->frame.seq_nr = sequenz_nr;
sequenz_nr += 1;
/* calculate size of the package (header + payload + fcs) */
packet->length = ieee802154_frame_get_hdr_len(&packet->frame) +
packet->frame.payload_len + 2;
if (packet->length > CC2420_MAX_PKT_LENGTH) {
return -1;
}
/* FCS is added in hardware */
uint8_t pkt[packet->length - 2];
/* generate pkt */
cc2420_gen_pkt(pkt, packet);
/* idle & flush tx */
cc2420_strobe(CC2420_STROBE_RFOFF);
cc2420_strobe(CC2420_STROBE_FLUSHTX);
/* write length and packet to fifo */
cc2420_write_fifo(&packet->length, 1);
cc2420_write_fifo(pkt, packet->length - 2);
unsigned int cpsr = disableIRQ();
cc2420_strobe(CC2420_STROBE_TXON);
// Wait for SFD to be set -> sync word transmitted
while (cc2420_get_sfd() == 0) {
abort_count++;
if (abort_count > CC2420_SYNC_WORD_TX_TIME) {
// Abort waiting. CC2420 maybe in wrong mode
// e.g. sending preambles for always
puts("[CC2420 TX] fatal error\n");
/* TODO: error handling */
packet->length = 0;
break;
}
}
DEBUG("SEQ: %u\n", packet->frame.seq_nr);
restoreIRQ(cpsr);
/* wait for packet to be send */
while (cc2420_get_sfd() != 0);
cc2420_switch_to_rx();
return packet->length;
}
/**
* @brief Static function to generate byte array from cc2420 packet.
*
*/
static void cc2420_gen_pkt(uint8_t *buf, cc2420_packet_t *packet)
{
uint8_t index, offset;
index = ieee802154_frame_init(&packet->frame, buf);
offset = index;
while (index < packet->length - 2) {
buf[index] = packet->frame.payload[index - offset];
index += 1;
}
}