L1: don't hexdump every packet we receive from L1CTL to console
[osmocom-bb.git] / src / target / firmware / layer1 / prim_pm.c
1 /* Layer 1 Power Measurement */
2
3 /* (C) 2010 by Harald Welte <laforge@gnumonks.org>
4  *
5  * All Rights Reserved
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  */
22
23 #include <stdint.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <stdlib.h>
27
28 #include <defines.h>
29 #include <debug.h>
30 #include <memory.h>
31 #include <byteorder.h>
32 #include <osmocore/gsm_utils.h>
33 #include <osmocore/msgb.h>
34 #include <calypso/dsp_api.h>
35 #include <calypso/irq.h>
36 #include <calypso/tpu.h>
37 #include <calypso/tsp.h>
38 #include <calypso/dsp.h>
39 #include <calypso/timer.h>
40 #include <comm/sercomm.h>
41
42 #include <layer1/sync.h>
43 #include <layer1/agc.h>
44 #include <layer1/tdma_sched.h>
45 #include <layer1/tpu_window.h>
46 #include <layer1/l23_api.h>
47
48 #include <l1a_l23_interface.h>
49
50 static void l1ddsp_meas_read(uint8_t nbmeas, uint16_t *pm)
51 {
52         uint8_t i;
53
54         for (i = 0; i < nbmeas; i++)
55                 pm[i] = (uint16_t) ((dsp_api.db_r->a_pm[i] & 0xffff) >> 3);
56         dsp_api.r_page_used = 1;
57 }
58
59 /* scheduler callback to issue a power measurement task to the DSP */
60 static int l1s_pm_cmd(__unused uint8_t p1,
61                       __unused uint8_t p2, uint16_t arfcn)
62 {
63         putchart('P');
64
65         dsp_api.db_w->d_task_md = 2;
66         dsp_api.ndb->d_fb_mode = 0; /* wideband search */
67         dsp_end_scenario();
68
69         /* Program TPU */
70         //l1s_rx_win_ctrl(arfcn, L1_RXWIN_PW);
71         l1s_rx_win_ctrl(arfcn, L1_RXWIN_NB);
72         tpu_end_scenario();
73
74         return 0;
75 }
76
77 /* scheduler callback to read power measurement resposnse from the DSP */
78 static int l1s_pm_resp(__unused uint8_t p1, __unused uint8_t p2,
79                        uint16_t arfcn)
80 {
81         struct l1ctl_pm_resp *pmr;
82         uint16_t pm_level[2];
83
84         putchart('p');
85
86         l1ddsp_meas_read(2, pm_level);
87
88         printd("PM MEAS: %-4d dBm, %-4d dBm ARFCN=%u\n",
89                 agc_inp_dbm8_by_pm(pm_level[0])/8,
90                 agc_inp_dbm8_by_pm(pm_level[1])/8, arfcn);
91
92         if (!l1s.pm.msg)
93                 l1s.pm.msg = l1ctl_msgb_alloc(L1CTL_PM_RESP);
94
95         if (msgb_tailroom(l1s.pm.msg) < sizeof(*pmr)) {
96                 /* flush current msgb */
97                 l1_queue_for_l2(l1s.pm.msg);
98                 /* allocate a new msgb and initialize header */
99                 l1s.pm.msg = l1ctl_msgb_alloc(L1CTL_PM_RESP);
100         }
101
102         pmr = msgb_put(l1s.pm.msg, sizeof(*pmr));
103         pmr->band_arfcn = htons(arfcn);
104         /* FIXME: do this as RxLev rather than DBM8 ? */
105         pmr->pm[0] = dbm2rxlev(agc_inp_dbm8_by_pm(pm_level[0])/8);
106         pmr->pm[1] = dbm2rxlev(agc_inp_dbm8_by_pm(pm_level[1])/8);
107
108         if (l1s.pm.mode == 1) {
109                 if (l1s.pm.range.arfcn_next <= l1s.pm.range.arfcn_end) {
110                         /* schedule PM for next ARFCN in range */
111                         l1s_pm_test(1, l1s.pm.range.arfcn_next);
112                         l1s.pm.range.arfcn_next++;
113                 } else {
114                         /* we have finished, flush the msgb to L2 */
115                         struct l1ctl_hdr *l1h = l1s.pm.msg->l1h;
116                         l1h->flags |= L1CTL_F_DONE;
117                         l1_queue_for_l2(l1s.pm.msg);
118                         l1s.pm.msg = NULL;
119                 }
120         }
121
122         return 0;
123 }
124
125 /* Schedule a power measurement test */
126 void l1s_pm_test(uint8_t base_fn, uint16_t arfcn)
127 {
128         printd("l1s_pm_test(%u, %u)\n", base_fn, arfcn);
129         tdma_schedule(base_fn, &l1s_pm_cmd, 0, 0, arfcn);
130         tdma_schedule(base_fn + 2, &l1s_pm_resp, 0, 0, arfcn);
131 }