/* * Copyright 2015-2016 Cel Skeggs * * This file is part of the CCRE, the Common Chicken Runtime Engine. * * The CCRE is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * The CCRE 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 Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with the CCRE. If not, see <http://www.gnu.org/licenses/>. */ package ccre.frc; import java.io.IOException; import ccre.bus.RS232IO; import ccre.bus.RS232Bus.Parity; import ccre.bus.RS232Bus.StopBits; final class RS232Direct implements RS232IO { private boolean closed; private final byte port; RS232Direct(byte port, int baudRate, Parity parity, StopBits stopBits, float timeout, int dataBits) { this.port = port; DirectRS232.init(port, baudRate, dataBits, parityToByte(parity), stopBitsToByte(stopBits), timeout); } private byte parityToByte(Parity parity) { switch (parity) { case PARITY_EVEN: return DirectRS232.PARITY_EVEN; case PARITY_MARK: return DirectRS232.PARITY_MARK; case PARITY_NONE: return DirectRS232.PARITY_NONE; case PARITY_ODD: return DirectRS232.PARITY_ODD; case PARITY_SPACE: return DirectRS232.PARITY_SPACE; default: throw new IllegalArgumentException("Invalid parity: " + parity); } } private byte stopBitsToByte(StopBits stopBits) { switch (stopBits) { case STOP_ONE: return DirectRS232.STOP_ONE; case STOP_ONE_POINT_FIVE: return DirectRS232.STOP_ONE_POINT_FIVE; case STOP_TWO: return DirectRS232.STOP_TWO; default: throw new IllegalArgumentException("Invalid stop bits: " + stopBits); } } public void setTermination(Character end) throws IOException { if (closed) { throw new IOException("SerialIO closed."); } DirectRS232.setTermination(port, end); } public byte[] readBlocking(int max) throws IOException { if (closed) { throw new IOException("SerialIO closed."); } if (max <= 0) { return new byte[0]; } int ready = DirectRS232.getBytesReceived(port); if (ready <= 0) { byte[] gotten = DirectRS232.read(port, 1); while (gotten.length == 0) { // block for minimal amount of time if any data has been // received gotten = DirectRS232.read(port, 1); } ready = DirectRS232.getBytesReceived(port); if (max == 1 || ready <= 0) { return gotten; } byte[] rest = DirectRS232.read(port, Math.min(ready, max)); byte[] out = new byte[rest.length + 1]; out[0] = gotten[0]; System.arraycopy(rest, 0, out, 1, rest.length); return out; } else { return DirectRS232.read(port, Math.min(ready, max)); } } @Override public boolean hasAvailableBytes() throws IOException { return DirectRS232.getBytesReceived(port) > 0; } public byte[] readNonblocking(int max) throws IOException { if (closed) { throw new IOException("SerialIO closed."); } int count = Math.min(DirectRS232.getBytesReceived(port), max); return count <= 0 ? new byte[0] : DirectRS232.read(port, count); } public void flush() throws IOException { if (closed) { throw new IOException("SerialIO closed."); } DirectRS232.flush(port); } public void setFlushOnWrite(boolean flushOnWrite) throws IOException { if (closed) { throw new IOException("SerialIO closed."); } DirectRS232.setWriteBufferMode(port, flushOnWrite ? DirectRS232.FLUSH_ON_ACCESS : DirectRS232.FLUSH_WHEN_FULL); } public void writeFully(byte[] bytes, int from, int to) throws IOException { if (closed) { throw new IOException("SerialIO closed."); } if (from != 0) { System.arraycopy(bytes, from, bytes, 0, to - from); } int remaining = to - from; while (true) { int done = DirectRS232.write(port, bytes, remaining); if (done >= remaining) { break; } if (closed) { throw new IOException("SerialIO closed."); } remaining -= done; System.arraycopy(bytes, done, bytes, 0, remaining); } } public int writePartial(byte[] bytes, int from, int to) throws IOException { if (closed) { throw new IOException("SerialIO closed."); } if (from != 0) { System.arraycopy(bytes, from, bytes, 0, to - from); } return DirectRS232.write(port, bytes, to - from); } @Override public void resetSerial() throws IOException { if (closed) { throw new IOException("SerialIO closed."); } DirectRS232.clear(port); } public void close() throws IOException { if (!closed) { closed = true; flush(); DirectRS232.close(port); } // TODO: Provide access to the other method of SerialPort? } }