[h=2] Re: LCD text wrapping and looking at previous text cut off?[/h]
To MagIO2,
You will never see something else but the content of char[0]-char[31]. At least I'd expect to have an offset which can be set, so that the display starts at other lines.
Why you don't see anything ... $1f might be undefined in the display. The useable characters usually start at $20 (=space). You can easily print out all the characters of the display to see which will show something and which not, as this is depending on the brand of the display anyways. Also above 128 you can find anything, for example chinese characters....
In other words: Try it with a character where you know that it should display something
Line byte "X"[320]
How do you set an offset? Also, to clarify, i used $1F as an example, but had no intention that it would present other character. So, what is the highest hexadecimal number that shows english text and computer commands (i.e.- carriage return)?
And what do you mean by "over 128, you can find anything? Is that also referring to hexadecimal value?
What also do you mean by "Line byte "X"[320], if it can't exceed 128? I am confused about that.
$1F is what you print on the LCD right? And you expect to see something! But some of the values available in a byte simply show nothing on the display as the ROM font of the LCD display does not contain pixels for these characters.
I would start with a small program which shows you all the possible characters from 0-255 ($00-$FF). Then you will see what characters the brand which produces the LCD has implemented. The first characters (I think 8) are definitely empty because you can add user defined character data there. As in most environments the byte values below $20 are considered as control characters, some LCDs will show nothing here. The range from $20-$7f is defined according to the ASCII characters (have a look in wikipedia). And above $7F it again depends on the brand what characters you will find there. As I said, I've seen displays showing chinese symbols.
If you want to store text-characters in a byte you can also use "X" for example. You don't have to know which byte value represents the X.
List
byte "X"[320]
will simply create 320 times X in the List-array.
"How do you set an offset?"
Well ... let's assume a line can be bigger than 16 characters, say 64 characters. If you have a backlog of 10 rows in HUB-RAM you will still only be able to show a 16x2 window on the LCD. The backlog buffer would be
byte backlog[ 64*10 ]
If you want to show a window on the LCD you have to define where to start - this is what I mean with offset. An offset of 0 will show the first row. An offset of 64 will show the 2nd row. 128 shows the 3rd row .....
With an offset of 1, the display will start at the 2nd column. An offset of 140 will start output in row 3 column 12.
A display loop would look like that:
repeat y from 0 to 1
repeat x from 0 to 15
lcd.putc( backlog[ offset + y*64 + x ] )
It is probably a sad indication of being a nerdy propellerhead asking how many ascii values you can name off the top of your head. I'll start with (decimal) 7,10,13,27,32 and 65. Others will no doubt be able to do more. Bonus points for knowing the decimal and hex values!
Hey, guys.
I finally got some code up for LCD byte sending practice, and i would like to know about this problem:
When i send the characters through the repeat loop, and try to copy the characters through a different loop, all i get on the serial LCD is backslashes. What am i doing wrong?
That is slightly odd. Looking at the code, I would have expected you would have got nothing on the display.
What are you trying to do on the display? One thing that is sometimes helpful is to put comments on each line saying what that line does. Then you can go through each line and ask - is this doing what I actually want it to do?
Are you trying to print some ascii characters from 32 to 126?
I think what you really want to do in the first loop is:
repeat backlog from 1 to 94
char[ backlog ] := char[ backlog - 1] + 1
backlog++ is wrong at this place, as the repeat loop already increments the variable.
This would create a sequence of characters starting from $21 in the char-array.
That's a good lesson to learn. But you can also change the code I gave you to work with the serial interface LCD. You simply write a little loop which permanently writes the content of a screen-buffer to the LCD. Pretty much the same you do in your second loop.
1. resize char array to char[ 2*16 ]
2. change the 1st loop to initialize the LCD with spaces (" " or $20)
3. put gotoxy(x, y) outside of the loop - I guess this display also will put chars coming in a sequence on behind the other
4. do the lcd.putc for 32 characters without waitcnt
5. start this 2nd loop in it's own COG
6. in my code replace all @scrbuf1 by @char and all @scrbuf2 by @char+16 and remove all LCD.* related code.
Thanks, MagIO2.
To answer Dr. Acula's question, i was praciticing buffering code to the 2x16 character serial LCD by using a repeat loop to initialize the data, incrementing the ASCII hex value by 1 to get different characters. Then, the next repeat loop takes the characters and prints the first 5 (it can be any number up to 32). However, i get the first character right, but the rest are just slashes, which aren't next in the ASCII. What's going on? Sorry about my lack of documentation. I'll do that from now on.
MagIO2:
backlog++ is wrong at this place, as the repeat loop already increments the variable.
This would create a sequence of characters starting from $21 in the char-array.
That's a good lesson to learn. But you can also change the code I gave you to work with the serial interface LCD. You simply write a little loop which permanently writes the content of a screen-buffer to the LCD. Pretty much the same you do in your second loop.
1. resize char array to char[ 2*16 ]
2. change the 1st loop to initialize the LCD with spaces (" " or $20)
3. put gotoxy(x, y) outside of the loop - I guess this display also will put chars coming in a sequence on behind the other
1. where do i start if i was to use your own code?
2. resizing the char array would make the entire memory map short, right? i wanted to make a large array, then buffer parts to the LCD.
3. The gotoxy should be in the loop if i want to move over to the next column to fill the character, right? I'm confused about why it has to be on the outside.
4. Does all LCDs have to be initialized with spaces before buffering actual characters to and from the memory array?
I'd first start with understanding the proposed changes to your code.
The goal is to have a screenbuffer just big enough to keep the content of one screen and continuously send the characters to the LCD. This will run in it's own COG endlessly! The advantage is that each other COG can simply write into the screenbuffer and the content will show up on the screen automatically.
About 2.)
Yes, the buffer you need in HUB-RAM is just as big as the LCD screen. The backlog is written to the SWAP-file which can be any size!
About 3.)
Gotoxy is only needed once if you write characters that should appear one after the other. The LCD has an internal pointer which is incremented automatically. So, if you call gotoxy 1,1 the pointer will be set. If you then call putc the character is written to position 1,1. If you then send another character with putc it's written on position 2,1 .....
At best you only need gotoxy once to set it to the upper left corner and then send 32 characters in a row
at worst it only works per line: goto upper left corner, send 16 characters, goto next line, print 16 characters
About 4.)
It's not about initializing the LCD, it's about initializing the screenbuffer which is sent to the LCD continuously.
About 1.)
1. Do the changes to your code.
2. Make your code a function
3. Copy into my code and call COGNEW on this function
4. Make my code write into your screenbuffer (@char/@char+16) instead of (@scrbuf1/@scrbuf2).
i was copying your code, and i encountered a problem:
sdfat.vOpenSwap( 0, string("SWAP3.SYS") )
--- vOpenSwap is not a subroutine file. Is there another variation of fsrw, or is this your modification mentioned earlier?
....and second
PUB dec( adr, val ) | i
i := 0
IF (val < 0)
-val
byte[ adr ][ i++ ] := "-"
i:=5
if val>0
repeat while val<>0
byte[ adr ][i--]:="0"+val//10
val:=val/10
else
byte[ adr ]:="0"
i was copying your code, and i encountered a problem:
sdfat.vOpenSwap( 0, string("SWAP3.SYS") )
--- vOpenSwap is not a subroutine file. Is there another variation of fsrw, or is this your modification mentioned earlier?
....and second
PUB dec( adr, val ) | i
i := 0
IF (val < 0)
-val
byte[ adr ][ i++ ] := "-"
i:=5
if val>0
repeat while val<>0
byte[ adr ][i--]:="0"+val//10
val:=val/10
else
byte[ adr ]:="0"
As I wrote in #30: "It's available in the forum http://forums.parallax.com/showthread.php?117573-Virtual-Memory ." Maybe it also helps to read the thread, as you have to prepare the SD-card. (1. format it, 2. copy a SWAP3.SYS to it which is big enough...)
The purpose of the loop is to convert a long to a decimal string. Each iteration will output a digit.
// gives you the rest of the division. val // 10 simply means it gives you the value of the least significant digit. For example: 123 will give you a 3.
Adding 3 to "0" converts the numerical 3 to the character "3". In the next step val := val / 10 the 3 is removed from the number, as in integer you have no fractional part. 123 / 10 = 12.
If this division is somewhen 0 you're done with converting the number.
I was analyzing your code for your LCD screen buffer and i would like to have a simulation of how the (PUB dec) works. What exactly does it do to the strings? Why does it say :
if val>0 repeat while val<>0
byte[ adr ][i--]:="0"+val//10
val:=val/10
else
byte[ adr ][i]:="0"
The second and third line confuses me by what it does. Please explain, thnx.
I was analyzing your code for your LCD screen buffer and i would like to have a simulation of how the (PUB dec) works. What exactly does it do to the strings? Why does it say :
Code:
if val>0 repeat while val<>0 byte[ adr ][i--]:="0"+val//10 val:=val/10 else byte[ adr ]:="0"
The second and third line confuses me by what it does. Please explain, thnx.
I'm so sure that I already explained this dec ... either it's a deja'vu or I'm getting to old ...
Ok, this DEC seems to be a special version, as it can only convert up to 6 digits without overwriting something because of the
i:=5. The point is, that i goes from 5 to 0 - from right to left. The digit on the right is the units digit, so you are not interested in the any amount above 9. You get this by using the modulo operator //. So, let's say value := 1234 -> value // 10 = 4. But now you have the binary value and you have to convert it to ASCII for the output. Fortunately the ASCII characters for numbers are sorted starting with "0", then "1", "2".... As ASCIIs are also numbers for a uC, you can simply add "0" + 4 to get "4".
For the next loop the units digit is no longer needed, so we do a decimal "shift" of the number by dividing by 10:
value := value / 10 which results in 1234 / 10 = 123. Now the next units digit of value is really the tens digit of the original number, that's why it's written left hand side of the buffer.
Next loop will work with 12, next with 1 and the next loop gives you a 0 which tells the loop that we're done.
The point of doing it this way (right to left) is, that each number is right alligned no matter how many digits it has (0-6).
I bought the parallax keyboard and microSD and the ps2 header, and i am ready to start. I've already got text onto the LCD from the keyboard using simple getkey commands from the keyboard object.
How do i start with the microSD and buffering the text from the mSD to the LCD and still get the key input from the keyboard?
Comments
You will never see something else but the content of char[0]-char[31]. At least I'd expect to have an offset which can be set, so that the display starts at other lines.
Why you don't see anything ... $1f might be undefined in the display. The useable characters usually start at $20 (=space). You can easily print out all the characters of the display to see which will show something and which not, as this is depending on the brand of the display anyways. Also above 128 you can find anything, for example chinese characters....
In other words: Try it with a character where you know that it should display something
Line byte "X"[320]
How do you set an offset? Also, to clarify, i used $1F as an example, but had no intention that it would present other character. So, what is the highest hexadecimal number that shows english text and computer commands (i.e.- carriage return)?
And what do you mean by "over 128, you can find anything? Is that also referring to hexadecimal value?
What also do you mean by "Line byte "X"[320], if it can't exceed 128? I am confused about that.
I would start with a small program which shows you all the possible characters from 0-255 ($00-$FF). Then you will see what characters the brand which produces the LCD has implemented. The first characters (I think 8) are definitely empty because you can add user defined character data there. As in most environments the byte values below $20 are considered as control characters, some LCDs will show nothing here. The range from $20-$7f is defined according to the ASCII characters (have a look in wikipedia). And above $7F it again depends on the brand what characters you will find there. As I said, I've seen displays showing chinese symbols.
If you want to store text-characters in a byte you can also use "X" for example. You don't have to know which byte value represents the X.
List
byte "X"[320]
will simply create 320 times X in the List-array.
"How do you set an offset?"
Well ... let's assume a line can be bigger than 16 characters, say 64 characters. If you have a backlog of 10 rows in HUB-RAM you will still only be able to show a 16x2 window on the LCD. The backlog buffer would be
byte backlog[ 64*10 ]
If you want to show a window on the LCD you have to define where to start - this is what I mean with offset. An offset of 0 will show the first row. An offset of 64 will show the 2nd row. 128 shows the 3rd row .....
With an offset of 1, the display will start at the 2nd column. An offset of 140 will start output in row 3 column 12.
A display loop would look like that:
http://www.asciitable.com/
$7E according to the table.
It is probably a sad indication of being a nerdy propellerhead asking how many ascii values you can name off the top of your head. I'll start with (decimal) 7,10,13,27,32 and 65. Others will no doubt be able to do more. Bonus points for knowing the decimal and hex values!
(sometimes it takes awhile to get facts into your head and make it work properly. Thank you for your patience.)
I'll most likely post more code as time progresses for revision.
I finally got some code up for LCD byte sending practice, and i would like to know about this problem:
When i send the characters through the repeat loop, and try to copy the characters through a different loop, all i get on the serial LCD is backslashes. What am i doing wrong?
TransmitLCD 3.spin
What are you trying to do on the display? One thing that is sometimes helpful is to put comments on each line saying what that line does. Then you can go through each line and ask - is this doing what I actually want it to do?
Are you trying to print some ascii characters from 32 to 126?
backlog++ is wrong at this place, as the repeat loop already increments the variable.
This would create a sequence of characters starting from $21 in the char-array.
That's a good lesson to learn. But you can also change the code I gave you to work with the serial interface LCD. You simply write a little loop which permanently writes the content of a screen-buffer to the LCD. Pretty much the same you do in your second loop.
1. resize char array to char[ 2*16 ]
2. change the 1st loop to initialize the LCD with spaces (" " or $20)
3. put gotoxy(x, y) outside of the loop - I guess this display also will put chars coming in a sequence on behind the other
4. do the lcd.putc for 32 characters without waitcnt
5. start this 2nd loop in it's own COG
6. in my code replace all @scrbuf1 by @char and all @scrbuf2 by @char+16 and remove all LCD.* related code.
To answer Dr. Acula's question, i was praciticing buffering code to the 2x16 character serial LCD by using a repeat loop to initialize the data, incrementing the ASCII hex value by 1 to get different characters. Then, the next repeat loop takes the characters and prints the first 5 (it can be any number up to 32). However, i get the first character right, but the rest are just slashes, which aren't next in the ASCII. What's going on? Sorry about my lack of documentation. I'll do that from now on.
MagIO2:
1. where do i start if i was to use your own code?
2. resizing the char array would make the entire memory map short, right? i wanted to make a large array, then buffer parts to the LCD.
3. The gotoxy should be in the loop if i want to move over to the next column to fill the character, right? I'm confused about why it has to be on the outside.
4. Does all LCDs have to be initialized with spaces before buffering actual characters to and from the memory array?
The goal is to have a screenbuffer just big enough to keep the content of one screen and continuously send the characters to the LCD. This will run in it's own COG endlessly! The advantage is that each other COG can simply write into the screenbuffer and the content will show up on the screen automatically.
About 2.)
Yes, the buffer you need in HUB-RAM is just as big as the LCD screen. The backlog is written to the SWAP-file which can be any size!
About 3.)
Gotoxy is only needed once if you write characters that should appear one after the other. The LCD has an internal pointer which is incremented automatically. So, if you call gotoxy 1,1 the pointer will be set. If you then call putc the character is written to position 1,1. If you then send another character with putc it's written on position 2,1 .....
At best you only need gotoxy once to set it to the upper left corner and then send 32 characters in a row
at worst it only works per line: goto upper left corner, send 16 characters, goto next line, print 16 characters
About 4.)
It's not about initializing the LCD, it's about initializing the screenbuffer which is sent to the LCD continuously.
About 1.)
1. Do the changes to your code.
2. Make your code a function
3. Copy into my code and call COGNEW on this function
4. Make my code write into your screenbuffer (@char/@char+16) instead of (@scrbuf1/@scrbuf2).
i was copying your code, and i encountered a problem:
sdfat.vOpenSwap( 0, string("SWAP3.SYS") )
--- vOpenSwap is not a subroutine file. Is there another variation of fsrw, or is this your modification mentioned earlier?
....and second
PUB dec( adr, val ) | i
i := 0
IF (val < 0)
-val
byte[ adr ][ i++ ] := "-"
i:=5
if val>0
repeat while val<>0
byte[ adr ][i--]:="0"+val//10
val:=val/10
else
byte[ adr ]:="0"
What is the purpose of this loop? I am curious.
MagIO2,
i was copying your code, and i encountered a problem:
sdfat.vOpenSwap( 0, string("SWAP3.SYS") )
--- vOpenSwap is not a subroutine file. Is there another variation of fsrw, or is this your modification mentioned earlier?
....and second
PUB dec( adr, val ) | i
i := 0
IF (val < 0)
-val
byte[ adr ][ i++ ] := "-"
i:=5
if val>0
repeat while val<>0
byte[ adr ][i--]:="0"+val//10
val:=val/10
else
byte[ adr ]:="0"
What is the purpose of this loop? I am curious.
As I wrote in #30: "It's available in the forum http://forums.parallax.com/showthread.php?117573-Virtual-Memory ." Maybe it also helps to read the thread, as you have to prepare the SD-card. (1. format it, 2. copy a SWAP3.SYS to it which is big enough...)
The purpose of the loop is to convert a long to a decimal string. Each iteration will output a digit.
// gives you the rest of the division. val // 10 simply means it gives you the value of the least significant digit. For example: 123 will give you a 3.
Adding 3 to "0" converts the numerical 3 to the character "3". In the next step val := val / 10 the 3 is removed from the number, as in integer you have no fractional part. 123 / 10 = 12.
If this division is somewhen 0 you're done with converting the number.
I was analyzing your code for your LCD screen buffer and i would like to have a simulation of how the (PUB dec) works. What exactly does it do to the strings? Why does it say :
The second and third line confuses me by what it does. Please explain, thnx.
I was analyzing your code for your LCD screen buffer and i would like to have a simulation of how the (PUB dec) works. What exactly does it do to the strings? Why does it say :
Code:
if val>0 repeat while val<>0 byte[ adr ][i--]:="0"+val//10 val:=val/10 else byte[ adr ]:="0"
The second and third line confuses me by what it does. Please explain, thnx.
Ok, this DEC seems to be a special version, as it can only convert up to 6 digits without overwriting something because of the
i:=5. The point is, that i goes from 5 to 0 - from right to left. The digit on the right is the units digit, so you are not interested in the any amount above 9. You get this by using the modulo operator //. So, let's say value := 1234 -> value // 10 = 4. But now you have the binary value and you have to convert it to ASCII for the output. Fortunately the ASCII characters for numbers are sorted starting with "0", then "1", "2".... As ASCIIs are also numbers for a uC, you can simply add "0" + 4 to get "4".
For the next loop the units digit is no longer needed, so we do a decimal "shift" of the number by dividing by 10:
value := value / 10 which results in 1234 / 10 = 123. Now the next units digit of value is really the tens digit of the original number, that's why it's written left hand side of the buffer.
Next loop will work with 12, next with 1 and the next loop gives you a 0 which tells the loop that we're done.
The point of doing it this way (right to left) is, that each number is right alligned no matter how many digits it has (0-6).
How do i start with the microSD and buffering the text from the mSD to the LCD and still get the key input from the keyboard?