/*
 * File:   vezérl?1.c
 * Author: Otthon
 *
 * Created on 2016. február 20., 12:01
 */

#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <delays.h>

#define SW1     PORTCbits.RC0  //SWITCH 1 RC0 INPUT
#define SW2     PORTCbits.RC1  //SWITCH 2 RC1
#define SW3     PORTCbits.RC2  //SWITCH 3 RC2
#define SW4     PORTCbits.RC3  //SWITCH 4 RC3

#define LED1    LATDbits.LATD0  //LED 1 RD0 OUTPUT
#define LED2    LATDbits.LATD1  //LED 2 RD1
#define LED3    LATDbits.LATD2  //LED 3 RD2
#define LED4    LATDbits.LATD3  //LED 4 RD3

#define TROUT1    LATDbits.LATD4  //TRANZISTOR OUTPUT1 RD4
#define TROUT2    LATDbits.LATD5  //TRANZISTOR OUTPUT2 RD5

#define lcd_rs LATEbits.LATE2
#define lcd_rw LATEbits.LATE1
#define lcd_en LATEbits.LATE0
#define lcd_port LATB

unsigned int POT1;//AN0 duty
unsigned char POT2;//AN1 frequency
unsigned char flag1;//flag variable
unsigned char flag2;
unsigned char flag3;
unsigned char POT1_PRE;//POT1 PREVIOUS VALUE
unsigned char POT2_PRE;//POT2 PREVIOUS VALUE
unsigned char POT_1;//POT_1 FOR LCD
unsigned int POT_2;
unsigned int PTPER;//PTPER VALUE
unsigned short long PDC1;//PWM PDC1 VALUE
unsigned int PDC2;//PWM PDC2 VALUE
const rom unsigned int Freq_array[]={2500,	2500,	2500,	2500,	2500,	2500,	2500,	2500,	2475,	2475,	2475,	2475,	2463,	2463,	2463,	2463,	2451,	2451,	2451,	2451,	2439,	2439,	2439,	2439,	2427,	2427,	2427,	2427,	2415,	2415,	2415,	2415,	2404,	2404,	2404,	2404,	2392,	2392,	2392,	2392,	2381,	2381,	2381,	2381,	2370,	2370,	2370,	2370,	2358,	2358,	2358,	2358,	2347,	2347,	2347,	2347,	2336,	2336,	2336,	2336,	2326,	2326,	2326,	2326,	2315,	2315,	2315,	2315,	2304,	2304,	2304,	2304,	2294,	2294,	2294,	2294,	2283,	2283,	2283,	2283,	2273,	2273,	2273,	2273,	2262,	2262,	2262,	2262,	2252,	2252,	2252,	2252,	2242,	2242,	2242,	2242,	2232,	2232,	2232,	2232,	2222,	2222,	2222,	2222,	2212,	2212,	2212,	2212,	2203,	2203,	2203,	2203,	2193,	2193,	2193,	2193,	2183,	2183,	2183,	2183,	2174,	2174,	2174,	2174,	2165,	2165,	2165,	2165,	2155,	2155,	2155,	2155,	2146,	2146,	2146,	2146,	2137,	2137,	2137,	2137,	2128,	2128,	2128,	2128,	2119,	2119,	2119,	2119,	2110,	2110,	2110,	2110,	2101,	2101,	2101,	2101,	2092,	2092,	2092,	2092,	2083,	2083,	2083,	2083,	2075,	2075,	2075,	2075,	2066,	2066,	2066,	2066,	2058,	2058,	2058,	2058,	2049,	2049,	2049,	2049,	2041,	2041,	2041,	2041,	2033,	2033,	2033,	2033,	2024,	2024,	2024,	2024,	2016,	2016,	2016,	2016,	2008,	2008,	2008,	2008,	2000,	2000,	2000,	2000,	1992,	1992,	1992,	1992,	1984,	1984,	1984,	1984,	1976,	1976,	1976,	1976,	1969,	1969,	1969,	1969,	1961,	1961,	1961,	1961,	1953,	1953,	1953,	1953,	1946,	1946,	1946,	1946,	1938,	1938,	1938,	1938,	1931,	1931,	1931,	1931,	1923,	1923,	1923,	1923,	1916,	1916,	1916,	1916,	1908,	1908,	1908,	1908,	1901,	1901,	1901,	1901};
//PTMER VALUE ARRAY

void Timer_ISR(void);
#pragma code vector=0x08
void vector08(void){
    _asm goto Timer_ISR _endasm
}
#pragma code

#pragma interrupt Timer_ISR
void Timer_ISR(void){   //interrupt
    //TIMER INTERRUPT
  INTCONbits.TMR0IF = 0;
  T0CONbits.TMR0ON=0;
  TMR0H=0b10011000;//40MHz clock 40/4*10^6*128*39062=0,33sec
  TMR0L=0b10010110;
  T0CONbits.TMR0ON=1;
  
  //ADC
    POT1_PRE=POT1;
    POT2_PRE=POT2;
    ADCON0= 0b00000001;  //ADC ENEABLE
    Delay100TCYx(1);   //WAIT 10uSEC
    ADCON0bits.GODONE = 1;     //ADC START
    while(ADCON0bits.GODONE);   //WAITING FOR ADC FINISHED
    POT1 = ADRESH;  //RESULT HIGH BYTE IN POT1
    ADCON0=0b00000101;  //CHANNEL CHANGING
    Delay100TCYx(1);
    ADCON0bits.GODONE = 1;
    while(ADCON0bits.GODONE);
    POT2 = ADRESH;
    ADCON0bits.ADON = 0;
    
    //PWM if POT1 or POT2 changed ->PWM set, POT value change
    if(POT1_PRE!=POT1 || POT2_PRE!=POT2 || flag3==1){
    
    PTPER=POT2/4+200;   //PTPER BETWEEN 200-263->19KhZ-25KhZ POT2 FREQUENCY
    POT_1=POT1*100/255; //POT1 CONVERT BETWEEN 0-100
    POT_2=Freq_array[POT2];//POT2 value: 100*real frequency in kHz
    
    //PWM CHANNEL 0
    PDC1=PTPER*2;       //DUTY CYCLE MAX 50%
    PDC1=PDC1*POT1;
    PDC1=PDC1>>8;   //DIVIDE 256 (divide /255? or shift divide 256?)
    //PWM CHANNEL 1
    PDC2=PTPER*4;   //DUTY CYCLE=MAX DUTY CYCLE (PTPER*4)-PDC1
    
    if(PDC1<5){  //NAGYON ALACSONY KITÖLTÉSI TNYEZONÉL PWM és TIMER OFF
        PWMCON0=0x00;
        PTCON1bits.PTEN=0;
    }
    else{
    PDC2=PDC2-PDC1; //SYMMETRICAL SQUARE SIGNAL
    PWMCON0=0x00;   //PWM DISABLED
    PTCON1bits.PTEN=0;  //TIMER OFF
    OVDCOND=0b00000110; //PWM PIN0 and PWM PIN3 DISABLED, ACTIVE ONLY PWM1 ADN PWM2
    OVDCONS=0b00000001;
    
    PTPERL=PTPER&0xFF;  //PWM PERIOD WRITING
    PTPERH=PTPER>>8;
    PDC0L=PDC1&0xFF;    //DUTY CYCLE WRITING
    PDC0H=PDC1>>8;
    PDC1L=PDC2&0xFF;
    PDC1H=PDC2>>8;
    PTMRH=0;    //PWM TIMER=0
    PTMRL=0;
    PWMCON0=0b00110000; //PWM ENABLED
    PTCON1bits.PTEN=1;  //PWM TIMER ON
    }
    } 
    flag2=1;    //FLAG BIT FOR LCD WRITING
}
   
    //ADC-PORTA INITIAL
void INI_PORTS(void){
    LATA=0;
    TRISA=0X03;
    ANSEL0 = 0b00000011; //AN0, AN1 ANALOG OTHERS DIGITAL
    ANSEL1 = 0X00;
    ADCHS=0X00;
    ADCON0 = 0X00;  //SINGLE CHANNEL
    ADCON1 = 0X00;
    ADCON2 = 0b00110010;    //32Tosc 12TAD
    ADCON3 = 0b11000000;      //ADC INTERRUPT DISABLED
    
    //PORTB INITIAL
    LATB = 0x00;      //PORTB OUTPUT DELETED
    TRISB = 0X00;   //RB0-RB7 OUTPUT  
    
    //PORTC INITIAL
    LATC = 0x00;      //PORTC OUTPUT DELETED
    TRISC = 0X0F;   //RC0-RC3 INPUT, RC4-RC7 OUTPUT
    
    //PORTD INITIAL
    LATD = 0x00;      //PORTD OUTPUT DELETED
    TRISD = 0X00;   //RD0-RD7 OUTPUT
    
    //PORTE INITIAL
    LATE = 0x00;      //PORTE OUTPUT DELETED
    TRISE = 0X00;   //RE0-RE2 OUTPUT
    
    //timer ini
    INTCON=0b10100000;
    T0CON=0b00000110; //16Bit mode, prescaler 1:128
    
     //pwm config
    PTCON0=0b00000110; //countinous up-down count mode, prescale 1:4
    PWMCON1=0X00;
    DTCON=0;    //deadtime=0
    }
  
       //KIJELZO ENABLE LÁB BE-KI KAPCSOLÁSA
void lcd_en_pulse(void){
   Delay1KTCYx(3);//300usec várakozás
   lcd_en=1;
   Delay1KTCYx(3);
   lcd_en=0;
   Delay1KTCYx(3);
}

//FÉLBÁJTOK BEÍRÁSA A B PORTBA
void lcd_write_nibble(unsigned char data){
   lcd_port=data&0xF0;  //'ÉS'-ELÉS 0XF0-VAL, FELSO 4 BIT MARAD ALSÓK MIND 0
   lcd_en_pulse();
   }

//A BEÉRKEZO 8 BIT SZÉTVÁLASZTÁSA FÉLBÁJTOKRA
void lcd_write(unsigned char data){
    lcd_write_nibble(data);
    lcd_write_nibble(data<<4); //SHIFTELÉS JOBBRA 4-EL ALSÓ 4 BIT A FELSOBE
    Delay1KTCYx(1);//100usec várakozás
}

//ADATÍRÁS
void lcd_write_data(unsigned char data){
    lcd_rs=1;
    lcd_write(data);
}

//PARANCS KIADÁS
void lcd_write_command(unsigned char data){
    lcd_rs=0;
    lcd_write(data);
} 

    //LCD INICIALIZÁLÁSA
void lcd_ini(void){
    lcd_rs=0;
    lcd_en=0;
    lcd_rw=0;
    lcd_port=0;
    Delay10KTCYx(50);//50ms várakozás
    lcd_write_nibble(0x30);
    Delay1KTCYx(50);//5ms várakozás
    lcd_write_nibble(0x30);
    Delay1KTCYx(10);//1ms várakozás
    lcd_write_nibble(0x30);
    Delay1KTCYx(10);
    lcd_write_nibble(0x20);//4 BITES ÜZEMMÓD
    Delay1KTCYx(10);
    lcd_write_command(0x28);//2 SOROS ÜZEMMÓD
    Delay1KTCYx(10);
    lcd_write_command(0x08);//KIJELZO KI
    Delay1KTCYx(10);
    lcd_write_command(0x01);//KIJELZO TÖRLÉSE
    Delay1KTCYx(10);
    lcd_write_command(0x0C);//KIJELZO BE, KURZOR: NINCS VILLOGÁS SE ALÁHÚZÁS
    Delay1KTCYx(10);
}

void timer0(void){
        TMR0H=0b10011000;//40MHz clock 40/4*10^6*128*39062=0,33sec
        TMR0L=0b10010110;
        T0CONbits.TMR0ON=1;
    }
 
//KIJELZORE ÍRÁS
void _user_putc(char c){
    lcd_write_data(c);
}

void stop(void){
    T0CONbits.TMR0ON=0; //TIMER OFF
    PWMCON0=0x00;
    PTCON1bits.PTEN=0;
    lcd_write_command(0x01);//KIJELZO TÖRLÉSE
    printf("Press Start - ON");
    Delay10KTCYx(100);
    POT1=0;
    POT2=0;
    LED2=0;
    LED3=1;
    flag1=1;
    flag2=0;
    flag3=1;
}

void start(void){
    lcd_write_command(0x01);//KIJELZO TÖRLÉSE
    printf("PWM DUTY:   0%");
    lcd_write_command(0xC0);
    printf("FREQ:   00.00kHz");
    LED2=1;
    LED3=0;
    POT1_PRE=0;
    POT2_PRE=0;
    timer0();
    flag1=0;
}

void POT1_write(void){
    lcd_write_command(0x8A);//Kijelzo 1 sor 11 karakter
    if(POT_1<100){
        if(POT_1<10){
    printf("  %d", POT_1);
        }
        else{
    printf(" %d", POT_1);
    }
    }
    else{
    printf("%d", POT_1);
    }
    flag2=0;
}

void POT2_write(void){
    lcd_write_command(0xC8);//Kijelzo 2 sor 8 karakter
    printf("%d.%02d", POT_2/100, POT_2%100); //if 5khz POT_2 value 500, if 2,5khz POT_2=250
    flag2=0;
}

 void main(void) {
    POT1=0;
    POT2=0;
    POT_1=0;
    POT_2=0;
    POT1_PRE=0;
    POT2_PRE=0;
    flag1=0;
    flag2=0;
    flag3=0;
    PDC1=0;
    PDC2=0;
    PTPER=0;
    INI_PORTS();
    LED1=1;
    LED2=0;
    LED3=0;
    lcd_ini();
    
    //welcome and loading screen
    stdout=_H_USER;//PRINTF-HEZ
    lcd_write_command(0x84);//1 sor 5. karakter
    printf("Welcome!");
    Delay10KTCYx(250);//VÁRAKOZÁS a(K)TCYx(b)=a*(1000)*clock source/4*b
    Delay10KTCYx(250);//40MHz/4=0,1usec 0,1usec*1000*10*250=0,25sec
    lcd_write_command(0xC0);//MÁSODIK SOR
    printf("Prog_v.1 loading");
    Delay10KTCYx(250);//40MHz/4=0,1usec 0,1usec*1000*10*250=0,25sec
    Delay10KTCYx(250);
    Delay10KTCYx(250);
    stop();
    WDTCONbits.SWDTEN=1; //WDT ON
    
    //MAIN PROGRAM
     while(1){
        ClrWdt(); //WDT CLEARED, WDT GENERATE RESET EVRY 496ms IF NOT CLEARED
        if(SW1==0){
            if(SW2==1){
              if(flag1==1){
                  start();
              }  
            }
        }
        
        if(flag2==1){
            if(POT1_PRE!=POT1){
            POT1_write();
            }
            if(POT2_PRE!=POT2 || flag3==1){
                POT2_write();
                flag3=0;//jelz?bit, hogy a stop után mindenképpen 1x lefusson a pot2_write 0->5kHz
            }
        }
        
        if(SW2==0){
            if(flag1==0){
                stop();
            }
        }
  
 }
 }