2 * Copyright 2006 Free Software Foundation, Inc.
4 * This file is part of GNU Radio
6 * GNU Radio is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
11 * GNU Radio is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Radio; see the file COPYING. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street,
19 * Boston, MA 02110-1301, USA.
22 // Application specific includes
26 #include <boost/scoped_array.hpp>
28 // System includes (FIXME: autoconf these)
35 d_device = new struct ftdi_context;
36 if (ftdi_init(d_device))
37 fprintf(stderr, "ftdi_init: %s", d_device->error_str);
40 d_rate = EZDOP_DEFAULT_RATE;
42 d_ant = 8; // FIXME: get from controller.h
62 // Attaches to first found device matching ID strings
63 if (ftdi_usb_open(d_device, EZDOP_VENDORID, EZDOP_PRODUCTID)) {
64 fprintf(stderr, "ftdi_usb_open: %s", d_device->error_str);
84 if (ftdi_usb_close(d_device)) {
85 fprintf(stderr, "ftdi_usb_close: %s", d_device->error_str);
99 if (ftdi_usb_reset(d_device)) {
100 fprintf(stderr, "ftdi_usb_reset: %s", d_device->error_str);
104 // Set FTDI chipset baudrate for bitbang
105 if (ftdi_set_baudrate(d_device, EZDOP_BAUDRATE)) {
106 fprintf(stderr, "ftdi_set_baudrate: %s", d_device->error_str);
110 // Toggle DTR (-->AVR RESET)
112 if (ftdi_enable_bitbang(d_device, EZDOP_BBDIR)) {
113 fprintf(stderr, "ftdi_enable_bitbang: %s", d_device->error_str);
117 // Lower DTR by writing 0 to bitbang output
118 if (!send_byte(0x00)) // This actually lowers all outputs, not just DTR
121 // 10 ms sleep with RESET low
124 // Now raise DTR by writing 1 to bitbang output
125 if (!send_byte(0xFF)) // This actually raises all outputs, not just DTR
128 if (ftdi_disable_bitbang(d_device)) {
129 fprintf(stderr, "ftdi_disable_bitbang: %s", d_device->error_str);
133 // Minimum chunk size for reads to reduce latency
134 if (ftdi_read_data_set_chunksize(d_device, 256)) {
135 fprintf(stderr, "ftdi_read_data_set_chunksize: %s", d_device->error_str);
139 // 100 ms after RESET cleared to let things warm up
142 d_rate = EZDOP_DEFAULT_RATE;
146 bool ezdop::set_rate(int rate)
151 // Rate command is one byte, followed by rate as operand
152 int divisor = 2000/rate;
153 if (send_byte(EZDOP_CMD_RATE) && send_byte((unsigned char)divisor)) {
166 d_rotating = send_byte(EZDOP_CMD_ROTATE);
170 bool ezdop::stop_rotating()
175 // TODO: set to antenna #1, perhaps do this in firmware instead
176 d_rotating = send_byte(EZDOP_CMD_STOP);
185 return (send_byte(EZDOP_CMD_STREAM));
188 bool ezdop::stop_streaming()
193 return (send_byte(EZDOP_CMD_STROFF));
196 bool ezdop::send_byte(unsigned char data)
201 if (ftdi_write_data(d_device, &data, 1) != 1) {
202 fprintf(stderr, "ftdi_write_data: %s", d_device->error_str);
209 int ezdop::read_raw(unsigned char *buffer, unsigned int length)
215 // Read samples from USB port, 2 bytes per sample
216 int rd = ftdi_read_data(d_device, buffer, length);
218 fprintf(stderr, "ftdi_read_data: %s", d_device->error_str);
225 typedef boost::scoped_array<unsigned char> unsigned_char_scoped_array;
227 int ezdop::read_iq(complex<float> *buffer, unsigned int samples, float &volume)
233 // 4 phases, d_rate samples per phase, 2 bytes per sample
234 int raw_size = 8*d_rate*samples;
235 unsigned_char_scoped_array raw(new unsigned char[raw_size]);
237 // Read until required bytes are read. Will block until bytes arrive.
239 while (rd < raw_size)
240 rd += read_raw(&raw[rd], raw_size-rd);
242 // Iterate through read bytes and invoke state machine
243 int i = 0, j = 0; // i index inputs, j indexes outputs
245 while (i < raw_size) {
246 unsigned char ch = raw[i++];
247 if (d_state == ST_LO) {
248 d_val = ch; // Save lo byte
249 d_state = ST_HI; // Switch states
250 continue; // Done with this state
253 if (d_state == ST_HI) {
254 unsigned char ant = ch >> 4; // antenna is high nibble
255 if (ant != d_ant) { // Didn't get expected antenna
256 // Abort current sequence
260 d_in_phase = 0; d_quadrature = 0;
261 d_val = ch; // Act as if this were a lo byte instead
262 continue; // Stay in ST_HI
266 // Got correct antenna
267 d_val |= (ch & 0x03) << 8; // Mask off and save audio high value
269 // This down-converts rotation frequency to exactly 0 Hz
270 // while integrating audio response over duration of one antenna phase
271 if (d_ant == 8) // +I
273 else if (d_ant == 4) // +Q
274 d_quadrature += d_val;
275 else if (d_ant == 2) // -I
277 else if (d_ant == 1) // -Q
278 d_quadrature -= d_val;
282 // Update expected antenna and sequence
283 if (++d_seq == d_rate) {
286 if (d_ant == 0) { // fell off the end
287 d_ant = 8; // FIXME: grab from controller.h
289 // We've accumulated I and Q over a whole antenna rotation
290 // Output complex<float> in range [-1.0, 1.0]
291 buffer[j++] = complex<float>(d_in_phase/(1024.0*d_rate),
292 d_quadrature/(1024.0*d_rate));
293 d_in_phase = 0; d_quadrature = 0;
297 d_state = ST_LO; // Switch states