Reputation: 597
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
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
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
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