All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jdk.dio.pwm.PWMChannel Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package jdk.dio.pwm;

import java.io.IOException;
import java.nio.IntBuffer;

import jdk.dio.BufferAccess;
import jdk.dio.ClosedDeviceException;
import jdk.dio.Device;
import jdk.dio.DeviceManager;
import jdk.dio.UnavailableDeviceException;
import jdk.dio.UnsupportedByteOrderException;
import jdk.dio.gpio.GPIOPin;

import romizer.WeakDontRenameClass;

/**
 * The {@code 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 {@code PWMChannel} instance can be opened by a call to one of the * {@link DeviceManager#open(int) DeviceManager.open(id,...)} methods using its ID or by a call to one of the * {@link DeviceManager#open(java.lang.String, java.lang.Class, java.lang.String[]) * DeviceManager.open(name,...)} methods using its name. When a {@code PWMChannel} instance is opened with an ad-hoc * {@link PWMChannelConfig} configuration (which includes its hardware addressing information) using one of the * {@link DeviceManager#open(jdk.dio.DeviceConfig) DeviceManager.open(config,...)} methods it is not * assigned any ID nor name. *

* Once opened, an application can set the pulse period using the {@link #setPulsePeriod setPulsePeriod} and then generate a certain * number of pulses of a specified width by calling one of the {@link #generate 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 * {@link #startGeneration(int, int, jdk.dio.pwm.GenerationListener) startGeneration} methods with a * {@link GenerationListener} instance which will get notified upon completion. Such an asynchronous pulse generation * can be stopped or canceled by calling the {@link #stopGeneration 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 {@link #close PWMChannel.close} method to * close the PWM channel. Any further attempt to use a PWM channel which has been closed will result in a * {@link ClosedDeviceException} been thrown. *

* Upon opening a PWM channel the default pulse width and duty cycle are always {@code 0}; the idle * state is platform or configuration-specific. *

Buffered I/O and Direct I/O Transfers

* A PWM channel may support buffered I/O or direct I/O operations depending on * the capabilities of the underlying device hardware and driver.
* Buffered output - output in buffering mode - may be requested by setting the * output buffer size parameter of the {@link PWMChannelConfig} configuration to * a value greater than {@code 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 * {@link PWMChannelConfig#getOutputBufferSize PWMChannelConfig.getOutputBufferSize} method.
* When a PWM channel is not working in buffering mode, direct I/O may be * enabled by providing direct {@code 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 * {@link BufferAccess#prepareBuffer BufferAccess.prepareBuffer}). Output methods * using double buffering may only support efficient direct operations if both * buffers are suitable for such operations. *

Permission Requirement For PWM Channels Configured with an Explicit GPIO Output Pin

* Opening a {@code PWMChannel} instance with an ad-hoc configuration requires * the {@link jdk.dio.pwm.PWMPermission PWMPermission.OPEN} to be granted; * opening an instance of a {@code PWMChannel} configured with an explicit {@code GPIOPin} output * on which the pulses are to be generated requires, in addition, the * {@link jdk.dio.gpio.GPIOPinPermission GPIOPinPermission.OPEN} permission to be granted * on the designated GPIO pin. *

* Opening a {@code 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")
 * 
*
* * @see GenerationListener * @see PWMPermission * @see jdk.dio.gpio.GPIOPinPermission * @since 1.0 */ @apimarker.API("device-io_1.1_pwm") @WeakDontRenameClass public interface PWMChannel extends Device, BufferAccess { /** * Sets the scaled pulse period of this PWM channel. The * effective pulse period is calculated from the * currently set scale factor as can be retrieved using {@link #getScaleFactor 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 {@code period} will be aligned to the closest lower supported discrete period value. The resulting, actual * pulse period can be retrieved by a call to {@link #getPulsePeriod() getPulsePeriod}. * If the current scale factor as returned by * {@link #getScaleFactor getScaleFactor} is {@code scale} and the current scaled * pulse period value - after alignment - is {@code sPeriod} * then the effective pulse period is calculated as follows:

*
*
     * {@code ePeriod = (sPeriod / scale)}
     * 
*
* * @param period * the scaled pulse period as a period in microseconds. * @throws IOException * if some other I/O error occurs. * @throws UnavailableDeviceException * if this device is not currently available - such as it is locked by another application. * @throws ClosedDeviceException * if the device has been closed. * @throws InvalidPulseRateException * if {@code period} is greater than the maximum pulse period (see {@link #getMaxPulsePeriod getMaxPulsePeriod}) * or lower than the minimum pulse period (see {@link #getMinPulsePeriod getMinPulsePeriod}). * @throws IllegalArgumentException * if {@code period} is negative or zero. */ void setPulsePeriod(int period) throws IOException, UnavailableDeviceException, ClosedDeviceException; /** * Gets the scaled pulse period of this PWM channel (in microseconds). The * effective pulse period can then be calculated from the * currently set scale factor as can be retrieved using {@link #getScaleFactor getScaleFactor}. * If the pulse period was not set previously using * {@link #setPulsePeriod 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. * * @return the scaled pulse period (in microseconds). * @throws IOException * if some other I/O error occurs. * @throws UnavailableDeviceException * if this device is not currently available - such as it is locked by another application. * @throws ClosedDeviceException * if the device has been closed. */ int getPulsePeriod() throws IOException, UnavailableDeviceException, ClosedDeviceException; /** * Sets the pulse period scale factor of this PWM channel. * The current * scaled pulse period value is reset to the new resulting minimum scaled pulse period * value. A call to this method should be immediately followed by a call to * the {@link #setPulsePeriod setPulsePeriod} method in order to set * an appropriate scaled pulse period. * * @param factor the scale factor (a number greater or equal to {@code 1.0}). * @throws IllegalArgumentException if {@code factor} is {@link Double#NaN NaN}, is less than {@code 1.0} or, * if the setting of the scale factor would result * in the scaled pulse period range to be outside the range {@code [1 - }{@link Integer#MAX_VALUE}{@code ]}. * @throws IOException if some other I/O error occurs. * @throws UnavailableDeviceException if this device is not currently * available - such as it is locked by another application. * @throws ClosedDeviceException if the device has been closed. * * @see #getScaleFactor * @see #setPulsePeriod */ void setScaleFactor(double factor) throws IOException, UnavailableDeviceException, ClosedDeviceException; /** * Gets the pulse period scale factor of this PWM channel. If the scale * factor is {@code scale} and the scaled pulse period value as * returned by {@link #getPulsePeriod getPulsePeriod} is {@code sPeriod} then the * effective pulse period is calculated as follows:
*
     * {@code ePeriod = (sPeriod / scale)}
     * 
*
* Conversely, the scaled pulse period value to set using * {@link #setPulsePeriod} to obtain the effective pulse * period {@code ePeriod} is calculated as follows:
*
     * {@code sPeriod = (ePeriod * scale)}
     * 
*
* The scale factor also applies to the minimum and maximum scaled pulse periods * as respectively returned by {@link #getMinPulsePeriod getMinPulsePeriod} * and {@link #getMaxPulsePeriod getMaxPulsePeriod}. *

* If the pulse period scale factor was not set previously using * {@link #setScaleFactor setScaleFactor}, the device configuration-specific * default value is returned. *

* * @return the scale factor. * @throws IOException * if some other I/O error occurs. * @throws UnavailableDeviceException * if this device is not currently available - such as it is locked by another * application. * @throws ClosedDeviceException * if the device has been closed. */ double getScaleFactor() throws IOException, UnavailableDeviceException, ClosedDeviceException; /** * Gets the scaled maximum pulse period of this PWM channel (in microseconds) that can bet set by a call to * {@link #setPulsePeriod setPulsePeriod}. The maximum effective pulse period * can be calculated from the currently set scale factor as can be retrieved using * {@link #getScaleFactor getScaleFactor}. * * @return the maximum scaled pulse period (in microseconds). * @throws IOException * if some other I/O error occurs. * @throws UnavailableDeviceException * if this device is not currently available - such as it is locked by another application. * @throws ClosedDeviceException * if the device has been closed. */ int getMaxPulsePeriod() throws IOException, UnavailableDeviceException, ClosedDeviceException; /** * Gets the minimum scaled pulse period of this PWM channel (in microseconds) that can bet set by a call to * {@link #setPulsePeriod setPulsePeriod}. The minimum effective pulse period * can be calculated from the currently set scale factor as can be retrieved using * {@link #getScaleFactor getScaleFactor}. * * @return the minimum scaled pulse period (in microseconds). * @throws IOException * if some other I/O error occurs. * @throws UnavailableDeviceException * if this device is not currently available - such as it is locked by another application. * @throws ClosedDeviceException * if the device has been closed. */ int getMinPulsePeriod() throws IOException, UnavailableDeviceException, ClosedDeviceException; /** * Generates a pulse train containing the specified count of pulses of the specified width. * The pulse width value is scaled; the effective pulse width can be calculated * from the currently set scale factor as can be retrieved using {@link #getScaleFactor getScaleFactor}. *

* To generate pulses of a specific duty cycle {@code 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 {@code width} will be aligned to the closest lower supported discrete width value. *

* The operation will return only after generating all of the {@code count} requested pulses. *

* The pulses will be generated according to the current effective pulse period * as determined by the current scaled pulse period (see {@link #getPulsePeriod getPulsePeriod}) * and the current scale factor {@link #getScaleFactor 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. *

* * @param width * the scaled pulse width (in microseconds). * @param count * the maximum number of pulses to generate. * * @throws IOException * if some other I/O error occurs. * @throws IllegalArgumentException * if {@code width} or {@code count} is equal to or less than {@code 0} or if {@code width} is greater * than the currently set period. * @throws UnavailableDeviceException * if this device is not currently available - such as it is locked by another application. * @throws ClosedDeviceException * if the device has been closed. * @throws IllegalStateException * if an asynchronous pulse generation session is already active. */ void generate(int width, int count) throws IOException, UnavailableDeviceException, ClosedDeviceException; /** * Generates a pulse train from the specified sequence of pulse widths. The provided buffer contains the * scaled widths of the pulses to generate; the effective pulse widths can be calculated * from the currently set scale factor as can be retrieved using {@link #getScaleFactor getScaleFactor}. *

* r pulses will be generated by this channel, where r is the number of integers (pulse widths) * remaining in the buffer, that is, {@code src.remaining()}, at the moment this method is invoked. *

* Suppose that a pulse width integer value sequence of length n is provided, where {@code 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 {@code p + n - 1}. Upon return * the buffer's position will be equal to {@code p + n}; its limit will not have changed. *
* The operation will block until all of the r pulse width values * remaining in the provided {@code 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 {@link #getPulsePeriod getPulsePeriod}) * and the current scale factor {@link #getScaleFactor 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 {@link 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. *

* * @param src * the buffer from which the scaled pulse width integer values can be retrieved. * @throws NullPointerException * If {@code src} is {@code null}. * @throws IllegalStateException * if an asynchronous pulse generation is already active. * @throws UnavailableDeviceException * if this device is not currently available - such as it is locked by another application. * @throws UnsupportedByteOrderException * if the byte ordering of the provided buffer is not supported (see Device Byte Order). * @throws ClosedDeviceException * if the device has been closed. * @throws IOException * if some other I/O error occurs. */ void generate(IntBuffer src) throws IOException, UnavailableDeviceException, UnsupportedByteOrderException, ClosedDeviceException; /** * Starts an asynchronous pulse train generation session - continuously generating pulses of the specified width * until explicitly stopped. * The pulse width value is scaled; the effective pulse width can be calculated * from the currently set scale factor as can be retrieved using {@link #getScaleFactor getScaleFactor}. *

* The pulses will be generated according to the current effective pulse period * as determined by the current scaled pulse period (see {@link #getPulsePeriod getPulsePeriod}) * and the current scale factor {@link #getScaleFactor getScaleFactor}. *

* If the underlying platform or driver does not support the requested width value * then {@code 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 {@link #stopGeneration stopGeneration}. *

* Only one pulse generation session can be going on at any time. *

* * @param width * the scaled pulse width (in microseconds). * * @throws IOException * if some other I/O error occurs. * @throws IllegalArgumentException * if {@code width} is equal to or less than * {@code 0} or if {@code width} is greater than the currently set period. * @throws UnavailableDeviceException * if this device is not currently available - such as it is locked by another application. * @throws ClosedDeviceException * if the device has been closed. * @throws IllegalStateException * if another synchronous or asynchronous generation is already active. */ void startGeneration(int width) throws IOException, UnavailableDeviceException, ClosedDeviceException; /** * Starts an asynchronous pulse train generation session - generating pulses of the specified width up to the * specified count. The provided {@link 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 {@link #getScaleFactor getScaleFactor}. *

* The pulses will be generated according to the current effective pulse period * as determined by the current scaled pulse period (see {@link #getPulsePeriod getPulsePeriod}) * and the current scale factor {@link #getScaleFactor getScaleFactor}. *

* If the underlying platform or driver does not support the requested width value * then {@code 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 {@link #stopGeneration stopGeneration}. *

* Only one pulse generation session can be going on at any time. *

* * @param width * the scaled pulse width (in microseconds). * @param count * the maximum number of pulses to generate. * @param listener * the {@link GenerationListener} instance to be notified when the count of generated pulses reaches the * specified count value. * * @throws IOException * if some other I/O error occurs. * @throws IllegalArgumentException * if {@code count} is equal to or less than {@code 0} or if {@code width} is equal to or less than * {@code 0} or if {@code width} is greater than the currently set period. * @throws NullPointerException * if {@code listener} is {@code null}. * @throws UnavailableDeviceException * if this device is not currently available - such as it is locked by another application. * @throws ClosedDeviceException * if the device has been closed. * @throws IllegalStateException * if another synchronous or asynchronous generation is already active. */ void startGeneration(int width, int count, GenerationListener listener) throws IOException, UnavailableDeviceException, ClosedDeviceException; /** * 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. The provided buffer contains the scaled widths of the pulses to generate; the effective * pulse widths can be calculated from the currently set scale factor as can be retrieved using * {@link #getScaleFactor getScaleFactor}. * Additional rounds are asynchronously fetched by notifying the provided {@link 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 {@link GenerationRoundListener} instance. *

* Pulse generation can be stopped by a call to {@link #stopGeneration stopGeneration}. *

* r integers will be written to this channel, where r is the number of integers remaining in the * buffer (possibly {@code 0}), that is, {@code 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 {@code 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 {@code 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 {@code 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 {@link #stopGeneration 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 {@link #getPulsePeriod getPulsePeriod}) * and the current scale factor {@link #getScaleFactor getScaleFactor}. The * pulse period can be changed by the provided {@link GenerationRoundListener} instance upon notification of each * pulse train subsequence. *

* Upon notification of the provided {@code GenerationRoundListener} * the reference to the provided {@code src} buffer can be retrieved from the * {@code RoundCompletionEvent} using the {@link jdk.dio.RoundCompletionEvent#getBuffer() getBuffer} method. *
* A buffer with {@code 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 {@link jdk.dio.RoundCompletionEvent#isOnError() 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 {@link 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. *

* * @param src * the buffer from which the scaled pulse width integer values can be retrieved. * @param listener * the {@link GenerationRoundListener} instance to be notified when pulses have been generated for all * the width values remaining in the buffer. * @throws NullPointerException * If {@code src} or {@code listener} is {@code null}. * @throws IllegalArgumentException * if the provided buffer {@code src} has a zero-capacity. * @throws IllegalStateException * if another synchronous or asynchronous output generation is already active. * @throws UnavailableDeviceException * if this device is not currently available - such as it is locked by another application. * @throws UnsupportedByteOrderException * if the byte ordering of the provided buffers is not supported. * @throws ClosedDeviceException * if the device has been closed. * @throws IOException * if some other I/O error occurs. */ void startGeneration(IntBuffer src, GenerationRoundListener listener) throws IOException, UnavailableDeviceException, UnsupportedByteOrderException, ClosedDeviceException; /** * Starts asynchronous pulse train generation in successive rounds. *

* This method behaves identically to {@link #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 {@code 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 * {@link #stopGeneration stopGeneration} is not predictable even if called from within the * listener. *

* Upon notification of the provided {@code GenerationRoundListener} * the reference to the current working buffer (initially {@code src1}) can be retrieved from the * {@code RoundCompletionEvent} using the {@link jdk.dio.RoundCompletionEvent#getBuffer() getBuffer} method. *
* A working buffer with {@code 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 {@link jdk.dio.RoundCompletionEvent#isOnError() 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 {@link 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. *

* * @param src1 * the first buffer from which the scaled pulse width integer values can be retrieved. * @param src2 * the second buffer from which the scaled pulse width integer values can be retrieved. * @param listener * the {@link GenerationRoundListener} instance to be notified when pulses have been generated for all * the width values remaining in the working buffer. * @throws NullPointerException * If {@code src1}, {@code src2} or {@code listener} is {@code null}. * @throws IllegalStateException * if another synchronous or asynchronous output generation is already active. * @throws IllegalArgumentException * if any of the buffers {@code src1} and {@code src2} has a zero-capacity or * if they are the same or overlap. * @throws UnavailableDeviceException * if this device is not currently available - such as it is locked by another application. * @throws UnsupportedByteOrderException * if the byte ordering of the any of the provided buffers is not supported (see Device Byte Order). * @throws ClosedDeviceException * if the device has been closed. * @throws IOException * if some other I/O error occurs. */ void startGeneration(IntBuffer src1, IntBuffer src2, GenerationRoundListener listener) throws IOException, UnavailableDeviceException, UnsupportedByteOrderException, ClosedDeviceException; /** * Stops (cancels) the currently active pulse generation session as started by a call to one * of the {@link #startGeneration startGeneration} methods. *

* This method return silently if no pulse generation session is currently active. *

* * @throws IOException * if some other I/O error occurs. * @throws UnavailableDeviceException * if this device is not currently available - such as it is locked by another application. * @throws ClosedDeviceException * if the device has been closed. */ void stopGeneration() throws IOException, UnavailableDeviceException, ClosedDeviceException; /** * Gets the output on which the pulses are generated. *

* A concurrent runtime change of the dynamic configuration parameters of the * output (such as of its direction) may result in {@code IOException} being * thrown by PWM operations. *

* * @return the output on which the pulses are generated; or {@code null} if the output is implicit. * * @since 1.1 */ GPIOPin getOutput(); }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy