The iPod controller that I submitted for the mbed challenge

Dependencies:   mbed Motordriver PID

Committer:
networker
Date:
Wed May 04 15:41:13 2011 +0000
Revision:
0:371773dd3dd1
first publication

Who changed what in which revision?

UserRevisionLine numberNew contents of line
networker 0:371773dd3dd1 1 /* mbed TextLCD23017 Library, for a 4-bit LCD based on HD44780
networker 0:371773dd3dd1 2 * Copyright (c) 2007-2010, sford, http://mbed.org
networker 0:371773dd3dd1 3 *
networker 0:371773dd3dd1 4 * Permission is hereby granted, free of charge, to any person obtaining a copy
networker 0:371773dd3dd1 5 * of this software and associated documentation files (the "Software"), to deal
networker 0:371773dd3dd1 6 * in the Software without restriction, including without limitation the rights
networker 0:371773dd3dd1 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
networker 0:371773dd3dd1 8 * copies of the Software, and to permit persons to whom the Software is
networker 0:371773dd3dd1 9 * furnished to do so, subject to the following conditions:
networker 0:371773dd3dd1 10 *
networker 0:371773dd3dd1 11 * The above copyright notice and this permission notice shall be included in
networker 0:371773dd3dd1 12 * all copies or substantial portions of the Software.
networker 0:371773dd3dd1 13 *
networker 0:371773dd3dd1 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
networker 0:371773dd3dd1 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
networker 0:371773dd3dd1 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
networker 0:371773dd3dd1 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
networker 0:371773dd3dd1 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
networker 0:371773dd3dd1 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
networker 0:371773dd3dd1 20 * THE SOFTWARE.
networker 0:371773dd3dd1 21 */
networker 0:371773dd3dd1 22 #include <stdarg.h>
networker 0:371773dd3dd1 23 #include "TextLCD23017.h"
networker 0:371773dd3dd1 24 #include "mbed.h"
networker 0:371773dd3dd1 25
networker 0:371773dd3dd1 26 /**************************************************************
networker 0:371773dd3dd1 27 Port A: databus 8-bit bidir, also used as input for keys (A2-A7)
networker 0:371773dd3dd1 28 IntA wired to mbed pin??
networker 0:371773dd3dd1 29 PortB: B0 out: keys out, set low to read keys on PortA
networker 0:371773dd3dd1 30 B1 in: rot.enc. push button act.L
networker 0:371773dd3dd1 31 B2 out: buzzer
networker 0:371773dd3dd1 32 B3 in: rot.enc. A
networker 0:371773dd3dd1 33 B4 in: rot.enc. B
networker 0:371773dd3dd1 34 B5 out: LCD E (CS\)
networker 0:371773dd3dd1 35 B6 out: LCD R\W (WR\)
networker 0:371773dd3dd1 36 B7 out: LCD RS (A0)
networker 0:371773dd3dd1 37 **************************************************************/
networker 0:371773dd3dd1 38 TextLCD23017::TextLCD23017(MCP23017& intf, LCDType type) : _intf(intf), _type(type) {
networker 0:371773dd3dd1 39 ::printf("creating lcd\n");
networker 0:371773dd3dd1 40 wait(0.015); // Wait 15ms to ensure powered up of LCD
networker 0:371773dd3dd1 41 //init the MCP23017
networker 0:371773dd3dd1 42 intf.direction(PORT_A, PORT_DIR_IN); //input
networker 0:371773dd3dd1 43 intf.direction(PORT_B, INPUTS);// rot enc input
networker 0:371773dd3dd1 44 intf.configurePullUps(PORT_A, PORT_DIR_IN);
networker 0:371773dd3dd1 45 intf.configurePullUps(PORT_B, INPUTS);
networker 0:371773dd3dd1 46 intf.write(PORT_B, 0x00); //enable keys
networker 0:371773dd3dd1 47 //intf.interruptPolarity(ACTIVE_LOW);
networker 0:371773dd3dd1 48 intf.mirrorInterrupts(true);
networker 0:371773dd3dd1 49
networker 0:371773dd3dd1 50 //initialisation according to HD44780 datasheet
networker 0:371773dd3dd1 51 // send "Display Settings" 2 times for 8 bit interface
networker 0:371773dd3dd1 52 writeByte(0x30);
networker 0:371773dd3dd1 53 wait(0.0041); // this command takes 4.1ms, so wait for it
networker 0:371773dd3dd1 54 writeByte(0x30);
networker 0:371773dd3dd1 55
networker 0:371773dd3dd1 56
networker 0:371773dd3dd1 57 writeByte(0x38); // 8-bit mode, 2 lines 8x5 font
networker 0:371773dd3dd1 58 //wait(0.000040f); // most instructions take 40us
networker 0:371773dd3dd1 59 writeByte(0x08); //display off, cursor off
networker 0:371773dd3dd1 60 writeByte(0x01); //clear display
networker 0:371773dd3dd1 61 writeByte(0x06); //increment, no shift
networker 0:371773dd3dd1 62 //from here on busy can be tested
networker 0:371773dd3dd1 63
networker 0:371773dd3dd1 64 writeCommand(0x0F); //display on, cursor on, blink on
networker 0:371773dd3dd1 65 // cls();
networker 0:371773dd3dd1 66 ::printf("lcd created\n");
networker 0:371773dd3dd1 67 }
networker 0:371773dd3dd1 68
networker 0:371773dd3dd1 69 int TextLCD23017::printf (char * format, ...) {
networker 0:371773dd3dd1 70 char buffer[40];
networker 0:371773dd3dd1 71 va_list args;
networker 0:371773dd3dd1 72 va_start (args, format);
networker 0:371773dd3dd1 73 int rv=vsprintf (buffer,format, args);
networker 0:371773dd3dd1 74 // ::printf("printing:'%s'\n", buffer);
networker 0:371773dd3dd1 75 writeString (buffer);
networker 0:371773dd3dd1 76 va_end (args);
networker 0:371773dd3dd1 77 return rv;
networker 0:371773dd3dd1 78 }
networker 0:371773dd3dd1 79
networker 0:371773dd3dd1 80 //busy not used, i2c is slow enough
networker 0:371773dd3dd1 81 bool TextLCD23017::busy() {//assume PORT_A is input, PORT_A intr disabled, takes minimum 10bytes ~1ms
networker 0:371773dd3dd1 82 //setup and hold of RS-E are not met!
networker 0:371773dd3dd1 83 _intf.write(PORT_B, RW|E|KEYS); //read R=1, E=1, disable keys
networker 0:371773dd3dd1 84 _ar = _intf.read(PORT_A);
networker 0:371773dd3dd1 85 _intf.write(PORT_B, KEYS); //read R=0, E=0
networker 0:371773dd3dd1 86 return (_ar & 0x80) ;//return with keys disabled
networker 0:371773dd3dd1 87 }
networker 0:371773dd3dd1 88
networker 0:371773dd3dd1 89 void TextLCD23017::character(int column, int row, int c) {
networker 0:371773dd3dd1 90 int a = address(column, row);
networker 0:371773dd3dd1 91 writeCommand(a);
networker 0:371773dd3dd1 92 writeData(c);
networker 0:371773dd3dd1 93 }
networker 0:371773dd3dd1 94
networker 0:371773dd3dd1 95 void TextLCD23017::cls() {
networker 0:371773dd3dd1 96 writeCommand(0x01); // cls, and set cursor to 0
networker 0:371773dd3dd1 97 wait(0.00164f); // This command takes 1.64 ms
networker 0:371773dd3dd1 98 locate(0, 0);
networker 0:371773dd3dd1 99 }
networker 0:371773dd3dd1 100
networker 0:371773dd3dd1 101 void TextLCD23017::locate(int column, int row) {
networker 0:371773dd3dd1 102 _column = column;
networker 0:371773dd3dd1 103 _row = row;
networker 0:371773dd3dd1 104 }
networker 0:371773dd3dd1 105
networker 0:371773dd3dd1 106 int TextLCD23017::_putc(int value) {
networker 0:371773dd3dd1 107 if (value == '\n') {
networker 0:371773dd3dd1 108 _column = 0;
networker 0:371773dd3dd1 109 _row++;
networker 0:371773dd3dd1 110 if (_row >= rows()) {
networker 0:371773dd3dd1 111 _row = 0;
networker 0:371773dd3dd1 112 }
networker 0:371773dd3dd1 113 } else {
networker 0:371773dd3dd1 114 character(_column, _row, value);
networker 0:371773dd3dd1 115 _column++;
networker 0:371773dd3dd1 116 if (_column >= columns()) {
networker 0:371773dd3dd1 117 _column = 0;
networker 0:371773dd3dd1 118 _row++;
networker 0:371773dd3dd1 119 if (_row >= rows()) {
networker 0:371773dd3dd1 120 _row = 0;
networker 0:371773dd3dd1 121 }
networker 0:371773dd3dd1 122 }
networker 0:371773dd3dd1 123 }
networker 0:371773dd3dd1 124 return value;
networker 0:371773dd3dd1 125 }
networker 0:371773dd3dd1 126
networker 0:371773dd3dd1 127 int TextLCD23017::_getc() {
networker 0:371773dd3dd1 128 return -1;
networker 0:371773dd3dd1 129 }
networker 0:371773dd3dd1 130
networker 0:371773dd3dd1 131 void TextLCD23017::writeByte(int value) {//5 transactions of 3 bytes ~150bits ~1.5ms
networker 0:371773dd3dd1 132 _intf.direction(PORT_A, PORT_DIR_OUT); //set to output
networker 0:371773dd3dd1 133 _intf.write(PORT_A, value);//put value on data bus
networker 0:371773dd3dd1 134 _intf.write(PORT_B, E|KEYS);//write instruction register, E=1
networker 0:371773dd3dd1 135 _intf.write(PORT_B, KEYS);//E returns to 0
networker 0:371773dd3dd1 136 _intf.direction(PORT_A, PORT_DIR_IN); //set to input
networker 0:371773dd3dd1 137 }
networker 0:371773dd3dd1 138
networker 0:371773dd3dd1 139 void TextLCD23017::writeCommand(int command) {//3 transactions 3 bytes ~0.9ms + busy + writeByte = 3.4ms
networker 0:371773dd3dd1 140 // while (busy()) /*wait*/ ;
networker 0:371773dd3dd1 141 writeByte(command);
networker 0:371773dd3dd1 142 _intf.write(PORT_B, 0);//enable keys
networker 0:371773dd3dd1 143 }
networker 0:371773dd3dd1 144
networker 0:371773dd3dd1 145 void TextLCD23017::writeData(int data) {
networker 0:371773dd3dd1 146 // while (busy()) /*wait*/ ;
networker 0:371773dd3dd1 147 _intf.direction(PORT_A, PORT_DIR_OUT); //set to output
networker 0:371773dd3dd1 148 _intf.write(PORT_A, data);//put data on data bus
networker 0:371773dd3dd1 149 _intf.write(PORT_B, RS|KEYS);//setup RS
networker 0:371773dd3dd1 150 _intf.write(PORT_B, E|RS|KEYS);//write data register, E=1, RS=1
networker 0:371773dd3dd1 151 _intf.write(PORT_B, RS|KEYS);//E returns to 0
networker 0:371773dd3dd1 152 _intf.direction(PORT_A, PORT_DIR_IN); //set to input
networker 0:371773dd3dd1 153 _intf.write(PORT_B, 0);//enable keys
networker 0:371773dd3dd1 154 }
networker 0:371773dd3dd1 155
networker 0:371773dd3dd1 156 void TextLCD23017::writeString(char *s) {//convert a string into LCD commands
networker 0:371773dd3dd1 157 char buffer[240];//size must be > 4*strlen(s) + 7
networker 0:371773dd3dd1 158 char *p = strtok(s,"\n");
networker 0:371773dd3dd1 159 _intf.direction(PORT_A, PORT_DIR_OUT); //set to output
networker 0:371773dd3dd1 160 //assume RS=0, E=0, R/W = 0
networker 0:371773dd3dd1 161 while (p) {
networker 0:371773dd3dd1 162 // ::printf("section:'%s'\n", p);
networker 0:371773dd3dd1 163 int i = 0;
networker 0:371773dd3dd1 164 if (p != s) {//don't do this the first time (not a newline)
networker 0:371773dd3dd1 165 _column = 0;
networker 0:371773dd3dd1 166 if (++_row >= rows()) _row = 0;
networker 0:371773dd3dd1 167 }
networker 0:371773dd3dd1 168 buffer[i++] = E|KEYS;//B, clock RS and RW
networker 0:371773dd3dd1 169 buffer[i++] = address(_column, _row);//A, this data is used
networker 0:371773dd3dd1 170 buffer[i++] = KEYS;//B, clock data
networker 0:371773dd3dd1 171 buffer[i++] = address(_column, _row);//A, dummy
networker 0:371773dd3dd1 172 buffer[i++] = RS|KEYS;//B, setup RS
networker 0:371773dd3dd1 173 for (int j = 0; j < strlen(p) && i<sizeof(buffer)-4; j++) {
networker 0:371773dd3dd1 174 buffer[i++] = p[j];//A, dummy
networker 0:371773dd3dd1 175 buffer[i++] = E|RS|KEYS;//B, clock RS and RW
networker 0:371773dd3dd1 176 buffer[i++] = p[j];//A, this data is used
networker 0:371773dd3dd1 177 buffer[i++] = RS|KEYS;//B, clock data
networker 0:371773dd3dd1 178 if (++_column >= columns()) {
networker 0:371773dd3dd1 179 _column = 0;
networker 0:371773dd3dd1 180 if (++_row >= rows()) _row = 0;
networker 0:371773dd3dd1 181 }
networker 0:371773dd3dd1 182 }//RS=1, E=0, RW=0
networker 0:371773dd3dd1 183 p = strtok(0, "\n");
networker 0:371773dd3dd1 184 buffer[i++] = 0;//A, dummy
networker 0:371773dd3dd1 185 buffer[i++] = (p!=0) ? KEYS : 0; //B, release RS
networker 0:371773dd3dd1 186 _intf.write(PORT_B, buffer, i, p != 0);//start with B, send all substrings as a single transaction
networker 0:371773dd3dd1 187 }
networker 0:371773dd3dd1 188 _intf.direction(PORT_A, PORT_DIR_IN); //set to input
networker 0:371773dd3dd1 189 }
networker 0:371773dd3dd1 190
networker 0:371773dd3dd1 191 int TextLCD23017::address(int column, int row) {
networker 0:371773dd3dd1 192 switch (_type) {
networker 0:371773dd3dd1 193 case LCD20x4:
networker 0:371773dd3dd1 194 switch (row) {
networker 0:371773dd3dd1 195 case 0:
networker 0:371773dd3dd1 196 return 0x80 + column;
networker 0:371773dd3dd1 197 case 1:
networker 0:371773dd3dd1 198 return 0xc0 + column;
networker 0:371773dd3dd1 199 case 2:
networker 0:371773dd3dd1 200 return 0x94 + column;
networker 0:371773dd3dd1 201 case 3:
networker 0:371773dd3dd1 202 return 0xd4 + column;
networker 0:371773dd3dd1 203 }
networker 0:371773dd3dd1 204 case LCD16x2B:
networker 0:371773dd3dd1 205 return 0x80 + (row * 40) + column;
networker 0:371773dd3dd1 206 case LCD16x2:
networker 0:371773dd3dd1 207 case LCD20x2:
networker 0:371773dd3dd1 208 default:
networker 0:371773dd3dd1 209 return 0x80 + (row * 0x40) + column;
networker 0:371773dd3dd1 210 }
networker 0:371773dd3dd1 211 }
networker 0:371773dd3dd1 212
networker 0:371773dd3dd1 213 int TextLCD23017::columns() {
networker 0:371773dd3dd1 214 switch (_type) {
networker 0:371773dd3dd1 215 case LCD20x4:
networker 0:371773dd3dd1 216 case LCD20x2:
networker 0:371773dd3dd1 217 return 20;
networker 0:371773dd3dd1 218 case LCD16x2:
networker 0:371773dd3dd1 219 case LCD16x2B:
networker 0:371773dd3dd1 220 default:
networker 0:371773dd3dd1 221 return 16;
networker 0:371773dd3dd1 222 }
networker 0:371773dd3dd1 223 }
networker 0:371773dd3dd1 224
networker 0:371773dd3dd1 225 int TextLCD23017::rows() {
networker 0:371773dd3dd1 226 switch (_type) {
networker 0:371773dd3dd1 227 case LCD20x4:
networker 0:371773dd3dd1 228 return 4;
networker 0:371773dd3dd1 229 case LCD16x2:
networker 0:371773dd3dd1 230 case LCD16x2B:
networker 0:371773dd3dd1 231 case LCD20x2:
networker 0:371773dd3dd1 232 default:
networker 0:371773dd3dd1 233 return 2;
networker 0:371773dd3dd1 234 }
networker 0:371773dd3dd1 235 }