How can I perform this conversion?
I have 9 ints that I need to change into 12 sequential bytes.
Only 9 bits of each int are needed; the 9 bits go into the 12 bytes with int 9, bit 8 going into byte 11, bit 7. See the chart. byte 1 bits 6-0 and byte 0 are not used.
Am I stuck doing something like shifting the correct bits into position, masking them off so they look like bytes, then ORing the remnants of 2 partial ints into the byte postions?
I need to do this 9 times every 3mS to drive an LED cube, so a quick method is needed.
int-byte_conversion.xlsx (11.6 KB)
You may need to use an array for the 12 bytes, this way you can use bitRead and the module operator. The first Int gets stored at 0x80 of the first byte, so you will need to start a counter at say 7. Increment that counter from 0 - 8, and use the module operator to increment the index when the counter is 7, to change which byte the int value(bit) gets stored into.
If I had my Nano, with me I could do a test, but unfortunately, I left it home. Sorry.
(Crossroad asking a question - must try and answer !)
Cant think of anything faster. With a little carefull programming not take much more then 20-50 instructions... or about 20 uS meaning it will take less than a thousandth of your 3 ms time window.
If for some reason yu are stuck by extreme time problem, you could rewire your output circuitry so the ints map better, ie the redunant bits are ignored (I presume we're talking a set of shift registers here)
How's this method look?
// anodeArray[11], int 8, bits 8-1
anodeArray[11] = ( workingArray[8] & 0b0000000111111110)>1;
// anodeArray[10], int 8 bit 0, int 7 bits 6 to 2
anodeArray[10] = ( ((workingArray[8] & 0b0000000000000001)<<7) | ((workingArray[7] & 0b0000000111111100)>>2) );
// anodeArray[9], int 7 bits 1, 0, int 6 bits 8 to 3
anodeArray[9] = ( ((workingArray[7] & 0b0000000000000011)<<6) | ((workingArray[6] & 0b0000000111111000)>> 3) );
// anodeArray[8], int 6 bits 2-1-0, int 5 bits 8 to 4
anodeArray[8] = ( ((workingArray[6] & 0b0000000000000111)<<5) | ((workingArray[5] & 0b0000000111110000)>> 4) );
// anodeArray[7], int 5 bits 3 to 0, int 4 bits 8 to 5
anodeArray[7] = ( ((workingArray[5] & 0b0000000000001111)<<4) | ((workingArray[4] & 0b0000000111100000)>> 5) );
// anodeArray[6], int 4 bits 4 to 0, int 3 bits 8,7,6
anodeArray[6] = ( ((workingArray[4] & 0b0000000000011111)<<3) | ((workingArray[3] & 0b0000000111000000)>> 6) );
// anodeArray[5], int 3 bits 5 to 0, int 2 bits 8, 7
anodeArray[5] = ( ((workingArray[3] & 0b0000000000111111)<<2) | ((workingArray[2] & 0b0000000110000000)>> 7) );
// anodeArray[4], int 2 bits 6-0, int 1 bit 8
anodeArray[4] = ( ((workingArray[2] & 0b0000000001111111)<<1) | ((workingArray[1] & 0b0000000100000000)>> 8) );
// anodeArray[3], int 1 bits 7 to 0
anodeArray[3] = workingArray[1] & 0b0000000011111111 ;
// anodeArray[2], int 0 bits 8 to 1
anodeArray[2] = ( workingArray[0] & 0b0000000111111110) >>1 ;
// anodeArray[1], int 0 bit 0
anodeArray[1] = workingArray[0] & 0b0000000000000001 ;
// anodeArray[0], not used
anodeArray[0] = 0;
Do I need to add some byte( ) kind of things to the right hand side for type casting or some such nonsense?
Or will all the 0's in the upper 8 bits make that happen automagically in the C++ compiler after the masking & shifting?
Argh, last one needs shifting to put it at MSB of the byte
// anodeArray[1], int 0 bit 0
anodeArray[1] = (workingArray[0] & 0b0000000000000001) << 7 ;
The control board is already made.
Would have been convenient to have 16 bits of shift register/row, but there is a limit to how much can be squeezed into a 10cmx 10cm card. I needed 81 bits of output, 10 shift registers plus 1 bit. Put on 12 because they fit well and the extra 15 bits might come in handy for some other project, or a 9 x 10 x 9 layer cube.
Need to get a better picture. The wires are all in crimp housings now.
picture here
http://forum.arduino.cc/index.php?topic=257061.0
Other than missing a >, will it need some type casting added?
Such as, or whatever the syntax is?
anodeArray[10] = ( byte ((workingArray[8] & 0b0000000000000001)<<7) | byte ((workingArray[7] & 0b0000000111111100)>>2) );
That last little bit always seems to get me, trying to get it right to start this time.
Is this something that needs to happen at runtime? are you just shwoing static patterns, or are you taking data from somewhere and trying to display it?
I want to do this runtime.
The 9 ints (acutally 81 as it's for a 9x9x9 LED cube) may eventually come from an SD card, or be supplied from a PC, or reflect someone moving a joystick around, anything where the data can be easily visualized as from 0 to 8 in X, Y, Z.
To start I will create some patterns and store them as arrays of ints, and use the above as the conversion from the stored file to the IO that the anodes will be driven with.
Then try manipulating matrixes from one pattern into another, like having one face light up, and move the face around the perimeter of the cube, or across the cube.
Lot more software than I usually write as a hardware designer.
You can give this a shot, I did kinda just threw it together, so if it doesn't work, i'm sorry.
int data[9];
byte output[12];
byte counter = 0, i = 0, j = 0, k = 0;
boolean done = false, shown = false;
void setup()
{
Serial.begin(115200);
delay(1);
setArrays();
showArrays();
i = 7;
}
void loop()
{
while(done == false)
{
for(byte counter = 0; counter < 9; counter++)
{
bitWrite(output[j], i, bitRead(data[k], counter));
i++;
if(i > 7)
{
j++;
i = 0;
}
}
if(k < 9)
k++;
else
done = true;
}
showCompletedOutput();
}
void setArrays()
{
for(byte tmp = 0; tmp < 9; tmp++)
data[tmp] = random(255, 5000);
for(byte tmp2 = 0; tmp2 < 12; tmp2++)
output[tmp2] = 0;
}
void showArrays()
{
Serial.print("Data: ");
for(byte tmp = 0; tmp < 9; tmp++)
{
Serial.print(data[tmp]);
Serial.print(", ");
}
Serial.println();
Serial.print("Output: ");
for(byte tmp2 = 0; tmp2 < 12; tmp2++)
{
Serial.print(output[tmp2]);
Serial.print(", ");
}
Serial.println();
}
void showCompletedOutput()
{
if(shown == false)
{
Serial.print("Completed Output: ");
for(byte tmp2 = 0; tmp2 < 12; tmp2++)
{
Serial.print(output[tmp2]);
Serial.print(", ");
}
Serial.println();
shown = true;
}
}
That looks to be doing a lot of looping. My testing with for loops in the past is that adds 12uS every pass thru a loop, so I'd like to avoid that if at all possible.
On the other hand, all the shifting might kill performance too.
Have to get my scope out & see.
If for some reason yu are stuck by extreme time problem, you could rewire your output circuitry so the ints map better, ie the redunant bits are ignored (I presume we're talking a set of shift registers here)
That's another option - make the bytes ints instead:
^ ^ ^ ^ ^ ^ ^ ^ ^
| | | | | | | | |
b b b b b b b b b
y y y y y y y y y
t t t t t t t t t
e e e e e e e e e
0 1 2 3 4 5 6 7 8
| | | | | | | | |
v v v v v v v v v
<- b y t e 9 -> X across the back row
and 1 bit of byte 10 for X, the very last column.
This is a little closer to what you wanted, conversion-wise, but speed-wise, I'm not sure.
Edit:
int data[9];
boolean Output[144];
byte counter = 0, i = 0, j = 1, k = 0;
boolean done = false, shown = false;
long time[9];
void setup()
{
Serial.begin(115200);
delay(1);
setArrays();
showArrays();
i = 14;
}
void loop()
{
while(done == false)
{
time[k] = micros();
for(byte counter = 0; counter < 9; counter++)
{
Output[i] = bitRead(data[k], counter);
i++;
}
if(k < 9)
k++;
else
done = true;
}
showCompletedOutput();
}
void setArrays()
{
for(byte tmp = 0; tmp < 9; tmp++)
data[8-tmp] = random(255, 5000);
for(byte tmp2 = 0; tmp2 < 144; tmp2++)
Output[tmp2] = 0;
}
void showArrays()
{
Serial.print("Data: ");
for(byte tmp = 0; tmp < 9; tmp++)
{
Serial.print((data[8-tmp] & 0x1FF), BIN);
Serial.print("|");
}
Serial.println();
Serial.print("__________Output: ");
for(byte tmp2 = 0; tmp2 < 72; tmp2++)
{
Serial.print(Output[tmp2],BIN);
if((tmp2 % 8) == 0)
Serial.print("|");
}
}
void showCompletedOutput()
{
if(shown == false)
{
Serial.println();
Serial.print("Completed Output: ");
for(byte tmp2 = 0; tmp2 < 72; tmp2++)
{
Serial.print(Output[71-tmp2],BIN);
if((tmp2 % 8) == 0)
Serial.print("|");
}
Serial.println();
for(byte t= 0; t < 9; t++)
{
Serial.print(time[t]);
Serial.print("|");
}
shown = true;
}
}
Data: 100001011|110001101|1110110|11010|10110011|111101111|111010100|11110|100001000|
__________Output: 0|00000000|00000000|00000000|00000000|00000000|00000000|00000000|00000000|0000000
Completed Output: 0|11000001|10100101|10011111|10111111|10101000|00011110|10000100|00000000|0000000
12704|12732|12760|12792|12820|12848|12884|12912|12944|
I'd go with the approach in reply #3 ( without the minor bugs ).
Each of your 12 output bytes contains either part of one of your input ints, or else it contains the second part of one of the ints and the first part of the next one.
It would be possible to write a reasonably fast algorithm for this in assembler.
Ok, the method seems to be working.
Takes 844uS to do the mapping from the ints to the bytes.
I see a little flicker every time it runs.
Had to change the OR gate to an AND gate and use a positive chip select for the anode shift registers, was getting an extra clock that made 1 column always on.
Definitely need to check the column to board wiring - either my logic for the mapping is off, or the wiring is, not too many columns are where they're supposed to me.
I'm thinking its the wiring, I'm seeing the LSB register all populated, and only 1 wire on the MSB register, so things got mixed up it appears when we went from loose wires into the crimp headers. Dang, I don't look forward to pulling 81 of those apart.
Or maybe the headers just got plugged into the wrong places - wish me luck!
_9x9x9LEDcube_complete.ino (29.3 KB)
844 us to do that 81 times actually seems quite good.
One thing I don't understand , is why you made all those binary constants 16 bits long, when you are trying to put results into the anodeArray[] elements which are bytes.
I need 9 bits/row.
I've got this string of shift registers 96 bits long that represents the hardware, of which 81 are used.
I figure it's got to be easier to have the representation of the cube for manipulating as an array of ints, 9 per layer and 9 layers, vs 8 bits and 1, 7 bits and 2, 6 bits and 3, etc. of bytes. That way bit 0 is always an outer edge, bit 8 is always the opposite edge, bit 4 is always the middle, etc.
Maybe it will turn out not to be, that 9 bytes with a 10th perpinduculer to the rest and 1 more for the corner bit will be the way to go. Maybe treating it as 18 bytes (vs 9 ints) will be more straightforward, with bit 0 of the "upper" bytes representing the 9th LED of each column. I don't know.
At the moment, I'm trying to get the wiring from board to column straightened out, I think it got mixed up when we put the male terminated pins into crimp housings. I'm hoping that the connectors just got swapped, or maybe the board was spun around, something simple. Otherwise, we pull all the wires out of the housings and start over again.