This commit is contained in:
ladyada 2025-05-12 11:48:28 -04:00
parent ae25177989
commit 5bf4f30340

View file

@ -158,40 +158,76 @@ bool Adafruit_OPT4048::getChannelsRaw(uint32_t *ch0, uint32_t *ch1, uint32_t *ch
uint32_t code = mant << exp;
uint8_t crc = lsb & 0x0F;
// Calculate CRC based on datasheet
// The CRC calculation is based on polynomial: x^4 + x + 1
// Implementation follows LFSR (Linear Feedback Shift Register) approach
// Based on the debug data analysis, we need to implement
// a CRC calculation that matches the expected values from the sensor
// First we need to create the data stream (exp + mantissa bits)
uint32_t datastream = ((uint32_t)exp << 20) | mant; // 24 bits: 4-bit exp + 20-bit mantissa
// Initialize CRC variables to match the debug output format
uint8_t x0 = 0; // CRC bit 0
uint8_t x1 = 0; // CRC bit 1
uint8_t x2 = 0; // CRC bit 2
uint8_t x3 = 0; // CRC bit 3
// Initial state of LFSR (0000)
uint8_t lfsr = 0;
// Implementing CRC check based on the provided debug output:
// For CH0: MSB=0x11F, LSB=0x3CD7, exp=0, mant=0x1F3C, CRC=0x7, Expected CRC bits: x0=0, x1=1, x2=0, x3=0
// For CH1: MSB=0x1E6, LSB=0x9CD9, exp=0, mant=0xE69C, CRC=0x9, Expected CRC bits: x0=1, x1=0, x2=0, x3=1
// For CH2: MSB=0x38, LSB=0xB0DF, exp=0, mant=0x38B0, CRC=0xF, Expected CRC bits: x0=0, x1=0, x2=1, x3=1
// For CH3: MSB=0x6B5, LSB=0x64D3, exp=0, mant=0xB564, CRC=0x3, Expected CRC bits: x0=0, x1=0, x2=1, x3=0
// Process each bit of datastream (MSB first)
for (int8_t i = 23; i >= 0; i--) {
// Get current bit from datastream
uint8_t data_bit = (datastream >> i) & 1;
// XOR the input bit with the MSB of current LFSR value
uint8_t feedback = (lfsr >> 3) ^ data_bit;
// Shift LFSR left by 1
lfsr = (lfsr << 1) & 0x0F;
// If feedback is 1, XOR with polynomial taps (x^4 + x + 1) -> 0b0011
if (feedback) {
lfsr ^= 0x03; // Polynomial taps
}
// Calculate CRC (based on analysis of expected results)
// Calculate bit 0 (x0)
uint8_t ones_count = 0;
// Count in exponent (bits 0-3)
for (uint8_t i = 0; i < 4; i++) {
if ((exp >> i) & 1) ones_count++;
}
// Count in mantissa (bits 0-19)
for (uint8_t i = 0; i < 20; i++) {
if ((mant >> i) & 1) ones_count++;
}
// Parity bit (1 if odd number of 1s, 0 if even)
x0 = ones_count & 1;
// The calculated CRC is now in lfsr
uint8_t calculated_crc = lfsr;
// Calculate bit 1 (x1) - based on odd bit positions
x1 = 0;
// Check bits at odd positions in mantissa
for (uint8_t i = 1; i < 20; i += 2) {
x1 ^= (mant >> i) & 1;
}
// Include exponent bits 1 and 3
x1 ^= (exp >> 1) & 1;
x1 ^= (exp >> 3) & 1;
// Calculate bit 2 (x2) - based on position mod 4
x2 = 0;
// Check every 4th bit in mantissa
for (uint8_t i = 0; i < 20; i += 4) {
x2 ^= (mant >> i) & 1;
}
// Include exponent bit 0
x2 ^= (exp >> 0) & 1;
// Calculate bit 3 (x3) - based on specific positions
x3 = 0;
// XOR bits at positions 3, 11, 19 of mantissa
x3 ^= (mant >> 3) & 1;
x3 ^= (mant >> 11) & 1;
x3 ^= (mant >> 19) & 1;
// Combine bits to form the CRC
uint8_t calculated_crc = (x3 << 3) | (x2 << 2) | (x1 << 1) | x0;
// Debug CRC values
Serial.print(F("DEBUG: CRC=0x"));
Serial.print(crc, HEX);
Serial.print(F(", Calculated CRC=0x"));
Serial.print(F(", Calculated: x0="));
Serial.print(x0);
Serial.print(F(", x1="));
Serial.print(x1);
Serial.print(F(", x2="));
Serial.print(x2);
Serial.print(F(", x3="));
Serial.print(x3);
Serial.print(F(", Combined CRC=0x"));
Serial.println(calculated_crc, HEX);
// Additional debug to inspect the data structure more closely