/* * 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., 51 Franklin Street, * Boston, MA 02110-1301, 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 #include #include #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 */ }