/*
Forum: https://forum.arduino.cc/t/can-this-array-rotation-be-better/1167029
Wokwi:https://wokwi.com/projects/375568237709771777
*/
// Initialized with "heart" image
uint32_t frame[3] = {
0x3184a444,
0x42081100,
0xa0040000
};
// Initialized with "heart" image
byte rot_frame[12] = {0, 96, 144, 136, 68, 34, 68, 136, 144, 96, 0, 0};
unsigned long startTime = 0;
constexpr byte NoOfTest = 10;
void setup() {
Serial.begin(115200);
Serial.println("Start");
//printMatrix();
Serial.println(F("---convert---"));
startTime = micros();
for (int k = 0; k < NoOfTest; k++) convertFrame();
Serial.print((micros() - startTime) / NoOfTest);
Serial.println(F(" microsec per conversion"));
//printMatrix();
Serial.println(F("---rotate----"));
startTime = micros();
for (int k = 0; k < NoOfTest; k++) rotateFrame();
Serial.print((micros() - startTime) / NoOfTest);
Serial.println(F(" microsec per rotation"));
//printMatrix();
Serial.println(F("---rotAndConv----"));
startTime = micros();
for (int k = 0; k < NoOfTest; k++) rotAndConv();
Serial.print((micros() - startTime) / NoOfTest);
Serial.println(F(" microsec per rotAndConv"));
printMatrix();
}
void loop() {
}
// Function to convert 8 byte array to 32 bit matrix data
constexpr byte arrLen = 8;
constexpr uint8_t startBitNo[arrLen] = {31, 19, 7, 27, 15, 3, 23, 11};
constexpr uint8_t startFrameIndex[arrLen] = {0, 0, 0, 1, 1, 1, 2, 2};
uint8_t frameIndex[arrLen] = {0, 0, 0, 1, 1, 1, 2, 2};
uint8_t bitNo[arrLen];
void convertFrame() {
// Prepare arrays
memcpy(bitNo, startBitNo, sizeof bitNo);
memcpy(frameIndex, startFrameIndex, sizeof frameIndex);
for (int i = 0; i < 3; i++) {
frame[i] = 0;
}
// Convert from 8 bit rot_frame to 32 bit frame array
for (int i = 0; i < 12; i++) {
for (int j = 0; j < arrLen; j++) {
if (rot_frame[i] & (1 << (7 - j))) {
frame[frameIndex[j]] |= (1ul << bitNo[j]);
}
bitNo[j]--;
if (bitNo[j] > 31) {
bitNo[j] = 31;
frameIndex[j]++;
}
}
}
}
// Another try: rotAndConv
void rotAndConv() {
byte mask;
uint32_t bitToAdd;
uint32_t row[arrLen];
for (int i = 0; i < arrLen; i++) {
row[i] = 0;
};
mask = 1;
for (int j = 0; j < 8; j++) {
bitToAdd = 1uL << 11;
for (int i = 0; i < 12; i++) {
if (rot_frame[i] & mask) {
row[j] |= bitToAdd;
}
bitToAdd = bitToAdd >> 1;
}
mask = mask << 1;
}
frame[0] = (row[7] << 20) + (row[6] << 8) + (row[5] >> 4);
frame[1] = (row[5] << 28) + (row[4] << 16) + (row[3 << 4])+(row[2] >> 8);
frame[2] = (row[2] << 24) + (row[1] << 12) + row[0];
}
// Original: Shorter but takes about five times longer
void rotateFrame() {
for (int i = 0; i < 3; i++) {
frame[i] = 0;
}
for (int i = 0; i < 96; i++) {
if (rot_frame[i % 12] & (1 << (7 - (i / 12)))) {
frame[i / 32] |= (1ul << (31 - (i % 32)));
}
}
}
// Functions to print the matrix via Serial
void printBinary(uint32_t val, byte from, byte to, bool CR) {
byte bitN = to;
for (int i = from; i <= to; i++, bitN--) {
if (val & (1uL << (bitN) )) Serial.print("1");
else Serial.print("0");
}
if (CR) Serial.println();
}
void printMatrix() {
printBinary(frame[0], 20, 31, true);
printBinary(frame[0], 8, 19, true);
printBinary(frame[0], 0, 7, false);
printBinary(frame[1], 28, 31, true);
printBinary(frame[1], 16, 27, true);
printBinary(frame[1], 4, 15, true);
printBinary(frame[1], 0, 3, false);
printBinary(frame[2], 24, 31, true);
printBinary(frame[2], 12, 23, true);
printBinary(frame[2], 0, 11, true);
}