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 }