/* HiFiLOGIX 0.2.0 (Fix 1) dewdude@gmail.com - 12-JAN-2019 !!! IMPORTANT NOTICE !!! As of 0.2.0 EEPROM support is no longer considered to be beta and has been fully integrated in to the main build. You should be aware of the following: It uses EEPROM addresses 1020 - 1023 It will erase any data you may have there during the initilization routine. If your EEPROM is smaller, or you don't want to use 1020 - 1023; then you'll need to change their #define to match what you want/need. Pin 2 is used for the hardware interrupt trigger that writes the data. It's set to run fall. This will be done in hardware by isolating a capacitor for the Arduino and tying pin 2 to the part of the power supply that will drop first. The reserve current should last long enough to update the values before draining. */ #include #include #include #include #include #define di 1022 #define dx 1021 #define db 1020 #define dt 1023 #include "logo.h" // XBMP data for logo. U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE); const char in0[] PROGMEM = "TAPE-2"; const char in1[] PROGMEM = "TAPE-1"; const char in2[] PROGMEM = "AUX"; const char in3[] PROGMEM = "TUNER"; const char in4[] PROGMEM = "PHONO-1"; const char in5[] PROGMEM = "PHONO-2"; const char * const inputs[] PROGMEM ={in0,in1,in2,in3,in4,in5}; // scl to pin 28 // sdl pin 27 int latchPin = 11; // 328 pin 17 - 595 pin 12 int clockPin = 9; // 15 - pin 11 int dataPin = 12; // 18 - 14 int IRin = 7; //13 int blanking = 5; // 11 int matrix = A1; // 23 byte eop = 0; byte ex = 0; byte ei = 0; IRrecv remote(IRin); decode_results ircode; char txt[8]; // There's something very important I forgot to tell you. void DontCrossTheStreams(byte op, byte x, byte i) { strcpy_P(txt, (char*)pgm_read_word(&(inputs[i]))); // Why? digitalWrite(latchPin, LOW); // It would be bad. shiftOut(dataPin, clockPin, LSBFIRST, op); // What do you mean, bad? digitalWrite(latchPin, HIGH); // Imagine all life as you know u8g2.clearBuffer(); // it stopping instaneously u8g2.drawStr(x,30,txt); // and every molecule in u8g2.sendBuffer(); // your body exploding eop = op; ex = x; ei = i; // at the speed of light. }// Total protonic reversal. // That's bad. // Important safety tip, thanks Egon. void eeprominit() { // This checks the EEPROM to see if it's // been initialized by the code before. if (EEPROM.read(dt) == 'F') { // Check address 1023 for init flag "T" return; } else { EEPROM.write(db, 16); EEPROM.write(dx, 32); EEPROM.write(di, 2); EEPROM.write(dt, 'F'); } } void lastbreath() { // The idea here is to throw a large capacitor on to the voltage rail EEPROM.write(db, eop); // powering the Arduino; but keep it from powering anything else. EEPROM.write(dx, ex); // Monitor the "other" 5V rail with pin 2 and trigger an interrupt EEPROM.write(di, ei); // and rely on the caps charge to keep charge long enough to write. } void annoyingtrick() { u8g2.clearBuffer(); // it stopping instaneously u8g2.drawStr(22,30,"RAVE"); // and every molecule in u8g2.sendBuffer(); for (int b = 0; b <=20000; b++){ byte trick = 0; trick = random(1,127); digitalWrite(latchPin, LOW); // It would be bad. shiftOut(dataPin, clockPin, LSBFIRST, trick); // What do you mean, bad? digitalWrite(latchPin, HIGH); delay(25);} DontCrossTheStreams(16,32,2); } void setup() { pinMode(latchPin, OUTPUT); pinMode(dataPin, OUTPUT); pinMode(clockPin, OUTPUT); pinMode(blanking, OUTPUT); eeprominit(); u8g2.begin(); remote.enableIRIn(); u8g2.firstPage(); // Logo is now bitmapped and since I only call it do { // once, it doesn't need it's own function. u8g2.drawXBMP(14,4,hifilogix_width,hifilogix_height,hifilogix_bits); } while ( u8g2.nextPage() ); delay(2000); // It takes the Denon about 4.5 seconds to kick speakers on. u8g2.setFont(u8g2_font_logisoso28_tr); DontCrossTheStreams(EEPROM.read(db),EEPROM.read(dx),EEPROM.read(di)); // Read settings stored in EEPROM. digitalWrite(blanking,HIGH); // Now drives a logic inverter. attachInterrupt (digitalPinToInterrupt(2), lastbreath, FALLING); // Write the values before your cap discharges! attachInterrupt (digitalPinToInterrupt(2), lastbreath, CHANGE); // Write the values before your cap discharges! attachInterrupt (digitalPinToInterrupt(2), lastbreath, LOW); } void loop() { int mx = analogRead(matrix); byte icode = 0; // I changed how I handed the inputs. if (remote.decode(&ircode)) { icode = ircode.value; remote.resume(); } // I don't know if it improves things, but I sure like how much smaller this section is. if ((mx > 850 && mx < 860) || (icode == 0x97)) DontCrossTheStreams(64,10,0); // The code I originally used to figure out my if ((mx > 2 && mx < 5) || (icode == 0x67)) DontCrossTheStreams(32,10,1); // remote codes returned 3 bytes in hex. I can't if ((mx > 45 && mx < 50) || (icode == 0x4F)) DontCrossTheStreams(16,32,2); // remember what that code was, but I only need if ((mx > 950 && mx < 970) || (icode == 0xCF)) DontCrossTheStreams(8,18,3); // the last bit with the remote I'm using. if ((mx > 22 && mx < 30) || (icode == 0xE7)) DontCrossTheStreams(6,1,4); // I'm working on making the bare-bones utility I if ((mx > 990 && mx < 1010) || (icode == 0x85)) DontCrossTheStreams(5,1,5); // wrote a bit more user-friendly. if (icode == 0xAD) annoyingtrick(); delay(200); }