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