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 "cc1110-ext.h"
22 #include "ioCCxx10_bitdef.h"
26 __xdata __at 0xff00 channel_info chan_table[NUM_CHANNELS];
39 void sleepMillis(int ms) {
44 for (j=0; j<1200;j++); // about 1 millisecond
50 /* IF of 457.031 kHz */
54 /* disable 3 highest DVGA settings */
55 AGCCTRL2 |= AGCCTRL2_MAX_DVGA_GAIN;
57 /* frequency synthesizer calibration */
63 /* "various test settings" */
68 /* no automatic frequency calibration */
72 /* set the channel bandwidth */
74 /* channel spacing should fit within 80% of channel filter bandwidth */
77 MDMCFG4 = 0xEC; /* 67.708333 kHz */
80 MDMCFG4 = 0x0C; /* 812.5 kHz */
83 MDMCFG4 = 0x6C; /* 270.833333 kHz */
88 /* set the radio frequency in Hz */
89 void set_radio_freq(u32 freq) {
90 /* the frequency setting is in units of 396.728515625 Hz */
91 u32 setting = (u32) (freq * .0025206154);
92 FREQ2 = (setting >> 16) & 0xff;
93 FREQ1 = (setting >> 8) & 0xff;
94 FREQ0 = setting & 0xff;
96 if ((band == BAND_300 && freq < MID_300) ||
97 (band == BAND_400 && freq < MID_400) ||
98 (band == BAND_900 && freq < MID_900))
102 /* select high VCO */
107 void calibrate_freq(u32 freq, u8 ch) {
108 set_radio_freq(freq);
113 /* wait for calibration */
116 /* store frequency/calibration settings */
117 chan_table[ch].freq2 = FREQ2;
118 chan_table[ch].freq1 = FREQ1;
119 chan_table[ch].freq0 = FREQ0;
120 chan_table[ch].fscal3 = FSCAL3;
121 chan_table[ch].fscal2 = FSCAL2;
122 chan_table[ch].fscal1 = FSCAL1;
124 /* get initial RSSI measurement */
125 chan_table[ch].ss = (RSSI ^ 0x80);
126 chan_table[ch].max = 0;
131 #define UPPER(a, b, c) ((((a) - (b) + ((c) / 2)) / (c)) * (c))
132 #define LOWER(a, b, c) ((((a) + (b)) / (c)) * (c))
134 /* set the center frequency in MHz */
135 u16 set_center_freq(u16 freq) {
152 margin = NARROW_MARGIN;
154 spacing = NARROW_SPACING;
157 margin = ULTRAWIDE_MARGIN;
158 step = ULTRAWIDE_STEP;
159 spacing = ULTRAWIDE_SPACING;
161 /* nearest 20 MHz step */
162 freq = ((freq + 10) / 20) * 20;
165 margin = WIDE_MARGIN;
167 spacing = WIDE_SPACING;
169 /* nearest 5 MHz step */
170 freq = ((freq + 2) / 5) * 5;
174 /* handle cases near edges of bands */
175 if (freq > EDGE_900) {
177 upper_limit = UPPER(MAX_900, margin, step);
178 lower_limit = LOWER(MIN_900, margin, step);
179 next_up = LOWER(MIN_300, margin, step);
180 next_down = UPPER(MAX_400, margin, step);
181 next_band_up = BAND_300;
182 next_band_down = BAND_400;
183 } else if (freq > EDGE_400) {
185 upper_limit = UPPER(MAX_400, margin, step);
186 lower_limit = LOWER(MIN_400, margin, step);
187 next_up = LOWER(MIN_900, margin, step);
188 next_down = UPPER(MAX_300, margin, step);
189 next_band_up = BAND_900;
190 next_band_down = BAND_300;
193 upper_limit = UPPER(MAX_300, margin, step);
194 lower_limit = LOWER(MIN_300, margin, step);
195 next_up = LOWER(MIN_400, margin, step);
196 next_down = UPPER(MAX_900, margin, step);
197 next_band_up = BAND_400;
198 next_band_down = BAND_900;
201 if (freq > upper_limit) {
203 if (new_band == band) {
204 new_band = next_band_up;
207 } else if (freq < lower_limit) {
209 if (new_band == band) {
210 new_band = next_band_down;
217 /* doing everything in Hz from here on */
220 min_hz = MIN_400 * 1000000;
221 max_hz = MAX_400 * 1000000;
224 min_hz = MIN_300 * 1000000;
225 max_hz = MAX_300 * 1000000;
228 min_hz = MIN_900 * 1000000;
229 max_hz = MAX_900 * 1000000;
233 /* calibrate upper channels */
235 max_chan = NUM_CHANNELS / 2;
236 while (hz <= max_hz && max_chan < NUM_CHANNELS) {
237 calibrate_freq(hz, max_chan);
242 /* calibrate lower channels */
243 hz = freq * 1000000 - spacing;
244 min_chan = NUM_CHANNELS / 2;
245 while (hz >= min_hz && min_chan > 0) {
247 calibrate_freq(hz, min_chan);
257 /* tune the radio using stored calibration */
259 FREQ2 = chan_table[ch].freq2;
260 FREQ1 = chan_table[ch].freq1;
261 FREQ0 = chan_table[ch].freq0;
263 FSCAL3 = chan_table[ch].fscal3;
264 FSCAL2 = chan_table[ch].fscal2;
265 FSCAL1 = chan_table[ch].fscal1;
268 void set_width(u8 w) {
271 set_center_freq(center_freq);
274 void poll_keyboard() {
279 vstep = (height == TALL) ? TALL_STEP : SHORT_STEP;
286 hstep = ULTRAWIDE_STEP;
301 set_width(ULTRAWIDE);
309 set_width(ULTRAWIDE);
333 vscroll = MIN(vscroll + vstep, MAX_VSCROLL);
337 vscroll = MAX(vscroll - vstep, MIN_VSCROLL);
340 max_hold = !max_hold;
356 center_freq = DEFAULT_FREQ;
357 user_freq = DEFAULT_FREQ;
365 max_chan = NUM_CHANNELS - 1;
367 //presumed to be done by GoodFET.
376 for (ch = min_chan; ch < max_chan; ch++) {
377 /* tune radio and start RX */
381 /* delay while waiting for RSSI measurement */
384 /* measurement needs a bit more time in narrow mode */
386 for (i = 350; i-- ;);
389 chan_table[ch].ss = (RSSI ^ 0x80);
391 chan_table[ch].max = MAX(chan_table[ch].ss,
394 chan_table[ch].max = 0;
401 chan_table[0].ss=0x00;
404 if (user_freq != center_freq)
405 user_freq = set_center_freq(user_freq);