/*- * Send an image through a train by toggling a motorized junction * * See http://www.spinellis.gr/itrain * * Copyright (c) 2009, Diomidis Spinellis * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: send.pde,v 1.5 2009/02/18 11:34:18 dds Exp $ */ import parport.*; ParallelPort lpt; boolean send3 = false; // True to send 3 bits / pixel int bitCount = 0; boolean emulate = false; boolean toSend = false; final float JUNCTION_MOVE_TIME = 250; // Motor run time for changing the junction final float IDLE_TIME = 2000; // Time needed for the train to pass the junction // States final int S_WAITING = 1; // Waiting for a train to pass final int S_MOVE_JUNCTION = 2; // Moving the junction final int S_IDLE = 3; // Idling, waiting for a train to move through the junction int state = S_WAITING; // Picture boolean img[][]; final int rows = 5; final int cols = 3; int pixelSize; // For caching color cacheImg[][]; color fillColor; // Used for measuring intervals long startTime; int sendingRow = 0; int sendingCol = -1; void setup() { if (!emulate) { lpt = new ParallelPort(0x378); } write(1); img = new boolean[rows][]; cacheImg = new color[rows][]; for (int i = 0; i < rows; i++) { img[i] = new boolean[cols]; cacheImg[i] = new color[cols]; } // Initialize img from its textual image String simg = " # " + "###" + " # " + " # " + "# #"; for (int r = 0; r < rows; r++) for (int c = 0; c < cols; c++) img[r][c] = (simg.charAt(r * cols + c) == '#'); pixelSize = screen.height / (rows + 2); size(screen.width, screen.height); if (send3) { sendingCol = 0; bitCount = -1; } background(0); } void drawPixel(int r, int c) { if (cacheImg[r][c] == fillColor) return; fill(fillColor); rect((screen.width - cols * pixelSize) / 2 + c * pixelSize, (r + 1) * pixelSize, pixelSize, pixelSize); cacheImg[r][c] = fillColor; } void drawFill(color c) { fillColor = c; } void wait(float time) { float m = millis(); while (millis() - m < time) continue; } public void write(int b) { if (!emulate) { lpt.write(b); return; } if ((b & 1) != 0) fill(0, 255, 0); else fill(255, 0, 0); rect(0, 0, 10, 10); if ((b & 2) != 0) fill(0, 255, 0); else fill(255, 0, 0); rect(10, 0, 10, 10); } void sendBit(boolean b) { byte val = 0; if (b) val |= 2; write(val); } boolean enginePasses() { if (emulate) return keyPressed; else return ((lpt.read() & 0x20) == 0); } void draw() { int sleep = 0; stroke(255, 255, 0); for (int r = 0; r < rows; r++) for (int c = 0; c < cols; c++) { if (r == sendingRow && c == sendingCol && ((millis() / 500) & 1) == 0) { if (img[r][c]) drawFill(color(180, 64, 64)); else drawFill(color(64)); } else if (img[r][c]) drawFill(color(255, 0, 0)); else drawFill(color(0)); drawPixel(r, c); } switch (state) { case S_WAITING: if (enginePasses()) { if (!send3 || (send3 && ++bitCount == 3)) { // Advance to next pixel if (++sendingCol == cols) { sendingCol = 0; if (++sendingRow == rows) sendingRow = 0; } bitCount = 0; } sendBit(img[sendingRow][sendingCol]); startTime = millis(); state = S_MOVE_JUNCTION; sleep = 50; toSend = !toSend; } break; case S_MOVE_JUNCTION: if (millis() - startTime > JUNCTION_MOVE_TIME) { write(1); startTime = millis(); state = S_IDLE; sleep = 500; } break; case S_IDLE: if (millis() - startTime > IDLE_TIME) { state = S_WAITING; sleep = 200; } break; default: background(255, 0, 0); } try { Thread.sleep(200); } catch (InterruptedException e) { ; } }