diff --git a/CHANGELOG b/CHANGELOG index 83228aa..740bff1 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,58 @@ CHANGELOG: +Version 0.1.8: + + Software: + No longer clear the shift register. + Originally I did this to make sure the register was cleared...because I honestly wasn't 100% sure what was + going on. I looked at some examples...did some things...and got excited when it worked. In complete total + hindsight....I actually didn't need to do this. Originally I did it "just to be sure" it got cleared...and + for a while since I wasn't exactly sure what the shift-register functions fully did; I just left it. The + change I made in 0.1.6 of adding arguments to DontCrossTheStreams seemed to make a lot of things fall in to + place...and it turns out that when I finally got to the point of deciding to try adding EEPROM support..that + change made the entire thing easier to implement. 0.1.7 practically rewrote the whole loop, which lead to me + doing it to the rest of the code. + + Three functions removed. + clearShiftRegister was removed to already mentioned redundancy. updateShiftRegister had it's few lines of + code moved to DontCrossTheStreams. logo() had it's code moved from it's own function to just directly into + the setup function. With this change, DontCrossTheStreams has morphed from it's original function of just + setting the shift register to all 0, in to being the entire process of changing inputs. Though I did figure + out that functions really didn't add much bloat. Between 0.1.7 and 0.1.8 I only shaved 22 bytes off the + original compile size. + + I have no clue what it takes to optimize C. I barely know it. + + srEnable renamed to blanking. + This better represents what it does. While this is probably more notoriously known in regards to CRT + operation; I'm a pinball guy by trade and the term is used quite a bit on the solid-state/digital + machines. + + EEPROM Beta: + Remember how I said someday the default boot wouldn't be static? Well, I've done it. This beta version uses + 3 bytes of EEPROM space to store the last used input as well as one additional byte to indicate if default + information exists and to load if it it does, or write it if it doesn't. It currently uses bytes 1020 - 1023, + the end of the EEROM on my ATMega 328. 1020 stores the byte for the shift register, 1021 stores the x offset + for the display, 1022 stores the index pointer to the name, and 1023 stores a "T" if it's written settings. + Right now, it will update those addresses on each input change; and read those settings on boot to pass to + DontTouchTheStreams. + + While I toyed around with the idea of something like FRAM to avoid the lifetime limitations and just write + each source change; I've decided I'm going to give the Arduino a lot of capacitance on it's power supply, + attach a sense circuit to the main power supply, and just write those values when it detects a power-off. + The code only updates if necessary; so if you power it off on the same input it was powered-up at, it won't + write. In theory...if you write to this thing twice a day it will take close to 100 years to hit the write + limit. + + But I haven't implemented that in hardware...though I have some ideas. Until I do this is considered a beta + version that won't burn the EEPROM out like writing to it in loop; but still does so every single input + change. + + It is written off the 0.1.8 code. + + Hardware: + No changes; but eliminating the reset circuit on the dev prototype has caused zero ill effects with the blanking. + Version 0.1.7: Main: diff --git a/README.md b/README.md index 0d08c75..89cc3bf 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ Arduino Control for Your Vintage Stereo 05-Jan-2020: Version 0.1.5 - Fixed stupid mistake in hardware. Flipped logic of srEnable for new circuit. 05-Jan-2020: Version 0.1.6 - Lots of code clean-up, condensing, rewriting. 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. ```` @@ -102,9 +103,10 @@ This sketch requires the following libaries: Please install them via Library Manager or however you install libaries. Check indvidual project pages for LICENSE info. + # Media -[![Picture of prototype rig](/images/prototype.jpg "Prototype")*Prototype & Development Build* +![Picture of prototype rig](/images/prototype.jpg "Prototype")*Prototype & Development Build* More recent prototype build. @@ -115,7 +117,9 @@ broken and I don't feel like putting a gig worth of video in the repository, so [Now I've Got A Remote Control](https://www.youtube.com/watch?v=I30OaMii4l4) -[OLED, Relay Control, and HiFiLOGIX] (https://youtu.be/vn3nhpWjckw) +[OLED, Relay Control, and HiFiLOGIX] (https://www.youtube.com/watch?v=vn3nhpWjckw) + +[EEPROM Beta Demo] (https://www.youtube.com/watch?v=cMGZij3sTnE) # License diff --git a/hifilogix-eeprombeta.ino b/hifilogix-eeprombeta.ino new file mode 100644 index 0000000..021a632 --- /dev/null +++ b/hifilogix-eeprombeta.ino @@ -0,0 +1,112 @@ +/* + HiFiLOGIX EEPROM BETA (0.1.8 Base) + + dewdude@gmail.com - 08-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 +#define di 1022 +#define dx 1021 +#define db 1020 +#include "logo.h" // XBMP data for logo. + +U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE); + +const char *inputs[] = {"TAPE-2","TAPE-1","AUX","TUNER","PHONO-2","PHONO-1"}; +int latchPin = 11; +int clockPin = 9; +int dataPin = 12; +int IRin = 7; +int blanking = 5; +int matrix = A0; +IRrecv remote(IRin); +decode_results ircode; + +void DontCrossTheStreams(byte op, int x, int i) // There's something very important I forgot to tell you. +{// Don't cross the streams. // 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,inputs[i]); // 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() { +if (EEPROM.read(1023) == 'T') { + return; + } else { + EEPROM.write(db, 16); + EEPROM.write(dx, 32); + EEPROM.write(di, 2); + EEPROM.write(1023, '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); // Moved here since logo is bitmap. + DontCrossTheStreams(EEPROM.read(db),EEPROM.read(dx),EEPROM.read(di)); // THIS IS NO LONGER STATIC IN THE BETA! (yay.) + 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 c269851..56b7bec 100644 --- a/hifilogix.ino +++ b/hifilogix.ino @@ -1,7 +1,7 @@ /* - HiFiLOGIX 0.1.7 + HiFiLOGIX 0.1.8 - dewdude@gmail.com - 06-JAN-2019 + dewdude@gmail.com - 08-JAN-2019 */ #include @@ -16,38 +16,20 @@ int latchPin = 11; int clockPin = 9; int dataPin = 12; int IRin = 7; -int srEnable = 5; +int blanking = 5; int matrix = A0; -byte out = 0; IRrecv remote(IRin); decode_results ircode; -void logo() // Logo is now bitmapped. Saves a good bit of space this way. -{ - u8g2.firstPage(); - do { - u8g2.drawXBMP(14,4,hifilogix_width,hifilogix_height,hifilogix_bits); - } while ( u8g2.nextPage() ); -} // I also borrowed this from an example. I'll figure out how it works later. - - -void updateShiftRegister() -{ - digitalWrite(latchPin, LOW); - shiftOut(dataPin, clockPin, LSBFIRST, out); - digitalWrite(latchPin, HIGH); -} - -void DontCrossTheStreams(byte op, int x, int i) // Oh yeah, this much nicer than 8 seperate functions. -{ - out = 0; - updateShiftRegister(); - out = op; // No more bitset. This works better. - updateShiftRegister(); - u8g2.clearBuffer(); - u8g2.drawStr(x,30,inputs[i]); - u8g2.sendBuffer(); -// Don't cross the streams! +void DontCrossTheStreams(byte op, int x, int i) // There's something I forgot to tell you. +{// Don't cross the streams. // It would be bad. + digitalWrite(latchPin, LOW); // What do you mean, bad? + shiftOut(dataPin, clockPin, LSBFIRST, op); // Imagine all life as you know it + digitalWrite(latchPin, HIGH); // stopping instaneously and every + u8g2.clearBuffer(); // molecule in your body exploding + u8g2.drawStr(x,30,inputs[i]); // At the speed of light. + u8g2.sendBuffer(); // Total protonic reversal. + // That's bad. // Important safety tip, thanks Egon. } void setup() @@ -55,29 +37,32 @@ void setup() pinMode(latchPin, OUTPUT); pinMode(dataPin, OUTPUT); pinMode(clockPin, OUTPUT); - pinMode(srEnable, OUTPUT); + pinMode(blanking, OUTPUT); u8g2.begin(); remote.enableIRIn(); - logo(); // It's so pretty! - delay(2000); // It takes the Denon about 4.5 seconds to kick speakers on. - u8g2.setFont(u8g2_font_logisoso28_tr); // Moved here since logo is bitmap. - DontCrossTheStreams(16,32,2); // Someday this will not be static. - digitalWrite(srEnable,HIGH); // Now drives a logic inverter. + 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); // Moved here since logo is bitmap. + DontCrossTheStreams(16,32,2); // THIS IS NO LONGER STATIC IN THE BETA! (yay.) + digitalWrite(blanking,HIGH); // Now drives a logic inverter. } void loop() { int mx = analogRead(matrix); -byte icode = 0; // I changed how I handed the inputs. +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 > 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); diff --git a/utilities/README.md b/utilities/README.md new file mode 100644 index 0000000..b6117cc --- /dev/null +++ b/utilities/README.md @@ -0,0 +1,21 @@ +HiFiLOGIX Utilities + +The following sketches have been created to aid you should you decide to build +and use HiFiLOGIX for your own system. + +# Analog Switch Matrix Helper + +This literally just reads the value returned by the ADC on A0 and displays it to +the serial console. + +It is recommended that you take these measurements with a pull-down resistor on A0. + +Upload the sketch, open serial monitor. You should either see a bunch of 0's if you +have a pull-down resistor connected; or some wildly changing numbers if you don't. +Stick a resistor between A0 and 5V. The ADC in the ATMega will spit out a number +between 0 and 1023 and display it on the console. I really can't stress enough how +much better this works if you have a pull-down on A0. + +In theory you could calculate all this out by figuring out what voltage the A0 pin +would see in the voltage-divider you're creating; then figuring out what it's 5-bit +sampled value would be. But that's a pain in the ass. \ No newline at end of file diff --git a/utilities/analogmatrixhelper.ino b/utilities/analogmatrixhelper.ino new file mode 100644 index 0000000..2bb1a0d --- /dev/null +++ b/utilities/analogmatrixhelper.ino @@ -0,0 +1,22 @@ +/* + * Analog Switch Matrix Helper + * + * This sketch basically spits out the integer value of the A0 line + * to the serial console. Just plop a resistor between 5V and A0. + * The code in HiFiLOGIX is set up to use a range to account for + * drift and other variables. + * + */ + +char data[100]; + +void setup() { +Serial.begin(9600) +} + +void loop() { + int ain = analogRead(A0); + sprintf(data,"%4d",ain); + Serial.println(data); + delay(250); +}