' BS1_PROG.DOC ' A PBASIC Program by Sheldon X. Charrett ' Firmware for LCD Readout Module interfaced with Decoder Module ' A DTMF Decoder ' Copyright 1998 by Sheldon X. Charrett ' CONSTANTS ' ~~~~~~~~~ SYMBOL E = 4 ' LCD enable pin (1 = enabled) SYMBOL RS = 5 ' Register Select (1 = char) SYMBOL DV = pin6 ' Refers to I/O pin (P6) of LCD Module’s IC1 (not pin 6 of IC) SYMBOL MODE = pin7 ' VARIABLES ' ~~~~~~~~~ SYMBOL outp = B0 ' output workspace SYMBOL char = B1 ' char sent to LCD SYMBOL address = B3 SYMBOL ctr = B4 ' LOAD THE EEPROM ' ~~~~~~~~~~~~~~~ ' **** SOFTWARE FIX **** ' This allows for straight PCB Traces EEPROM ("D84#206B195A3*7C") ' Initialize the LCD (Hitatchi HD44780 controller) ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ LCD_INIT: Pins = %00000011 ' 8‑bit mode dirs = %00111111 ' ~~~~~~~~~~ PULSOUT E, 1 PAUSE 5 PULSOUT E, 1 PULSOUT E, 1 Pins = %00000010 ' 4‑bit mode PULSOUT E, 1 ' ~~~~~~~~~~ char = %00101000 ' Dual line display / 5x7 font GOSUB LCD_WRITE ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ char = %00000100 ' Don't allow increment (bit 2) GOSUB LCD_WRITE ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ char = %00000001 ' Display clear GOSUB LCD_WRITE ' ~~~~~~~~~~~~~ char = %00001110 ' Display & cursor on GOSUB LCD_WRITE ' ~~~~~~~~~~~~~~~~~~~ HIGH RS ' LCD to character mode ' ***************************************************************** ' MAIN CODE ' ***************************************************************** START: ctr = 0 read 255, address ' find program end LOOP: if DV = 1 then WAIT ' See if a new DTMF tone is present if MODE = 1 then PLAYBACK ' See if user wants to read EEPROM goto LOOP ' Otherwise keep looping WAIT: if DV = 1 then WAIT ' Wait until tone is done SEND_2_LCD: ' Send the 8870 output to the LCD dirs = %00110000 ' Prepare for 4‑bit read I/O pins 0 – 3 (not IC pins) let char = pins ' Read DTMF code let char = char & %00001111 ' Mask off high bits READ char, char ' Grab proper character from EEPROM GOSUB LCD_WRITE ' Write data to LCD GOSUB WrEEPROM ' Write data to EEPROM ctr = ctr+1 ' Increment the Counter GOSUB JUMP ' See if we need address change GOTO LOOP ' Wait for next DTMF tone ' ************************************************************************* ' SUB‑ROUTINES ' ************************************************************************* PLAYBACK: read 255, address char = %00000001 ' Clear LCD GOSUB LCD_CONTROL char = %00001110 ' Cursor On GOSUB LCD_CONTROL ctr = 0 ' Reset the counter READOUT: address = address – 1 ' decrement the address read address, char ' put data at address into char GOSUB LCD_WRITE ' write data at address to LCD PAUSE 250 ' print out slowly for peace of mind ctr = ctr + 1 ' increment counter GOSUB jump ' see if we need to jump to non-contiguous address space if MODE = 0 then START ' see if user wants to exit if ctr = 16 then START ' limit to one screen (there is still memory to play with) goto READOUT LCD_CONTROL: LOW RS ' tell the LCD it’s receiving a command GOSUB LCD_WRITE ' send the command HIGH RS ' put LCD back in data mode RETURN ' Return from subroutine LCD_WRITE: ' Write char to LCD dirs = %11111111 Pins = Pins & %00100000 ' RS = 1, data bus clear outp = char / 16 ' get high nibble Pins = Pins | outp ' output the nibble PULSOUT E, 1 ' strobe the Enable line Pins = Pins & %00100000 ' RS = 1, data bus clear outp = char & %00001111 ' get low nibble Pins = Pins | outp ' output the nibble PULSOUT E, 1 ' strobe the Enable line dirs = %00110000 ' Reset Pin Directions RETURN ' Return from subroutine WrEEPROM: ' Write Character to EEPROM: address = address ‑ 1 WRITE address, char if ctr = 16 then LCD_INIT RETURN ' Return from subroutine JUMP: ' Rectify Hitachi's addressing scheme IF ctr <> 8 then skip ' Rectify P‑BASIC's IF command char = %11000000 ' 192 in decimal (second 1/2 of LCD) gosub LCD_CONTROL ' Nested RETURN is no problem here RETURN ' Return to address stored by GOSUB skip: RETURN ' Return to address stored by GOSUB