Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

migrated to the jSerialComm backed, added support for interrupts #2

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,5 @@ buildNumber.properties
/copybin.sh
/Digital.sh
/upload.sh

*.bak
Binary file modified Digital.jar
Binary file not shown.
11 changes: 8 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@
<dependencies>

<dependency>
<groupId>com.neuronrobotics</groupId>
<artifactId>nrjavaserial</artifactId>
<version>3.11.0</version>
<groupId>com.fazecast</groupId>
<artifactId>jSerialComm</artifactId>
<version>[2.0.0,3.0.0)</version>
</dependency>

<dependency>
Expand All @@ -82,6 +82,11 @@
<version>4.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>
</dependencies>


Expand Down
22 changes: 22 additions & 0 deletions src/main/java/de/neemann/digital/plugin/COMInterface.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,26 @@ public interface COMInterface {
* Closes the port.
*/
void close();

/**
* Checks if there is new data in the receive buffer
*
* @return true if new data is available
*/
boolean available();

/**
* Subscribes a DataAvailInterface object which will be notified when new data is received from the
* serial port
*
* @param sub the observer object
*/
void subscribeToDataAvail(DataAvailInterface sub);

/**
* Unsubscribes a previously subscribed DataAvailInterface
*
* @param sub the observer object
*/
void unSubscribeToDataAvail(DataAvailInterface sub);
}
21 changes: 14 additions & 7 deletions src/main/java/de/neemann/digital/plugin/ComPort.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
import de.neemann.digital.core.*;
import de.neemann.digital.core.element.*;

import javax.swing.*;

import static de.neemann.digital.core.element.PinInfo.input;

/**
* A simple ComPort
*/
public class ComPort extends Node implements Element {
public class ComPort extends Node implements Element, DataAvailInterface {

private static final Key<String> COM_PORT =
new Key<>("comPort", "/dev/ttyUSB0")
Expand Down Expand Up @@ -61,7 +63,7 @@ public String getDescription(ElementAttributes elementAttributes) {
*/
public ComPort(ElementAttributes attr) {
d_out = new ObservableValue("D_r", 8).setDescription("Data read from the physical port.");
avail = new ObservableValue("av", 1).setDescription("If set to one there was data available. Valid only if rd=1 and c is rising.");
avail = new ObservableValue("av", 1).setDescription("If set to one there is data available.");
portName = attr.get(COM_PORT);
baudRate = attr.get(BAUD_RATE);
comData = -1;
Expand Down Expand Up @@ -91,11 +93,10 @@ public void readInputs() {
public void writeOutputs() {
if (comData < 0) {
d_out.setToHighZ();
avail.setBool(false);
} else {
d_out.setValue(comData);
avail.setBool(true);
}
avail.setBool(comInterface.available());
}

@Override
Expand All @@ -113,10 +114,16 @@ public ObservableValues getOutputs() {

@Override
public void init(Model model) throws NodeException {
comInterface = new RxTxComPort(portName, baudRate);
comInterface = new de.neemann.digital.plugin.JSerialComPort(portName, baudRate);
comInterface.subscribeToDataAvail(this);
model.addObserver(modelEvent -> {
if (modelEvent.equals(ModelEvent.STOPPED))
if (modelEvent.equals(ModelEvent.CLOSED))
comInterface.close();
}, ModelEvent.STOPPED);
}, ModelEvent.CLOSED.getType());
}

@Override
public void onDataAvailable() {
getModel().modify(this::hasChanged);
}
}
13 changes: 13 additions & 0 deletions src/main/java/de/neemann/digital/plugin/DataAvailInterface.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package de.neemann.digital.plugin;

/**
* Abstraction allowing asynchronous events upon incoming data
*/
public interface DataAvailInterface {

/**
* Triggered when new data is received
*/
void onDataAvailable();

}
126 changes: 126 additions & 0 deletions src/main/java/de/neemann/digital/plugin/JSerialComPort.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package de.neemann.digital.plugin;

import de.neemann.digital.core.NodeException;
import com.fazecast.jSerialComm.*;
import org.apache.commons.collections.Buffer;
import org.apache.commons.collections.BufferUtils;
import org.apache.commons.collections.buffer.CircularFifoBuffer;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

public class JSerialComPort implements COMInterface, SerialPortDataListener {
private final SerialPort serialPort;
private final OutputStream outputStream;
private final InputStream inputStream;
private final Buffer cache;
private final List<DataAvailInterface> datasubs;

public JSerialComPort(String portName, int baudRate) throws NodeException {
cache = BufferUtils.synchronizedBuffer(new CircularFifoBuffer(1024));

try {
serialPort = SerialPort.getCommPort(portName);
} catch (SerialPortInvalidPortException e) {
throw new NodeException("Port " + portName + " is in invalid!");
}

if (!serialPort.setComPortParameters(baudRate,
8,
SerialPort.ONE_STOP_BIT,
SerialPort.NO_PARITY)) {
serialPort.closePort();
throw new NodeException("Invalid parameter for port " + portName + "!");
}

if (!serialPort.openPort()) {
throw new NodeException("Cannot open port " + portName + "!");
}

inputStream = serialPort.getInputStream();
outputStream = serialPort.getOutputStream();
serialPort.addDataListener(this);
datasubs = new ArrayList<>();
}

private NodeException createNodeException(String message, Exception e) {
String m = e.getMessage();
if (m == null || m.length() == 0)
return new NodeException(message + ": " + e.getClass().getSimpleName(), e);
else
return new NodeException(message, e);
}

@Override
public void write(int data) {
if (outputStream != null) {
try {
outputStream.write(data);
} catch (IOException e) {
e.printStackTrace();
}
}
}

@Override
public int readData() {
if (!cache.isEmpty()) {
return (int) cache.remove();
}
return -1;
}

@Override
public void close() {
if (serialPort != null) {
datasubs.clear();
serialPort.removeDataListener();
serialPort.closePort();
}
}

@Override
public boolean available() {
return !cache.isEmpty();
}

@Override
public int getListeningEvents() {
return SerialPort.LISTENING_EVENT_DATA_AVAILABLE;
}

@Override
public void serialEvent(SerialPortEvent serialPortEvent) {
if (serialPortEvent.getEventType() != SerialPort.LISTENING_EVENT_DATA_AVAILABLE) return;

for (int i=0; i<serialPort.bytesAvailable(); i++) {
try {
int datum = inputStream.read();
if (datum >= 0) {
cache.add(datum);
}
} catch (IOException e) {
return;
}
}

if (!cache.isEmpty()) {
for (DataAvailInterface sub : datasubs) {
sub.onDataAvailable();
}
}
}

@Override
public void subscribeToDataAvail(DataAvailInterface sub) {
datasubs.add(sub);
}

@Override
public void unSubscribeToDataAvail(DataAvailInterface sub) {
datasubs.remove(sub);
}
}
136 changes: 0 additions & 136 deletions src/main/java/de/neemann/digital/plugin/RxTxComPort.java

This file was deleted.