jdk.dio.dac.DACChannel Maven / Gradle / Ivy
Show all versions of org.openjdk.dio Show documentation
/*
* 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.dac;
import jdk.dio.*;
import java.io.IOException;
import java.nio.IntBuffer;
import romizer.WeakDontRenameClass;
/**
* The {@code DACChannel} interface provides methods for controlling a DAC (Digital to Analog
* Converter) channel.
*
* One DAC device can have several channels. Raw digital output values (samples) are converted to
* analog output values according to the DAC channel resolution. The raw digital output values may
* range from {@link #getMinValue getMinValue} to {@link #getMaxValue getMaxValue}. Actual output
* voltage values can be calculated from the raw digital output values and the
* Reference Voltage value as returned by {@link #getVRefValue getVRefValue}.
*
* A DAC channel may be identified by the numeric ID and by the name (if any defined) that
* correspond to its registered configuration. A {@code DACChannel} 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 DACChannel} instance is
* opened with an ad-hoc {@link DACChannelConfig} 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 write an output value to a DAC channel by calling the
* {@link #generate(int) generate(int)} method or can write a series of output values to be
* converted over a period of time by calling the {@link #generate(IntBuffer) generate(IntBuffer)}
* method.
*
* An application can also asynchronously write a series of output values (samples) to be converted
* at a certain rate by calling the {@link #startGeneration(IntBuffer, GenerationRoundListener)
* startGeneration} method with a {@link GenerationRoundListener} instance which will get cyclicly
* and asynchronously invoked to fetch more values to be converted. Analog output generation can be
* stopped by calling the {@link #stopGeneration stopGeneration} method.
*
* Only one output generation (synchronous or asynchronous) can be going on at any time.
*
* When an application is no longer using an DAC channel it should call the {@link #close close}
* method to close the DAC channel. Any further attempt to set or get the value of a DAC channel
* which has been closed will result in a {@link ClosedDeviceException} been thrown.
*
* Asynchronous notification of output generation completion is only loosely tied to
* hardware-level interrupt requests. The platform does not guarantee notification in a
* deterministic/timely manner.
* Buffered I/O and Direct I/O Transfers
* A DAC 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 DACChannelConfig} 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 DACChannelConfig#getOutputBufferSize DACChannelConfig.getOutputBufferSize} method.
* When a DAC 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.
*
* @see GenerationRoundListener
* @since 1.0
*/
@apimarker.API("device-io_1.1_dac")
@WeakDontRenameClass
public interface DACChannel extends Device, BufferAccess {
/**
* Returns the maximum raw value this channel can convert. If the DAC device resolution is
* {@code n} then the {@code min} value returned by {@link #getMinValue getMinValue} and the
* {@code max} value returned by {@link #getMaxValue getMaxValue} are such that:
*
*
* {@code (max - min) == (2^n - 1)}.
*
*
*
*
* @return the maximum raw value this channel can convert.
* @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 getMaxValue() throws IOException, UnavailableDeviceException, ClosedDeviceException;
/**
* Gets the minimum scaled output sampling interval (in microseconds) that can be set using
* {@link #setSamplingInterval setSamplingInterval}. The minimum effective sampling interval
* can be calculated from the currently set scale factor as can be retrieved using
* {@link #getScaleFactor getScaleFactor}.
*
* @return the minimum scaled output sampling interval (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 getMinSamplingInterval() throws IOException, UnavailableDeviceException, ClosedDeviceException;
/**
* Gets the maximum scaled output sampling interval (in microseconds) that can be set using
* {@link #setSamplingInterval setSamplingInterval}. The maximum effective sampling interval
* can be calculated from the currently set scale factor as can be retrieved using
* {@link #getScaleFactor getScaleFactor}.
*
* @return the maximum scaled output sampling interval (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.
* @since 1.1
*/
int getMaxSamplingInterval() throws IOException, UnavailableDeviceException, ClosedDeviceException;
/**
* Returns the minimum raw value this channel can convert. If the DAC device resolution is
* {@code n} then the {@code min} value returned by {@link #getMinValue getMinValue} and the
* {@code max} value returned by {@link #getMaxValue getMaxValue} are such that:
*
*
* {@code (max - min) == (2^n - 1)}.
*
*
*
*
* @return the minimum raw value this channel can convert.
* @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 getMinValue() throws IOException, UnavailableDeviceException, ClosedDeviceException;
/**
* Gets the scaled output sampling interval (in microseconds). The
* effective sampling interval can then be calculated from the
* currently set scale factor as can be retrieved using {@link #getScaleFactor getScaleFactor}.
* If the sampling interval was not
* set previously using {@link #setSamplingInterval setSamplingInterval}, 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 sampling interval values supported by the underlying platform or driver.
*
* @return the scaled output sampling interval (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 getSamplingInterval() throws IOException, UnavailableDeviceException, ClosedDeviceException;
/**
* Returns the Reference Voltage value of this DAC channel. If the reference voltage is
* {@code vRef} and the DAC device resolution is {@code n} then the actual output voltage value
* corresponding to a raw value {@code value} written to this channel can be calculated as
* follows:
*
*
* {@code vOutput = (value * vRef) / (2^n)}
*
*
*
*
* @return the Reference Voltage value of this channel.
* @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 getVRefValue() throws IOException, UnavailableDeviceException, ClosedDeviceException;
/**
* Sets the sampling interval scale factor of this DAC channel.
* The current
* scaled sampling interval value is reset to the new resulting minimum scaled sampling interval
* value. A call to this method should be immediately followed by a call to
* the {@link #setSamplingInterval setSamplingInterval} method in order to set
* an appropriate scaled sampling interval.
*
* @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 sampling interval 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 #setSamplingInterval
*/
void setScaleFactor(double factor) throws IOException, UnavailableDeviceException, ClosedDeviceException;
/**
* Gets the sampling interval scale factor of this DAC channel. If the scale
* factor is {@code scale} and the scaled sampling interval value as
* returned by {@link #getSamplingInterval getSamplingInterval} is {@code sInterval} then the
* effective sampling interval is calculated as follows:
*
* {@code eInterval = (sInterval / scale)}
*
*
* Conversely, the scaled sampling interval value to set using
* {@link #setSamplingInterval} to obtain the effective sampling
* interval {@code eInterval} is calculated as follows:
*
* {@code sInterval = (eInterval * scale)}
*
*
*
* The scale factor also applies to the minimum and maximum scaled sampling intervals
* as respectively returned by {@link #getMinSamplingInterval getMinSamplingInterval}
* and {@link #getMaxSamplingInterval getMaxSamplingInterval}.
*
* If the sampling interval 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;
/**
* Sets the scaled output sampling interval (in microseconds). The
* effective sampling interval is calculated from the
* currently set scale factor as can be retrieved using {@link #getScaleFactor getScaleFactor}.
* Whether changing the sampling interval
* 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 interval value
* then {@code interval} will be aligned to the closest lower supported discrete interval value. The resulting, actual
* scaled sampling interval can be retrieved by a call to {@link #getSamplingInterval getSamplingInterval}.
* If the current scale factor as returned by
* {@link #getScaleFactor getScaleFactor} is {@code scale} and the current scaled
* sampling interval value - after alignment - is {@code sInterval}
* then the effective sampling interval can be calculated as follows:
*
*
* {@code eInterval = (sInterval / scale)}
*
*
*
* @param interval
* the scaled output sampling interval (in microseconds).
* @throws IOException
* if some other I/O error occurs.
* @throws InvalidOutputSamplingRateException
* if {@code interval} is greater than the maximum sampling interval (see {@link #getMaxSamplingInterval getMaxSamplingInterval})
* or lower than the minimum sampling interval (see {@link #getMinSamplingInterval getMinSamplingInterval}).
* @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 IllegalArgumentException
* if {@code interval} is negative or zero.
*/
void setSamplingInterval(int interval) throws IOException, UnavailableDeviceException,
ClosedDeviceException;
/**
* Writes the provided raw output value to this channel. The corresponding converted analog
* output value will be held until it is overwritten by another output generation.
*
* This method may be invoked at any time. If another thread has already initiated a synchronous
* output generation upon this channel then an invocation of this method will block until the
* first operation is complete.
*
* Only one output generation (synchronous or asynchronous) can be going on at any time.
*
*
* @param value
* the raw value to be output.
* @throws IOException
* if some other I/O error occurs.
* @throws IllegalArgumentException
* if the provided raw value is not within the range defined by
* {@link #getMinValue getMinValue} and {@link #getMaxValue getMaxValue}.
* @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 output generation is already active.
*/
void generate(int value) throws IOException, UnavailableDeviceException, ClosedDeviceException;
/**
* Writes a sequence of raw output values from the provided buffer to this channel for
* conversion.
*
* The raw output values will be converted according to the current effective output sampling interval
* as determined by the current scaled sampling interval (see {@link #getSamplingInterval getSamplingInterval})
* and the current scale factor {@link #getScaleFactor getScaleFactor}.
*
* r integers will be written to this channel, where r is the number of integers
* remaining in the buffer, that is, {@code src.remaining()}, at the moment this method is
* invoked.
*
* 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; the index of
* the last integer 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.
* This operation will return only after all of the r raw output 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 raw output values have been copied to the internal output buffer.
*
* 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.
*
* This method may be invoked at any time. If another thread has already initiated a synchronous
* output generation upon this channel, however, then an invocation of this method will block
* until the first operation is complete.
*
* Only one output generation (synchronous or asynchronous) can be going on at any time.
*
* This method does not throw an {@link IllegalArgumentException} if any of the
* designated raw values is not within the range defined by {@link #getMinValue getMinValue}
* and {@link #getMaxValue getMaxValue}. If a value is not within range the actual analog value
* output by the DAC device is hardware- or driver-specific: the output value may for example be
* equal to the maximum output value or it may correspond to the raw value where the most
* significant bits beyond the {@code n} bits of the DAC device resolution have been truncated.
*
*
* @param src
* the buffer from which the integer raw values can be retrieved.
* @throws NullPointerException
* If {@code src} is {@code null}.
* @throws IllegalStateException
* if an 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 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 asynchronous analog output generation on this channel from a series of raw output
* values (samples). More values to be converted are asynchronously fetched by notifying the
* provided {@link GenerationRoundListener} instance once the whole sequence of raw output values have
* been converted. The raw output values to be converted are read from the provided buffer.
*
* Analog output 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 more values to convert the
* buffer's position will be equal to {@code p + n}; its limit will not have changed.
* 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.
* 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 raw output values have been copied to the
* internal output buffer; otherwise the listener will only be invoked after all the
* r raw output values have been transferred to the driver/hardware.
*
* The raw output values will be converted according to the current effective output sampling interval
* as determined by the current scaled sampling interval (see {@link #getSamplingInterval getSamplingInterval})
* and the current scale factor {@link #getScaleFactor getScaleFactor}.
*
* 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 output 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 raw values is not within the range defined by {@link #getMinValue getMinValue}
* and {@link #getMaxValue getMaxValue}. If a value is not within range the actual analog value
* output by the DAC device is hardware- or driver-specific: the output value may for example be
* equal to the maximum output value or it may correspond to the raw value where the most
* significant bits beyond the {@code n} bits of the DAC device resolution have been truncated.
*
*
* @param src
* the buffer from which the integer raw sampled output values are to be retrieved.
* @param listener
* the {@link GenerationRoundListener} instance to be notified when all the output
* values have been converted.
* @throws NullPointerException
* If {@code src} or {@code listener} is {@code null}.
* @throws IllegalStateException
* if another synchronous or asynchronous output generation is already active.
* @throws IllegalArgumentException
* if the provided buffer {@code src} has a zero-capacity.
* @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 startGeneration(IntBuffer src, GenerationRoundListener listener) throws IOException,
UnavailableDeviceException, UnsupportedByteOrderException, ClosedDeviceException;
/**
* Starts asynchronous analog output generation on this channel from a series of raw output
* values (samples).
*
* 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 all the raw output values remaining in the
* current working buffer (initially {@code src1}) have been converted and conversion will
* proceed with the alternate buffer (which will become the current working buffer). Conversion
* 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 output 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 raw values is not within the range defined by {@link #getMinValue getMinValue}
* and {@link #getMaxValue getMaxValue}. If a value is not within range the actual analog value
* output by the DAC device is hardware- or driver-specific: the output value may for example be
* equal to the maximum output value or it may correspond to the raw value where the most
* significant bits beyond the {@code n} bits of the DAC device resolution have been truncated.
*
*
* @param src1
* the first buffer from which the integer raw sampled output values are to be
* retrieved.
* @param src2
* the second buffer from which the integer raw sampled output values are to be
* retrieved.
* @param listener
* the {@link GenerationRoundListener} instance to be notified when all the output
* values have been converted.
* @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 the asynchronous analog output generation on this channel as started by a call to one
* of the {@link #startGeneration startGeneration} methods.
*
* This method return silently if no asynchronous analog output generation 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;
}