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