Main Site Documentation

2x16 LCD Scroll


#1

Is there a simple way to scroll a 2x16 LCD or do I have to shift each display segment myself?


#2

Jeff’s Live Text is great to deal with this
(link removed) and
http://lcdlivetext.codeplex.com/. Worth checking out !


#3

Yeh I think I already saw that and doesn’t it involve using the input keys?

What I mean is marquee style, I know the arduino liquidcrystal lib supports this, perhaps I should try and port it although I’m not too up on how arduino works :confused:


#4

The demo app with LCD Live Text uses the buttons but there is absolutely no reason you ‘have’ to use buttons to make it scroll. The Scroll method is publicly accessible so you can call it with what ever logic suites your needs.

        /// <summary>
        /// Scroll display
        /// </summary>
        /// <param name="direction">Scroll direction</param>
        public void Scroll(ScrollDirection direction)
        {
            switch (direction)
            {
                case ScrollDirection.Up:
                    if (Offset_Y > 0) { Offset_Y--; }
                    break;
                case ScrollDirection.Down:
                    if (Offset_Y < VirtualRows - LCD_Rows) { Offset_Y++; }
                    break;
                case ScrollDirection.Right:
                    if (Offset_X < VirtualCols - LCD_Cols) { Offset_X++; }
                    break;
                case ScrollDirection.Left:
                    if (Offset_X > 0) { Offset_X--; }
                    break;
            }

            updateScrollIcon();
            flags |= Flags.update;
        }

#5

Yes but this is scrolling en-mass I’m talking about a scrolling marquee, I got something going by simply shifting each block however it’s a bit flickery. I know the Arduino takes commands to do this and it makes it a bit smoother but I’m unsure how to use them/how they work.

You can see their LiquidCrystal codes here: http://github.com/arduino/Arduino/tree/master/libraries/LiquidCrystal/

I think it just instructs the LCD to move it’s own internal character buffers :confused:


#6

If you use the built in scrolling in the LCD then it will shift the whole display as well as you are just changing the memory cell that is used for the top/left cell and you are limited to the 40 column memory width for each line. To make a marque style for a single line you would have to add a bit of code to include an offset per row.


#7

I managed to get it scrolling however things seem to slow down when I start using the second line as well (for example scroll first, keep second static). The events are firing off on time it’s just not updating in the timeframe alloted, am I missing some fundamental thing?

The LCD updates like this:


        private static void ThreadProc()
        {
            while (true) {
                // Copy buffers to screen
                lock (locker) {
                    /*
                    for(int i = 0; i < 16; i++) {
                        // First line
                        SetCursor(0,(byte)i);
                        PutChar(line_1_buffer[i]);

                        // Second line
                        SetCursor(1,(byte)i);
                        PutChar(line_2_buffer[i]);
                    }
                     */

                    SetCursor(0,0);

                    for (int i = 0; i < 16; i++) PutChar(line_1_buffer[i]);

                    SetCursor(1,0);

                    for (int i = 0; i < 16; i++) PutChar(line_2_buffer[i]);
                }

                // Sleep
                Thread.Sleep(10);
            }
        }

        public static void UpdateBuffer(int line, byte[] buffer)
        {
            // Copy buffers
            lock (locker) {
                switch (line) {
                    case 0: buffer.CopyTo(line_1_buffer,0);
                            break;
                    case 1: buffer.CopyTo(line_2_buffer,0);
                            break;
                }
            }
        }

Each of the lines update like this:


        private void OnTimer(object state)
        {
            string buffer;

            if (!scroll) {
                // Copy into buffer
                if (text.Length < 16) {
                    buffer = text;

                    while (buffer.Length < 16) buffer += " ";
                } else {
                    buffer = text.Substring(0,16);
                }
            } else {
                // Set up initial scroll buffer if it's empty
                if (scroll_buffer == String.Empty) scroll_buffer = CLEAR_LINE + text;

                // Copy scroll buffer into buffer
                if (scroll_buffer.Length < 16) {
                    buffer = scroll_buffer;

                    // Add padding to buffer
                    while (buffer.Length < 16) buffer += " ";
                } else {
                    buffer = scroll_buffer.Substring(0,16);
                }

                // Chew off the first character in the scroll buffer
                if (scroll_counter >= scroll_interval) {
                    scroll_buffer = scroll_buffer.Substring(1);
                    scroll_counter = 0;
                } else {
                    scroll_counter += 10;
                }
            }

            byte[] byte_buffer = new byte[16];

            for(int i = 0; i < 16; i++) byte_buffer[i] = 32;

            for(int i = 0; i < buffer.Length; i++) {
                if (i > 15) break;

                byte_buffer[i] = (byte)buffer[i];
            }

            LCDDriver.UpdateBuffer(row,byte_buffer);
        }

Anybody have any thoughts?


#8

No thoughts? :frowning:


#9

I thought those displays have a built in command to rotate text. I never used it though but I remember seeing it


#10

From what I have found, yes and no, it has commands to scroll etc but from what I can tell it moves them en-mass and not like a marquee.

Also of the commands I’ve tried I haven’t been able to get most to work :confused:


#11

So, I figured what the main issue slowing things down was, I was updating constantly regardless of any changes to what is displayed. Adding a check to see if new buffer was different from last buffer and only updating then seems to settle things.

Anyhow I’ve posted the driver musings at: http://www.tinyclr.com/forum/4/1362/


#12

Since ‘you’ are the one making any changes, just set a flag to indicated that the display needs to be refreshed. The next time the refresh timer fires you look for the state of the flag and output to the LCD if needed. No need to compare buffers.


#13

Yeh that would be better, I’ll modify the code to reflect that idea.


#14

I wouldn’t use much code

I would create a string object and duplicate the first 16 chars at the end, then change it to a byte array and just blit 16 chars at a time to the screen and just move the byte array pointer.

flushing the 2x16 is extremely quick so it would be too fast and you would need to slow it down

Cheers Ian


#15

[quote]I would create a string object and duplicate the first 16 chars at the end, then change it to a byte array and just blit 16 chars at a time to the screen and just move the byte array pointer.
[/quote]

Sort of what I did for LCDLiveText. I did not include scrolling individual rows or marque style scrolling. I created a byte array that is virtual rows * virtual columns in size and just adjust index into this array for each row. There are several different ways to handle a marquee style scroll, My first thought was to keep a secondary index into the row to indicate the offset position and then copying from the source array to the destination array for the LCD becomes just like working with a circular buffer.