package ioio.lib.impl; import ioio.lib.api.PulseInput; import ioio.lib.api.exception.ConnectionLostException; import ioio.lib.impl.IncomingState.DataModuleListener; import java.util.LinkedList; import java.util.Queue; class IncapImpl extends AbstractPin implements DataModuleListener, PulseInput { private static final int MAX_QUEUE_LEN = 32; private final PulseMode mode_; private final int incapNum_; private long lastDuration_; private final float timeBase_; private final boolean doublePrecision_; private boolean valid_ = false; // TODO: a fixed-size array would have been much better than a linked list. private Queue<Long> pulseQueue_ = new LinkedList<Long>(); public IncapImpl(IOIOImpl ioio, PulseMode mode, int incapNum, int pin, int clockRate, int scale, boolean doublePrecision) throws ConnectionLostException { super(ioio, pin); mode_ = mode; incapNum_ = incapNum; timeBase_ = 1.0f / (scale * clockRate); doublePrecision_ = doublePrecision; } @Override public float getFrequency() throws InterruptedException, ConnectionLostException { if (mode_ != PulseMode.FREQ && mode_ != PulseMode.FREQ_SCALE_4 && mode_ != PulseMode.FREQ_SCALE_16) { throw new IllegalStateException( "Cannot query frequency when module was not opened in frequency mode."); } return 1.0f / getDuration(); } @Override public synchronized float getDuration() throws InterruptedException, ConnectionLostException { checkState(); while (!valid_) { wait(); checkState(); } return timeBase_ * lastDuration_; } @Override public synchronized float waitPulseGetDuration() throws InterruptedException, ConnectionLostException { if (mode_ != PulseMode.POSITIVE && mode_ != PulseMode.NEGATIVE) { throw new IllegalStateException( "Cannot wait for pulse when module was not opened in pulse mode."); } checkState(); while (pulseQueue_.isEmpty() && state_ == State.OPEN) { wait(); } checkState(); return timeBase_ * pulseQueue_.remove(); } @Override public synchronized void dataReceived(byte[] data, int size) { lastDuration_ = ByteArrayToLong(data, size); if (pulseQueue_.size() == MAX_QUEUE_LEN) { pulseQueue_.remove(); } pulseQueue_.add(lastDuration_); valid_ = true; notifyAll(); } private static long ByteArrayToLong(byte[] data, int size) { long result = 0; int i = size; while (i-- > 0) { result <<= 8; result |= ((int) data[i]) & 0xFF; } if (result == 0) { result = 1 << (size * 8); } return result; } @Override public synchronized void reportAdditionalBuffer(int bytesToAdd) { } @Override public synchronized void close() { ioio_.closeIncap(incapNum_, doublePrecision_); super.close(); } @Override public synchronized void disconnected() { notifyAll(); super.disconnected(); } }