Skip to content

Commit a12398a

Browse files
committed
Revert poll-based multiplex timing - but now the old code calculates fade duration correctly from EEPROM
1 parent 535f697 commit a12398a

File tree

1 file changed

+82
-143
lines changed

1 file changed

+82
-143
lines changed

sixtube_lm/sixtube_lm.ino

Lines changed: 82 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ Some are skipped when they wouldn't apply to a given clock's hardware config; se
160160
const byte optsLoc[] = {16,17,18,19,20,22,23,24,39,25,40,21,41,27, 28, 30,32,33,34, 35, 37};
161161
const word optsDef[] = { 2, 1, 0, 0, 0, 0, 0, 0,61, 0,61, 0,61, 0,1320, 360, 0, 1, 5, 480,1020};
162162
const word optsMin[] = { 1, 1, 0, 0, 0, 0, 0, 0,49, 0,49, 0,49, 0, 0, 0, 0, 0, 0, 0, 0};
163-
const word optsMax[] = { 2, 5, 3, 1,50, 6, 2,60,88, 1,88, 4,88, 2,1439,1439, 2, 6, 6,1439,1439};
163+
const word optsMax[] = { 2, 5, 3, 1,20, 6, 2,60,88, 1,88, 4,88, 2,1439,1439, 2, 6, 6,1439,1439};
164164

165165
//RTC objects
166166
DS3231 ds3231; //an object to access the ds3231 specifically (temp, etc)
@@ -231,12 +231,12 @@ void loop(){
231231
}
232232
}
233233
//Check the RTC and inputs every every 50ms - avoids overpolling(?) and switch bounce(?)
234-
if(pollLast+50<now) { //todo 20 vs 50
235-
pollLast=now;
236-
checkRTC(false); //if clock has ticked, decrement timer if running, and updateDisplay
237-
checkInputs(); //if inputs have changed, this will do things + updateDisplay as needed
238-
doSetHold(); //if inputs have been held, this will do more things + updateDisplay as needed
239-
}
234+
//if(pollLast+50<now) { //todo 20 vs 50
235+
pollLast=now;
236+
checkRTC(false); //if clock has ticked, decrement timer if running, and updateDisplay
237+
checkInputs(); //if inputs have changed, this will do things + updateDisplay as needed
238+
doSetHold(); //if inputs have been held, this will do more things + updateDisplay as needed
239+
//}
240240
//Every loop cycle, cycle the display
241241
cycleDisplay(); //keeps the display hardware multiplexing cycle going
242242
}
@@ -1032,158 +1032,97 @@ byte binOutB[4] = {6,7,8,9};
10321032
//3 pins out to anode channel switches
10331033
byte anodes[3] = {11,12,13};
10341034

1035-
int displayIn[6]={11,11,11,11,11,11};
1036-
int displayOut[6]={11,11,11,11,11,11};
1037-
1038-
//ms
1039-
/*
1040-
------ ------ ------
1041-
full transition, let's say is 200ms
1042-
transition start is 10000ms
1043-
cycle = 6 (normal) or 3 (dim)
1044-
mils diff at 1st cycle is 0; nextDur = ((diff*(6-1))/200)+1 = 1; lastDur = (6-nextDur) = 5;
1045-
mils diff at 2nd cycle is 10; nextDur = 1....
1046-
3rd - 20
1047-
4th - 30
1048-
5th - 40; nextDur = 2.... lastDur = 4......
1049-
1050-
1st - 0 - /0!!!!!!!!
1051-
1052-
at 6ms per digit, 1ms change each time, 3 pairs of digits = 75ms transition.
1053-
=====- =====- =====-
1054-
====-- ====-- ====--
1055-
===--- ===--- ===---
1056-
==---- ==---- ==----
1057-
=----- =----- =-----
1058-
at 4ms per digit, 4x4x3 = 48ms
1059-
at 3ms per digit, 3x3x3 = 27ms
1060-
at 6ms 6x6x3 = 108ms
1061-
*/
1062-
1063-
/*
1064-
I'm thinking this can't be done with ms polling, because at 6ms it's flickery enough to see it, and at 4ms it's not, because if we use polling, the actual lighting durations may not be as consistent as they need to be, mils() are not precise enough. durations may not necessarily be the same every time, but I don't think the durations are the same every time. So the alternative is to use delay()
1065-
*/
1035+
byte displayLast[6]={11,11,11,11,11,11}; //for noticing changes to displayNext and fading the display to it
10661036

1067-
const int fadeDur = 4; //each multiplexed pair of digits appears for this amount of time: partly next digit, partly last digit, partly dim (if applicable)
1068-
const int dimDur = 2; //half of fadeDur for half brightness? don't go over fadeDur-2
1069-
int fadeNextDur = 0; //Fading in displayNext values
1070-
int fadeLastDur = 0; //Fading out displayOut values
1071-
unsigned long fadeStartLast = 0; //when the last digit fade was started
1072-
byte cycleStage = 0; //Which stage of the multiplexing cycle we're in
1073-
unsigned long cycleLast = 0; //when the last stage was started
1074-
int cycleDelay = 0; //how long until the next stage starts - set from fadeNextDur and fadeLastDur
1037+
const int fadeDur = 5; //ms - each multiplexed pair of digits appears for this amount of time per cycle
1038+
const int dimDur = 4; //ms - portion of fadeDur that is left dark during dim times
1039+
int fadeNextDur = 0; //ms - during fade, incoming digit's portion of fadeDur
1040+
int fadeLastDur = 0; //ms - during fade, outgoing digit's portion of fadeDur
1041+
unsigned long fadeStartLast = 0; //millis - when the last digit fade was started
10751042
unsigned long setStartLast = 0; //to control flashing during start
10761043

1077-
word outputCounter = 0;
1078-
10791044
void initOutputs() {
10801045
for(byte i=0; i<4; i++) { pinMode(binOutA[i],OUTPUT); pinMode(binOutB[i],OUTPUT); }
10811046
for(byte i=0; i<3; i++) { pinMode(anodes[i],OUTPUT); }
10821047
pinMode(10, OUTPUT); //Alarm signal pin
10831048
}
10841049

10851050
void cycleDisplay(){
1086-
unsigned long mics = micros();
10871051
unsigned long mils = millis();
10881052

1089-
if(mics < cycleLast) { //because mics will overflow every 70 mins
1090-
cycleLast = 0;
1091-
//need some more elegant stuff here with fadeStartLast
1053+
//Other display code decides whether we should dim per function or time of day
1054+
bool dim = (displayDim==1?1:0);
1055+
//But if we're setting, decide here to dim for every other 500ms since we started setting
1056+
if(fnSetPg>0) {
1057+
if(setStartLast==0) setStartLast = mils;
1058+
dim = 1-(((mils-setStartLast)/500)%2);
1059+
} else {
1060+
if(setStartLast>0) setStartLast=0;
1061+
}
1062+
1063+
fadeLastDur = fadeDur-(dim?dimDur:0); //by default, last digit displays for entire fadeDur minus dim time
1064+
1065+
if(readEEPROM(20,false)==0 || dim) { //fading disabled or dim
1066+
if(fadeStartLast) fadeStartLast = 0; //cancel any fade currently going - dim state doesn't have enough steps to fade well
1067+
//TODO enable updateDisplay to configurably update both arrays to prevent fades
1068+
for(byte i=0; i<6; i++) if(displayNext[i] != displayLast[i]) displayLast[i] = displayNext[i];
10921069
}
1093-
if(cycleLast+cycleDelay < mics) {
1094-
cycleLast = mics;
1095-
1096-
//Other display code decides whether we should dim per function or time of day
1097-
bool dim = 0; //(displayDim==1?1:0); TODO undo
1098-
//But if we're setting, decide here to dim for every other 500ms since we started setting
1099-
if(fnSetPg>0) {
1100-
if(setStartLast==0) setStartLast = mils;
1101-
dim = 1-(((mils-setStartLast)/500)%2);
1102-
} else {
1103-
if(setStartLast>0) setStartLast=0;
1070+
else { //fading enabled
1071+
if(fadeStartLast==0) { //not fading - time to fade?
1072+
for(byte i=0; i<6; i++) if(displayNext[i] != displayLast[i]) { fadeStartLast = mils; break; }
11041073
}
1074+
if(fadeStartLast!=0) { //currently fading
1075+
//let the next digit steal some display time from the last digit
1076+
//ex: if fade time (from EEPROM) is 20ms, and fadeDur (next+last) is 6ms:
1077+
// at 0ms, next = (( 0*(6-1))/20)+1 = 1; last = (6-nextDur) = 5;
1078+
// at 10ms, next = ((10*(6-1))/20)+1 = 3; last = (6-nextDur) = 3; ...
1079+
// at 20ms, next = ((20*(6-1))/20)+1 = 6; next = total, so fade is over!
1080+
//TODO facilitate longer fades by writing a tweening function that smooths the frames, i.e. 111121222
1081+
fadeNextDur = (((mils-fadeStartLast)*(fadeDur-1))/(readEEPROM(20,false)*10))+1;
1082+
if(fadeNextDur >= fadeLastDur) { //fade is over
1083+
fadeStartLast = 0;
1084+
fadeNextDur = 0;
1085+
fadeLastDur = fadeDur;
1086+
for(byte j=0; j<6; j++) displayLast[j] = displayNext[j];
1087+
} //end fade is over
1088+
else { //shorten last digit display duration by subtracting next display duration from it
1089+
fadeLastDur = fadeLastDur - fadeNextDur;
1090+
}
1091+
} //end curently fading
1092+
} //end fading enabled
11051093

1106-
if(displayDim>0) { //if other display code says to shut off entirely, skip this part
1107-
1108-
int fadeFullDur = 0; //readEEPROM(20,false)*10; //50 becomes 500. TODO can you cancel the fade when a change is made?
1109-
1110-
switch(cycleStage){
1111-
case 0: //off and delay for dim, if applicable - also shift the delays
1112-
cycleStage++;
1113-
digitalWrite(anodes[2], LOW);
1114-
for(byte a=0; a<6; a++) displayIn[a] = displayNext[a];
1115-
if(fadeFullDur>0) { //if fade enabled
1116-
if(fadeStartLast==0) { //If we've completely faded, check to see if new differs from old, then initiate a new fade
1117-
for(byte i=0; i<6; i++) if(displayIn[i] != displayOut[i]) { fadeStartLast = mils; break; }
1118-
}
1119-
if(fadeStartLast!=0) { //If we're working on fading
1120-
// ( (diff*(6-1)) / 200 )+1 = 1;
1121-
fadeNextDur = ( ((mils-fadeStartLast)*(fadeDur-(dim?dimDur:0)-1)) / fadeFullDur )+1;
1122-
//partial based on time since fadeStatLast and EEPROM overall digit fade setting
1123-
if(fadeNextDur >= fadeDur) { fadeNextDur = fadeDur; fadeStartLast = 0; for(byte j=0; j<6; j++) displayOut[j] = displayIn[j]; } //end of the fade
1124-
fadeLastDur = fadeDur-(dim?dimDur:0)-fadeNextDur; if(fadeLastDur > fadeDur) fadeLastDur = 0; //just in case it loops around (does this happen?)
1125-
}
1126-
} else { //no fade - we don't care about any of the fadeLast stuff, always go straight to next
1127-
fadeNextDur = fadeDur-(dim?dimDur:0);
1128-
}
1129-
if(dim) { cycleDelay = dimDur; break; } //otherwise continue
1130-
case 1: //Anode channel 0: tubes #2 (min x10) and #5 (sec x1), outgoing digits on
1131-
cycleStage++;
1132-
setCathodes(displayOut[2],displayOut[5]); //Via d2b decoder chip, set cathodes to old digits
1133-
digitalWrite(anodes[0], HIGH); //Turn on tubes
1134-
if(fadeLastDur>0) { cycleDelay = fadeLastDur; break; } //Display for fade-out cycles, if applicable //(displayOutFade[0]/(dim?4:1))
1135-
case 2: //incoming digits on
1136-
cycleStage++;
1137-
setCathodes(displayIn[2],displayIn[5]); //Switch cathodes to new digits
1138-
cycleDelay = fadeNextDur; break; //Display for fade-in cycles
1139-
case 3: //off and pause for dim
1140-
cycleStage++;
1141-
digitalWrite(anodes[0], LOW); //Turn off tubes
1142-
if(dim) { cycleDelay = dimDur; break; } //otherwise continue
1143-
case 4: //Anode channel 1: tubes #1 (hour x1) and #4 (sec x10), outgoing digits on
1144-
cycleStage++;
1145-
setCathodes(displayOut[4],displayOut[1]);
1146-
digitalWrite(anodes[1], HIGH);
1147-
if(fadeLastDur>0) { cycleDelay = fadeLastDur; break; }
1148-
case 5: //incoming digits on
1149-
cycleStage++;
1150-
setCathodes(displayIn[4],displayIn[1]);
1151-
cycleDelay = fadeNextDur; break;
1152-
case 6: //off and pause for dim
1153-
cycleStage++;
1154-
digitalWrite(anodes[1], LOW);
1155-
if(dim) { cycleDelay = dimDur; break; } //otherwise continue
1156-
case 7: //Anode channel 2: tubes #0 (hour x10) and #3 (min x1), outgoing digits on
1157-
cycleStage++;
1158-
setCathodes(displayOut[0],displayOut[3]);
1159-
digitalWrite(anodes[2], HIGH);
1160-
if(fadeLastDur>0) { cycleDelay = fadeLastDur; break; }
1161-
case 8: //incoming digits on
1162-
cycleStage=0;
1163-
setCathodes(displayIn[0],displayIn[3]);
1164-
cycleDelay = fadeNextDur; break;
1165-
default: break;
1166-
} //end switch(cycleStage)
1167-
1168-
// if(outputCounter < 50) {
1169-
// outputCounter++;
1170-
// Serial.print(outputCounter,DEC);
1171-
// Serial.print(F(" "));
1172-
// Serial.print(cycleLast,DEC);
1173-
// Serial.print(F(" "));
1174-
// Serial.print(cycleStage,DEC);
1175-
// Serial.print(F(" "));
1176-
// Serial.print(cycleDelay,DEC);
1177-
// Serial.println();
1178-
// }
1179-
1180-
} //end if displayDim>0
1181-
else if(fadeLastDur>0) { //if we've just shut off the display in the middle of a fade (does this ever happen?), set things up for when display comes back
1182-
fadeLastDur = 0; //force a full fade in to the new value...
1183-
for(byte k=0; k<6; k++) { displayOut[k] = 0; } //...from a blank display
1184-
} //end if fadeLastDur>0
1094+
if(displayDim>0) { //if other display code says to shut off entirely, skip this part
1095+
//Anode channel 0: tubes #2 (min x10) and #5 (sec x1)
1096+
setCathodes(displayLast[2],displayLast[5]); //Via d2b decoder chip, set cathodes to old digits
1097+
digitalWrite(anodes[0], HIGH); //Turn on tubes
1098+
delay(fadeLastDur);//-(dim?dimDur:0)); //Display for fade-out cycles
1099+
setCathodes(displayNext[2],displayNext[5]); //Switch cathodes to new digits
1100+
delay(fadeNextDur);//-(dim?dimDur:0)); //Display for fade-in cycles
1101+
digitalWrite(anodes[0], LOW); //Turn off tubes
1102+
1103+
if(dim) delay(dimDur);
1104+
1105+
//Anode channel 1: tubes #4 (sec x10) and #1 (hour x1)
1106+
setCathodes(displayLast[4],displayLast[1]);
1107+
digitalWrite(anodes[1], HIGH);
1108+
delay(fadeLastDur);
1109+
setCathodes(displayNext[4],displayNext[1]);
1110+
delay(fadeNextDur);
1111+
digitalWrite(anodes[1], LOW);
1112+
1113+
if(dim) delay(dimDur);
1114+
1115+
//Anode channel 2: tubes #0 (hour x10) and #3 (min x1)
1116+
setCathodes(displayLast[0],displayLast[3]);
1117+
digitalWrite(anodes[2], HIGH);
1118+
delay(fadeLastDur);
1119+
setCathodes(displayNext[0],displayNext[3]);
1120+
delay(fadeNextDur);
1121+
digitalWrite(anodes[2], LOW);
1122+
1123+
if(dim) delay(dimDur);
1124+
} //end if displayDim>0
11851125

1186-
} //end cycleLast cycle
11871126
} //end cycleDisplay()
11881127

11891128
void setCathodes(byte decValA, byte decValB){

0 commit comments

Comments
 (0)