1 /* Synchronous part of GSM Layer 1 */
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>
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.
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.
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.
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>
44 #include <abb/twl3025.h>
46 //#define DEBUG_EVERY_TDMA
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>
57 #include <l1a_l23_interface.h>
61 static l1s_cb_t l1s_cb = NULL;
63 void l1s_set_handler(l1s_cb_t cb)
68 #define ADD_MODULO(sum, delta, modulo) do { \
69 if ((sum += delta) >= modulo) \
73 #define GSM_MAX_FN (26*51*2048)
75 static void l1s_time_inc(struct gsm_time *time, uint32_t delta_fn)
77 ADD_MODULO(time->fn, delta_fn, GSM_MAX_FN);
80 ADD_MODULO(time->t2, 1, 26);
81 ADD_MODULO(time->t3, 1, 51);
83 /* if the new frame number is a multiple of 51 */
85 ADD_MODULO(time->tc, 1, 8);
87 /* if new FN is multiple of 51 and 26 */
89 ADD_MODULO(time->t1, 1, 2048);
92 gsm_fn2gsmtime(time, time->fn);
95 static void l1s_time_dump(const struct gsm_time *time)
97 printf("fn=%u(%u/%2u/%2u)", time->fn, time->t1, time->t2, time->t3);
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)
103 uint8_t bsic = (sb >> 2) & 0x3f;
106 memset(time, 0, sizeof(*time));
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;
114 /* TS 05.02 Chapter 4.3.3 TDMA frame number */
115 time->fn = gsm_gsmtime2fn(time);
117 time->tc = (time->fn / 51) % 8;
122 extern uint16_t rf_arfcn; // TODO
124 /* clip a signed 16bit value at a certain limit */
125 int16_t clip_int16(int16_t angle, int16_t clip_at)
129 else if (angle < -clip_at)
135 int16_t l1s_snr_int(uint16_t snr)
140 uint16_t l1s_snr_fract(uint16_t snr)
142 uint32_t fract = snr & 0x3ff;
143 fract = fract * 1000 / (2 << 10);
145 return fract & 0xffff;
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)
154 #define AFC_MAX_ANGLE 328 /* 0.01 radian in fx1.15 */
155 #define AFC_SNR_THRESHOLD 2560 /* 2.5 dB in fx6.10 */
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)
163 /* synchronize the L1S to a new timebase (typically a new cell */
164 static void synchronize_tdma(struct l1_cell_info *cinfo)
167 uint32_t tpu_shift = cinfo->time_alignment;
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. */
173 tpu_shift = (l1s.tpu_offset + tpu_shift) % QBITS_PER_TDMA;
175 fn_offset = cinfo->fn_offset - 1;
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
180 if (tpu_shift < SWITCH_TIME)
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;
187 l1s.tpu_offset = tpu_shift;
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);
195 /* FIXME: properly end the TPU window at the emd of l1_sync() */
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);
204 /* The serving cell now no longer has a frame or bit offset */
205 cinfo->fn_offset = 0;
206 cinfo->time_alignment = 0;
209 static void l1s_reset_hw(void)
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;
218 /* we have to really reset the TPU, otherwise FB detection
219 * somtimes returns wrong TOA values. */
223 tpu_enq_wait(5); /* really needed ? */
224 tpu_enq_offset(l1s.tpu_offset);
229 uint32_t fnr_report; /* frame number when DSP reported it */
230 int attempt; /* which attempt was this ? */
237 /* computed values */
241 static void dump_mon_state(struct mon_state *fb)
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());
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));
257 static struct mon_state _last_fb, *last_fb = &_last_fb;
259 static int read_fb_result(struct mon_state *st, int attempt)
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];
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;
273 dsp_api.ndb->d_fb_det = 0;
274 dsp_api.ndb->a_sync_demod[D_TOA] = 0; /* TSM30 does it (really needed ?) */
276 /* Update AFC with current frequency offset */
277 afc_correct(st->freq_diff, rf_arfcn);
279 //tpu_dsp_frameirq_enable();
283 static void read_sb_result(struct mon_state *st, int attempt)
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];
290 st->freq_diff = ANGLE_TO_FREQ(st->angle);
291 st->fnr_report = l1s.current_time.fn;
292 st->attempt = attempt;
296 if (st->snr > AFC_SNR_THRESHOLD)
297 afc_input(st->freq_diff, rf_arfcn, 1);
299 afc_input(st->freq_diff, rf_arfcn, 0);
301 dsp_api.r_page_used = 1;
304 #define TIMER_TICKS_PER_TDMA 1875
306 static int last_timestamp;
308 static inline void check_lost_frame(void)
310 int diff, timestamp = hwtimer_read(1);
312 if (last_timestamp < timestamp)
313 last_timestamp += (4*TIMER_TICKS_PER_TDMA);
315 diff = last_timestamp - timestamp;
319 last_timestamp = timestamp;
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)
331 l1s.current_time = l1s.next_time;
332 l1s_time_inc(&l1s.next_time, 1);
333 //l1s_time_dump(&l1s.current_time); putchar(' ');
336 dsp_api.r_page_used = 0;
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;
342 dsp_api.db_w = (T_DB_MCU_TO_DSP *) BASE_API_W_PAGE_1;
344 if (dsp_api.r_page == 0)
345 dsp_api.db_r = (T_DB_DSP_TO_MCU *) BASE_API_R_PAGE_0;
347 dsp_api.db_r = (T_DB_DSP_TO_MCU *) BASE_API_R_PAGE_1;
349 /* Reset MCU->DSP page */
350 dsp_api_memset((uint16_t *) dsp_api.db_w, sizeof(*dsp_api.db_w));
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;
360 /* execute the sched_items that have been scheduled for this
362 tdma_sched_execute();
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));
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 */
376 //dsp_end_scenario();
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);
383 tdma_sched_advance();
386 /* ABORT command ********************************************************/
388 static int l1s_abort_cmd(__unused uint8_t p1, __unused uint8_t p2,
389 __unused uint16_t p3)
393 /* similar to l1s_reset_hw() without touching the TPU */
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;
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;
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);
413 void l1s_dsp_abort(void)
415 /* abort right now */
416 tdma_schedule(0, &l1s_abort_cmd, 0, 0, 0);
419 /* FCCH Burst *****************************************************************/
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)
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;
437 l1s_rx_win_ctrl(rf_arfcn, L1_RXWIN_FB);
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)
448 int ntdma, qbits, fn_offset;
452 if (!dsp_api.ndb->d_fb_det) {
453 /* we did not detect a FB, fall back to mode 0! */
455 /* If we don't reset here, we get DSP DMA errors */
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);
466 printf("FB%u ", dsp_api.ndb->d_fb_mode);
467 read_fb_result(last_fb, attempt);
469 /* FIXME: where did this magic 23 come from? */
472 if (last_fb->toa < 0) {
473 qbits = (last_fb->toa + BITS_PER_TDMA) * 4;
476 ntdma = (last_fb->toa) / BITS_PER_TDMA;
477 qbits = (last_fb->toa - ntdma * BITS_PER_TDMA) * 4;
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;
485 struct l1_cell_info *cinfo = &l1s.serving_cell;
487 cinfo->fn_offset = fnr_delta;
488 cinfo->time_alignment = qbits;
489 cinfo->arfcn = rf_arfcn;
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);
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);
502 /* We found a frequency burst, reset everything and start next task */
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 */
511 /* Don't synchronize_tdma() yet, it does probably not work
512 * reliable due to the TPU reset) */
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) {
521 /* synchronize before reading SB */
522 synchronize_tdma(&l1s.serving_cell);
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 ?) */
532 /* If we don't reset here, we get DSP DMA errors */
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);
538 l1s_fb_test(fn_offset + 10 - l1s.current_time.fn - 1, 0);
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(),
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(),
563 void l1s_fb_test(uint8_t base_fn, uint8_t fb_mode)
567 /* schedule the FB detection command */
568 tdma_schedule(base_fn, &l1s_fbdet_cmd, 0, fb_mode, 0);
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);
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);
582 /* SCH Burst Detection ********************************************************/
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
588 extern const struct tdma_sched_item rach_sched_set_ul[];
590 static int l1s_sbdet_resp(__unused uint8_t p1, uint8_t attempt,
591 __unused uint16_t p3)
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;
604 if (dsp_api.db_r->a_sch[0] & (1<<B_SCH_CRC)) {
605 /* after 2nd attempt, restart */
609 /* mark READ page as being used */
610 dsp_api.r_page_used = 1;
617 printf("SB%d ", attempt);
618 read_sb_result(last_fb, dsp_api.frame_ctr);
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);
625 l1s.serving_cell.bsic = bsic;
627 /* calculate synchronisation value (TODO: only complete for qbits) */
629 qbits = last_fb->toa * 4;
630 fn_offset = l1s.current_time.fn; // TODO
632 if (qbits > QBITS_PER_TDMA) {
633 qbits -= QBITS_PER_TDMA;
635 } else if (qbits < 0) {
636 qbits += QBITS_PER_TDMA;
640 fnr_delta = last_fb->fnr_report - attempt;
641 bits_delta = fnr_delta * BITS_PER_TDMA;
643 cinfo->fn_offset = fnr_delta;
644 cinfo->time_alignment = qbits;
645 cinfo->arfcn = rf_arfcn;
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);
651 printf(" qbits=%u\n", qbits);
653 if (l1s.sb.count > 5 && l1s.sb.synced == 0) {
654 synchronize_tdma(&l1s.serving_cell);
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);
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));
669 l1_queue_for_l2(msg);
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. */
686 if (l1s.sb.count > 10 && sb_time.t3 == 41) {
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);
692 /* We have just seen a SCH burst, we know the next one
693 * is not in less than 7 TDMA frames from now */
700 static int l1s_sbdet_cmd(__unused uint8_t p1, __unused uint8_t p2,
701 __unused uint16_t p3)
705 dsp_api.db_w->d_task_md = SB_DSP_TASK;
706 dsp_api.ndb->d_fb_mode = 0; /* wideband search */
710 l1s_rx_win_ctrl(rf_arfcn, L1_RXWIN_SB);
716 void l1s_sb_test(uint8_t base_fn)
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);
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);
731 /* Normal Burst ***************************************************************/
733 static int l1s_nb_resp(__unused uint8_t p1, uint8_t burst_id, uint16_t p3)
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;
742 /* just for debugging, d_task_d should not be 0 */
743 if (dsp_api.db_r->d_task_d == 0) {
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);
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];
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);
764 afc_input(sig->nb.meas[burst_id].freq_err, rf_arfcn, 0);
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;
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;
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;
786 /* actually issue the signal */
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));
797 /* Set Channel Number depending on MFrame Task ID */
798 dl->chan_nr = mframe_task2chan_nr(mf_task_id, 0); /* FIXME: TS */
800 /* Set SACCH indication in Link IDentifier */
801 if (mf_task_flags & MF_F_SACCH)
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;
811 dl->snr = avg_snr / 4;
812 dl->rx_level = (avg_dbm8 / (8*4)) + 110;
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);
819 /* clear downlink task */
820 dsp_api.db_w->d_task_d = 0;
823 /* mark READ page as being used */
824 dsp_api.r_page_used = 1;
829 static int l1s_nb_cmd(__unused uint8_t p1, uint8_t burst_id,
830 __unused uint16_t p3)
832 uint8_t tsc = l1s.serving_cell.bsic & 0x7;
835 dsp_load_rx_task(ALLC_DSP_TASK, burst_id, tsc);
838 l1s_rx_win_ctrl(rf_arfcn, L1_RXWIN_NB);
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(),
855 /* Transmit Burst *************************************************************/
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 };
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)
865 dsp_api.r_page_used = 1;
870 /* Channel type definitions for DEDICATED mode */
871 #define INVALID_CHANNEL 0
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
889 void l1s_tx_apc_helper(void)
893 /* Load the ApcOffset into the DSP */
895 dsp_api.ndb->d_apcoff = ABB_VAL(APCOFF, (1 << 6) | MY_OFFSET) | 1; /* 2x slope for the GTA-02 ramp */
897 /* Load the TX Power into the DSP */
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
903 dsp_api.db_w->d_power_ctl = ABB_VAL(AUXAPC, 0xC0); /* 2 dBm pulse with offset 4 (GSM-1800) */
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]);
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);
913 static uint8_t loc_cnt = 0;
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)
919 uint8_t mf_task_id = p3 & 0xff;
920 uint8_t mf_task_flags = p3 >> 8;
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);
932 /* before sending first of the four bursts, copy data to API ram */
934 uint16_t *info_ptr = dsp_api.ndb->a_cu;
935 struct llist_head *tx_queue;
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];
946 puts("SDCCH queue ");
947 tx_queue = &l1s.tx_queue[L1S_CHAN_MAIN];
949 msg = msgb_dequeue(tx_queue);
951 /* If the TX queue is empty, send idle pattern */
953 puts("TX idle pattern\n");
956 puts("TX uplink msg\n");
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.
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]);
971 /* Copy last UWORD8 (23rd) in the 12th word after header. */
972 info_ptr[14] = data[22];
973 printf("%02x\n", data[22]);
979 tsc = 7; // !!!!! nanoBTS configuration for SDCCH 0 !!!!!!!!
981 dsp_load_tx_task(DUL_DSP_TASK, burst_id, tsc);
984 l1s_tx_win_ctrl(rf_arfcn, L1_TXWIN_NB, 0);
990 void l1s_tx_test(uint8_t base_fn, uint8_t type)
992 printf("Starting TX %d\n", type);
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);
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(),
1021 /* Interrupt handler */
1022 static void frame_irq(__unused enum irq_nr nr)
1027 /* reset the layer1 as part of synchronizing to a new cell */
1028 void l1s_reset(void)
1034 /* reset scheduler and hardware */
1044 for (i = 0; i < ARRAY_SIZE(l1s.tx_queue); i++)
1045 INIT_LLIST_HEAD(&l1s.tx_queue[i]);
1047 sched_gsmtime_init();
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);
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);