public interface PWMChannel extends Device<PWMChannel>, BufferAccess<java.nio.IntBuffer>
PWMChannel
interface provides methods for controlling a PWM (Pulse Width Modulation) signal generator
channel.
One PWM generator/controller can have several channels. A PWM channel can generate pulses on a digital output line (possibly a GPIO pin).
A PWM channel may be identified by the numeric ID and by the name (if any defined) that correspond to its
registered configuration. A PWMChannel
instance can be opened by a call to one of the
DeviceManager.open(id,...)
methods using its ID or by a call to one of the
DeviceManager.open(name,...)
methods using its name. When a PWMChannel
instance is opened with an ad-hoc
PWMChannelConfig
configuration (which includes its hardware addressing information) using one of the
DeviceManager.open(config,...)
methods it is not
assigned any ID nor name.
Once opened, an application can set the pulse period using the setPulsePeriod
and then generate a certain
number of pulses of a specified width by calling one of the generate
methods.
An application can also asynchronously generate a train of pulses either of a specified width up to a specified
maximum count or from widths specified in a buffer by calling one of the
startGeneration
methods with a
GenerationListener
instance which will get notified upon completion. Such an asynchronous pulse generation
can be stopped or canceled by calling the stopGeneration
method.
Only one output/generation operation (synchronous or asynchronous) can be going on at any time.
When an application is no longer using a PWM channel it should call the PWMChannel.close
method to
close the PWM channel. Any further attempt to use a PWM channel which has been closed will result in a
ClosedDeviceException
been thrown.
Upon opening a PWM channel the default pulse width and duty cycle are always 0
; the idle
state is platform or configuration-specific.
PWMChannelConfig
configuration to
a value greater than 0
; whether or not the channel will indeed work
in buffering mode and will use an internal output buffer of the size requested
is up to the device driver. An application may check whether a channel is
working in buffering mode by calling the
PWMChannelConfig.getOutputBufferSize
method. Buffer
s to the output methods; whether
efficient direct output transfers will be used depends on the underlying
hardware and driver capabilities and on whether the provided buffers are
suitable for such operations (see
BufferAccess.prepareBuffer
). Output methods
using double buffering may only support efficient direct operations if both
buffers are suitable for such operations.
PWMChannel
instance with an ad-hoc configuration requires
the PWMPermission.OPEN
to be granted;
opening an instance of a PWMChannel
configured with an explicit GPIOPin
output
on which the pulses are to be generated requires, in addition, the
GPIOPinPermission.OPEN
permission to be granted
on the designated GPIO pin.
Opening a PWMChannel
with the following ad hoc sample configuration:
PWMChannelConfig config = new PWMChannelConfig.Builder() .setControllerNumber(1) .setChannelNumber(1) .setOutputConfig(new GPIOPinConfig.Builder() .setControllerNumber(3) .setPinNumber(1) .setDirection(GPIOPinConfig.DIR_OUTPUT_ONLY) .setDriveMode(GPIOPinConfig.MODE_OUTPUT_PUSH_PULL) .build()) .setScaleFactor(1.0) .setPulsePeriod(10) .setIdleState(IDLE_STATE_HIGH) .setPulseAlignment(ALIGN_CENTER) .setOutputBufferSize(0) .build();
requires the following permissions to be granted:
PWMChannelPermission("1:1", "open") GPIOPinPermission("3:1", "open")
GenerationListener
,
PWMPermission
,
GPIOPinPermission
BIG_ENDIAN, LITTLE_ENDIAN, MIXED_ENDIAN
Modifier and Type | Method and Description |
---|---|
void |
generate(java.nio.IntBuffer src)
Generates a pulse train from the specified sequence of pulse widths.
|
void |
generate(int width,
int count)
Generates a pulse train containing the specified count of pulses of the specified width.
|
int |
getMaxPulsePeriod()
Gets the scaled maximum pulse period of this PWM channel (in microseconds) that can bet set by a call to
setPulsePeriod . |
int |
getMinPulsePeriod()
Gets the minimum scaled pulse period of this PWM channel (in microseconds) that can bet set by a call to
setPulsePeriod . |
GPIOPin |
getOutput()
Gets the output on which the pulses are generated.
|
int |
getPulsePeriod()
Gets the scaled pulse period of this PWM channel (in microseconds).
|
double |
getScaleFactor()
Gets the pulse period scale factor of this PWM channel.
|
void |
setPulsePeriod(int period)
Sets the scaled pulse period of this PWM channel.
|
void |
setScaleFactor(double factor)
Sets the pulse period scale factor of this PWM channel.
|
void |
startGeneration(int width)
Starts an asynchronous pulse train generation session - continuously generating pulses of the specified width
until explicitly stopped.
|
void |
startGeneration(java.nio.IntBuffer src,
GenerationRoundListener listener)
Starts asynchronous pulse train generation in successive rounds - initially generating pulses of the specified
widths up to the specified initial count - as indicated by the number of remaining elements in the provided
buffer.
|
void |
startGeneration(java.nio.IntBuffer src1,
java.nio.IntBuffer src2,
GenerationRoundListener listener)
Starts asynchronous pulse train generation in successive rounds.
|
void |
startGeneration(int width,
int count,
GenerationListener listener)
Starts an asynchronous pulse train generation session - generating pulses of the specified width up to the
specified count.
|
void |
stopGeneration()
Stops (cancels) the currently active pulse generation session as started by a call to one
of the
startGeneration methods. |
close, getByteOrder, getDescriptor, isOpen, tryLock, unlock
getInputBuffer, getOutputBuffer, prepareBuffer
void setPulsePeriod(int period) throws java.io.IOException, UnavailableDeviceException, ClosedDeviceException
getScaleFactor
.
Whether changing the pulse period
has an immediate effect or not on an active (synchronous or asynchronous) generation is
device- as well as platform-dependent.
If the underlying platform or driver
does not support the requested pulse period value
then period
will be aligned to the closest lower supported discrete period value. The resulting, actual
pulse period can be retrieved by a call to getPulsePeriod
.
If the current scale factor as returned by
getScaleFactor
is scale
and the current scaled
pulse period value - after alignment - is sPeriod
then the effective pulse period is calculated as follows:
ePeriod = (sPeriod / scale)
period
- the scaled pulse period as a period in microseconds.java.io.IOException
- if some other I/O error occurs.UnavailableDeviceException
- if this device is not currently available - such as it is locked by another application.ClosedDeviceException
- if the device has been closed.InvalidPulseRateException
- if period
is greater than the maximum pulse period (see getMaxPulsePeriod
)
or lower than the minimum pulse period (see getMinPulsePeriod
).java.lang.IllegalArgumentException
- if period
is negative or zero.int getPulsePeriod() throws java.io.IOException, UnavailableDeviceException, ClosedDeviceException
getScaleFactor
.
If the pulse period was not set previously using
setPulsePeriod
the device configuration-specific default value is returned.
Additionally, the value returned may differ from the previously set or configured value as it may have
been adjusted to account for the timer resolution or discrete pulse period values supported by the underlying platform or driver.java.io.IOException
- if some other I/O error occurs.UnavailableDeviceException
- if this device is not currently available - such as it is locked by another application.ClosedDeviceException
- if the device has been closed.void setScaleFactor(double factor) throws java.io.IOException, UnavailableDeviceException, ClosedDeviceException
setPulsePeriod
method in order to set
an appropriate scaled pulse period.factor
- the scale factor (a number greater or equal to 1.0
).java.lang.IllegalArgumentException
- if factor
is NaN
, is less than 1.0
or,
if the setting of the scale factor would result
in the scaled pulse period range to be outside the range [1 -
Integer.MAX_VALUE
]
.java.io.IOException
- if some other I/O error occurs.UnavailableDeviceException
- if this device is not currently
available - such as it is locked by another application.ClosedDeviceException
- if the device has been closed.getScaleFactor()
,
setPulsePeriod(int)
double getScaleFactor() throws java.io.IOException, UnavailableDeviceException, ClosedDeviceException
scale
and the scaled pulse period value as
returned by getPulsePeriod
is sPeriod
then the
effective pulse period is calculated as follows: Conversely, the scaled pulse period value to set usingePeriod = (sPeriod / scale)
setPulsePeriod(int)
to obtain the effective pulse
period ePeriod
is calculated as follows: The scale factor also applies to the minimum and maximum scaled pulse periods as respectively returned bysPeriod = (ePeriod * scale)
getMinPulsePeriod
and getMaxPulsePeriod
.
If the pulse period scale factor was not set previously using
setScaleFactor
, the device configuration-specific
default value is returned.
java.io.IOException
- if some other I/O error occurs.UnavailableDeviceException
- if this device is not currently available - such as it is locked by another
application.ClosedDeviceException
- if the device has been closed.int getMaxPulsePeriod() throws java.io.IOException, UnavailableDeviceException, ClosedDeviceException
setPulsePeriod
. The maximum effective pulse period
can be calculated from the currently set scale factor as can be retrieved using
getScaleFactor
.java.io.IOException
- if some other I/O error occurs.UnavailableDeviceException
- if this device is not currently available - such as it is locked by another application.ClosedDeviceException
- if the device has been closed.int getMinPulsePeriod() throws java.io.IOException, UnavailableDeviceException, ClosedDeviceException
setPulsePeriod
. The minimum effective pulse period
can be calculated from the currently set scale factor as can be retrieved using
getScaleFactor
.java.io.IOException
- if some other I/O error occurs.UnavailableDeviceException
- if this device is not currently available - such as it is locked by another application.ClosedDeviceException
- if the device has been closed.void generate(int width, int count) throws java.io.IOException, UnavailableDeviceException, ClosedDeviceException
getScaleFactor
.
To generate pulses of a specific duty cycle dutyCycle
, this method may be called as follows:
float dutyCycle = 0.5f; pwmChannel.generate((pwmChannel.getPulsePeriod() * dutyCycle), count);
If the underlying platform or driver
does not support the requested width value
then width
will be aligned to the closest lower supported discrete width value.
The operation will return only after generating all of the count
requested pulses.
The pulses will be generated according to the current effective pulse period
as determined by the current scaled pulse period (see getPulsePeriod
)
and the current scale factor getScaleFactor
.
This method may be invoked at any time. If another thread has already initiated a synchronous output operation upon this channel then an invocation of this method will block until the first operation is complete.
Only one output operation (synchronous or asynchronous) can be going on at any time.
width
- the scaled pulse width (in microseconds).count
- the maximum number of pulses to generate.java.io.IOException
- if some other I/O error occurs.java.lang.IllegalArgumentException
- if width
or count
is equal to or less than 0
or if width
is greater
than the currently set period.UnavailableDeviceException
- if this device is not currently available - such as it is locked by another application.ClosedDeviceException
- if the device has been closed.java.lang.IllegalStateException
- if an asynchronous pulse generation session is already active.void generate(java.nio.IntBuffer src) throws java.io.IOException, UnavailableDeviceException, UnsupportedByteOrderException, ClosedDeviceException
getScaleFactor
.
r pulses will be generated by this channel, where r is the number of integers (pulse widths)
remaining in the buffer, that is, src.remaining()
, at the moment this method is invoked.
Suppose that a pulse width integer value sequence of length n is provided, where 0 <= n <= r
. The sequence starts at index p, where p is the buffer's position at the moment this method is
invoked; the index of the last pulse width integer value written will be p + n - 1
. Upon return
the buffer's position will be equal to p + n
; its limit will not have changed.
The operation will block until all of the r pulse width values
remaining in the provided src
buffer have been written or otherwise
transferred to the driver/hardware. If this channel uses an internal output buffer and
is therefore working in buffering mode this method will block until all the
r pulse width values have been copied to the internal output buffer.
The pulses will be generated according to the current effective pulse period
as determined by the current scaled pulse period (see getPulsePeriod
)
and the current scale factor getScaleFactor
.
This method may be invoked at any time. If another thread has already initiated a synchronous pulse generation upon this channel, however, then an invocation of this method will block until the first operation is complete.
Only one pulse generation (synchronous or asynchronous) can be going on at any time.
This method does not throw an IllegalArgumentException
if any of the designated pulse width values
is greater than the currently set period. If a pulse width value is not within range
the actual width of the pulse generated by the PWM device is hardware- or driver-specific: the pulse width
may for example be equal to the set period, corresponding to a 100% duty cycle.
If the underlying platform or driver
does not support the requested width value
then the actual width of the pulse generated by the PWM device is hardware- or driver-specific: the pulse width
may, for example, be aligned to the closest lower supported discrete width value.
src
- the buffer from which the scaled pulse width integer values can be retrieved.java.lang.NullPointerException
- If src
is null
.java.lang.IllegalStateException
- if an asynchronous pulse generation is already active.UnavailableDeviceException
- if this device is not currently available - such as it is locked by another application.UnsupportedByteOrderException
- if the byte ordering of the provided buffer is not supported (see Device Byte Order).ClosedDeviceException
- if the device has been closed.java.io.IOException
- if some other I/O error occurs.void startGeneration(int width) throws java.io.IOException, UnavailableDeviceException, ClosedDeviceException
getScaleFactor
.
The pulses will be generated according to the current effective pulse period
as determined by the current scaled pulse period (see getPulsePeriod
)
and the current scale factor getScaleFactor
.
If the underlying platform or driver does not support the requested width value
then width
will be aligned to the closest lower supported discrete width value.
Pulse generation will immediately start and proceed asynchronously. It may be stopped prior to completion by a
call to stopGeneration
.
Only one pulse generation session can be going on at any time.
width
- the scaled pulse width (in microseconds).java.io.IOException
- if some other I/O error occurs.java.lang.IllegalArgumentException
- if width
is equal to or less than
0
or if width
is greater than the currently set period.UnavailableDeviceException
- if this device is not currently available - such as it is locked by another application.ClosedDeviceException
- if the device has been closed.java.lang.IllegalStateException
- if another synchronous or asynchronous generation is already active.void startGeneration(int width, int count, GenerationListener listener) throws java.io.IOException, UnavailableDeviceException, ClosedDeviceException
GenerationListener
instance will be invoked upon completion, that is when
the count of generated pulses reaches the specified count value.
The pulse width value is scaled; the effective pulse width can be calculated
from the currently set scale factor as can be retrieved using getScaleFactor
.
The pulses will be generated according to the current effective pulse period
as determined by the current scaled pulse period (see getPulsePeriod
)
and the current scale factor getScaleFactor
.
If the underlying platform or driver does not support the requested width value
then width
will be aligned to the closest lower supported discrete width value.
Pulse generation will immediately start and proceed asynchronously. It may be stopped prior to completion by a
call to stopGeneration
.
Only one pulse generation session can be going on at any time.
width
- the scaled pulse width (in microseconds).count
- the maximum number of pulses to generate.listener
- the GenerationListener
instance to be notified when the count of generated pulses reaches the
specified count value.java.io.IOException
- if some other I/O error occurs.java.lang.IllegalArgumentException
- if count
is equal to or less than 0
or if width
is equal to or less than
0
or if width
is greater than the currently set period.java.lang.NullPointerException
- if listener
is null
.UnavailableDeviceException
- if this device is not currently available - such as it is locked by another application.ClosedDeviceException
- if the device has been closed.java.lang.IllegalStateException
- if another synchronous or asynchronous generation is already active.void startGeneration(java.nio.IntBuffer src, GenerationRoundListener listener) throws java.io.IOException, UnavailableDeviceException, UnsupportedByteOrderException, ClosedDeviceException
getScaleFactor
.
Additional rounds are asynchronously fetched by notifying the provided GenerationRoundListener
instance once the initial count of pulses have been generated. The widths of the initial pulses to be generated
are read from the provided buffer; the widths of the pulses to generate during the subsequent rounds are read
from that very same buffer upon invocation of the provided GenerationRoundListener
instance.
Pulse generation can be stopped by a call to stopGeneration
.
r integers will be written to this channel, where r is the number of integers remaining in the
buffer (possibly 0
), that is, src.remaining()
, at the moment this method is initially invoked and then subsequently when the listener is returning.
Suppose that an integer sequence of length n is written, where 0 <= n <= r
. This integer
sequence will be transferred from the buffer starting at index p, where p is the buffer's position
at the moment this method is invoked and then subsequently when the listener is returning; the index of the last integer written will be p + n - 1
.
Upon invocation of the listener to fetch the widths of more pulses to generate the buffer's position will be equal to p + n
; its limit will not have changed.
If this channel
uses an internal output buffer and is therefore working in buffering mode the listener will only be
invoked after all the r pulse width values have been copied to the
internal output buffer; otherwise the listener will only be invoked after all the
r pulse width values have been transferred to the driver/hardware.
The buffer's position upon stopping this asynchronous operation by a call to stopGeneration
is not predictable unless called from within the listener.
The pulses will be generated according to the current effective pulse period
as determined by the current scaled pulse period (see getPulsePeriod
)
and the current scale factor getScaleFactor
. The
pulse period can be changed by the provided GenerationRoundListener
instance upon notification of each
pulse train subsequence.
Upon notification of the provided GenerationRoundListener
the reference to the provided src
buffer can be retrieved from the
RoundCompletionEvent
using the getBuffer
method.
A buffer with 0
integers remaining to be written (that is a buffer already empty) at the moment this method is initially
invoked or then subsequently when the listener is returning will not stop the asynchronous operation; the listener is
guaranteed to be called back again at the latest as soon as all other events pending at the time of notification have been dispatched.
The underrun condition resulting from the listener notification
returning with an empty buffer will be reported on the subsequent notifications through
the RoundCompletionEvent.isOnError
method.
Only one pulse generation (synchronous or asynchronous) can be going on at any time.
Buffers are not safe for use by multiple concurrent threads so care should be taken to not access the provided buffer until the operation (or a round thereof) has completed. Interfering with the asynchronous operation by accessing and modifying the provided buffer concurrently may yield unpredictable results.
This method does not throw an IllegalArgumentException
if any of the designated pulse width values
is greater than the currently set period. If a pulse width value is not within range
the actual width of the pulse generated by the PWM device is hardware- or driver-specific: the pulse width
may for example be equal to the set period, corresponding to a 100% duty cycle.
If the underlying platform or driver does not support a requested width value
then the actual width of the pulse generated by the PWM device is hardware- or driver-specific: the pulse width
may, for example, be aligned to the closest lower supported discrete width value.
src
- the buffer from which the scaled pulse width integer values can be retrieved.listener
- the GenerationRoundListener
instance to be notified when pulses have been generated for all
the width values remaining in the buffer.java.lang.NullPointerException
- If src
or listener
is null
.java.lang.IllegalArgumentException
- if the provided buffer src
has a zero-capacity.java.lang.IllegalStateException
- if another synchronous or asynchronous output generation is already active.UnavailableDeviceException
- if this device is not currently available - such as it is locked by another application.UnsupportedByteOrderException
- if the byte ordering of the provided buffers is not supported.ClosedDeviceException
- if the device has been closed.java.io.IOException
- if some other I/O error occurs.void startGeneration(java.nio.IntBuffer src1, java.nio.IntBuffer src2, GenerationRoundListener listener) throws java.io.IOException, UnavailableDeviceException, UnsupportedByteOrderException, ClosedDeviceException
This method behaves identically to startGeneration(IntBuffer, GenerationRoundListener)
excepts that it
uses double-buffering - the provided buffers must not have a zero-capacity and must not overlap
- that is the backing array sections or memory regions they refer to must not overlap.
Notification will happen when pulses have been generated for all the width values
remaining in the current working buffer (initially src1
) and generation will proceed with the alternate buffer (which will become the
current working buffer). Generation will only be suspended if the previous event has not yet been handled. Also,
the position of the current working buffer upon stopping this asynchronous operation by a call to
stopGeneration
is not predictable even if called from within the
listener.
Upon notification of the provided GenerationRoundListener
the reference to the current working buffer (initially src1
) can be retrieved from the
RoundCompletionEvent
using the getBuffer
method.
A working buffer with 0
integers remaining to be written (that is a buffer already empty) at the moment this method is initially
invoked or then subsequently when the listener is returning will not stop the asynchronous operation; the listener is
guaranteed to be called back again at the latest as soon as all other events pending at the time of notification have been dispatched.
The underrun condition resulting from the listener notification
returning with an empty buffer will be reported on the subsequent notifications through
the RoundCompletionEvent.isOnError
method.
Only one pulse generation (synchronous or asynchronous) can be going on at any time.
Buffers are not safe for use by multiple concurrent threads so care should be taken to not access the provided buffers until the operation (or a round thereof) has completed. Interfering with the asynchronous operation by accessing and modifying the provided buffers concurrently may yield unpredictable results.
This method does not throw an IllegalArgumentException
if any of the designated pulse width values
is greater than the currently set period. If a pulse width value is not within range
the actual width of the pulse generated by the PWM device is hardware- or driver-specific: the pulse width
may for example be equal to the set period, corresponding to a 100% duty cycle.
If the underlying platform or driver does not support a requested width value
then the actual width of the pulse generated by the PWM device is hardware- or driver-specific: the pulse width
may, for example, be aligned to the closest lower supported discrete width value.
src1
- the first buffer from which the scaled pulse width integer values can be retrieved.src2
- the second buffer from which the scaled pulse width integer values can be retrieved.listener
- the GenerationRoundListener
instance to be notified when pulses have been generated for all
the width values remaining in the working buffer.java.lang.NullPointerException
- If src1
, src2
or listener
is null
.java.lang.IllegalStateException
- if another synchronous or asynchronous output generation is already active.java.lang.IllegalArgumentException
- if any of the buffers src1
and src2
has a zero-capacity or
if they are the same or overlap.UnavailableDeviceException
- if this device is not currently available - such as it is locked by another application.UnsupportedByteOrderException
- if the byte ordering of the any of the provided buffers is not supported (see Device Byte Order).ClosedDeviceException
- if the device has been closed.java.io.IOException
- if some other I/O error occurs.void stopGeneration() throws java.io.IOException, UnavailableDeviceException, ClosedDeviceException
startGeneration
methods.
This method return silently if no pulse generation session is currently active.
java.io.IOException
- if some other I/O error occurs.UnavailableDeviceException
- if this device is not currently available - such as it is locked by another application.ClosedDeviceException
- if the device has been closed.GPIOPin getOutput()
A concurrent runtime change of the dynamic configuration parameters of the
output (such as of its direction) may result in IOException
being
thrown by PWM operations.
null
if the output is implicit.Copyright © 2012, 2015, Oracle and/or its affiliates. All rights reserved.
Legal Notices