'jleblanc 3.21.06
'NEW VERSION WITH crappy CALL AND RESPONSE ESQ SYSTEM
'this code writes a keyboard input out to the LCD
'Hiting enter will send the message to Processing and display it
'the LCD will clear so you can start again!
'uses code from Daryl Owen 7/11/00 (see my website for link)
'for my connector: 
    'red to ground
    'white to power
    'black to C4
    'yellow to C5
'See just below for LCD setup

DEFINE OSC 20

'SETUP COMMUNICATION WITH XPORT
    ' We communicate with the XPort using 9600 8N1 serial
        true9600 CON 84
        timeOut CON 50   ' the serial incoming timeout in milliseconds
        'NOTE: this code is not currently using the timeOut constant
    ' Our serial communication pins
        tx VAR PORTC.6
        rx VAR PORTC.7
    ' Used to read data from the XPort
        inByteX VAR BYTE 'gets mouseposition X
        inByteX=1
        inByteY VAR BYTE  'gets mouseposition Y
        inByteY=1
    ' Used to send a byte from the XPort
        outByte VAR BYTE
    ' Track whether or not we are connected to the remote server
        connected VAR BIT
        connected = 0

'SETUP LCD
    'This setup will tell PBP a 2-line LCD is connected in 4-bit 
    'mode with the data bus on the top 4 bits of PORTB, Register 
    'Select on PORTB.1, and Enable on PORTB.0.
    'Data Bits go like: 3>B.7, 2>B.6, 1>B.5, 0>B.4
	DEFINE LCD_DREG	PORTB
	' Set starting Data bit (0 or 4) if 4-bit bus
	DEFINE LCD_DBIT	4
	' Set LCD Register Select port
	DEFINE LCD_RSREG	PORTB
	' Set LCD Register Select bit
	DEFINE LCD_RSBIT	1
	' Set LCD Enable port
	DEFINE LCD_EREG	PORTB
	' Set LCD Enable bit
	DEFINE LCD_EBIT	0
	' Set LCD bus size (4 or 8 bits)
	DEFINE LCD_BITS	4
	' Set number of lines on LCD
	DEFINE LCD_LINES	2
	' Set command delay time in us
	DEFINE LCD_COMMANDUS	2000
	' Set data delay time in us
	DEFINE LCD_DATAUS	50

'Variables used to interface with keyboard
    Keypress VAR BYTE'Keyboard value read from keyboard
    AscKey VAR BYTE'This is used to send key scan data and subroutine controls to other subroutines
    TempReg VAR BYTE'Misc temp register
    Temp2Reg VAR BYTE'Misc temp register
    ShiftReg VAR BIT'Stores the shift key status. 1=shift 0=no shift
    DumpReg VAR BIT'Temp reg for dumping keypress values after a releasecommand
'Message array
    i VAR BYTE
    pos VAR BYTE
    Msg VAR BYTE[24]
    control VAR BYTE
'initialize
    pos=0
    FOR  i=0 TO 23
        Msg[i]=" "
    NEXT i

LCDOUT $fe, 1   ' Clear screen
LCDOUT "Starting Up"  ' Send Hello Message
PAUSE 5000
LCDOUT $fe, 1   ' Clear screen


Main:
        GOSUB ScanKeyboard'Gets key pressed keycode
        GOSUB BackSpace 'Handles backspacing
        GOSUB ChrtoASCII'Changes keycode into ascii
        GOSUB UpdateMSG 'Updates Msg array
        
        GOSUB RenderScreen 'Updates LCD
GOTO Main

WAITmsg:
    'After the command A is sent
    'control will get number of pieces
    'We KNOW that processing will send 24 pieces
    SERIN2 rx,true9600,[wait ("A"),control]
    FOR i=0 TO control-1 'Control will always be 24
        SERIN2 rx, true9600, [Msg[i]]
    NEXT
    
    GOSUB RenderScreen
    
    'THEN wait for return to exit and return
    GOSUB ScanforReturn
RETURN

ScanKeyboard:
    DumpReg = 0
    DumpKeys:'NOTE
    
    AscKey = 0
    Keypress = 0
    TrisC.5 = 1 : PortC.5 = 1 'Release Clock Line for Com from Keyboard to PIC
    GOSUB ClockCycle'Dumps start bit
    FOR TempReg = 0 TO 7
        GOSUB ClockCycle
        IF PortC.4 = 1 THEN 'Calculates bit value
            LOOKUP TempReg,[1,2,4,8,16,32,64,128],Temp2Reg
            Keypress = Keypress + Temp2Reg'Adds the bit values together
        ENDIF
    NEXT TempReg
    
    GOSUB ClockCycle'Dumps parity bit
    GOSUB ClockCycle'Dumps stop bit
    TrisC.5 = 0 : PortC.5 = 0 'Set Clock Line Low and hold Com from Keyboard to PIC

    IF Keypress = $F0 THEN'If key release command then go again
        DumpReg = 1'Set so that next key will also get dumped
        GOTO DumpKeys'Rerun loop
    ENDIF

    IF Keypress=$58 || Keypress=$12 || Keypress=$59 && DumpReg = 1 THEN'Turn off ShiftReg
        ShiftReg = 0'Sets the Shift Reg for Shift
        AscKey = 255'Will not print anything on LCD
    ENDIF

    IF DumpReg = 1 THEN'If this loop was to dump chr then send a 255 to next
        DumpReg = 0 '???????
        Keypress = 255
    ENDIF

    IF Keypress=$58 || Keypress=$12 || Keypress=$59 THEN'Turn on ShiftReg
        ShiftReg = 1'Sets the Shift Reg for Shift
        AscKey = 255'Will not print anything on LCD
    ENDIF
        
    'IF hit return then send message
    IF Keypress=$5A THEN'Turn on ShiftReg
        HIGH PortA.0
        GOSUB SENDmsg
        'We want now to reset everything
          FOR i=0 TO 23
             Msg[i]=" "
          NEXT
          pos=0
          'GO TO SOMETHING LIKE A WAIT ROUTINE
          GOSUB WAITmsg
        AscKey = 255'Will not print anything on LCD
    ENDIF    
RETURN

ScanforReturn:
    DumpReg = 0
    DumpKeysAA:'NOTE
    
    AscKey = 255'NOTE WAS 0 !!!!!!
    Keypress = 0
    TrisC.5 = 1 : PortC.5 = 1 'Release Clock Line for Com from Keyboard to PIC
    GOSUB ClockCycle'Dumps start bit
    FOR TempReg = 0 TO 7
        GOSUB ClockCycle
        IF PortC.4 = 1 THEN 'Calculates bit value
            LOOKUP TempReg,[1,2,4,8,16,32,64,128],Temp2Reg
            Keypress = Keypress + Temp2Reg'Adds the bit values together
        ENDIF
    NEXT TempReg
    
    GOSUB ClockCycle'Dumps parity bit
    GOSUB ClockCycle'Dumps stop bit
    TrisC.5 = 0 : PortC.5 = 0 'Set Clock Line Low and hold Com from Keyboard to PIC

    IF Keypress = $F0 THEN'If key release command then go again
        DumpReg = 1'Set so that next key will also get dumped
        GOTO DumpKeysAA'Rerun loop
    ENDIF

    IF DumpReg = 1 THEN'If this loop was to dump chr then send a 255 to next
        DumpReg = 0 '???????
        Keypress = 255
    ENDIF

    'IF hit return then exit and ready to write again
    'ELSE rerun the loop
    IF Keypress=$5A THEN
        'We want now to reset everything
          FOR i=0 TO 23
             Msg[i]=" "
          NEXT
          pos=0
         AscKey = 255'Will not print anything on LCD
    ELSE
         GOTO DumpKeysAA'Rerun loop
    ENDIF    
RETURN



   SENDmsg:
        FOR i=0 TO 23
             SEROUT2 tx, true9600, [Msg[i]]
        NEXT
    RETURN

UpdateMSG:'This will convert the key scan codes to ASCCII
    IF AscKey <> 255 THEN
        Msg[pos]=Keypress
        pos=pos+1
        IF pos > 23 THEN pos=23
    ENDIF
RETURN

RenderScreen:
    'Clear Screen
    LCDOUT $fe, 1
        'Render first line
        FOR i=0 TO 11
                LCDOUT  Msg[i]
        NEXT
    'Move to second line
    LCDOUT $fe, $C0
        'Render second line
        FOR i=12 TO 23
                LCDOUT  Msg[i]
        NEXT
RETURN

ClockCycle:'Waits for the clock to cycle from keyboard
    HoldClockLow:
        IF PortC.5 = 0 THEN HoldClockLow
    HoldClockHi:
        IF PortC.5 = 1 THEN HoldClockHi
RETURN

ChrtoASCII:'Converts keycode into ASCII
    IF AscKey <> 255 THEN
        AscKey = 255
        LOOKDOWN Keypress,[69,22,30,38,37,46,54,61,62,70,28,50,33,35,36,43,52,51,67,59,66,75,58,49,68,77,21,45,27,44,60,42,29,34,53,26,41,78,85,93,84,91,76,82,65,73,74],AscKey
        
        IF ShiftReg = 0 THEN
            LOOKUP AscKey,["0123456789abcdefghijklmnopqrstuvwxyz -=|{};',./"],Keypress
        ELSE
            LOOKUP AscKey,[")!@#$%^&*(ABCDEFGHIJKLMNOPQRSTUVWXYZ _+|{}:'<>?"],Keypress
        ENDIF
    ENDIF
RETURN

BackSpace:
    IF Keypress = $66 THEN'Backspace key pressed
        IF pos=23 THEN 
            IF Msg[pos]=" " THEN
                pos=pos-1: Msg[pos]=" "
            ELSE
                Msg[pos]=" "
            ENDIF
        ELSE
            IF pos > 0 THEN 
                pos=pos-1
                Msg[pos]=" "
            ENDIF
        ENDIF
       
        AscKey = 255 'Don't enable further writing
    ENDIF
RETURN



'//jleblanc 3.20.06
'//This is not very clean but it recieves bytes (24)
'//from the PIC and displays it in the window

'//IMPORT JAVA .awt FOR GUI//
'import java.awt.*;
'import java.io.*;  // this is the input/output library needed for data streams
'import java.net.*; // this is the network library needed for sockets

'public class Messenger extends PApplet implements ActionListener
'{
'  //NETWORK STUFF
'    String host; 
'    int port;
'    Socket mySocket;                    // declare Socket
'    DataInputStream myInputStream;      // declare data input stream. This will run within a socket, bringing data into Java
'    DataOutputStream myOutputStream;    // declare data output stream. This will run within a socket, sending data out from Java
'    byte myDataIn, myDataOut;           // declare some variables to store the data we're sending and receiving
'      //NOTE that in processing a byte is from 127 to -128 where:
'      //for a byte from 0-255  0->0, 127->127, 128->-128, 255->-1
'    int DATA=0;

'    //String message;
'    int holdsize;
'    byte[] hold = new byte[30];
  
'  //STRING STUFF
'    String message;
'    TextField input = new TextField("msg", 25);
'    Button send = new Button();
'    PFont font;
    
'  //VARIABLES NEEDED//////////////////////////
'  //String[] stringhold = new String[1];
'  String displayString;
'  byte[] bytehold = new byte[24];
'  int i;
  
'  int signal;
'  int flip;
'////////////////////////////////////////////                               

'  void setup() 
'  {
'    size(500,250);
'    background(0);

'    //SET NETWORK STUFF
'    host = "128.122.151.199";  // define a host to communicate with. This can be a name or IP address
'    port = 10001;              // define a port to contact on that host. Must be a number, typically 10001 for an XPort

'    //SET INTERFACE STUFF 
'    font = loadFont("ArialMT-24.vlw");

'    //Storage Variables
'    message = "test";
'    displayString="initial";
    
'    flip=0;

'  }//END setup


'  void draw () 
'  {    
'    background(50); smooth (); fill(255);
'    textFont(font); textSize(24);
  
'  //CHECK NETWORK
'    checkConnection(host, port);        // subroutine to create a connection, via a socket, to the XPort
'  //Get the incoming Message
'    GatherMsg();
'  //After that send a message back
'    Acknowledge();
'    println("FLIP "+flip);
'  }//END draw

'  void Acknowledge()
'  {
'      int ddd;
      
'      String a=str(millis()%1000);
      
'      if(flip==1)
'      {
'      //NOTE this should be given a max size
'      myDataOut = 65; 
'      sendSomeData(myDataOut);
      
'      holdsize=message.length();
'      myDataOut = (byte) 24;//holdsize; 
'      sendSomeData(myDataOut);
      
'      for(int i=0; i<hold.length; i++)
'      {
'        hold[i]=(byte)' ';
'      }
      
'      for(int i=0; i<a.length(); i++)
'      {
'        hold[i]=(byte) a.charAt(i);
'      }
'      //SECOND we send the message
'      //The question is should we send a signal character ahead of time?
'      for(int i=0; i<holdsize;i++)
'      {
'        myDataOut = hold[i];//redundant in some ways
'        sendSomeData(myDataOut);
'        //should we pause in these gaps?
'      }
'      //flip=0;
'      delay(10); //WE WAIT SO DON'T OVERLOAD PIC??????
     
'      }                                            
'    }//END Acknowledge

'  void GatherMsg()
'  {
'        String[] stringhold = new String[1];        
'        signal=0;
'        i=0;
'       //while (dataIsWaiting()==false)
'      //{}
         
'      while (dataIsWaiting() == true)        
'      {     
'        myDataIn = getSomeData();         
'        bytehold[i]=(byte)(myDataIn);
'        i++;
'        signal=1;
'        flip=1;
'      }
    
'    if(signal==1)
'    {
'      //initialize msg
'        stringhold[0]="";
'      //Load the string
'        for(int x=0; x<i; x++)
'        { stringhold=append(stringhold,str((char)bytehold[x])); println(x);}
'      //Create single string   
'        displayString=join(stringhold,"");
'     }
     
'    text(displayString, 20,20);  
'  }







'//INTERFACE FUNCTIONS

'  void actionPerformed(ActionEvent e) 
'  {
'    String command = e.getActionCommand();

'    if (command == "SEND")
'    {
'      message = getText(input);//message gets whatever is in the text box
      
'      //NOW WE MUST SEND IT!!!!!
'      //So this is the test send a message section
'    //We want to take a string and break it up into an array of bytes and then send them
'      //FIRST we load the hold array with the message
'      //NOTE this should be given a max size
'      myDataOut = 65; 
'      sendSomeData(myDataOut);
      
'      holdsize=message.length();
'      myDataOut = (byte) holdsize; 
'      sendSomeData(myDataOut);
      
'      for(int i=0; i<message.length(); i++)
'      {
'        hold[i]=(byte) message.charAt(i);
'      }
'      //SECOND we send the message
'      //The question is should we send a signal character ahead of time?
'      for(int i=0; i<holdsize;i++)
'      {
'        myDataOut = hold[i];//redundant in some ways
'        sendSomeData(myDataOut);
'        //should we pause in these gaps?
'      }                                               
'    }//END of if for send
    
'  }//END actionPerformed

 
'  String getText(TextField input)
'  {
'    return input.getText();
'  }
  

'//NETWORK FUNCTIONS
      
'  ////////CHECK CONNECTION\\\\\\\\
'void checkConnection(String host, int port) 
'{
'  if(mySocket == null || mySocket.isConnected() == false) 
'  {                 
'    println("trying to connect to: " + host + " at port: " + port);
    
'    try  // make an attempt to run the following code
'    {                                      
'      mySocket = new Socket(host,port); // initialize socket, connecting it to a host computer's port
'      println("connected!");
'    }
'    catch(Exception e)  // if the "try" attempt gave an error, run the following code
'    {                        
'      e.printStackTrace();                       // print the error to the log
'      println("unable to connect to: " + host + " at port: " + port);
'    }
'  }
'}


'////////CHECK TO SEE IF DATA IS WAITING TO COME IN\\\\\\\\\\\
'boolean dataIsWaiting() 
'{
'  boolean bytesAvailable = false;
  
'  if ( myInputStream == null) // if there's no active input stream
'  {  
'    try // create an new input stream from a particular socket
'    {
'      myInputStream = new DataInputStream(mySocket.getInputStream()); 
'      println("opening input stream");
'    }
'    catch (Exception e) 
'    {
'      e.printStackTrace();
'      println("error while opening input stream");
'    }
'  }
  
'  try 
'  {
'    if (myInputStream.available()>0) // check to see if any bytes are available
'    {      
'      bytesAvailable = true;                // ...and if they are set the variable to true
'      println(myInputStream.available() + " bytes available...");
'    }
'  }
'  catch(Exception e) 
'  {
'    e.printStackTrace();
'    println("error while checking for bytes available");
'  }
'  return bytesAvailable;
'}


'////////GET SOME DATA \\\\\\\\\\
'byte getSomeData() 
'{
'  byte inData = 0; // declare and initialize the data variable
'  try 
'  {
'    if (myInputStream.available()>0) //   only read the byte if there's a byte to read [this is a redundant check]
'    {  
'      inData = myInputStream.readByte();  // read a byte from the input stream
'      println("data received: " + inData);
'    }
'  }
'  catch(Exception e)
'  {
'    e.printStackTrace();
'    println("no data");
'  }
'  return inData;
'}


'////////SEND SOME DATA\\\\\\\\\\
'void sendSomeData(byte outData)
'{
'  if (myOutputStream == null) // if there's no active output stream
'  { 
'    try 
'    {
'      myOutputStream = new DataOutputStream(mySocket.getOutputStream()); // create an new output stream from a particular socket
'    }
'    catch (Exception e) 
'    {
'      e.printStackTrace();
'     // println("no output stream");
'    }
'  }
  
'  try
'  {
'    myOutputStream.writeByte(outData); // write a byte to the output stream
'    //println("data sent: " + outData);
'  }
'  catch(Exception e)
'  {
'    e.printStackTrace();
'    //println("event send failed");
'  } 
'}


'public void stop() // when the program quits
'{ 
'  try 
'  {
'    myInputStream.close();  // close the input stream
'    myOutputStream.close(); // close the output stream
'    mySocket.close(); // close the socket
'  }
'  catch (Exception e) 
'  {
'    e.printStackTrace();
'    println("couldn't close connection");
'  }
'}  
'}//END Messenger