Marco Vitchi Thulin
3e159ccf0a
Overcomment bitwise operations to provide detailed explanations to each operation and how they work.
161 lines
No EOL
4.8 KiB
C
161 lines
No EOL
4.8 KiB
C
#include<avr/io.h>
|
|
#include "common.h"
|
|
|
|
// PB3 - ADF4350 LE
|
|
// PB2 - USCK to ADF4350 CLK
|
|
// PB1 - DO to ADF4350 DATA
|
|
// PB0 - ADF4350 LD
|
|
// PB4 - Lock Status LED
|
|
|
|
void Delay(uint32_t);
|
|
uint8_t SendReceiveSPIData(uint8_t);
|
|
void SendSPIDataADF4350 (uint32_t);
|
|
|
|
int main()
|
|
{
|
|
// Set instructions to configure the ADF4350 for a 1 GHz +5dBm output.
|
|
uint32_t ar0=0x500000;
|
|
uint32_t ar1=0x8008011;
|
|
uint32_t ar2=0x4e42;
|
|
uint32_t ar3=0x4b3;
|
|
uint32_t ar4=0xac803c;
|
|
uint32_t ar5=0x580005;
|
|
|
|
// Alternative instructions for a 1001.25 MHz +5dBm output.
|
|
//uint32_t ar0=0x500008;
|
|
//uint32_t ar1=0x8008029;
|
|
//uint32_t ar2=0x4e42;
|
|
//uint32_t ar3=0x4b3;
|
|
//uint32_t ar4=0xac803c;
|
|
//uint32_t ar5=0x580005;
|
|
|
|
// Set direction of PB1 (DO) and PB2 (USCK) as output.
|
|
// This is done by using left shift operations.
|
|
// Binary 1 is shifted by the number of bits specified by PB1 and PB2.
|
|
// The OR operator is used to "combine" them into one byte,
|
|
// for example 0b00000010 + 0b00000100 = 0b00000110.
|
|
// We use DDBx because we are modifying the DDRx register.
|
|
DDRB = (1 << DDB1) | (1 << DDB2);
|
|
|
|
// Set the USI to three wire SPI mode.
|
|
// This is done by setting the USI Control Register to a value where only
|
|
// bit position USIWM0 is set to binary one.
|
|
USICR = (1 << USIWM0);
|
|
|
|
// Set direction of PB4 (Status LED) as output.
|
|
// Done by shifting 1 into bit position PB4.
|
|
DDRB |= (1 << DDB4);
|
|
|
|
// Set direction of PB3 (LE) as output.
|
|
// The exact same thing as above but PB3.
|
|
DDRB |= (1 << DDB3);
|
|
|
|
// Clear PB3 (LE) state by setting its bit to 0.
|
|
// First shift 1 into bit position PB3.
|
|
// ~ is bitwise NOT, and flips all bits.
|
|
// Finally &= clears PB3 by setting it low, while leaving other bits unchanged.
|
|
// Unlike the previous lines we use PBx instead of DDBx for bit position,
|
|
// this is because we are modifying the PORTx register.
|
|
// So at this point PB3 is configured as an output and is low.
|
|
PORTB &= ~(1 << PB3);
|
|
|
|
// Set direction of PB0 (LD Input) as input.
|
|
// This is done by setting it low using the same method as above.
|
|
DDRB &= ~(1 << DDB0);
|
|
|
|
// Enable pull-up resistor on PB0
|
|
// This is done by setting the state to high,
|
|
// after configuring as input (above).
|
|
PORTB |= (1 << PB0);
|
|
|
|
// Flash the Status LED (PB4) to show that everything works
|
|
PORTB |= (1 << PB4);
|
|
Delay(500000);
|
|
PORTB &= ~(1 << PB4);
|
|
Delay(100000);
|
|
|
|
// Enter loop waiting for frequency lock to be achieved
|
|
while (1)
|
|
{
|
|
// Read the state of LD (PB0)
|
|
uint8_t ldState = PINB & (1 << PINB0);
|
|
|
|
// If LD (PB0) is low, turn on the LED (PB4)
|
|
if (ldState == 0)
|
|
PORTB |= (1 << PORTB4); // Turn on the LED
|
|
else
|
|
PORTB &= ~(1 << PORTB4); // Turn off the LED
|
|
}
|
|
}
|
|
|
|
// General purpose delay.
|
|
void Delay(uint32_t tmax)
|
|
{
|
|
uint32_t i;
|
|
for (i=0;i < tmax ; i++)
|
|
{
|
|
// nop = "no operation", does nothing for 1 cycle.
|
|
asm("nop");
|
|
}
|
|
}
|
|
|
|
// Send an 8 bit word via SPI1 and receive an 8 bit word at the same time
|
|
uint8_t SendReceiveSPIData(uint8_t value)
|
|
{
|
|
uint8_t lout = 0;
|
|
short int i=0;
|
|
|
|
// Prob change the 8 below to len of value?
|
|
for(i=0;i<8;i++)
|
|
{
|
|
///USIDR = value[i]; // Wrong way to do it apparently, still saving for future reference
|
|
USIDR = (value >> i) & 0x01; // Write data bytes in Data register, will cause them to get sent on clock
|
|
while(USIOIF==0) // heck USI data counter overflow flag to detect the end of transmission every byte
|
|
{
|
|
USICR|=(1<<USICLK)|(1<<USITC); // Enable clock for transmission and generate clock for slave deivce
|
|
}
|
|
USISR|=(1<<USIOIF); // Clear USI data counter overflow flag
|
|
}
|
|
|
|
// Read in a 16 bit frame
|
|
///uint16_t inbyte = *(uint32_t *)(SPI1_BASE + 0x0c);
|
|
//return inbyte;
|
|
}
|
|
|
|
// Send a 32 bit register value to the ADF4350
|
|
void SendSPIDataADF4350 (uint32_t outval)
|
|
{
|
|
// Split into 4 x 8-bit words.
|
|
// This is done since each "packet" can only be 8-bit.
|
|
uint8_t byte1 = (outval & 0xFF000000) >> 24;
|
|
uint8_t byte2 = (outval & 0x00FF0000) >> 16;
|
|
uint8_t byte3 = (outval & 0x0000FF00) >> 8;
|
|
uint8_t byte4 = outval & 0x000000FF;
|
|
|
|
// Send these to the ADF4350 via SPI
|
|
SendReceiveSPIData (byte1);
|
|
SendReceiveSPIData (byte2);
|
|
SendReceiveSPIData (byte3);
|
|
SendReceiveSPIData (byte4);
|
|
|
|
// 2 x 16 version (for reference):
|
|
// split into 2 x 16 bit words
|
|
///uint16_t highWord = (outval & 0xffff0000) >> 16;
|
|
///uint16_t lowWord = outval & 0x0000ffff;
|
|
// send these to the ADF4350 via SPI
|
|
///SendReceiveSPIData (highWord);
|
|
///SendReceiveSPIData (lowWord);
|
|
|
|
// Delay to make sure the clock has gone low before LE is taken high.
|
|
Delay(10);
|
|
|
|
// Pull LE high to load the data into the ADF4350 register.
|
|
PORTB |= (1 << PB3);
|
|
|
|
// Short delay while LE is high (minimum of 20ns).
|
|
// This is to make sure the ADF4350 has time to register bits.
|
|
Delay(100);
|
|
|
|
// Pull LE low again.
|
|
PORTB &= ~(1 << PB3);
|
|
} |