Arduino library for Mitsubishi 50530 LCD displays ( 40x3 )


Here's a first version of a library for LCD displays based on the Mitsubishi 50530 chip.

We have tested it on an Optrex DMC-50652N display , but it should also work on a Seiko/IIS C456002A

We'll add cleaner wiring diagram later, but the data pins should be at :

digital 0 -> DB7 (databit 7) digital 1 -> DB6 (databit 6) digital 2 -> DB5 (databit 5) digital 3 -> DB4 (databit 4) digital 4 -> EX (Execute) digital 5 -> R/W (Read/Write) digital 6 -> I/OC1 (IO Control 1) digital 7 -> I/OC2 (IO Control 2)

5V -> VSS (GND) Gnd -> Vdd (logic power)

VLCD (LCD power) should get a voltage of 12v in our tests , or the LCD display shows no characters ( in our test ), so you need an external power source for that...

Remarks are welcome !

Created by Jeroen van Beirendonck & Stefaan Ponnet - inspired on the work of these guys :

Here's a first version of a library for LCD displays based on the Mitsubishi 50530 chip.

It looks like something (the library) is missing.

Try it again - there are limits on what you can do on your first post.


Sorry for that , the link is right here :

Remarks / patches are welcome !

hi i'm trying to use your lib but 2 problems i need do use things like : lcd.print (" Controler"); lcd.print(tempC) is this possible ???

Best Regards Jaime Branco

ok i have change your libs now we can use lcd.print()

#include "LCD50530.h"

#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include "Arduino.h"
LCD50530::LCD50530(uint8_t ioc1, uint8_t ioc2, uint8_t rw, uint8_t ex, uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7)
	init(ioc1, ioc2, rw, ex, d4, d5, d6, d7);

void LCD50530::init(uint8_t ioc1, uint8_t ioc2, uint8_t rw, uint8_t ex, uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7)
  _ioc1_pin = ioc1;
  _ioc2_pin = ioc2;
  _rw_pin = rw;
  _ex_pin = ex;
  _data_pins[0] = d4;
  _data_pins[1] = d5;
  _data_pins[2] = d6;
  _data_pins[3] = d7; 

  DDRD = B11111111; // Default: Set all ports to output (Atmel shortcut)    

void LCD50530::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) {  
  int totalChar = cols*lines;

  uint8_t displaySize = 0x00;
  if(lines <= 1)
	displaySize |= LCD_1LINE;
  else if (lines == 2)
	displaySize |= LCD_2LINE;
	displaySize |= LCD_4LINE;
  if(totalChar <= 160) {
	displaySize |= LCD_160CHAR;
	_cols = 160/lines;
  else if(totalChar <= 192) {
	displaySize |= LCD_192CHAR;	
	_cols = 192/lines;	
  else if(totalChar <= 224) {
	displaySize |= LCD_224CHAR; 
	_cols = 224/lines;	
  else{ // 256 characters - 
	displaySize |= LCD_256CHAR;
	_cols = 256/lines;
  _functionmode = LCD_4BITMODE | LCD_5x8DOTS | displaySize;
  command(LCD_FUNCTIONMODESET | _functionmode); 
  _displaymode = LCD_DISPLAYON;
  command(LCD_DISPLAYMODESET | _displaymode);

  command(LCD_ENTRYMODESET | _entrymode); 

/********** high level commands, for the user! */
void LCD50530::clear()
  command(LCD_CLEARDISPLAY);  // clear display, set cursor position to zero

void LCD50530::home()
  command(LCD_RETURNHOME);  // set cursor position to zero

void LCD50530::setCursor(uint8_t col, uint8_t row)
  uint8_t instruction = row*_cols+col;
  send(instruction, 1<<_ioc1_pin | 1<<_ioc2_pin);

// Turn the display on/off (quickly)
void LCD50530::noDisplay() {
  _displaymode &= ~LCD_DISPLAYON;
  command(LCD_DISPLAYMODESET | _displaymode);
void LCD50530::display() {
  _displaymode |= LCD_DISPLAYON;
  command(LCD_DISPLAYMODESET | _displaymode);

// Turns the underline cursor on/off
void LCD50530::noCursor() {
  _displaymode &= ~LCD_CURSORON;
  command(LCD_DISPLAYMODESET | _displaymode);
void LCD50530::cursor() {
  _displaymode |= LCD_CURSORON;
  command(LCD_DISPLAYMODESET | _displaymode);

// Turns the underline cursor on/off
void LCD50530::noUnderline() {
  _displaymode &= ~LCD_UNDERLINEON;
  command(LCD_DISPLAYMODESET | _displaymode);
void LCD50530::underline() {
  _displaymode |= LCD_UNDERLINEON;
  command(LCD_DISPLAYMODESET | _displaymode);
// Turn on and off the blinking cursor
void LCD50530::noCursorBlink() {
  _displaymode &= ~LCD_CURSORBLINKON;
  command(LCD_DISPLAYMODESET | _displaymode);
void LCD50530::cursorBlink() {
  _displaymode |= LCD_CURSORBLINKON;
  command(LCD_DISPLAYMODESET | _displaymode);

// Turn on and off the blinking cursor
void LCD50530::noCharBlink() {
  _displaymode &= ~LCD_CHRBLINKON;
  command(LCD_DISPLAYMODESET | _displaymode);
void LCD50530::charBlink() {
  _displaymode |= LCD_CHRBLINKON;
  command(LCD_DISPLAYMODESET | _displaymode);

// These commands moves the cursor one space in the directopn without changing the RAM
void LCD50530::shiftCursor(uint8_t direction) {    
  command(LCD_SHIFTCOMMAND | LCD_CURSORSHIFT | (direction<<2));

// These commands moves the display one space in the directopn without changing the RAM
void LCD50530::shiftDisplay(uint8_t direction) {
// This is for text that flows Left to Right
void LCD50530::moveCursorAfterInstruction(uint8_t direction, uint8_t instruction) {
  _entrymode &= B01000111;
  _entrymode |= ((instruction | direction) <<3);
  command(LCD_ENTRYMODESET | _entrymode);

void LCD50530::moveDisplayAfterInstruction(uint8_t direction, uint8_t instruction) {
  _entrymode &= B01111000;
  _entrymode |= instruction | direction;
  command(LCD_ENTRYMODESET | _entrymode);

void LCD50530::holdCursor(void) {
	command(LCD_ENTRYMODESET & B01000111);

void LCD50530::holdDisplay(void) {
	command(LCD_ENTRYMODESET & B01111000);

// This is for text that flows Left to Right
void LCD50530::leftToRight(void) {
  moveCursorAfterInstruction(LCD_WRITE, LCD_RIGHT);

// This is for text that flows Right to Left
void LCD50530::rightToLeft(void) {
	moveCursorAfterInstruction(LCD_WRITE, LCD_LEFT);

// This will 'right justify' text from the cursor
void LCD50530::autoscroll(void) {
  moveDisplayAfterInstruction(LCD_WRITE, LCD_RIGHT);

// This will 'left justify' text from the cursor
void LCD50530::noAutoscroll(void) {
  moveDisplayAfterInstruction(LCD_WRITE, LCD_LEFT);

/*********** mid level commands, for sending data/cmds */

inline void LCD50530::command(uint8_t value) {
  send(value, 0); 

void LCD50530::writechar(uint8_t value) {
  send(value, 1<<_ioc2_pin);  
inline size_t LCD50530::write(uint8_t value) {
  send(value, HIGH);
  return 1; // assume sucess

/************ low level data pushing commands **********/

// write either command or data, with automatic 4/8-bit selection
void LCD50530::send(uint8_t value, uint8_t controlpins) {
  while(busyState());	// Wait while the lcd controller is still busy       
  write4bits(value, controlpins);
  write4bits(value<<4, controlpins);

void LCD50530::pulseExecute(void) {
  digitalWrite(_ex_pin, HIGH);
  digitalWrite(_ex_pin, LOW);

void LCD50530::write4bits(uint8_t value, uint8_t controlpins) {
  PORTD = (value & B11110000) | controlpins;

	Returns the state of the lcd controller
	When 0 is returned, the controller is ready for a new instruction
uint8_t LCD50530::busyState() {
  uint8_t state = 0;
  DDRD = B00001111; // Set data pins to input
  PORTD = 1<<_rw_pin;
  digitalWrite(_ex_pin, HIGH);
  state = digitalRead(_data_pins[3]);
  digitalWrite(_ex_pin, LOW);
  PORTD = 1<<_rw_pin;
  digitalWrite(_ex_pin, HIGH);
  state |= digitalRead(_data_pins[3]);
  digitalWrite(_ex_pin, LOW);
  DDRD = B11111111; // Reset pins to output
  return state;


LCD driver for Mitsubishi 50530 compatible displays


#ifndef LCD50530_h
#define LCD50530_h

#include <inttypes.h>
#include "Print.h"

// Full commands
#define LCD_NOOP 0x00
#define LCD_RETURNHOME 0x03

// Partial commands (with flags)
#define LCD_BLINKFREQSET 0x04		// with flags
#define LCD_WRITERAMULINESET 0x08	// with flags
#define LCD_UNDERLINEMODESET 0x0C	// with flags
#define LCD_SHIFTCOMMAND 0x10		// with flags
#define LCD_DISPLAYMODESET 0x20		// with flags
#define LCD_ENTRYMODESET 0x40		// with flags
#define LCD_FUNCTIONMODESET 0xC0	// with flags

//#define LCD_SETCGRAMADDR 0x40
//#define LCD_SETDDRAMADDR 0x80

// flags for function mode set
#define LCD_8BITMODE 0x20
#define LCD_4BITMODE 0x00
#define LCD_4LINE 0x08
#define LCD_2LINE 0x04
#define LCD_1LINE 0x00
#define LCD_5x12DOTS 0x00
#define LCD_5x8DOTS 0x10
#define LCD_160CHAR 0x03
#define LCD_192CHAR 0x02
#define LCD_224CHAR 0x01
#define LCD_256CHAR 0x00

// TODO: RAM -- setting region (page 28/29 of datasheet)

// flags for display set entry mode
#define LCD_DISPLAYMOVEREAD 0x01	// Update display address after reading RAM data
#define LCD_DISPLAYMOVEWRITE 0x02	// Update display address after writing RAM data
#define LCD_CURSORMOVEREAD 0x08		// Update cursor address after reading RAM data
#define LCD_CURSORMOVEWRITE 0x10	// Update cursor address after writing RAM data
#define LCD_DISPLAYMOVERIGHT 0x00	// Display address decremented after instruction
#define LCD_DISPLAYMOVELEFT 0x04	// Display address incremented after instruction
#define LCD_CURSORMOVELEFT 0x20		// Cursor address decremented after instruction
#define LCD_CURSORMOVERIGHT 0x00	// Cursor address incremented after instruction

#define LCD_LEFT	0x04
#define LCD_RIGHT	0x00
#define LCD_READ	0x01
#define LCD_WRITE	0x02

// flags for display on/off control
#define LCD_DISPLAYON 0x10		// Turn all displays on
#define LCD_DISPLAYOFF 0x00		// Turn all displays off
#define LCD_CURSORON 0x08		// Turn on cursor display
#define LCD_CURSOROFF 0x00		// Turn off cursor display
#define LCD_UNDERLINEON 0x04	// Turn on underline display
#define LCD_UNDERLINEOFF 0x00	// Turn off underline display
#define LCD_CURSORBLINKON 0x02	// Blinking cursor display
#define LCD_CURSORBLINKOFF 0x00	// Cursor display without blinking
#define LCD_CHRBLINKON 0x01		// Blinking Character display of cursor position
#define LCD_CHRBLINKOFF 0x00	// Character display without blinking
// flags for display/cursor shift command
#define LCD_CURSORSHIFT 0x08
#define LCD_SHIFTLEFT 0x01
#define LCD_SHIFTRIGHT 0x00

// TODO: flags for underline mode instruction (SU)
// TODO: flags for Write underline bit instruction (WU)
// TODO: flags for Set blink frequency instruction (SB)

class LCD50530 : public Print {
  LCD50530(uint8_t ioc1, uint8_t ioc2, uint8_t rw, uint8_t ex, uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7);

  void init(uint8_t ioc1, uint8_t ioc2, uint8_t rw, uint8_t ex, uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7);
  void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS);

  void clear();
  void home();

  void noDisplay();
  void display();
  void noCursor();
  void cursor();
  void noUnderline();
  void underline();
  void noCursorBlink();
  void cursorBlink();
  void noCharBlink();
  void charBlink();

  void moveCursorAfterInstruction(uint8_t direction, uint8_t instruction);
  void moveDisplayAfterInstruction(uint8_t direction, uint8_t instruction);
  void holdCursor();
  void holdDisplay();

  void shiftCursor(uint8_t direction);
  void shiftDisplay(uint8_t direction);
  void leftToRight();
  void rightToLeft();
  void autoscroll();
  void noAutoscroll();

  //void createChar(uint8_t, uint8_t[]);
  void setCursor(uint8_t, uint8_t); 
  void command(uint8_t);
  void writechar(uint8_t);
  virtual size_t write(uint8_t);
  using Print::write;
  void send(uint8_t, uint8_t);
  void write4bits(uint8_t, uint8_t);
  void pulseExecute();
  uint8_t busyState();

  uint8_t _ioc1_pin; // LOW: command.  HIGH: character.
  uint8_t _ioc2_pin; // LOW: command.  HIGH: character.
  uint8_t _rw_pin; // LOW: write to LCD.  HIGH: read from LCD.
  uint8_t _ex_pin; // activated by a HIGH pulse.
  uint8_t _data_pins[4];

  uint8_t _functionmode;
  uint8_t _displaymode;
  uint8_t _entrymode;

  uint8_t _initialized;

  uint8_t _numlines, _currline;
  uint8_t _cols;