Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1085 | pj | 1 | /* Project: HARTIK 3.0 */ |
2 | /* Description: Hard Real TIme Kernel for 386 & higher machines */ |
||
3 | /* Author: Paolo Gai <pgai@rsk.it> */ |
||
4 | /* Advanced Linux Sound Architecture (ALSA) */ |
||
5 | /* Copyright (c) by Jaroslav Kysela <perex@jcu.cz> */ |
||
6 | /* Luca Abeni */ |
||
7 | /* FFTW by M. Frigo and S. G. Johnson */ |
||
8 | |||
9 | /* Date: 08/09/1999 */ |
||
10 | |||
11 | /* File: fftplay.c */ |
||
12 | /* Revision: 1.00 (Kernel 0.1.4; Library 0.0.9; Util 0.0.4) */ |
||
13 | |||
14 | |||
15 | /* |
||
16 | |||
17 | FFTPlay 1.0 |
||
18 | ----------- |
||
19 | |||
20 | This application reads data from the audio microphone and then put it |
||
21 | to the screen in a graphical oscilloscope-like form (both standard Hartik |
||
22 | SB driver and Alsa driver can be used). |
||
23 | |||
24 | The application also calculate a FFT on the latest values, and displays |
||
25 | the power spectrum in tho ways, one like an equalizator, and the other in a |
||
26 | 2D form. |
||
27 | |||
28 | A resolution of 1024x768, 64K colors is used. |
||
29 | |||
30 | The task set is composed by these tasks and functions: |
||
31 | |||
32 | Self buffering functions (SB only) |
||
33 | ---------------------------------- |
||
34 | this function takes the samples read by the mic and then makes a window |
||
35 | with the last WINDATA_NSAMPLES samples. The window is then put in |
||
36 | the CAB windata. |
||
37 | |||
38 | Task raw and task mixer (ALSA only) |
||
39 | ----------------------------------- |
||
40 | These tasks are used with the Alsa driver; because it doesn't support the |
||
41 | self-buffering mode, we have to do a forever cycle in witch we have to read |
||
42 | all the data. Then the data are managed like the self-buffering functions of |
||
43 | the SB driver or sent to the mixer task (with a STREAM mailbox) which makes |
||
44 | the window. |
||
45 | (This approach is not good for realtime...) |
||
46 | |||
47 | Task wave |
||
48 | --------- |
||
49 | This task read the last window and then put it on the screen in a wave form |
||
50 | on the top of the screen. |
||
51 | The task's period is set to 40 ms (25 fps). |
||
52 | |||
53 | Task fft |
||
54 | -------- |
||
55 | This task read the last window and then it computes the FFT. |
||
56 | With the FFT data it computes the power spectrum, whitch is sent to the |
||
57 | CAB pwrdata. |
||
58 | The task's period is set to 10 ms (good for the 2D story task). |
||
59 | This task is the only Hard Task. |
||
60 | |||
61 | Task equ |
||
62 | -------- |
||
63 | This task read the last power spectrum and displays it in a graphical |
||
64 | form, like a hi-fi equalizator. |
||
65 | The Histograms can be white or coloured like the equ2D task (see EQU_SHADE) |
||
66 | The task's period is set to 40 ms (25 fps). |
||
67 | |||
68 | Task equ2D |
||
69 | ---------- |
||
70 | This task read the lasf power spectrum and displays it in a graphical |
||
71 | one-line form. Each pixel is a power coefficient, and its colour shade |
||
72 | from black (no power) to red (high power) passing through green and blue. |
||
73 | The task display the last EQU2D_WIDTH power lines. |
||
74 | The task's period is set to 10 ms (good for the 2D story task). |
||
75 | |||
76 | **************************************************************************** |
||
77 | TASK LOAD |
||
78 | **************************************************************************** |
||
79 | |||
80 | period wcet |
||
81 | task tick (ms) us % |
||
82 | -------------------------------------------------------- |
||
83 | sound driver 24->3 12->1.5 200 0.016->0.133 |
||
84 | wave 80 40 11500 0.2875 |
||
85 | fft 20 10 3000 0.3000 |
||
86 | equ 80 40 7000 0.1750 |
||
87 | equ2D 20 10 500 0.0500 |
||
88 | ------------- |
||
89 | 0.812 (last 4) |
||
90 | */ |
||
91 | |||
92 | #include <ll/ll.h> |
||
93 | |||
94 | #include <kernel/types.h> |
||
95 | #include <kernel/model.h> |
||
96 | #include <kernel/func.h> |
||
97 | |||
98 | #include <modules/cabs.h> |
||
99 | |||
100 | #include <string.h> |
||
101 | #include <stdlib.h> |
||
102 | #include <semaphore.h> |
||
103 | |||
104 | #include <drivers/keyb.h> |
||
105 | #include <drivers/crtwin.h> |
||
106 | #include <drivers/glib.h> |
||
107 | #include <drivers/sound.h> |
||
108 | #include <ports/rfftw.h> |
||
109 | |||
110 | /* now the load constants... */ |
||
111 | |||
112 | #define WCET_WAVE 11500 |
||
113 | #define WCET_FFT 3000 |
||
114 | #define WCET_EQU 500 |
||
115 | #define WCET_EQU2D 500 |
||
116 | |||
117 | #define PERIOD_WAVE 40000 |
||
118 | #define PERIOD_FFT 10000 |
||
119 | #define PERIOD_EQU 40000 |
||
120 | #define PERIOD_EQU2D 10000 |
||
121 | |||
122 | /* define if shorts critical sections wanted */ |
||
123 | #define SHORT_CRITICAL_SECTIONS(x) \ |
||
124 | if (!((x)%64)) \ |
||
125 | { \ |
||
126 | sem_post(&mutex); \ |
||
127 | sem_wait(&mutex); \ |
||
128 | } |
||
129 | |||
130 | /* define if you want NRT or SOFT... */ |
||
131 | #define TASK_TYPE SOFT |
||
132 | //#define TASK_TYPE NRT |
||
133 | |||
134 | |||
135 | |||
136 | /* Only 4 Debug... */ |
||
137 | /*#define NO_GRX */ |
||
138 | |||
139 | /* Samples are 16-bit signed integers */ |
||
140 | typedef short SAMPLE; |
||
141 | #define MAX_SAMPLE 32768 |
||
142 | |||
143 | /* Informations about the sampling rate and buffers */ |
||
144 | WORD rawdata_nsamples; |
||
145 | WORD rawdata_buffer_size; |
||
146 | WORD rawdata_freq; |
||
147 | |||
148 | /* Numbers of samples of the sample window */ |
||
149 | #define WINDATA_NSAMPLES 1024 |
||
150 | |||
151 | /* task WAVE */ |
||
152 | /* the point (wave_x,wave_y) is on the center left of the area... */ |
||
153 | #define WAVE_NSAMPLES 1024 |
||
154 | #define WAVE_X 0 |
||
155 | #define WAVE_Y 130 |
||
156 | #define WAVE_HEIGHT 80 |
||
157 | |||
158 | /* task FFT */ |
||
159 | #define FFT_NSAMPLES WINDATA_NSAMPLES |
||
160 | #define PWR_NSAMPLES (FFT_NSAMPLES/2+1) |
||
161 | |||
162 | /* task EQU */ |
||
163 | /* the point (equ_x, equ_y) is the top right corner */ |
||
164 | #define EQU_NSAMPLES PWR_NSAMPLES |
||
165 | #define EQU_X 170 |
||
166 | #define EQU_Y 255 |
||
167 | #define EQU_HEIGHT 170 |
||
168 | #define EQU_SHADE |
||
169 | |||
170 | /* task EQU2D */ |
||
171 | /* the point (equ2d_x, equ2d_y) is the top left corner */ |
||
172 | #define EQU2D_NSAMPLES EQU_NSAMPLES |
||
173 | #define EQU2D_X 255 |
||
174 | #define EQU2D_Y EQU_Y |
||
175 | #define EQU2D_WIDTH 768 |
||
176 | #define EQU2D_CLIP 255 |
||
177 | |||
178 | /* scenario */ |
||
179 | #define SCENARIO_NLABEL 16 |
||
180 | |||
181 | /* Scale factors */ |
||
182 | #define FFT_SCALE (16384.0) |
||
183 | #define EQU_SCALE (32.0) |
||
184 | #define EQU2D_SCALE (8.0) |
||
185 | //#define EQU_SCALE (64.0) |
||
186 | //#define EQU2D_SCALE (16.0) |
||
187 | |||
188 | |||
189 | /* CAB ports... */ |
||
190 | CAB cab_windata; /* a window on the last WINDATA_DIM samples */ |
||
191 | CAB cab_pwrdata; /* the last power spectrum */ |
||
192 | |||
193 | /* for the cab_windata */ |
||
194 | typedef struct { |
||
195 | int start; |
||
196 | SAMPLE sample[WINDATA_NSAMPLES]; |
||
197 | } window; |
||
198 | |||
199 | /* for the cab_pwrdata */ |
||
200 | typedef struct { |
||
201 | fftw_real p[PWR_NSAMPLES]; |
||
202 | } power; |
||
203 | |||
204 | /* graphic mutex... */ |
||
205 | sem_t mutex; |
||
206 | |||
207 | // win is global... because is used by raw_infun... |
||
208 | window win; |
||
209 | |||
210 | |||
211 | |||
212 | /* useful colors... */ |
||
213 | int white; |
||
214 | int black; |
||
215 | int red; |
||
216 | |||
217 | static void version( void ) |
||
218 | { |
||
219 | cprintf( "Hartik FFT Play 1.0\n" ); |
||
220 | cprintf( "-----------------------\n" ); |
||
221 | cprintf( "by Paolo Gai 1999\n" ); |
||
222 | cprintf( " <pj@hartik.sssup.it>\n" ); |
||
223 | cprintf( "-----------------------\n" ); |
||
224 | } |
||
225 | |||
226 | void reverse(char s[]) |
||
227 | { |
||
228 | int c, i, j; |
||
229 | |||
230 | for (i = 0, j = strlen(s)-1; i<j; i++, j--) |
||
231 | { |
||
232 | c = s[i]; |
||
233 | s[i] = s[j]; |
||
234 | s[j] = c; |
||
235 | } |
||
236 | } |
||
237 | |||
238 | char * itoa(int n, char *s) |
||
239 | { |
||
240 | int i, sign; |
||
241 | |||
242 | if ((sign = n) < 0) |
||
243 | n = -n; |
||
244 | |||
245 | i = 0; |
||
246 | |||
247 | do |
||
248 | { |
||
249 | s[i++] = n % 10 + '0'; |
||
250 | } while ((n /= 10) > 0); |
||
251 | |||
252 | if (sign < 0) |
||
253 | s[i++] = '-'; |
||
254 | |||
255 | s[i] = 0; |
||
256 | |||
257 | reverse(s); |
||
258 | |||
259 | return s; |
||
260 | } |
||
261 | |||
262 | |||
263 | |||
264 | /* |
||
265 | This is the self-buffering function: read the samples and put their mean |
||
266 | value in a CAB |
||
267 | */ |
||
268 | int raw_infun(void *b) |
||
269 | { |
||
270 | int i; |
||
271 | char *w; |
||
272 | SAMPLE *audiobuf = (SAMPLE *)b; |
||
273 | |||
274 | for (i=0; i<rawdata_nsamples/2; i++) { |
||
275 | win.sample[win.start] = audiobuf[i]; |
||
276 | win.start = (win.start+1) % WINDATA_NSAMPLES; |
||
277 | } |
||
278 | |||
279 | w = cab_reserve(cab_windata); |
||
280 | memcpy(w, &win, sizeof(window)); |
||
281 | cab_putmes(cab_windata,w); |
||
282 | |||
283 | #if defined(NO_GRX) |
||
284 | cprintf("X"); //"XXX%d\n",win.sample[win.start]); |
||
285 | #endif |
||
286 | return 0; |
||
287 | } |
||
288 | |||
289 | |||
290 | |||
291 | void init_rawdata() |
||
292 | { |
||
293 | int i; |
||
294 | char *w; |
||
295 | |||
296 | win.start = 0; |
||
297 | for (i=0; i<WINDATA_NSAMPLES; i++) |
||
298 | win.sample[i] = 0; |
||
299 | |||
300 | w = cab_reserve(cab_windata); |
||
301 | memcpy(w, &win, sizeof(window)); |
||
302 | cab_putmes(cab_windata,w); |
||
303 | } |
||
304 | |||
305 | |||
306 | |||
307 | |||
308 | |||
309 | TASK wave_task() |
||
310 | { |
||
311 | window *p; |
||
312 | int x,y; |
||
313 | int s; |
||
314 | |||
315 | while(1) |
||
316 | { |
||
317 | p = (window *)cab_getmes(cab_windata); |
||
318 | |||
319 | /* let's print the wave */ |
||
320 | sem_wait(&mutex); |
||
321 | for(x = WAVE_X, s = p->start; |
||
322 | x < WAVE_X+WAVE_NSAMPLES; |
||
323 | x++, s = (s+1)%WINDATA_NSAMPLES ) |
||
324 | { |
||
325 | y = WAVE_Y + (WAVE_HEIGHT * p->sample[s]) / MAX_SAMPLE; |
||
326 | SHORT_CRITICAL_SECTIONS(x); |
||
327 | grx_plot(x,y,white); |
||
328 | } |
||
329 | sem_post(&mutex); |
||
330 | |||
331 | task_endcycle(); |
||
332 | |||
333 | /* let's erase the wave */ |
||
334 | sem_wait(&mutex); |
||
335 | for(x = WAVE_X, s = p->start; |
||
336 | x < WAVE_X+WAVE_NSAMPLES; |
||
337 | x++, s = (s+1)%WINDATA_NSAMPLES ) |
||
338 | { |
||
339 | y = WAVE_Y + (WAVE_HEIGHT * p->sample[s]) / MAX_SAMPLE; |
||
340 | SHORT_CRITICAL_SECTIONS(x); |
||
341 | grx_plot(x,y,black); |
||
342 | } |
||
343 | sem_post(&mutex); |
||
344 | |||
345 | cab_unget(cab_windata,(char *)p); |
||
346 | |||
347 | } |
||
348 | } |
||
349 | |||
350 | |||
351 | rfftw_plan plan; |
||
352 | |||
353 | void fft_close(void *arg) |
||
354 | { |
||
355 | rfftw_destroy_plan(plan); |
||
356 | } |
||
357 | |||
358 | |||
359 | TASK fft_task() |
||
360 | { |
||
361 | fftw_real in[FFT_NSAMPLES], out[FFT_NSAMPLES]; |
||
362 | power power_spectrum; |
||
363 | |||
364 | #if defined(NO_GRX) |
||
365 | fftw_real max = 0.0; |
||
366 | #endif |
||
367 | |||
368 | char *m; |
||
369 | |||
370 | int k, i; |
||
371 | |||
372 | window *p; |
||
373 | |||
374 | plan = rfftw_create_plan(FFT_NSAMPLES, FFTW_REAL_TO_COMPLEX, FFTW_ESTIMATE); |
||
375 | |||
376 | sys_atrunlevel(fft_close, NULL, RUNLEVEL_BEFORE_EXIT); |
||
377 | |||
378 | while(1) |
||
379 | { |
||
380 | /* Let's prepare the intput FFT data */ |
||
381 | p = (window *)cab_getmes(cab_windata); |
||
382 | |||
383 | for (k = 0, i = p->start; |
||
384 | k < FFT_NSAMPLES; |
||
385 | k++, i = (i+1)%WINDATA_NSAMPLES) |
||
386 | in[k] = p->sample[i]/FFT_SCALE; |
||
387 | |||
388 | cab_unget(cab_windata,(char *)p); |
||
389 | |||
390 | /* zero-padding if needed */ |
||
391 | for (k=WINDATA_NSAMPLES; k < FFT_NSAMPLES; k++) |
||
392 | in[k] = 0.0; |
||
393 | |||
394 | rfftw_one(plan, in, out); |
||
395 | |||
396 | /* power spectrum computation */ |
||
397 | power_spectrum.p[0] = out[0]*out[0]; /* DC component */ |
||
398 | for (k = 1; k < PWR_NSAMPLES; ++k) /* (k < N/2 rounded up) */ |
||
399 | power_spectrum.p[k] = out[k]*out[k] + out[FFT_NSAMPLES-k]*out[FFT_NSAMPLES-k]; |
||
400 | if (FFT_NSAMPLES % 2 == 0) /* N is even */ |
||
401 | power_spectrum.p[FFT_NSAMPLES/2] = out[FFT_NSAMPLES/2]*out[FFT_NSAMPLES/2]; /* Nyquist freq. */ |
||
402 | |||
403 | m = cab_reserve(cab_pwrdata); |
||
404 | memcpy(m, &power_spectrum, sizeof(power)); |
||
405 | cab_putmes(cab_pwrdata,m); |
||
406 | |||
407 | #if defined(NO_GRX) |
||
408 | max = 0.0; |
||
409 | for (k=0; k<PWR_NSAMPLES; k++) |
||
410 | if (power_spectrum.p[k] > max) |
||
411 | max = power_spectrum.p[k]; |
||
412 | |||
413 | //cprintf("%f %f\n",max,(max / EQU_SCALE) ); |
||
414 | #endif |
||
415 | |||
416 | task_endcycle(); |
||
417 | |||
418 | } |
||
419 | } |
||
420 | |||
421 | /* structure is like the wave task... */ |
||
422 | TASK equ_task() |
||
423 | { |
||
424 | power *p; |
||
425 | |||
426 | int x[PWR_NSAMPLES]; |
||
427 | int y; |
||
428 | int s; |
||
429 | |||
430 | int r,g,b; |
||
431 | |||
432 | while(1) |
||
433 | { |
||
434 | p = (power *)cab_getmes(cab_pwrdata); |
||
435 | |||
436 | /* print the lines */ |
||
437 | sem_wait(&mutex); |
||
438 | for(y = EQU_Y, s = 0; |
||
439 | s < EQU_NSAMPLES; |
||
440 | y++, s++ ) |
||
441 | { |
||
442 | x[s] = (int)(p->p[s] / EQU_SCALE); |
||
443 | |||
444 | if (x[s] > EQU_HEIGHT) |
||
445 | x[s] = EQU_HEIGHT; |
||
446 | |||
447 | x[s] = EQU_X - x[s]; |
||
448 | |||
449 | |||
450 | #if defined(EQU_SHADE) |
||
451 | |||
452 | /* like the task equ2d... */ |
||
453 | r = (int)(p->p[s] / EQU2D_SCALE); |
||
454 | if (r > EQU2D_CLIP) |
||
455 | r = EQU2D_CLIP; |
||
456 | |||
457 | if (r< 64) g = r * 4; |
||
458 | else if (r<128) g = (128-r) * 4; |
||
459 | else g = 0; |
||
460 | |||
461 | if (r<128) b = 0; |
||
462 | else if (r<192) b = (r-128) * 4; |
||
463 | else b = (256-r) * 4; |
||
464 | |||
465 | SHORT_CRITICAL_SECTIONS(y); |
||
466 | grx_line(EQU_X,y,x[s],y,rgb16(r,g,b)); |
||
467 | #else |
||
468 | SHORT_CRITICAL_SECTIONS(y); |
||
469 | grx_line(EQU_X,y,x[s],y,white); |
||
470 | #endif |
||
471 | } |
||
472 | sem_post(&mutex); |
||
473 | |||
474 | task_endcycle(); |
||
475 | |||
476 | /* erase the lines... */ |
||
477 | sem_wait(&mutex); |
||
478 | for(y = EQU_Y, s = 0; |
||
479 | s < EQU_NSAMPLES; |
||
480 | y++, s++ ) |
||
481 | { |
||
482 | SHORT_CRITICAL_SECTIONS(y); |
||
483 | grx_line(EQU_X,y,x[s],y,black); |
||
484 | } |
||
485 | sem_post(&mutex); |
||
486 | |||
487 | cab_unget(cab_pwrdata,(char *)p); |
||
488 | |||
489 | } |
||
490 | } |
||
491 | |||
492 | TASK equ2d_task() |
||
493 | { |
||
494 | power *p; |
||
495 | |||
496 | int pwrint; |
||
497 | |||
498 | int x = 0; |
||
499 | |||
500 | int y,s; |
||
501 | |||
502 | int r,g,b; |
||
503 | |||
504 | while(1) |
||
505 | { |
||
506 | |||
507 | p = (power *)cab_getmes(cab_pwrdata); |
||
508 | |||
509 | /* print the line */ |
||
510 | sem_wait(&mutex); |
||
511 | |||
512 | for(y = EQU2D_Y, s = 0; |
||
513 | s < EQU2D_NSAMPLES; |
||
514 | y++, s++ ) |
||
515 | { |
||
516 | pwrint = (int)(p->p[s] / EQU2D_SCALE); |
||
517 | |||
518 | if (pwrint > EQU2D_CLIP) |
||
519 | pwrint = EQU2D_CLIP; |
||
520 | |||
521 | r = pwrint; |
||
522 | |||
523 | if (pwrint< 64) g = pwrint * 4; |
||
524 | else if (pwrint<128) g = (128-pwrint) * 4; |
||
525 | else g = 0; |
||
526 | |||
527 | if (pwrint<128) b = 0; |
||
528 | else if (pwrint<192) b = (pwrint-128) * 4; |
||
529 | else b = (256-pwrint) * 4; |
||
530 | |||
531 | SHORT_CRITICAL_SECTIONS(y); |
||
532 | grx_plot(EQU2D_X+x,y,rgb16(r,g,b)); |
||
533 | } |
||
534 | |||
535 | x = (x+1) % EQU2D_WIDTH; |
||
536 | grx_line(EQU2D_X+x,EQU2D_Y,EQU2D_X+x,EQU2D_Y+EQU2D_NSAMPLES,white); |
||
537 | |||
538 | sem_post(&mutex); |
||
539 | |||
540 | cab_unget(cab_pwrdata,(char *)p); |
||
541 | |||
542 | task_endcycle(); |
||
543 | } |
||
544 | } |
||
545 | |||
546 | TASK prova_task() |
||
547 | { |
||
548 | window *p; |
||
549 | |||
550 | while(1) |
||
551 | { |
||
552 | p = (window *)cab_getmes(cab_windata); |
||
553 | cprintf("%d %d %d\t", p->start /*sample[0]*/,p->sample[1],p->sample[2]); |
||
554 | cab_unget(cab_windata,(char *)p); |
||
555 | |||
556 | task_endcycle(); |
||
557 | } |
||
558 | } |
||
559 | |||
560 | |||
561 | void scenario(int f) |
||
562 | { |
||
563 | int i,y; |
||
564 | char s[6]; |
||
565 | |||
566 | grx_line(0,WAVE_Y-WAVE_HEIGHT-1,1023,WAVE_Y-WAVE_HEIGHT-1,red); |
||
567 | grx_line(0,WAVE_Y+WAVE_HEIGHT+1,1023,WAVE_Y+WAVE_HEIGHT+1,red); |
||
568 | grx_line(0,EQU_Y-11 ,1023,EQU_Y-11 ,red); |
||
569 | |||
570 | |||
571 | |||
572 | /* lines near the frequencies */ |
||
573 | grx_line(EQU_X +1,EQU_Y,EQU_X +1,EQU_Y+EQU_NSAMPLES,red); |
||
574 | grx_line(EQU2D_X-1,EQU_Y,EQU2D_X-1,EQU_Y+EQU_NSAMPLES,red); |
||
575 | |||
576 | for (i=0; i<SCENARIO_NLABEL; i++) |
||
577 | { |
||
578 | y = (i*EQU_NSAMPLES)/(SCENARIO_NLABEL-1); |
||
579 | if (i == SCENARIO_NLABEL-1) y--; |
||
580 | grx_line(EQU_X +1,EQU_Y+y,EQU_X +10,EQU_Y+y,red); |
||
581 | grx_line(EQU2D_X-1,EQU_Y+y,EQU2D_X-10,EQU_Y+y,red); |
||
582 | |||
583 | itoa((i*f)/(SCENARIO_NLABEL-1),s); |
||
584 | grx_text(s,EQU_X+20,EQU_Y+y-8,white,black); |
||
585 | } |
||
586 | |||
587 | grx_text("FFTPlay 1.0 - by Paolo Gai 1999 <pj@hartik.sssup.it>", 0,8, rgb16(0,255,0), black ); |
||
588 | grx_text("...press ENTER key to exit..." , 0,24, rgb16(0,255,0), black ); |
||
589 | |||
590 | grx_text("FFT Power Spectrum", 0 , EQU_Y-21, rgb16(0,0,255), black); |
||
591 | grx_text("FFT Power Story", EQU2D_X+16, EQU_Y-21, rgb16(0,0,255), black); |
||
592 | grx_text("Waveform" , 0, WAVE_Y-WAVE_HEIGHT-10, rgb16(0,0,255), black); |
||
593 | |||
594 | } |
||
595 | |||
596 | |||
597 | |||
598 | |||
599 | void compute_params(int *freq,WORD *nsamp, WORD *per) |
||
600 | { |
||
601 | if (*freq< 2000) |
||
602 | { |
||
603 | cprintf("WARNING: frequency less than 2000Hz\n ---> frequency set to 2000Hz\n"); |
||
604 | *freq = 2000; |
||
605 | } |
||
606 | if (*freq<= 8000) { *nsamp = 128; *per = 10; return; } |
||
607 | if (*freq<=16000) { *nsamp = 256; *per = 10; return; } |
||
608 | if (*freq<=24000) { *nsamp = 512; *per = 10; return; } |
||
609 | if (*freq>48000) |
||
610 | { |
||
611 | cprintf("WARNING: frequency greather than 48000Hz\n ---> frequency set to 48000Hz\n"); |
||
612 | *freq = 48000; |
||
613 | } |
||
614 | if (*freq<=48000) { *nsamp = 1024;*per = 10; return; } |
||
615 | } |
||
616 | |||
617 | |||
618 | |||
619 | void my_close(void *arg) |
||
620 | { |
||
621 | grx_close(); |
||
622 | sys_status(3); |
||
623 | } |
||
624 | |||
625 | |||
626 | void endfun(KEY_EVT *k) |
||
627 | { |
||
628 | cprintf("Ctrl-Brk pressed! Ending...\n"); |
||
629 | sys_end(); |
||
630 | } |
||
631 | |||
632 | int main(int argc, char **argv) |
||
633 | { |
||
634 | int modenum; |
||
635 | |||
636 | int f; |
||
637 | |||
638 | /* irq period... */ |
||
639 | WORD period; |
||
640 | |||
641 | KEY_EVT k; |
||
642 | |||
643 | SOFT_TASK_MODEL m3, m4, m5, m6; |
||
644 | |||
645 | PID p3,p4,p5,p6; |
||
646 | |||
647 | version(); |
||
648 | |||
649 | if (argc == 1) |
||
650 | { |
||
651 | cprintf("type x fftplay <freq>"); |
||
652 | return 0; |
||
653 | } |
||
654 | |||
655 | f = atoi(argv[1]); |
||
656 | compute_params(&f,&rawdata_nsamples,&period); |
||
657 | |||
658 | keyb_set_map(itaMap); |
||
659 | k.flag = CNTR_BIT; |
||
660 | k.scan = KEY_C; |
||
661 | k.ascii = 'c'; |
||
662 | keyb_hook(k,endfun); |
||
663 | k.flag = CNTL_BIT; |
||
664 | k.scan = KEY_C; |
||
665 | k.ascii = 'c'; |
||
666 | keyb_hook(k,endfun); |
||
667 | |||
668 | cab_windata = cab_create("windata", sizeof(window), 4); |
||
669 | cab_pwrdata = cab_create("pwr", sizeof(power), 4); |
||
670 | |||
671 | /* Init the sound lib */ |
||
672 | sound_init((rawdata_nsamples * sizeof(SAMPLE)), NULL); |
||
673 | sound_info(); |
||
674 | |||
675 | /* Init the data used by the raw_infun */ |
||
676 | init_rawdata(); |
||
677 | |||
678 | /* Start the self-buffering sampling operation */ |
||
679 | sound_setfun(raw_infun, (int (*)(void *))-1); |
||
680 | sound_sample(NULL, f, 0, DMA_OP | PCM16 | MYFUN, NULL); |
||
681 | |||
682 | cprintf("Press Enter..."); |
||
683 | while (keyb_getchar() != 13); |
||
684 | |||
685 | sys_atrunlevel(my_close, NULL, RUNLEVEL_BEFORE_EXIT); |
||
686 | |||
687 | #if !defined(NO_GRX) |
||
688 | grx_init(); |
||
689 | modenum = grx_getmode(1024, 768, 16); |
||
690 | grx_setmode(modenum); |
||
691 | |||
692 | /* init the graphic mutex */ |
||
693 | sem_init(&mutex, 0, 1); |
||
694 | |||
695 | /* useful colors ... */ |
||
696 | white = rgb16(255,255,255); |
||
697 | black = rgb16(0,0,0); |
||
698 | red = rgb16(255,0,0); |
||
699 | |||
700 | scenario(f/2); |
||
701 | |||
702 | #endif |
||
703 | |||
704 | #if !defined(NO_GRX) |
||
705 | soft_task_default_model(m3); |
||
706 | soft_task_def_period(m3, PERIOD_WAVE); |
||
707 | soft_task_def_met(m3, WCET_WAVE); |
||
708 | soft_task_def_group(m3, 1); |
||
709 | p3 = task_create("wave", wave_task, &m3, NULL); |
||
710 | if (p3 == -1) { |
||
711 | perror("FFTPlay: Could not create task <wave>\n"); |
||
712 | sys_end(); |
||
713 | } |
||
714 | #endif |
||
715 | |||
716 | soft_task_default_model(m4); |
||
717 | soft_task_def_period(m4, PERIOD_FFT); |
||
718 | soft_task_def_met(m4, WCET_FFT); |
||
719 | soft_task_def_group(m4, 1); |
||
720 | soft_task_def_stack(m4,32*1024); |
||
721 | soft_task_def_usemath(m4); |
||
722 | p4 = task_create("fft", fft_task, &m4, NULL); |
||
723 | if (p4 == -1) { |
||
724 | perror("FFTPlay: Could not create task <fft>\n"); |
||
725 | sys_end(); |
||
726 | } |
||
727 | |||
728 | #if !defined(NO_GRX) |
||
729 | soft_task_default_model(m5); |
||
730 | soft_task_def_period(m5, PERIOD_EQU); |
||
731 | soft_task_def_met(m5, WCET_EQU); |
||
732 | soft_task_def_group(m5, 1); |
||
733 | soft_task_def_stack(m5,32*1024); |
||
734 | soft_task_def_usemath(m5); |
||
735 | p5 = task_create("equ", equ_task, &m5, NULL); |
||
736 | if (p5 == -1) { |
||
737 | perror("FFTPlay: Could not create task <equ>\n"); |
||
738 | sys_end(); |
||
739 | } |
||
740 | #endif |
||
741 | |||
742 | #if !defined(NO_GRX) |
||
743 | soft_task_default_model(m6); |
||
744 | soft_task_def_period(m6, PERIOD_EQU2D); |
||
745 | soft_task_def_met(m6, WCET_EQU2D); |
||
746 | soft_task_def_group(m6, 1); |
||
747 | soft_task_def_stack(m6,32*1024); |
||
748 | soft_task_def_usemath(m6); |
||
749 | p6 = task_create("equ2D", equ2d_task, &m5, NULL); |
||
750 | if (p6 == -1) { |
||
751 | perror("FFTPlay: Could not create task <equ2D>\n"); |
||
752 | sys_end(); |
||
753 | } |
||
754 | #else |
||
755 | /* Start the prova task */ |
||
756 | //task_def_wcet(m6,1000); |
||
757 | //task_activate(task_create("prova",prova_task,TASK_TYPE,PERIODIC,200,&m6)); |
||
758 | #endif |
||
759 | |||
760 | group_activate(1); |
||
761 | |||
762 | /* Wait until the user get bored */ |
||
763 | while (keyb_getchar() != 13); |
||
764 | |||
765 | sys_end(); |
||
766 | |||
767 | return 0; |
||
768 | } |
||
769 | |||
770 |