public interface Sequencer extends Closeable
The Sequencer interface enables generation of very precisely-timed digital waveforms,
primarily targeted for different kinds of actuators, such as different kinds of motors, solenoids
and LEDs. The output comprises one or more channels, each of which can have one of several
different types. The output channels type and their assignments to pins are determined when the
Sequencer instance is created and cannot be changed during its lifetime. A
Sequencer instance is obtained via IOIO#openSequencer(ChannelConfig[]).
Each channel is configured with one of the Sequencer.ChannelConfig subclasses. For example,
Sequencer.ChannelCueBinary specified a binary output, useful for controlling an LED or a solenoid.
This configuration includes, among other things, the pin specification for this channel. See the
individual subclasses documentation for more information.
Once instantiated, the Sequencer gets fed with a stream of <cue, duration> pairs. A
cue is a set of instructions telling each of the channels what to do, or more precisely, one
Sequencer.ChannelCue per channel. The concrete type of the Sequencer.ChannelCue depends on the
channel type, for example, a channel that has been configured with Sequencer.ChannelConfigBinary,
expects a Sequencer.ChannelCueBinary for its cue. In this example, the cue will specify whether
this output should be high or low. When a cue is combined with a duration, it has the semantics
of "for this much time, generate this waveform". A stream of such pairs can represent a complex
multi-channel waveform.
The above <cue, duration> pairs are pushed into the Sequencer via the
push(ChannelCue[], int) method. They will not yet be executed, but rather queue up.
There is a limited number of cues that can be queued. Attempting to push more will block until a
cue has been executed. In order to avoid blocking (especially during the initial fill of the
queue - see below), the available() method returns the number of pushes that can be done
without blocking. Once a few of them have been queued up, execution may start by calling
start() . During execution, more cues can be pushed, and ideally fast enough so that
execution never needs to stall. During execution, pause() will suspend execution as soon
as the currently executed cue is done, without clearing the queue of pending cues. Operation can
then be resumed by calling start() again. Calling stop() will immediately stop
execution and clear the queue.
start(), it is recommended to pre-fill the
cue FIFO priorly. The recommended sequence of operations is:
// Open the sequencer.
Sequencer s = ioio_.openSequencer(...);
// At this point, the FIFO might still be at zero capacity, wait until opening is complete.
s.waitEventType(Sequencer.Event.Type.STOPPED);
// Now our FIFO is empty and at full capacity. Fill it entirely.
while (s.available() > 0) {
s.push(...);
}
// Now we can start!
s.start();
Sequencer is paused
or stopped without having to clear the queue. For this purpose, the
manualStart(ChannelCue[]) command can be used. Calling it will immediately begin
execution of a given cue, without changing the queue previously given. Unlike cues scheduled via
push(ChannelCue[], int), these cues have no duration, and will keep executing until
manualStop() is called. After that, normal operation can be resumed by calling
start() again.
Sequencer can be in, and the methods which
can be called to change it:
| Current State | Method | Next State |
|---|---|---|
| Idle | start() |
Running |
manualStart(ChannelCue[]) |
Manual | |
stop() |
Idle (and clear the queue) | |
manualStop() |
Idle (no-op) | |
| Running | pause() |
Idle |
stop() |
Idle (and clear the queue) | |
| Manual | manualStop() |
Idle |
stop() |
Idle (and clear the queue) | |
manualStart(ChannelCue[]) |
Manual (new cue) |
start().
The client can poll for the last event that occured via getLastEvent(), or block until
the next one arrives using waitEvent(). The latter features a limited-size queue, so
events are not lost as long as the client reads continuously. The queue is initially 32-events
long, but could be changed using setEventQueueSize(int). The sequencer will report the
following kinds of events, via the Sequencer.Event type:
getLastEvent() before any event has arrived.waitEvent()
Execution progress can be tracked at any time by examining the Sequencer.Event.numCuesStarted
field, which will increment every time actual execution of a cue has begun.
It will be reset back to 0 following a stop().
| Modifier and Type | Interface and Description |
|---|---|
static interface |
Sequencer.ChannelConfig
A marker interface for channel configurations.
|
static class |
Sequencer.ChannelConfigBinary
Configuration for a binary channel.
|
static class |
Sequencer.ChannelConfigFmSpeed
Configuration for a channel of type FM speed.
|
static class |
Sequencer.ChannelConfigPwmPosition
Configuration for a channel of type PWM Position.
|
static class |
Sequencer.ChannelConfigPwmSpeed
Configuration for a channel of type PWM speed.
|
static class |
Sequencer.ChannelConfigSteps
Configuration for a channel of type steps.
|
static interface |
Sequencer.ChannelCue
A marker interface for channel cues.
|
static class |
Sequencer.ChannelCueBinary
A cue for a binary channel.
|
static class |
Sequencer.ChannelCueFmSpeed
A cue for a FM speed channel.
|
static class |
Sequencer.ChannelCuePwmPosition
A cue for a PWM position channel.
|
static class |
Sequencer.ChannelCuePwmSpeed
A cue for a PWM speed channel.
|
static class |
Sequencer.ChannelCueSteps
A cue for a steps channel.
|
static class |
Sequencer.Clock
A clock rate selection, which implies a time-base.
|
static class |
Sequencer.Event
A sequencer event.
|
| Modifier and Type | Method and Description |
|---|---|
int |
available()
Get the number of cues which can be pushed without blocking.
|
Sequencer.Event |
getLastEvent()
Get the most recent execution event.
|
void |
manualStart(Sequencer.ChannelCue[] cues)
Execute a cue until further notice.
|
void |
manualStop()
Stop a manual cue currently running.
|
void |
pause()
Pause execution of the sequence.
|
void |
push(Sequencer.ChannelCue[] cues,
int duration)
Push a timed cue to the sequencer.
|
void |
setEventQueueSize(int size)
Sets a new size for the incoming event queue.
|
void |
start()
Start execution of the sequence.
|
void |
stop()
Stop execution of the sequence.
|
Sequencer.Event |
waitEvent()
Waits until an execution event occurs and returns it.
|
void |
waitEventType(Sequencer.Event.Type type)
A convenience method for blocking until an event of a certain type appears on the event
queue.
|
void push(Sequencer.ChannelCue[] cues, int duration) throws ConnectionLostException, java.lang.InterruptedException
This method will block until there is at least one free space in the FIFO (which may be
forever if the sequencer is not running -- use available() first in this
case). Then, it will queue the cue for execution.
cues - An array of channel cues. Has to be the exact same length as the
Sequencer.ChannelConfig array that was used to configure the sequencer. Each
element's type should be the counterpart of the corresponding configuration type.
For example, it element number 5 in the configuration array was of type
Sequencer.ChannelConfigBinary, then cues[5] needs to be of type
Sequencer.ChannelCueBinaryduration - The time duration for which this cue is to be executed, before moving to the next
cue (or stalling). The units are 16 microseconds. For example, passing 10 here
would mean a duration of 160 microseconds. Valid values are [2..65536] (approx.
1.05 seconds).ConnectionLostException - Connection to the IOIO was lost before or during this operation.java.lang.InterruptedException - The operation was interrupted before completion.void manualStart(Sequencer.ChannelCue[] cues) throws ConnectionLostException
This method may only be called when the sequencer is not in the Running state. It will not
affect the queue of pending timed-cues previously filled via push(ChannelCue[], int)
calls. The cue will be executed until explicitly stopped via manualStop(). A
subsequent call to manualStart(ChannelCue[]) can be used to immediately have a new
cue take into effect.
cues - An array of channel cues to execute. See the description of the same argument in
push(ChannelCue[], int) for details.ConnectionLostException - Connection to the IOIO was lost before or during this operation.void manualStop()
throws ConnectionLostException
This may be called only when a the sequencer is not in the Running state, typically in the
Manual state, as result of a previous manualStart(ChannelCue[]). This causes the
execution to stop immediately and the sequencer is now back in paused mode, ready for another
manual cue or for resuming execution of its previously queued sequence. Calling while in the
Idle state is legal, but does nothing.
ConnectionLostException - Connection to the IOIO was lost before or during this operation.void start()
throws ConnectionLostException
This method will cause any previously queued cues (via push(ChannelCue[], int)) to
start execution in order of pushing, according to their specified timings. The sequencer must
be paused before calling this method.
ConnectionLostException - Connection to the IOIO was lost before or during this operation.void pause()
throws ConnectionLostException
This method can be called when the sequencer is running, as result of previous invocation of
start(). It will cause execution to suspend as soon as the currently executing cue
is done. The queue of pending cues will not be affected, and operation can be resumed
seamlessly by calling start() again.
ConnectionLostException - Connection to the IOIO was lost before or during this operation.void stop()
throws ConnectionLostException
This will cause the sequence execution to stop immediately (without waiting for the current cue to complete). All previously queued cues will be discarded. The sequence will then go to paused state.
ConnectionLostException - Connection to the IOIO was lost before or during this operation.int available()
throws ConnectionLostException
This is useful for pre-filling the queue before starting the sequencer, or if the client
wants to do other operations on the same thread that pushes cues. The value returned will
indicate how many calls to push(ChannelCue[], int) can be completed without
blocking.
ConnectionLostExceptionSequencer.Event getLastEvent() throws ConnectionLostException
This includes the event type and the number of cues that started executing, since opening the
sequencer or the last call to stop(). Immediately after opening the sequencer, the
event type may be Sequencer.Event.Type.CLOSED, and as soon as the sequencer finished opening an
Sequencer.Event.Type.STOPPED will be sent.
ConnectionLostException - Connection to the IOIO was lost before or during this operation.Sequencer.Event waitEvent() throws ConnectionLostException, java.lang.InterruptedException
In case the client is not reading fast enough, older events will be discarded as new once arrive, so that the queue always stores the most recent events.
ConnectionLostException - Connection to the IOIO was lost before or during this operation.java.lang.InterruptedException - The operation was interrupted before completion.void waitEventType(Sequencer.Event.Type type) throws ConnectionLostException, java.lang.InterruptedException
ConnectionLostException - Connection to the IOIO was lost before or during this operation.java.lang.InterruptedException - The operation was interrupted before completion.void setEventQueueSize(int size)
throws ConnectionLostException
Initially the size of the queue is 32, which should suffice for most purposes. If, however, a client is not able to read frequently enough to not miss events, increasing the size is an option.
Any pending events will be discarded. It is recommended to call this method only once, immediately after opening the sequencer.
size - The new queue size.ConnectionLostException - Connection to the IOIO was lost before or during this operation.