/*
  _  _  ___  ___  ___   __   ___     _   _  _  __   ___  __  _    _ 
 ( )( )(  _)(__ \(_  ) (  ) (_  )   / ) ( )( )(  ) (__ \(  )( \/\/ )
  \\//  ) _)/ __/ / /  /__\  / /   / /   \\// /__\ / __/ )(  \    / 
  (__) (___)\___)(___)(_)(_)(___) (_/    (__)(_)(_)\___)(__)  \/\/                                                                                          

  ADF4351 Programmer for a Local Oscillator, Version 1.
  Designed to be run on a PIC12F683, to ber compiled on MPLAB X IDE with XC8 compiler.
  VE2ZAZ/VA2IW, September 2023. https://ve2zaz,net
  Usage licence: Attribution 4.0 International ? CC BY 4.0 - Creative Commons. Read https://creativecommons.org/licenses/by/4.0/deed.en
*/

// Compiler Directives
#include <xc.h>
#include <pic12f683.h>              // Compiled for PIC12F683

// Constants
#define _XTAL_FREQ  250000          // Oscillator frequency considered by the compiler and simulator
#define DATA GP0                    // SPI pins as labeled on ADF4351
#define CLK GP1
#define LE GP2

// PIC Configuration bytes (Fuses)
#pragma config FOSC = INTOSCIO  	// Internal oscillator selected, I/O function on RA4 pin, I/O function on RA5 pin
#pragma config WDTE = OFF       	
#pragma config PWRTE = OFF      	
#pragma config MCLRE = OFF      	
#pragma config CP = OFF         	
#pragma config CPD = OFF        	
#pragma config BOREN = OFF      	
#pragma config IESO = OFF       	
#pragma config FCMEN = OFF   


// ADF4151 Configuration data (32 bit registers). Must be written in a Reg6-Reg0 order at power up.
const unsigned char ADF_Config_Data[24] = 
{
//  33222222    22221111    11111100    00000000        // Target Output Frequency: 3408 MHz
//  10987654    32109876    54321098    76543210        
//  ||||||||    ||||||||    ||||||||    ||||||||            
  0b00000000, 0b01000000, 0b00000000, 0b00000101, // Reg 5  LD_PIN_MODE:(DIGITAL_LOCK_DETECT) 
//  ||||||||    ||||||||    ||||||||    ||||||||    
  0b00000000, 0b10000110, 0b01000000, 0b00111100, // Reg 4  OUT_PWR:3(+5DBM) RF_OUT:1(ENA) AUX_OUT_PWR:0(-4dBm)
//  ||||||||    ||||||||    ||||||||    ||||||||            AUX_RF_OUT:0(DIS) AUX_OUT_SEL:0(DIVIDED)) MTLD:0(DIS)
//  ||||||||    ||||||||    ||||||||    ||||||||            VCO_PD:0(POWERED UP) BAND_SEL_CLK_DIV:100 RF_DIV_SEL:0(DIV-BY-1)
//  ||||||||    ||||||||    ||||||||    ||||||||            FB_SEL:1(FUNDAMENTAL)
//  ||||||||    ||||||||    ||||||||    ||||||||            
  0b00000000, 0b01000000, 0b01000000, 0b00000011, // Reg 3  12B_CLK_DIV:2048 CLK_DIV_MODE:0(OFF) CSR:0(DIS)
//  ||||||||    ||||||||    ||||||||    ||||||||            CHRG_CANCEL:0(DIS) ABP:1(INT-M) BND_SEL_CLK_MODE:0(LOW) 
//  33222222    22221111    11111100    00000000
//  10987654    32109876    54321098    76543210
//  ||||||||    ||||||||    ||||||||    ||||||||       
  0b00011000, 0b00000000, 0b01001110, 0b01000010, // Reg 2  CTR_RST:0 CP_3ST:0 POWER-DOWN:0 PD_POL:1(POS)  
//  ||||||||    ||||||||    ||||||||    ||||||||            LDP:0(10ns) LDF:0(FRAC-N) CP_CURR:0(2.5)
//  ||||||||    ||||||||    ||||||||    ||||||||            DOUBL_BUFF:0(DIS) R:1 REF_DIV_2:0(DIS) REF_DBLR:0(DIS)
//  ||||||||    ||||||||    ||||||||    ||||||||            MUXOUT:5(DIGITAL_LD) NOISE_MODE:0(LOW NOISE)
//  ||||||||    ||||||||    ||||||||    ||||||||            
  0b00000000, 0b00000000, 0b10000000, 0b01010001, // Reg 1  PHASE:1 MOD:10 PHASE_ADJ:0(OFF) PRESCALER:0(4/5)
//  ||||||||    ||||||||    ||||||||    ||||||||    
  0b00000000, 0b10101010, 0b00000000, 0b01000000, // Reg 0  INT:340  FRAC:8 
//  ||||||||    ||||||||    ||||||||    ||||||||
//  33222222    22221111    11111100    00000000
//  10987654    32109876    54321098    76543210
};

// Global Variables
unsigned char addr, byte;
int bit_pos;


void setup()
{
    // Microcontroller register initialization
    PIR1 =       0;          // Disable interrupts
    IOC =        0b00000000; // Disable I/O pin driven interrupts
    PIE1 =       0b00000000; // Do not allow interrupts
    OPTION_REG = 0b00000111; // Globally active Pull-ups.
    WPU =        0b00101111; // Individual pull-ups activations
    OSCCON =     0b00100001; // Internal oscillator selection. 250 Khz frequency selection
    T1CON =      0b00000100; // TMR1 disabled
    T2CON =      0b01111011; // TMR2 disabled
    CCP1CON =    0b00000000; // No PWM
    ADCON0 =     0b10000000; // No ADC
    ANSEL =      0b00000000; // No analog functions on pins
    CMCON0 =     0b00010111; // No comparator
    CMCON1 =     0b00000000; // No comparator
    VRCON =      0b00100001; // No comparator
    WDTCON =     0b00010100; // Warchdog turned off
    GPIO   =     0b00000100; // Set proper level on pins before enabling the outputs
    TRISIO =     0b11111000; // Assign I/O pins as shown below:
								//	GP5-not used 
								//	GP4-not used 
								//	GP3-Input only, not used 
								//	GP2-LE output
								//	GP1-CLK output 
								//	GP0-DATA output 
}


void main(void) 
{
    setup();                        // Setup function, run only once
	__delay_ms(1000);               // 1 second stabilisation pause
    for (addr=0 ;addr<6 ;addr++)    // Send all six long words to ADF4351
    {
        LE = 0;                     // Lower LE line
        for (byte=0 ;byte<4 ;byte++) // Send the 4 bytes that make the 32-bit word
        {    
            for (bit_pos = 7; bit_pos >= 0; bit_pos--)  // Send the 8 bits of each byte, MSB first
            {
                DATA = ((ADF_Config_Data[addr*4 + byte] & (1<<bit_pos))>>bit_pos) & 1;
                CLK = 1;            // Send a low-high-low CLK pulse
                CLK = 0;
            }    
        }
        DATA = 0;                   // Lower DATA line (optional)
        LE = 1;                     // Lift LE line
    }    
    asm("SLEEP");                   // Stop CPU to kill noise
}
