PDA

View Full Version : better coding methods to freeing active ram in small pics



longpole001
- 7th December 2012, 07:07
Hi guys , i have code that is now finding hard to fit using 128 bytes of active ram the pic has , is there link to a list of things to do in way of methods / checks that might help free up both active ram and code space

also does defining a bit instead of byte as a variable save active ram space ?


cheers

Acetronics2
- 7th December 2012, 07:16
use pure assembler ... :rolleyes:

Ok, being a bit more serious ( ? ) ...

@ first OVERALL have a very neat scheme of what your processor must do ... called " program chart ". ;)

after that ... picbasic pro command sometimes need to be looked at closer ( use of if-then instead of select case, retrieve tables use instead of calculations ... i.e )

but not general method except knowing exactly what you want to do ... :D

Alain

HenrikOlsson
- 7th December 2012, 08:13
also does defining a bit instead of byte as a variable save active ram space
Yes, if you declare, for example, 5 bits PBP will stuff them into a single byte compared to occupying 5 bytes if declared as such. Obviously if you only have one bit it doesn't matter, it would still need to be stored somewhere and the only available size inside the PIC is a byte.

Many times you can reuse variables, you may have variables that are only used in certain sections of the code and each time you enter that section the value of those variables are recalculated so it doesn't matter if you overrwrite them / re-use them in other sections. If it gets REALLY tight you can use unused hardware registers of the PIC as storage locations, if you're not using TMR0 you can use that to store a BYTE - for example.

You could always post the code here and someone might come up with some good advice.

/Henrik.

longpole001
- 7th December 2012, 09:35
thanks guys , i have reused the variables where they are not used outside the routines called , but now i have variables that must be used global , still searching/ change / clean , but managed to have 1 byte spare now in 128bytes of ram for variables and it compiles

but it be nice to see a few methods listed of how to " trim " code when forced to make it leaner on at least ram , find that the 2k program mem is a factor but often i hit the lack of ram factor before program mem issues on the smaller pics

for example as ACE indicated , use if - then instead of case - why , is it that it tend to use less ram , or better for program space or both ?
defining variables correctly / reusing is always good

cheers

sheldon

pedja089
- 7th December 2012, 10:07
I notice that nested IF's use less code space than one if with multiple AND's.
Probably it use less ram.
For more complex condition instead of
IF (x<8 OR X>2) AND y=1 THEN your stuff...(77words used)
I use this:


IfVar=0
IF x<8 THEN IfVar=1
IF x>2 THEN IfVar=1
IF y<>1 THEN IfVar=0

IF IfVar=1 THEN
IfVar=0
your stuff...
ENDIF
31 words used.
IfVar is unused bit of byte. For example IfVar var seconds.7

longpole001
- 7th December 2012, 12:25
interesting - had code that was compiling to 2001 words , code had a large section of select case with 24 case options ( buttons ) , replacing them with if then , compiled to 1978 words , does not look as nice but heck worth the saving in program space

Ioannis
- 7th December 2012, 12:58
When I have bits using them as bit variables or flags, I set them as this:



my_flag var byte
flag1 var my_flag.0
flag2 var my_flag.1

etc


Also recently Darrel gave a tip for a calculation.



IF ABS(x-y)>16 THEN...


Using this:



IF X>Y THEN
Z=X-Y
ELSE
Z=Y-X
ENDIF


which compiles about the half size.

So, a little common sense and experimenting is all that is needed.

Ioannis

Mike, K8LH
- 7th December 2012, 21:35
I notice that nested IF's use less code space than one if with multiple AND's.
Probably it use less ram.
For more complex condition instead of
IF (x<8 OR X>2) AND y=1 THEN your stuff...(77words used)
I use this:


IfVar=0
IF x<8 THEN IfVar=1
IF x>2 THEN IfVar=1
IF y<>1 THEN IfVar=0

IF IfVar=1 THEN
IfVar=0
your stuff...
ENDIF
31 words used.
IfVar is unused bit of byte. For example IfVar var seconds.7

But wouldn't that be the same as;



if y = 1 then
your stuff...
endif


????

pedja089
- 8th December 2012, 01:39
Hehe... it's just example...
I wrote first thing that came on my mind...
Ok...

IF (X<8 OR Z>2) AND Y=1 THEN your stuff...(77words used)



IfVar=0
IF X<8 THEN IfVar=1
IF Z>2 THEN IfVar=1
IF y<>1 THEN IfVar=0

IF IfVar=1 THEN
IfVar=0
your stuff...
ENDIF
31 words used.
Better???

longpole001
- 18th December 2012, 01:36
:) so as a bit of summery to date , what i have seen and do to reduce code size and ram allocation are as follows.
But this is no where near complete , but add / correct where needed !!!
1. Use the correct variable size – eg bit byte word
2. Where multi flags are required of setup myflags as a byte, with variable = myflags.0, for each flag


Myflags var byte
Timeout_flag_0 var Myflags.0
Timeout_flag_1 var Myflags.1
Fade_flags_0 var Myflags.2
Fade_flags_1 var Myflags.3




3. Keep variables that are used in subroutine to min and reuse in each subroutine ( don’t forget to set to 0 in each routine at start)
4. Keep Global variables to small number and to a byte
5. When doing a read such as pulsin , and using a word variable , if accuracy is not as a big issue for other processing then dont assign words to an array with the results / divide the result so a byte value in array is used


FOR X = 0 TO 31 ' grab 32 incoming pulses
PULSIN IR,1,leader ' now measuring high-going pulse widths ( pulsin_max set to 21600 = 108ms )
BtnVal(x) = leader/2 ' leader divide by 2 so array Btnval(x) is byte (<255) not word value
NEXT X


6 where practical for code reading and structure , replace case select code with if , then statements





if DByte[4] = $6F then ' Red - remote 1
read remotetype + Red ,STDByte[4] ' read eeprom remote 2 location + button offset
STDByte[3] = (~ STDByte[4]) ' bitwise Not the value of byte4 to be byte3
endif
if DByte[4] = $4F then ' Btn01 - remote 1
read remotetype + Btn01 ,STDByte[4] ' read eeprom remote 2 location + button offset
STDByte[3] = (~ STDByte[4]) ' bitwise Not the value of byte4 to be byte3
endif
if DByte[4] = $57 then ' Btn02 - remote 1
read remotetype + Btn02 ,STDByte[4] ' read eeprom remote 2 location + button offset
STDByte[3] = (~ STDByte[4]) ' bitwise Not the value of byte4 to be byte3
endif
if DByte[4] = $67 then ' Btn03 - remote 1
read remotetype + Btn03 ,STDByte[4] ' read eeprom remote 2 location + button offset
STDByte[3] = (~ STDByte[4]) ' bitwise Not the value of byte4 to be byte3
endif



7 replace if x= 1 And y=1 then statements , with multi if statements , uses less words in compile


8. when doing a read from a table in eeprom , its better to multi reads than keep in variables
9. assigning constants with a variable name and use as the offset in lookup table and then doing a read at that location is better than using a variable for each name in the table
10 love DT_int14.bas , routines but has high hit on ram on small pics , so better to use for all interrupts for timers , IOC etc , than setting up other code to monitor interrupt flags outside of DT routines
11 math calculations , not sure , not had to do much of those where its been an issue ??

rsocor01
- 19th December 2012, 05:16
Also, check this thread out for more tips.

http://www.picbasic.co.uk/forum/showthread.php?t=12105&highlight=code

ofuzzy1
- 21st December 2012, 17:47
What is your issue programming or outputting?

Ran into the same brickwall and used the onboard NV ram for stuffing the output messages.
Used the debug instead of serout/hserout it uses less space
Then Used gosub for calling the output and read the text one letter and used char+128 to indicate EOL/EOM.

The gosub used much less space using individual functions:
so if you had a lot of conditions; set them up as a matrix and work them against the matrix, calling all from the NV ram.
Amazingly ugly but did it on a bet. Even had room for a copyright :)

Next time just buy the larger [read better] part, they wind up being cheaper :)
12f1840 / 16f182x / 16f193[8/9]

Newark.com has decent pricing. [last years pricing, but you get the idea]



PIC12F683 8dip 20MHZ 2Kprog 128nvB 256EE 6I/O $1.41 or $1.15
PIC12F1822 8 dip 2kprog 256ram 128nvB 6 i/o $1.20
PIC12F1840-I/P 8 PDIP IO6 Prog7K 256B RAM 128nvB 32MHz 3tmr $1.18



Using the NV -- Ofuzzy1 & W_Alarm are now text strings residing in the NV

CharBump con $80
Ofuzzy1 data @$10, "(C)2011 Ofuzzy1 AllRightsReserved-Not for Life Critical Use", "!" + CharBump
W_Alarm Data "Alarm", "_" + CharBump


gosub Print_Copyright
...

Print_Copyright:
gosub Print_SP2 : gosub CR_LF3 ': gosub CR_LF
zb= Ofuzzy1 : gosub Print_Phrase
gosub CR_LF3 ': gosub CR_LF
return



to print a phrase out use this:
ab, bb, zb are byte sized VAR

Print_Phrase: ' Call with zb = ROM_Memory_Location [byte]
bb = 1
Do until !BB ' = 0
read zb, ab
if ab > CharBump-1 then
ab = ab - CharBump
bb = 0
endif
debug ab
zb= zb + 1
loop
return

to call get the phrase ready to print use this:

Print_Copyright:
gosub CR_LF
zb= Ofuzzy1 : gosub Print_Phrase
return

Need 3 or 2 or 1 line feeds?

CR_LF3:
debug LF,cr
CR_LF2:
debug LF,cr
CR_LF:
debug CR,LF
return