Podcast #128: We chat with Kent C Dodds about why he loves React and discuss what life was like in the dark days before Git. Listen now.
2 of 2 added 1119 characters in body

I think the problem is that there is more to serial I/O than just bits coming in. Otherwise, if nothing was sending, you would always read 0 from the serial port. Serial has a start and stop bit, for example. I doubt you could use the hardware serial to read in random bits.

If you are going to do this in software, you will have less than 16 clock cycles per bit - enough time to run about 15 instructions. It is not impossible, but very difficult.

There are two ways to read the data in code.

Option 1: Disable interrupts, and hand-write assembler that takes exactly the right amount of time. If you branch, make sure all branches take the same amount of time. I think all assembler instructions on Atmel take 1 cycle. You will need to pad out your loop to a predictable size. At 1.024mhz, the clock will drift by 2.4%, which means you'll either have to supersample (e.g. take one sample every 12 instructions, then throw away the samples closest to the clock interval) or you'll have to make some loops longer than others. If you store 8 bits per byte (as opposed to having an array of 77 bytes, storing 1 bit in each, which would be quicker), then you might get away with making "move to next byte" a different length. Try to measure each sample in the MIDDLE of the allowed period, or as close to it as you can. You may have to unroll your loops (i.e. instead of "repeat this 77 times", do "do it, do it again, do it again....).

Or you might be able to write an ISR - Your ISR would have to be very short, basically "write the current time to a pre-defined array". Now you have 15 instructions to get the data out, but padding it OUT isn't so critical. With this method, you will get one datapoint per CHANGE (rising or falling signal). I don't know if micros() would be quick enough. Then, once the read is complete, you can post-process the data at your leisure. The ISR will be called at the start of the clock cycle following the change in signal, so this is likely to be easier.


Micros only has a resolution of 4 microseconds, so you will have to make your own "clock". The easiest way to do this, is to set a counter with about how long you think it will take (, then hand-code a loop to decrement this, until zero. As far as I can make out, the decrement loop should take 2 cycle (decrement the counter, if-not-zero jump back to decrement). So if you start it at 800, it should take 100ms to reach zero. Remember that the ISR will stop the counter for the duration, you will need to compensate. Make sure that this loop isn't optimized out! Your ISR will be: copy the (above) counter into an array, increment your array pointer by 1 (so next time you put it in a different slot in your array). After the counter reaches zero, disable your ISR, and find the difference between each number and the next; add a constant (worked out by trial and error), round to the nearest 8 (which should be pretty close). Divide by 8. The first result should be the delay to the start of the data (first 1); the second will be the number of consecutive 1's, then the number of consecutive 0's, etc.