I need to store 512 bits that I'll read one at a time in a loop. I tried using an array, but that's really slow. I could create 64 bytes and somehow use those, but I'm hoping there's a better way. Basically the code needs to do something like this:

int array[512];

for(int i; i < 512; i++){ array = digitalRead(2);}

I'm actually PIND to do the read because digitalRead is too slow, and that seems to be working well. Any ideas on something I can use?

What do you consider slow and what data read rate do you consider adequate on your 16MHz CPU?

Lets look a little what the assembler offers. I will assume here that the compile does use it reasonable efficently, if not you will have to break out the assembler.

The basic data type of the ATmega is the byte. Loading and storing a byte can be done in 2 CPU cycles, a word takes 4. So using int instead of char will cut down on loading time. To make things even better, doing a bit-shift in a register takes 1 CPU cycle.

So if you use your int array, for 8 bits you use 8*4=32 CPU cycles for the storing alone. If you use a char array and set bits, you use 7 cycles for the shifting, 2 cycles for writing you the byte and up to 8 cycles to handle the bits set to 1, giving a total of 9 to 17 cycles. Getting the data from the port or checking of the bit is 1 is assumed to be equivalent, the same with the loop control.

In sum, the gain is nice, but not dramatic. The main benefit in my opinion is, that you use 64B of storage instead of 1kB, which is a dramatic gain considering that you have only 1kB (or 2kB) available on your CPU (ATmega168 or ATmega328 assumed). Your array takes the whole RAM of your CPU. To put it mildly, this is a very bad idea.

The main problem here is a slight uneven read rate when the byte needs to be written. If you want to get reading as evenly as possible, you're probably faring better with a loop and slowing down the reading between the bits with nop if necessary.

Thanks for all the ideas! There's a lot of good information to go off of. I agree with the space issues with the array, I was just using that to illustrate what I need. Like I said I only need to save a 1 or a 0 for each reading. I might be missing something, but all the examples are only for a single byte, is there an easy way to do multiple bytes easily? From what I've seen it looks like the array is slow to assign to because of the indexing, not the actual assignment.

Writing out a byte is reasonably fast. The code shown above was only to demonstrate various ideas how to handle the bitwise stuff. After that group of 8, you just store the byte and start with the next one. Done in assembler, writing to the array and incrementing the pointer would entail a penalty of 2 CPU cycles. If you consider that too slow, it's time to rethink your structure and perhaps even the platform choice again.

void loop() { byte *ptr=&bits[0]; i = 0; do { *ptr++ = PIND; i--; } while (i != 0); do { *ptr++ = PIND; i--; } while (i != 0);}Using the two loops prevents the AVR from having to do slower 16bit math... This will compile to code that would be hard to write any faster using equivalent algorithm (ie looping)

Good to know about the indexing, I thought I read somewhere it was slow.

Oh, in general it can be slow, especially for multi-dimensional arrays where converting some set of indicies to the actual address/value involves one or more multiplications. But a particularly simple use of an index array (as in the example here) all of that slowness might disappear because the compiler is smarter than you think.

I guess, in other words, if there's a simple way of making a simple thing faster, it's possible to likely that that is already done for you automatically...