-
Notifications
You must be signed in to change notification settings - Fork 1
Provider creation overview
There is base API and wrapper for most common usage called soundProviderTask
. First one provide more customisable and flexible way, second - easier to use in most situations.
Let me just show definion:
QueueHandle_t queue = NULL; // Read from here
QueueHandle_t controlQueue = NULL; // Read controlling data from here
// PROVIDER CONTROL INTERFACE START
virtual void provider_start() = 0; // Start filling (should be ok if started)
virtual void provider_pause() {}; // Optional methods for extra optimisation
virtual void provider_resume() {};
virtual void provider_stop() = 0; // Stop filling (should be ok if isn't started)
virtual void provider_restart() {provider_stop(); provider_start();} // This one calls if track repeats (default implementation should work, but it is better to write your own)
// PROVIDER CONTROL INTERFACE END
void postSample(SoundData sample);
void postControl(SoundProviderControl ctrl);
void queueReset();
virtual unsigned long int getFrequency() = 0; // Frequency in Hz, should be constant
Pretty easy, right?
So, you should implement:
void provider_start()
void provider_stop()
unsigned long int getFrequency()
Also, optional functions:
void provider_pause()
void provider_resume()
void provider_restart()
All of that functions should be as fast as possible and non-blocking, because all of them calls from timer's callback.
So, you should use it that way:
- Post samples using
postSample(sample)
. - When nothing to post, send end-of-queue using
postControl(END)
. - In case of error, post error using
postControl(FAILURE)
.
In most cases base API is too complicated, so it is much better to use wrapper. It implements easier API. So a piece of code, again:
// TASK PROVIDER INTERFACE START
virtual void task_prestart() {};
virtual void task_poststart() {};
virtual void task_code() = 0;
virtual void task_prestop() {};
virtual void task_poststop() {};
// TASK PROVIDER INTERFACE END
// PROVIDER CONTROL INTERFACE START
void provider_start(); // Start filling (should be ok if started)
void provider_stop(); // Stop filling (should be ok if isn't started)
// PROVIDER CONTROL INTERFACE END
void taskProviderCode();
void stopFromTask();
TaskHandle_t taskHandle = NULL;
size_t stackSize = 2048;
It implements provider_start()
and provider_stop()
, so you still can redefine other methods.
Main part of code is placed in task_code()
. Task starts in provider_start()
. It doesn't need to stop itself at the end, but still must call postControl()
. If you don't leave function or want emergency stop, call stopFromTask()
. If you want to do something with your task by youself, its handle stored in taskHandle
, but make shure that it isn't NULL
.
Now custom code for start and stop is optional and should be implemented in task_*start()
and task_*stop()
. As you can understand, task_pre*()
calls before starting/stopping, and task_post*()
after.
If default stackSize
is too small, you always can increace it.