diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2fbbeff --- /dev/null +++ b/.gitignore @@ -0,0 +1,22 @@ +# eclipse +bin +*.launch +.settings +.metadata +.classpath +.project + +# idea +out +*.ipr +*.iws +*.iml +.idea + +# gradle +.gradle +build/ + +# general +*.log +desktop.ini diff --git a/Jimbo/Boards/com/fourtronix/ZeroPoint.java b/Jimbo/Boards/com/fourtronix/ZeroPoint.java deleted file mode 100644 index 608abed..0000000 --- a/Jimbo/Boards/com/fourtronix/ZeroPoint.java +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (C) 2016 Jim Darby. - * - * This library 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. - * - * This library 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 this library. If not, see - * . - */ - -package Jimbo.Boards.com.fourtronix; - -import com.pi4j.io.gpio.GpioController; -import com.pi4j.io.gpio.GpioFactory; -import com.pi4j.io.gpio.GpioPinDigitalOutput; -import com.pi4j.io.gpio.RaspiPin; - -import com.pi4j.component.servo.Servo; -import com.pi4j.component.servo.ServoDriver; -import com.pi4j.component.ComponentBase; - -/** - * This class controls the 4tronix ZeroPoint. - * - * @author Jim Darby. - */ - -public class ZeroPoint extends ComponentBase implements Servo -{ - /** - * Construct a ZeroPoint object. There can be only one (TM) and we have - * no way of checking one is actually wired up. - */ - public ZeroPoint () - { - moveto (0); - } - - /** - * Move to a specific step. This uses the original version of the values - * with the range 0 to 600. - * - * @param pos The position to move to. - */ - public void moveto (int pos) - { - // Already there? - if (pos == location) - return; - - final boolean up = pos > location; - final int steps = up ? (pos - location) : (location - pos); - - for (int i = 0; i < steps; ++i) - { - if (up) - { - phase += 1; - - if (phase >= SEQUENCE.length) - phase = 0; - } - else - { - phase -= 1; - - if (phase < 0) - phase = SEQUENCE.length - 1; - } - - for (int j = 0; j < pins.length; ++j) - pins[j].setState (SEQUENCE[phase][j]); - - try - { - // Lots of debate over the rate. 500 steps per second seems to - // work all the time. - - Thread.sleep (2); - } - - // That didn't got according to play.... But ignore it. - catch (InterruptedException ex) - { - } - } - - location = pos; - } - - /** - * Set the position using the Servo interface. It's not a servo but - * seems to wat to act like one. - * - * @param pos The position: -100 to +100. - */ - @Override - public void setPosition (float pos) - { - moveto ((int) ((pos + 100) / 200 * (MAX - MIN) + MIN)); - } - - /** - * Return the current position in the range -100 to +100. - * - * @return The position. - */ - @Override - public float getPosition () - { - return (float) (((double) (location - MIN) / (MAX - MIN) - 0.5) * 200); - } - - /** - * Return the servo driver used. As we don't use on this returns null. - * This may cause problems later. - * - * @return The servo driver (null). - */ - @Override - public ServoDriver getServoDriver () - { - return null; - } - - /** - * Implement the off option for the servo. This makes it all passive. - */ - @Override - public void off () - { - for (int i = 0; i < pins.length; ++i) - pins[i].setState (false); - } - - /** - * The SEQUENCE from Gareth. This doesn't appear to be the standard one. - * There may be some odd wiring going on here. Or I just don't understand! - */ - static private final boolean[][] SEQUENCE = - { - { true, false, false, true}, - { true, false, true, false}, - {false, true, true, false}, - {false, true, false, true} - }; - - /** The GPIO controller we're going to use. */ - private final GpioController gpio = GpioFactory.getInstance(); - - /** Our list of pins used. */ - private final GpioPinDigitalOutput pins[] = - { - gpio.provisionDigitalOutputPin (RaspiPin.GPIO_07, "A"), - gpio.provisionDigitalOutputPin (RaspiPin.GPIO_00, "B"), - gpio.provisionDigitalOutputPin (RaspiPin.GPIO_01, "C"), - gpio.provisionDigitalOutputPin (RaspiPin.GPIO_02, "D") - }; - - /** Our current location. Start at 650 then we move to zero. */ - private int location = 650; - /** Our current phase in the steps. */ - private int phase = 0; - - /** The minimum step value used. */ - public static final int MIN = 0; - /** The maximum step value used. */ - public static final int MAX = 600; - - public static void main (String args[]) throws InterruptedException - { - ZeroPoint zp = new ZeroPoint (); - - System.out.println ("At " + zp.location + " aka " + zp.getPosition ()); - zp.moveto (MAX); - System.out.println ("At " + zp.location + " aka " + zp.getPosition ()); - - zp.moveto (MAX / 2); - System.out.println ("At " + zp.location + " aka " + zp.getPosition ()); - Thread.sleep (500); - - zp.setPosition (-50); - System.out.println ("At " + zp.location + " aka " + zp.getPosition ()); - Thread.sleep (1000); - - zp.setPosition (50); - System.out.println ("At " + zp.location + " aka " + zp.getPosition ()); - Thread.sleep (1000); - - zp.setPosition (0); - System.out.println ("At " + zp.location + " aka " + zp.getPosition ()); - Thread.sleep (1000); - } - } - \ No newline at end of file diff --git a/Jimbo/Boards/com/pimoroni/Blinkt.java b/Jimbo/Boards/com/pimoroni/Blinkt.java deleted file mode 100644 index 5944f12..0000000 --- a/Jimbo/Boards/com/pimoroni/Blinkt.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2016-2017 Jim Darby. - * - * This software 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. - * - * This software 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 this software; if not, If not, see - * . - */ - -package Jimbo.Boards.com.pimoroni; - -import com.pi4j.io.gpio.GpioFactory; -import com.pi4j.io.gpio.RaspiPin; - -import Jimbo.Devices.APA102; - -import Jimbo.Graphics.Point; -import Jimbo.Graphics.Colour; -import Jimbo.Graphics.ColourMatrix; -import Jimbo.Graphics.ColourMatrixDemo; -import java.io.IOException; - -/** - * This class drives a Pimoroni Blinkt LED string. - * - * @author Jim Darby - */ -public class Blinkt implements ColourMatrix -{ - public Blinkt () - { - a = new APA102 (GpioFactory.getInstance(), RaspiPin.GPIO_04, RaspiPin.GPIO_05, 8); - } - - /** - * Set a pixel the generic way. - * - * @param p The pixel to set. - * @param value The colour to set it to. - */ - @Override - public void setPixel(Point p, Colour value) - { - if (p.getY () != 0) - throw new IllegalArgumentException ("Invalid Y coordinate"); - - set (p.getX (), value.getRed (), value.getGreen (), value.getBlue (), 31); - } - - /** - * Set a LED to a specific red, green and blue value. We also set the - * brightness. - * - * @param n The LED number, in the range 0 to the number of LEDs minus one. - * @param r The red value (0 to 255). - * @param g The green value (0 to 255). - * @param b The blue value (0 to 255). - * @param bright The brightness (0 to 31). - */ - public void set (int n, int r, int g, int b, int bright) - { - a.set (n, r, g, b, bright); - } - - /** - * Update the LED chain. - */ - @Override - public final void show () - { - a.show (); - } - - /** - * Return a point with the maximum values for X and Y in this - * matrix. - * - * @return The maximum size. - */ - @Override - public Point getMax () - { - return MAX; - } - - /** - * Run a simple test demo on the board. - * - * @param args The command line arguments. They're ignored. - * - * @throws InterruptedException If Thread.sleep gets interrupted. - * @throws java.io.IOException In case of trouble. - */ - public static void main (String args[]) throws InterruptedException, IOException - { - final Blinkt b = new Blinkt (); - - ColourMatrixDemo.run (b); - } - - /** The width of the board. */ - public static final int WIDTH = 8; - /** The height of the board. */ - public static final int HEIGHT = 1; - /** The maximum X value. */ - public static final int MAX_X = WIDTH - 1; - /** The maximum Y value. */ - public static final int MAX_Y = HEIGHT - 1; - - /** The maximum values as a Point. */ - private final static Point MAX = new Point (MAX_X, MAX_Y); - - /** Internal pointer to the hat. */ - private final APA102 a; -} diff --git a/Jimbo/Boards/com/pimoroni/MicroDotPHAT.java b/Jimbo/Boards/com/pimoroni/MicroDotPHAT.java deleted file mode 100644 index adee2b0..0000000 --- a/Jimbo/Boards/com/pimoroni/MicroDotPHAT.java +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (C) 2016 Jim Darby. - * - * This software 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. - * - * This software 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 this software; if not, If not, see - * . - */ - -package Jimbo.Boards.com.pimoroni; - -import com.pi4j.io.i2c.I2CBus; - -import Jimbo.Devices.Pi2C; -import Jimbo.Devices.IS31FL3730; -import java.io.IOException; - -/** - * This class interfaces to the Pimoroni Micro Dot pHAT. It consists of three - * IS31FL3730 controller chips wired to six displays in a delightfully unusual - * manner. I blame the grog! - * - * @author Jim Darby - */ -public class MicroDotPHAT -{ - /** - * Constructor - builds an object to handle the device. Only one may be used - * at once. - * - * @throws IOException In case of error - * @throws InterruptedException In case of error - */ - public MicroDotPHAT () throws IOException, InterruptedException - { - final I2CBus bus = Pi2C.useBus (); - - for (int i = 0; i < driver.length; ++i) - { - driver[i] = new IS31FL3730 (bus, ADDRS[i]); - driver[i].setMode (IS31FL3730.MODE_M12 | IS31FL3730.MODE_8X8); - driver[i].setLightingEffect (IS31FL3730.LER_35MA); - driver[i].setPWM (128); - - for (int j = 0; j < 8; ++j) - { - m1[i][j] = 0; - m2[i][j] = 0; - } - - driver[i].fastUpdateM1 (m1[i]); - driver[i].fastUpdateM2 (m2[i]); - driver[i].update (); - } - } - - /** - * Set a single bit on the display. The origin is at the bottom left, as it - * should be. - * - * @param x The x coordinate, range 0 to 29. - * @param y The y coordinate, range 0 to 6. - * @param on Make the pixel light up? - * @throws IOException In case of issues. - */ - public void set (int x, int y, boolean on) throws IOException - { - // Validate parameters - if ( x< 0 || x >= WIDTH || y < 0 || y >= HEIGHT) - throw new IOException ("Invalid coordidinates"); - - // Now figure out the display and the coordinates on it. - final int index = x / 10; - final boolean left = (x % 10) < 5; - final int offset = x % 5; - final int y_flip = HEIGHT - 1 - y; - - // Now map it into the device - if (left) - { - if (on) - m2[index][offset] |= (byte) (1 << y_flip); - else - m2[index][offset] &= (byte) ~(1 << y_flip); - } - else - { - if (on) - m1[index][y_flip] |= (byte) (1 << offset); - else - m1[index][y_flip] &= (byte) ~(1 << offset); - } - } - - /** - * Set a decimal point on the display. - * - * @param n Which one. 0 is leftmost, 5 is rightmost. - * @param on Turn it on or off? True for on, false for off. - * @throws IOException In case of error. - */ - public void setPoint (int n, boolean on) throws IOException - { - if (n < 0 || n > 5) - throw new IOException ("Invalid decimal point"); - - // Now figure out the display and the coordinates on it. - final int index = n / 2; - final boolean left = (n % 2) == 0; - - // Now map it into the device - if (left) - { - if (on) - m2[index][7] |= (byte) (0x40); - else - m2[index][7] &= (byte) ~(0x40); - } - else - { - if (on) - m1[index][6] |= (byte) 0x80; - else - m1[index][6] &= (byte) ~(0x80); - } - } - - /** - * Update the physical device. - * @throws IOException In case of problems. - */ - public void update () throws IOException - { - for (int i = 0; i < driver.length; ++i) - { - driver[i].fastUpdateM1 (m1[i]); - driver[i].fastUpdateM2 (m2[i]); - driver[i].update (); - } - } - - /** - * Set the PWM of the board. - * @param pwm Bright nice in range 0 to 128 (yes, 129 levels). - * @throws IOException In case of trouble. - */ - public void setPWM (int pwm) throws IOException - { - // Rather naughtily we let the lower level routines do the range checking. - for (int i = 0; i < driver.length; ++i) - driver[i].setPWM (pwm); - } - - /** - * Basic test routine. - * @param args Command line arguments, ignored. - * @throws IOException In case of error. - * @throws InterruptedException In case of error. - */ - public static void main (String[] args) throws IOException, InterruptedException - { - final MicroDotPHAT m = new MicroDotPHAT (); - boolean setting = true; - int pwm = 128; - - while (true) - { - for (int i = 0; i < 6; ++i) - { - m.setPoint (i, setting); - m.update (); - Thread.sleep (200); - } - - for (int y = 0; y < HEIGHT; ++y) - for (int x = 0; x < WIDTH; ++x) - { - m.setPWM (pwm); - - pwm -= 1; - - if (pwm < 0) - pwm = 128; - - m.set (x, y, setting); - m.update (); - - Thread.sleep (5); - } - - setting = !setting; - } - } - - /** The width of the device. */ - public static final int WIDTH = 30; - /** The height of the device. */ - public static final int HEIGHT = 7; - - /** The addresses, left to right, of the chips */ - private static final int[] ADDRS = { 0x63, 0x62, 0x61 }; - /** Our drivers for each chip. */ - private final IS31FL3730 driver[] = new IS31FL3730[ADDRS.length]; - - /** Local cache of M1 data. */ - private final byte[][] m1 = new byte[driver.length][8]; - /** Local cache of M2 data. */ - private final byte[][] m2 = new byte[driver.length][8]; -} diff --git a/Jimbo/Boards/com/pimoroni/Piglow.java b/Jimbo/Boards/com/pimoroni/Piglow.java deleted file mode 100644 index 6755719..0000000 --- a/Jimbo/Boards/com/pimoroni/Piglow.java +++ /dev/null @@ -1,343 +0,0 @@ -/* - * Copyright (C) 2016 Jim Darby. - * - * This library 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. - * - * This library 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 this library; if not, see - * . - */ - -package Jimbo.Boards.com.pimoroni; - -import java.io.IOException; - -import Jimbo.Devices.SN3218; -import Jimbo.Devices.Pi2C; - -/** - * This class allows control of the Piglow from Pimoroni. - * - * The device has three legs each of six LEDs. The LEDs are coloured (from - * inside to outside) white, blue, green, yellow, orange and red. - * - * @author Jim Darby. - */ -public class Piglow -{ - /** - * Construct a Piglow controller. - * - * @throws IOException In case of difficulty. - * @throws InterruptedException In case of difficulty. - */ - public Piglow () throws IOException, InterruptedException - { - pg = new SN3218 (Pi2C.useBus ()); - } - - /** - * Set a specific LED to a specific value. The mapping from LED number to - * which one it is is a little curious so it's often better to use the more - * nuanced routines. - * - * @param led The LED to set. - * @param value The value to set it to. - * @throws IOException In case of error. - */ - public void set (int led, int value) throws IOException - { - pg.set (led, value); - } - - /** - * Set all the red LEDs to a specific value. - * - * @param value The value to set. - * @throws IOException In case of error. - */ - public void setReds (int value) throws IOException - { - set (REDS, value); - } - - /** - * Set all the orange LEDs to a specific value. - * - * @param value The value to set. - * @throws IOException In case of error. - */ - public void setOranges (int value) throws IOException - { - set (ORANGES, value); - } - - /** - * Set all the yellow LEDs to a specific value. - * - * @param value The value to set. - * @throws IOException In case of error. - */ - public void setYellows (int value) throws IOException - { - set (YELLOWS, value); - } - - /** - * Set all the green LEDs to a specific value. - * - * @param value The value to set. - * @throws IOException In case of error. - */ - public void setGreens (int value) throws IOException - { - set (GREENS, value); - } - - /** - * Set all the blue LEDs to a specific value. - * - * @param value The value to set. - * @throws IOException In case of error. - */ - public void setBlues (int value) throws IOException - { - set (BLUES, value); - } - - /** - * Set all the white LEDs to a specific value. - * - * @param value The value to set. - * @throws IOException In case of error. - */ - public void setWhites (int value) throws IOException - { - set (WHITES, value); - } - - /** - * Set all the LEDs on leg 0 to a specific value. - * - * @param value The value to set. - * @throws IOException In case of error. - */ - public void setLeg0 (int value) throws IOException - { - set (LEG0, value); - } - - /** - * Set all the LEDs on leg 1 to a specific value. - * - * @param value The value to set. - * @throws IOException In case of error. - */ - public void setLeg1 (int value) throws IOException - { - set (LEG1, value); - } - - /** - * Set all the LEDs on leg 2 to a specific value. - * - * @param value The value to set. - * @throws IOException In case of error. - */ - public void setLeg2 (int value) throws IOException - { - set (LEG2, value); - } - - /** - * Set all the LEDs on a given leg to a specific value. - * - * @param leg The leg to set. - * @param value The value to set. - * @throws IOException In case of error. - */ - public void setLeg (int leg, int value) throws IOException - { - if (leg < 0 || leg >= LEGS.length) - throw new IOException ("Invalid leg given"); - - set (LEGS[leg], value); - } - - /** - * Set a leg to a series of values. - * - * @param leg The leg to use. - * @param values The values to use. - * @throws IOException In case of trouble. - */ - public void setLeg (int leg, int values[]) throws IOException - { - if (leg < 0 || leg >= LEGS.length) - throw new IOException ("Invalid leg given"); - - if (LEGS[leg].length != values.length) - throw new IOException ("Invalid leg data given"); - - for (int i = 0; i < values.length; ++i) - set (LEGS[leg][i], values[i]); - } - - /** - * Set all the legs. This should be an array of type int[3][6]. - * - * @param values The array of information. It should be of type int[3][6]. - * @throws IOException In case of trouble. - */ - public void setLegs (int values[][]) throws IOException - { - for (int i = 0; i < values.length; ++i) - setLeg (i, values[i]); - } - - /** - * Set a number of LEDs to a specific value. - * - * @param leds The LEDs to set. - * @param value The value to set. - * @throws IOException In case of error. - */ - public void set (byte[] leds, int value) throws IOException - { - for (int i = 0; i < leds.length; ++i) - set (leds[i], value); - } - - /** - * Update the Piglow from the set data. - * - * @throws IOException in case of error. - */ - public void update () throws IOException - { - pg.update (); - } - - /** The device we're working with. */ - private final SN3218 pg; - - /** All the red LEDs. */ - private static final byte[] REDS = { 6, 17, 0 }; - /** All the orange LEDs. */ - private static final byte[] ORANGES = { 7, 16, 1 }; - /** All the yellow LEDs. */ - private static final byte[] YELLOWS = { 8, 15, 2 }; - /** All the green LEDs. */ - private static final byte[] GREENS = { 5, 13, 3 }; - /** All the blue LEDs. */ - private static final byte[] BLUES = { 4, 11, 14 }; - /** All the white LEDs. */ - private static final byte[] WHITES = { 9, 10, 12 }; - - /** All the LEDs on leg 0. */ - private static final byte[] LEG0 = { 9, 4, 5, 8, 7, 6 }; - /** All the LEDs on leg 1. */ - private static final byte[] LEG1 = { 10, 11, 13, 15, 16, 17 }; - /** All the LEDs on leg 2. */ - private static final byte[] LEG2 = { 12, 14, 3, 2, 1, 0 }; - /** All the legs. */ - private static final byte[][] LEGS = { LEG0, LEG1, LEG2 }; - /**All the rings. */ - private static final byte[][] RINGS = { WHITES, BLUES, GREENS, YELLOWS, ORANGES, REDS }; - - - public static void main (String args[]) throws IOException, InterruptedException - { - Piglow pg = new Piglow (); - - for (int i = 0; i < 18; ++i) - { - System.out.println (i); - pg.set (i, 40); - pg.update (); - Thread.sleep (100); - pg.set (i, 0); - pg.update (); - Thread.sleep (100); - } - - pg.setReds (255); - pg.update (); - Thread.sleep (100); - pg.setReds (0); - - pg.setOranges (255); - pg.update (); - Thread.sleep (100); - pg.setOranges (0); - - pg.setYellows (255); - pg.update (); - Thread.sleep (100); - pg.setYellows (0); - - pg.setGreens (255); - pg.update (); - Thread.sleep (100); - pg.setGreens (0); - - pg.setBlues (255); - pg.update (); - Thread.sleep (100); - pg.setBlues (0); - - pg.setWhites (255); - pg.update (); - Thread.sleep (100); - pg.setWhites (0); - - pg.setLeg0 (255); - pg.update (); - Thread.sleep (100); - pg.setLeg0 (0); - - pg.setLeg1 (255); - pg.update (); - Thread.sleep (100); - pg.setLeg1 (0); - - pg.setLeg2 (255); - pg.update (); - Thread.sleep (100); - pg.setLeg2 (0); - pg.update (); - - while (true) - { - for (int step = 0; step < 256; ++step) - { - final double offset = (Math.PI * step) / 255; - - pg.setReds (toLed (Math.sin (Math.PI * 0 / 6 + offset))); - pg.setOranges (toLed (Math.sin (Math.PI * 1 / 6 + offset))); - pg.setYellows (toLed (Math.sin (Math.PI * 2 / 6 + offset))); - pg.setGreens (toLed (Math.sin (Math.PI * 3 / 6 + offset))); - pg.setBlues (toLed (Math.sin (Math.PI * 4 / 6 + offset))); - pg.setWhites (toLed (Math.sin (Math.PI * 5 / 6 + offset))); - pg.update (); - Thread.sleep (4); - } - } - } - - private static int toLed (double value) - { - if (value < 0) - value = -value; - - return (int) (255 * value); - } -} diff --git a/Jimbo/Boards/com/pimoroni/RainbowHAT.java b/Jimbo/Boards/com/pimoroni/RainbowHAT.java deleted file mode 100644 index a5226ea..0000000 --- a/Jimbo/Boards/com/pimoroni/RainbowHAT.java +++ /dev/null @@ -1,560 +0,0 @@ -/* - * Copyright (C) 2017 Jim Darby. - * - * This software 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. - * - * This software 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 this software; if not, If not, see - * . - */ - -package Jimbo.Boards.com.pimoroni; - -import com.pi4j.io.i2c.I2CBus; -import com.pi4j.io.gpio.RaspiPin; -import com.pi4j.io.gpio.GpioFactory; -import com.pi4j.io.gpio.GpioController; -import com.pi4j.io.gpio.Pin; -import com.pi4j.io.gpio.GpioPinDigitalInput; -import com.pi4j.io.gpio.GpioPinDigitalOutput; -import com.pi4j.io.gpio.PinPullResistance; - -import Jimbo.Devices.Pi2C; -import Jimbo.Devices.HT16K33; -import Jimbo.Devices.BMP280; -import Jimbo.Devices.APA102; -import Jimbo.Graphics.Colour; -import Jimbo.Graphics.ColourMatrix; -import Jimbo.Graphics.ColourMatrixDemo; -import Jimbo.Graphics.FlipX; -import Jimbo.Graphics.Mapping; -import Jimbo.Graphics.Point; - -import java.io.IOException; -import java.time.LocalTime; - -/** - * Driver class for the Rainbow HAT. - * - * @author Jim Darby - */ -public class RainbowHAT -{ - public static void main (String args[]) throws IOException, InterruptedException - { - boolean rainbow = true; - - for (int i = 0; i < args.length; ++i) - { - if (args[i].equals ("--norainbow")) - rainbow = false; - else - System.out.println ("Option " + args[i] + " ignored."); - } - - final RainbowHAT r = new RainbowHAT (); - - r.show ("Hola"); - r.setPoint (3, true); - r.update (); - - Thread.sleep (1000); - - final GpioPinDigitalOutput red = r.getRed (); - final GpioPinDigitalOutput green = r.getGreen (); - final GpioPinDigitalOutput blue = r.getBlue (); - final GpioPinDigitalInput a = r.getA (); - final GpioPinDigitalInput b = r.getB (); - final GpioPinDigitalInput c = r.getC (); - - boolean a_down = false; - boolean b_down = false; - boolean c_down = false; - - int state = 1; - - red. setState (true); - green.setState (false); - blue. setState (false); - - if (rainbow) - new Thread (new ColourMatrixDemo (r.getLEDs ())).start (); - - while (true) - { - final int old_state = state; - - if (a.isLow ()) - { - if (!a_down) - { - System.out.println ("A down"); - a_down = true; - state = 1; - } - } - else - { - if (a_down) - { - System.out.println ("A up"); - a_down = false; - } - } - - if (b.isLow ()) - { - if (!b_down) - { - System.out.println ("B down"); - b_down = true; - state = 2; - } - } - else - { - if (b_down) - { - System.out.println ("B up"); - b_down = false; - } - } - - if (c.isLow ()) - { - if (!c_down) - { - System.out.println ("C down"); - c_down = true; - state = 3; - } - } - else - { - if (c_down) - { - System.out.println ("C up"); - c_down = false; - } - } - - if (state != old_state) - { - System.out.println ("State is now " + state); - - red. setState (state == 1); - green.setState (state == 2); - blue. setState (state == 3); - } - - r.setPoint (0, false); - r.setPoint (1, false); - r.setPoint (2, false); - r.setPoint (3, false); - - switch (state) - { - case 1: - { - final LocalTime now = LocalTime.now (); - - r.setDigit (0, now.getHour () / 10); - r.setDigit (1, now.getHour () % 10); - r.setDigit (2, now.getMinute () / 10); - r.setDigit (3, now.getMinute () % 10); - - r.setPoint (1, now.getNano () > 500000000); - } - - break; - - case 2: - - { - final double temp = r.getBMP280 ().read ().getTemperature (); - - if (temp < -99 || temp >= 1000) - { - r.show ("Err"); - } - else - { - r.show (String.format ("%4d", (int) (temp * 10))); - r.setPoint (2, true); - } - } - - break; - - case 3: - - { - final double pressure = r.getBMP280 ().read ().getPressure () / 100; - - if (pressure < 0 || pressure >= 10000) - { - r.show ("Err"); - } - else - { - r.show (String.format ("%4d", (int) pressure)); - } - } - - break; - - default: - System.out.println ("In a strange state: " + state); - state = 1; - break; - } - - r.update (); - - Thread.sleep (20); - } - } - - /** - * Construct a RainbowHAT controller object. - * - * @throws IOException In case of error. - * @throws InterruptedException In case of error. - */ - public RainbowHAT () throws IOException, InterruptedException - { - final I2CBus bus = Pi2C.useBus (); - - display = new HT16K33 (bus, 0x70); - bmp280 = new BMP280 (bus, 0x77); - gpio = GpioFactory.getInstance (); - } - - /** - * Display a string on the 4-character display. - * - * @param s The string to display. - * @throws IOException In case of error. - */ - public void show (String s) throws IOException - { - for (int i = 0; i < Math.min(s.length (), 4); ++i) - { - final char ch = s.charAt (i); - - if (ch >= 0 && ch < CHARS.length) - display.setWord (i, CHARS[ch]); - else - display.setWord (i, (short) 0); - } - - for (int i = s.length (); i < 4; ++i) - display.setWord (i, (short) 0); - } - - /** - * Set the decimal point on the display. - * - * @param pos The decimal point: 0 to 3. - * @param on true for on, otherwise false. - * @throws IOException In case of error. - */ - public void setPoint (int pos, boolean on) throws IOException - { - if (pos < 0 || pos > 3) - throw new IllegalArgumentException ("RainbowHAT invalid point position"); - - // Some magic here.... - display.setBit (pos * 16 + 14, on); - } - - /** - * Set a specific character on the display to a specific numerical value. - * - * @param pos The position: 0 to 3. - * @param value The value: 0 to 9. - * @throws IOException In case of error. - */ - public void setDigit (int pos, int value) throws IOException - { - if (pos < 0 || pos > 3) - throw new IllegalArgumentException ("RainbowHAT invalid point position"); - - if (value < 0 || value > 9) - throw new IllegalArgumentException ("RainbowHAT invalid numeric value"); - - display.setWord (pos, CHARS['0' + value]); - } - - /** - * Return a digital output for the red LED (above the A button). - * - * @return The output. - */ - public GpioPinDigitalOutput getRed () - { - if (red == null) - red = provisionOut (RaspiPin.GPIO_22, "Red LED"); - - return red; - } - - /** - * Return a digital output for the green LED (above the B button). - * - * @return The output. - */ - public GpioPinDigitalOutput getGreen () - { - if (green == null) - green = provisionOut (RaspiPin.GPIO_24, "Green LED"); - - return green; - } - - /** - * Return a digital output for the blue LED (above the C button). - * - * @return The output. - */ - public GpioPinDigitalOutput getBlue () - { - if (blue == null) - blue = provisionOut (RaspiPin.GPIO_25, "Blue LED"); - - return blue; - } - - /** - * Return a GpioPinDigitalInput for the B button. - * - * @return The input. - */ - public GpioPinDigitalInput getA () - { - if (a == null) - a = provisionIn (RaspiPin.GPIO_29, "A"); - - return a; - } - - /** - * Return a GpioPinDigitalInput for the B button. - * - * @return The input. - */ - public GpioPinDigitalInput getB () - { - if (b == null) - b = provisionIn (RaspiPin.GPIO_28, "B"); - - return b; - } - - /** - * Return a GpioPinDigitalInput for the C button. - * - * @return The input. - */ - public GpioPinDigitalInput getC () - { - if (c == null) - c = provisionIn (RaspiPin.GPIO_27, "C"); - - return c; - } - - /** - * Return the BMP280 device. - * - * @return The BMP280 device. - */ - public BMP280 getBMP280 () - { - return bmp280; - } - - /** - * Return the APA102 LEDs. - * - * @return The LEDs - */ - public LEDs getLEDs () - { - if (leds == null) - leds = new LEDs (gpio); - - return leds; - } - - /** - * Update the 4-character display. - * - * @throws IOException In case of error. - */ - public void update () throws IOException - { - display.update (); - } - - public static class LEDs implements ColourMatrix - { - /** - * Construct the LEDs. We need a GPIO controller and the other - * parameters are defined by the board. - * - * @param gpio The GPIO Controller. - */ - private LEDs (GpioController gpio) - { - cs = gpio.provisionDigitalOutputPin (RaspiPin.GPIO_10, "LED Chip Select"); - cs.low (); - apa102 = new APA102 (gpio, RaspiPin.GPIO_12, RaspiPin.GPIO_14, 7); - cs.high (); - - map = new FlipX (WIDTH, HEIGHT); - } - - /** - * Return the maximum X and Y coordinates. - * - * @return The values. - */ - @Override - public Point getMax () - { - return MAX; - } - - /** - * Set a specific pixel to a specific value. The height is 1 and the - * width is 7 meaning the X coordinate goes from 0 to 6 and the Y has - * to be 0. - * - * @param p The point to change. - * @param value The value to change it to. - */ - @Override - public void setPixel (Point p, Colour value) - { - apa102.setPixel (map.map (p), value); - } - - /** - * Update the LEDs. - * - * @throws IOException In case of error. - */ - @Override - public void show () throws IOException - { - cs.low (); - apa102.show (); - cs.high (); - } - - /** - * Scale the brightness to avoid blindness. - * - * @param brightness The brightness scale factor: 0 to 31. - */ - public void brightness (int brightness) - { - apa102.brightness(brightness); - } - - /** The width of the board. */ - public final int WIDTH = 7; - /** The height of the board. */ - public static final int HEIGHT = 1; - /** The maximum X value. */ - public final int MAX_X = WIDTH - 1; - /** The maximum Y value. */ - public static final int MAX_Y = HEIGHT - 1; - /** The maximum values as a Point. */ - private final Point MAX = new Point (MAX_X, MAX_Y); - - /** Point to the underlying APA102 driver. */ - private final APA102 apa102; - /** Select pin. */ - private final GpioPinDigitalOutput cs; - /** Point mapping. */ - private final Mapping map; - } - - /** - * Provision an input pin. This will set the pin as an input and also set - * pull up on it. - * - * @param p The pin the create. - * @param name The name of the pin. - * @return The allocate pin object. - */ - private GpioPinDigitalInput provisionIn (Pin p, String name) - { - return gpio.provisionDigitalInputPin (p, name, PinPullResistance.PULL_UP); - } - - /** - * Provision an input pin. This will set the pin as an output. - * - * @param p The pin the create. - * @param name The name of the pin. - * @return The allocate pin object. - */ - private GpioPinDigitalOutput provisionOut (Pin p, String name) - { - return gpio.provisionDigitalOutputPin (p, name); - } - - /** The object that handles the 4-character display. */ - private final HT16K33 display; - /** The object that handles the temperature/pressure sensor. */ - private final BMP280 bmp280; - /** The GPIO Controller we're using. */ - private final GpioController gpio; - - /** The red LED. */ - private GpioPinDigitalOutput red = null; - /** The green LED. */ - private GpioPinDigitalOutput green = null; - /** The blue LED. */ - private GpioPinDigitalOutput blue = null; - /** The A button input. */ - private GpioPinDigitalInput a = null; - /** The B button input. */ - private GpioPinDigitalInput b = null; - /** The C button input. */ - private GpioPinDigitalInput c = null; - /** The LED handler object. */ - private LEDs leds = null; - - /** Characters we can put on the 4-character display. Keep it clean! */ - private static final short[] CHARS = - { - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0006, 0x0220, 0x12ce, 0x12ed, 0x0c24, 0x235d, 0x0400, - 0x2400, 0x0900, 0x3fc0, 0x12c0, 0x0800, 0x00c0, 0x0000, 0x0c00, - 0x0c3f, 0x0006, 0x00db, 0x008f, 0x00e6, 0x2069, 0x00fd, 0x0007, - 0x00ff, 0x00ef, 0x1200, 0x0a00, 0x2400, 0x00c8, 0x0900, 0x1083, - 0x02bb, 0x00f7, 0x128f, 0x0039, 0x120f, 0x00f9, 0x0071, 0x00bd, - 0x00f6, 0x1200, 0x001e, 0x2470, 0x0038, 0x0536, 0x2136, 0x003f, - 0x00f3, 0x203f, 0x20f3, 0x00ed, 0x1201, 0x003e, 0x0c30, 0x2836, - 0x2d00, 0x1500, 0x0c09, 0x0039, 0x2100, 0x000f, 0x0c03, 0x0008, - 0x0100, 0x1058, 0x2078, 0x00d8, 0x088e, 0x0858, 0x0071, 0x048e, - 0x1070, 0x1000, 0x000e, 0x3600, 0x0030, 0x10d4, 0x1050, 0x00dc, - 0x0170, 0x0486, 0x0050, 0x2088, 0x0078, 0x001c, 0x2004, 0x2814, - 0x28c0, 0x200c, 0x0848, 0x0949, 0x1200, 0x2489, 0x0520, 0x0000 - }; -} diff --git a/Jimbo/Boards/com/pimoroni/ScrollPHATHD.java b/Jimbo/Boards/com/pimoroni/ScrollPHATHD.java deleted file mode 100644 index 7551b77..0000000 --- a/Jimbo/Boards/com/pimoroni/ScrollPHATHD.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) 2017 Jim Darby. - * - * This library 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. - * - * This library 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 this library. If not, see - * . - */ - -package Jimbo.Boards.com.pimoroni; - -import java.io.IOException; - -import com.pi4j.io.i2c.I2CBus; -import com.pi4j.io.i2c.I2CFactory; - -import Jimbo.Devices.IS31FL3731; - -import Jimbo.Graphics.Point; -import Jimbo.Graphics.MonoMatrix; -import Jimbo.Graphics.MonoMatrixDemo; - -/** - * This class controls a Pimoroni ScrollpHAT HD. - * - * @author Jim Darby - */ -public class ScrollPHATHD implements MonoMatrix -{ - /** - * Create a ScrollPHATHD object. - * - * @throws IOException In case of issues. - * @throws I2CFactory.UnsupportedBusNumberException In case it can't find - * the correct I2C bus. - * @throws java.lang.InterruptedException In case of issues. - */ - public ScrollPHATHD () throws IOException, I2CFactory.UnsupportedBusNumberException, InterruptedException - { - phat = new IS31FL3731 (I2CFactory.getInstance (I2CBus.BUS_1), 0x74); - } - - /** - * Update the displayed data. Call this after setting up what you want - * displayed and it will transfer it to the device and hence actually - * display it. - * - * @throws IOException In case of problems. - */ - @Override - public void show () throws IOException - { - phat.update (); - } - - /** - * Set a specific pixel on or off. This works in the most efficient - * way. - * - * @param x The x coordinate. - * @param y The y coordinate. - * @param pwm The PWM value. - */ - @Override - public void setPixel (int x, int y, int pwm) - { - if (x < 0 || x > MAX_X || y < 0 || y > MAX_Y) - throw new IllegalArgumentException ("Invalid co-ordinates for set"); - - if (flip_x) - x = MAX_X - x; - - if (flip_y) - y = MAX_Y - y; - - // Piratical wiring madness! - - if (x >= 8) - { - x = (x - 8) * 2; - y = MAX_Y - y; - } - else - { - x = 15 - x * 2; - } - - phat.setLed (0, x * 8 + y, pwm); - } - - /** - * Set a pixel in the generic way. - * - * @param p The pixel. - * @param value The value. - */ - @Override - public void setPixel (Point p, Integer value) - { - setPixel (p.getX (), p.getY (), value); - } - - /** - * Optionally flip the x, y or both arguments. Useful for rotating - * and other general diddling of the display, - * - * @param x Flip the x coordinates? - * @param y Flip the y coordinates? - */ - public void flip (boolean x, boolean y) - { - flip_x = x; - flip_y = y; - } - - /** - * Get the maximum values for X and Y. - * - * @return A Point containing the maximum values. - */ - @Override - public Point getMax () - { - return MAX; - } - - public static void main (String args[]) throws IOException, I2CFactory.UnsupportedBusNumberException, InterruptedException - { - ScrollPHATHD p = new ScrollPHATHD (); - - MonoMatrixDemo.run (p); - } - - /** Device width. */ - public final static int WIDTH = 17; - /** Device height. */ - public final static int HEIGHT = 7; - /** The maximum X value. */ - public final static int MAX_X = WIDTH - 1; - /** The maximum Y value. */ - public final static int MAX_Y = HEIGHT - 1; - - /** The maximum values as a Point. */ - private final static Point MAX = new Point (MAX_X, MAX_Y); - - /** The device itself. */ - private final IS31FL3731 phat; - /** Flag to flip the x coordinate. */ - private boolean flip_x = false; - /** Flag to flip the y coordinate. */ - private boolean flip_y = false; -} diff --git a/Jimbo/Boards/com/pimoroni/ScrollPhat.java b/Jimbo/Boards/com/pimoroni/ScrollPhat.java deleted file mode 100644 index 1d3dbd2..0000000 --- a/Jimbo/Boards/com/pimoroni/ScrollPhat.java +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (C) 2016-2017 Jim Darby. - * - * This library 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. - * - * This library 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 this library. If not, see - * . - */ - -package Jimbo.Boards.com.pimoroni; - -import java.io.IOException; - -import com.pi4j.io.i2c.I2CBus; -import com.pi4j.io.i2c.I2CFactory; - -import Jimbo.Graphics.Point; -import Jimbo.Graphics.BitMatrix; -import Jimbo.Graphics.BitMatrixDemo; - -import Jimbo.Devices.IS31FL3730; - -/** - * This class controls a Pimoroni ScrollpHAT. - * - * @author Jim Darby - */ -public class ScrollPhat implements BitMatrix -{ - /** - * Create a ScroolPhat object. - * - * @throws IOException In case of issues. - * @throws I2CFactory.UnsupportedBusNumberException In case it can't find - * bus. - */ - public ScrollPhat () throws IOException, I2CFactory.UnsupportedBusNumberException - { - phat = new IS31FL3730 (I2CFactory.getInstance (I2CBus.BUS_1)); - - // Set five by 11. - phat.setMode (IS31FL3730.MODE_5X11 | IS31FL3730.MODE_M1); - - // Use 40mA drive - phat.setLightingEffect (IS31FL3730.LER_40MA); - - // It's a Pimoroni device, default LEDs to quarter power to avoid - // user blindness. - phat.setPWM (IS31FL3730.MAX_PWM / 4); - - // Clear it - for (int i = 0; i < data.length; ++i) - data[i] = 0; - - show (); - } - - /** - * Update the displayed data. Call this after setting up what you want - * displayed and it will transfer it to the device and hence actually - * display it. - * - * @throws IOException In case of problems. - */ - @Override - public final void show () throws IOException - { - phat.fastUpdateM1 (data); - } - - /** - * Set a specific pixel on or off. - * - * @param x The x coordinate. - * @param y The y coordinate. - * @param on True for on, otherwise false. - */ - @Override - public void setPixel (int x, int y, boolean on) - { - if (x < 0 || x > MAX_X || y < 0 || y > MAX_Y) - throw new IllegalArgumentException ("Invalid co-ordinates for set"); - - if (flip_x) - x = MAX_X - x; - - // We flip around Y because the board is wired "upside down". - if (!flip_y) - y = MAX_Y - y; - - if (on) - data[x] |= (1 << y); - else - data[x] &= ~(1 << y); - } - - - /** - * Set a pixel in the generic way. - * - * @param p The pixel. - * @param value The value. - */ - @Override - public void setPixel(Point p, Boolean value) - { - setPixel (p, value.booleanValue ()); - } - - /** - * Optionally flip the x, y or both arguments. Useful for rotating - * and other general diddling of the display, - * - * @param x Flip the x coordinates? - * @param y Flip the y coordinates? - */ - public void flip (boolean x, boolean y) - { - flip_x = x; - flip_y = y; - } - - /** - * Set the number of tries before logging a warning. Note this will - * never log if there isn't a retry. - * - * @param n The number of tries, must be non-negative. - * - * @throws IOException On a bad paramters. - */ - public void setTriesWarning (int n) throws IOException - { - phat.setTriesWarning (n); - } - - /** - * Return a point with the maximum values for X and Y in this - * matrix. - * - * @return The maximum size. - */ - @Override - public Point getMax () - { - return MAX; - } - - /** The device width. */ - public static final int WIDTH = 11; - /** The device height. */ - public static final int HEIGHT = 5; - - /** - * The maximum x value. X coordinates must be in the range 0 to this - * INCLUSIVE. - */ - private static final int MAX_X = WIDTH - 1; - /** - * The maximum y value. Y coordinates must be in the range 0 to this - * INCLUSIVE. - */ - private static final int MAX_Y = HEIGHT - 1; - - /** The maximum values as a Point. */ - private final static Point MAX = new Point (MAX_X, MAX_Y); - - /** Internal pointer to the low-level device. */ - private final IS31FL3730 phat; - /** Data we hold for the display. */ - private final byte data[] = new byte[12]; - /** Do we flip the x coordinate? */ - private boolean flip_x = false; - /** Do we flip the y coordinate? */ - private boolean flip_y = false; - - /** - * Test routine. - * - * @param args the command line arguments - * @throws java.io.IOException In case of problem. - * @throws java.lang.InterruptedException In case of problem. - * @throws com.pi4j.io.i2c.I2CFactory.UnsupportedBusNumberException In case of problem. - */ - public static void main(String[] args) throws IOException, InterruptedException, I2CFactory.UnsupportedBusNumberException - { - ScrollPhat s = new ScrollPhat (); - - s.setTriesWarning (0); - - BitMatrixDemo.run (s); - } -} diff --git a/Jimbo/Boards/com/pimoroni/UnicornHAT.java b/Jimbo/Boards/com/pimoroni/UnicornHAT.java deleted file mode 100644 index 70ac389..0000000 --- a/Jimbo/Boards/com/pimoroni/UnicornHAT.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (C) 2017 Jim Darby. - * - * This software 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. - * - * This software 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 this software; if not, If not, see - * . - */ - -package Jimbo.Boards.com.pimoroni; - -import Jimbo.Devices.WS2811.WS2811; -import Jimbo.Devices.WS2811.WS2811Raw; - -import Jimbo.Graphics.Snake; -import Jimbo.Graphics.FlipY; -import Jimbo.Graphics.SwapXY; -import Jimbo.Graphics.Point; -import Jimbo.Graphics.Colour; -import Jimbo.Graphics.ColourMatrix; -import Jimbo.Graphics.ColourMatrixDemo; -import java.io.IOException; - -/** - * This class controls the Pimoroni Unicorn HAT. - * - * @author Jim Darby - */ - -public class UnicornHAT implements ColourMatrix -{ - /** - * Construct a new UnicornHAT object. We can have only one though this - * isn't checked. The brightness is defaulted to 25% (because Pimoroni). - */ - public UnicornHAT () - { - h = new WS2811 (WIDTH, HEIGHT, new Snake (new SwapXY (new FlipY (WIDTH, HEIGHT))), WS2811Raw.WS2811_STRIP_GRB, 0.25); - } - - /** - * Construct a new UnicornHAT object. We can have only one though this - * isn't checked. - * - * @param brightness The value of brightness to use: 0.0 to 1.0. - */ - public UnicornHAT (double brightness) - { - h = new WS2811 (WIDTH, HEIGHT, new Snake (WIDTH, HEIGHT), WS2811Raw.WS2811_STRIP_GRB, brightness); - } - - /** - * Sets a pixel to a specific colour. - * - * @param p The address of the Pixel. - * @param r The red value: 0 to 255. - * @param g The green value: 0 to 255. - * @param b The blue value: 0 to 255. - */ - @Override - public void setPixel (Point p, int r, int g, int b) - { - h.setPixel (p, r, g, b); - } - - /** - * Set a specific pixel to a specific Colour value. - * - * @param p The point to set. - * @param c The colour to set it to. - */ - @Override - public void setPixel (Point p, Colour c) - { - h.setPixel (p, c); - } - - /** - * Update the display. - */ - @Override - public void show () - { - h.show (); - } - - /** - * Return a point with the maximum values for X and Y in this - * matrix. - * - * @return The maximum size. - */ - @Override - public Point getMax () - { - return MAX; - } - - /** - * Run a simple test demo on the board. - * - * @param args The command line arguments. They're ignored. - * - * @throws InterruptedException If Thread.sleep gets interrupted. - * @throws java.io.IOException In case of trouble. - */ - public static void main (String args[]) throws InterruptedException, IOException - { - final UnicornHAT u = new UnicornHAT (); - - ColourMatrixDemo.run (u); - } - - /** The width of the board. */ - public static final int WIDTH = 8; - /** The height of the board. */ - public static final int HEIGHT = 8; - /** The maximum X value. */ - public static final int MAX_X = WIDTH - 1; - /** The maximum Y value. */ - public static final int MAX_Y = HEIGHT - 1; - - /** The maximum values as a Point. */ - private final static Point MAX = new Point (MAX_X, MAX_Y); - - /** Internal pointer to the hat. */ - private final WS2811 h; -} diff --git a/Jimbo/Boards/com/pimoroni/UnicornHATHD.java b/Jimbo/Boards/com/pimoroni/UnicornHATHD.java deleted file mode 100644 index 6dfcfbe..0000000 --- a/Jimbo/Boards/com/pimoroni/UnicornHATHD.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (C) 2017 Jim Darby. - * - * This software 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. - * - * This software 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 this software; if not, If not, see - * . - */ - -package Jimbo.Boards.com.pimoroni; - -import java.util.Arrays; -import java.io.IOException; - -import Jimbo.Graphics.Point; -import Jimbo.Graphics.Colour; -import Jimbo.Graphics.ColourMatrix; -import Jimbo.Graphics.ColourMatrixDemo; - -import com.pi4j.io.spi.SpiChannel; -import com.pi4j.io.spi.SpiDevice; -import com.pi4j.io.spi.SpiFactory; - -/** - * This class controls the Pimoroni Unicorn HAT HD. - * - * @author Jim Darby - */ -public class UnicornHATHD implements ColourMatrix -{ - /** - * Construct a UnicornHATHD object. - * - * @throws IOException In case of error. - */ - public UnicornHATHD () throws IOException - { - dev = SpiFactory.getInstance (SpiChannel.CS0, 9000000, SpiDevice.DEFAULT_SPI_MODE); - Arrays.fill (data, (byte) 0); - data[0] = 0x72; - show (); - } - - /** - * Sets a pixel to a specific colour. This is implemented in the fastest - * possible way. - * - * @param x The X coordinate (0 to 15). - * @param y The Y coordinate (0 to 15). - * @param r The red value: 0 to 255. - * @param g The green value: 0 to 255. - * @param b The blue value: 0 to 255. - */ - @Override - public void setPixel (int x, int y, int r, int g, int b) - { - if (x < 0 || x > MAX_X || y < 0 || y > MAX_Y) - throw new IllegalArgumentException ("Invalid coordinates for setPixel"); - - if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255) - throw new IllegalArgumentException ("Invalid colour for setPixel"); - - final int base = (x + WIDTH * (MAX_Y - y)) * 3 + 1; - - data[base ] = (byte) r; - data[base + 1] = (byte) g; - data[base + 2] = (byte) b; - } - - /** - * Set a specific pixel to a specific Colour value. This is the generic - * interface. - * - * @param p The point to set. - * @param value The colour to set it to. - */ - @Override - public void setPixel(Point p, Colour value) - { - setPixel (p.getX (), p.getY (), - value.getRed (), value.getGreen (), value.getBlue ()); - } - - /** - * Update the display. - */ - @Override - public final void show () throws IOException - { - dev.write (data, 0, data.length); - } - - /** - * Return a point with the maximum values for X and Y in this - * matrix. - * - * @return The maximum size. - */ - @Override - public Point getMax () - { - return MAX; - } - - /** - * Run a simple test demo on the board. - * - * @param args The command line arguments. They're ignored. - * - * @throws InterruptedException If Thread.sleep gets interrupted. - * @throws java.io.IOException In case of trouble. - */ - public static void main (String args[]) throws InterruptedException, IOException - { - final UnicornHATHD u = new UnicornHATHD (); - - ColourMatrixDemo.run (u); - } - - /** The width of the board. */ - public static final int WIDTH = 16; - /** The height of the board. */ - public static final int HEIGHT = 16; - /** The maximum X value. */ - public static final int MAX_X = WIDTH - 1; - /** The maximum Y value. */ - public static final int MAX_Y = HEIGHT - 1; - - /** The maximum values as a Point. */ - private final static Point MAX = new Point (MAX_X, MAX_Y); - - /** Data for the hat. */ - private final byte data[] = new byte [WIDTH * HEIGHT * 3 + 1]; - /** The SPI device we're going to use. */ - private final SpiDevice dev; -} diff --git a/Jimbo/Boards/com/pimoroni/UnicornPhat.java b/Jimbo/Boards/com/pimoroni/UnicornPhat.java deleted file mode 100644 index 1419118..0000000 --- a/Jimbo/Boards/com/pimoroni/UnicornPhat.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2017 Jim Darby. - * - * This software 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. - * - * This software 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 this software; if not, If not, see - * . - */ - -package Jimbo.Boards.com.pimoroni; - -import Jimbo.Devices.WS2811.WS2811; -import Jimbo.Devices.WS2811.WS2811Raw; - -import Jimbo.Graphics.FlipY; -import Jimbo.Graphics.Point; -import Jimbo.Graphics.Colour; -import Jimbo.Graphics.ColourMatrix; -import Jimbo.Graphics.ColourMatrixDemo; -import java.io.IOException; - -/** - * This class controls the Pimoroni Unicorn pHAT. - * - * @author Jim Darby - */ -public class UnicornPhat implements ColourMatrix -{ - /** - * Construct a new UnicornPhat object. We can have only one though this - * isn't checked. The brightness is defaulted to 25% (because Pimoroni). - */ - public UnicornPhat () - { - h = new WS2811 (WIDTH, HEIGHT, new FlipY (WIDTH, HEIGHT), WS2811Raw.WS2811_STRIP_GRB, 0.25); - } - - /** - * Construct a new UnicornPhat object. We can have only one though this - * isn't checked. - * - * @param brightness The value of brightness to use: 0.0 to 1.0. - */ - public UnicornPhat (double brightness) - { - h = new WS2811 (WIDTH, HEIGHT, new FlipY (WIDTH, HEIGHT), WS2811Raw.WS2811_STRIP_GRB, brightness); - } - - /** - * Sets a pixel to a specific colour. - * - * @param p The address of the Pixel. - * @param r The red value: 0 to 255. - * @param g The green value: 0 to 255. - * @param b The blue value: 0 to 255. - */ - @Override - public void setPixel (Point p, int r, int g, int b) - { - h.setPixel (p, r, g, b); - } - - /** - * Set a specific pixel to a specific Colour value. - * - * @param p The point to set. - * @param c The colour to set it to. - */ - @Override - public void setPixel (Point p, Colour c) - { - h.setPixel (p, c); - } - - /** - * Update the display. - */ - @Override - public void show () - { - h.show (); - } - - /** - * Return a point with the maximum values for X and Y in this - * matrix. - * - * @return The maximum size. - */ - @Override - public Point getMax () - { - return MAX; - } - - /** - * Run a simple test demo on the board. - * - * @param args The command line arguments. They're ignored. - * - * @throws InterruptedException If Thread.sleep gets interrupted. - * @throws java.io.IOException In case of trouble. - */ - public static void main (String args[]) throws InterruptedException, IOException - { - final UnicornPhat u = new UnicornPhat (); - - ColourMatrixDemo.run (u); - } - - /** The width of the board. */ - public static final int WIDTH = 8; - /** The height of the board. */ - public static final int HEIGHT = 4; - /** The maximum X value. */ - public static final int MAX_X = WIDTH - 1; - /** The maximum Y value. */ - public static final int MAX_Y = HEIGHT - 1; - - /** The maximum values as a Point. */ - private final static Point MAX = new Point (MAX_X, MAX_Y); - - /** Internal pointer to the hat. */ - private final WS2811 h; -} diff --git a/Jimbo/Boards/com/thepihut/ZeroSeg.java b/Jimbo/Boards/com/thepihut/ZeroSeg.java deleted file mode 100644 index 626de14..0000000 --- a/Jimbo/Boards/com/thepihut/ZeroSeg.java +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Copyright (C) 2016 Jim Darby. - * - * This library 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. - * - * This library 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 this library. If not, see - * . - */ -package Jimbo.Boards.com.thepihut; - -import com.pi4j.io.spi.SpiChannel; -import com.pi4j.io.gpio.RaspiPin; -import com.pi4j.io.gpio.GpioFactory; -import com.pi4j.io.gpio.GpioController; -import com.pi4j.io.gpio.GpioPinDigitalInput; - -import Jimbo.Devices.MAX7219; -import java.io.IOException; - -import java.time.LocalTime; -import java.time.LocalDate; - - -/** - * Driver class for The Pi Hut's ZeroSeg (designed by Average Man vs - * Pi). - * - * @author Jim Darby - */ -public class ZeroSeg -{ - public ZeroSeg () throws IllegalArgumentException, IOException - { - dev = new MAX7219 (SpiChannel.CS0, 1); - - // Set up and blank display - - shutdown (false); - displayTest (false); - setDecodeMode (MAX7219.DECODE_NONE); - setIntensity (8); - setScanLimit (7); - update (); - - final GpioController gpio = GpioFactory.getInstance (); - - left = gpio.provisionDigitalInputPin (RaspiPin.GPIO_00, "Left"); - right = gpio.provisionDigitalInputPin (RaspiPin.GPIO_25, "Right"); - } - - /** - * Put a single value into the byte for a specific digit. In this - * case we renumber them 0 on the left to 7 on the right. - * - * @param digit The digit to update. 0 to 7. - * @param value The byte value put in. - * - * @throws IOException In case of error. - */ - public void writeDigit (int digit, int value) throws IOException - { - final byte[] map = {7, 6, 5, 4, 3, 2, 1, 0}; - - if (digit < 0 || digit >= map.length) - throw new IllegalArgumentException ("Invalid digit"); - - if (value < 0 || value > 0xff) - throw new IllegalArgumentException ("Invalid value"); - - dev.writeDigit (map[digit], (byte) value); - } - - /** - * Sets the decode mode. - * - * @param mode The mode. One of DECODE_NONE, DECODE_B_FOR_0, - * DECODE_B_FOR_0_3 or DECODE_B_FOR_0_7. This either puts no decoding in - * (for DECODE_NONE) or maps the bottom four bits for digit 0 - * (DECODE_B_FOR_0), digits 1 to 3 (DECODE_B_FOR_0_3) or all the digits - * (DECODE_B_FOR_0_7). The decode turns the bottom 4 bits into 0 to 9, - * minus, E, H, L, P and blank (in that order). - * - * Does anyone else think someone was trapped in the factory and put the - * HELP in there as a “message in a bottle”? - * - * @throws IOException In case of error. - */ - public void setDecodeMode (byte mode) throws IOException - { - dev.setDecodeMode (mode); - } - - /** - * Set the intensity of the device. - * - * @param intensity The intensity level. It must be in the range 0 to 15. - * - * @throws IOException In case of error. - */ - public void setIntensity (int intensity) throws IOException - { - dev.setIntensity (intensity); - } - - /** - * Set the scan limit. The scan limit is the number of displays actually - * used. The value is between 0 and 7 for 1 to 8 displays. - * - * @param limit The limit on the number of displays. - * - * @throws IOException In case of error. - */ - public void setScanLimit (int limit) throws IOException - { - dev.setScanLimit (limit); - } - - /** - * Set the shutdown status of all devices. - * - * @param active If true the device is shut down. - * - * @throws IOException In case of problems. - */ - public void shutdown (boolean active) throws IOException - { - dev.shutdown (active); - } - - /** - * Set test mode. This sets all segments of all the displays on. - * - * @param active True to engage, false to turn off. - * - * @throws IOException In case of problems. - */ - public void displayTest (boolean active) throws IOException - { - dev.displayTest (active); - } - - /** - * Send all the display information to the device. This is done in one - * go to avoid excessive use of the bus on update of each digit. - * - * @throws IOException In case of problems. - */ - public void update () throws IOException - { - dev.update (); - } - - /** - * Get the left hand button. - * - * @return The Pin handler. - */ - public GpioPinDigitalInput getLeftPin () - { - return left; - } - - /** - * Get the right hand button. - * - * @return The Pin handler. - */ - public GpioPinDigitalInput getRightPin () - { - return right; - } - - public static void main (String args[]) throws IOException, InterruptedException - { - final ZeroSeg z = new ZeroSeg (); - final GpioPinDigitalInput left = z.getLeftPin (); - final GpioPinDigitalInput right = z.getRightPin (); - boolean time = true; - boolean old_left = true; - int intensity = 8; - boolean old_right = true; - boolean intensity_up = true; - - while (true) - { - boolean changed = false; - - // If left goes from high to low switch mode - if (left.isHigh ()) - { - old_left = true; - } - else - { - // High to low - if (old_left) - { - time = !time; - old_left = false; - changed = true; - } - } - - if (time) - { - final LocalTime now = LocalTime.now (); - - if (changed) - z.setDecodeMode (MAX7219.DECODE_NONE); - - z.writeDigit (0, DIGIT_MAP[now.getHour () / 10]); - z.writeDigit (1, DIGIT_MAP[now.getHour () % 10]); - z.writeDigit (2, 0); - z.writeDigit (3, DIGIT_MAP[now.getMinute () / 10]); - z.writeDigit (4, DIGIT_MAP[now.getMinute () % 10]); - z.writeDigit (5, 0); - z.writeDigit (6, DIGIT_MAP[now.getSecond () / 10]); - z.writeDigit (7, DIGIT_MAP[now.getSecond () % 10]); - - z.update (); - } - else - { - final LocalDate now = LocalDate.now (); - - if (changed) - z.setDecodeMode (MAX7219.DECODE_B_FOR_0_7); - - z.writeDigit (0, now.getYear () / 1000); - z.writeDigit (1, (now.getYear () / 100) % 10); - z.writeDigit (2, (now.getYear () / 10) % 10); - z.writeDigit (3, now.getYear () % 10); - z.writeDigit (4, now.getMonthValue () / 10); - z.writeDigit (5, now.getMonthValue () % 10); - z.writeDigit (6, now.getDayOfMonth () / 10); - z.writeDigit (7, now.getDayOfMonth () % 10); - - z.update (); - } - - // If right goes from high to low update intensity - if (right.isHigh ()) - { - old_right = true; - } - else - { - // High to low - if (old_right) - { - old_right = false; - - if (intensity_up) - { - if (intensity == 15) - { - intensity = 14; - intensity_up = false; - } - else - { - intensity += 1; - } - } - else - { - if (intensity == 0) - { - intensity = 1; - intensity_up = true; - } - else - { - intensity -= 1; - } - } - - z.setIntensity (intensity); - } - } - - Thread.sleep (10); - } - } - - public static final byte DIGIT_MAP[] = - { - 0x7e, 0x30, 0x6d, 0x79, 0x33, - 0x5b, 0x5f, 0x70, 0x7f, 0x7b - }; - - private final MAX7219 dev; - private final GpioPinDigitalInput left; - private final GpioPinDigitalInput right; -} diff --git a/Jimbo/Boards/me/kano/LightShow.java b/Jimbo/Boards/me/kano/LightShow.java deleted file mode 100644 index 88f3d72..0000000 --- a/Jimbo/Boards/me/kano/LightShow.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) 2017 Jim Darby. - * - * This library 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. - * - * This library 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 this library. If not, see - * . - */ - -package Jimbo.Boards.me.kano; - -import Jimbo.Graphics.MonoMatrix; -import Jimbo.Graphics.MonoMatrixDemo; -import Jimbo.Graphics.Point; -import com.pi4j.io.serial.Baud; -import com.pi4j.io.serial.DataBits; -import com.pi4j.io.serial.FlowControl; -import com.pi4j.io.serial.Parity; - -import com.pi4j.io.serial.Serial; -import com.pi4j.io.serial.SerialDataEvent; -import com.pi4j.io.serial.SerialFactory; -import com.pi4j.io.serial.SerialDataEventListener; -import com.pi4j.io.serial.SerialConfig; -import com.pi4j.io.serial.SerialPort; -import com.pi4j.io.serial.StopBits; -import java.io.IOException; - -/** - * This class controls the Kano LightShow board that's part of the powerup kit. - * - * @author Jim Darby - */ -public class LightShow implements MonoMatrix -{ - /** - * Constructor for the Kano LightShow that comes with the powerup - * kit. - * - * @throws IOException In case of error. - * @throws InterruptedException In case of error. - */ - public LightShow () throws IOException, InterruptedException - { - port = SerialFactory.createInstance (); - - // Add a daya sink for any input - port.addListener (new DataSink ()); - - // Now configure it. This is hardcoded for the LightShow. - final SerialConfig config = new SerialConfig (); - - config.device (SerialPort.getDefaultPort()). - baud (Baud._38400). - dataBits( DataBits._8). - parity (Parity.NONE). - stopBits (StopBits._1). - flowControl (FlowControl.NONE); - - port.open (config); - - data = new byte[WIDTH * HEIGHT]; - - for (int i = 0; i < data.length; ++i) - data[i] = 0; - - show (); - } - - /** - * Set a specific pixel on or off. This works in the most efficient - * way. - * - * @param x The x coordinate. - * @param y The y coordinate. - * @param pwm The PWM value. - */ - @Override - public void setPixel (int x, int y, int pwm) - { - if (x < 0 || x > MAX_X || y < 0 || y > MAX_Y || pwm < 0 || pwm > MAX_PWM) - throw new IllegalArgumentException ("Invalid parameters for setPixel"); - - data[x + WIDTH * (MAX_Y - y)] = (byte) (pwm >> 5); - } - - /** - * Set a pixel in the generic way. - * - * @param p The pixel. - * @param value The value. - */ - @Override - public void setPixel (Point p, Integer value) - { - setPixel (p.getX (), p.getY (), value); - } - - /** - * Update the displayed data. Call this after setting up what you want - * displayed and it will transfer it to the device and hence actually - * display it. - * - * @throws IOException In case of error - */ - @Override - public final void show() throws IOException - { - port.write (START); - port.write (data); - } - - /** - * Return the maximum X and Y values as a Point. - * - * @return The maximum X and Y values as a Point - */ - @Override - public Point getMax() - { - return MAX; - } - - /** - * A class that implements the SerialDataEventListener interface - * and just ignores everything that happens. We need this otherwise - * the data just piles up. - */ - private static class DataSink implements SerialDataEventListener - { - /** - * Read and ignore any data. - * - * @param e The data to ignore - */ - @Override - public void dataReceived(SerialDataEvent e) - { - // And ignore it! - } - } - - public static void main (String args[]) throws IOException, InterruptedException - { - LightShow l = new LightShow (); - - MonoMatrixDemo.run (l); - } - - /** The display's width. */ - private static final int WIDTH = 9; - /** The display's height. */ - private static final int HEIGHT = 14; - /** The maximum X value. */ - public final static int MAX_X = WIDTH - 1; - /** The maximum Y value. */ - public final static int MAX_Y = HEIGHT - 1; - /** The maximum values as a Point. */ - private final static Point MAX = new Point (MAX_X, MAX_Y); - - /** Start marker. */ - private static final byte START = 0x55; - /** Maximum PWM value. */ - private static final int MAX_PWM = 255; - - - /** The serial port to use. */ - private final Serial port; - /** The data for the display. */ - private final byte[] data; -} diff --git a/Jimbo/Boards/uk/co/pocketmoneytronics/RGBTree.java b/Jimbo/Boards/uk/co/pocketmoneytronics/RGBTree.java deleted file mode 100644 index 8f8a03e..0000000 --- a/Jimbo/Boards/uk/co/pocketmoneytronics/RGBTree.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2017 Jim Darby. - * - * This library 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. - * - * This library 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 this library. If not, see - * . - */ - -package Jimbo.Boards.uk.co.pocketmoneytronics; - -import Jimbo.Devices.WS2811.WS2811; -import Jimbo.Devices.WS2811.WS2811Raw; - -import Jimbo.Graphics.Point; -import Jimbo.Graphics.Identity; -import Jimbo.Graphics.Colour; - -/** - * The class controls the WS2811-based RGB Christmas tree from - * PocketMoneyTronics. - * - * @author Jim Darby - */ -public class RGBTree -{ - /** - * Construct the tree. - */ - public RGBTree () - { - tree = new WS2811 (PIXELS, 1, new Identity (PIXELS, 1), WS2811Raw.WS2811_STRIP_RGB, 0.25); - } - - /** - * Set a specific pixel to a specific Colour value. - * - * @param n The pixel number. - * @param r The red value. - * @param g The green value. - * @param b The blue value. - */ - public void setPixel (int n, int r, int g, int b) - { - tree.setPixel (new Point (n, 0), r, g, b); - } - - /** - * Set a specific pixel to a specific Colour value. - * - * @param n The pixel number. - * @param c The colour to set it to. - */ - public void setPixel (int n, Colour c) - { - tree.setPixel (new Point (n, 0), c); - } - - /** - * Update the display. - */ - public void show () - { - tree.show (); - } - - /** - * Demo program. - * - * @param args Command line parameters. - * - * @throws java.lang.InterruptedException In case of interruption. - */ - public static void main (String args[]) throws InterruptedException - { - RGBTree t = new RGBTree (); - - final Colour[] colours = new Colour[3]; - - colours[0] = new Colour (255, 0, 0); - colours[1] = new Colour (0, 255, 0); - colours[2] = new Colour (0, 0, 255); - - for (int i = 0; i < colours.length; ++i) - { - for (int j = 0; j < PIXELS; ++j) - t.setPixel (j, colours[i]); - - t.show (); - - Thread.sleep (500); - } - } - - /** Number of pixels. */ - public final static int PIXELS = 6; - /** The tree. */ - private final WS2811 tree; -} diff --git a/Jimbo/Devices/APA102.java b/Jimbo/Devices/APA102.java deleted file mode 100644 index 8f0a686..0000000 --- a/Jimbo/Devices/APA102.java +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright (C) 2016-2017 Jim Darby. - * - * This software 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. - * - * This software 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 this software; if not, If not, see - * . - */ - -package Jimbo.Devices; - -import com.pi4j.io.gpio.GpioController; -import com.pi4j.io.gpio.GpioFactory; -import com.pi4j.io.gpio.GpioPinDigitalOutput; -import com.pi4j.io.gpio.Pin; -import com.pi4j.io.gpio.RaspiPin; - -import Jimbo.Graphics.Colour; -import Jimbo.Graphics.ColourMatrix; -import Jimbo.Graphics.ColourMatrixDemo; -import Jimbo.Graphics.Point; - -import java.io.IOException; - -/** - * This class drives a chain of APA102 "intelligent" LEDs. - * - * @author Jim Darby - */ -public class APA102 implements ColourMatrix -{ - /** - * Construct an APA102 controller. - * - * @param gpio The GpioController to use. - * @param data_pin The data pin to use - * @param clock_pin The clock pin to use. - * @param n The number of LEDs in the chain. - */ - public APA102 (GpioController gpio, Pin data_pin, Pin clock_pin, int n) - { - WIDTH = n; - MAX_X = WIDTH - 1; - MAX = new Point (MAX_X, MAX_Y); - dat = gpio.provisionDigitalOutputPin (data_pin); - clk = gpio.provisionDigitalOutputPin (clock_pin); - data = new int[n]; - - // Set all off to start with. - for (int i = 0; i < WIDTH; ++i) - data[i] = 0; - - // And push that out to the devices. - show (); - } - - /** - * Set a LED to a specific red, green and blue value. We also set the - * brightness. - * - * @param n The LED number, in the range 0 to the number of LEDs minus one. - * @param r The red value (0 to 255). - * @param g The green value (0 to 255). - * @param b The blue value (0 to 255). - * @param bright The brightness (0 to 31). - */ - public void set (int n, int r, int g, int b, int bright) - { - if (n < 0 || n >= WIDTH || - r < 0 || r > 255 || - g < 0 || g > 255 || - b < 0 || b > 255 || - bright < 0 || bright > 31) - throw new IllegalArgumentException ("Invalid parameter"); - - data[n] = (bright << 24) | (r << 16) | (g << 8) | b; - } - - /** - * Return a point with the maximum values for X and Y in this - * matrix. - * - * @return A Point object with the maximum values for X and Y. - */ - @Override - public Point getMax() - { - return MAX; - } - - /** - * Set a pixel the generic way. - * - * @param p The pixel to set. - * @param value The colour to set it to. - */ - @Override - public void setPixel(Point p, Colour value) - { - if (p.getY () != 0) - throw new IllegalArgumentException ("Invalid Y coordinate"); - - set (p.getX (), value.getRed (), value.getGreen (), value.getBlue (), brightness); - } - - /** - * Update the LED chain. - */ - @Override - public final void show () - { - // Transmit preamble - for (int i = 0; i < 4; ++i) - write_byte ((byte) 0); - - // Send data - for (int i = 0; i < WIDTH; ++i) - write_led (data[i]); - - // And latch it - latch (); - } - - /** - * Scale the brightness to avoid blindness. - * - * @param brightness The brightness scale factor: 0 to 31. - */ - - public final void brightness (int brightness) - { - if (brightness < 0 || brightness > 31) - throw new IllegalArgumentException ("Invalid brightness"); - - this.brightness = brightness; - } - - /** - * Write out a single byte. It goes out MSB first. - * - * @param out The byte to write. - */ - private void write_byte (byte out) - { - for (int i = 7; i >= 0; --i) - { - dat.setState ((out & (1 << i)) != 0); - clk.setState (true); - clk.setState (false); - } - } - - /** - * Write out a single LEDs information. - * - * @param data The data for that LED. - */ - private void write_led (int data) - { - write_byte ((byte) (0xe0 | ((data >> 24) & 0x1f))); - - write_byte ((byte) (data)); - write_byte ((byte) (data >> 8)); - write_byte ((byte) (data >> 16)); - } - - /** - * Latch the data into the devices. This has prompted much discussion as - * data sheet seems to be a work of fiction. These values seem to work. - * - * In case of any difficulties, blame Gadgetoid: it's all his fault! - */ - private void latch () - { - // Transmit zeros not ones! - dat.setState (false); - - // And 36 of them! - for (int i = 0; i < 36; ++i) - { - clk.setState (true); - clk.setState (false); - } - } - - public static void main (String args[]) throws InterruptedException, IOException - { - APA102 blinkt = new APA102 (GpioFactory.getInstance(), RaspiPin.GPIO_04, RaspiPin.GPIO_05, 8); - - for (int x = 0; x < 8; ++x) - { - blinkt.set (x, 255, 0, 0, 31); - blinkt.show (); - Thread.sleep (500); - blinkt.set (x, 0, 0, 0, 31); - blinkt.show (); - } - - ColourMatrixDemo.run (blinkt); - } - - /** The pin we use for data. */ - private final GpioPinDigitalOutput dat; - /** The pin we use for the clock. */ - private final GpioPinDigitalOutput clk; - /** The data for each LED in the chain. */ - private final int[] data; - /** Scale factor for brightness. Defaults to 8 (of 31) because Pimoroni. */ - private int brightness = 8; - - /** The width of the board. */ - public final int WIDTH; - /** The height of the board. */ - public static final int HEIGHT = 1; - /** The maximum X value. */ - public final int MAX_X; - /** The maximum Y value. */ - public static final int MAX_Y = HEIGHT - 1; - - /** The maximum values as a Point. */ - private final Point MAX; -} diff --git a/Jimbo/Devices/BMP280.java b/Jimbo/Devices/BMP280.java deleted file mode 100644 index 314006d..0000000 --- a/Jimbo/Devices/BMP280.java +++ /dev/null @@ -1,511 +0,0 @@ -/* - * Copyright (C) 2017 Jim Darby. - * - * This library 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. - * - * This library 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 this library. If not, see - * . - */ - -package Jimbo.Devices; - -import java.io.IOException; - -import com.pi4j.io.i2c.I2CBus; -import com.pi4j.io.i2c.I2CDevice; -import com.pi4j.io.i2c.I2CFactory; - - -/** - * A class to talk to the BMP280 digital pressure and temperature - * sensor. - * - * @author Jim Darby - */ -public class BMP280 -{ - /** - * This class is used to return the result from a reading of a - * BMP280 device. It is (typically) constructed by the {@code BMP280} - * class as a result of asking for a reading and returns the values read in - * a convenient form. - */ - public class Result - { - /** - * This constructs the result value. - * - * @param pressure The pressure (in Pa). - * @param temperature The temperature (in degrees Celsius). - */ - public Result (double pressure, double temperature) - { - this.pressure = pressure; - this.temperature = temperature; - } - - /** - * This method returns the pressure reading in Pa. The value is - * set in the constructor and cannot be modified. - * - * @return The pressure in Pa. - */ - public double getPressure () - { - return pressure; - } - - /** - * This methods returns the temperature in degrees Celsius times 10. - * The value is set in the constructor and cannot be modified. - * - * @return The temperature in degrees Celsius. - */ - public double getTemperature () - { - return temperature; - } - - /** Where we hold the pressure (in Pa). */ - private final double pressure; - /** Where we hold the temperature (in Celsius). */ - private final double temperature; - } - - public static void main (String args[]) throws I2CFactory.UnsupportedBusNumberException, IOException, InterruptedException - { - BMP280 b = new BMP280 (I2CFactory.getInstance (I2CBus.BUS_1), 0x77); - - while (true) - { - Result r = b.read (); - System.out.println ("Temperature " + r.getTemperature () + " pressure " +r.getPressure ()); - Thread.sleep (1000); - } - } - - /** - * This is the constructor for the BMP280 class. It takes the bus the - * device is on and the address on that bus (which can be varied by setting - * various pins on the device. - * - * @param bus The {@code I2CBus} the device is on. - * @param dev The device address on that bus (it can be changed). - * - * @throws IOException If something goes amiss talking to the device. - */ - public BMP280 (I2CBus bus, int dev) throws IOException - { - // Get a device object to use for communication. - device = bus.getDevice (dev); - - // Verify it really is a BMP280 - final int signature = device.read (SIGNATURE_REG); - - if (signature != SIGNATURE) - throw new IOException ("BMP280: Invalid signature (" + signature + ')'); - - // Load the device calibration data (all in one go!). - final int got = device.read (CALIBRATION_REG, buffer, 0, BUFFER_SIZE); - - // Did we get it all? - if (got != BUFFER_SIZE) - throw new IOException ("BMP280: Failed to read calibration coefficients"); - - // The values are all 16-bit but T1 and P1 are unsigned. As Java - // doesn't have unsigned variables but bytes are signed we take great - // care with the following shifts and masks and place the results in - // 32-bit ints where they fit properly. - T1 = ((buffer[ 1] & 0xff) << 8) | (buffer[ 0] & 0xff); - T2 = ((buffer[ 3] ) << 8) | (buffer[ 2] & 0xff); - T3 = ((buffer[ 5] ) << 8) | (buffer[ 4] & 0xff); - P1 = ((buffer[ 7] & 0xff) << 8) | (buffer[ 6] & 0xff); - P2 = ((buffer[ 9] ) << 8) | (buffer[ 8] & 0xff); - P3 = ((buffer[11] ) << 8) | (buffer[10] & 0xff); - P4 = ((buffer[13] ) << 8) | (buffer[12] & 0xff); - P5 = ((buffer[15] ) << 8) | (buffer[14] & 0xff); - P6 = ((buffer[17] ) << 8) | (buffer[16] & 0xff); - P7 = ((buffer[19] ) << 8) | (buffer[18] & 0xff); - P8 = ((buffer[21] ) << 8) | (buffer[20] & 0xff); - P9 = ((buffer[23] ) << 8) | (buffer[22] & 0xff); - - if (DEBUGGING) - { - System.out.println ("T: " + T1 + ' ' + T2 + ' ' + T3); - System.out.println ("P: " + P1 + ' ' + P2 + ' ' + P3 + ' ' + P4 + ' ' + - P5 + ' ' + P6 + ' ' + P7 + ' ' + P8 + ' ' + P9); - } - - config (4, 4, false); - control (5, 5, 3); - } - - /** - * Test constructor for the BMP180. It runs through the standard test - * sequence for the temperature compensation to verify it. - */ - private BMP280 () - { - device = null; - - T1 = 27504; - T2 = 26435; - T3 = -1000; - - if (compensateTemperatureInt (519888) != 2508) - System.out.println ("Failed integer temperature validation!"); - - if (!within (compensateTemperatureFloat (519888), 25.08, 0.01)) - System.out.println ("Failed floating point temperature validation"); - - P1 = 36477; - P2 = -10685; - P3 = 3024; - P4 = 2855; - P5 = 140; - P6 = -7; - P7 = 15500; - P8 = -14600; - P9 = 6000; - - if (compensatePressureInt (415148) != 100653) - System.out.println ("Failed integer pressure validation!"); - - if (!within (compensatePressureFloat (415148), 100653.27, 0.01)) - System.out.println ("Failed floating point pressure validation!"); - } - - /** - * Set up the control register. For full details you'll need to read the - * data sheet. - * - * @param temperature_oversampling 0 means skip reading temperature. 1 to - * 5 means oversample 2^(n-1) times. 6 and above mean oversample 16 times. - * Only values in the range 0 to 7 are acceptable. - * @param pressure_oversampling 0 means skip reading temperature. 1 to - * 5 means oversample 2^(n-1) times. 6 and above mean oversample 16 times. - * Only values in the range 0 to 7 are acceptable. - * @param power_mode 0 is sleep mode, 1 and 2 are forced mode and 3 is - * normal mode. - * - * @throws IOException In case of error. - */ - public final void control (int temperature_oversampling, - int pressure_oversampling, - int power_mode) throws IOException - { - if (temperature_oversampling < 0 || temperature_oversampling > 7 || - pressure_oversampling < 0 || pressure_oversampling > 7 || - power_mode < 0 || power_mode > 3) - throw new IOException ("BMP280: Invalid control"); - - final byte value = (byte) ((temperature_oversampling << 5) | - (pressure_oversampling << 2) | power_mode); - - device.write (CONTROL_REG, value); - } - - /** - * Set the configuration register. For full details you'll need to read - * the data sheet. - * - * @param inactive Set the inactive duration. - * @param filter Set the IIR filter parameter. - * @param spi Switch to SPI mode. - * - * @throws IOException In case of error. - */ - public final void config (int inactive, int filter, boolean spi) throws IOException - { - if (inactive < 0 || inactive > 7 || - filter < 0 || filter > 7) - throw new IOException ("BMP280: Invalid config"); - - final byte value = (byte) ((inactive << 5) | (filter << 2) | (spi ? 1 : 0)); - - device.write (CONFIG_REG, value); - } - - public Result read () throws IOException - { - if (device.read (RESULTS_REG, buffer, 0, DATA_SIZE) != DATA_SIZE) - throw new IOException ("BMP280: Short data read"); - - final int pressure_adc = ((buffer[0] & 0xff) << 12) + - ((buffer[1] & 0xff) << 4) + ((buffer[2] & 0xff) >> 4); - final int temperature_adc = ((buffer[3] & 0xff) << 12) + - ((buffer[4] & 0xff) << 4) + ((buffer[5] & 0xff) >> 4); - - // They need to be calculated in the order as the temperature - // calculation sets a varaible to asist with pressure calculation. - // Thanks Bosch! - - final double temperature = compensateTemperatureFloat (temperature_adc); - final double pressure = compensatePressureFloat (pressure_adc); - - if (DEBUGGING) - { - System.out.println ("Raw: pressure " + pressure_adc + " temperature " + temperature_adc); - System.out.println ("Cooked: temperature " + temperature + " pressure " + pressure); - } - - return new Result (pressure, temperature); - } - - /** - * Calculate the compensated temperature using the integer version - * of the algorithm. - * - * @param adc The ADC value - * - * @return The temperature in hundreths of a degree Celsius. - */ - private int compensateTemperatureInt (int adc) - { - // This horror is from the data sheet. Don't blame me! - - final int var1 = ((((adc >> 3) - (T1 << 1))) * (T2)) >> 11; - final int var2 = (((((adc >> 4) - (T1)) * ((adc >> 4) - (T1))) >> 12) * (T3)) >> 14; - t_fine_int = var1 + var2; - final int T = (t_fine_int * 5 + 128) >> 8; - - if (DEBUGGING) - System.out.println ("var1 " + var1 + " var2 " + var2 + " t_fine " + t_fine_int + " T " + T); - - return T; - } - - /** - * Calculate the compensated temperature using the floating point - * version of the algorithm. - * - * @param adc The ADC value - * - * @return The temperature in degrees Celsius. - */ - private double compensateTemperatureFloat (int adc) - { - // This horror is from the data sheet. Don't blame me! - - final double val1 = (adc / 16384.0 - T1 / 1024.0) * T2; - final double val2 = ((adc / 131072.0) - T1 / 8192.0) * (adc / 131072.0 - T1 / 8192.0) * T3; - - t_fine_double = val1 + val2; - - final double T = t_fine_double / 5120; - - if (DEBUGGING) - System.out.println ("val1 " + val1 + " val2 " + val2 + " t_fine " + t_fine_double + " T " + T); - - return T; - } - - /** - * Calculate the compensated pressure using integer arithmetic. - * - * @param adc The ADC result. - * - * @return The pressure in Pascals. - */ - private int compensatePressureInt (int adc) - { - // This horror is from the data sheet. Don't blame me! - - long var1, var2, p; - var1 = ((long) t_fine_int) - 128000; - - if (DEBUGGING) - System.out.println ("var1 " + var1); - - var2 = var1 * var1 * (long) P6; - - if (DEBUGGING) - System.out.println ("var2 " + var2); - - var2 = var2 + ((var1*(long) P5)<<17); - - if (DEBUGGING) - System.out.println ("var2 " + var2); - - var2 = var2 + (((long) P4)<<35); - - if (DEBUGGING) - System.out.println ("var2 " + var2); - - var1 = ((var1 * var1 * (long) P3)>>8) + ((var1 * (long) P2)<<12); - - if (DEBUGGING) - System.out.println ("var1 " + var1); - - var1 = (((((long) 1)<<47)+var1))*((long) P1)>>33; - - if (DEBUGGING) - System.out.println ("var1 " + var1); - - if (var1 == 0) - { - return 0; // avoid exception caused by division by zero - } - - p = 1048576-adc; - - if (DEBUGGING) - System.out.println ("p " + p); - - p = (((p<<31)-var2)*3125)/var1; - - if (DEBUGGING) - System.out.println ("p " + p); - - var1 = (((long) P9) * (p>>13) * (p>>13)) >> 25; - - if (DEBUGGING) - System.out.println ("var1 " + var1); - - var2 = (((long) P8) * p) >> 19; - - if (DEBUGGING) - System.out.println ("var2 " + var2); - - p = ((p + var1 + var2) >> 8) + (((long) P7)<<4); - - if (DEBUGGING) - System.out.println ("p " + p); - - return (int) ((p + 128) / 256); - } - - /** - * Calculate the compensated pressure using floating point - * arithmetic. - * - * @param adc The ADC result. - * - * @return The pressure in Pascals. - */ - private double compensatePressureFloat (int adc) - { - // This horror is from the data sheet. Don't blame me! - - double var1, var2, p; - - var1 = t_fine_double / 2.0 - 64000; - - if (DEBUGGING) - System.out.println ("var1 " + var1); - - var2 = var1 * var1 * P6 / 32768; - - if (DEBUGGING) - System.out.println ("var2 " + var2); - - var2 = var2 + var1 * P5 * 2; - - if (DEBUGGING) - System.out.println ("var2 " + var2); - - var2 = var2 / 4 + P4 * 65536.0; - - if (DEBUGGING) - System.out.println ("var2 " + var2); - - var1 = ((var1 * var1 * P3) / 524288.0 + (var1 * P2 )) / 524288.0; - - if (DEBUGGING) - System.out.println ("var1 " + var1); - - var1 = (1 + var1 / 32768) * P1; - - if (DEBUGGING) - System.out.println ("var1 " + var1); - - if (var1 == 0) - { - return 0; // avoid exception caused by division by zero - } - - p = 1048576 - adc; - - if (DEBUGGING) - System.out.println ("p " + p); - - p = (p - var2 / 4096) * 6250 / var1; - - if (DEBUGGING) - System.out.println ("p " + p); - - var1 = P9 * p * p / 2147483648.0; - - if (DEBUGGING) - System.out.println ("var1 " + var1); - - var2 = P8 * p / 32768; - - if (DEBUGGING) - System.out.println ("var2 " + var2); - - p = p + (var1 + var2 + P7) / 16.0; - - if (DEBUGGING) - System.out.println ("p " + p); - - return p; - } - - private static boolean within (double a, double b, double limit) - { - return Math.abs (a - b) < limit; - } - - /** Locate of signature register. */ - private static final int SIGNATURE_REG = 0xd0; - /** Signature value. */ - private static final int SIGNATURE = 0x58; - /** Location of calibration data. */ - private static final int CALIBRATION_REG = 0x88; - /** Location of status register. */ - private static final int STATUS_REG = 0xf3; - /** Location of control register. */ - private static final int CONTROL_REG = 0xf4; - /** Location of configuration register. */ - private static final int CONFIG_REG = 0xf5; - /** Largest read data sized used (in fact calibration data). */ - private static final int BUFFER_SIZE = 24; - /** Base of data. */ - private static final int RESULTS_REG = 0xf7; - /** Size of data. */ - private static final int DATA_SIZE = 6; - /** Run in debugging mode. */ - private static final boolean DEBUGGING = false; - - /** The I2C device. */ - private final I2CDevice device; - /** Buffer used for reading results. */ - private final byte[] buffer = new byte[BUFFER_SIZE]; - - // Compensation parameters. - private final int T1; - private final int T2; - private final int T3; - private final int P1; - private final int P2; - private final int P3; - private final int P4; - private final int P5; - private final int P6; - private final int P7; - private final int P8; - private final int P9; - - int t_fine_int; - double t_fine_double; -} diff --git a/Jimbo/Devices/HT16K33.java b/Jimbo/Devices/HT16K33.java deleted file mode 100644 index 52628e7..0000000 --- a/Jimbo/Devices/HT16K33.java +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright (C) 2018 Jim Darby. - * - * This library 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. - * - * This library 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 this library. If not, see - * . - */ - -package Jimbo.Devices; - -import java.io.IOException; - -import com.pi4j.io.i2c.I2CBus; -import com.pi4j.io.i2c.I2CDevice; -import com.pi4j.io.i2c.I2CFactory; - -/** - * This class controls a HT16K33 display controller. - * - * @author Jim Darby - */ -public class HT16K33 -{ - public HT16K33 (I2CBus bus, int dev) throws IOException - { - // Get a device object to use for communication. - device = bus.getDevice (dev); - - setOscillator (true); - setDisplay (true, DISPLAY_STEADY); - setBrightness (15); - - for (int i = 0; i < buffer.length; ++i) - buffer[i] = 0x00; - - update (); - } - - /** - * Turn the main oscillator on or off. Having the oscillator off is - * standby mode and on is the normal run mode. - * - * @param on Turn the oscillator on or not. - * - * @throws IOException In case of trouble. - */ - public void setOscillator (boolean on) throws IOException - { - device.write ((byte) (SETUP_REG | (on ? SETUP_ON : 0))); - } - - /** - * Set the display parameters. There is an on/off boolean and the blink - * rate which can be one of DISPLAY_STEADY (where it's on permanently), - * DISPLAY_TWOHZ (flashing at 2Hz), DISPLAY_ONEHZ (flashing at 1Hz) or - * DISPLAY_HALFHZ (flashing at 0.5Hz). - * - * @param on Display on/off. - * @param blink DISPLAY_STEADY, DISPLAY_TWOHZ, DISPLAY_ONEHZ or - * DISPLAY_HALFHZ. - * - * @throws IOException In case of trouble. - */ - public void setDisplay (boolean on, int blink) throws IOException - { - if (blink < 0 || blink > 3) - throw new IllegalArgumentException ("HT16K33 invalid blink value"); - - device.write ((byte) (DISPLAY_REG | (blink << 1) | (on ? DISPLAY_ON : 0))); - } - - /** - * Set the display's brightness level. - * - * @param level The brightness level: 0 to 15 mapping to 1/16 to 16/16 max. - * - * @throws IOException In case of trouble. - */ - public void setBrightness (int level) throws IOException - { - if (level < 0 || level > 15) - throw new IllegalArgumentException ("HT16K33 invalid brightness value"); - - device.write ((byte) (BRIGHTNESS_REG | level)); - } - - /** - * Set a single bit in the display on or off. Bits are number from byte - * zero upwards and inside a byte from LSB to MSB. - * - * @param bit The bit to set (in the range 0 to 127). - * @param on Set the bit on or off. - */ - public void setBit (int bit, boolean on) - { - if (bit < 0 || bit > buffer.length * 8 - 1) - throw new IllegalArgumentException ("HT16K33 invalid bit number"); - - final int index = bit / 8; - final byte value = (byte) (1 << (bit % 8)); - - if (on) - buffer[index] |= value; - else - buffer[index] &= ~value; - } - - /** - * Set a specific byte in the buffer. - * - * @param which Which byte to set (0 to 15). - * @param value The value to set it to. - */ - public void setByte (int which, byte value) - { - if (which < 0 || which >= buffer.length) - throw new IllegalArgumentException ("HT16K33 invalid byte number"); - - buffer[which] = value; - } - /** - * Set a specific word in the buffer. The words are stored in little - * endian format. - * - * @param which Which byte to set (0 to 15). - * @param value The value to set it to. - */ - - public void setWord (int which, short value) - { - if (which < 0 || which >= buffer.length / 2) - throw new IllegalArgumentException ("HT16K33 invalid byte number"); - - buffer[which*2 + 1] = (byte) (value >> 8); - buffer[which*2] = (byte) value; - } - - /** - * Update the display. - * - * @throws IOException In case of trouble. - */ - public void update () throws IOException - { - device.write (0, buffer); - } - -/** - * Test program. - * - * @param args (ignored) - * - * @throws IOException In case of trouble. - * @throws com.pi4j.io.i2c.I2CFactory.UnsupportedBusNumberException In case of trouble. - * @throws InterruptedException In case of trouble. - */ - public static void main (String args[]) throws IOException, I2CFactory.UnsupportedBusNumberException, InterruptedException - { - HT16K33 h = new HT16K33 (I2CFactory.getInstance (I2CBus.BUS_1), 0x70); - - boolean reset = false; - - while (true) - { - for (int i = 0; i < 128; ++i) - { - if (i > 0 && reset) - h.setBit (i - 1, false); - - System.out.println ("Setting bit " + i); - h.setBit (i, true); - h.update (); - - Thread.sleep (1000); - } - - reset = !reset; - } - } - - /** The I2C device. */ - private final I2CDevice device; - /** The data buffer */ - private final byte[] buffer = new byte[16]; - - /** Address of the setup register. */ - static private final int SETUP_REG = 0x20; - /** Command to turn the device on. */ - static private final byte SETUP_ON = 0x01; - /** Address of the display setup register. */ - static private final int DISPLAY_REG = 0x80; - /** Value to turn the display on. */ - static private final byte DISPLAY_ON = 0x01; - /** Value for no blinking. */ - static private final byte DISPLAY_STEADY = 0x00; - /** Value for blinking at 2 Hz. */ - static private final byte DISPLAY_TWOHZ = 0x01; - /** Value for blinking at 1Hz. */ - static private final byte DISPLAY_ONEHZ = 0x02; - /** Value for blinking at 0.5 Hz. */ - static private final byte DISPLAY_HALFHZ = 0x03; - /** Address of brightness register. */ - static private final int BRIGHTNESS_REG = 0xe0; -} diff --git a/Jimbo/Devices/IS31FL3730.java b/Jimbo/Devices/IS31FL3730.java deleted file mode 100644 index 2eaf1b4..0000000 --- a/Jimbo/Devices/IS31FL3730.java +++ /dev/null @@ -1,389 +0,0 @@ -/* - * Copyright (C) 2016 Jim Darby. - * - * This library 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. - * - * This library 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 this library. If not, see - * . - */ - -package Jimbo.Devices; - -import java.io.IOException; - -import com.pi4j.io.i2c.I2CBus; -import com.pi4j.io.i2c.I2CDevice; - -import java.util.logging.Logger; -import java.util.logging.Level; - -/** - * This class drive the IS31FL3730 display controller. It's primary goal is to - * be generic so that its users can provide the appropriate parameters to make - * it work with the highly board specific implementation. - * - * @author Jim Darby - */ -public class IS31FL3730 -{ - private static final Logger LOG = Logger.getLogger ("Jimbo.Devices.IS31FL3730"); - - /** - * Constructor. This uses the default device address on the given bus. - * - * @param bus The bus the controller is on. - * @throws IOException When it can't create the bus device. - */ - public IS31FL3730 (I2CBus bus) throws IOException - { - this (bus, I2C_ADDR); - } - - /** - * Constructor. The uses a specified address on the given bus, - * - * @param bus The bus the controller is on. - * @param addr The address on the bus - * @throws IOException When it can't create the bus device. - */ - public IS31FL3730 (I2CBus bus, int addr) throws IOException - { - device = bus.getDevice (addr); - - // Clear retry timers - for (int i = 0; i < MAX_TRIES; ++i) - tries [i] = 0; - } - - /** - * Set the mode of the device. You really want to read the manual for this. - * - * @param mode You can have (or not) MODE_SSD, MODE_AE and one of: - * MODE_8X8, MODE_7X9, MODE_6X10 or MODE_9X11 and one of: - * MODE_M1, MODE_M2 or MODE_M12. - * @throws IOException If anything goes wrong. - */ - public void setMode (int mode) throws IOException - { - // Did they set any naughty bits? - if ((mode & ~(0x9f)) != 0) - throw new IllegalArgumentException ("Bad mode value " + mode); - - retryWrite (REG_CONFIG, (byte) mode); - } - - /** - * Set a single byte in M1. - * - * @param offset The offset (0 to 10). - * @param value The value - * @throws java.io.IOException On invalid parameters or error. - */ - public void setM1 (byte offset, byte value) throws IOException - { - if (offset < 0 || offset > 10) - throw new IllegalArgumentException ("Invalid offset " + offset); - - retryWrite (REG_M1_BASE + offset, value); - } - - /** - * Set a single byte in M2. - * - * @param offset The offset (0 to 10). - * @param value The value - * @throws java.io.IOException On invalid parameters or error. - */ - public void setM2 (byte offset, byte value) throws IOException - { - if (offset < 0 || offset > 10) - throw new IllegalArgumentException ("Invalid offset " + offset); - - retryWrite (REG_M2_BASE + offset, value); - } - - /** - * Write the M1 matrix data and then (maybe) hit the update register. - * This needs between 1 to 12 bytes of data but the 12th (if there) - * isn't used for anything useful except triggering the device to update. - * - * @param data A 1- to 12-item byte array. - * @throws IOException In case of problems. - */ - public void fastUpdateM1 (byte data[]) throws IOException - { - if (data.length < 1 || data.length > 12) - throw new IllegalArgumentException ("Invalid fastUpdate data"); - - retryWrite (REG_M1_BASE, data, 0, data.length); - } - - /** - * Write the entire M2 matrix data. - * - * @param data A 1- to 11-item byte array. - * @throws IOException In case of problems. - */ - public void fastUpdateM2 (byte data[]) throws IOException - { - if (data.length < 1 || data.length > 11) - throw new IllegalArgumentException ("Invalid fastUpdate data"); - - retryWrite (REG_M2_BASE, data, 0, data.length); - } - - /** - * Set the lighting effect register. See the datasheet for the full details. - * In summary, if you're using the audio input you set the gain here using - * one of the LER_*DB values for the appropriate decibel gain. You should - * always use one of the LER_*MA values to set the driver current for the - * LEDs in the matrix. - * - * @param effect The value to use. Must be between 0 and 127 inclusive. - * @throws IOException In case of error. - */ - public void setLightingEffect (int effect) throws IOException - { - if (effect < 0 || effect > 127) - throw new IllegalArgumentException ("Invalid effect " + effect); - - retryWrite (REG_LER, (byte) effect); - } - - /** - * Set the PWM parameter. - * - * @param pwm The PWM value. Must be between 0 and 128 inclusive. - * @throws IOException In case of error. - */ - public void setPWM (int pwm) throws IOException - { - if (pwm < 0 || pwm > MAX_PWM) - throw new IllegalArgumentException ("Bad PWM " + pwm); - - retryWrite (REG_PWM, (byte) pwm); - } - - /** - * Tell the device to update its display. - * - * @throws IOException In case things go wrong. - */ - public void update () throws IOException - { - retryWrite (REG_UCR, (byte) 0x00); - } - - /** - * Try a bus write until it works. - * - * @param reg The register to write. - * @param value The value to write - * @throws IOException If it really can't be made to work! - */ - private void retryWrite (int reg, byte value) throws IOException - { - buffer1[0] = value; - - retryWrite (reg, buffer1, 0, 1); - } - - /** - * Try a bus write until it works. - * - * @param reg The register to write. - * @param value The values to write - * @throws IOException If it really can't be made to work! - */ - private void retryWrite (int reg, byte[] value, int base, int length) throws IOException - { - IOException error = null; - - for (int i = 0; i < MAX_TRIES; ++i) - { - try - { - device.write (reg, value, base, length); - ++tries[i]; - - if (i > 0) - printTries (); - - error = null; - break; - } - - catch (IOException e) - { - error = e; - } - - try - { - Thread.sleep (1); - } - - catch (InterruptedException e) - { - LOG.log (Level.WARNING, "Sleep interrupted: {0}", e.getLocalizedMessage ()); - } - } - - if (error != null) - throw error; - } - - /** - * Set the number of tries before logging a warning. Note this will - * never log if there isn't a retry. - * - * @param n The number of tries, which must be non-negative. - */ - public void setTriesWarning (int n) - { - if (n < 0) - throw new IllegalArgumentException ("Bad number of tries " + n); - - warn_tries = n; - } - - /** - * Print out diagnostic information in case of failure. - */ - private void printTries () - { - int total = 0; - int failed = 0; - boolean summarise = false; - - for (int i = 0; i < MAX_TRIES; ++i) - { - total += tries[i]; - - if (i > 0 && tries[i] != 0) - { - failed += tries[i] * i; - - if (i > warn_tries) - { - LOG.log (Level.INFO, "Retries {0} = {1}", new Object[]{i, tries[i]}); - summarise = true; - } - } - } - - if (summarise) - LOG.log (Level.INFO, "As as percentage: {0}", (((double) failed / total)) * 100); - } - - // Dealing with communication and communication problems - - /** Buffer for single byte writes. */ - private final byte[] buffer1 = new byte[1]; - /** Warn if this or more tried needed to communicate with device. */ - private int warn_tries = 4; - /** The maximum number of tries to send something over the bus. */ - private static final int MAX_TRIES = 20; - /** Create a histogram of the number of tries;. */ - private final int tries[] = new int[MAX_TRIES]; - - /** The default I2C address of the device. */ - private static final byte I2C_ADDR = 0x60; - - /** Configuration register. */ - private static final byte REG_CONFIG = 0x00; - /** Base of Matrix 1 data. */ - private static final byte REG_M1_BASE = 0x01; - /** Base of Matrix 2 data. */ - private static final byte REG_M2_BASE = 0x0e; - /** Update control register. */ - private static final byte REG_UCR = 0x0c; - /** Lighting effects register. */ - private static final byte REG_LER = 0x0d; - /** PWM register. */ - private static final byte REG_PWM = 0x19; - /** Reset register */ - private static final byte REG_RESET = (byte) 0xff; - - /** Software shutdown mode */ - public static final byte MODE_SSD = (byte) 0x80; - /** Set matrix 1 only */ - public static final byte MODE_M1 = 0x00; - /** Set matrix 2 only */ - public static final byte MODE_M2 = 0x08; - /** Set matrix 1 and 2 */ - public static final byte MODE_M12 = 0x18; - /** Audio enable */ - public static final byte MODE_AE = 0x04; - /** Set 8x8 */ - public static final byte MODE_8X8 = 0x00; - /** Set 7*9 */ - public static final byte MODE_7X9 = 0x01; - /** Set 6*10 */ - public static final byte MODE_6X10 = 0x02; - /** Set 5*11 */ - public static final byte MODE_5X11 = 0x03; - - /** Set drive to 5mA. */ - public static final byte LER_05MA = 0x08; - /** Set drive to 10mA. */ - public static final byte LER_10MA = 0x09; - /** Set drive to 15mA. */ - public static final byte LER_15MA = 0x0a; - /** Set drive to 20mA. */ - public static final byte LER_20MA = 0x0b; - /** Set drive to 25mA. */ - public static final byte LER_25MA = 0x0c; - /** Set drive to 30mA. */ - public static final byte LER_30MA = 0x0d; - /** Set drive to 35mA. */ - public static final byte LER_35MA = 0x0e; - /** Set drive to 40mA. */ - public static final byte LER_40MA = 0x00; - /** Set drive to 45mA. */ - public static final byte LER_45MA = 0x01; - /** Set drive to 50mA. */ - public static final byte LER_50MA = 0x02; - /** Set drive to 55mA. */ - public static final byte LER_55MA = 0x03; - /** Set drive to 60mA. */ - public static final byte LER_60MA = 0x04; - /** Set drive to 65mA. */ - public static final byte LER_65MA = 0x05; - /** Set drive to 70mA. */ - public static final byte LER_70MA = 0x06; - /** Set drive to 75mA. */ - public static final byte LER_75MA = 0x07; - - /** Set audio gain to 0db. */ - public static final byte LER_0DB = 0x00; - /** Set audio gain to +3db. */ - public static final byte LER_3DB = 0x10; - /** Set audio gain to +6db. */ - public static final byte LER_6DB = 0x20; - /** Set audio gain to +9db. */ - public static final byte LER_9DB = 0x30; - /** Set audio gain to +12db. */ - public static final byte LER_12DB = 0x40; - /** Set audio gain to +15db. */ - public static final byte LER_15DB = 0x50; - /** Set audio gain to +18db. */ - public static final byte LER_18DB = 0x60; - /** Set audio gain to -6db. */ - public static final byte LER_M6DB = 0x70; - - /** The maximum value the PWM can be. */ - public static final int MAX_PWM = 128; - - /** Point to the device we're using. */ - private final I2CDevice device; -} diff --git a/Jimbo/Devices/IS31FL3731.java b/Jimbo/Devices/IS31FL3731.java deleted file mode 100644 index d3e3219..0000000 --- a/Jimbo/Devices/IS31FL3731.java +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright (C) 2017 Jim Darby. - * - * This library 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. - * - * This library 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 this library. If not, see - * . - */ - -package Jimbo.Devices; - -import java.io.IOException; - -import com.pi4j.io.i2c.I2CBus; -import com.pi4j.io.i2c.I2CDevice; - -/** - * This class controls the IS31FL3731 display controller. It's currently - * very limited in what it offers but it isn't bad.... - * - * @author Jim Darby - */ -public class IS31FL3731 -{ - /** - * This uses the given device address on the given bus. - * - * @param bus The I2C bus to use. - * @param addr The address on the bus. - * - * @throws IOException In case of trouble. - * @throws InterruptedException In case of trouble. - */ - public IS31FL3731 (I2CBus bus, int addr) throws IOException, InterruptedException - { - device = bus.getDevice (addr); - - for (int i = 0; i < NUM_FRAMES; ++i) - { - // Turn blinking off - for (int j = BLINK_BASE; j < BLINK_END; ++j) - FRAME[i][j] = 0; - - // Turn LEDs on - for (int j = ENABLE_BASE; j < ENABLE_END; ++j) - FRAME[i][j] = (byte) 0xff; - - // Set the brightness to zero - for (int j = PWM_BASE; j < PWM_END; ++j) - FRAME[i][j] = 0; - - // Upload it to the device - sendFrame (i, FRAME[i]); - - // Set dirty markers - DIRTY_LOW[i] = FRAME_LEN; - DIRTY_HIGH[i] = -1; - } - - // Set "sensible" defaults - FUNCTION_BUFFER[REG_CONFIG] = 0x00; - FUNCTION_BUFFER[REG_DISPLAY] = 0x00; - FUNCTION_BUFFER[REG_AP1] = 0x00; - FUNCTION_BUFFER[REG_AP2] = 0x00; - FUNCTION_BUFFER[REG_RESERVED] = 0x00; // Not used - FUNCTION_BUFFER[REG_OPTION] = 0x00; - FUNCTION_BUFFER[REG_AUDIO] = 0x00; - FUNCTION_BUFFER[REG_FRAME] = 0x00; // Read only - FUNCTION_BUFFER[REG_BREATH1] = 0x00; - FUNCTION_BUFFER[REG_BREATH2] = 0x00; - FUNCTION_BUFFER[REG_SHUTDOWN] = 0x01; // Activate (only non-default!) - FUNCTION_BUFFER[REG_AGC_CTL] = 0x00; - FUNCTION_BUFFER[REG_AGC_RATE] = 0x00; - - sendFunction (); - } - - /** - * Set the PWM value of a specific LED in a specific frame. - * - * @param frame The frame the LED is in. - * @param led The LED number in that frame. - * @param pwm The PWM value. - */ - public void setLed (int frame, int led, int pwm) - { - if (frame < 0 || frame >= NUM_FRAMES) - throw new IllegalArgumentException ("Invalid frame " + frame); - - if (led < 0 || led >= NUM_LEDS) - throw new IllegalArgumentException ("Invalid LED " + led); - - if (pwm < 0 || pwm > MAX_PWM) - throw new IllegalArgumentException ("Invalid PWM " + pwm); - - final int index = PWM_BASE + led; - - FRAME[frame][index] = (byte) pwm; - - // Update the dirty values - - if (index > DIRTY_HIGH[frame]) - DIRTY_HIGH[frame] = index; - - if (index < DIRTY_LOW[frame]) - DIRTY_LOW[frame] = index; - } - - /** - * Update the display. - * - * @throws IOException In case of trouble. - */ - public void update () throws IOException - { - for (int i = 0; i < NUM_FRAMES; ++i) - { - if (DIRTY_HIGH[i] >= DIRTY_LOW[i]) - { - setPage (i); - - device.write(DIRTY_LOW[i], FRAME[i], DIRTY_LOW[i], DIRTY_HIGH[i] - DIRTY_LOW[i] + 1); - - DIRTY_LOW[i] = FRAME_LEN; - DIRTY_HIGH[i] = -1; - } - } - } - - /** - * Send a specific frame to the device. - * - * @param frame The frame to send. - * @param data The data to send. - * - * @throws IOException In case of trouble. - */ - private void sendFrame (int frame, byte[] data) throws IOException - { - if (frame < 0 || frame >= NUM_FRAMES) - throw new IllegalArgumentException ("Bad frame number " + frame); - - setPage (frame); - device.write (0, data); - } - - /** - * Send the function data to the device. - * - * @throws IOException In case of trouble. - */ - private void sendFunction () throws IOException - { - setPage (FUNCTION_PAGE); - device.write (0, FUNCTION_BUFFER); - } - - /** - * Set the page we're currently writing to. - * - * @param to The page we want to use. - * - * @throws IOException In case of trouble. - */ - private void setPage (int to) throws IOException - { - if ((to < 0 || to > 7) && to != FUNCTION_PAGE) - throw new IllegalArgumentException ("Bad page number " + to); - - if (to != current_page) - { - device.write (REG_CMD, (byte) to); - current_page = to; - } - } - - public static void main (String args[]) throws IOException, InterruptedException - { - IS31FL3731 d = new IS31FL3731 (Pi2C.useBus (), 0x74); - - for (int i = 0; i < 144; ++i) - { - d.setLed (0, i, 0xff); - d.update (); - Thread.sleep (100); - d.setLed (0, i, 0x00); - d.update (); - Thread.sleep (100); - } - } - - /** Number of LEDs per frame. */ - public final static int NUM_LEDS = 144; - /** Number of frames. */ - public final static int NUM_FRAMES = 8; - /** Maximum PWM value. */ - public final static int MAX_PWM = 0xff; - - /** Point to the device we're using. */ - private final I2CDevice device; - /** Current page we're on. */ - private int current_page = -1; - /** Two byte buffer. */ - //private final byte BUFFER2[] = new byte[2]; - - /** Frame output buffer. */ - //private final byte FRAME_BUFFER[] = new byte[1 + FRAME_LEN]; - /** Function buffer. */ - private final byte FUNCTION_BUFFER[] = new byte[FUNCTION_LEN]; - /** Frame storage. */ - private final byte FRAME[][] = new byte[NUM_FRAMES][FRAME_LEN]; - /** Dirty low marker. */ - private final int DIRTY_LOW[] = new int[NUM_FRAMES]; - /** Dirty high marker. */ - private final int DIRTY_HIGH[] = new int[NUM_FRAMES]; - - /** The command register. */ - private final static byte REG_CMD = (byte) 0xfd; - /** The function register page. */ - private final static int FUNCTION_PAGE = 0x0b; - - /** The configuration register. */ - private final static int REG_CONFIG = 0x00; - /** The display register. */ - private final static int REG_DISPLAY = 0x01; - private final static int REG_AP1 = 0x02; - private final static int REG_AP2 = 0x03; - /** The reserved register. */ - private final static int REG_RESERVED = 0x04; - /** The option register. */ - private final static int REG_OPTION = 0x05; - /** The audio register. */ - private final static int REG_AUDIO = 0x06; - /** The Frame register. */ - private final static int REG_FRAME = 0x07; - /** The breath register (part 1). */ - private final static int REG_BREATH1 = 0x08; - /** The breath register (part 2). */ - private final static int REG_BREATH2 = 0x09; - /** The shutdown register. */ - private final static int REG_SHUTDOWN = 0x0a; - /** The AGC control register. */ - private final static int REG_AGC_CTL = 0x0b; - /** The AGC rate register. */ - private final static int REG_AGC_RATE = 0x0c; - - /** Base of enable bits. */ - private final static int ENABLE_BASE = 0x00; - /** End of enable bits (+ 1!). */ - private final static int ENABLE_END = ENABLE_BASE + NUM_LEDS / 8; - /** Base of blink bits. */ - private final static int BLINK_BASE = ENABLE_END; - /** End of blink bits (+ 1!). */ - private final static int BLINK_END = BLINK_BASE + NUM_LEDS / 8; - /** Base of PWM data. */ - private final static int PWM_BASE = BLINK_END; - /** End of PWM data (+ 1!). */ - private final static int PWM_END = PWM_BASE + NUM_LEDS; - - /** Length of frame data. */ - private final static int FRAME_LEN = PWM_END; - /** Length of function data. */ - private final static int FUNCTION_LEN = 0x0d; -} diff --git a/Jimbo/Devices/MAX7219.java b/Jimbo/Devices/MAX7219.java deleted file mode 100644 index c208b11..0000000 --- a/Jimbo/Devices/MAX7219.java +++ /dev/null @@ -1,481 +0,0 @@ -/* - * Copyright (C) 2016 Jim Darby. - * - * This library 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. - * - * This library 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 this library. If not, see - * . - */ - -package Jimbo.Devices; - -import java.io.IOException; - -import com.pi4j.io.spi.SpiChannel; -import com.pi4j.io.spi.SpiDevice; -import com.pi4j.io.spi.SpiFactory; - -/** - * A class to talk to the MAX7219 display multiplexor. - * - * @author Jim Darby - */ -public class MAX7219 -{ - /** - * Constructor for a MAX7219 object. - * - * @param channel The SPI channel it's on. - * @param chained How many of them are chained. - * - * @throws IllegalArgumentException For an invalid argument. - * @throws IOException In case of error. - */ - public MAX7219 (SpiChannel channel, int chained) throws IllegalArgumentException, IOException - { - if (chained < 1) - throw new IllegalArgumentException ("MAX7219 needs at least one device"); - - this.chained = chained; - - // We set 10 MHz (device limit) but in practice it'll be a power of 2 so 8MHz. - dev = SpiFactory.getInstance (channel, 10000000, SpiDevice.DEFAULT_SPI_MODE); - - // Allocate the buffer - buffer = new byte[chained * BYTES_PER_DEV]; - - for (int i = 0; i < buffer.length; ++i) - buffer[i] = 0; - - tx_buffer = new byte[2 * chained]; - } - - /** - * Put a single value into the byte for a specific digit. This version sends - * it to all the displays. - * - * @param digit The digit to update. 0 to 7. - * @param value The byte value put in. - * - * @throws IOException In case of error. - */ - public void writeDigit (byte digit, byte value) throws IOException - { - validateDigit (digit); - - for (int i = 0; i < chained; ++i) - buffer[i * BYTES_PER_DEV + digit] = value; - } - - /** - * Put a single value into the byte for a specific digit on a specific - * device. The devices are numbered from 0 (the first in the chain) to - * the chained parameter passed to the constructor minus 1. - * - * @param device The device number. - * @param digit The digit to update. 0 to 7. - * @param value The byte value put in. - * - * @throws IOException In case of error. - */ - public void writeDigit (int device, byte digit, byte value) throws IOException - { - validateDevice (device); - validateDigit (digit); - - buffer[device * BYTES_PER_DEV + digit] = value; - } - - /** - * Sets the decode mode for all devices. - * - * @param mode The mode. One of DECODE_NONE, DECODE_B_FOR_0, - * DECODE_B_FOR_0_3 or DECODE_B_FOR_0_7. This either puts no decoding in - * (for DECODE_NONE) or maps the bottom four bits for digit 0 - * (DECODE_B_FOR_0), digits 1 to 3 (DECODE_B_FOR_0_3) or all the digits - * (DECODE_B_FOR_0_7). The decode turns the bottom 4 bits into 0 to 9, - * minus, E, H, L, P and blank (in that order). - * - * Does anyone else think someone was trapped in the factory and put the - * HELP in there as a “message in a bottle”? - * - * @throws IOException In case of error. - */ - public void setDecodeMode (byte mode) throws IOException - { - validateMode (mode); - - tx_update (REG_DECODE_MODE, mode); - } - - /** - * Sets the decode mode for a specific device.. - * - * @param device The device to be addressed. This starts at 0 and must be - * less than the total number of devices. - * @param mode The mode. One of DECODE_NONE, DECODE_B_FOR_0, - * DECODE_B_FOR_0_3 or DECODE_B_FOR_0_7. This either puts no decoding in - * (for DECODE_NONE) or maps the bottom four bits for digit 0 - * (DECODE_B_FOR_0), digits 1 to 3 (DECODE_B_FOR_0_3) or all the digits - * (DECODE_B_FOR_0_7). The decode turns the bottom 4 bits into 0 to 9, - * minus, E, H, L, P and blank (in that order). - * - * Does anyone else think someone was trapped in the factory and put the - * HELP in there as a “message in a bottle”? - * - * @throws IOException In case of error. - */ - public void setDecodeMode (int device, byte mode) throws IOException - { - validateDevice (device); - validateMode (mode); - - tx_update (REG_NO_OP, mode, device, REG_DECODE_MODE); - } - - /** - * Set the intensity of the device. - * - * @param intensity The intensity level. It must be in the range 0 to 15. - * - * @throws IOException In case of error. - */ - public void setIntensity (int intensity) throws IOException - { - validateIntensity (intensity); - - tx_update (REG_INTENSITY, (byte) intensity); - } - - /** - * Set the intensity of the device. - * - * @param device The device to be addressed. This starts at 0 and must be - * less than the total number of devices. - * @param intensity The intensity level. It must be in the range 0 to 15. - * - * @throws IOException In case of error. - */ - public void setIntensity (int device, int intensity) throws IOException - { - validateDevice (device); - validateIntensity (intensity); - - tx_update (REG_NO_OP, (byte) intensity, device, REG_INTENSITY); - } - - /** - * Set the scan limit on all devices. The scan limit is the number of - * displays actually used. The value is between 0 and 7 for 1 to 8 displays. - * - * @param limit The limit on the number of displays. - * - * @throws IOException In case of error. - */ - public void setScanLimit (int limit) throws IOException - { - validateDigit (limit); - - tx_update (REG_SCAN_LIMIT, (byte) limit); - } - - /** - * Set the scan limit on a specific device. The scan limit is the number of - * displays actually used. The value is between 0 and 7 for 1 to 8 displays. - * - * @param device The device this applies to. - * @param limit The limit on the number of displays. - * - * @throws IOException In case of error. - */ - public void setScanLimit (int device, int limit) throws IOException - { - validateDevice (device); - validateDigit (limit); - - tx_update (REG_NO_OP, (byte) limit, device, REG_SCAN_LIMIT); - } - - /** - * Set the shutdown status of all devices. - * - * @param active If true the device is shut down. - * - * @throws IOException In case of problems. - */ - public void shutdown (boolean active) throws IOException - { - tx_update (REG_SHUTDOWN, active ? (byte) 0 : (byte) 1); - } - - /** - * Set the shutdown status of a specific device. - * - * @param device The device this applies to. - * @param active If true the device is shut down. - * - * @throws IOException In case of problems. - */ - public void shutdown (int device, boolean active) throws IOException - { - validateDevice (device); - - tx_update (REG_NO_OP, active ? (byte) 0 : (byte) 1, device, REG_SHUTDOWN); - } - - /** - * Set test mode for all displays. This sets all segments of all the - * displays on. - * - * @param active True to engage, false to turn off. - * - * @throws IOException In case of problems. - */ - public void displayTest (boolean active) throws IOException - { - tx_update (REG_DISPLAY_TEST, active ? (byte) 1 : (byte) 0); - } - - /** - * Set test mode for all displays. This sets all segments of the display on. - * - * @param device The device this applies to. - * @param active True to engage, false to turn off. - * - * @throws IOException In case of problems. - */ - public void displayTest (int device, boolean active) throws IOException - { - validateDevice (device); - - tx_update (REG_NO_OP, active ? (byte) 1 : (byte) 0, device, REG_DISPLAY_TEST); - } - - /** - * Send all the display information to the device. This is done in one go to - * avoid excessive use of the bus on update of each digit. - * - * @throws IOException In case of problems. - */ - public void update () throws IOException - { - for (int digit = 0; digit < BYTES_PER_DEV; ++digit) - { - for (int device = 0; device < chained; ++device) - { - final int base = (chained - device - 1) * 2; - tx_buffer[base] = (byte) (REG_DIGIT0 + digit); - tx_buffer[base + 1] = buffer[device * BYTES_PER_DEV + digit]; - } - - dev.write (tx_buffer, 0, tx_buffer.length); - - /*System.out.print ("Buffer"); - - for (int i = 0; i < tx_buffer.length; ++i) - System.out.print (" " + tx_buffer[i]); - - System.out.println ();*/ - } - } - - /** - * Check if the device is valid. - * - * @param device The device ID. Must be in the range 0 ≤ device < chained. - */ - private void validateDevice (int device) - { - if (device < 0 || device >= chained) - throw new IllegalArgumentException ("Invalid device"); - } - - /** - * Check if the digit is valid. - * - * @param digit The digit on the device. Must be in the range 0 ≤ digit < 8. - */ - private void validateDigit (int digit) - { - if (digit < 0 || digit >= BYTES_PER_DEV) - throw new IllegalArgumentException ("Invalid digit"); - } - - /** - * Validate the device mode. It must be one of DECODE_NONE, DECODE_B_FOR_0, - * DECODE_B_FOR_0_3 or DECODE_B_FOR_0_7. - * - * @param mode The device mode. - */ - private void validateMode (int mode) - { - switch (mode) - { - case DECODE_NONE: - case DECODE_B_FOR_0: - case DECODE_B_FOR_0_3: - case DECODE_B_FOR_0_7: - break; - - default: - throw new IllegalArgumentException ("Invalid decode mode"); - } - } - - /** - * Validate the device intensity. It should be in the range 0 ≤ intensity - * < 16. - * - * @param intensity The intensity. - */ - private void validateIntensity (int intensity) - { - if (intensity < 0 || intensity > 0x0f) - throw new IllegalArgumentException ("Invalid intensity"); - } - - /** - * Transmit an update to all controllers. The command and parameter pair is - * sent to each device in the chain. - * - * @param command The command to send. - * @param param The command's parameter. - * - * @throws IOException In case of error. - */ - private void tx_update (byte command, byte param) throws IOException - { - tx_update (command, param, -1, REG_NO_OP); - } - - /** - * Transmit an update to all controllers. The command and parameter pair is - * sent to each device in the chain *except* for except which gets the - * command exception. - * - * @param command The command to send. - * @param param The command's parameter. - * @param except The device that gets a *different* command. - * @param exception What the command to the exception device is. - * - * @throws IOException In case of error. - */ - private void tx_update (byte command, byte param, int except, byte exception) throws IOException - { - for (int i = 0; i < chained; ++i) - { - final int base = (chained - i - 1) * 2; - tx_buffer[base] = (i == except) ? exception : command; - tx_buffer[base + 1] = param; - } - - /*System.out.print ("Buffer"); - - for (int i = 0; i < tx_buffer.length; ++i) - System.out.print (" " + tx_buffer[i]); - - System.out.println ();*/ - - dev.write (tx_buffer, 0, tx_buffer.length); - } - - - public static void main (String args[]) throws IOException, InterruptedException - { - MAX7219 m = new MAX7219 (SpiChannel.CS0, 2); - - m.shutdown (false); - - m.displayTest (true); - Thread.sleep (1000); - m.displayTest (0, false); - - m.setIntensity ((byte) 8); - m.setScanLimit ((byte) 7); - - for (byte digit = 0; digit < 8; ++digit) - m.writeDigit (0, digit, (byte) 0); - - m.setDecodeMode (DECODE_B_FOR_0_7); - - for (byte digit = 0; digit < 8; ++digit) - for (byte value = 0; value < 0x10; ++value) - { - m.writeDigit (0, digit, value); - m.update (); - Thread.sleep (500); - m.writeDigit (0, digit, (byte) 0); - } - - m.setDecodeMode (DECODE_NONE); - - for (byte digit = 0; digit < 8; ++digit) - for (byte bit = 0; bit < 8; ++bit) - { - m.writeDigit (0, digit, (byte) (1 << bit)); - m.update (); - Thread.sleep (500); - m.writeDigit (0, digit, (byte) 0); - } - - m.update (); - } - - /** Number of chained devices. */ - private final int chained; - /** The SPI device we're going to use. */ - private final SpiDevice dev; - /** The buffer that holds all the display information. */ - private final byte[] buffer; - /** The buffer we use to transmit commands. */ - private final byte[] tx_buffer; - - /** No decode mode. The bit maps goes to the segments. */ - public static final byte DECODE_NONE = 0x00; - /** Just decode the first display. */ - public static final byte DECODE_B_FOR_0 = 0x01; - /** Decode displays 0 to 3 and not 4 to 7. */ - public static final byte DECODE_B_FOR_0_3 = 0x0f; - /** Decode all the displays. */ - public static final byte DECODE_B_FOR_0_7 = (byte) 0xff; - - /** The number of bytes per device. Also the number of digits per device. */ - private static final int BYTES_PER_DEV = 8; - /** The NO-OP register. */ - private static final byte REG_NO_OP = 0x0; - /** The register for digit 0. */ - private static final byte REG_DIGIT0 = 0x1; - /** The register for digit 1. */ - private static final byte REG_DIGIT1 = 0x2; - /** The register for digit 2. */ - private static final byte REG_DIGIT2 = 0x3; - /** The register for digit 3. */ - private static final byte REG_DIGIT3 = 0x4; - /** The register for digit 4. */ - private static final byte REG_DIGIT4 = 0x5; - /** The register for digit 5. */ - private static final byte REG_DIGIT5 = 0x6; - /** The register for digit 6. */ - private static final byte REG_DIGIT6 = 0x7; - /** The register for digit 7. */ - private static final byte REG_DIGIT7 = 0x8; - /** The register that controls the decode mode. */ - private static final byte REG_DECODE_MODE = 0x9; - /** The register that controls the intensity. */ - private static final byte REG_INTENSITY = 0xa; - /** The register that controls the scan limit. */ - private static final byte REG_SCAN_LIMIT = 0xb; - /** The register that controls shutdown. */ - private static final byte REG_SHUTDOWN = 0xc; - /** The register that controls the display test. */ - private static final byte REG_DISPLAY_TEST = 0xf; -} diff --git a/Jimbo/Devices/Pi2C.java b/Jimbo/Devices/Pi2C.java deleted file mode 100644 index 6cabe90..0000000 --- a/Jimbo/Devices/Pi2C.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (C) 2016 Jim Darby. - * - * This library 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. - * - * This library 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 this library. If not, see - * . - */ - -package Jimbo.Devices; - -import com.pi4j.io.i2c.I2CBus; -import com.pi4j.io.i2c.I2CFactory; -import com.pi4j.system.SystemInfo; - -import java.io.IOException; - -/** - * This class let's us find the right I2C bus to use. It does so by looking at - * the hardware version. Now it can also return the board type, whether it's a - * plus (40 pin) board and if it's the original rev1. - * - * @author Jim Darby - */ -public class Pi2C -{ - /** - * Determine the correct I2C bus to use. - * @return The bus. - * @throws IOException In case of error. - * @throws InterruptedException In case of error. - */ - public static I2CBus useBus () throws IOException, InterruptedException - { - check_board (); - - return bus; - } - - /** - * Determine the board type. - * @return The board type. - * @throws IOException In case of error. - * @throws InterruptedException In case of error. - */ - public static SystemInfo.BoardType boardType () throws IOException, InterruptedException - { - check_board (); - - return type; - } - - /** - * Are we a plus (40-pin) model? - * @return if we are. - * @throws IOException In case of error. - * @throws InterruptedException In case of error. - */ - public static boolean isPlus () throws IOException, InterruptedException - { - check_board (); - - return plus; - } - - /** - * Check the board we're running on and see what we can find. - * @throws IOException In case of problems. - * @throws InterruptedException In case of problems. - */ - private static synchronized void check_board () throws IOException, InterruptedException - { - int use_i2cbus; - type = SystemInfo.getBoardType (); - - switch (type) - { - // What do we know that it's bus 0? This is the most useful as - // we know about all the old boards. - case RaspberryPi_A: - case RaspberryPi_B_Rev1: - // Use the original I2C bus, rev1 and not plus - use_i2cbus = I2CBus.BUS_0; - rev1 = true; - plus = false; - break; - - // What do we *know* that's bus 1? - case RaspberryPi_B_Rev2: - use_i2cbus = I2CBus.BUS_1; - rev1 = false; - plus = false; - break; - - // Now bus 1 and plus (40-pin connector - case RaspberryPi_A_Plus: - case RaspberryPi_B_Plus: - - case RaspberryPi_2B: - case RaspberryPi_3B: - case RaspberryPi_Zero: - case RaspberryPi_ZeroW: - use_i2cbus = I2CBus.BUS_1; - rev1 = false; - plus = true; - break; - - // End up here for uknown Pies - case RaspberryPi_Unknown: - throw new IOException ("Unknown Raspberry Pi model"); - - case UNKNOWN: - // End up here for totally unknown boards - throw new IOException ("Unknown board type"); - - // End up here if we're totally confused - default: - throw new IOException ("Unknown board type with unexpected return value"); - } - - try - { - bus = I2CFactory.getInstance (use_i2cbus); - } - - catch (I2CFactory.UnsupportedBusNumberException e) - { - throw new IOException ("Unable to find correct I2C bus."); - } - - board_looked = true; - } - - /** Holds the bus once we find it */ - private static I2CBus bus = null; - /** Have we looked for the board type? */ - private static boolean board_looked = false; - /** What board type have we found? */ - private static SystemInfo.BoardType type; - /** Are we running on a Plus? */ - private static boolean plus; - /** Are we running on a 1 rev 1? */ - private static boolean rev1; -} diff --git a/Jimbo/Devices/SN3218.java b/Jimbo/Devices/SN3218.java deleted file mode 100644 index 88c0488..0000000 --- a/Jimbo/Devices/SN3218.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (C) 2016 Jim Darby. - * - * This library 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. - * - * This library 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 this library; if not, see - * . - */ -package Jimbo.Devices; - -import java.io.IOException; - -import com.pi4j.io.i2c.I2CBus; -import com.pi4j.io.i2c.I2CDevice; - -/** - * The class interfaces to the Si-EN Technology SN3214 LED driver chip. This - * device is used in many cool devices, not least in things from Pimoroni for - * the Raspberry Pi. - * - * @author Jim Darby - */ -public class SN3218 { - - /** - * Construct a SN3218 driver. - * - * @param bus The bus the device is on. - * @throws IOException In case of problems. - */ - public SN3218 (I2CBus bus) throws IOException - { - // Set the data up. All enabled, all off - - for (int i = 0; i < LEDS; ++i) - data[i] = 0; - - for (int i = 0; i < ENABLES; ++i) - data[LEDS + i] = 0x3f; - - // Tell the device to go. Any value will do but this is in memory of - // Douglas Adams. - data[LEDS + ENABLES] = 42; - - // Allocate device - device = bus.getDevice (0x54); - - // And set everything up - device.write (0, wakeup, 0, wakeup.length); - } - - /** - * Set a single output to a value. - * - * @param led The LED (in the range 0 to 17). - * @param value The value (in the range 0 to 255). - * @throws IOException On an invalid parameter. - */ - public void set (int led, int value) throws IOException - { - if (led < 0 || led >= LEDS) - throw new IOException ("Invalid LED " + led); - - if (value < 0 || value > 255) - throw new IOException ("Invalid level " + value); - - data[led] = (byte) value; - } - - /** - * Set an RGB LED group with three values. The way the device is wired up - * determines the specific groupings. - * - * @param led The LED in the range 0 - 5. - * @param v1 The first value. - * @param v2 The second value. - * @param v3 The third value. - * @throws IOException On an invalid parameter. - */ - public void set (int led, int v1, int v2, int v3) throws IOException - { - if (led < 0 || led >= LEDS / 3) - throw new IOException ("Invalid RGB LED " + led); - - if (v1 < 0 || v1 > 255 || v2 < 0 || v2 > 255 || v3 < 0 || v3 > 255) - throw new IOException ("Invalid colour value"); - - data[led * 3 ] = (byte) v1; - data[led * 3 + 1] = (byte) v2; - data[led * 3 + 2] = (byte) v3; - } - - /** - * Update the display. This sends all the updated value to the LEDs. - * - * @throws IOException In case of an I2C error. - */ - public void update () throws IOException - { - device.write(1, data, 0, data.length); - } - - /** The I2C device. */ - private final I2CDevice device; - /** The number of LEDs. */ - private final static int LEDS = 18; - /** The number of enable bytes. */ - private final static int ENABLES = 3; - /** The number of go bytes. */ - private final static int GOS = 1; - /** The size of the data we hold: 18 values, 3 enables 1 go. */ - private final static int DATA_SIZE = LEDS + ENABLES + GOS; - /** The data we hold for the device. Starts at offset ONE in the device! */ - private final byte[] data = new byte[DATA_SIZE]; - /** Wakeup data. */ - private final byte[] wakeup = { - 0x01, // Wake up the device - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Data part one - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Data part two - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Data part three - 0x3f, 0x3f, 0x3f, // Enable all outputs - 0x42 // And go! - }; -} diff --git a/Jimbo/Devices/WS2811/Makefile b/Jimbo/Devices/WS2811/Makefile deleted file mode 100644 index 6b15db4..0000000 --- a/Jimbo/Devices/WS2811/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -CLASSPATH=/home/pi/NetBeansProjects/PiJava/build/classes -JAVAINC=-I /usr/lib/jvm/jdk-8-oracle-arm32-vfp-hflt/include -I /usr/lib/jvm/jdk-8-oracle-arm32-vfp-hflt/include/linux -RPI_WS281xDIR=/home/pi/rpi_ws281x - -libjavaws2811.so: WS2811.o ${RPI_WS281xDIR}/libws2811.a - gcc -o $@ -shared $^ -lstdc++ - -WS2811.o: WS2811.C Jimbo_Devices_WS2811_WS2811Raw.h ${RPI_WS281xDIR}/ws2811.h - gcc -O -c -g -fpic ${JAVAINC} -I ${RPI_WS281xDIR} WS2811.C - -Jimbo_Devices_WS2811_WS2811Raw.h: - javah -classpath ${CLASSPATH} Jimbo.Devices.WS2811.WS2811Raw - -clean: - rm libjavaws2811.so WS2811.o Jimbo_Devices_WS2811_WS2811Raw.h - -fred: - javah ~/NetBeansProjects/PiJava/build/classes/Jimbo/Devices/WS2812/WS2811Raw - gcc -o libws2811.so -shared WS2811Raw.o Build/rpi_ws281x/libws2811.a -lstdc++ diff --git a/Jimbo/Devices/WS2811/WS2811.C b/Jimbo/Devices/WS2811/WS2811.C deleted file mode 100644 index 69ac3c2..0000000 --- a/Jimbo/Devices/WS2811/WS2811.C +++ /dev/null @@ -1,158 +0,0 @@ -#include -#include - -extern "C" { -#include -} - -#include "Jimbo_Devices_WS2811_WS2811Raw.h" - -namespace -{ - bool in_use (false); - - const int TARGET_FREQ (WS2811_TARGET_FREQ); - const int GPIO_PIN (18); - const int DMA (10); - - ws2811_t leds; -} - -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: WS2811_WS2811 - * Method: ws2811_init - * Signature: (I)Z - */ -JNIEXPORT jboolean JNICALL Java_Jimbo_Devices_WS2811_WS2811Raw_ws2811_1init - (JNIEnv *env, jclass c, jint type, jint length) -{ - if (in_use) - return JNI_FALSE; - - // std::cout << "In C++ land, type = " << type - // << " length = " << length - // << std::endl; - - leds.freq = TARGET_FREQ; - leds.dmanum = DMA; - leds.channel[0].gpionum = GPIO_PIN; - leds.channel[0].count = length; - leds.channel[0].invert = 0; - leds.channel[0].brightness = 255; - leds.channel[0].strip_type = type; - leds.channel[1].gpionum = 0; - leds.channel[1].count = 0; - leds.channel[1].invert = 0; - leds.channel[1].brightness = 0; - - if (ws2811_init (&leds) != WS2811_SUCCESS) - return JNI_FALSE; - - in_use = true; - - return JNI_TRUE; -} - -/* - * Class: Jimbo_Devices_WS2811_WS2811Raw - * Method: ws2811_brightness - * Signature: (I)Z - */ - -JNIEXPORT jboolean JNICALL Java_Jimbo_Devices_WS2811_WS2811Raw_ws2811_1brightness - (JNIEnv *env, jclass c, jint value) -{ - if (value < 0 || value > 255) - { - std::cerr << "WS2811 brightness set to " << value << std::endl; - return JNI_FALSE; - } - - leds.channel[0].brightness = value; - return JNI_TRUE; -} - -/* - * Class: WS2811_WS2811 - * Method: ws2811_update - * Signature: ([I)Z - */ -JNIEXPORT jboolean JNICALL Java_Jimbo_Devices_WS2811_WS2811Raw_ws2811_1update - (JNIEnv *env, jclass c, jintArray jdata) -{ - if (!in_use) - return JNI_FALSE; - - jboolean copy; - - const jint len = env->GetArrayLength (jdata); - - // std::cout << "Update with " << len << " items" << std::endl; - - if (len != leds.channel[0].count) - return JNI_FALSE; - - jint *raw = env->GetIntArrayElements (jdata, ©); - - // std::cout << "Got the data, copy is " << (int) copy << std::endl; - // std::cout << "Data at " << leds.channel[0].leds << std::endl; - - for (int i = 0; i < len; ++i) - leds.channel[0].leds[i] = raw[i]; - - // std::cout << "Releasing elements" << std::endl; - - env->ReleaseIntArrayElements (jdata, raw, 0); - - // std::cout << "Rendering" << std::endl; - - ws2811_render (&leds); - - // std::cout << "And we're done" << std::endl; - - return JNI_TRUE; -} - -/* - * Class: WS2811_WS2811 - * Method: ws2811_wait - * Signature: ()Z - */ -JNIEXPORT jboolean JNICALL Java_Jimbo_Devices_WS2811_WS2811Raw_ws2811_1wait - (JNIEnv *env, jclass c) -{ - if (!in_use) - return JNI_FALSE; - - // std::cout << "Wait" << std::endl; - - ws2811_wait (&leds); - - return JNI_TRUE; -} - -/* - * Class: WS2811_WS2811 - * Method: ws2811_close - * Signature: ()Z - */ -JNIEXPORT jboolean JNICALL Java_Jimbo_Devices_WS2811_WS2811Raw_ws2811_1close - (JNIEnv *env, jclass c) -{ - const bool result = in_use; - - // std::cout << "That's all folks!" << std::endl; - - in_use = false; - - ws2811_fini (&leds); - - return result; -} - -#ifdef __cplusplus -} -#endif diff --git a/Jimbo/Devices/WS2811/WS2811.java b/Jimbo/Devices/WS2811/WS2811.java deleted file mode 100644 index e185d42..0000000 --- a/Jimbo/Devices/WS2811/WS2811.java +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright (C) 2016-2017 Jim Darby. - * - * This library 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. - * - * This library 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 this library; if not, see - * . - */ - -package Jimbo.Devices.WS2811; - -import Jimbo.Graphics.Mapping; -import Jimbo.Graphics.Point; -import Jimbo.Graphics.Colour; -import Jimbo.Graphics.ColourMatrix; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.StandardCopyOption; - -/** - * Provide a sensible interface to the WS2811 library. IT tries to - * provide access to the essentials of the underlying C library. - * - * @author Jim Darby - */ -public class WS2811 implements ColourMatrix -{ - /** - * Create an interface to the WS2811 hardware. - * - * @param width The width of the display. - * @param height The height of the display. - * @param map A mapping that takes (0,0) as the lower left and converts it - * into whatever the display actually uses. - * @param type The type of the display. One of WS2811Raw.WS2811_STRIP_RGB, - * SWS2811Raw.W2811_STRIP_RBG, WS2811Raw.WS2811_STRIP_GRB, - * WS2811Raw.WS2811_STRIP_GBR, WS2811Raw.WS2811_STRIP_BRG, - * WS2811Raw.WS2811_STRIP_BGR. - * @param brightness A scaling factor for the brightness: [0.0,1.0]. - */ - public WS2811 (int width, int height, - Mapping map, - int type, - double brightness) - { - if (width <= 0 || height <= 0 || - (type != WS2811Raw.WS2811_STRIP_RGB) && - (type != WS2811Raw.WS2811_STRIP_RBG) && - (type != WS2811Raw.WS2811_STRIP_GRB) && - (type != WS2811Raw.WS2811_STRIP_GBR) && - (type != WS2811Raw.WS2811_STRIP_BRG) && - (type != WS2811Raw.WS2811_STRIP_BGR) || - brightness < 0 || brightness > 1) - throw new IllegalArgumentException ("Invalid parameter to WS2811"); - - i_width = width; - i_height = height; - max = new Point (i_width - 1, i_height - 1); - - final Point out = map.getOutMax (); - - final int o_width = out.getX () + 1; - final int o_height = out.getY () + 1; - - leds = o_width * o_height; - this.map = new int[leds]; - data = new int[leds]; - - for (int y = 0; y < i_height; ++y) - for (int x = 0; x < i_width; ++x) - { - final Point p = map.map (new Point (x, y)); - final int value = p.getX () + o_width * p.getY (); - - this.map[x + i_width * y] = value; - } - - for (int i = 0; i < leds; ++i) - data[i] = 0; - - loadNative (); - - if (!WS2811Raw.ws2811_init (type, leds)) - throw new IllegalArgumentException ("Unable to start WS2811"); - - WS2811Raw.ws2811_brightness ((int) (brightness * 255)); - WS2811Raw.ws2811_update (data); - } - - /** - * Set a specific pixel to a specific RGB value. This works in the - * most efficient way. - * - * @param p The point to set. - * @param r Red value: [0,255]. - * @param g Green value: [0,255]. - * @param b Blue value: [0,255]. - */ - @Override - public void setPixel (Point p, int r, int g, int b) - { - if (!p.inside (max) || - r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255) - throw new IllegalArgumentException ("Invalid parameter to WS2811.setPixel"); - - final int x = p.getX (); - final int y = p.getY (); - - // System.out.println ("pos " + x + ',' + y + " -> " + map[x + i_width * y]); - - data[map[x + i_width * y]] = (r << 16) | (g << 8) | b; - } - - /** - * Set a specific pixel to a specific colour. This is the generic - * interface. - * - * @param p The pixel to set. - * @param c The colour to set. - */ - @Override - public void setPixel (Point p, Colour c) - { - setPixel (p, c.getRed (), c.getGreen (), c.getBlue ()); - } - - /** - * Send the data to the string. - */ - @Override - public void show () - { - WS2811Raw.ws2811_update (data); - } - - /** - * Return a point with the maximum values for X and Y in this - * matrix. - * - * @return The maximum size. - */ - @Override - public Point getMax () - { - return max; - } - - /** - * Shut everything down. - */ - void close () - { - WS2811Raw.ws2811_close (); - } - - /** - * Support routine to load the native library. Very strongly inspired - * by code from the pi4j library itself. - */ - private static void loadNative () - { - if (nativeLoaded) - return; - - try - { - final String path = "/Jimbo/Devices/WS2811/libjavaws2811.so"; - - Path inputPath = Paths.get (path); - - if (!inputPath.isAbsolute ()) - throw new IllegalArgumentException ("The path has to be absolute, but found: " + inputPath); - - final String fileNameFull = inputPath.getFileName ().toString (); - final int dotIndex = fileNameFull.indexOf ('.'); - - if (dotIndex < 0 || dotIndex >= fileNameFull.length () - 1) - throw new IllegalArgumentException ("The path has to end with a file name and extension, but found: " + fileNameFull); - - final String fileName = fileNameFull.substring (0, dotIndex); - final String extension = fileNameFull.substring (dotIndex); - - final Path target = Files.createTempFile (fileName, extension); - final File targetFile = target.toFile (); - - targetFile.deleteOnExit (); - - // System.out.println ("Tempfile at " + target); - - try (InputStream source = WS2811.class.getResourceAsStream (inputPath.toString ())) - { - if (source == null) - throw new FileNotFoundException ("File " + inputPath + " was not found in classpath."); - - Files.copy (source, target, StandardCopyOption.REPLACE_EXISTING); - } - - // Finally, load the library - System.load (target.toAbsolutePath ().toString ()); - } - - catch (Exception | UnsatisfiedLinkError e) - { - System.out.println ("Failed to load native library: " + e); - } - - nativeLoaded = true; - } - - /** The total input width. */ - final private int i_width; - /** The total input height. */ - final private int i_height; - /** A point containing the maximum values for X and Y. */ - final private Point max; - - /** The total number of LEDs (WS2811s to be precise) we have. */ - final private int leds; - - /** The map from input (X,Y) to data (X,Y). */ - final private int[] map; - /** The data of what is on the string (or will be when show is called. */ - final private int[] data; - - /** Have we loaded the native library. */ - private static boolean nativeLoaded = false; -} diff --git a/Jimbo/Devices/WS2811/WS2811Raw.java b/Jimbo/Devices/WS2811/WS2811Raw.java deleted file mode 100644 index 969f082..0000000 --- a/Jimbo/Devices/WS2811/WS2811Raw.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2017 Jim Darby. - * - * This library 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. - * - * This library 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 this library; if not, see - * . - */ - -package Jimbo.Devices.WS2811; - -/** - * The most basic interface to the native libraries. We try and do as much as - * possible in Java land. - * - * @author Jim Darby - */ - -public class WS2811Raw -{ - /** - * Initialise the system. Only one user may use it at once. - * @param type The type of the string. One of WS2811_STRIP_RGB, - * WS2811_STRIP_RBG, WS2811_STRIP_GRB, WS2811_STRIP_GBR, WS2811_STRIP_BRG - * or WS2811_STRIP_BGR. - * - * @param length the number of units in the string - * - * @return If it worked. - */ - public static native boolean ws2811_init (int type, int length); - - /** - * Set the brightness level. The value is a double in the range 0.0 to 1.0. - * - * @param level The scaling in the range 0 to 255. - * - * @return true if it worked. - */ - public static native boolean ws2811_brightness (int level); - - /** - * Send the data to the string. - * - * @param data An array of ints, one per unit in the string. This must me - * the same length as used for the ws2811_init method. - * - * @return If it worked. - */ - public static native boolean ws2811_update (int[] data); - - /** - * Wait for the DMA to complete. - * - * @return If it worked. - */ - public static native boolean ws2811_wait (); - - /** - * Shut the system down. - * - * @return If it worked. - */ - public static native boolean ws2811_close (); - - public static final int WS2811_STRIP_RGB = 0x100800; - public static final int WS2811_STRIP_RBG = 0x100008; - public static final int WS2811_STRIP_GRB = 0x081000; - public static final int WS2811_STRIP_GBR = 0x080010; - public static final int WS2811_STRIP_BRG = 0x001008; - public static final int WS2811_STRIP_BGR = 0x000810; -} diff --git a/Jimbo/Graphics/BitMatrix.java b/Jimbo/Graphics/BitMatrix.java deleted file mode 100644 index f19e538..0000000 --- a/Jimbo/Graphics/BitMatrix.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2018 Jim Darby. - * - * This library 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. - * - * This library 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 this library; if not, see - * . - */ - -package Jimbo.Graphics; - -/** - * This interface describes a matrix of bit values. - * - * @author Jim Darby - */ -public interface BitMatrix extends Matrix -{ - /** - * Sets a pixel to a specific colour. - * - * @param x The X coordinate of the pixel. - * @param y The Y coordinate of the pixel. - * @param on If the pixel is on. - */ - default public void setPixel (int x, int y, boolean on) - { - setPixel (new Point (x, y), on); - } - - /** - * Clear (blank) a pixel at a specific point. - * - * @param p The pixel to clear. - */ - @Override - default void clearPixel (Point p) - { - setPixel (p, BLACK); - } - - /** The value used to clear a pixel. */ - static final boolean BLACK = false; -} diff --git a/Jimbo/Graphics/BitMatrixDemo.java b/Jimbo/Graphics/BitMatrixDemo.java deleted file mode 100644 index 3f07945..0000000 --- a/Jimbo/Graphics/BitMatrixDemo.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2017 Jim Darby. - * - * This library 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. - * - * This library 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 this library. If not, see - * . - */ - -package Jimbo.Graphics; - -import java.io.IOException; - -/** - * Do a demo on an arbitrary BitMatrix. - * - * @author Jim Darby - */ -public class BitMatrixDemo -{ - /** - * Run the demo given a ColourMatrix. - * - * @param m The ColourMatrix to use. - * - * @throws InterruptedException In case of thread badness. - * @throws java.io.IOException In case of trouble. - */ - public static void run (BitMatrix m) throws InterruptedException, IOException - { - final Point limits = m.getMax (); - final int max_x = limits.getX (); - final int max_y = limits.getY (); - - while (true) - for (int on = 0; on < 2; ++on) - for (int x = 0; x <= max_x; ++x) - for (int y = 0; y <= max_y; ++y) - { - m.setPixel (x, y, on == 0); - m.show (); - Thread.sleep (50); - } - } -} diff --git a/Jimbo/Graphics/Colour.java b/Jimbo/Graphics/Colour.java deleted file mode 100644 index aed1134..0000000 --- a/Jimbo/Graphics/Colour.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2017 Jim Darby. - * - * This library 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. - * - * This library 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 this library; if not, see - * . - */ - -package Jimbo.Graphics; - -/** - * This class describes a colour. - * - * @author Jim Darby - */ -public class Colour -{ - /** - * Create from red, green and blue values. All in the range 0 to 255. - * If this condition isn't met it will throw an IllegalArgumentException. - * - * @param red The red component. - * @param green The green component. - * @param blue The blue component. - */ - public Colour (int red, int green, int blue) - { - if (red < 0 || red > 255 || - green < 0 || green > 255 || - blue < 0 || blue > 255) - throw new IllegalArgumentException ("Invalid parameter to Colour"); - - this.red = red; - this.green = green; - this.blue = blue; - } - - /** - * Create the colour from an angle (in degrees) in a colour wheel. 0 - * is full red, 120 is full green and 240 is full blue. It must be in the - * range 0 to 360 inclusive. If this condition isn't met it will throw an - * IllegalArgumentException. - * - * @param angle The angle in the range 0 to 360 inclusive. - */ - public Colour (double angle) - { - if (angle >= 0 && angle < 120) - { - red = (int) (255 * (120.0 - angle) / 120.0); - green = 255 - red; - blue = 0; - - return; - } - - if (angle >= 120 && angle < 240) - { - red = 0; - green = (int) (255 * (240.0 - angle) / 120.0); - blue = 255 - green; - - return; - } - - if (angle >= 240 && angle <= 360) - { - green = 0; - blue = (int) (255 * (360.0 - angle) / 120.0); - red = 255 - blue; - - return; - } - - throw new IllegalArgumentException ("Invalid parameter to Colour"); - } - - /** - * Return the red component. - * - * @return The value. - */ - public int getRed () - { - return red; - } - - /** - * Return the green component. - * - * @return The value. - */ - public int getGreen () - { - return green; - } - - /** - * Return the blue component. - * - * @return The value. - */ - public int getBlue () - { - return blue; - } - - /** Where we store the red value. */ - final private int red; - /** Where we store the green value. */ - final private int green; - /** Where we store the blue value. */ - final private int blue; -} diff --git a/Jimbo/Graphics/ColourMatrix.java b/Jimbo/Graphics/ColourMatrix.java deleted file mode 100644 index a17606f..0000000 --- a/Jimbo/Graphics/ColourMatrix.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2018 Jim Darby. - * - * This library 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. - * - * This library 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 this library; if not, see - * . - */ - -package Jimbo.Graphics; - -/** - * This interface describes a matrix of RGB Pixels. - * - * @author Jim Darby - */ -public interface ColourMatrix extends Matrix -{ - /** - * Sets a pixel to a specific colour. - * - * @param p The address of the Pixel. - * @param r The red value: 0 to 255. - * @param g The green value: 0 to 255. - * @param b The blue value: 0 to 255. - */ - default public void setPixel (Point p, int r, int g, int b) - { - setPixel (p, new Colour (r, g, b)); - } - - /** - * Sets a pixel to a specific colour. - * - * @param x The X coordinate of the pixel. - * @param y The Y coordinate of the pixel. - * @param r The red value: 0 to 255. - * @param g The green value: 0 to 255. - * @param b The blue value: 0 to 255. - */ - default public void setPixel (int x, int y, int r, int g, int b) - { - setPixel (new Point (x, y), new Colour (r, g, b)); - } - - /** - * Sets a pixel to a specific colour. - * - * @param x The X coordinate of the pixel. - * @param y The Y coordinate of the pixel. - * @param c The colour to set it to. - */ - default public void setPixel (int x, int y, Colour c) - { - setPixel (new Point (x, y), c); - } - - /** - * Clear (blank) a pixel at a specific point. - * - * @param p The pixel to clear. - */ - @Override - default void clearPixel (Point p) - { - setPixel (p, BLACK); - } - - /** The colour used for clearing a pixel. */ - static final Colour BLACK = new Colour (0, 0, 0); -} diff --git a/Jimbo/Graphics/ColourMatrixDemo.java b/Jimbo/Graphics/ColourMatrixDemo.java deleted file mode 100644 index 13acec9..0000000 --- a/Jimbo/Graphics/ColourMatrixDemo.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (C) 2017 Jim Darby. - * - * This library 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. - * - * This library 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 this library; if not, see - * . - */ - -package Jimbo.Graphics; - -import java.io.IOException; - -/** - * Do a demo on an arbitrary ColourMatrix. - * - * @author Jim Darby - */ -public class ColourMatrixDemo implements Runnable -{ - public ColourMatrixDemo (ColourMatrix m) - { - this.m = m; - } - - @Override - public void run () - { - try - { - run (m); - } - - catch (InterruptedException | IOException e) - { - System.out.println ("ColourMatrixDemo thread got an exception: " + e); - } - } - - /** - * Run the demo given a ColourMatrix. This is a static, non-threaded - * version but is used by the threaded non-static version. - * - * @param m The ColourMatrix to use. - * - * @throws InterruptedException In case of thread badness. - * @throws java.io.IOException In case of trouble. - */ - public static void run (ColourMatrix m) throws InterruptedException, IOException - { - final Point limits = m.getMax (); - final int max_x = limits.getX (); - final int max_y = limits.getY (); - - // Basic scan - - int phase = 0; - - for (int y = 0; y <= max_y; ++y) - for (int x = 0; x <= max_x; ++x) - { - final Point p = new Point (x, y); - m.setPixel (p, - (phase == 0) ? 0x80 : 0x00, - (phase == 1) ? 0x80 : 0x00, - (phase == 2) ? 0x80 : 0x00); - m.show (); - Thread.sleep (250); - m.setPixel (p, 0x00, 0x00, 0x00); - m.show (); - Thread.sleep (50); - - phase = (phase + 1) % 3; - } - - // "I made it rainbow!" TM - - phase = 0; - - final double max_distance = Math.sqrt (max_x * max_x + max_y * max_y); - - while (true) - { - for (int y = 0; y <= limits.getY (); ++y) - for (int x = 0; x <= limits.getX (); ++x) - { - final double distance = Math.sqrt (x*x + y*y); - final double fraction = distance / max_distance; - - double value = 360 * (1 - fraction) + phase; - - if (value > 360) - value -= 360; - - final Colour c = new Colour (value); - - m.setPixel (new Point (x, y), c); - } - - m.show (); - - phase += 1; - - if (phase == 360) - phase = 0; - - Thread.sleep (10); - } - } - - /** The matrix we'll be working on. */ - private final ColourMatrix m; -} diff --git a/Jimbo/Graphics/FlipX.java b/Jimbo/Graphics/FlipX.java deleted file mode 100644 index 5e9db5f..0000000 --- a/Jimbo/Graphics/FlipX.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2017 Jim Darby. - * - * This library 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. - * - * This library 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 this library; if not, see - * . - */ - -package Jimbo.Graphics; - -/** - * This class flips the X coordinates of a point around. So if the input x - * range is 0 to n the mapped X point will be n - x. The y coordinate remains - * the same. - * - * @author Jim Darby - */ -public class FlipX extends Mapping -{ - /** - * Create a mapping given the width and height of the input. Note that the - * valid X coordinates are from 0 to width - 1 and the valid Y coordinates - * are from 0 to height - 1. - * - * @param width The input width. - * @param height The input height. - */ - public FlipX (int width, int height) - { - super (new Point (width - 1, height - 1)); - } - - /** - * Create a mapping given a previous mapping. The width and height are - * inherited from the previous item. - * - * @param before The previous mapping. - */ - public FlipX (Mapping before) - { - super (before, before.getOutMax ()); - } - - /** - * Perform a mapping. Given a point p at (X,Y) it returns a point with the - * X coordinate reversed (i.e. with X in the range [0,n] it returns n - x. - * Y remains unchanged. - * - * @param p The input point. - * @return The mapped result. - */ - @Override - public Point map (Point p) - { - if (before != null) - p = before.map (p); - - validateIn (p); - - final Point result = new Point (getInMax ().getX () - p.getX (), p.getY ()); - - validateOut (result); - - return result; - } - - /** - * Return a printable form of the mapping. - * - * @return The String representation. - */ - @Override - public String toString () - { - String result = "FlipX from " + getInMax () + " to " + getOutMax (); - - if (before != null) - result = before.toString () + ' ' + result; - - return result; - } -} - diff --git a/Jimbo/Graphics/FlipY.java b/Jimbo/Graphics/FlipY.java deleted file mode 100644 index bc8fad1..0000000 --- a/Jimbo/Graphics/FlipY.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2017 Jim Darby. - * - * This library 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. - * - * This library 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 this library; if not, see - * . - */ - -package Jimbo.Graphics; - -/** - * This class flips the Y coordinates of a point around. So if the input y - * range is 0 to n the mapped Y point will be n - y. The X coordinate remains - * the same. - * - * @author Jim Darby - */ -public class FlipY extends Mapping -{ - /** - * Create a mapping given the width and height of the input. Note that the - * valid X coordinates are from 0 to width - 1 and the valid Y coordinates - * are from 0 to height - 1. - * - * @param width The input width. - * @param height The input height. - */ - public FlipY (int width, int height) - { - super (new Point (width - 1, height - 1)); - } - - /** - * Create a mapping given a previous mapping. The width and height are - * inherited from the previous item. - * - * @param before The previous mapping. - */ - public FlipY (Mapping before) - { - super (before, before.getOutMax ()); - } - - /** - * Perform a mapping. Given a point p at (X,Y) it returns a point with the - * Y coordinate reversed (i.e. with Y in the range [0,n] it returns n - y. - * X remains unchanged. - * - * @param p The input point. - * @return The mapped result. - */ - @Override - public Point map (Point p) - { - if (before != null) - p = before.map (p); - - validateIn (p); - - final Point result = new Point (p.getX (), getInMax ().getY () - p.getY ()); - - validateOut (result); - - return result; - } - - /** - * Return a printable form of the mapping. - * - * @return The String representation. - */ - @Override - public String toString () - { - String result = "FlipY from " + getInMax () + " to " + getOutMax (); - - if (before != null) - result = before.toString () + ' ' + result; - - return result; - } -} diff --git a/Jimbo/Graphics/Identity.java b/Jimbo/Graphics/Identity.java deleted file mode 100644 index f1e450c..0000000 --- a/Jimbo/Graphics/Identity.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2017 Jim Darby. - * - * This library 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. - * - * This library 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 this library; if not, see - * . - */ - -package Jimbo.Graphics; - -/** - * This class flips the X coordinates of a point around. So if the input x - * range is 0 to n the mapped X point will be n - x. The y coordinate remains - * the same. - * - * @author Jim Darby - */ -public class Identity extends Mapping -{ - /** - * Create a mapping given the width and height of the input. Note that the - * valid X coordinates are from 0 to width - 1 and the valid Y coordinates - * are from 0 to height - 1. - * - * @param width The input width. - * @param height The input height. - */ - public Identity (int width, int height) - { - super (new Point (width - 1, height - 1)); - } - - /** - * Create a mapping given a previous mapping. The width and height are - * inherited from the previous item. - * - * @param before The previous mapping. - */ - public Identity (Mapping before) - { - super (before, before.getOutMax ()); - } - - /** - * Perform a mapping. This performs no actual action on the Point! - * - * @param p The input point. - * @return The mapped result. - */ - @Override - public Point map (Point p) - { - if (before != null) - p = before.map (p); - - validateIn (p); - - final Point result = p; - - validateOut (result); - - return result; - } - - /** - * Return a printable form of the mapping. - * - * @return The String representation. - */ - @Override - public String toString () - { - String result = "Identity from " + getInMax () + " to " + getOutMax (); - - if (before != null) - result = before.toString () + ' ' + result; - - return result; - } -} - diff --git a/Jimbo/Graphics/Mapping.java b/Jimbo/Graphics/Mapping.java deleted file mode 100644 index cb47432..0000000 --- a/Jimbo/Graphics/Mapping.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2017 Jim Darby. - * - * This library 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. - * - * This library 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 this library; if not, see - * . - */ -package Jimbo.Graphics; - -/** - * This defines the generic mapping class hierarchy. It takes an input Point - * and produces an output point. - * - * @author Jim Darby - */ -public abstract class Mapping -{ - /** - * Define a mapping where both input and output sizes are the same. - * - * @param inOutMax A point giving the maximum values for X and Y in both - * input and output - */ - public Mapping (Point inOutMax) - { - inMax = inOutMax; - outMax = inOutMax; - before = null; - } - - /** - * Define a mapping where input and output sizes are different. - * - * @param inMax The maximum input size. - * @param outMax The maximum output size. - */ - public Mapping (Point inMax, Point outMax) - { - this.inMax = inMax; - this.outMax = outMax; - before = null; - } - - /** - * Define a mapping where the input size is determined by a previous - * transformation and the output size is given. The previous transformation - * is remembered and performed whenever a mapping is done. - * - * @param before The previous transformation. - * @param outMax The output size. - */ - public Mapping (Mapping before, Point outMax) - { - this.inMax = before.getOutMax (); - this.outMax = outMax; - this.before = before; - } - - /** - * Validate that the input parameter is within the size expected, - * - * @param p The input point. - */ - public void validateIn (Point p) - { - if (p.inside (inMax)) - return; - - throw new IllegalArgumentException ("Input co-ordinate " + p + " outside " + inMax); - } - - /** - * Validate that the output parameter is within the size expected, - * - * @param p The output point. - */ - public void validateOut (Point p) - { - if (p.inside (outMax)) - return; - - throw new IllegalArgumentException ("Output co-ordinate " + p + " outside " + outMax); - } - - /** - * Return the input limit. - * - * @return The input limit. - */ - public Point getInMax () - { - return inMax; - } - - /** - * Return the original input limit. If we have a previous mapping then ask - * that otherwise return ours. - * - * @return The original input limit. - */ - public Point getOriginalMax () - { - return (before == null) ? inMax : before.getOriginalMax (); - } - - /** - * Return the output limit. - * - * @return The output limit. - */ - public Point getOutMax () - { - return outMax; - } - - /** - * Abstract method to perform a mapping. - * - * @param p The point to map. - * @return The mapped value. - */ - abstract public Point map (Point p); - - /** - * Return a printable version of the mapping. - * - * @return A printable String. - */ - @Override - abstract public String toString (); - - /** The input maximum. */ - protected final Point inMax; - /** The output maximum. */ - protected final Point outMax; - /** The previous mapping. */ - protected Mapping before; -} diff --git a/Jimbo/Graphics/Matrix.java b/Jimbo/Graphics/Matrix.java deleted file mode 100644 index 962bd82..0000000 --- a/Jimbo/Graphics/Matrix.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2018 Jim Darby. - * - * This library 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. - * - * This library 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 this library; if not, see - * . - */ - -package Jimbo.Graphics; - -import java.io.IOException; - -/** - * This interface is the top level of the Matrix hierarchy. It just has - * a size on it. - * - * @author Jim Darby - * @param The type of pixel it is - */ -public interface Matrix -{ - /** - * Return a point with the maximum values for X and Y in this - * matrix. - * - * @return The maximum size. - */ - public Point getMax (); - - /** - * Set a pixel to a specific value. - * - * @param p The pixel to set. - * @param value The value to set it to. - */ - void setPixel (Point p, T value); - - /** - * Clear (blank) a pixel at a specific point. - * - * @param p The pixel to clear. - */ - void clearPixel (Point p); - - /** - * Update the display. - * - * @throws java.io.IOException In case of trouble. - */ - public void show () throws IOException; -} diff --git a/Jimbo/Graphics/MonoMatrix.java b/Jimbo/Graphics/MonoMatrix.java deleted file mode 100644 index cc9a44b..0000000 --- a/Jimbo/Graphics/MonoMatrix.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2018 Jim Darby. - * - * This library 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. - * - * This library 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 this library; if not, see - * . - */ - -package Jimbo.Graphics; - -/** - * This interface describes a matrix of monochrome Pixels. - * - * @author Jim Darby - */ -public interface MonoMatrix extends Matrix -{ - /** - * Sets a pixel to a specific value. - * - * @param x The X coordinate of the pixel. - * @param y The Y coordinate of the pixel. - * @param value The value to set in the range 0 to 255. - */ - default public void setPixel (int x, int y, int value) - { - setPixel (new Point (x, y), new Integer (value)); - } - - /** - * Sets a pixel to a specific value. - * - * @param p The pixel to set. - * @param value The value to set in the range 0.0 to 1.0. - */ - default public void setPixel (Point p, double value) - { - if (value < 0 || value > 1) - throw new IllegalArgumentException ("Invalid pixel value " + value); - - setPixel (p, new Integer ((int) (value * 255 + 0.5))); - } - - /** - * Sets a pixel to a specific value. - * - * @param x The X coordinate of the pixel. - * @param y The Y coordinate of the pixel. - * @param value The value to set in the range 0.0 to 1.0. - */ - default public void setPixel (int x, int y, double value) - { - if (value < 0 || value > 1) - throw new IllegalArgumentException ("Invalid pixel value " + value); - - setPixel (new Point (x, y), new Integer ((int) (value * 255 + 0.5))); - } - - /** - * Clear (blank) a pixel at a specific point. - * - * @param p The pixel to clear. - */ - @Override - default void clearPixel (Point p) - { - setPixel (p, BLACK); - } - - /** The value used to clear a pixel. */ - static final Integer BLACK = 0; -} diff --git a/Jimbo/Graphics/MonoMatrixDemo.java b/Jimbo/Graphics/MonoMatrixDemo.java deleted file mode 100644 index 81c716f..0000000 --- a/Jimbo/Graphics/MonoMatrixDemo.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2018 Jim Darby. - * - * This library 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. - * - * This library 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 this library; if not, see - * . - */ - -package Jimbo.Graphics; - -import java.io.IOException; - -/** - * Do a demo on an arbitrary MonoMatrix. - * - * @author Jim Darby - */ -public class MonoMatrixDemo -{ - /** - * Run the demo given a ColourMatrix. - * - * @param m The ColourMatrix to use. - * - * @throws InterruptedException In case of thread badness. - * @throws java.io.IOException In case of trouble. - */ - public static void run (MonoMatrix m) throws InterruptedException, IOException - { - final Point limits = m.getMax (); - final int max_x = limits.getX (); - final int max_y = limits.getY (); - final Double on = new Double (1); - final Double off = new Double (0); - final Clock clock = Clock.isClockable(m) ? new Clock <> (m) : null; - - for (int y = 0; y <= max_y; ++y) - for (int x = 0; x <= max_x; ++x) - { - final Point p = new Point (x, y); - m.setPixel (p, on); - m.show (); - Thread.sleep (50); - m.setPixel (p, off); - m.show (); - } - - final double max_distance = Math.sqrt (max_x * max_x + max_y * max_y); - - int phase = 0; - - while (true) - { - for (int y = 0; y <= max_y; ++y) - for (int x = 0; x <= max_x; ++x) - { - final double distance = Math.sqrt (x*x + y*y); - final double fraction = 1 - distance / max_distance; - final double value = Math.sin ((fraction + phase / 100.0) * 2 * Math.PI); - final Double pixel = 0.5 + 0.5 * value; - final Point p = new Point (x, y); - - m.setPixel (p, pixel); - } - - if (clock != null) - clock.filter(); - - m.show (); - - phase += 1; - - if (phase == 100) - phase = 0; - - Thread.sleep (10); - } - } -} diff --git a/Jimbo/Graphics/Point.java b/Jimbo/Graphics/Point.java deleted file mode 100644 index 1e5b38a..0000000 --- a/Jimbo/Graphics/Point.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2017 Jim Darby. - * - * This library 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. - * - * This library 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 this library; if not, see - * . - */ - -package Jimbo.Graphics; - -/** - * This class represents a point on the x,y plane. It's held as a purely - * integer point where both x and y are greater then or equal to zero. - * - * @author Jim Darby - */ -public class Point -{ - /** - * Create a point with the given x and y coordinates. Both of these - * must be greater than or equal to zero as they represent a point on a - * display. - * - * @param x The x coordinate. - * @param y The y coordinate. - */ - public Point (int x, int y) - { - if (x < 0 || y < 0) - throw new IllegalArgumentException ("Negative co-ordinate in (" + x + ',' + y + ')'); - - this.x = x; - this.y = y; - } - - /** - * Get the x coordinate. - * - * @return The x coordinate. - */ - public int getX () - { - return x; - } - - /** - * Get the y coordinate. - * - * @return The y coordinate. - */ - public int getY () - { - return y; - } - - /** - * Return the item as a string contain both the x and y coordinates. - * - * @return A string representation. - */ - @Override - public String toString () - { - return "(" + x + ',' + y + ')'; - } - - /** - * Is a given point "inside" this point. This is better defined as the - * points coordinates both being less than or equal to our coordinates. - * - * @param p The point's coordinates. - * @return If the parameter's x and y coordinates are both less than or - * equal to ours. - */ - public boolean inside (Point p) - { - return x <= p.x && y <= p.y; - } - - /** Our x coordinate. */ - private final int x; - /** Our y coordinate. */ - private final int y; -} diff --git a/Jimbo/Graphics/Snake.java b/Jimbo/Graphics/Snake.java deleted file mode 100644 index a549511..0000000 --- a/Jimbo/Graphics/Snake.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2017 Jim Darby. - * - * This library 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. - * - * This library 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 this library; if not, see - * . - */ - -package Jimbo.Graphics; - -/** - * The class performs a "snake" mapping of a point. This is very useful when - * the wiring of pixels is a little "unusual". It flips the X value but only on - * alternate lines. This allows a layout such as: - * - * 15 14 13 12 - * 08 09 10 11 - * 07 06 05 04 - * 00 01 02 03 - * - * @author Jim Darby. - */ -public class Snake extends Mapping -{ - /** - * Create a mapping given the width and height of the input. Note that the - * valid X coordinates are from 0 to width - 1 and the valid Y coordinates - * are from 0 to height - 1. - * - * @param width The input width. - * @param height The input height. - */ - public Snake (int width, int height) - { - super (new Point (width - 1, height - 1)); - } - - /** - * Create a mapping given a previous mapping. The width and height are - * inherited from the previous item. - * - * @param before The previous mapping. - */ - public Snake (Mapping before) - { - super (before, before.getOutMax ()); - } - - /** - * Perform a mapping. The flips odd numbered X lines. - * - * @param p The input point. - * @return The mapped result. - */ - @Override - public Point map (Point p) - { - if (before != null) - p = before.map (p); - - validateIn (p); - - final Point result = ((p.getY () & 1) != 0) ? new Point (getInMax ().getX () - p.getX (), p.getY ()) : p; - - validateOut (result); - - return result; - } - - /** - * Return a printable form of the mapping. - * - * @return The String representation. - */ - @Override - public String toString () - { - String result = "Snake from " + getInMax () + " to " + getOutMax (); - - if (before != null) - result = before.toString () + ' ' + result; - - return result; - } -} - diff --git a/Jimbo/Graphics/SwapXY.java b/Jimbo/Graphics/SwapXY.java deleted file mode 100644 index 25e6c6a..0000000 --- a/Jimbo/Graphics/SwapXY.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2017 Jim Darby. - * - * This library 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. - * - * This library 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 this library; if not, see - * . - */ - -package Jimbo.Graphics; - -/** - * This class swaps the X and Y coordinates over. - * - * So: - * - * 04 05 06 07 - * 00 01 02 03 - * - * becomes: - * - * 03 07 - * 02 06 - * 01 05 - * 00 04 - * - * @author Jim Darby. - */ -public class SwapXY extends Mapping -{ - /** - * Create a mapping given the width and height of the input. Note that the - * valid X coordinates are from 0 to width - 1 and the valid Y coordinates - * are from 0 to height - 1. - * - * @param width The input width. - * @param height The input height. - */ - public SwapXY (int width, int height) - { - super (new Point (width - 1, height - 1), new Point (height - 1, width - 1)); - } - - /** - * Create a mapping given a previous mapping. The width and height are - * inherited from the previous item. - * - * @param before The previous mapping. - */ - public SwapXY (Mapping before) - { - super (before, new Point (before.getOutMax ().getY (), before.getOutMax ().getX ())); - } - - /** - * Perform a mapping. This swaps the X and Y values over. - * - * @param p The input point. - * @return The mapped result. - */ - @Override - public Point map (Point p) - { - if (before != null) - p = before.map (p); - - validateIn (p); - - final Point result = new Point (p.getY (), p.getX ()); - - validateOut (result); - - return result; - } - - /** - * Return a printable form of the mapping. - * - * @return The String representation. - */ - @Override - public String toString () - { - String result = "SwapXY in " + getInMax () + " out " + getOutMax (); - - if (before != null) - result = before.toString () + ' ' + result; - - return result; - } -} diff --git a/Jimbo/Logging/Logging.java b/Jimbo/Logging/Logging.java deleted file mode 100644 index f0858dd..0000000 --- a/Jimbo/Logging/Logging.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2016 Jim Darby. - * - * This software 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. - * - * This software 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 this software; if not, If not, see - * . - */ - -package Jimbo.Logging; - -import java.util.logging.Logger; -import java.util.logging.Handler; -import java.util.logging.LogRecord; - -import java.text.MessageFormat; - -import java.time.Instant; -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; -import java.time.ZoneOffset; -import java.time.ZoneId; -import java.time.temporal.ChronoUnit; -import java.util.logging.Level; - -/** - * Some useful stuff to customise logging for us. - * - * @author Jim Darby - */ -public class Logging -{ - public static void useStdout () - { - // Find the root logger - final Logger root_logger = Logger.getLogger (""); - - // Now kill off all the other handlers. - - Handler[] handlers = root_logger.getHandlers(); - - for (Handler handler : handlers) - root_logger.removeHandler (handler); - - // And insert ours. - root_logger.addHandler (new Reporter ()); - } - - /** - * Our own logging record handler class. Essentially just timestamps - * the record and then sends it to stdout. - */ - private static class Reporter extends Handler - { - /** - * Actually process a log record. - * - * @param r The log record to process. - */ - @Override - public void publish(LogRecord r) - { - // Extract raw message from the record - String text = r.getMessage (); - - // The message can be null, if so ignore it. - if (text == null) - return; - - final Object[] parameters = r.getParameters(); - - // Do we need to format the message? Thanks to Brenton for finding this - // algorithm. For full details see: - // https://docs.oracle.com/javase/8/docs/api/java/util/logging/Formatter.html#formatMessage-java.util.logging.LogRecord- - if (parameters != null && parameters.length != 0 && text.contains ("{0")) - text = new MessageFormat (text).format (parameters); - - final Instant instant = Instant.ofEpochMilli (r.getMillis()).truncatedTo (ChronoUnit.SECONDS); - final ZoneId zone = ZoneOffset.systemDefault (); - final LocalDateTime stamp = LocalDateTime.ofInstant (instant, zone); - final String when = stamp.format (DateTimeFormatter.ISO_LOCAL_DATE_TIME); - - System.out.println ("[" + when + "] " + text); - - /*System.out.println ("Logging record:"); - System.out.println (" Time: " + when); - System.out.println (" Level: " + r.getLevel()); - System.out.println (" Name: " + r.getLoggerName ()); - System.out.println (" Formatted: " + text); - System.out.println ();*/ - } - - @Override - public void flush() - { - } - - @Override - public void close() throws SecurityException - { - } - } - - public static void main (String args[]) - { - useStdout (); - - final Logger LOG = Logger.getLogger ("Test logger"); - - LOG.info ("Testing"); - - for (String s : args) - LOG.log (Level.INFO, "{0}", s); - } -} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README.md b/README.md deleted file mode 100644 index feea6ac..0000000 --- a/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# PiJava - -This is where I hold my Pi-specific Java work. diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..e61918c --- /dev/null +++ b/build.gradle @@ -0,0 +1,27 @@ +apply plugin: 'java-library' +version = 1.0 + +sourceCompatibility = targetCompatibility = 1.8 //same as pi4j + +repositories { + maven { url 'https://oss.sonatype.org/content/groups/public' } +} + +dependencies { + api 'com.pi4j:pi4j-core:1.2-SNAPSHOT' +} + +jar { + manifest { + attributes "Automatic-Module-Name": "com.github.jimbo.pijava.blinkt" + } +} + +task sourcesJar(type: Jar, dependsOn: classes) { + classifier = 'sources' + from sourceSets.main.allSource +} + +artifacts { + archives sourcesJar +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..91ca28c Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..16d2805 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.7-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..cccdd3d --- /dev/null +++ b/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..f955316 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/src/main/java/jimbo/pijava/blinkt/BlinktController.java b/src/main/java/jimbo/pijava/blinkt/BlinktController.java new file mode 100644 index 0000000..2fffcc7 --- /dev/null +++ b/src/main/java/jimbo/pijava/blinkt/BlinktController.java @@ -0,0 +1,204 @@ +/* + * Copyright (C) 2016-2017 Jim Darby. + * + * This software 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. + * + * This software 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 this software; if not, If not, see + * . + */ + +package jimbo.pijava.blinkt; + +import com.pi4j.io.gpio.GpioController; +import com.pi4j.io.gpio.GpioFactory; +import com.pi4j.io.gpio.GpioPinDigitalOutput; +import com.pi4j.io.gpio.Pin; +import com.pi4j.io.gpio.RaspiPin; + +/** + * This is a derivative class of Jim Darby's APA102 & Blinkt controllers + * + * @author Jim Darby + * @author HoldYourWaffle + */ +public class BlinktController { + /** The pin we use for the clock */ + private final GpioPinDigitalOutput clk; + + /** The pin we use for data */ + private final GpioPinDigitalOutput dat; + + /** The data for each LED in the chain */ + private final int[] data; + + /** Brightness (0 - 31) field used to set colors */ + private int brightness; + + /** + * Construct an Pimoroni Blinkt! controller + * + * @param gpio The GpioController to use + * @param data_pin The data pin to use + * @param clock_pin The clock pin to use + */ + public BlinktController(GpioController gpio, Pin data_pin, Pin clock_pin) { + dat = gpio.provisionDigitalOutputPin(data_pin); + clk = gpio.provisionDigitalOutputPin(clock_pin); + data = new int[8]; + + reset(); + push(); + } + + /** + * Construct an Pimoroni Blinkt! controller with the default data and clock pin + * + * @param gpio The GpioController to use + */ + public BlinktController(GpioController gpio) { + this(gpio, RaspiPin.GPIO_04, RaspiPin.GPIO_05); + } + + /** Construct a Pimoroni Blinkt! controller with the default {@link GpioController}, data and clock pin */ + public BlinktController() { + this(GpioFactory.getInstance(), RaspiPin.GPIO_04, RaspiPin.GPIO_05); + } + + + + /** Update the LED chain */ + public void push() { + // Transmit preamble + for (int i = 0; i < 4; ++i) + write_byte((byte) 0); + + // Send data + for (int i = 0; i < 8; ++i) + write_led(data[i]); + + // And latch it + latch(); + } + + /** Both {@link #clear()} and {@link #setBrightness(float)} to 0 */ + public void reset() { + clear(); + setBrightness(1); + } + + /** Clear the data for pixel n */ + public void clear(int n) { + data[n] = 0; + } + + /** Clear the data of all pixels */ + public void clear() { + for (int i = 0; i < 8; ++i) + data[i] = 0; + } + + + /** + * Set the brightness field used for {@link #set(int, int, int, int)} + * + * @param brightness The brightness scale factor (0-1) + */ + public void setBrightness(float brightness) { + if (brightness < 0 || brightness > 1) throw new IllegalArgumentException("Invalid brightness "+brightness); + this.brightness = (int) (brightness * 31); + } + + + /** Get {@link #brightness} */ + public float getBrightness() { + return brightness / 31F; + } + + + /** + * Set an LED to a specific red, green, blue and brightness value + * + * @param n The LED number (0-7) + * @param red The red value (0-255) + * @param green The green value (0-255) + * @param blue The blue value (0-255) + * @param brightness The brightness (0-1) + * + * @see #push() + */ + public void set(int n, int red, int green, int blue, float brightness) { + if (n < 0 || n >= 8) throw new IllegalArgumentException("n must be larget than 0 and smaller than 8"); + if (red < 0 || red > 255) throw new IllegalArgumentException("red must be between 0 and 255"); + if (green < 0 || green > 255) throw new IllegalArgumentException("green must be between 0 and 255"); + if (blue < 0 || blue > 255) throw new IllegalArgumentException("blue must be between 0 and 255"); + + data[n] = ((int)(brightness*31) << 24) | (red << 16) | (green << 8) | blue; + } + + /** + * Set a LED to a specific red, green and blue value using a brightness of {@link #brightness} + * + * @param n The LED number (0-7) + * @param red The red value (0-255) + * @param green The green value (0-255) + * @param blue The blue value (0-255) + * + * @see #setBrightness(float) + * @see #push() + */ + public void set(int n, int red, int green, int blue) { + if (n < 0 || n >= 8) throw new IllegalArgumentException("n must be larget than 0 and smaller than 8"); + if (red < 0 || red > 255) throw new IllegalArgumentException("red must be between 0 and 255"); + if (green < 0 || green > 255) throw new IllegalArgumentException("green must be between 0 and 255"); + if (blue < 0 || blue > 255) throw new IllegalArgumentException("blue must be between 0 and 255"); + + data[n] = (brightness << 24) | (red << 16) | (green << 8) | blue; + } + + + + /** Write out a single byte. It goes out MSB first */ + private void write_byte(byte out) { + for (int i = 7; i >= 0; --i) { + dat.setState((out & (1 << i)) != 0); + clk.setState(true); + clk.setState(false); + } + } + + /** Write out a single LEDs information */ + private void write_led(int data) { + write_byte((byte) (0xe0 | ((data >> 24) & 0x1f))); + + write_byte((byte) (data)); + write_byte((byte) (data >> 8)); + write_byte((byte) (data >> 16)); + } + + /** + * Latch the data into the devices. This has prompted much discussion as + * data sheet seems to be a work of fiction. These values seem to work. + * + * In case of any difficulties, blame Gadgetoid: it's all his fault! + */ + private void latch() { + // Transmit zeros not ones! + dat.setState(false); + + // And 36 of them! + for (int i = 0; i < 36; ++i) { + clk.setState(true); + clk.setState(false); + } + } + +}