141 lines
4 KiB
Java
141 lines
4 KiB
Java
package de.zuim.ledcontrol;
|
|
|
|
import com.fazecast.jSerialComm.SerialPort;
|
|
import com.fazecast.jSerialComm.SerialPortDataListener;
|
|
import com.fazecast.jSerialComm.SerialPortEvent;
|
|
|
|
import java.awt.*;
|
|
import java.awt.geom.AffineTransform;
|
|
import java.awt.image.AffineTransformOp;
|
|
import java.awt.image.BufferedImage;
|
|
import java.nio.charset.StandardCharsets;
|
|
|
|
public class LEDControl {
|
|
public static final int WIDTH = 32;
|
|
public static final int HEIGHT = 16;
|
|
public static final int LED_NUM = WIDTH * HEIGHT;
|
|
public static final int BAUD = 1000000;
|
|
private static final int FRAME_MS = 40;
|
|
|
|
|
|
private SerialPort port;
|
|
private final byte[][][] leds = new byte[WIDTH][HEIGHT][3];
|
|
private final EffectManager eff;
|
|
private BufferedImage scaledImage;
|
|
|
|
public LEDControl() {
|
|
eff = new EffectManager();
|
|
|
|
Runtime.getRuntime().addShutdownHook(new Thread(() -> port.closePort()));
|
|
|
|
connect();
|
|
|
|
sendLoop();
|
|
}
|
|
|
|
private void sendLoop() {
|
|
long time = System.nanoTime();
|
|
long iteration = 0;
|
|
|
|
long minTimeDelta = Long.MAX_VALUE,
|
|
maxTimeDelta = 0,
|
|
avgTimeDelta = 0;
|
|
|
|
while (true) {
|
|
if (port == null || !port.isOpen()) {
|
|
if (!connect()) {
|
|
sleep(1000);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
long timeDelta = System.nanoTime() - time;
|
|
if (timeDelta > maxTimeDelta)
|
|
maxTimeDelta = timeDelta;
|
|
if (timeDelta < minTimeDelta)
|
|
minTimeDelta = timeDelta;
|
|
avgTimeDelta += timeDelta;
|
|
time = System.nanoTime();
|
|
|
|
renderFrame(timeDelta);
|
|
|
|
port.writeBytes(new byte[]{(byte) 255}, 1); //start of new frame
|
|
|
|
for (int x = 0; x < WIDTH; x++) {
|
|
for (int y = 0; y < HEIGHT; y++) {
|
|
int col = scaledImage.getRGB(x, (x % 2 == 1) ? leds[0].length - y - 1 : y);
|
|
leds[x][y][0] = (byte) Math.min(((col >> 16) & 0xff), 254);
|
|
leds[x][y][1] = (byte) Math.min((col >> 8) & 0xff, 254);
|
|
leds[x][y][2] = (byte) Math.min(((col) & 0xff), 254);
|
|
port.writeBytes(leds[x][y], 3);
|
|
}
|
|
}
|
|
|
|
sleep(FRAME_MS);//(int) (FRAME_MS) - ((System.nanoTime()-time)/1000000)));
|
|
|
|
if (iteration % 1000 == 0 && iteration > 0) {
|
|
System.out.println("Frametime: " + (Math.round(avgTimeDelta / 1000.0) / 100000) / 10.0 + "ms (" + (Math.round(minTimeDelta) / 100000) / 10.0 + "ms - " + (Math.round(maxTimeDelta) / 100000) / 10.0 + "ms) " + iteration + " Frames");
|
|
minTimeDelta = Long.MAX_VALUE;
|
|
maxTimeDelta = 0;
|
|
avgTimeDelta = 0;
|
|
}
|
|
iteration++;
|
|
}
|
|
}
|
|
|
|
private boolean connect() {
|
|
SerialPort[] ports = SerialPort.getCommPorts();
|
|
if (ports.length > 0) {
|
|
port = SerialPort.getCommPorts()[0];
|
|
System.out.println("Connect to " + port.getDescriptivePortName() + " " + port.getSystemPortName() + " ");
|
|
port.setComPortParameters(BAUD, 8, 1, 0);
|
|
if (port.openPort()) {
|
|
port.addDataListener(new SerialPortDataListener() {
|
|
@Override
|
|
public int getListeningEvents() {
|
|
return SerialPort.LISTENING_EVENT_DATA_RECEIVED;
|
|
}
|
|
|
|
@Override
|
|
public void serialEvent(SerialPortEvent event) {
|
|
System.err.println("Received: " + new String(event.getReceivedData(), StandardCharsets.US_ASCII));
|
|
}
|
|
});
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private void sleep(int ms) {
|
|
try {
|
|
Thread.sleep(ms);
|
|
} catch (InterruptedException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
private void renderFrame(long timeDelta) {
|
|
BufferedImage image = new BufferedImage(WIDTH * eff.getActiveEffect().getScale(), HEIGHT * eff.getActiveEffect().getScale(), BufferedImage.TYPE_INT_ARGB);
|
|
Graphics g = image.getGraphics();
|
|
eff.getActiveEffect().render(timeDelta, g);
|
|
g.dispose();
|
|
|
|
if (eff.getActiveEffect().getScale() == 1) {
|
|
scaledImage = image;
|
|
} else {
|
|
scaledImage = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB);
|
|
AffineTransform at = new AffineTransform();
|
|
at.scale(1.0 / eff.getActiveEffect().getScale(), 1.0 / eff.getActiveEffect().getScale());
|
|
AffineTransformOp scaleOp =
|
|
new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);
|
|
scaledImage = scaleOp.filter(image, scaledImage);
|
|
}
|
|
}
|
|
|
|
public static void main(String[] args) {
|
|
new LEDControl();
|
|
}
|
|
}
|