
I have lots of ideas for applications of these things, including:
- General purpose VFO with keypad and knob
- Sweep test generator, paired with a digital rf signal measurer for computer plotting filters etc
- Automated antenna analyser with a digital SWR measuring thingy
This code is written in C and uses avrlibc. I'm working on a Mac but it will work the same on Linux or that other OS that was quite popular.
/*
Control an AD9851 DDS with an ATMega85
*/
#include <avr/io.h>
// Sets up the default speed for delay.h
#define F_CPU 800000UL
#include <util/delay.h>
#include <math.h> // for pow()
// Pins used to talk to the DDS chip
#define LOAD 4
#define CLOCK 3
#define DATA 0
#define LED 1
#define DDS_CLOCK 180000000UL
#define OUTPORT PORTB
#define OUTPORTDIRECTION DDRB
void sendFrequency(unsigned long frequency);
void byte_out(unsigned char byte);
void outOne();
void outZero();
void bitSetHi(volatile uint8_t *port, int bit);
void bitSetLo(volatile uint8_t *port, int bit);
int main (void)
{
OUTPORTDIRECTION = _BV(LOAD) | _BV(CLOCK) | _BV(DATA) | _BV(LED);
unsigned long freq;
// flash an led to show we're alive
int i;
for(i = 0; i < 10; i++)
{
bitSetHi(&OUTPORT, LED);
_delay_ms(100);
bitSetLo(&OUTPORT, LED);
_delay_ms(100);
}
while (1)
{
// Do a frequency sweep in Hz
for(freq = 10000000; freq < 10001000; freq++)
{
sendFrequency(freq);
_delay_ms(1);
}
}
return 0;
}
void bitSetHi(volatile uint8_t *port, int bit)
{
*port |= ( 1<<bit );
}
void bitSetLo(volatile uint8_t *port, int bit)
{
*port &= ~( 1<<bit );
}
void sendFrequency(unsigned long frequency)
{
unsigned long tuning_word = (frequency * pow(2, 32)) / DDS_CLOCK;
bitSetLo(&OUTPORT, LOAD); // take load pin low
int i;
for(i = 0; i < 32; i++)
{
if ((tuning_word & 1) == 1)
outOne();
else
outZero();
tuning_word = tuning_word >> 1;
}
byte_out(0x09);
bitSetHi(&OUTPORT, LOAD); // Take load pin high again
}
void byte_out(unsigned char byte)
{
int i;
for (i = 0; i < 8; i++)
{
if ((byte & 1) == 1)
outOne();
else
outZero();
byte = byte >> 1;
}
}
void outOne()
{
bitSetLo(&OUTPORT, CLOCK);
_delay_ms(1);
bitSetHi(&OUTPORT, DATA);
_delay_ms(1);
bitSetHi(&OUTPORT, CLOCK);
_delay_ms(1);
bitSetLo(&OUTPORT, DATA);
_delay_ms(1);
}
void outZero()
{
bitSetLo(&OUTPORT, CLOCK);
_delay_ms(1);
bitSetLo(&OUTPORT, DATA);
_delay_ms(1);
bitSetHi(&OUTPORT, CLOCK);
_delay_ms(1);
}
The AMQRP board has it's own regulator and has a 5V output so I'm powering the ATTiny85 from that power rather than a separate input. Here's a nifty spot reference. Simple enough even for me to build.
