Shop OBEX P1 Docs P2 Docs Learn Events
How do I shift a number and get each bit 1 at a time — Parallax Forums

How do I shift a number and get each bit 1 at a time

CelticLordCelticLord Posts: 50
edited 2014-09-30 06:11 in General Discussion
Example: if I take a number say 148 and I want to shift it left 8 times but get each of the bits every time I shift it......
10010100 << 1 = 1
00101000 << 1 = 0
01010000 << 1 = 0
10100000 << 1 = 1
01000000 << 1 = 0
10000000 << 1 = 1
00000000 << 1 = 0
00000000 << 1 = 0

This is posible in asm with the flags but I want to do it in spin.

Comments

  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-09-29 09:29
    You can get the least signicant bit by "and"ing it with one. Shift the value right to keep moving the bits over.

    Bitwise and is the "&" symbol.
  • CelticLordCelticLord Posts: 50
    edited 2014-09-29 09:36
    ok..
    When I feed it
    MaxOut (DOut, CLK, %10000010, 8)
    I get the expected bits, but when I feed it...
    MaxOut (DOut, CLK, %0110000000000000, 16)
    I get all 0's
    PUB MaxOut (Dpin, Cpin, oValue, obits)| bitNum
      REPEAT obits                                                                
        Num := oValue >>= (obits-1)
        obits--
    
  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-09-29 09:59
    I haven't tested the below, but I think it should show you how to set multiple outputs at once.
    CON 
      HIGH_PIN = 23
      LOW_PIN = 16
    
    PUB Main | oValue
      dira[HIGH_PIN..LOW_PIN] := 255
      repeat
        LightBits(oValue++)
        waitcnt(clkfreq / 4 + cnt)
    
    PUB LightBits(value)
      
      outa[HIGH_PIN..LOW_PIN] := value
    
    

    I think I was replying to a different post. The above code doesn't correspond to the question in post #3 (which I think CelticLord was still editing when I initially replied.)

    I'll leave this post in case it's useful but it doesn't answer the question asked.
  • CelticLordCelticLord Posts: 50
    edited 2014-09-29 10:06
    This is all being sent to 1 Data pin on MAX1497 ADC chip. So i need to be able to get each bit from a 16 bit word.
    As i said it works fine on byte but all 0's with the word?
  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-09-29 10:14
    The "send" method in this tutorial of shows how to shift bits out. The method was written with I2C in mind so just delete the line:
    [COLOR=#333333][FONT=Lucida Console]value := ((!value) >< 8)[/FONT][/COLOR]
    

    To keep it from reversing the bits.
  • CelticLordCelticLord Posts: 50
    edited 2014-09-29 10:33
    Apparently Im not understanding or your not, that is for byte size numbers hence Repeat 8 in the code. When I try doing it as in my code and that code, Word >>= n, it just returns 0's
  • tomcrawfordtomcrawford Posts: 1,126
    edited 2014-09-29 10:54
    My inclination would be to align the first bit at bit 31 by left shifting (32-obits) and then left cycle one bit at a time (leaving the current output bit at bit zero).
  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-09-29 11:10
    CelticLord wrote: »
    Apparently Im not understanding or your not, that is for byte size numbers hence Repeat 8 in the code. When I try doing it as in my code and that code, Word >>= n, it just returns 0's

    You should be able to change the "8" to any number up to 32. If it won't shift more than 8 I suggest posting all your code as an archive. The problem may be elsewhere in the code.

    All local variables are longs (32-bit).
  • CelticLordCelticLord Posts: 50
    edited 2014-09-29 11:58
    Please try I keep getting everything but what I need
    VAR                                                          ' Conversion Result
      Long Num
      Word Volts                                                 ' Result --> mVolts
      Word Value, Mout                                                 ' Result --> Value
      Byte Status, rFlag
    PUB Main
      'pst.Str(String(2,1,1,"ADC CH 0: ",2,1,2,"        Raw   : Volts"))  
      dira[DOut]~~
      dira[Clk]~~
      dira[DIn]~
      dira[CS]~~
      outa[CS]~~
      outa[CS]~
      MaxOut (DOut, CLK, %10000010, 8)                           ' Enable Write to Control Register %10 00001 0
      MaxOut (DOut, CLK, %0110000000000000, 16)                  ' Enable bit ON ,RANGE = 2.0 Volts %0110000000000000
      
      
    PUB MaxOut (Dpin, Cpin, oValue, obits)| bitNum
        'Tryed to alaign it assuming its 32 bit local var---------------
        if obits > 8
          Mout := oValue -> 17
        else
          Mout := oValue -> 25    
        '---------------------------------------------------------------
        
        Num := 0 
        REPEAT obits
          Num := Mout >>= (obits-1)
          obits--
          if Num > 0
            outa[Dpin]~~
          else
            outa[Dpin]~           
          !outa[Cpin]                                              ' cycle clock          
          !outa[Cpin]
          pst.Str(String("     ",13))'2,2,4))
          pst.dec(Num)
          pst.Str(String("     ",13))'2,2,14))
          pst.dec(obits)                                                            
        waitcnt(clkfreq+cnt)                              
        waitcnt(1000 + cnt)                                      ' delay                
      outa[Dpin]~                                                ' Set data to low  
    
  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-09-29 12:06
    I linked to code showing how to shift out bits. The code you posted doesn't look much like what I suggested. Nor does it look like you followed my advice in your other thread.

    I'm using strike out a lot today.

    Sorry, the code I linked to was I2C code. I'll modify your code to do what I think you want it to. This will take a couple of minutes.

    Edit: I changed my mind.
  • CelticLordCelticLord Posts: 50
    edited 2014-09-29 12:12
    Look Im trying to learn this spin so if you'd help and not just talk. Im lost as to what you were doing I guess. Frustraited as XXXX too
  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-09-29 12:23
    Duane Degn wrote: »
    I'll modify your code to do what I think you want it to. This will take a couple of minutes.

    I'm working on your code to show you how to shift bits and I get this?
    CelticLord wrote: »
    Look Im trying to learn this spin so if you'd help and not just talk. Im lost as to what you were doing I guess. Frustraited as XXXX too

    Good bye.
  • Dave HeinDave Hein Posts: 6,347
    edited 2014-09-29 12:48
    Celtic,

    I would suggest shifting your data all the way to the left to align it with the most significant bit, which is the sign bit. That way you can determine the value of the bit by checking the sign of the value. To do this you should make Mout a long instead of a word.

    Your initial alignment statement should then be:

    Mout := ovalue << (32 - obits)

    The first lines of your repeat loop would be
      repeat obits
        Num := Mout
        Mout <<= 1
        if Num < 0
          outa[Dpin]~~
        else
          outa[Dpin]~
    
  • JonnyMacJonnyMac Posts: 9,105
    edited 2014-09-30 06:11
    This is all very easy once you get the hang of Spin, and stop trying to make it work like PBASIC.

    Tips:
    -- define your connections to the MAX1487 as constants -- no need to pass pin #s (as you only have on device, right?)
    -- learn the shift (<<, >>) and rotate (<-, ~>) operators as they are very powerful

    Reviewing the data sheet, it looks like you can do 8- or 16-bit reads, and always with a control byte. I would code a general read routine like this:
    pub read_1497(ctrl, bits) | work
    
      outa[CS] := 0                                                 ' chip select low
    
      ctrl <<= 24                                                   ' move to high byte
    
      repeat 8                                                      ' shift out control byte
        outa[DIN] := ctrl <-= 1                                     ' rotate for msb
        outa[SCLK] := 1
        outa[SCLK] := 0
    
      work := 0
        
      repeat bits                                                   ' shift in data bits
        work := (work << 1) | ina[DOUT]
        outa[SCLK] := 1
        outa[SCLK] := 0
    
      outa[CS] := 1                                                 ' de-select
    
      return work
    


    Again, this assumes that the pins are defined as constants and setup (outputs where needed) in the initialization part of your program.

    BTW, DIN is the Propeller pin connected to the MAX1497.DIN pin; DOUT is the Propeller pin connected to the MAX1497.DOUT pin.

    Finally...
    Look Im trying to learn this spin so if you'd help and not just talk.


    Comments like that are the fastest way to get you added to an "Ignore User" list (Congrats, you've already made Duane's). Nobody owes you anything here. Be polite and you'll get the help you need.
Sign In or Register to comment.