#include <xc.h> 
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
// PIC18F452 Configuration Bit Settings 4 xpll ak tif 12mhz KTISTALLE 48MHZDE CALISIYOR.
#pragma config OSC = HSPLL      // 
#pragma config OSCS = ON        // 
#pragma config PWRT = OFF       // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOR = OFF         // Brown-out Reset Enable bit (Brown-out Reset enabled)
#pragma config BORV = 20        // Brown-out Reset Voltage bits (VBOR set to 2.0V)
#pragma config WDT = OFF         // Watchdog Timer Enable bit (WDT enabled)
#pragma config WDTPS = 128      // Watchdog Timer Postscale Select bits (1:128)
#pragma config CCP2MUX = OFF      // CCP2 Mux bit (CCP2 input/output is multiplexed with RC1)
#pragma config STVR = ON        // Stack Full/Underflow Rack Full/Underflow will cause RESET)
#pragma config LVP = OFF        // Low Voltage ICSP Enable bit (Low Voltage ICSP disabled)
#define _XTAL_FREQ 12000000 //12mhz istege gore 20mhz kadar olabilir
#ifndef uchar
typedef   unsigned char   uchar;
#endif
#ifndef ushort
typedef   unsigned short   ushort;
#endif
#ifndef uint
typedef   unsigned int   uint;
#endif
#ifndef ulong
typedef   unsigned long   ulong;
#endif
//////////////////LCD REGISTER AYARLARI////////////////////////////////////
#define      LCD_FIRST_ROW                    128
#define      LCD_SECOND_ROW                192
#define      LCD_THIRD_ROW                    148
#define      LCD_FOURTH_ROW                 212
#define      LCD_CLEAR                                1
#define      LCD_RETURN_HOME                 2
#define      LCD_CURSOR_OFF                   12
#define      LCD_UNDERLINE_ON                14
#define      LCD_BLINK_CURSOR_ON         15
#define      LCD_MOVE_CURSOR_LEFT      16
#define      LCD_MOVE_CURSOR_RIGHT    20
#define      LCD_TURN_OFF                         0
#define      LCD_TURN_ON                           8
#define      LCD_SHIFT_LEFT                       24
#define      LCD_SHIFT_RIGHT                     28
//////////////////////LCD  PORT AYATLARI///////////////////////////////////////////
#define LCD_RD7      LATBbits.LATB7       // D7
#define TRISRB7       TRISBbits.TRISB7
#define LCD_RD6      LATBbits.LATB6       // D6
#define TRISRB6       TRISBbits.TRISB6
#define LCD_RD5      LATBbits.LATB5       // D5
#define TRISRB5       TRISBbits.TRISB5
#define LCD_RD4      LATBbits.LATB4       // D4
#define TRISRB4       TRISBbits.TRISB4
#define LCD_EN        LATBbits.LATB3       // EN
#define TRISEN         TRISBbits.TRISB3
#define LCD_RS        LATBbits.LATB2       // RS
#define TRISRS         TRISBbits.TRISB2
///////////////STEP VE YUKARI   ASAGI BUTONU/////GIRIS OLARAK  AYARLANDI////
#define TRISC0 = 1; 
#define TRISC1 = 1; 
#define TRISC2 = 1; 
#define  STEP       PORTCbits.RC0
#define  YUKARI    PORTCbits.RC1      
#define  ASAGI      PORTCbits.RC2
//////////////////////////////////////////////////////////////////////////////////////
#define SDA               LATBbits.LATB0        // port B0 CIKIS
#define SCK              LATBbits.LATB1        // port B1 CIKIS
///////////////////BIR SIFIR AYARLARI/////////////////////////////////////////
#define Set_SDA_Low     SDA = 0                  // SDA KONUMU  data
#define Set_SDA_High    SDA = 1                  // SDA KONUMU
#define Set_SCK_Low     SCK = 0    // SCK KONUMU saat
#define Set_SCK_High    SCK = 1    //SCK KONUMU
//////////////////////////////////////////////////////////////////////////////////
#define I2C_Speed   40// I2C gecikmesi durma gore azaltilip cogaltila bilinir.
////////////////////////si5351/////////////////////////////////////////////////////////////
#define SYNTH_MS_0               42  // PPL A CIKIS Degeri 42
#define SI5351A_ADDRESS     192  //Aslinda 96   192 kullanmak gerekiyor
#define SI_CLK0_CONTROL       16   
#define SI_CLK1_CONTROL       17
#define SI_CLK2_CONTROL       18
#define SI_SYNTH_PLL_A       26
#define SI_SYNTH_PLL_B       34
#define SI_SYNTH_MS_0      42
#define SI_SYNTH_MS_1      50
#define SI_SYNTH_MS_2      58
#define SI_PLL_RESET    177
#define SI_R_DIV_1        0   
#define SI_R_DIV_2       16
#define SI_R_DIV_4       32 
#define SI_R_DIV_8       48
#define SI_R_DIV_16       64
#define SI_R_DIV_32       80
#define SI_R_DIV_64      96 
#define SI_R_DIV_128   112 
#define SI_CLK_SRC_PLL_A   0 
#define SI_CLK_SRC_PLL_B   32 
#define XTAL_FREQ            25000000    //Kristal frekansi  25 YADA 27 MHZ FARKETMEZ
#define XTAL_LOAD_CAP          183     //10 pf ic kondansator aktiv  resisterin 183 une yazilacak
#define SI5351_CRYSTAL_LOAD_10PF         (3<<6)   //10pf ic kondansator
///////////////////////////////////////////////////////////////////////////////////////////
void Lcd_Init(void);
void Lcd_Char(char c);
void Lcd_Command(unsigned char command);//LCD COMMAND
void Lcd_yazi(unsigned char y, unsigned char x, const char *buffer);//harf sayi gostermek icin
void print(unsigned char y, unsigned char x, char *buffer);
/////////////////////// I2C ICIN FONKSIYONLAR  /////////////////////////////
void i2c_yaz( unsigned char byte); //baslangicta fonksiyon tanimliyoruz       
void i2c_init( void );   //baslangicta fonksiyon tanimliyoruz       
void i2c_basla( void ); //baslangicta fonksiyon tanimliyoruz             
void i2c_durdur( void );   //baslangicta fonksiyon tanimliyoruz          
void yaz(unsigned char RegisterAddresi, unsigned int  Registerdegeri);    
 ///////////////////////////////SI5351 ICIN FONKSIYONLAR//////////////////
void SetFreq(unsigned long frequency);
void kur_bolucu(unsigned char synth, unsigned long divider, unsigned char Div);       
void kur_pll(unsigned char pll,unsigned char mult,unsigned long num,unsigned long denom);    
void Delayms(unsigned int gecik);   
void Lcd_Delay5us(void);
void Lcd_Delay5500us(void);
///////////////////////////////////////////////////////////////////////////////////
void Lcd_Delay5us(void){
__delay_us(5);
__delay_us(5);   
}
void Lcd_Delay5500us(void){
__delay_us(5500);
}
 void Delayms(unsigned int gecik)   
    {   
       unsigned int i,j;   
           for(i=0;i<gecik;i++) 
                    for(j=0;j<1500;j++); 
    } 
char step=4;    //baslangic step 1khz  
unsigned long long  frekans=7150000;   //baslangic frekansi   
unsigned char TempBuffer[60]=""; //LCD de yaziyi gostermek icin
//lcd portları
void  Lcd_Init(void){
unsigned char data;
TRISRB7 = 0; 
TRISRB6 = 0;
TRISRB5 = 0; 
TRISRB4 = 0; 
TRISEN = 0; 
TRISRS = 0;
LCD_RD7 = 0; 
LCD_RD6 = 0; 
LCD_RD5 = 0; 
LCD_RD4 = 0; 
LCD_EN = 0; 
LCD_RS = 0;
Lcd_Delay5500us(); 
Lcd_Delay5500us(); 
Lcd_Delay5500us(); 
Lcd_Delay5500us(); 
Lcd_Delay5500us(); 
Lcd_Delay5500us(); 
Lcd_Delay5500us();
Lcd_Delay5500us(); 
Lcd_Delay5500us(); 
Lcd_Delay5500us();
for(data = 1; data < 4; data ++)
   {
LCD_RD7 = 0; 
LCD_RD6 = 0; 
LCD_RD5 = 1; 
LCD_RD4 = 1; 
LCD_EN = 0; 
LCD_RS = 0;
LCD_RD7 = 0; 
LCD_RD6 = 0; 
LCD_RD5 = 1; 
LCD_RD4 = 1; 
LCD_EN = 1; 
LCD_RS = 0;
Lcd_Delay5us();
Lcd_Delay5us();    
Lcd_Delay5us();
Lcd_Delay5us();
 Lcd_Delay5us();
Lcd_Delay5us();   
LCD_RD7 = 0; 
LCD_RD6 = 0; 
LCD_RD5 = 1; 
LCD_RD4 = 1; 
LCD_EN = 0; 
LCD_RS = 0;
   Lcd_Delay5500us();
  Lcd_Delay5500us(); 
Lcd_Delay5500us();    
Lcd_Delay5500us();
  Lcd_Delay5500us(); 
Lcd_Delay5500us(); 
}
LCD_RD7 = 0; 
LCD_RD6 = 0; 
LCD_RD5 = 1; 
LCD_RD4 = 0; 
LCD_EN = 0; 
LCD_RS = 0;
LCD_RD7 = 0; 
LCD_RD6 = 0; 
LCD_RD5 = 1; 
LCD_RD4 = 0; 
LCD_EN = 1; 
LCD_RS = 0;
Lcd_Delay5us();
Lcd_Delay5us();
Lcd_Delay5us();
Lcd_Delay5us();
Lcd_Delay5us();
Lcd_Delay5us();
LCD_RD7 = 0; 
LCD_RD6 = 0; 
LCD_RD5 = 1; 
LCD_RD4 = 0; 
LCD_EN = 0; 
LCD_RS = 0;
Lcd_Delay5500us();
Lcd_Delay5500us();
Lcd_Delay5500us();
Lcd_Delay5500us();
data = 40; Lcd_Command(data);
data = 16; Lcd_Command(data);
data = 1;  Lcd_Command(data);
data = 15; Lcd_Command(data);////lcd portları bitis
Lcd_Command(LCD_CURSOR_OFF);
}
void Lcd_Char(char c){
LCD_EN = 0; LCD_RS = 1;
LCD_RD7 = (c & 0b10000000)>>7; 
LCD_RD6 = (c & 0b01000000)>>6;
LCD_RD5 = (c & 0b00100000)>>5; 
LCD_RD4 = (c & 0b00010000)>>4;
_delay(5);
LCD_EN = 1;
Lcd_Delay5us();
Lcd_Delay5us();
LCD_EN = 0;
LCD_RD7 = (c & 0b00001000)>>3;
LCD_RD6 = (c & 0b00000100)>>2;
LCD_RD5 = (c & 0b00000010)>>1; 
LCD_RD4 = (c & 0b00000001);
_delay(5);
LCD_EN = 1; 
Lcd_Delay5us();
Lcd_Delay5us(); 
LCD_EN = 0;
Lcd_Delay5500us();
}
void Lcd_Command(unsigned char command){
LCD_EN = 0; LCD_RS = 0;
LCD_RD7 = (command & 0b10000000)>>7; 
LCD_RD6 = (command & 0b01000000)>>6;
LCD_RD5 = (command & 0b00100000)>>5; 
LCD_RD4 = (command & 0b00010000)>>4;
_delay(5);
LCD_EN = 1; 
Lcd_Delay5us();
Lcd_Delay5us();
LCD_EN = 0;
LCD_RD7 = (command & 0b00001000)>>3; 
LCD_RD6 = (command & 0b00000100)>>2;
LCD_RD5 = (command & 0b00000010)>>1; 
LCD_RD4 = (command & 0b00000001);
_delay(5);
LCD_EN = 1;
Lcd_Delay5us();
Lcd_Delay5us();
LCD_EN = 0;
Lcd_Delay5500us();
Lcd_Delay5500us();
}
void print(unsigned char y, unsigned char x, char *buffer){
unsigned char data;
switch(y){
case 1: data = 127 + x; break;  
case 2: data = 191 + x; break;
case 3: data = 147 + x; break;
case 4: data = 211 + x; break;
default: break;}
Lcd_Command(data);
while(*buffer)               
     {
      Lcd_Char(*buffer);
      buffer++;             
     }
return;
}
void Lcd_yazi(unsigned char y, unsigned char x, const char *buffer){
unsigned char data;
switch(y){
case 1: data = 127 + x; break;
case 2: data = 191 + x; break;
case 3: data = 147 + x; break;
case 4: data = 211 + x; break;
default: break;}
Lcd_Command(data);
while(*buffer)            
     {
      Lcd_Char(*buffer);
      buffer++;           
     }
return;
}
void kur_pll(unsigned char pll, unsigned char mult, unsigned long num, unsigned long denom)  
{
   unsigned long P1; unsigned long P2; unsigned long P3;  //degiskenler p1,p2,p3 
   P1 = (unsigned long)(128 * ((float)num / (float)denom));
   P1 = (unsigned long)(128 * (unsigned long)(mult) + P1 - 512);
   P2 = (unsigned long)(128 * ((float)num / (float)denom));
   P2 = (unsigned long)(128 * num - denom * P2); P3 = denom;
   yaz(pll + 0, (P3 & 0x0000FF00) >> 8);
   yaz(pll + 1, (P3 & 0x000000FF));
   yaz(pll + 2, (P1 & 0x00030000) >> 16);
   yaz(pll + 3, (P1 & 0x0000FF00) >> 8);
   yaz(pll + 4, (P1 & 0x000000FF));
   yaz(pll + 5, ((P3 & 0x000F0000) >> 12) | ((P2 & 0x000F0000) >> 16));
   yaz(pll + 6, (P2 & 0x0000FF00) >> 8);
   yaz(pll + 7, (P2 & 0x000000FF));
} 
void kur_bolucu(unsigned char synth, unsigned long divider, unsigned char Div)   // konmaz
{
   unsigned long P1;               //ayar P1    degisken 
   unsigned long P2;               // ayr P2    degisken 
   unsigned long P3;               // ayarP3    degisken 
   P1 = 128 * divider - 512;
   P2 = 0;    // P2 = 0, P3 = 1, bölücü için bir tam sayi
   P3 = 1;
                 yaz(synth + 0,   (P3 & 0x0000FF00) >> 8);
                 yaz(synth + 1,   (P3 & 0x000000FF));
   yaz(synth + 2,   ((P1 & 0x00030000) >> 16) | Div);
                 yaz(synth + 3,   (P1 & 0x0000FF00) >> 8);
   yaz(synth + 4,   (P1 & 0x000000FF));
   yaz(synth + 5,   ((P3 & 0x000F0000) >> 12) | ((P2 & 0x000F0000) >> 16));
   yaz(synth + 6,   (P2 & 0x0000FF00) >> 8);
   yaz(synth + 7,   (P2 & 0x000000FF));
}
   void SetFreq(unsigned long frequency)    //  (frequency degisken)
  {
   unsigned long pllFreq;             // degisken 
   unsigned long xtalFreq = XTAL_FREQ;                        // degisken 
   unsigned long l;                                            // degisken 
   double  f;//float  f;                   // degisken 
   unsigned char mult;                // degisken 
   unsigned long num;                // degisken 
   unsigned long denom;              // degisken 
   unsigned long divider;                // degisken 
                 divider = 900000000 / frequency;  //  Bölme orani 900000000                 
   if (divider%2)                      //bolumden kalani eksilt
                 divider --;                        // Bir çift tamsayi bölme 
   pllFreq = divider * frequency;       // hesapla bölücü 
   mult = pllFreq / xtalFreq;       //pll çarpan  
   l = pllFreq % xtalFreq;          //Üç bölüm
   f = l;                           // tamsayi
   f *= 1048575;          // num ve denom, kesirli kisimlar, pay ve payda
   f /= xtalFreq;          //her biri 20 bittir (aralik 0..1048575)
   num = (ulong)f;             //çarpan mult + num / denom
   denom = 1048575;            // payda maksimum 1048575
   kur_pll(SI_SYNTH_PLL_A, mult, num, denom);            // pll ye git
   kur_bolucu(SI_SYNTH_MS_0, divider, SI_R_DIV_1);    //bolucuye git
   yaz(SI_CLK0_CONTROL, 0x4F | SI_CLK_SRC_PLL_A);   // yaz git A ciktisini ac
}
void i2c_init(void)             
   {       
Set_SDA_High;//   SDA = 1;   
Set_SCK_High;//   SCK = 1;  
   } 
void i2c_basla( void ){       
  int i;
  Set_SDA_High;
  for(i = 0; i<I2C_Speed; ++i );  
  Set_SCK_High;
  for(i = 0; i<I2C_Speed; ++i );  
  Set_SDA_Low;
  for(i = 0; i<I2C_Speed; ++i );  
  Set_SCK_Low;
  for(i = 0; i<I2C_Speed; ++i ); 
  for( i = 0; i<I2C_Speed; ++i ); 
  for(i = 0; i<I2C_Speed; ++i ); 
  for(i = 0; i<I2C_Speed; ++i ); 
  }      
//----------------- I2C -----------------------------------------------//
void i2c_durdur( void ){       
  int i;
  Set_SDA_Low;
  for(i = 0; i<I2C_Speed; ++i );     //gecikme I2C_Speed
  Set_SCK_High;
  for(i = 0; i<I2C_Speed; ++i );    //gecikme I2C_Speed 
  Set_SDA_High;
  for(i = 0;  i<I2C_Speed; ++i );  //gecikme I2C_Speed
  for( i = 0; i<I2C_Speed; ++i );    //gecikme I2C_Speed
  for( i = 0; i<I2C_Speed; ++i );  //gecikme I2C_Speed
  for( i = 0; i<I2C_Speed; ++i );  //gecikme I2C_Speed
   }
void i2c_yaz( unsigned char byte ){    
  unsigned char temp=byte;
  int i,j;
    for(j = 0; j<8; ++j ){  //Beytleri taramak icin for dongusu
    for(i = 0; i<I2C_Speed; ++i )     //gecikmeyi ver
    if( (temp&0x80) == 0x80 )  //eger temp 0x80 se esitle 0x80 ne
     Set_SDA_High;       // bir yap      yukarda define ile tanimli (Set_SDA_High)
    else
      Set_SDA_Low;       // sifir yap yukarda define ile tanimli   (Set_SDA_Low)
    temp <<=1;      //sola yit
    for(i = 0; i<I2C_Speed; ++i ) //gecikme
    Set_SCK_High;
    for(i = 0; i<I2C_Speed; ++i ) 
    Set_SCK_Low;
  } 
  TRISB0 = 1;  //8 inci bit icin SDA giris yapildi.
  for(i = 0; i<I2C_Speed; ++i ) 
  Set_SCK_High;
  for(i = 0; i<I2C_Speed; ++i ) 
  Set_SCK_Low;
  TRISB0 = 0; //SDA  cikis yapildi
}    
void yaz(unsigned char RegisterAddresi, unsigned int  Registerdegeri)  
   {
    i2c_basla();              // basla'ya gitI2C yi baslat
    i2c_yaz(SI5351A_ADDRESS); //i2c_yaza git  si5351nin adresini yaz (192 )   
    i2c_yaz(RegisterAddresi); //i2c_yaza git  ilk beyti sal
    i2c_yaz(Registerdegeri);  //i2c_yaza git  ikinci beyti sal
    i2c_durdur();             //i2c_durdura git durdur
  }
//LCDde frekans gostermek icin 
void segmentler(unsigned long t, unsigned char *str, unsigned char n)    
    {        
   unsigned char a[12]; int i, j;                                          
                a[0]= (t/100000000000)%10;                                             
                a[1]= (t/10000000000)%10;
                a[2]= (t/1000000000)%10;                                          
                a[3]= (t/100000000)%10;                                           
                a[4]= (t/10000000)%10;                                            
                a[5]= (t/1000000)%10;                                             
                a[6]= (t/100000)%10;  
                a[7]= (t/10000)%10;                                          
                a[8]= (t/1000)%10;                                           
                a[9]= (t/100)%10;                                            
                a[10]=(t/10)%10;                                             
                a[11]=(t/1)%10; 
        for(i=0; i<12; i++) a=a+'0';                                                               
        for(i=0; a=='0' && i<=4; i++);                                  
        for(j=12-n; j<i; j++) { *str=' ';     
       if ((j == 8) || (j == 5)) *++str = 46; str++; }   //46 noktayi temsil eder ornek 7.155.000                                                          
        for(; i<12; i++)  { *str=a; 
       if ((i == 8) || (i == 5)) *++str = 46;  str++; }   //46 noktayi temsil eder ornek 14.155.000   
                *str='\0'; }
        void  main()
  {       
TRISA=0x00;  
TRISB=0x00;  //
TRISC = 0x07;// 1 2 ve 3 pini giris digerleri cikis 
 PORTA=0x00;PORTB=0x00; PORTC=0x00;   //portlar temizledi
  Lcd_Init();
  Lcd_Command(LCD_CLEAR);
  Lcd_Command(LCD_CURSOR_OFF);
     i2c_init();                                        
      Lcd_yazi(2,2, "Yasa"); //harf sayi gostermek icin
      Delayms(1200);Delayms(1200);
     yaz(XTAL_LOAD_CAP,SI5351_CRYSTAL_LOAD_10PF);  //25mhz nin kristalin 10 pf sini aktiv et(XTAL_LOAD_CAP)              
     Lcd_yazi(2,2, "1 khz   ");   
     SetFreq(frekans);   //SetFreq fonksiyona git icindeki isleri yap 
     segmentler(frekans,&TempBuffer[0],10); 
     print(1, 2, &TempBuffer[0]);  Delayms(200);   
     while(1)   // while nin arasina calisacak  gorevler yazilir
       {           
     if(STEP== 0) { step++;   if (step>7) step=1; Delayms(800);      
          if(step== 1) { Lcd_yazi(2,2, "1 hrz   ");   } 
          if(step== 2) {Lcd_yazi(2,2, "10 hrz  ");   } 
          if(step== 3) { Lcd_yazi(2,2, "100 hrz "); }  
          if(step== 4) {Lcd_yazi(2,2, "1 khz   ");   } 
          if(step== 5) {Lcd_yazi(2,2, "10 khz  "); } 
          if(step== 6) {Lcd_yazi(2,2, "100 khz "); }  
          if(step== 7) {Lcd_yazi(2,2, "1 mhz   "); }  }        
     if(ASAGI== 0)  { Delayms(200);
          if(step== 1) {frekans=frekans - 1; } 
          if(step== 2) {frekans=frekans - 10;   } 
          if(step== 3) {frekans=frekans - 100;  }  
          if(step== 4) {frekans=frekans - 1000;   } 
          if(step== 5) {frekans=frekans - 10000;   } 
          if(step== 6) {frekans=frekans - 100000;   }     
          if(step== 7) {frekans=frekans - 1000000;   }  
          if(frekans >1600000000 ) frekans=0;  
      if(frekans <1 )  frekans=0 ;     
          SetFreq(frekans);   //SetFreq fonksiyona git icindeki isleri yap 
     segmentler(frekans,&TempBuffer[0],10);    // lcdde_frekansgoster
     print(1, 2, &TempBuffer[0]);  ;Delayms(200);  }  //buton gecikmesi    
    if(YUKARI== 0) { Delayms(200); 
         if(step== 1) { frekans=frekans +1; } 
         if(step== 2) {frekans=frekans +10;  } 
         if(step== 3) { frekans=frekans +100;  }  
         if(step== 4) { frekans=frekans +1000;  } 
         if(step== 5) {frekans=frekans + 10000;  }
         if(step== 6) {frekans=frekans + 100000;  }     
         if(step== 7) {frekans=frekans +1000000;   } 
         if(frekans >1600000000 ) frekans=0;
      if(frekans <1 )  frekans=0 ;  
         SetFreq(frekans);   //SetFreq fonksiyona git icindeki isleri yap 
    segmentler(frekans,&TempBuffer[0],10);  // lcdde_frekansgoster 
     print(1, 2, &TempBuffer[0]);   Delayms(200);  }  //buton gecikmesi
      } 
 }