' ========================================================================= ' ' File...... PingWithLCD.SXB ' ' Updated... 01/06/10 ' ' ========================================================================= ' ------------------------------------------------------------------------- ' Program Description ' ------------------------------------------------------------------------- ' This program is a combination of two of JonnyMac's programs and combines ' Ping with the parallel 2x16 LCD from Parallax. ' ------------------------------------------------------------------------- ' Conditional Compilation Symbols ' ------------------------------------------------------------------------- ' ------------------------------------------------------------------------- ' Device Settings ' ------------------------------------------------------------------------- ID "LCD-4" DEVICE SX28, OSCXT1, BOR42 FREQ 4_000_000 ' ------------------------------------------------------------------------- ' I/O Pins ' ------------------------------------------------------------------------- LcdPort PIN RB ' port to use DB7 PIN LcdPort.7 OUTPUT DB6 PIN LcdPort.6 OUTPUT DB5 PIN LcdPort.5 OUTPUT DB4 PIN LcdPort.4 OUTPUT RS PIN LcdPort.3 OUTPUT RW PIN LcdPort.2 OUTPUT E PIN LcdPort.1 OUTPUT ' BackLight PIN LcdPort.0 OUTPUT ' to transistor circuit PingIO PIN RC.0 ' Output to Ping ' ------------------------------------------------------------------------- ' Constants ' ------------------------------------------------------------------------- Yes CON 1 No CON 0 IsOn CON 1 IsOff CON 0 MultiLine CON 0 SingleLine CON 1 LcdCls CON $01 ' clear the LCD * LcdHome CON $02 ' move cursor home * LcdCrsrL CON $10 ' move cursor left LcdCrsrR CON $14 ' move cursor right LcdDispL CON $18 ' shift chars left LcdDispR CON $1C ' shift chars right LcdDDRam CON $80 ' Display Data RAM control LcdCGRam CON $40 ' Character Generator RAM LcdLine1 CON $80 ' DDRAM address of line 1 LcdLine2 CON $C0 ' DDRAM address of line 2 LcdLine3 CON $14 ' DDRAM address of line 3 LcdLine4 CON $54 ' DDRAM address of line 4 ' * LCD needs 2ms delay after these commands 'ForceFeed CON 55 ' just a test to help me figure out LCD_DEC ' ------------------------------------------------------------------------- ' Variables ' ------------------------------------------------------------------------- cmdChar VAR Byte ' command / character pos VAR Byte ' line position newChr VAR Byte ' new character cell VAR Byte ' cell # for animation distance VAR Word ' distance tmpB1 VAR Byte ' work vars tmpB2 VAR Byte tmpB3 VAR Byte tmpB4 VAR Byte tmpW1 VAR Word nStr VAR Byte (5) ' used by LCD_HEX, LCD_DEC ' ========================================================================= ' Subroutine / Function / Task Declarations ' ========================================================================= LCD_INIT SUB 0, 1, Byte ' initialize LCD LCD_BLIP SUB 0 ' blip LCD "E" pin LCD_CMD SUB 1, 1, Byte ' send LCD command LCD_OUT SUB 1, 1, Byte ' print char on LCD LCD_STR SUB 2, 2, Word ' print string on LCD LCD_DEC SUB 1, 3 LCD_SET_CRSR SUB 1, 1, Byte ' set cursor mode LCD_SET_CHAR SUB 3, 3, Word, Byte ' set custom char data DELAY_MS SUB 2, 2, Word, Word ' shell for PAUSE DELAY_US SUB 2, 2, Word, Word ' shell for PAUSEUS GET_DISTANCE FUNC 1, 0 ' read from Ping ' ========================================================================= PROGRAM Start ' ========================================================================= Start: PLP_A = %0000 ' pull-ups on unused pins PLP_B = %1111_1110 PLP_C = %0000_0001 Lcd_Setup: DELAY_MS 500 ' let LCD self-init LCD_INIT ' initialize (multi-line) Main: distance = GET_DISTANCE DELAY_MS 100 LCD_CMD LcdCls DELAY_MS 25 ' for effect watch distance, 8, udec break LCD_STR "Distance: " LCD_DEC distance ' LCD_DEC ForceFeed DELAY_MS 1000 GOTO Main ' ------------------------------------------------------------------------- ' Subroutine / Function / Task Code ' ------------------------------------------------------------------------- ' Use: result = GET_DISTANCE ' -- reads distance from Ping))) sensor ' -- units based on Conditional Compilation directive FUNC GET_DISTANCE result VAR tmpW1 HIGH PingIO ' "ping" the sensor DELAY_US 10 PingIO = 0 DELAY_US 5 ' let output settle INPUT PingIO ' setup for return pulse result = 0 ' clear return value \ JNB PingIO, $ ' wait for leading edge DO ' time the echo INC result '{$IFDEF English} PAUSEUS 73.746 ' measure inches '{$ELSE} PAUSEUS 29.034 ' measure centimeters '{$ENDIF} LOOP UNTIL PingIO = 0 ' stop on falling edge result = result >> 1 ' remove return trip RETURN result ENDFUNC ' ------------------------------------------------------------------------- ' Use: LCD_INIT {single} ' -- initializes LCD in 4-bit mode ' -- defaults to multi-line; single-line if single.0 = 1 SUB LCD_INIT single VAR tmpB3 IF __PARAMCNT = 0 THEN single = 0 ELSE single = __PARAM1.0 ENDIF LcdPort = %0011_0000 ' 8-bit mode LCD_BLIP DELAY_MS 5 LCD_BLIP DELAY_US 125 LCD_BLIP LcdPort = %0010_0000 ' 4-bit mode LCD_BLIP IF single.0 = 0 THEN LCD_CMD %0010_1000 ' multi-line ENDIF LCD_CMD %0000_1100 ' display on, no cursor LCD_CMD %0000_0110 ' auto-increment cursor ENDSUB ' ------------------------------------------------------------------------- ' Use: LCD_BLIP SUB LCD_BLIP E = 1 DELAY_US 2 E = 0 DELAY_US 50 ' instruction delay ENDSUB ' ------------------------------------------------------------------------- ' Use: LCD_CMD cmd ' -- send command to LCD ' -- sets buss to cmd (RS = 0), write (RW = 0) ' -- uses LCD_OUT to move command to LCD SUB LCD_CMD RS = 0 ' command mode GOTO LCD_OUT ' jump over ENDSUB ENDSUB ' ------------------------------------------------------------------------- ' Use: LCD_OUT char ' -- send character to LCD ' -- sets buss to character (RS = 1), write (RW = 0) ' -- preserves RS and backlight outputs SUB LCD_OUT byteOut VAR tmpB1 ' byte to send nibOut VAR tmpB2 ' nibble work variable byteOut = __PARAM1 ' save output byte nibOut = byteOut & $F0 ' isolate high nibble LcdPort = LcdPort & %0000_1001 ' clear buss, save RS & BL LcdPort = LcdPort | nibOut ' output high nibble LCD_BLIP SWAP byteOut ' swap nibbles nibOut = byteOut & $F0 ' isolate low nibble LcdPort = LcdPort & %0000_1001 LcdPort = LcdPort | nibOut LCD_BLIP RS = 1 ' default to write mode ENDSUB ' ------------------------------------------------------------------------- ' Use: LCD_STR [string | Label] ' -- prints embedded string or z-string at Label SUB LCD_STR sAddr VAR tmpW1 ' address of string sChar VAR __PARAM1 ' character from string sAddr = __WPARAM12 ' copy address DO READINC sAddr, sChar ' get a character IF sChar = 0 THEN EXIT ' if 0, we're done LCD_OUT sChar ' print the character LOOP ENDSUB ' ------------------------------------------------------------------------- ' Use: LCD_DEC value {, digits } ' -- prints "value" in DEC format ' -- "digits" MUST be specified with word values ' -- DEC3 or DEC5 format is used if "digits" not specified or invalid SUB LCD_DEC dValue VAR tmpW1 dDigits VAR tmpB3 dIdx VAR tmpB4 IF __PARAMCNT = 1 THEN ' byte w/o digits dValue = __PARAM1 dDigits = 3 ELSEIF __PARAMCNT = 2 THEN ' byte w/digits dValue = __PARAM1 dDigits = __PARAM2 ELSE ' word w/digits dValue = __WPARAM12 dDigits = __PARAM3 ENDIF IF dDigits = 0 THEN ' validate digits dDigits = 5 ELSEIF dDigits > 5 THEN dDigits = 5 ENDIF STR nStr, dValue ' to decimal string dIdx = 5 - dDigits ' point to first char DO WHILE dIdx < 5 LCD_OUT nStr(dIdx) INC dIdx LOOP ENDSUB ' ------------------------------------------------------------------------- ' Use: LCD_SET_CRSR ' -- set cursor on (1) or off (0) SUB LCD_SET_CRSR crsrCmd VAR __PARAM2 crsrCmd = %0000_1100 ' display on, no cursor crsrCmd.1 = __PARAM1.0 ' set cursor to parameter LCD_CMD crsrCmd ENDSUB ' ------------------------------------------------------------------------- ' Use: LCD_SET_CHAR Label, char# ' -- moves custom char data from Label to CGRam for char# SUB LCD_SET_CHAR chAddr VAR tmpW1 ' address of char data chNum VAR tmpB3 ' character # chIdx VAR tmpB4 ' loop control chByte VAR __PARAM1 ' byte to send to CGRam chAddr = __WPARAM12 ' copy address chNum = __PARAM3 & %0000_0111 ' limit: 0 to 7 chNum = chNum << 3 ' x8 (bytes per character) chNum = chNum | LcdCGRam ' create CGRam address LCD_CMD chNum ' point to character RAM FOR chIdx = 0 TO 7 READINC chAddr, chByte ' read data byte LCD_OUT chByte ' write to CGRAM NEXT ENDSUB ' ------------------------------------------------------------------------- ' Use: DELAY_MS duration ' -- shell for PAUSE SUB DELAY_MS '{$IFUSED DELAY_MS} msDuration VAR __WPARAM12 PAUSE msDuration '{$ENDIF} ENDSUB ' ------------------------------------------------------------------------- ' Use: DELAY_US duration ' -- shell for PAUSEUS SUB DELAY_US '{$IFUSED DELAY_US} usDuration VAR __WPARAM12 PAUSEUS usDuration '{$ENDIF} ENDSUB