PDA

View Full Version : Can someone help me to modify Darrel Taylor's STRINGS.PBP



jessey
- 14th October 2005, 10:04
Hello Everyone

I'm looking for a way to modify Darrel's program but I don't understand the ASM portion of his code. I've managed to modify parts of the PBP portion of the program and it works like a charm. Has anyone here used Darrel Taylor's STRINGS.PBP? http://www.pbpgroup.com/modules/wfsection/article.php?articleid=10 It's a great routine that saves heaps of code space when printing to an Lcd. I'm using it in a program for printing multiple instructions (over 150 prints @ 18 words ea) to the Lcd which explains to the user how the program functions and how to program the different variables needed to have the program operate efficiently. Probably as good as having a printed manual but one that you can't loose. I'm also using it for each button press to display (while the button is pressed) where the program is going and what's happening, which I think makes it easier to navigate all the user functions.

The strings.pbp code is set up (thanks to Darrel's help) with two pushbuttons to control the instruction functions, one to view the first print then each additional press of the same pushbutton prints the next screen. The other pushbutton ends the viewing and returns to the main program loop.

What I'd like to be able to do, is to implement in the asm code portion of the routine, additional code so that a third pushbutton could be used to view the previous print in the Inst1: subroutine if that's possible? Having a "view previous print pushbutton" would be the icing on the cake for my program! Can anyone help me out with this one? I've included some parts of my program that relates to Darrel's code in an attachment below that shows how my pushbuttons are set up to use Darrel's code.

Thanks
jessey

Darrel Taylor
- 14th October 2005, 16:03
Hi jessey,

Wow, there's 15 set's of instructions in there now? There were only 2 when the chip was "Maxed Out" to begin with. Cool!

It should be pretty easy, but it's been over a year since I've seen this program. Give me a little time to digest it again, and I'll get back to you.

.

Darrel Taylor
- 14th October 2005, 17:12
Oh, that wasn't too tough afterall.

First, you need to declare the button's input, and add a variable.
PrevButton VAR PORTB.0 ' Or, wherever it is
PrevPressed VAR BITThen change the routines shown here. Modifications are in Red.
ShowInstructions:
ButtonDown = 1 ' Button was pressed to get here
If T = 1 THEN PauseTime = PageTime ' display each screen for 20ms
If S = 1 THEN PauseTime = PageTime2 ' display each screen for 1ms
DisplayCount = 0 ' Reset the loop counter
ShowAgain: ' Start from 1st instruction
Finished = 0
Addr = CurrentInst ' Set the address of the Instruction text
NextPage:
LCDOUT $FE,2 ' Home cursor
GOSUB DisplayPage ' Display 1 Page
KeepWaiting:
GOSUB ButtonPause ' Check buttons while pausing
IF PrevPressed = 1 THEN
PrevPressed = 0
IF Addr - 36 >= CurrentInst THEN
Addr = Addr - 36
ELSE
GOTO KeepWaiting
ENDIF
ENDIF
If Finished = 1 THEN InstructionsDone ' if The_Lcd_Push_Button Finished=1
Readcode Addr, TwoChars ' Check for END of instructions
if (TwoChars & $7F) = $7E THEN InstructionsDone
goto NextPage ' if not EOF display next page
InstructionsDone:
DisplayCount = DisplayCount + 1
if DisplayCount = MaxShows THEN Finished = 1
If Finished = 0 THEN ShowAgain
Return

' ------------------------------------------[ Watch buttons while Pausing ]-----
ButtonPause:
for PauseLoop = 1 to PauseTime ' approx. 1 ms per loop
pauseUS 980

If ButtonDown = 1 THEN ' If a button is already Pressed
GOSUB DebounceButtons ' wait for it to be released
Else ' ELSE If ButtonDown = 0 THEN
IF S = 1 THEN ' Display description of button press
ButtonDown = 1 ' set var
Finished = 1 ' Indicate that we're done reading
S = 0 ' this is set to = 1 in mainloop 1ms
Return ' Go back to mainloop with 1ms pause
endif

if The_Lcd_Push_Button = Is_Pressed THEN
ButtonDown = 1 ' set var
Finished = 1 ' Indicate that we're done reading
T = 0 ' this is set to = 1 in mainloop 20 sec
Return ' go back to the mainloop.
EndIF

If View_Instructions_Push_Button = Is_Pressed THEN
ButtonDown = 1 ' set var
PWM Buzzer,175,1 ' indicate were going to the next page
Return ' Stop pausing and Goto next Page
EndIf

IF PrevButton = Is_Pressed THEN
ButtonDown = 1
PrevPressed = 1
RETURN
ENDIF

EndIf
next PauseLoop
Return

DebounceButtons:
If The_Lcd_Push_Button = Is_Not_Pressed THEN
IF View_Instructions_Push_Button = Is_Not_Pressed THEN
IF PrevButton = Is_Not_Pressed THEN
PAUSE 20
IF PrevButton = Is_Not_Pressed THEN
If The_Lcd_Push_Button = Is_Not_Pressed THEN
IF View_Instructions_Push_Button = Is_Not_Pressed THEN ButtonDown = 0
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
RETURN

Completely Un-Tested though.

.

jessey
- 15th October 2005, 23:57
Hi Darrel

Wow that was quick, I sure appreciate your help. I'll try implementing your changes and get to you as soon as possible with the results.

Thanks Again
jessey

jessey
- 19th October 2005, 12:22
Hi Darrel

Thanks for your improvements. Your PrevPressed code works like a charm but I noticed that when the Inst1: subroutine reaches the end print that it doesn't return like it should. All the other ones that are used for button press descriptions work to return though. Any ideas on what I did wrong or what I can do to get it to work as intended? I managed to get it to return by using a counter to return when the last print is counted but it dosen't display the last screen.

I've spent the last few nights (late nights) working on your code with great results. I've managed to add code to your STRINGS.PBP that allows me to navigate through the 148 prints of instructions with relative ease. I've included the code I wrote to compliment your PrevPressed routine for you to look at.

In the main portion of my program, I have a few variables that are user adjustable using up and down pushbuttons, so I used those 2 existing push buttons to go up and down to view
the next and previous screens for the instructions. Then I added some more code and using another existing push button that when pressed together with either the up or down pushbutton performs a sort of auto repeat that advances or reverses the prints to the Lcd very quickly. I used counters to keep track of which print was showing to the Lcd then added IF..THEN's before the counters to be able to stop at certain prints (preset numbers) that will be the beginning of an instruction topic to make it easy to find the different topics without having to go through all 148 prints to find them. It took a few late nights to get it working properly but it sure was worth it.

I'd appreciate it if you could have a look at it to see if you see any hidden got ya's in my new updated routines. Another question, I've maxed out the amount of prints I can get in my program without getting an error when compiling, is there a way to get more prints to the Lcd with your program?

Thanks for your help
jessey

Darrel Taylor
- 22nd October 2005, 20:36
Jessey,

I haven't found anything that would cause a problem with just Inst1:

The only thing i can think of is that maybe one on the DA statements has the wrong number of characters in it. The Prev button relies on there being exactly 18 bytes per "print" to work properly. The lastest program you posted looks fine in that respect, but it's not the real data, so maybe you could check them.

As for packing more text in the program, well, it may be time for a bigger chip, or to move it all off chip into some eeprom. uggg

.

jessey
- 13th December 2005, 08:52
Jessey,

I haven't found anything that would cause a problem with just Inst1:

The only thing i can think of is that maybe one on the DA statements has the wrong number of characters in it. The Prev button relies on there being exactly 18 bytes per "print" to work properly. The lastest program you posted looks fine in that respect, but it's not the real data, so maybe you could check them.

As for packing more text in the program, well, it may be time for a bigger chip, or to move it all off chip into some eeprom. uggg

.

Hello Darrel,

I finally got my package delivered and switched my code for your strings over to a bigger chip, I'm now using a 18F452. I have my DS1820 thermostat code running on the 18F452 and everything is working good now but I can't seem to get your STRINGS example for the 16-bit pic's to work using the LCDOUT command. It was over a year ago now, if you can remember back that far (no pun intended LOL), that you helped me set up the strings for the 14-bit 16F877 using push buttons for multiple prints and switching the hserout to LCDOUT commands.

I have since modified your strings example for the 16F877 code and it works like a charm, I even got it to return with the last print now. Now I'd like to be able add more prints hopefully by switching over to this bigger chip. I really hate to bother you with this but I've exhausted all attempts at modifying your example for the 18F's. If you get some time, could you please look over my code and offer any suggestions, I'd sure appreciate it. I did get it to work with limited success but am really struggling. Maybe I should be looking to switch my LCDOUT commands to using HSEROUT but I can't seem to find any code examples that explain how to do that. I've included the strings as I have it written for the 16f877.

Thanks
jessey

Darrel Taylor
- 14th December 2005, 06:44
Hi Jessey,

Yeah, the 18F's work with bytes instead of words, so the addressing needs to be different.

I think you should be able to change this
NextWord:
Addr = Addr + 1 ' Point to next two characters
goto DisplayPage ' Continue with rest of the string
PageDone:
Addr = Addr + 1 ' Point to next two characters


to this

NextWord:
Addr = Addr + 2 ' Point to next two characters
goto DisplayPage ' Continue with rest of the string
PageDone:
Addr = Addr + 2 ' Point to next two characters


But then that sounds too easy to be true. :)

.

jessey
- 14th December 2005, 13:12
Hello Darrel,

I did as you suggested with limited success as I'm now getting screens that have unreadable charters in the instructions. I have both the forward and reverse buttons working good now to advance and go previous one at a time and also to advance quickly and go previous quickly when the button is held down for 2 1/2 seconds. In order to get the buttons working properly I had to change the statement below from 36 to 72.

IF Addr - 72 >= CurrentInst THEN ' it reverses now with 72
Addr = Addr - 72 ' it wouldn't reverse with the 2-72's being 36

I think the garbled text has something to do with the TwoChars Variable because I tried using your original code example from your web site for the 18F's to use the Char Variable just to see and it did print but just the top line of the display and of course it wouldn't advance but it did print the top line as it was written in my code. Below is what I tried. I've been trying various things to try and resolve it but am stumped now.

StringOut: ' Send the string out via Hserout
Readcode Addr, Char ' Get a character
if Char = 0 then StringDone ' Look for Null char, Stop if found
LCDOUT Char ' Send char
Addr = Addr + 1 ' Point to next character
GOTO StringOut ' Continue with rest of the string
StringDone:
return

Any ideas on what I could try to get it to print properly? I really appreciate your help.

Thanks
jessey

Darrel Taylor
- 8th January 2006, 01:05
Hi again jessey,

Saw your message on the old list. Again, sorry!

So where are we? Are things pretty much the same as in the last post, or did you make any progress?

Darrel

jessey
- 8th January 2006, 13:46
Hi Darrel,

Thanks for your time here, I just thought you were busy and I didn't want to bother you.

About the only thing I found was that when I implemented your changes was that I got unreadable charters and using short presses of the #1 button did advance the prints one at a time and holding down the #1 button for a couple of seconds did advance the prints to my preset stops ok but the #2 button to go to a previous screen didn't work at all until I changed the 36's to 72's as I posted in my last reply. My buttons do work as expected now.

I'm completely lost but I think it has something to do with the TwoChars Variable over-flowing or something (just a guess)? Maybe it has something to do with this statement "Char = TwoChars >> 7", but like I say, I don't understand the asm portion of the code or the reasoning for the shifts so I'm lost here as well. I'm sure it doesn't have anything to do with the modifications I made to the pbp portion of the code which is posted in a previous post here. Any ideas?

Thanks
jessey

mister_e
- 8th January 2006, 17:47
I've never tried with 18F but, have you compare your code with the suggested 16bit core version from darrel's site? DA will work slightly different from 14 to 16bits core.

http://www.pbpgroup.com/modules/wfsection/article.php?articleid=10


For use with 16-bit PIC's

The 16-bit PIC's work with things as bytes instead of words, so it actually becomes easier to extract the strings. Instead of reading 2 characters at a time, you only have to get 1. Here is a modification to the strings program above for use with PIC18x chips.

The only real difference is in the StringOut routine.

'************************************************* ***************
'* Name : STRINGS-16.PBP *
'* Author : Darrel Taylor *
'* Date : 6/12/2005 *
'* Note: Strings must be NULL Terminated *
'************************************************* ***************
DEFINE LOADER_USED 1 ' If using bootloader
DEFINE OSC 4
DEFINE HSER_TXSTA 24h ' Use this for Higher Baud Rates
DEFINE HSER_SPBRG 25 ' 9600 Baud at 4mhz

Addr var word
Char var byte

Clear

goto StartLoop ' Required

String1:
@ da "This is a string",0

AnotherString:
@ da "Here is another string",0

'------------GetAddress Macro - Location insensitive -------------------------
ASM
GetAddress macro Label, Wout ; Returns the Address of a Label as a Word
CHK?RP Wout
movlw low Label
movwf Wout
movlw High Label
movwf Wout + 1
endm
ENDASM


StartLoop ' This loop repeats continuously just as a test.
@ GetAddress _String1, _Addr ' Get address of String
gosub StringOut ' Send the String
hserout [13,10] ' New Line

@ GetAddress _AnotherString, _Addr ' Get address of String
gosub StringOut ' Send the String
hserout [13,10] ' New Line
pause 500
goto StartLoop ' Repeat


StringOut: ' Send the string out via Hserout
Readcode Addr, Char ' Get a character
if Char = 0 then StringDone ' Look for Null char, Stop if found
hserout [Char] ' Send char
Addr = Addr + 1 ' Point to next character
goto StringOut ' Continue with rest of the string
StringDone:
return


end


There's also some great thread in this forum. Do a search with embedded string

hth

Darrel Taylor
- 8th January 2006, 23:11
There we go, get a little Team work going here. Hi Steve.

And yes, I think the 16-bit version is the way to go since the 18F's work at a Byte-size level. But it causes a couple problems with the old version that was written for a 14-bit core.

The Original version used DA to pack 2 7-bit bytes into a 14-bit word. This left us without the ability to include $FE,$C0 in the data to jump to the second line. So we replaced $FE,$C0 with 0x7F in the data, and made the substitution during the printout.

Now that it's on a 16-bit device, that limitation is gone. But "DA" still tries to align everything to Word Boundaries, so 0x7F ends up being 2 bytes in the data 007F. Then when reading back 1 byte at a time, it comes across the first 0x00h and says, I found a "0", I must be done. But it's not.

Same thing happens with the 0, at the end of each screen. Here's the data for 2 lines
0001C2 4120 4C4C 574F da " ALLOW THE SOIL ", 0x7F, "TO DRY OUT UNTIL",0
5420 4548 5320
494F 204C 007F
4F54 4420 5952
4F20 5455 5520
544E 4C49 0000


So, let's get rid of the 0x7F, and replace it with 0xC0FE. The result looks like ...
0001C2 4120 4C4C 574F da " ALLOW THE SOIL ", 0xC0FE, "TO DRY OUT UNTIL",0
5420 4548 5320
494F 204C C0FE
4F54 4420 5952
4F20 5455 5520
544E 4C49 0000


Now we should be able to send the data without any 0x7F translation. But we still have an extra 00 at the end. So when it finds the end of the screen marker "00", it can just add 2 to the address, so it will skip the second 00.

Here's the way the data should look now
Inst1:
ASM
da " TO SET THE ", 0xC0FE, "WATERING SCEDULE",0
da " ALLOW THE SOIL ", 0xC0FE, "TO DRY OUT UNTIL",0
da " IT REQUIRES ", 0xC0FE, " A WATERING ",0
da " THEN ADJUST ", 0xC0FE, " THE PUMP ON # ",0
da " BY ROTATING POT", 0xC0FE, " #4 UNTIL IT ",0
da "EQUALS THE MOIST", 0xC0FE, "# AT WHICH TIME ",0
da " THE PUMP WILL ", 0xC0FE, " TURN ON ",0
da " NOW EVERY TIME ", 0xC0FE, "IT DRIES OUT TO ",0
da " THAT MOISTURE ", 0xC0FE, "LEVEL IT WILL BE",0
da " WATERED ", 0xC0FE, " AUTOMATICALLY ",0
da " SET IT ONCE AND", 0xC0FE, " FORGET IT ",0
da " PRESS SWITCH 4 ", 0xC0FE, " TO EXIT ",0,0x7E
EndAsm ' The Last word must always be 0x7E


And, here's the new DisplayPage routine
DisplayPage: ' Send the string to the LCD
Readcode Addr, Char ' Get a character
if Char = 0 then StringDone ' Look for Null char, Stop if found
LCDOUT Char ' Send char
Addr = Addr + 1 ' Point to next character
goto DisplayPage ' Continue with rest of the string
StringDone:
Addr = Addr + 2 ' Skip last 0x00
return

I have tested it. But I probably haven't considered all the ramifications of integrating it into your complete program. So let me know if it causes anything new.

.

jessey
- 10th January 2006, 13:03
Hi Darrel,

That was great! Success at last. I struggled for a bit but finally got it up & running with your new revision and it's working flawlessly. Thanks a million!! Thanks for your input too Steve, it's appreciated.

I've got another question if you have the time. I downloaded the free beta upgrade for my epic programmer so I could programme my 18F452 and it works good but I have to select the "erase before programming" option when programming, otherwise I get a programming error. The only hassle with that is that I have to reset all my adjustable (saved eeprom) variables whenever I reprogram my chip. Any idea on what's happening with that? There must be something I'm doing wrong or not setting properly but I can't figure it out. I can re-programme my 877 with the same epic & beta upgrade without loosing my saved variables.

Once again, thanks for getting me up and running, I'm including the code if anyone is interested in viewing it.

Thanks
jessey

Darrel Taylor
- 10th January 2006, 20:29
WooHoo! It's Done!
http://heebeejeebee.co.uk/pics/avatar/homjump.gif

And, that's just the nature of 18F's. You have to Erase before Programming, and it erases everything.

.

jessey
- 12th March 2006, 16:55
Hi Darrel,

I hate to pester you but I have another question regarding your STRINGS.PBP if it's possible to do. My question is, if there's a way to address each of the da prints below so I can make a decision on what I want to happen in my PBP code based on whichever print is showing?

Inst1:
ASM
da " ", 0xC0FE, " ",0
da " ", 0xC0FE, " ",0
There are over 100 prints here!
da " ", 0xC0FE, " ",0,0x7E
EndAsm

You have the last print addressed with 0x7E to indicate the end of the Inst1 with this statement "IF Char = $7E THEN InstructionsDone" and it works good to indicate the last print but if i try and use it else where then it gives me one un-readable character in the da print that I add it to and it also shifts the print one space to the left in the next da print. I tried adding 0,0x1, 0,0x2, 0,0x3 ect to each of the da prints but I get the same results.

What I'm trying to do is to block some instruction prints for a duel powered project I'm working on instead of having to use two separate instruction sets and two pushbuttons. So far I've been using a counter in the Pauseloop to know which print is showing and it works good for fast forwarding and fast reversing the prints but when I try to combine blocking certain prints with fast forwarding and fast rewinds then it gets a little tricky. It'll save me a lot of code space if I can combine both instructions sets into one, instead of having to have one Inst1 set to explain the battery operation and another separate Inst2 set for the transformer.

Is there a not too difficult way of doing this in the asm portion of your STRINGS code?

Thanks
jessey

mister_e
- 12th March 2006, 20:36
Want to save code space... my suggestion will certainely to use an external EEPROM. Now you can Use an ARRAY var or your PIC internal EEPROM to store the specific address of each of your prints.

EDIT: OK now I can see what you want. i guess it's possible to store the DA label address into an array or internal eeprom... that make me think of something interesting indeed.

Darrel Taylor
- 13th March 2006, 01:41
Hmmm, I guess Homer was a little premature up there.

Well, let's see what we can do. Let's choose another "Marker", kind of like the 0x7E, but this time we'll use it to mark the changes in a "Thread". So I'll choose 0xFF, but could be just about any other non-printable number. Along with the Marker, we'll put another number to indicate what to do next. So the end of a Thread section will have something like 0x01FF.

Taking the same data again, and splitting it into "Threads". I realize the text doesn't make sense when playing it back, but it's some sample data to use for now.
Inst1:
ASM
da " TO SET THE ", 0xC0FE, "WATERING SCEDULE",0 ; both threads
da " ALLOW THE SOIL ", 0xC0FE, "TO DRY OUT UNTIL",0 ; start here
da " IT REQUIRES ", 0xC0FE, " A WATERING ",0
da " THEN ADJUST ", 0xC0FE, " THE PUMP ON # ",0,0x01FF

Thread1
da " BY ROTATING POT", 0xC0FE, " #4 UNTIL IT ",0 ; only shows
da "EQUALS THE MOIST", 0xC0FE, "# AT WHICH TIME ",0 ; when Thread=1
da " THE PUMP WILL ", 0xC0FE, " TURN ON ",0,0x02FF

Thread2
da " BY ROTATING POT", 0xC0FE, " #5 UNTIL IT ",0 ; only shows
da "EQUALS THE MOIST", 0xC0FE, "# AT WHICH TIME ",0 ; when Thread=2
da " THE PUMP WILL ", 0xC0FE, " TURN OFF ",0,0x02FF

Inst1End
da " NOW EVERY TIME ", 0xC0FE, "IT DRIES OUT TO ",0 ; both threads
da " THAT MOISTURE ", 0xC0FE, "LEVEL IT WILL BE",0 ; finish here
da " WATERED ", 0xC0FE, " AUTOMATICALLY ",0
da " SET IT ONCE AND", 0xC0FE, " FORGET IT ",0
da " PRESS SWITCH 4 ", 0xC0FE, " TO EXIT ",0,0x7E
EndAsm ' The Last word must always be 0x7E
Then, just above where the routine checks for $7E, add this code that looks for the Marker. And decides where to go next.
if Char = $FF then
Addr = Addr + 1
Readcode Addr, Char
IF Char = 1 then ; 0x01FF found
if Thread = 1 then
@ GetAddress Thread1, _Addr
endif
if Thread = 2 then
@ GetAddress Thread2, _Addr
Endif
endif
if Char = 2 then ; 0x02FF found
@ GetAddress Inst1End, _Addr
endif
endifOf course you'll need to add a variable

Thread VAR BYTE

Now then, before starting the Display routines, set the Thread variable to indicate which path to take and then call the display routines like normal.
Thread = 2
@ GetAddress _Inst1, _Addr
Gosub NextLine

The sample Markers are just an example, you could have any number of different tasks specified in that "Number" that goes with the Marker. Allowing you to jump in and out of any portion as needed.


HTH,
Darrel

jessey
- 23rd May 2006, 06:57
Hi Darrel & Steve,

It's been a while since I got my computer back and working good, I lost my Outlook Express and only had intermitted internet access for quite some time and finally have it resolved now.

Good to see you back here in all your splendor Steve. It's hard to keep a good man down.

Wow, I can't wait to try your new code here Darrel, it looks like just what the doctor ordered. These instructions are just getting better and better all the time.

It'll take me a while to integrate your code but I'll plug away at it and thanks Darrel I sure appreciate all your fine work and the time you spent on this. I'll post your code when I get it integrated with the push buttons and the rest of my code.

Thanks
jessey