Project

General

Profile

Download (5.1 KB) Statistics
| Branch: | Tag: | Revision:
1 956debaf Christian Daniel
#include <stdio.h>
2
#include <stdlib.h>
3
#include <string.h>
4
#include <unistd.h>
5
#include <math.h>
6
#include <portaudio.h>
7
#include "serial.h"
8
#include "utils.h"
9
10
struct SweepState {
11
	int serialFd;
12
	int settleTime;
13
	int sampleTime;
14
	uint64_t freq;
15
	double acc;
16
	double num;
17
	double start;
18
	double stop;
19
};
20
21
static int printSyntax()
22
{
23
	fprintf(stderr, "Error: Invalid command line!\n\n"
24
		"syntax: sdr-sweep /dev/ttyUSB0 start stop"
25
		"  - start = start frequency in MHz, e.g 88.5\n"
26
		"  - stop = stop frequency in MHz, e.g. 108\n"
27
		"frequency range of OsmoSDR is 64MHz - 1700MHz\n");
28
29
	return EXIT_FAILURE;
30
}
31
32
static void setFreq(int fd, uint64_t freq)
33
{
34
	char str[128];
35
	char* c;
36
	char str2[2] = { '\0', '\0' };
37
38
	while(serialGetS(fd, str, sizeof(str), 1) >= 0)
39
		;
40
41
	sprintf(str, "tuner.freq=%llu\r", freq);
42
43
	for(c = str; *c != '\0'; c++) {
44
		serialPutC(fd, *c);
45
		if(*c == '\r')
46
			str2[0] = '\n';
47
		else str2[0] = *c;
48
		if(serialExpect(fd, str2, 1) < 0) {
49
			serialPutC(fd, *c);
50
			if(serialExpect(fd, str2, 1) < 0) {
51
				fprintf(stderr, "serial port broken (%d = %c)\n", *c, *c);
52
				return;
53
			}
54
		}
55
	}
56
}
57
58
static int audioCallback(const void* inputBuffer, void* outputBuffer,
59
	unsigned long framesPerBuffer,
60
	const PaStreamCallbackTimeInfo* timeInfo,
61
	PaStreamCallbackFlags statusFlags,
62
	void* userData)
63
{
64
	struct SweepState* state = (struct SweepState*)userData;
65
	int i;
66
	const int16_t* input = (const int16_t*)inputBuffer;
67
	uint8_t c;
68
	double v;
69
	int max;
70
71
	//fprintf(stderr, "block %lu\n", framesPerBuffer);
72
73
	while(serialGetC(state->serialFd, &c, 0) >= 0)
74
		//fprintf(stderr, "%c", c);
75
		;
76
77
	if(state->settleTime > 0) {
78
		state->settleTime -= framesPerBuffer;
79
		if(state->settleTime <= 0) {
80
			state->sampleTime = 100000;
81
			state->acc = 0.0;
82
			state->num = 0.0;
83
		}
84
		return 0;
85
	}
86
87
	if(state->sampleTime > 0) {
88
		max = 0;
89
		for(i = 0; i < framesPerBuffer; i++) {
90
			if(abs(*input) > max)
91
				max = abs(*input);
92
			v = *input / 32768.0;
93
			state->acc += v * v;
94
			input++;
95
			if(abs(*input) > max)
96
				max = abs(*input);
97
			v = *input / 32768.0;
98
			state->acc += v * v;
99
			input++;
100
			state->num += 2;
101
		}
102
		//fprintf(stderr, "-> %d\n", max);
103
104
		state->sampleTime -= framesPerBuffer;
105
		if(state->sampleTime <= 0) {
106
			printf("%.1f\t%.1f\n", state->freq / 1000000.0, 20.0 * log10(sqrt(state->acc / state->num)));
107
			fflush(stdout);
108
			state->freq += 100000;
109
			setFreq(state->serialFd, state->freq);
110
			state->settleTime = 500000;
111
		}
112
	}
113
114
	return 0;
115
}
116
117
static PaStream* audioOpen(struct SweepState* state)
118
{
119
	int numDevices;
120
	const PaDeviceInfo* deviceInfo;
121
	PaError err;
122
	int i;
123
	int dev = -1;
124
	PaStream* stream = NULL;
125
	PaStreamParameters inputParameters;
126
127
	err = Pa_Initialize();
128
	if(err != paNoError)
129
		goto error_noinit;
130
131
	numDevices = Pa_GetDeviceCount();
132
	if(numDevices < 0) {
133
		err = numDevices;
134
		goto error;
135
	}
136
137
	for(i = 0; i < numDevices; i++) {
138
		deviceInfo = Pa_GetDeviceInfo(i);
139
		fprintf(stderr, "#%02d -> [%s]\n", i, deviceInfo->name);
140
		if(strncmp(deviceInfo->name, "OsmoSDR", 7) == 0)
141
			dev = i;
142
	}
143
	if(dev < 0) {
144
		fprintf(stderr, "OsmoSDR not found!\n");
145
		Pa_Terminate();
146
		return NULL;
147
	}
148
149
	fprintf(stderr, "Using device #%02d (sample rate %.0f Hz)\n", dev, Pa_GetDeviceInfo(dev)->defaultSampleRate);
150
151
	bzero(&inputParameters, sizeof(inputParameters));
152
	inputParameters.channelCount = 2;
153
	inputParameters.device = dev;
154
	inputParameters.hostApiSpecificStreamInfo = NULL;
155
	inputParameters.sampleFormat = paInt16;
156
	inputParameters.suggestedLatency = Pa_GetDeviceInfo(dev)->defaultHighInputLatency ;
157
	inputParameters.hostApiSpecificStreamInfo = NULL;
158
159
	err = Pa_OpenStream(&stream, &inputParameters, NULL, Pa_GetDeviceInfo(dev)->defaultSampleRate, 20000,
160
		paClipOff | paDitherOff, audioCallback, state);
161
	if(err != paNoError)
162
		goto error_noinit;
163
164
	err = Pa_StartStream(stream);
165
	if(err != paNoError)
166
		goto error_noinit;
167
168
	return stream;
169
170
error:
171
	Pa_Terminate();
172
173
error_noinit:
174
	fprintf(stderr, "PortAudio error: %s\n", Pa_GetErrorText(err));
175
	return NULL;
176
}
177
178
static void audioClose(PaStream* stream)
179
{
180
	PaError err;
181
182
	err = Pa_StopStream(stream);
183
	if(err != paNoError)
184
		fprintf(stderr, "PortAudio error: %s\n", Pa_GetErrorText(err));
185
186
	err = Pa_CloseStream(stream);
187
	if(err != paNoError)
188
		fprintf(stderr, "PortAudio error: %s\n", Pa_GetErrorText(err));
189
190
	err = Pa_Terminate();
191
	if(err != paNoError)
192
		fprintf(stderr, "PortAudio error: %s\n", Pa_GetErrorText(err));
193
}
194
195
int main(int argc, char* argv[])
196
{
197
	HANDLE fd;
198
	PaStream* stream;
199
	struct SweepState state;
200
201
	if(argc < 4)
202
		return printSyntax();
203
204
	if((fd = serialOpen(argv[1])) == INVALID_HANDLE_VALUE)
205
		return EXIT_FAILURE;
206
207
	memset(&state, 0x00, sizeof(struct SweepState));
208
	state.serialFd = fd;
209
	state.settleTime = 100000;
210
	state.start = atof(argv[2]);
211
	state.stop = atof(argv[3]);
212
	state.freq = state.start * 1000000.0;
213
	serialPutS(fd, "\r\r\rtuner.init!\r\r\r");
214
	setFreq(fd, state.freq);
215
216
	if((stream = audioOpen(&state)) == NULL) {
217
		serialClose(fd);
218
		return EXIT_FAILURE;
219
	}
220
221
	fprintf(stderr, "sweep running...\n");
222
223
	while(1) {
224
		sleep(1);
225
		if(state.freq > state.stop * 1000000.0)
226
			break;
227
		fprintf(stderr, "...%.1f MHz...\n", state.freq / 1000000.0);
228
	}
229
230
	audioClose(stream);
231
	serialClose(fd);
232
233
	return EXIT_FAILURE;
234
}
Add picture from clipboard (Maximum size: 48.8 MB)