Subversion Repositories svnkaklik

Rev

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