Mercurial > hg > beaglert
comparison core/RTAudio.cpp @ 301:e4392164b458 prerelease
RENAMED BeagleRT to Bela AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, scripts probably not working
author | Giulio Moro <giuliomoro@yahoo.it> |
---|---|
date | Fri, 27 May 2016 14:34:41 +0100 |
parents | c55c6f6c233c |
children | 421a69d42943 |
comparison
equal
deleted
inserted
replaced
300:dbeed520b014 | 301:e4392164b458 |
---|---|
25 #include <native/task.h> | 25 #include <native/task.h> |
26 #include <native/timer.h> | 26 #include <native/timer.h> |
27 #include <native/intr.h> | 27 #include <native/intr.h> |
28 #include <rtdk.h> | 28 #include <rtdk.h> |
29 | 29 |
30 #include "../include/BeagleRT.h" | 30 #include "../include/Bela.h" |
31 #include "../include/PRU.h" | 31 #include "../include/PRU.h" |
32 #include "../include/I2c_Codec.h" | 32 #include "../include/I2c_Codec.h" |
33 #include "../include/GPIOcontrol.h" | 33 #include "../include/GPIOcontrol.h" |
34 | 34 |
35 // ARM interrupt number for PRU event EVTOUT7 | 35 // ARM interrupt number for PRU event EVTOUT7 |
75 int gRTAudioVerbose = 0; // Verbosity level for debugging | 75 int gRTAudioVerbose = 0; // Verbosity level for debugging |
76 int gAmplifierMutePin = -1; | 76 int gAmplifierMutePin = -1; |
77 int gAmplifierShouldBeginMuted = 0; | 77 int gAmplifierShouldBeginMuted = 0; |
78 | 78 |
79 // Context which holds all the audio/sensor data passed to the render routines | 79 // Context which holds all the audio/sensor data passed to the render routines |
80 BeagleRTContext gContext; | 80 BelaContext gContext; |
81 | 81 |
82 // User data passed in from main() | 82 // User data passed in from main() |
83 void *gUserData; | 83 void *gUserData; |
84 | 84 |
85 // initAudio() prepares the infrastructure for running PRU-based real-time | 85 // initAudio() prepares the infrastructure for running PRU-based real-time |
94 // userData is an opaque pointer which will be passed through to the setup() | 94 // userData is an opaque pointer which will be passed through to the setup() |
95 // function for application-specific use | 95 // function for application-specific use |
96 // | 96 // |
97 // Returns 0 on success. | 97 // Returns 0 on success. |
98 | 98 |
99 int BeagleRT_initAudio(BeagleRTInitSettings *settings, void *userData) | 99 int Bela_initAudio(BelaInitSettings *settings, void *userData) |
100 { | 100 { |
101 // Sanity checks | 101 // Sanity checks |
102 if(settings->pruNumber < 0 || settings->pruNumber > 1) { | 102 if(settings->pruNumber < 0 || settings->pruNumber > 1) { |
103 cout << "Invalid PRU number " << settings->pruNumber << endl; | 103 cout << "Invalid PRU number " << settings->pruNumber << endl; |
104 return -1; | 104 return -1; |
108 return -1; | 108 return -1; |
109 } | 109 } |
110 | 110 |
111 rt_print_auto_init(1); | 111 rt_print_auto_init(1); |
112 | 112 |
113 BeagleRT_setVerboseLevel(settings->verbose); | 113 Bela_setVerboseLevel(settings->verbose); |
114 strncpy(gPRUFilename, settings->pruFilename, MAX_PRU_FILENAME_LENGTH); | 114 strncpy(gPRUFilename, settings->pruFilename, MAX_PRU_FILENAME_LENGTH); |
115 gUserData = userData; | 115 gUserData = userData; |
116 | 116 |
117 // Initialise context data structure | 117 // Initialise context data structure |
118 memset(&gContext, 0, sizeof(BeagleRTContext)); | 118 memset(&gContext, 0, sizeof(BelaContext)); |
119 | 119 |
120 if(gRTAudioVerbose) { | 120 if(gRTAudioVerbose) { |
121 cout << "Starting with period size " << settings->periodSize << "; "; | 121 cout << "Starting with period size " << settings->periodSize << "; "; |
122 if(settings->useAnalog) | 122 if(settings->useAnalog) |
123 cout << "analog enabled\n"; | 123 cout << "analog enabled\n"; |
229 cout << "Error: unable to initialise audio codec\n"; | 229 cout << "Error: unable to initialise audio codec\n"; |
230 return 1; | 230 return 1; |
231 } | 231 } |
232 | 232 |
233 // Set default volume levels | 233 // Set default volume levels |
234 BeagleRT_setDACLevel(settings->dacLevel); | 234 Bela_setDACLevel(settings->dacLevel); |
235 BeagleRT_setADCLevel(settings->adcLevel); | 235 Bela_setADCLevel(settings->adcLevel); |
236 // TODO: add more argument checks | 236 // TODO: add more argument checks |
237 for(int n = 0; n < 2; n++){ | 237 for(int n = 0; n < 2; n++){ |
238 if(settings->pgaGain[n] > 59.5){ | 238 if(settings->pgaGain[n] > 59.5){ |
239 std::cerr << "PGA gain out of range [0,59.5]\n"; | 239 std::cerr << "PGA gain out of range [0,59.5]\n"; |
240 exit(1); | 240 exit(1); |
241 } | 241 } |
242 BeagleRT_setPgaGain(settings->pgaGain[n], n); | 242 Bela_setPgaGain(settings->pgaGain[n], n); |
243 } | 243 } |
244 BeagleRT_setHeadphoneLevel(settings->headphoneLevel); | 244 Bela_setHeadphoneLevel(settings->headphoneLevel); |
245 | 245 |
246 // Call the user-defined initialisation function | 246 // Call the user-defined initialisation function |
247 if(!setup(&gContext, userData)) { | 247 if(!setup(&gContext, userData)) { |
248 cout << "Couldn't initialise audio rendering\n"; | 248 cout << "Couldn't initialise audio rendering\n"; |
249 return 1; | 249 return 1; |
277 else { | 277 else { |
278 // All systems go. Run the loop; it will end when gShouldStop is set to 1 | 278 // All systems go. Run the loop; it will end when gShouldStop is set to 1 |
279 | 279 |
280 if(!gAmplifierShouldBeginMuted) { | 280 if(!gAmplifierShouldBeginMuted) { |
281 // First unmute the amplifier | 281 // First unmute the amplifier |
282 if(BeagleRT_muteSpeakers(0)) { | 282 if(Bela_muteSpeakers(0)) { |
283 if(gRTAudioVerbose) | 283 if(gRTAudioVerbose) |
284 rt_printf("Warning: couldn't set value (high) on amplifier mute pin\n"); | 284 rt_printf("Warning: couldn't set value (high) on amplifier mute pin\n"); |
285 } | 285 } |
286 } | 286 } |
287 | 287 |
304 | 304 |
305 // Create a calculation loop which can run independently of the audio, at a different | 305 // Create a calculation loop which can run independently of the audio, at a different |
306 // (equal or lower) priority. Audio priority is defined in BEAGLERT_AUDIO_PRIORITY; | 306 // (equal or lower) priority. Audio priority is defined in BEAGLERT_AUDIO_PRIORITY; |
307 // priority should be generally be less than this. | 307 // priority should be generally be less than this. |
308 // Returns an (opaque) pointer to the created task on success; 0 on failure | 308 // Returns an (opaque) pointer to the created task on success; 0 on failure |
309 AuxiliaryTask BeagleRT_createAuxiliaryTask(void (*functionToCall)(void* args), int priority, const char *name, void* args, bool autoSchedule) | 309 AuxiliaryTask Bela_createAuxiliaryTask(void (*functionToCall)(void* args), int priority, const char *name, void* args, bool autoSchedule) |
310 { | 310 { |
311 InternalAuxiliaryTask *newTask = (InternalAuxiliaryTask*)malloc(sizeof(InternalAuxiliaryTask)); | 311 InternalAuxiliaryTask *newTask = (InternalAuxiliaryTask*)malloc(sizeof(InternalAuxiliaryTask)); |
312 | 312 |
313 // Attempt to create the task | 313 // Attempt to create the task |
314 if(rt_task_create(&(newTask->task), name, 0, priority, T_JOINABLE | T_FPU)) { | 314 if(rt_task_create(&(newTask->task), name, 0, priority, T_JOINABLE | T_FPU)) { |
328 | 328 |
329 getAuxTasks().push_back(newTask); | 329 getAuxTasks().push_back(newTask); |
330 | 330 |
331 return (AuxiliaryTask)newTask; | 331 return (AuxiliaryTask)newTask; |
332 } | 332 } |
333 AuxiliaryTask BeagleRT_createAuxiliaryTask(void (*functionToCall)(void), int priority, const char *name, bool autoSchedule) | 333 AuxiliaryTask Bela_createAuxiliaryTask(void (*functionToCall)(void), int priority, const char *name, bool autoSchedule) |
334 { | 334 { |
335 InternalAuxiliaryTask *newTask = (InternalAuxiliaryTask*)malloc(sizeof(InternalAuxiliaryTask)); | 335 InternalAuxiliaryTask *newTask = (InternalAuxiliaryTask*)malloc(sizeof(InternalAuxiliaryTask)); |
336 | 336 |
337 // Attempt to create the task | 337 // Attempt to create the task |
338 if(rt_task_create(&(newTask->task), name, 0, priority, T_JOINABLE | T_FPU)) { | 338 if(rt_task_create(&(newTask->task), name, 0, priority, T_JOINABLE | T_FPU)) { |
354 return (AuxiliaryTask)newTask; | 354 return (AuxiliaryTask)newTask; |
355 } | 355 } |
356 | 356 |
357 // Schedule a previously created (and started) auxiliary task. It will run when the priority rules next | 357 // Schedule a previously created (and started) auxiliary task. It will run when the priority rules next |
358 // allow it to be scheduled. | 358 // allow it to be scheduled. |
359 void BeagleRT_scheduleAuxiliaryTask(AuxiliaryTask task) | 359 void Bela_scheduleAuxiliaryTask(AuxiliaryTask task) |
360 { | 360 { |
361 InternalAuxiliaryTask *taskToSchedule = (InternalAuxiliaryTask *)task; | 361 InternalAuxiliaryTask *taskToSchedule = (InternalAuxiliaryTask *)task; |
362 if(taskToSchedule->started == false){ // Note: this is not the safest method to check if a task | 362 if(taskToSchedule->started == false){ // Note: this is not the safest method to check if a task |
363 BeagleRT_startAuxiliaryTask(task); // is started (or ready to be resumed), but it probably is the fastest. | 363 Bela_startAuxiliaryTask(task); // is started (or ready to be resumed), but it probably is the fastest. |
364 // A safer approach would use rt_task_inquire() | 364 // A safer approach would use rt_task_inquire() |
365 } | 365 } |
366 rt_task_resume(&taskToSchedule->task); | 366 rt_task_resume(&taskToSchedule->task); |
367 } | 367 } |
368 void BeagleRT_autoScheduleAuxiliaryTasks(){ | 368 void Bela_autoScheduleAuxiliaryTasks(){ |
369 vector<InternalAuxiliaryTask*>::iterator it; | 369 vector<InternalAuxiliaryTask*>::iterator it; |
370 for(it = getAuxTasks().begin(); it != getAuxTasks().end(); it++) { | 370 for(it = getAuxTasks().begin(); it != getAuxTasks().end(); it++) { |
371 if ((InternalAuxiliaryTask *)(*it)->autoSchedule){ | 371 if ((InternalAuxiliaryTask *)(*it)->autoSchedule){ |
372 BeagleRT_scheduleAuxiliaryTask(*it); | 372 Bela_scheduleAuxiliaryTask(*it); |
373 } | 373 } |
374 } | 374 } |
375 } | 375 } |
376 | 376 |
377 // Calculation loop that can be used for other tasks running at a lower | 377 // Calculation loop that can be used for other tasks running at a lower |
405 if(gRTAudioVerbose == 1) | 405 if(gRTAudioVerbose == 1) |
406 rt_printf("auxiliary task %s ended\n", name); | 406 rt_printf("auxiliary task %s ended\n", name); |
407 } | 407 } |
408 | 408 |
409 | 409 |
410 int BeagleRT_startAuxiliaryTask(AuxiliaryTask task){ | 410 int Bela_startAuxiliaryTask(AuxiliaryTask task){ |
411 InternalAuxiliaryTask *taskStruct; | 411 InternalAuxiliaryTask *taskStruct; |
412 taskStruct = (InternalAuxiliaryTask *)task; | 412 taskStruct = (InternalAuxiliaryTask *)task; |
413 if(taskStruct->started == true) | 413 if(taskStruct->started == true) |
414 return 0; | 414 return 0; |
415 if(rt_task_start(&(taskStruct->task), &auxiliaryTaskLoop, taskStruct)) { | 415 if(rt_task_start(&(taskStruct->task), &auxiliaryTaskLoop, taskStruct)) { |
422 | 422 |
423 // startAudio() should be called only after initAudio() successfully completes. | 423 // startAudio() should be called only after initAudio() successfully completes. |
424 // It launches the real-time Xenomai task which runs the audio loop. Returns 0 | 424 // It launches the real-time Xenomai task which runs the audio loop. Returns 0 |
425 // on success. | 425 // on success. |
426 | 426 |
427 int BeagleRT_startAudio() | 427 int Bela_startAudio() |
428 { | 428 { |
429 // Create audio thread with high Xenomai priority | 429 // Create audio thread with high Xenomai priority |
430 if(rt_task_create(&gRTAudioThread, gRTAudioThreadName, 0, BEAGLERT_AUDIO_PRIORITY, T_JOINABLE | T_FPU)) { | 430 if(rt_task_create(&gRTAudioThread, gRTAudioThreadName, 0, BEAGLERT_AUDIO_PRIORITY, T_JOINABLE | T_FPU)) { |
431 cout << "Error: unable to create Xenomai audio thread" << endl; | 431 cout << "Error: unable to create Xenomai audio thread" << endl; |
432 return -1; | 432 return -1; |
448 } | 448 } |
449 | 449 |
450 // The user may have created other tasks. Start those also. | 450 // The user may have created other tasks. Start those also. |
451 vector<InternalAuxiliaryTask*>::iterator it; | 451 vector<InternalAuxiliaryTask*>::iterator it; |
452 for(it = getAuxTasks().begin(); it != getAuxTasks().end(); it++) { | 452 for(it = getAuxTasks().begin(); it != getAuxTasks().end(); it++) { |
453 int ret = BeagleRT_startAuxiliaryTask(*it); | 453 int ret = Bela_startAuxiliaryTask(*it); |
454 if(ret != 0) | 454 if(ret != 0) |
455 return -2; | 455 return -2; |
456 } | 456 } |
457 return 0; | 457 return 0; |
458 } | 458 } |
459 | 459 |
460 // Stop the PRU-based audio from running and wait | 460 // Stop the PRU-based audio from running and wait |
461 // for the tasks to complete before returning. | 461 // for the tasks to complete before returning. |
462 | 462 |
463 void BeagleRT_stopAudio() | 463 void Bela_stopAudio() |
464 { | 464 { |
465 // Tell audio thread to stop (if this hasn't been done already) | 465 // Tell audio thread to stop (if this hasn't been done already) |
466 gShouldStop = true; | 466 gShouldStop = true; |
467 | 467 |
468 if(gRTAudioVerbose) | 468 if(gRTAudioVerbose) |
481 rt_task_join(&(taskStruct->task)); | 481 rt_task_join(&(taskStruct->task)); |
482 } | 482 } |
483 } | 483 } |
484 | 484 |
485 // Free any resources associated with PRU real-time audio | 485 // Free any resources associated with PRU real-time audio |
486 void BeagleRT_cleanupAudio() | 486 void Bela_cleanupAudio() |
487 { | 487 { |
488 cleanup(&gContext, gUserData); | 488 cleanup(&gContext, gUserData); |
489 | 489 |
490 // Clean up the auxiliary tasks | 490 // Clean up the auxiliary tasks |
491 vector<InternalAuxiliaryTask*>::iterator it; | 491 vector<InternalAuxiliaryTask*>::iterator it; |
517 gAmplifierMutePin = -1; | 517 gAmplifierMutePin = -1; |
518 } | 518 } |
519 | 519 |
520 // Set the level of the DAC; affects all outputs (headphone, line, speaker) | 520 // Set the level of the DAC; affects all outputs (headphone, line, speaker) |
521 // 0dB is the maximum, -63.5dB is the minimum; 0.5dB steps | 521 // 0dB is the maximum, -63.5dB is the minimum; 0.5dB steps |
522 int BeagleRT_setDACLevel(float decibels) | 522 int Bela_setDACLevel(float decibels) |
523 { | 523 { |
524 if(gAudioCodec == 0) | 524 if(gAudioCodec == 0) |
525 return -1; | 525 return -1; |
526 return gAudioCodec->setDACVolume((int)floorf(decibels * 2.0 + 0.5)); | 526 return gAudioCodec->setDACVolume((int)floorf(decibels * 2.0 + 0.5)); |
527 } | 527 } |
528 | 528 |
529 // Set the level of the ADC | 529 // Set the level of the ADC |
530 // 0dB is the maximum, -12dB is the minimum; 1.5dB steps | 530 // 0dB is the maximum, -12dB is the minimum; 1.5dB steps |
531 int BeagleRT_setADCLevel(float decibels) | 531 int Bela_setADCLevel(float decibels) |
532 { | 532 { |
533 if(gAudioCodec == 0) | 533 if(gAudioCodec == 0) |
534 return -1; | 534 return -1; |
535 return gAudioCodec->setADCVolume((int)floorf(decibels * 2.0 + 0.5)); | 535 return gAudioCodec->setADCVolume((int)floorf(decibels * 2.0 + 0.5)); |
536 } | 536 } |
537 | 537 |
538 // Set the level of the Programmable Gain Amplifier | 538 // Set the level of the Programmable Gain Amplifier |
539 // 59.5dB is maximum, 0dB is minimum; 0.5dB steps | 539 // 59.5dB is maximum, 0dB is minimum; 0.5dB steps |
540 int BeagleRT_setPgaGain(float decibels, int channel){ | 540 int Bela_setPgaGain(float decibels, int channel){ |
541 if(gAudioCodec == 0) | 541 if(gAudioCodec == 0) |
542 return -1; | 542 return -1; |
543 return gAudioCodec->setPga(decibels, channel); | 543 return gAudioCodec->setPga(decibels, channel); |
544 } | 544 } |
545 | 545 |
546 // Set the level of the onboard headphone amplifier; affects headphone | 546 // Set the level of the onboard headphone amplifier; affects headphone |
547 // output only (not line out or speaker) | 547 // output only (not line out or speaker) |
548 // 0dB is the maximum, -63.5dB is the minimum; 0.5dB steps | 548 // 0dB is the maximum, -63.5dB is the minimum; 0.5dB steps |
549 int BeagleRT_setHeadphoneLevel(float decibels) | 549 int Bela_setHeadphoneLevel(float decibels) |
550 { | 550 { |
551 if(gAudioCodec == 0) | 551 if(gAudioCodec == 0) |
552 return -1; | 552 return -1; |
553 return gAudioCodec->setHPVolume((int)floorf(decibels * 2.0 + 0.5)); | 553 return gAudioCodec->setHPVolume((int)floorf(decibels * 2.0 + 0.5)); |
554 } | 554 } |
555 | 555 |
556 // Mute or unmute the onboard speaker amplifiers | 556 // Mute or unmute the onboard speaker amplifiers |
557 // mute == 0 means unmute; otherwise mute | 557 // mute == 0 means unmute; otherwise mute |
558 // Returns 0 on success | 558 // Returns 0 on success |
559 int BeagleRT_muteSpeakers(int mute) | 559 int Bela_muteSpeakers(int mute) |
560 { | 560 { |
561 int pinValue = mute ? LOW : HIGH; | 561 int pinValue = mute ? LOW : HIGH; |
562 | 562 |
563 // Check that we have an enabled pin for controlling the mute | 563 // Check that we have an enabled pin for controlling the mute |
564 if(gAmplifierMutePin < 0) | 564 if(gAmplifierMutePin < 0) |
566 | 566 |
567 return gpio_set_value(gAmplifierMutePin, pinValue); | 567 return gpio_set_value(gAmplifierMutePin, pinValue); |
568 } | 568 } |
569 | 569 |
570 // Set the verbosity level | 570 // Set the verbosity level |
571 void BeagleRT_setVerboseLevel(int level) | 571 void Bela_setVerboseLevel(int level) |
572 { | 572 { |
573 gRTAudioVerbose = level; | 573 gRTAudioVerbose = level; |
574 } | 574 } |