#include <stdio.h>
#include "driverlib.h"
#include "device.h"

//
// Defines
//
#define MSG_DATA_LENGTH    8    // "Don't care" for a Receive mailbox
#define RX_MSG_OBJ_ID      1    // Use mailbox 1

//
// Globals
//
uint16_t rxMsgData[8];          // Buffer for received data
volatile uint16_t X, Y, Dim;

#define LED_SET_WARM_PWM        0x08280000
#define LED_SET_COOL_PWM        0x08280001
#define LED_SET_RED_PWM         0x08280002
#define LED_SET_GREEN_PWM       0x08280003
#define LED_SET_BLUE_PWM        0x08280004


/**
 * hello.c
 */
int main(void)
{
    int i;
    uint16_t warm, cool, red, green, blue;

    //
    // If running from flash copy RAM only functions to RAM   
    //
#ifdef _FLASH
    memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
#endif      

    //
    // Initialize device clock and peripherals
    //
    Device_init();

    //
    // Initialize GPIO
    //
    Device_initGPIO();

    //printf("CAN Bus test: DEVICE_SYSCLK_FREQ = %ld\n", DEVICE_SYSCLK_FREQ);
	
    //
    // Configure GPIO pins for CANTX/CANRX
    //
/*     GPIO_setPinConfig(DEVICE_GPIO_CFG_CANRXA); */
/*     GPIO_setPinConfig(DEVICE_GPIO_CFG_CANTXA); */
    GPIO_setPinConfig(GPIO_12_CANTXB);
    GPIO_setPinConfig(GPIO_17_CANRXB);

    //
    // Initialize the CAN controller
    //
    CAN_initModule(CANB_BASE);

    //
    // Set up the CAN bus bit rate to 500kbps for each module
    // Refer to the Driver Library User Guide for information on how to set
    // tighter timing control. Additionally, consult the device data sheet
    // for more information about the CAN module clocking.
    //
    CAN_setBitRate(CANB_BASE, DEVICE_SYSCLK_FREQ, 1000000, 10);

    //CAN_setBitTiming(CANB_BASE, 5, 1, 7, 4, 2);
    //
    // Initialize the receive message object used for receiving CAN messages.
	// Possible flags: CAN_MSG_OBJ_NO_FLAGS, CAN_MSG_OBJ_USE_EXT_FILTER,
	//                 CAN_MSG_OBJ_USE_DIR_FILTER
    // Message Object Parameters:
    //      CAN Module: A
    //      Message Object ID Number: 1
    //      Message Identifier: 0x1F9FFFFA
    //      Message Frame: Extended
    //      Message Type: Receive
    //      Message ID Mask: 0x1F000000
    //      Message Object Flags: UMask, MXtd, MDir
    //      Message Object flag CAN_MSG_OBJ_USE_ID_FILTER enables usage 
    //       of msgIDMask parameter for Message Identifier based filtering
    //      Message Data Length: "Don't care" for a Receive mailbox
    CAN_setupMessageObject(CANB_BASE, RX_MSG_OBJ_ID, 0x1555aab4,
                           CAN_MSG_FRAME_EXT, CAN_MSG_OBJ_TYPE_RX, 
			   0x1555aab4, CAN_MSG_OBJ_NO_FLAGS,
			   MSG_DATA_LENGTH);

    //
    // Start CAN module A operations
    //
    CAN_startModule(CANB_BASE);

    //printf("CANB started\n");
	
    //
    // Start reception - Just wait for data from another node
    //
    while (1) {
        //
        // Poll bit0 in CAN_NDAT_21 register to check completion of Reception
        //
        //if(((HWREGH(CANB_BASE + CAN_O_ES) & CAN_ES_RXOK)) == CAN_ES_RXOK) { 
	if ((HWREG_BP(CANB_BASE + CAN_O_NDAT_21) & (1 << (RX_MSG_OBJ_ID - 1))) != 0) {
            //
            // Get the received message
            //
            asm("  NOP");
            CAN_readMessage(CANB_BASE, RX_MSG_OBJ_ID, rxMsgData);
	    X = (rxMsgData[0] << 8) + rxMsgData[1];
	    Y = (rxMsgData[2] << 8) + rxMsgData[3];
	    Dim = (rxMsgData[4] << 8) + rxMsgData[5];
/* 	    for (i = 0 ; i < MSG_DATA_LENGTH ; i++) */
/* 		printf("[%d]: 0x%04x\n", i, rxMsgData[i]); */
	    //printf("%u: %u, %u, %u\n", rxMsgData[6], X, Y, Dim);

#if 0
	    xy_to_tdrgb(X / 65535.0f, Y / 65535.0f, Dim / 65535.0f,
			&warm, &cool, &red, &green, &blue);

	    printf("(   => (%5u, %5u, %5u, %5u, %5u)\n", 
		   warm, cool, red, green, blue);

#if 0
	    SendLED(fixture->fd, LED_SET_WARM_PWM,      warm);
	    SendLED(fixture->fd, LED_SET_COOL_PWM,      cool);
	    SendLED(fixture->fd, LED_SET_RED_PWM,       red);
	    SendLED(fixture->fd, LED_SET_GREEN_PWM,     green);
	    SendLED(fixture->fd, LED_SET_BLUE_PWM,      blue);
#endif
#endif
	}
    }

    return 0;
}
