/*
 * File:   main.c
 * Author: hamilton
 *
 * Created on November 4, 2013, 4:11 PM
 */

#include <dsp.h>
#include <stdio.h>
#include <string.h>
#include "xc.h"
#include "UART.h"
#include "config.h"
#include "extern.h"
#include "conv.h"
#include "init.h"
#include "can.h"
#include "BatterySignalDecode.h"
#include "sendCANPackets.h"
#include "bms_hardware.h"
#include "I2C.h"



#define CHECK_BIT(var,pos) (((var)>>(pos)) & 1)


//_FOSCSEL(FNOSC_FRC) // FNOSC<2:0> = 000(FRC oscillator)  IES0 = 1  (Start with FRC and then switch to user selected clock when ready)
_FOSCSEL(FNOSC_PRIPLL)
_FOSC(FCKSM_CSECMD & OSCIOFNC_ON) // FCKSM<1:0> = 01 (clock switching enable, fail safe clock monitor disabled)   OSCIOFNC = 0 (OSC2 pin is GPIO)     POSCMD<1:0> = 11  (Primary oscillator disabled)
_FWDT(FWDTEN_OFF) // FWDTEN = 0(watchdog timer software enabled/disabled)  WINDIS = 1 (watchdog timer in non-window mode)  PLLKEN = 1 (clock switch to pll will wait for lock signal)  WDTPRE = 1 (1:128 watchdog prescaler)  WDTPOST<3:0> = 1111 (watchdog postscaler = 1:32768)
_FPOR(FPWRT_PWR128) //PWMPIN = 1 (MCPWM pins controlled by PORT register at device reset)   HPOL = 1 (MCPWM high side pins are active high)  LPOL = 1 (MCPWM low side pins are active high) FPWRT<2:0> = 11 (power on reset timer value = 128ms)
_FICD(ICS_PGD1 & JTAGEN_OFF) // JTAGEN = 0 (JTAG disabled)   ICS<1:0> = 11  (ICD communicate on PGEC1 and PGED1

float PH1PWM_DC = 0;
float PH2PWM_DC = 0;
float PH3PWM_DC = 0;
const int MC_PWM_Period = 0x7fff;


int step;
unsigned int halls = 0;
unsigned int pos;


void (*getErrLoc(void))(void); // Get Address Error Loc
void (*errLoc)(void); // Function Pointer   

int main(void) {

    int j;
    char s[256];
    float last_time = 0;

    /* Configure Oscillator to operate the device at ~10Mhz
       Fosc= Fin*M/(N1*N2), Fcy=Fosc/2
       Fosc= 7.37*(43)/(2*8)=19.806875Mhz for Fosc, Fcy = 9.9034375Mhz */
    /* Configure PLL prescaler, PLL postscaler, PLL divisor */
    PLLFBD = 41; /* M = PLLFBD + 2 */
    CLKDIVbits.PLLPOST = 0; /* N1 = 2 */
    CLKDIVbits.PLLPRE = 0; /* N2 = 2 */
    __builtin_write_OSCCONH(0x01); /* New Oscillator selection from FRC only, to FRC w/ PLL */
    //__builtin_write_OSCCONL(0x01); /* Request oscillator switch */
    __builtin_write_OSCCONL(0x03); /* Enable secondary (LP) oscillator and Request oscillator switch */

    while (OSCCONbits.COSC != 0b001); /* Wait for Oscillator to switch to FRC w/ PLL */
    while (OSCCONbits.LOCK != 1); /* Wait for Pll to Lock */

    //Set up UARTS
    InitU1();

    I2C1CONbits.I2CEN = 0;
    
    //init TMR1 to interrupt at 25Hz, based on 32768Hz crystal SOSC
    _T1IP = 2; //Set to lower priority than all the rest.
    TMR1 = 0; //Clear the timer

#if CAN_PACKET_RATE==25
    PR1 = 1311; //Should give a 25Hz interrupt at 32768Hz clock
    T1CON = 0x8002; //enabled, prescaler 1:1, external clock (SOSC)
#endif
#if CAN_PACKET_RATE==10
    //  PR1 =3277;  //Should give a 10Hz interrupt at 32768Hz clock
    T1CON = 0x8002; //enabled, prescaler 1:1, external clock (SOSC)
#endif
#if CAN_PACKET_RATE==5
    PR1 = 6554; //Should give a 5Hz interrupt at 32768Hz clock
    T1CON = 0x8002; //enabled, prescaler 1:1, external clock (SOSC)
#endif
    _T1IF = 0; //Clear Interrupt
    _T1IE = 0; //Keep Interrupt disabled until everything is set up.


    // init TMR3 to provide the timebase for interrupt that starts the AIO process
    T3CON = 0x8000;
    PR3 = 283 - 1; //Rolls over at 139 kHz and adc sampling.  
    _T3IF = 0; //Clear interrupt
    _T3IE = 0; //Keep Interrupt disabled.


    // TMR4is used to provide a microsecond resolution delay feature
    T4CON = 0x8000;
    PR4 = 400; //Rolls over at ~100kHz, provides 10uS resolution 
    _T4IF = 0; //Clear interrupt
    _T4IE = 1; //Enable Interrupt.

    //Setup digital outputs
    TRISAbits.TRISA9 = 1; //Don't make this an output, it's connected to ground as Vref-.
    TRISAbits.TRISA10 = 1; //Don't make this an output, it's connected to 3.3V as Vref+.


    //    TRISD = 0xffff;
    //    TRISDbits.TRISD0 = 0;  //CAN loopback pin, set low to make CAN work properly, or leave it an input?
    //   TRISDbits.TRISD2 = 0;  //Gas Bypass enable
    //    TRISDbits.TRISD3 = 0;  //Stepper Enable
    //    TRISDbits.TRISD12 = 0;  //Laser Rangefinder enable
    //    TRISDbits.TRISD15 = 0;  //UART1 RTS
    TRISD = 0x6ff2;
    _RD0 = 0; //Set CAN loopback pin low
    _RD12 = 1; //Enable rangefinder switch

    TRISE = 0xff00;


    TRISG = 0xffff;
    TRISGbits.TRISG0 = 0; // CAN SILENT
    TRISGbits.TRISG0 = 0; // CAN ENABLE:

    TRISGbits.TRISG1 = 0; //SCK2
    TRISGbits.TRISG6 = 1; //SCK2
    TRISGbits.TRISG7 = 1; //SDI2
    TRISGbits.TRISG8 = 0; //SDO2
    TRISGbits.TRISG9 = 1; //SS2
    TRISGbits.TRISG12 = 0; //BME Power
    TRISGbits.TRISG13 = 0; //Battery Switch GatePS Enable.
    TRISGbits.TRISG14 = 0; //Battery_Slow
    TRISGbits.TRISG15 = 0; //Battery_Switch

    _RG0 = 0; // CAN SILENT
    _RG1 = 1; // CAN SILENT
    
    _RG12 = 0;  //BME280 Power off

    //Set up motor control module, this periphial controls the PWM outputs that drive the relays.
    InitMCPWM();


    //Set up DMA channel and ADC
    InitDma0(); //Argument is number of samples to transfer per interrupt.
    InitADC_WithIntrpt();

    //Set up SPI
    InitSPI();
    
    InitIIC();
    //Enable CAN transceiver.    

    //init CAN bus
    InitCAN1(); //Setup CAN1
    InitDma12(); //Setup two DMA channels for use with CAN1
    for (j = 0; j < ECAN1_NUM_TX_BUFFERS; j++) //Setup CAN messages type and frame type for each message.
    {
        message[j].message_type = CAN_MSG_DATA; //data message
        message[j].frame_type = CAN_FRAME_EXT; //extended (29 bit identifier)
    }

    //Setup FIR filters
    FIRDelayInit(&ADC_Filter);

    Status.status = 0; //Initialize status union to zeros.

    // Enable Timer interrupts now that everything is set up.
    _T1IE = 1; //Enable 25Hz Interrupt, _T1Interrupt gets called at the beginning of each period.

    char EEPROM_Device_Addr = 0xA0;
    //int EEPROM_Reg_Addr = 0x00002000;
       int EEPROM_Reg_Addr = 0x00000000;

    _RA2 = 0; // Un-WriteProtect EEPROM

    
    char data[64];
    
    while (1) {
        if (time > last_time + 1) //Wait for time to be updated.
        {

            int N = 5;

            for (int i = 0; i<N; i++)
                data[i] = i;
            
           
          //  WriteI2CData(EEPROM_Device_Addr,EEPROM_Reg_Addr,data,N);
         
            
            unsigned int j = 10000;
            while(j-- >  0);
            
            for (int i = 0; i<N; i++)
                data[i] = 0x12;
            
            
            ReadI2CData(EEPROM_Device_Addr, EEPROM_Reg_Addr,data, N);

            last_time = time;

            sprintf(s, "%f  ", time); putsU1(s);
            for (int i = 0; i<N; i++)
            {                   
               sprintf(s," %d ",I2C_Data[i]);  putsU1(s);
            }
            sprintf(s,"\r\n");  putsU1(s);




        }
    }
    return 0;
} //main
