# xmpl_trx_echo.c - Echo Frames

This example shows, how frames are received and retransmitted if their CRC was correct. This example is esentially a combination from xmpl_trx_tx.c - Transmitting Frames and xmpl_trx_rx.c - Receiving Frames. The retransmission of the frames is initiated within the transceiver interrupt routine without any CCA.

Note:
  Use this example with care !!! You can mess up your sensor network easily.

Code Example

    /* $Id$ */
    /* Example for echoing received frames */

    #include "board.h"
    #include "transceiver.h"
    #include "ioutil.h"
    #include  <util/crc16.h>
    #include "xmpl.h"

    static uint8_t rxfrm[MAX_FRAME_SIZE];
    static volatile uint8_t rxcnt;
    static uint8_t state;

    int main(void)
    {
    trx_regval_t rval;

        /* This will stop the application before initializing the radio transceiver
         * (ISP issue with MISO pin, see FAQ)
         */
        trap_if_key_pressed();

        /* Step 0: init MCU peripherals */
        LED_INIT();
        trx_io_init(SPI_RATE_1_2);
        LED_SET_VALUE(LED_MAX_VALUE);
        LED_SET_VALUE(0);

        /* Step 1: initialize the transceiver */
        TRX_RESET_LOW();
        TRX_SLPTR_LOW();
        DELAY_US(TRX_RESET_TIME_US);
        TRX_RESET_HIGH();
        trx_reg_write(RG_TRX_STATE,CMD_TRX_OFF);
        DELAY_US(TRX_INIT_TIME_US);
        rval = trx_bit_read(SR_TRX_STATUS);
        ERR_CHECK(TRX_OFF!=rval);
        LED_SET_VALUE(1);

        /* Step 2: setup transmitter
         * - configure radio channel
         * - go into RX state,
         * - enable "receive end" IRQ
         */
        trx_bit_write(SR_CHANNEL,CHANNEL);
        trx_reg_write(RG_TRX_STATE,CMD_RX_ON);
    #if defined(TRX_IRQ_TRX_END)
        trx_reg_write(RG_IRQ_MASK,TRX_IRQ_TRX_END);
    #elif defined(TRX_IRQ_RX_END) && defined(TRX_IRQ_TX_END)
        trx_reg_write(RG_IRQ_MASK,TRX_IRQ_RX_END | TRX_IRQ_TX_END);
    #else
    #  error "Unknown IRQ bits"
    #endif
        sei();
        LED_SET_VALUE(2);

        /* Step 3: Going to receive frames */
        rxcnt = 0;

        LED_SET_VALUE(0);
        while(1);
    }

    #if defined(TRX_IF_RFA1)
    ISR(TRX24_RX_END_vect)
    {
    uint8_t *pfrm, tmp, flen;
    uint16_t crc;

        LED_SET_VALUE(0);
        /* upload frame and check for CRC16 validity */
        pfrm = rxfrm;
        flen = trx_frame_read(pfrm, sizeof(rxfrm), NULL);
        tmp = flen;
        crc = 0;
        do
        {
            crc = _crc_ccitt_update(crc, *pfrm++);
        }
        while(tmp--);
        /* if crc is correct, update RX frame counter */
        if (crc == 0)
        {
            rxcnt ++;
            /* echo the frame if CRC is valid*/
            trx_reg_write(RG_TRX_STATE,CMD_FORCE_TRX_OFF);
            trx_reg_write(RG_TRX_STATE,CMD_PLL_ON);
            /*invert sequence number, just to show if it is from pinger */
            rxfrm[2] ^=0xff;
            DELAY_US(16); /* wait 1 symbol, XXX check this timing */
            TRX_SLPTR_HIGH();
            TRX_SLPTR_LOW();
            trx_frame_write(flen,rxfrm);
            state = STATE_TX;
        }

        /* display current frame count */
        LED_SET_VALUE(rxcnt);

    }

    ISR(TRX24_TX_END_vect)
    {

        trx_reg_write(RG_TRX_STATE,CMD_RX_ON);
        state = STATE_RX;
    }
    #else  /* !RFA1 */
    ISR(TRX_IRQ_vect)
    {
    static volatile trx_regval_t irq_cause;
    uint8_t *pfrm, tmp, flen;
    uint16_t crc;

        irq_cause = trx_reg_read(RG_IRQ_STATUS);
        if (irq_cause & TRX_IRQ_TRX_END)
        {

            if (state == STATE_TX)
            {
                trx_reg_write(RG_TRX_STATE,CMD_RX_ON);
                state = STATE_RX;
            }
            else
            {
                LED_SET_VALUE(0);
                /* upload frame and check for CRC16 validity */
                pfrm = rxfrm;
                flen = trx_frame_read(pfrm, sizeof(rxfrm), NULL);
                tmp = flen;
                crc = 0;
                do
                {
                    crc = _crc_ccitt_update(crc, *pfrm++);
                }
                while(tmp--);
                /* if crc is correct, update RX frame counter */
                if (crc == 0)
                {
                    rxcnt ++;
                    /* echo the frame if CRC is valid*/
                    trx_reg_write(RG_TRX_STATE,CMD_FORCE_TRX_OFF);
                    trx_reg_write(RG_TRX_STATE,CMD_PLL_ON);
                    /*invert sequence number, just to show if it is from pinger */
                    rxfrm[2] ^=0xff;
                    DELAY_US(16); /* wait 1 symbol, XXX check this timing */
                    TRX_SLPTR_HIGH();
                    TRX_SLPTR_LOW();
                    trx_frame_write(flen,rxfrm);
                    state = STATE_TX;
                }

                /* display current frame count */
                LED_SET_VALUE(rxcnt);

            }
        }
    }
    #endif  /* RFA1 */

    /* EOF */