'jleblanc 4.13.06
'this code writes a keyboard input out to Xterm
'uses code from Daryl Owen 7/11/00 (see my website for link)
'for my connector: 
    'red to ground
    'white to power
    'black to  A4
    'yellow to  A5
'NOTE THE ADCON CALL IN HERE. YOU NEED IT TO MAKE PORT A DIGITAL

DEFINE OSC 20

'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
'Variables used with LCD
    CursorLocation VAR BYTE'Cursor Location on LCD
    CursorMin VAR BYTE'Minimum cursor position
    CursorMax VAR BYTE'Maximum cursor position

    ADCON1 = %10000110

SEROUT2 PORTC.6, 16468, ["Starting Up", 10, 13]
PAUSE 1000

Main:
    GOSUB ScanKeyboard'Gets key pressed keycode
    GOSUB KeyFilters'Filters out unprintable Chrs
    GOSUB ChrtoASCII'Changes keycode into ascii
    GOSUB UpdateXTERM 'Print to the window
GOTO Main

ScanKeyboard:
    DumpReg = 0
    DumpKeys:'NOTE
    
    AscKey = 0
    Keypress = 0
    TrisA.1 = 1 : PortA.5 = 1 'Release Clock Line for Com from Keyboard to PIC
    GOSUB ClockCycle'Dumps start bit
    FOR TempReg = 0 TO 7
        GOSUB ClockCycle
        IF PortA.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
    TrisA.1 = 0 : PortA.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
RETURN

UpdateXTERM:'This will convert the key scan codes to ASCCII
    IF AscKey <> 255 THEN
           SEROUT2 PORTC.6, 16468, [Keypress]
    ENDIF
RETURN


UpdateLCD:'This will convert the key scan codes to ASCCII
    IF AscKey <> 255 THEN
        'LCDOUT $FE,CursorLocation, Keypress
        CursorLocation = CursorLocation + 1
        GOSUB CheckCurPos
    ENDIF
RETURN

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

ChrtoASCII:'Converts keycode into ASCII
    IF AscKey = 254 THEN SkipASCII'No Conversion

    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
        LOOKUP AscKey,["0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ -+\[];',./"],Keypress
    ENDIF
SkipASCII:
RETURN

KeyFilters:
    IF Keypress = $66 THEN'Backspace key pressed
        'LCDOUT $FE,CursorLocation," "'Prints a blank
        CursorLocation = CursorLocation - 1'Moves cursor back 1 spaces. Note:The LCD cursor location will have a blank printed from the ASCII lookuptable.
        GOSUB CheckCurPos
        'LCDOUT $FE,CursorLocation," "'Prints a blank
        AscKey = 255'Will not print anything on LCD
    ENDIF

    IF Keypress=$1E && ShiftReg = 1 THEN
        Keypress="@"
        AscKey = 254
    ENDIF
RETURN

CheckCurPos:'Verifies cursor is within limits
    IF CursorLocation > CursorMax THEN
        CursorLocation = CursorMax
    ENDIF
    IF CursorLocation < CursorMin THEN
        CursorLocation = CursorMin
    ENDIF
RETURN