lcd_i2c.c (5353B)
1 // ------------------------------------------------------------------------------ 2 // Copyright 2018 Stephen Stebbing. telecnatron.com 3 // 4 // Licensed under the Telecnatron License, Version 1.0 (the “License”); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // https://telecnatron.com/software/licenses/ 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an “AS IS” BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // ------------------------------------------------------------------------------ 16 17 #include "lcd_i2c.h" 18 19 #include <wiringPi.h> 20 #include <wiringPiI2C.h> 21 #include <stdarg.h> 22 #include <stdio.h> 23 #include <stdlib.h> 24 25 // pcf8574 bit positions of the lcd control pins 26 // bits 4 to 7 are the data bits 27 #define LCD_I2C_RS 0 28 #define LCD_I2C_RW 1 29 #define LCD_I2C_E 2 30 #define LCD_I2C_BACKLIGHT 3 31 32 // convenience macros 33 // write current value of output variable to device 34 #define LCD_I2C_WRITE(lcd_p) wiringPiI2CWrite(lcd_p->fd, lcd_p->output); 35 // enable 36 #define LCD_I2C_E_HI(lcd_p) lcd_p->output |= (1<<LCD_I2C_E) 37 #define LCD_I2C_E_LO(lcd_p) lcd_p->output &=~ (1<<LCD_I2C_E) 38 // set data or instruction mode 39 #define LCD_I2C_RS_D(lcd_p) lcd_p->output |= (1<<LCD_I2C_RS) 40 #define LCD_I2C_RS_I(lcd_p) lcd_p->output &=~ (1<<LCD_I2C_RS) 41 // set the data nibble - 42 // note: will need to change this for devices with different wiring. 43 #define LCD_I2C_DATA_NIBBLE(lcd_p, x) lcd_p->output= (x<<4 | (lcd_p->output & 0x0f)) 44 //! set the lcd data ram address to that passed, only lower 7 bits are used. 45 #define LCD_I2C_SET_DD_RAM_ADDRESS(lcd_p, address) lcd_i2c_write_i(lcd_p, 0x80 | ((address) & 0x7f) ) 46 47 // ----------------------------------------------------- 48 // static functions 49 // ----------------------------------------------------- 50 static void lcd_i2c_e_assert(lcd_i2c_t *lcd) 51 { 52 LCD_I2C_E_LO(lcd); 53 LCD_I2C_WRITE(lcd); 54 LCD_I2C_E_HI(lcd); 55 LCD_I2C_WRITE(lcd); 56 LCD_I2C_E_LO(lcd); 57 LCD_I2C_WRITE(lcd); 58 } 59 60 //! Write passed data to device 61 //! Note: RS must be set prior to calling 62 static void lcd_i2c_write(lcd_i2c_t *lcd, uint8_t data) 63 { 64 // high nibble 65 LCD_I2C_DATA_NIBBLE(lcd, (data >> 4)); 66 lcd_i2c_e_assert(lcd); 67 // low nibble 68 LCD_I2C_DATA_NIBBLE(lcd, (data & 0x0f)); 69 lcd_i2c_e_assert(lcd); 70 // delay for command to be executed 71 delayMicroseconds(50); 72 } 73 74 // ----------------------------------------------------- 75 // user callable functions 76 // ----------------------------------------------------- 77 void lcd_i2c_gotoxy(lcd_i2c_t *lcd, uint8_t x, uint8_t y) 78 { 79 // note: on two line devices, second line begins at address 0x40 80 // XXX so this will work with 1 and 2 line devices, but probabaly not with 4. 81 LCD_I2C_SET_DD_RAM_ADDRESS( lcd, y*0x40 + x ); 82 lcd->x=x; 83 lcd->y=y; 84 } 85 86 void lcd_i2c_printf(lcd_i2c_t *lcd, char* format, ...) 87 { 88 va_list args; 89 char *spp=NULL; 90 91 va_start(args, format); 92 int r=vasprintf(&spp, format, args); 93 if(r!=-1){ 94 lcd_i2c_puts(lcd, spp); 95 free(spp); 96 } 97 va_end(args); 98 } 99 100 int lcd_i2c_setup( lcd_i2c_t *lcd,int address) 101 { 102 lcd->output=0; 103 lcd->fd=wiringPiI2CSetup(address); 104 // XXX for now, alway use a 1602 display 105 lcd->rows=2; 106 lcd->cols=16; 107 return lcd->fd; 108 } 109 110 void lcd_i2c_write_i(lcd_i2c_t *lcd, uint8_t data) 111 { 112 LCD_I2C_RS_I(lcd); 113 lcd_i2c_write(lcd,data); 114 } 115 116 void lcd_i2c_write_d(lcd_i2c_t *lcd, uint8_t data) 117 { 118 LCD_I2C_RS_D(lcd); 119 lcd_i2c_write(lcd,data); 120 } 121 122 void lcd_i2c_clear(lcd_i2c_t *lcd) 123 { 124 lcd_i2c_write_i(lcd, 0x1); 125 delay(2); // delay for command to take effect 126 } 127 128 void lcd_i2c_home(lcd_i2c_t *lcd) 129 { 130 lcd_i2c_write_i(lcd, 0x02); 131 lcd->x=0; 132 lcd->y=0; 133 delay(2); // delay for command to take effect 134 } 135 136 void lcd_i2c_putc(lcd_i2c_t *lcd, char c) 137 { 138 lcd_i2c_write_d(lcd, c); 139 // printf("c: %c (%i,%i)\n",c, lcd->x, lcd->y); 140 if(++lcd->x == lcd->cols){ 141 lcd->x=0; 142 if(++lcd->y == lcd->rows){ 143 lcd->y=0; 144 } 145 lcd_i2c_gotoxy(lcd,lcd->x,lcd->y); 146 } 147 } 148 149 void lcd_i2c_puts(lcd_i2c_t *lcd, const char* str) 150 { 151 while(*str!='\x0'){ 152 lcd_i2c_putc(lcd,*str++); 153 } 154 } 155 156 void lcd_i2c_init(lcd_i2c_t *lcd) 157 { 158 LCD_I2C_E_LO(lcd); 159 LCD_I2C_RS_I(lcd); 160 LCD_I2C_WRITE(lcd); 161 162 // software reset 163 LCD_I2C_DATA_NIBBLE(lcd,0x3); 164 lcd_i2c_e_assert(lcd); 165 delay(5); // ms 166 lcd_i2c_e_assert(lcd); 167 delayMicroseconds(150); 168 lcd_i2c_e_assert(lcd); 169 delayMicroseconds(150); 170 171 // set 4 bit mode 172 LCD_I2C_DATA_NIBBLE(lcd,0x02); 173 lcd_i2c_e_assert(lcd); 174 175 // entry mode - 0x06 is display shift on, increment address counter 176 lcd_i2c_write_i(lcd,0x06); 177 178 // set cursor 179 LCD_I2C_CURSOR_BLINK_OFF(lcd); 180 LCD_I2C_CURSOR_OFF(lcd); 181 182 // clear and home 183 lcd_i2c_clear(lcd); 184 lcd_i2c_home(lcd); 185 186 } 187 188 /** 189 * Turn backlight on or off 190 * @param ct lcd_i2c_t control structure for the device 191 * @param on Turn on if non-zero, off otherwise 192 */ 193 void lcd_i2c_backlight(lcd_i2c_t *lcd, uint8_t on) 194 { 195 if(on) 196 lcd->output |= (1<<LCD_I2C_BACKLIGHT); 197 else 198 lcd->output &=~ (1<<LCD_I2C_BACKLIGHT); 199 LCD_I2C_WRITE(lcd); 200 }