Maker Pro
Maker Pro

Converting Switch/Case statement in C to ASM?

chopnhack

Apr 28, 2014
1,576
Joined
Apr 28, 2014
Messages
1,576
I have no issues with a extra case, i simply looped it back into the program. The trouble I have in simulation is the ANDLW is not generating a 0-3 value.
 

Harald Kapp

Moderator
Moderator
Nov 17, 2011
13,738
Joined
Nov 17, 2011
Messages
13,738
Your last code in post #15 is:
Code:
  movf  RANDOM,W   
  ANDWF  three,0
What's your code using ANDLW?
 

chopnhack

Apr 28, 2014
1,576
Joined
Apr 28, 2014
Messages
1,576
Your last code in post #15 is:
Code:
  movf  RANDOM,W
  ANDWF  three,0
What's your code using ANDLW?

It's the second line in loop under Main's LOOP. I also found a RNG, but that is not working either.
What do the operands do with BTFSC RANDOM,4? I thought that it would shift RANDOM by 4 places? When I simulate the lines that have BTFSC, they do nothing to the RANDOM register. (Edit - I will have to watch these registers in binary - apparently bit 4 is checked for zero). When it gets to the ANDLW line, it just tests boolean, if the number is not equal, a zero value is then loaded into W register. It looks like I need to find different code to accomplish what you were talking about (AND 0x03).
Thanks in advance for looking and helping.

;*******************************************************************************
; *
; Filename: *
; Date:02/23/2016 *
; FileVersion:0.6 *
; Author: *
; Company: *
; Description:Simple prog. to blink one port using ASM and repeated code *
; *
;*******************************************************************************
; *
; RevisionHistory: *
;0.0 syntax corrections and can't figure out __config issue!!! *
; 0.1 commented out config, temp. fix, used proper addressing of individual *
; -bits instead of broadly setting entire PORT *
; 0.2 blinking! - will have to play with values to achieve better timing *
; 0.3 learned how to access OSCCON and changed freq. - times closer to 1 sec *
; 0.4 LOOP'ed just the on/off and updated delay funct.-true100ms at 32k clock *
;0.5Create functions for different time delays *
;0.6Randomizewith TMR0 *
;*******************************************************************************

#include"p10LF320.inc"

;CONFIG
;__config 0x3FE6
__CONFIG _FOSC_INTOSC & _BOREN_ON & _WDTE_OFF & _PWRTE_OFF & _MCLRE_ON & _CP_OFF & _LVP_ON & _LPBOR_ON & _BORV_LO & _WRT_OFF

case0 equ .0
case1 equ .1
case2 equ .2
case3 equ .3
three equ .3


My_var UDATA
dc1 res 1
dc2 res 1
dc3 res 1
dc4 res 1
RANDOM res 4

RES_VECT CODE 0x0000 ; processor reset vector
GOTO START ; go to beginning of program

Delay100ms
movwf dc3
dly2 movlw .1
movwf dc2
movlw .1 ;.127
movwf dc1 ;clrf dc1

dly1 decfsz dc1,f
goto dly1
decfsz dc2,f
goto dly1
decfsz dc3,f
goto dly2

retlw 0

On movlw b'0100' ;setting RA2 high
movwf PORTA
retlw 0

Off movlw b'0000' ;RA2 low
movwf PORTA
retlw 0


Standard
call On
movlw .1 ;.60
movwf Delay100ms
call Delay100ms
call Off
movlw .5
movwf Delay100ms
call Delay100ms
return ;retlw 0

Slow
call On
movlw .5 ;.175
movwf Delay100ms
call Delay100ms
call Off
movlw .2 ;.5
movwf Delay100ms
call Delay100ms
retlw 0

Fast
movlw .1
movwf dc4
One
call On
movlw .2 ;.25
movwf Delay100ms
call Delay100ms
call Off
movlw .1 ;.4
movwf Delay100ms
call Delay100ms
decfsz dc4
goto One
retlw 0


;*******************************************************************************
; MAIN PROGRAM
;*******************************************************************************

MAIN_PROG CODE ; let linker place main program

START
movlw b'00000010'
movwf OSCCON
clrf ANSELA ;digital i/o
clrf TRISA ;output
clrf PORTA ;clearing PORTA, all low except RA3

movf TMR0,W
movwf RANDOM
RLF RANDOM
RLF RANDOM
BTFSC RANDOM,4
XORLW 1
BTFSC RANDOM,5
XORLW 1
BTFSC RANDOM,3
XORLW 1
MOVWF RANDOM

LOOP

movf RANDOM,W
ANDLW 0x03

xorlw case0
btfsc STATUS, Z ;If SWITCH = CASE0, jump to LABEL0
goto Standard

xorlw case1^case0
btfsc STATUS, Z ;If SWITCH = CASE1, jump to LABEL1
goto Slow


xorlw case2^case1
btfsc STATUS, Z ;If SWITCH = CASE2, jump to LABEL2
goto Fast


xorlw case3^case2
btfsc STATUS, Z ;If SWITCH = CASE3, jump to LABEL3
goto LOOP

goto LOOP



end
 
Last edited:

Harald Kapp

Moderator
Moderator
Nov 17, 2011
13,738
Joined
Nov 17, 2011
Messages
13,738
I think you really need help from someone who knows PIC assembler by heart. I'm sorry that what little I managed to find out doesn't help.
The only thing hat might have an influence is the notaton 0x03 for the number 3. When I used this notation I was thinking "C". Maybe the PIC assembler requires a different syntax?
 

Arouse1973

Adam
Dec 18, 2013
5,178
Joined
Dec 18, 2013
Messages
5,178
It's the second line in loop under Main's LOOP. I also found a RNG, but that is not working either.
What do the operands do with BTFSC RANDOM,4? I thought that it would shift RANDOM by 4 places? When I simulate the lines that have BTFSC, they do nothing to the RANDOM register. (Edit - I will have to watch these registers in binary - apparently bit 4 is checked for zero). When it gets to the ANDLW line, it just tests boolean, if the number is not equal, a zero value is then loaded into W register. It looks like I need to find different code to accomplish what you were talking about (AND 0x03).
Thanks in advance for looking and helping.

Hi John
Can we have a quick re-cap on where you are now. I have tried to pick up this thread but I am struggling. It looks like you are trying to create a random number by ANDing something together? The btfsc tests bit 4 of the register and if zero jumps over the next instruction in the code. Is that what you wanted to know?
cheers
Adam
 

chopnhack

Apr 28, 2014
1,576
Joined
Apr 28, 2014
Messages
1,576
I'm sorry that what little I managed to find out doesn't help.
The only thing hat might have an influence is the notaton 0x03 for the number 3.
Not all Harald, you have been a huge help and suggested an excellent solution, I have just failed to implement it properly or have made some other novice mistake. Your help is much appreciated and thank you!

Hi John
Can we have a quick re-cap on where you are now. I have tried to pick up this thread but I am struggling. It looks like you are trying to create a random number by ANDing something together? The btfsc tests bit 4 of the register and if zero jumps over the next instruction in the code. Is that what you wanted to know?
cheers
Adam

Hi Adam, yes, thanks for the clarification of btfsc - I wasn't sure at first, but I reset my simulation to see the binary values and was able to watch them change so that part of the code is indeed working. As written the part that doesnt work as intended is the ANDLW - we thought it would AND 0x03, basically doing a modulo 3, but in fact when I watch it, it seems to do a boolean op. instead. I will try what Harald mentioned above to rule out issues with using decimal vs. hex. I need to rewrite the asm with more comments - its on at least the seventh variation of version 0.6!!!

Edit - I watched with ANDLW 0x03. What I saw was, b'00000100' (decimal 4, h0x04) was passed to W, when passed to next line ANDLW 0x03 the value of W changed from b'00000100' to b'00000000'. According to the datasheet, the ANDLW was supposed to AND the contents of W with the 'k' literal which in this case is 0x03 and then place that back in W.
 
Last edited:

Harald Kapp

Moderator
Moderator
Nov 17, 2011
13,738
Joined
Nov 17, 2011
Messages
13,738
Edit - I watched with ANDLW 0x03. What I saw was, b'00000100' (decimal 4, h0x04) was passed to W, when passed to next line ANDLW 0x03 the value of W changed from b'00000100' to b'00000000'. According to the datasheet, the ANDLW was supposed to AND the contents of W with the 'k' literal which in this case is 0x03 and then place that back in W.
And that is what it does. ANDing two binary values in this contect means the boolean AND between the corresponding bits (bitwise AND):
Code:
0000 0011 AND
|||| ||||
0001 0000 =
-------------------
0000 0000

In C the equivalent operator is & (bitwise) as compared to && (operates on boolean variables).
 

Harald Kapp

Moderator
Moderator
Nov 17, 2011
13,738
Joined
Nov 17, 2011
Messages
13,738
It looks like you are trying to create a random number by ANDing something together?
Adam, there are actually two tasks:
  1. Generate a random number. One idea was to grab the count from a free running timer.
  2. Depending on the random number perform one out of three subroutine.

#2 John tried to do by computing Random MOD 3 which would give him an integer between 0....2.
As John is very limited in memory (sorry, not John himself, his PIC :D) I suggested he use Random AND 0x03 instead, which would give him a number 0...3. By discarding one of the 4 possible results (discard it, get a new Random number, try again until the result is one of the 3 legal results) this would have the same effect at less memory and runtime requirements.
As I showed in my post #10, by making RAndom==3 the illegal case, one can even minimize the code further.

I think the issue is John's misunderstanding of the AND operation, which I tried to clarify above.
 

chopnhack

Apr 28, 2014
1,576
Joined
Apr 28, 2014
Messages
1,576
I think the issue is John's misunderstanding of the AND operation, which I tried to clarify above.

Yes, I am understanding now that it is operating as a boolean evaluation, but I was expecting a modulo function!

but what if John uses module 4 instead? This operation is a simple AND 0x03, fast and small.
The result is a number between 0...3,

The above is why I thought that. The current code checks for 0,1,2,3 however the frequency of those numbers appearing is going to be very low since we are starting with an 8 bit number! Zero is the likely outcome since most will not be true after being AND'ed. I really need more of a modulo function for this to work as written or come up with a new routine.
 

Harald Kapp

Moderator
Moderator
Nov 17, 2011
13,738
Joined
Nov 17, 2011
Messages
13,738
Yes, I am understanding now that it is operating as a boolean evaluation, but I was expecting a modulo function!
AND is not MOD, right, but in this special case AND 0x03 is equivalent to MOD 4!
What it does is to create a number between 0...3 (for AND 0x03) from any integer input. If the last 2 bits of the integer input are random enough, the result of Random AND 0x03 will be random, too (at least, I think, for your purpose).

Zero is the likely outcome since most will not be true after being AND'ed. I really need more of a modulo function for this to work as written or come up with a new routine.
The issue then is not the reduction of the random number to a number between 0...n, but the lack of randomness in the input integer. The cure is to use a "better" pseudo random number generator (books have been written on that topic).

Instead of using the last 2 bits of your integer input (if they are "not random enough"), you can use other bits, too, e.g. use bits 2 and3 (provided these are "random" enough) by adding a shift operation:
Result = (Random AND 0x0C)>>2; //excuse my using C notation :D
Or simply use Random AND 0x0C and change the select case statement (respectively your case-constants) from cases 0...3 to 0; 4; 8 and 12 (note the gaps between the cases due to the unshifted result of the AND).
 

Arouse1973

Adam
Dec 18, 2013
5,178
Joined
Dec 18, 2013
Messages
5,178
Adam, there are actually two tasks:
  1. Generate a random number. One idea was to grab the count from a free running timer.
  2. Depending on the random number perform one out of three subroutine.

#2 John tried to do by computing Random MOD 3 which would give him an integer between 0....2.
As John is very limited in memory (sorry, not John himself, his PIC :D) I suggested he use Random AND 0x03 instead, which would give him a number 0...3. By discarding one of the 4 possible results (discard it, get a new Random number, try again until the result is one of the 3 legal results) this would have the same effect at less memory and runtime requirements.
As I showed in my post #10, by making RAndom==3 the illegal case, one can even minimize the code further.

I think the issue is John's misunderstanding of the AND operation, which I tried to clarify above.

Thanks Harald, I now understand....
Adam
 

Arouse1973

Adam
Dec 18, 2013
5,178
Joined
Dec 18, 2013
Messages
5,178
Yes, I am understanding now that it is operating as a boolean evaluation, but I was expecting a modulo function!



The above is why I thought that. The current code checks for 0,1,2,3 however the frequency of those numbers appearing is going to be very low since we are starting with an 8 bit number! Zero is the likely outcome since most will not be true after being AND'ed. I really need more of a modulo function for this to work as written or come up with a new routine.

Could you not mask the upper bits to get rid of them?
Adam
 

Harald Kapp

Moderator
Moderator
Nov 17, 2011
13,738
Joined
Nov 17, 2011
Messages
13,738
Could you not mask the upper bits to get rid of them?
That's what AND 0x03 is supposed to do.
This list I generated using Excel and consecutive input numbers:
Code:
Input    AND 0x03
0    0
1    1
2    2
3    3
4    0
5    1
6    2
7    3
8    0
9    1
10    2
11    3
12    0
13    1
14    2
15    3
16    0

Using random input numbers in the range 0...255 this list looks as follows:
Code:
237    1
50    2
58    2
224    0
16    0
131    3
166    2
88    0
135    3
174    2
34    2
136    0
93    1
53    1
24    0
47    3
234    2
205    1
42    2
167    3
133    1
186    2
147    3
205    1
192    0
24    0
120    0
If you like, I can elaborate a bit on the math behind "AND 0x03" == MOD 4.

@chopnhack : I'm not sure I understand what exactly you expect. The code excamples I gave you so far result in exactly what I think is what you are looking for. I may misunderstand you, or you may expect something different than what you write. From the above examples you can take it that "0" is not considerably more frequent than 1, 2 or 3.

What is yor expectation of a "random" series óf numbers?
 
Last edited:

Arouse1973

Adam
Dec 18, 2013
5,178
Joined
Dec 18, 2013
Messages
5,178
Ok yes I agree with Harald. Like this. So this should be the result you get in W after the ANDING.
AND.PNG
 
Last edited:

Arouse1973

Adam
Dec 18, 2013
5,178
Joined
Dec 18, 2013
Messages
5,178
If I do this in the simulator it works and I get the value back in WREG when it finishes. I tried a few values and get the same results as Harald.
For 234 the answer is 2.
AND2.PNG

AND3.PNG
 

chopnhack

Apr 28, 2014
1,576
Joined
Apr 28, 2014
Messages
1,576
AND is not MOD, right, but in this special case AND 0x03 is equivalent to MOD 4!
Oh boy :oops: - I just verified that... I did not use enough examples to verify my previous observation, my apologies! I was reading the datasheet and remembered seeing that the AND performed a boolean function, but it was the ANDWF not the ANDLW and that certainly makes a difference.

I seeded W with random numbers and AND 0x03 does indeed do the same thing as modulo 4. Brilliant!! Not necessary to explain modulo, it returns the remainder of a division by 4 and is very useful.

The issue then is not the reduction of the random number to a number between 0...n, but the lack of randomness in the input integer. The cure is to use a "better" pseudo random number generator (books have been written on that topic).
Agreed completely. I am thinking of changing the TMR0 into a counter instead, such that it produces a running number that increments with the clock cycle. That should give me more random numbers. As a timer, it is giving me a static startup value. In simulation it seems to like the value of 5 consistently and therefore when its fed through the small RNG section of code, it gives the same net result.

I will toy with this for a bit and keep you all posted. Thank you again for the input and helping me straighten out this mess!! :D
 

Harald Kapp

Moderator
Moderator
Nov 17, 2011
13,738
Joined
Nov 17, 2011
Messages
13,738
Agreed completely. I am thinking of changing the TMR0 into a counter instead, such that it produces a running number that increments with the clock cycle.
I had implicitly assumed that you had the timer running this way all time long. Of course, if the timer isn't running, it can't generate any number even less random ones. Make sure it runs really fast to avoid reading the same number again and again.
 

Harald Kapp

Moderator
Moderator
Nov 17, 2011
13,738
Joined
Nov 17, 2011
Messages
13,738
View attachment 25503
Adam.
while your code works fine, It uses the f register and therefore requires to put the literal 0x03 into the f register gefore doing the ANDWL. I had suggested using ANDLW which saves one operation in runtime and memory by directly ANDING W with the literal.
 

Arouse1973

Adam
Dec 18, 2013
5,178
Joined
Dec 18, 2013
Messages
5,178
Yeah you can do it either way for sure. I just did it this way to show John that the functions work.
Adam
 

chopnhack

Apr 28, 2014
1,576
Joined
Apr 28, 2014
Messages
1,576
I am working on TMR0's function and how it is implemented on this chip. I posted in Microchip's forum seeking assistance on how to properly setup the SFR's for this feature. The TMR0 in simulation and in circuit live is not acting as a timer. We should see the TMR0 register value change and increment with each clock cycle, instead it is staying static and thus so is my random number generator. I tried to use it as a counter, but that too did not seem to function. Apparently I do not have the function setup or initialized correctly. Also, from reading the datasheet it seems that the counter feature would require a clock in signal. I will keep you guys posted as to what I find out.

Thanks again for your help!
 
Top