Esempio n. 1
0
void main()
{
	unsigned long id;
	BYTE cpt_RB4;
	BYTE cpt_RB5;
    BYTE data_envoi;
    BYTE data_recu[8];
    BYTE dataLen;
    int i;
    
    ECAN_RX_MSG_FLAGS flags;
	init();
	
	cpt_RB4 = 0;
	cpt_RB5 = 0;
	data_envoi = 0;
	
	for (i = 0; i < 8;i++)
		data_recu[i] = 0xFF;
	
	printf(NL NL "début programme" NL);
    ECANInitialize();
    ECANSetBaudRate(2, 4, 8, 8, 8);
    
	while(1)
	{
		if(TRUE == ECANReceiveMessage(&id, data_recu, &dataLen, &flags))
		{
			PIC1_ONLY printf("ECAN: reçu %u octet(s) : %u" NL, dataLen, data_recu[0]);
			led_afficher_int(data_recu[0]);
		}
		
		
		if(bouton_RB4_pressed())
		{
			cpt_RB4 = cpt_RB4 + 1;
			
			data_envoi = (BYTE)cpt_RB4;
			while (!ECANSendMessage(0, &data_envoi, 1, 0));
			PIC1_ONLY printf("compteur de RB4 : %u" NL, cpt_RB4);
			
			led_afficher_int(cpt_RB4);
		}
			
		if(bouton_RB5_pressed())
		{
			cpt_RB5 = cpt_RB5 + 1;
			
			data_envoi = (BYTE)cpt_RB5;
			while (!ECANSendMessage(0, &data_envoi, 1, 0));
			PIC1_ONLY printf("compteur de RB5 : %u" NL, cpt_RB5);
			
			led_afficher_int(cpt_RB5);
		}
	}
}
Esempio n. 2
0
void main() {

    BYTE data = 0;

    TRISBbits.TRISB0 = 1; // rb0 en entrée (bouton)
    TRISBbits.TRISB1 = 1; // rb1 en entrée (bouton)

    //Configure les interruptions externes sur INT0 sur front (1:montant 0:descendant)
    INTCON2bits.INTEDG0 = 0;
    //Active les interruptions externes sur INT0
    INTCONbits.INT0IE = 1;

    //Configure les interruptions externes sur INT1 sur front (1:montant 0:descendant)
    INTCON2bits.INTEDG1 = 0;
    //Configure l'interruption externe INT1 sur 1:Haut prio 0:Basse prio
    INTCON3bits.INT1IP = 1;
    //Active les interruptions externes sur INT1
    INTCON3bits.INT1IE = 1;

    //Active l'interruption sur les changement de RB4 à RB7 p117
    INTCONbits.RBIE = 1;
    //Initialise le flag interruption sur les changement de RB4 à RB7
    INTCONbits.RBIF = 0;
    //Haute priorité sur interruption sur les changement de RB4 à RB7
    INTCON2bits.RBIP = 1;

    //Configure l'oscillateur interne sur 4MHz
    OSCCON = 0xEE;
    //Active les priorités sur interruption
    RCONbits.IPEN = 1;
    //Active les interruptions de haute prio
    INTCONbits.GIE = 1;
    //Active les interruptions de basse prio
    INTCONbits.PEIE = 1;

    TRISDbits.TRISD0 = 1; // rb0 en entrée (bouton)
    TRISDbits.TRISD1 = 1; // rb1 en entrée (bouton)


    ECANInitialize();



    ECANSendMessage(0x224, &data, 8, 0b00000011);

    while (1) {





    }
}
//opens the CAN port and reads the dip switch settings to determine the slave's address
//outputs the can address
void CAN_Initialize(void)
{
	//ensure proper TRIS settings
	TRISB |= 0b00001000;//set the CAN input (RB3) to input
	TRISC &= 0b11111011;//set the CAN output (RB2) to output
	//actually start the CAN module
	ECANInitialize();
	////was in Krishna's code (not sure if it is necessary or not)//////
	// defined ECANPoll.c 
  	CIOCONbits.ENDRHI =1;
	//////////
	return;
}
Esempio n. 4
0
void main(void)
{
    unsigned long id;
    BYTE data[4];
    BYTE dataLen;
    ECAN_RX_MSG_FLAGS flags;


    ECANInitialize();

    // This function is for illustration purpose only.
    // It shows how an application would perform run-time initialization.
    // Normally, ECANInitialize() would initialize  ECAN module
    // as per ECAN.def options.  You would do run-time initialization
    // only if the ECAN optoins need to be changed at run-time.
    //RunTimeInitialization();

    while( !ECANSendMessage(0x123, data, 0, ECAN_TX_STD_FRAME) );


    do
    {
        while( !ECANReceiveMessage(&id, data, &dataLen, &flags) )
        {
            // Pushed down RB4 will fill-up FIFO/buffers.
            while( PORTB_RB4 == 0 );
        }


        id++;
        while( !ECANSendMessage(id, data, dataLen, flags) );

        // Delay so that when we are transmitting contents of FIFO all at once,
        // CANKing can receive it correctly without overflowing its buffer.
        id = 0xafff;
        while( id-- );
    } while(1);
}
Esempio n. 5
0
File: can.c Progetto: Yalir/Archi1A
void can_init(void)
{
	ECANInitialize();
    ECANSetBaudRate(2, 4, 8, 8, 8);
}
void main (void)
{
	unsigned long int i;
	unsigned int voltage;
	unsigned char temp;
	unsigned int received_CAN_ID;
	signed long  int current;
	//can receiving variables
	char messageReceived = 0;
	char dataReceived[8]={0,0,0,0,0,0,0,0};	//maximum length that can be recieved
	char lengthReceived = 0, flagsReceived = 0;
	unsigned long addressReceived = 0;
	
	//set all of the unused pins to output and have them output 0;
	TRISA = 0x00;
  	TRISB = 0x08;
	TRISC = 0x00;
	TRISD = 0x00;
	TRISE = 0x00;
	LATA = 0x00;
	LATB = 0x00;
	LATC = 0x00;
	LATD = 0x00;
	LATE = 0x00;
	
	//open the serial port
	openSerialPort();
	//setup the can port
	ECANInitialize();																							    // defined ECANPoll.c
  	CIOCONbits.ENDRHI =1;  

	while(1)
	{
		messageReceived = 0;
		//LATCbits.LATC3 = ~LATCbits.LATC3;
		messageReceived = ECANReceiveMessage(&addressReceived, &dataReceived, &lengthReceived, &flagsReceived);

		while(messageReceived == 1)
		{
			messageReceived = 0;
			//if it has the reading bit set

			//printf("CAN_ID = 0x%.3lx\r\n", addressReceived);
			
			if(((MASK_BPS_READING | MASK_BPS_SLAVE) | addressReceived) == (MASK_BPS_READING | MASK_BPS_SLAVE))
			{
				//just behave as if it is a slave and print out the information received
				received_CAN_ID = (addressReceived & MASK_BPS_SLAVE) >> 2;
				//memcpy(&voltage, dataReceived, 2);	//requires string.h
				memcpy_reduced(&voltage, dataReceived);
				temp = dataReceived[2];
				printf("V[%.2d]=%u\n\r", received_CAN_ID, voltage);
				printf("T[%.2d]=%.2d\n\r", received_CAN_ID, temp);
			}
			else if(((MASK_BPS_MASTER | MASK_BPS_READING) == addressReceived)) //if current reading
			{
				if(lengthReceived == 4)
				{
					int i; int d;
					unsigned char *test ;
					signed long * current_u;
				//	signed int *stupid;
					test = (void*) dataReceived;
				//	memcpy_reduced(&current, dataReceived);

					current_u = (void*)dataReceived;
				//for(i = 0; i < 4; i++) printf("[%d]  --  %x  --- %x\n\r",i,test[i], dataReceived[i]);
				printf("BC=%ld\n\r",*current_u);
				}
			}
			else if(((MASK_BPS_MASTER | MASK_BPS_READING | MASK_ENERGY) == addressReceived)) //if energy reading
			{
				if(lengthReceived == 4)
				{
					long *energy = (void*)dataReceived;
					printf("E=%ld\n\r",*energy);
				}
			}
			else if(((MASK_BPS_MASTER | MASK_BPS_READING | MASK_CBS) == addressReceived))	//if shutdown message or cbs reading
			{
				
				if(lengthReceived == 4)
				{
					printf("Shutting Car Down\n\r");
					memcpy_reduced(&voltage, &(dataReceived[1]));
					temp = dataReceived[3];
					printf("Addr = %.2x\n\r", dataReceived[0]);
					printf("Volt = %u\n\r", voltage);
					printf("temp = %.2d\n\r", temp);
				}
				if(lengthReceived == 1)
				{
					unsigned char * module;
					module = (void*) dataReceived;
					printf("CBS=%d\n\r",*module);

				}
			}
			
			//check for any more messages
			//for(i=0; i<1000; ++i);
			messageReceived = ECANReceiveMessage(&addressReceived, &dataReceived, &lengthReceived, &flagsReceived);
		}
Esempio n. 7
0
void main(void) {

	/*************************
	 * Variable Declarations *
	 *************************/

    BYTE radio_sw[2], drs_over_sw[2], fan_over_sw[2], fuel_map_sw[2], paddle_l_sw[2], paddle_r_sw[2];
    BYTE ADLmsg[8];
	BYTE cycleStates[2], intensity;
	unsigned int bounceTimer[2];
	unsigned int CAN_tmr;


    /*********************
     * Oscillator Set-Up *
     *********************/
    #ifdef INTERNAL
            // OSCTUNE
            OSCTUNEbits.INTSRC = 0;		// Internal Oscillator Low-Frequency Source Select (1 for 31.25 kHz from 16MHz/512 or 0 for internal 31kHz)
            OSCTUNEbits.PLLEN = 1;		// Frequency Multiplier PLL Select (1 to enable)
            OSCTUNEbits.TUN5 = 0;		// Fast RC Oscillator Frequency Tuning (seems to be 2's comp encoding)
            OSCTUNEbits.TUN4 = 0;		// 011111 = max
            OSCTUNEbits.TUN3 = 0;		// ... 000001
            OSCTUNEbits.TUN2 = 0;		// 000000 = center (running at calibrated frequency)
            OSCTUNEbits.TUN1 = 0;		// 111111 ...
            OSCTUNEbits.TUN0 = 0;		// 100000

            // OSCCCON
            OSCCONbits.IDLEN = 1;		// Idle Enable Bit (1 to enter idle mode after SLEEP instruction else sleep mode is entered)
            OSCCONbits.IRCF2 = 1;		// Internal Oscillator Frequency Select Bits
            OSCCONbits.IRCF1 = 1;		// When using HF, settings are:
            OSCCONbits.IRCF0 = 1;		// 111 - 16 MHz, 110 - 8MHz (default), 101 - 4MHz, 100 - 2 MHz, 011 - 1 MHz
            OSCCONbits.SCS1 = 0;
            OSCCONbits.SCS0 = 0;

            // OSCCON2
            OSCCON2bits.MFIOSEL = 0;

            while(!OSCCONbits.HFIOFS);	// wait for stable clock

    #else
            // OSCTUNE
            OSCTUNEbits.INTSRC = 0;		// Internal Oscillator Low-Frequency Source Select (1 for 31.25 kHz from 16MHz/512 or 0 for internal 31kHz)
            OSCTUNEbits.PLLEN = 1;		// Frequency Multiplier PLL Select (1 to enable)

            // OSCCCON
            OSCCONbits.SCS1 = 0;		// select configuration chosen oscillator
            OSCCONbits.SCS0 = 0;		// SCS = 00

            // OSCCON2
            OSCCON2bits.MFIOSEL = 0;

            while(!OSCCONbits.OSTS);	// wait for stable external clock
    #endif

    /*********************
     * Peripherals Setup *
     *********************/

	// turn on and configure the A/D converter module
	OpenADC(ADC_FOSC_64 & ADC_RIGHT_JUST & ADC_4_TAD, ADC_CH0 & ADC_INT_OFF, ADC_REF_VDD_VDD & ADC_REF_VDD_VSS & ADC_NEG_CH0);
	ANCON0 = 0b00100111;	// AN0 - 2 and AN5 are analog
	ANCON1 = 0x00;          // rest are digital
	TRISAbits.TRISA0 = INPUT;
	TRISAbits.TRISA1 = INPUT;
	TRISAbits.TRISA2 = INPUT;
	TRISAbits.TRISA5 = INPUT;

	// turn on and configure the TIMER1 oscillator
	OpenTimer0(TIMER_INT_ON & T0_8BIT & T0_SOURCE_INT & T0_PS_1_128);
	WriteTimer0(0x82);		// load timer register
	millis = 0;				// clear milliseconds count
	INTCONbits.TMR0IE = 1;	// turn on timer0 interupts

    // SPI setup
    SSPSTATbits.CKE = 1;		// SPI Clock Select, 1 = transmit on active to idle
    SSPCON1bits.CKP = 0;		// Clock Polarity Select, 0 = low level is idle state
    SSPCON1bits.SSPM = 0b1010;	// Clk Frequecy (Note: FOSC = 64MHz)
    SSPCON1bits.SSPEN = 1;      // SPI Enable, 1 enables

    // SPI pin I/O setup
    TRISCbits.TRISC3 = OUTPUT;	// SCK
    TRISCbits.TRISC5 = OUTPUT;	// SDO
    TRISDbits.TRISD3 = OUTPUT;	// CS
    CS = 1;

	// driver set up
	intensity = 0x0F;
	driver_write(DISP_MODE, NORMAL);		// leave test mode
	driver_write(SHUTDOWN, SHUTDOWN_OFF);	// leave shutdown mode
	driver_write(INTENSITY, intensity);		// set brightness to highest
    driver_write(SCAN, FULL_SCAN);          // Set scan to all digits
    driver_write(DECODE, NO_DECODE);        // Decoding disabled

	// set displays to display zero
	write_gear(0);
	write_num(0, 2, LEFT);
	write_num(0, 2, RIGHT);

	// intialize states
	cycleStates[LEFT] = CYCLE_L;
	cycleStates[RIGHT] = CYCLE_R;
	holdText[LEFT] = holdText[RIGHT] = TRUE;
	refreshTime[LEFT] = refreshTime[RIGHT] = holdTimer[LEFT] = holdTimer[RIGHT] =
						blinkTimer[LEFT] = blinkTimer[RIGHT] = millis;
	displayStates[LEFT] = OIL_T;
	displayStates[RIGHT] = ENGINE_T;

	ECANInitialize();		// setup ECAN

    // interrupts setup
	INTCONbits.GIE = 1;		// Global Interrupt Enable (1 enables)
	INTCONbits.PEIE = 1;	// Peripheral Interrupt Enable (1 enables)
	RCONbits.IPEN = 0;		// Interrupt Priority Enable (1 enables)

	TRISCbits.TRISC6 = OUTPUT;	// programmable termination
	TERM_LAT = FALSE;

	while(1) {

		// check for change in button state
		if(cycleStates[LEFT] != CYCLE_L & millis - bounceTimer[LEFT] > BOUNCE_TIME) {
			// save new state
			cycleStates[LEFT] = CYCLE_L;
			bounceTimer[LEFT] = millis;
			// only change display if button is low
			if(!cycleStates[LEFT]) {
				if(++displayStates[LEFT] == NUM_CHAN)
					displayStates[LEFT] = 0;
				// put the appropriate text on the displays and
				// get the current time for timing logic
				updateText(LEFT, displayStates);
				holdText[LEFT] = TRUE;
				blinkTimer[LEFT] = holdTimer[LEFT] = millis;
			}
		}
		if(cycleStates[RIGHT] != CYCLE_R  & millis - bounceTimer[RIGHT] > BOUNCE_TIME) {
			cycleStates[RIGHT] = CYCLE_R;
			bounceTimer[RIGHT] = millis;
			if(!cycleStates[RIGHT]) {
				if(++displayStates[RIGHT] == NUM_CHAN)
					displayStates[RIGHT] = 0;
				updateText(RIGHT, displayStates);
				holdText[RIGHT] = TRUE;
                blinkTimer[RIGHT] = holdTimer[RIGHT] = millis;
			}
		}

		// update left and right displays with text or numerical data
		updateDisp(LEFT);
		updateDisp(RIGHT);
		write_gear(gear);

        // radio button
        if(!RADIO) {
            radio_sw[0] = 0x13;
            radio_sw[1] = 0x88;
        }
        else
            *(int *)radio_sw = 0;
#if 0
        // paddle switches
        if(PADDLE_L) {
            paddle_l_sw[0] = 0x13;
            paddle_l_sw[1] = 0x88;
        }
        else
            *(int *)paddle_l_sw = 0;
        if(PADDLE_R) {
            paddle_r_sw[0] = 0x13;
            paddle_r_sw[1] = 0x88;
        }
        else
            *(int *)paddle_r_sw = 0;
#endif
        // DRS override switch
        if(DRS_OVER) {
            drs_over_sw[0] = 0x13;
            drs_over_sw[1] = 0x88;
        }
        else
            *(int *)drs_over_sw = 0;
        // fan override switch
        if(FAN_OVER) {
            fan_over_sw[0] = 0x13;
            fan_over_sw[1] = 0x88;
        }
        else
            *(int *)fan_over_sw = 0;
        // fuel map switch
        if(FUEL_MAP) {
            fuel_map_sw[0] = 0x13;
            fuel_map_sw[1] = 0x88;
        }
        else
            *(int *)fuel_map_sw = 0;

		if(millis - CAN_tmr > CAN_PER) {
			CAN_tmr = millis;
			// send out the first three sampled switches
			ADLmsg[0] = 0x00;
			ADLmsg[1] = 0x00;
			ADLmsg[ADL1] = radio_sw[0];
			ADLmsg[ADL1 + 1] = radio_sw[1];
			ADLmsg[ADL2] = fan_over_sw[0];
			ADLmsg[ADL2 + 1] = fan_over_sw[1];
			ADLmsg[ADL3] = fuel_map_sw[0];
			ADLmsg[ADL3 + 1] = fuel_map_sw[1];
			ECANSendMessage(ADLid, ADLmsg, 8, ECAN_TX_STD_FRAME | ECAN_TX_NO_RTR_FRAME | ECAN_TX_PRIORITY_1);
			// send out first three rotary encoders
			ADLmsg[0] = 0x01;
			ADLmsg[1] = 0x00;
			ADLsample(ADLmsg, ADL4, LAUNCH_ROT);
			ADLsample(ADLmsg, ADL5, TRAC_ROT);
			ADLsample(ADLmsg, ADL6, DRS_ROT);
			ECANSendMessage(ADLid, ADLmsg, 8, ECAN_TX_STD_FRAME | ECAN_TX_NO_RTR_FRAME | ECAN_TX_PRIORITY_1);
		}



	} // end main loop

	return;
}
Esempio n. 8
0
void main(void)
{
    char TempVar;

    // variable used for IMU chip Autotest
    unsigned char IMUAutotestResult;

    // structure used to store IMU data
    struct IMUData CurrentIMUData;

    //  variable for CAN TX FIFO buffer
    struct CANTxMsg TempCANTxMsg;

    //  variable for CAN RX FIFO buffer
    struct CANRxMsg TempCANRxMsg;

    
    


    //----------------------------------------------------
    //----------  CPU internal configurations: -----------
    //----------------------------------------------------

    CLRWDT();                                 // clear watchdog timer at startup

    /* Configure the oscillator for the CPU */
    ConfigureOscillator();
    __delay_ms(10);             // wait for Oscillator to be stabilized


    // configure CPU GPIO for IMU board
    ConfigureGPIO();

   
    //USART Initialize();
    ConfigureUSART1();
    ConfigureUSART2();

    
    // SPI initialize
    ConfigureSPI();
    
    //CAN controller Initialize
    ECANInitialize();
    //Set MASK and Filters for CAN
    ECANFiltersInit();

    // Timers configuration
    ConfigureTimers();

    
    //----------------------------------------------------
    //----------  Global variables initialisation --------
    //----------------------------------------------------

    // tick counter initialisation
    TickCounter.AccelTick_ms=0;         
    TickCounter.GyroTick_ms=1;
    TickCounter.MagnetTick_ms=2;

    // initialize CAN tx FIFO
    CANTxFifoInit();
    CANRxFifoInit();

    // initialise USART RX FIFO's
    USARTFifoInit ();


    //----------------------------------------------------
    //------  external peripheral configurations: --------
    //----------------------------------------------------

    __delay_ms(10);              // wait for reset to be released on external peripherals
    
    ISM_RESET = 0;               // release reset of ISM module

    IMUInitRegisters();         // init of BMX055 chip
    IMUAutotestResult=IMUAutotest();              // launch IMU autotest

       
    //----------------------------------------------------
    //----------      GSM startup delay        -----------
    //----------------------------------------------------

    GSM_RTS=1;
    for(char i=0;i<200;i++)
    {
        __delay_ms(10);
        CLRWDT();                                 // clear watchdog timer each loop

    }
    GSM_RTS=0;

    __delay_ms(10);
    __delay_ms(10);


    //----------------------------------------------------
    //----------    Ready to go in main loop:  -----------
    //----------    interrupts activation      -----------
    //----------------------------------------------------
    
    ConfigureInterrupts();

    LED1=1;                     // everything is initialized: enable the PWR/booted LED

    //----------------------------------------------------
    //----------     GSM dummy AT command      -----------
    //----------------------------------------------------

    USART1Write('A');
    USART1Write('T');
    USART1Write(0x0D);

    for(char i=0;i<10;i++)
    {
        __delay_ms(10);
    }

    //-----------------------------------------------------
    //-------------  infinite main loop ----------
    //----------------------------------------------------


    while(1)
    {

        //--------------------------------------------------------------------------------
        //-------------  periodic tasks occures according to TickCounter variable----------
        //--------------------------------------------------------------------------------

        if(TickCounter.AccelTick_ms>IMU_TICK_PERIOD)
        {
            CLRWDT();                                 // clear watchdog timer each real time cycles

            LED2=1;
            TickCounter.AccelTick_ms=0;                // reset IMU tick counter to 0
            CurrentIMUData = IMUUpdateData();        // update IMU data from sensor

            // send Accelerometer data to CAN Fifo
        
            TempCANTxMsg.data_TX[0]=(char)(CurrentIMUData.XAccelerationData>>8);      //fill data buffer
            TempCANTxMsg.data_TX[1]=(char)(CurrentIMUData.XAccelerationData);
            TempCANTxMsg.data_TX[2]=(char)(CurrentIMUData.YAccelerationData>>8);
            TempCANTxMsg.data_TX[3]=(char)(CurrentIMUData.YAccelerationData);
            TempCANTxMsg.data_TX[4]=(char)(CurrentIMUData.ZAccelerationData>>8);
            TempCANTxMsg.data_TX[5]=(char)(CurrentIMUData.ZAccelerationData);
            TempCANTxMsg.data_TX[6]=0;
            TempCANTxMsg.data_TX[7]=0;

            TempCANTxMsg.dataLen= ACCEL_DATA_MESSAGE_LEN;
            TempCANTxMsg.id = (CAN_MESSAGE_IMU_TYPE << 7 | CAN_DEVICE_ADRESS <<4 | ACCEL_DATA_MESSAGE_ADRESS );
            TempCANTxMsg.flags = ECAN_TX_STD_FRAME;

            if(!CANTxFifo.Fifofull)
                 PutCANTxFifo(TempCANTxMsg);

            LED2=0;

        }

        if(TickCounter.GyroTick_ms>IMU_TICK_PERIOD)
        {
            //LED2=1;
            TickCounter.GyroTick_ms=0;                // reset IMU tick counter to 0

            // send Gyro data to CAN Fifo
        
            TempCANTxMsg.data_TX[0]=(char)(CurrentIMUData.XGyroscopeData>>8);
            TempCANTxMsg.data_TX[1]=(char)(CurrentIMUData.XGyroscopeData);
            TempCANTxMsg.data_TX[2]=(char)(CurrentIMUData.YGyroscopeData>>8);
            TempCANTxMsg.data_TX[3]=(char)(CurrentIMUData.YGyroscopeData);
            TempCANTxMsg.data_TX[4]=(char)(CurrentIMUData.ZGyroscopeData>>8);
            TempCANTxMsg.data_TX[5]=(char)(CurrentIMUData.ZGyroscopeData);

            TempCANTxMsg.dataLen= GYRO_DATA_MESSAGE_LEN;
            TempCANTxMsg.id = (CAN_MESSAGE_IMU_TYPE << 7 | CAN_DEVICE_ADRESS <<4 | GYRO_DATA_MESSAGE_ADRESS );
            TempCANTxMsg.flags = ECAN_TX_STD_FRAME;

            if(!CANTxFifo.Fifofull)
                 PutCANTxFifo(TempCANTxMsg);

        }
Esempio n. 9
0
/**
 * void main(void)
 *
 * Main program execution function
 */
void main(void) {

  /**
   * General initialization
   */

  init_unused_pins();
  init_oscillator();
  init_timer0();
  init_timer1();

  /**
   * Initialize I/O pins
   */

  // Init CAN termination pin
  TERM_TRIS = OUTPUT;
  TERM_LAT = 1; // Terminating

  // Init RADIO pins
#if FRONT
  RADIO0_TRIS = INPUT;
  RADIO1_TRIS = INPUT;
#endif

#if FRONT // Init FRONT ADC pins
  ADC_SPFL_TRIS = INPUT;
  ADC_SPFR_TRIS = INPUT;
  ADC_BPF_TRIS = INPUT;
  ADC_BPR_TRIS = INPUT;
  ADC_STRP_TRIS = INPUT;
  ADC_APPS0_TRIS = INPUT;
  ADC_APPS1_TRIS = INPUT;
  ADC_PTDP_TRIS = INPUT;

  ADC_UAN0_TRIS = OUTPUT;
  ADC_UAN0_LAT = 0;
#elif REAR // Init REAR ADC pins
  ADC_SPRL_TRIS = INPUT;
  ADC_SPRR_TRIS = INPUT;
  ADC_EOS_TRIS = INPUT;
  ADC_BCD_TRIS = INPUT;
  ADC_CTRI_TRIS = INPUT;
  ADC_CTRO_TRIS = INPUT;
  ADC_CTSP_TRIS = INPUT;
  ADC_CPSP_TRIS = INPUT;
  ADC_MCD_TRIS = INPUT;

  ADC_UAN0_TRIS = OUTPUT;
  ADC_UAN0_LAT = 0;
  ADC_UAN1_TRIS = OUTPUT;
  ADC_UAN1_LAT = 0;
#endif

  /**
   * Setup Peripherals
   */

#if FRONT
  ANCON0 = 0b11100110; // All analog except for AN0, AN3, AN4
  ANCON1 = 0b00000111; // All digital except for AN8, AN9, AN10
#elif REAR
  ANCON0 = 0b11111111; // All analog
  ANCON1 = 0b00000111; // All digital except for AN8, AN9, AN10
#endif
  init_ADC();

  ECANInitialize();

  // Interrupts setup
  INTCONbits.GIE = 1;		// Global Interrupt Enable (1 enables)
  INTCONbits.PEIE = 1;	// Peripheral Interrupt Enable (1 enables)
  RCONbits.IPEN = 0;		// Interrupt Priority Enable (1 enables)

  // Main loop
  while(1) {

    // Sample and send fast speed sensor channels on CAN
    send_fast_can();

    // Sample and send medium speed sensor channels on CAN
    send_med_can();

    // Sample and send slow speed sensor channels on CAN
    send_slow_can();

    // Send diagnostic CAN message
    send_diag_can();

#if FRONT
    if (radio_sw) {
      RADIO0_TRIS = OUTPUT;
      RADIO1_TRIS = OUTPUT;
      RADIO0_LAT = 0;
      RADIO1_LAT = 0;
    } else {
      RADIO0_TRIS = INPUT;
      RADIO1_TRIS = INPUT;
    }
#endif
  }
}