Shift code - Page 1
Forum section: electronics / general

author: yalect
author_rank: Regular Contributor
timestamp: March 27, 2018, 10:11:11 am
content: 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

author: Fire Doger
author_rank: Regular Contributor
timestamp: March 27, 2018, 10:19:01 am
content: Let's assume var= 0xff1<<3 = 0b00001000 (x1)Var>>1 = 0b0111111 (x2)x2&1 = 0b00000001 (x3)x3&x1 = 0You will always get 0.I guess you want something like this:PORTB|=((Var>>1)&1))<<3

author: yalect
author_rank: Regular Contributor
timestamp: March 27, 2018, 03:16:49 pm
content: Sorry, I didn't understand your reply but (1<<3) means PIN3 set to one then and logic with shift operation

author: rstofer
author_rank: Super Contributor
timestamp: March 27, 2018, 03:58:24 pm
content: Quote from: yalect on March 27, 2018, 03:16:49 pmBut 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...

author: cv007
author_rank: Frequent Contributor
timestamp: March 27, 2018, 04:10:35 pm
content: Not sure, but maybe you want something like this-PORTB |= ((Var>>1)&1)<<3; //will either be 0<<3 (does nothing) or 1<<3or this-if(Var&2) PORTB |= 1<<3; //or don't even bother if bit not set

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 27, 2018, 04:23:59 pm
content: Quote from: cv007 on March 27, 2018, 04:10:35 pmI'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/

author: mikerj
author_rank: Super Contributor
timestamp: March 27, 2018, 08:16:20 pm
content: Quote from: yalect on March 27, 2018, 10:11:11 amCode:PORTB |= (Var & 0x02) << 2;

author: Fire Doger
author_rank: Regular Contributor
timestamp: March 27, 2018, 10:14:01 pm
content: Quote from: yalect on March 27, 2018, 03:16:49 pm(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 pin3PortB |= (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 PortBPortB = 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 = Result0 & 0 = 00 & 1 = 01 & 0 = 01 & 1 = 1We 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-1111B = 0x0011-1100A&B = 0x0011-1100C = 0x0101-0101D = 0x0000-0111C&D = 0x0000-0101Ex1: 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&AIn your example you had a registervar = 0baaaa-aaxayou shifted it right inside parenthesesso var will be 0b0aaa-aaaxthen you masked it with 1 which is 0b0000-0001as examples above bits 1-7 will be 0 because in the mask they are 0so it becomes 0b0000-000xthen you mask it with (1<<3) which is 0b0000-1000bits 0,1,2,4,5,6,7 will be 0 because in the mask they are 0thats 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 beVar = 0baaaa-aaxaB = 0b0000-0010Var & B = 0b0000-00x0and 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-x000And finally the last step will be PORTB |= 0b0000-x000OR | is also a bitwise operatorA | B = Result0 | 0 = 00 | 1 = 11 | 0 = 11 | 1 = 1so its like0 | x = x1 | x = 1The 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