#include #include #include #include #include "delay.h" /* Definitions for pins */ #define PORTB_PLL_MUXOUT (1 << 0) #define PORTB_PLL_LE (1 << 4) #define PORTB_PLL_DATA (1 << 3) #define PORTB_PLL_CLK (1 << 2) void set_pin(int pin, int high) { if (high) { PORTB |= pin; } else { PORTB &= ~pin; } } void shift_out(uint8_t value) { for (uint8_t i = 0; i < 8; i++) { set_pin(PORTB_PLL_DATA, !!(value & (1 << (7 - i)))); set_pin(PORTB_PLL_CLK, 1); set_pin(PORTB_PLL_CLK, 0); } } void write_adf4002(uint32_t value) { set_pin(PORTB_PLL_LE, 0); shift_out((value & 0x00FF0000) >> 16); shift_out((value & 0x0000FF00) >> 8); shift_out(value & 0x000000FF); set_pin(PORTB_PLL_LE, 1); } volatile uint8_t systick; /* Timer (100Hz increment) */ volatile uint32_t seconds; /* 200Hz timer interrupt */ ISR(TIM0_COMPA_vect) { systick++; if (systick == 20) { systick = 0; seconds += 1; } } static int inittimer(void) { /* Start 200Hz system timer */ TCCR0B |= (1 << WGM01); // Configure timer for CTC mode TIMSK |= (1 << OCIE0A); // enable compare match A interrupt OCR0A = (uint8_t)(F_CPU / 64 / 50); // Set CTC compare value to 50ms TCCR0B |= ((1 << CS00) | (1 << CS01)); // Start timer at Fcpu/64 // Enable interrupts sei(); return 0; } int main(void) { systick = 0; seconds = 0; /* Configure GPIO */ PORTB = PORTB_PLL_LE; DDRB = PORTB_PLL_CLK | PORTB_PLL_LE | PORTB_PLL_DATA; /* initialise timer interrupt */ inittimer(); delay_ms(120); // See README.md const uint32_t r_counter = 400; const uint32_t n_counter = 1080; const uint32_t ldp = 1; // 5 consecutive cycles of phase delay less than 15ns before lock det const uint32_t cpi = 3; // I_CP = 2.5mA const uint32_t pd_polarity = 1; // positive const uint32_t muxout = 1; // lock detect, active high const uint32_t refernce_counter_latch = (ldp << 20) | (r_counter << 2) | 0; const uint32_t n_counter_latch = (n_counter << 8) | 1; const uint32_t function_latch = (cpi << 18) | (cpi << 15) | (pd_polarity << 7) | (muxout << 4) | 2; const uint32_t init_latch = (cpi << 18) | (cpi << 15) | (pd_polarity << 7) | (muxout << 4) | 3; // ADF4002 Datasheet Page 16 // Device Programming After Initial Statup // Initialisation Latch Method write_adf4002(init_latch); write_adf4002(function_latch); write_adf4002(refernce_counter_latch); write_adf4002(n_counter_latch); while (1) { /* // We actually dont use the timer, but the code is kept around as a reference. const uint32_t second = seconds % 60uL; const uint32_t minute = seconds / 60uL; if ((PINB & PORTB_PLL_MUXOUT) == 0) { delay_ms(600); } */ delay_ms(1000); } return 0; }