#select #case
Newzed
Posts: 2,503
I have a program for my bar graph that uses a lot of IF-THEN statements, and the program works fine.
I would like to use #SELECT #CASE insted of the IF-THEN statements.· For a starter I wrote:
AD0 var word
a = word
b = word
start:
SERIN 16, baud, [noparse][[/noparse]DEC AD0]
#DEFINE cnt =· AD0
#SELECT cnt
#CASE cnt>4000
a =0
b = 0
#CASE cnt>3750
a = 255
b = 255
#ENDSELECT
When I try to run it I get an error that the AD0 in the DEFINE statement is an illegal symbol.· Am I doing something wrong, or is this an improper use of SELECT-CASE?
Thanks
Sid
I would like to use #SELECT #CASE insted of the IF-THEN statements.· For a starter I wrote:
AD0 var word
a = word
b = word
start:
SERIN 16, baud, [noparse][[/noparse]DEC AD0]
#DEFINE cnt =· AD0
#SELECT cnt
#CASE cnt>4000
a =0
b = 0
#CASE cnt>3750
a = 255
b = 255
#ENDSELECT
When I try to run it I get an error that the AD0 in the DEFINE statement is an illegal symbol.· Am I doing something wrong, or is this an improper use of SELECT-CASE?
Thanks
Sid
Comments
Sid
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jon Williams
Applications Engineer, Parallax
AD0 is a run time variable, and as you already found out, your program works when you use the run time versions of the command, without the "#".
With the "#" is is evaluated at compile time. Jon uses that very effectively to make code that will run on different Stamps by using the #SELECT $STAMP directive with a #CASE for each Stamp. The compiler knows which stamp it needs to compile for, because in PBASIC 2.5, that is stated in the ' $STAMP directive.
I use the #SELECT directive when I want to have different versions of code that I can have compiled by number, for exaample as shown here emesystems.com/BS2pbasic25.htm. The one I want is defined at compile time, not a run-time variable.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Tracy Allen
www.emesystems.com
I converted all my IF/THEN statements to SELECT/CASE.· There were 17 so I got an error "Only 16 CASE Statements are allowed."· So I ended it at 16, then added one more SELECT/CASE in order to get my 17 statements in.· The program compiled OK - is this method legal?
Thanks
Sid
Hi Sid, I didn't realize there was a limit of 16, and it kind of surprises me. If you got your workaround to compile, and it works, then it's legal! Here is the program from the URL mentioned above, that explores the microcoding of the CASE-SELECT statement in PBASIC 2.5, translated to old PBASIC 2.0. This also shows one way to take advantage of #DEFINE/#SELECT/#CASE/#ENDSELECT. First put example=10 in the #DEFINE part, and then hit CTRL-M, scroll down and take a screen shot of the tokens produced by the program. Then put example =11 after the #DEFINE, hit CTRL-M again, and take a second screen shot. The #SELECT allows you to change which of the two code examples gets compiled. Now compare the two sets of tokens. You will see that they are identical. That shows that PBASIC 2.5 takes care of the work and the spagetti of a series of IF-THEN statements for you behind the scenes, when you use the nice, clean, efficient SELECT/CASE/ENDSELECT. Since it is resolved to a chain of IF/THEN GOTO statements in the native PBASIC 2.0, I don't see why the limit of 16. Maybe that is imposed by the compiler.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Tracy Allen
www.emesystems.com
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jon Williams
Applications Engineer, Parallax
SELECT mydata /50 - 48
...
would lead to code that repeats the expression evaluation for each subsequent CASE. ...Better use,
x = mydata/50-48
SELECT x
...
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Tracy Allen
www.emesystems.com
Sid
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jon Williams
Applications Engineer, Parallax
Sid
Start:
· AD0 = AD0 + 240
· IF (AD0 > 3999) THEN
··· AD0 = 240
· ENDIF
· idx = AD0 / 250
· READ (ALevel + idx), a
· READ (BLevel + idx), b
·
Cont:
Of course you have to put the list of 'a' and 'b' values into a couple DATA tables, but that would be easy to do an make modifying the program simpler.
A couple more notes: You might consider using meaningful variable names -- meaningful for you AND other programmers that is; I have no idea what a and b are for, and wouldn't without a lot of detailed analysis.· You're also using OUTPUT in the program; it is probably better to use HIGH or LOW as this sets the pin to an output and to a known level.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jon Williams
Applications Engineer, Parallax
Just as a general matter, the redundant code issue caused by inline mathematical calculations is by no means unique to PBASIC. I honestly can't think of an interpretive Basic Language variant that DOESN'T have that same "problem" and which always benefits from the pre-calculation step you indicated.
Regards,
Bruce Bates
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
<!--StartFragment -->
It turns out there's an even simpler solution:
Main:
· IF (ad0 > 249) THEN
··· GOSUB Set_Display
· ELSE
··· GOSUB Clear_Display
· ENDIF
· END
Set_Display:
· idx = (ad0 / 250) - 1········ ' determine left-most bit
· leds =·0····················· '·clear old value
· FOR idx = idx TO 0············' light appropriate bits
··· leds.LOWBIT(idx) = 1
· NEXT
· GOTO Update_Leds
Clear_Display:
· leds = $0000
Update_Leds:
· SHIFTOUT SData, Clock, MSBFIRST, [noparse][[/noparse]leds.BYTE0, leds.BYTE1]
· PULSOUT Latch, 5
· RETURN
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jon Williams
Applications Engineer, Parallax
·
Eventually, AD0 will be serined, but for the moment I had to generate a changing AD0.· I made a couple of other small changes just to make things easier.· The whole program only takes 6 percent of memory so I will be able to·incorporate it into any program I like.
I have attached a copy of Rev. A so you can see exactly what I did.
Thanks again - I'll have to remember about augmenting the bits of leds -
that's very neat.
Sid
Set_Display:
· leds =·0····················· '·clear old value
··idx = (ad0 / 250)···· ······· ' determine left-most bit
· IF (idx > 0) THEN
····FOR idx = (idx-1) TO 0······' light appropriate bits
····· leds.LOWBIT(idx) = 1
··· NEXT
· ENDIF
· GOTO Update_Leds
You can send any value (0·- 4000)·to this subroutine -- you don't have to filter values less than 250.· Also, you've added redundant SHIFTOUT code at Clear_Display in your new program.· You can simply set leds to zero at this point and let it drop through to Update_Leds; this gives your program the same operation and cuts down on space.· If you want to keep the redundant code, then it makes more sense to move the code from Update_Leds up to the end of Set_Display.· The only reason I crafted the code as I did was to optimize code space by removing redundancies.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jon Williams
Applications Engineer, Parallax