diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..ec76ec27 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +backup diff --git a/Form/Form.pde b/Form/Form.pde new file mode 100644 index 00000000..49f984fd --- /dev/null +++ b/Form/Form.pde @@ -0,0 +1,60 @@ +/* +This example demonstrates how to use the Form and Field classes from the +FreetronicsLCD library to provide a simple UI on the 16x2 LCD display. +*/ + +// include the library code: +#include +#include +#include +#include +#include +#include + +// Initialize the LCD +FreetronicsLCD lcd; + +// Note: if you are using the USBDroid and have reassigned pin D9 on the LCD shield to some +// other pin (e.g. A1), then you will need to initialize the shield with something like: +// FreetronicsLCD lcd(A1); +// See also: http://www.freetronics.com/pages/combining-the-lcd-keypad-shield-and-the-usbdroid + +// Create the main form and its fields. +Form mainForm(lcd); +TextField welcomeField(mainForm, "Form example", "v1.0"); +TimeField timeField(mainForm, "Time since reset", 24, TIMEFIELD_READ_ONLY); +IntField volumeField(mainForm, "Volume", 0, 100, 5, 85, "%"); +BoolField ledField(mainForm, "Status LED", "On", "Off", true); +TimeField durationField(mainForm, "Timer duration", 24, TIMEFIELD_READ_WRITE); + +#define STATUS_LED 13 + +void setup() { + // Status LED initially on. + pinMode(STATUS_LED, OUTPUT); + digitalWrite(STATUS_LED, HIGH); + + // Enable the screen saver, which will automatically blank the screen after 10 seconds. + // The screen will wake up again when a button is pressed or lcd.display() is called. + lcd.enableScreenSaver(); + + // Show the main form for the first time. + mainForm.show(); +} + +void loop() { + // Update the number of seconds since reset: + timeField.setValue(millis() / 1000); + + // Dispatch button events to the main form. + int button = lcd.getButton(); + if (mainForm.dispatch(button) == FORM_CHANGED) { + if (mainForm.isCurrent(ledField)) { + if (ledField.value()) + digitalWrite(STATUS_LED, HIGH); + else + digitalWrite(STATUS_LED, LOW); + } + } +} + diff --git a/libraries/FreetronicsLCD/BoolField.cpp b/libraries/FreetronicsLCD/BoolField.cpp new file mode 100644 index 00000000..0e40701f --- /dev/null +++ b/libraries/FreetronicsLCD/BoolField.cpp @@ -0,0 +1,83 @@ +#include "BoolField.h" + +BoolField::BoolField(const String &label) + : Field(label) + , _printLen(0) + , _value(false) +{ +} + +BoolField::BoolField(Form &form, const String &label) + : Field(form, label) + , _printLen(0) + , _value(false) +{ +} + +BoolField::BoolField(Form &form, const String &label, const String &trueLabel, const String &falseLabel, bool value) + : Field(form, label) + , _trueLabel(trueLabel) + , _falseLabel(falseLabel) + , _printLen(0) + , _value(value) +{ +} + +int BoolField::dispatch(int event) +{ + if (event == LCD_BUTTON_UP || event == LCD_BUTTON_DOWN || + event == LCD_BUTTON_SELECT) { + setValue(!_value); + return FORM_CHANGED; + } else { + return -1; + } +} + +void BoolField::enterField(bool reverse) +{ + Field::enterField(reverse); + printValue(); +} + +void BoolField::setValue(bool value) +{ + if (value != _value) { + _value = value; + if (isCurrent()) + printValue(); + } +} + +void BoolField::setTrueLabel(const String &trueLabel) +{ + _trueLabel = trueLabel; + if (isCurrent()) + printValue(); +} + +void BoolField::setFalseLabel(const String &falseLabel) +{ + _falseLabel = falseLabel; + if (isCurrent()) + printValue(); +} + +void BoolField::printValue() +{ + unsigned int len; + lcd()->setCursor(0, 1); + if (_value) { + lcd()->print(_trueLabel); + len = _trueLabel.length(); + while (len++ < _printLen) + lcd()->write(' '); + _printLen = _trueLabel.length(); + } else { + lcd()->print(_falseLabel); + len = _falseLabel.length(); + while (len++ < _printLen) + lcd()->write(' '); + _printLen = _falseLabel.length(); + } +} diff --git a/libraries/FreetronicsLCD/BoolField.h b/libraries/FreetronicsLCD/BoolField.h new file mode 100644 index 00000000..bc773e9c --- /dev/null +++ b/libraries/FreetronicsLCD/BoolField.h @@ -0,0 +1,34 @@ +#ifndef BoolField_h +#define BoolField_h + +#include "Field.h" + +class BoolField : public Field { +public: + explicit BoolField(const String &label); + BoolField(Form &form, const String &label); + BoolField(Form &form, const String &label, const String &trueLabel, const String &falseLabel, bool value); + + int dispatch(int event); + + void enterField(bool reverse); + + bool value() const { return _value; } + void setValue(bool value); + + String trueLabel() const { return _trueLabel; } + void setTrueLabel(const String &trueLabel); + + String falseLabel() const { return _falseLabel; } + void setFalseLabel(const String &falseLabel); + +private: + String _trueLabel; + String _falseLabel; + int _printLen; + bool _value; + + void printValue(); +}; + +#endif diff --git a/libraries/FreetronicsLCD/Field.cpp b/libraries/FreetronicsLCD/Field.cpp new file mode 100644 index 00000000..f1ce27c3 --- /dev/null +++ b/libraries/FreetronicsLCD/Field.cpp @@ -0,0 +1,71 @@ +#include "Field.h" + +Field::Field(const String &label) + : _label(label) + , _form(0) + , next(0) + , prev(0) +{ +} + +Field::Field(Form &form, const String &label) + : _label(label) + , _form(0) + , next(0) + , prev(0) +{ + form.addField(this); +} + +Field::~Field() +{ + if (_form) + _form->removeField(this); +} + +int Field::dispatch(int event) +{ + // Nothing to do here. + return -1; +} + +void Field::enterField(bool reverse) +{ + // Print the label and then position the cursor on the second line. + // We assume that the screen has just been cleared. + lcd()->print(_label); + lcd()->setCursor(0, 1); +} + +void Field::exitField() +{ + // Nothing to do here. +} + +void Field::setLabel(const String &label) +{ + if (isCurrent()) { + unsigned int prevLen = _label.length(); + unsigned int newLen = label.length(); + _label = label; + lcd()->setCursor(0, 0); + lcd()->print(label); + while (newLen++ < prevLen) + lcd()->write(' '); + updateCursor(); + } else { + _label = label; + } +} + +bool Field::isCurrent() const +{ + if (!_form->isVisible()) + return false; + return _form->currentField() == this; +} + +void Field::updateCursor() +{ + // Nothing to do here. +} diff --git a/libraries/FreetronicsLCD/Field.h b/libraries/FreetronicsLCD/Field.h new file mode 100644 index 00000000..0203d2cf --- /dev/null +++ b/libraries/FreetronicsLCD/Field.h @@ -0,0 +1,38 @@ +#ifndef Field_h +#define Field_h + +#include "Form.h" + +class Field { +public: + explicit Field(const String &label); + Field(Form &form, const String &label); + ~Field(); + + Form *form() const { return _form; } + + virtual int dispatch(int event); + + virtual void enterField(bool reverse); + virtual void exitField(); + + String label() const { return _label; } + void setLabel(const String &label); + + bool isCurrent() const; + +protected: + LiquidCrystal *lcd() const { return _form->_lcd; } + + virtual void updateCursor(); + +private: + String _label; + Form *_form; + Field *next; + Field *prev; + + friend class Form; +}; + +#endif diff --git a/libraries/FreetronicsLCD/Form.cpp b/libraries/FreetronicsLCD/Form.cpp new file mode 100644 index 00000000..a54a9991 --- /dev/null +++ b/libraries/FreetronicsLCD/Form.cpp @@ -0,0 +1,149 @@ +#include "Form.h" +#include "Field.h" + +Form::Form(LiquidCrystal &lcd) + : _lcd(&lcd) + , first(0) + , last(0) + , current(0) +{ +} + +Form::~Form() +{ + Field *field = first; + Field *next; + while (field != 0) { + next = field->next; + field->_form = 0; + field->next = 0; + field->prev = 0; + field = next; + } +} + +int Form::dispatch(int event) +{ + if (current) { + int exitval = current->dispatch(event); + if (exitval >= 0) + return exitval; + } + if (event == LCD_BUTTON_LEFT) + prevField(); + else if (event == LCD_BUTTON_RIGHT) + nextField(); + return 0; +} + +void Form::nextField() +{ + Field *field = current; + if (!field) + field = first; + if (field && field->next) + field = field->next; + else + field = first; + setCurrentField(field); +} + +void Form::prevField() +{ + Field *field = current; + if (!field) + field = last; + if (field && field->prev) + field = field->prev; + else + field = last; + setCurrentField(field); +} + +void Form::defaultField() +{ + setCurrentField(first); +} + +void Form::addField(Field *field) +{ + if (field->_form) + return; // Already added to a form. + field->_form = this; + field->next = 0; + field->prev = last; + if (last) + last->next = field; + else + first = field; + last = field; +} + +void Form::removeField(Field *field) +{ + if (field->_form != this) + return; // Not a member of this form. + if (current == field) { + if (field->next) + setCurrentField(field->next); + else if (field->prev) + setCurrentField(field->prev); + else + setCurrentField(0); + } + if (field->next) + field->next->prev = field->prev; + else + last = field->prev; + if (field->prev) + field->prev->next = field->next; + else + first = field->next; + field->_form = 0; + field->next = 0; + field->prev = 0; +} + +void Form::setCurrentField(Field *field) +{ + if (field && field->_form != this) + return; // Wrong form. + if (visible) { + bool reverse = false; + if (current) { + current->exitField(); + if (field->next == current) + reverse = true; + else if (!field->next && current == first) + reverse = true; + } + current = field; + _lcd->clear(); + if (current) + current->enterField(reverse); + } else { + current = field; + } +} + +void Form::show() +{ + if (!visible) { + if (!current) + current = first; + visible = true; + _lcd->clear(); + if (current) + current->enterField(false); + } +} + +void Form::hide() +{ + if (visible) { + if (current) + current->exitField(); + visible = false; + _lcd->clear(); + } +} diff --git a/libraries/FreetronicsLCD/Form.h b/libraries/FreetronicsLCD/Form.h new file mode 100644 index 00000000..4548dd74 --- /dev/null +++ b/libraries/FreetronicsLCD/Form.h @@ -0,0 +1,43 @@ +#ifndef Form_h +#define Form_h + +#include "FreetronicsLCD.h" + +class Field; + +#define FORM_CHANGED 1 + +class Form { +public: + explicit Form(LiquidCrystal &lcd); + ~Form(); + + int dispatch(int event); + + void nextField(); + void prevField(); + void defaultField(); + + void addField(Field *field); + void removeField(Field *field); + + Field *currentField() const { return current; } + void setCurrentField(Field *field); + + bool isCurrent(Field &field) const { return current == &field; } + + void show(); + void hide(); + bool isVisible() const { return visible; } + +private: + LiquidCrystal *_lcd; + Field *first; + Field *last; + Field *current; + bool visible; + + friend class Field; +}; + +#endif diff --git a/libraries/FreetronicsLCD/IntField.cpp b/libraries/FreetronicsLCD/IntField.cpp new file mode 100644 index 00000000..ecec5633 --- /dev/null +++ b/libraries/FreetronicsLCD/IntField.cpp @@ -0,0 +1,104 @@ +#include "IntField.h" + +IntField::IntField(const String &label) + : Field(label) + , _minValue(0) + , _maxValue(100) + , _stepValue(1) + , _value(0) + , _printLen(0) +{ +} + +IntField::IntField(Form &form, const String &label) + : Field(form, label) + , _minValue(0) + , _maxValue(100) + , _stepValue(1) + , _value(0) + , _printLen(0) +{ +} + +IntField::IntField(Form &form, const String &label, int minValue, int maxValue, int value) + : Field(form, label) + , _minValue(minValue) + , _maxValue(maxValue) + , _stepValue(1) + , _value(value) + , _printLen(0) +{ +} + +IntField::IntField(Form &form, const String &label, int minValue, int maxValue, int value, const String &suffix) + : Field(form, label) + , _minValue(minValue) + , _maxValue(maxValue) + , _stepValue(1) + , _value(value) + , _printLen(0) + , _suffix(suffix) +{ +} + +IntField::IntField(Form &form, const String &label, int minValue, int maxValue, int stepValue, int value, const String &suffix) + : Field(form, label) + , _minValue(minValue) + , _maxValue(maxValue) + , _stepValue(stepValue) + , _value(value) + , _printLen(0) + , _suffix(suffix) +{ +} + +int IntField::dispatch(int event) +{ + if (event == LCD_BUTTON_UP) { + setValue(_value + _stepValue); + return FORM_CHANGED; + } else if (event == LCD_BUTTON_DOWN) { + setValue(_value - _stepValue); + return FORM_CHANGED; + } + return -1; +} + +void IntField::enterField(bool reverse) +{ + Field::enterField(reverse); + printValue(); +} + +void IntField::setValue(int value) +{ + if (value < _minValue) + value = _minValue; + else if (value > _maxValue) + value = _maxValue; + if (value != _value) { + _value = value; + if (isCurrent()) + printValue(); + } +} + +void IntField::setSuffix(const String &suffix) +{ + _suffix = suffix; + if (isCurrent()) + printValue(); +} + +void IntField::printValue() +{ + String str(_value); + if (_suffix.length()) + str += _suffix; + lcd()->setCursor(0, 1); + lcd()->print(str); + unsigned int len = str.length(); + while (len++ < _printLen) + lcd()->write(' '); + _printLen = str.length(); +} diff --git a/libraries/FreetronicsLCD/IntField.h b/libraries/FreetronicsLCD/IntField.h new file mode 100644 index 00000000..5747c91c --- /dev/null +++ b/libraries/FreetronicsLCD/IntField.h @@ -0,0 +1,44 @@ +#ifndef IntField_h +#define IntField_h + +#include "Field.h" + +class IntField : public Field { +public: + explicit IntField(const String &label); + IntField(Form &form, const String &label); + IntField(Form &form, const String &label, int minValue, int maxValue, int value); + IntField(Form &form, const String &label, int minValue, int maxValue, int value, const String &suffix); + IntField(Form &form, const String &label, int minValue, int maxValue, int stepValue, int value, const String &suffix); + + int dispatch(int event); + + void enterField(bool reverse); + + int minValue() const { return _minValue; } + void setMinValue(int value) { _minValue = value; } + + int maxValue() const { return _maxValue; } + void setMaxValue(int value) { _maxValue = value; } + + int stepValue() const { return _stepValue; } + void setStepValue(int value) { _stepValue = value; } + + int value() const { return _value; } + void setValue(int value); + + String suffix() const { return _suffix; } + void setSuffix(const String &suffix); + +private: + int _minValue; + int _maxValue; + int _stepValue; + int _value; + int _printLen; + String _suffix; + + void printValue(); +}; + +#endif diff --git a/libraries/FreetronicsLCD/TextField.cpp b/libraries/FreetronicsLCD/TextField.cpp new file mode 100644 index 00000000..0fd5c417 --- /dev/null +++ b/libraries/FreetronicsLCD/TextField.cpp @@ -0,0 +1,38 @@ +#include "TextField.h" + +TextField::TextField(const String &label) + : Field(label) +{ +} + +TextField::TextField(Form &form, const String &label) + : Field(form, label) +{ +} + +TextField::TextField(Form &form, const String &label, const String &value) + : Field(form, label) + , _value(value) +{ +} + +void TextField::enterField(bool reverse) +{ + Field::enterField(reverse); + lcd()->print(_value); +} + +void TextField::setValue(const String &value) +{ + if (isCurrent()) { + unsigned int prevLen = _value.length(); + unsigned int newLen = value.length(); + _value = value; + lcd()->setCursor(0, 1); + lcd()->print(value); + while (newLen++ < prevLen) + lcd()->write(' '); + } else { + _value = value; + } +} diff --git a/libraries/FreetronicsLCD/TextField.h b/libraries/FreetronicsLCD/TextField.h new file mode 100644 index 00000000..6e9e862a --- /dev/null +++ b/libraries/FreetronicsLCD/TextField.h @@ -0,0 +1,21 @@ +#ifndef TextField_h +#define TextField_h + +#include "Field.h" + +class TextField : public Field { +public: + explicit TextField(const String &label); + TextField(Form &form, const String &label); + TextField(Form &form, const String &label, const String &value); + + void enterField(bool reverse); + + String value() const { return _value; } + void setValue(const String &value); + +private: + String _value; +}; + +#endif diff --git a/libraries/FreetronicsLCD/TimeField.cpp b/libraries/FreetronicsLCD/TimeField.cpp new file mode 100644 index 00000000..9810fc5d --- /dev/null +++ b/libraries/FreetronicsLCD/TimeField.cpp @@ -0,0 +1,209 @@ +#include "TimeField.h" + +#define EDIT_HOUR 0 +#define EDIT_MINUTE_TENS 1 +#define EDIT_MINUTE 2 +#define EDIT_SECOND_TENS 3 +#define EDIT_SECOND 4 + +TimeField::TimeField(const String &label) + : Field(label) + , _value(0) + , _maxHours(24) + , _printLen(0) + , _readOnly(false) + , editField(EDIT_HOUR) +{ +} + +TimeField::TimeField(Form &form, const String &label) + : Field(form, label) + , _value(0) + , _maxHours(24) + , _printLen(0) + , _readOnly(false) + , editField(EDIT_HOUR) +{ +} + +TimeField::TimeField(Form &form, const String &label, int maxHours, bool readOnly) + : Field(form, label) + , _value(0) + , _maxHours(maxHours) + , _printLen(0) + , _readOnly(readOnly) + , editField(EDIT_HOUR) +{ +} + +int TimeField::dispatch(int event) +{ + unsigned long newValue; + if (_readOnly) + return -1; + if (event == LCD_BUTTON_UP) { + newValue = _value; + if (editField == EDIT_HOUR) { + newValue += 60 * 60; + } else if (editField == EDIT_MINUTE_TENS) { + if (((newValue / 60) % 60) >= 50) + newValue -= 50 * 60; + else + newValue += 10 * 60; + } else if (editField == EDIT_MINUTE) { + if (((newValue / 60) % 60) == 59) + newValue -= 59 * 60; + else + newValue += 60; + } else if (editField == EDIT_SECOND_TENS) { + if ((newValue % 60) >= 50) + newValue -= 50; + else + newValue += 10; + } else { + if ((newValue % 60) == 59) + newValue -= 59; + else + newValue += 1; + } + setValue(newValue); + return FORM_CHANGED; + } else if (event == LCD_BUTTON_DOWN) { + newValue = _value; + if (editField == EDIT_HOUR) { + if (newValue < 60 * 60) + newValue += ((unsigned long)(_maxHours - 1)) * 60 * 60; + else + newValue -= 60 * 60; + } else if (editField == EDIT_MINUTE_TENS) { + if (((newValue / 60) % 60) < 10) + newValue += 50 * 60; + else + newValue -= 10 * 60; + } else if (editField == EDIT_MINUTE) { + if (((newValue / 60) % 60) == 0) + newValue += 59 * 60; + else + newValue -= 60; + } else if (editField == EDIT_SECOND_TENS) { + if ((newValue % 60) < 10) + newValue += 50; + else + newValue -= 10; + } else { + if ((newValue % 60) == 0) + newValue += 59; + else + newValue -= 1; + } + setValue(newValue); + return FORM_CHANGED; + } else if (event == LCD_BUTTON_LEFT) { + if (editField != EDIT_HOUR) { + --editField; + printTime(); + return 0; + } + } else if (event == LCD_BUTTON_RIGHT) { + if (editField != EDIT_SECOND) { + ++editField; + printTime(); + return 0; + } + } + return -1; +} + +void TimeField::enterField(bool reverse) +{ + Field::enterField(reverse); + if (reverse) + editField = EDIT_SECOND; + else + editField = EDIT_HOUR; + printTime(); + if (!_readOnly) + lcd()->cursor(); +} + +void TimeField::exitField() +{ + if (!_readOnly) + lcd()->noCursor(); + Field::exitField(); +} + +void TimeField::setValue(unsigned long value) +{ + unsigned long maxSecs = ((unsigned long)_maxHours) * 60 * 60; + value %= maxSecs; + if (value != _value) { + _value = value; + if (isCurrent()) + printTime(); + } +} + +void TimeField::setReadOnly(bool value) +{ + if (_readOnly != value) { + _readOnly = value; + printTime(); + if (isCurrent()) { + if (value) + lcd()->cursor(); + else + lcd()->noCursor(); + } + } +} + +void TimeField::printTime() +{ + lcd()->setCursor(0, 1); + int col = printField(_value / (60 * 60)); + int hourCol = col - 1; + lcd()->write(':'); + ++col; + col += printField((_value / 60) % 60); + int minuteCol = col - 1; + lcd()->write(':'); + ++col; + col += printField(_value % 60); + int secondCol = col - 1; + int tempCol = col; + while (tempCol++ < _printLen) + lcd()->write(' '); + _printLen = col; + if (!_readOnly) { + if (editField == EDIT_HOUR) + lcd()->setCursor(hourCol, 1); + else if (editField == EDIT_MINUTE_TENS) + lcd()->setCursor(minuteCol - 1, 1); + else if (editField == EDIT_MINUTE) + lcd()->setCursor(minuteCol, 1); + else if (editField == EDIT_SECOND_TENS) + lcd()->setCursor(secondCol - 1, 1); + else + lcd()->setCursor(secondCol, 1); + } +} + +int TimeField::printField(unsigned long value) +{ + if (value < 100) { + lcd()->write('0' + (int)(value / 10)); + lcd()->write('0' + (int)(value % 10)); + return 2; + } + unsigned long divisor = 100; + while ((value / divisor) >= 10) + divisor *= 10; + int digits = 0; + while (divisor > 0) { + lcd()->write('0' + (int)((value / divisor) % 10)); + divisor /= 10; + ++digits; + } + return digits; +} diff --git a/libraries/FreetronicsLCD/TimeField.h b/libraries/FreetronicsLCD/TimeField.h new file mode 100644 index 00000000..5f059c0d --- /dev/null +++ b/libraries/FreetronicsLCD/TimeField.h @@ -0,0 +1,40 @@ +#ifndef TimeField_h +#define TimeField_h + +#include "Field.h" + +#define TIMEFIELD_READ_ONLY true +#define TIMEFIELD_READ_WRITE false + +class TimeField : public Field { +public: + explicit TimeField(const String &label); + TimeField(Form &form, const String &label); + TimeField(Form &form, const String &label, int maxHours, bool readOnly); + + int dispatch(int event); + + void enterField(bool reverse); + void exitField(); + + unsigned long value() const { return _value; } + void setValue(unsigned long value); + + int maxHours() const { return _maxHours; } + void setMaxHours(int maxHours) { _maxHours = maxHours; } + + bool isReadOnly() const { return _readOnly; } + void setReadOnly(bool value); + +private: + unsigned long _value; + int _maxHours; + int _printLen; + bool _readOnly; + uint8_t editField; + + void printTime(); + int printField(unsigned long value); +}; + +#endif diff --git a/libraries/FreetronicsLCD/examples/Form/Form.pde b/libraries/FreetronicsLCD/examples/Form/Form.pde new file mode 100644 index 00000000..49f984fd --- /dev/null +++ b/libraries/FreetronicsLCD/examples/Form/Form.pde @@ -0,0 +1,60 @@ +/* +This example demonstrates how to use the Form and Field classes from the +FreetronicsLCD library to provide a simple UI on the 16x2 LCD display. +*/ + +// include the library code: +#include +#include +#include +#include +#include +#include + +// Initialize the LCD +FreetronicsLCD lcd; + +// Note: if you are using the USBDroid and have reassigned pin D9 on the LCD shield to some +// other pin (e.g. A1), then you will need to initialize the shield with something like: +// FreetronicsLCD lcd(A1); +// See also: http://www.freetronics.com/pages/combining-the-lcd-keypad-shield-and-the-usbdroid + +// Create the main form and its fields. +Form mainForm(lcd); +TextField welcomeField(mainForm, "Form example", "v1.0"); +TimeField timeField(mainForm, "Time since reset", 24, TIMEFIELD_READ_ONLY); +IntField volumeField(mainForm, "Volume", 0, 100, 5, 85, "%"); +BoolField ledField(mainForm, "Status LED", "On", "Off", true); +TimeField durationField(mainForm, "Timer duration", 24, TIMEFIELD_READ_WRITE); + +#define STATUS_LED 13 + +void setup() { + // Status LED initially on. + pinMode(STATUS_LED, OUTPUT); + digitalWrite(STATUS_LED, HIGH); + + // Enable the screen saver, which will automatically blank the screen after 10 seconds. + // The screen will wake up again when a button is pressed or lcd.display() is called. + lcd.enableScreenSaver(); + + // Show the main form for the first time. + mainForm.show(); +} + +void loop() { + // Update the number of seconds since reset: + timeField.setValue(millis() / 1000); + + // Dispatch button events to the main form. + int button = lcd.getButton(); + if (mainForm.dispatch(button) == FORM_CHANGED) { + if (mainForm.isCurrent(ledField)) { + if (ledField.value()) + digitalWrite(STATUS_LED, HIGH); + else + digitalWrite(STATUS_LED, LOW); + } + } +} + diff --git a/libraries/FreetronicsLCD/keywords.txt b/libraries/FreetronicsLCD/keywords.txt index 49217427..5b761ffd 100644 --- a/libraries/FreetronicsLCD/keywords.txt +++ b/libraries/FreetronicsLCD/keywords.txt @@ -1,5 +1,21 @@ FreetronicsLCD KEYWORD1 +Form KEYWORD1 +Field KEYWORD1 +BoolField KEYWORD1 +IntField KEYWORD1 +TextField KEYWORD1 +TimeField KEYWORD1 + getButton KEYWORD2 enableScreenSaver KEYWORD2 disableScreenSaver KEYWORD2 isScreenSaved KEYWORD2 + +show KEYWORD2 +hide KEYWORD2 +dispatch KEYWORD2 +isCurrent KEYWORD2 + +setLabel KEYWORD2 +setValue KEYWORD2 +value KEYWORD2