Shop OBEX P1 Docs P2 Docs Learn Events
Bitwise commands - Trying to understand — Parallax Forums

Bitwise commands - Trying to understand

JomsJoms Posts: 279
edited 2011-07-19 12:00 in Propeller 1
As many of you know, I have been playing with the prop for some time, but still having a hard time understanding how to use the binary commands. I am now working on a project that controls 12 DMX LED lights (each red/green/blue). Although I got the code working, I really think it can be cleaned up A LOT by the use of binary operators instead of the way I am doing it.

As an example, this is what I did to make it work. I created a variable that has 12 bytes, and really it only needs to control if the lights is on or off. So I use the following piece of code to turn the LED's on or off.
pub alloff | i
  repeat i from 0 to 11                                   'repeat 12 times
    ledonoff[i] := 0                                         'set all bytes to 0
  senddmxout                                              'send ledonoff var out
  waitcnt(clkfreq / (dmxin.read(5)+1) + cnt)     'used dmx channel 5 to change speed, mainly for chases
  main

To turn all the LED's on, I use the same as above, just with ledonoff := 255

This is what I use to send the dmx code:

pub senddmxout | light, chan, total, r, g, b    
  chan := 0
    repeat light from 0 to 11  
      r := 0
      g := 0
      b := 0
      total := dmxin.read(4)
      if ledonoff[light] > 0
        r := dmxin.read(1)                                           'red channel in
        g := dmxin.read(2)                                         'green channel in
        b := dmxin.read(3)                                          'blue channel in
      if total < r
        r := total
      if total < g
        g := total
      if total < b
        b := total           
      dmxout.write(chan++, r)
      dmxout.write(chan++, g)
      dmxout.write(chan++, b)

  pause(10)

  return

Now the learning part... I have been trying to revise the code to use a 3 byte array and use control the lights like this:
ledonoff === %0000_0000_0000        'would turn all lights off
ledonoff === %1111_1111_1111        'would turn all lights on

This is what I think I should use to send the dmx code:
pub senddmxout | light, chan, total, r, g, b    
  chan := 0
    repeat light from 0 to 11  
      r := 0              'set local red variable to 0
      g := 0             'set local green variable to 0
      b := 0             'set local blue variable to 0
      total := dmxin.read(4)                 'set dmx total
      if ledonoff[light]->     'check if variable is a 1 or 0, rotate right after checking     'PROBLEM LINE
        r := dmxin.read(1)        'red channel in
        g := dmxin.read(2)       'green channel in
        b := dmxin.read(3)       'blue channel in
      if total < r
        r := total
      if total < g
        g := total
      if total < b
        b := total           
      dmxout.write(chan++, r)
      dmxout.write(chan++, g)
      dmxout.write(chan++, b)

  pause(10)

  return

I am just trying to understand how to convert some of these for loops into a binary array so it will be much easier to control the lights in chases, etc. I know it is working now, but I want to get a better understanding also...

THANKS in advance for any explination you can have to step me closer to understanding this...

Comments

  • JonnyMacJonnyMac Posts: 9,208
    edited 2011-07-19 11:35
    It might be easy to use a method that returns a bit value (0 or 1) from any other value. This is what I use:
    pub getbit(target, pos)
    
    '' returns bit value (0..1) of target.pos
    
      if ((pos => 0) and (pos =< 31))
        return (target >> pos) & 1
      else
        return 0
    

    If all of your red channel bits are stored in a word, you could do something like this:
    repeat idx from 0 to 11
        red[idx] := getbit(redbits, idx) * 255
    

    If you don't want to be bothered with the getbit() method, there's always...
    repeat idx from 0 to 11
        if (redbits & (|< idx))
          red[idx] := 255
        else
          red[idx] := 0
    
  • JasonDorieJasonDorie Posts: 1,930
    edited 2011-07-19 12:00
    Simple operations:

    << is move all bits to the left. 000111 << 2 == 011100 (moved the bits left two positions)
    >> is move all bits to the right. 001100 >> 1 == 000110 (moved the bits right one position)

    To produce a number with a single bit position ON, use 1 << x, where x is the bit position to turn on. (1 << 5) produces 00010000.
    To produce a number with a single bit position OFF, use ~(1 << x).

    ~ is the NOT operator - it means "produce the bitwise opposite", like this:
    ~0010000 == 1101111

    | is "or". It mushes all the bits together, like this:

    001110
    | 010000
    011110 Bits that were on in EITHER input come out in the result.

    So, to set a specific bit in a number, use | (or) (1 << x) where x is the bit position from 0 to 31


    & is "and" - it takes the left argument and applies the right argument as a mask, like this:
    001110
    & 001000
    001000 Only the bits that were on in BOTH numbers come out in the result.

    You can use this to test if a bit is on, like this:
    if( (bunchOfBits & (1 << 5)) > 0 )
    // Bit 5 is on...

    To turn off a specific bit, use & ~(1 << x) - it takes that single bit, NOTs it to turn on all the other bits, leaving that single one off, then ANDs the original value by it.


    In JonnyMac's example, |< idx is a SPIN shortcut for (1 << idx).

    Sorry if this is simpler than you were looking for, but if you don't have a good handle on binary numbers, this is the place to start.
Sign In or Register to comment.