blob: a2267e2d3f06d4557a9a7fa578011faac810999e [file] [log] [blame]
dburgessb3a0ca42011-10-12 07:44:40 +00001/*
2* Copyright 2008, 2009, 2010 Free Software Foundation, Inc.
3* Copyright 2010 Kestrel Signal Processing, Inc.
4*
5* This software is distributed under the terms of the GNU Affero Public License.
6* See the COPYING file in the main directory for details.
7*
8* This use of this software may be subject to additional restrictions.
9* See the LEGAL file in the main directory for details.
10
11 This program is free software: you can redistribute it and/or modify
12 it under the terms of the GNU Affero General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU Affero General Public License for more details.
20
21 You should have received a copy of the GNU Affero General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
23
24*/
25
Thomas Tsou79403352013-11-09 17:04:29 -050026#ifdef HAVE_CONFIG_H
27#include "config.h"
28#endif
dburgessb3a0ca42011-10-12 07:44:40 +000029
30#include "Transceiver.h"
kurtis.heimerl67e3d5a2011-11-26 03:19:13 +000031#include "radioDevice.h"
dburgessb3a0ca42011-10-12 07:44:40 +000032
33#include <time.h>
34#include <signal.h>
35
36#include <GSMCommon.h>
37#include <Logger.h>
38#include <Configuration.h>
39
Thomas Tsouddd6def2013-07-30 18:47:30 +020040#define CONFIGDB "/etc/OpenBTS/OpenBTS.db"
41
Thomas Tsoufe269fe2013-10-14 23:56:51 -040042/* Samples-per-symbol for downlink path
43 * 4 - Uses precision modulator (more computation, less distortion)
44 * 1 - Uses minimized modulator (less computation, more distortion)
45 *
46 * Other values are invalid. Receive path (uplink) is always
Thomas Tsou79403352013-11-09 17:04:29 -050047 * downsampled to 1 sps. Default to 4 sps for all cases except for
48 * ARM and non-SIMD enabled architectures.
Thomas Tsoufe269fe2013-10-14 23:56:51 -040049 */
Thomas Tsou79403352013-11-09 17:04:29 -050050#if defined(HAVE_NEON) || !defined(HAVE_SSE3)
51#define SPS 1
52#else
53#define SPS 4
54#endif
Thomas Tsoufe269fe2013-10-14 23:56:51 -040055
Thomas Tsouddd6def2013-07-30 18:47:30 +020056ConfigurationTable gConfig(CONFIGDB);
dburgessb3a0ca42011-10-12 07:44:40 +000057
58volatile bool gbShutdown = false;
Thomas Tsouddd6def2013-07-30 18:47:30 +020059
dburgessb3a0ca42011-10-12 07:44:40 +000060static void ctrlCHandler(int signo)
61{
Thomas Tsoude1648c2013-10-15 16:18:58 -040062 std::cout << "Received shutdown signal" << std::endl;
63 gbShutdown = true;
dburgessb3a0ca42011-10-12 07:44:40 +000064}
65
Thomas Tsouddd6def2013-07-30 18:47:30 +020066/*
67 * Attempt to open and test the database file before
68 * accessing the configuration table. We do this because
69 * the global table constructor cannot provide notification
70 * in the event of failure.
71 */
72int testConfig(const char *filename)
73{
74 int rc, val = 9999;
75 sqlite3 *db;
76 std::string test = "sadf732zdvj2";
77
78 const char *keys[3] = {
79 "Log.Level",
80 "TRX.Port",
81 "TRX.IP",
82 };
83
84 /* Try to open the database */
85 rc = sqlite3_open(filename, &db);
86 if (rc || !db) {
87 std::cerr << "Config: Database could not be opened" << std::endl;
88 return -1;
89 } else {
90 sqlite3_close(db);
91 }
92
93 /* Attempt to set a value in the global config */
94 if (!gConfig.set(test, val)) {
95 std::cerr << "Config: Failed to set test key - "
96 << "permission to access the database?" << std::endl;
97 return -1;
98 } else {
99 gConfig.remove(test);
100 }
101
102 /* Attempt to query */
103 for (int i = 0; i < 3; i++) {
104 try {
105 gConfig.getStr(keys[i]);
106 } catch (...) {
107 std::cerr << "Config: Failed query on " << keys[i] << std::endl;
108 return -1;
109 }
110 }
111
112 return 0;
113}
dburgessb3a0ca42011-10-12 07:44:40 +0000114
115int main(int argc, char *argv[])
116{
Thomas Tsoue90a42b2013-11-13 23:38:09 -0500117 int trxPort, radioType, chans = 1, extref = 0, fail = 0, diversity = 0;
Thomas Tsou204a9f12013-10-29 18:34:16 -0400118 std::string logLevel, trxAddr, deviceArgs = "";
Thomas Tsoude1648c2013-10-15 16:18:58 -0400119 RadioDevice *usrp = NULL;
120 RadioInterface *radio = NULL;
121 Transceiver *trx = NULL;
Thomas Tsou204a9f12013-10-29 18:34:16 -0400122 VectorFIFO *fifo = NULL;
ttsouf60dafa2012-10-22 00:07:14 +0000123
Thomas Tsou204a9f12013-10-29 18:34:16 -0400124 if (argc == 3) {
ttsouf60dafa2012-10-22 00:07:14 +0000125 deviceArgs = std::string(argv[2]);
Thomas Tsou204a9f12013-10-29 18:34:16 -0400126 chans = atoi(argv[1]);
127 } else if (argc == 2) {
128 chans = atoi(argv[1]);
129 } else if (argc != 1) {
130 std::cout << argv[0] << " <number of channels> <device args>" << std::endl;
131 }
Thomas Tsoude1648c2013-10-15 16:18:58 -0400132
133 if (signal(SIGINT, ctrlCHandler) == SIG_ERR) {
134 std::cerr << "Couldn't install signal handler for SIGINT" << std::endl;
135 return EXIT_FAILURE;
ttsouf60dafa2012-10-22 00:07:14 +0000136 }
137
Thomas Tsoude1648c2013-10-15 16:18:58 -0400138 if (signal(SIGTERM, ctrlCHandler) == SIG_ERR) {
139 std::cerr << "Couldn't install signal handler for SIGTERM" << std::endl;
140 return EXIT_FAILURE;
dburgessb3a0ca42011-10-12 07:44:40 +0000141 }
Thomas Tsouddd6def2013-07-30 18:47:30 +0200142
dburgessb3a0ca42011-10-12 07:44:40 +0000143 // Configure logger.
Thomas Tsouddd6def2013-07-30 18:47:30 +0200144 if (testConfig(CONFIGDB) < 0) {
145 std::cerr << "Config: Database failure" << std::endl;
146 return EXIT_FAILURE;
147 }
dburgessb3a0ca42011-10-12 07:44:40 +0000148
Thomas Tsouddd6def2013-07-30 18:47:30 +0200149 logLevel = gConfig.getStr("Log.Level");
150 trxPort = gConfig.getNum("TRX.Port");
151 trxAddr = gConfig.getStr("TRX.IP");
Thomas Tsou010fff72013-10-16 00:31:18 -0400152
153 if (gConfig.defines("TRX.Reference"))
154 extref = gConfig.getNum("TRX.Reference");
155
156 if (extref)
157 std::cout << "Using external clock reference" << std::endl;
158 else
159 std::cout << "Using internal clock reference" << std::endl;
160
Thomas Tsouddd6def2013-07-30 18:47:30 +0200161 gLogInit("transceiver", logLevel.c_str(), LOG_LOCAL7);
dburgessb3a0ca42011-10-12 07:44:40 +0000162
163 srandom(time(NULL));
164
Thomas Tsoue90a42b2013-11-13 23:38:09 -0500165 if (diversity)
166 chans = 2;
167
168 usrp = RadioDevice::make(SPS, chans, diversity);
Thomas Tsou010fff72013-10-16 00:31:18 -0400169 radioType = usrp->open(deviceArgs, extref);
Thomas Tsoucb69f082013-04-08 14:18:26 -0400170 if (radioType < 0) {
kurtis.heimerle3320322011-11-28 06:26:08 +0000171 LOG(ALERT) << "Transceiver exiting..." << std::endl;
kurtis.heimerl67e3d5a2011-11-26 03:19:13 +0000172 return EXIT_FAILURE;
173 }
dburgessb3a0ca42011-10-12 07:44:40 +0000174
Thomas Tsoucb69f082013-04-08 14:18:26 -0400175 switch (radioType) {
176 case RadioDevice::NORMAL:
Thomas Tsoue90a42b2013-11-13 23:38:09 -0500177 radio = new RadioInterface(usrp, SPS, chans);
Thomas Tsoucb69f082013-04-08 14:18:26 -0400178 break;
Thomas Tsoufe269fe2013-10-14 23:56:51 -0400179 case RadioDevice::RESAMP_64M:
180 case RadioDevice::RESAMP_100M:
Thomas Tsoue90a42b2013-11-13 23:38:09 -0500181 radio = new RadioInterfaceResamp(usrp, SPS, chans);
182 break;
183 case RadioDevice::DIVERSITY:
184 radio = new RadioInterfaceDiversity(usrp, SPS, chans);
Thomas Tsoucb69f082013-04-08 14:18:26 -0400185 break;
186 default:
187 LOG(ALERT) << "Unsupported configuration";
Thomas Tsoude1648c2013-10-15 16:18:58 -0400188 fail = 1;
189 goto shutdown;
Thomas Tsoucb69f082013-04-08 14:18:26 -0400190 }
Thomas Tsoufe269fe2013-10-14 23:56:51 -0400191 if (!radio->init(radioType)) {
Thomas Tsou03e6ecf2013-08-20 20:54:54 -0400192 LOG(ALERT) << "Failed to initialize radio interface";
Thomas Tsoude1648c2013-10-15 16:18:58 -0400193 fail = 1;
194 goto shutdown;
Thomas Tsou03e6ecf2013-08-20 20:54:54 -0400195 }
Thomas Tsoucb69f082013-04-08 14:18:26 -0400196
Thomas Tsou204a9f12013-10-29 18:34:16 -0400197 trx = new Transceiver(trxPort, trxAddr.c_str(),
198 SPS, chans, GSM::Time(3,0), radio);
Thomas Tsoue57004d2013-08-20 18:55:33 -0400199 if (!trx->init()) {
200 LOG(ALERT) << "Failed to initialize transceiver";
Thomas Tsoude1648c2013-10-15 16:18:58 -0400201 fail = 1;
202 goto shutdown;
Thomas Tsoue57004d2013-08-20 18:55:33 -0400203 }
Thomas Tsou204a9f12013-10-29 18:34:16 -0400204
205 for (int i = 0; i < chans; i++) {
206 fifo = radio->receiveFIFO(i);
207 if (fifo && trx->receiveFIFO(fifo, i))
208 continue;
209
210 LOG(ALERT) << "Could not attach FIFO to channel " << i;
211 fail = 1;
212 goto shutdown;
213 }
214
dburgessb3a0ca42011-10-12 07:44:40 +0000215 trx->start();
Thomas Tsou96794cb2013-07-30 16:32:14 +0200216
Thomas Tsoude1648c2013-10-15 16:18:58 -0400217 while (!gbShutdown)
Thomas Tsou96794cb2013-07-30 16:32:14 +0200218 sleep(1);
dburgessb3a0ca42011-10-12 07:44:40 +0000219
Thomas Tsoude1648c2013-10-15 16:18:58 -0400220shutdown:
221 std::cout << "Shutting down transceiver..." << std::endl;
dburgessb3a0ca42011-10-12 07:44:40 +0000222
dburgessb3a0ca42011-10-12 07:44:40 +0000223 delete trx;
Thomas Tsoude1648c2013-10-15 16:18:58 -0400224 delete radio;
225 delete usrp;
226
227 if (fail)
228 return EXIT_FAILURE;
229
230 return 0;
dburgessb3a0ca42011-10-12 07:44:40 +0000231}