# HG changeset patch # User Giulio Moro # Date 1451307191 -3600 # Node ID 1e629f12632283798ef88dc1bb96bd650d6bce74 # Parent 2877bc2cd449ce934305a34212868983148437b0 AuxiliaryTask can now be scheduled from setup(). Closes #1373 diff -r 2877bc2cd449 -r 1e629f126322 .cproject --- a/.cproject Mon Dec 28 04:11:59 2015 +0100 +++ b/.cproject Mon Dec 28 13:53:11 2015 +0100 @@ -90,10 +90,20 @@ + + + + + + + + + + - + @@ -181,10 +191,20 @@ + + + + + + + + + + - + diff -r 2877bc2cd449 -r 1e629f126322 core/RTAudio.cpp --- a/core/RTAudio.cpp Mon Dec 28 04:11:59 2015 +0100 +++ b/core/RTAudio.cpp Mon Dec 28 13:53:11 2015 +0100 @@ -44,6 +44,7 @@ void (*function)(void); char *name; int priority; + bool started; } InternalAuxiliaryTask; const char gRTAudioThreadName[] = "beaglert-audio"; @@ -214,6 +215,7 @@ // Set default volume levels BeagleRT_setDACLevel(settings->dacLevel); BeagleRT_setADCLevel(settings->adcLevel); + // TODO: add more argument checks for(int n = 0; n < 2; n++){ if(settings->pgaGain[n] > 59.5){ std::cerr << "PGA gain out of range [0,59.5]\n"; @@ -301,18 +303,22 @@ newTask->function = functionToCall; newTask->name = strdup(name); newTask->priority = priority; + newTask->started = false; gAuxTasks.push_back(newTask); return (AuxiliaryTask)newTask; } -// Schedule a previously created auxiliary task. It will run when the priority rules next +// Schedule a previously created (and started) auxiliary task. It will run when the priority rules next // allow it to be scheduled. void BeagleRT_scheduleAuxiliaryTask(AuxiliaryTask task) { InternalAuxiliaryTask *taskToSchedule = (InternalAuxiliaryTask *)task; - + if(taskToSchedule->started == false){ // Note: this is not the safest method to check if a task + BeagleRT_startAuxiliaryTask(task); // is started (or ready to be resumed), but it probably is the fastest. + // A safer approach would use rt_task_inquire() + } rt_task_resume(&taskToSchedule->task); } @@ -340,6 +346,20 @@ rt_printf("auxiliary task %s ended\n", name); } + +int BeagleRT_startAuxiliaryTask(AuxiliaryTask task){ + InternalAuxiliaryTask *taskStruct; + taskStruct = (InternalAuxiliaryTask *)task; + if(taskStruct->started == true) + return 0; + if(rt_task_start(&(taskStruct->task), &auxiliaryTaskLoop, taskStruct)) { + cerr << "Error: unable to start Xenomai task " << taskStruct->name << endl; + return -1; + } + taskStruct->started = true; + return 0; +} + // startAudio() should be called only after initAudio() successfully completes. // It launches the real-time Xenomai task which runs the audio loop. Returns 0 // on success. @@ -370,12 +390,7 @@ // The user may have created other tasks. Start those also. vector::iterator it; for(it = gAuxTasks.begin(); it != gAuxTasks.end(); it++) { - InternalAuxiliaryTask *taskStruct = *it; - - if(rt_task_start(&(taskStruct->task), &auxiliaryTaskLoop, taskStruct)) { - cerr << "Error: unable to start Xenomai task " << taskStruct->name << endl; - return -1; - } + return BeagleRT_startAuxiliaryTask(*it); } return 0; diff -r 2877bc2cd449 -r 1e629f126322 include/BeagleRT.h --- a/include/BeagleRT.h Mon Dec 28 04:11:59 2015 +0100 +++ b/include/BeagleRT.h Mon Dec 28 13:53:11 2015 +0100 @@ -437,6 +437,7 @@ * This function will stop the BeagleRT audio/sensor system. After this function returns, no further * calls to render() will be issued. */ +int BeagleRT_startAuxiliaryTask(AuxiliaryTask it); void BeagleRT_stopAudio(); /** @@ -580,6 +581,21 @@ AuxiliaryTask BeagleRT_createAuxiliaryTask(void (*functionToCall)(void), int priority, const char *name); /** + * \brief Start an auxiliary task so that it can be run. + * + * This function will start an auxiliary task but will NOT schedule it. + * It will also set a flag in the associate InternalAuxiliaryTask to flag the + * task as "started", so that successive calls to the same function for a given AuxiliaryTask + * have no effect. + * The user should never be required to call this function directly, as it is called + * by BeagleRT_scheduleAuxiliaryTask if needed (e.g.: if a task is scheduled in setup() ) + * or immediately after starting the audio thread. + * +* \param task Task to start. + */ + +int BeagleRT_startAuxiliaryTask(AuxiliaryTask task); +/** * \brief Run an auxiliary task which has previously been created. * * This function will schedule an auxiliary task to run. When the task runs, the function in the first diff -r 2877bc2cd449 -r 1e629f126322 projects/basic_passthru/render.cpp --- a/projects/basic_passthru/render.cpp Mon Dec 28 04:11:59 2015 +0100 +++ b/projects/basic_passthru/render.cpp Mon Dec 28 13:53:11 2015 +0100 @@ -19,10 +19,20 @@ // // Return true on success; returning false halts the program. +AuxiliaryTask taskOne; +AuxiliaryTask taskTwo; +void funOne(){ + rt_printf("setup\n"); +} +void funTwo(){ + rt_printf("render\n"); +} bool setup(BeagleRTContext *context, void *userData) { // Nothing to do here... - +// taskOne = BeagleRT_createAuxiliaryTask(funOne, 1, "funOne"); +// taskTwo = BeagleRT_createAuxiliaryTask(funTwo, 99, "funTwo"); +// BeagleRT_scheduleAuxiliaryTask(taskOne); return true; } @@ -33,25 +43,28 @@ void render(BeagleRTContext *context, void *userData) { +// if(context->audioSampleCount % 16384 == 0) +// BeagleRT_scheduleAuxiliaryTask(taskTwo); // Simplest possible case: pass inputs through to outputs for(unsigned int n = 0; n < context->audioFrames; n++) { for(unsigned int ch = 0; ch < context->audioChannels; ch++) - context->audioOut[n * context->audioChannels + ch] = context->audioIn[n * context->audioChannels + ch]; + context->audioOut[n * context->audioChannels + ch] = + context->audioIn[n * context->audioChannels + ch]; } // Same with matrix, only if matrix is enabled - if(context->analogFrames != 0) { - for(unsigned int n = 0; n < context->analogFrames; n++) { - for(unsigned int ch = 0; ch < context->analogChannels; ch++) { - // Two equivalent ways to write this code - // The long way, using the buffers directly: - // context->analogOut[n * context->analogChannels + ch] = context->analogIn[n * context->analogChannels + ch]; - - // Or using the macros: - analogWriteFrame(context, n, ch, analogReadFrame(context, n, ch)); - } - } - } +// if(context->analogFrames != 0) { +// for(unsigned int n = 0; n < context->analogFrames; n++) { +// for(unsigned int ch = 0; ch < context->analogChannels; ch++) { +// // Two equivalent ways to write this code +// // The long way, using the buffers directly: +// // context->analogOut[n * context->analogChannels + ch] = context->analogIn[n * context->analogChannels + ch]; +// +// // Or using the macros: +// analogWriteFrame(context, n, ch, analogReadFrame(context, n, ch)); +// } +// } +// } } // cleanup() is called once at the end, after the audio has stopped.