ensure RF_ARFCN is part of l1ctl messages sent to host
[osmocom-bb.git] / src / target / firmware / layer1 / sync.c
1 /* Synchronous part of GSM Layer 1 */
2
3 /* (C) 2010 by Harald Welte <laforge@gnumonks.org>
4  * (C) 2010 by Dieter Spaar <spaar@mirider.augusta.de>
5  * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
6  *
7  * All Rights Reserved
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  *
23  */
24
25 #include <stdint.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <stdlib.h>
29
30 #include <debug.h>
31 #include <memory.h>
32 #include <calypso/dsp_api.h>
33 #include <calypso/irq.h>
34 #include <calypso/tpu.h>
35 #include <calypso/tsp.h>
36 #include <calypso/dsp.h>
37 #include <calypso/timer.h>
38 #include <comm/sercomm.h>
39 #include <comm/msgb.h>
40
41 #include <abb/twl3025.h>
42
43 #include <layer1/sync.h>
44 #include <layer1/afc.h>
45 #include <layer1/agc.h>
46 #include <layer1/tdma_sched.h>
47 #include <layer1/mframe_sched.h>
48 #include <layer1/sched_gsmtime.h>
49 #include <layer1/tpu_window.h>
50 #include <layer1/l23_api.h>
51
52 #include <l1a_l23_interface.h>
53
54 //#define DEBUG_EVERY_TDMA
55
56 /* A debug macro to print every TDMA frame */
57 #ifdef DEBUG_EVERY_TDMA
58 #define putchart(x) putchar(x)
59 #else
60 #define putchart(x)
61 #endif
62
63 struct l1s_state l1s;
64
65 static l1s_cb_t l1s_cb = NULL;
66
67 void l1s_set_handler(l1s_cb_t cb)
68 {
69         l1s_cb = cb;
70 }
71
72 #define ADD_MODULO(sum, delta, modulo)  do {    \
73         if ((sum += delta) >= modulo)           \
74                 sum -= modulo;                  \
75         } while (0)
76
77 #define GSM_MAX_FN      (26*51*2048)
78
79 static void l1s_time_inc(struct gsm_time *time, uint32_t delta_fn)
80 {
81         ADD_MODULO(time->fn, delta_fn, GSM_MAX_FN);
82
83         if (delta_fn == 1) {
84                 ADD_MODULO(time->t2, 1, 26);
85                 ADD_MODULO(time->t3, 1, 51);
86
87                 /* if the new frame number is a multiple of 51 */
88                 if (time->t3 == 0) {
89                         ADD_MODULO(time->tc, 1, 8);
90
91                         /* if new FN is multiple of 51 and 26 */
92                         if (time->t2 == 0)
93                                 ADD_MODULO(time->t1, 1, 2048);
94                 }
95         } else
96                 gsm_fn2gsmtime(time, time->fn);
97 }
98
99 static void l1s_time_dump(const struct gsm_time *time)
100 {
101         printf("fn=%u(%u/%2u/%2u)", time->fn, time->t1, time->t2, time->t3);
102 }
103
104 /* determine the GSM time and BSIC from a Sync Burst */
105 static uint8_t l1s_decode_sb(struct gsm_time *time, uint32_t sb)
106 {
107         uint8_t bsic = (sb >> 2) & 0x3f;
108         uint8_t t3p;
109
110         memset(time, 0, sizeof(*time));
111
112         /* TS 05.02 Chapter 3.3.2.2.1 SCH Frame Numbers */
113         time->t1 = ((sb >> 23) & 1) | ((sb >> 7) & 0x1fe) | ((sb << 9) & 0x600);
114         time->t2 = (sb >> 18) & 0x1f;
115         t3p = ((sb >> 24) & 1) | ((sb >> 15) & 6);
116         time->t3 = t3p*10 + 1;
117
118         /* TS 05.02 Chapter 4.3.3 TDMA frame number */
119         time->fn = gsm_gsmtime2fn(time);
120
121         time->tc = (time->fn / 51) % 8;
122
123         return bsic;
124 }
125
126 static int last_task_fnr;
127
128 extern uint16_t rf_arfcn; // TODO
129
130 /* clip a signed 16bit value at a certain limit */
131 int16_t clip_int16(int16_t angle, int16_t clip_at)
132 {
133         if (angle > clip_at)
134                 angle = clip_at;
135         else if (angle < -clip_at)
136                 angle = -clip_at;
137
138         return angle;
139 }
140
141 int16_t l1s_snr_int(uint16_t snr)
142 {
143         return snr >> 10;
144 }
145
146 uint16_t l1s_snr_fract(uint16_t snr)
147 {
148         uint32_t fract = snr & 0x3ff;
149         fract = fract * 1000 / (2 << 10);
150
151         return fract & 0xffff;
152 }
153
154 static void l1ddsp_meas_read(uint8_t nbmeas, uint16_t *pm)
155 {
156         uint8_t i;
157
158         for (i = 0; i < nbmeas; i++)
159                 pm[i] = (uint16_t) ((dsp_api.db_r->a_pm[i] & 0xffff) >> 3);
160         dsp_api.r_page_used = 1;
161 }
162
163 /* Convert an angle in fx1.15 notatinon into Hz */
164 #define BITFREQ_DIV_2PI         43104   /* 270kHz / 2 * pi */
165 #define BITFREQ_DIV_PI          86208   /* 270kHz / pi */
166 #define ANG2FREQ_SCALING        (2<<15) /* 2^15 scaling factor for fx1.15 */
167 #define ANGLE_TO_FREQ(angle)    ((int16_t)angle * BITFREQ_DIV_PI / ANG2FREQ_SCALING)
168
169 #define AFC_MAX_ANGLE           328     /* 0.01 radian in fx1.15 */
170 #define AFC_SNR_THRESHOLD       2560    /* 2.5 dB in fx6.10 */
171
172 #define BITS_PER_TDMA           1250
173 #define QBITS_PER_TDMA          (BITS_PER_TDMA * 4)     /* 5000 */
174 #define TPU_RANGE               QBITS_PER_TDMA
175 #define SWITCH_TIME             (TPU_RANGE-10)
176
177
178 static int fb_once = 0;
179
180 /* synchronize the L1S to a new timebase (typically a new cell */
181 static void synchronize_tdma(struct l1_cell_info *cinfo)
182 {
183         int32_t fn_offset;
184         uint32_t tpu_shift = cinfo->time_alignment;
185
186         /* NB detection only works if the TOA of the SB
187          * is within 0...8. We have to add 75 to get an SB TOA of 4. */
188         tpu_shift += 75;
189
190         tpu_shift = (l1s.tpu_offset + tpu_shift) % QBITS_PER_TDMA;
191
192         fn_offset = cinfo->fn_offset - 1;
193
194         /* if we're already very close to the end of the TPU frame,
195          * the next interrupt will basically occur now and we need to compensate */
196         if (tpu_shift < SWITCH_TIME)
197                 fn_offset++;
198
199 #if 0 /* probably wrong as we already added "offset" and "shift" above */
200         /* increment the TPU quarter-bit offset */
201         l1s.tpu_offset = (l1s.tpu_offset + tpu_shift) % TPU_RANGE;
202 #else
203         l1s.tpu_offset = tpu_shift;
204 #endif
205
206         puts("Synchronize_TDMA\n");
207         /* request the TPU to adjust the SYNCHRO and OFFSET registers */
208         tpu_enq_at(SWITCH_TIME);
209         tpu_enq_sync(l1s.tpu_offset);
210 #if 0
211         /* FIXME: properly end the TPU window at the emd of l1_sync() */
212         tpu_end_scenario();
213 #endif
214
215         /* Change the current time to reflect the new value */
216         l1s_time_inc(&l1s.current_time, fn_offset);
217         l1s.next_time = l1s.current_time;
218         l1s_time_inc(&l1s.next_time, 1);
219
220         /* The serving cell now no longer has a frame or bit offset */
221         cinfo->fn_offset = 0;
222         cinfo->time_alignment = 0;
223 }
224
225 static void l1s_reset_hw(void)
226 {
227         dsp_api.w_page = 0;
228         dsp_api.r_page = 0;
229         dsp_api.r_page_used = 0;
230         dsp_api.db_w = (T_DB_MCU_TO_DSP *) BASE_API_W_PAGE_0;
231         dsp_api.db_r = (T_DB_DSP_TO_MCU *) BASE_API_R_PAGE_0;
232         dsp_api.ndb->d_dsp_page = 0;
233
234         /* we have to really reset the TPU, otherwise FB detection
235          * somtimes returns wrong TOA values. */
236         tpu_reset(1);
237         tpu_reset(0);
238         tpu_rewind();
239         tpu_enq_wait(5); /* really needed ? */
240         tpu_enq_offset(l1s.tpu_offset);
241         tpu_end_scenario();
242 }
243
244 struct mon_state {
245         uint32_t fnr_report;    /* frame number when DSP reported it */
246         int attempt;            /* which attempt was this ? */
247
248         int16_t toa;
249         uint16_t pm;
250         uint16_t angle;
251         uint16_t snr;
252
253         /* computed values */
254         int16_t freq_diff;
255 };
256
257 static void dump_mon_state(struct mon_state *fb)
258 {
259 #if 0
260         printf("(%u:%u): TOA=%5u, Power=%4ddBm, Angle=%5dHz, "
261                 "SNR=%04x(%d.%u) OFFSET=%u SYNCHRO=%u\n", fb->fnr_report, fb->attempt,
262                 fb->toa, agc_inp_dbm8_by_pm(fb->pm)/8,
263                 ANGLE_TO_FREQ(fb->angle), fb->snr, l1s_snr_int(fb->snr),
264                 l1s_snr_fract(fb->snr), tpu_get_offset(), tpu_get_synchro());
265 #else
266         printf("(%u:%u): TOA=%5u, Power=%4ddBm, Angle=%5dHz ", fb->fnr_report, fb->attempt,
267                 fb->toa, agc_inp_dbm8_by_pm(fb->pm)/8,
268                 ANGLE_TO_FREQ(fb->angle));
269 #endif
270 }
271
272 static struct mon_state _last_fb, *last_fb = &_last_fb;
273
274 static int read_fb_result(int attempt)
275 {
276         last_fb->toa = dsp_api.ndb->a_sync_demod[D_TOA];
277         last_fb->pm = dsp_api.ndb->a_sync_demod[D_PM]>>3;
278         last_fb->angle = dsp_api.ndb->a_sync_demod[D_ANGLE];
279         last_fb->snr = dsp_api.ndb->a_sync_demod[D_SNR];
280
281         //last_fb->angle = clip_int16(last_fb->angle, AFC_MAX_ANGLE);
282         last_fb->freq_diff = ANGLE_TO_FREQ(last_fb->angle);
283         last_fb->fnr_report = l1s.current_time.fn;
284         last_fb->attempt = attempt;
285
286         dump_mon_state(last_fb);
287
288         dsp_api.ndb->d_fb_det = 0;
289         dsp_api.ndb->a_sync_demod[D_TOA] = 0; /* TSM30 does it (really needed ?) */
290
291         /* Update AFC with current frequency offset */
292         afc_correct(last_fb->freq_diff, rf_arfcn);
293
294         //tpu_dsp_frameirq_enable();
295         return 1;
296 }
297
298 static void read_sb_result(int attempt)
299 {
300         last_fb->toa = dsp_api.db_r->a_serv_demod[D_TOA];
301         last_fb->pm = dsp_api.db_r->a_serv_demod[D_PM]>>3;
302         last_fb->angle = dsp_api.db_r->a_serv_demod[D_ANGLE];
303         last_fb->snr = dsp_api.db_r->a_serv_demod[D_SNR];
304
305         last_fb->freq_diff = ANGLE_TO_FREQ(last_fb->angle);
306         last_fb->fnr_report = l1s.current_time.fn;
307         last_fb->attempt = attempt;
308
309         dump_mon_state(last_fb);
310
311         if (last_fb->snr > AFC_SNR_THRESHOLD)
312                 afc_input(last_fb->freq_diff, rf_arfcn, 1);
313         else
314                 afc_input(last_fb->freq_diff, rf_arfcn, 0);
315
316         dsp_api.r_page_used = 1;
317 }
318
319 #define TIMER_TICKS_PER_TDMA    1875
320
321 static int last_timestamp;
322
323 static inline void check_lost_frame(void)
324 {
325         int diff, timestamp = hwtimer_read(1);
326
327         if (last_timestamp < timestamp)
328                 last_timestamp += (4*TIMER_TICKS_PER_TDMA);
329
330         diff = last_timestamp - timestamp;
331         if (diff != 1875)
332                 printf("LOST!\n");
333
334         last_timestamp = timestamp;
335 }
336
337 /* main routine for synchronous part of layer 1, called by frame interrupt
338  * generated by TPU once every TDMA frame */
339 static void l1_sync(void)
340 {
341         putchart('+');
342
343         check_lost_frame();
344
345         /* Increment Time */
346         l1s.current_time = l1s.next_time;
347         l1s_time_inc(&l1s.next_time, 1);
348         //l1s_time_dump(&l1s.current_time); putchar(' ');
349
350         dsp_api.frame_ctr++;
351         dsp_api.r_page_used = 0;
352
353         /* Update pointers */
354         if (dsp_api.w_page == 0)
355                 dsp_api.db_w = (T_DB_MCU_TO_DSP *) BASE_API_W_PAGE_0;
356         else
357                 dsp_api.db_w = (T_DB_MCU_TO_DSP *) BASE_API_W_PAGE_1;
358
359         if (dsp_api.r_page == 0)
360                 dsp_api.db_r = (T_DB_DSP_TO_MCU *) BASE_API_R_PAGE_0;
361         else
362                 dsp_api.db_r = (T_DB_DSP_TO_MCU *) BASE_API_R_PAGE_1;
363
364         /* Reset MCU->DSP page */
365         dsp_api_memset((uint16_t *) dsp_api.db_w, sizeof(*dsp_api.db_w));
366
367         /* Update AFC */
368         afc_load_dsp();
369
370         if (dsp_api.ndb->d_error_status) {
371                 printf("DSP Error Status: %u\n", dsp_api.ndb->d_error_status);
372                 dsp_api.ndb->d_error_status = 0;
373         }
374
375 #if 0
376         if (l1s.task != dsp_api.db_r->d_task_md)
377                 printf("DSP task (%u) and L1S task (%u) disagree\n", dsp_api.db_r->d_task_md, l1s.task);
378 #endif
379         /* execute the sched_items that have been scheduled for this TDMA frame */
380         tdma_sched_execute();
381
382         if (dsp_api.r_page_used) {
383                 /* clear and switch the read page */
384                 dsp_api_memset((uint16_t *) dsp_api.db_r, sizeof(*dsp_api.db_r));
385
386                 /* TSM30 does it (really needed ?):
387                  * Set crc result as "SB not found". */
388                 dsp_api.db_r->a_sch[0] = (1<<B_SCH_CRC);   /* B_SCH_CRC =1, BLUD =0 */
389
390                 dsp_api.r_page ^= 1;
391         }
392
393         //dsp_end_scenario();
394
395         /* schedule new / upcoming TDMA items */
396         mframe_schedule(l1s.mf_tasks);
397         /* schedule new / upcoming one-shot events */
398         sched_gsmtime_execute(l1s.current_time.fn);
399
400         tdma_sched_advance();
401 }
402
403 /* ABORT command ********************************************************/
404
405 static int l1s_abort_cmd(uint8_t p1, uint8_t p2, uint16_t p3)
406 {
407         putchart('A');
408
409         /* similar to l1s_reset_hw() without touching the TPU */
410
411         dsp_api.w_page = 0;
412         dsp_api.r_page = 0;
413         dsp_api.r_page_used = 0;
414         dsp_api.db_w = (T_DB_MCU_TO_DSP *) BASE_API_W_PAGE_0;
415         dsp_api.db_r = (T_DB_DSP_TO_MCU *) BASE_API_R_PAGE_0;
416
417         /* Reset task commands. */
418         dsp_api.db_w->d_task_d  = NO_DSP_TASK; /* Init. RX task to NO TASK */
419         dsp_api.db_w->d_task_u  = NO_DSP_TASK; /* Init. TX task to NO TASK */
420         dsp_api.db_w->d_task_ra = NO_DSP_TASK; /* Init. RA task to NO TASK */
421         dsp_api.db_w->d_task_md = NO_DSP_TASK; /* Init. MONITORING task to NO TASK */
422         dsp_api.ndb->d_dsp_page = 0;
423
424         /* Set "b_abort" to TRUE, dsp will reset current and pending tasks */
425         dsp_api.db_w->d_ctrl_system |= (1 << B_TASK_ABORT);
426         return 0;
427 }
428
429 void l1s_dsp_abort(void)
430 {
431         /* abort right now */
432         tdma_schedule(0, &l1s_abort_cmd, 0, 0, 0);
433 }
434
435 /* FCCH Burst *****************************************************************/
436
437 /* scheduler callback to issue a FB detection task to the DSP */
438 static int l1s_fbdet_cmd(uint8_t p1, uint8_t fb_mode, uint16_t p3)
439 {
440         if (fb_mode == 0) {
441                 putchart('F');
442         } else {
443                 putchart('V');
444         }
445
446         /* Program DSP */
447         l1s.task = dsp_api.db_w->d_task_md = FB_DSP_TASK;       /* maybe with I/Q swap? */
448         dsp_api.ndb->d_fb_mode = fb_mode;
449         dsp_end_scenario();
450         last_task_fnr = dsp_api.frame_ctr;
451
452         /* Program TPU */
453         l1s_rx_win_ctrl(rf_arfcn, L1_RXWIN_FB);
454         tpu_end_scenario();
455
456         return 0;
457 }
458
459
460 /* scheduler callback to check for a FB detection response */
461 static int l1s_fbdet_resp(uint8_t p1, uint8_t attempt, uint16_t p3)
462 {
463         int ntdma, qbits, fn_offset;
464
465         putchart('f');
466
467         if (!dsp_api.ndb->d_fb_det) {
468                 /* we did not detect a FB, fall back to mode 0! */
469                 if (attempt == 12) {
470                         /* If we don't reset here, we get DSP DMA errors */
471                         tdma_sched_reset();
472
473                         /* if we are already synchronized initially */
474                         if (fb_once == 1)
475                                 l1s_fb_test(1, 1);
476                         else
477                                 l1s_fb_test(1, 0);
478                 }
479                 return 0;
480         }
481
482         printf("FB%u ", dsp_api.ndb->d_fb_mode);
483         read_fb_result(attempt);
484
485         last_fb->toa -= 23;
486
487         if (last_fb->toa < 0) {
488                 qbits = (last_fb->toa + BITS_PER_TDMA) * 4;
489                 ntdma = -1;
490         } else {
491                 ntdma = (last_fb->toa) / BITS_PER_TDMA;
492                 qbits = (last_fb->toa - ntdma * BITS_PER_TDMA) * 4;
493         }
494
495         {
496                 fn_offset = l1s.current_time.fn - attempt + ntdma;
497                 int fnr_delta = last_fb->fnr_report - attempt;
498                 int bits_delta = fnr_delta * BITS_PER_TDMA;
499
500                 struct l1_cell_info *cinfo = &l1s.serving_cell;
501
502                 cinfo->fn_offset = fnr_delta;
503                 cinfo->time_alignment = qbits;
504                 cinfo->arfcn = rf_arfcn;
505
506                 if (last_fb->toa > bits_delta)
507                         printf("=> DSP reports FB in bit that is %d bits in the future?!?\n",
508                                 last_fb->toa - bits_delta);
509                 else {
510                         int fb_fnr = last_task_fnr + last_fb->toa/BITS_PER_TDMA;
511                         printf("=>FB @ FNR %u fn_offset=%d qbits=%u\n", fb_fnr, fn_offset, qbits);
512                 }
513         }
514
515         if (dsp_api.frame_ctr > 500 && fb_once == 0) {
516                 /* Don't synchronize_tdma() yet, it does probably not work
517                  * reliable due to the TPU reset) */
518                 l1s_reset_hw();
519                 tdma_sched_reset();
520                 fb_once = 1;
521         } else {
522                 /* We found a frequency burst, reset everything and start next task */
523                 l1s_reset_hw();
524                 tdma_sched_reset();
525         }
526
527 #if 1
528         /* restart a SB or new FB detection task */
529         if (dsp_api.frame_ctr > 1000 && fb_once == 1 &&
530             abs(last_fb->freq_diff) < 1000)  {
531                 int delay;
532
533                 /* synchronize before reading SB */
534                 synchronize_tdma(&l1s.serving_cell);
535
536                 delay = fn_offset + 11 - l1s.current_time.fn - 1;
537                 dsp_api.ndb->d_fb_det = 0;
538                 dsp_api.ndb->a_sync_demod[D_TOA] = 0; /* TSM30 does it (really needed ?) */
539                 fb_once = 0;
540                 l1s_sb_test(delay);
541         } else
542 #endif
543         {
544                 /* If we don't reset here, we get DSP DMA errors */
545                 tdma_sched_reset();
546                 /* use FB_MODE_1 if we are within certain limits */
547                 if (abs(last_fb->freq_diff < 2000))
548                         l1s_fb_test(fn_offset + 10 - l1s.current_time.fn - 1, 1);
549                 else
550                         l1s_fb_test(fn_offset + 10 - l1s.current_time.fn - 1, 0);
551         }
552
553         return 0;
554 }
555
556 /* we don't really use this because we need to configure the fb_mode! */
557 static const struct tdma_sched_item fb_sched_set[] = {
558         SCHED_ITEM(l1s_fbdet_cmd, 0, 0),        SCHED_END_FRAME(),
559                                                 SCHED_END_FRAME(),
560         SCHED_ITEM(l1s_fbdet_resp, 0, 1),       SCHED_END_FRAME(),
561         SCHED_ITEM(l1s_fbdet_resp, 0, 2),       SCHED_END_FRAME(),
562         SCHED_ITEM(l1s_fbdet_resp, 0, 3),       SCHED_END_FRAME(),
563         SCHED_ITEM(l1s_fbdet_resp, 0, 4),       SCHED_END_FRAME(),
564         SCHED_ITEM(l1s_fbdet_resp, 0, 5),       SCHED_END_FRAME(),
565         SCHED_ITEM(l1s_fbdet_resp, 0, 6),       SCHED_END_FRAME(),
566         SCHED_ITEM(l1s_fbdet_resp, 0, 7),       SCHED_END_FRAME(),
567         SCHED_ITEM(l1s_fbdet_resp, 0, 8),       SCHED_END_FRAME(),
568         SCHED_ITEM(l1s_fbdet_resp, 0, 9),       SCHED_END_FRAME(),
569         SCHED_ITEM(l1s_fbdet_resp, 0, 10),      SCHED_END_FRAME(),
570         SCHED_ITEM(l1s_fbdet_resp, 0, 11),      SCHED_END_FRAME(),
571         SCHED_ITEM(l1s_fbdet_resp, 0, 12),      SCHED_END_FRAME(),
572         SCHED_END_SET()
573 };
574
575 void l1s_fb_test(uint8_t base_fn, uint8_t fb_mode)
576 {
577 #if 1
578         int i;
579         /* schedule the FB detection command */
580         tdma_schedule(base_fn, &l1s_fbdet_cmd, 0, fb_mode, 0);
581
582         /* schedule 12 attempts to read the result */
583         for (i = 1; i <= 12; i++) {
584                 uint8_t fn = base_fn + 1 + i;
585                 tdma_schedule(fn, &l1s_fbdet_resp, 0, i, 0);
586         }
587 #else
588         /* use the new scheduler 'set' and simply schedule the whole set */
589         /* WARNING: we cannot set FB_MODE_1 this way !!! */
590         tdma_schedule_set(base_fn, fb_sched_set, 0);
591 #endif
592 }
593
594 /* SCH Burst Detection ********************************************************/
595
596 static int sb_once = 0;
597
598 static uint8_t sb_cnt;
599
600 /* Note: When we get the SB response, it is 2 TDMA frames after the SB
601  * actually happened, as it is a "C W W R" task */
602 #define SB2_LATENCY     2
603
604 extern const struct tdma_sched_item rach_sched_set_ul[];
605
606 static int l1s_sbdet_resp(uint8_t p1, uint8_t attempt, uint16_t p3)
607 {
608         uint32_t sb;
609         uint8_t bsic;
610         static struct gsm_time sb_time;
611         int qbits, fn_offset;
612         struct l1_cell_info *cinfo = &l1s.serving_cell;
613         int fnr_delta, bits_delta;
614         struct l1ctl_sync_new_ccch_resp *l1;
615         struct msgb *msg;
616
617         putchart('s');
618
619         if (dsp_api.db_r->a_sch[0] & (1<<B_SCH_CRC)) {
620                 /* after 2nd attempt, restart */
621                 if (attempt == 2)
622                         l1s_sb_test(2);
623
624                 /* mark READ page as being used */
625                 dsp_api.r_page_used = 1;
626
627                 return 0;
628         }
629
630         sb_cnt++;
631
632         printf("SB%d ", attempt);
633         read_sb_result(dsp_api.frame_ctr);
634
635         sb = dsp_api.db_r->a_sch[3] | dsp_api.db_r->a_sch[4] << 16;
636         bsic = l1s_decode_sb(&sb_time, sb);
637         printf("=> SB 0x%08x: BSIC=%u ", sb, bsic);
638         l1s_time_dump(&sb_time);
639
640         l1s.serving_cell.bsic = bsic;
641
642         /* calculate synchronisation value (TODO: only complete for qbits) */
643         last_fb->toa -= 23;
644         qbits = last_fb->toa * 4;
645         fn_offset = l1s.current_time.fn; // TODO
646
647         if (qbits > QBITS_PER_TDMA) {
648                 qbits -= QBITS_PER_TDMA;
649                 fn_offset -= 1;
650         } else if (qbits < 0)  {
651                 qbits += QBITS_PER_TDMA;
652                 fn_offset += 1;
653         }
654
655         fnr_delta = last_fb->fnr_report - attempt;
656         bits_delta = fnr_delta * BITS_PER_TDMA;
657
658         cinfo->fn_offset = fnr_delta;
659         cinfo->time_alignment = qbits;
660         cinfo->arfcn = rf_arfcn;
661
662         if (last_fb->toa > bits_delta)
663                 printf("=> DSP reports SB in bit that is %d bits in the future?!?\n",
664                         last_fb->toa - bits_delta);
665         else
666                 printf(" qbits=%u\n", qbits);
667
668         if (sb_cnt > 5 && sb_once == 0) {
669                 synchronize_tdma(&l1s.serving_cell);
670                 sb_once = 1;
671         }
672
673         /* if we have recived a SYNC burst, update our local GSM time */
674         gsm_fn2gsmtime(&l1s.current_time, sb_time.fn + SB2_LATENCY);
675         /* compute next time from new current time */
676         l1s.next_time = l1s.current_time;
677         l1s_time_inc(&l1s.next_time, 1);
678
679         /* place it in the queue for the layer2 */
680         msg = l1_create_l2_msg(L1CTL_NEW_CCCH_RESP, sb_time.fn, last_fb->snr, rf_arfcn);
681         l1 = (struct l1ctl_sync_new_ccch_resp *) msgb_put(msg, sizeof(*l1));
682         l1->bsic = bsic;
683         l1_queue_for_l2(msg);
684
685 #if 0
686         tdma_sched_reset();
687 #else
688         /*
689                 If we call tdma_sched_reset(), which is only needed if there are
690                 further l1s_sbdet_resp() scheduled, we will bring dsp_api.db_r and
691                 dsp_api.db_w out of sync because we changed dsp_api.db_w for l1s_sbdet_cmd()
692                 and canceled l1s_sbdet_resp() which would change dsp_api.db_r. The DSP
693                 however expects dsp_api.db_w and dsp_api.db_r to be in sync (either 
694                 "0 - 0" or "1 - 1"). So we have to bring dsp_api.db_w and dsp_api.db_r
695                 into sync again, otherwise NB reading will complain. We probably don't
696                 need the Abort command and could just bring dsp_api.db_w and dsp_api.db_r
697                 into sync.
698         */
699         if (attempt != 2) {
700                 tdma_sched_reset();
701                 l1s_dsp_abort();
702         }
703 #endif
704         if (sb_cnt > 10 && sb_time.t3 == 41) {
705                 l1s_reset_hw();
706                 /* enable the MF Task for BCCH reading */
707                 l1s.mf_tasks |= (1 << MF_TASK_BCCH_NORM);
708                 l1s.mf_tasks |= (1 << MF_TASK_CCCH_COMB);
709         } else {
710                 /* We have just seen a SCH burst, we know the next one is not in
711                  * less than 7 TDMA frames from now */
712                 l1s_sb_test(7);
713         }
714
715         return 0;
716 }
717
718 static int l1s_sbdet_cmd(uint8_t p1, uint8_t p2, uint16_t p3)
719 {
720         putchart('S');
721
722         l1s.task = dsp_api.db_w->d_task_md = SB_DSP_TASK;
723         dsp_api.ndb->d_fb_mode = 0; /* wideband search */
724         dsp_end_scenario();
725
726         last_task_fnr = dsp_api.frame_ctr;
727
728         /* Program TPU */
729         l1s_rx_win_ctrl(rf_arfcn, L1_RXWIN_SB);
730         tpu_end_scenario();
731
732         return 0;
733 }
734
735 void l1s_sb_test(uint8_t base_fn)
736 {
737 #if 1
738         /* This is how it is done by the TSM30 */
739         tdma_schedule(base_fn, &l1s_sbdet_cmd, 0, 1, 0);
740         tdma_schedule(base_fn + 1, &l1s_sbdet_cmd, 0, 2, 0);
741         tdma_schedule(base_fn + 3, &l1s_sbdet_resp, 0, 1, 0);
742         tdma_schedule(base_fn + 4, &l1s_sbdet_resp, 0, 2, 0);
743 #else
744         tdma_schedule(base_fn, &l1s_sbdet_cmd, 0, 1, 0);
745         tdma_schedule(base_fn + 1, &l1s_sbdet_resp, 0, 1, 0);
746         tdma_schedule(base_fn + 2, &l1s_sbdet_resp, 0, 2, 0);
747 #endif
748 }
749
750 /* Power Measurement **********************************************************/
751
752 /* scheduler callback to issue a power measurement task to the DSP */
753 static int l1s_pm_cmd(uint8_t p1, uint8_t p2, uint16_t arfcn)
754 {
755         putchart('P');
756
757         l1s.task = dsp_api.db_w->d_task_md = 2;
758         dsp_api.ndb->d_fb_mode = 0; /* wideband search */
759         dsp_end_scenario();
760         last_task_fnr = dsp_api.frame_ctr;
761
762         /* Program TPU */
763         //l1s_rx_win_ctrl(arfcn, L1_RXWIN_PW);
764         l1s_rx_win_ctrl(arfcn, L1_RXWIN_NB);
765         tpu_end_scenario();
766
767         return 0;
768 }
769
770 /* scheduler callback to read power measurement resposnse from the DSP */
771 static int l1s_pm_resp(uint8_t p1, uint8_t p2, uint16_t p3)
772 {
773         uint16_t pm_level[2];
774         struct l1_signal sig;
775
776         putchart('p');
777
778         l1ddsp_meas_read(2, pm_level);
779
780         printd("PM MEAS: %-4d dBm, %-4d dBm ARFCN=%u\n", 
781                 agc_inp_dbm8_by_pm(pm_level[0])/8,
782                 agc_inp_dbm8_by_pm(pm_level[1])/8, rf_arfcn);
783
784         /* build and deliver signal */
785         sig.signum = L1_SIG_PM;
786         sig.arfcn = rf_arfcn;
787         sig.pm.dbm8[0] = agc_inp_dbm8_by_pm(pm_level[0]);
788         sig.pm.dbm8[1] = agc_inp_dbm8_by_pm(pm_level[1]);
789
790         if (l1s_cb)
791                 l1s_cb(&sig);
792
793         return 0;
794 }
795
796 void l1s_pm_test(uint8_t base_fn, uint16_t arfcn)
797 {
798         tdma_schedule(base_fn, &l1s_pm_cmd, 0, 0, arfcn);
799         tdma_schedule(base_fn + 2, &l1s_pm_resp, 0, 0, 0);
800 }
801
802 /* Normal Burst ***************************************************************/
803
804 static int l1s_nb_resp(uint8_t p1, uint8_t burst_id, uint16_t p3)
805 {
806         static struct l1_signal _nb_sig, *sig = &_nb_sig;
807         uint8_t mf_task_id = p3 & 0xff;
808         uint8_t mf_task_flags = p3 >> 8;
809         struct msgb *msg;
810
811         putchart('n');
812
813         /* just for debugging, d_task_d should not be 0 */
814         if (dsp_api.db_r->d_task_d == 0) {
815                 puts("EMPTY\n");
816                 return 0;
817         }
818
819         /* DSP burst ID needs to corespond with what we expect */
820         if (dsp_api.db_r->d_burst_d != burst_id) {
821                 printf("BURST ID %u!=%u\n", dsp_api.db_r->d_burst_d, burst_id);
822                 return 0;
823         }
824
825         sig->nb.meas[burst_id].toa_qbit = dsp_api.db_r->a_serv_demod[D_TOA];
826         sig->nb.meas[burst_id].pm_dbm8 = dsp_api.db_r->a_serv_demod[D_PM] >> 3;
827         sig->nb.meas[burst_id].freq_err = ANGLE_TO_FREQ(dsp_api.db_r->a_serv_demod[D_ANGLE]);
828         sig->nb.meas[burst_id].snr = dsp_api.db_r->a_serv_demod[D_SNR];
829
830         /* feed computed frequency error into AFC loop */
831         if (sig->nb.meas[burst_id].snr > AFC_SNR_THRESHOLD)
832                 afc_input(sig->nb.meas[burst_id].freq_err, rf_arfcn, 1);
833         else
834                 afc_input(sig->nb.meas[burst_id].freq_err, rf_arfcn, 0);
835
836         /* 4th burst, get frame data */
837         if (dsp_api.db_r->d_burst_d == 3) {
838                 struct l1ctl_info_dl *dl;
839                 struct l1ctl_data_ind *l1;
840                 uint8_t i, j;
841
842                 sig->signum = L1_SIG_NB;
843                 sig->nb.num_biterr = dsp_api.ndb->a_cd[2] & 0xffff;
844                 sig->nb.crc = ((dsp_api.ndb->a_cd[0] & 0xffff) & ((1 << B_FIRE1) | (1 << B_FIRE0))) >> B_FIRE0;
845                 sig->nb.fire = ((dsp_api.ndb->a_cd[0] & 0xffff) & (1 << B_FIRE1)) >> B_FIRE1;
846
847                 /* copy actual data, skipping the information block [0,1,2] */
848                 for (j = 0,i = 3; i < 15; i++) {
849                         sig->nb.frame[j++] = dsp_api.ndb->a_cd[i] & 0xFF;
850                         sig->nb.frame[j++] = (dsp_api.ndb->a_cd[i] >> 8) & 0xFF;
851                 }
852
853                 /* actually issue the signal */
854                 if (l1s_cb)
855                         l1s_cb(sig);
856
857                 /* place it in the queue for the layer2 */
858                 msg = l1_create_l2_msg(L1CTL_DATA_IND, l1s.current_time.fn-4, last_fb->snr, rf_arfcn);
859                 dl = (struct l1ctl_info_dl *) msg->data;
860                 l1 = (struct l1ctl_data_ind *) msgb_put(msg, sizeof(*l1));
861
862                 /* Set Channel Number depending on MFrame Task ID */
863                 dl->chan_nr = mframe_task2chan_nr(mf_task_id, 0); /* FIXME: TS */
864
865                 /* Set SACCH indication in Link IDentifier */
866                 if (mf_task_flags & MF_F_SACCH)
867                         dl->link_id = 0x40;
868                 else
869                         dl->link_id = 0x00;
870
871                 /* copy the snr and data */
872                 for (i = 0; i < 3; ++i)
873                         dl->snr[i] = sig->nb.meas[i].snr;
874                 for (i = 0; i < 23; ++i)
875                         l1->data[i] = sig->nb.frame[i];
876                 l1_queue_for_l2(msg);
877
878                 /* clear downlink task */
879                 l1s.task = dsp_api.db_w->d_task_d = 0;
880         }
881
882         /* mark READ page as being used */
883         dsp_api.r_page_used = 1;
884
885         return 0;
886 }
887
888 static int l1s_nb_cmd(uint8_t p1, uint8_t burst_id, uint16_t p3)
889 {
890         uint8_t tsc = l1s.serving_cell.bsic & 0x7;
891
892         putchart('N');
893         dsp_load_rx_task(ALLC_DSP_TASK, burst_id, tsc);
894         dsp_end_scenario();
895
896         l1s_rx_win_ctrl(rf_arfcn, L1_RXWIN_NB);
897         tpu_end_scenario();
898
899         return 0;
900 }
901
902 const struct tdma_sched_item nb_sched_set[] = {
903         SCHED_ITEM(l1s_nb_cmd, 0, 0),                                   SCHED_END_FRAME(),
904         SCHED_ITEM(l1s_nb_cmd, 0, 1),                                   SCHED_END_FRAME(),
905         SCHED_ITEM(l1s_nb_resp, 0, 0), SCHED_ITEM(l1s_nb_cmd, 0, 2),    SCHED_END_FRAME(),
906         SCHED_ITEM(l1s_nb_resp, 0, 1), SCHED_ITEM(l1s_nb_cmd, 0, 3),    SCHED_END_FRAME(),
907                                        SCHED_ITEM(l1s_nb_resp, 0, 2),   SCHED_END_FRAME(),
908                                        SCHED_ITEM(l1s_nb_resp, 0, 3),   SCHED_END_FRAME(),
909         SCHED_END_SET()
910 };
911
912
913 /* Transmit Burst *************************************************************/
914
915 const uint8_t ubUui[23]     = { 0x01, 0x03, 0x01, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b };
916
917 /* p1: type of operation (0: one NB, 1: one RACH burst, 2: four NB */
918 static int l1s_tx_resp(uint8_t p1, uint8_t burst_id, uint16_t p3)
919 {
920         putchart('t');
921
922         dsp_api.r_page_used = 1;
923
924         return 0;
925 }
926
927 /* Channel type definitions for DEDICATED mode */
928 #define INVALID_CHANNEL    0
929 #define TCH_F              1
930 #define TCH_H              2
931 #define SDCCH_4            3
932 #define SDCCH_8            4
933
934 /* Channel mode definitions for DEDICATED mode */
935 #define SIG_ONLY_MODE      0    // signalling only
936 #define TCH_FS_MODE        1    // speech full rate
937 #define TCH_HS_MODE        2    // speech half rate
938 #define TCH_96_MODE        3    // data 9,6 kb/s
939 #define TCH_48F_MODE       4    // data 4,8 kb/s full rate
940 #define TCH_48H_MODE       5    // data 4,8 kb/s half rate
941 #define TCH_24F_MODE       6    // data 2,4 kb/s full rate
942 #define TCH_24H_MODE       7    // data 2,4 kb/s half rate
943 #define TCH_EFR_MODE       8    // enhanced full rate
944 #define TCH_144_MODE       9    // data 14,4 kb/s half rate
945
946 static uint8_t loc_cnt = 0;
947
948 /* p1: type of operation (0: one NB, 1: one RACH burst, 2: four NB */
949 static int l1s_tx_cmd(uint8_t p1, uint8_t burst_id, uint16_t p3)
950 {
951         int i;
952         uint8_t tsc;
953         uint8_t mf_task_id = p3 & 0xff;
954         uint8_t mf_task_flags = p3 >> 8;
955
956         putchart('T');
957
958         /* Load the ApcOffset into the DSP */
959         #define  MY_OFFSET      4
960         dsp_api.ndb->d_apcoff = ABB_VAL(APCOFF, (1 << 6) | MY_OFFSET) | 1; /* 2x slope for the GTA-02 ramp */
961
962         /* Load the TX Power into the DSP */
963         /*
964            If the power is too low (below 0 dBm) the ramp is not OK,
965            especially for GSM-1800. However an MS does not send below
966            0dBm anyway.
967         */
968         dsp_api.db_w->d_power_ctl = ABB_VAL(AUXAPC, 0xC0); /* 2 dBm pulse with offset 4 (GSM-1800) */
969
970         /* Update the ramp according to the PCL */
971         for (i = 0; i < 16; i++)
972                 dsp_api.ndb->a_ramp[i] = ABB_VAL(APCRAM, twl3025_default_ramp[i]);
973
974         /* The Ramp Table is sent to ABB only once after RF init routine called */
975         dsp_api.db_w->d_ctrl_abb |= (1 << B_RAMP) | (1 << B_BULRAMPDEL);
976
977         if (p1 == 0) /* DUL_DSP_TASK, one normal burst */
978                 dsp_load_tch_param(0, SIG_ONLY_MODE, INVALID_CHANNEL, 0, 0, 0);
979         else if (p1 == 2) /* DUL_DSP_TASK, four normal bursts */
980                 dsp_load_tch_param(0, SIG_ONLY_MODE, SDCCH_4, 0, 0, 0);
981
982         /* before sending first of the four bursts, copy data to API ram */
983         if (burst_id == 0) {
984                 if (p1 == 0 || p1 == 2) { // DUL_DSP_TASK
985                         uint16_t *info_ptr = dsp_api.ndb->a_cu;
986                         struct llist_head *tx_queue;
987                         struct msgb *msg;
988                         const uint8_t *data;
989                         uint8_t j;
990
991                         /* distinguish between DCCH and ACCH */
992                         if (mf_task_flags & MF_F_SACCH) {
993                                 puts("SACCH queue ");
994                                 tx_queue = &l1s.tx_queue[L1S_CHAN_SACCH];
995                         } else {
996                                 puts("SDCCH queue ");
997                                 tx_queue = &l1s.tx_queue[L1S_CHAN_MAIN];
998                         }
999                         msg = msgb_dequeue(tx_queue);
1000
1001                         /* If the TX queue is empty, send idle pattern */
1002                         if (!msg) {
1003                                 puts("TX idle pattern\n");
1004                                 data = ubUui;
1005                         } else {
1006                                 puts("TX uplink msg\n");
1007                                 data = msg->l3h;
1008                         }
1009
1010                         /* Fill data block Header */
1011                         info_ptr[0] = (1 << B_BLUD);     // 1st word: Set B_BLU bit.
1012                         info_ptr[1] = 0;                 // 2nd word: cleared.
1013                         info_ptr[2] = 0;                 // 3rd word: cleared.
1014
1015                         /* Copy first 22 bytes in the first 11 words after header. */
1016                         for (i=0, j=(3+0); j<(3+11); j++) {
1017                                 info_ptr[j] = ((uint16_t)(data[i])) | ((uint16_t)(data[i+1]) << 8);
1018                                 printf("%02x %02x ", data[i], data[i+1]);
1019                                 i += 2;
1020                         }
1021                         /* Copy last UWORD8 (23rd) in the 12th word after header. */
1022                         info_ptr[14] = data[22];
1023                         printf("%02x\n", data[22]);
1024
1025                         if (msg)
1026                                 msgb_free(msg);
1027                 } else if (p1 == 1) { // RACH_DSP_TASK
1028                         uint16_t  *info_ptr;
1029                         uint8_t data[2];
1030
1031                         data[0] = l1s.serving_cell.bsic << 2;
1032                         data[1] = 0x00 + loc_cnt; // channel request, location update, loc_cnt as random reference
1033                         loc_cnt++;
1034                         if (loc_cnt > 16)
1035                                 loc_cnt = 0;
1036
1037                         info_ptr = &dsp_api.ndb->d_rach;
1038                         info_ptr[0] = ((uint16_t)(data[0])) | ((uint16_t)(data[1])<<8);
1039                 }
1040         }
1041
1042         if (p1 == 0 || p1 == 2) {
1043                 tsc = 7; // !!!!! nanoBTS configuration for SDCCH 0 !!!!!!!!
1044
1045                 dsp_load_tx_task(DUL_DSP_TASK, burst_id, tsc);
1046                 dsp_end_scenario();
1047
1048                 l1s_tx_win_ctrl(rf_arfcn, L1_TXWIN_NB, 0);
1049                 tpu_end_scenario();
1050         } else if (p1 == 1) {
1051                 dsp_api.db_w->d_task_ra = RACH_DSP_TASK;
1052                 dsp_end_scenario();
1053
1054                 l1s_tx_win_ctrl(rf_arfcn, L1_TXWIN_AB, 0);
1055                 tpu_end_scenario();
1056         }
1057
1058         return 0;
1059 }
1060
1061 void l1s_tx_test(uint8_t base_fn, uint8_t type)
1062 {
1063         printf("Starting TX %d\n", type);
1064
1065         if (type == 0) {// one normal burst
1066                 tdma_schedule(base_fn, &l1s_tx_cmd, 0, 0, 0);
1067                 tdma_schedule(base_fn + 2, &l1s_tx_resp, 0, 0, 0);
1068         } else if (type == 1) { // one RACH burst
1069                 tdma_schedule(base_fn, &l1s_tx_cmd, 1, 0, 0);
1070                 tdma_schedule(base_fn + 2, &l1s_tx_resp, 1, 0, 0);
1071         } else if (type == 2) { // four normal burst
1072                 tdma_schedule(base_fn, &l1s_tx_cmd, 2, 0, 0);
1073                 tdma_schedule(base_fn + 1, &l1s_tx_cmd, 2, 1, 0);
1074                 tdma_schedule(base_fn + 2, &l1s_tx_resp, 2, 0, 0);
1075                 tdma_schedule(base_fn + 2, &l1s_tx_cmd, 2, 2, 0);
1076                 tdma_schedule(base_fn + 3, &l1s_tx_resp, 2, 1, 0);
1077                 tdma_schedule(base_fn + 3, &l1s_tx_cmd, 2, 3, 0);
1078                 tdma_schedule(base_fn + 4, &l1s_tx_resp, 2, 2, 0);
1079                 tdma_schedule(base_fn + 5, &l1s_tx_resp, 2, 3, 0);
1080         }
1081 }
1082
1083 /* sched sets for uplink */
1084 const struct tdma_sched_item rach_sched_set_ul[] = {
1085         SCHED_ITEM(l1s_tx_cmd, 1, 0),                                   SCHED_END_FRAME(),
1086                                                                         SCHED_END_FRAME(),
1087         SCHED_ITEM(l1s_tx_resp, 1, 0),                                  SCHED_END_FRAME(),
1088         SCHED_END_SET()
1089 };
1090 const struct tdma_sched_item nb_sched_set_ul[] = {
1091         SCHED_ITEM(l1s_tx_cmd, 2, 0),                                   SCHED_END_FRAME(),
1092         SCHED_ITEM(l1s_tx_cmd, 2, 1),                                   SCHED_END_FRAME(),
1093         SCHED_ITEM(l1s_tx_resp, 2, 0), SCHED_ITEM(l1s_tx_cmd, 2, 2),    SCHED_END_FRAME(),
1094         SCHED_ITEM(l1s_tx_resp, 2, 1), SCHED_ITEM(l1s_tx_cmd, 2, 3),    SCHED_END_FRAME(),
1095                                        SCHED_ITEM(l1s_tx_resp, 2, 2),   SCHED_END_FRAME(),
1096                                        SCHED_ITEM(l1s_tx_resp, 2, 3),   SCHED_END_FRAME(),
1097         SCHED_END_SET()
1098 };
1099
1100
1101 /* Interrupt handler */
1102 static void frame_irq(enum irq_nr nr)
1103 {
1104         l1_sync();
1105 }
1106
1107 void l1s_init(void)
1108 {
1109         unsigned int i;
1110
1111         for (i = 0; i < ARRAY_SIZE(l1s.tx_queue); i++)
1112                 INIT_LLIST_HEAD(&l1s.tx_queue[i]);
1113
1114         sched_gsmtime_init();
1115
1116         /* register FRAME interrupt as FIQ so it can interrupt normal IRQs */
1117         irq_register_handler(IRQ_TPU_FRAME, &frame_irq);
1118         irq_config(IRQ_TPU_FRAME, 1, 1, 0);
1119         irq_enable(IRQ_TPU_FRAME);
1120
1121         /* configure timer 1 to be auto-reload and have a prescale of 12 (13MHz/12 == qbit clock) */
1122         hwtimer_enable(1, 1);
1123         hwtimer_load(1, (1875*4)-1);
1124         hwtimer_config(1, 0, 1);
1125         hwtimer_enable(1, 1);
1126 }
1127