_           _                 
 | |_ ___  __| |____  ___ _   _ 
 | __/ _ \/ _` |_  / / _ \ | | |
 | ||  __/ (_| |/ / |  __/ |_| |
  \__\___|\__,_/___(_)___|\__,_|

Binary Signal Detective signal recorder for laptop screen

The example output signal is for a video with the character sequence "Demo" encoded in it, as provided here.

Output signal as plain text file: signal_example.csv

To plot the data in Octave / MATLAB:

s = csvread ('signal_example.csv');
plot(s)

insert alt text here

Arduino code:

//
// Binary Signal Detective signal viewer - written by Ted Burke - 4-Mar-2025
//
// This program is designed to work with an LED-based light detector circuit
// to record a binary signal encoded into a video with a square that flashes
// back and forth between black and white. On my laptop screen, the light
// is not constant when the screen is white - instead it pulses at high
// frequency (the period is about 15ms, based on a very rough measurement).
// The output of the light detector circuit is consistently high (close to 5V)
// when the screen is black, but emits negative pulses (going down close to 0V)
// when the screen is white. To filter out the pulses, this program reads 16
// samples at sample rate of approximately 1 kHz into a "short buffer".
// Every time the short buffer has been filled with new samples, the minimum
// value from the short buffer is selected and written as the next sample
// in the "long buffer". This is basically equivalent to a minimum filter,
// followed by 16x downsampling. When the button (pin D2) is pressed, the
// contents of the long buffer (i.e. the last N samples) are written to the
// serial connection.
//

#define N 625  // long buffer length (approximately 10 seconds @ T_s = 16ms)
#define M 16   // short buffer length (approximately 16ms @ T_s = 1ms)

int n = 0, m = 0;
unsigned char longbuf[N];
unsigned char shortbuf[M];

void setup()
{
  Serial.begin(115200);
}

void loop()
{
  // Add a sample (divided by 4 to fit in one byte) to the short buffer every 1ms
  delayMicroseconds(1000);
  shortbuf[m] = analogRead(7) >> 2;
  m = (m+1)%M;

  // Only add to long buffer once every M samples
  if (m) return;

  // Every M samples, take the minimum from the last M samples and add it to the long buffer
  longbuf[n] = 255;
  for (m=0 ; m<M ; ++m) if (shortbuf[m] < longbuf[n]) longbuf[n] = shortbuf[m];
  m = 0;
  n = (n+1)%N;

  // If the button is pressed, print the last N samples from the long buffer via serial
  if(digitalRead(2))
  {
    for (m=0 ; m<N ; ++m)
    {
      Serial.println(longbuf[n]);
      n = (n+1)%N;
    }
    m = 0;
    delay(1000);
  }
}