Project

General

Profile

patch_osmo_trx_lms_roh_2019-04-12_2.diff

roh, 04/12/2019 07:42 PM

View differences:

Transceiver52M/device/lms/LMSDevice.cpp
41 41
#define LMS_MIN_BW_SUPPORTED 2.5e6 /* 2.5mHz, minimum supported by LMS */
42 42
#define LMS_CALIBRATE_BW_HZ OSMO_MAX(GSM_CARRIER_BW, LMS_MIN_BW_SUPPORTED)
43 43

  
44
static int compat_LMS_VCTCXORead(lms_device_t *dev, uint16_t *val, bool memory)
45
{
46
#if HAVE_LMS_VCTCXO_EEPROM_SAVING
47
	return LMS_VCTCXORead(dev, val, memory);
48
#else
49
	return LMS_VCTCXORead(dev, val);
50
#endif
51
}
52

  
53
static int compat_LMS_VCTCXOWrite(lms_device_t *dev, uint16_t val, bool memory)
54
{
55
#if HAVE_LMS_VCTCXO_EEPROM_SAVING
56
	return LMS_VCTCXOWrite(dev, val, memory);
57
#else
58
	return LMS_VCTCXOWrite(dev, val);
59
#endif
60
}
61

  
62 44
LMSDevice::LMSDevice(size_t tx_sps, size_t rx_sps, InterfaceType iface, size_t chans, double lo_offset,
63 45
		     const std::vector<std::string>& tx_paths,
64 46
		     const std::vector<std::string>& rx_paths):
......
78 60

  
79 61
LMSDevice::~LMSDevice()
80 62
{
63
	unsigned int i;
81 64
	LOGC(DDEV, INFO) << "Closing LMS device";
82 65
	if (m_lms_dev) {
66
		/* disable all channels */
67
		for (i=0; i<chans; i++) {
68
			LMS_EnableChannel(m_lms_dev, LMS_CH_RX, i, false);
69
			LMS_EnableChannel(m_lms_dev, LMS_CH_TX, i, false);
70
		}
83 71
		LMS_Close(m_lms_dev);
84 72
		m_lms_dev = NULL;
85 73
	}
......
145 133

  
146 134
int LMSDevice::open(const std::string &args, int ref, bool swap_channels)
147 135
{
148
	//lms_info_str_t dev_str;
149 136
	lms_info_str_t* info_list;
150
	lms_range_t range_lpfbw_rx, range_lpfbw_tx, range_sr;
151
	float_type sr_host, sr_rf, lpfbw_rx, lpfbw_tx;
152
	uint16_t dac_val;
137
	const lms_dev_info_t* device_info;
138
	lms_range_t range_sr;
139
	float_type sr_host, sr_rf;
153 140
	unsigned int i, n;
154 141
	int rc, dev_id;
155 142

  
......
188 175

  
189 176
	delete [] info_list;
190 177

  
178
	device_info = LMS_GetDeviceInfo(m_lms_dev);
179

  
180
	if ((ref != REF_EXTERNAL) && (ref != REF_INTERNAL))
181
	{
182
		LOGC(DDEV, ALERT) << "Invalid reference type";
183
		goto out_close;
184
	}
185

  
186
	/* if reference clock is external setup must happen _before_ calling LMS_Init */
187
        /* FIXME make external reference frequency configurable */
188
	if (ref == REF_EXTERNAL) {
189
		LOGC(DDEV, INFO) << "Setting External clock reference to 10MHz";
190
		/* Assume an external 10 MHz reference clock */
191
		if (LMS_SetClockFreq(m_lms_dev, LMS_CLOCK_EXTREF, 10000000.0) < 0)
192
			goto out_close;
193
	}
194

  
191 195
	LOGC(DDEV, INFO) << "Init LMS device";
192 196
	if (LMS_Init(m_lms_dev) != 0) {
193 197
		LOGC(DDEV, ERROR) << "LMS_Init() failed";
194 198
		goto out_close;
195 199
	}
196 200

  
201
	/* LimeSDR-Mini does not have switches but needs soldering to select external/internal clock */
202
	/* LimeNET-Micro also does not like selecting internal clock*/
203
	/* also set device specific maximum tx levels selected by phasenoise measurements*/
204
	if (strncmp(device_info->deviceName,"LimeSDR-USB",11)==0)
205
	{
206
	/* if reference clock is internal setup must happen _after_ calling LMS_Init */
207
		if (ref == REF_INTERNAL) {
208
			LOGC(DDEV, INFO) << "Setting Internal clock reference";
209
		if (LMS_SetClockFreq(m_lms_dev, LMS_CLOCK_EXTREF, -1) < 0)
210
			goto out_close;
211
		}
212
		maxTxGainClamp = 73.0;
213
	}
214
	else
215
		if (strncmp(device_info->deviceName,"LimeSDR-Mini",12)==0)
216
			maxTxGainClamp = 66.0;
217
		else
218
			maxTxGainClamp = 71.0; /* "LimeNET-Micro", etc FIXME pciE based LMS boards?*/
219

  
220
	/* enable all used channels */
221
	for (i=0; i<chans; i++) {
222
		if (LMS_EnableChannel(m_lms_dev, LMS_CH_RX, i, true) < 0)
223
			goto out_close;
224

  
225
		if (LMS_EnableChannel(m_lms_dev, LMS_CH_TX, i, true) < 0)
226
			goto out_close;
227
        }
228

  
229
	/* set samplerate */
197 230
	if (LMS_GetSampleRateRange(m_lms_dev, LMS_CH_RX, &range_sr))
198 231
		goto out_close;
199 232
	print_range("Sample Rate", &range_sr);
......
209 242
	/* FIXME: make this device/model dependent, like UHDDevice:dev_param_map! */
210 243
	ts_offset = static_cast<TIMESTAMP>(8.9e-5 * GSMRATE * tx_sps); /* time * sample_rate */
211 244

  
212
	switch (ref) {
213
	case REF_INTERNAL:
214
		LOGC(DDEV, INFO) << "Setting Internal clock reference";
215
		/* Ugly API: Selecting clock source implicit by writing to VCTCXO DAC ?!? */
216
		if (compat_LMS_VCTCXORead(m_lms_dev, &dac_val, false) < 0)
217
			goto out_close;
218
		LOGC(DDEV, INFO) << "Setting VCTCXO to " << dac_val;
219
		if (compat_LMS_VCTCXOWrite(m_lms_dev, dac_val, false) < 0)
220
			goto out_close;
221
		break;
222
	case REF_EXTERNAL:
223
		LOGC(DDEV, INFO) << "Setting External clock reference to " << 10000000.0;
224
		/* Assume an external 10 MHz reference clock */
225
		if (LMS_SetClockFreq(m_lms_dev, LMS_CLOCK_EXTREF, 10000000.0) < 0)
226
			goto out_close;
227
		break;
228
	default:
229
		LOGC(DDEV, ALERT) << "Invalid reference type";
230
		goto out_close;
231
	}
232

  
233
	if (LMS_GetLPFBWRange(m_lms_dev, LMS_CH_RX, &range_lpfbw_rx))
234
		goto out_close;
235
	print_range("LPFBWRange Rx", &range_lpfbw_rx);
236
	if (LMS_GetLPFBWRange(m_lms_dev, LMS_CH_RX, &range_lpfbw_tx))
237
		goto out_close;
238
	print_range("LPFBWRange Tx", &range_lpfbw_tx);
239
	lpfbw_rx = OSMO_MIN(OSMO_MAX(1.4001e6, range_lpfbw_rx.min), range_lpfbw_rx.max);
240
	lpfbw_tx = OSMO_MIN(OSMO_MAX(5.2e6, range_lpfbw_tx.min), range_lpfbw_tx.max);
241

  
242
	LOGC(DDEV, INFO) << "LPFBW: Rx=" << lpfbw_rx << " Tx=" << lpfbw_tx;
243

  
245
	/* configure antennas */
244 246
	if (!set_antennas()) {
245 247
		LOGC(DDEV, ALERT) << "LMS antenna setting failed";
246
		return -1;
247
	}
248

  
249
	/* Perform Rx and Tx calibration */
250
	for (i=0; i<chans; i++) {
251
		LOGC(DDEV, INFO) << "Setting LPFBW chan " << i;
252
		if (LMS_SetLPFBW(m_lms_dev, LMS_CH_RX, i, lpfbw_rx) < 0)
253
			goto out_close;
254
		if (LMS_SetLPFBW(m_lms_dev, LMS_CH_TX, i, lpfbw_tx) < 0)
255
			goto out_close;
256
		LOGC(DDEV, INFO) << "Calibrating chan " << i;
257
		if (LMS_Calibrate(m_lms_dev, LMS_CH_RX, i, LMS_CALIBRATE_BW_HZ, 0) < 0)
258
			goto out_close;
259
		if (LMS_Calibrate(m_lms_dev, LMS_CH_TX, i, LMS_CALIBRATE_BW_HZ, 0) < 0)
260
			goto out_close;
248
		goto out_close;
261 249
	}
262 250

  
263 251
	samplesRead = 0;
......
286 274

  
287 275
	/* configure the channels/streams */
288 276
	for (i=0; i<chans; i++) {
289
		if (LMS_EnableChannel(m_lms_dev, LMS_CH_RX, i, true) < 0)
277
		/* set Gains for calibration/filter setup */
278
		/* TX gain to maximum */
279
		setTxGain(maxTxGain(), i);
280
		/* RX gain to midpoint */
281
		setRxGain(((minRxGain() + maxRxGain()) / 2), i);
282

  
283
		/* set upRx and Tx filters */
284
		if (!do_filters(i))
290 285
			return false;
291

  
292
		if (LMS_EnableChannel(m_lms_dev, LMS_CH_TX, i, true) < 0)
286
		/* Perform Rx and Tx calibration */
287
		if (!do_calib(i))
293 288
			return false;
294 289

  
295
		// Set gains to midpoint
296
		setTxGain((minTxGain() + maxTxGain()) / 2, i);
297
		setRxGain((minRxGain() + maxRxGain()) / 2, i);
298

  
290
		/* configure Streams */
299 291
		m_lms_stream_rx[i] = {};
300 292
		m_lms_stream_rx[i].isTx = false;
301 293
		m_lms_stream_rx[i].channel = i;
......
348 340
	for (i=0; i<chans; i++) {
349 341
		LMS_DestroyStream(m_lms_dev, &m_lms_stream_tx[i]);
350 342
		LMS_DestroyStream(m_lms_dev, &m_lms_stream_rx[i]);
351
		LMS_EnableChannel(m_lms_dev, LMS_CH_RX, i, false);
352
		LMS_EnableChannel(m_lms_dev, LMS_CH_TX, i, false);
353
	}
343
}
354 344

  
355 345
	started = false;
356 346
	return true;
357 347
}
358 348

  
349
/* do rx and tx calibration - depends on gain, freq and bw */
350
bool LMSDevice::do_calib(size_t chan)
351
{
352
	LOGC(DDEV, INFO) << "Calibrating chan " << chan;
353
	if (LMS_Calibrate(m_lms_dev, LMS_CH_RX, chan, LMS_CALIBRATE_BW_HZ, 0) < 0)
354
		return false;
355
	if (LMS_Calibrate(m_lms_dev, LMS_CH_TX, chan, LMS_CALIBRATE_BW_HZ, 0) < 0)
356
		return false;
357
	return true;
358
}
359

  
360
/* do filter config - depends on bw only? */
361
bool LMSDevice::do_filters(size_t chan)
362
{
363
	lms_range_t range_lpfbw_rx, range_lpfbw_tx;
364
	float_type lpfbw_rx, lpfbw_tx;
365

  
366
	LOGC(DDEV, INFO) << "Setting filters on chan " << chan;
367
	if (LMS_GetLPFBWRange(m_lms_dev, LMS_CH_RX, &range_lpfbw_rx))
368
		return false;
369
	print_range("LPFBWRange Rx", &range_lpfbw_rx);
370
	if (LMS_GetLPFBWRange(m_lms_dev, LMS_CH_RX, &range_lpfbw_tx))
371
		return false;
372
	print_range("LPFBWRange Tx", &range_lpfbw_tx);
373

  
374
	lpfbw_rx = OSMO_MIN(OSMO_MAX(1.4001e6, range_lpfbw_rx.min), range_lpfbw_rx.max);
375
	lpfbw_tx = OSMO_MIN(OSMO_MAX(5.2e6, range_lpfbw_tx.min), range_lpfbw_tx.max);
376

  
377
	LOGC(DDEV, INFO) << "LPFBW: Rx=" << lpfbw_rx << " Tx=" << lpfbw_tx;
378

  
379
	LOGC(DDEV, INFO) << "Setting LPFBW chan " << chan;
380
	if (LMS_SetLPFBW(m_lms_dev, LMS_CH_RX, chan, lpfbw_rx) < 0)
381
		return false;
382
	if (LMS_SetLPFBW(m_lms_dev, LMS_CH_TX, chan, lpfbw_tx) < 0)
383
		return false;
384
	return true;
385
}
386

  
359 387
double LMSDevice::maxTxGain()
360 388
{
361
	return 73.0;
389
	return maxTxGainClamp;
362 390
}
363 391

  
364 392
double LMSDevice::minTxGain()
......
388 416
	if (LMS_SetGaindB(m_lms_dev, LMS_CH_TX, chan, dB) < 0)
389 417
		LOGC(DDEV, ERR) << "chan " << chan <<": Error setting TX gain to " << dB << " dB";
390 418

  
419
//FIXME crashes when called while stream is running
420
//	do_calib(chan);
421

  
391 422
	return dB;
392 423
}
393 424

  
......
403 434
	if (LMS_SetGaindB(m_lms_dev, LMS_CH_RX, chan, dB) < 0)
404 435
		LOGC(DDEV, ERR) << "chan "<< chan << ": Error setting RX gain to " << dB << " dB";
405 436

  
437
//FIXME crashes when called while stream is running
438
//	do_calib(chan);
439

  
406 440
	return dB;
407 441
}
408 442

  
......
548 582
}
549 583

  
550 584
GSM::Time LMSDevice::minLatency() {
551
	/* Empirical data from a handful of
552
	relatively recent machines shows that the B100 will underrun when
553
	the transmit threshold is reduced to a time of 6 and a half frames,
554
	so we set a minimum 7 frame threshold. */
555
	return GSM::Time(6,7);
585
	/* UNUSED on limesdr (only used on usrp1/2) */
586
	return GSM::Time(0,0);
556 587
}
557 588

  
558 589
void LMSDevice::update_stream_stats(size_t chan, bool * underrun, bool * overrun)
Transceiver52M/device/lms/LMSDevice.h
64 64
	TIMESTAMP ts_initial, ts_offset;
65 65

  
66 66
	double rxGain;
67
	double maxTxGainClamp;
67 68

  
69
	bool do_calib(size_t chan);
70
	bool do_filters(size_t chan);
68 71
	int get_ant_idx(const std::string & name, bool dir_tx, size_t chan);
69 72
	bool flush_recv(size_t num_pkts);
70 73
	void update_stream_stats(size_t chan, bool * underrun, bool * overrun);
Add picture from clipboard (Maximum size: 48.8 MB)