Нет, по ссылке выше
Можно как-то так, думаю.
const uint8_t frameOnRam[] = {
0b11010010, 0b00000000, 0b10011000, 0b00000001,
0b00000011, 0b10000000, 0b00000000, 0b01100000,
0b00000110, 0b00001100, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000001,
0b00000000, 0b00000000, 0b00000000, 0b00000001
};
const uint8_t frameOnProgmem[] PROGMEM = {
0b10000011, 0b01010101, 0b10011000, 0b00000001,
0b00000011, 0b10000000, 0b00000000, 0b01100000,
0b00000110, 0b00001100, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000001,
0b00000000, 0b00000000, 0b00000000, 0b00000001
};
const uint8_t ledQuantity = 20;
class __FlashArrayHelper;
#define FA(array_name) (reinterpret_cast<const __FlashArrayHelper *>(array_name))
// RAM-placed data case
bool getBitOnPosition(uint16_t _position, const uint8_t* _data) {
// No bounds checking here
uint16_t offset = _position >> 3;
uint8_t bitNo = 7 - (_position - (offset << 3));
uint8_t dataByte = _data[offset];
return ((dataByte >> bitNo) & 0x01);
}
// PROGMEM-placed data case
bool getBitOnPosition(uint16_t _position, const __FlashArrayHelper * _data) {
uint16_t offset = _position >> 3;
uint8_t bitNo = 7 - (_position - (offset << 3));
uint8_t dataByte = pgm_read_byte_near(reinterpret_cast<const uint8_t*>(_data) + offset);
return ((dataByte >> bitNo) & 0x01);
}
void setup() {
Serial.begin(115200);
Serial.println(F("Bit array access demo"));
Serial.println(F("Take frames from RAM"));
for (uint16_t frameOffset = 0; (sizeof(frameOnRam) * 8) > frameOffset; frameOffset += ledQuantity) {
for (uint16_t ledNo = 0; ledQuantity > ledNo; ledNo++) {
bool isLedOn = getBitOnPosition(frameOffset + ledNo, frameOnRam);
Serial.print(isLedOn); Serial.print(' ');
}
Serial.println();
}
Serial.println(F("Take frames from PROGMEM"));
for (uint16_t frameOffset = 0; (sizeof(frameOnProgmem) * 8) > frameOffset; frameOffset += ledQuantity) {
for (uint16_t ledNo = 0; ledQuantity > ledNo; ledNo++) {
bool isLedOn = getBitOnPosition(frameOffset + ledNo, FA(frameOnProgmem));
Serial.print(isLedOn); Serial.print(' ');
}
Serial.println();
}
}
void loop() {}
UPD: поддал оверлоада на PROGMEM
хм…
а почему не
uint8_t bitNo = 7 - (_position & 0x7);
Да в последнюю минуту понял, что надо бы перевернуть вывод, чтобы было по-человечески. Не стал уже там извращаться.
А, вопрос не про это. Такую кракозябру я делал, чтобы понятна была логика. Ну, я так полагаю, что она остаётся понятной: на 8 поделили, на 8 умножили. А там уже пусть иринка оптимизирует, как хочет.
Большое спасибо. Буду разбираться на выходных.
Тема самому интересна, поэтому решил добавить.
В моём примере из #19 описана простая функция, позволяющая записать любой бит в массив uint32_t. При этом биты нумеруются от младшего к старшему.
А в этом примере массив разбит на кадры(по 20 бит), и биты адресуются линейно, по порядку, начиная со старшего бита
Спойлер
uint32_t mass[4] = {0, 0, 0, 0};
#define CADRvolum 20
void write_mass(uint32_t *massiv, byte cadr, byte bitNum, bool Bit)
{
uint32_t fullBitNum = cadr * CADRvolum + bitNum;//полный номер бита в массиве
bitWrite( *((massiv + fullBitNum/32)), 31 - (fullBitNum % 32), Bit);
}
void setup() {
Serial.begin(9600);
}
void loop() {
static uint16_t cadre = 0;//счёт кадров, начиная с 0
static byte bitNum = 0;// счёт номера бита в кадре, начиная с 0
bool BITstat;
bitNum % 2 ? BITstat = true : BITstat = false;//определяем чётные и нечётные биты
write_mass(mass, cadre, bitNum, BITstat);//записываем в массив бит № bitNum
//в кадре № cadre
for(byte ii = 0; ii < 4; ii++)
{
Serial.print(mass[ii], BIN);
Serial.print(' ');
}
Serial.println();
bitNum++;
if(bitNum > CADRvolum - 1)//
{
bitNum = 0;
cadre++;
}
if(cadre > 5)
for(;;);
}
зачем?
К чему тут эти кадры, если биты все равно пишут в массив uint32_t подряд?
Бессмысленный какой-то пример…
Написал п мотивам #1. Видимо так удобнее.