CharacterDisplay Module on 4.3

Hi guys,

With 4.2 framework I was using a custom CharacterDisplay class that allowed me to set & show custom characters by means of 2 functions that are named CustomCharSet and CustomCharPrint.

Now I want to upgrade to 4.3 framework so I downloaded the CharacterDisplay 4.3 class (here: https://bitbucket.org/ghi_elect/gadgeteer/src/985ade835fd675b6b1cf004aa4bc732eca8d5244/Modules/GHIElectronics/CharacterDisplay/CharacterDisplay_43/CharacterDisplay_43.cs?at=master ) and I copied the 2 functions I need for custom characters… but something doesn’t work.

Can you help me to understand where is the error?

Thx, this is the class I edited:

namespace Gadgeteer.Modules.GHIElectronics
{
    /// <summary>
    /// A CharacterDisplay module for Microsoft .NET Gadgeteer
    /// </summary>
    public class Display_HD44780_AGI_43 : GTM.Module
    {
        private GTI.DigitalOutput lcdRS;
        private GTI.DigitalOutput lcdE;

        private GTI.DigitalOutput lcdD4;
        private GTI.DigitalOutput lcdD5;
        private GTI.DigitalOutput lcdD6;
        private GTI.DigitalOutput lcdD7;

        private GTI.DigitalOutput backlight;

        private int currentRow;

        private static byte[] ROW_OFFSETS = new byte[4] { 0x00, 0x40, 0x14, 0x54 };
        private const byte DISP_ON = 0x0C;
        private const byte CLR_DISP = 1;
        private const byte CUR_HOME = 2;
        private const byte SET_CURSOR = 0x80;

        private void WriteNibble(byte b)
        {
            this.lcdD7.Write((b & 0x8) != 0);
            this.lcdD6.Write((b & 0x4) != 0);
            this.lcdD5.Write((b & 0x2) != 0);
            this.lcdD4.Write((b & 0x1) != 0);

            this.lcdE.Write(true);
            this.lcdE.Write(false);

            Thread.Sleep(1);
        }

        private void SendCommand(byte command)
        {
            this.lcdRS.Write(false);

            this.WriteNibble((byte)(command >> 4));
            this.WriteNibble(command);

            Thread.Sleep(2);

            this.lcdRS.Write(true);
        }

        /// <summary>Constructs a new instance.</summary>
        /// <param name="socketNumber">The socket that this module is plugged in to.</param>
        public Display_HD44780_AGI_43(int socketNumber)
        {
            Socket socket = Socket.GetSocket(socketNumber, true, this, null);

            socket.EnsureTypeIsSupported('Y', this);

            this.lcdRS = GTI.DigitalOutputFactory.Create(socket, GT.Socket.Pin.Four, false, null);
            this.lcdE = GTI.DigitalOutputFactory.Create(socket, GT.Socket.Pin.Three, false, null);
            this.lcdD4 = GTI.DigitalOutputFactory.Create(socket, GT.Socket.Pin.Five, false, null);
            this.lcdD5 = GTI.DigitalOutputFactory.Create(socket, GT.Socket.Pin.Seven, false, null);
            this.lcdD6 = GTI.DigitalOutputFactory.Create(socket, GT.Socket.Pin.Nine, false, null);
            this.lcdD7 = GTI.DigitalOutputFactory.Create(socket, GT.Socket.Pin.Six, false, null);

            this.backlight = GTI.DigitalOutputFactory.Create(socket, GT.Socket.Pin.Eight, true, null);

            this.currentRow = 0;

            this.SendCommand(0x33);
            this.SendCommand(0x32);
            this.SendCommand(Display_HD44780_AGI_43.DISP_ON);
            this.SendCommand(Display_HD44780_AGI_43.CLR_DISP);

            Thread.Sleep(3);
        }

        /// <summary>
        /// Prints the passed in string to the screen at the current cursor position. 
        /// A newline character (\n) will move the cursor to the start of the next row.
        /// </summary>
        /// <param name="value">The string to print.</param>
        public void Print(string value)
        {
            for (int i = 0; i < value.Length; i++)
                this.Print(value[i]);
        }

        /// <summary>
        /// Prints a character to the screen at the current cursor position.
        /// A newline character (\n) will move the cursor to the start of the next row.
        /// </summary>
        /// <param name="value">The character to display.</param>
        public void Print(char value)
        {
            if (value != '\n')
            {
                this.WriteNibble((byte)(value >> 4));
                this.WriteNibble((byte)value);
            }
            else
            {
                this.SetCursorPosition((this.currentRow + 1) % 2, 0);
            }
        }

        /// <summary>
        /// Clears the screen.
        /// </summary>
        public void Clear()
        {
            this.SendCommand(Display_HD44780_AGI_43.CLR_DISP);

            Thread.Sleep(2);
        }

        /// <summary>
        /// Places the cursor at the top left of the screen.
        /// </summary>
        public void CursorHome()
        {
            this.SendCommand(Display_HD44780_AGI_43.CUR_HOME);

            Thread.Sleep(2);
        }

        /// <summary>
        /// Moves the cursor to given position.
        /// </summary>
        /// <param name="row">The new row.</param>
        /// <param name="column">The new column.</param>
        public void SetCursorPosition(int row, int column)
        {
            if (column > 15 || column < 0) throw new System.ArgumentOutOfRangeException("column", "column must be between 0 and 15.");
            if (row > 1 || row < 0) throw new System.ArgumentOutOfRangeException("row", "row must be between 0 and 1.");

            this.currentRow = row;

            this.SendCommand((byte)(Display_HD44780_AGI_43.SET_CURSOR | Display_HD44780_AGI_43.ROW_OFFSETS[row] | column));
        }

        /// <summary>
        /// Whether or not the backlight is enabled.
        /// </summary>
        public bool BacklightEnabled
        {
            get
            {
                return this.backlight.Read();
            }
            set
            {
                this.backlight.Write(value);
            }
        }


        public void CustomCharSet(byte memory_position, byte charRow0, byte charRow1, byte charRow2, byte charRow3, byte charRow4, byte charRow5, byte charRow6, byte charRow7)
        {
            //first command starts the character definition by setting 1 of the 8 memory locations dedicated to storage.
            switch (memory_position)
            {
                case 0:
                    SendCommand(0x40);
                    break;
                case 1:
                    SendCommand(0x41);
                    break;
                case 2:
                    SendCommand(0x42);
                    break;
                case 3:
                    SendCommand(0x43);
                    break;
                case 4:
                    SendCommand(0x44);
                    break;
                case 5:
                    SendCommand(0x45);
                    break;
                case 6:
                    SendCommand(0x46);
                    break;
                case 7:
                    SendCommand(0x47);
                    break;
            }

            //next 8 commands send the character definition
            SendCommand(charRow0);
            SendCommand(charRow1);
            SendCommand(charRow2);
            SendCommand(charRow3);
            SendCommand(charRow4);
            SendCommand(charRow5);
            SendCommand(charRow6);
            SendCommand(charRow7);

            Thread.Sleep(1);
        }

        public void CustomCharPrint(byte memory_position)
        {
            switch (memory_position)
            {
                case 0:
                    SendCommand(0x80);
                    break;
                case 1:
                    SendCommand(0x81);
                    break;
                case 2:
                    SendCommand(0x82);
                    break;
                case 3:
                    SendCommand(0x83);
                    break;
                case 4:
                    SendCommand(0x84);
                    break;
                case 5:
                    SendCommand(0x85);
                    break;
                case 6:
                    SendCommand(0x86);
                    break;
                case 7:
                    SendCommand(0x87);
                    break;
            }
        }



    }
}

Weekly doesn’t work?

I think Gus wants to know exactly what doesnt work? Please clarify that error you get, and give more details.

I meant what doesn’t work?

sorry, you’re right!
First of all: the code is compiled with success.

At runtime the char display works but when I set the first custom char it changes its behavior.
Setting a custom char causes the erasing of all characters displayed and thereafter the char display doesn’t show nothing anymore. It seems that I write those custom chars in wrong memory sectors, but the char display is always the same… the only one change is the framework.

@ BigFoot - The character display is very sensitive to timings, they could have changed slightly between 4.2 and 4.3. If you can, I would verify with a logic analyzer what you see on the lines and compare it to what the module expects in its datasheet.

@ John - Unfortunately I don’t have a logic analyzer (and I never used it).
What do you suggest?

@ BigFoot - try setting one character if possible and see if it works. When we had some timing issues, adding Sleeps throughout the code improved reliability.

@ John - I fixed the code and I created a codeshare for who might need in future: https://www.ghielectronics.com/community/codeshare/entry/947

Hope this helps.