From 264f4198cece252ff34931a699f8602d2038f219 Mon Sep 17 00:00:00 2001 From: dewdude Date: Sat, 11 Jan 2020 23:59:19 -0500 Subject: [PATCH] Version 0.2.0: EEPROM is no longer beta. Beta deleted. --- CHANGELOG | 10 +++ README.md | 33 +++++++--- hifilogix-eeprombeta.ino | 127 --------------------------------------- hifilogix.ino | 53 +++++++++++----- 4 files changed, 75 insertions(+), 148 deletions(-) delete mode 100644 hifilogix-eeprombeta.ino diff --git a/CHANGELOG b/CHANGELOG index 6056417..58fc181 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,15 @@ CHANGELOG: +Version 0.2.0: + + Software: + EEPROM Support out of beta. Added hardware interrupt routine for it. + Using the EEPROM is now the default action for the software, meaning the beta version + has gone away. This sketch absolutely makes use of the EEPROM as part of it's boot + routine. It will overwrite data on first boot and loads the "default" input every + boot. The update is done via an interrupt. More on that will be explained later as + it will require some power-supply hacking I'll have to design. + Version 0.1.9: Software: diff --git a/README.md b/README.md index 1baff16..ec11660 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ Arduino Control for Your Vintage Stereo 06-Jan-2020: Version 0.1.7 - More code clean-up, practical rewrite of main loop. Bitmapped the logo. 09-Jan-2020: Version 0.1.8 - Code consolidation. Additional beta version with EEPROM support. Added utilities. 10-Jan-2020: Version 0.1.9 - Moved input name table to program space. +11-Jan-2020: Version 0.2.0 - EEPROM code now out of beta. Writes with hardware interrupt now. ```` @@ -92,15 +93,33 @@ but it's possible I may wind up writing a routine for "self-programming". As of Version 0.1.4 we now support the SSD1306 based 128x32 OLED Display. -In the future I will be adding some kind of NVRam storage. This will facilitate actually storing configuration options, remote -programming codes, and to store the last-used input. I may also use this to store graphic data for the OLED display to -emulate the original segmented font display of the Denon. +# EEPROM Usage -# Software +Version 0.2.0 brought the EEPROM code out of beta. It is now a default feature of the main version. + +THE SKETCH DOESN'T CARE WHAT DATA YOU HAVE AT 1020 - 1023 OR IF YOU HAVE THE CIRCUIT TO PROPERLY USE IT. IT WILL WRITE OVER +IT THE FIRST TIME YOU RUN IT. + +YOU MUST CHANGE THE VALUES IF YOUR EEPROM IS SMALLER OR WANT TO USE DIFFERENT ADDRESSES. + +The sketch currently uses 4 bytes of EEPROM space to store the input last selected at power off. One byte is used to store the +byte sent to the shift register, one stores the x offset for the display, the other stores the index to the array that contains +the name; the exact same information used for arguments to DontCrossTheStreams(). This information is read during boot. -Both the main version and EEPROM beta are essentially the same. The normal version has all the EEPROM code commented out by default -and the beta has the EEPROM code active. This was done for the lazy who don't like/want/know-how to modify code. This won't matter -once I work out the hardware for the interrupt triggering and EEPROM support leaves beta. +In order to ensure there's valid data; the fourth byte is used to indicate if the initialization routine has run. If the last +byte contains "T", then we assume the data we want is valid. If T is not found; then the function writes the default data for +the AUX input and writes the initalization flag. + +Data is written to the EEPROM by way of a hardware interrupt. The basic idea is to throw a lot of capacitance on to the Arduino +in a way that it's isolated to the Arduino and montior "the other side" of the 5V rail. When the 5V line drops as a result of +turning off the amplifier; the capacitor should power the Arduino long enough to detect the falling state of pin 2 and write the +data to the EEPROM...if necessary. + +If you leave pin 2 floating it seems to do nothing. If you connect it to ground it does nothing. If it drops out at the same time +as the Arduino, it does nothing. If you do nothing with this pin the thing behaves just like before; with the exception that the +default never changes. + +# Software This sketch requires the following libaries: - IRRemote (https://github.com/z3t0/Arduino-IRremote) diff --git a/hifilogix-eeprombeta.ino b/hifilogix-eeprombeta.ino deleted file mode 100644 index 074d5df..0000000 --- a/hifilogix-eeprombeta.ino +++ /dev/null @@ -1,127 +0,0 @@ -/* - HiFiLOGIX EEROM BETA 0.1.9 - - dewdude@gmail.com - 09-JAN-2019 - - !!! IMPORTANT !!! - - IF YOU HAVE DATA AT ADDRESSES 1020 - 1023, THIS SKETCH WILL CHANGE IT. - - IF YOUR EEPROM IS SMALLER, YOU WILL NEED TO CHANGE THE ADDRESSES. - - THIS CURRENTLY WRITES TO THE EEPROM EVERY SOURCE CHANGE. - - Address 1020 stores the byte to be sent to the shift register. - Address 1021 stores the x offset for the display. - Address 1022 contains the index of the input string array. - Address 1023 contains the letter "T" if defaults exist. - - On boot the script looks for the letter "T" at address 1023. - If it exists this is supposed to indicate it's been initialized - and it will continue with the main setup loop. If not, it writes - default values to locations 1020 - 1022 and writes T to 1023. - - During the setup loop, the values stored at 1020 - 1022 are - fed as arguments to DontCrossTheStreams. I could probably do - this with a bunch of if loops to read a single byte and translate - that in to the rest...but I don't know how that would affect the - memory. - - */ -#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}; // Drop the entire array in to program space. - -int latchPin = 11; -int clockPin = 9; -int dataPin = 12; -int IRin = 7; -int blanking = 5; -int matrix = A0; -IRrecv remote(IRin); -decode_results ircode; -char txt[8]; - -void DontCrossTheStreams(byte op, int x, int i) // There's something very important I forgot to tell you. -{ // Don't cross the streams. - 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 - EEPROM.update(db, op); // at the speed of light. - EEPROM.update(dx, x); // Total protonic reversal. - EEPROM.update(di, i); // 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) == 'T') { // Check address 1023 for init flag "T" - return; - } else { - EEPROM.write(db, 16); - EEPROM.write(dx, 32); - EEPROM.write(di, 2); - EEPROM.write(dt, 'T'); - } -} - -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)); // THIS IS NO LONGER STATIC IN THE BETA! (yay.) - //DontCrossTheStreams(16,32,2); - digitalWrite(blanking,HIGH); // Now drives a logic inverter. -} - -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 > 100 && mx < 200) || (icode == 0x97)) DontCrossTheStreams(64,10,0); // The code I originally used to figure out my -if ((mx > 500 && mx < 600) || (icode == 0x67)) DontCrossTheStreams(32,10,1); // remote codes returned 3 bytes in hex. I can't -if ((mx > 900 && mx < 950) || (icode == 0x4F)) DontCrossTheStreams(16,32,2); // remember what that code was, but I only need -if ((mx > 1000) || (icode == 0xCF)) DontCrossTheStreams(8,18,3); // the last bit with the remote I'm using. -if ((mx > 820 && mx < 899) || (icode == 0xE7)) DontCrossTheStreams(6,1,4); // I'm working on making the bare-bones utility I -if ((mx > 700 && mx < 800) || (icode == 0x85)) DontCrossTheStreams(5,1,5); // wrote a bit more user-friendly. -delay(200); -} \ No newline at end of file diff --git a/hifilogix.ino b/hifilogix.ino index c1ce2f8..d285831 100644 --- a/hifilogix.ino +++ b/hifilogix.ino @@ -1,18 +1,35 @@ /* - HiFiLOGIX 0.1.9 + HiFiLOGIX 0.2.0 dewdude@gmail.com - 09-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 falues before + draining. */ #include #include #include #include -/*#include +#include #define di 1022 #define dx 1021 #define db 1020 -#define dt 1023 */ +#define dt 1023 #include "logo.h" // XBMP data for logo. U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE); @@ -24,7 +41,7 @@ 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}; // Drop the entire array in to program space. +const char * const inputs[] PROGMEM ={in0,in1,in2,in3,in4,in5}; int latchPin = 11; int clockPin = 9; @@ -32,11 +49,14 @@ int dataPin = 12; int IRin = 7; int blanking = 5; int matrix = A0; +byte eop = 0; +byte ex = 0; +byte ei = 0; IRrecv remote(IRin); decode_results ircode; char txt[8]; -void DontCrossTheStreams(byte op, int x, int i) // There's something very important I forgot to tell you. +void DontCrossTheStreams(byte op, byte x, byte i) // There's something very important I forgot to tell you. { // Don't cross the streams. strcpy_P(txt, (char*)pgm_read_word(&(inputs[i]))); // Why? digitalWrite(latchPin, LOW); // It would be bad. @@ -45,14 +65,13 @@ void DontCrossTheStreams(byte op, int x, int i) // There's something u8g2.clearBuffer(); // it stopping instaneously u8g2.drawStr(x,30,txt); // and every molecule in u8g2.sendBuffer(); // your body exploding - //EEPROM.update(db, op); // at the speed of light. - //EEPROM.update(dx, x); // Total protonic reversal. - //EEPROM.update(di, i); // That's bad. -} // Important safety tip, thanks Egon. + 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 +void eeprominit() { // This checks the EEPROM to see if it's // been initialized by the code before. if (EEPROM.read(dt) == 'T') { // Check address 1023 for init flag "T" return; @@ -62,7 +81,13 @@ if (EEPROM.read(dt) == 'T') { // Check address 102 EEPROM.write(di, 2); EEPROM.write(dt, 'T'); } -} */ +} + +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.update(dx, ex); // Monitor the "other" 5V rail with pin 2 and trigger an interrupt + EEPROM.update(di, ei); // and rely on the caps charge to keep charge long enough to write. +} void setup() { @@ -70,7 +95,7 @@ void setup() pinMode(dataPin, OUTPUT); pinMode(clockPin, OUTPUT); pinMode(blanking, OUTPUT); - //eeprominit(); + eeprominit(); u8g2.begin(); remote.enableIRIn(); u8g2.firstPage(); // Logo is now bitmapped and since I only call it @@ -79,9 +104,9 @@ void setup() } 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)); // THIS IS NO LONGER STATIC IN THE BETA! (yay.) - DontCrossTheStreams(16,32,2); + 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! } void loop()