#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "lcd.h"
#include "kniznica.h"

#define _XTAL_FREQ 4000000

// CONFIG1L
#pragma config FEXTOSC = OFF    // External Oscillator Selection (Oscillator not enabled)
#pragma config RSTOSC = HFINTOSC_1MHZ// Reset Oscillator Selection (HFINTOSC with HFFRQ = 4 MHz and CDIV = 4:1)

// CONFIG1H
#pragma config CLKOUTEN = OFF   // Clock out Enable bit (CLKOUT function is disabled)
#pragma config PR1WAY = ON      // PRLOCKED One-Way Set Enable bit (PRLOCK bit can be cleared and set only once)
#pragma config CSWEN = ON       // Clock Switch Enable bit (Writing to NOSC and NDIV is allowed)
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor enabled)

// CONFIG2L
#pragma config MCLRE = EXTMCLR  // MCLR Enable bit (If LVP = 0, MCLR pin is MCLR; If LVP = 1, RE3 pin function is MCLR )
#pragma config PWRTS = PWRT_OFF // Power-up timer selection bits (PWRT is disabled)
#pragma config MVECEN = ON      // Multi-vector enable bit (Multi-vector enabled, Vector table used for interrupts)
#pragma config IVT1WAY = ON     // IVTLOCK bit One-way set enable bit (IVTLOCK bit can be cleared and set only once)
#pragma config LPBOREN = OFF    // Low Power BOR Enable bit (ULPBOR disabled)
#pragma config BOREN = SBORDIS  // Brown-out Reset Enable bits (Brown-out Reset enabled , SBOREN bit is ignored)

// CONFIG2H
#pragma config BORV = VBOR_2P45 // Brown-out Reset Voltage Selection bits (Brown-out Reset Voltage (VBOR) set to 2.45V)
#pragma config ZCD = OFF        // ZCD Disable bit (ZCD disabled. ZCD can be enabled by setting the ZCDSEN bit of ZCDCON)
#pragma config PPS1WAY = ON     // PPSLOCK bit One-Way Set Enable bit (PPSLOCK bit can be cleared and set only once; PPS registers remain locked after one clear/set cycle)
#pragma config STVREN = ON      // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config DEBUG = OFF      // Debugger Enable bit (Background debugger disabled)
#pragma config XINST = OFF      // Extended Instruction Set Enable bit (Extended Instruction Set and Indexed Addressing Mode disabled)

// CONFIG3L
#pragma config WDTCPS = WDTCPS_31// WDT Period selection bits (Divider ratio 1:65536; software control of WDTPS)
#pragma config WDTE = OFF       // WDT operating mode (WDT Disabled; SWDTEN is ignored)

// CONFIG3H
#pragma config WDTCWS = WDTCWS_7// WDT Window Select bits (window always open (100%); software control; keyed access not required)
#pragma config WDTCCS = SC      // WDT input clock selector (Software Control)

// CONFIG4L
#pragma config BBSIZE = BBSIZE_512// Boot Block Size selection bits (Boot Block size is 512 words)
#pragma config BBEN = OFF       // Boot Block enable bit (Boot block disabled)
#pragma config SAFEN = OFF      // Storage Area Flash enable bit (SAF disabled)
#pragma config WRTAPP = OFF     // Application Block write protection bit (Application Block not write protected)

// CONFIG4H
#pragma config WRTB = OFF       // Configuration Register Write Protection bit (Configuration registers (300000-30000Bh) not write-protected)
#pragma config WRTC = OFF       // Boot Block Write Protection bit (Boot Block (000000-0007FFh) not write-protected)
#pragma config WRTD = OFF       // Data EEPROM Write Protection bit (Data EEPROM not write-protected)
#pragma config WRTSAF = OFF     // SAF Write protection bit (SAF not Write Protected)
#pragma config LVP = ON         // Low Voltage Programming Enable bit (Low voltage programming enabled. MCLR/VPP pin function is MCLR. MCLRE configuration bit is ignored)

// CONFIG5L
#pragma config CP = OFF         // PFM and Data EEPROM Code Protection bit (PFM and Data EEPROM code protection disabled)

// CONFIG5H

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#define Btn_LDO         !PORTAbits.RA0
#define Btn_boost       !PORTAbits.RA1
#define Btn_buck        !PORTAbits.RA2
#define Btn_pump        !PORTAbits.RA3
#define Btn_in          !PORTAbits.RA4

#define LED_in           PORTAbits.RA6
#define LED_pump         PORTCbits.RC0
#define LED_LDO          PORTCbits.RC1
#define LED_boost        PORTCbits.RC2
#define LED_buck         PORTCbits.RC3
#define LED_load_LDO     PORTEbits.RE0
#define LED_load_boost   PORTEbits.RE1
#define LED_load_buck    PORTEbits.RE2

#define SW_LDO           LATFbits.LF0
#define SW_boost         LATFbits.LF1
#define SW_buck          LATFbits.LF2
#define SW_pump          LATFbits.LF3
#define SW_load_LDO      LATFbits.LF5
#define SW_load_boost    LATFbits.LF6
#define SW_load_buck     LATFbits.LF7

char status_Btn_in = 0, status_Btn_LDO = 0, status_Btn_boost = 0, status_Btn_buck = 0, status_Btn_pump = 0; 
char status_Btn_in_prev = 0, status_Btn_LDO_prev = 0, status_Btn_boost_prev = 0, status_Btn_buck_prev = 0, status_Btn_pump_prev = 0; 
char Btn_in_count = 0; 
char buffer[16];
uint8_t supply_state = 0, variable =0, status_variable = 0, variable_change = 0, first_row = 0;
float temp;
uint16_t resultAD;

void __interrupt(irq(IRQ_CCP1)) CCP1Isr(void)
{
    status_Btn_in = Btn_in;
    status_Btn_LDO = Btn_LDO;
    status_Btn_boost = Btn_boost;
    status_Btn_buck = Btn_buck;
    status_Btn_pump = Btn_pump;
    status_variable = variable;
    
	if(status_Btn_in == 1 && status_Btn_in_prev == 0)
    {
         Btn_in_count = 1;
    }
    
    if(status_Btn_LDO == 1 && status_Btn_LDO_prev == 0)
    {
        variable = 1;
    }
    
    if(status_Btn_boost == 1 && status_Btn_boost_prev == 0)
    {
        variable = 2;
    }
    
    if(status_Btn_buck == 1 && status_Btn_buck_prev == 0)
    {
        variable = 3;
    }
    
    if(status_Btn_pump == 1 && status_Btn_pump_prev == 0)
    {
        variable = 4;
    }
    
    if(variable != status_variable)
    {
        variable_change = 1;
    }
    
    status_Btn_in_prev = status_Btn_in;
    status_Btn_LDO_prev = status_Btn_LDO;
    status_Btn_boost_prev = status_Btn_boost;
    status_Btn_buck_prev = status_Btn_buck;
    status_Btn_pump_prev = status_Btn_pump;
    
    PIR4bits.CCP1IF = 0; //CCP1 flag off
}

void __interrupt(irq(default)) defaultIsr(void)
{

}

void main () 
{
    pinSet();
    supplyOff();
    
    initTimer();    
    initAdc();
    initLcd();
    
    posLcd (1, 4); //Vypisane do stredu prveho riadku
    writeLcd ("ZVOL ZDROJ");
    
    initB();
    
    while (1)
    {
        if(Btn_in_count) //Ak sa stlaci tlacidlo zapojenia zdroja
        {
            if(supply_state == 0) //Ak nie je zapojeny ziadny zdroj do obvodu
            {
                if(variable !=0) //Ak je zvoleny zdroj
                {
                    variable_change = 0; //Premenna variable_change sa nastavi do nuly, aby sa mohol nastavit iny zdroj
                    LED_in = 1; //LED in sa zapne
                    clearLcdRow (1); //Vycisti sa prvy riadok
                    posLcd (1, 2); //Vypise do stredu prveho riadku
                    writeLcd ("ZAPNUTY ZDROJ");
                    first_row = 0; //Indikacia napisu v prvom riadku "ZAPNI ZDROJ" - ak nie je tak 0
                    switch(variable)
                    {
                       case 1:
                           SW_LDO = 1;
                           SW_load_LDO = 1;
                           break;
                       case 2:
                           SW_boost = 1;
                           SW_load_boost = 1;
                           break;
                       case 3:   
                           SW_buck = 1;
                           SW_load_buck = 1;
                           break;
                       case 4:
                           SW_pump = 1;
                           break;
                       default:
                           supplyOff();
                           break;
                    }
                    supply_state = 1; //Nastavi sa premenna zapojeneho zdroja, tzn. nejaky zdroj je zapojeny do obvodu
                }
            }
            else //Ak uz je zapojeny nejaky zdroj do obvodu
            {
                supplyOff(); //Vynuluju sa vsetky zdroje
                variable = 0; //Nie je vybrany ziadny zdroj
                supply_state = 0; //Nie je do obvodu zapojeny ziadny zdroj
                clearLcd(); //Vycisti sa Lcd
                posLcd (1, 4); //Vypisane do stredu prveho riadku
                writeLcd ("ZVOL ZDROJ");
            }
            Btn_in_count = 0;
        }
        
        if(variable != 0 && supply_state == 0) //Ak je vybrany zdroj a ziadny nie je zapojeny
        {
            supplySet (variable); //Zasvietia LED pri vybranom zdroji a jeho zatazi
            if(first_row == 0) //Ak je napis iny ako "ZAPNI ZDROJ" vynuluje sa prvy riadok
            {
                clearLcdRow (1); //Vycisti sa prvy riadok
                first_row = 1; //Napis v prvom riadku je "ZAPNI ZDROJ"
            }
            posLcd (1, 3); //Vypise do stredu prveho riadku
            writeLcd ("ZAPNI ZDROJ");
            displaySupply(); //Zobrazi na displeji zvoleny zdroj a jeho individualnu zataz
        }
        else if(variable_change == 1 && supply_state == 1) //Ak bol vybrany novy zdroj a nejaky zdroj je zapojeny do obvodu
        {
            supplySet (variable); //Odpoji sa zapojeny zdroj a nastavi sa novy
            LED_in = 0; 
            supply_state = 0; //Nie je zspojeny ziadny zdroj do obvodu
            variable_change = 0; //Premenna zmeny zdroja do nuly
            if(first_row == 0) //Ak je napis iny ako "ZAPNI ZDROJ" vynuluje sa prvy riadok
            {
                clearLcdRow (1); //Vycisti sa prvy riadok
                first_row = 1;
            }
            posLcd (1, 3); //Vypise do stredu prveho riadku
            writeLcd ("ZAPNI ZDROJ");
            displaySupply(); //Zobrazi na displeji zvoleny zdroj a jeho individualnu zataz
        }
        
        if(PIR6bits.TMR3IF)
        {
            if(variable <= 4 && variable != 0)
            {
                updateTemperature();
                PIR6bits.TMR3IF = 0; //TMR3 flag off
            }
        }
    }
}



