Electronic – Decoding a Two-Wire SPI-esque Serial Protocol

oscilloscopeprotocolreverse-engineeringserialspi

I'm working on a project that involves the optical sensor from a mouse. I've got the original control PCB (still populated, save for the optical sensor itself), and I've got the optical sensor on my custom PCB, supposed to be controlled by an nrf51822. I've wired the clock + data pins (it's a two-wire interface) to both boards, driven by the original control board (I've set my clock and data pins as inputs with no pulling resistors).

I'm trying to capture traffic to determine what signals are being sent, but I'm not having a lot of luck – I suspect my clock rate is too low. As quickly as possible (just inside a while true loop), I'm scanning my clock pin and my data pin, then printing them both to my console output over UART at 1M baud. Running this loop empty for 5 seconds results in ~4000 cycles, meaning I'm getting >1ms run time for each loop – which I think is my main problem.

As it is, I capture (in roughly 700 scans) 100 groups of alternating "clock 1 and data 1" and "clock 0 and data 0" – each group is 4-9 items (that is, 4-9 "1s" on both, followed by 4-9 "0s" on both). Then, about 400 scans later (~0.5 seconds) I get the same thing, but 54 groups. At that point I stopped scanning.

Is there any way to either:
A) Speed up my scan cycle so I can capture the traffic more accurately?
or
B) Decode what I already have (doubtful)?

Do I need to consider an alternate route? I haven't found any access to an oscilloscope, which is… unfortunate.

I'd appreciate any advice. Thanks.

Best Answer

As Chris Stratton indicated in his comments to the other answer you need to change the way your software works.

There are two options:

Option 1:
Run in a tight loop polling the pins and recording a timestamp into a buffer when they change state. If the value hasn't changed don't do anything.
Once the buffer is full output the times recorded over the serial link.

Option 2:
Use the serial and clock line inputs as interrupts. When the pins change record to a buffer a timestamp for the transition and the new state of the pin.
Have a background loop send the logged data out on the serial port keeping up with the data as best it can while indicating if the buffer has overflowed.

Both of them solve the big issue that you have that you are trying to output serial data from within a time critical piece of code, printf is slow and serial ports run at a glacial pace, never do them in a section of code that you need to run quickly. Option 1 is simpler and will probably cope with slightly higher frequencies but will only record for as long as you have space to buffer and could possibly report two edges very close together as being in the wrong order. Option 2 outputs while it's running and so should be able to run for longer (whether it's 1 edge more or keeps up and runs indefinably depends on the speeds of the edges and the serial port) but due to the interrupt overhead will have a lower top speed and is more complex to code.

The other obvious solution is to borrow / rent an oscilloscope or logic analyser from someone.