//Descrizione programma : modulazione PWM sul piedino RC2/CCP1 (TRISC<2> a 0)
//Descrizione del funzionamento : Tramite il modulo CCP viene generata un ond quadra modulata in
//PWM, il periodo dell'onda quadra e' pari a : [(PR2} + 1] * 4 * Tosc * (TMR2 prescaler value). Quando
//TMR2 e' uguale a PR2 avvengono i seguenti eventi : TMR2 viene resettato, il pin CCP1 viene
//posto a 1 a menoche' il duty cicle non sia dello 0%, il duty cicle del PWM viene memorizzato
//da CCPR1L a CCPR1H.
//Il duty cicle e' un valore a 10 bit i cui 8 bit piu' significativi vengono memorizzati in 
//CCPR1L e i due bit meno significativi vengono memorizzati in CCP1CON<5:4>.
//Il duty cicle e' pari a : (CCPR1L:CCP1CON<5:4>) * Tosc * (TMR2 prescaler value).
//Con due pulsanti su RB0 (UP) ed RB1 (DOWN) si comandano le variazioni di duty cicle.
//Se in uscitauscita a RC2/CCP1 si connette un semplice filtro passa basso che tagli ad una frequenza che sia almeno
//la meta' di quella dell'onda Pwm, meglio se ancor piu' bassa, cioe' meno di 1 Hz, viene estratta la componente continua
//del segnale. In questo modo abbiamo ottenuto un convertitore digitale analogico a 10 bit, su 5 volt di escursione del 
//segnale per ogni pressione del tasto UP o del tasto DOWN abbiamo un incrmento/decremento di soli 5/1024 = 4.883 mV.

//Calcoli :
//Fclock = 4 Mhz 
//PR2 = 255
//Prescaler Timer2 = 1:16
//PWMPeriod = 256 * 4 * 250 * 16 * 10^-9 = 4.096 mS
//PWMFrequency = 244 Hz
//Duty Cicle = (0...1023) * Tosc * (TMR2 prescaler value)
//Duty Cicle = (0...1023) * 250 * 16 * 10^-9
//Con 1023 il valore risultante di duty cicle deve essere pari al periodo cioe' 4.096 mS e cosi e'.   

//Dati di sistema
//Fclock         : 4 MHz
//Tclock         : 250 nS
//Tistruzione    : 1 uS

//INCLUDE files
#include <pic.h>


//Configurazione bit di programmazione
//Oscillatore : XT
//Watchdog : OFF
//Power Up Timer : ON
//Code Protect : ALL
//Brown Out Detect : ON
//Low Voltage Program : Disable
//Data EE Protect : OFF
//Flash Program Write : Disable
//Background Debug : Disable

//0b 0000 0101 0100 0001
__CONFIG(0x0D41);


//Tipo di segnale (analogico o digitale) sui PORTx
#define ADMode 0x06;   //tutto in digitale

//Collegamenti a PORTA
//RA0 (OUT) --> NU
//RA1 (OUT) --> NU
//RA2 (OUT) --> NU
//RA3 (OUT) --> NU
//RA4 (OUT) --> NU
//RA5 (OUT) --> NU
#define PortAInit 0x00;
#define TrisAInit 0x00;

//Colelgamenti a PORTB
//RB0 (IN)   <-- UP
//RB1 (IN)   <-- DOWN
//RB2 (OUT) --> NU
//RB3 (OUT) --> NU
//RB4 (OUT) --> NU
//RB5 (OUT) --> NU
//RB6 (OUT) --> NU
//RB7 (OUT) --> NU
#define PortBInit 0x00;
#define TrisBInit 0x03;

//Colelgamenti a PORTC
//RC0 (OUT) --> Pulse Width Modulation
//RC1 (OUT) --> NU
//RC2 (OUT) --> NU
//RC3 (OUT) --> NU
//RC4 (OUT) --> NU
//RC5 (OUT) --> NU
//RC6 (OUT) --> NU
//RC7 (OUT) --> NU
#define PortCInit 0x00;
#define TrisCInit 0x00;

//Colelgamenti a PORTD
//RD0 (OUT) --> NU
//RD1 (OUT) --> NU
//RD2 (OUT) --> NU
//RD3 (OUT) --> NU
//RD4 (OUT) --> NU
//RD5 (OUT) --> NU
//RD6 (OUT) --> NU
//RD7 (OUT) --> NU
#define PortDInit 0x00;
#define TrisDInit 0x00;

//Colelgamenti a PORTE
//RE0 (OUT) --> NU
//RE1 (OUT) --> NU
//RE2 (OUT) --> NU
#define PortEInit 0x00;
#define TrisEInit 0x00;

//Simboli
#define UP RB0
#define DOWN RB1

//Prototipi
void SystemInit (void);
void Delay(unsigned int);
void PWMLoad (unsigned int);

//Variabili
unsigned int PWM; //contiene il valore da 0 a 1023 da assegnare ai registri appositi



//Main
void main(void)
{
 SystemInit();
 for (;;)
 {
  if (UP==0 & PWM !=1023)   //se spingo UP e PWM non e' al massimo
  {
   PWM++;                   //incrementa PWM
   PWMLoad(PWM);            //carica nuovo valore di PWM
   Delay(100);              //piccola isteresi di ritardo che serve se tengo premuto il tasto
  }

  if (DOWN==0 & PWM !=0)    //se spingo DOWN e PWM non e' al minimo
  {            
   PWM--;                   //decrementa PWM
   PWMLoad(PWM);            //carica nuovo valore di PWM
   Delay(100);              //piccola isteresi di ritardo che serve se tengo premuto il tasto
  } 
 }
 
}


//*********************************************************************************************************************************
//Definizione funzioni

void SystemInit (void)
{
 //Tipi di segnali sui portx
 ADCON1 = ADMode;

 //Inizializzazione PORTx
 PORTA = PortAInit;
 PORTB = PortBInit;
 PORTC = PortCInit;
 PORTD = PortDInit;
 PORTE = PortEInit;


 //Direzione PORTx
 TRISA = TrisAInit;
 TRISB = TrisBInit;
 TRISC = TrisCInit;
 TRISD = TrisDInit;
 TRISE = TrisEInit;


 //Registro OPTION
 RBPU    = 0;           //pull up su RBx
 PR2     = 255;         //periodo pwm = 4.096 mS
 T2CKPS1 = 1;           //prescaler Timer2 1:16
 T2CKPS0 = 1;           //    "        "    "
 CCPR1L  = 0;           //valore iniziale di PWM pari a 0
 CCP1CON = 0b00001100;  //modo PWM + valore iniziale PWM pari a 0
 TMR2ON  = 1;           //Timer2 abilitato
}


//routine di ritardo
void Delay (unsigned int Value)
{
 unsigned int Time;
 for (Time=0; Time<Value; Time++);
}


//routine di caricamento nuovi valori di PWM
void PWMLoad (unsigned int PWMValue)
{
 CCP1CON = CCP1CON & 0b11001111;   //azzera CCP1CON <5:4> e lascia stare tutti gli altri
 CCP1CON = CCP1CON | ((PWMValue << 4) & 0b00110000);  //sposta in 4 a sx (per mettere i due bit meno
                                          //significativi (0 e 1) in posizione 4 e 5 e li
                                          //scrive in CCP1CON<5:4>
 CCPR1L = PWMValue >> 2;                  //scrive in CCPR1L gli 8 bit piu' significativi di PWM
}



