diff --git a/examples/SetNameAndID/SetNameAndID.ino b/examples/SetNameAndID/SetNameAndID.ino index 8b4d131..53cf81d 100644 --- a/examples/SetNameAndID/SetNameAndID.ino +++ b/examples/SetNameAndID/SetNameAndID.ino @@ -14,7 +14,7 @@ ---------------------------------------------------------------------------- */ -// Version 1.0 +// Version 2.0 /* ------------------------------------------------------------------------------ @@ -61,14 +61,20 @@ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // All the constant stings const char StrName[] PROGMEM = "NAME"; const char StrID[] PROGMEM = "ID"; +const char StrYes[] PROGMEM = "YES"; +const char StrNo[] PROGMEM = "NO"; const char StrSaveQ[] PROGMEM = "SAVE?"; +const char StrSaved[] PROGMEM = "SAVED"; +const char StrShowNameQ1[] PROGMEM = "Show Unit Name"; +const char StrShowNameQ2[] PROGMEM = "on logo screen?"; const char StrBtnChangeName[] PROGMEM = "UP:change Unit Name"; const char StrBtnChangeID[] PROGMEM = "DOWN:change Unit ID"; +const char StrBtnShowName[] PROGMEM = "LEFT:set \"show name\""; const char StrBtnMenu[] PROGMEM = "A:menu"; const char StrBtnSave[] PROGMEM = "B:save"; const char StrBtnYes[] PROGMEM = "A:yes"; const char StrBtnNo[] PROGMEM = "B:no"; -const char StrBtnLogo[] PROGMEM = "LEFT:show boot logo"; +const char StrBtnTestLogo[] PROGMEM = "DOWN:test boot logo"; const char StrHex[] PROGMEM = "hex"; const char StrDecimal[] PROGMEM = "decimal"; @@ -91,8 +97,8 @@ const char StrDecimal[] PROGMEM = "decimal"; #define MENU_ID_DECIMAL_X (centerStrLen(5) + (WIDTH / 4)) #define MENU_ID_Y (MENU_HEADINGS_Y + CHAR_HEIGHT + 1) -#define MENU_BTN_LOGO_X 0 -#define MENU_BTN_LOGO_Y 56 +#define MENU_BTN_SHOW_NAME_X 0 +#define MENU_BTN_SHOW_NAME_Y 56 #define NAME_TITLE_X centerStr_P(StrName) @@ -151,13 +157,32 @@ const char StrDecimal[] PROGMEM = "decimal"; #define ID_SAVE_X (ID_SAVE_Q_X + ((strlen_P(StrSaveQ) * CHAR_WIDTH) + CHAR_WIDTH)) #define ID_SAVE_Y (ID_LARGE_Y + 1) +#define SHOW_NAME_BTN_MENU_X 0 +#define SHOW_NAME_BTN_MENU_Y 0 +#define SHOW_NAME_BTN_SAVE_X rightStr_P(StrBtnSave) +#define SHOW_NAME_BTN_SAVE_Y SHOW_NAME_BTN_MENU_Y +#define SHOW_NAME_Q_1_X centerStr_P(StrShowNameQ1) +#define SHOW_NAME_Q_1_Y 12 +#define SHOW_NAME_Q_2_X centerStr_P(StrShowNameQ2) +#define SHOW_NAME_Q_2_Y (SHOW_NAME_Q_1_Y + 8) +#define SHOW_NAME_YES_X ((WIDTH / 2) - ((strlen_P(StrYes) + 1) * CHAR_WIDTH * 2)) +#define SHOW_NAME_YES_Y 34 +#define SHOW_NAME_NO_X ((WIDTH / 2) + (CHAR_WIDTH * 2)) +#define SHOW_NAME_NO_Y SHOW_NAME_YES_Y +#define SHOW_NAME_TEST_X 0 +#define SHOW_NAME_TEST_Y 56 +#define SHOW_NAME_SAVED_X centerStr2_P(StrSaved) +#define SHOW_NAME_SAVED_Y ((HEIGHT / 2) - CHAR_HEIGHT) + // Calculation of the number of frames to wait before button auto-repeat starts #define DELAY_FRAMES (REPEAT_DELAY / (1000 / FRAME_RATE)) // The Arduino "magic" has trouble creating prototypes for functions called // by pointers, so they're declared here manually -void stateMain(), stateName(), stateID(), stateSaveName(), stateSaveID(); -void screenMain(), screenName(), screenID(), screenSaveName(), screenSaveID(); +void stateMain(), stateName(), stateID(), stateShowName(); +void stateSaveName(), stateSaveID(); +void screenMain(), screenName(), screenID(), screenShowName(); +void screenSaveName(), screenSaveID(); Arduboy2 arduboy; @@ -167,11 +192,14 @@ byte nameIndex; uint16_t unitID; byte idIndex; +boolean showNameFlag; + // Assign numbers for each state/screen enum State : byte { sMain, sName, sID, + sShowName, sSaveName, sSaveID, sMAX = sSaveID @@ -184,6 +212,7 @@ void (*stateFunc[sMAX + 1])() = { stateMain, stateName, stateID, + stateShowName, stateSaveName, stateSaveID }; @@ -193,6 +222,7 @@ void (*screenFunc[sMAX + 1])() = { screenMain, screenName, screenID, + screenShowName, screenSaveName, screenSaveID }; @@ -246,9 +276,7 @@ void stateMain() { setState(sID); } else if (arduboy.justPressed(LEFT_BUTTON)) { - arduboy.bootLogo(); - delay(1000); - setState(sMain); + setState(sShowName); } } @@ -322,6 +350,29 @@ void stateID() { } } +// STATE: Set "Show Unit Name" flag +void stateShowName() { + if (arduboy.justPressed(RIGHT_BUTTON)) { + showNameToggle(); + } + else if (arduboy.justPressed(LEFT_BUTTON)) { + showNameToggle(); + } + else if (arduboy.justPressed(A_BUTTON)) { + setState(sMain); + } + else if (arduboy.justPressed(B_BUTTON)) { + saveShowName(); + setState(sShowName); + } + else if (arduboy.justPressed(DOWN_BUTTON)) { + showNameFlag = arduboy.readShowUnitNameFlag(); + arduboy.bootLogo(); + delay(1000); + setState(sShowName); + } +} + // STATE: Prompt to save the unit name void stateSaveName() { if (arduboy.justPressed(A_BUTTON)) { @@ -367,7 +418,7 @@ void screenMain() { printIDHex(MENU_ID_HEX_X, MENU_ID_Y); printIDDecimal(MENU_ID_DECIMAL_X, MENU_ID_Y); - printStr_P(MENU_BTN_LOGO_X, MENU_BTN_LOGO_Y, StrBtnLogo); + printStr_P(MENU_BTN_SHOW_NAME_X, MENU_BTN_SHOW_NAME_Y, StrBtnShowName); } // DISPLAY: Change unit name @@ -389,6 +440,20 @@ void screenID() { printIDCursors(); } +// DISPLAY: Set "Show Unit Name" flag +void screenShowName() { + printStr_P(SHOW_NAME_BTN_MENU_X, SHOW_NAME_BTN_MENU_Y, StrBtnMenu); + printStr_P(SHOW_NAME_BTN_SAVE_X, SHOW_NAME_BTN_SAVE_Y, StrBtnSave); + printStr_P(SHOW_NAME_Q_1_X, SHOW_NAME_Q_1_Y, StrShowNameQ1); + printStr_P(SHOW_NAME_Q_2_X, SHOW_NAME_Q_2_Y, StrShowNameQ2); + arduboy.setTextSize(2); + printStr_P(SHOW_NAME_YES_X, SHOW_NAME_YES_Y, StrYes); + printStr_P(SHOW_NAME_NO_X, SHOW_NAME_NO_Y, StrNo); + arduboy.setTextSize(1); + printShowNameCursor(); + printStr_P(SHOW_NAME_TEST_X, SHOW_NAME_TEST_Y, StrBtnTestLogo); +} + // DISPLAY: Prompt to save the unit name void screenSaveName() { printNameScreenCommon(); @@ -407,6 +472,21 @@ void screenSaveID() { printIDLarge(ID_SAVE_X, ID_SAVE_Y); } +// Save the "Show Unit Name" flag and overlay the "SAVED" message on the screen +void saveShowName() { + arduboy.writeShowUnitNameFlag(showNameFlag); + arduboy.fillRect(SHOW_NAME_SAVED_X - 4, SHOW_NAME_SAVED_Y - 4, + strlen_P(StrSaved) * CHAR_WIDTH * 2 + 6, CHAR_HEIGHT * 2 + 6); + arduboy.setTextColor(BLACK); + arduboy.setTextBackground(WHITE); + arduboy.setTextSize(2); + printStr_P(SHOW_NAME_SAVED_X, SHOW_NAME_SAVED_Y, StrSaved); + arduboy.setTextSize(1); + arduboy.setTextColor(WHITE); + arduboy.setTextBackground(BLACK); + arduboy.display(); + delay(1000); +} // --------------------- Printing Functions ------------------------------ @@ -458,6 +538,18 @@ void printIDCursors() { ID_BINARY_Y + CHAR_HEIGHT + 1, CHAR_WIDTH * 4 - 1); } +// Print the current "Show Unit Name" cursor +void printShowNameCursor() { + if (showNameFlag) { + arduboy.fillRect(SHOW_NAME_YES_X, SHOW_NAME_YES_Y + (CHAR_HEIGHT * 2), + (strlen_P(StrYes) * CHAR_WIDTH - 1) * 2, 2); + } + else { + arduboy.fillRect(SHOW_NAME_NO_X, SHOW_NAME_NO_Y + (CHAR_HEIGHT * 2), + (strlen_P(StrNo) * CHAR_WIDTH - 1) * 2, 2); + } +} + // Print the unit name in normal size including an extent underline // at the given location void printName(int x, int y) { @@ -621,11 +713,12 @@ void printBinaryNybble(int x, int y, byte val) { // ---------------- Control and Utility Functions ------------------------ -// Get the current unit name and ID from EEPROM +// Get the current unit name and ID, and the "Show Unit Name" flag, from EEPROM void readEEPROM() { memset(unitName, 0, sizeof(unitName)); arduboy.readUnitName(unitName); unitID = arduboy.readUnitID(); + showNameFlag = arduboy.readShowUnitNameFlag(); } // Increment the name character at the cursor position @@ -701,6 +794,12 @@ void idCursorLeft() { drawScreen(); } +// Toggle the "Show Unit Name" selection +void showNameToggle() { + showNameFlag = !showNameFlag; + drawScreen(); +} + // Start the button auto-repeat delay void startButtonDelay() { delayCount = DELAY_FRAMES; @@ -723,6 +822,12 @@ int centerStr_P(const char* str) { return (WIDTH / 2) - (strlen_P(str) * CHAR_WIDTH / 2); } +// Calculate the X coordinate to center a size 2 string located in +// program memory +int centerStr2_P(const char* str) { + return (WIDTH / 2) - (strlen_P(str) * CHAR_WIDTH); +} + // Calculate the X coordinate to right justify a string in program memory int rightStr_P(const char* str) { return WIDTH - (strlen_P(str) * CHAR_WIDTH) + 1; diff --git a/keywords.txt b/keywords.txt index 0f843bd..620b25e 100644 --- a/keywords.txt +++ b/keywords.txt @@ -66,6 +66,7 @@ paint8Pixels KEYWORD2 paintScreen KEYWORD2 pollButtons KEYWORD2 pressed KEYWORD2 +readShowUnitNameFlag KEYWORD2 readUnitID KEYWORD2 readUnitName KEYWORD2 safeMode KEYWORD2 @@ -81,6 +82,7 @@ SPItransfer KEYWORD2 systemButtons KEYWORD2 toggle KEYWORD2 width KEYWORD2 +writeShowUnitNameFlag KEYWORD2 writeUnitID KEYWORD2 writeUnitName KEYWORD2 diff --git a/src/Arduboy2.cpp b/src/Arduboy2.cpp index d5fad59..71e0088 100644 --- a/src/Arduboy2.cpp +++ b/src/Arduboy2.cpp @@ -983,6 +983,19 @@ void Arduboy2Base::writeUnitName(char* name) } } +bool Arduboy2Base::readShowUnitNameFlag() +{ + return (EEPROM.read(EEPROM_SYS_FLAGS) & SYS_FLAG_UNAME_MASK); +} + +void Arduboy2Base::writeShowUnitNameFlag(bool val) +{ + uint8_t flags = EEPROM.read(EEPROM_SYS_FLAGS); + + bitWrite(flags, SYS_FLAG_UNAME, val); + EEPROM.update(EEPROM_SYS_FLAGS, flags); +} + void Arduboy2Base::swap(int16_t& a, int16_t& b) { int16_t temp = a; @@ -1051,7 +1064,14 @@ void Arduboy2::bootLogoText() void Arduboy2::bootLogoExtra() { - uint8_t c = EEPROM.read(EEPROM_UNIT_NAME); + uint8_t c; + + if (!readShowUnitNameFlag()) + { + return; + } + + c = EEPROM.read(EEPROM_UNIT_NAME); if (c != 0xFF && c != 0x00) { @@ -1063,10 +1083,11 @@ void Arduboy2::bootLogoExtra() { write(c); c = EEPROM.read(++i); - } while (i < EEPROM_UNIT_NAME + ARDUBOY_UNIT_NAME_LEN); + } + while (i < EEPROM_UNIT_NAME + ARDUBOY_UNIT_NAME_LEN); display(); - delay(1500); + delay(1000); } } diff --git a/src/Arduboy2.h b/src/Arduboy2.h index c53fb4d..8bf8c79 100644 --- a/src/Arduboy2.h +++ b/src/Arduboy2.h @@ -38,13 +38,17 @@ #define ARDUBOY_UNIT_NAME_LEN 6 /**< The maximum length of the unit name string. */ #define EEPROM_VERSION 0 -#define EEPROM_BRIGHTNESS 1 +#define EEPROM_SYS_FLAGS 1 #define EEPROM_AUDIO_ON_OFF 2 #define EEPROM_UNIT_ID 8 // A uint16_t binary unit ID #define EEPROM_UNIT_NAME 10 // An up to 6 character unit name. Cannot contain // 0x00 or 0xFF. Lengths less than 6 are padded // with 0x00 +// EEPROM_SYS_FLAGS values +#define SYS_FLAG_UNAME 0 // Display the unit name on the logo screen +#define SYS_FLAG_UNAME_MASK _BV(SYS_FLAG_UNAME) + /** \brief * Start of EEPROM storage space for sketches. * @@ -959,6 +963,38 @@ class Arduboy2Base : public Arduboy2Core */ void writeUnitName(char* name); + /** \brief + * Read the "Show Unit Name" flag in system EEPROM. + * + * \return `true` if the flag is set to indicate that the unit name should + * be displayed. `false` if the flag is set to not display the unit name. + * + * \details + * The "Show Unit Name" flag is used to determine whether the system + * unit name is to be displayed at the end of the boot logo sequence. + * This function returns the value of this flag. + * + * \see writeShowUnitNameFlag() writeUnitName() readUnitName() + * Arduboy2::bootLogoExtra() + */ + bool readShowUnitNameFlag(); + + /** \brief + * Write the "Show Unit Name" flag in system EEPROM. + * + * \param val If `true` the flag is set to indicate that the unit name should + * be displayed. If `false` the flag is set to not display the unit name. + * + * \details + * The "Show Unit Name" flag is used to determine whether the system + * unit name is to be displayed at the end of the boot logo sequence. + * This function allows the flag to be saved with the desired value. + * + * \see readShowUnitNameFlag() writeUnitName() readUnitName() + * Arduboy2::bootLogoExtra() + */ + void writeShowUnitNameFlag(bool val); + /** \brief * A counter which is incremented once per frame. * @@ -1113,11 +1149,14 @@ class Arduboy2 : public Print, public Arduboy2Base * the bottom of the screen. This function pauses for a short time to allow * the name to be seen. * + * The name is not displayed if the "Show Unit Name" flag is not set. + * * \note * This function would not normally be called directly from within a sketch * itself. * - * \see readUnitName() writeUnitName() bootLogo() bootLogoText() begin() + * \see readUnitName() writeUnitName() bootLogo() bootLogoText() + * writeShowUnitNameFlag() begin() */ virtual void bootLogoExtra();