/* * BasicFlipClock.cpp * * Created: 8/7/2017 2:41:20 PM * Author : Spencer Hamblin * This is the main application code for the Basic Flip Clock designed and built by Spencer Hamblin * License : MIT, Do what ever you want with this code. But if you fuck it up it's on you. */ #include "BasicFlipClockLib.h" //bool alarmState, timeSet, alarmSet; bool displayReset = false; uint8_t blankDisplay[10] = {0,0,0,0,0,0,0,0,0,0}; uint8_t whiteDisplay[10] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; uint8_t displayState [10] = {0,0,0,0,0,0,0,0,0,0};//Current State For the Displays in the raw format uint8_t oldDisplayState [10] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};//Old Display State for smart update in raw format uint8_t oldMinutes = 0; uint8_t oldHours = 0; uint8_t minutes = 0xFF;//Set both to invalid state at start to make sure that the displays are updated uint8_t hours = 0xFF; //This 0,0 condition could arise on battery replacement with the RTC, though unlikely this accounts for it uint8_t seconds = 0; uint8_t minutesAlarm = 0; uint8_t hoursAlarm = 0; uint8_t alarmSetBTNTicks = 0; uint8_t timeSetBTNTicks = 0; uint8_t capSenseBTNTicks = 0; uint8_t upBTNTicks = 0; uint8_t downBTNTicks = 0; uint8_t alarmTicks = 0; bool alarmSetBTNReg = false; bool timeSetBTNReg = false; bool capSenseBTNReg = false; bool upBTNReg = false; bool downBTNReg = false; uint8_t lightOnFlag = 0; uint8_t switchState = 0;//Hold the current status of the buttons for the current event loop bool alarmSetState = false; bool timeSetState = false; bool alarmOnState = false; bool alarmEn = false; bool lightEn = false; bool easyAlarm = false; bool setHours = false;//Status of flag for timeSet and alarmSet unsigned int timeOutValue = 0; unsigned int lightTimeOutValue = 0; unsigned int brightness = 0; int8_t adjustmentValue = 0; int main(void) { initalSetUp(); //setLight16Bit(0xFFFF); getTime(seconds, minutesAlarm,hoursAlarm ,ALARM_REGISTER_RTC); //Flip all disp to off //chirp(); simpleDispUpdate(blankDisplay); delay_mS(2500); simpleDispUpdate(whiteDisplay); delay_mS(2500); while (true)//Main Event Loop { //Read Switch States switchState = getSwitchState(); //Check time //getTime(minutes,hours); #define debounceLongTime 100 if(switchState & ALM_BUT_MASK){ if(alarmSetBTNTicks == 255)alarmSetBTNTicks = 254; alarmSetBTNTicks++; if((alarmSetBTNTicks == debounceLongTime) & !timeSetState ){ if(alarmSetState){//double beep when leaving state chirp(); delay_mS(50); chirp(); }else chirp(); alarmSetState = !alarmSetState;//Toggles Value hours = hoursAlarm; minutes = minutesAlarm; setHours = false; }else if((alarmSetBTNTicks == debounceLongTime) & timeSetState){ timeSetState = false; chirp(); delay_mS(50); chirp(); } }else{ alarmSetBTNTicks = 0; //alarmSetBTNReg = false; } if(switchState & TIME_BUT_MASK){ if(timeSetBTNTicks == 255)timeSetBTNTicks = 254; timeSetBTNTicks++; if((timeSetBTNTicks == debounceLongTime) & !alarmSetState){ if(timeSetState){//double beep when leaving state chirp(); delay_mS(50); chirp(); }else chirp(); timeSetState = !timeSetState; setHours = false; }else if((timeSetBTNTicks == debounceLongTime) & alarmSetState){ alarmSetState = false; chirp(); delay_mS(50); chirp(); } }else{ timeSetBTNTicks = 0; //timeSetBTNReg = false; } if(switchState & UP_BUT_MASK){ if(upBTNTicks == 255)upBTNTicks = 254; upBTNTicks++; }else{ upBTNTicks = 0; } if(switchState & DOWN_BUT_MASK){ if(downBTNTicks == 255)downBTNTicks = 254; downBTNTicks++; }else{ downBTNTicks = 0; } if(switchState & ALM_SWITCH_MASK){ //if(alarmEn == false)alarmStatUpdate(true); alarmEn = true; }else{ //if(alarmEn == true)alarmStatUpdate(false); alarmEn = false; } if(switchState & LIGHT_SWITCH_MASK){ lightEn = true; }else{ lightEn = false; } //Read Cap Sensor #define capSenseThreashold 10 if(capSensor()){ if(capSenseBTNTicks == 255)capSenseBTNTicks = 254; capSenseBTNTicks++; if(capSenseBTNTicks > capSenseThreashold)capSenseBTNReg = true; }else{ if(capSenseBTNTicks > capSenseThreashold)capSenseBTNTicks = capSenseThreashold;//Uses ticks to detect off, lowers to reasonable value if(capSenseBTNTicks == 0){ capSenseBTNReg = false; } else{ capSenseBTNTicks--; } } //-----------Manage States--------------------------------------------// #define buttonSinglePress 1 #define buttonMediumPress 20 //#define buttonLongPress 30 #define buttonVelocityRate 5//Controls how many ticks it steps back #define alarmStepInterval 27 if(alarmOnState){//State for when alarm is going off if(easyAlarm){ softAlarm(); lightOnFlag = 1; easyAlarm = false; alarmOnState = false; setLight16Bit(maxBrightness); }else{ if(alarmTicks < alarmStepInterval){ tone(2700); setLight16Bit(maxBrightness); }else{ tone(0); setLight16Bit(0); if(alarmTicks > (alarmStepInterval * 2)) alarmTicks = 0; } alarmTicks++; if(capSenseBTNReg){//Disable alarm if pressed alarmOnState = false; lightOnFlag = 1; setLight16Bit(maxBrightness); tone(0); delay_mS(100); chirp(); //minutes += 1; } } if(!timeWindowBefore(minutes+1,hours,minutesAlarm,hoursAlarm,2)){//Exit alarm based on cap sense or timer setLight16Bit(maxBrightness); alarmOnState = false; lightOnFlag = 1;//Sets flag for code is aware of lights state softAlarm(); tone(0); delay_mS(100); chirp(); //minutes += 1;//This makes sure that the display is updated imidatly when the alarm is exited } //getTime(seconds, minutes , hours, TIME_REGISTER_RTC); //Code removed, it won't fit. IT's not a huge issue if the display does not update when the alarm is sounding. It's only 1-3 minutes after all. /*if( (oldMinutes != minutes)){//Check to see if a display update is needed timeToDisplayFormat(displayState, minutes, hours, alarmEn); simpleDispUpdate(displayState); oldMinutes = minutes; }*/ }else if(timeSetState | alarmSetState){/////////////////////////////////////////////////////////////////////////////////////////// setLight16Bit(0); lightOnFlag = 0; timeOutValue++; if((timeSetBTNTicks == 2) | (alarmSetBTNTicks == 2)){//Toggle hours or minutes setting chirp(); setHours = !setHours; } if(setHours){ if(upBTNTicks == buttonSinglePress){ hours += 1; }else if(downBTNTicks == buttonSinglePress){ hours -= 1; }else if(upBTNTicks >= buttonMediumPress){ hours += 3; upBTNTicks -= buttonVelocityRate; }else if(downBTNTicks >= buttonMediumPress){ hours -= 3; downBTNTicks -= buttonVelocityRate; } if(hours > 128){//Triggers if hours underflows and loops back hours -= 232; }else if(hours > 23){//Triggers if hours goes over 24 to loop 25 back to zero hours -= 24; } }else{ if(upBTNTicks == buttonSinglePress){ minutes += 1; }else if(downBTNTicks == buttonSinglePress){ minutes -= 1; }else if(upBTNTicks >= buttonMediumPress){ minutes += 5; upBTNTicks -= buttonVelocityRate; }else if(downBTNTicks >= buttonMediumPress){ minutes -= 5; downBTNTicks -= buttonVelocityRate; } if(minutes > 128){//Triggers if minutes underflows and loops back minutes -= 196; }else if(minutes > 59){//Triggers if minutes goes over 59 to loop 60 back to zero minutes -= 59; } } if(timeSetState){ setTime(minutes,hours, TIME_REGISTER_RTC); }else{ setTime(minutes,hours, ALARM_REGISTER_RTC); hoursAlarm = hours; minutesAlarm = minutes; } if((oldHours != hours) || (oldMinutes != minutes)){ timeToDisplayFormat(displayState, minutes, hours, alarmEn); simpleDispUpdate(displayState); } oldMinutes = minutes; oldHours = hours; if(timeOutValue > setingTimeOut){ timeSetState = 0; alarmSetState = 0; chirp(); delay_mS(50); chirp(); } }else {//Normal State for clock operations----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //oldMinutes = minutes; //oldHours = hours; timeOutValue = 0;//Zero time out from time/alarm setters //-------Get Current Time-------// //getTime(seconds, minutes , hours, TIME_REGISTER_RTC); if(minutes == minutesAlarm && hours == hoursAlarm && seconds == 0 && alarmEn == true){//Sets off alarm alarmOnState = true; } /*if( (oldMinutes != minutes) | (oldHours != hours) ){//Check to see if a display update is needed timeToDisplayFormat(displayState, minutes, hours, alarmEn); simpleDispUpdate(displayState); oldMinutes = minutes; oldHours = hours; }*/ #define EASY_ALARM_CHRIP_RATE 300 if(capSenseBTNReg && !easyAlarm && alarmEn && timeWindowBefore(minutesAlarm,hoursAlarm,minutes,hours,lightMinutesBeforeAlarm)){ softAlarm(); easyAlarm = true; lightOnFlag = 1; } if((lightEn && alarmEn && timeWindowBefore(minutesAlarm,hoursAlarm,minutes,hours,lightMinutesBeforeAlarm)) || alarmOnState){ brightness = timeDifferenceToBrightness(seconds, minutes, hours, minutesAlarm, hoursAlarm, lightMinutesBeforeAlarm, maxBrightness); if(easyAlarm){ setLight16Bit(0xFFFF); }else{ setLight16Bit(brightness); } lightOnFlag = 1; }else if(lightEn){//State machine for light states. Includes transition states if((lightOnFlag == 0) & capSenseBTNReg){ setLight16Bit(maxBrightness); lightOnFlag = 1; }else if((lightOnFlag == 1) & !capSenseBTNReg){ lightOnFlag = 2; }else if((lightOnFlag == 2) & capSenseBTNReg){ setLight16Bit(0); lightOnFlag = 3; }else if((lightOnFlag == 3) & !capSenseBTNReg){ lightOnFlag = 0; } if(lightOnFlag == 1 || lightOnFlag == 2){//Reset light to off it enough time passes. Will be used when left on deliberatly or after an alarm lightTimeOutValue++; if(lightTimeOutValue >= lightTimeOut){ setLight16Bit(0); lightOnFlag = 0; } }else{ lightTimeOutValue = 0; } easyAlarm = false; }else{//If light switch is off immediately disable lights setLight16Bit(0); lightOnFlag = 0; easyAlarm= false; } } //This is part of a size optimization effort. Instead of checking the time in alarmOn and normal state and re-using commands they are all grouped here to save program space if( !alarmSetState && !timeSetState){ oldMinutes = minutes; oldHours = hours; getTime(seconds, minutes , hours, TIME_REGISTER_RTC); if( (oldMinutes != minutes) | (oldHours != hours) ){//Check to see if a display update is needed timeToDisplayFormat(displayState, minutes, hours, alarmEn); simpleDispUpdate(displayState); //oldMinutes = minutes; //oldHours = hours; } } delay_mS(10);//Set timing of loop } }