B+[M+1]+E) * TPB ] represents the minimum time to complete an LCD read or write operation, this minimum time must be greater than the LCD enable cycle time, tC, which is specified as 450 ns. For the configuration described above, [(B+[M+1]+E) * TPB] = [(5) * 100 ns] = 500 ns, thereby satisfying the LCD timing specifications. If the cycle time is too short, wait periods can be added to any segment within the allowable ranges. Since the PMP is clocked from the peripheral bus clock, it is likely that the PMP cycle is slower than the core CPU, which means that the PMP also has a busy flag that must be polled before writing or reading the next byte. With the PMP interrupt disabled, the only way to determine if the PMP is ready for the next read or write cycle is to poll the PMP flag. The PMPMasterWrite function provided in the PIC32 Peripheral Library polls the PMP flag to ensure it has been cleared prior to writing. The code for writing to the LCD using the PMP is shown in Listing 7.3. —- ==== Listing 7.3. LCD Write Function Using the PMP ====

void writeLCD( int addr, char c)    
{
   while( busyLCD());	// Wait for LCD to be ready
   PMPSetAddress( addr);  // Set LCD RS control
   PMPMasterWrite( c);    // initiate write sequence
} // End of writeLCD

—- Reading the PMP requires two successive read operations, as shown in Listing 7.4. Figure 7.17 shows that the PIC32 reads the Busy Flag 14 times before the Busy Flag resets. Since the readLCD function calls mPMPMasterReadByte(); twice in a row before returning the value, the readLCD function is only called seven times before the Busy Flag is returned as zero. Regardless of how many times the Busy Flag is read, the LCD doesn’t return a Busy Flag value of zero until 33.6 μs after the LCD write operation. A capture of the timing for the PMP is shown in Appendix B. —- ==== Listing 7.4. LCD Read Function Using the PMP ====

char readLCD( int addr )
{
   PMPSetAddress( addr);       // Set LCD RS control
   mPMPMasterReadByte();       // initiate dummy read sequence
   return mPMPMasterReadByte();// read actual data
} // End of readLCD

—- For additional details concerning the PIC32 PMP, refer to Section 13 of the PIC32 Family Reference Manual. —- ===== 7. References ===== - Basys MX3 Data sheet. - PIC32MX330/350/370/430/450/470 Family Data Sheet. - 2 Line 16 Character LCD Data Sheet, http://www.lcd-modules.com.tw/upload/web/SC/SC1602B.pdf. - LCD Data sheet, https://www.sparkfun.com/datasheets/LCD/ADM1602K-NSW-FBS-3.3v.pdf. - ASCII Table, http://www.asciitable.com/. —- ===== Appendix A: Unit 3 Parts Configuration ===== Figure A.1. LCD connection schematic diagram for Labs 3a and 3b. Figure A.1. LCD connection schematic diagram for Labs 3a and 3b. —- ===== Appendix B: LCD Custom Instrumentation ===== As noted above in section 4.2, Fig. B.2 through Fig. B.4 show data from an Analog Discovery 2 connected directly to the LCD data pins and the three handshaking and control pins, RS, R/W, and EN. Figure B.1 shows a prototype of the Basys MX3 that was altered to include longer header pins on the LCD. This custom modification was made to enable testing during software development. It is not required to make this modification in order to complete Lab 3a and Lab 3b. Note the Analog Discovery 2 is not connected directly to the on-board 30-pin Analog Discovery 2 connector, J4, in this case because the LCD data pins are not broken out to the Analog Discovery Interface connector. Figure B.1. Equipment configuration used in Lab 3a and 3b for Unit 3. Figure B.1. Equipment configuration used in Lab 3a and 3b for Unit 3. The alternate method to implementing fixed delays, as was discussed in the main body of this text, when writing control or display data bytes is to continuously read the LCD Busy Flag and wait for the Busy Flag to be reset before completing any read or write operation. Therefore, there is no waiting to read the Busy Flag. Figure B.2 is a screen capture of this operation. The Busy Flag and DDRAM address is initially read as 0x4c, meaning that the cursor is located at the 12th character position on the second line and the Busy Flag is off. Following that, a new cursor position, 0x48, is written to the LCD. The value shown in Fig. B.2 is 0xC8 because the 8th bit is set to instruct the LCD to move the cursor to a new position using the “Set DDRAM Address” instruction. The Busy Flag and DDRAM address is read six consecutive times. The busy flag is set high the first five times. The sixth time the busy flag is set low (not busy) and the address shows 0x48, meaning the cursor position is now located for the eighth character position of the second row. The period the Busy Flag reads high for is 33.6 μs. This is consistent with the 39 μs listed in Table 7.3. Again, the execution times shown in Table 7.3 are worst case and dependent on operating temperature and supply voltage. Figure B.2. LCD timing diagram for a Set Cursor Position instruction using 1 μs setup and EN extension delays. Figure B.2. LCD timing diagram for a Set Cursor Position instruction using 1 μs setup and EN extension delays. Figure B.3 shows the timing for the Set Cursor Position instruction where the read cycle speed is increased by a factor of 10. Note that the period waiting for the instruction execution to complete is still 33.6 μs, thus showing the LCD processing time is independent of the processor to LCD interface speed. Figure B.3. LCD timing diagram for a Set Cursor Position instruction using 0.1 μs setup and EN extension delays. Figure B.3. LCD timing diagram for a Set Cursor Position instruction using 0.1 μs setup and EN extension delays. Figure B.4 shows the similar timing of the Set Cursor Position when the PMP interface to the LCD is used in place of the Bit-Banging type of parallel bus control. As one can readily see, the LCD response in Fig. B.3 is very similar to Fig. B.4; however, as discussed in Section 7.5, the PMP interface requires far fewer lines of instruction code. Figure B.4. LCD timing diagram for a Set Cursor Position instruction using the PIC32 PMP interface. Figure B.4. LCD timing diagram for a Set Cursor Position instruction using the PIC32 PMP interface. —- ===== Appendix C: LCD Custom Characters ===== When you send the ASCII code for a character like “A” to an LCD module, the LCD controller looks up the appropriate 5×8-pixel pattern in ROM (read-only memory) and displays that pattern on the LCD. That character-generator ROM contains 192 bit-mapped characters corresponding to the alphabet, numbers, punctuation, and a limited set of Japanese Kanji characters and Greek symbols. The ROM is part of the main LCD controller (e.g., HD44780, KS0066, etc.), is mask-programmed, and cannot be changed by the user. The manufacturers do offer alternative symbol sets in ROM for European and Asian languages, but most U.S. distributors stock only the standard character set shown in the LCD Serial Backpack manual. Alphanumeric LCD controllers do not allow you to turn individual pixels on or off – they just let you pick a particular pattern (corresponding to an ASCII code) and display it on the screen. If you can't change the ROM and you can't control pixels, how do you create graphics on these LCDs? It’s easy! There is a 64-byte block of RAM (random-access memory) that the LCD controller uses in the same way as it does the ROM-based character-generator. This is the CGRAM. When the controller receives an ASCII code in the range that's mapped to the CGRAM, it uses the bit patterns stored there to display a pattern on the LCD. The main difference is that you can write to CGRAM, thereby defining your own graphic symbols. A character LCD that uses the HD44780 or the KS0068 controller allows for eight programmable characters. The character patterns must initially be programmed into the CGRAM of the LCD. First, the CGRAM must be selected by setting the CGRAM address for the character that is to be programmed. Each eight consecutive addresses, starting at CGRAM address zero, are assigned to one programmable graphical character. Each bit of the data at each address sets the pixel on (1) or off (0). The pixels on a particular row at the right of the character display have the lowest binary value. The rows of pixels start at the top and move down the character as the addresses increase in value, as shown in Fig. C.1. Figure C.1. Example bitmap for a programmable graphical character. Figure C.1. Example bitmap for a programmable graphical character. A web-based character calculator can be used to help determine the list of bytes that need to be written to the CGRAM. Be advised that the calculator in the second reference only generates seven bytes of data and does not specify data for the bottom row of pixels. Writing to CGRAM is a lot like moving the cursor to a particular position on the display and displaying characters at that new location. The steps are shown in Listing C.1. —- ==== Listing C.1. Steps to Program Graphical Characters ===== - Reset RS and R/W pins of the LCD to prepare the LCD to accept instructions. - Set the CG RAM address by sending an instruction byte from 64 to 127 (locations 0-63 in CGRAM). - Switch to DATA MODE by changing the RS pin to one. - Send bytes with the bit patterns for your symbol(s). The LCD controller automatically increments CGRAM addresses, just as it does cursor positions on the display. - To leave CGRAM, switch to COMMAND MODE to set the address counter to a valid display address (e.g., 128, 1st character of 1st line); the clear-screen instruction (byte 1); or the home instruction (byte 2). Now bytes are once again being written to the visible portion of the display. - To see the custom character(s) you have defined, print ASCII codes 0 through 7. —- Back to Unit 2 Go to Lab 3a Go to Lab 3b Go to Unit 4 Part 1