Thread: bit manipulation in both directions

  1. #1
    Registered User
    Join Date
    Apr 2008
    Posts
    204

    bit manipulation in both directions

    Hi.
    I am trying to write a couple of algorithms that take in a 16 bit number, use a mask to move along the bits and if the mask & number = 1, do something.
    The first thing to point out is this is going on a microcontroller. For that reason i am not looping through the entire 16 bit value in one go, I only do one at a time, so the program can return to whatever else it was doing in the mean time, and only do the next "bit" when a timer ticks so I need to save the last state of the changing variables between function calls.
    I only however need the 12 Most significant bits, the 4 least significant bits I am using for something else, so my boundaries of the mask are 0x8000 and 0x10. One of my algorithms goes from left to right arpUp, and one goes from right to left:
    Code:
    void Arpeggiator::arpUp(unsigned int chord, int numOctaves) {
    	
    	if (mask == 0x10) {
    		mask = 0x8000;
    		arpPosition = leftBoundary;
    	}
    	if (mask & chord) {
    		arpeggioPlay(arpPosition);
    	}
    	mask >>= 1;
    	arpPosition++;
    }
    So this checks if it is at the right boundary. If so, move the mask back to the left. and move the variable also.
    The problem with that is it doesnt do "arpPlay()" when mask == 0x10 and (mask & chord)
    I "could" do if (mask < 0x10) but I cant do the equivelent check for the arpDown function (if (mask > 0x8000)) because thats the end of the memory for the 16 bit value so I have:

    Code:
    void Arpeggiator::arpDown(unsigned int chord, int numOctaves) {
    	arpPosition--;
    	if (arpPosition < startNote){
    		arpPosition = startNote + 12;
    	}
    	if (mask & chord) {
    		arpeggioPlay(arpPosition);
    	}
    	maskDown <<= 1;
    	if (mask == 0x8000) {
    		if (mask & chord) {
    			arpeggioPlay(60);
    		}
    		mask = 0x10;
    	}
    }
    This ones a bit of a mess, because Ive been trying a few things. It sort of works, but its the end conditions that cause me problems

    I also dont like hardcoding in
    Code:
    if (mask & chord) {
    			arpeggioPlay(60);
    		}
    when the check to see if mask == 0x8000, seems like a hack.

    im also trying to use mask and arpPosition as member variables to save on memory, but that means that depending on which of the above two are called, there needs to be some initial setup.
    Thanks guys

  2. #2
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    Have you tried something like if ( mask >= 0x10 && chord & mask ) ... because I think that will work. Clearly you want to play arpeggios up to and including that point if necessary.

  3. #3
    Registered User
    Join Date
    Apr 2008
    Posts
    204
    What about when it hits 0x8000? Will it just stop?
    Sorry do you mind showing me what you would do for the other direction? Im not sure how to handle that one.

  4. #4
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    I think that should be treated as a special case, because as you say, it is a 16-bit boundary. I wouldn't want to tell you to write something like

    if ( mask <= 0x8000 && chord & mask )

    The comparison itself is probably okay but instructions like mask <<= 1 would cause overflow, unlike what would happen when mask == 0x10, going in the other direction. No underflow there. Sorry if I've been unhelpful.

  5. #5
    Registered User
    Join Date
    Apr 2008
    Posts
    204
    So what would be the solution - thats my problem, I cant work out the solution to that "special case".

  6. #6
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    By special case, I mean we should probably stick to code that you have already, since you are already treating mask == 0x8000 as a special case, and it works. I can't really think of a logically equivalent way that is sufficiently safe. If you can guarantee that int is more than 16-bits, then you can try what I posted earlier with nothing to worry about.

  7. #7
    Registered User
    Join Date
    Jun 2011
    Posts
    4,513
    Perhaps I'm not fully understanding what you're trying to accomplish, but couldn't you just do the mask first, and then check the position to see if you should wrap around to the other boundary?

    i.e.

    Code:
    void Arpeggiator::arpUp(unsigned int chord, int numOctaves) {
    
        if (mask & chord) {
            arpeggioPlay(arpPosition);
        }
        if (mask == 0x10) {
            mask = 0x8000;
            arpPosition = leftBoundary;
        }
        else {
            mask >>= 1;
            arpPosition++;
        }
    }
    
    
    void Arpeggiator::arpDown(unsigned int chord, int numOctaves) {
    
        if (mask & chord) {
            arpeggioPlay(arpPosition);
        }
        if (mask == 0x8000) {
            mask = 0x10;
            arpPosition = rightBoundary;
        }
        else {
            maskDown <<= 1;
            arpPosition--;
            if (arpPosition < startNote){
                arpPosition = startNote + 12;
            }
        }
    }

  8. #8
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    When shifting left, the 0x8000 value will shift the bit off the end and wind up equalling zero, so you can check for 0 instead of > 0x8000.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. I need directions
    By JacobN in forum C++ Programming
    Replies: 5
    Last Post: 09-26-2008, 07:22 AM
  2. C student doesn't understand directions
    By Boboki in forum C Programming
    Replies: 9
    Last Post: 02-17-2005, 05:05 PM
  3. Directions!!!!!!!!
    By Joe100 in forum C++ Programming
    Replies: 13
    Last Post: 09-25-2003, 05:21 PM
  4. Directions
    By whistlenm1 in forum A Brief History of Cprogramming.com
    Replies: 4
    Last Post: 08-06-2002, 01:03 PM