I am trying to use the GPIO pins on a raspberry pi to link to the headphone-type linkport on a ti-84 plus.
here is my code
ported TICL class
Code:
ported key demo
Code:
running the code on the raspberry pi produced the following output.
Code:
the calculator seems to be receiving the data i'm sending it, but nothing is apearring onscreen, and the return header does not contain the ACK, but contains a 0, and the last 2 bytes sent by the rpi.
Also, it takes several seconds for the two get calls to return
what's going wrong here?[/code]
here is my code
ported TICL class
Code:
import com.pi4j.io.gpio.GpioPin;
import com.pi4j.io.gpio.GpioPinDigitalMultipurpose;
import com.pi4j.io.gpio.PinMode;
import com.pi4j.io.gpio.PinPullResistance;
import com.pi4j.io.gpio.PinState;
public class TICL {
public static final byte ERR_READ_TIMEOUT = -1;
public static final byte ERR_WRITE_TIMEOUT = -2;
public static final byte ERR_BAD_CHECKSUM = -3;
public static final byte ERR_BUFFER_OVERFLOW = -4;
public static final byte ERR_INVALID = -5;
public static final byte COMP82 = 0x02;
public static final byte COMP83 = 0x03;
public static final byte COMP85 = 0x05;
public static final byte COMP86 = 0x06;
public static final byte COMP89 = 0x09;
public static final byte COMP92 = 0x09;
public static final byte CBL82 = 0x12;
public static final byte CBL85 = 0x15;
public static final byte CBL89 = 0x19;
public static final byte CBL92 = 0x19;
public static final byte COMP83P = 0x23;
public static final byte CALC83P = 0x73;
public static final byte CALC82 = (byte) 0x82;
public static final byte CALC83 = (byte) 0x83;
public static final byte CALC85a = (byte) 0x85;
public static final byte CALC89 = (byte) 0x89;
public static final byte CALC92 = (byte) 0x89;
public static final byte CALC85b = (byte) 0x95;
public static final byte VAR = 0x06;
public static final byte CTS = 0x09;
public static final byte DATA = 0x15;
public static final byte VER = 0x2D;
public static final byte SKIP = 0x36;
public static final byte EXIT = 0x36;
public static final byte ACK = 0x56;
public static final byte ERR = 0x5A;
public static final byte RDY = 0x68;
public static final byte SCR = 0x6D;
public static final byte KEY = (byte) 0x87;
public static final byte DEL = (byte) 0x88;
public static final byte EOT = (byte) 0x92;
public static final byte REQ = (byte) 0xA2;
public static final byte RTS = (byte) 0xC9;
boolean verbose;
public static final int TIMEOUT =4000;
public static final int GET_ENTER_TIMEOUT= 30000;
GpioPinDigitalMultipurpose tip_;
GpioPinDigitalMultipurpose ring_;
public TICL(GpioPinDigitalMultipurpose tip, GpioPinDigitalMultipurpose ring)
{
tip_=tip;
ring_=ring;
}
public void setVerbosity(boolean b)
{
verbose=b;
}
public int send(byte[] header, byte[] data, int datalength) {
if (verbose) {
System.out.print("snd type 0x");
System.out.print(Integer.toHexString(header[1]));
System.out.print(" as EP 0x");
System.out.print(Integer.toHexString(header[0]));
System.out.print(" len ");
System.out.println(datalength);
}
// Send all of the bytes in the header
for(int idx = 0; idx < 4; idx++) {
int rval = sendByte(header[idx]);
if (rval != 0)
return rval;
}
// If no data, we're done
if (datalength == 0) {
return 0;
}
// These also indicate that there are
// no data bytes to be sent
if (header[1] == CTS ||
header[1] == VER ||
header[1] == ACK ||
header[1] == ERR ||
header[1] == RDY ||
header[1] == SCR ||
header[1] == KEY ||
header[1] == EOT)
{
return 0;
}
// Send all of the bytes in the data buffer
short checksum = 0;
for(int idx = 0; idx < datalength; idx++) {
byte outbyte;
// Get a byte if we need
outbyte = data[idx];
// Try to send this byte
int rval = sendByte(outbyte);
if (rval != 0)
return rval;
checksum += outbyte;
}
// Send the checksum
int rval = sendByte((byte) (checksum & 0x00ff));
if (rval != 0)
return rval;
rval = sendByte((byte) ((checksum >> 8) & 0x00ff));
return rval;
}
public int sendByte(byte bt) {
long previousMillis = 0;
// Send all of the bits in this byte
for(int bit = 0; bit < 8; bit++) {
// Wait for both lines to be high before sending the bit
previousMillis = 0;
while (digitalRead(ring_) ==0 || digitalRead(tip_) == 0) {
if (previousMillis++ > TIMEOUT) {
resetLines();
return ERR_WRITE_TIMEOUT;
}
}
// Pull one line low to indicate a new bit is going out
boolean bitval = (bt & 1)==1;
GpioPinDigitalMultipurpose line = (bitval)?ring_:tip_;
line.setMode(PinMode.DIGITAL_OUTPUT);//pinMode(line, OUTPUT);
line.setState(PinState.LOW);//digitalWrite(line, LOW);
// Wait for peer to acknowledge by pulling opposite line low
line = (bitval)?tip_:ring_;
previousMillis =System.currentTimeMillis();
while (digitalRead(line) == 1) {
if (System.currentTimeMillis()-previousMillis > TIMEOUT) {
resetLines();
return ERR_WRITE_TIMEOUT;
}
}
// Wait for peer to indicate readiness by releasing that line
resetLines();
previousMillis =System.currentTimeMillis();
while (digitalRead(line) == 0) {
if (System.currentTimeMillis()-previousMillis > TIMEOUT) {
resetLines();
return ERR_WRITE_TIMEOUT;
}
}
// Rotate the next bit to send into the low bit of the byte
bt>>>= 1;
}
return 0;
}
public int get(byte[] header, byte[] data, int[] datalength, int maxlength) {
int rval;
// Get the 4-byte header: sender, message, length
for(int idx = 0; idx < 4; idx++) {
rval = getByte(header,idx);
if (rval!=0l)
return rval;
}
datalength[0] = (int)header[2] | ((int)header[3] << 8);
if (verbose) {
System.out.print("Recv typ 0x");
System.out.print(header[1]);
System.out.print(" from EP 0x");
System.out.print(Integer.toHexString(header[0]));
System.out.print(" len ");
System.out.println(Integer.toHexString(datalength[0]));
}
if (datalength[0] == 0)
return 0;
// These also indicate that there are
// no data bytes to be received
if (header[1] == CTS ||
header[1] == VER ||
header[1] == ACK ||
header[1] == ERR ||
header[1] == RDY ||
header[1] == SCR ||
header[1] == KEY ||
header[1] == EOT)
{
return 0;
}
// Check if this is a data-free message
if (datalength[0] > maxlength) {
if (verbose) {
System.out.print("Msg buf ovfl: ");
System.out.print(datalength[0]);
System.out.print(" > ");
System.out.println(maxlength);
}
return ERR_BUFFER_OVERFLOW;
}
// Get the data bytes, if there are any.
short checksum = 0;
for(int idx = 0; idx < datalength[0]; idx++) {
// Try to get all the bytes, or fail if any of the
// individual byte reads fail
rval = getByte(data,idx);
if (rval != 0)
return rval;
// Update checksum
checksum += data[idx];
}
// Receive and check the checksum
byte[] recv_checksum= new byte[2];
for(int idx = 0; idx < 2; idx++) {
rval = getByte(recv_checksum,idx);
if (rval!=0)
return rval;
}
// Die on a bad checksum
if (checksum != (short)(((int)recv_checksum[1] << 8) | (int)recv_checksum[0]))
return ERR_BAD_CHECKSUM;
return 0;
}
public int getByte(byte[] bt, int i) {
long previousMillis = 0;
bt[i] = 0;
// Pull down each bit and store it
for (int bit = 0; bit < 8; bit++) {
int linevals;
previousMillis = System.currentTimeMillis();
while ((linevals = ((digitalRead(ring_) << 1) | digitalRead(tip_))) == 0x03) {
if (System.currentTimeMillis()-previousMillis > GET_ENTER_TIMEOUT) {
resetLines();
return ERR_READ_TIMEOUT;
}
}
System.out.println(linevals);
// Store the bit, then acknowledge it
bt[i] = (byte) ((bt[i] >>> 1) | ((linevals == 0x01)?0x80:0x00));
GpioPinDigitalMultipurpose line = (linevals == 0x01)?tip_:ring_;
line.setMode(PinMode.DIGITAL_OUTPUT);//pinMode(line, OUTPUT);
line.setState(PinState.LOW);//digitalWrite(line, LOW);
// Wait for the peer to indicate readiness
line = (linevals == 0x01)?ring_:tip_;
previousMillis = System.currentTimeMillis();
while (digitalRead(line) == 0) { //wait for the other one to go low
if (System.currentTimeMillis()-previousMillis > TIMEOUT) {
resetLines();
return ERR_READ_TIMEOUT;
}
}
// Now set them both high and to input
resetLines();
}
return 0;
}
private int digitalRead(GpioPinDigitalMultipurpose pin) {
if(pin.getState()==PinState.HIGH)
return 1;
return 0;
}
public void resetLines() {
ring_.setMode(PinMode.DIGITAL_INPUT); // pinMode(ring_, INPUT); // set pin to input
ring_.setPullResistance(PinPullResistance.PULL_UP); //digitalWrite(ring_, HIGH); // turn on pullup resistors
tip_.setMode(PinMode.DIGITAL_INPUT); //pinMode(tip_, INPUT); // set pin to input
tip_.setPullResistance(PinPullResistance.PULL_UP); //digitalWrite(tip_, HIGH); // turn on pullup resistors
}
}
ported key demo
Code:
import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.gpio.GpioPin;
import com.pi4j.io.gpio.GpioPinDigitalMultipurpose;
import com.pi4j.io.gpio.PinMode;
import com.pi4j.io.gpio.RaspiPin;
public class typetest {
public static void main(String[] args) throws Exception
{
final GpioController gpio = GpioFactory.getInstance();
final GpioPinDigitalMultipurpose tip=gpio.provisionDigitalMultipurposePin(RaspiPin.GPIO_00,PinMode.DIGITAL_INPUT);
final GpioPinDigitalMultipurpose ring=gpio.provisionDigitalMultipurposePin(RaspiPin.GPIO_01,PinMode.DIGITAL_INPUT);
TICL ticl = new TICL(tip, ring);
ticl.resetLines();
ticl.setVerbosity(true);
while(true)
{
byte[] header = {TICL.COMP83P, TICL.KEY, (byte) 0xA6, 0x00};
int rval;
int[] rlen = new int[1];
System.out.println(Integer.toHexString(header[0]&0xff)+" "+Integer.toHexString(header[1]&0xff)+" "+Integer.toHexString(header[2]&0xff)+" "+Integer.toHexString(header[3]&0xff));
rval = ticl.send(header, null, 0); // Send KEY message
System.out.println("send returned");
if (rval != 0) {
System.out.print("Send returned ");
System.out.println(rval);
} else {
ticl.get(header, null, rlen, 0); // Get ACK
System.out.println("ack");
System.out.println(Integer.toHexString(header[0]&0xff)+" "+Integer.toHexString(header[1]&0xff)+" "+Integer.toHexString(header[2]&0xff)+" "+Integer.toHexString(header[3]&0xff));
if (rval != 0) {
System.out.print("Get returned ");
System.out.println(rval);
}
ticl.get(header, null, rlen, 0); // Get key process notification
System.out.println("process");
System.out.println(Integer.toHexString(header[0]&0xff)+" "+Integer.toHexString(header[1]&0xff)+" "+Integer.toHexString(header[2]&0xff)+" "+Integer.toHexString(header[3]&0xff));
if (rval != 0) {
System.out.print("Get returned ");
System.out.println(rval);
}
}
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
}
running the code on the raspberry pi produced the following output.
Code:
23 87 a6 0
snd type 0xffffff87 as EP 0x23 len 0
send returned
ack
0 87 a6 0
process
0 87 a6 0
23 87 a6 0
snd type 0xffffff87 as EP 0x23 len 0
send returned
the calculator seems to be receiving the data i'm sending it, but nothing is apearring onscreen, and the return header does not contain the ACK, but contains a 0, and the last 2 bytes sent by the rpi.
Also, it takes several seconds for the two get calls to return
what's going wrong here?[/code]