// Requires NQC 2.2 or higher and RCX firmware 2.0 // Clock Reader, auto-synchronized // With light sensor auto-calibration / raw mode (variation is inverted, less light -> higher readings) // Next bit encoding depends on previous bit color // State encoding : // Present state Encoding Next State // 0 Yellow = 0 2 // 0 Grey = 1 1 // 1 Black = 0 0 // 1 Yellow = 1 2 // 2 Black = 0 0 // 2 Grey = 1 1 #define Center 3 #define Light SENSOR_2 #define CardPresent SENSOR_1 int State; int Value; int Cpt; int Aff; // Threshold between black and grey int BG; // Threshold between grey and yellow int GJ; // Hysteresis int Hyst=5; int Yellow; int Black; task main() { SetSensorType(Light,SENSOR_TYPE_LIGHT); SetSensorMode(Light,SENSOR_MODE_RAW); SetSensor(CardPresent,SENSOR_TOUCH); while (true) { until (CardPresent==1); Aff=0; SetUserDisplay( Aff, 0); OnFwd(OUT_C); GetValue(); PlaySound(1); Aff=Value%10000; switch( Value/10000) { case 0: SetUserDisplay( Aff, 0); break; case 1: SetUserDisplay( Aff, 1); break; case 2: SetUserDisplay( Aff, 2); break; case 3: SetUserDisplay( Aff, 3); break; } } } void GetValue() { Yellow = Light-10; // use -10 because of diffusing tape : background is farther thus darker BG = Yellow+30; // First approximation of Black/Grey threshold Value = 0; State = 0; Cpt=0; until (Light > BG + Hyst); // First plate is black Wait(Center); Black = Light; // Get Black value // Define Thresholds BG=Black-(Black-Yellow)*3/14; GJ=Yellow+(Black-Yellow)*2/7; do { Cpt++; Value *= 2; switch (State) { case 0: until (Light < BG - Hyst); Wait(Center); if (Light < GJ) { State = 2; } else { Value += 1; State = 1; } break; case 1: until ((Light > BG + Hyst)|| (Light < GJ - Hyst)); Wait(Center); if (Light > BG) { State = 0; } else { Value += 1; State = 2; } break; case 2: until (Light > GJ + Hyst); Wait(Center); if (Light > BG) { State = 0; } else { Value += 1; State = 1; } break; } } while ( Cpt < 15 ); Wait(50); Float(OUT_C); }