Merge commit 'cbc8062ef8ba10690aa64b433d0efdccb46f496a'
[osmocom-bb.git] / src / target / firmware / apps / l1test / main.c
1 /* main program of Free Software for Calypso Phone */
2
3 /* (C) 2010 by Harald Welte <laforge@gnumonks.org>
4  *
5  * All Rights Reserved
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  */
22
23 #include <stdint.h>
24 #include <stdio.h>
25
26 #include <debug.h>
27 #include <memory.h>
28 #include <rffe.h>
29 #include <keypad.h>
30 #include <board.h>
31
32 #include <abb/twl3025.h>
33 #include <display.h>
34 #include <rf/trf6151.h>
35
36 #include <comm/sercomm.h>
37 #include <comm/timer.h>
38
39 #include <calypso/clock.h>
40 #include <calypso/tpu.h>
41 #include <calypso/tsp.h>
42 #include <calypso/irq.h>
43 #include <calypso/misc.h>
44
45 #include <layer1/sync.h>
46 #include <layer1/tpu_window.h>
47
48 #define SCAN
49
50 #ifdef SCAN
51 /* if scanning is enabled, scan from 0 ... 124 */
52 #define BASE_ARFCN      0
53 #else
54 /* fixed ARFCN in GSM1800 at which Harald has his GSM test license */
55 #define BASE_ARFCN      871
56 #endif
57
58 /* FIXME: We need proper calibrated delay loops at some point! */
59 void delay_us(unsigned int us)
60 {
61         volatile unsigned int i;
62
63         for (i= 0; i < us*4; i++) { i; }
64 }
65
66 void delay_ms(unsigned int ms)
67 {
68         volatile unsigned int i;
69
70         for (i= 0; i < ms*1300; i++) { i; }
71 }
72
73 /* Main Program */
74 const char *hr = "======================================================================\n";
75
76 /* Best ARFCN MAP ************************************************************/
77
78 struct arfcn_map {
79         uint16_t arfcn;
80         int16_t dbm8;
81 };
82
83 static struct arfcn_map best_arfcn_map[10];
84 static void best_arfcn_update(uint16_t arfcn, int16_t dbm8)
85 {
86         unsigned int i;
87         for (i = 0; i < ARRAY_SIZE(best_arfcn_map); i++) {
88                 if (best_arfcn_map[i].dbm8 < dbm8 ||
89                     best_arfcn_map[i].dbm8 == 0) {
90                         best_arfcn_map[i].dbm8 = dbm8;
91                         best_arfcn_map[i].arfcn = arfcn;
92                         return;
93                 }
94         }
95 }
96
97 static void best_arfcn_dump(void)
98 {
99         unsigned int i;
100
101         for (i = 0; i < ARRAY_SIZE(best_arfcn_map); i++) {
102                 if (best_arfcn_map[i].dbm8 == 0)
103                         continue;
104                 printf("ARFCN %3d: %d dBm\n",
105                         best_arfcn_map[i].arfcn,
106                         best_arfcn_map[i].dbm8/8);
107         }
108 }
109
110
111 /* MAIN program **************************************************************/
112
113 enum l1test_state {
114         STATE_NONE,
115         STATE_PM,
116         STATE_FB,
117 };
118
119 static void l1test_state_change(enum l1test_state new_state)
120 {
121         switch (new_state) {
122         case STATE_PM:
123                 puts("Performing power measurement over GSM900\n");
124                 l1s_pm_test(1, BASE_ARFCN);
125                 break;
126         case STATE_FB:
127                 puts("Starting FCCH Recognition\n");
128                 l1s_fb_test(1, 0);
129                 break;
130         case STATE_NONE:
131                 /* disable frame interrupts */
132                 tpu_frame_irq_en(0, 0);
133                 break;
134         }
135 }
136
137 /* completion call-back for the L1 Sync Pwer Measurement */
138 static void l1s_signal_cb(struct l1_signal *sig)
139 {
140         uint16_t i, next_arfcn;
141
142         switch (sig->signum) {
143         case L1_SIG_PM:
144                 best_arfcn_update(sig->arfcn, sig->pm.dbm8[0]);
145                 next_arfcn = sig->arfcn + 1;
146
147                 if (next_arfcn >= 124) {
148                         puts("ARFCN Top 10 Rx Level\n");
149                         best_arfcn_dump();
150
151                         trf6151_rx_window(0, best_arfcn_map[0].arfcn, 40, 0);
152                         tpu_end_scenario();
153
154                         /* PM phase completed, do FB det */
155                         l1test_state_change(STATE_FB);
156
157                         break;
158                 }
159
160                 /* restart Power Measurement */
161                 l1s_pm_test(1, next_arfcn);
162                 break;
163         case L1_SIG_NB:
164                 puts("NB SNR ");
165                 for (i = 0; i < 4; i++) {
166                         uint16_t snr = sig->nb.meas[i].snr;
167                         printf("%d.%03u ", l1s_snr_int(snr), l1s_snr_fract(snr));
168                 }
169                 putchar('\n');
170                 printf("--> Frame %d %d 0x%04X ",  sig->nb.fire, sig->nb.crc, sig->nb.num_biterr);
171                 for (i = 0; i < ARRAY_SIZE(sig->nb.frame); i++)
172                         printf("%02X ", sig->nb.frame[i]);
173                 putchar('\n');
174                 break;
175         }
176 }
177
178 static void key_handler(enum key_codes code, enum key_states state);
179
180 int main(void)
181 {
182         board_init();
183         puts("\n\nHello World from " __FILE__ " program code\n");
184
185         puts(hr);
186         /* Dump device identification */
187         dump_dev_id();
188         puts(hr);
189
190         keypad_set_handler(&key_handler);
191
192         /* Dump clock config aftee PLL set */
193         calypso_clk_dump();
194         puts(hr);
195
196         display_set_attr(DISP_ATTR_INVERT);
197         display_puts("l1test.bin");
198
199         layer1_init();
200         l1s_set_handler(&l1s_signal_cb);
201
202         //dsp_checksum_task();
203 #ifdef SCAN
204         l1test_state_change(STATE_PM);
205 #else
206         l1test_state_change(STATE_FB);
207 #endif
208         tpu_frame_irq_en(1, 1);
209
210         while (1) {
211                 update_timers();
212         }
213
214         /* NOT REACHED */
215
216         twl3025_power_off();
217 }
218
219 static int8_t vga_gain = 40;
220 static int high_gain = 0;
221 static int afcout = 0;
222
223 static void update_vga_gain(void)
224 {
225         printf("VGA Gain: %u %s\n", vga_gain, high_gain ? "HIGH" : "LOW");
226         trf6151_set_gain(vga_gain, high_gain);
227         tpu_enq_sleep();
228         tpu_enable(1);
229         tpu_wait_idle();
230 }
231
232 static void tspact_toggle(uint8_t num)
233 {
234         printf("TSPACT%u toggle\n", num);
235         tsp_act_toggle((1 << num));
236         tpu_enq_sleep();
237         tpu_enable(1);
238         tpu_wait_idle();
239 }
240
241 static void key_handler(enum key_codes code, enum key_states state)
242 {
243         if (state != PRESSED)
244                 return;
245
246         switch (code) {
247         case KEY_1:     /* VGA gain decrement */
248                 vga_gain -= 2;
249                 if (vga_gain < 14)
250                         vga_gain = 14;
251                 update_vga_gain();
252                 break;
253         case KEY_2:     /* High/Low Rx gain */
254                 high_gain ^= 1;
255                 update_vga_gain();
256                 break;
257         case KEY_3:     /* VGA gain increment */
258                 vga_gain += 2;
259                 if (vga_gain > 40)
260                         vga_gain = 40;
261                 update_vga_gain();
262                 break;
263         case KEY_4:
264                 tspact_toggle(6);       /* TRENA (RFFE) */
265                 break;
266         case KEY_5:
267                 tspact_toggle(8);       /* GSM_TXEN (RFFE) */
268                 break;
269         case KEY_6:
270                 tspact_toggle(1);       /* PAENA (RFFE) */
271                 break;
272         case KEY_7:                     /* decrement AFC OUT */
273                 afcout -= 100;
274                 if (afcout < -4096)
275                         afcout = -4096;
276                 twl3025_afc_set(afcout);
277                 printf("AFC OUT: %u\n", twl3025_afcout_get());
278                 break;
279         case KEY_9:                     /* increase AFC OUT */
280                 afcout += 100;
281                 if (afcout > 4095)
282                         afcout = 4095;
283                 twl3025_afc_set(afcout);
284                 printf("AFC OUT: %u\n", twl3025_afcout_get());
285                 break;
286         default:
287                 break;
288         }
289 }