Fork of Smoothie to port to mbed non-LPC targets.
Fork of Smoothie by
I2CLCD.h
00001 /* 00002 This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl). 00003 Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 00004 Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 00005 You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 00006 */ 00007 #ifndef I2CLCD_H 00008 #define I2CLCD_H 00009 00010 #include "LcdBase.h" 00011 00012 #include "I2C.h" // mbed.h lib 00013 #include "wait_api.h" // mbed.h lib 00014 #include "libs/Config.h" 00015 00016 using namespace std; 00017 #include <vector> 00018 #include <string> 00019 #include <cstdio> 00020 #include <cstdarg> 00021 00022 // commands 00023 #define LCD_CLEARDISPLAY 0x01 00024 #define LCD_RETURNHOME 0x02 00025 #define LCD_ENTRYMODESET 0x04 00026 #define LCD_DISPLAYCONTROL 0x08 00027 #define LCD_CURSORSHIFT 0x10 00028 #define LCD_FUNCTIONSET 0x20 00029 #define LCD_SETCGRAMADDR 0x40 00030 #define LCD_SETDDRAMADDR 0x80 00031 00032 // flags for display entry mode 00033 #define LCD_ENTRYRIGHT 0x00 00034 #define LCD_ENTRYLEFT 0x02 00035 #define LCD_ENTRYSHIFTINCREMENT 0x01 00036 #define LCD_ENTRYSHIFTDECREMENT 0x00 00037 00038 // flags for display on/off control 00039 #define LCD_DISPLAYON 0x04 00040 #define LCD_DISPLAYOFF 0x00 00041 #define LCD_CURSORON 0x02 00042 #define LCD_CURSOROFF 0x00 00043 #define LCD_BLINKON 0x01 00044 #define LCD_BLINKOFF 0x00 00045 00046 // flags for display/cursor shift 00047 #define LCD_DISPLAYMOVE 0x08 00048 #define LCD_CURSORMOVE 0x00 00049 #define LCD_MOVERIGHT 0x04 00050 #define LCD_MOVELEFT 0x00 00051 00052 // flags for function set 00053 #define LCD_8BITMODE 0x10 00054 #define LCD_4BITMODE 0x00 00055 #define LCD_2LINE 0x08 00056 #define LCD_1LINE 0x00 00057 #define LCD_5x10DOTS 0x04 00058 #define LCD_5x8DOTS 0x00 00059 00060 // flags for backlight control 00061 #define LCD_BACKLIGHT 0x08 00062 #define LCD_NOBACKLIGHT 0x00 00063 00064 #define En 1<<2 // Enable bit 00065 #define Rw 1<<1 // Read/Write bit 00066 #define Rs 1<<0 // Register select bit 00067 00068 // config settings 00069 #define panel_checksum CHECKSUM("panel") 00070 #define encoder_a_pin_checksum CHECKSUM("encoder_a_pin") 00071 #define encoder_b_pin_checksum CHECKSUM("encoder_b_pin") 00072 #define up_button_pin_checksum CHECKSUM("up_button_pin") 00073 #define down_button_pin_checksum CHECKSUM("down_button_pin") 00074 #define click_button_pin_checksum CHECKSUM("click_button_pin") 00075 00076 class I2CLCD : public LcdBase { 00077 public: 00078 I2CLCD() { 00079 // Default values 00080 this->i2c_address = 0x27; 00081 this->backlightval = 0x00; 00082 this->displaycontrol = 0x00; 00083 this->displayfunction = 0x00; 00084 this->displaymode = 0x00; 00085 00086 // I2C com 00087 this->i2c = new mbed::I2C(P0_27, P0_28); 00088 00089 // configure the pins to use 00090 this->encoder_a_pin.from_string(THEKERNEL->config->value( panel_checksum, encoder_a_pin_checksum)->by_default("nc")->as_string())->as_input()->pull_up(); 00091 this->encoder_b_pin.from_string(THEKERNEL->config->value( panel_checksum, encoder_b_pin_checksum)->by_default("nc")->as_string())->as_input()->pull_up(); 00092 this->click_pin.from_string(THEKERNEL->config->value( panel_checksum, click_button_pin_checksum )->by_default("nc")->as_string())->as_input()->pull_up(); 00093 this->up_pin.from_string(THEKERNEL->config->value( panel_checksum, up_button_pin_checksum)->by_default("nc")->as_string())->as_input()->pull_up(); 00094 this->down_pin.from_string(THEKERNEL->config->value( panel_checksum, down_button_pin_checksum)->by_default("nc")->as_string())->as_input()->pull_up(); 00095 00096 } 00097 virtual ~I2CLCD() { 00098 delete this->i2c; 00099 } 00100 00101 int getEncoderResolution() { 00102 return 1; 00103 } 00104 00105 uint8_t readButtons() { 00106 uint8_t state= 0; 00107 state |= (this->click_pin.get() ? BUTTON_SELECT : 0); 00108 state |= (this->up_pin.get() ? BUTTON_UP : 0); 00109 state |= (this->down_pin.get() ? BUTTON_DOWN : 0); 00110 return state; 00111 } 00112 00113 int readEncoderDelta() { 00114 static int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0}; 00115 static uint8_t old_AB = 0; 00116 old_AB <<= 2; //remember previous state 00117 old_AB |= ( this->encoder_a_pin.get() + ( this->encoder_b_pin.get() * 2 ) ); //add current state 00118 return enc_states[(old_AB&0x0f)]; 00119 } 00120 00121 void expanderWrite(char data){ 00122 this->i2c->start(); 00123 this->i2c->write(this->i2c_address<<1); 00124 this->i2c->write((char)((char)data | (char)backlightval)); 00125 this->i2c->stop(); 00126 } 00127 00128 void pulseEnable(char data){ 00129 this->expanderWrite(data | En); // En high 00130 wait_us(1); // enable pulse must be >450ns 00131 this->expanderWrite(data & ~En); // En low 00132 wait_us(50); // commands need > 37us to settle 00133 } 00134 00135 void write4bits(char value) { 00136 this->expanderWrite(value); 00137 this->pulseEnable(value); 00138 } 00139 00140 void send(char value, char mode) { 00141 uint8_t highnib=value&0xf0; 00142 uint8_t lownib=(value<<4)&0xf0; 00143 this->write4bits((highnib)|mode); 00144 this->write4bits((lownib)|mode); 00145 } 00146 00147 void command(char value) { 00148 this->send(value, 0); 00149 } 00150 00151 void write(const char* line, int len) { 00152 for (int i = 0; i < len; ++i) { 00153 this->send(*line++, Rs); 00154 } 00155 } 00156 00157 void home(){ 00158 this->command(LCD_RETURNHOME); // set cursor position to zero 00159 wait_us(2000); // this command takes a long time! 00160 } 00161 00162 void clear(){ 00163 this->command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero 00164 wait_us(2000); // this command takes a long time! 00165 } 00166 00167 void display() { 00168 this->displaycontrol |= LCD_DISPLAYON; 00169 this->command(LCD_DISPLAYCONTROL | this->displaycontrol); 00170 } 00171 00172 void setCursor(uint8_t col, uint8_t row){ 00173 int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 }; 00174 if ( row > 4 ) { 00175 row = 4-1; // we count rows starting w/0 00176 } 00177 this->command(LCD_SETDDRAMADDR | (col + row_offsets[row])); 00178 } 00179 00180 void init(){ 00181 // Setup 00182 this->displayfunction = LCD_4BITMODE | LCD_2LINE | LCD_5x8DOTS; 00183 this->backlightval = LCD_NOBACKLIGHT; 00184 00185 // Now we pull both RS and R/W low to begin commands 00186 wait_ms(50); 00187 this->expanderWrite(this->backlightval); 00188 wait_ms(1000); 00189 00190 // we start in 8bit mode, try to set 4 bit mode 00191 for( char i=0;i<3;i++){ 00192 this->write4bits(0x03 << 4); 00193 wait_us(4500); 00194 } 00195 00196 // finally, set to 4-bit interface 00197 this->write4bits(0x02 << 4); 00198 00199 // set # lines, font size, etc. 00200 this->command(LCD_FUNCTIONSET | this->displayfunction); 00201 00202 // turn the display on with no cursor or blinking default 00203 this->displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; 00204 this->display(); 00205 00206 // clear it off 00207 this->clear(); 00208 00209 // Initialize to default text direction (for roman languages) 00210 this->displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; 00211 00212 // set the entry mode 00213 this->command(LCD_ENTRYMODESET | displaymode); 00214 00215 this->home(); 00216 wait(0.1); 00217 00218 this->backlightval=LCD_BACKLIGHT; 00219 expanderWrite(0); 00220 00221 } 00222 00223 private: 00224 char displaymode; 00225 char displayfunction; 00226 char displaycontrol; 00227 char i2c_address; 00228 char backlightval; 00229 00230 mbed::I2C* i2c; 00231 00232 Pin encoder_a_pin; 00233 Pin encoder_b_pin; 00234 Pin click_pin; 00235 Pin up_pin; 00236 Pin down_pin; 00237 }; 00238 00239 00240 #endif
Generated on Tue Jul 12 2022 20:09:02 by 1.7.2