start to use libosmocore within the firmware
[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/st7558.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 enum l1test_state l1test_state;
120
121 static void l1test_state_change(enum l1test_state new_state)
122 {
123         switch (new_state) {
124         case STATE_PM:
125                 puts("Performing power measurement over GSM900\n");
126                 l1s_pm_test(1, BASE_ARFCN);
127                 break;
128         case STATE_FB:
129                 puts("Starting FCCH Recognition\n");
130                 l1s_fb_test(1, 0);
131                 break;
132         case STATE_NONE:
133                 /* disable frame interrupts */
134                 tpu_frame_irq_en(0, 0);
135                 break;
136         }
137 }
138
139 /* completion call-back for the L1 Sync Pwer Measurement */
140 static void l1s_signal_cb(struct l1_signal *sig)
141 {
142         uint16_t i, next_arfcn;
143
144         switch (sig->signum) {
145         case L1_SIG_PM:
146                 best_arfcn_update(sig->arfcn, sig->pm.dbm8[0]);
147                 next_arfcn = sig->arfcn + 1;
148
149                 if (next_arfcn >= 124) {
150                         puts("ARFCN Top 10 Rx Level\n");
151                         best_arfcn_dump();
152
153                         trf6151_rx_window(0, best_arfcn_map[0].arfcn, 40, 0);
154                         tpu_end_scenario();
155
156                         /* PM phase completed, do FB det */
157                         l1test_state_change(STATE_FB);
158
159                         break;
160                 }
161
162                 /* restart Power Measurement */
163                 l1s_pm_test(1, next_arfcn);
164                 break;
165         case L1_SIG_NB:
166                 puts("NB SNR ");
167                 for (i = 0; i < 4; i++) {
168                         uint16_t snr = sig->nb.meas[i].snr;
169                         printf("%d.%03u ", l1s_snr_int(snr), l1s_snr_fract(snr));
170                 }
171                 putchar('\n');
172                 printf("--> Frame %d %d 0x%04X ",  sig->nb.fire, sig->nb.crc, sig->nb.num_biterr);
173                 for (i = 0; i < ARRAY_SIZE(sig->nb.frame); i++)
174                         printf("%02X ", sig->nb.frame[i]);
175                 putchar('\n');
176                 break;
177         }
178 }
179
180 static void key_handler(enum key_codes code, enum key_states state);
181
182 int main(void)
183 {
184         board_init();
185         puts("\n\nHello World from " __FILE__ " program code\n");
186
187         puts(hr);
188         /* Dump device identification */
189         dump_dev_id();
190         puts(hr);
191
192         keypad_set_handler(&key_handler);
193
194         /* Dump clock config aftee PLL set */
195         calypso_clk_dump();
196         puts(hr);
197
198         st7558_set_attr(DISP_ATTR_INVERT);
199         st7558_puts("l1test.bin");
200
201         layer1_init();
202         l1s_set_handler(&l1s_signal_cb);
203
204         //dsp_checksum_task();
205 #ifdef SCAN
206         l1test_state_change(STATE_PM);
207 #else
208         l1test_state_change(STATE_FB);
209 #endif
210         tpu_frame_irq_en(1, 1);
211
212         while (1) {
213                 update_timers();
214         }
215
216         /* NOT REACHED */
217
218         twl3025_power_off();
219 }
220
221 static int8_t vga_gain = 40;
222 static int high_gain = 0;
223 static int afcout = 0;
224
225 static void update_vga_gain(void)
226 {
227         printf("VGA Gain: %u %s\n", vga_gain, high_gain ? "HIGH" : "LOW");
228         trf6151_set_gain(vga_gain, high_gain);
229         tpu_enq_sleep();
230         tpu_enable(1);
231         tpu_wait_idle();
232 }
233
234 static void tspact_toggle(uint8_t num)
235 {
236         printf("TSPACT%u toggle\n", num);
237         tsp_act_toggle((1 << num));
238         tpu_enq_sleep();
239         tpu_enable(1);
240         tpu_wait_idle();
241 }
242
243 static void key_handler(enum key_codes code, enum key_states state)
244 {
245         if (state != PRESSED)
246                 return;
247
248         switch (code) {
249         case KEY_1:     /* VGA gain decrement */
250                 vga_gain -= 2;
251                 if (vga_gain < 14)
252                         vga_gain = 14;
253                 update_vga_gain();
254                 break;
255         case KEY_2:     /* High/Low Rx gain */
256                 high_gain ^= 1;
257                 update_vga_gain();
258                 break;
259         case KEY_3:     /* VGA gain increment */
260                 vga_gain += 2;
261                 if (vga_gain > 40)
262                         vga_gain = 40;
263                 update_vga_gain();
264                 break;
265         case KEY_4:
266                 tspact_toggle(6);       /* TRENA (RFFE) */
267                 break;
268         case KEY_5:
269                 tspact_toggle(8);       /* GSM_TXEN (RFFE) */
270                 break;
271         case KEY_6:
272                 tspact_toggle(1);       /* PAENA (RFFE) */
273                 break;
274         case KEY_7:                     /* decrement AFC OUT */
275                 afcout -= 100;
276                 if (afcout < -4096)
277                         afcout = -4096;
278                 twl3025_afc_set(afcout);
279                 printf("AFC OUT: %u\n", twl3025_afcout_get());
280                 break;
281         case KEY_9:                     /* increase AFC OUT */
282                 afcout += 100;
283                 if (afcout > 4095)
284                         afcout = 4095;
285                 twl3025_afc_set(afcout);
286                 printf("AFC OUT: %u\n", twl3025_afcout_get());
287                 break;
288         default:
289                 break;
290         }
291 }