Set of routines to access 16*32character LCD display on WattBob I board.
Dependents: Assignment_2_herpe Final_V1 ass2 ass2 ... more
WattBob_TextLCD.cpp@7:020722c18a8b, 2011-03-24 (annotated)
- Committer:
- jimherd
- Date:
- Thu Mar 24 13:46:06 2011 +0000
- Revision:
- 7:020722c18a8b
- Parent:
- 0:e5b7c70254ac
- Child:
- 8:5a1c4254e4a6
Fixed bug in \locate\ function
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
jimherd | 0:e5b7c70254ac | 1 | /* draft mbed TextLCD |
jimherd | 0:e5b7c70254ac | 2 | * (c) 2007/8, sford |
jimherd | 0:e5b7c70254ac | 3 | * Modified jherd |
jimherd | 0:e5b7c70254ac | 4 | */ |
jimherd | 0:e5b7c70254ac | 5 | |
jimherd | 0:e5b7c70254ac | 6 | #include "WattBob_TextLCD.h" |
jimherd | 0:e5b7c70254ac | 7 | #include "MCP23017.h" |
jimherd | 0:e5b7c70254ac | 8 | |
jimherd | 0:e5b7c70254ac | 9 | #include "mbed.h" |
jimherd | 0:e5b7c70254ac | 10 | |
jimherd | 0:e5b7c70254ac | 11 | /* |
jimherd | 0:e5b7c70254ac | 12 | * Initialisation |
jimherd | 0:e5b7c70254ac | 13 | * ============== |
jimherd | 0:e5b7c70254ac | 14 | * |
jimherd | 0:e5b7c70254ac | 15 | * After attaching the supply voltage/after a reset, the display needs to be brought in to a defined state |
jimherd | 0:e5b7c70254ac | 16 | * |
jimherd | 0:e5b7c70254ac | 17 | * - wait approximately 15 ms so the display is ready to execute commands |
jimherd | 0:e5b7c70254ac | 18 | * - Execute the command 0x30 ("Display Settings") three times (wait 1,64ms after each command, the busy flag cannot be queried now). |
jimherd | 0:e5b7c70254ac | 19 | * - The display is in 8 bit mode, so if you have only connected 4 data pins you should only transmit the higher nibble of each command. |
jimherd | 0:e5b7c70254ac | 20 | * - If you want to use the 4 bit mode, now you can execute the command to switch over to this mode now. |
jimherd | 0:e5b7c70254ac | 21 | * - Execute the "clear display" command |
jimherd | 0:e5b7c70254ac | 22 | * |
jimherd | 0:e5b7c70254ac | 23 | * Timing |
jimherd | 0:e5b7c70254ac | 24 | * ====== |
jimherd | 0:e5b7c70254ac | 25 | * |
jimherd | 0:e5b7c70254ac | 26 | * Nearly all commands transmitted to the display need 40us for execution. |
jimherd | 0:e5b7c70254ac | 27 | * Exceptions are the commands "Clear Display and Reset" and "Set Cursor to Start Position" |
jimherd | 0:e5b7c70254ac | 28 | * These commands need 1.64ms for execution. These timings are valid for all displays working with an |
jimherd | 0:e5b7c70254ac | 29 | * internal clock of 250kHz. But I do not know any displays that use other frequencies. Any time you |
jimherd | 0:e5b7c70254ac | 30 | * can use the busy flag to test if the display is ready to accept the next command. |
jimherd | 0:e5b7c70254ac | 31 | * |
jimherd | 0:e5b7c70254ac | 32 | * _e is kept high apart from calling clock |
jimherd | 0:e5b7c70254ac | 33 | * _rw is kept 0 (write) apart from actions that uses it differently |
jimherd | 0:e5b7c70254ac | 34 | * _rs is set by the data/command writes |
jimherd | 0:e5b7c70254ac | 35 | * |
jimherd | 0:e5b7c70254ac | 36 | * RS = 7 |
jimherd | 0:e5b7c70254ac | 37 | * RW = 6 |
jimherd | 0:e5b7c70254ac | 38 | * E = 5 |
jimherd | 0:e5b7c70254ac | 39 | * Back light = 4 |
jimherd | 0:e5b7c70254ac | 40 | * D4 = 0 |
jimherd | 0:e5b7c70254ac | 41 | * D5 = 1 |
jimherd | 0:e5b7c70254ac | 42 | * D6 = 2 |
jimherd | 0:e5b7c70254ac | 43 | * D7 = 3 |
jimherd | 0:e5b7c70254ac | 44 | */ |
jimherd | 0:e5b7c70254ac | 45 | |
jimherd | 0:e5b7c70254ac | 46 | WattBob_TextLCD::WattBob_TextLCD(MCP23017 *port) { |
jimherd | 0:e5b7c70254ac | 47 | // |
jimherd | 0:e5b7c70254ac | 48 | // Initialise pointer to MCP23017 object |
jimherd | 0:e5b7c70254ac | 49 | // |
jimherd | 0:e5b7c70254ac | 50 | par_port = port; |
jimherd | 0:e5b7c70254ac | 51 | par_port->config(0x0F00, 0x0F00, 0x0F00); |
jimherd | 0:e5b7c70254ac | 52 | |
jimherd | 0:e5b7c70254ac | 53 | _rows = 2; |
jimherd | 0:e5b7c70254ac | 54 | _columns = 16; |
jimherd | 0:e5b7c70254ac | 55 | |
jimherd | 0:e5b7c70254ac | 56 | _rw(0); |
jimherd | 0:e5b7c70254ac | 57 | _e(0); |
jimherd | 0:e5b7c70254ac | 58 | _rs(0); // command mode |
jimherd | 0:e5b7c70254ac | 59 | |
jimherd | 0:e5b7c70254ac | 60 | // Should theoretically wait 15ms, but most things will be powered up pre-reset |
jimherd | 0:e5b7c70254ac | 61 | // so i'll disable that for the minute. If implemented, could wait 15ms post reset |
jimherd | 0:e5b7c70254ac | 62 | // instead |
jimherd | 0:e5b7c70254ac | 63 | // wait(0.015); |
jimherd | 0:e5b7c70254ac | 64 | |
jimherd | 0:e5b7c70254ac | 65 | // send "Display Settings" 3 times (Only top nibble of 0x30 as we've got 4-bit bus) |
jimherd | 0:e5b7c70254ac | 66 | for(int i=0; i<3; i++) { |
jimherd | 0:e5b7c70254ac | 67 | writeNibble(0x3); |
jimherd | 0:e5b7c70254ac | 68 | wait(0.00164); // this command takes 1.64ms, so wait for it |
jimherd | 0:e5b7c70254ac | 69 | } |
jimherd | 0:e5b7c70254ac | 70 | writeNibble(0x2); // 4-bit mode |
jimherd | 0:e5b7c70254ac | 71 | writeCommand(0x28); // Function set 001 BW N F - - |
jimherd | 0:e5b7c70254ac | 72 | writeCommand(0x0C); |
jimherd | 0:e5b7c70254ac | 73 | writeCommand(0x6); // Cursor Direction and Display Shift : 0000 01 CD S (CD 0-left, 1-right S(hift) 0-no, 1-yes |
jimherd | 0:e5b7c70254ac | 74 | |
jimherd | 0:e5b7c70254ac | 75 | cls(); |
jimherd | 0:e5b7c70254ac | 76 | } |
jimherd | 0:e5b7c70254ac | 77 | |
jimherd | 0:e5b7c70254ac | 78 | int WattBob_TextLCD::_putc(int value) { |
jimherd | 0:e5b7c70254ac | 79 | if(value == '\n') { |
jimherd | 0:e5b7c70254ac | 80 | newline(); |
jimherd | 0:e5b7c70254ac | 81 | } else { |
jimherd | 0:e5b7c70254ac | 82 | writeData(value); |
jimherd | 0:e5b7c70254ac | 83 | } |
jimherd | 0:e5b7c70254ac | 84 | return value; |
jimherd | 0:e5b7c70254ac | 85 | } |
jimherd | 0:e5b7c70254ac | 86 | |
jimherd | 0:e5b7c70254ac | 87 | int WattBob_TextLCD::_getc() { |
jimherd | 0:e5b7c70254ac | 88 | return 0; |
jimherd | 0:e5b7c70254ac | 89 | } |
jimherd | 0:e5b7c70254ac | 90 | |
jimherd | 0:e5b7c70254ac | 91 | void WattBob_TextLCD::newline() { |
jimherd | 0:e5b7c70254ac | 92 | _column = 0; |
jimherd | 0:e5b7c70254ac | 93 | _row++; |
jimherd | 0:e5b7c70254ac | 94 | if(_row >= _rows) { |
jimherd | 0:e5b7c70254ac | 95 | _row = 0; |
jimherd | 0:e5b7c70254ac | 96 | } |
jimherd | 0:e5b7c70254ac | 97 | locate(_column, _row); |
jimherd | 0:e5b7c70254ac | 98 | } |
jimherd | 0:e5b7c70254ac | 99 | |
jimherd | 0:e5b7c70254ac | 100 | void WattBob_TextLCD::locate(int row, int column) { |
jimherd | 0:e5b7c70254ac | 101 | if(column < 0 || column >= _columns || row < 0 || row >= _rows) { |
jimherd | 0:e5b7c70254ac | 102 | // error("locate(%d,%d) out of range on %dx%d display", column, row, _columns, _rows); |
jimherd | 0:e5b7c70254ac | 103 | return; |
jimherd | 0:e5b7c70254ac | 104 | } |
jimherd | 0:e5b7c70254ac | 105 | |
jimherd | 0:e5b7c70254ac | 106 | _row = row; |
jimherd | 0:e5b7c70254ac | 107 | _column = column; |
jimherd | 7:020722c18a8b | 108 | int address = 0x80 + (_row * 0x40) + _column; // memory starts at 0x80, and internally it is 40 chars per row (only first 16 used) |
jimherd | 0:e5b7c70254ac | 109 | writeCommand(address); |
jimherd | 0:e5b7c70254ac | 110 | } |
jimherd | 0:e5b7c70254ac | 111 | |
jimherd | 0:e5b7c70254ac | 112 | void WattBob_TextLCD::cls() { |
jimherd | 0:e5b7c70254ac | 113 | writeCommand(0x01); // Clear Display |
jimherd | 0:e5b7c70254ac | 114 | wait(0.00164f); // This command takes 1.64 ms |
jimherd | 0:e5b7c70254ac | 115 | locate(0, 0); |
jimherd | 0:e5b7c70254ac | 116 | } |
jimherd | 0:e5b7c70254ac | 117 | |
jimherd | 0:e5b7c70254ac | 118 | void WattBob_TextLCD::reset() { |
jimherd | 0:e5b7c70254ac | 119 | cls(); |
jimherd | 0:e5b7c70254ac | 120 | } |
jimherd | 0:e5b7c70254ac | 121 | |
jimherd | 0:e5b7c70254ac | 122 | void WattBob_TextLCD::clock() { |
jimherd | 0:e5b7c70254ac | 123 | wait(0.000040f); |
jimherd | 0:e5b7c70254ac | 124 | _e(1); |
jimherd | 0:e5b7c70254ac | 125 | wait(0.000040f); // most instructions take 40us |
jimherd | 0:e5b7c70254ac | 126 | _e(0); |
jimherd | 0:e5b7c70254ac | 127 | } |
jimherd | 0:e5b7c70254ac | 128 | |
jimherd | 0:e5b7c70254ac | 129 | void WattBob_TextLCD::writeNibble(int value) { |
jimherd | 0:e5b7c70254ac | 130 | _d(value); |
jimherd | 0:e5b7c70254ac | 131 | clock(); |
jimherd | 0:e5b7c70254ac | 132 | } |
jimherd | 0:e5b7c70254ac | 133 | |
jimherd | 0:e5b7c70254ac | 134 | void WattBob_TextLCD::writeByte(int value) { |
jimherd | 0:e5b7c70254ac | 135 | writeNibble((value >> 4) & 0x000F); |
jimherd | 0:e5b7c70254ac | 136 | writeNibble((value >> 0) & 0x000F); |
jimherd | 0:e5b7c70254ac | 137 | } |
jimherd | 0:e5b7c70254ac | 138 | |
jimherd | 0:e5b7c70254ac | 139 | void WattBob_TextLCD::writeCommand(int command) { |
jimherd | 0:e5b7c70254ac | 140 | _rs(0); |
jimherd | 0:e5b7c70254ac | 141 | writeByte(command); |
jimherd | 0:e5b7c70254ac | 142 | } |
jimherd | 0:e5b7c70254ac | 143 | |
jimherd | 0:e5b7c70254ac | 144 | void WattBob_TextLCD::writeData(int data) { |
jimherd | 0:e5b7c70254ac | 145 | _rs(1); |
jimherd | 0:e5b7c70254ac | 146 | writeByte(data); |
jimherd | 0:e5b7c70254ac | 147 | _column++; |
jimherd | 0:e5b7c70254ac | 148 | if(_column >= _columns) { |
jimherd | 0:e5b7c70254ac | 149 | newline(); |
jimherd | 0:e5b7c70254ac | 150 | } |
jimherd | 0:e5b7c70254ac | 151 | } |
jimherd | 0:e5b7c70254ac | 152 | |
jimherd | 0:e5b7c70254ac | 153 | void WattBob_TextLCD::_rs(int data) { |
jimherd | 0:e5b7c70254ac | 154 | par_port->write_bit(data, RS_BIT); |
jimherd | 0:e5b7c70254ac | 155 | } |
jimherd | 0:e5b7c70254ac | 156 | |
jimherd | 0:e5b7c70254ac | 157 | void WattBob_TextLCD::_rw(int data) { |
jimherd | 0:e5b7c70254ac | 158 | par_port->write_bit(data, RW_BIT); |
jimherd | 0:e5b7c70254ac | 159 | } |
jimherd | 0:e5b7c70254ac | 160 | |
jimherd | 0:e5b7c70254ac | 161 | void WattBob_TextLCD::_e(int data) { |
jimherd | 0:e5b7c70254ac | 162 | par_port->write_bit(data, E_BIT); |
jimherd | 0:e5b7c70254ac | 163 | } |
jimherd | 0:e5b7c70254ac | 164 | |
jimherd | 0:e5b7c70254ac | 165 | void WattBob_TextLCD::_d(int data) { |
jimherd | 0:e5b7c70254ac | 166 | par_port->write_mask((unsigned short)data, (unsigned short)0x000F); |
jimherd | 0:e5b7c70254ac | 167 | } |