Ability to scroll lines in 4x20 display
I need some help in understanding how to do this. If anyone has some examples or sample code it would be much appreciated.
What I have is a 4x20 display with a rotary encoder and I want the ability to scroll through received data sent to the display. Lets say for example I have a buffer I want to scroll through that has 300 bytes of characters in it. The display is only capable of 80 at a time.
So what I am thinking is there needs to be a way that I can store the 300 bytes of characters maybe in an array? And then be able to scroll through the array in 20 byte chunks only moving the lines up or down depending on the turn of the encoder.
I have no idea how to do this or if it can even be done.
Thanks for your help.
Don
What I have is a 4x20 display with a rotary encoder and I want the ability to scroll through received data sent to the display. Lets say for example I have a buffer I want to scroll through that has 300 bytes of characters in it. The display is only capable of 80 at a time.
So what I am thinking is there needs to be a way that I can store the 300 bytes of characters maybe in an array? And then be able to scroll through the array in 20 byte chunks only moving the lines up or down depending on the turn of the encoder.
I have no idea how to do this or if it can even be done.
Thanks for your help.
Don

Comments
For LC-Display-characters an array of bytes is sufficient
I haven't tested the code below. It is meant as a raw template to give you an idea how it can be done
The buffer contains the 300 ASCII-codes of the data you want to display.
VAR byte Buffer[300] long Index long n PUB OneLineUp Index := Index - 20 if Index < 0 Index := 0 repeat n from 0 to 79 LCD.SendChar(Buffer[Index + n] PUB OneLineDown Index := Index + 20 If Index > 220 Index := 220 repeat n from 0 to 80 LCD.SendChar(Buffer[Index + n]mabye you have to add a command to switch to the next line
keep the questions coming
best regards
Stefan
The use of constant is to optimize the code a bit so that the math operations are done at compile time and a fixed value is inserted into the actual bytecode.
The #> and <# are used to constrain the values in one shot instead of doing multiple evaluations.
The code simplifies scrolling by simply sending the direction the encoder has turned. This allows you to use standard encoder reading objects that return direction.
http://obex.parallax.com/objects/576/
Thanks.
Don
pedward- what does the variable "offset" in the method DisplayBuffer(offset) represent?
Help!
con _clkmode = xtal1 + pll16x _clkfreq = 80_000_000 MS_001 = 80_000_000 / 1_000 buffer_size = 300 obj oled : "oled" ' 4-bit OLED driver encdr : "grayenc2_with_pb" ' 2-bit, graycode encoder var byte buffer[300] long index pub main | n oled.init(0, 20, 4) ' initialize display on P0 pause(500) encdr.init(20, 1, 0, 100, 50, 22) ' detented encoder on P20 and pushbutton on P22 oled.cmd(oled#CLS) ' clear display pause(200) oled.moveto(1, 1) oled.str(string("Character Scrolling ")) oled.moveto(1, 2) oled.str(string("demo on 4x20 display")) if encdr.read > 50 index += 20 index := index #> 0 <# constant(buffer_size - 80) oled.moveto(1, 1) repeat n from 0 to constant(79) oled.str(message[index] + n) pub pause(ms) | t t := cnt repeat ms waitcnt(t += MS_001) dat message byte "Line 1 of display..." byte "Line 2 of display..." byte "Line 3 of display..." byte "Line 4 of display..." byte "Line 5 of display..." byte "Line 6 of display..." byte "Line 7 of display..." byte "Line 8 of display..." byte "Line 9 of display..." byte "Line 10 of display.." byte "Line 11 of display.." byte "Line 12 of display.." byte "Line 13 of display.." byte "Line 14 of display.." byte "Line 15 of display.." byte "Line 16 of display.." byte "Line 17 of display.." byte "Line 18 of display.." byte "Line 19 of display.." byte "Line 20 of display.."If so I'd still suggest to use my driver, as it takes care of all. I checked it with the LCD_menu.spin demo which comes with the driver. It uses exactly what you need for the scrolling:
This line will start the driver
Setup of lines which use a buffer:
In CMD_SETLEN you specify the width of the line. In the demo it's 11 because I want some cursor-characters on the left and on the right. You would simply set it to 40.
With CMD_SETLINE you specify the start-position for a line. $40 is the LCD-address of the 2nd line, so specifying $42 means that the 3rd character of line 2 is the start of the characters controlled by the buffer. ($00,$40,$14 and $54 are the start addresses of the different lines of the display.) @menu is the address of the buffer itself.
In my demo-code I setup 3 lines for a menu using the same buffer at different positions. Of course you can also setup 3 lines with 3 different buffers of different size ... or only 1 line with 1 buffer.
Scrolling all 3 lines is then as easy as that:
if scroll_left LCD.exec( LCD#CMD_OTSCROLL, 14<<16 + 14<<8 + 14 ) else LCD.exec( LCD#CMD_OTSCROLL, (255-13)<<16 + (255-13)<<8 + 255-13 )where 14 and (255-13) is the number of characters to scroll and <<16 / <<8 / <<0 tells which line to scroll.So, scrolling only one line 40 characters looks like
LCD.exec( LCD#CMD_OTSCROLL, 40 )
In your code you simply update the buffer as you like. It's like a screen-buffer and the display-driver will take care of refreshing the LCD.
con _clkmode = xtal1 + pll16x _clkfreq = 80_000_000 MS_001 = 80_000_000 / 1_000 buffer_size = 300 obj oled : "oled" ' 4-bit OLED driver encdr : "grayenc2_with_pb" ' 2-bit, graycode encoder VAR byte Buffer[300] long Index long n ,lyne pub Main | oldval, newval oled.init(0, 20, 4) ' initialize display on P0 pause(500) encdr.init(20, 1, 0, 100, 50, 22) ' detented encoder on P20 and pushbutton on P22 oled.cmd(oled#CLS) ' clear display pause(200) oled.moveto(1, 1) oled.str(string("Character Scrolling ")) oled.moveto(1, 2) oled.str(string("demo on 4x20 display")) bytemove(@Buffer, @message, 300) 'fills the buffer encdr.set(10) oldval := 0 Index := 0 repeat newval := encdr.read // 10 if newval > oldval OneLineDown elseif newval < oldval OneLineUp oldval := newval oled.moveto(17, 1) oled.dec(Index) pause(250) PUB OneLineUp Index := Index - 20 if Index < 0 Index := 0 repeat lyne from 1 to 4 oled.moveto(1, lyne) repeat n from 0 to 19 oled.out(Buffer[Index+((lyne-1)*20) + n]) PUB OneLineDown Index := Index + 20 If Index > 220 Index := 220 repeat lyne from 1 to 4 oled.moveto(1, lyne) repeat n from 0 to 19 oled.out(Buffer[Index+((lyne-1)*20) + n]) PUB send20 oled.moveto(1, lyne) repeat n from 0 to 80 oled.out(Buffer[Index + n]) pub pause(ms) | t t := cnt repeat ms waitcnt(t += MS_001) dat message byte "Line 1 of display..." byte "Line 2 of display..." byte "Line 3 of display..." byte "Line 4 of display..." byte "Line 5 of display..." byte "Line 6 of display..." byte "Line 7 of display..." byte "Line 8 of display..." byte "Line 9 of display..." byte "Line 10 of display.." byte "Line 11 of display.." byte "Line 12 of display.." byte "Line 13 of display.." byte "Line 14 of display.." byte "Line 15 of display.." byte "Line 16 of display.." byte "Line 17 of display.." byte "Line 18 of display.." byte "Line 19 of display.." byte "Line 20 of display.."No need to create an extra buffer.
And scrolling works with:
if newval > oldval LCD.exec( LCD#CMD_OTSCROLL, 20<<24 + 20<<16 + 20<<8 + 20 ) elseif newval < oldval LCD.exec( LCD#CMD_OTSCROLL, 20<<24 + (255-19)<<16 + (255-19)<<8 + 255-19 )Maybe you can extend the if statements a bit to avoid scrolling when you reached the boundaries.