diff --git a/trxcon/Makefile.am b/trxcon/Makefile.am index 5b1002c8..0458891b 100644 --- a/trxcon/Makefile.am +++ b/trxcon/Makefile.am @@ -1,21 +1,51 @@ -AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6 +include $(top_srcdir)/Makefile.common -SUBDIRS = \ - include \ - src \ +AM_CPPFLAGS = \ + $(all_includes) \ + -I$(top_srcdir)/include \ + -Iinclude \ + $(LIBOSMOCORE_CFLAGS) \ + $(LIBOSMOCODING_CFLAGS) \ + $(LIBOSMOGSM_CFLAGS) \ $(NULL) -ACLOCAL_AMFLAGS = -I m4 - -BUILT_SOURCES = \ - $(top_srcdir)/.version \ - $(NULL) -EXTRA_DIST = \ - .version \ +AM_CFLAGS = \ + -Wall \ + -Iinclude \ + $(LIBOSMOCORE_CFLAGS) \ + $(LIBOSMOCODING_CFLAGS) \ + $(LIBOSMOGSM_CFLAGS) \ $(NULL) -# versioning magic -$(top_srcdir)/.version: - echo $(VERSION) > $@-t && mv $@-t $@ -dist-hook: - echo $(VERSION) > $(distdir)/.tarball-version + +AM_CPPFLAGS += $(STD_DEFINES_AND_INCLUDES) +AM_CXXFLAGS = -Wall -O3 -g -ldl -lpthread -Iinclude + +noinst_LTLIBRARIES = libtrxcon.la + +libtrxcon_la_SOURCES = \ + src/sched_lchan_common.c \ + src/sched_lchan_pdtch.c \ + src/sched_lchan_desc.c \ + src/sched_lchan_xcch.c \ + src/sched_lchan_tchf.c \ + src/sched_lchan_tchh.c \ + src/sched_lchan_rach.c \ + src/sched_lchan_sch.c \ + src/sched_mframe.c \ + src/sched_clck.c \ + src/sched_prim.c \ + src/sched_trx.c \ + src/l1ctl_server.c \ + src/l1ctl.c \ + src/trx_if.c \ + src/logging.c \ + src/trxcon_fsm.c \ + src/trxcon.c \ + $(NULL) + +libtrxcon_la_LIBADD = \ + $(LIBOSMOCORE_LIBS) \ + $(LIBOSMOCODING_LIBS) \ + $(LIBOSMOGSM_LIBS) \ + $(NULL) diff --git a/trxcon/include/osmocom/bb/trxcon/l1ctl_proto.h b/trxcon/include/osmocom/bb/trxcon/l1ctl_proto.h new file mode 100644 index 00000000..a15f9051 --- /dev/null +++ b/trxcon/include/osmocom/bb/trxcon/l1ctl_proto.h @@ -0,0 +1,389 @@ +/* Messages to be sent between the different layers */ + +/* (C) 2010 by Harald Welte + * (C) 2010 by Holger Hans Peter Freyther + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __L1CTL_PROTO_H__ +#define __L1CTL_PROTO_H__ + +enum { + _L1CTL_NONE = 0, + L1CTL_FBSB_REQ, + L1CTL_FBSB_CONF, + L1CTL_DATA_IND, + L1CTL_RACH_REQ, + L1CTL_DM_EST_REQ, + L1CTL_DATA_REQ, + L1CTL_RESET_IND, + L1CTL_PM_REQ, /* power measurement */ + L1CTL_PM_CONF, /* power measurement */ + L1CTL_ECHO_REQ, + L1CTL_ECHO_CONF, + L1CTL_RACH_CONF, + L1CTL_RESET_REQ, + L1CTL_RESET_CONF, + L1CTL_DATA_CONF, + L1CTL_CCCH_MODE_REQ, + L1CTL_CCCH_MODE_CONF, + L1CTL_DM_REL_REQ, + L1CTL_PARAM_REQ, + L1CTL_DM_FREQ_REQ, + L1CTL_CRYPTO_REQ, + L1CTL_SIM_REQ, + L1CTL_SIM_CONF, + L1CTL_TCH_MODE_REQ, + L1CTL_TCH_MODE_CONF, + L1CTL_NEIGH_PM_REQ, + L1CTL_NEIGH_PM_IND, + L1CTL_TRAFFIC_REQ, + L1CTL_TRAFFIC_CONF, + L1CTL_TRAFFIC_IND, + L1CTL_BURST_IND, + + /* configure TBF for uplink/downlink */ + L1CTL_TBF_CFG_REQ, + L1CTL_TBF_CFG_CONF, + + L1CTL_DATA_TBF_REQ, + L1CTL_DATA_TBF_CONF, + + /* Extended (11-bit) RACH (see 3GPP TS 05.02, section 5.2.7) */ + L1CTL_EXT_RACH_REQ, +}; + +enum ccch_mode { + CCCH_MODE_NONE = 0, + CCCH_MODE_NON_COMBINED, + CCCH_MODE_COMBINED, + CCCH_MODE_COMBINED_CBCH, +}; + +enum neigh_mode { + NEIGH_MODE_NONE = 0, + NEIGH_MODE_PM, + NEIGH_MODE_SB, +}; + +enum l1ctl_coding_scheme { + L1CTL_CS_NONE, + L1CTL_CS1, + L1CTL_CS2, + L1CTL_CS3, + L1CTL_CS4, + L1CTL_MCS1, + L1CTL_MCS2, + L1CTL_MCS3, + L1CTL_MCS4, + L1CTL_MCS5, + L1CTL_MCS6, + L1CTL_MCS7, + L1CTL_MCS8, + L1CTL_MCS9, +}; + +/* + * NOTE: struct size. We do add manual padding out of the believe + * that it will avoid some unaligned access. + */ + +/* there are no more messages in a sequence */ +#define L1CTL_F_DONE 0x01 + +struct l1ctl_hdr { + uint8_t msg_type; + uint8_t flags; + uint8_t padding[2]; + uint8_t data[0]; +} __attribute__((packed)); + +/* + * downlink info ... down from the BTS.. + */ +struct l1ctl_info_dl { + /* GSM 08.58 channel number (9.3.1) */ + uint8_t chan_nr; + /* GSM 08.58 link identifier (9.3.2) */ + uint8_t link_id; + /* the ARFCN and the band. FIXME: what about MAIO? */ + uint16_t band_arfcn; + + uint32_t frame_nr; + + uint8_t rx_level; /* 0 .. 63 in typical GSM notation (dBm+110) */ + uint8_t snr; /* Signal/Noise Ration (dB) */ + uint8_t num_biterr; + uint8_t fire_crc; + + uint8_t payload[0]; +} __attribute__((packed)); + +/* new CCCH was found. This is following the header */ +struct l1ctl_fbsb_conf { + int16_t initial_freq_err; + uint8_t result; + uint8_t bsic; + /* FIXME: contents of cell_info ? */ +} __attribute__((packed)); + +/* CCCH mode was changed */ +struct l1ctl_ccch_mode_conf { + uint8_t ccch_mode; /* enum ccch_mode */ + uint8_t padding[3]; +} __attribute__((packed)); + +/* 3GPP TS 44.014, section 5.1 (Calypso specific numbers) */ +enum l1ctl_tch_loop_mode { + L1CTL_TCH_LOOP_OPEN = 0x00, + L1CTL_TCH_LOOP_A = 0x01, + L1CTL_TCH_LOOP_B = 0x02, + L1CTL_TCH_LOOP_C = 0x03, + L1CTL_TCH_LOOP_D = 0x04, + L1CTL_TCH_LOOP_E = 0x05, + L1CTL_TCH_LOOP_F = 0x06, + L1CTL_TCH_LOOP_I = 0x07, +}; + +/* TCH mode was changed */ +struct l1ctl_tch_mode_conf { + uint8_t tch_mode; /* enum tch_mode */ + uint8_t audio_mode; + uint8_t tch_loop_mode; /* enum l1ctl_tch_loop_mode */ + struct { /* 3GPP TS 08.58 9.3.52, 3GPP TS 44.018 10.5.2.21aa */ + uint8_t start_codec; + uint8_t codecs_bitmask; + } amr; +} __attribute__((packed)); + +/* data on the CCCH was found. This is following the header */ +struct l1ctl_data_ind { + uint8_t data[23]; +} __attribute__((packed)); + +/* traffic from the network */ +struct l1ctl_traffic_ind { + uint8_t data[0]; +} __attribute__((packed)); + +/* + * uplink info + */ +struct l1ctl_info_ul { + /* GSM 08.58 channel number (9.3.1) */ + uint8_t chan_nr; + /* GSM 08.58 link identifier (9.3.2) */ + uint8_t link_id; + uint8_t padding[2]; + + uint8_t payload[0]; +} __attribute__((packed)); + +struct l1ctl_info_ul_tbf { + /* references l1ctl_tbf_cfg_req.tbf_nr */ + uint8_t tbf_nr; + uint8_t coding_scheme; + uint8_t padding[2]; + /* RLC/MAC block, size determines CS */ + uint8_t payload[0]; +} __attribute__((packed)); + +/* + * msg for FBSB_REQ + * the l1_info_ul header is in front + */ +struct l1ctl_fbsb_req { + uint16_t band_arfcn; + uint16_t timeout; /* in TDMA frames */ + + uint16_t freq_err_thresh1; + uint16_t freq_err_thresh2; + + uint8_t num_freqerr_avg; + uint8_t flags; /* L1CTL_FBSB_F_* */ + uint8_t sync_info_idx; + uint8_t ccch_mode; /* enum ccch_mode */ + uint8_t rxlev_exp; /* expected signal level */ +} __attribute__((packed)); + +#define L1CTL_FBSB_F_FB0 (1 << 0) +#define L1CTL_FBSB_F_FB1 (1 << 1) +#define L1CTL_FBSB_F_SB (1 << 2) +#define L1CTL_FBSB_F_FB01SB (L1CTL_FBSB_F_FB0|L1CTL_FBSB_F_FB1|L1CTL_FBSB_F_SB) + +/* + * msg for CCCH_MODE_REQ + * the l1_info_ul header is in front + */ +struct l1ctl_ccch_mode_req { + uint8_t ccch_mode; /* enum ccch_mode */ + uint8_t padding[3]; +} __attribute__((packed)); + +/* + * msg for TCH_MODE_REQ + * the l1_info_ul header is in front + */ +struct l1ctl_tch_mode_req { + uint8_t tch_mode; /* enum gsm48_chan_mode */ +#define AUDIO_TX_MICROPHONE (1<<0) +#define AUDIO_TX_TRAFFIC_REQ (1<<1) +#define AUDIO_RX_SPEAKER (1<<2) +#define AUDIO_RX_TRAFFIC_IND (1<<3) + uint8_t audio_mode; + uint8_t tch_loop_mode; /* enum l1ctl_tch_loop_mode */ + struct { /* 3GPP TS 08.58 9.3.52, 3GPP TS 44.018 10.5.2.21aa */ + uint8_t start_codec; + uint8_t codecs_bitmask; + } amr; +} __attribute__((packed)); + +/* the l1_info_ul header is in front */ +struct l1ctl_rach_req { + uint8_t ra; + uint8_t combined; + uint16_t offset; +} __attribute__((packed)); + + +/* the l1_info_ul header is in front */ +struct l1ctl_ext_rach_req { + uint16_t ra11; + uint8_t synch_seq; + uint8_t combined; + uint16_t offset; +} __attribute__((packed)); + +/* the l1_info_ul header is in front */ +struct l1ctl_par_req { + int8_t ta; + uint8_t tx_power; + uint8_t padding[2]; +} __attribute__((packed)); + +struct l1ctl_h0 { + uint16_t band_arfcn; +} __attribute__((packed)); + +struct l1ctl_h1 { + uint8_t hsn; + uint8_t maio; + uint8_t n; + uint8_t _padding[1]; + uint16_t ma[64]; +} __attribute__((packed)); + +struct l1ctl_dm_est_req { + uint8_t tsc; + uint8_t h; + union { + struct l1ctl_h0 h0; + struct l1ctl_h1 h1; + }; + uint8_t tch_mode; + uint8_t audio_mode; +} __attribute__((packed)); + +struct l1ctl_dm_freq_req { + uint16_t fn; + uint8_t tsc; + uint8_t h; + union { + struct l1ctl_h0 h0; + struct l1ctl_h1 h1; + }; +} __attribute__((packed)); + +struct l1ctl_crypto_req { + uint8_t algo; + uint8_t key_len; + uint8_t key[0]; +} __attribute__((packed)); + +struct l1ctl_pm_req { + uint8_t type; + uint8_t padding[3]; + + union { + struct { + uint16_t band_arfcn_from; + uint16_t band_arfcn_to; + } range; + }; +} __attribute__((packed)); + +#define BI_FLG_DUMMY (1 << 4) +#define BI_FLG_SACCH (1 << 5) + +struct l1ctl_burst_ind { + uint32_t frame_nr; + uint16_t band_arfcn; /* ARFCN + band + ul indicator */ + uint8_t chan_nr; /* GSM 08.58 channel number (9.3.1) */ + uint8_t flags; /* BI_FLG_xxx + burst_id = 2LSBs */ + uint8_t rx_level; /* 0 .. 63 in typical GSM notation (dBm+110) */ + uint8_t snr; /* Reported SNR >> 8 (0-255) */ + uint8_t bits[15]; /* 114 bits + 2 steal bits. Filled MSB first */ +} __attribute__((packed)); + +/* a single L1CTL_PM response */ +struct l1ctl_pm_conf { + uint16_t band_arfcn; + uint8_t pm[2]; +} __attribute__((packed)); + +enum l1ctl_reset_type { + L1CTL_RES_T_BOOT, /* only _IND */ + L1CTL_RES_T_FULL, + L1CTL_RES_T_SCHED, +}; + +/* argument to L1CTL_RESET_REQ and L1CTL_RESET_IND */ +struct l1ctl_reset { + uint8_t type; + uint8_t pad[3]; +} __attribute__((packed)); + +struct l1ctl_neigh_pm_req { + uint8_t n; + uint8_t padding[1]; + uint16_t band_arfcn[64]; + uint8_t tn[64]; +} __attribute__((packed)); + +/* neighbour cell measurement results */ +struct l1ctl_neigh_pm_ind { + uint16_t band_arfcn; + uint8_t pm[2]; + uint8_t tn; + uint8_t padding; +} __attribute__((packed)); + +/* traffic data to network */ +struct l1ctl_traffic_req { + uint8_t data[0]; +} __attribute__((packed)); + +struct l1ctl_tbf_cfg_req { + /* future support for multiple concurrent TBFs. 0 for now */ + uint8_t tbf_nr; + /* is this about an UL TBF (1) or DL (0) */ + uint8_t is_uplink; + uint8_t padding[2]; + + /* one USF for each TN, or 255 for invalid/unused */ + uint8_t usf[8]; +} __attribute__((packed)); + +#endif /* __L1CTL_PROTO_H__ */ diff --git a/trxcon/include/osmocom/bb/trxcon/trx_if.h b/trxcon/include/osmocom/bb/trxcon/trx_if.h index 1faa6105..2f2a0452 100644 --- a/trxcon/include/osmocom/bb/trxcon/trx_if.h +++ b/trxcon/include/osmocom/bb/trxcon/trx_if.h @@ -73,3 +73,4 @@ int trx_if_cmd_measure(struct trx_instance *trx, int trx_if_tx_burst(struct trx_instance *trx, const struct l1sched_burst_req *br); +int trx_if_cmd_sync(struct trx_instance *trx); diff --git a/trxcon/src/Makefile.am b/trxcon/src/Makefile.am index 3af004d6..8245162b 100644 --- a/trxcon/src/Makefile.am +++ b/trxcon/src/Makefile.am @@ -1,3 +1,5 @@ +include $(top_srcdir)/Makefile.common + AM_CPPFLAGS = \ $(all_includes) \ -I$(top_srcdir)/include \ @@ -11,6 +13,9 @@ AM_CFLAGS = \ $(NULL) +AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) +AM_CXXFLAGS = -Wall -O3 -g -ldl -lpthread + noinst_LTLIBRARIES = libl1sched.la libl1sched_la_SOURCES = \ @@ -35,9 +40,9 @@ libl1sched_la_LIBADD = \ $(NULL) -bin_PROGRAMS = trxcon +noinst_LTLIBRARIES = libtrxcon.la -trxcon_SOURCES = \ +libtrxcon_SOURCES = \ l1ctl_server.c \ l1ctl.c \ trx_if.c \ @@ -46,7 +51,7 @@ trxcon_SOURCES = \ trxcon.c \ $(NULL) -trxcon_LDADD = \ +libtrxcon_LDADD = \ libl1sched.la \ $(LIBOSMOCORE_LIBS) \ $(LIBOSMOGSM_LIBS) \ diff --git a/trxcon/src/l1ctl.c b/trxcon/src/l1ctl.c index 5f1e6107..a9f15209 100644 --- a/trxcon/src/l1ctl.c +++ b/trxcon/src/l1ctl.c @@ -335,7 +335,7 @@ static int l1ctl_rx_fbsb_req(struct l1ctl_client *l1c, struct msgb *msg) struct trxcon_param_fbsb_search_req req = { .pchan_config = l1ctl_ccch_mode2pchan_config(fbsb->ccch_mode), - .timeout_ms = ntohs(fbsb->timeout) * GSM_TDMA_FN_DURATION_uS / 1000, + .timeout_ms = 2000, .band_arfcn = ntohs(fbsb->band_arfcn), }; diff --git a/trxcon/src/logging.c b/trxcon/src/logging.c index 5c16ac5e..29be652b 100644 --- a/trxcon/src/logging.c +++ b/trxcon/src/logging.c @@ -58,7 +58,7 @@ static struct log_info_cat trx_log_info_cat[] = { .name = "DSCH", .description = "Scheduler management", .color = "\033[1;36m", - .enabled = 1, .loglevel = LOGL_NOTICE, + .enabled = 0, .loglevel = LOGL_NOTICE, }, [DSCHD] = { .name = "DSCHD", diff --git a/trxcon/src/trx_if.c b/trxcon/src/trx_if.c index 6f225ee0..d4e057cf 100644 --- a/trxcon/src/trx_if.c +++ b/trxcon/src/trx_if.c @@ -338,6 +338,11 @@ int trx_if_cmd_txtune(struct trx_instance *trx, uint16_t band_arfcn) return trx_ctrl_cmd(trx, 1, "TXTUNE", "%u", freq10 * 100); } +int trx_if_cmd_sync(struct trx_instance *trx) +{ + return trx_ctrl_cmd(trx, 1, "SYNC", 0); +} + /* * Power measurement * @@ -620,13 +625,7 @@ static int trx_data_rx_cb(struct osmo_fd *ofd, unsigned int what) rssi = -(int8_t) buf[5]; toa256 = ((int16_t) (buf[6] << 8) | buf[7]); - /* Copy and convert bits {254..0} to sbits {-127..127} */ - for (unsigned int i = 0; i < 148; i++) { - if (buf[8 + i] == 255) - bits[i] = -127; - else - bits[i] = 127 - buf[8 + i]; - } + memcpy(bits, buf + 8, 148); if (tn >= 8) { LOGPFSMSL(trx->fi, DTRXD, LOGL_ERROR, "Illegal TS %d\n", tn); diff --git a/trxcon/src/trxcon.c b/trxcon/src/trxcon.c index d46cd8ec..10eb4eda 100644 --- a/trxcon/src/trxcon.c +++ b/trxcon/src/trxcon.c @@ -18,6 +18,7 @@ * */ +#define _GNU_SOURCE #include #include #include @@ -27,6 +28,7 @@ #include #include #include +#include #include @@ -452,12 +454,31 @@ static void signal_handler(int signum) } } +extern void init_external_transceiver(int argc, char **argv); +extern void stop_trx(); +extern volatile bool gshutdown; + int main(int argc, char **argv) { struct l1ctl_server_cfg server_cfg; struct l1ctl_server *server = NULL; int rc = 0; + cpu_set_t cpuset; + + CPU_ZERO(&cpuset); + CPU_SET(3, &cpuset); + pthread_setaffinity_np(pthread_self(), sizeof(cpuset), &cpuset); + + int prio = sched_get_priority_max(SCHED_RR) - 5; + struct sched_param param; + param.sched_priority = prio; + int rv = sched_setscheduler(0, SCHED_RR, ¶m); + if (rv < 0) { + LOGP(DAPP, LOGL_ERROR, "Failed to set sched!\n"); + exit(0); + } + printf("%s", COPYRIGHT); handle_options(argc, argv); @@ -469,12 +490,12 @@ int main(int argc, char **argv) msgb_talloc_ctx_init(tall_trxcon_ctx, 0); /* Setup signal handlers */ - signal(SIGINT, &signal_handler); - signal(SIGTERM, &signal_handler); - signal(SIGABRT, &signal_handler); - signal(SIGUSR1, &signal_handler); - signal(SIGUSR2, &signal_handler); - osmo_init_ignore_signals(); + // signal(SIGINT, &signal_handler); + // signal(SIGTERM, &signal_handler); + // signal(SIGABRT, &signal_handler); + // signal(SIGUSR1, &signal_handler); + // signal(SIGUSR2, &signal_handler); + // osmo_init_ignore_signals(); /* Init logging system */ trx_log_init(tall_trxcon_ctx, app_data.debug_mask); @@ -530,8 +551,7 @@ int main(int argc, char **argv) /* Initialize pseudo-random generator */ srand(time(NULL)); - while (!app_data.quit) - osmo_select_main(0); + init_external_transceiver(argc, argv); exit: if (server != NULL) diff --git a/trxcon/src/trxcon_fsm.c b/trxcon/src/trxcon_fsm.c index 0d03740e..0243fd44 100644 --- a/trxcon/src/trxcon_fsm.c +++ b/trxcon/src/trxcon_fsm.c @@ -134,17 +134,19 @@ static void trxcon_st_reset_action(struct osmo_fsm_inst *fi, l1sched_configure_ts(trxcon->sched, 0, req->pchan_config); /* Only if current ARFCN differs */ - if (trxcon->l1p.band_arfcn != req->band_arfcn) { + // if (trxcon->l1p.band_arfcn != req->band_arfcn) { /* Update current ARFCN */ trxcon->l1p.band_arfcn = req->band_arfcn; /* Tune transceiver to required ARFCN */ trx_if_cmd_rxtune(trxcon->phyif, req->band_arfcn); trx_if_cmd_txtune(trxcon->phyif, req->band_arfcn); - } + // } /* Transceiver might have been powered on before, e.g. * in case of sending L1CTL_FBSB_REQ due to signal loss. */ + trx_if_cmd_sync(trxcon->phyif); + if (!trx->powered_up) trx_if_cmd_poweron(trxcon->phyif); break;