Overcomment bitwise operations

Overcomment bitwise operations to provide detailed explanations to each operation and how they work.
This commit is contained in:
Marco Vitchi Thulin 2024-03-15 09:40:02 +01:00
parent ae9afdde18
commit 3e159ccf0a

111
main.c
View file

@ -2,8 +2,8 @@
#include "common.h" #include "common.h"
// PB3 - ADF4350 LE // PB3 - ADF4350 LE
// PB2 - SCK to ADF4350 CLK // PB2 - USCK to ADF4350 CLK
// PB1 - DO (MOSI) to ADF4350 DATA // PB1 - DO to ADF4350 DATA
// PB0 - ADF4350 LD // PB0 - ADF4350 LD
// PB4 - Lock Status LED // PB4 - Lock Status LED
@ -13,7 +13,7 @@ void SendSPIDataADF4350 (uint32_t);
int main() int main()
{ {
// set instructions to configure the ADF4350 for a 1 GHz +5dBm output // Set instructions to configure the ADF4350 for a 1 GHz +5dBm output.
uint32_t ar0=0x500000; uint32_t ar0=0x500000;
uint32_t ar1=0x8008011; uint32_t ar1=0x8008011;
uint32_t ar2=0x4e42; uint32_t ar2=0x4e42;
@ -21,7 +21,7 @@ int main()
uint32_t ar4=0xac803c; uint32_t ar4=0xac803c;
uint32_t ar5=0x580005; uint32_t ar5=0x580005;
// alternative instructions for a 1001.25 MHz +5dBm output // Alternative instructions for a 1001.25 MHz +5dBm output.
//uint32_t ar0=0x500008; //uint32_t ar0=0x500008;
//uint32_t ar1=0x8008029; //uint32_t ar1=0x8008029;
//uint32_t ar2=0x4e42; //uint32_t ar2=0x4e42;
@ -29,41 +29,58 @@ int main()
//uint32_t ar4=0xac803c; //uint32_t ar4=0xac803c;
//uint32_t ar5=0x580005; //uint32_t ar5=0x580005;
// set direction of PB1 (DO) and PB2 (USCK) as output // Set direction of PB1 (DO) and PB2 (USCK) as output.
DDRB=(1<<PB1)|(1<<PB2); // 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 to three wire mode (SPI) // Set the USI to three wire SPI mode.
USICR=(1<<USIWM0); // This is done by setting the USI Control Register to a value where only
///USICR=(0<<USIWM1); not needed, already 0 // bit position USIWM0 is set to binary one.
USICR = (1 << USIWM0);
// set direction of PB4 (status LED) as output // Set direction of PB4 (Status LED) as output.
DDRB |= (1 << PB4); // Done by shifting 1 into bit position PB4.
DDRB |= (1 << DDB4);
// set direction of PB3 (LE) as open-drain output // Set direction of PB3 (LE) as output.
DDRB |= (1 << PB3); // The exact same thing as above but PB3.
DDRB |= (1 << DDB3);
// set PB3 (LE) low // Clear PB3 (LE) state by setting its bit to 0.
PORTB &= ~(1 << PORTB3); // 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 // Set direction of PB0 (LD Input) as input.
// This is done by setting it low using the same method as above.
DDRB &= ~(1 << DDB0); DDRB &= ~(1 << DDB0);
// enable pull-up resistor on PB0 // Enable pull-up resistor on PB0
PORTB |= (1 << PORTB0); // 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 // Flash the Status LED (PB4) to show that everything works
PORTB |= (1 << PORTB4); PORTB |= (1 << PB4);
Delay(500000); Delay(500000);
PORTB &= ~(1 << PORTB4); PORTB &= ~(1 << PB4);
Delay(100000); Delay(100000);
// enter loop waiting for frequency lock to be achieved // Enter loop waiting for frequency lock to be achieved
while (1) while (1)
{ {
// read the state of LD (PB0) // Read the state of LD (PB0)
uint8_t ldState = PINB & (1 << PINB0); uint8_t ldState = PINB & (1 << PINB0);
// if LD (PB0) is low, turn on the LED (PB4) // If LD (PB0) is low, turn on the LED (PB4)
if (ldState == 0) if (ldState == 0)
PORTB |= (1 << PORTB4); // Turn on the LED PORTB |= (1 << PORTB4); // Turn on the LED
else else
@ -71,32 +88,33 @@ int main()
} }
} }
// general purpose delay // General purpose delay.
void Delay(uint32_t tmax) void Delay(uint32_t tmax)
{ {
uint32_t i; uint32_t i;
for (i=0;i < tmax ; i++) for (i=0;i < tmax ; i++)
{ {
asm("nop"); // 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 // 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 SendReceiveSPIData(uint8_t value)
{ {
uint8_t lout = 0; uint8_t lout = 0;
short int i=0; short int i=0;
// prob change the 8 below to len of value? // Prob change the 8 below to len of value?
for(i=0;i<8;i++) for(i=0;i<8;i++)
{ {
///USIDR = value[i]; // wrong way to do it apparently, still saving for future reference ///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 USIDR = (value >> i) & 0x01; // Write data bytes in Data register, will cause them to get sent on clock
while(USIOIF==0) // check USI data counter overflow flag to detect the end of transmission every byte 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 USICR|=(1<<USICLK)|(1<<USITC); // Enable clock for transmission and generate clock for slave deivce
} }
USISR|=(1<<USIOIF); // clear USI data counter overflow flag USISR|=(1<<USIOIF); // Clear USI data counter overflow flag
} }
// Read in a 16 bit frame // Read in a 16 bit frame
@ -104,22 +122,23 @@ uint8_t SendReceiveSPIData(uint8_t value)
//return inbyte; //return inbyte;
} }
// send a 32 bit register value to the ADF4350 // Send a 32 bit register value to the ADF4350
void SendSPIDataADF4350 (uint32_t outval) void SendSPIDataADF4350 (uint32_t outval)
{ {
// split into 4 x 8-bit words // 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 byte1 = (outval & 0xFF000000) >> 24;
uint8_t byte2 = (outval & 0x00FF0000) >> 16; uint8_t byte2 = (outval & 0x00FF0000) >> 16;
uint8_t byte3 = (outval & 0x0000FF00) >> 8; uint8_t byte3 = (outval & 0x0000FF00) >> 8;
uint8_t byte4 = outval & 0x000000FF; uint8_t byte4 = outval & 0x000000FF;
// send these to the ADF4350 via SPI // Send these to the ADF4350 via SPI
SendReceiveSPIData (byte1); SendReceiveSPIData (byte1);
SendReceiveSPIData (byte2); SendReceiveSPIData (byte2);
SendReceiveSPIData (byte3); SendReceiveSPIData (byte3);
SendReceiveSPIData (byte4); SendReceiveSPIData (byte4);
// 2 x 16 version: // 2 x 16 version (for reference):
// split into 2 x 16 bit words // split into 2 x 16 bit words
///uint16_t highWord = (outval & 0xffff0000) >> 16; ///uint16_t highWord = (outval & 0xffff0000) >> 16;
///uint16_t lowWord = outval & 0x0000ffff; ///uint16_t lowWord = outval & 0x0000ffff;
@ -127,12 +146,16 @@ void SendSPIDataADF4350 (uint32_t outval)
///SendReceiveSPIData (highWord); ///SendReceiveSPIData (highWord);
///SendReceiveSPIData (lowWord); ///SendReceiveSPIData (lowWord);
// delay so the clock has gone low before LE is taken high // Delay to make sure the clock has gone low before LE is taken high.
Delay(10); Delay(10);
// pull LE high to load the data into the ADF4350 register
PORTB |= (1 << PORTB3); // Pull LE high to load the data into the ADF4350 register.
// short delay while LE is high (minimum of 20ns) PORTB |= (1 << PB3);
Delay(30);
// pull LE low again // Short delay while LE is high (minimum of 20ns).
PORTB &= ~(1 << PORTB3); // This is to make sure the ADF4350 has time to register bits.
Delay(100);
// Pull LE low again.
PORTB &= ~(1 << PB3);
} }