'jleblanc 4.14.06
'This is working, just does keyboard to 4X16 line LCD
'this will send a message to a board running rf_413_3

'for my connector: 
    'red to ground
    'white to power
    'black to A0
    'yellow to A1
'See just below for LCD setup

DEFINE OSC 20
'include modedefs.bas for shiftin and out modes
INCLUDE "modedefs.bas"

''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
'    ' 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

'Setup KeyBoard System
    'The keyboard runs off PORTA so this sets it to all digital
        ADCON1 = %10000110
        KeyData VAR PORTA.0
        KeyClk VAR PORTA.1

'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[48] 'For 16 x 3
    control VAR BYTE
'initialize
    pos=0
    FOR  i=0 TO 47
        Msg[i]=" "
    NEXT i

'***************************************************************************
'*VARIABLES
'***************************************************************************
    'general purpose variables
'        i VAR BYTE
        counter VAR BYTE    
    'pin definitions for comm w/ Laipec TRW-24G
        RF_CE   VAR    PORTD.7 'yellow
        RF_CS   VAR    PORTD.3 'dark green
        RF_DR   VAR    PORTD.2 'blue
    'channel 1 PIN definitions
        RF_CLK1 VAR    PORTD.1 'black
        RF_DATA_In VAR PORTD.0 'light blue
        RF_DATA_Out VAR PORTD.0
    'I/O + Control PINS
        switch  VAR portc.4
        receiveLED  VAR portc.3
        sendLED VAR portc.2    
    ' THIS IS THE ADDRESS FOR THE MiRF v01
        WhichAddress1 VAR BYTE    'Channel 1
        WhichAddress2 VAR BYTE    'Channel 2    
    ' DEFINE VARIABLES FOR SERIAL TO PC
        inv9600 CON 16468   ' baudmode for serin2 and serout2: 9600 8-N-1 inverted
        non9600 CON 84      ' baudmode for serin2 and serout2: 9600 8-N-1 non-inverted    
    'constants for RF configuration modes
        CONRFRX VAR BYTE
        CONRFTX VAR BYTE    
    'indicates state of current RF configuration - TX is 0, RX is 1
        RFCurrentState VAR BIT    
    'hold data for RF message
        RFDataArrayIN VAR BYTE[19]
        RFDataArrayOUT VAR BYTE[19]   
    'hold data for RF configuration
        RFConfigArray VAR BYTE[16]    
    'variables for each received or sent message
        msgFromID VAR BYTE
        msgToID VAR BYTE
    'ID variables    
        me  VAR BYTE    'ID that should be set to a unique number for each board
        friend  VAR BYTE
        me = 1      'ID that should be set to a unique number for each board
        friend = 2    
     'this variable in association with switch triggers a send   
         trigger VAR BIT
         trigger=0
         line_number VAR BYTE
         line_number=0         
     'Display Array
        DisplayArray VAR BYTE[48]   '3 lines by 16 bytes

'************************************************************************
'*Bootup
'************************************************************************

      WhichAddress1 =$BA 'These are things maybe to change????
       WhichAddress2 =$BA
       PORTA = %00000000;
       TRISA = %00000001;  ' 0 = Output, 1 = Input  (A.1 is RxPC)
    
       PORTB = %00000000;
       TRISB = %01101010;  ' 0 = Output, 1 = Input (C.1 is RF_DATA_In, C.3 is RF_DR)
    
       'intialize RF module configuration
       'constants to define receive/transmit modes at 2402 Mhz frequency
       CONRFRX = $05
       CONRFTX = $04
       RFCurrentState = CONRFRX
    
       GOSUB initRFConfig
    
       msgToID = 0   ' CHANGE THIS TO WHO SHOULD RECIEVE MESSAGE
       msgFromID = me   '  CHANGE THIS TO ID OF SENDER
       
    LCDOUT $fe, 1   ' Clear screen
    LCDOUT "Starting Up"  ' Send Hello Message
    PAUSE 5000
    LCDOUT $fe, 1   ' Clear screen

'************************************************************************
'*Main Loop
'************************************************************************
    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

'************************************************************************
'*Sub Programs
'************************************************************************

ScanKeyboard:
    DumpReg = 0
    DumpKeys:'NOTE
    
    AscKey = 0
    Keypress = 0
    INPUT KeyClk : KeyClk = 1 'Release Clock Line for Com from Keyboard to PIC
    GOSUB ClockCycle'Dumps start bit
    FOR TempReg = 0 TO 7
        GOSUB ClockCycle
        IF KeyData = 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
    OUTPUT KeyClk : KeyClk = 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
'        '****************************************************
'       'CURRENTLY NO SEND OUT ROUTINE USED
'       '*****************************************************
'        GOSUB SENDmsg
        
        
'          'GO TO SOMETHING LIKE A WAIT ROUTINE
'          '****************************************************
'          'WE DON'T GO TO THE WAIT ROUTINE HERE
'          '*****************************************************
'          'GOSUB WAITmsg

        'WE WANT TO SEND THE DATA
             msgToID = friend   ' CHANGE THIS TO WHO SHOULD RECIEVE MESSAGE
           'Send 3 times
                line_number=1
                GOSUB sendData    ' goto the sendData function
                PAUSE 50
                line_number=2
                GOSUB sendData    ' goto the sendData function
                PAUSE 50
                line_number=3
                GOSUB sendData    ' goto the sendData function
                PAUSE 50
                
        'We want now to reset everything
          FOR i=0 TO 47
             Msg[i]=" "
          NEXT
          pos=0    
        AscKey = 255'Will not print anything on LCD
    ENDIF    
RETURN
 

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

 Renderscreen:
            'Clear Screen
            LCDOUT $fe, 1
            'Print some message  line 1
            FOR i=0 TO 15
                    LCDOUT  Msg[i]
            NEXT
            'Move to second line
            LCDOUT $fe, $C0
            FOR i=16 TO 31
                    LCDOUT  Msg[i]
            NEXT
            'Move to third line
            LCDOUT $fe, $90
            FOR i=32 TO 47
                    LCDOUT  Msg[i]
            NEXT   
    RETURN'RUNDISPLAY

ClockCycle:'Waits for the clock to cycle from keyboard
    HoldClockLow:
        IF KeyClk = 0 THEN HoldClockLow
    HoldClockHi:
        IF KeyClk = 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=47 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

'***************************************************************************
'*SUB PROGRAMS
'***************************************************************************       
    'RECEIVERF   
    'LOADARRAYS   
    'RUNDISPLAY   
    'SENDDATA   
    'SETRFCONFIG  
    'INITRFCONFIG
     
    RECEIVERF:   
        INPUT RF_DATA_In 'Redudant? given we say this in main loop?
       'power down RF front-end for current conservation
       LOW RF_CE
       'clock in data from RF-24G to PIC
       FOR i=0 TO 18
           'clock should follow data by at least 50nsec
           ''This basically sends out a clock signal
           ''SHIFTIN  DataPin,ClockPin,Mode,[Var{\Bits}...]
           SHIFTIN RF_DATA_In, RF_CLK1, MSBPRE, [RFDataArrayIN[i]\8]
       NEXT
    
       'send received data to PC for serial debugging 
            FOR i=0 TO 18
            SEROUT2 PORTC.6, 16468, [RFDataArrayIN[i]]  'Non DEC
            NEXT
            SEROUT2 PORTC.6, 16468, [10, 13]  'Non DEC
    
    'OUTPUT TO LCD
             GOSUB LoadArrays
            
       'power up RF front-end again
      HIGH RF_CE
      'Absorb the incoming Message
      msgToID = RFDataArrayIN[0]       'the receiver is in msgToID
      msgFromID = RFDataArrayIN[1]    'sender information in msgFromID
    
      'Here we blink to acknowledge we have received the message
        HIGH receiveLED:PAUSE 50:LOW receiveLED:PAUSE 50
        HIGH receiveLED:PAUSE 50:LOW receiveLED:PAUSE 50    
    RETURN 'RECEIVERF
    
    LOADARRAYS:
        'Note array element [2] is the line number
        'Load first Line
        IF RFDataArrayIN[2]=1 THEN        
            'Load first part of array
            FOR i=0 TO 15
                DisplayArray[i]=RFDataArrayIN[i+3]
            NEXT
        ENDIF
        'Load second Line
        IF RFDataArrayIN[2]=2 THEN
            'Load second part of array
            FOR i=0 TO 15
                DisplayArray[i+16]=RFDataArrayIN[i+3]
            NEXT
        ENDIF
        'Load third Line + Display
        IF RFDataArrayIN[2]=3 THEN
            'Load third part of array
            FOR i=0 TO 15
                DisplayArray[i+32]=RFDataArrayIN[i+3]
            NEXT
            'Print the whole array
            GOSUB RunDisplay                                        
        ENDIF   
    RETURN'LOADARRAYS
    
    RUNDISPLAY:
            'Clear Screen
            LCDOUT $fe, 1
            'Print some message  line 1
            FOR i=0 TO 15
                    LCDOUT  DisplayArray[i]
            NEXT
            'Move to second line
            LCDOUT $fe, $C0
            FOR i=16 TO 31
                    LCDOUT  DisplayArray[i]
            NEXT
            'Move to third line
            LCDOUT $fe, $90
            FOR i=32 TO 47
                    LCDOUT  DisplayArray[i]
            NEXT   
    RETURN'RUNDISPLAY
    
    SETARRAY:
    
    RETURN'SETOUTARRAY
    
    SENDDATA:
        '19 byte message
        'Load the RF data out array with our message
           RFDataArrayOUT[0] = msgToID
           RFDataArrayOUT[1] = msgFromID
           RFDataArrayOUT[2] = line_number 'this is line number 1-3, here just the number of times we've sent
'           'This it the paragraph message
'           RFDataArrayOUT[3] = "0"'byteval'msgData1
'           RFDataArrayOUT[4] = "1"'msgData2
'           RFDataArrayOUT[5] = "2"'msgData2
'           RFDataArrayOUT[6] = "3"'msgData2
'           RFDataArrayOUT[7] = "4"'msgData2
'           RFDataArrayOUT[8] = "5"'msgData2
'           RFDataArrayOUT[9] = "6"'msgData2
'           RFDataArrayOUT[10] = "7"'msgData2
'           RFDataArrayOUT[11] = "8"'msgData2
'           RFDataArrayOUT[12] = "9"'msgData2
'           RFDataArrayOUT[13] = "A"'msgData2
'           RFDataArrayOUT[14] = line_number+48'msgData2
'           RFDataArrayOUT[15] = "C"'msgData2
'           RFDataArrayOUT[16] = "D"'msgData2
'           RFDataArrayOUT[17] = "E"'msgData2
'           RFDataArrayOUT[18] = "F"'msgData2

        FOR i=0 TO 15
            RFDataArrayOUT[i+3]=Msg[i]
        NEXT
    
           'set RF to transmit mode...
            RFCurrentState = CONRFTX
            GOSUB setRFConfig
    
    ' for shockburst TX, the sum of RX address, payload, and CRC must be less than 256 bits long
    ' the chip then tacks on a preamble to this message, and the total msg is 266 bits
    
           OUTPUT RF_DATA_Out   'Makes the pin an Output
    
           'get back into active mode
           HIGH RF_CE
    
           'Need pause between CE high and DATA clock out
           PAUSEUS 100
    
           'clock out 5 byte RF address of recipient
           FOR i = 8 TO 12
               'clock out this byte
               SHIFTOUT RF_DATA_Out, RF_CLK1, MSBFIRST, [RFConfigArray[i]\8]
           NEXT
    
           'clock out 19 bytes of data payload
           FOR i = 0 TO 18
               'clock out this byte
               SHIFTOUT RF_DATA_Out, RF_CLK1, MSBFIRST, [RFDataArrayOUT[i]\8]
           NEXT
    
           'start shockburst transmission
           LOW RF_CE
           PAUSEUS 300
    
           'flash LED to indicate that we transmitted
           HIGH sendLED:PAUSE 50:LOW sendLED:PAUSE 50
           HIGH sendLED:PAUSE 50:LOW sendLED:PAUSE 50
        
           'afterward, set RF back to its default receive state
                RFCurrentState = CONRFRX
                GOSUB setRFConfig
    RETURN'SENDATA
           
    SETRFCONFIG:  '  THIS IS USED TO SWITCH BETWEEN RECIEVE AND TRANSMIT MODES    
       'during configuration of the transmitter, we need RF_DATA as an output
       OUTPUT RF_DATA_Out
    
       'set chip to configure mode (CE low, CS high)
       LOW RF_CE
       HIGH RF_CS
    
       'pause between CS high and DATA clockout
       PAUSEUS 100
    
       'RFCurrentState indicates 2402 Mhz frequency and either RX or TX state
       'clock out new configuration data from PIC to RF-24G
       SHIFTOUT RF_DATA_Out, RF_CLK1, MSBFIRST, [RFCurrentState\8]
    
       'configuration set on falling edge of CS
       LOW RF_CS
       LOW RF_CE
    
       'for consistency with the rx, stick this here
       INPUT RF_DR
    
       'flash the LED on B6 to indicate that we configured
       'high DEBUG_LED1
      ' pause 250
       'low DEBUG_LED1    
    RETURN'SETRFCONFIG
    
    INITRFCONFIG:
       'configuration is a 144 bit word
       'must be clocked in MSB first
       'bit map
       '143:120 - reserved for testing
       '119:112 - length of data payload section RX channel 2
       '111-104 - length of data payload section RX channel 1
       '103:64  - up to 5 byte address for RX channel 2
       '63:24   - up to 5 byte address for RX channel 1
       '23:18   - number of address bits (both RX channels)
       '17      - 8 or 16 bit CRC
       '16      - enable on-chip CRCD generation/checking
       '15      - enable two channel receive mode
       '14      - communication mode (direct or shockburst)
       '13      - RF data rate (1Mbps requires 16Mhz crystal)
       '12:10   - crystal frequency
       '9:8     - RF output power
       '7:1     - frequency channel
       '0       - RX or TX operation
    
       'setup RFConfigArray with config bytes, see datasheet for default configuration
       'this array is backwards so we can clock from MSB to LSB by increasing the index
       'Data bits 119-112: Max data width on channel 2 (excluding CRC and adrs)
        RFConfigArray[1] = $98 'payloadSize, 19 BYTES (this is 19*8 for bits in hex)
       'Data bits 111-104: Max data width on channel 1 (excluding CRC and adrs)
        RFConfigArray[2] = $98 'payloadSize, 19 BYTES
       'Data bits 103-64: Channel 2 address, 5 bytes (40 bits)
        RFConfigArray[3] = WhichAddress2
        RFConfigArray[4] = WhichAddress2
        RFConfigArray[5] = WhichAddress2
        RFConfigArray[6] = WhichAddress2
        RFConfigArray[7] = WhichAddress2
       'Data bits 63-24: Channel 1 address, 5 bytes (40 bits)
        RFConfigArray[8] = WhichAddress1
        RFConfigArray[9] = WhichAddress1
        RFConfigArray[10] = WhichAddress1
        RFConfigArray[11] = WhichAddress1
        RFConfigArray[12] = WhichAddress1
       'Data bits 23-16: Address width and CRC  - 40 bit addr, 16 bit CRC, CRC enabled
        RFConfigArray[13] = $A3
       'Data bits 15-8: One Channel Receive, Shockburst Enabled, 250 kilobits, etc
        RFConfigArray[14] = $4F
       'Data bits 7-0: 2402 Mhz frequency, RX enabled/disabled (depending on RFCurrentState)
        RFConfigArray[15] = RFCurrentState
    
       '===================================================================
       'During configuration of the transmitter, we need RF_DATA as an output
       INPUT RF_DR
       INPUT RF_DATA_In
       OUTPUT RF_DATA_Out
    
       'set chip to configure mode (CE low, CS high)
       LOW RF_CE
       HIGH RF_CS
    
       'pause between CS high and DATA clockout
       PAUSEUS 100
    
       'clock out configuration bytes from PIC to RF-24G
       FOR i = 1 TO 15
           'set config one byte at a time from MSB to LSB
           SHIFTOUT RF_DATA_Out, RF_CLK1, MSBFIRST, [RFConfigArray[i]\8]
       NEXT
       'configuration is set on the falling edge of CS, bring it low
       LOW RF_CS
       LOW RF_CE
    
       'flash LED on pin B6 to debug that we configured
       HIGH sendLED:PAUSE 250:LOW sendLED:PAUSE 250
       HIGH receiveLED:PAUSE 250:LOW receiveLED:PAUSE 250
       HIGH sendLED:PAUSE 250:LOW sendLED:PAUSE 250
       HIGH receiveLED:PAUSE 250:LOW receiveLED:PAUSE 250
    
    RETURN'INITRFCONFIG
    
'***************************************************************************
'*END SUB PROGRAMS
'***************************************************************************    



'********************************************************************
'*I/O Functions
'*NOTE: These are made to run with Xport! Will not work with RF
'*They must be rewritten to work with RF
'********************************************************************
    'SENDmsg
    'WAITmsg
    'ScanforReturn




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

'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

'ScanforReturn:
'    DumpReg = 0
'    DumpKeysAA:'NOTE
    
'    AscKey = 255'NOTE WAS 0 !!!!!!
'    Keypress = 0
'    Input keyclk : keyclk = 1 'Release Clock Line for Com from Keyboard to PIC
'    GOSUB ClockCycle'Dumps start bit
'    FOR TempReg = 0 TO 7
'        GOSUB ClockCycle
'        'IF PortA.0 = 1 THEN 'Calculates bit value
'        IF keydata = 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
'    output keyclk : keyclk = 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 47
'             Msg[i]=" "
'          NEXT
'          pos=0
'         AscKey = 255'Will not print anything on LCD
'    ELSE
'         GOTO DumpKeysAA'Rerun loop
'    ENDIF    
'RETURN