' *** LCD16x2-CustCharDriver14M2.bas ******************* 2011.10.01 *** ' This program runs on a Picaxe-14M2 @ 8MHz. It receives serial data ' from a master processor & diplays it on an HD 44780-type 16x2 LCD. ' Because we are using DB5...DB2 rather than DB7...DB4, high nibbles ' need to be divided by 4 and low nibbles multiplied by 4 in order ' to place the data on the correct pins. ' Note: see this month's Primer article for detailed explanations ' of the comments that are numbered [1] through [6] ' *** Constants ******* symbol cmnd = 0 ' RSbit = 0 (low) for command bytes symbol text = 1 ' RSbit = 1 (high) for text bytes symbol enPin = B.1 ' LCD enable pin on B.1 symbol rxPin = C.4 ' serial data received on C.4 ' *** Variables ******* symbol char = b0 ' character to be sent to LCD symbol index = b1 ' used in for/next loop symbol nibHi = b2 ' the high nibble of char symbol nibLo = b3 ' the low nobble of char symbol RSbit = b4 ' used to set up for cmnd/text byte symbol temp = b5 ' used to manipulate character data symbol RSpin = pinB.0 ' here, we're using RSpin as a variable ' (to access the state of the input), ' so the form "pinB.0" is required ' *** Directives ****** #com 3 ' set COM port for downloading #picaxe 14M2 ' set compiler mode #terminal off ' *** Data ************ ' Lowercase "g" ' don't change the order of the chars data (%00000) data (%00000) data (%01111) ' **** data (%10001) ' * * data (%10001) ' * * data (%01111) ' **** data (%00001) ' * data (%01110) ' *** ' Lowercase "p" data (%00000) data (%00000) data (%10110) ' * ** data (%11001) ' ** * data (%10001) ' * * data (%11110) ' **** data (%10000) ' * data (%10000) ' * ' Lowercase "q" data (%00000) data (%00000) data (%01101) ' ** * data (%10011) ' * ** data (%10001) ' * * data (%01111) ' **** data (%00001) ' * data (%00001) ' * ' Lowercase "j" data (%00010) ' * data (%00000) ' data (%00110) ' ** data (%00010) ' * data (%00010) ' * data (%00010) ' * data (%10010) ' * * data (%01100) ' ** ' Lowercase "y" data (%00000) data (%00000) data (%10001) ' * * data (%10001) ' * * data (%10001) ' * * data (%01111) ' **** data (%00001) ' * data (%01110) ' *** ' Backslash data (%00000) data (%10000) ' * data (%01000) ' * data (%00100) ' * data (%00010) ' * data (%00001) ' * data (%00000) data (%00000) ' Bullet data (%00000) data (%01110) ' *** data (%11111) ' ***** data (%11111) ' ***** data (%11111) ' ***** data (%01110) ' *** data (%00000) data (%00000) ' Heart data (%00000) data (%01010) ' * * data (%11111) ' ***** data (%11111) ' ***** data (%01110) ' *** data (%00100) ' * data (%00000) data (%00000) ' Display on LCD data 64,("Three jolly pigs") data 80,("ready to receive") ' *** Begin Main Program ********************************************** setfreq m32 ' run as fast as possible [1] dirsB = %11111111 ' all PortB pins are outputs to the LCD dirsC = %11000111 ' C.3, C.4, and C.5 are fixed as inputs. ' *** Initialize the LCD *** outpinsB = 0 ' clear all output lines pause 1600 ' pause 200 mS for LCD initialization outpinsB = 12 ' (48/4=12) set to 4-bit operation pulsout enPin,8 ' send data pause 80 ' pause 10 mS pulsout enPin,8 ' send again pulsout enPin,8 ' send again (necessary in 4-bit mode) outpinsB = 8 ' (32/4=8) set to 4-bit operation pulsout enPin,8 ' send data. pulsout enPin,8 ' send again (necessary in 4-bit mode) outpinsB = 32 ' (128/4=32) set to 2 line operation pulsout enPin,8 ' send data char = 12 ' display on, cursor off gosub OutToLCD ' send instruction to LCD ' *** Load custom chars into CGRAM *** char = 64 ' command: define custom characters RSbit = cmnd gosub OutToLCD2 RSbit = text for index = 0 to 63 ' install 8 custom characters read index, char gosub OutToLCD2 next index ' *** Indicate "Ready to receive data." *** [2] ' (You can remove this section when everything is working properly.) char = 1 ' instruction: clear display gosub OutToLCD ' send instruction to LCD pause 16 ' minimum 2mS delay for clear display char = 128 ' instruction: go to start of 1st row gosub OutToLCD ' send instruction to LCD for index = 64 to 79 ' output data to 1st row of LCD read index, char ' read character from EEPROM gosub OutToLCD ' send character to LCD next index char = 192 ' instruction: go to start of 2nd row gosub OutToLCD ' send instruction to LCD for index = 80 to 95 ' output data to 2nd row of LCD read index, char ' read character from EEPROM gosub OutToLCD ' send character to LCD next index wait 16 ' allow 2 seconds to read display char = 1 ' clear display and go home gosub OutToLCD ' send instruction to LCD pause 16 ' minimum 2mS delay for clear display ' *** Main loop: Receive data and display it. *** do bptr = 28 ' Set up to begin storing data at location 28, [3] ' (just above the 28 general purpose variables) serin rxPin,N9600_32,@bptrinc ' no timeut; so wait for first char [4] ' This may look silly, but a loop wouldn't be fast enough! [5] serin [800], RxPin, N9600_32, @bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc @bptr = 0 ' We're using 0 as an end of transmission marker.[6] bptr = 28 ' Reset the byte pointer to the first location. do until @bptr = 0 ' loop until we reach the EOT character char = @bptrinc ' get each byte gosub OutToLCD ' and send it to the LCD loop ' do loop loop ' main loop ' *** End Main Program - Subroutines Follow *************************** ' *** OutByte Subroutine: Output 1 byte to the LCD display *** OutToLCD: select case char case 0 to 31 RSbit = cmnd ' set up for command case 128 to 207 ' commands for moving the cursor RSbit = cmnd ' to any on-screen location case 103,106,112,113 ' "g", "j", "p", & "q" char = char - 103 RSbit = text ' set up for text byte case 121 ' "y" char = 4 RSbit = text ' set up for text byte else ' all other text RSbit = text ' set up for text byte endselect OutToLCD2: nibHi = char & %11110000 ' isolate high nibble of char nibHi = nibHi / 4 ' move to pins 5,4 ,3 & 2 outpinsB = nibHi ' place high nibble of char onto pins RSpin = RSbit ' RSpin = 0 for cmnd or 1 for text pulsout enPin,1 ' send data nibLo = char & %00001111 ' isolate low nibble of char nibLo = nibLo * 4 ' move to pins 5,4 ,3 & 2 outpinsB = nibLo ' place low nibble of char onto pins RSpin = RSbit ' RSpin = 0 for cmnd or 1 for text pulsout enPin,1 ' send data return