//Power Rangers
//Major Contributors: Anjola Ladenegan & Sarah Ritter
//Other Contributors: Evan Syers & Meaghan Hannon


//This file contains the reference curves in form of 3 dimensional arrays.
//This file also contains the power point tracking algorithm
#include <stdio.h>
#include <stdlib.h>
#include "SDlib.h"
#include "SDlib_LCD.h"
#include "configbitsrev2014vSarah.h"
#include <xc.h>
#include "Array_File.h"
#include <math.h>
#include <plib.h>




/*
 *
 */

void A2D_init(void);
int A2D_conv_voltage(void);
int A2D_conv_current(void);
int A2D_conv_battery(void);
double PowerPoint(double, double);
double DutyCycle (double, double);
void PWM_Generator(double);


int main(int argc, char** argv) {



    double voltage;
    double current1 = 4.75;
    double current2 = 4.75;
    double battery;
    double reqvoltage;
    double dutycycle_des;
    double dutycycle_act=0;
    double voltageread;
    double currentread1;
    double currentread2;
    double batteryread;
    double currentout;

    LCD_init();
    serial_init(57600UL);
    set_output_device(2);

    A2D_init();

    double counter1=0;
    double counter2=0;


        
    while (1){

       /* dutycycle_des = 0;

            while(fabs(dutycycle_des-dutycycle_act)>0.001){
                if (dutycycle_des>dutycycle_act){
                    dutycycle_act = dutycycle_act + 0.0005;
                }
                else if(dutycycle_des<=dutycycle_act){
                    dutycycle_act = dutycycle_act - 0.0005;
                }
                PWM_Generator(dutycycle_act);
            }

        PWM_Generator(dutycycle_des);

        batteryread = A2D_conv_battery();
        //battery = (double) batteryread*((3.3/1023)*7);
        
        
        if(battery>12){
            for (counter1=0; counter1<100; counter1++){
                /*LCD_display_on();
                LCD_clear();
                LCD_setpos(0,0);
                printf("Battery Voltage > 12. Not Charging");
                dutycycle_act = dutycycle_des;
                delay_ms(250);
            }
        }*/
        //else{


            //for(counter2=0; counter2<500; counter2++){

            battery = 12;

            voltageread = A2D_conv_voltage();
            voltage = (double) voltageread*((3.3/1023)*9.3);

            currentread1 = A2D_conv_current();
            current1 = (double) currentread1*((3.3/1023)*(4.03));

            currentread2 = A2D_conv_current();
            current2 = (double) currentread2*((3.3/1023)*(4.03));

                if (fabs(currentread1-currentread2)>.5){
                    if (currentread1>currentread2){
                        currentout = current1;
                    }
                    else if (currentread2>currentread1){
                    currentout = current2;
                    }
                }
                else if(fabs(currentread1-currentread2)<.5){
                    currentout = current1;
                

        reqvoltage=PowerPoint(voltage, currentout);

        dutycycle_des=DutyCycle(reqvoltage,battery);

        if(dutycycle_act!=0){
           while(fabs(dutycycle_des-dutycycle_act)>0.001){
                if (dutycycle_des>dutycycle_act){
                     dutycycle_act = dutycycle_act + 0.0005;
                }
                 else if(dutycycle_des<=dutycycle_act){
                     dutycycle_act = dutycycle_act - 0.0005;
                }
            PWM_Generator(dutycycle_act);
            }
        }

        //dutycycle_des = .5;
        PWM_Generator(dutycycle_des);

        dutycycle_act = dutycycle_des;

        LCD_display_on();
        LCD_clear();
        LCD_setpos(0,0);
 
        printf("Voltage : %.4f\r   Current: %.4f\r    Battery : %.4f\r   DutyRatio: %.4f\r", voltage, currentout, battery, dutycycle_act);
        delay_ms(250);
        }
        
    

    }

    return (EXIT_SUCCESS);
}

void A2D_init(void){
//    AD1PCFG = 0; // This statement was giving us errors

    AD1CON1 = 0;
    AD1CON1bits.FORM = 4; // 32-bit unsigned Integer
    AD1CON2 = 0;
    AD1CON3 = 0;
    AD1CON3bits.ADCS = 3; // Set for the clock source
    AD1CON1bits.ON = 1;

}

 int A2D_conv_voltage(void){

    
    int data;
    AD1CHSbits.CH0SA = 4;
    AD1CON1bits.SAMP = 1; // Start Acquisition
    delay_us(1);
    AD1CON1bits.SAMP = 0; // Start Conversion

    while(!AD1CON1bits.DONE);
    data = ADC1BUF0; // Return Samples


    return (data);
}

 int A2D_conv_current(void){


    int data;
    AD1CHSbits.CH0SA = 5;
    AD1CON1bits.SAMP = 1; // Start Acquisition
    delay_us(1);
    AD1CON1bits.SAMP = 0; // Start Conversion

    while(!AD1CON1bits.DONE);
    data = ADC1BUF0; // Return Samples


    return (data);
 }


 int A2D_conv_battery(void){

         int data;
    AD1CHSbits.CH0SA = 6;
    AD1CON1bits.SAMP = 1; // Start Acquisition
    delay_us(1);
    AD1CON1bits.SAMP = 0; // Start Conversion

    while(!AD1CON1bits.DONE);
    data = ADC1BUF0; // Return Samples


    return (data);

 }

/* double PowerPoint (double voltage, double current){

    double incurr = current; //0.7;  //INCOMING CURRENT
    double involt = voltage; //20.5; //INCOMING VOLTAGE
    double voltagerange = 0.5;
    double d=0;
    int c=0;
    int p=0;
    int m=0;
    int n=0;
    int row,column;
    double minimum_holder=1;
    double minimum=0;
    double max=0.0;
    double volt=0.0;

    int i = 0;
    int j = 0;
    
    for (i = 0; i < 5; i++) 
    {
        for(j=0; j<20; j++) 
            {
            d=sqrt(pow((Array1[i][j][0]-involt),2)+(pow((Array1[i][j][1]-incurr),2)));
            
            if (d<=minimum_holder)
                {
                    minimum=d;

                }
                minimum_holder=d;
            if (d<=voltagerange)
                {

                    m++;
                    printf ("The distance to the curve is %f\n",d);
                    printf("Interpolated Voltage is = %g \n", Array1[i][j][0]);
                    printf("Interpolated Current is = %g \n", Array1[i][j][1]);
                    printf("Interpolated Power is %f\n",Array1[i][j][2]);
                    printf("This is on curve %d\n",i+1);
                    p=i;

                }
                            
            }
    }


            

        if (d==0)
            {
                //printf("This point is not close enough to any curve\n");
            }
        else
            {       

                for (c = 0; c < 20; c++)
                    {
                        if(Array1[p][c][2]>max)

                            {
                                max=Array1[p][c][2];
                                volt=Array1[p][c][0];   
                        
                            }                                      
                    }

                    //printf("The Maximum Power on that curve is %f\n", max);
                    //printf("The required voltage is %f\n",volt);
            }

 }*/

 double PowerPoint (double voltage, double current)
 {

    double incurr = current; //0.7;  //INCOMING CURRENT
    double involt = voltage; //20.5; //INCOMING VOLTAGE
    double max=0.0;
    double volt=0.0;
    double distarray[120]={0};
    int count=0;
    int location;
    int w=0;
    int position;
    int c=0;


    int i;
    int j;

    for (i = 0; i < 6; i++)
    {
        for( j=0; j<20; j++)
       {
            distarray[count]=sqrt(pow((Array1[i][j][0]-involt),2)+(pow((Array1[i][j][1]-incurr),2)));

            //printf("distance is %f\n", distarray[count]);
            count=count+1;
        }
    }


    double min = distarray[0];
    for ( w = 1 ; w < 120 ; w++ )
    {
        if ( distarray[w] < min )
        {
           min = distarray[w];
           location = w+1;
        }
    }
        //printf("The closest is : %f\n",min );
        //printf("located at %d\n",location);



        if (location<=20)
        {
                position=location-1;
                    //printf("Interpolated Voltage is = %g \n", Array1[0][position][0]);
                    //printf("Interpolated Current is = %g \n", Array1[0][position][1]);
                    //printf("Interpolated Power is %f\n",Array1[0][position][2]);
                    //printf("This is on curve 1\n");
                    for (c = 0; c < 20; c++)
                    {
                        if(Array1[0][c][2]>max)

                            {
                                max=Array1[0][c][2];
                                volt=Array1[0][c][0];

                            }

                    }




                    //printf("The Maximum Power on that curve is %f\n", max);
                    //printf("The required voltage is %f\n",volt);

        }



        if(location>20 && location<=40)
        {
        position=(location-20)-1;

                    //printf("Interpolated Voltage is = %g \n", Array1[1][position][0]);
                    //printf("Interpolated Current is = %g \n", Array1[1][position][1]);
                    //printf("Interpolated Power is %f\n",Array1[1][position][2]);
                    //printf("This is on curve 2\n");

                    for (c = 0; c < 20; c++)
                    {
                        if(Array1[1][c][2]>max)

                            {
                                max=Array1[1][c][2];
                                volt=Array1[1][c][0];

                            }

                    }




                    //printf("The Maximum Power on that curve is %f\n", max);
                    //printf("The required voltage is %f\n",volt);

        }



      if(location>40 && location<=60)
       {
        position=(location-40)-1;

                    //printf("Interpolated Voltage is = %g \n", Array1[2][position][0]);
                    //printf("Interpolated Current is = %g \n", Array1[2][position][1]);
                    //printf("Interpolated Power is %f\n",Array1[2][position][2]);
                    //printf("This is on curve 3\n");
                    for (c = 0; c < 20; c++)
                    {
                        if(Array1[2][c][2]>max)

                            {
                                max=Array1[2][c][2];
                                volt=Array1[2][c][0];

                            }

                    }




                    //printf("The Maximum Power on that curve is %f\n", max);
                    //printf("The required voltage is %f\n",volt);

        }



      if(location>60 && location<=80)
       {
        position=(location-60)-1;

                    //printf("Interpolated Voltage is = %g \n", Array1[3][position][0]);
                    //printf("Interpolated Current is = %g \n", Array1[3][position][1]);
                    //printf("Interpolated Power is %f\n",Array1[3][position][2]);
                    //printf("This is on curve 4\n");
                    for (c = 0; c < 20; c++)
                    {
                        if(Array1[3][c][2]>max)

                            {
                                max=Array1[3][c][2];
                                volt=Array1[3][c][0];

                            }

                    }




                    //printf("The Maximum Power on that curve is %f\n", max);
                    //printf("The required voltage is %f\n",volt);

        }


      if(location>80 && location<=100)
       {
        position=(location-80)-1;

                    //printf("Interpolated Voltage is = %g \n", Array1[4][position][0]);
                    //printf("Interpolated Current is = %g \n", Array1[4][position][1]);
                    //printf("Interpolated Power is %f\n",Array1[4][position][2]);
                    //printf("This is on curve 5\n");
                    for (c = 0; c < 20; c++)
                    {
                        if(Array1[4][c][2]>max)

                            {
                                max=Array1[4][c][2];
                                volt=Array1[4][c][0];

                            }

                    }




                    //printf("The Maximum Power on that curve is %f\n", max);
                    //printf("The required voltage is %f\n",volt);

        }


       if(location>100 && location<=120)
        {
        position=(location-100)-1;

                    //printf("Interpolated Voltage is = %g \n", Array1[5][position][0]);
                    //printf("Interpolated Current is = %g \n", Array1[5][position][1]);
                    //printf("Interpolated Power is %f\n",Array1[5][position][2]);
                    //printf("This is on curve 6");
                    for (c = 0; c < 20; c++)
                    {
                        if(Array1[5][c][2]>max)

                            {
                                max=Array1[5][c][2];
                                volt=Array1[5][c][0];

                            }

                    }

                    //printf("The Maximum Power on that curve is %f\n", max);
                    //printf("The required voltage is %f\n",volt);
        }

        if (min>=10)
            {
                //printf("This point is not close enough to any curve\n");
                volt=0;
            }
                    return volt;

    }



double DutyCycle (double reqvoltage, double batteryvoltage)
 {
     double duty;

    /*if(batteryvoltage < 3.000 || reqvoltage < 10.00){
        duty = 0;
    }*/
    //else {
        duty = batteryvoltage/reqvoltage;
    //}

    return duty;
 }


void PWM_Generator(double dutycycle)
{
    //SYSTEMConfigPerformance(SYSCLK); // function that optimizes performance of PIC32
    double systemclock = 80000000;
    double pwm_freq = 100000;


    OC1CON = 0x0000; // Turn off the OC1 when performing the setup
    OC1R = 0x0064; // Initialize primary Compare register
    OC1RS = 0x0064; // // Initialize secondary Compare register
    OC1CON = 0x0006; // Configure standard PWM mode for output compare module 1

    // A write to PRy configures the PWM frequency
    // PR = [FPB / (PWM Frequency * TMR Prescale Value)] ? 1
    // : note the TMR Prescaler is 1 and is thus ignored
    PR2 = (systemclock / pwm_freq) - 1;

    // A write to OCxRS configures the duty cycle
    // : OCxRS / PRy = duty cycle
    OC1RS = (PR2 + 1) * (dutycycle);

    T2CONSET = 0x8000;      // Enable Timer2, prescaler 1:1
    OC1CONSET = 0x8000;     // Enable Output Compare Module 1


}
