This shows you the differences between two versions of the page.
arduino:metp0000_driver_library [2019/01/16 09:54] tony |
arduino:metp0000_driver_library [2023/03/12 22:01] (current) tony [METP0000 Library] |
||
---|---|---|---|
Line 33: | Line 33: | ||
===== Hardware description ===== | ===== Hardware description ===== | ||
- | The controller consists of a single NEC D7225GB ({{:electronic:datasheet:nec:upd7225.pdf|μPD7225}}) chip, with a Schmitt trigger inverter input buffer ({{http://xgistor-echo.scorchingbay.nz/files/Electronics/datasheets/74HC14.pdf|74HC14}}), another inverter ({{http://www.ti.com/lit/ds/symlink/sn74hc05.pdf|74HC05}}) and an 8-bit parallel-in/serial out shift register ({{http://xgistor-echo.scorchingbay.nz/files/Electronics/datasheets/74HC165.pdf|74HC165}}). The inverters mean that all the control signals to the μPD7225 are inverted, but this is easily accommodated in software. The control lines are brought out on an 8 pin RJ45 style connector (as used for twisted pair Ethernet). The signals are are "Busy", "Reset", "SI" (serial input), "SCLK" (serial clock), "CS" (chip select) and "C/D" (control/data). | + | The controller consists of a single NEC D7225GB ({{:electronic:datasheet:nec:upd7225.pdf|μPD7225}}) chip, with a Schmitt trigger inverter input buffer ({{http://xgistor-echo.scorchingbay.nz/files/Electronics/datasheets/74HC14.pdf|74HC14}}), another inverter ({{http://www.ti.com/lit/ds/symlink/sn74hc05.pdf|74HC05}}) and an 8-bit parallel-in/serial-out shift register ({{http://xgistor-echo.scorchingbay.nz/files/Electronics/datasheets/74HC165.pdf|74HC165}}). The inverters mean that all the control signals to the μPD7225 are inverted, but this is easily accommodated in software. The control lines are brought out on an 8 pin RJ45 style connector (as used for twisted-pair Ethernet). The signals are are "Busy", "Reset", "SI" (serial input), "SCLK" (serial clock), "CS" (chip select) and "C/D" (control/data). |
Initially I interfaced all the control lines, but realised that I didn't need to use the Reset or the C/D line. Reset could be wired to do a reset at power on, and C/D could be tied low which would hold the chip in command receipt state continually. The other two pins are +5V and Ground. | Initially I interfaced all the control lines, but realised that I didn't need to use the Reset or the C/D line. Reset could be wired to do a reset at power on, and C/D could be tied low which would hold the chip in command receipt state continually. The other two pins are +5V and Ground. | ||
Line 52: | Line 52: | ||
It took me a while to realise that the inbuilt segment decoder on the μPD7225 chip wasn't really much use. The 7-segment decoder couldn't drive all nine segments and an examination of the board revealed that the COM3 output wasn't connected so the 14-segment decoder wasn't being used either. ((It is conceivable that the 14-segment decoder was used, but COM3 was ignored, I haven't checked out this possibility.))\\ | It took me a while to realise that the inbuilt segment decoder on the μPD7225 chip wasn't really much use. The 7-segment decoder couldn't drive all nine segments and an examination of the board revealed that the COM3 output wasn't connected so the 14-segment decoder wasn't being used either. ((It is conceivable that the 14-segment decoder was used, but COM3 was ignored, I haven't checked out this possibility.))\\ | ||
\\ | \\ | ||
- | So it appeared that the only way to address all the segments of each character was to use the command "write-immediate-data", to write directly into the display memory - three writes of 3 bit words (n to n+2 on the segment layout diagram). Hence my driver does not need to do any "data" writes, everything is a "command" write, the "C/D" control line is not needed.\\ | + | So it appeared that the only way to address all the segments of each character was to use the command "write-immediate-data", to write directly into the display memory - three writes of 3-bit words (n to n+2 on the segment layout diagram). Hence my driver does not need to do any "data" writes, everything is a "command" write, the "C/D" control line is not needed.\\ |
\\ | \\ | ||
- | Details of the module's controller configuration choices : R1 across the cl1/cl2 clock generation pins is 200kΩ - giving nominally an about 120kHz clock. The resistor ladder wired across the Vlc1,2,3 pins is for 1/3 bias. COM3 appears to be unconnected, which implies a divide by 3 time division type of LCD (using COM0,1,2). | + | Details of the module's controller configuration choices : R1 across the cl1/cl2 clock generation pins is 200kΩ - giving nominally an about 120kHz clock. The resistor ladder wired across the Vlc1,2,3 pins is for 1/3 bias. COM3 appears to be unconnected, which implies a divide by 3 time-division type of LCD (using COM0,1,2). |
- | Testing was done with mode byte set to 0x48 (= 1/3 bias method, divide-by-3 time division drive , and a frequency division ratio of 1/2^7 (frame frequency=fCL /(2^7 × 3)).\\ | + | Testing was done with mode byte set to 0x48 (= 1/3 bias method, divide-by-3 time-division drive , and a frequency division ratio of 1/2^7 (frame frequency=fCL /(2^7 × 3)).\\ |
\\ | \\ | ||
\\ | \\ | ||
Line 68: | Line 68: | ||
There is no contrast adjustment on this module. | There is no contrast adjustment on this module. | ||
- | ===== METP0000 Library ===== | + | ===== METP0000 library ===== |
- | As mentioned earlier the library is based on a standard Arduino LiquidCrystal.cpp LCD library. I wrote a version (v1.30) with a "write()" function suitable for using with the standard <print.h> routines. This worked fine, but didn't allow for controlling the decimal point - it was unable to set the decimal point as part of a digit. Instead it had to display a blank digit with a decimal point set in the corner. Besides looking strange, that wasted a whole digit space just to display a decimal point, and we don't have a lot of digits to play with. | + | As mentioned earlier the library is based on a standard Arduino LiquidCrystal.cpp LCD library. I wrote a version (v1.30) with a "write()" function suitable for use with the standard <print.h> routines. This worked fine, but didn't allow for controlling the decimal point - it was unable to set the decimal point as part of a digit. Instead it had to display a blank digit with a decimal point set in the corner. Besides looking strange, that wasted a whole digit space just to display a decimal point, and we don't have a lot of digits to play with. |
==== Character Set ==== | ==== Character Set ==== | ||
- | Because driving the 9 segments necessitates bypassing the 7 segment decoder, we are free to create whatever character shapes we wish out of the available segments. To simplify development I used a 16bit word to define each character - 3 nybbles containing 3bits each, plus a fourth nybble that I occasionally used to specify the digit position (as not all digit positions are exactly the same). If I continue to develop this driver, I might truncate this to 8bits per digit, and handle the single bits for the decimal point or comma separately. I initially hand crafted a table of 9 bit alpha-numeric character patterns based on other peoples 7-segment character fonts. I then came across Jose Pino's XLS spreadsheet ((http://www.josepino.com/microcontroller/7-segment-ascii)), which I modified for the 9 segments and odd coding required for this display. In my version the results are shown as a 3 digit number suitable to use as the hex character definition in my driver.\\ | + | Because driving the 9 segments necessitates bypassing the 7 segment decoder, we are free to create whatever character shapes we wish out of the available segments. To simplify development I used a 16bit word to define each character - 3 nybbles containing 3bits each, plus a fourth nybble that I occasionally used to specify the digit position (as not all digit positions are exactly the same). If I continue to develop this driver, I might truncate this to 8bits per digit, and handle the single bits for the decimal point or comma separately. I initially hand crafted a table of 9-bit alpha-numeric character patterns based on other peoples 7-segment character fonts. I then came across Jose Pino's XLS spreadsheet ((http://www.josepino.com/microcontroller/7-segment-ascii)), which I modified for the 9 segments and odd coding required for this display. In my version the results are shown as a 3 digit number suitable to use as the hex character definition in my driver.\\ |
{{ :arduino:metp0000:metp0000 character_set.png?600 |7 Segment character set v1.1.}} | {{ :arduino:metp0000:metp0000 character_set.png?600 |7 Segment character set v1.1.}} | ||
{{:arduino:metp0000:metp0000_7seg_design.xls|7 Segment design spreadsheet in Excel format}}, for designing segment layout.\\ | {{:arduino:metp0000:metp0000_7seg_design.xls|7 Segment design spreadsheet in Excel format}}, for designing segment layout.\\ | ||
Line 132: | Line 132: | ||
In normal operation the μPD7225 would be configured to use the segment decoder, so a display sequence would consist of asserting Chip select (CS), asserting Command/Data (CD) for a command, writing the positioning the data pointer (cursor) command, asserting C/D for data, writing digit codes to the LCD, and de-asserting CS. The digit codes are 8bits, the MSB selecting between the 7 and 14 segment decoders, and then 4 or 7 bits are data for the decoder. For the 7 segment decoder data values from 0 to 9 generate the symbols '0' through '9' on the display. Internally the decoder just stores a sequence of bits into the display memory, corresponding to the segments to be displayed. So after positioning the cursor 6 writes are needed to fill the 6 digit display. | In normal operation the μPD7225 would be configured to use the segment decoder, so a display sequence would consist of asserting Chip select (CS), asserting Command/Data (CD) for a command, writing the positioning the data pointer (cursor) command, asserting C/D for data, writing digit codes to the LCD, and de-asserting CS. The digit codes are 8bits, the MSB selecting between the 7 and 14 segment decoders, and then 4 or 7 bits are data for the decoder. For the 7 segment decoder data values from 0 to 9 generate the symbols '0' through '9' on the display. Internally the decoder just stores a sequence of bits into the display memory, corresponding to the segments to be displayed. So after positioning the cursor 6 writes are needed to fill the 6 digit display. | ||
- | If the decoder is not used, you instead write bits corresponding to the desired segment patterns directly to the display memory. And here the sequence is slightly different as the sets of 3 data bits specifying each segment are part of write-immediate-data-commands (or to look at it another way there are lots of commands, each one specifying a different part of the segment pattern). A sequence of three commands defines the segments displayed at one digit location. So after positioning the cursor 18 writes are need to fill the 6 digit display. But all of these writes are 'commands', no 'data' writes are needed. | + | If the decoder is not used, you instead write bits corresponding to the desired segment patterns directly to the display memory. And here the sequence is slightly different as the sets of 3 data bits specifying each segment are part of write-immediate-data-commands (or to look at it another way there are lots of commands, each one specifying a different part of the segment pattern). A sequence of three commands defines the segments displayed at one digit location. So after positioning the cursor 18 writes are needed to fill the 6 digit display. But all of these writes are 'commands', no 'data' writes are needed. |
==== Standard LiquidCrystal library functions implemented ==== | ==== Standard LiquidCrystal library functions implemented ==== | ||
Line 197: | Line 197: | ||
All the print() functions are re-inventions of the wheel necessitated by wanting to handle the decimal point segment as an extra character space. That is, when a decimal point or full-stop (period) is printed by these routines, they turn on the appropriate decimal point segment instead of somehow using the whole digit position just for that character. This allows us to print what would otherwise be 7 character strings like ''"1.23456"'', rather than ''"1 .2345"''. This even extends to printing strings like ''"8.8.8.8.8.8"''. But we can't print a leading ''"."'' or a trailing ''"."'' without having a blank digit at that first or last location - eg ''" .12345"'' or ''"12345. "'' . This is because there physically isn't a leading or trailing decimal point as part of the display segments.\\ | All the print() functions are re-inventions of the wheel necessitated by wanting to handle the decimal point segment as an extra character space. That is, when a decimal point or full-stop (period) is printed by these routines, they turn on the appropriate decimal point segment instead of somehow using the whole digit position just for that character. This allows us to print what would otherwise be 7 character strings like ''"1.23456"'', rather than ''"1 .2345"''. This even extends to printing strings like ''"8.8.8.8.8.8"''. But we can't print a leading ''"."'' or a trailing ''"."'' without having a blank digit at that first or last location - eg ''" .12345"'' or ''"12345. "'' . This is because there physically isn't a leading or trailing decimal point as part of the display segments.\\ | ||
- | We could conceivably extent this to the "comma" segment, or accommodate Europeans languages that use a comma ''","'' as a decimal signifier rather than ''"."'' . The comma segment is really just a 'tail' below the decimal point, and it looks better to display the decimal point and comma tail segments to get a good looking comma. But handling commas presents two problems. First the comma segments are on the opposite side of each digit (see single digit image in the "Hardware description" section), complicating the logic, especially if you want to display the decimal point simultaneously with the comma to form a more complete looking comma. The second problem is that I use the comma as a small corner "tick" in my alphanumeric characters to hint that this is an alternate use of the same symbol. | + | We could conceivably extent this to the "comma" segment, or accommodate European languages that use a comma ''","'' as a decimal signifier rather than ''"."'' . The comma segment is really just a 'tail' below the decimal point, and it looks better to display the decimal point and comma tail segments to get a good looking comma. But handling commas presents two problems. First, the comma segments are on the opposite side of each digit (see single-digit image in the "Hardware description" section), complicating the logic, especially if you want to display the decimal point simultaneously with the comma to form a more complete looking comma. The second problem is that I use the comma as a small corner "tick" in my alphanumeric characters to hint that this is an alternate use of the same symbol. |
I am still contemplating whether it is sensible to drive such a short display as though it is a normal character output device, it might be more useful to have output routines that update the whole display each time, rather than printing a partial line, and keeping track of the cursor. | I am still contemplating whether it is sensible to drive such a short display as though it is a normal character output device, it might be more useful to have output routines that update the whole display each time, rather than printing a partial line, and keeping track of the cursor. | ||
Line 239: | Line 239: | ||
* [[https://github.com/adafruit/Adafruit-RGB-LCD-Shield-Library/blob/master/Adafruit_RGBLCDShield.cpp|Adafruit RGB LCD Shield-Library | * [[https://github.com/adafruit/Adafruit-RGB-LCD-Shield-Library/blob/master/Adafruit_RGBLCDShield.cpp|Adafruit RGB LCD Shield-Library | ||
]]. | ]]. | ||
+ | * [[:arduino:ks0073 driver library|KS0073 SPI LCD]], LCD display panel Arduino driver | ||
* [[:arduino:mx300 driver library|Canon MX300]], Canon MX300/310 printer LCD display panel Arduino driver. | * [[:arduino:mx300 driver library|Canon MX300]], Canon MX300/310 printer LCD display panel Arduino driver. | ||
* [[:arduino:uPD7228 driver library|NEC µPD7228]] and μPD16434 LCD display panels Arduino driver | * [[:arduino:uPD7228 driver library|NEC µPD7228]] and μPD16434 LCD display panels Arduino driver |