The Mizar32 LCD Display is an add-on hardware module that plugs into all six of the Mizar32 main board's bus connectors. It has a 16-column by 2-line Liquid Crystal Display, where each position can display one of a range of characters, and it has six push buttons: left, right, up, down, select and reset.
The red reset button resets the on-board PIC microcontroller that controls the display, while the five buttons can be read by the main processor over the I2C bus.
The LCD display board is run by a PIC 16F84 microcontroller, which is a low-power processor running a program written by Simplemachines that talks to the Ampire 162B LCD panel, detects button presses and communicates with the main AVR32 processor over the I2C bus.
The LCD panel itself hosts another microprocessor, the SED 1278, which receives commands from the PIC, generates characters for the LCD panel and keeps the display refreshed. It has an internal character memory of 40 characters by two lines, of which 16x2 are shown at any one time on the LCD screen. The SED 1278's program is in ROM and cannot be changed.
I2C bus speed
When talking with the LCD display over I2C, the Mizar32's I2C bus must be set to a speed no faster than 50kHz. If the Mizar32 talks with other I2C devices at speeds up to 100kHz, this will not confuse the LCD display: it is able to recognise its own address (and reject all other addresses) at up to 100kHz but can only process data packets at a maximum of 50kHz.
The LCD display module needs the Mizar32 to be powered from its 7.2 volt DC power jack. If you wish to run it from the Mizar32's USB power supply, you can solder a wire on the underside of the LCD board from pin 1 of the BUS5 connector (near the centre of the board's edge) to pin 2 of the LCD1 connector (near the LEFT button).
I2C command set
The board responds to the 8-bit I2C command bytes 0x7C to 0x7F (7-bit slave addresses 62 and 63):
||Send commands to the LCD|
||Read the LCD RAM address|
||Send data bytes to the LCD|
||Read the push-button switches|
I2C command 7C: Send LCD commands
Physically the LCD display has 2 rows of 16 characters, but internally it has a character memory which holds 40 characters per row and the 16x2 visible display only ever shows a portion of the internal character memory.
Printing past the end of the 40th character of the first row of the character memory passes automatically to the start of the second row and going past the 40th character of the second row continues at the start of the first row. Similarly, when moving the cursor left from the first character of either row moves it to the 40th position of the other row.
Clear display and return home
Command byte 0: Reset the LCD module
For the SED1278, command byte 0 is a no-op. Here, instead, the PIC recognises it as a special case and resets the SED:
- clear screen
- no cursor displayer
- two rows of characters
- 8x5 pixel character font
- cursor moves right when character data are sent; display does not shift
Command byte 1: Clear display
Command byte 1 writes spaces into every position of the character memory, moves the cursor to the first row, first column of the character memory and resets the display shift so that the first characters of each line of the internal character memory are aligned to the first characters of the physical display.
Command byte 2: Return home
Command byte 2 moves the cursor to the first row, first column of the character memory and resets the display shift. It's the same as "clear display" without clearing the contents of the character memory.
Data entry modes
Command byte 4: when printing, move cursor right
After command byte 4, printing a character to the LCD display makes the cursor move one position to the right: if the cursor goes off the right edge of the physical display, it continues to write to the internal character memory but the cursor, and these characters, are not shown on the physical display.
Command byte 5: when printing, shift display right
This is another way to print text backwards, this time keeping the cursor in the same position in the display and shifting the text one place to the right each time a character is printed. If you are in this mode with the cursor at (1,1) and print "
Hello", you'll end up with the
H in the fifth position of the first row and "
olle" in the first four positions of the second, because going off either end of one row of the 40-column character memory always continues at the opposite end of the other line.
Command byte 6: when printing, move cursor left
When command byte 6 has been sent, printing a character makes the cursor move one place to the left, so if you print "Hello", the writing comes out backwards on the display "
olleH" leaving the cursor to the left of the last character. To see this, you would first have to move the cursor to the right of the display, otherwise it would immediately go off the left edge of the display, leaving only an "H" visible and printing the "
olle" at the end of the second line (off the screen).
Command byte 7: when printing, shift display left
After command byte 7, each time a character is sent to the display, the cursor remains in the same physical position and all the displayed characters move left by one place. Another way to see it is that the 16x2 physical display moves one place to the right on the virtual display so that, for example, if it was displaying columns 1-16, it then displays columns 2-17. To see the text you print, you would first have to move the cursor to the right side of the display, otherwise everything you display would immediately be shifted off the left edge of the display, and would only re-appear on the right edge when you had printed another 24 characters (24 because the virtual display is 40 characters wide and the physical one 16 wide).
Turning the display on and off and saying what type of cursor you want displayed are done together.
Command byte 8: turn display off
This turns the display off, showing a blank panel. However, it remembers what data are in the 40x2 character memory, the user-defined characters, the cursor position and which part of the character memory was being displayed on the physical display.
Command byte 12: turn display on with no cursor
If the display was off, it is turned back on, but no cursor will be displayed.
If the display was off, it is turned back on, and at the cursor position a blinking black block will be displayed.
Command byte 14: turn display on with underline cursor
If the display was off, it is turned back on, and at the cursor position, the bottom line of the character cell will be all black.
In this case, you get both the constant underline and the blinking block. I'm not sure why you would want that...
Cursor or display shift
There is another way to shift the visible part of the 40-column memory left or right, and to move the cursor one place left or right.
Command byte 16: Move cursor one place left
This moves the cursor one character place left both in the memory and on the display. If it moves off the visible part of the display, the cursor is not visibile, and it if moves left from column 1, it goes to column 40 of the other line.
Command byte 20: Move cursor one place right
This moves the cursor one character place right both in the memory and on the display. If it moves off the visible part of the display, the cursor is not visibile, and it if moves right from column 40, it goes to column 1 of the other line.
Command byte 24: Shift the display one place left
This changes which part of the virtual display is visible on the physical display. It shifts all the visible characters to the left by one place, revealing a new column of characters from the virtual display at the right edge.
When shifting the display, the cursor remains in the same place in the internal character memory, so on the physical display it is also seen to move one place to the left.
Command byte 28: Shift the display one place right
The reverse effect is obtained with command 28, which moves the displayed characters and cursor one place to the right and reveals two new characters on the left side. Again, the cursor stays with the character that it was sitting on before.
Command bytes 32-63
Bits 4, 8 and 16 of these commands set the display operating mode:
|4||Display font type||5x8||5x11|
|8||Number of display lines||1 line||2 lines|
|16||Interface data length||4 bits||8 bits|
For the Mizar32 display module, you need 5x8, 2 lines, 4 bits, which is the default setting made on power-up.
Command bytes 64-127: Set CG RAM address
If it 64 is set and bit 128 clear, the lowest 6 bits move the cursor from the display to the character-generator RAM. The following data bytes do not display anything on the screen, but instead they say which dots are clear and which black of the eight user-definable characters with codes 0 to 7 (and 8 to 15).
The first user-definable character's definition is in locations 64 to 71, the second from 72 to 79, and so on. Each byte defines one row of the character working from top to bottom, with the five least significant bits defining the five pixels of each row in order 16, 8, 4, 2, 1 from left to right. A "one" bit is displayed black.
For example, to define characters 0 and 1 as left-pointing and right-pointing black triangles:
|*||*||3 = 2 + 1||*||*||24 = 16 + 8|
|*||*||*||7 = 4 + 2 + 1||*||*||*||28 = 16 + 8 + 4|
|*||*||*||*||15 = 8 + 4 + 2 + 1||*||*||*||*||30 = 16 + 8 + 4 + 2|
|*||*||*||7 = 4 + 2 + 1||*||*||*||28 = 16 + 8 + 4|
|*||*||3 = 2 + 1||*||*||24 = 16 + 8|
In eLua, you can do this with the functions:
mizar32.lcd.definechar(0, 1, 3, 7, 15, 7, 3, 1) mizar32.lcd.definechar(1, 16, 24, 28, 30, 28, 24, 16)
and to return to regular character-writing mode, you must issue the following command:
Command bytes 128-255: Set DD RAM address
If the top bit of a command byte is set, the lower 7 bits set the position of the cursor within the data memory, which is where the next character will be stored in the display's character memory (and shown on the screen when the display is shifted so as to show that part of the character memory).
|Codes||Where the cursor moves to|
|128-167||The first row of 40 characters|
|192-231||The second row of 40 characters|
I don't know what happens if you set a DD RAM address of 168-191 or 232-255.
I2C command 7D: Read Address Counter
0x7D reads the current position of the cursor within the character memory and sends it back over the I2C bus.
This is the internal memory address of where the next character will be stored if you send a data byte. The byte that is returned is a value from 0 to 127 that corresponds to lower 7 bits of the codes used in the "Set DD RAM address" command above.
I2C command 7E: Send LCD data bytes
0x7E sends data to the LCD display.
Each data byte you send usually displays one character on the LCD display and moves the cursor right one position.
|Codes||What they display|
|0-7||Eight user-defined characters|
|8-15||The same eight user-defined characters|
|32-126||Standard ASCII characters|
|160-255||Chinese characters and special symbols|
The exception is when you have just sent one of command bytes 64-127, which make the following data bytes set the pixels of a user-definable character (see above, "Set CG RAM address").
0x7F fetches the current state of the LCD module's push-button switches as a byte with some combination of the lower 5 bits set to indicate which buttons are currently held down.
The display can reliably detect whether the Select button is held down and up to two of the other four buttons. If three of the other buttons are held down, the module returns a byte saying that all four are pressed (this is a consequence of the way the buttons are connected on the circuit board to give you five buttons with only four wires).
If you are feeling brave, you can talk to the LCD Display module using the above codes and eLua's
i2c platform module primitives. For example, to display "
Hello}" you would say:
i2c.setup(0, 50000) i2c.start(0) ack = i2c.address(0, 63, i2c.TRANSMITTER) if ack then i2c.write(0, "Hello") end i2c.stop(0)
Simplemachines has added a platform module to eLua,
mizar32.lcd.*(), which does all the I2C magic and special timing for you.
Using this module to achieve the above, you would say: