/*
 * Copyright (c) 2007, Swedish Institute of Computer Science
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the Institute nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *
 * $Id: rf230bb.c,v 1.1 2009/07/08 16:17:07 dak664 Exp $
*/

/**
 *  \brief This module contains radio driver code for the Atmel
 *  AT86RF230. It is modified to use the contiki core MAC layer.
 *
 *  \author Blake Leverett <bleverett@gmail.com>
 *          Mike Vidales <mavida404@gmail.com>
 *          Eric Gnoske <egnoske@gmail.com>
 *          David Kopf <dak664@embarqmail.com>
 *
*/

/**  \addtogroup wireless
 * @{
 */

/**
 *  \defgroup radiorf230 RF230 interface
 * @{
 */
/**
 *  \file
 *  This file contains "barebones" radio driver code for use with the
 *  contiki core MAC layer.
 *
 */


#include <stdio.h>
#include <string.h>

#include "contiki.h"

//#if defined(__AVR__)
#include <avr/io.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
//#elif defined(__MSP430__)
//#include <io.h>
//#endif

#include "dev/leds.h"
#include "dev/spi.h"
#include "rf230bb.h"
#include "hal.h"
//#include "frame.h"
#include "radio.h"

#include "net/rime/packetbuf.h"
#include "net/rime/rimestats.h"

#include "sys/timetable.h"

#define WITH_SEND_CCA 0


#if RF230_CONF_TIMESTAMPS
#include "net/rime/timesynch.h"
#define TIMESTAMP_LEN 3
#else /* RF230_CONF_TIMESTAMPS */
#define TIMESTAMP_LEN 0
#endif /* RF230_CONF_TIMESTAMPS */
#define FOOTER_LEN 2

#ifndef RF230_CONF_CHECKSUM
#define RF230_CONF_CHECKSUM 0
#endif /* RF230_CONF_CHECKSUM */

#if RF230_CONF_CHECKSUM
#include "lib/crc16.h"
#define CHECKSUM_LEN 2
#else
#define CHECKSUM_LEN 0
#endif /* RF230_CONF_CHECKSUM */

#define AUX_LEN (CHECKSUM_LEN + TIMESTAMP_LEN + FOOTER_LEN)

struct timestamp {
  uint16_t time;
  uint8_t authority_level;
};


#define FOOTER1_CRC_OK      0x80
#define FOOTER1_CORRELATION 0x7f

#define DEBUG 0
#if DEBUG
#define PRINTF(FORMAT,args...) printf_P(PSTR(FORMAT),##args)
#else
#define PRINTF(...) do {} while (0)
#endif

/* XXX hack: these will be made as Chameleon packet attributes */
rtimer_clock_t rf230_time_of_arrival, rf230_time_of_departure;

int rf230_authority_level_of_sender;

#if RF230_CONF_TIMESTAMPS
static rtimer_clock_t setup_time_for_transmission;
static unsigned long total_time_for_transmission, total_transmission_len;
static int num_transmissions;
#endif /* RF230_CONF_TIMESTAMPS */

/* RF230 hardware delay times, from datasheet */
typedef enum{
    TIME_TO_ENTER_P_ON               = 510, /**<  Transition time from VCC is applied to P_ON. */
    TIME_P_ON_TO_TRX_OFF             = 510, /**<  Transition time from P_ON to TRX_OFF. */
    TIME_SLEEP_TO_TRX_OFF            = 880, /**<  Transition time from SLEEP to TRX_OFF. */
    TIME_RESET                       = 6,   /**<  Time to hold the RST pin low during reset */
    TIME_ED_MEASUREMENT              = 140, /**<  Time it takes to do a ED measurement. */
    TIME_CCA                         = 140, /**<  Time it takes to do a CCA. */
    TIME_PLL_LOCK                    = 150, /**<  Maximum time it should take for the PLL to lock. */
    TIME_FTN_TUNING                  = 25,  /**<  Maximum time it should take to do the filter tuning. */
    TIME_NOCLK_TO_WAKE               = 6,   /**<  Transition time from *_NOCLK to being awake. */
    TIME_CMD_FORCE_TRX_OFF           = 1,   /**<  Time it takes to execute the FORCE_TRX_OFF command. */
    TIME_TRX_OFF_TO_PLL_ACTIVE       = 180, /**<  Transition time from TRX_OFF to: RX_ON, PLL_ON, TX_ARET_ON and RX_AACK_ON. */
    TIME_STATE_TRANSITION_PLL_ACTIVE = 1,   /**<  Transition time from PLL active state to another. */
}radio_trx_timing_t;

/*---------------------------------------------------------------------------*/
PROCESS(rf230_process, "RF230 receiver");
/*---------------------------------------------------------------------------*/

int rf230_send(const void *data, unsigned short len);
int rf230_read(void *buf, unsigned short bufsize);
void rf230_set_receiver(void (* recv)(const struct radio_driver *d));
int rf230_on(void);
int rf230_off(void);

const struct radio_driver rf230_driver =
  {
    rf230_send,
    rf230_read,
    rf230_set_receiver,
    rf230_on,
    rf230_off,
  };

static void (* receiver_callback)(const struct radio_driver *);

//signed char rf230_last_rssi;
//uint8_t rf230_last_correlation;

static uint8_t receive_on;
//static uint8_t rssi_val;
uint8_t rx_mode;
/* Radio stuff in network byte order. */
//static uint16_t pan_id;

//static int channel;


/*----------------------------------------------------------------------------*/
/** \brief  This function return the Radio Transceivers current state.
 *
 *  \retval     P_ON               When the external supply voltage (VDD) is
 *                                 first supplied to the transceiver IC, the
 *                                 system is in the P_ON (Poweron) mode.
 *  \retval     BUSY_RX            The radio transceiver is busy receiving a
 *                                 frame.
 *  \retval     BUSY_TX            The radio transceiver is busy transmitting a
 *                                 frame.
 *  \retval     RX_ON              The RX_ON mode enables the analog and digital
 *                                 receiver blocks and the PLL frequency
 *                                 synthesizer.
 *  \retval     TRX_OFF            In this mode, the SPI module and crystal
 *                                 oscillator are active.
 *  \retval     PLL_ON             Entering the PLL_ON mode from TRX_OFF will
 *                                 first enable the analog voltage regulator. The
 *                                 transceiver is ready to transmit a frame.
 *  \retval     BUSY_RX_AACK       The radio was in RX_AACK_ON mode and received
 *                                 the Start of Frame Delimiter (SFD). State
 *                                 transition to BUSY_RX_AACK is done if the SFD
 *                                 is valid.
 *  \retval     BUSY_TX_ARET       The radio transceiver is busy handling the
 *                                 auto retry mechanism.
 *  \retval     RX_AACK_ON         The auto acknowledge mode of the radio is
 *                                 enabled and it is waiting for an incomming
 *                                 frame.
 *  \retval     TX_ARET_ON         The auto retry mechanism is enabled and the
 *                                 radio transceiver is waiting for the user to
 *                                 send the TX_START command.
 *  \retval     RX_ON_NOCLK        The radio transceiver is listening for
 *                                 incomming frames, but the CLKM is disabled so
 *                                 that the controller could be sleeping.
 *                                 However, this is only true if the controller
 *                                 is run from the clock output of the radio.
 *  \retval     RX_AACK_ON_NOCLK   Same as the RX_ON_NOCLK state, but with the
 *                                 auto acknowledge module turned on.
 *  \retval     BUSY_RX_AACK_NOCLK Same as BUSY_RX_AACK, but the controller
 *                                 could be sleeping since the CLKM pin is
 *                                 disabled.
 *  \retval     STATE_TRANSITION   The radio transceiver's state machine is in
 *                                 transition between two states.
 */
uint8_t
radio_get_trx_state(void)
{
    return hal_subregister_read(SR_TRX_STATUS);
}

/*----------------------------------------------------------------------------*/
/** \brief  This function checks if the radio transceiver is sleeping.
 *
 *  \retval     true    The radio transceiver is in SLEEP or one of the *_NOCLK
 *                      states.
 *  \retval     false   The radio transceiver is not sleeping.
 */
bool radio_is_sleeping(void)
{
    bool sleeping = false;

    /* The radio transceiver will be at SLEEP or one of the *_NOCLK states only if */
    /* the SLP_TR pin is high. */
    if (hal_get_slptr() != 0){
        sleeping = true;
    }

    return sleeping;
}

/*----------------------------------------------------------------------------*/
/** \brief  This function will reset the state machine (to TRX_OFF) from any of
 *          its states, except for the SLEEP state.
 */
void
radio_reset_state_machine(void)
{
    hal_set_slptr_low();
    delay_us(TIME_NOCLK_TO_WAKE);
    hal_subregister_write(SR_TRX_CMD, CMD_FORCE_TRX_OFF);
    delay_us(TIME_CMD_FORCE_TRX_OFF);
}
/*----------------------------------------------------------------------------*/
/** \brief  This function will change the current state of the radio
 *          transceiver's internal state machine.
 *
 *  \param     new_state        Here is a list of possible states:
 *             - RX_ON        Requested transition to RX_ON state.
 *             - TRX_OFF      Requested transition to TRX_OFF state.
 *             - PLL_ON       Requested transition to PLL_ON state.
 *             - RX_AACK_ON   Requested transition to RX_AACK_ON state.
 *             - TX_ARET_ON   Requested transition to TX_ARET_ON state.
 *
 *  \retval    RADIO_SUCCESS          Requested state transition completed
 *                                  successfully.
 *  \retval    RADIO_INVALID_ARGUMENT Supplied function parameter out of bounds.
 *  \retval    RADIO_WRONG_STATE      Illegal state to do transition from.
 *  \retval    RADIO_BUSY_STATE       The radio transceiver is busy.
 *  \retval    RADIO_TIMED_OUT        The state transition could not be completed
 *                                  within resonable time.
 */
radio_status_t
radio_set_trx_state(uint8_t new_state)
{
    uint8_t original_state;

    /*Check function paramter and current state of the radio transceiver.*/
    if (!((new_state == TRX_OFF)    ||
          (new_state == RX_ON)      ||
          (new_state == PLL_ON)     ||
          (new_state == RX_AACK_ON) ||
          (new_state == TX_ARET_ON))){
        return RADIO_INVALID_ARGUMENT;
    }

    if (radio_is_sleeping() == true){
        return RADIO_WRONG_STATE;
    }

    // Wait for radio to finish previous operation
    for(;;)
    {
        original_state = radio_get_trx_state();
        if (original_state != BUSY_TX_ARET &&
            original_state != BUSY_RX_AACK &&
            original_state != BUSY_RX && 
            original_state != BUSY_TX)
            break;
    }

    if (new_state == original_state){
        return RADIO_SUCCESS;
    }


    /* At this point it is clear that the requested new_state is: */
    /* TRX_OFF, RX_ON, PLL_ON, RX_AACK_ON or TX_ARET_ON. */

    /* The radio transceiver can be in one of the following states: */
    /* TRX_OFF, RX_ON, PLL_ON, RX_AACK_ON, TX_ARET_ON. */
    if(new_state == TRX_OFF){
        radio_reset_state_machine(); /* Go to TRX_OFF from any state. */
    } else {
        /* It is not allowed to go from RX_AACK_ON or TX_AACK_ON and directly to */
        /* TX_AACK_ON or RX_AACK_ON respectively. Need to go via RX_ON or PLL_ON. */
        if ((new_state == TX_ARET_ON) &&
            (original_state == RX_AACK_ON)){
            /* First do intermediate state transition to PLL_ON, then to TX_ARET_ON. */
            /* The final state transition to TX_ARET_ON is handled after the if-else if. */
            hal_subregister_write(SR_TRX_CMD, PLL_ON);
            delay_us(TIME_STATE_TRANSITION_PLL_ACTIVE);
        } else if ((new_state == RX_AACK_ON) &&
                 (original_state == TX_ARET_ON)){
            /* First do intermediate state transition to RX_ON, then to RX_AACK_ON. */
            /* The final state transition to RX_AACK_ON is handled after the if-else if. */
            hal_subregister_write(SR_TRX_CMD, RX_ON);
            delay_us(TIME_STATE_TRANSITION_PLL_ACTIVE);
        }

        /* Any other state transition can be done directly. */
        hal_subregister_write(SR_TRX_CMD, new_state);

        /* When the PLL is active most states can be reached in 1us. However, from */
        /* TRX_OFF the PLL needs time to activate. */
        if (original_state == TRX_OFF){
            delay_us(TIME_TRX_OFF_TO_PLL_ACTIVE);
        } else {
            delay_us(TIME_STATE_TRANSITION_PLL_ACTIVE);
        }
    } /*  end: if(new_state == TRX_OFF) ... */

    /*Verify state transition.*/
    radio_status_t set_state_status = RADIO_TIMED_OUT;

    if (radio_get_trx_state() == new_state){
        set_state_status = RADIO_SUCCESS;
        /*  set rx_mode flag based on mode we're changing to */
        if (new_state == RX_ON ||
            new_state == RX_AACK_ON){
            rx_mode = true;
        } else {
            rx_mode = false;
    }
    }

    return set_state_status;
}

/*---------------------------------------------------------------------------*/
void
rf230_waitidle(void)
{
//	PRINTF("rf230_waitidle");
	uint8_t radio_state;

    for(;;)
    {
        radio_state = hal_subregister_read(SR_TRX_STATUS);
        if (radio_state != BUSY_TX_ARET &&
            radio_state != BUSY_RX_AACK &&
            radio_state != BUSY_RX && 
            radio_state != BUSY_TX)
            break;
       PRINTF(".");
    }
}

/*---------------------------------------------------------------------------*/
static uint8_t locked, lock_on, lock_off;

static void
on(void)
{
  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
  PRINTF("rf230 internal on\n");
  receive_on = 1;

  hal_set_slptr_low();
//radio_is_waking=1;//can test this before tx instead of delaying
  delay_us(TIME_SLEEP_TO_TRX_OFF);
  delay_us(TIME_SLEEP_TO_TRX_OFF);//extra delay for now

    radio_set_trx_state(RX_AACK_ON);
// flushrx();
}
static void
off(void)
{
  PRINTF("rf230 internal off\n");
  receive_on = 0;
  
  /* Wait for transmission to end before turning radio off. */
  rf230_waitidle(); 

  /* Force the device into TRX_OFF. */   
  radio_reset_state_machine();
   
  /* Sleep Radio */
  hal_set_slptr_high();

  ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
}
/*---------------------------------------------------------------------------*/
#define GET_LOCK() locked = 1
static void RELEASE_LOCK(void) {
  if(lock_on) {
    on();
    lock_on = 0;
  }
  if(lock_off) {
    off();
    lock_off = 0;
  }
  locked = 0;
}
/*---------------------------------------------------------------------------*/
void
rf230_set_receiver(void (* recv)(const struct radio_driver *))
{
//PRINTF("rf230_set receiver\n");
  receiver_callback = recv;
}

/*---------------------------------------------------------------------------*/
int
rf230_off(void)
{
// PRINTF("rf230_off\n");	
  /* Don't do anything if we are already turned off. */
  if(receive_on == 0) {
    return 1;
  }

  /* If we are called when the driver is locked, we indicate that the
     radio should be turned off when the lock is unlocked. */
  if(locked) {
    lock_off = 1;
    return 1;
  }
  off();

  return 1;
}
/*---------------------------------------------------------------------------*/
int
rf230_on(void)
{
//PRINTF("rf230_on\n");
  if(receive_on) {
    return 1;
  }
  if(locked) {
    lock_on = 1;
    return 1;
  }
  on();

  return 1;
}
/*---------------------------------------------------------------------------*/
int
rf230_get_channel(void)
{
    return hal_subregister_read(SR_CHANNEL);
//	return channel;
}
/*---------------------------------------------------------------------------*/
void
rf230_set_channel(int c)
{
 /* Wait for any transmission to end. */
  rf230_waitidle();
	
//channel=c;
  hal_subregister_write(SR_CHANNEL, c);

}
/*---------------------------------------------------------------------------*/
void
rf230_set_pan_addr(uint16_t pan,uint16_t addr,uint8_t *ieee_addr)
{
  PRINTF("rf230: PAN=%x Short Addr=%x\n",pan,addr);
  
  uint8_t abyte;
  abyte = pan & 0xFF;
  hal_register_write(RG_PAN_ID_0,abyte);
  abyte = (pan >> 8*1) & 0xFF;
  hal_register_write(RG_PAN_ID_1, abyte);

  abyte = addr & 0xFF;
  hal_register_write(RG_SHORT_ADDR_0, abyte);
  abyte = (addr >> 8*1) & 0xFF;
  hal_register_write(RG_SHORT_ADDR_1, abyte);  

  if (ieee_addr != NULL) {
	PRINTF("MAC=%x",*ieee_addr);
	hal_register_write(RG_IEEE_ADDR_7, *ieee_addr++);
	PRINTF(":%x",*ieee_addr);
 	hal_register_write(RG_IEEE_ADDR_6, *ieee_addr++);
 	PRINTF(":%x",*ieee_addr);
 	hal_register_write(RG_IEEE_ADDR_5, *ieee_addr++);
 	PRINTF(":%x",*ieee_addr);
    hal_register_write(RG_IEEE_ADDR_4, *ieee_addr++);
 	PRINTF(":%x",*ieee_addr);
 	hal_register_write(RG_IEEE_ADDR_3, *ieee_addr++);
 	PRINTF(":%x",*ieee_addr);
 	hal_register_write(RG_IEEE_ADDR_2, *ieee_addr++);
 	PRINTF(":%x",*ieee_addr);
 	hal_register_write(RG_IEEE_ADDR_1, *ieee_addr++);
 	PRINTF(":%x",*ieee_addr);
 	hal_register_write(RG_IEEE_ADDR_0, *ieee_addr);
 	PRINTF("\n");
  }
 
}

/*---------------------------------------------------------------------------*/
/* Process to handle input packets
 * Receive interrupts cause this process to be polled
 * It calls the core MAC layer which calls rf230_read to get the packet
*/
PROCESS_THREAD(rf230_process, ev, data)
{
  PROCESS_BEGIN();
  
  while(1) {
    PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
    
#if RF230_TIMETABLE_PROFILING
    TIMETABLE_TIMESTAMP(rf230_timetable, "poll");
#endif /* RF230_TIMETABLE_PROFILING */
        
    if(receiver_callback != NULL) {
      receiver_callback(&rf230_driver);
#if RF230_TIMETABLE_PROFILING
      TIMETABLE_TIMESTAMP(rf230_timetable, "end");
      timetable_aggregate_compute_detailed(&aggregate_time,
					   &rf230_timetable);
      timetable_clear(&rf230_timetable);
#endif /* RF230_TIMETABLE_PROFILING */
    } else {
      PRINTF("rf230_process not receiving function\n");
//    flushrx();
    }
  }

  PROCESS_END();
}
/*---------------------------------------------------------------------------*/
/*
 * This routine is called by the radio receive interrupt in hal.c
 * It just sets the poll flag for the rf230 process.
 */
#if RF230_CONF_TIMESTAMPS
static volatile rtimer_clock_t interrupt_time;
static volatile int interrupt_time_set;
#endif /* RF230_CONF_TIMESTAMPS */
#if RF230_TIMETABLE_PROFILING
#define rf230_timetable_size 16
TIMETABLE(rf230_timetable);
TIMETABLE_AGGREGATE(aggregate_time, 10);
#endif /* RF230_TIMETABLE_PROFILING */
void
rf230_interrupt(void)
{
#if RF230_CONF_TIMESTAMPS
  interrupt_time = timesynch_time();
  interrupt_time_set = 1;
#endif /* RF230_CONF_TIMESTAMPS */

  process_poll(&rf230_process);
#if RF230_TIMETABLE_PROFILING
  timetable_clear(&rf230_timetable);
  TIMETABLE_TIMESTAMP(rf230_timetable, "interrupt");
#endif /* RF230_TIMETABLE_PROFILING */
  return;
}
/* The frame is buffered to rxframe in the interrupt routine in hal.c */
  hal_rx_frame_t rxframe;
/*---------------------------------------------------------------------------*/
int
rf230_read(void *buf, unsigned short bufsize)
{

  uint8_t *framep;
 // uint8_t footer[2];
  uint8_t len;
#if RF230_CONF_CHECKSUM
  uint16_t checksum;
#endif /* RF230_CONF_CHECKSUM */
#if RF230_CONF_TIMESTAMPS
  struct timestamp t;
#endif /* RF230_CONF_TIMESTAMPS */

  PRINTF("rf230_read: %u bytes lqi %u crc %u\n",rxframe.length,rxframe.lqi,rxframe.crc);
#if DEBUG>1
  for (len=0;len<rxframe.length;len++) PRINTF(" %x",rxframe.data[len]);PRINTF("\n");
#endif
  if (rxframe.length==0) {
    return 0;
  }

#if RF230_CONF_TIMESTAMPS
bomb
  if(interrupt_time_set) {
    rf230_time_of_arrival = interrupt_time;
    interrupt_time_set = 0;
  } else {
    rf230_time_of_arrival = 0;
  }
  rf230_time_of_departure = 0;
#endif /* RF230_CONF_TIMESTAMPS */
  GET_LOCK();
//  if(rxframe.length > RF230_MAX_PACKET_LEN) {
//    // Oops, we must be out of sync.
//  flushrx();
//    RIMESTATS_ADD(badsynch);
//    RELEASE_LOCK();
//    return 0;
//  }

//hal returns two extra bytes containing the checksum
//below works because auxlen is 2
  len = rxframe.length;
  if(len <= AUX_LEN) {
 // flushrx();
    RIMESTATS_ADD(tooshort);
    RELEASE_LOCK();
    return 0;
  }
  
  if(len - AUX_LEN > bufsize) {
//  flushrx();
    RIMESTATS_ADD(toolong);
    RELEASE_LOCK();
    return 0;
  }
  /* Transfer the frame, stripping the checksum */
  framep=&(rxframe.data[0]);
  memcpy(buf,framep,len-2);
  /* Clear the length field to allow buffering of the next packet */
  rxframe.length=0;
 // framep+=len-AUX_LEN+2;


#if RF230_CONF_CHECKSUM
bomb
  memcpy(&checksum,framep,CHECKSUM_LEN);
  framep+=CHECKSUM_LEN;
#endif /* RF230_CONF_CHECKSUM */
#if RF230_CONF_TIMESTAMPS
bomb
  memcpy(&t,framep,TIMESTAMP_LEN);
  framep+=TIMESTAMP_LEN;
#endif /* RF230_CONF_TIMESTAMPS */
//  memcpy(&footer,framep,FOOTER_LEN);
 
#if RF230_CONF_CHECKSUM
bomb
  if(checksum != crc16_data(buf, len - AUX_LEN, 0)) {
    PRINTF("rf230: checksum failed 0x%04x != 0x%04x\n",
	   checksum, crc16_data(buf, len - AUX_LEN, 0));
  }
  
  if(footer[1] & FOOTER1_CRC_OK &&
     checksum == crc16_data(buf, len - AUX_LEN, 0)) {
#else
  if (rxframe.crc) {
#endif /* RF230_CONF_CHECKSUM */

/*
    packetbuf_copyfrom(parsed_frame->payload, parsed_frame->payload_length);
    packetbuf_set_datalen(parsed_frame->payload_length);
  
  	memcpy(dest_reversed, (uint8_t *)parsed_frame->dest_addr, UIP_LLADDR_LEN);
	memcpy(src_reversed, (uint8_t *)parsed_frame->src_addr, UIP_LLADDR_LEN);
  
	//Change addresses to expected byte order 
	byte_reverse((uint8_t *)dest_reversed, UIP_LLADDR_LEN);
	byte_reverse((uint8_t *)src_reversed, UIP_LLADDR_LEN);
  
	packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, (const rimeaddr_t *)dest_reversed);
	packetbuf_set_addr(PACKETBUF_ADDR_SENDER, (const rimeaddr_t *)src_reversed);

  */  
    
    packetbuf_set_attr(PACKETBUF_ATTR_RSSI, hal_subregister_read( SR_RSSI ));
    packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, rxframe.lqi);
    
    RIMESTATS_ADD(llrx);
    
#if RF230_CONF_TIMESTAMPS
bomb
    rf230_time_of_departure =
      t.time +
      setup_time_for_transmission +
      (total_time_for_transmission * (len - 2)) / total_transmission_len;
  
    rf230_authority_level_of_sender = t.authority_level;

    packetbuf_set_attr(PACKETBUF_ATTR_TIMESTAMP, t.time);
#endif /* RF230_CONF_TIMESTAMPS */
  
  } else {
	PRINTF("rf230: Bad CRC\n");
    RIMESTATS_ADD(badcrc);
    len = AUX_LEN;
  }
// if (?)
     /* Another packet has been received and needs attention. */
//    process_poll(&rf230_process);
//  }
  
  RELEASE_LOCK();
  
  if(len < AUX_LEN) {
    return 0;
  }

  return len - AUX_LEN;
}
/*---------------------------------------------------------------------------*/
void
rf230_set_txpower(uint8_t power)
{
  if (power > TX_PWR_17_2DBM){
    power=TX_PWR_17_2DBM;
  }
  if (radio_is_sleeping() ==true) {
	PRINTF("rf230_set_txpower:Sleeping");
  } else {
    hal_subregister_write(SR_TX_PWR, power);
  }

}
/*---------------------------------------------------------------------------*/
int
rf230_get_txpower(void)
{
  if (radio_is_sleeping() ==true) {
	PRINTF("rf230_get_txpower:Sleeping");
	return 0;
  } else {
    return hal_subregister_read(SR_TX_PWR);
  }
}
/*---------------------------------------------------------------------------*/
int
rf230_rssi(void)
{
  int rssi;
  int radio_was_off = 0;
  
  /*The RSSI measurement should only be done in RX_ON or BUSY_RX.*/
  if(!receive_on) {
    radio_was_off = 1;
    rf230_on();
  }

  rssi = (int)((signed char)hal_subregister_read(SR_RSSI));

  if(radio_was_off) {
    rf230_off();
  }
  return rssi;
}
/*---------------------------------------------------------------------------*/
int
rf230_send(const void *payload, unsigned short payload_len)
{
//  int i;
  uint8_t total_len,buffer[RF230_MAX_TX_FRAME_LENGTH],*pbuf;
#if RF230_CONF_TIMESTAMPS
  struct timestamp timestamp;
#endif /* RF230_CONF_TIMESTAMPS */
#if RF230_CONF_CHECKSUM
  uint16_t checksum;
#endif /* RF230_CONF_CHECKSUM */

  GET_LOCK();

  if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) {
    rf230_set_txpower(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) - 1);
  } else {
    rf230_set_txpower(TX_PWR_17_2DBM);
  }
  
  RIMESTATS_ADD(lltx);

#if RF230_CONF_CHECKSUM
  checksum = crc16_data(payload, payload_len, 0);
#endif /* RF230_CONF_CHECKSUM */
  total_len = payload_len + AUX_LEN;
  /*Check function parameters and current state.*/
  if (total_len > RF230_MAX_TX_FRAME_LENGTH){
    return -1;
  }
  pbuf=&buffer[0];
  memcpy(pbuf,payload,payload_len);
  pbuf+=payload_len;
  
#if RF230_CONF_CHECKSUM
  memcpy(pbuf,&checksum,CHECKSUM_LEN);
  pbuf+=CHECKSUM_LEN;
#endif /* RF230_CONF_CHECKSUM */

#if RF230_CONF_TIMESTAMPS
  timestamp.authority_level = timesynch_authority_level();
  timestamp.time = timesynch_time();
  memcpy(pbuf,&timestamp,TIMESTAMP_LEN);
  pbuf+=TIMESTAMP_LEN;
#endif /* RF230_CONF_TIMESTAMPS */
 
/*Below comments were for cc240 radio, don't know how they apply to rf230 - DAK */
  /* The TX FIFO can only hold one packet. Make sure to not overrun
   * FIFO by waiting for transmission to start here and synchronizing
   * with the RF230_TX_ACTIVE check in rf230_send.
   *
   * Note that we may have to wait up to 320 us (20 symbols) before
   * transmission starts.
   */
//#ifdef TMOTE_SKY
//#define LOOP_20_SYMBOLS 400	/* 326us (msp430 @ 2.4576MHz) */
//#elif __AVR__
//#define LOOP_20_SYMBOLS 500	/* XXX */
//#endif
#define LOOP_20_SYMBOLS 500
 
 /* Wait for any previous transmission to finish. */
  rf230_waitidle();

  hal_subregister_write(SR_TRX_CMD, CMD_FORCE_TRX_OFF);
  delay_us(TIME_P_ON_TO_TRX_OFF);

  radio_set_trx_state(TX_ARET_ON);	//enable auto ack
//#if WITH_SEND_CCA
//    radio_set_trx_state(TX_ARET_ON); //enable auto ack
//#endif /* WITH_SEND_CCA */

 /* Toggle the SLP_TR pin to initiate the frame transmission. */
 
  PRINTF("rf230: sending %d bytes\n", payload_len);
  hal_set_slptr_high();
  hal_set_slptr_low();
  hal_frame_write(buffer, total_len);
  
//  for(i = LOOP_20_SYMBOLS; i > 0; i--) {//dak was working with this

   if(1) {
#if RF230_CONF_TIMESTAMPS
      rtimer_clock_t txtime = timesynch_time();
#endif /* RF230_CONF_TIMESTAMPS */

      if(receive_on) {
	     ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
      }
      ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);

      /* We wait until transmission has ended so that we get an
	  accurate measurement of the transmission time.*/
      rf230_waitidle();
      radio_set_trx_state(RX_AACK_ON);//Re-enable receive mode
#if RF230_CONF_TIMESTAMPS
      setup_time_for_transmission = txtime - timestamp.time;

      if(num_transmissions < 10000) {
	    total_time_for_transmission += timesynch_time() - txtime;
	    total_transmission_len += total_len;
	    num_transmissions++;
      }
#endif /* RF230_CONF_TIMESTAMPS */

#ifdef ENERGEST_CONF_LEVELDEVICE_LEVELS
      ENERGEST_OFF_LEVEL(ENERGEST_TYPE_TRANSMIT,rf230_get_txpower());
#endif
      ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
      if(receive_on) {
	    ENERGEST_ON(ENERGEST_TYPE_LISTEN);
      }

      RELEASE_LOCK();
      return 0;
    }
//  }
  
  /* If we are using WITH_SEND_CCA, we get here if the packet wasn't
     transmitted because of other channel activity. */
  RIMESTATS_ADD(contentiondrop);
  PRINTF("rf230: do_send() transmission never started\n");
  RELEASE_LOCK();
  return -3;			/* Transmission never started! */
}/*---------------------------------------------------------------------------*/
void
rf230_init(void)
{
  /* Wait in case VCC just applied */
  delay_us(TIME_TO_ENTER_P_ON);

  /* Calibrate oscillator */
// calibrate_rc_osc_32k();

  /* Initialize Hardware Abstraction Layer. */
  hal_init();
  
  /* Do full rf230 Reset */
  hal_set_rst_low();
  hal_set_slptr_low();
  delay_us(TIME_RESET);
  hal_set_rst_high();

  /* Force transition to TRX_OFF. */
  hal_subregister_write(SR_TRX_CMD, CMD_FORCE_TRX_OFF);
  delay_us(TIME_P_ON_TO_TRX_OFF);
  
  /* Verify that it is a supported version */
  uint8_t tvers = hal_register_read(RG_VERSION_NUM);
  uint8_t tmanu = hal_register_read(RG_MAN_ID_0);

  if ((tvers != RF230_REVA) && (tvers != RF230_REVB))
    PRINTF("rf230: Unsupported version %u\n",tvers);
  if (tmanu != SUPPORTED_MANUFACTURER_ID) 
    PRINTF("rf230: Unsupported manufacturer ID %u\n",tmanu);

  PRINTF("rf230: Version %u, ID %u\n",tvers,tmanu);
  hal_register_write(RG_IRQ_MASK, RF230_SUPPORTED_INTERRUPT_MASK);

    /* Turn off address decoding. */
//  reg = getreg(RF230_MDMCTRL0);
//  reg &= ~ADR_DECODE;
//  setreg(RF230_MDMCTRL0, reg);

  /* Change default values as recomended in the data sheet, */
  /* correlation threshold = 20, RX bandpass filter = 1.3uA. */
//  setreg(RF230_MDMCTRL1, CORR_THR(20));
//  reg = getreg(RF230_RXCTRL1);
//  reg |= RXBPF_LOCUR;
//  setreg(RF230_RXCTRL1, reg);
  
  /* Set the FIFOP threshold to maximum. */
 // setreg(RF230_IOCFG0, FIFOP_THR(127));

  /* Turn off "Security enable" (page 32). */
//  reg = getreg(RF230_SECCTRL0);
//  reg &= ~RXFIFO_PROTECTION;
//  setreg(RF230_SECCTRL0, reg);

 // rf230_set_pan_addr(0xffff, 0x0000, NULL);
 // rf230_set_channel(24);
  /* Set up the radio for auto mode operation. */
  hal_subregister_write(SR_MAX_FRAME_RETRIES, 2 );
  hal_subregister_write(SR_TX_AUTO_CRC_ON, 1);
  hal_subregister_write(SR_TRX_CMD, CMD_RX_AACK_ON);
  
  /* Start the packet receive process */
  process_start(&rf230_process, NULL);
}