### Author Topic: Shift code  (Read 1939 times)

0 Members and 1 Guest are viewing this topic.

#### yalect

• Regular Contributor
• Posts: 141
##### Shift code
« on: March 27, 2018, 10:11:11 am »
Hi,
I would like to ask  you that I want to shift Var right or left (Var>>1) and move it to Port or check Pin of port every time, I wrote the instruction below but it doesn't work for me, for example PORTB, PIN3:
PORTB|=((1<<3)&((Var>>1)&1))
can give me instruction actually work (on Multisim)?
Thanks

#### Fire Doger

• Regular Contributor
• Posts: 208
• Country:
• Stefanos
##### Re: Shift code
« Reply #1 on: March 27, 2018, 10:19:01 am »
Let's assume var= 0xff
1<<3 = 0b00001000 (x1)
Var>>1 = 0b0111111 (x2)
x2&1 = 0b00000001 (x3)
x3&x1 = 0
You will always get 0.

I guess you want something like this:
PORTB|=((Var>>1)&1))<<3

#### yalect

• Regular Contributor
• Posts: 141
##### Re: Shift code
« Reply #2 on: March 27, 2018, 03:16:49 pm »
Sorry, I didn't understand your reply but (1<<3) means PIN3 set to one then and logic with shift operation

#### rstofer

• Super Contributor
• Posts: 9929
• Country:
##### Re: Shift code
« Reply #3 on: March 27, 2018, 03:58:24 pm »
Sorry, I didn't understand your reply but (1<<3) means PIN3 set to one then and logic with shift operation

But nothing gets put into the port until the entire expression is evaluated and the result of your expression is always 0.

Walk through Fire Doger's explanation and his solution.

It isn't 1 that you want to shift left, it is the result of the expression you want to shift.

I think...

#### cv007

• Frequent Contributor
• Posts: 852
##### Re: Shift code
« Reply #4 on: March 27, 2018, 04:10:35 pm »
Not sure, but maybe you want something like this-
PORTB |= ((Var>>1)&1)<<3; //will either be 0<<3 (does nothing) or 1<<3
or this-
if(Var&2) PORTB |= 1<<3; //or don't even bother if bit not set

#### SiliconWizard

• Super Contributor
• Posts: 15192
• Country:
##### Re: Shift code
« Reply #5 on: March 27, 2018, 04:23:59 pm »
if(Var&2) PORTB |= 1<<3; //or don't even bother if bit not set

I'd vote for this one, as it's the clearest way (by far) of writing this IMO.
The fact there is a test in this statement may or may not add execution time, completely depending on how it's compiled and the underlying instruction set, so I would not bother trying to micro-optimize this at the expense of readability.

Unless, of course, you are competing for this: https://ioccc.org/

#### mikerj

• Super Contributor
• Posts: 3306
• Country:
##### Re: Shift code
« Reply #6 on: March 27, 2018, 08:16:20 pm »
Hi,
I would like to ask  you that I want to shift Var right or left (Var>>1) and move it to Port or check Pin of port every time, I wrote the instruction below but it doesn't work for me, for example PORTB, PIN3:
PORTB|=((1<<3)&((Var>>1)&1))
can give me instruction actually work (on Multisim)?
Thanks

Code: [Select]
PORTB |= (Var & 0x02) << 2;

#### Fire Doger

• Regular Contributor
• Posts: 208
• Country:
• Stefanos
##### Re: Shift code
« Reply #7 on: March 27, 2018, 10:14:01 pm »
Sorry, I didn't understand your reply but (1<<3) means PIN3 set to one then and logic with shift operation
(1<<3)&.... doesn't mean make PIN3 1, its part of the logic.
Everything after = will execute first and at the end the result will assigned to PORT.
PortB = (1<<3); means shift 0b0000-0001 3 positions left and put it in portB. 1 will be in bit3 which is associated with pin3
PortB |= (1<<3); means shift 0b0000-0001 3 positions left, get PortB, compare each bit from the shifted value and PortB and then assign the result of OR | operation back to PortB

PortB = banana<<3;  means shift banana 3 positions left and put it in portB.
PortB =foo()<<3; means shift the result of foo() 3 positions left and put it in portB.

& is a bit-wise operator:
Truth table:
A & B = Result
0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1

We use & to "mask" a register
(Use truth table 1 by 1 for each bit on same positions, result.bit0 will be A.bit0 & B.bit0, result.bit1 will be A.bit1 & B.bit1, and so on....)
A = 0x1111-1111
B = 0x0011-1100
A&B = 0x0011-1100

C = 0x0101-0101
D = 0x0000-0111
C&D = 0x0000-0101

Ex1: we discarded bits 0,1,6,7 (no mater if they are 0 or 1 in A in result they will be 0 because our mask "B" has 0 in these positions)
Ex2: we discarded bits 2,4,5,6,7 (some of them were 0 some were 1, in result they will be 0 because our mask "D" has 0 in these positions)
P.S. you can define "mask" whatever you want, A&B == B&A

In your example you had a register
var = 0baaaa-aaxa
you shifted it right inside parentheses
so var will be 0b0aaa-aaax
then you masked it with 1 which is 0b0000-0001
as examples above bits 1-7 will be 0 because in the mask they are 0
so it becomes 0b0000-000x
then you mask it with (1<<3) which is 0b0000-1000
bits 0,1,2,4,5,6,7 will be 0 because in the mask they are 0
thats why your code always makes an OR and assign "|=" on PortB pin 3 with a 0.

If you want to get bit 1 from var you mask bit 1 as mikerj suggested (Var & 0x02)
*in example it will be
Var = 0baaaa-aaxa
B = 0b0000-0010
Var & B = 0b0000-00x0

and then you shift the result to correct position. Because its already in bit 1 you will shift it only 2 times to go to bit 3 which is associated with Pin3.
0b000-00x0 << 2 = 0b0000-x000

And finally the last step will be PORTB |= 0b0000-x000

OR | is also a bitwise operator
A | B = Result
0 | 0 = 0
0 | 1 = 1
1 | 0 = 1
1 | 1 = 1

so its like
0 | x = x
1 | x = 1

The best way to do what we understood that you want to do it is with mikerj code line.

If you want to do something else try to explain it or draw it in paint or with text by using "x" for the bit that you are interested in Var and what you want to do with it.

*English is not my native language, that's the best way I can explain it
« Last Edit: March 27, 2018, 10:41:49 pm by Fire Doger »

Smf