Changed menu system to allow for more settings like intensity

This commit is contained in:
Mark van Renswoude 2017-12-03 21:27:45 +01:00
parent 9b62af6f11
commit 70dfde8562
22 changed files with 544 additions and 263 deletions

View File

@ -12,13 +12,13 @@
platform = atmelavr
board = pro16MHzatmega328
framework = arduino
upload_protocol = stk500v1
upload_flags = -P$UPLOAD_PORT -b$UPLOAD_SPEED
board_f_cpu = 1000000L
;upload_protocol = stk500v1
;upload_flags = -P$UPLOAD_PORT -b$UPLOAD_SPEED
;upload_speed = 19200
board_f_cpu = 16000000L
lib_deps =
Bounce2
Encoder
upload_port = COM7
upload_speed = 19200

View File

@ -1,6 +1,6 @@
#include "Config.h"
byte LCDCharArrow[8] = {
byte LCDCharArrowRightMap[8] = {
B00000,
B01000,
B01100,
@ -10,3 +10,42 @@ byte LCDCharArrow[8] = {
B00000,
};
byte LCDCharArrowLeftMap[8] = {
B00000,
B00100,
B01100,
B11100,
B01100,
B00100,
B00000,
};
byte LCDCharArrowRightHollowMap[8] = {
B00000,
B01000,
B00100,
B00010,
B00100,
B01000,
B00000,
};
byte LCDCharArrowLeftHollowMap[8] = {
B00000,
B00100,
B01000,
B10000,
B01000,
B00100,
B00000,
};
byte LCDCharUpDownMap[8] = {
B00000,
B00100,
B01110,
B00000,
B01110,
B00100,
B00000,
};

View File

@ -28,6 +28,16 @@ static const int LargeStep = 10;
static const int MenuTimeout = 2000;
extern byte LCDCharArrow[8];
static const uint8_t LCDCharArrowRight = 0;
static const uint8_t LCDCharArrowLeft = 1;
static const uint8_t LCDCharArrowRightHollow = 2;
static const uint8_t LCDCharArrowLeftHollow = 3;
static const uint8_t LCDCharUpDown = 4;
extern byte LCDCharArrowRightMap[8];
extern byte LCDCharArrowLeftMap[8];
extern byte LCDCharArrowRightHollowMap[8];
extern byte LCDCharArrowLeftHollowMap[8];
extern byte LCDCharUpDownMap[8];
#endif

View File

@ -16,3 +16,11 @@ void StartExposureTimer(unsigned long currentTime)
ExposureTimerStart = currentTime;
}
String FormatTime(unsigned int Time)
{
String minutes = String(ExposureTime / 60);
String seconds = String(ExposureTime % 60);
return minutes + ':' + (seconds.length() == 1 ? '0' + seconds : seconds);
}

View File

@ -10,4 +10,6 @@ extern unsigned long ExposureTimerStart;
void ResetExposureTime();
void StartExposureTimer(unsigned long currentTime);
String FormatTime(unsigned int Time);
#endif

View File

@ -0,0 +1,119 @@
#include "Screen/BaseMenuScreen.h"
#include "Config.h"
#include "Buzzer.h"
void BaseMenuScreen::setEnableMenuScroll(bool value)
{
if (value != mEnableMenuScroll)
{
mEnableMenuScroll = value;
printScrollIndicators();
}
}
void BaseMenuScreen::onShow()
{
printTitle();
printScrollIndicators();
printValue();
}
void BaseMenuScreen::onHide()
{
}
void BaseMenuScreen::printTitle()
{
LiquidCrystal* display = getDisplay();
const char* title = getTitle();
uint8_t titleLength = strlen(title);
uint8_t maxWidth = LCDWidth - 2;
display->setCursor(1, 0);
if (titleLength >= maxWidth)
{
// Title too long, cut off
char* character = (char*)title;
for (uint8_t i = 0; i < maxWidth; i++)
{
display->write(byte(*character));
character++;
}
}
else
{
// Center title
uint8_t offset = (maxWidth - titleLength) / 2;
for (uint8_t i = 0; i < offset; i++)
display->write(' ');
display->print(title);
offset += titleLength;
while (offset < LCDWidth - 2)
{
display->print(' ');
offset++;
}
}
}
void BaseMenuScreen::printScrollIndicators()
{
LiquidCrystal* display = getDisplay();
display->setCursor(0, 0);
if (hasPrevious())
display->write(getEnableMenuScroll() ? LCDCharArrowLeft : LCDCharArrowLeftHollow);
else
display->write(' ');
display->setCursor(LCDWidth - 1, 0);
if (hasNext())
display->write(getEnableMenuScroll() ? LCDCharArrowRight : LCDCharArrowRightHollow);
else
display->write(' ');
}
void BaseMenuScreen::printValue()
{
LiquidCrystal* display = getDisplay();
display->setCursor(0, 1);
for (uint8_t x = 0; x < LCDWidth; x++)
display->write(' ');
}
void BaseMenuScreen::onEncoder(long lastPosition, long newPosition)
{
if (mEnableMenuScroll)
{
if (newPosition > lastPosition)
{
if (hasNext())
{
buzzSelect();
gotoNext();
}
}
else
{
if (hasPrevious())
{
buzzSelect();
gotoPrevious();
}
}
}
}

View File

@ -0,0 +1,41 @@
#ifndef __BaseMenuScreen
#define __BaseMenuScreen
#include <stdbool.h>
#include "ScreenManager.h"
/*
* Base menu screen
* Provides the base for a menu screen, allows scrolling to
* the previous or next menu screen or performs an action.
*/
class BaseMenuScreen : public BaseScreen
{
private:
bool mEnableMenuScroll = true;
protected:
bool getEnableMenuScroll() { return mEnableMenuScroll; }
void setEnableMenuScroll(bool value);
virtual bool hasPrevious() = 0;
virtual bool hasNext() = 0;
virtual const char* getTitle() = 0;
virtual void gotoPrevious() {}
virtual void gotoNext() {}
void printTitle();
void printScrollIndicators();
virtual void printValue();
public:
BaseMenuScreen(ScreenManager* screenManager) : BaseScreen(screenManager) { }
virtual void onShow();
virtual void onHide();
virtual void onEncoder(long lastPosition, long newPosition);
};
#endif

View File

@ -1,18 +1,21 @@
#include "ScreenCountdown.h"
#include "ScreenSetTime.h"
#include "CountdownScreen.h"
#include "Screen/SetTimeScreen.h"
#include "ExposureTimer.h"
#include "Config.h"
#include "Buzzer.h"
void ScreenCountdown::printRemainingTime()
void CountdownScreen::printRemainingTime()
{
getDisplay()->setCursor(0, 1);
printTime(ExposureTime - ((getCurrentTime() - ExposureTimerStart) / 1000));
String time = FormatTime(ExposureTime - ((getCurrentTime() - ExposureTimerStart) / 1000));
// TODO blank out, center, etc
getDisplay()->print(time);
}
void ScreenCountdown::onShow()
void CountdownScreen::onShow()
{
mLastDisplayed = -1;
@ -24,27 +27,27 @@ void ScreenCountdown::onShow()
}
void ScreenCountdown::onHide()
void CountdownScreen::onHide()
{
digitalWrite(PinLED, LOW);
}
void ScreenCountdown::onButton()
void CountdownScreen::onButton()
{
// TODO Confirmation?
buzzClick();
getScreenManager()->show<ScreenSetTime>();
getScreenManager()->show<SetTimeScreen>();
}
void ScreenCountdown::onEncoder(long lastPosition, long newPosition)
void CountdownScreen::onEncoder(long lastPosition, long newPosition)
{
// TODO Allow adding / removing time?
}
void ScreenCountdown::onTick()
void CountdownScreen::onTick()
{
long elapsed = (getCurrentTime() - ExposureTimerStart) / 1000;
@ -59,7 +62,7 @@ void ScreenCountdown::onTick()
buzzCompleted();
ExposureTimerStart = 0;
getScreenManager()->show<ScreenSetTime>();
getScreenManager()->show<SetTimeScreen>();
}
else if (elapsed != mLastDisplayed)
{

View File

@ -1,5 +1,5 @@
#ifndef __ScreenCountdown
#define __ScreenCountdown
#ifndef __CountdownScreen
#define __CountdownScreen
#include "ScreenManager.h"
@ -7,20 +7,20 @@
* Countdown screen
* Shows the remaining time.
*/
class ScreenCountdown : public BaseScreen
class CountdownScreen : public BaseScreen
{
private:
int mLastDisplayed;
protected:
void printRemainingTime();
public:
ScreenCountdown(ScreenManager* screenManager) : BaseScreen(screenManager) { }
CountdownScreen(ScreenManager* screenManager) : BaseScreen(screenManager) { }
void onShow();
void onHide();
void onButton();
void onEncoder(long lastPosition, long newPosition);
void onTick();

View File

@ -0,0 +1,84 @@
#include "Screen/IntensityScreen.h"
#include "Screen/SetTimeScreen.h"
#include "Screen/StartScreen.h"
#include "ExposureTimer.h"
#include "Buzzer.h"
#include "Config.h"
void IntensityScreen::printValue()
{
LiquidCrystal* display = getDisplay();
display->setCursor(0, 1);
String intensity = "100%";
uint8_t offset = (LCDWidth - intensity.length()) / 2;
for (uint8_t space = 0; space < offset; space++)
display->print(' ');
display->print(intensity);
offset += intensity.length();
if (getEditMode())
{
display->write(LCDCharUpDown);
offset++;
}
for (uint8_t space = offset; space < LCDWidth; space++)
display->print(' ');
}
void IntensityScreen::gotoPrevious()
{
buzzSelect();
getScreenManager()->show<SetTimeScreen>();
}
void IntensityScreen::gotoNext()
{
buzzSelect();
getScreenManager()->show<StartScreen>();
}
void IntensityScreen::onHide()
{
}
void IntensityScreen::onButton()
{
buzzSelect();
setEditMode(!getEditMode());
printValue();
}
void IntensityScreen::onEncoder(long lastPosition, long newPosition)
{
if (getEditMode())
{
buzzSelect();
/*
if (newPosition > lastPosition)
ExposureTime += ExposureTime >= LargeStepTreshold ? LargeStep : SmallStep;
else if (ExposureTime > 0)
ExposureTime -= ExposureTime > LargeStepTreshold ? LargeStep : SmallStep;
*/
printValue();
}
else
BaseMenuScreen::onEncoder(lastPosition, newPosition);
}
void IntensityScreen::onTick()
{
}

View File

@ -0,0 +1,36 @@
#ifndef __IntensityScreen
#define __IntensityScreen
#include "ScreenManager.h"
#include "Screen/BaseMenuScreen.h"
/*
* Intensity screen
* Allows changing of the intensity.
*/
class IntensityScreen : public BaseMenuScreen
{
protected:
inline bool getEditMode() { return !getEnableMenuScroll(); }
inline void setEditMode(bool value) { setEnableMenuScroll(!value); }
bool hasPrevious() { return true; }
bool hasNext() { return true; }
const char* getTitle() { return "Intensity"; }
void gotoPrevious();
void gotoNext();
void printValue();
public:
IntensityScreen(ScreenManager* screenManager) : BaseMenuScreen(screenManager) { }
void onHide();
void onButton();
void onEncoder(long lastPosition, long newPosition);
void onTick();
};
#endif

View File

@ -1,100 +0,0 @@
#include "ScreenMenu.h"
#include "ScreenSetTime.h"
#include "ScreenCountdown.h"
#include "ExposureTimer.h"
#include "Config.h"
#include "Buzzer.h"
void ScreenMenu::updateLastActivity()
{
mLastActivity = getCurrentTime();
}
void ScreenMenu::printExposureTime()
{
getDisplay()->setCursor(0, 1);
printTime(ExposureTime);
}
void ScreenMenu::printMenuCursor()
{
getDisplay()->setCursor(0, 0);
getDisplay()->write(mSelected == 0 ? (byte)0 : ' ');
getDisplay()->setCursor(9, 0);
getDisplay()->write(mSelected == 1 ? (byte)0 : ' ');
}
void ScreenMenu::onShow()
{
updateLastActivity();
mSelected = 0;
getDisplay()->setCursor(0, 0);
getDisplay()->print(" Start Reset ");
printMenuCursor();
printExposureTime();
}
void ScreenMenu::onHide()
{
}
void ScreenMenu::onButton()
{
buzzClick();
switch (mSelected)
{
case 0:
digitalWrite(PinLED, HIGH);
StartExposureTimer(getCurrentTime());
getScreenManager()->show<ScreenCountdown>();
break;
case 1:
ResetExposureTime();
getScreenManager()->show<ScreenSetTime>();
}
}
void ScreenMenu::onEncoder(long lastPosition, long newPosition)
{
updateLastActivity();
if (newPosition > lastPosition)
{
if (mSelected < 1)
{
buzzSelect();
mSelected++;
printMenuCursor();
}
}
else
{
if (mSelected > 0)
{
buzzSelect();
mSelected--;
printMenuCursor();
}
}
}
void ScreenMenu::onTick()
{
if (getCurrentTime() - mLastActivity >= MenuTimeout)
getScreenManager()->show<ScreenSetTime>();
}

View File

@ -1,33 +0,0 @@
#ifndef __ScreenMenu
#define __ScreenMenu
#include "ScreenManager.h"
/*
* Menu screen
* Allows starting the timer or resetting the time to the last used value.
*/
class ScreenMenu : public BaseScreen
{
private:
int mSelected;
unsigned long mLastActivity;
protected:
void updateLastActivity();
void printExposureTime();
void printMenuCursor();
public:
ScreenMenu(ScreenManager* screenManager) : BaseScreen(screenManager) { }
void onShow();
void onHide();
void onButton();
void onEncoder(long lastPosition, long newPosition);
void onTick();
};
#endif

View File

@ -1,52 +0,0 @@
#include "ScreenSetTime.h"
#include "Screen/ScreenMenu.h"
#include "ExposureTimer.h"
#include "Buzzer.h"
#include "Config.h"
void ScreenSetTime::printExposureTime()
{
getDisplay()->setCursor(0, 1);
printTime(ExposureTime);
}
void ScreenSetTime::onShow()
{
getDisplay()->setCursor(0, 0);
getDisplay()->print("Exposure time: ");
printExposureTime();
}
void ScreenSetTime::onHide()
{
}
void ScreenSetTime::onButton()
{
buzzClick();
getScreenManager()->show<ScreenMenu>();
}
void ScreenSetTime::onEncoder(long lastPosition, long newPosition)
{
buzzSelect();
if (newPosition > lastPosition)
ExposureTime += ExposureTime >= LargeStepTreshold ? LargeStep : SmallStep;
else if (ExposureTime > 0)
ExposureTime -= ExposureTime > LargeStepTreshold ? LargeStep : SmallStep;
printExposureTime();
}
void ScreenSetTime::onTick()
{
}

View File

@ -1,26 +0,0 @@
#ifndef __ScreenSetTime
#define __ScreenSetTime
#include "ScreenManager.h"
/*
* Time screen
* Allows changing of the exposure time. Pressing the button will switch to the menu.
*/
class ScreenSetTime : public BaseScreen
{
protected:
void printExposureTime();
public:
ScreenSetTime(ScreenManager* screenManager) : BaseScreen(screenManager) { }
void onShow();
void onHide();
void onButton();
void onEncoder(long lastPosition, long newPosition);
void onTick();
};
#endif

View File

@ -0,0 +1,74 @@
#include "Screen/SetTimeScreen.h"
#include "Screen/IntensityScreen.h"
#include "ExposureTimer.h"
#include "Buzzer.h"
#include "Config.h"
void SetTimeScreen::printValue()
{
LiquidCrystal* display = getDisplay();
display->setCursor(0, 1);
String time = FormatTime(ExposureTime);
uint8_t offset = (LCDWidth - time.length()) / 2;
for (uint8_t space = 0; space < offset; space++)
display->print(' ');
display->print(time);
offset += time.length();
if (getEditMode())
{
display->write(LCDCharUpDown);
offset++;
}
for (uint8_t space = offset; space < LCDWidth; space++)
display->print(' ');
}
void SetTimeScreen::gotoNext()
{
buzzSelect();
getScreenManager()->show<IntensityScreen>();
}
void SetTimeScreen::onHide()
{
}
void SetTimeScreen::onButton()
{
buzzSelect();
setEditMode(!getEditMode());
printValue();
}
void SetTimeScreen::onEncoder(long lastPosition, long newPosition)
{
if (getEditMode())
{
buzzSelect();
if (newPosition > lastPosition)
ExposureTime += ExposureTime >= LargeStepTreshold ? LargeStep : SmallStep;
else if (ExposureTime > 0)
ExposureTime -= ExposureTime > LargeStepTreshold ? LargeStep : SmallStep;
printValue();
}
else
BaseMenuScreen::onEncoder(lastPosition, newPosition);
}
void SetTimeScreen::onTick()
{
}

View File

@ -0,0 +1,35 @@
#ifndef __SetTimeScreen
#define __SetTimeScreen
#include "ScreenManager.h"
#include "Screen/BaseMenuScreen.h"
/*
* Time screen
* Allows changing of the exposure time.
*/
class SetTimeScreen : public BaseMenuScreen
{
protected:
inline bool getEditMode() { return !getEnableMenuScroll(); }
inline void setEditMode(bool value) { setEnableMenuScroll(!value); }
bool hasPrevious() { return false; }
bool hasNext() { return true; }
const char* getTitle() { return "Time"; }
void gotoNext();
void printValue();
public:
SetTimeScreen(ScreenManager* screenManager) : BaseMenuScreen(screenManager) { }
void onHide();
void onButton();
void onEncoder(long lastPosition, long newPosition);
void onTick();
};
#endif

View File

@ -0,0 +1,30 @@
#include "Screen/StartScreen.h"
#include "Screen/IntensityScreen.h"
#include "ExposureTimer.h"
#include "Buzzer.h"
#include "Config.h"
void StartScreen::gotoPrevious()
{
buzzSelect();
getScreenManager()->show<IntensityScreen>();
}
void StartScreen::onHide()
{
}
void StartScreen::onButton()
{
buzzSelect();
//setEditMode(!getEditMode());
}
void StartScreen::onTick()
{
}

29
src/Screen/StartScreen.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef __StartScreen
#define __StartScreen
#include "ScreenManager.h"
#include "Screen/BaseMenuScreen.h"
/*
* Start screen
* Allows starting the exposure.
*/
class StartScreen : public BaseMenuScreen
{
protected:
bool hasPrevious() { return true; }
bool hasNext() { return false; }
const char* getTitle() { return "Start"; }
void gotoPrevious();
public:
StartScreen(ScreenManager* screenManager) : BaseMenuScreen(screenManager) { }
void onHide();
void onButton();
void onTick();
};
#endif

View File

@ -17,22 +17,3 @@ LiquidCrystal* BaseScreen::getDisplay()
return mScreenManager->getDisplay();
}
void BaseScreen::printTime(int value)
{
String minutes = String(value / 60);
String seconds = String(value % 60);
int textLength = minutes.length() + 1 + 2;
getDisplay()->print(minutes);
getDisplay()->print(":");
if (seconds.length() == 1)
getDisplay()->print("0");
getDisplay()->print(seconds);
for (int space = textLength + 1; space < LCDWidth; space++)
getDisplay()->print(" ");
}

View File

@ -17,9 +17,6 @@ class BaseScreen
unsigned long getCurrentTime();
LiquidCrystal* getDisplay();
void printTime(int value);
public:
BaseScreen(ScreenManager* screenManager)
{

View File

@ -4,7 +4,7 @@
#include <LiquidCrystal.h>
#include "Config.h"
#include "ScreenManager.h"
#include "Screen/ScreenSetTime.h"
#include "Screen/SetTimeScreen.h"
#include "Buzzer.h"
#include "ExposureTimer.h"
@ -36,11 +36,15 @@ void setup()
ResetExposureTime();
lcd.createChar(0, LCDCharArrow);
lcd.createChar(LCDCharArrowRight, LCDCharArrowRightMap);
lcd.createChar(LCDCharArrowLeft, LCDCharArrowLeftMap);
lcd.createChar(LCDCharArrowRightHollow, LCDCharArrowRightHollowMap);
lcd.createChar(LCDCharArrowLeftHollow, LCDCharArrowLeftHollowMap);
lcd.createChar(LCDCharUpDown, LCDCharUpDownMap);
lcd.begin(LCDWidth, LCDHeight);
screenManager = new ScreenManager(&lcd, &currentTime);
screenManager->show<ScreenSetTime>();
screenManager->show<SetTimeScreen>();
buzzStartup();
}