Pages

Sunday, January 13, 2013

MCP23008 IO Expander - LCD1602

Now I am thinking of adding an 16 characters x 2 lines LCD to the Raspberry Pi.  I am using my old Netduino LCD class as a template to start with.


/// *************************************************************************
/// Class: Lcd
/// Author: TL Fong
/// Created: 2011may21
/// Updated: 2012jun21
/// *************************************************************************

using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Diagnostics;
using Microsoft.SPOT;
using Microsoft.SPOT.IO;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.NetduinoPlus;
using Microsoft.SPOT.Net.NetworkInformation;

namespace Soner01
{
    public class Lcd
    {
        public static int _lineLength;
        public static OutputPort _rsPort;
        public static OutputPort _enablePort;
        public static OutputPort _dataPort0;
        public static OutputPort _dataPort1;
        public static OutputPort _dataPort2;
        public static OutputPort _dataPort3;
        public static OutputPort _dataPort4;
        public static OutputPort _dataPort5;
        public static OutputPort _dataPort6;
        public static OutputPort _dataPort7;

        public static OutputPort[] dataOutputPortArray;

        public static bool LOW = false;
        public static bool HIGH = true;

        public static int INSTRUCTION_REGISTER = 0;
        public static int DATA_REGISTER = 1;

        public static int LOW_NIBBLE = 0;
        public static int HIGH_NIBBLE = 1;

        public static int POWER_RESET_DELAY = 5000 / 1000;
        public static int VERY_LONG_INSTRUCTION_DELAY = 5000 / 1000;
        public static int LONG_INSTRUCTION_DELAY = 2000 / 1000;
        public static int SHORT_INSTRUCTION_DELAY = 100 / 100;

        public static int SET_8_BIT_INTERFACE_0X30 = 0x30;
        public static int SET_4_BIT_INTERFACE_0X20 = 0x20;
        public static int EIGHT_BIT_TWO_LINE_FIVE_TIMES_TEN_DOT = 0x28;
        public static int SET_4_BIT_TWO_LINES_FIVE_TIMES_EIGHT_DOTS = 0x28;
        public static int SET_DISPLAY_OFF_CURSOR_OFF_BLINK_OFF = 0x08;
        public static int SET_DISPLAY_ON_CURSOR_OFF_BLINK_OFF = 0x0C;
        public static int CLEAR = 0x01;
        public static int HOME = 0x02;

        public static int currentDisplayMode = 0x08;
        public static int DISPLAY_ON = 0x04;
        public static int CURSOR_ON = 0x02;
        public static int BLINK_ON = 0x01;

        public static int SET_CURSOR_MOVE_RIGHT_ADDRESS_INCREMENT = 0x06;
        public static int ONE_SECOND = 1000;
        public static int TWO_SECONDS = 2000;
        public static int TEN_TIMES = 10;


        public static void delayMilliSeconds(int count)        {
            for (int i = 0; i < count; i++)
            {
                for (int j = 0; j < 25; j++)
                {
                    /// do nothing
                }
            }
        }

        public static void delayMicroSeconds(int count)        {
            for (int i = 0; i < (count / 50); i++) // one loop == 50 uS
            {
                /// do nothing
            }
        }

        public Lcd(OutputPort[] lcdOutputPortArray, int lineLength)        {
            _rsPort = lcdOutputPortArray[0];
            _enablePort = lcdOutputPortArray[1];
            _dataPort0 = lcdOutputPortArray[2];
            _dataPort1 = lcdOutputPortArray[3];
            _dataPort2 = lcdOutputPortArray[4];
            _dataPort3 = lcdOutputPortArray[5];
            _lineLength = lineLength;

            dataOutputPortArray = new OutputPort[4];
            dataOutputPortArray[0] = _dataPort0;
            dataOutputPortArray[1] = _dataPort1;
            dataOutputPortArray[2] = _dataPort2;
            dataOutputPortArray[3] = _dataPort3;

            // if (_lineLength == 16)
            //  setupLcd();

            // if (_lineLength == 20)
            // setupLcd();
        }

        public void setupLcd()        {
            delayMilliSeconds(20); // wait > 15mS for LCD's Vcc to reach 4.5V

            writeInstructionPseudo8BitMode(SET_8_BIT_INTERFACE_0X30);
            delayMilliSeconds(5); // wait > 4.1 mS

            writeInstructionPseudo8BitMode(SET_8_BIT_INTERFACE_0X30); // wait > 100 uS by default
            writeInstructionPseudo8BitMode(SET_8_BIT_INTERFACE_0X30); // wait > 100 uS by default
            writeInstructionPseudo8BitMode(SET_4_BIT_INTERFACE_0X20); // wait > 100 uS by default
            writeInstruction4BitMode(SET_4_BIT_TWO_LINES_FIVE_TIMES_EIGHT_DOTS);
            writeInstruction4BitMode(currentDisplayMode | DISPLAY_ON | CURSOR_ON & ~BLINK_ON);
            clear(); // > 1.53 mS
            home(); // > 1.53 mS               
        }

        public void writeLcdPin(OutputPort outputPort, bool portSignal)        {
            if (portSignal == HIGH)
                outputPort.Write(HIGH);
            else
                outputPort.Write(LOW);
        }

        public void selectInstructionRegister()        {
            writeLcdPin(_rsPort, LOW);
        }

        public void selectDataRegister()        {
            writeLcdPin(_rsPort, HIGH);
        }

        public void disableWritePulse()        {
            writeLcdPin(_enablePort, LOW);
        }

        public void enableWritePulse()        {
            writeLcdPin(_enablePort, HIGH);
            writeLcdPin(_enablePort, LOW);
        }

        public void writeNibble(int dataByte, int nibblePosition, int registerType)        {
            if (registerType == 0)
                selectInstructionRegister();
            else
                selectDataRegister();

            disableWritePulse();
            if (nibblePosition == HIGH_NIBBLE)
            {
                for (int i = 0; i < 4; i++)  // write high nibble
                {
                    if (((dataByte >> (i + 4)) & 0x01) == 1)
                        writeLcdPin(dataOutputPortArray[i], HIGH);
                    else
                        writeLcdPin(dataOutputPortArray[i], LOW);
                }
            }

            if (nibblePosition == LOW_NIBBLE)
            {
                for (int i = 0; i < 4; i++)  // write low nibble
                {
                    if (((dataByte >> i) & 0x01) == 1)
                        writeLcdPin(dataOutputPortArray[i], HIGH);
                    else
                        writeLcdPin(dataOutputPortArray[i], LOW);
                }
            }

            enableWritePulse();
            delayMicroSeconds(200);
        }

        public void writeDataByte(int dataByte, int registerType)        {
            writeNibble(dataByte, HIGH_NIBBLE, registerType);
            writeNibble(dataByte, LOW_NIBBLE, registerType);
        }

        public void writeInstructionPseudo8BitMode(int instruction)        {
            writeNibble(instruction, HIGH_NIBBLE, INSTRUCTION_REGISTER);
        }

        public void writeInstruction4BitMode(int instruction)        {
            writeDataByte(instruction, INSTRUCTION_REGISTER);
        }

        public void writeData4BitMode(int instruction)        {
            writeDataByte(instruction, DATA_REGISTER);
        }

        public void writeDataByte8BitMode(int dataByte, int registerType)        {
            if (registerType == 0)
                selectInstructionRegister();
            else
                selectDataRegister();

            disableWritePulse();
            for (int i = 0; i < 8; i++)
            {
                if (((dataByte >> i) & 0x01) == 1)
                    writeLcdPin(dataOutputPortArray[i], HIGH);
                else
                    writeLcdPin(dataOutputPortArray[i], LOW);
            }

            enableWritePulse();
            delayMicroSeconds(100);
        }

        public void writeInstruction8BitMode(int instruction)        {
            writeDataByte8BitMode(instruction, INSTRUCTION_REGISTER);
        }

        public void writeData8BitMode(int instruction)        {
            writeDataByte8BitMode(instruction, DATA_REGISTER);
        }

        public void clear()
        {
            writeDataByte(CLEAR, INSTRUCTION_REGISTER);
            delayMilliSeconds(2);
        }

        public void home()        {
            writeDataByte(HOME, INSTRUCTION_REGISTER);
            delayMilliSeconds(2);
        }

        void cursor(int row, int column)        {
            switch (row)
            {
                case 1:
                    writeDataByte(0x80 | (0x00 + (column - 1)), INSTRUCTION_REGISTER);
                    break;
                case 2:
                    writeDataByte(0x80 | (0x40 + (column - 1)), INSTRUCTION_REGISTER);
                    break;
                case 3:
                    if (_lineLength == 16)
                        writeDataByte(0x80 | (0x10 + (column - 1)), INSTRUCTION_REGISTER); // 0x10 for 16 char
                    else
                        writeDataByte(0x80 | (0x14 + (column - 1)), INSTRUCTION_REGISTER); // 0x14 for 20 char
                    break;
                case 4:
                    if (_lineLength == 16)
                        writeDataByte(0x80 | (0x50 + (column - 1)), INSTRUCTION_REGISTER); // 0x50 for 16 char
                    else
                        writeDataByte(0x80 | (0x54 + (column - 1)), INSTRUCTION_REGISTER); // 0x54 for 20 char
                    break;
                default:
                    break;
            }
        }

        void cursor20(int row, int column)        {
            switch (row)
            {
                case 1:
                    writeDataByte(0x80 | (0x00 + (column - 1)), INSTRUCTION_REGISTER);
                    break;
                case 2:
                    writeDataByte(0x80 | (0x40 + (column - 1)), INSTRUCTION_REGISTER);
                    break;
                case 3:
                    writeDataByte(0x80 | (0x14 + (column - 1)), INSTRUCTION_REGISTER);
                    break;
                case 4:
                    writeDataByte(0x80 | (0x54 + (column - 1)), INSTRUCTION_REGISTER);
                    break;
                default:
                    break;
            }
        }


        public void printChar(char xchar)        {
            writeData4BitMode(xchar);
        }

        public void printLine(string str)        {
            char[] charArray;
            charArray = str.ToCharArray(0, str.Length);

            foreach (char ch in charArray)
            {
                printChar(ch);
            }
        }

        public void printLineRowColumn(string str, int row, int column)        {
            cursor(row, column);

            char[] charArray;
            charArray = str.ToCharArray(0, str.Length);

            foreach (char ch in charArray)
            {
                printChar(ch);
            }
        }

        public void blinkDisplay(int count)        {
            int displayOn = (currentDisplayMode | DISPLAY_ON | CURSOR_ON & ~BLINK_ON);
            int displayOff = (currentDisplayMode & ~DISPLAY_ON | CURSOR_ON & ~BLINK_ON);

            for (int i = 0; i < count; i++)
            {
                writeDataByte(0x08, INSTRUCTION_REGISTER);
                delayMilliSeconds(500);
                writeDataByte(0x0C, INSTRUCTION_REGISTER);
                delayMilliSeconds(500);
            }
        }

        /*
        ///  Timing calibration functions

        public static void display2TicksBetween1Second()
        {
            Lcd lcd = new Lcd("LCD1602", Pins.GPIO_PIN_D8, Pins.GPIO_PIN_D9, Pins.GPIO_PIN_D10, Pins.GPIO_PIN_D11, Pins.GPIO_PIN_D12, Pins.GPIO_PIN_D13);

            var tick1 = Utility.GetMachineTime().Ticks;
            string str1 = tick1.ToString();
            lcd.cursor(1, 1);
            lcd.printLine("T1 = ");
            lcd.printLine(str1);

            Thread.Sleep(1000);
            var tick2 = Utility.GetMachineTime().Ticks;
            string str2 = tick2.ToString();
            lcd.cursor(2, 1);
            lcd.printLine("T2 = ");
            lcd.printLine(str2);
        }

        /// Note: There are 1,194,645 ticks in 1 second, or 0.837uS per tick (1,194,688)
        public static void displayNumberOfTicksIn1Second()        {
            Lcd lcd = new Lcd("LCD1602", Pins.GPIO_PIN_D8, Pins.GPIO_PIN_D9, Pins.GPIO_PIN_D10, Pins.GPIO_PIN_D11, Pins.GPIO_PIN_D12, Pins.GPIO_PIN_D13);

            var tick1 = Utility.GetMachineTime().Ticks;
            Thread.Sleep(1000);
            var tick2 = Utility.GetMachineTime().Ticks;
            lcd.cursor(1, 1);
            lcd.printLine("Tk/S = ");
            string ticks = ((tick2 - tick1)).ToString();
            lcd.printLine(ticks);
            lcd.printLine("          ");

            lcd.cursor(2, 1);
            lcd.printLine("Tk/mS =   ");
            ticks = ((tick2 - tick1) / 1000).ToString();
            lcd.printLine(ticks);
            lcd.printLine("          ");
        }

        /// Note: There are 10004053 ticks/S, 10004ticks/mS, or 0.1uS/tick or 100 nS/tick
        public static void displayDelayTimeOfNoOpLoops(long loopCount)        {
            Lcd lcd = new Lcd("LCD1602", Pins.GPIO_PIN_D8, Pins.GPIO_PIN_D9, Pins.GPIO_PIN_D10, Pins.GPIO_PIN_D11, Pins.GPIO_PIN_D12, Pins.GPIO_PIN_D13);

            lcd.cursor(1, 1);
            lcd.printLine("Loops = ");
            lcd.printLine(loopCount.ToString());

            var tick1 = Utility.GetMachineTime().Ticks;
            // while (loopCount-- > 0)
            // {
            // do nothing
            // }

            for (int i = 0; i < loopCount; i++)
            {
                // do nothing
            }

            var tick2 = Utility.GetMachineTime().Ticks;
            lcd.cursor(2, 1);
            lcd.printLine("Seconds =   ");
            string ticks = ((tick2 - tick1) / 10004503).ToString();
            lcd.printLine(ticks);
            lcd.printLine("          ");
        }

        // Note: 250,000 noop while loops == 12 seconds => 1 second has 20,833 loops => 1 loop == 48 uS
        //       250,000 noop for loops == 11 second => 1 second = 22,727 loops, 1 loop == 44 uS

        public static void displaySecondsTimer(int secondCount)        {
            Lcd lcd = new Lcd("LCD1602", Pins.GPIO_PIN_D8, Pins.GPIO_PIN_D9, Pins.GPIO_PIN_D10, Pins.GPIO_PIN_D11, Pins.GPIO_PIN_D12, Pins.GPIO_PIN_D13);

            lcd.cursor(1, 1);
            lcd.printLine(secondCount.ToString());
            lcd.printLine(" Seconds begin");

            long loopCount = secondCount * 22727;
            for (long i = 0; i < loopCount; i++)
            {
                //do nothing
            }

            lcd.cursor(2, 1);
            lcd.printLine(secondCount.ToString());
            lcd.printLine(" Seconds end");
        }

        public static void displayRealTime()        {
            Lcd lcd = new Lcd("LCD1602", Pins.GPIO_PIN_D8, Pins.GPIO_PIN_D9, Pins.GPIO_PIN_D10, Pins.GPIO_PIN_D11, Pins.GPIO_PIN_D12, Pins.GPIO_PIN_D13);

            lcd.printLineRowColumn("Hello Kitty 003", 1, 1);
            DateTime dt1 = new DateTime(2011, 4, 17, 12, 39, 0);
            // String.Format("{0:yyyy MMM dd mm ss tt}", dt1);
            lcd.printLineRowColumn(dt1.ToString("s"), 2, 1);
        }

        public static void testLcd1604(string str_title, string str_date, string str03, string str04)        {
            Lcd lcd = new Lcd("LCD1602", Pins.GPIO_PIN_D8, Pins.GPIO_PIN_D9, Pins.GPIO_PIN_D10, Pins.GPIO_PIN_D11, Pins.GPIO_PIN_D12, Pins.GPIO_PIN_D13);
            lcd.cursor(1, 1);
            lcd.printLine(str_title);
            lcd.cursor(2, 1);
            lcd.printLine(str_date);
            lcd.cursor(3, 1);
            lcd.printLine(str03);
            lcd.cursor(4, 1);
            lcd.printLine(str04);
            lcd.blinkDisplay(3);
        }

        public static void testLcd2004(string str_title, string str_date, string str03, string str04)        {
            Lcd lcd = new Lcd("LCD1602", Pins.GPIO_PIN_D8, Pins.GPIO_PIN_D9, Pins.GPIO_PIN_D10, Pins.GPIO_PIN_D11, Pins.GPIO_PIN_D12, Pins.GPIO_PIN_D13);
            lcd.cursor20(1, 1);
            lcd.printLine(str_title);
            lcd.cursor20(2, 1);
            lcd.printLine(str_date);
            lcd.cursor20(3, 1);
            lcd.printLine(str03);
            lcd.cursor20(4, 1);
            lcd.printLine(str04);
            lcd.blinkDisplay(3);
        }

        public static void testGetNetworkTime()        {
            DateTime currentTime = NtpClient.GetNetworkTime("hk.pool.ntp.org");
            Debug.Print("*** Current Network Time is " + currentTime.ToString("s") + " ***");

            string fileName = @"\SD\text03.txt";
            FileStream sdFileHandler = File.Exists(fileName)
                    ? new FileStream(fileName, FileMode.Append)
                    : new FileStream(fileName, FileMode.Create);

            StreamWriter sdFileWriter = new StreamWriter(sdFileHandler);
            sdFileWriter.WriteLine(currentTime.ToString("s"));
            sdFileWriter.Flush();
            sdFileWriter.Close();

            Lcd lcd = new Lcd("LCD1602", Pins.GPIO_PIN_D8, Pins.GPIO_PIN_D9, Pins.GPIO_PIN_D10, Pins.GPIO_PIN_D11, Pins.GPIO_PIN_D12, Pins.GPIO_PIN_D13);
            lcd.printLineRowColumn("Network Time Test", 1, 1);
            lcd.printLineRowColumn(currentTime.ToString("s"), 2, 1);
            lcd.blinkDisplay(3);
        }
         */
    }

/// *************************************************************************
/// Class: TestLcd
/// Created: 2012jun21
/// Updated: 2011jun22
/// *************************************************************************

using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Diagnostics;
using Microsoft.SPOT;
using Microsoft.SPOT.IO;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.NetduinoPlus;
using Microsoft.SPOT.Net.NetworkInformation;

namespace Soner01
{
    public class TestLcd    {
        // *** General declarations ***

        public static bool LOW = false;
        public static bool HIGH = true;

        public static Int16 OFF = 0;
        public static Int16 ON = 1;

        public static bool USE_GLITCH_FILTER = true;
        public static int ledChannelNumber = 0;
        public static int lcd1602ChannelNumber = 1;
        public static int lcd2004ChannelNumber = 2;

        public static int lineLength16 = 16;
        public static int lineLength20 = 20;

        // *** Beeper declarations ***
        public Cpu.Pin beeperPwmPin = Pins.GPIO_PIN_D5;
        // *** Led declarations ***
        public Cpu.Pin ledPinLe = Pins.GPIO_PIN_D8;
        public Cpu.Pin ledPinDp = Pins.GPIO_PIN_D9;

        public Cpu.Pin ledPinDataA = Pins.GPIO_PIN_D10;
        public Cpu.Pin ledPinDataB = Pins.GPIO_PIN_D11;
        public Cpu.Pin ledPinDataC = Pins.GPIO_PIN_D12;
        public Cpu.Pin ledPinDataD = Pins.GPIO_PIN_D13;

        public OutputPort ledLePort;
        public OutputPort ledDpPort;
        public OutputPort ledDataPortA;
        public OutputPort ledDataPortB;
        public OutputPort ledDataPortC;
        public OutputPort ledDataPortD;

        // *** Lcd declarations ***
        public OutputPort lcdRsPort;
        public OutputPort lcdEnablePort;
        public OutputPort lcdDataPort4;
        public OutputPort lcdDataPort5;
        public OutputPort lcdDataPort6;
        public OutputPort lcdDataPort7;

        // *** TestLed constructor ***
        public TestLcd()        {
            // *** create PWM buzzerPort and create Buzzer buzzer ***

            PWM buzzerPort = new PWM(Pins.GPIO_PIN_D5);
            Buzzer buzzer = new Buzzer(buzzerPort);

            // *** Create DeMux ***
            OutputPort deMuxAddPort0 = new OutputPort(Pins.GPIO_PIN_D0, LOW);
            OutputPort deMuxAddPort1 = new OutputPort(Pins.GPIO_PIN_D1, LOW);
            OutputPort deMuxAddPort2 = new OutputPort(Pins.GPIO_PIN_D2, LOW);
            OutputPort deMuxLePort = new OutputPort(Pins.GPIO_PIN_D3, LOW);

            OutputPort deMuxDataPort0 = new OutputPort(Pins.GPIO_PIN_D8, LOW);
            OutputPort deMuxDataPort1 = new OutputPort(Pins.GPIO_PIN_D9, LOW);
            OutputPort deMuxDataPort2 = new OutputPort(Pins.GPIO_PIN_D10, LOW);
            OutputPort deMuxDataPort3 = new OutputPort(Pins.GPIO_PIN_D11, LOW);
            OutputPort deMuxDataPort4 = new OutputPort(Pins.GPIO_PIN_D12, LOW);
            OutputPort deMuxDataPort5 = new OutputPort(Pins.GPIO_PIN_D13, LOW);

            OutputPort[] deMuxDataPortArray = new OutputPort[4];
            deMuxDataPortArray[0] = deMuxLePort;
            deMuxDataPortArray[1] = deMuxAddPort0;
            deMuxDataPortArray[2] = deMuxAddPort1;
            deMuxDataPortArray[3] = deMuxAddPort2;

            Demux demux = new Demux(deMuxDataPortArray);
            // *** Create Lcd ***
            OutputPort lcdRsPort = deMuxDataPort0;
            OutputPort lcdEnablePort = deMuxDataPort1;
            OutputPort lcdDataPort4 = deMuxDataPort2;
            OutputPort lcdDataPort5 = deMuxDataPort3;
            OutputPort lcdDataPort6 = deMuxDataPort4;
            OutputPort lcdDataPort7 = deMuxDataPort5;

            OutputPort[] lcdOutputPortArray = new OutputPort[6];
            lcdOutputPortArray[0] = lcdRsPort;
            lcdOutputPortArray[1] = lcdEnablePort;
            lcdOutputPortArray[2] = lcdDataPort4;
            lcdOutputPortArray[3] = lcdDataPort5;
            lcdOutputPortArray[4] = lcdDataPort6;
            lcdOutputPortArray[5] = lcdDataPort7;


            // *** Test LCD1602 ***
            Lcd lcd1602 = new Lcd(lcdOutputPortArray, lineLength16);
            demux.selectChannel(lcd1602ChannelNumber);

            lcd1602.setupLcd();
            lcd1602.clear();
            lcd1602.home();

            lcd1602.printLineRowColumn("LCD Test 1602 01", 1, 1);
            lcd1602.printLineRowColumn("2012sep10       ", 2, 1);

            // *** Test LCD2004 ***
            Lcd lcd2004 = new Lcd(lcdOutputPortArray, lineLength20);
            demux.selectChannel(lcd2004ChannelNumber);

            lcd2004.setupLcd();
            lcd2004.clear();
            lcd2004.home();

            lcd2004.printLineRowColumn("LCD Test 2004 02", 1, 1);
            lcd2004.printLineRowColumn("2012sep10       ", 2, 1);
            lcd2004.printLineRowColumn("Line 03         ", 3, 1);
            lcd2004.printLineRowColumn("Line 04         ", 4, 1);

            Debug.Print("*** testLcd() ends. ***");
            buzzer.beep(200, 200, 4);
        }
    }
}

.END

No comments:

Post a Comment