package org.myrobotlab.pickToLight;
import java.util.HashMap;
import org.myrobotlab.framework.Platform;
import org.myrobotlab.framework.Service;
import org.myrobotlab.logging.LoggerFactory;
import org.myrobotlab.logging.Logging;
import org.slf4j.Logger;
import com.pi4j.io.i2c.I2CDevice;
import com.pi4j.io.i2c.I2CFactory;
/*
* 0x80 = The I/R sensor input (must write a 1 bit initially)
0x7C = Unused bits
0x02 = LED (Write 0 to turn ON the LED; write 1 to turn OFF)
0x01 = "Chip select" for 7-segment display controller
Since the 0x80 bit must be written with a 1 to enable the sensor input, it is recommended that
ALL writes to the I/O expander write that bit high.
As a result, there are only four possible values that should be written:
0x80 - 128 = LED ON and display selected
0x81 - 129 = LED ON and display de-selected
0x82 - 130 = LED OFF and display selected
0x83 - 131 = LED OFF and display de-selected
*/
public class Module {
public class BlinkThread extends Thread {
public int blinkNumber = 5;
public int blinkDelay = 100;
public String value = "";
public boolean leaveDisplayOn = true;
public boolean leaveLEDOn = false;
@Override
public void run() {
int count = 0;
while (count < 5) {
// selector &= ~MASK_DISPLAY; WRONG !
if (value != null) {
display(value);
}
ledOn();
Service.sleep(blinkDelay);
if (value != null) {
display("");
}
ledOff();
// selector |= MASK_LED; WRONG !!
Service.sleep(blinkDelay);
++count;
}
if (leaveDisplayOn) {
// selector &= ~MASK_DISPLAY; WONG
display(value);
}
if (leaveLEDOn) {
ledOn();
}
}
}
public class CycleThread extends Thread {
public boolean isRunning = false;
int delay = 300;
String msg;
public CycleThread(String msg, int delay) {
this.msg = " " + msg + " ";
this.delay = delay;
}
@Override
public void run() {
isRunning = true;
try {
while (isRunning) {
// start with scroll on page
for (int i = 0; i < msg.length() - 3; ++i) {
display(msg.substring(i, i + 4));
sleep(delay);
}
}
} catch (InterruptedException e) {
isRunning = false;
}
}
}
public final static Logger log = LoggerFactory.getLogger(Module.class);
transient private com.pi4j.io.i2c.I2CBus i2cbus;
transient private com.pi4j.io.i2c.I2CDevice device;
Address2 address = new Address2();
String type;
String version; // hardware version
String state;
int selector = 0x83; // IR selected - LED OFF
static public final int MASK_DISPLAY = 0x01;
static public final int MASK_LED = 0x02;
static public final int MASK_SENSOR = 0x80;
// private String lastValue = "";
static private boolean translationInitialized = false;
transient static HashMap<String, Byte> translation = new HashMap<String, Byte>();
transient CycleThread ct = null;
public static void initTranslation() {
translation.put("", (byte) 0);
translation.put(" ", (byte) 0);
translation.put(":", (byte) 3);
// translation.put("of", (byte)0)
translation.put("a", (byte) 119);
translation.put("b", (byte) 124);
translation.put("c", (byte) 57);
translation.put("d", (byte) 94);
translation.put("e", (byte) 121);
translation.put("f", (byte) 113);
translation.put("g", (byte) 111);
translation.put("h", (byte) 118);
translation.put("i", (byte) 48);
translation.put("J", (byte) 30);
translation.put("k", (byte) 118);
translation.put("l", (byte) 56);
translation.put("m", (byte) 21);
translation.put("n", (byte) 84);
translation.put("o", (byte) 63);
translation.put("p", (byte) 115);
translation.put("q", (byte) 103);
translation.put("r", (byte) 80);
translation.put("s", (byte) 109);
translation.put("t", (byte) 120);
translation.put("u", (byte) 62);
translation.put("v", (byte) 98);
translation.put("x", (byte) 118);
translation.put("y", (byte) 110);
translation.put("z", (byte) 91);
translation.put("-", (byte) 64);
// translation.put("dot", (byte)???);
translation.put("0", (byte) 63);
translation.put("1", (byte) 6);
translation.put("2", (byte) 91);
translation.put("3", (byte) 79);
translation.put("4", (byte) 102);
translation.put("5", (byte) 109);
translation.put("6", (byte) 125);
translation.put("7", (byte) 7);
translation.put("8", (byte) 127);
translation.put("9", (byte) 111);
translationInitialized = true;
}
public static byte translate(char c) {
byte b = 0;
String s = String.valueOf(c).toLowerCase();
if (translation.containsKey(s)) {
b = translation.get(s);
} else {
log.info(String.format("character %s not translated", c));
}
return b;
}
public Module(int bus, int i2cAddress) {
try {
address.setI2CBus(bus);
address.setI2CAddress(i2cAddress);
Platform platform = Platform.getLocalInstance();
if (platform.isArm()) {
// create I2C communications bus instance
i2cbus = I2CFactory.getInstance(bus);
// create I2C device instance
device = i2cbus.getDevice(i2cAddress);
}
if (!translationInitialized) {
initTranslation();
}
} catch (Exception e) {
Logging.logError(e);
}
}
public void blinkOff(String msg, int blinkNumber, int blinkDelay) {
log.info(String.format("blinkOff %s", msg));
BlinkThread b = new BlinkThread();
b.blinkNumber = blinkNumber;
b.blinkDelay = blinkDelay;
b.value = msg;
b.leaveDisplayOn = false;
b.start();
}
public void blinkOn(String msg, int blinkNumber, int blinkDelay) {
BlinkThread b = new BlinkThread();
b.blinkNumber = blinkNumber;
b.blinkDelay = blinkDelay;
b.value = msg;
b.start();
}
public void clear() {
cycleStop();
selector |= MASK_LED;
display("");
}
public void cycle(String msg) {
if (ct != null) {
cycleStop();
}
ct = new CycleThread(msg, 300);
ct.start();
}
public void cycle(String msg, int delay) {
if (ct != null) {
cycleStop();
}
ct = new CycleThread(msg, delay);
ct.start();
}
public void cycleStop() {
if (ct != null) {
ct.isRunning = false;
ct.interrupt();
ct = null;
display(" ");
}
}
public String display(String str) {
// lastValue = str;
// d1 d2 : d3 d4
byte[] display = new byte[] { 0, 0x17, 0, 0, 0, 0 };
if (str == null || str == "") {
writeDisplay(display);
return str;
}
if (str.length() < 4) {
str = String.format("%4s", str);
}
display[5] = translate(str.charAt(0));
display[4] = translate(str.charAt(1));
display[3] = translate(str.charAt(2));
display[2] = translate(str.charAt(3));
writeDisplay(display);
return str;
}
public int getI2CAddress() {
return address.getI2CAddress();
}
public int getI2CBus() {
return address.getI2CBus();
}
public int ledOff() {
try {
selector |= MASK_LED;
log.info("ledOff {}", Integer.toHexString(selector));
device.write((byte) selector);
} catch (Exception e) {
log.error(String.format("ledOff device %d error in writing", address.controller));
Logging.logError(e);
}
return selector;
}
// TODO - should only have to wrap the highest level transaction (WebGui
// Thread) -
// such that smaller transaction handling is not necessary
public int ledOn() {
try {
selector &= ~MASK_LED;
log.info("ledOn {}", Integer.toHexString(selector));
device.write((byte) selector);
} catch (Exception e) {
log.error(String.format("ledOn device %d error in writing", address.controller));
Logging.logError(e);
}
return selector;
}
public void logByteArray(byte[] data) {
logByteArray("", data);
}
public void logByteArray(String prefix, byte[] data) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < data.length; ++i) {
sb.append(data[i]);
if (i != data.length) {
sb.append(",");
}
}
log.info(String.format("%s %s", prefix, sb.toString()));
}
public int readSensor() {
try {
// sudo i2cset -y 1 0x10 0x83
// sudo i2cget -y 1 0x10
// lame should bitwise this
// I have a feeling LED and display affect
// YOU CANT HAVE LED ON WHEN POLLING SENSOR ??
// device.write((byte) 0x83);
// need to do bitwise mask !!!
return device.read();
} catch (Exception e) {
Logging.logError(e);
}
return -1;
}
public byte[] writeDisplay(byte[] data) {
if (device == null) {
log.error("device is null");
return data;
}
try {
if (log.isDebugEnabled()) {
logByteArray("writeDisplay", data);
}
// select display
device.write((byte) (selector &= ~MASK_DISPLAY)); // FIXME NOT
// CORRECT !
I2CDevice display = i2cbus.getDevice(0x38);
display.write(data, 0, data.length);
// de-select display
device.write((byte) (selector |= MASK_DISPLAY));// FIXME NOT CORRECT
// ! for LED
} catch (Exception e) {
log.error(String.format("writeDisplay device %d error in writing", address.controller));
Logging.logError(e);
}
return data;
}
}