/****************************************************************************
application range_demo_plus_tx.c, range demo plus...transmitter

This application continuously transmits or receives a packet. If switch 1 is 
depressed during start up, then a packet is continuously transmitted and the 
second LED 2 flashes. If switch 2 is depressed during start up, then the device 
is set into continuous receive mode and the bottom LED 1 flashes.

The application will process ACK packets and show the same number of LEDs 
as the RX side of range demo plus.



 $Author: b06900 $
 $Date: 2008/03/05 22:49:14 $
 $Name:  $

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

#include <hidef.h> /* for EnableInterrupts macro */
#include "pub_def.h"
#include "APP_SMAC_API.h"
#include "freescale_radio_hardware.h"
#include "range_demo_plus_tx.h"
#if SMAC_FEATURE_OTAP == TRUE
#include "APP_OTAP_API.h"
#endif // SMAC_FEATURE_OTAP == TRUE
#if SMAC_FEATURE_SECURITY == TRUE
#include "APP_security_API.h"
#endif // SMAC_FEATURE_SECURITY == TRUE
#if (EMBEDDED_BOOTLOADER == TRUE)  
#include "bootloader user api.h"
#endif

#if SMAC_FEATURE_OTAP == TRUE
#include "APP_OTAP_API.h"
#endif // SMAC_FEATURE_OTAP == TRUE


#if SMAC_FEATURE_SECURITY == TRUE
#include "APP_security_API.h"
#endif // SMAC_FEATURE_SECURITY == TRUE

UINT32 crc_f(UINT32 sprava);

/* Global Variables */ 
UINT8 gu8RTxMode; /* needed for s-mac, application can read this variable */
                /* rtx_mode is the software state variable of the radio */
                /* This variable reflects the current state of MC13192 */
INT8 gi8AppStatus= 0; 
UINT8 gu8LedStatus= 0;
UINT8 SaveTxBuffer[4];
UINT8 CrcTxBuffer[4];
UINT8 control[4];
UINT8 channel = 0;
UINT8 adjust = 10;
UINT32 message=0;
static tRxPacket sRxPacket;  /*SMAC structure for RX packets  */
static tTxPacket sTxPacket;    /*SMAC structure for TX packets	 */

void main(void) {

    static UINT8 au8RxDataBuffer[20];    /*Data buffer to hold RX data, if you want larger packets change 20 to what you need.*/
    static UINT8 au8TxDataBuffer[20];    /*Data buffer to hold TX data, if you want larger packets change 20 to what you need.	 */
    UINT16 u16loop;
    UINT32 crc_a;
    
    /*Initialize the packet.*/
    sTxPacket.u8DataLength = 0;                 /*Set TX default to 0*/
    sTxPacket.pu8Data = &au8TxDataBuffer[0];    /*Load the address of our txbuffer into tx structure.*/
    sRxPacket.u8DataLength = 0;                 /*Set RX default to 0*/
    sRxPacket.pu8Data = &au8RxDataBuffer[0];    /*Load the address of our rxbuffer into rx structure*/
    sRxPacket.u8MaxDataLength = 100;            /*Define the max buffer we are interested in.*/
    sRxPacket.u8Status = 0;                     /*initialize the status packet to 0.*/
  

  
    MCUInit();        /*Initialize the mcu, setup GPIOs, SPI, clock scheme, etc.*/
    RadioInit();
    AppInit();
          
#if (EMBEDDED_BOOTLOADER == TRUE)
    boot_init();  /*Initialize the bootloader...in bootloader user api.c*/
#endif 
#if (EMBEDDED_BOOTLOADER == TRUE)
    boot_call();  /*Checks for user request for bootloader.*/
                    /*Runs bootloader if requested.  Code will not return.*/
#endif 

    (void)MLMESetMC13192ClockRate(0);  /* Set initial Clk speed from MC13192s CLKO*/
    UseExternalClock();    /* switch clock sources to EXTERNAL clock */
    
    /* include your start up code here */    
    EnableInterrupts; /* Turn on system interrupts */
    (void)MLMESetChannelRequest(CHANNEL_NUMBER);    /*Set channel zero, can be changed to users preference*/
    
#if (EMBEDDED_BOOTLOADER == TRUE)
    boot_init();  /*Initialize the bootloader...in bootloader user api.c*/
#endif 
    
  /******************************************************************
  To adjust output power call the MLME_MC13192_PA_output_adjust() with:
  
  MAX_POWER     (+3 to +5dBm)
  NOMINAL_POWER (0 dBm)
  MIN_POWER     ~(-16dBm)
  
  or somewhere custom ? (0-15, 11 (NOMINAL_POWER) being Default power)

    ******************************************************************/
    (void)MLMEMC13192PAOutputAdjust(OUTPUT_POWER);    /*Set MAX power setting*/
  //MLME_MC13192_PA_output_adjust(MIN_POWER);    /*Set MIN power setting*/
  //MLME_MC13192_PA_output_adjust(NOMINAL_POWER);    /*Set Nominal power setting    */
  
  
  
  
    gi8AppStatus= INITIAL_STATE;        /*Set the initial u8app_statusof the application state variable to INITIAL_STATE*/
        
    /*loop forever*/
    for (;;) 
    {

        switch (gi8AppStatus) 
        {
        case INITIAL_STATE:        /*Walk the LEDs*/
            /*For TX*/
            LED1 = LED_OFF;        /*Turn off all LEDs*/
            LED2 = LED_OFF;
            LED3 = LED_OFF;
                        
            LED1 = LED_ON;                                    /*Lights LED1*/
            for (u16loop = 0; u16loop < LED_DELAY; u16loop++);        
            LED1 = LED_OFF; LED2 = LED_ON;                    /*Lights LED2, Turns off LED1*/
            for (u16loop = 0; u16loop < LED_DELAY; u16loop++);
            LED2 = LED_OFF; LED3 = LED_ON;                    /*Lights LED3, Turns off LED2	 */
            for (u16loop = 0; u16loop < LED_DELAY; u16loop++);
            LED3 = LED_OFF;                                  /*Turns off LED3*/
            
            (void)MLMESetChannelRequest(0);
            (void)MLMEMC13192PAOutputAdjust(10);
             
            gi8AppStatus = DO_CRC;    
            break;
                                        
        case TX_STATE:
            
           LED1 ^= 1;
           
           if (message<4294960000) message +=256;
           else message=256;
           
           
           
           message &= 0xFFFFFF00; /* poslednych 8 bitov je crc kod*/

	  			 crc_a = crc_f(message); /* vytvorenie crc kodu pre message*/
		  		 
		  		 message |= crc_a;      /* pridanie k message crc kod*/
			  	 
			  	 SaveTxBuffer[3] = message;        /* naplnenie Save pola pre pripad opetovneho poslania*/
			  	 SaveTxBuffer[2] = message >> 8;
			  	 SaveTxBuffer[1] = message >> 16;
			  	 SaveTxBuffer[0] = message >> 24;
			  	 
			  	 
			  	 /*Load the tx buffer with the ZigBee packet.*/
            au8TxDataBuffer[0] = SaveTxBuffer[0];
            au8TxDataBuffer[1] = SaveTxBuffer[1];
            au8TxDataBuffer[2] = SaveTxBuffer[2];
            au8TxDataBuffer[3] = SaveTxBuffer[3];
            
            sTxPacket.u8DataLength = 4;    /*Set the data length of the packet.  in this case, 6.*/
            (void)MCPSDataRequest(&sTxPacket);    
                        
            gi8AppStatus= DO_CRC; 
            
            break;
            
        case RX_STATE:
          
            MLMERXEnableRequest(&sRxPacket,0xFFFFFFFF); /*Zero means wait forever with RX ON.*/
            
            gi8AppStatus= WAITING_FOR_ACK;
                                 
            break;
                
        case RESET_STATE:
            /*MC13192 Reset, reinitialize and return to default state (TX_STATE).	  */
            RadioInit();
            gi8AppStatus= INITIAL_STATE;
            break;
            
        case RECEIVER_ALWAYS_ON:
            break;
            
        case WAITING_FOR_ACK:
            /* At this point only two things happen, 1-we receive the ack packet or 2-timeout.
             * Either way the TX will leave this state and continue. Low power mode could be placed here
             * because both 1 and 2 are interrupt driven, in this case we keep it simple 
             */
            break;
            
        case BAD_STATE: /*Packet bol zly, preposleme znovu*/
            
            LED2 ^= 1;
            
            au8TxDataBuffer[0] = SaveTxBuffer[0];
            au8TxDataBuffer[1] = SaveTxBuffer[1];
            au8TxDataBuffer[2] = SaveTxBuffer[2];
            au8TxDataBuffer[3] = SaveTxBuffer[3];
            
            sTxPacket.u8DataLength = 4;    /*Set the data length of the packet.  in this case, 6.*/
            (void)MCPSDataRequest(&sTxPacket);    
            
            gi8AppStatus= RX_STATE;    
            
            break;
            
         case SET_STATE:
            
            LED3 ^= 1;
            
            (void)MLMESetChannelRequest(channel);
            (void)MLMEMC13192PAOutputAdjust(adjust);
            
            gi8AppStatus= RX_STATE; 
            break;
           
         case START_STATE:
            
            channel = 0;
            adjust = 10;
            (void)MLMESetChannelRequest(channel);
            (void)MLMEMC13192PAOutputAdjust(adjust);
            
            gi8AppStatus= RX_STATE;
            break;
         
         case DO_CRC:
          
           if (message<4294960000) message +=256;
           else message=256;
           
           
           
           message &= 0xFFFFFF00; /* poslednych 8 bitov je crc kod*/

	  			 crc_a = crc_f(message); /* vytvorenie crc kodu pre message*/
		  		 
		  		 message |= crc_a;      /* pridanie k message crc kod*/
			  	 
			  	 CrcTxBuffer[3] = message;        /* naplnenie Save pola pre pripad opetovneho poslania*/
			  	 CrcTxBuffer[2] = message >> 8;
			  	 CrcTxBuffer[1] = message >> 16;
			  	 CrcTxBuffer[0] = message >> 24;
           
           gi8AppStatus= RX_STATE;
           break;
          
         case SEND_NEXT:
            
            LED1 ^= 1;
            
            SaveTxBuffer[0] = CrcTxBuffer[0];
            SaveTxBuffer[1] = CrcTxBuffer[1];
            SaveTxBuffer[2] = CrcTxBuffer[2];
            SaveTxBuffer[3] = CrcTxBuffer[3];
            
            /*Load the tx buffer with the ZigBee packet.*/
            au8TxDataBuffer[0] = SaveTxBuffer[0];
            au8TxDataBuffer[1] = SaveTxBuffer[1];
            au8TxDataBuffer[2] = SaveTxBuffer[2];
            au8TxDataBuffer[3] = SaveTxBuffer[3];
            
            sTxPacket.u8DataLength = 4;    /*Set the data length of the packet.  in this case, 6.*/
            (void)MCPSDataRequest(&sTxPacket);    
                        
            gi8AppStatus= DO_CRC; 
            
            break;
          
        default:
            break;
        
        }
    }
}


void MCPSDataIndication(tRxPacket *sRxPacket) 
{
    if (sRxPacket->u8Status == TIMEOUT) {

        /* Put timeout condition code here */
        gi8AppStatus = INITIAL_STATE;    /*Should not get here.*/

    }
   
   if (sRxPacket->u8Status == SUCCESS) {
      switch (sRxPacket->pu8Data[0]){
        case 'G': gi8AppStatus = SEND_NEXT;  break;
        case 'B': gi8AppStatus = BAD_STATE; break;
        case 'S': 
          gi8AppStatus = SET_STATE; 
          channel = sRxPacket->pu8Data[1];
          adjust = sRxPacket->pu8Data[2];
          break; 
          
        default:  gi8AppStatus = RX_STATE;  break;
      }
   }
}

void MLMEMC13192ResetIndication() {
    /* Notifies you that the MC13192 has been reset.
     * Application must handle this here.
     */
    

    gi8AppStatus = RESET_STATE;    /*MC13192 reset, re-initialize.*/

}

void AppInit() {
  /* Init LED's 1-OFF 0-ON */
    LED1 = 1; /* Default is off */
    LED2 = 1;
    LED3 = 1;
    LED4 = 1;
    
    LED1DIR = 1; /*Set the DDIR register as Outputs for the LED pins*/
    LED2DIR = 1;
    LED3DIR = 1;
    LED4DIR = 1;
    
    /* Set Push button pull ups */
    PB0PU = 1;
    PB1PU = 1;
    PB2PU = 1;
    PB3PU = 1;
    
  #if SMAC_FEATURE_OTAP == TRUE
  if (PB0 == 0){
    KBI1SC = 0x00; /* Turn On Interrupts */
    OTAPActivate();
  }
  #endif // SMAC_FEATURE_OTAP == TRUE    
}

/********************************
 *                              *
 *funkcia pre tvorenie crc kodu:*
 *                              *
 ********************************/

UINT32 crc_f(UINT32 sprava){
	UINT32 gp=0xC6800000, crc; /*11000110100000000000000000000000*/
	UINT8 i;
	
	crc = sprava;
	for (i=0; i<24; i++){
		if (crc & 0x80000000){
			crc ^= gp;
			
		}
		crc <<=1;
	}
	crc >>=24;
	return crc;					 
}