summaryrefslogtreecommitdiff
path: root/ezdop/src/firmware/dopctrl.c
diff options
context:
space:
mode:
Diffstat (limited to 'ezdop/src/firmware/dopctrl.c')
-rw-r--r--ezdop/src/firmware/dopctrl.c193
1 files changed, 193 insertions, 0 deletions
diff --git a/ezdop/src/firmware/dopctrl.c b/ezdop/src/firmware/dopctrl.c
new file mode 100644
index 000000000..f499d6c35
--- /dev/null
+++ b/ezdop/src/firmware/dopctrl.c
@@ -0,0 +1,193 @@
+/*
+ * AE6HO EZ-Doppler firmware for onboard ATmega8 microcontroller
+ * Copyright 2006 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * ARCHITECTURE
+ *
+ * Timer0 is 8000 Hz time base
+ * PORTD.2 through PORTD.5 are doppler antenna array element enables.
+ * PORTB.0 is a diagnostic LED, set low to light up
+ * ADC7 is audio input
+ * ADC6 is RSSI input - not yet used
+ *
+ */
+
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <avr/signal.h>
+#include "dopctrl.h"
+
+#define LED 0
+#define turn_off_led() PORTB |= _BV(LED);
+#define turn_on_led() PORTB &= ~_BV(LED);
+
+#define ANT1 _BV(2)
+#define ANT2 _BV(3)
+#define ANT3 _BV(4)
+#define ANT4 _BV(5)
+#define ANTMASK ANT1|ANT2|ANT3|ANT4
+
+#define ADCAIN 7
+#define BAUDRATE 250000
+
+/* Assume these are all set to zero in startup code */
+
+uint8_t rotate; /* Flag to indicate antennas should rotate or not */
+uint8_t streaming; /* Flag to indicate continuous sampling */
+uint8_t antennas; /* Holds shadow copy of PORTD antennas */
+uint8_t speed; /* Holds samples per phase increment */
+uint8_t phase; /* Holds rotation phase (measured in samples */
+
+uint8_t audio_hi; /* High byte of ADC sample of audio */
+uint8_t audio_lo; /* Low byte of ADC sample of audio */
+
+uint8_t rx; /* Temporary holds received byte from USART */
+uint8_t command; /* Temporary to hold command when getting operand */
+uint8_t cmdbyte; /* Tracks bytes received in multi-byte commands */
+
+int main(void)
+{
+ /* Diagnostic port setup */
+ DDRB = _BV(LED); /* PB0 is output */
+ turn_off_led();
+
+ /* Antenna control port setup */
+ speed = 4; /* Todo: read from EEPROM */
+ antennas = ANT1; /* Start with antenna #1 */
+ PORTD = antennas; /* Set port value */
+ DDRD = ANTMASK; /* Set antenna enables as PORTD outputs */
+
+ /* ADC port setup */
+ ADMUX = _BV(REFS0)|ADCAIN; /* AVCC is reference, use ADC for audio input (ADC7) */
+ ADCSRA = _BV(ADEN)|_BV(ADIE)|0x07; /* Enable converter, prescale by 128, enable ADC interrupt */
+
+ /* USART port setup*/
+ UCSRA = 0; /* Normal asynchronous mode */
+ UCSRB = _BV(TXEN)|_BV(RXEN)|_BV(RXCIE); /* Enable transmitter and receiver, and receiver interrupts */
+ UCSRC = _BV(URSEL)|_BV(UCSZ1)|_BV(UCSZ0); /* 8N1 format */
+ UBRRH = 0; /* Set baud rate prescaler to 3 */
+ UBRRL = 3; /* To get 250000 bps */
+
+ /* Set up 8000 Hz time base */
+ timer_enable_int(_BV(TOIE0)); /* Turn on Timer0 output overflow interrupt */
+ TCCR0 = _BV(CS01); /* Clock Timer0 from CLK/8 */
+
+ sei(); /* Let 'er rip! */
+ return 0;
+}
+
+/* Timer0 overflow interrupt handler
+ *
+ * Creates 8000 Hz time base, or 125us budget
+ *
+ */
+SIGNAL(SIG_OVERFLOW0)
+{
+ /* Reload Timer0 samples to 8, results in 8000 Hz overflow interrupt */
+ TCNT0 = 0x08;
+
+ if (streaming) {
+ /* Kick-off an audio sample conversion, will interrupt 104us later */
+ ADCSRA |= _BV(ADSC);
+
+ /* Write the first byte of previous sample and enable UDRIE */
+ UDR = audio_lo;
+ UCSRB |= _BV(UDRIE);
+ }
+
+ if (!rotate) /* Skip rotating antenna if not started */
+ return;
+
+ /* Increment antenna phase and see if antenna need to be rotated */
+ if (++phase == speed) {
+ phase = 0;
+
+ /* Sequence antenna array elements */
+ antennas >>= 1;
+ antennas &= ANTMASK;
+
+ if (!antennas)
+ antennas = ANT4;
+ PORTD = antennas;
+ }
+}
+
+/* ADC conversion complete interrupt handler
+ *
+ * Read value and store. Assume prior sample has been handled.
+ *
+ */
+SIGNAL(SIG_ADC)
+{
+ audio_lo = ADCL;
+ audio_hi = ADCH;
+}
+
+/* USART data transmit holding register empty interrupt handler
+ *
+ * First byte is always sent from timer interrupt
+ * So second byte gets sent here with UDRIE disabled
+ *
+ */
+SIGNAL(SIG_UART_DATA)
+{
+ /* Write second byte of previous sample and disable UDRIE */
+ UDR = audio_hi | (antennas << 2);
+ UCSRB &= ~_BV(UDRIE);
+}
+
+/* USART receive complete interrupt handler
+ *
+ * Received bytes are commands, with one or two bytes of operands following
+ *
+ */
+SIGNAL(SIG_UART_RECV)
+{
+ rx = UDR;
+
+ if (cmdbyte == 0) {
+ if (rx == EZDOP_CMD_ROTATE) /* Start rotation */
+ rotate = 1;
+ else if (rx == EZDOP_CMD_STOP) /* Stop rotation */
+ rotate = 0;
+ else if (rx == EZDOP_CMD_RATE) { /* Set rotation rate */
+ command = rx;
+ cmdbyte = 1;
+ }
+ else if (rx == EZDOP_CMD_STREAM) /* Stream audio samples */
+ streaming = 1;
+ else if (rx == EZDOP_CMD_STROFF) /* Stop streaming */
+ streaming = 0;
+ else
+ turn_on_led(); /* Unknown command */
+ }
+ else if (cmdbyte == 1) {
+ if (command == EZDOP_CMD_RATE) { /* Operand is number of samples per phase increment */
+ speed = rx;
+ cmdbyte = 0;
+ }
+ else
+ turn_on_led(); /* Bogus command state */
+ }
+ else
+ turn_on_led(); /* Bogus command state */
+}