0.1.8 - EEPROM Beta - Utilities

master
Jay 4 years ago
parent fceb37c9e0
commit 5501df73e3

@ -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:

@ -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

@ -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 <Wire.h>
#include <U8g2lib.h>
#include <IRremote.h>
#include <EEPROM.h>
#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);
}

@ -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 <Wire.h>
@ -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);

@ -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.

@ -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);
}
Loading…
Cancel
Save