avr-minimal/main.cc
2015-09-15 19:06:25 -05:00

108 lines
2.7 KiB
C++

#include <avr/interrupt.h>
#include <avr/io.h>
#include <stdint.h>
#include <stdio.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#define PIN_LED (5) // onboard LED is PORTD5
#define PUTS_PP(x, ...) puts_P(PSTR(x), ## __VA_ARGS__)
#define PRINTF_PP(x, ...) printf_P(PSTR(x), ## __VA_ARGS__)
#define SCANF_PP(x, ...) scanf_P(PSTR(x), ## __VA_ARGS__)
#define FREQ_BASE (120e6)
#define W_CLK (5) // PORTB5, SCK = pin 13
#define FQ_UD (4) // PORTB4 = pin 12
#define DATA7 (3) // PORTB3, MOSI = pin 11
#define TRIG (2) // PORTB2 = pin 10
void setup() {
// set up SPI interface @ 8MHz
SPCR = (1<<SPE) | (1<<MSTR);
SPSR = (1<<SPI2X); // fOSC/2
// enable outputs
DDRB = (1<<W_CLK) | (1<<FQ_UD) | (1<<DATA7) << (1<<TRIG);
// strobe once to put device in serial mode
PORTD |= (1<<FQ_UD);
PORTD &= ~(1<<FQ_UD);
}
void shift_byte(unsigned char b) {
loop_until_bit_is_clear(SPSR, SPIF);
SPDR = b;
}
void set_freq_raw(unsigned long f) {
PRINTF_PP("set_freq_raw %lu\n", f);
shift_byte(0x0);
shift_byte(f & 0xff); f >>= 8;
shift_byte(f & 0xff); f >>= 8;
shift_byte(f & 0xff); f >>= 8;
shift_byte(f & 0xff);
loop_until_bit_is_clear(SPSR, SPIF);
PORTD |= (1<<FQ_UD);
PORTD &= ~(1<<FQ_UD);
// strobe FQ_UP
}
unsigned long raw_freq(unsigned long khz) {
return (unsigned long)(khz * (1000. * 4294967295. / FREQ_BASE));
}
void set_freq(unsigned long khz) {
set_freq_raw(raw_freq(khz));
}
void sweep(unsigned long lo, unsigned long hi, int steps) {
lo = raw_freq(lo);
hi = raw_freq(hi);
// rounding error assumed unimportant
unsigned long delta = (hi - lo) / steps;
PORTB |= (1<<TRIG); // trigger your scope
for(int u = 0; u < steps; u++ ) {
set_freq_raw(lo);
lo += delta;
}
PORTB &= ~(1<<TRIG);
}
int main() {
unsigned long freq, freq_end;
int steps;
DDRD |= (1<<PIN_LED);
usage:
PUTS_PP(
"f ### - set frequency ###kHz\n"
"s #1# #2# #3# - sweep from frequency #1#kHz to #2#kHz in #3# steps"
);
while(1) {
int op = getchar();
switch(op) {
case 'f':
SCANF_PP("%lu", &freq);
set_freq(freq); break;
case 's':
SCANF_PP("%lu %lu %i", &freq, &freq_end, &steps);
PUTS_PP("press any key to cancel");
// fallthrough
do {
sweep(freq, freq_end, steps);
} while(!(UCSR0A & (1<<RXC0)));
break;
case '?':
goto usage;
}
}
}
/*
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. This file is offered as-is,
without any warranty.
*/