原创 CC2520点对点通信误码测试

2009-2-23 17:13 3187 2 2 分类: 通信

https://static.assets-stash.eet-china.com/album/old-resources/2009/2/23/8df0df95-28af-43a6-9e2c-07494c95b1a5.rar工程文件


/***********************************************************************************
  Filename:  per_test.c


  Description:  This application functions as a packet error rate (PER) tester.
  One node is set up as transmitter and the other as receiver. The role and
  configuration parameters for the PER test of the node is chosen on initalisation
  by navigating the joystick and confirm the choices with S1.


  The configuration parameters are channel, burst size and tx power. Push S1 to
  enter the menu. Then the configuration parameters are set by pressing
  joystick to right or left (increase/decrease value) and confirm with S1.


  After configuration of both the receiver and transmitter, the PER test is
  started by pressing joystick up on the transmitter. By pressing joystick up
  again the test is stopped.


***********************************************************************************/


/***********************************************************************************
* INCLUDES
*/
#include "hal_lcd.h"
#include "hal_led.h"
#include "hal_int.h"
#include "hal_timer_32k.h"
#include "hal_joystick.h"
#include "hal_board.h"
#include "hal_rf.h"
#include "hal_assert.h"
#include "util_lcd.h"
#include "basic_rf.h"
#include "per_test.h"
#include <string.h>


/***********************************************************************************
* CONSTANTS
*/
// Application states
#define IDLE                      0
#define TRANSMIT_PACKET           1


/***********************************************************************************
* LOCAL VARIABLES
*/
static basicRfCfg_t basicRfConfig;
static perTestPacket_t txPacket;
static perTestPacket_t rxPacket;
static volatile uint8 appState;
static volatile uint8 appStarted;


/***********************************************************************************
* LOCAL FUNCTIONS
*/
static void appTimerISR(void);
static void appStartStop(void);
static void appTransmitter();
static void appReceiver();


/***********************************************************************************
* @fn          appTimerISR
*
* @brief       32KHz timer interrupt service routine. Signals PER test transmitter
*              application to transmit a packet by setting application state.
*
* @param       none
*
* @return      none
*/
static void appTimerISR(void)
{
    appState = TRANSMIT_PACKET;
}



/***********************************************************************************
* @fn          appStartStop
*
* @brief       Joystick up interrupt service routine. Start or stop 32KHz timer,
*              and thereby start or stop PER test packet transmission.
*
* @param       none
*
* @return      none
*/
static void appStartStop(void)
{
    // toggle value
    appStarted ^= 1;


    if(appStarted) {
        halTimer32kIntEnable();
    }
    else {
        halTimer32kIntDisable();
    }
}



/***********************************************************************************
* @fn          appConfigTimer
*
* @brief       Configure timer interrupts for application. Uses 32KHz timer
*
* @param       uint16 rate - Frequency of timer interrupt. This value must be
*              between 1 and 32768 Hz
*
* @return      none
*/
static void appConfigTimer(uint16 rate)
{
    halTimer32kInit(TIMER_32K_CLK_FREQ/rate);
    halTimer32kIntConnect(&appTimerISR);
}



/***********************************************************************************
* @fn          appReceiver
*
* @brief       Application code for the receiver mode. Puts MCU in endless loop
*
* @param       basicRfConfig - file scope variable. Basic RF configuration data
*              rxPacket - file scope variable of type perTestPacket_t
*
* @return      none
*/
static void appReceiver()
{
    uint32 segNumber="0";
    int16 perRssiBuf[RSSI_AVG_WINDOW_SIZE] = {0};    // Ring buffer for RSSI
    uint8 perRssiBufCounter = 0;                     // Counter to keep track of the
    // oldest newest byte in RSSI
    // ring buffer
    perRxStats_t rxStats = {0,0,0,0};
    int16 rssi;


#ifdef INCLUDE_PA
    uint8 gain;


    // Select gain (for modules with CC2590/91 only)
    gain =appSelectGain();
    halRfSetGain(gain);
#endif


    // Initialize BasicRF
    basicRfConfig.myAddr = RX_ADDR;
    if(basicRfInit(&basicRfConfig)==FAILED) {
      HAL_ASSERT(FALSE);
    }
    basicRfReceiveOn();


    halLcdClear();
    halLcdWriteLines("PER Tester", "Receiver", "Ready");


    // Main loop
    while (TRUE) {
        while(!basicRfPacketIsReady());
        if(basicRfReceive((uint8*)&rxPacket, MAX_PAYLOAD_LENGTH, &rssi)>0)
        {
            halLedSet(3);
     char rssiString[16];
            sprintf(rssiString,(char const *)"%d dBm",rssi);
            Print(HAL_LCD_LINE_4,0,"RSSI: ",1);
            Print(HAL_LCD_LINE_4,48,(uint8 *)rssiString ,1); 
   // Change byte order from network to host order
   UINT32_NTOH(rxPacket.seqNumber);
            segNumber = rxPacket.seqNumber;


            // Subtract old RSSI value from sum
            rxStats.rssiSum -= perRssiBuf[perRssiBufCounter];
            // Store new RSSI value in ring buffer, will add it to sum later
            perRssiBuf[perRssiBufCounter] =  rssi;


            // Add the new RSSI value to sum
            rxStats.rssiSum += perRssiBuf[perRssiBufCounter];
            if (++perRssiBufCounter == RSSI_AVG_WINDOW_SIZE) {
                perRssiBufCounter = 0;      // Wrap ring buffer counter
            }


            // Check if received packet is the expected packet
            if (rxStats.expectedSeqNum == segNumber) {
                rxStats.expectedSeqNum++;
            }
            // If there is a jump in the sequence numbering this means some packets in
            // between has been lost.
            else if (rxStats.expectedSeqNum < segNumber){
                rxStats.lostPkts += segNumber - rxStats.expectedSeqNum;
                rxStats.expectedSeqNum = segNumber + 1;
            }
            // If the sequence number is lower than the previous one, we will assume a
            // new data burst has started and we will reset our statistics variables.
            else {
                // Update our expectations assuming this is a new burst
                rxStats.expectedSeqNum = segNumber + 1;
                rxStats.rcvdPkts = 0;
                rxStats.lostPkts = 0;
            }
            rxStats.rcvdPkts++;


            // reset statistics if button 1 is pressed
            if(HAL_BUTTON_1_PUSHED()){
                rxStats.expectedSeqNum = segNumber + 1;
                rxStats.rcvdPkts = 0;
                rxStats.lostPkts = 0;
            }


            // Update LCD
            // PER in units per 1000
            Print(HAL_LCD_LINE_3,0,"PER: ",1);
            Printn8(HAL_LCD_LINE_3,40,(int32)((rxStats.lostPkts*1000)/(rxStats.lostPkts+rxStats.rcvdPkts)),1,4);
            Print(HAL_LCD_LINE_3,72, " /1000",1);
             //Printn8(HAL_LCD_LINE_4,48,(int32)rxStats.rssiSum/32,1,4);
            //Print(HAL_LCD_LINE_4,80, "dBm",1);


            //halLcdDisplayValue(HAL_LCD_LINE_1, "PER: ", (int32)((rxStats.lostPkts*1000)/(rxStats.lostPkts+rxStats.rcvdPkts)), " /1000");
           // halLcdDisplayValue(HAL_LCD_LINE_2, "RSSI: ", (int32)rxStats.rssiSum/32, "dBm");
            #ifndef SRF04EB
            //halLcdDisplayValue(HAL_LCD_LINE_3, "Recv'd: ", (int32)rxStats.rcvdPkts, NULL);
            #endif
            halLedClear(3);
        }
    }
}



/***********************************************************************************
* @fn          appTransmitter
*
* @brief       Application code for the transmitter mode. Puts MCU in endless
*              loop
*
* @param       basicRfConfig - file scope variable. Basic RF configuration data
*              txPacket - file scope variable of type perTestPacket_t
*              appState - file scope variable. Holds application state
*              appStarted - file scope variable. Controls start and stop of
*                           transmission
*
* @return      none
*/
static void appTransmitter()
{
    uint32 burstSize="0";
    uint32 pktsSent="0";
    uint8 appTxPower;
 uint8 n;


    // Initialize BasicRF
    basicRfConfig.myAddr = TX_ADDR;
    if(basicRfInit(&basicRfConfig)==FAILED) {
      HAL_ASSERT(FALSE);
    }


    // Set TX output power
    appTxPower = appSelectOutputPower();
    halRfSetTxPower(appTxPower);


    // Set burst size
    burstSize = appSelectBurstSize();


    // Basic RF puts on receiver before transmission of packet, and turns off
    // after packet is sent
    basicRfReceiveOff();


    // Config timer and IO
    appConfigTimer(PACKET_RATE);
    halJoystickInit();


    // Initalise packet payload
    txPacket.seqNumber = 0;
    for(n = 0; n < sizeof(txPacket.padding); n++) {
        txPacket.padding[n] = n;
    }


    halLcdClear();
    halLcdWriteLines("PER Tester", "Joystick Push", "start/stop");


    // Main loop
    while (TRUE) {


        // Wait for user to start application
        while(!halJoystickPushed() );
        appStartStop();


        halLcdClear();
        halLcdWriteLines("PER Tester", "Transmitter", NULL);


        while(appStarted) {
            if( halJoystickPushed() ) {
                appStartStop();
            }


            if (pktsSent < burstSize) {
                if( appState == TRANSMIT_PACKET ) {
                    // Make sure sequence number has network byte order
                    UINT32_HTON(txPacket.seqNumber);


                    basicRfSendPacket(RX_ADDR, (uint8*)&txPacket, PACKET_SIZE);


                    // Change byte order back to host order before increment
                    UINT32_NTOH(txPacket.seqNumber);
                    txPacket.seqNumber++;


                    pktsSent++;
                    #ifdef SRF04EB
                    halLcdDisplayValue(HAL_LCD_LINE_2, "Sent: ", (int32)pktsSent, NULL);
                    #else
                    //halLcdDisplayValue(HAL_LCD_LINE_4, "Sent: ", (int32)pktsSent, NULL);
                    Printn8(HAL_LCD_LINE_4 ,20 ,pktsSent,1,10);
                    #endif
                    appState = IDLE;


                    halLedToggle(3);
                }
            }
            else
                appStarted = !appStarted;
        }


        // Reset statistics and sequence number
        pktsSent = 0;
        txPacket.seqNumber = 0;
        halLcdClear();
        halLedClear(2);
        halLcdWriteLines("PER Test", "Joystick Push", "start/stop");
    }
}



/***********************************************************************************
* @fn          main
*
* @brief       This is the main entry of the "PER test" application.
*
* @param       basicRfConfig - file scope variable. Basic RF configuration data
*              appState - file scope variable. Holds application state
*              appStarted - file scope variable. Used to control start and stop of
*              transmitter application.
*
* @return      none
*/
void main (void)
{
    uint8 appMode;


    appState = IDLE;
    appStarted = FALSE;
 
    // Config basicRF
    basicRfConfig.panId = PAN_ID;
    basicRfConfig.ackRequest = FALSE;


    // Initialise board peripherals
    halBoardInit();


    // Initalise hal_rf
    if(halRfInit()==FAILED) {
      HAL_ASSERT(FALSE);
    }


    // Indicate that device is powered
    halLedSet(1);


    // Print Logo and splash screen on LCD
    utilPrintLogo("PER Tester");


    // Wait for user to press S1 to enter menu
    while (!HAL_BUTTON_1_PUSHED());
    halMcuWaitMs(350);
    halLcdClear();


    // Set channel
    basicRfConfig.channel = appSelectChannel();


    // Set mode
    appMode = appSelectMode();


    // Transmitter application
    if(appMode == MODE_TX) {
        // No return from here
        appTransmitter();
    }
    // Receiver application
    else if(appMode == MODE_RX) {
        // No return from here
        appReceiver();
    }
    // Role is undefined. This code should not be reached
    HAL_ASSERT(FALSE);
}

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
2
关闭 站长推荐上一条 /3 下一条