Searching \ for '[PIC]: Shifting a number through a byte' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: piclist.com/techref/microchip/devices.htm?key=pic
Search entire site for: 'Shifting a number through a byte'.

Exact match. Not showing close matches.
PICList Thread
'[PIC]: Shifting a number through a byte'
2000\08\16@115614 by Jean-Michel Howland

flavicon
face
Hi all,

I need to shift a 5 bit number in, through and out of a byte using bit0 to
bit4 and not affect bit5 - bit7.

The best way I can think of an example is if you had two 8 bit wide
registers next to each other like the following.  The 5 bit value in byte 2
is shifted left throughout byte 1 and out.

byte1     byte2

XXX00000  xxx11111      start state
XXX00001  xxx11110
XXX00011  xxx11100
XXX00111  xxx11000
XXX01111  xxx10000
XXX11111  xxx00000
XXX11110  xxx00000
XXX11100  xxx00000
XXX11000  xxx00000
XXX10000  xxx00000
XXX00000  xxx00000      end state

Only byte 1 is important, byte 2 is just for my example.

X = can not be changed.
x = not used

Anyone have any ideas on how to do this?  I think a couple of loops and
some bit testing & setting will do it but I just can't seem to crack the
algorithm needed.

Regards
Jean-Michel.

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

2000\08\16@124614 by Michael Rigby-Jones

flavicon
face
{Quote hidden}

I think I'd use a temporary variable and logically combine the shifted
result with byte1.

e.g.
       CLRF    temp            ; ensure our temp variable is clear to begin
with
       RLF     byte2,F ; align incomming word to MSB's (assuming this is
ok??)
       RLF     byte2,F
       RLF     byte2,F

       MOVLW 5
       MOVWF count             ; initialise loop counter

shift:
       RLF     byte2,F ; move the MSB of incomming word into CARRY
       RLF     temp,F  ; and then move it into the LSB of temp

       MOVF    byte1,W ; get current state of byte one
       ANDLW 0xE0              ; clear the 5 lsb's
       IORWF   temp,W  ; set the 5 LSB's according to temp
       MOVWF byte1             ; move the result back into byte1
                                               ; result in byte1 is correct
here

       DECFSZ  count
       GOTO            shift


I think this would work OK as long as the XXX bits in byte1 are not changed
(e.g. by an interrupt) during the middle four instructions of the shift
loop.
I don't even know why I attempted this, Scott or Dmitry will probably have
it whittled down to 3 instructions :o)

Cheers

Mike

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

2000\08\16@125231 by M. Adam Davis

flavicon
face
You are looking to rotate the lower five bits of a byte through the lower five
bits of a register without affecting the higher 3 bits.

The algorithm could be as follows, using two temp registers and assuming the
byte to be worked on is in W, the result goes in W.  The original byte is in
TEMP1:

Copy W to temp1
Rotate W Left
Remove (clear) the top three bits or W (AND W with 0b0001.1111)
Copy W to temp2
Move temp1 to W
Remove the bottom 5 bits of W (AND W with 0b1110.0000)
Add temp2 to W

I know there are other ways to do this (shorter, faster, fewer registers, etc).
But this is a good way to do it.  The example assembly is below:

MOVWF   TEMP1
RLF     W
ANDLW   0b0001.1111
MOVWF   TEMP2
MOVF    TEMP1, W
ANDLW   0b1110.0000
ADDWF   TEMP2, W                ;You can also use IORWF here.

I hope this helps!

-Adam

Jean-Michel Howland wrote:
{Quote hidden}

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

2000\08\16@130459 by Jim Ham

flavicon
face
How about the brute force method: shift the whole byte, then put back the
upper three bits. No temporaries used and W untouched:

set carry appropriately, then

        rlf     byte1, F        ; rotate carry into LSB
        bcf     byte1, 5        ; bit by bit move back the upper three bits
        btfsc   byte1, 6
        bsf     byte1, 5
        bcf     byte1, 6
        btfsc   byte1, 7
        bsf     byte1, 6
        bcf     byte1, 7
        btfsc   STATUS, C       ; bit seven now in carry
        bsf     byte1, 7

If you need to keep the byte correct at all times I think you'll need a
temporary:

        set carry appropiately
        rlf     byte1, W        ; rotate but put result in W
        andlw   0x1F            ; clear the upper three bits
        movwf   temp            ; store it
        movlw   0xE0
        andwf   byte1, W        ; move upper three bits to W
        iorwf   temp, W ; OR in the shifted lower 5 bits
        movwf   byte1           ; ... and put it back.


Regards,
Jim Ham


At 08:44 AM 8/16/2000 , you wrote:
{Quote hidden}

Jim Ham, Porcine Associates
(650)326-2669 fax(650)326-1071
"http://www.porcine.com"

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

2000\08\16@131551 by Tim Hamel

picon face
Hi,

This sounds interesting, so I thought I'd take a crack at it. The way I look
at it is to save your data to a temp register and another "working" register,
swap the high/low nibbles and shift out, then restore the temp register. Like
so:

movwf  temp
movwf  temp2
swapf   temp2, 1  ;result would be 11111xxx

<---Insert shift out routine here--->

movfw  temp        ;restore original value

I'm not sure this would work...but I tried!

Regards,

Tim Hamel



> {Original Message removed}

2000\08\16@134236 by Jim Ham

flavicon
face
Here's a middle-of-the-road solution. No temporary but uses W and corrupts
temp1 for a few instructions:

        set carry appropriately
        movlw   0x1F
        rlf     byte1, F        ; rotate in place, byte1 now corrupt
        andwf   byte1, F        ; clear upper three bits
        rrf     byte1, W        ; get the original back in W
        andlw   0xE0            ; clear the lower 5 bits
        iorwf   byte1, F        ; restore upper 3 bits, byte1 now OK

How about the brute force method: shift the whole byte, then put back the
upper three bits. No temporaries used and W untouched:

set carry appropriately, then

        rlf     byte1, F        ; rotate carry into LSB
        bcf     byte1, 5        ; bit by bit move back the upper three bits
        btfsc   byte1, 6
        bsf     byte1, 5
        bcf     byte1, 6
        btfsc   byte1, 7
        bsf     byte1, 6
        bcf     byte1, 7
        btfsc   STATUS, C       ; bit seven now in carry
        bsf     byte1, 7

If you need to keep the byte correct at all times I think you'll need a
temporary:

        set carry appropriately
        rlf     byte1, W        ; rotate but put result in W
        andlw   0x1F            ; clear the upper three bits
        movwf   temp            ; store it
        movlw   0xE0
        andwf   byte1, W        ; move upper three bits to W
        iorwf   temp, W ; OR in the shifted lower 5 bits
        movwf   byte1           ; ... and put it back.


Regards,
Jim Ham


At 08:44 AM 8/16/2000 , you wrote:
{Quote hidden}

Jim Ham, Porcine Associates
(650)326-2669 fax(650)326-1071
"http://www.porcine.com"

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

2000\08\16@135933 by Bob Bullock

flavicon
face
Here is my crack at this.  First a couple of assumptions that would affect
the solution.  I assumed a 14-bit core part.  I assumed that you wanted
both byte1 and byte2 to be correct as in your example after each bit shift.

A couple of things to watch for in some of the solutions posted previously.
I noticed an "RLF       W"  instruction that looks like it should rotate the WREG
left 1 bit
You can do this on the 16-bit core parts, but WREG is not an addressable
register on the 12 and 14-bit core parts.

In another solution byte2 was rotated left three bits to align it at the
MSB.  Only thing to watch out for here is what value you are rotating into
byte2 in the carry.  This depends on if you really need byte2 to turn out
as in your example.

I didn't show the looping control logic

       clrf    byte1
loop:
       clrc                    ;clear carry into byte 2
       rlf     byte2,f ;rotate byte left once
       movf    byte1,w ;load byte1 into WREG
       clrc                    ;clear carry
       btfsc   byte2,5 ;set or clear carry to be same as bit 5
       setc                    ;note that clrc and setc translated by MPASM to bcf 3,0 and bsf 3,0
       rlf     byte1,w ;rotate bit into byte and leave in WREG
       andlw   B'00011111'     ;clear bits 5..7
       movwf   temp1           ;save for second
       movlw   B'11100000'     ;load mask to clear bits 0..4
       andwf   byte1,w ;get original high order bits from byte1
       iorwf   temp1,w ;combine the two
       movwf   byte1           ;and write back to byte1


At 11:44 PM 8/16/2000 +0800, you wrote:
{Quote hidden}

Bob Bullock
President
Western Support Group Ltd.
bobbspamKILLspamprostyle.com
Certified Microchip Consultants
http://www.microchip.com/10/Consult/Country/Canada/index6.htm#915-277

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

2000\08\16@141827 by Bob Ammerman

picon face
Here is a no-temporary, never leaves the value inconsistent, way to do it:

assume the current value of the byte  is in the_byte, and is represented
by the bit pattern:

   x y z a b c d e

where 'x y z' must be kept, and the new bit must be shifted in on the right
pushing 'b c d e' to the left one bit.
'a' of course drops out entirely.

then:

   movf        the_byte,W          ; W = x y z a b c d e
   andlw      B'00001111'        ; W = 0 0 0 0 b c d e
   addwf      the_byte,W          ; W = x y z a b c d e  + b c d e
   btfsc        the_byte,4            ; Was 'A' set?
   addlw      0-B'00010000'    ; Yes, take it out of the answer

W is now 'x y z a b c d e' + '0 0 0 0 b c d e' - '0 0 0 a 0 0 0 0'

This if of course equal to 'x y z b c d e 0' because we are adding two each
of 'b', 'c', 'd' and 'e', which will shift them up one position, and the two
'a's cancel each other.

Now we just have to insert the new bit into the LSBit of "W" before storing
the result.


Bob Ammerman
RAm Systems
(contract development of high performance, high function, low-level
sofftware)

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

2000\08\16@143500 by Jim Ham

flavicon
face
Well, this doesn't work. I must be suffering from brain-fade. I added line
numbers below. Note that on line 04 I modify the contents of byte1, then on
line 05 I expect to get back the original contents. Good trick!

Regards,

Jim Ham

At 10:35 AM 8/16/2000 , you wrote:
{Quote hidden}

Jim Ham, Porcine Associates
(650)326-2669 fax(650)326-1071
"http://www.porcine.com"

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

2000\08\16@150746 by Jim Ham

flavicon
face
Bob

Amazing clever as usual, but I'm confused. Wouldn't the final addlw
sometimes produce a carry into bit 5? Could you use an XOR rather than an
ADD to reverse the bit without the resulting carry?

Regards,

Jim Ham

At 11:17 AM 8/16/2000 , you wrote:
{Quote hidden}

Jim Ham, Porcine Associates
(650)326-2669 fax(650)326-1071
"http://www.porcine.com"

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

2000\08\16@152558 by Mike Eggleston

picon face
Bob Ammerman wrote:

{Quote hidden}

A very elegant solution!

Mike

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

2000\08\16@155726 by Oliver Broad

flavicon
face
rlf    byte1,w
xorwf    byte1,w
andlw    b'00011111'
xorwf    byte1,f


Oliver.

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

2000\08\16@161631 by Dmitry Kiryashov

flavicon
face
Hello Jean-Michel.

As far as I understand you need I can see two ways to do it.

1. You only need to shift single one register.

       rlf     byte1,W         ;get new bit from carry

       xorwf   byte1,W         ;get difference
       andlw   B'00011111'     ;0's will mask unchanged bits
       xorwf   byte1,F         ;update only required bits

2. You need to shift in such way through many registers.

       rlf     byte1,W         ;get new bit from carry
       andlw   B'00111111'     ;mask msb's but last
       addlw   B'11100000'     ;copy last to carry

       xorwf   byte1,W
       andlw   B'00011111'     ;see explanation of
       xorwf   byte1,F         ;this in example above
;then
;
       rlf     byte2,W
       andlw   B'00111111'
       addlw   B'11100000'
;
;and so on as many bytes as you need ;)


WBR Dmitry.



{Quote hidden}

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

2000\08\16@172651 by Bob Ammerman

picon face
I bow to a master!

Bob Ammerman
RAm Systems
(contract development of high performance, high function, low-level
sofftware)

{Original Message removed}

2000\08\16@190012 by Bob Ammerman

picon face
Actually the final ADDLW is actually _subtracting_ the value of A, only if
it was added in before. The add and subtract cancel each other, and thus
their affect on bits 5 through 7.

Carry is thus not an issue.

{Original Message removed}

2000\08\16@191617 by Scott Dattalo

face
flavicon
face
It isn't immediately clear from your question whether the upper three bits need
to be held constant all of the time OR only after every 5 bits are shifted
in. If it's the latter, then you could do this:

   rrf   byte1,f
   swapf byte1,f

and then proceed with the 5 (left) shifts.


Scott

On Thu, 17 Aug 2000, Dmitry Kiryashov wrote:

{Quote hidden}

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

2000\08\16@205259 by Jim Ham

flavicon
face
At 03:56 PM 8/16/2000 , you wrote:
>Actually the final ADDLW is actually _subtracting_ the value of A, only if
>it was added in before. The add and subtract cancel each other, and thus
>their affect on bits 5 through 7.
>
>Carry is thus not an issue.

Hmmm....

start with the_byte = 0b0001 0000

> > >     movf        the_byte,W          ; W = x y z a b c d e

W = 0b0001 0000

> > >     andlw      B'00001111'        ; W = 0 0 0 0 b c d e

W = 0b0000 0000

> > >     addwf      the_byte,W          ; W = x y z a b c d e  + b c d e

W = 0b0001 0000

> > >     btfsc        the_byte,4            ; Was 'A' set?

yes

> > >     addlw      B'00010000'    ; Yes, take it out of the answer

W = 0b0010 0000

To subtract wouldn't you have to add the 2's compliment?

addlw   0b1111 0000

for the result of:

W = 0b0000 0000

Am I missing something here? I normally don't try to keep up with the
"masters"!

Regards,

Jim Ham




Jim Ham, Porcine Associates
(650)326-2669 fax(650)326-1071
"http://www.porcine.com"

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

2000\08\16@221300 by Bob Ammerman

picon face
Jim,

Adding the two's complement is exactly what I was doing. The original
instruction was:

   addlw    0-B'0001000'

Notice the '0-' in front of the value.

I find that MPASM is sometimes confused by a unary minus, hence I always
subtract from zero.

I use addlw rather than sublw because sublw is defined to compute
'literal-W', rather than 'W-literal'.

It sure is good to see that someone is watching me closely on this stuff ;-)

obtw: Jim Ham :: Porcine Associates - awesome!

Bob Ammerman
RAm Systems
(contract development of high performance, high function, low-level
sofftware)

{Original Message removed}

More... (looser matching)
- Last day of these posts
- In 2000 , 2001 only
- Today
- New search...