Carlo
Carlo

Reputation: 597

How to make specific bit manipulation?

I'm doing practice of bit manipulation in arduino with a 74HC595 shift register.

I would like to create an algorithm that allows the binary digit to perform this way:

1 0 0 0 0 0 0 1

0 1 0 0 0 0 1 0

0 0 1 0 0 1 0 0

.

.

.

1 0 0 0 0 0 0 1

In this type of function the decimal values are: (129,66,36,24,24,36,66,129) and so on in a loop.

How can I perform this type of shifting? I don't have any fluency thinking this type of operation, I have only performed a circular shift with "an algorithm" like:

//my circular shift

myByte = myByte*128 + myByte/2

But I don't know how to perform the output that I showed.

How can I do this? Thanks

Upvotes: 1

Views: 110

Answers (3)

Carlo
Carlo

Reputation: 597

Noticing that:

129,66,36,24,24,36,66,129 = 128+1; 64+2 ; 32+4; 16+8; 16+8; 32+4; 64+2; 128+1;

I ended up with this code:

int latchPin = 11;
int clockPin = 9;
int dataPin = 12;
int dt = 2000;
uint8_t n1 = 128, n2 = 1;
byte myByte = 0b10000001; //in BIN

void setup() {
Serial.begin(9600);
pinMode(latchPin,OUTPUT);
pinMode(dataPin,OUTPUT);
pinMode(clockPin,OUTPUT);
}

//circular shift to the left
void loop() {
digitalWrite(latchPin,LOW);
shiftOut(dataPin,clockPin,LSBFIRST,myByte);
digitalWrite(latchPin,HIGH);
int i;


myByte = 0b10000001; //restarting the value of 129
        Serial.print("BIN: ");
        Serial.print(myByte,BIN);
        Serial.print(" --> ");
        Serial.print("HEX: ");
        Serial.print(myByte,HEX);
        Serial.print(" --> ");
        Serial.print("DEC: ");
        Serial.println(myByte,DEC);
        delay(200);


    for (int i = 0; i < 7; i++) {
        Serial.print("i:  ");
        Serial.println(i);
        //int i1 = i+1;
        //int myGap = myByte - (pow(2,i));      //no need to round when it's raised to 0;
        //int firstpart = (myGap/2);
        //int secondpart = 0.5 + pow(2,i1);     //because it rounds the number. (i.e --> 1.9999 = 1)
        //myByte = firstpart+ secondpart;

          myByte = (myByte - (pow(2,i)))/2 + (0.5 + pow(2,i+1));

        //Serial.print("firstpart: ");
        //Serial.println(firstpart);
        //Serial.print("secondpart: ");
        //Serial.println(secondpart);
        //delay(3000);
        Serial.print("BIN: ");
        Serial.print(myByte,BIN);
        Serial.print(" --> ");
        Serial.print("HEX: ");
        Serial.print(myByte,HEX);
        Serial.print(" --> ");
        Serial.print("DEC: ");
        Serial.println(myByte,DEC);
        digitalWrite(latchPin,LOW);
        shiftOut(dataPin,clockPin,LSBFIRST,myByte);
        digitalWrite(latchPin,HIGH);
        delay(100);
    }
//myByte = myByte*2;    //shift by right //using MSBFIRTS
//delay(dt);
}

And it works.

Upvotes: 0

Vlad from Moscow
Vlad from Moscow

Reputation: 311126

For example you can use the following approach

#include <iostream>
#include <iomanip>
#include <limits>

int main() 
{
    unsigned char b = 0b10000001;
    int width = std::numeric_limits<unsigned char>::digits / 2;

    for ( int i = 0; i < width; i++ )
    {
            std::cout << std::hex << static_cast<int>( b ) << " - "
                      << std::dec << static_cast<int>( b ) << '\n';
            b = ( b & ( 0b1111 << width ) ) >> 1 | ( b & 0b1111 ) << 1;
    }

    for ( int i = 0; i < width; i++ )
    {
            std::cout << std::hex << static_cast<int>( b ) << " - "
                      << std::dec << static_cast<int>( b ) << '\n';
            b = ( b & ( 0b1111 << width ) ) << 1 | ( b & 0b1111 ) >> 1;
    }

    return 0;
}

The program output is

81 - 129
42 - 66
24 - 36
18 - 24
18 - 24
24 - 36
42 - 66
81 - 129

Upvotes: 1

JohnFilleau
JohnFilleau

Reputation: 4288

You're looking for a single operation that can be applied to an 8 bit number and result in the given pattern.

You want

x_(n+1) = f(x_(n))

for all given inputs and outputs. The problem is that there are a few potential inputs that have one of two possible outputs. You want both

36 = f(66)

and

129 = f(66)

This can't be done using only one variable. You can either implement a lookup table for the sequence you want (which is what I suggest). Or you can take two variables, implement circular shifts (in opposite directions) on each, and take the bitwise OR of the results.

uint8_t n1 = 128, n2 = 1;
for(;;)
{
    std::cout << n1 | n2 << "\n";
    n1 = circular_right_shift(n1);
    n2 = circular_left_shift(n2);
}

Upvotes: 1

Related Questions