mirror of https://github.com/MLXXXp/Arduboy2.git
Add read/write EEPROM unit name and ID functions
Also: - Changes to show the unit name on the boot logo screen - Added new example sketch SetNameAndID to allow setting the name and ID - Updated the LICENSE.txt file and made changes to include it in the Doxygen generated documentation
This commit is contained in:
parent
8125862bfe
commit
2fede9cb86
16
LICENSE.txt
16
LICENSE.txt
|
@ -1,10 +1,14 @@
|
||||||
|
/**
|
||||||
|
\page licenses Software License Agreements
|
||||||
|
\verbatim
|
||||||
|
|
||||||
Software License Agreements
|
Software License Agreements
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Licensed under the BSD 3-clause license:
|
Licensed under the BSD 3-clause license:
|
||||||
|
|
||||||
Arduboy2 library:
|
Arduboy2 library:
|
||||||
Copyright (c) 2016, Scott Allen
|
Copyright (c) 2017, Scott Allen
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
The Arduboy2 library was forked from the Arduboy library:
|
The Arduboy2 library was forked from the Arduboy library:
|
||||||
|
@ -19,6 +23,10 @@ https://github.com/adafruit/Adafruit_SSD1306
|
||||||
Copyright (c) 2012, Adafruit Industries
|
Copyright (c) 2012, Adafruit Industries
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
|
SetNameAndID example sketch:
|
||||||
|
Copyright (c) 2017, Scott Allen
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
modification, are permitted provided that the following conditions are met:
|
modification, are permitted provided that the following conditions are met:
|
||||||
1. Redistributions of source code must retain the above copyright
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
@ -44,8 +52,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Licensed under the BSD 2-clause license:
|
Licensed under the BSD 2-clause license:
|
||||||
|
|
||||||
Portions of the Arduboy library, and thus the Arduboy2 library, based on
|
Portions of the Arduboy library, and thus portions of the Arduboy2 library,
|
||||||
the Adafruit-GFX library:
|
based on the Adafruit-GFX library:
|
||||||
https://github.com/adafruit/Adafruit-GFX-Library
|
https://github.com/adafruit/Adafruit-GFX-Library
|
||||||
Copyright (c) 2012 Adafruit Industries
|
Copyright (c) 2012 Adafruit Industries
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
@ -127,3 +135,5 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
Lesser General Public License for more details.
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
===============================================================================
|
===============================================================================
|
||||||
|
\endverbatim
|
||||||
|
*/
|
||||||
|
|
|
@ -50,7 +50,9 @@ At the start of the sketch, the **ARDUBOY** logo scrolls down from the top of th
|
||||||
|
|
||||||
The RGB LED lights red then green then blue while the logo is scrolling. (If your Arduboy is one of those that has the RGB LED installed incorrectly, then it will light blue then off then red). This pattern is different than with Arduboy V1.1, which lit and then faded red (or blue if the LED is incorrectly installed).
|
The RGB LED lights red then green then blue while the logo is scrolling. (If your Arduboy is one of those that has the RGB LED installed incorrectly, then it will light blue then off then red). This pattern is different than with Arduboy V1.1, which lit and then faded red (or blue if the LED is incorrectly installed).
|
||||||
|
|
||||||
Once the logo display completes, the sketch continues.
|
A user settable *unit name* of up to 6 characters can be saved in system EEPROM memory. If set, this name will be briefly displayed at the bottom of the boot logo screen, after the logo stops scrolling down. This feature is only available if the *Arduboy2* class is used, not the *Arduboy2Base* class. This is because it requires the text display functions, which are only available in the *Arduboy2* class.
|
||||||
|
|
||||||
|
Once the logo display sequence completes, the sketch continues.
|
||||||
|
|
||||||
### "Flashlight" mode
|
### "Flashlight" mode
|
||||||
|
|
||||||
|
@ -188,9 +190,9 @@ void Arduboy2Base::begin()
|
||||||
// check for and handle buttons held during start up for system control
|
// check for and handle buttons held during start up for system control
|
||||||
systemButtons();
|
systemButtons();
|
||||||
|
|
||||||
bootLogo();
|
|
||||||
|
|
||||||
audio.begin();
|
audio.begin();
|
||||||
|
|
||||||
|
bootLogo();
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,730 @@
|
||||||
|
// =======================================================================
|
||||||
|
// Manage an Arduboy's unit name and ID stored in the system EEPROM area
|
||||||
|
// =======================================================================
|
||||||
|
|
||||||
|
/*
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
The area in EEPROM reserved by the library for global system use includes
|
||||||
|
space to store a Unit Name and Unit ID. These can be read by sketches,
|
||||||
|
using the readUnitName() and readUnitID() functions. Also, the Arduboy2
|
||||||
|
class will display the Unit Name at the end of the boot logo sequence,
|
||||||
|
if possible, during start up.
|
||||||
|
|
||||||
|
This sketch allows the Unit Name and Unit ID to be set or changed and saved.
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Version 1.0
|
||||||
|
|
||||||
|
/*
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
Copyright (c) 2017, Scott Allen
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the copyright holders nor the names of its contributors
|
||||||
|
may be used to endorse or promote products derived from this software
|
||||||
|
without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS "AS IS" AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||||
|
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||||
|
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Arduboy2.h>
|
||||||
|
|
||||||
|
// The frame rate determines the button auto-repeat rate for unit name entry
|
||||||
|
#define FRAME_RATE 10
|
||||||
|
|
||||||
|
// The unit ID auto-repeat rate is slowed, compared to the unit name rate, by
|
||||||
|
// repeating only once per the defined number of frames
|
||||||
|
#define ID_REPEAT_FRAMES 3
|
||||||
|
|
||||||
|
// Delay time before button auto-repeat starts, in milliseconds
|
||||||
|
#define REPEAT_DELAY 700
|
||||||
|
|
||||||
|
// All the constant stings
|
||||||
|
const char StrName[] PROGMEM = "NAME";
|
||||||
|
const char StrID[] PROGMEM = "ID";
|
||||||
|
const char StrSaveQ[] PROGMEM = "SAVE?";
|
||||||
|
const char StrBtnChangeName[] PROGMEM = "UP:change Unit Name";
|
||||||
|
const char StrBtnChangeID[] PROGMEM = "DOWN:change Unit ID";
|
||||||
|
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 StrHex[] PROGMEM = "hex";
|
||||||
|
const char StrDecimal[] PROGMEM = "decimal";
|
||||||
|
|
||||||
|
#define CHAR_WIDTH 6
|
||||||
|
#define CHAR_HEIGHT 8
|
||||||
|
#define SMALL_SPACE 4 // The number of pixels for a small space between groups
|
||||||
|
|
||||||
|
// Defines for text and field locations
|
||||||
|
#define MENU_BTN_CHANGE_NAME_X 0
|
||||||
|
#define MENU_BTN_CHANGE_NAME_Y 0
|
||||||
|
#define MENU_NAME_X centerStrLen(ARDUBOY_UNIT_NAME_LEN)
|
||||||
|
#define MENU_NAME_Y (MENU_BTN_CHANGE_NAME_Y + CHAR_HEIGHT + 3)
|
||||||
|
|
||||||
|
#define MENU_BTN_CHANGE_ID_X 0
|
||||||
|
#define MENU_BTN_CHANGE_ID_Y 26
|
||||||
|
#define MENU_HEADING_HEX_X (centerStr_P(StrHex) - (WIDTH / 4))
|
||||||
|
#define MENU_HEADING_DECIMAL_X (centerStr_P(StrDecimal) + (WIDTH / 4))
|
||||||
|
#define MENU_HEADINGS_Y (MENU_BTN_CHANGE_ID_Y + CHAR_HEIGHT + 1)
|
||||||
|
#define MENU_ID_HEX_X (centerStrLen(5) - (WIDTH / 4))
|
||||||
|
#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 NAME_TITLE_X centerStr_P(StrName)
|
||||||
|
#define NAME_TITLE_Y 0
|
||||||
|
|
||||||
|
#define NAME_BTN_MENU_X 0
|
||||||
|
#define NAME_BTN_MENU_Y 0
|
||||||
|
#define NAME_BTN_SAVE_X rightStr_P(StrBtnSave)
|
||||||
|
#define NAME_BTN_SAVE_Y NAME_BTN_MENU_Y
|
||||||
|
|
||||||
|
#define NAME_LARGE_X centerStrLen(ARDUBOY_UNIT_NAME_LEN * 2)
|
||||||
|
#define NAME_LARGE_Y 11
|
||||||
|
|
||||||
|
#define NAME_HEX_X 0
|
||||||
|
#define NAME_HEX_Y 40
|
||||||
|
#define NAME_DECIMAL_X 0
|
||||||
|
#define NAME_DECIMAL_Y 54
|
||||||
|
|
||||||
|
#define NAME_BTN_YES_X 0
|
||||||
|
#define NAME_BTN_YES_Y 0
|
||||||
|
#define NAME_BTN_NO_X rightStr_P(StrBtnNo)
|
||||||
|
#define NAME_BTN_NO_Y NAME_BTN_YES_Y
|
||||||
|
|
||||||
|
#define NAME_SAVE_Q_X (centerStr_P(StrSaveQ) - ((6 * CHAR_WIDTH) + (CHAR_WIDTH / 2)))
|
||||||
|
#define NAME_SAVE_Q_Y (NAME_LARGE_Y + (CHAR_HEIGHT / 2) + 3)
|
||||||
|
#define NAME_SAVE_X (NAME_SAVE_Q_X + ((strlen_P(StrSaveQ) * CHAR_WIDTH) + CHAR_WIDTH))
|
||||||
|
#define NAME_SAVE_Y (NAME_LARGE_Y + 3)
|
||||||
|
|
||||||
|
|
||||||
|
#define ID_TITLE_X centerStr_P(StrID)
|
||||||
|
#define ID_TITLE_Y 0
|
||||||
|
|
||||||
|
#define ID_BTN_MENU_X 0
|
||||||
|
#define ID_BTN_MENU_Y 0
|
||||||
|
#define ID_BTN_SAVE_X rightStr_P(StrBtnSave)
|
||||||
|
#define ID_BTN_SAVE_Y ID_BTN_MENU_Y
|
||||||
|
|
||||||
|
#define ID_LARGE_X centerStrLen(5 * 2)
|
||||||
|
#define ID_LARGE_Y 13
|
||||||
|
|
||||||
|
#define ID_2_DECIMAL_X 12
|
||||||
|
#define ID_2_DECIMAL_Y 38
|
||||||
|
#define ID_DECIMAL_X (WIDTH - (CHAR_WIDTH * 5 + 12))
|
||||||
|
#define ID_DECIMAL_Y ID_2_DECIMAL_Y
|
||||||
|
|
||||||
|
#define ID_BINARY_X 0
|
||||||
|
#define ID_BINARY_Y 54
|
||||||
|
|
||||||
|
#define ID_BTN_YES_X 0
|
||||||
|
#define ID_BTN_YES_Y 0
|
||||||
|
#define ID_BTN_NO_X rightStr_P(StrBtnNo)
|
||||||
|
#define ID_BTN_NO_Y ID_BTN_YES_Y
|
||||||
|
|
||||||
|
#define ID_SAVE_Q_X (centerStr_P(StrSaveQ) - ((5 * CHAR_WIDTH) + (CHAR_WIDTH / 2)))
|
||||||
|
#define ID_SAVE_Q_Y (ID_LARGE_Y + (CHAR_HEIGHT / 2) + 1)
|
||||||
|
#define ID_SAVE_X (ID_SAVE_Q_X + ((strlen_P(StrSaveQ) * CHAR_WIDTH) + CHAR_WIDTH))
|
||||||
|
#define ID_SAVE_Y (ID_LARGE_Y + 1)
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
|
||||||
|
Arduboy2 arduboy;
|
||||||
|
|
||||||
|
char unitName[ARDUBOY_UNIT_NAME_LEN + 1];
|
||||||
|
byte nameIndex;
|
||||||
|
|
||||||
|
uint16_t unitID;
|
||||||
|
byte idIndex;
|
||||||
|
|
||||||
|
// Assign numbers for each state/screen
|
||||||
|
enum State : byte {
|
||||||
|
sMain,
|
||||||
|
sName,
|
||||||
|
sID,
|
||||||
|
sSaveName,
|
||||||
|
sSaveID,
|
||||||
|
sMAX = sSaveID
|
||||||
|
};
|
||||||
|
|
||||||
|
byte currentState;
|
||||||
|
|
||||||
|
// Function pointer array for button handling
|
||||||
|
void (*stateFunc[sMAX + 1])() = {
|
||||||
|
stateMain,
|
||||||
|
stateName,
|
||||||
|
stateID,
|
||||||
|
stateSaveName,
|
||||||
|
stateSaveID
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function pointer array for screen drawing
|
||||||
|
void (*screenFunc[sMAX + 1])() = {
|
||||||
|
screenMain,
|
||||||
|
screenName,
|
||||||
|
screenID,
|
||||||
|
screenSaveName,
|
||||||
|
screenSaveID
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned int delayCount = 0;
|
||||||
|
boolean repeating = false;
|
||||||
|
|
||||||
|
|
||||||
|
// ============================= SETUP ===================================
|
||||||
|
void setup() {
|
||||||
|
arduboy.begin();
|
||||||
|
arduboy.setFrameRate(FRAME_RATE);
|
||||||
|
setState(sMain);
|
||||||
|
}
|
||||||
|
// =======================================================================
|
||||||
|
|
||||||
|
|
||||||
|
// =========================== MAIN LOOP =================================
|
||||||
|
void loop() {
|
||||||
|
if (!arduboy.nextFrame()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
arduboy.pollButtons();
|
||||||
|
|
||||||
|
(*stateFunc[currentState])();
|
||||||
|
|
||||||
|
if ((delayCount != 0) && (--delayCount == 0)) {
|
||||||
|
repeating = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// =======================================================================
|
||||||
|
|
||||||
|
|
||||||
|
// ------------------------- Program States ------------------------------
|
||||||
|
|
||||||
|
// Set to the given state and display the screen for that state
|
||||||
|
// Can be called with the current state to update the current screen
|
||||||
|
void setState(byte newState) {
|
||||||
|
currentState = newState;
|
||||||
|
stopButtonRepeat();
|
||||||
|
drawScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
// STATE: Main selection screen
|
||||||
|
void stateMain() {
|
||||||
|
if (arduboy.justPressed(UP_BUTTON)) {
|
||||||
|
setState(sName);
|
||||||
|
}
|
||||||
|
else if (arduboy.justPressed(DOWN_BUTTON)) {
|
||||||
|
setState(sID);
|
||||||
|
}
|
||||||
|
else if (arduboy.justPressed(LEFT_BUTTON)) {
|
||||||
|
arduboy.bootLogo();
|
||||||
|
delay(1000);
|
||||||
|
setState(sMain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// STATE: Change unit name
|
||||||
|
void stateName() {
|
||||||
|
if (arduboy.justPressed(UP_BUTTON)) {
|
||||||
|
nameCharInc();
|
||||||
|
startButtonDelay();
|
||||||
|
}
|
||||||
|
else if (arduboy.justPressed(DOWN_BUTTON)) {
|
||||||
|
nameCharDec();
|
||||||
|
startButtonDelay();
|
||||||
|
}
|
||||||
|
else if (repeating && arduboy.pressed(UP_BUTTON)) {
|
||||||
|
nameCharInc();
|
||||||
|
}
|
||||||
|
else if (repeating && arduboy.pressed(DOWN_BUTTON)) {
|
||||||
|
nameCharDec();
|
||||||
|
}
|
||||||
|
else if (arduboy.justPressed(RIGHT_BUTTON)) {
|
||||||
|
nameCursorRight();
|
||||||
|
}
|
||||||
|
else if (arduboy.justPressed(LEFT_BUTTON)) {
|
||||||
|
nameCursorLeft();
|
||||||
|
}
|
||||||
|
else if (arduboy.justPressed(A_BUTTON)) {
|
||||||
|
setState(sMain);
|
||||||
|
}
|
||||||
|
else if (arduboy.justPressed(B_BUTTON)) {
|
||||||
|
setState(sSaveName);
|
||||||
|
}
|
||||||
|
else if (repeating) {
|
||||||
|
stopButtonRepeat();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// STATE: Change unit ID
|
||||||
|
void stateID() {
|
||||||
|
if (arduboy.justPressed(UP_BUTTON)) {
|
||||||
|
idDigitInc();
|
||||||
|
startButtonDelay();
|
||||||
|
}
|
||||||
|
else if (arduboy.justPressed(DOWN_BUTTON)) {
|
||||||
|
idDigitDec();
|
||||||
|
startButtonDelay();
|
||||||
|
}
|
||||||
|
else if (repeating && arduboy.pressed(UP_BUTTON)) {
|
||||||
|
if (arduboy.everyXFrames(ID_REPEAT_FRAMES)) {
|
||||||
|
idDigitInc();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (repeating && arduboy.pressed(DOWN_BUTTON)) {
|
||||||
|
if (arduboy.everyXFrames(ID_REPEAT_FRAMES)) {
|
||||||
|
idDigitDec();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (arduboy.justPressed(RIGHT_BUTTON)) {
|
||||||
|
idCursorRight();
|
||||||
|
}
|
||||||
|
else if (arduboy.justPressed(LEFT_BUTTON)) {
|
||||||
|
idCursorLeft();
|
||||||
|
}
|
||||||
|
else if (arduboy.justPressed(A_BUTTON)) {
|
||||||
|
setState(sMain);
|
||||||
|
}
|
||||||
|
else if (arduboy.justPressed(B_BUTTON)) {
|
||||||
|
setState(sSaveID);
|
||||||
|
}
|
||||||
|
else if (repeating) {
|
||||||
|
stopButtonRepeat();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// STATE: Prompt to save the unit name
|
||||||
|
void stateSaveName() {
|
||||||
|
if (arduboy.justPressed(A_BUTTON)) {
|
||||||
|
arduboy.writeUnitName(unitName);
|
||||||
|
setState(sMain);
|
||||||
|
}
|
||||||
|
else if (arduboy.justPressed(B_BUTTON)) {
|
||||||
|
setState(sName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// STATE: Prompt to save the unit ID
|
||||||
|
void stateSaveID() {
|
||||||
|
if (arduboy.justPressed(A_BUTTON)) {
|
||||||
|
arduboy.writeUnitID(unitID);
|
||||||
|
setState(sMain);
|
||||||
|
}
|
||||||
|
else if (arduboy.justPressed(B_BUTTON)) {
|
||||||
|
setState(sID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------- Screen Display ------------------------------
|
||||||
|
|
||||||
|
// Display the screen for the current state
|
||||||
|
void drawScreen() {
|
||||||
|
arduboy.clear();
|
||||||
|
(*screenFunc[currentState])();
|
||||||
|
arduboy.display();
|
||||||
|
}
|
||||||
|
|
||||||
|
// DISPLAY: Main screen
|
||||||
|
void screenMain() {
|
||||||
|
readEEPROM();
|
||||||
|
nameIndex = idIndex = 0;
|
||||||
|
|
||||||
|
printStr_P(MENU_BTN_CHANGE_NAME_X, MENU_BTN_CHANGE_NAME_Y, StrBtnChangeName);
|
||||||
|
printName(MENU_NAME_X, MENU_NAME_Y);
|
||||||
|
|
||||||
|
printStr_P(MENU_BTN_CHANGE_ID_X, MENU_BTN_CHANGE_ID_Y, StrBtnChangeID);
|
||||||
|
printStr_P(MENU_HEADING_HEX_X, MENU_HEADINGS_Y, StrHex);
|
||||||
|
printStr_P(MENU_HEADING_DECIMAL_X, MENU_HEADINGS_Y, StrDecimal);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// DISPLAY: Change unit name
|
||||||
|
void screenName() {
|
||||||
|
printNameScreenCommon();
|
||||||
|
printStr_P(NAME_BTN_MENU_X, NAME_BTN_MENU_Y, StrBtnMenu);
|
||||||
|
printStr_P(NAME_BTN_SAVE_X, NAME_BTN_SAVE_Y, StrBtnSave);
|
||||||
|
printNameLarge(NAME_LARGE_X, NAME_LARGE_Y);
|
||||||
|
printNameUnderline(NAME_LARGE_X, NAME_LARGE_Y);
|
||||||
|
printNameCursors();
|
||||||
|
}
|
||||||
|
|
||||||
|
// DISPLAY: Change unit ID
|
||||||
|
void screenID() {
|
||||||
|
printIDScreenCommon();
|
||||||
|
printStr_P(ID_BTN_MENU_X, ID_BTN_MENU_Y, StrBtnMenu);
|
||||||
|
printStr_P(ID_BTN_SAVE_X, ID_BTN_SAVE_Y, StrBtnSave);
|
||||||
|
printIDLarge(ID_LARGE_X, ID_LARGE_Y);
|
||||||
|
printIDCursors();
|
||||||
|
}
|
||||||
|
|
||||||
|
// DISPLAY: Prompt to save the unit name
|
||||||
|
void screenSaveName() {
|
||||||
|
printNameScreenCommon();
|
||||||
|
printStr_P(NAME_BTN_YES_X, NAME_BTN_YES_Y, StrBtnYes);
|
||||||
|
printStr_P(NAME_BTN_NO_X, NAME_BTN_NO_Y, StrBtnNo);
|
||||||
|
printSavePrompt(NAME_SAVE_Q_X, NAME_SAVE_Q_Y);
|
||||||
|
printNameLarge(NAME_SAVE_X, NAME_SAVE_Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// DISPLAY: Prompt to save the unit ID
|
||||||
|
void screenSaveID() {
|
||||||
|
printIDScreenCommon();
|
||||||
|
printStr_P(ID_BTN_YES_X, ID_BTN_YES_Y, StrBtnYes);
|
||||||
|
printStr_P(ID_BTN_NO_X, ID_BTN_NO_Y, StrBtnNo);
|
||||||
|
printSavePrompt(ID_SAVE_Q_X, ID_SAVE_Q_Y);
|
||||||
|
printIDLarge(ID_SAVE_X, ID_SAVE_Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// --------------------- Printing Functions ------------------------------
|
||||||
|
|
||||||
|
// Print the name entry screen common information
|
||||||
|
void printNameScreenCommon() {
|
||||||
|
printStr_P(NAME_TITLE_X, NAME_TITLE_Y, StrName);
|
||||||
|
printNameHex(NAME_HEX_X, NAME_HEX_Y);
|
||||||
|
printNameDecimal(NAME_DECIMAL_X, NAME_DECIMAL_Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print the name entry screen common information
|
||||||
|
void printIDScreenCommon() {
|
||||||
|
printStr_P(ID_TITLE_X, ID_TITLE_Y, StrID);
|
||||||
|
printIDDecimalBytes(ID_2_DECIMAL_X, ID_2_DECIMAL_Y);
|
||||||
|
printIDDecimal(ID_DECIMAL_X, ID_DECIMAL_Y);
|
||||||
|
printIDBinary(ID_BINARY_X, ID_BINARY_Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print the name screen cursors
|
||||||
|
void printNameCursors() {
|
||||||
|
arduboy.fillRect(NAME_LARGE_X + (nameIndex * CHAR_WIDTH * 2),
|
||||||
|
NAME_LARGE_Y + (CHAR_HEIGHT * 2) + 2,
|
||||||
|
(CHAR_WIDTH * 2) - 2, 2);
|
||||||
|
|
||||||
|
arduboy.drawFastHLine(NAME_HEX_X +
|
||||||
|
(nameIndex * (CHAR_WIDTH * 3 + SMALL_SPACE)),
|
||||||
|
NAME_HEX_Y + CHAR_HEIGHT + 1, CHAR_WIDTH * 3 - 1);
|
||||||
|
|
||||||
|
arduboy.drawFastHLine(NAME_DECIMAL_X +
|
||||||
|
(nameIndex * (CHAR_WIDTH * 3 + SMALL_SPACE)),
|
||||||
|
NAME_DECIMAL_Y + CHAR_HEIGHT + 1, CHAR_WIDTH * 3 - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print the ID screen cursors
|
||||||
|
void printIDCursors() {
|
||||||
|
arduboy.fillRect(ID_LARGE_X + ((idIndex + 1) * (CHAR_WIDTH * 2)),
|
||||||
|
ID_LARGE_Y + (CHAR_HEIGHT * 2),
|
||||||
|
(CHAR_WIDTH * 2) - 2, 2);
|
||||||
|
|
||||||
|
arduboy.drawFastHLine(ID_2_DECIMAL_X +
|
||||||
|
((idIndex / 2) * (CHAR_WIDTH * 3 + SMALL_SPACE)),
|
||||||
|
ID_2_DECIMAL_Y + CHAR_HEIGHT + 1, CHAR_WIDTH * 3 - 1);
|
||||||
|
|
||||||
|
arduboy.drawFastHLine(ID_DECIMAL_X, ID_DECIMAL_Y + CHAR_HEIGHT + 1,
|
||||||
|
CHAR_WIDTH * 5 - 1);
|
||||||
|
|
||||||
|
arduboy.drawFastHLine((ID_BINARY_X + CHAR_WIDTH + SMALL_SPACE) +
|
||||||
|
(idIndex * (CHAR_WIDTH * 4 + SMALL_SPACE)),
|
||||||
|
ID_BINARY_Y + CHAR_HEIGHT + 1, CHAR_WIDTH * 4 - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print the unit name in normal size including an extent underline
|
||||||
|
// at the given location
|
||||||
|
void printName(int x, int y) {
|
||||||
|
printStr(x, y, unitName);
|
||||||
|
|
||||||
|
y += (CHAR_HEIGHT + 1);
|
||||||
|
for (byte i = 0; i < ARDUBOY_UNIT_NAME_LEN; i++, x += CHAR_WIDTH) {
|
||||||
|
arduboy.drawFastHLine(x, y, CHAR_WIDTH - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print the unit name in large size at the given location
|
||||||
|
void printNameLarge(int x, int y) {
|
||||||
|
arduboy.setTextSize(2);
|
||||||
|
printStr(x, y, unitName);
|
||||||
|
arduboy.setTextSize(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a line below the large name showing the current length
|
||||||
|
// Coordinates are for the name itself
|
||||||
|
void printNameUnderline(int x, int y) {
|
||||||
|
int lWidth;
|
||||||
|
|
||||||
|
if (unitName[0] != 0) {
|
||||||
|
x -= 1;
|
||||||
|
y += ((CHAR_HEIGHT * 2) + 6);
|
||||||
|
lWidth = (strlen(unitName) * (CHAR_WIDTH * 2));
|
||||||
|
arduboy.drawPixel(x, y);
|
||||||
|
arduboy.drawPixel(x + lWidth - 1, y);
|
||||||
|
arduboy.drawFastHLine(x, y + 1, lWidth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print the unit name in hex at the given location
|
||||||
|
void printNameHex(int x, int y) {
|
||||||
|
for (byte i = 0; i < ARDUBOY_UNIT_NAME_LEN; i++) {
|
||||||
|
printHex8(x, y, unitName[i]);
|
||||||
|
x += CHAR_WIDTH * 3 + SMALL_SPACE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print the unit name in decimal at the given location
|
||||||
|
void printNameDecimal(int x, int y) {
|
||||||
|
for (byte i = 0; i < ARDUBOY_UNIT_NAME_LEN; i++) {
|
||||||
|
printDecimal8(x, y, unitName[i]);
|
||||||
|
x += CHAR_WIDTH * 3 + SMALL_SPACE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print the unit ID in large size at the given location
|
||||||
|
void printIDLarge(int x, int y) {
|
||||||
|
arduboy.setTextSize(2);
|
||||||
|
printIDHex(x, y);
|
||||||
|
arduboy.setTextSize(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print the unit ID in normal size at the given location
|
||||||
|
void printIDHex(int x, int y) {
|
||||||
|
printHex16(x, y, unitID);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print the unit ID as 2 decimal bytes at the given location
|
||||||
|
void printIDDecimalBytes(int x, int y) {
|
||||||
|
printDecimal8(x, y, unitID >> 8);
|
||||||
|
printDecimal8(x + CHAR_WIDTH * 3 + SMALL_SPACE, y, unitID & 0x00FF);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print the unit ID in decimal at the given location
|
||||||
|
void printIDDecimal(int x, int y) {
|
||||||
|
printDecimal16(x, y, unitID);
|
||||||
|
}
|
||||||
|
|
||||||
|
// print the unit ID in binary at the given location as 4 nybbles
|
||||||
|
// with a leading 'b'
|
||||||
|
void printIDBinary(int x, int y) {
|
||||||
|
arduboy.setCursor(x, y);
|
||||||
|
arduboy.print('b');
|
||||||
|
x += CHAR_WIDTH + SMALL_SPACE;
|
||||||
|
for (char i = 3 * 4; i >= 0; i -= 4) {
|
||||||
|
printBinaryNybble(x, y, (byte)(unitID >> i));
|
||||||
|
x += CHAR_WIDTH * 4 + SMALL_SPACE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print the save prompt in reverse at the given location
|
||||||
|
void printSavePrompt(int x, int y) {
|
||||||
|
arduboy.fillRect(x - 2, y - 2,
|
||||||
|
strlen_P(StrSaveQ) * CHAR_WIDTH + 3, CHAR_HEIGHT + 3);
|
||||||
|
arduboy.setTextColor(BLACK);
|
||||||
|
arduboy.setTextBackground(WHITE);
|
||||||
|
printStr_P(x, y, StrSaveQ);
|
||||||
|
arduboy.setTextColor(WHITE);
|
||||||
|
arduboy.setTextBackground(BLACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print a string at the given location
|
||||||
|
void printStr(int x, int y, char* str) {
|
||||||
|
arduboy.setCursor(x, y);
|
||||||
|
arduboy.print(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print a string in program memory at the given location
|
||||||
|
void printStr_P(int x, int y, const char* str) {
|
||||||
|
arduboy.setCursor(x, y);
|
||||||
|
arduboy.print((__FlashStringHelper*)(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print an 8 bit number in decimal, right justified with leading spaces
|
||||||
|
void printDecimal8(int x, int y, byte val) {
|
||||||
|
printDecimalHelper(x, y, 2, 100, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print a 16 bit number in decimal, right justified with leading spaces
|
||||||
|
void printDecimal16(int x, int y, unsigned int val) {
|
||||||
|
printDecimalHelper(x, y, 4, 10000, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print a right justified decimal number, given width-1 and (width-1)^10
|
||||||
|
void printDecimalHelper(int x, int y, byte width, unsigned int pwr10,
|
||||||
|
unsigned int val) {
|
||||||
|
arduboy.setCursor(x, y);
|
||||||
|
while (width > 0) {
|
||||||
|
if (val >= pwr10) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
arduboy.print(' ');
|
||||||
|
pwr10 /= 10;
|
||||||
|
width--;
|
||||||
|
}
|
||||||
|
arduboy.print(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print an 8 bit hex number with leading x and zeros
|
||||||
|
void printHex8(int x, int y, byte val) {
|
||||||
|
arduboy.setCursor(x, y);
|
||||||
|
arduboy.print('x');
|
||||||
|
if (val < 16) {
|
||||||
|
arduboy.print('0');
|
||||||
|
}
|
||||||
|
arduboy.print(val, HEX);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print a 16 bit hex number with leading x and zeros
|
||||||
|
void printHex16(int x, int y, unsigned int val) {
|
||||||
|
arduboy.setCursor(x, y);
|
||||||
|
arduboy.print('x');
|
||||||
|
for (char i = 3 * 4; i >= 0; i -= 4) {
|
||||||
|
arduboy.print((val >> i) & 0x000F, HEX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print a nybble in binary from the lowest 4 bits of the provided byte
|
||||||
|
void printBinaryNybble(int x, int y, byte val) {
|
||||||
|
arduboy.setCursor(x, y);
|
||||||
|
|
||||||
|
for (char i = 3; i >= 0; i--) {
|
||||||
|
arduboy.print((val >> i) & 0x01);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------- Control and Utility Functions ------------------------
|
||||||
|
|
||||||
|
// Get the current unit name and ID from EEPROM
|
||||||
|
void readEEPROM() {
|
||||||
|
memset(unitName, 0, sizeof(unitName));
|
||||||
|
arduboy.readUnitName(unitName);
|
||||||
|
unitID = arduboy.readUnitID();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increment the name character at the cursor position
|
||||||
|
void nameCharInc() {
|
||||||
|
while (invalidChar(++unitName[nameIndex])) { }
|
||||||
|
drawScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrement the name character at the cursor position
|
||||||
|
void nameCharDec() {
|
||||||
|
while (invalidChar(--unitName[nameIndex])) { }
|
||||||
|
drawScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return true if the given character is not allowed
|
||||||
|
boolean invalidChar(char c) {
|
||||||
|
return (c == '\n') || (c == '\r') || ((byte)c == 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move the name cursor right
|
||||||
|
void nameCursorRight() {
|
||||||
|
if (++nameIndex == ARDUBOY_UNIT_NAME_LEN) {
|
||||||
|
nameIndex = 0;
|
||||||
|
}
|
||||||
|
drawScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move the name cursor left
|
||||||
|
void nameCursorLeft() {
|
||||||
|
if (nameIndex == 0) {
|
||||||
|
nameIndex = ARDUBOY_UNIT_NAME_LEN - 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nameIndex--;
|
||||||
|
}
|
||||||
|
drawScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increment the ID digit at the cursor position
|
||||||
|
void idDigitInc() {
|
||||||
|
uint16_t mask = 0xF000 >> (idIndex * 4);
|
||||||
|
uint16_t val = 0x1000 >> (idIndex * 4);
|
||||||
|
|
||||||
|
unitID = (unitID & ~mask) | ((unitID + val) & mask);
|
||||||
|
drawScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrement the ID digit at the cursor position
|
||||||
|
void idDigitDec() {
|
||||||
|
uint16_t mask = 0xF000 >> (idIndex * 4);
|
||||||
|
uint16_t val = 0x1000 >> (idIndex * 4);
|
||||||
|
|
||||||
|
unitID = (unitID & ~mask) | ((unitID - val) & mask);
|
||||||
|
drawScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move the ID cursor right
|
||||||
|
void idCursorRight() {
|
||||||
|
if (++idIndex == sizeof(unitID) * 2) {
|
||||||
|
idIndex = 0;
|
||||||
|
}
|
||||||
|
drawScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move the ID cursor left
|
||||||
|
void idCursorLeft() {
|
||||||
|
if (idIndex == 0) {
|
||||||
|
idIndex = sizeof(unitID) * 2 - 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
idIndex--;
|
||||||
|
}
|
||||||
|
drawScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the button auto-repeat delay
|
||||||
|
void startButtonDelay() {
|
||||||
|
delayCount = DELAY_FRAMES;
|
||||||
|
repeating = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop the button auto-repeat or delay
|
||||||
|
void stopButtonRepeat() {
|
||||||
|
delayCount = 0;
|
||||||
|
repeating = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the X coordinate to center a string of the given length
|
||||||
|
int centerStrLen(unsigned int len) {
|
||||||
|
return (WIDTH / 2) - (len * CHAR_WIDTH / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the X coordinate to center a string located in program memory
|
||||||
|
int centerStr_P(const char* str) {
|
||||||
|
return (WIDTH / 2) - (strlen_P(str) * CHAR_WIDTH / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
|
@ -112,7 +112,7 @@ WARN_LOGFILE =
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
# Configuration options related to the input files
|
# Configuration options related to the input files
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
INPUT = ./src ./README.md
|
INPUT = ./src ./README.md ./LICENSE.txt
|
||||||
INPUT_ENCODING = UTF-8
|
INPUT_ENCODING = UTF-8
|
||||||
FILE_PATTERNS = *.c *.cc *.cxx *.cpp *.c++ *.h *.hh *.hxx *.hpp *.h++
|
FILE_PATTERNS = *.c *.cc *.cxx *.cpp *.c++ *.h *.hh *.hxx *.hpp *.h++
|
||||||
RECURSIVE = NO
|
RECURSIVE = NO
|
||||||
|
|
|
@ -64,6 +64,8 @@ paint8Pixels KEYWORD2
|
||||||
paintScreen KEYWORD2
|
paintScreen KEYWORD2
|
||||||
pollButtons KEYWORD2
|
pollButtons KEYWORD2
|
||||||
pressed KEYWORD2
|
pressed KEYWORD2
|
||||||
|
readUnitID KEYWORD2
|
||||||
|
readUnitName KEYWORD2
|
||||||
saveOnOff KEYWORD2
|
saveOnOff KEYWORD2
|
||||||
setCursor KEYWORD2
|
setCursor KEYWORD2
|
||||||
setFrameRate KEYWORD2
|
setFrameRate KEYWORD2
|
||||||
|
@ -75,6 +77,8 @@ setTextWrap KEYWORD2
|
||||||
systemButtons KEYWORD2
|
systemButtons KEYWORD2
|
||||||
toggle KEYWORD2
|
toggle KEYWORD2
|
||||||
width KEYWORD2
|
width KEYWORD2
|
||||||
|
writeUnitID KEYWORD2
|
||||||
|
writeUnitName KEYWORD2
|
||||||
|
|
||||||
# Sprites class
|
# Sprites class
|
||||||
drawErase KEYWORD2
|
drawErase KEYWORD2
|
||||||
|
|
|
@ -42,9 +42,9 @@ void Arduboy2Base::begin()
|
||||||
// check for and handle buttons held during start up for system control
|
// check for and handle buttons held during start up for system control
|
||||||
systemButtons();
|
systemButtons();
|
||||||
|
|
||||||
bootLogo();
|
|
||||||
|
|
||||||
audio.begin();
|
audio.begin();
|
||||||
|
|
||||||
|
bootLogo();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Arduboy2Base::flashlight()
|
void Arduboy2Base::flashlight()
|
||||||
|
@ -56,7 +56,7 @@ void Arduboy2Base::flashlight()
|
||||||
sendLCDCommand(OLED_ALL_PIXELS_ON); // smaller than allPixelsOn()
|
sendLCDCommand(OLED_ALL_PIXELS_ON); // smaller than allPixelsOn()
|
||||||
digitalWriteRGB(RGB_ON, RGB_ON, RGB_ON);
|
digitalWriteRGB(RGB_ON, RGB_ON, RGB_ON);
|
||||||
|
|
||||||
while(!pressed(DOWN_BUTTON)) {
|
while (!pressed(DOWN_BUTTON)) {
|
||||||
idle();
|
idle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,8 +113,13 @@ void Arduboy2Base::bootLogo()
|
||||||
|
|
||||||
delay(750);
|
delay(750);
|
||||||
digitalWrite(BLUE_LED, RGB_OFF);
|
digitalWrite(BLUE_LED, RGB_OFF);
|
||||||
|
|
||||||
|
bootLogoExtra();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Virtual function overridden by derived class
|
||||||
|
void Arduboy2Base::bootLogoExtra() { }
|
||||||
|
|
||||||
/* Frame management */
|
/* Frame management */
|
||||||
|
|
||||||
void Arduboy2Base::setFrameRate(uint8_t rate)
|
void Arduboy2Base::setFrameRate(uint8_t rate)
|
||||||
|
@ -896,6 +901,58 @@ bool Arduboy2Base::collide(Rect rect1, Rect rect2)
|
||||||
rect2.y + rect2.height <= rect1.y);
|
rect2.y + rect2.height <= rect1.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t Arduboy2Base::readUnitID()
|
||||||
|
{
|
||||||
|
return EEPROM.read(EEPROM_UNIT_ID) |
|
||||||
|
(((uint16_t)(EEPROM.read(EEPROM_UNIT_ID + 1))) << 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Arduboy2Base::writeUnitID(uint16_t id)
|
||||||
|
{
|
||||||
|
EEPROM.update(EEPROM_UNIT_ID, (uint8_t)(id & 0xff));
|
||||||
|
EEPROM.update(EEPROM_UNIT_ID + 1, (uint8_t)(id >> 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t Arduboy2Base::readUnitName(char* name)
|
||||||
|
{
|
||||||
|
char val;
|
||||||
|
uint8_t dest;
|
||||||
|
uint8_t src = EEPROM_UNIT_NAME;
|
||||||
|
|
||||||
|
for (dest = 0; dest < ARDUBOY_UNIT_NAME_LEN; dest++)
|
||||||
|
{
|
||||||
|
if ((val = EEPROM.read(src)) == 0x00 || (byte)val == 0xFF)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
name[dest] = val;
|
||||||
|
src++;
|
||||||
|
}
|
||||||
|
|
||||||
|
name[dest] = 0x00;
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Arduboy2Base::writeUnitName(char* name)
|
||||||
|
{
|
||||||
|
bool done = false;
|
||||||
|
uint8_t dest = EEPROM_UNIT_NAME;
|
||||||
|
|
||||||
|
for (uint8_t src = 0; src < ARDUBOY_UNIT_NAME_LEN; src++)
|
||||||
|
{
|
||||||
|
if (name[src] != 0x00 && !done)
|
||||||
|
{
|
||||||
|
EEPROM.update(dest, name[src]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
done = true;
|
||||||
|
EEPROM.update(dest, 0x00);
|
||||||
|
}
|
||||||
|
dest++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Arduboy2Base::swap(int16_t& a, int16_t& b)
|
void Arduboy2Base::swap(int16_t& a, int16_t& b)
|
||||||
{
|
{
|
||||||
int16_t temp = a;
|
int16_t temp = a;
|
||||||
|
@ -918,6 +975,27 @@ Arduboy2::Arduboy2()
|
||||||
textWrap = 0;
|
textWrap = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Arduboy2::bootLogoExtra()
|
||||||
|
{
|
||||||
|
uint8_t c = EEPROM.read(EEPROM_UNIT_NAME);
|
||||||
|
|
||||||
|
if (c != 0xFF && c != 0x00)
|
||||||
|
{
|
||||||
|
uint8_t i = EEPROM_UNIT_NAME;
|
||||||
|
cursor_x = 50;
|
||||||
|
cursor_y = 56;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
write(c);
|
||||||
|
c = EEPROM.read(++i);
|
||||||
|
} while (i < EEPROM_UNIT_NAME + ARDUBOY_UNIT_NAME_LEN);
|
||||||
|
|
||||||
|
display();
|
||||||
|
delay(1500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
size_t Arduboy2::write(uint8_t c)
|
size_t Arduboy2::write(uint8_t c)
|
||||||
{
|
{
|
||||||
if (c == '\n')
|
if (c == '\n')
|
||||||
|
|
128
src/Arduboy2.h
128
src/Arduboy2.h
|
@ -8,6 +8,7 @@
|
||||||
#define ARDUBOY2_H
|
#define ARDUBOY2_H
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
#include <EEPROM.h>
|
||||||
#include "Arduboy2Core.h"
|
#include "Arduboy2Core.h"
|
||||||
#include "Sprites.h"
|
#include "Sprites.h"
|
||||||
#include <Print.h>
|
#include <Print.h>
|
||||||
|
@ -34,9 +35,15 @@
|
||||||
#define ARDUBOY_LIB_VER 30000
|
#define ARDUBOY_LIB_VER 30000
|
||||||
|
|
||||||
// EEPROM settings
|
// EEPROM settings
|
||||||
|
#define ARDUBOY_UNIT_NAME_LEN 6 /**< The maximum length of the unit name string. */
|
||||||
|
|
||||||
#define EEPROM_VERSION 0
|
#define EEPROM_VERSION 0
|
||||||
#define EEPROM_BRIGHTNESS 1
|
#define EEPROM_BRIGHTNESS 1
|
||||||
#define EEPROM_AUDIO_ON_OFF 2
|
#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
|
||||||
|
|
||||||
/** \brief
|
/** \brief
|
||||||
* Start of EEPROM storage space for sketches.
|
* Start of EEPROM storage space for sketches.
|
||||||
|
@ -180,7 +187,7 @@ class Arduboy2Base : public Arduboy2Core
|
||||||
*
|
*
|
||||||
* \note
|
* \note
|
||||||
* To free up some code space for use by the sketch, `boot()` can be used
|
* To free up some code space for use by the sketch, `boot()` can be used
|
||||||
* instead of `begin()` allow the elimination of some of the things that
|
* instead of `begin()` to allow the elimination of some of the things that
|
||||||
* aren't really required, such as displaying the boot logo.
|
* aren't really required, such as displaying the boot logo.
|
||||||
*
|
*
|
||||||
* \see boot()
|
* \see boot()
|
||||||
|
@ -229,10 +236,18 @@ class Arduboy2Base : public Arduboy2Core
|
||||||
* The Arduboy logo scrolls down from the top of the screen to the center
|
* The Arduboy logo scrolls down from the top of the screen to the center
|
||||||
* while the RGB LEDs light in sequence.
|
* while the RGB LEDs light in sequence.
|
||||||
*
|
*
|
||||||
* \see begin() boot()
|
* This function calls `bootLogoExtra()` after the logo stops scrolling down,
|
||||||
|
* which derived classes can implement to add additional information to the
|
||||||
|
* logo screen. The `Arduboy2` class uses this to display the unit name.
|
||||||
|
*
|
||||||
|
* \see begin() boot() Arduboy2::bootLogoExtra()
|
||||||
*/
|
*/
|
||||||
void bootLogo();
|
void bootLogo();
|
||||||
|
|
||||||
|
// Called by bootLogo() to allow derived classes to display additional
|
||||||
|
// information after the logo stops scrolling down.
|
||||||
|
virtual void bootLogoExtra();
|
||||||
|
|
||||||
/** \brief
|
/** \brief
|
||||||
* Clear the display buffer.
|
* Clear the display buffer.
|
||||||
*
|
*
|
||||||
|
@ -807,6 +822,97 @@ class Arduboy2Base : public Arduboy2Core
|
||||||
*/
|
*/
|
||||||
bool collide(Rect rect1, Rect rect2);
|
bool collide(Rect rect1, Rect rect2);
|
||||||
|
|
||||||
|
/** \brief
|
||||||
|
* Read the unit ID from system EEPROM.
|
||||||
|
*
|
||||||
|
* \return The value of the unit ID stored in system EEPROM.
|
||||||
|
*
|
||||||
|
* \details
|
||||||
|
* This function reads the unit ID that has been set in system EEPROM.
|
||||||
|
* The ID can be any value. It is intended to allow different units to be
|
||||||
|
* uniquely identified.
|
||||||
|
*
|
||||||
|
* \see writeUnitID() readUnitName()
|
||||||
|
*/
|
||||||
|
uint16_t readUnitID();
|
||||||
|
|
||||||
|
/** \brief
|
||||||
|
* Write a unit ID to system EEPROM.
|
||||||
|
*
|
||||||
|
* \param id The value of the unit ID to be stored in system EEPROM.
|
||||||
|
*
|
||||||
|
* \details
|
||||||
|
* This function writes a unit ID to a reserved location in system EEPROM.
|
||||||
|
* The ID can be any value. It is intended to allow different units to be
|
||||||
|
* uniquely identified.
|
||||||
|
*
|
||||||
|
* \see readUnitID() writeUnitName()
|
||||||
|
*/
|
||||||
|
void writeUnitID(uint16_t id);
|
||||||
|
|
||||||
|
/** \brief
|
||||||
|
* Read the unit name from system EEPROM.
|
||||||
|
*
|
||||||
|
* \param name A pointer to a string array variable where the unit name will
|
||||||
|
* be placed. The string will be up to 6 characters and terminated with a
|
||||||
|
* null (0x00) character, so the provided array must be at least 7 bytes long.
|
||||||
|
*
|
||||||
|
* \return The length of the string (0-6).
|
||||||
|
*
|
||||||
|
* \details
|
||||||
|
* This function reads the unit name that has been set in system EEPROM. The
|
||||||
|
* name is in ASCII and can contain any values except 0xFF and the
|
||||||
|
* null (0x00) terminator value.
|
||||||
|
*
|
||||||
|
* The name can be used for any purpose. It could identify the owner or
|
||||||
|
* give the unit itself a nickname. A sketch could use it to automatically
|
||||||
|
* fill in a name or initials in a high score table, or display it as the
|
||||||
|
* "player" when the opponent is the computer.
|
||||||
|
*
|
||||||
|
* \note
|
||||||
|
* Sketches can use the defined value `ARDUBOY_UNIT_NAME_LEN` instead of
|
||||||
|
* hard coding a 6 when working with the unit name. For example, to allocate
|
||||||
|
* a buffer and read the unit name into it:
|
||||||
|
* \code
|
||||||
|
* // Buffer for maximum name length plus the terminator
|
||||||
|
* char unitName[ARDUBOY_UNIT_NAME_LEN + 1];
|
||||||
|
*
|
||||||
|
* // The actual name length
|
||||||
|
* byte unitNameLength;
|
||||||
|
*
|
||||||
|
* unitNameLength = arduboy.readUnitName(unitName);
|
||||||
|
* \endcode
|
||||||
|
*
|
||||||
|
* \see writeUnitName() readUnitID() Arduboy2::bootLogoExtra()
|
||||||
|
*/
|
||||||
|
uint8_t readUnitName(char* name);
|
||||||
|
|
||||||
|
/** \brief
|
||||||
|
* Write a unit name to system EEPROM.
|
||||||
|
*
|
||||||
|
* \param name A pointer to a string array variable containing the unit name
|
||||||
|
* to be saved. The string can be up to 6 characters and must be terminated
|
||||||
|
* with a null (0x00) character. It can contain any values except 0xFF.
|
||||||
|
*
|
||||||
|
* \details
|
||||||
|
* This function writes a unit name to a reserved area in system EEPROM.
|
||||||
|
* The name is in ASCII and can contain any values except 0xFF and the
|
||||||
|
* null (0x00) terminator value. The newline character (LF, \\n, 0x0A) and
|
||||||
|
* carriage return character (CR, \\r, 0x0D) should also be avoided.
|
||||||
|
*
|
||||||
|
* The name can be used for any purpose. It could identify the owner or
|
||||||
|
* give the unit itself a nickname. A sketch could use it to automatically
|
||||||
|
* fill in a name or initials in a high score table, or display it as the
|
||||||
|
* "player" when the opponent is the computer.
|
||||||
|
*
|
||||||
|
* \note
|
||||||
|
* Sketches can use the defined value `ARDUBOY_UNIT_NAME_LEN` instead of
|
||||||
|
* hard coding a 6 when working with the unit name.
|
||||||
|
*
|
||||||
|
* \see readUnitName() writeUnitID() Arduboy2::bootLogoExtra()
|
||||||
|
*/
|
||||||
|
void writeUnitName(char* name);
|
||||||
|
|
||||||
/** \brief
|
/** \brief
|
||||||
* A counter which is incremented once per frame.
|
* A counter which is incremented once per frame.
|
||||||
*
|
*
|
||||||
|
@ -931,6 +1037,24 @@ class Arduboy2 : public Print, public Arduboy2Base
|
||||||
* \see Arduboy2::write()
|
* \see Arduboy2::write()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/** \brief
|
||||||
|
* Show the unit name at the bottom of the boot logo screen.
|
||||||
|
*
|
||||||
|
* \details
|
||||||
|
* This function is called by the `bootLogo()` function.
|
||||||
|
*
|
||||||
|
* If a unit name has been saved in system EEPROM, it will be displayed at
|
||||||
|
* the bottom of the screen. This function pauses for a short time to allow
|
||||||
|
* the name to be seen.
|
||||||
|
*
|
||||||
|
* \note
|
||||||
|
* This function would not normally be called directly from within a sketch
|
||||||
|
* itself.
|
||||||
|
*
|
||||||
|
* \see readUnitName() writeUnitName() bootLogo() begin()
|
||||||
|
*/
|
||||||
|
virtual void bootLogoExtra();
|
||||||
|
|
||||||
/** \brief
|
/** \brief
|
||||||
* Write a single ASCII character at the current text cursor location.
|
* Write a single ASCII character at the current text cursor location.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue