PicBasic Pro Compiler Code Optimizations
<-back to Index
Here are a few tricks that I've learned to save on code space using the MELabs PBP BASIC compiler for Microchip PIC microcontrollers. My compiler is the most recent as of Jan. '02, version 2.40a with the update that fixes the array indexing issue. (See below.)
Array accessing--saves 2 words
Incrementing Variables--saves 2 words
For-Next Loops--saves 1 word
Replace For-Next with While--Saves 2-4 words
More For-Next Loops--saves up to 13-14 words
IF ... AND...Then's--saves 5 words
ADCIN--Lots of room for saving time, up to 100uS.
Code Location--code dependant
NOTE: This page is brand new as of Jan 10, '02, and subject to updates. Please check back once in to catch corrections (such as the note on incrementing variables) and additions.
Note 2: If using assembly in place of the compiled basic, make sure you address the Banking issue. Code above 2k will have this requirement.
If you have a suggestion for this list, feel free to direct submissions to cliff@griffinlab.com .
New method:
j=i+1
array[j]=...
compiles two words shorter than the old "shorter" version:
array[i+1]=...
Note also that the above new method is a workaround for the PBP 2.40 bug that gives a compile error with the original 2.40 version. If you download the 2.40a update from the MELabs web site, you won't receive the compile time error.
Another trick to save a word is to
use an assembly routine to increment variables:
@ incf _Time ,1
This compiles two words shorter, but is functionally equivalent to
Time = Time + 1
Don't forget the underscore before Time in the assembly line.
NOTE: With feedback from Jeff Schmoyer, he has indicated that the incrementation
of a byte only takes "one word to do this with byte-sized variables.
With word- sized variables, it will use 3 words. It will also take care of
the banking issue. Many users have variables in several banks. The
compiler will make sure to set the appropriate bank." So, unless you set
the variable into a specific memory bank and your code is there also, do not use
this. So...use this with caution.
Save one word by using 0 to 9 instead of 1 to 10!
For x = 0 to 9 'note: one word shorter!
'...code here...
next x
For x = 1 to 10 'note: one word longer
'...code here...
next x
Replace For-Next Loops with While:
Instead of using a for next loop:
for i = 1 to 10
next
Use a While loop, and save two words. Note that you will save two words regardless of the starting value, either 0 or 1.
i=1
while i<11
i=i+1 ' even better
if you use @ incf _i ,1
wend
As noted, you can use the assembler technique for incrementing i, and you'll save two more words! See the notes above on incrementing before implementing this!
This technique saves 14 words
space over a For-Next loop:
x = 0
' set up for an assember For-Next loop of 256
LoopI:
Pause
5 'misc. code
goes here.
'Note that the F in the following line is to
'indicate that you are accessing a File register.
@ incfsz _x, F
'again, remember the underscore before your variable name.
@ goto _loopI
' like the NEXT statement. Use the underscore!
The above sample is to loop 256 times. To count down from, say 10 to 1, set x=10
and replace the incfsz (increment file, skip next line if it =0) with decfsz,
(decrement & skip if zero). This will save 13 words:
x = 10
'equivalent to For x=10 to 1 step -1
Loopl:
pause 5
@ decfsz _x,F 'will jump out of the loop if
x=0
@ goto _Loopl
Using two IF commands saves five words
looptest:
'if (i=1) and (k=1) then looptest
Instead, use this technique:
if i=1 then
if k=1 then looptest
endif
ADCIN and Reading Analog Inputs
There is a LOT of room for saving execution time during an ADCIN read. The ADCIN command had a time delay in it, making it even worse. Here is an example of reading the analog port before the ADCIN command came about:
' Subroutine to get pot x value
getx:
ADCON0 = $41 ' Set A/D to Fosc/8, Channel 0, On
Pauseus 50 ' Wait for channel to setup
ADCON0.2 = 1 ' Start conversion
Pauseus 50 ' Wait for conversion
x = ADRESH
Return
There are two things you can do to save time here. The obvious thing is to replace the 50uS pause commands with code. Another thing to do is to replace the "start conversion" command and the second pause with this code:
GO_DONE = 1
' Start conversion by setting GO_DONE bit
while GO_DONE = 1 : wend 'then wait for it to clear
What this does is start the conversion and then waits just until it's done, rather than an arbitrary predetermined amount of time that will cover all conversion times.
Note that I have not verified this tip, but it was offered by Ben of the PICBasic list. Jeff Schmoyer--the PBP author--has indicated that code location is NOT an issue with more recent versions. As expected, he has made many code size and speed improvements over the years.
>What I did was to move my subroutines up to the front of my program right after my variable definitions. Then put a goto statement in, to jump past the subroutines and the code SHRUNK by 96 words!!! Hope the explanations helps someone else trying to squeeze every last drop of space out.
'variable declarations . .
goto EndSub
'subroutines here . .
EndSub: 'Start program here Loop: . .
'code . .
goto loop
end
Copyright 2002, Cliff Griffin