/*
 * File:   PWM.c
 * Author: Vojta
 *
 * Created on 5. zá?í 2022, 14:34
 */


#include "hlava.h"


void PWM_init(void)
{
    RA5PPS = 0x09; //CCP1OUT na RA5
    T2PR = 199; // f_PWM = 10 kHz + 1:4 prescaler
    CCP1CON = 0b10001111; //CCP ON, PWM Right-aligned format (FMT = 0) , PWM Operation
    CCPTMRS0bits.C1TSEL = 0x01; //CCP1 is based off Timer1 in Capture/Compare mode and Timer2 in PWM mode
    duty(0); 
    
    TMR2IF = 0; // Clear the TMR2IF interrupt flag bit
    T2CLKCON = 0x01; // Fosc/4 on timer 2 as clk source
    T2CONbits.CKPS = 0x02; // 1:4 Prescaler on TMR2
    T2CONbits.ON = 1; // Timer2 ON
    while(!TMR2IF); // viz PWM setup
    TRISA5=0; //aktivace PWM pinu
}

void duty (unsigned int duty) // rozliseni 9.64 bits = 2^9.64 = 800max
{
    CCPR1H = (unsigned char) ( duty >> 8 );                                                                                                    
    CCPR1L = (unsigned char) ( 0xFF & duty );                                                                                                                                       
}

unsigned char max_vykon(void)
{
    if(coil_res > 3900 && coil_res0 < 41000 ) //pokud je odpor vetsi jak 4.1 ohm nebo mensi jak 0.39 ohm tak vykon bude 0
    {
        unsigned char max_vykon;
        unsigned int V_coil;
        //bat_volt *= 10^-2V
        V_coil = (unsigned int) ( ((unsigned long) 840 * (unsigned long) coil_res0) / ((unsigned long)coil_res0 + 25 + 130) ); // *10^-2 V, Rbat = 130*10^-4 ohm , Rdson = 25*10^-4 ohm, Vbat_max = 8,4 V
        
        max_vykon = (unsigned char)   ( ((unsigned long)V_coil *(unsigned long)V_coil)  / ((unsigned long)coil_res0) );          
        
        if(TC_ON)
        {
            max_vykon = (unsigned char) ( ( (unsigned long) max_vykon * (1000 - 160) ) / 1000 ); // -16% z max vykonu kvuli mezeram pri TC, princip vypoctu stejny jak u duty_cycle s TC_ON
        }
        
        return max_vykon;
    }else
        return 0;   
}

void set_PWM_vykon(unsigned char P_coil, unsigned char TC_ON1) //zhruba 400us
{
    unsigned int V_coil;
    unsigned int duty_cycle;
    unsigned int duty_PWM_cycle;
    
    V_coil = (unsigned int) ( ((unsigned long) V_bat * (unsigned long) coil_res) / ((unsigned long)coil_res + 25 + 130) ); // *10^-2 V, Rbat = 130*10^-4 ohm , Rdson = 25*10^-4 ohm
    duty_cycle = (unsigned int) ( ( (unsigned long) P_coil * (unsigned long) coil_res * 1000 ) / (  (unsigned long)V_coil * (unsigned long) V_coil ) ); // *10^-1 % ==> napr 100 = 10% duty_cycle, 
    
    if(TC_ON1) //jestli je TC rezim zapnuty, 1600 us mezera
    {
        duty_cycle = (unsigned int) ( ( (unsigned long) duty_cycle * (1000 + 160) ) / 1000 ); // +16% pricist k duty_cycle kvuli mezeram pri TC (kazdych 10ms 1,6ms mezera)
    }
    
    if(duty_cycle >= 1000) duty_cycle = 1000 ; //kdyz je duty_cycle vetsi jak 100% tak at je 100%   
    duty_PWM_cycle = (unsigned int) ( (8 * duty_cycle) / 10 ) ; // prevod z rozsahu 0-1000 na 0-800
    if(duty_PWM_cycle >= 800) duty_PWM_cycle = 800 ;
  
    duty(duty_PWM_cycle);
}

void set_vykon(void)
{
    unsigned char max_vykon0 = max_vykon();
    if(vykon > max_vykon0) vykon = max_vykon0; //aby to zobrazilo max vykon pokud jsme nastavili max vykon ve wattage modu bet TC a pak zaply TC a pak prepli na vykon   
    set_PWM_vykon(vykon,TC_ON);    
}

void TC_AND_VYKON_reinit(void)
{
    if( TC_ON )
    coil_res1 = coil_res1_vypocet(tc_teplota); //vypocet odporu pro nastavenou teplotu jestli je TC zaply
    else
    coil_res1 = 0; // jestli je TC vypnuty tak dej odpor 0 pro jistotu
    
    set_vykon();    
}