Login [Register]
Don't have an account? Register now to chat, post, use our tools, and much more.
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:

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]
What makes you conclude that the calculator is receiving correctly if you're not getting a proper ACK?
the raspberry pi signals by pulling one of the lines low, which line it is determines if the bit is a 1 or a 0. the calculator then pulls the other line low to acknowledge the bit. then both lines are reset and the next bit is signalled. I'm not getting any send timeouts, so i know the send routine works. the calculator's not sending any ack PACKETS.
You could probably test to see if that's the case using Calcsys' port monitor...
deepthought wrote:
the raspberry pi signals by pulling one of the lines low, which line it is determines if the bit is a 1 or a 0. the calculator then pulls the other line low to acknowledge the bit. then both lines are reset and the next bit is signalled. I'm not getting any send timeouts, so i know the send routine works. the calculator's not sending any ack PACKETS.
Do you have a multimeter to confirm that the voltage levels are correct (0V and 5V)? You should also try using CalcSys' port monitor, as Hitech suggested.
KermMartian wrote:
deepthought wrote:
the raspberry pi signals by pulling one of the lines low, which line it is determines if the bit is a 1 or a 0. the calculator then pulls the other line low to acknowledge the bit. then both lines are reset and the next bit is signalled. I'm not getting any send timeouts, so i know the send routine works. the calculator's not sending any ack PACKETS.
Do you have a multimeter to confirm that the voltage levels are correct (0V and 5V)? You should also try using CalcSys' port monitor, as Hitech suggested.

On this topic, I think he got it working over USB.

However, I think that that's just it, Kerm - the Raspberry Pi runs at 3.3v. Although I've heard of hooking a 3.3v GPIO OUTPUT pin directly to a 5v INPUT pin on another device, which works because 3.3v is enough voltage to be considered HIGH by the 5v device (DO NOT try sending 5v INTO the Pi's GPIO pins, you will fry your Pi), I imagine the calculator would be less tolerant of voltages and would need a logic level converter.

(Actually, the reason I bought my logic level converter was so I could use my Arduino as a USB to TTL adapter for my Pi.)
Ah, he seemed sufficiently knowledgeable that I assumed he was using a 3.3V <-> 5V logic level converter, but you're right, he may not be. If that's the case, then a level converter is absolutely de rigeur for Raspberry Pi-to-calculator communication.
Looking back at the arduino topic, logic levels isn't it.
deepthought wrote:
I've decided to scrap my wireless module and just go with a raspberry pi and a level converter to interface with the calc. is there any sort of linkport serial console i could use to check my send and get routines?

So disregard my last post.
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 1
» All times are GMT - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement