Update i2c driver to have pins defined via config file, rather than hardcoded

This commit is contained in:
Rhys Williams
2016-07-23 11:14:53 +12:00
parent 54e718ff77
commit 606e2913f0
3 changed files with 165 additions and 37 deletions
+55
View File
@@ -2516,6 +2516,61 @@ Size=40x2
DelayBus=false
DelayMult=1
Keypad=no
#i2c_line_RS=0x10
#i2c_line_RW=0x20
#i2c_line_EN=0x40
#i2c_line_BL=0x80
#i2c_line_D4=0x01
#i2c_line_D5=0x02
#i2c_line_D6=0x04
#i2c_line_D7=0x08
# BacklightInvert=yes
# The Backlight Invert is used if a 0 turns the backlight on, and 1 turns it off, i.e. npn transistor
]]>
</screen>
</example>
<para>
If your port expander has different wiring you can re-assign the pins in the config file
</para>
<example id="hd44780-i2c-config.example alternative wiring">
<title>HD44780: Configuration for I<superscript>2</superscript>C with port expander
Alternative Wiring</title>
<screen>
<![CDATA[
- PCF8574AP: P0 P1 P2 P3 P4 P5 P6 P7
- | | | | | | | |
- HD44780: RS RW EN BL D4 D5 D6 D7
]]>
</screen>
</example>
<example id="hd44780-i2c-config.example alternative config">
<title>HD44780: Configuration for I<superscript>2</superscript>C with port expander
alternative config</title>
<screen>
<![CDATA[
[HD44780]
ConnectionType=i2c
Device=/dev/i2c-0
Port=0x20
Size=40x2
DelayBus=false
DelayMult=1
Keypad=no
i2c_line_RS=0x01
i2c_line_RW=0x02
i2c_line_EN=0x04
i2c_line_BL=0x80
i2c_line_D4=0x10
i2c_line_D5=0x20
i2c_line_D6=0x40
i2c_line_D7=0x80
Backlight=yes
BacklightInvert=yes
#The Backlight Invert is used if a 0 turns the backlight on, and 1 turns it off,
i.e. npn transistor
]]>
</screen>
</example>
+95 -37
View File
@@ -13,17 +13,38 @@
* 1997 Matthias Prinke <m.prinke@trashcan.mcnet.de>
*
* The connections are:
* PCF8574AP LCD
* P0 (4) D4 (11)
* P1 (5) D5 (12)
* P2 (6) D6 (13)
* P3 (7) D7 (14)
* P4 (9) RS (4)
* P5 (10) RW (5)
* P6 (11) EN (6)
* PCF8574AP Bit LCD
* P0 (4) 0x01 D4 (11)
* P1 (5) 0x02 D5 (12)
* P2 (6) 0x04 D6 (13)
* P3 (7) 0x08 D7 (14)
* P4 (9) 0x10 RS (4)
* P5 (10) 0x20 RW (5)
* P6 (11) 0x40 EN (6)
* P7 (12) 0x80 /backlight (optional, active-low)
*
* Backlight
* P7 (12) /backlight (optional, active-low)
* Configuration:
\verbatim
alternative wiring example:
PCF8574AP: P0 P1 P2 P3 P4 P5 P6 P7
| | | | | | | |
HD44780: RS RW EN BL D4 D5 D6 D7
in LCDd.conf we then need to define
i2c_line_RS=0x01
i2c_line_RW=0x02
i2c_line_EN=0x04
i2c_line_BL=0x80
i2c_line_D4=0x10
i2c_line_D5=0x20
i2c_line_D6=0x40
i2c_line_D7=0x80
Backlight=yes
BacklightInvert=yes
The Backlight Invert is used if a 0 turns the backlight on, and 1 turns it off, i.e. npn transistor
\endverbatim
*
* Configuration:
* device=/dev/i2c-0 # the device file of the i2c bus
@@ -89,6 +110,11 @@ void i2c_HD44780_close(PrivateData *p);
#define RW 0x20
#define EN 0x40
#define BL 0x80
#define D4 0x01
#define D5 0x02
#define D6 0x04
#define D7 0x08
#define BL_INVERT 0
// note that the above bits are all meant for the data port of PCF8574
#define I2C_ADDR_MASK 0x7f
@@ -145,14 +171,34 @@ hd_init_i2c(Driver *drvthis)
PrivateData *p = (PrivateData*) drvthis->private_data;
HD44780_functions *hd44780_functions = p->hd44780_functions;
int enableLines = EN;
char device[256] = DEFAULT_DEVICE;
p->i2c_backlight_invert = drvthis->config_get_bool(drvthis->name, "BacklightInvert", 0, BL_INVERT);
p->i2c_line_RS = drvthis->config_get_int(drvthis->name, "i2c_line_RS", 0, RS);
p->i2c_line_RW = drvthis->config_get_int(drvthis->name, "i2c_line_RW", 0, RW);
p->i2c_line_EN = drvthis->config_get_int(drvthis->name, "i2c_line_EN", 0, EN);
p->i2c_line_BL = drvthis->config_get_int(drvthis->name, "i2c_line_BL", 0, BL);
p->i2c_line_D4 = drvthis->config_get_int(drvthis->name, "i2c_line_D4", 0, D4);
p->i2c_line_D5 = drvthis->config_get_int(drvthis->name, "i2c_line_D5", 0, D5);
p->i2c_line_D6 = drvthis->config_get_int(drvthis->name, "i2c_line_D6", 0, D6);
p->i2c_line_D7 = drvthis->config_get_int(drvthis->name, "i2c_line_D7", 0, D7);
report(RPT_INFO, "HD44780: I2C: Init using D4 and D5, and or'd lines, invert", p->i2c_line_RS);
report(RPT_INFO, "HD44780: I2C: Pin RS mapped to 0x%02X", p->i2c_line_RS);
report(RPT_INFO, "HD44780: I2C: Pin RW mapped to 0x%02X", p->i2c_line_RW);
report(RPT_INFO, "HD44780: I2C: Pin EN mapped to 0x%02X", p->i2c_line_EN);
report(RPT_INFO, "HD44780: I2C: Pin BL mapped to 0x%02X", p->i2c_line_BL);
report(RPT_INFO, "HD44780: I2C: Pin D4 mapped to 0x%02X", p->i2c_line_D4);
report(RPT_INFO, "HD44780: I2C: Pin D5 mapped to 0x%02X", p->i2c_line_D5);
report(RPT_INFO, "HD44780: I2C: Pin D6 mapped to 0x%02X", p->i2c_line_D6);
report(RPT_INFO, "HD44780: I2C: Pin D7 mapped to 0x%02X", p->i2c_line_D7);
report(RPT_INFO, "HD44780: I2C: Invert Backlight %d", p->i2c_backlight_invert);
char device[256] = DEFAULT_DEVICE;
#ifdef HAVE_DEV_IICBUS_IIC_H
struct iiccmd cmd;
bzero(&cmd, sizeof(cmd));
#endif
p->backlight_bit = BL;
p->backlight_bit = p->i2c_line_BL;
/* READ CONFIG FILE */
@@ -209,44 +255,49 @@ hd_init_i2c(Driver *drvthis)
// powerup the lcd now
/* We'll now send 0x03 a couple of times,
* which is in fact (FUNCSET | IF_8BIT) >> 4 */
i2c_out(p, 0x03);
* which is in fact (FUNCSET | IF_8BIT) >> 4
*/
i2c_out(p, p->i2c_line_D4 | p->i2c_line_D5);
if (p->delayBus)
hd44780_functions->uPause(p, 1);
i2c_out(p, enableLines | 0x03);
i2c_out(p, p->i2c_line_EN | p->i2c_line_D4 | p->i2c_line_D5);
if (p->delayBus)
hd44780_functions->uPause(p, 1);
i2c_out(p, 0x03);
i2c_out(p, p->i2c_line_D4 | p->i2c_line_D5);
hd44780_functions->uPause(p, 15000);
i2c_out(p, enableLines | 0x03);
i2c_out(p, p->i2c_line_EN | p->i2c_line_D4 | p->i2c_line_D5);
if (p->delayBus)
hd44780_functions->uPause(p, 1);
i2c_out(p, 0x03);
i2c_out(p, p->i2c_line_D4 | p->i2c_line_D5);
hd44780_functions->uPause(p, 5000);
i2c_out(p, enableLines | 0x03);
i2c_out(p, p->i2c_line_EN | p->i2c_line_D4 | p->i2c_line_D5);
if (p->delayBus)
hd44780_functions->uPause(p, 1);
i2c_out(p, 0x03);
i2c_out(p, p->i2c_line_D4 | p->i2c_line_D5);
hd44780_functions->uPause(p, 100);
i2c_out(p, enableLines | 0x03);
i2c_out(p, p->i2c_line_EN | p->i2c_line_D4 | p->i2c_line_D5);
if (p->delayBus)
hd44780_functions->uPause(p, 1);
i2c_out(p, 0x03);
i2c_out(p, p->i2c_line_D4 | p->i2c_line_D5);
hd44780_functions->uPause(p, 100);
// now in 8-bit mode... set 4-bit mode
i2c_out(p, 0x02);
/*
OLD (FUNCSET | IF_4BIT) >> 4 0x02
ALT (FUNCSET | IF_4BIT) 0x20
*/
i2c_out(p, p->i2c_line_D5);
if (p->delayBus)
hd44780_functions->uPause(p, 1);
i2c_out(p, enableLines | 0x02);
i2c_out(p, p->i2c_line_EN | p->i2c_line_D5);
if (p->delayBus)
hd44780_functions->uPause(p, 1);
i2c_out(p, 0x02);
i2c_out(p, p->i2c_line_D5);
hd44780_functions->uPause(p, 100);
// Set up two-line, small character (5x8) mode
@@ -279,23 +330,28 @@ i2c_HD44780_close(PrivateData *p) {
void
i2c_HD44780_senddata(PrivateData *p, unsigned char displayID, unsigned char flags, unsigned char ch)
{
unsigned char enableLines = 0, portControl = 0;
unsigned char h = (ch >> 4) & 0x0f; // high and low nibbles
unsigned char l = ch & 0x0f;
unsigned char portControl = 0;
unsigned char h=0;
unsigned char l=0;
if( ch & 0x80 ) h |= p->i2c_line_D7;
if( ch & 0x40 ) h |= p->i2c_line_D6;
if( ch & 0x20 ) h |= p->i2c_line_D5;
if( ch & 0x10 ) h |= p->i2c_line_D4;
if( ch & 0x08 ) l |= p->i2c_line_D7;
if( ch & 0x04 ) l |= p->i2c_line_D6;
if( ch & 0x02 ) l |= p->i2c_line_D5;
if( ch & 0x01 ) l |= p->i2c_line_D4;
if (flags == RS_INSTR)
portControl = 0;
else //if (flags == RS_DATA)
portControl = RS;
portControl = p->i2c_line_RS;
portControl |= p->backlight_bit;
enableLines = EN;
i2c_out(p, portControl | h);
if (p->delayBus)
p->hd44780_functions->uPause(p, 1);
i2c_out(p, enableLines | portControl | h);
i2c_out(p, p->i2c_line_EN | portControl | h);
if (p->delayBus)
p->hd44780_functions->uPause(p, 1);
i2c_out(p, portControl | h);
@@ -303,7 +359,7 @@ i2c_HD44780_senddata(PrivateData *p, unsigned char displayID, unsigned char flag
i2c_out(p, portControl | l);
if (p->delayBus)
p->hd44780_functions->uPause(p, 1);
i2c_out(p, enableLines | portControl | l);
i2c_out(p, p->i2c_line_EN | portControl | l);
if (p->delayBus)
p->hd44780_functions->uPause(p, 1);
i2c_out(p, portControl | l);
@@ -317,7 +373,9 @@ i2c_HD44780_senddata(PrivateData *p, unsigned char displayID, unsigned char flag
*/
void i2c_HD44780_backlight(PrivateData *p, unsigned char state)
{
p->backlight_bit = ((!p->have_backlight||state) ? 0 : BL);
if ( p->i2c_backlight_invert == 0 )
p->backlight_bit = ((!p->have_backlight||state) ? 0 : p->i2c_line_BL);
else // Inverted backlight - npn transistor
p->backlight_bit = ((p->have_backlight && state) ? p->i2c_line_BL : 0);
i2c_out(p, p->backlight_bit);
}
+15
View File
@@ -155,6 +155,21 @@ typedef struct hd44780_private_data {
int ftdi_line_backlight;
#endif
#ifdef HAVE_I2C
/* libi2c-based connection types */
int i2c_backlight_invert;
int i2c_line_RS;
int i2c_line_RW;
int i2c_line_EN;
int i2c_line_BL;
int i2c_line_D4;
int i2c_line_D5;
int i2c_line_D6;
int i2c_line_D7;
#endif
#ifdef WITH_ETHLCD
int sock; /**< socket for TCP devices */
#endif