/*******************************************************************************
*   @fn         syncReceivedISR
*
*   @brief      Function running every time a sync word has been received
*
*   @param      none
*
*   @return     none
*/
static void syncReceivedISR(void) {

    uint8 numRxBytes;
    uint8 writeByte;

    // After the sync word is received one needs to wait for the two
    // length bytes to be put in the RX FIFO
    do {
        cc112xSpiReadReg(CC112X_NUM_RXBYTES, &numRxBytes, 1);
    } while (numRxBytes < 2);

    // Read the length byte and store it in the packetLength variable
    cc112xSpiReadRxFifo(rxBuffer, 2);
    pBufferIndex += 2;
    packetLength =  (uint16)(((uint16)(rxBuffer[0] << 8)) | rxBuffer[1]);

    // Make sure that the packet length is in the correct range, update
    // variables and enable interrupt on falling edge of GPIO3 (PKT_SYNC_RXTX)
    if ((packetLength > MAX_VARIABLE_LENGTH) 
        && (packetLength <= PACKET_LENGTH)) {
        bytesLeft = packetLength + 2;
        fixedPacketLength = bytesLeft  % (MAX_VARIABLE_LENGTH + 1);
        writeByte = fixedPacketLength;
        cc112xSpiWriteReg(CC112X_PKT_LEN, &writeByte, 1);

        // Clear interrupt flag and enable GPIO3
        ioPinIntClear(IO_PIN_PORT_1, GPIO3);
        ioPinIntEnable(IO_PIN_PORT_1, GPIO3);

    } else { // Exit RX and flush RX FIFO due to length byte being out of range
        trxSpiCmdStrobe(CC112X_SIDLE);
        trxSpiCmdStrobe(CC112X_SFRX);
        state = RX_START;
    }
  
    // Clear ISR flag
    ioPinIntClear(IO_PIN_PORT_1, GPIO2);
}
static void setDirection(uint8 dir){
	uint8 writeByte;
        
	//dir = 1 => RX
	//dir = 0 => TX
	
	if (dir) {
		// Application specific registers
		// FIFO_THR = 120
		// GPIO0 = RXFIFO_THR
		// GPIO2 = PKT_SYNC_RXTX
		// GPIO3 = PKT_SYNC_RXTX
		writeByte = INFINITE_PACKET_LENGTH_MODE;
		cc112xSpiWriteReg(CC112X_PKT_CFG0, &writeByte, 1);
		writeByte = 0x78; cc112xSpiWriteReg(CC112X_FIFO_CFG, &writeByte, 1);
		writeByte = 0x00; cc112xSpiWriteReg(CC112X_IOCFG0,   &writeByte, 1);
		writeByte = 0x06; cc112xSpiWriteReg(CC112X_IOCFG2,   &writeByte, 1);
		writeByte = 0x06; cc112xSpiWriteReg(CC112X_IOCFG3,   &writeByte, 1);

		// Connect ISR function to GPIO0
		ioPinIntRegister(IO_PIN_PORT_1, GPIO0, &rxFifoAboveThresholdISR);

		// Interrupt on falling edge
		ioPinIntTypeSet(IO_PIN_PORT_1, GPIO0, IO_PIN_RISING_EDGE);

		// Clear interrupt
		ioPinIntClear(IO_PIN_PORT_1, GPIO0);

		// Enable interrupt
		ioPinIntEnable(IO_PIN_PORT_1, GPIO0);

		// Connect ISR function to GPIO2
		ioPinIntRegister(IO_PIN_PORT_1, GPIO2, &syncReceivedISR);

		// Interrupt on falling edge
		ioPinIntTypeSet(IO_PIN_PORT_1, GPIO2, IO_PIN_RISING_EDGE);

		// Clear interrupt
		ioPinIntClear(IO_PIN_PORT_1, GPIO2);

		// Enable interrupt
		ioPinIntEnable(IO_PIN_PORT_1, GPIO2);

		// Set up interrupt on GPIO3 (PKT_SYNC_RXTX)
		ioPinIntRegister(IO_PIN_PORT_1, GPIO3, &packetReceivedISR);

		// Interrupt on falling edge
		ioPinIntTypeSet(IO_PIN_PORT_1, GPIO3, IO_PIN_FALLING_EDGE);
	}
	else {
		// Application specific registers
		// FIFO_THR = 120
		// GPIO0 = TXFIFO_THR
		// GPIO2 = PKT_SYNC_RXTX
		writeByte = INFINITE_PACKET_LENGTH_MODE;
		cc112xSpiWriteReg(CC112X_PKT_CFG0, &writeByte, 1);
		writeByte = 0x78; cc112xSpiWriteReg(CC112X_FIFO_CFG, &writeByte, 1);
		writeByte = 0x02; cc112xSpiWriteReg(CC112X_IOCFG0,   &writeByte, 1);
		writeByte = 0x06; cc112xSpiWriteReg(CC112X_IOCFG2,   &writeByte, 1);
		
		// Connect ISR function to GPIO0
		ioPinIntRegister(IO_PIN_PORT_1, GPIO0, &txFifoBelowThresholdISR);

		// Interrupt on falling edge
		ioPinIntTypeSet(IO_PIN_PORT_1, GPIO0, IO_PIN_FALLING_EDGE);

		// Clear interrupt
		ioPinIntClear(IO_PIN_PORT_1, GPIO0);

		// Enable interrupt
		ioPinIntEnable(IO_PIN_PORT_1, GPIO0);

		// Connect ISR function to GPIO2
		ioPinIntRegister(IO_PIN_PORT_1, GPIO2, &packetSentISR);

		// Interrupt on falling edge
		ioPinIntTypeSet(IO_PIN_PORT_1, GPIO2, IO_PIN_FALLING_EDGE);

		// Clear interrupt
		ioPinIntClear(IO_PIN_PORT_1, GPIO2);

		// Enable interrupt
		ioPinIntEnable(IO_PIN_PORT_1, GPIO2);
	}
}
/*******************************************************************************
*   @fn         runRX
*
*   @brief      Puts radio in RX and waits for packets. Function assumes
*               that status bytes are appended in the RX_FIFO
*               Update packet counter and display for each packet received.
*
*   @param      none
*
*   @return     none
*/
static void runRX(void) {

    uint8 rxBuffer[128] = {0};
    uint8 rxBytes;
    uint8 marcState;

    // Connect ISR function to GPIO2
    ioPinIntRegister(IO_PIN_PORT_1, GPIO2, &radioRxISR);

    // Interrupt on falling edge
    ioPinIntTypeSet(IO_PIN_PORT_1, GPIO2, IO_PIN_FALLING_EDGE);

    // Clear ISR flag
    ioPinIntClear(IO_PIN_PORT_1, GPIO2);

    // Enable interrupt
    ioPinIntEnable(IO_PIN_PORT_1, GPIO2);

    // Update LCD
    updateLcd();

    // Set radio in RX
    trxSpiCmdStrobe(CC120X_SRX);

    // Infinite loop
    while(TRUE) {

        // Wait for packet received interrupt
        if(packetSemaphore == ISR_ACTION_REQUIRED) {

            // Read number of bytes in RX FIFO
            cc120xSpiReadReg(CC120X_NUM_RXBYTES, &rxBytes, 1);

            // Check that we have bytes in FIFO
            if(rxBytes != 0) {

                // Read MARCSTATE to check for RX FIFO error
                cc120xSpiReadReg(CC120X_MARCSTATE, &marcState, 1);

                // Mask out MARCSTATE bits and check if we have a RX FIFO error
                if((marcState & 0x1F) == RX_FIFO_ERROR) {

                    // Flush RX FIFO
                    trxSpiCmdStrobe(CC120X_SFRX);
                } else {

                    // Read n bytes from RX FIFO
                    cc120xSpiReadRxFifo(rxBuffer, rxBytes);

                    // Check CRC ok (CRC_OK: bit7 in second status byte)
                    // This assumes status bytes are appended in RX_FIFO
                    // (PKT_CFG1.APPEND_STATUS = 1)
                    // If CRC is disabled the CRC_OK field will read 1
                    if(rxBuffer[rxBytes - 1] & 0x80) {

                        // Update packet counter
                        packetCounter++;
                    }
                }
            }

            // Update LCD
            updateLcd();

            // Reset packet semaphore
            packetSemaphore = ISR_IDLE;

            // Set radio back in RX
            trxSpiCmdStrobe(CC120X_SRX);
        }
    }
}
/*******************************************************************************
*   @fn         main
*
*   @brief      Runs the main routine
*
*   @param      none
*
*   @return     none
*/
void main(void) {

    uint8 writeByte;

    // Initialize MCU and peripherals
    initMCU();

    // Write radio registers (preferred settings from SmartRF Studio)
    registerConfig();

    // Application specific registers
    // FIFO_THR = 120
    // GPIO0 = RXFIFO_THR
    // GPIO2 = PKT_SYNC_RXTX
    // GPIO3 = PKT_SYNC_RXTX
    writeByte = INFINITE_PACKET_LENGTH_MODE;
    cc112xSpiWriteReg(CC112X_PKT_CFG0, &writeByte, 1);
    writeByte = 0x78; cc112xSpiWriteReg(CC112X_FIFO_CFG, &writeByte, 1);
    writeByte = 0x00; cc112xSpiWriteReg(CC112X_IOCFG0,   &writeByte, 1);
    writeByte = 0x06; cc112xSpiWriteReg(CC112X_IOCFG2,   &writeByte, 1);
    writeByte = 0x06; cc112xSpiWriteReg(CC112X_IOCFG3,   &writeByte, 1);

    bspLedSet(BSP_LED_ALL);
    
    // Calibrate the radio according to the errata note
    manualCalibration();

    // Connect ISR function to GPIO0
    ioPinIntRegister(IO_PIN_PORT_1, GPIO0, &rxFifoAboveThresholdISR);

    // Interrupt on falling edge
    ioPinIntTypeSet(IO_PIN_PORT_1, GPIO0, IO_PIN_RISING_EDGE);

    // Clear interrupt
    ioPinIntClear(IO_PIN_PORT_1, GPIO0);

    // Enable interrupt
    ioPinIntEnable(IO_PIN_PORT_1, GPIO0);

    // Connect ISR function to GPIO2
    ioPinIntRegister(IO_PIN_PORT_1, GPIO2, &syncReceivedISR);

    // Interrupt on falling edge
    ioPinIntTypeSet(IO_PIN_PORT_1, GPIO2, IO_PIN_RISING_EDGE);

    // Clear interrupt
    ioPinIntClear(IO_PIN_PORT_1, GPIO2);

    // Enable interrupt
    ioPinIntEnable(IO_PIN_PORT_1, GPIO2);

    // Set up interrupt on GPIO3 (PKT_SYNC_RXTX)
    ioPinIntRegister(IO_PIN_PORT_1, GPIO3, &packetReceivedISR);

    // Interrupt on falling edge
    ioPinIntTypeSet(IO_PIN_PORT_1, GPIO3, IO_PIN_FALLING_EDGE);

    printWelcomeMessage();

    while (TRUE) {
        switch (state) {

            //------------------------------------------------------------------
            case RX_START:
            //------------------------------------------------------------------
            trxSpiCmdStrobe(CC112X_SRX);
            pBufferIndex = rxBuffer;

            // Disable interrupt on GPIO3
            ioPinIntDisable(IO_PIN_PORT_1, GPIO3);

            state = RX_WAIT;

            //------------------------------------------------------------------
            case RX_WAIT:
            //------------------------------------------------------------------
            if (packetReceived) {
                packetReceived = FALSE;

                // Check CRC and update LCD if CRC OK
                if ((rxBuffer[packetLength + 3]) & CRC_OK)
                    updateLcd();

                // Change to infinite packet length mode
                pktFormat = INFINITE;
                writeByte = INFINITE_PACKET_LENGTH_MODE;
                cc112xSpiWriteReg(CC112X_PKT_CFG0, &writeByte, 1);

                state = RX_START;
            }
            break;

            //------------------------------------------------------------------
            default:
            //------------------------------------------------------------------

            break;
        }
    }
}