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