Subversion Repositories svnkaklik

Rev

Rev 542 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log

Rev Author Line No. Line
532 kaklik 1
///////////////////////////////////////////////////////////////////////////////////
2
//                        This small demo of sonar.
3
// Program allow distance measuring.
4
//
5
//
6
///////////////////////////////////////////////////////////////////////////////////
526 kaklik 7
 
8
#include <stdio.h>
9
#include <stdlib.h>
10
#include <string.h>
11
#include <sched.h>
12
#include <errno.h>
13
#include <getopt.h>
14
#include <alsa/asoundlib.h>
15
#include <sys/time.h>
16
#include <math.h>
17
 
18
static char *device = "plughw:0,0";			/* playback device */
19
static snd_pcm_format_t format = SND_PCM_FORMAT_S16;	/* sample format */
536 kaklik 20
static unsigned int rate = 98000;			/* stream rate */
526 kaklik 21
static unsigned int buffer_time = 500000;		/* ring buffer length in us */
22
static unsigned int period_time = 100000;		/* period time in us */
23
static int verbose = 0;					/* verbose flag */
24
static int resample = 1;				/* enable alsa-lib resampling */
25
static int period_event = 0;				/* produce poll event after each period */
26
 
533 kaklik 27
#define SOUND_SPEED	340
538 kaklik 28
#define SIGNAL_SAMPLES 100000
542 kaklik 29
#define CHIRP_OFFSET	0 
533 kaklik 30
 
531 kaklik 31
unsigned int chirp_size;
527 kaklik 32
 
526 kaklik 33
int period=0;
527 kaklik 34
int cperiod=0;
532 kaklik 35
int chirp[100000];
36
short signal[1000000];		// record 6s of input samples
526 kaklik 37
 
38
static snd_pcm_sframes_t buffer_size;	// size of buffer at sound card
39
static snd_pcm_sframes_t period_size;	//samples per frame
40
static snd_output_t *output = NULL;
41
 
540 kaklik 42
static int set_hwparams(snd_pcm_t *handle, snd_pcm_hw_params_t *params, unsigned int channels)
526 kaklik 43
{
44
	unsigned int rrate;
45
	snd_pcm_uframes_t size;
46
	int err, dir;
47
 
48
	/* choose all parameters */
49
	err = snd_pcm_hw_params_any(handle, params);
50
	if (err < 0) {
51
		printf("Broken configuration for playback: no configurations available: %s\n", snd_strerror(err));
52
		return err;
53
	}
54
	/* set hardware resampling */
55
	err = snd_pcm_hw_params_set_rate_resample(handle, params, resample);
56
	if (err < 0) {
57
		printf("Resampling setup failed for playback: %s\n", snd_strerror(err));
58
		return err;
59
	}
60
	/* set the interleaved read/write format */
540 kaklik 61
	err = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
526 kaklik 62
	if (err < 0) {
63
		printf("Access type not available for playback: %s\n", snd_strerror(err));
64
		return err;
65
	}
66
	/* set the sample format */
67
	err = snd_pcm_hw_params_set_format(handle, params, format);
68
	if (err < 0) {
69
		printf("Sample format not available for playback: %s\n", snd_strerror(err));
70
		return err;
71
	}
72
	/* set the count of channels */
73
	err = snd_pcm_hw_params_set_channels(handle, params, channels);
74
	if (err < 0) {
75
		printf("Channels count (%i) not available for playbacks: %s\n", channels, snd_strerror(err));
76
		return err;
77
	}
78
	/* set the stream rate */
79
	rrate = rate;
80
	err = snd_pcm_hw_params_set_rate_near(handle, params, &rrate, 0);
81
	if (err < 0) {
82
		printf("Rate %iHz not available for playback: %s\n", rate, snd_strerror(err));
83
		return err;
84
	}
85
	if (rrate != rate) {
86
		printf("Rate doesn't match (requested %iHz, get %iHz)\n", rate, err);
87
		return -EINVAL;
88
	}
537 kaklik 89
	else printf("Rate set to %i Hz\n", rate, err); 
526 kaklik 90
	/* set the buffer time */
91
	err = snd_pcm_hw_params_set_buffer_time_near(handle, params, &buffer_time, &dir);
92
	if (err < 0) {
93
		printf("Unable to set buffer time %i for playback: %s\n", buffer_time, snd_strerror(err));
94
		return err;
95
	}
96
	err = snd_pcm_hw_params_get_buffer_size(params, &size);
97
	if (err < 0) {
98
		printf("Unable to get buffer size for playback: %s\n", snd_strerror(err));
99
		return err;
100
	}
101
	buffer_size = size;
102
	/* set the period time */
103
	err = snd_pcm_hw_params_set_period_time_near(handle, params, &period_time, &dir);
104
	if (err < 0) {
105
		printf("Unable to set period time %i for playback: %s\n", period_time, snd_strerror(err));
106
		return err;
107
	}
108
	err = snd_pcm_hw_params_get_period_size(params, &size, &dir);
109
	if (err < 0) {
110
		printf("Unable to get period size for playback: %s\n", snd_strerror(err));
111
		return err;
112
	}
113
	period_size = size;
114
	/* write the parameters to device */
115
	err = snd_pcm_hw_params(handle, params);
116
	if (err < 0) {
117
		printf("Unable to set hw params for playback: %s\n", snd_strerror(err));
118
		return err;
119
	}
120
	return 0;
121
}
122
 
123
static int set_swparams(snd_pcm_t *handle, snd_pcm_sw_params_t *swparams)
124
{
125
	int err;
126
 
127
	/* get the current swparams */
128
	err = snd_pcm_sw_params_current(handle, swparams);
129
	if (err < 0) {
130
		printf("Unable to determine current swparams for playback: %s\n", snd_strerror(err));
131
		return err;
132
	}
133
	/* start the transfer when the buffer is almost full: */
134
	/* (buffer_size / avail_min) * avail_min */
135
	err = snd_pcm_sw_params_set_start_threshold(handle, swparams, (buffer_size / period_size) * period_size);
136
	if (err < 0) {
137
		printf("Unable to set start threshold mode for playback: %s\n", snd_strerror(err));
138
		return err;
139
	}
140
	/* allow the transfer when at least period_size samples can be processed */
141
	/* or disable this mechanism when period event is enabled (aka interrupt like style processing) */
142
	err = snd_pcm_sw_params_set_avail_min(handle, swparams, period_event ? buffer_size : period_size);
143
	if (err < 0) {
144
		printf("Unable to set avail min for playback: %s\n", snd_strerror(err));
145
		return err;
146
	}
147
	/* enable period events when requested */
148
	if (period_event) {
149
		err = snd_pcm_sw_params_set_period_event(handle, swparams, 1);
150
		if (err < 0) {
151
			printf("Unable to set period event: %s\n", snd_strerror(err));
152
			return err;
153
		}
154
	}
155
	/* write the parameters to the playback device */
156
	err = snd_pcm_sw_params(handle, swparams);
157
	if (err < 0) {
158
		printf("Unable to set sw params for playback: %s\n", snd_strerror(err));
159
		return err;
160
	}
161
	return 0;
162
}
163
 
164
struct async_private_data {
165
	signed short *samples;
166
	snd_pcm_channel_area_t *areas;
167
	unsigned int period;
168
};
169
 
539 kaklik 170
 
171
////// SIGNAL GENERATION STUFF
526 kaklik 172
/*int linear_chirp(int *pole, int delka_pole){  // vygeneruje linearni chirp a vzorky ulozi do pole
173
 
174
static const float f0 = 0.0001;
175
static const float k = 0.00001;
176
 
177
int t;
178
 
179
//  if((spozdeni+delka) < delka_pole)
180
    for(t=0;t < delka_pole;t++) pole[t] = round ( 10000*sin(2*M_PI*(t+faze)*(f0+(k/2)*(t+faze))) );
181
    faze +=t;
182
//  else return 0;
183
 
527 kaklik 184
}*/
526 kaklik 185
 
532 kaklik 186
// vygeneruje linearni chirp a vzorky ulozi do pole
539 kaklik 187
unsigned int linear_windowed_chirp(unsigned int *pole, unsigned int delka_pole,unsigned int offset)
188
{
527 kaklik 189
unsigned int maxval = (1 << (snd_pcm_format_width(format) - 1)) - 1;
526 kaklik 190
 
539 kaklik 191
static const float f0 = 1000;
543 kaklik 192
static const float fmax = 7000;
536 kaklik 193
static const float Tw = 0.002;
527 kaklik 194
static float k;
526 kaklik 195
 
531 kaklik 196
unsigned int n=0;
197
double t;
198
unsigned int perioda;
526 kaklik 199
 
532 kaklik 200
  k=2*(fmax-f0)/Tw;
201
  perioda = rate*Tw; 
526 kaklik 202
 
532 kaklik 203
  for(n=0;n<=perioda;n++){
204
     t = (double) n/ (double)rate;
540 kaklik 205
     pole[n+offset] = (short) floor( (0.35875 - 0.48829*cos(2*M_PI*t*1/Tw) + 0.14128*cos(2*M_PI*2*t*1/Tw) - 0.01168*cos(2*M_PI*3*t*1/Tw))*maxval*sin(2*M_PI*(t)*(f0+(k/2)*(t))) );
532 kaklik 206
  }
539 kaklik 207
  return (perioda+offset);
527 kaklik 208
}
209
 
532 kaklik 210
// generate sine samples and store
531 kaklik 211
int sine(unsigned int *pole, unsigned int delka_pole)
526 kaklik 212
{
527 kaklik 213
unsigned int maxval = (1 << (snd_pcm_format_width(format) - 1)) - 1;
531 kaklik 214
unsigned int n;
215
double t;
216
 
217
  for(n=0;n < delka_pole;n++){
218
    t = 440.0 * (double) n/ (double)rate;
540 kaklik 219
    pole[n] = (short) floor(maxval*sin(2*M_PI*t));
531 kaklik 220
  }
526 kaklik 221
}
539 kaklik 222
//// generate simple sine ping
223
unsigned int sine_ping(unsigned int *pole, unsigned int delka_pole,unsigned int offset, double frequency)
224
{
225
unsigned int maxval = (1 << (snd_pcm_format_width(format) - 1)) - 1;
226
unsigned int n;
227
double t;
526 kaklik 228
 
539 kaklik 229
  for(n=0;n < delka_pole;n++){
230
    t = frequency * (double) n/ (double)rate;
540 kaklik 231
    pole[n] = (short) floor(maxval*sin(2*M_PI*t));
539 kaklik 232
  }
233
}
526 kaklik 234
 
539 kaklik 235
/////////// CALL BACK STUFF ///////////////////
526 kaklik 236
static void async_playback_callback(snd_async_handler_t *ahandler)
237
{
238
	snd_pcm_t *handle = snd_async_handler_get_pcm(ahandler);
527 kaklik 239
/*	struct async_private_data *data = snd_async_handler_get_callback_private(ahandler);
526 kaklik 240
	signed short *samples = data->samples;
527 kaklik 241
	snd_pcm_channel_area_t *areas = data->areas;*/
526 kaklik 242
	snd_pcm_sframes_t avail;
243
	int err;
244
 
245
	avail = snd_pcm_avail_update(handle);
531 kaklik 246
	while ((avail >= period_size) && ((period*period_size) < chirp_size) ) {
526 kaklik 247
 
527 kaklik 248
		err = snd_pcm_writei(handle, (chirp+period*period_size), period_size);
526 kaklik 249
		if (err < 0) {
250
			printf("Write error: %s\n", snd_strerror(err));
251
			exit(EXIT_FAILURE);
252
		}
253
		if (err != period_size) {
254
			printf("Write error: written %i expected %li\n", err, period_size);
255
			exit(EXIT_FAILURE);
256
		}
257
		avail = snd_pcm_avail_update(handle);
527 kaklik 258
		period++;
526 kaklik 259
	}
260
}
261
 
527 kaklik 262
static void async_capture_callback(snd_async_handler_t *ahandler)
263
{
264
	snd_pcm_t *handle = snd_async_handler_get_pcm(ahandler);
265
/*	struct async_private_data *data = snd_async_handler_get_callback_private(ahandler);
266
	signed short *samples = data->samples;
267
	snd_pcm_channel_area_t *areas = data->areas;*/
268
	snd_pcm_sframes_t avail;
269
	int err;
270
 
271
	avail = snd_pcm_avail_update(handle);
532 kaklik 272
	while ((avail >= period_size) /*&& ((period*period_size) < (CHIRP_SIZE-100))*/ ) {  // segmentation fault checking disabled
527 kaklik 273
 
274
		err = snd_pcm_readi(handle, (signal+cperiod*period_size), period_size);
275
		if (err < 0) {
276
			printf("Read error: %s\n", snd_strerror(err));
277
			exit(EXIT_FAILURE);
278
		}
279
		if (err != period_size) {
280
			printf("Read error: red %i expected %li\n", err, period_size);
281
			exit(EXIT_FAILURE);
282
		}
283
		avail = snd_pcm_avail_update(handle);
284
		cperiod++;
531 kaklik 285
	}
527 kaklik 286
}
287
 
288
 
526 kaklik 289
int main(int argc, char *argv[])
290
{
291
	snd_pcm_t *playback_handle, *capture_handle;
292
	int err;
293
	snd_pcm_hw_params_t *hwparams;
294
	snd_pcm_sw_params_t *swparams;
295
	signed short *frame;  // pointer to array of samples
296
	unsigned int chn;
297
	snd_pcm_channel_area_t *areas;
298
 
299
	struct async_private_data data;
527 kaklik 300
	snd_async_handler_t *chandler, *phandler;
526 kaklik 301
	int count;
532 kaklik 302
	unsigned int i,j,m,n;
536 kaklik 303
	unsigned int delay[10];	//store delay of signifed correlation
541 kaklik 304
  	long int l,r;  // store correlation at strict time
542 kaklik 305
	long int correlationl[SIGNAL_SAMPLES]; //array to store correlation curve
306
	long int correlationr[SIGNAL_SAMPLES]; //array to store correlation curve
307
	int L_signal[SIGNAL_SAMPLES];
308
	int R_signal[SIGNAL_SAMPLES];
526 kaklik 309
 
527 kaklik 310
	FILE *out;
526 kaklik 311
 
312
	snd_pcm_hw_params_alloca(&hwparams);
313
	snd_pcm_sw_params_alloca(&swparams);
314
 
540 kaklik 315
	printf("Simple PC sonar ver. 000000001 starting work.. \n");
537 kaklik 316
 
532 kaklik 317
//open and set playback device
526 kaklik 318
	if ((err = snd_pcm_open(&playback_handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
319
		printf("Playback open error: %s\n", snd_strerror(err));
320
		return 0;
321
	}
322
 
540 kaklik 323
	if ((err = set_hwparams(playback_handle, hwparams, 1)) < 0) {
526 kaklik 324
		printf("Setting of hwparams failed: %s\n", snd_strerror(err));
325
		exit(EXIT_FAILURE);
326
	}
327
	if ((err = set_swparams(playback_handle, swparams)) < 0) {
328
		printf("Setting of swparams failed: %s\n", snd_strerror(err));
329
		exit(EXIT_FAILURE);
330
	}
331
 
332
//open and set capture device
333
	if ((err = snd_pcm_open(&capture_handle, device, SND_PCM_STREAM_CAPTURE, 0)) < 0) {
334
		printf("Playback open error: %s\n", snd_strerror(err));
335
		return 0;
336
	}
337
 
540 kaklik 338
	if ((err = set_hwparams(capture_handle, hwparams, 2)) < 0) {
526 kaklik 339
		printf("Setting of hwparams failed: %s\n", snd_strerror(err));
340
		exit(EXIT_FAILURE);
341
	}
530 kaklik 342
	if ((err = set_swparams(capture_handle, swparams)) < 0) {
526 kaklik 343
		printf("Setting of swparams failed: %s\n", snd_strerror(err));
344
		exit(EXIT_FAILURE);
530 kaklik 345
	}
526 kaklik 346
 
539 kaklik 347
/// generate ping pattern
526 kaklik 348
 
541 kaklik 349
        chirp_size=linear_windowed_chirp(chirp,1000000, CHIRP_OFFSET);
539 kaklik 350
 
527 kaklik 351
/// register playback callback 
352
	err = snd_async_add_pcm_handler(&phandler, playback_handle, async_playback_callback, &data); // fill by dummy &data
526 kaklik 353
	if (err < 0) {
354
		printf("Unable to register async handler\n");
355
		exit(EXIT_FAILURE);
356
	}
531 kaklik 357
	for (period = 0; period < 2; period++) {
526 kaklik 358
 
527 kaklik 359
		err = snd_pcm_writei(playback_handle, (chirp+period*period_size), period_size);
526 kaklik 360
		if (err < 0) {
361
			printf("Initial write error: %s\n", snd_strerror(err));
362
			exit(EXIT_FAILURE);
363
		}
364
		if (err != period_size) {
365
			printf("Initial write error: written %i expected %li\n", err, period_size);
366
			exit(EXIT_FAILURE);
367
		}
368
	}
369
 
527 kaklik 370
// register capture callback 
371
	err = snd_async_add_pcm_handler(&chandler, capture_handle, async_capture_callback, &data); // fill by dummy &data
372
	if (err < 0) {
373
		printf("Unable to register async handler\n");
374
		exit(EXIT_FAILURE);
375
	}
376
 
526 kaklik 377
 
527 kaklik 378
//start capture
379
	if ((err = snd_pcm_prepare (capture_handle)) < 0) {
380
		fprintf (stderr, "cannot prepare audio interface for use (%s)\n",
381
			 snd_strerror (err));
382
		exit (1);
383
	}
384
 
385
	err = snd_pcm_start(capture_handle);
386
	if (err < 0) {
387
			printf("Start error: %s\n", snd_strerror(err));
388
			exit(EXIT_FAILURE);
389
	}
538 kaklik 390
 
391
 
392
//start playback
393
	if (snd_pcm_state(playback_handle) == SND_PCM_STATE_PREPARED) {
394
		err = snd_pcm_start(playback_handle);
395
		if (err < 0) {
396
			printf("Start error: %s\n", snd_strerror(err));
397
			exit(EXIT_FAILURE);
398
		}
399
	}
400
 
527 kaklik 401
 
532 kaklik 402
//wait until all samples aren't transmitted
403
	printf("Waiting for transmitt all samples\n");
531 kaklik 404
	while(cperiod<10) {
526 kaklik 405
		sleep(1);
532 kaklik 406
		printf(".");
527 kaklik 407
	}	
542 kaklik 408
//// 
409
	j=0;
410
	for(i=0;i < SIGNAL_SAMPLES;i++){
411
	  L_signal[i]=signal[j];
412
	  R_signal[i]=signal[j+1];
413
	  j+=2;
414
	}
415
 
543 kaklik 416
//        linear_windowed_chirp(L_signal,1000000, 1000);
417
 
537 kaklik 418
	printf("\nData transmitted... \ncorrelating...\n");
542 kaklik 419
	for(n=0; n < (SIGNAL_SAMPLES - chirp_size);n++){
540 kaklik 420
	  l=0;
421
          r=0;
543 kaklik 422
	  for(m=CHIRP_OFFSET;m < chirp_size;m++)
540 kaklik 423
          {
542 kaklik 424
            l += chirp[m]*L_signal[m+n];	// correlate with left channel
425
            r += chirp[m]*R_signal[m+n];	// correlate with right channel
540 kaklik 426
          }
427
	  correlationl[n]=l;
428
	  correlationr[n]=r;
533 kaklik 429
	}
532 kaklik 430
 
543 kaklik 431
	printf("\nSearching echos...\n");
533 kaklik 432
	r=0;
540 kaklik 433
	l=0;
536 kaklik 434
	for(n=0; n < (SIGNAL_SAMPLES - chirp_size);n++){			//najde nejvetsi korelace
540 kaklik 435
	  if (l < correlationl[n]){
536 kaklik 436
	  delay[1] = n;
540 kaklik 437
	  l = correlationl[n];
533 kaklik 438
	  }
540 kaklik 439
	  if (r < correlationr[n]){
541 kaklik 440
	  delay[2] = n;
540 kaklik 441
	  r = correlationr[n];
442
	  }
543 kaklik 443
	}
532 kaklik 444
 
542 kaklik 445
  out=fopen("./output.txt","w");
540 kaklik 446
  j=0;
543 kaklik 447
  for(i=0;i<=100000;i++){
542 kaklik 448
    fprintf(out,"%6d %6d %6d %6d %9ld %9ld\n",i,chirp[i],L_signal[i],R_signal[i],correlationl[i], correlationr[i]);
540 kaklik 449
    j+=2;
450
  }
542 kaklik 451
  fclose(out);
532 kaklik 452
 
536 kaklik 453
	printf("\nEcho zacina na: %d vzorku.\n", delay[1]);
454
	printf("Casove na: %f s\n", ((float)delay[1]/rate));
455
	printf("vzdalenost: %f m\n", (SOUND_SPEED*(float)delay[1]/rate));
456
 
526 kaklik 457
	snd_pcm_close(playback_handle);
540 kaklik 458
	snd_pcm_close(capture_handle); 
526 kaklik 459
	return 0;
460
}
461