2 * Copyright 2010 Michael Ossmann
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2, or (at your option)
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; see the file COPYING. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street,
17 * Boston, MA 02110-1301, USA.
21 #include "ioCCxx10_bitdef.h"
25 __xdata channel_info chan_table[NUM_CHANNELS];
38 void sleepMillis(int ms) {
43 for (j=0; j<1200;j++); // about 1 millisecond
49 /* IF of 457.031 kHz */
53 /* disable 3 highest DVGA settings */
54 AGCCTRL2 |= AGCCTRL2_MAX_DVGA_GAIN;
56 /* frequency synthesizer calibration */
62 /* "various test settings" */
67 /* no automatic frequency calibration */
71 /* set the channel bandwidth */
73 /* channel spacing should fit within 80% of channel filter bandwidth */
76 MDMCFG4 = 0xEC; /* 67.708333 kHz */
79 MDMCFG4 = 0x0C; /* 812.5 kHz */
82 MDMCFG4 = 0x6C; /* 270.833333 kHz */
87 /* set the radio frequency in Hz */
88 void set_radio_freq(u32 freq) {
89 /* the frequency setting is in units of 396.728515625 Hz */
90 u32 setting = (u32) (freq * .0025206154);
91 FREQ2 = (setting >> 16) & 0xff;
92 FREQ1 = (setting >> 8) & 0xff;
93 FREQ0 = setting & 0xff;
95 if ((band == BAND_300 && freq < MID_300) ||
96 (band == BAND_400 && freq < MID_400) ||
97 (band == BAND_900 && freq < MID_900))
101 /* select high VCO */
106 void calibrate_freq(u32 freq, u8 ch) {
107 set_radio_freq(freq);
112 /* wait for calibration */
115 /* store frequency/calibration settings */
116 chan_table[ch].freq2 = FREQ2;
117 chan_table[ch].freq1 = FREQ1;
118 chan_table[ch].freq0 = FREQ0;
119 chan_table[ch].fscal3 = FSCAL3;
120 chan_table[ch].fscal2 = FSCAL2;
121 chan_table[ch].fscal1 = FSCAL1;
123 /* get initial RSSI measurement */
124 chan_table[ch].ss = (RSSI ^ 0x80);
125 chan_table[ch].max = 0;
130 #define UPPER(a, b, c) ((((a) - (b) + ((c) / 2)) / (c)) * (c))
131 #define LOWER(a, b, c) ((((a) + (b)) / (c)) * (c))
133 /* set the center frequency in MHz */
134 u16 set_center_freq(u16 freq) {
151 margin = NARROW_MARGIN;
153 spacing = NARROW_SPACING;
156 margin = ULTRAWIDE_MARGIN;
157 step = ULTRAWIDE_STEP;
158 spacing = ULTRAWIDE_SPACING;
160 /* nearest 20 MHz step */
161 freq = ((freq + 10) / 20) * 20;
164 margin = WIDE_MARGIN;
166 spacing = WIDE_SPACING;
168 /* nearest 5 MHz step */
169 freq = ((freq + 2) / 5) * 5;
173 /* handle cases near edges of bands */
174 if (freq > EDGE_900) {
176 upper_limit = UPPER(MAX_900, margin, step);
177 lower_limit = LOWER(MIN_900, margin, step);
178 next_up = LOWER(MIN_300, margin, step);
179 next_down = UPPER(MAX_400, margin, step);
180 next_band_up = BAND_300;
181 next_band_down = BAND_400;
182 } else if (freq > EDGE_400) {
184 upper_limit = UPPER(MAX_400, margin, step);
185 lower_limit = LOWER(MIN_400, margin, step);
186 next_up = LOWER(MIN_900, margin, step);
187 next_down = UPPER(MAX_300, margin, step);
188 next_band_up = BAND_900;
189 next_band_down = BAND_300;
192 upper_limit = UPPER(MAX_300, margin, step);
193 lower_limit = LOWER(MIN_300, margin, step);
194 next_up = LOWER(MIN_400, margin, step);
195 next_down = UPPER(MAX_900, margin, step);
196 next_band_up = BAND_400;
197 next_band_down = BAND_900;
200 if (freq > upper_limit) {
202 if (new_band == band) {
203 new_band = next_band_up;
206 } else if (freq < lower_limit) {
208 if (new_band == band) {
209 new_band = next_band_down;
216 /* doing everything in Hz from here on */
219 min_hz = MIN_400 * 1000000;
220 max_hz = MAX_400 * 1000000;
223 min_hz = MIN_300 * 1000000;
224 max_hz = MAX_300 * 1000000;
227 min_hz = MIN_900 * 1000000;
228 max_hz = MAX_900 * 1000000;
232 /* calibrate upper channels */
234 max_chan = NUM_CHANNELS / 2;
235 while (hz <= max_hz && max_chan < NUM_CHANNELS) {
236 calibrate_freq(hz, max_chan);
241 /* calibrate lower channels */
242 hz = freq * 1000000 - spacing;
243 min_chan = NUM_CHANNELS / 2;
244 while (hz >= min_hz && min_chan > 0) {
246 calibrate_freq(hz, min_chan);
256 /* tune the radio using stored calibration */
258 FREQ2 = chan_table[ch].freq2;
259 FREQ1 = chan_table[ch].freq1;
260 FREQ0 = chan_table[ch].freq0;
262 FSCAL3 = chan_table[ch].fscal3;
263 FSCAL2 = chan_table[ch].fscal2;
264 FSCAL1 = chan_table[ch].fscal1;
267 void set_width(u8 w) {
270 set_center_freq(center_freq);
273 void poll_keyboard() {
278 vstep = (height == TALL) ? TALL_STEP : SHORT_STEP;
285 hstep = ULTRAWIDE_STEP;
300 set_width(ULTRAWIDE);
308 set_width(ULTRAWIDE);
332 vscroll = MIN(vscroll + vstep, MAX_VSCROLL);
336 vscroll = MAX(vscroll - vstep, MIN_VSCROLL);
339 max_hold = !max_hold;
355 center_freq = DEFAULT_FREQ;
356 user_freq = DEFAULT_FREQ;
364 max_chan = NUM_CHANNELS - 1;
366 //presumed to be done by GoodFET.
373 for (ch = min_chan; ch < max_chan; ch++) {
374 /* tune radio and start RX */
378 /* delay while waiting for RSSI measurement */
381 /* measurement needs a bit more time in narrow mode */
383 for (i = 350; i-- ;);
386 chan_table[ch].ss = (RSSI ^ 0x80);
388 chan_table[ch].max = MAX(chan_table[ch].ss,
391 chan_table[ch].max = 0;
400 if (user_freq != center_freq)
401 user_freq = set_center_freq(user_freq);