mirror of
https://github.com/eclipse/upm.git
synced 2025-03-15 04:57:30 +03:00
lcm1602: add 4-bit gpio support with RS and Enable pins
In addition, move the command/data sending methods into the protected block so that derived classes can use them if need be. Signed-off-by: Jon Trulson <jtrulson@ics.com> Signed-off-by: Mihai Tudor Panu <mihai.tudor.panu@intel.com>
This commit is contained in:
parent
8462e8ce52
commit
5a6fb122ec
@ -7,6 +7,8 @@
|
||||
* Author: Thomas Ingleby <thomas.c.ingleby@intel.com>
|
||||
* Copyright (c) 2014 Intel Corporation.
|
||||
*
|
||||
* Contributions: Jon Trulson <jtrulson@ics.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
@ -33,14 +35,18 @@
|
||||
|
||||
using namespace upm;
|
||||
|
||||
Lcm1602::Lcm1602(int bus_in, int addr_in) : m_i2c_lcd_control(bus_in)
|
||||
Lcm1602::Lcm1602(int bus_in, int addr_in) :
|
||||
m_i2c_lcd_control(new mraa::I2c(bus_in)),
|
||||
m_gpioRS(0), m_gpioEnable(0), m_gpioD0(0),
|
||||
m_gpioD1(0), m_gpioD2(0), m_gpioD3(0)
|
||||
{
|
||||
mraa_result_t error = MRAA_SUCCESS;
|
||||
m_name = "Lcm1602 (I2C)";
|
||||
m_isI2C = true;
|
||||
|
||||
m_lcd_control_address = addr_in;
|
||||
|
||||
error = m_i2c_lcd_control.address(m_lcd_control_address);
|
||||
error = m_i2c_lcd_control->address(m_lcd_control_address);
|
||||
if (error != MRAA_SUCCESS) {
|
||||
fprintf(stderr, "Failed to initialize i2c bus\n");
|
||||
return;
|
||||
@ -71,8 +77,83 @@ Lcm1602::Lcm1602(int bus_in, int addr_in) : m_i2c_lcd_control(bus_in)
|
||||
home();
|
||||
}
|
||||
|
||||
Lcm1602::Lcm1602(uint8_t rs, uint8_t enable, uint8_t d0,
|
||||
uint8_t d1, uint8_t d2, uint8_t d3) :
|
||||
m_i2c_lcd_control(0),
|
||||
m_gpioRS(new mraa::Gpio(rs)), m_gpioEnable(new mraa::Gpio(enable)),
|
||||
m_gpioD0(new mraa::Gpio(d0)), m_gpioD1(new mraa::Gpio(d1)),
|
||||
m_gpioD2(new mraa::Gpio(d2)), m_gpioD3(new mraa::Gpio(d3))
|
||||
{
|
||||
mraa_result_t error = MRAA_SUCCESS;
|
||||
m_name = "Lcm1602 (4-bit GPIO)";
|
||||
m_isI2C = false;
|
||||
|
||||
// setup our gpios
|
||||
|
||||
m_gpioRS->dir(mraa::DIR_OUT);
|
||||
m_gpioEnable->dir(mraa::DIR_OUT);
|
||||
|
||||
m_gpioD0->dir(mraa::DIR_OUT);
|
||||
m_gpioD1->dir(mraa::DIR_OUT);
|
||||
m_gpioD2->dir(mraa::DIR_OUT);
|
||||
m_gpioD3->dir(mraa::DIR_OUT);
|
||||
|
||||
|
||||
// set RS and Enable low to begin issuing commands
|
||||
m_gpioRS->write(0);
|
||||
m_gpioEnable->write(0);
|
||||
|
||||
// wait to stabilize
|
||||
usleep(100000);
|
||||
|
||||
// set 4bit mode
|
||||
|
||||
// These steps are adapted from the HD44780 datasheet, figure 24
|
||||
|
||||
// try 1
|
||||
write4bits(0x03);
|
||||
usleep(4500);
|
||||
|
||||
// try 2
|
||||
write4bits(0x03);
|
||||
usleep(4500);
|
||||
|
||||
// try 3
|
||||
write4bits(0x03);
|
||||
usleep(150);
|
||||
|
||||
// Finally, put into 4 bit mode
|
||||
write4bits(0x02);
|
||||
|
||||
// Set number of lines
|
||||
send(LCD_FUNCTIONSET | LCD_2LINE | LCD_4BITMODE | LCD_5x8DOTS, 0);
|
||||
send(LCD_DISPLAYCONTROL | LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF, 0);
|
||||
usleep(2000);
|
||||
clear();
|
||||
|
||||
// Set entry mode.
|
||||
send(LCD_ENTRYMODESET | LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT, 0);
|
||||
|
||||
home();
|
||||
}
|
||||
|
||||
Lcm1602::~Lcm1602()
|
||||
{
|
||||
// clean up after ourselves
|
||||
if (m_isI2C)
|
||||
{
|
||||
delete m_i2c_lcd_control;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete m_gpioRS;
|
||||
delete m_gpioEnable;
|
||||
|
||||
delete m_gpioD0;
|
||||
delete m_gpioD1;
|
||||
delete m_gpioD2;
|
||||
delete m_gpioD3;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -104,13 +185,19 @@ Lcm1602::setCursor(int row, int column)
|
||||
mraa_result_t
|
||||
Lcm1602::clear()
|
||||
{
|
||||
return send(LCD_CLEARDISPLAY, 0);
|
||||
mraa_result_t ret;
|
||||
ret = send(LCD_CLEARDISPLAY, 0);
|
||||
usleep(2000); // this command takes awhile
|
||||
return ret;
|
||||
}
|
||||
|
||||
mraa_result_t
|
||||
Lcm1602::home()
|
||||
{
|
||||
return send(LCD_RETURNHOME, 0);
|
||||
mraa_result_t ret;
|
||||
ret = send(LCD_RETURNHOME, 0);
|
||||
usleep(2000); // this command takes awhile
|
||||
return ret;
|
||||
}
|
||||
|
||||
mraa_result_t
|
||||
@ -118,10 +205,10 @@ Lcm1602::createChar(uint8_t charSlot, uint8_t charData[])
|
||||
{
|
||||
mraa_result_t error = MRAA_SUCCESS;
|
||||
charSlot &= 0x07; // only have 8 positions we can set
|
||||
error = m_i2c_lcd_control.writeReg(LCD_CMD, LCD_SETCGRAMADDR | (charSlot << 3));
|
||||
error = send(LCD_SETCGRAMADDR | (charSlot << 3), 0);
|
||||
if (error == MRAA_SUCCESS) {
|
||||
for (int i = 0; i < 8; i++) {
|
||||
error = m_i2c_lcd_control.writeReg(LCD_DATA, charData[i]);
|
||||
error = send(charData[i], LCD_RS);
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,10 +224,28 @@ mraa_result_t
|
||||
Lcm1602::send(uint8_t value, int mode)
|
||||
{
|
||||
mraa_result_t ret = MRAA_SUCCESS;
|
||||
uint8_t h = value & 0xf0;
|
||||
uint8_t l = (value << 4) & 0xf0;
|
||||
ret = write4bits(h | mode);
|
||||
ret = write4bits(l | mode);
|
||||
uint8_t h;
|
||||
uint8_t l;
|
||||
|
||||
if (m_isI2C)
|
||||
{
|
||||
h = value & 0xf0;
|
||||
l = (value << 4) & 0xf0;
|
||||
ret = write4bits(h | mode);
|
||||
ret = write4bits(l | mode);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// else, gpio (4 bit)
|
||||
|
||||
// register select
|
||||
m_gpioRS->write(mode);
|
||||
|
||||
h = value >> 4;
|
||||
l = value & 0x0f;
|
||||
|
||||
ret = write4bits(h);
|
||||
ret = write4bits(l);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -148,25 +253,58 @@ mraa_result_t
|
||||
Lcm1602::write4bits(uint8_t value)
|
||||
{
|
||||
mraa_result_t ret = MRAA_SUCCESS;
|
||||
ret = expandWrite(value);
|
||||
ret = pulseEnable(value);
|
||||
|
||||
if (m_isI2C)
|
||||
{
|
||||
ret = expandWrite(value);
|
||||
ret = pulseEnable(value);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// else gpio
|
||||
ret = m_gpioD0->write( ((value >> 0) & 0x01) );
|
||||
ret = m_gpioD1->write( ((value >> 1) & 0x01) );
|
||||
ret = m_gpioD2->write( ((value >> 2) & 0x01) );
|
||||
ret = m_gpioD3->write( ((value >> 3) & 0x01) );
|
||||
|
||||
ret = pulseEnable(value); // value is ignored here for gpio
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
mraa_result_t
|
||||
Lcm1602::expandWrite(uint8_t value)
|
||||
{
|
||||
// invalid for gpio
|
||||
if (!m_isI2C)
|
||||
return MRAA_ERROR_INVALID_RESOURCE;
|
||||
|
||||
uint8_t buffer = value | LCD_BACKLIGHT;
|
||||
return m_i2c_lcd_control.writeByte(buffer);
|
||||
return m_i2c_lcd_control->writeByte(buffer);
|
||||
}
|
||||
|
||||
mraa_result_t
|
||||
Lcm1602::pulseEnable(uint8_t value)
|
||||
{
|
||||
mraa_result_t ret = MRAA_SUCCESS;
|
||||
ret = expandWrite(value | LCD_EN);
|
||||
|
||||
if (m_isI2C)
|
||||
{
|
||||
ret = expandWrite(value | LCD_EN);
|
||||
usleep(1);
|
||||
ret = expandWrite(value & ~LCD_EN);
|
||||
usleep(50);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// else gpio
|
||||
|
||||
ret = m_gpioEnable->write(0);
|
||||
usleep(1);
|
||||
ret = expandWrite(value & ~LCD_EN);
|
||||
usleep(50);
|
||||
ret = m_gpioEnable->write(1);
|
||||
usleep(1); // must be > 450ns
|
||||
ret = m_gpioEnable->write(0);
|
||||
usleep(100); // must be >37us
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -7,6 +7,8 @@
|
||||
* Author: Thomas Ingleby <thomas.c.ingleby@intel.com>
|
||||
* Copyright (c) 2014 Intel Corporation.
|
||||
*
|
||||
* Contributions: Jon Trulson <jtrulson@ics.com>
|
||||
*
|
||||
* Permission is hereby granted, free of uint8_tge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
@ -29,6 +31,7 @@
|
||||
|
||||
#include <string>
|
||||
#include <mraa/i2c.hpp>
|
||||
#include <mraa/gpio.hpp>
|
||||
#include "lcd.h"
|
||||
|
||||
namespace upm
|
||||
@ -63,6 +66,22 @@ class Lcm1602 : public LCD
|
||||
* @param address the slave address the lcd is registered on
|
||||
*/
|
||||
Lcm1602(int bus, int address);
|
||||
|
||||
/**
|
||||
* Lcm1602 alternate constructor, used for GPIO based hd44780
|
||||
* controllers supporting RS, Enable, and 4 data pins in 4-bit
|
||||
* mode.
|
||||
*
|
||||
* @param rs register select pin
|
||||
* @param enable enable pin
|
||||
* @param d0 data 0 pin
|
||||
* @param d1 data 1 pin
|
||||
* @param d2 data 2 pin
|
||||
* @param d3 data 3 pin
|
||||
*/
|
||||
Lcm1602(uint8_t rs, uint8_t enable,
|
||||
uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3);
|
||||
|
||||
/**
|
||||
* Lcm1602 Destructor
|
||||
*/
|
||||
@ -105,14 +124,25 @@ class Lcm1602 : public LCD
|
||||
*/
|
||||
mraa_result_t createChar(uint8_t charSlot, uint8_t charData[]);
|
||||
|
||||
private:
|
||||
protected:
|
||||
mraa_result_t send(uint8_t value, int mode);
|
||||
mraa_result_t write4bits(uint8_t value);
|
||||
mraa_result_t expandWrite(uint8_t value);
|
||||
mraa_result_t pulseEnable(uint8_t value);
|
||||
|
||||
private:
|
||||
int m_lcd_control_address;
|
||||
mraa::I2c m_i2c_lcd_control;
|
||||
mraa::I2c* m_i2c_lcd_control;
|
||||
|
||||
// true if using i2c, false otherwise (gpio)
|
||||
bool m_isI2C;
|
||||
|
||||
// gpio operation
|
||||
mraa::Gpio* m_gpioRS;
|
||||
mraa::Gpio* m_gpioEnable;
|
||||
mraa::Gpio* m_gpioD0;
|
||||
mraa::Gpio* m_gpioD1;
|
||||
mraa::Gpio* m_gpioD2;
|
||||
mraa::Gpio* m_gpioD3;
|
||||
};
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user