Skip to content

Instantly share code, notes, and snippets.

@robinp
Created June 16, 2025 00:03
Show Gist options
  • Save robinp/a7cea526519385e9b4bf1ad30aca8cce to your computer and use it in GitHub Desktop.
Save robinp/a7cea526519385e9b4bf1ad30aca8cce to your computer and use it in GitHub Desktop.
LCD segment driver output decoder
// the setup routine runs once when you press reset:
void setup() {
ADCSRA &= ~(bit (ADPS0) | bit (ADPS1) | bit (ADPS2)); // clear prescaler bits
/*
ADCSRA |= bit (ADPS0); // 2
ADCSRA |= bit (ADPS1); // 4
ADCSRA |= bit (ADPS0) | bit (ADPS1); // 8
ADCSRA |= bit (ADPS2); // 16
ADCSRA |= bit (ADPS0) | bit (ADPS2); // 32
ADCSRA |= bit (ADPS1) | bit (ADPS2); // 64
ADCSRA |= bit (ADPS0) | bit (ADPS1) | bit (ADPS2); // 128
*/
// Note: as found by gammon, prescaler=8 gives garbage,
// but 16 is already fast and stable. In our case fast is
// important, to get the related signals in sync.
ADCSRA |= bit (ADPS2); // 16
// TODO add cap 0.1nF to ground and AREF?
analogReference(DEFAULT);
// see http://gammon.com.au/adc
bitSet (DIDR0, ADC0D); // disable digital buffer on A0
bitSet (DIDR0, ADC1D); // disable digital buffer on A1
bitSet (DIDR0, ADC2D); // disable digital buffer on A2
bitSet (DIDR0, ADC3D); // disable digital buffer on A3
bitSet (DIDR0, ADC4D); // disable digital buffer on A4
bitSet (DIDR0, ADC5D); // disable digital buffer on A5
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
}
long i = 0;
long j = 0;
int sMin[2] = {1023,1023};
int sMax[2] = {-1023, -1023};
int sAvg[2] = {0,0};
int cur[2] = {0,0};
#define COMS 2
#define SEGS 4
// com shifted, we don't sample com0 only com1 and com2
int com[COMS] = {A5, A4};
int seg[SEGS] = {A3, A2, A1, A0};
int cv[COMS];
int sv[SEGS];
#define PCS 7
char pn[PCS] = {'t', 'R', 'r', 'b', 'L', 'm', 'l'};
int pc[PCS] = {0, 0, 0, 0, 1, 1, 1};
int ps[PCS] = {0, 1, 2, 3, 0, 1, 2};
int pa[PCS] = {0, 0, 0, 0, 0, 0, 0};
#define DIGITS 10
int nummasks[DIGITS] = {
0b01011111, // 0
0b00000110, // 1
0b01101011, // 2
0b00101111, // 3
0b00110110, // 4
0b00111101, // 5
0b01111101, // 6
0b00000111,
0b01111111,
0b00111111,
};
#define ACTIVE 600
#define PASSIVE 400
#define MEASREPS 1000
// the loop routine runs over and over again forever:
void loop() {
for (int p = 0; p < PCS; p++) {
pa[p] = 0;
}
for (int m = 0; m < MEASREPS; m++) {
/*
for (int c = 0; c < COMS; c++) {
cv[c] = analogRead(com[c]);
}
for (int s = 0; s < SEGS; s++) {
sv[s] = analogRead(seg[s]);
}
for (int p = 0; p < PCS; p++) {
int v = cv[pc[p]] - sv[ps[p]];
if (abs(v) > ACTIVE) ++pa[p];
}
*/
for (int p = 0; p < PCS; p++) {
// Re-read current values, so we have good chance
// to sample them in-phase (vs sampling with delay
// and getting out-of-phase).
int c = analogRead(com[pc[p]]);
int s = analogRead(seg[ps[p]]);
int v = c - s;
if (abs(v) > ACTIVE) ++pa[p];
}
// Note: above approach could sample disproportionately,
// but it seems it samples quite fairly.
// Not really needed, but try to jiggle the phase slightly
// in case we are badly in-sync.. though what if exactly
// this makes it badly in-sync..
delayMicroseconds(4);
}
Serial.println(j++);
int maxp = 0;
for (int p = 0; p < PCS; p++) {
Serial.print(pn[p]);
Serial.print(":");
Serial.println(pa[p]);
if (pa[p] > maxp) maxp = pa[p];
}
if (maxp > 40) {
int cutoff = maxp / 2;
for (int d=0; d<DIGITS; d++) {
int v = nummasks[d];
int p;
for (p = 0; p < PCS; p++) {
if ((pa[p]>cutoff) != ((v & 0x01) == 1)) break;
v = v >> 1;
}
if (p == PCS) {
Serial.print("Found: "); Serial.println(d);
break;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment