diff --git a/.gitignore b/.gitignore index cc96914..94f90d1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,15 +1 @@ -# Ignore vim temp and swap files -*~ -*.swp -*.swo - -# Ignore working files -.build -Makefile -ino.ini -work -*.eep - -# Ignore OS bookkeeping -.DS_Store -Thumbs.db +doxygen/ diff --git a/README.md b/README.md index 395e0d5..bb39a14 100644 --- a/README.md +++ b/README.md @@ -1,31 +1,30 @@ -#Arduboy2 Library +# Arduboy2 Library The **Arduboy2** library is a fork of the [Arduboy library](https://github.com/Arduboy/Arduboy) which provides a standard *application programming interface* (API) to the display, buttons and other hardware of the Arduino based [Arduboy miniature game system](https://www.arduboy.com/). -The name *Arduboy2* doesn't indicate that it's for a new "next generation" of the Arduboy hardware. The name was changed so it can coexist in the Arduino IDE with the current Arduboy library, without conflict. This way, existing sketches can continue to use the *Arduboy* library and class, without changes, while new sketches can be written (or old ones modified) to use and take advantage of the capabilities of the *Arduboy2* class and library. +The name *Arduboy2* doesn't indicate that it's for a new "next generation" of the Arduboy hardware. The name was changed so it can coexist in the Arduino IDE with the current *Arduboy* library, without conflict. This way, existing sketches can continue to use the *Arduboy* library and class, without changes, while new sketches can be written (or old ones modified) to use and take advantage of the capabilities of the *Arduboy2* class and library. ## Installation -At the moment, probably the easiest way to install the Arduboy2 library is to use the *Add .ZIP Library...* feature of the Arduino IDE. A properly formatted *.zip* file containing the latest stable release of the library can be obtained from -https://mlxxxp.github.io/downloads/Arduboy2/ +The Arduboy2 library can be installed using the Arduino IDE Library Manager: -- Download *Arduboy2.zip* to a folder on your computer, such as *Downloads*. The folder you put it in doesn't matter as long as you know how to find the file later. Don't unzip the file. -- In the Arduino IDE select from the menus: `Sketch > Include Library > Add .ZIP Library...` -- Locate and select the *Arduboy2.zip* file then click on the *OK* button. The library should now be installed and ready to use. -- Once the library is installed, you can delete the *Arduboy2.zip* file, if desired. +- In the Arduino IDE select from the menus: `Sketch > Include Library > Manage Libraries...` +- In the Library Manager *Filter your search...* field enter *arduboy2*. +- Click somewhere within the Arduboy2 entry. +- Click on the *Install* button. For more library installation information see -[Installing Additional Arduino Libraries - Importing a .zip Library](https://www.arduino.cc/en/Guide/Libraries#toc4) +[Installing Additional Arduino Libraries - Using the Library Manager](https://www.arduino.cc/en/Guide/Libraries#toc3) ## What's different from Arduboy V1.1 -A main goal of Arduboy2 is to provide ways in which more code space can be freed for use by large sketches. Another goal is to allow methods other than the *"tunes"* functions to be used to produce sounds. Arduboy2 remains substantially compatible with [Arduboy library V1.1](https://github.com/Arduboy/Arduboy/releases/tag/v1.1), which was the latest stable release at the time of the fork. Arduboy2 is based on the code targeted for Arduboy library V1.2, which was still in development and unreleased at the time it was forked. +A main goal of Arduboy2 is to provide ways in which more code space can be freed for use by large sketches. Another goal is to allow methods other than the *tunes* functions to be used to produce sounds. Arduboy2 remains substantially compatible with [Arduboy library V1.1](https://github.com/Arduboy/Arduboy/releases/tag/v1.1), which was the latest stable release at the time of the fork. Arduboy2 is based on the code targeted for Arduboy library V1.2, which was still in development and unreleased at the time it was forked. Main differences between Arduboy2 and Arduboy V1.1 are: -- The *ArduboyTunes* subclass, which provided the *tunes.xxx()* functions, has been removed. It's functionality is available in a separate [*ArduboyPlaytune* library](https://github.com/Arduboy/ArduboyPlayTune). By removing these functions, more code space may become available because interrupt routines and other support code was being compiled in even if a sketch didn't make use them. Another benefit is that without the automatic installation of timer interrupt service routines, other audio generating functions and libraries, that need access to the same interrupts, can now be used. Removal of the *"tunes"* functions is the main API incompatibility with Arduboy V1.1. Sketches written to use *"tunes"* functions will need some minor modifications in order to make them work with Arduboy2 plus ArduboyPlaytune, [ArduboyTones](https://github.com/MLXXXp/ArduboyTones), or some other audio library. -- Arduboy library V1.1 uses timer 1 for the *"tunes"* functions. This causes problems when attempting to control the Arduboy's RGB LED using PWM, such as with *setRGBled()*, because it also requires timer 1. Since the *"tunes"* functionality has been removed from Arduboy2, there are no problems with using the RGB LED (except those caused by the RGB LED being incorrectly installed). Of course, using an external library that uses timer 1, such as *ArduboyPlaytune*, may reintroduce the problems. However, using a library that doesn't use timer 1, such as *ArduboyTones*, is now an option. +- The *ArduboyTunes* subclass, which provided the *tunes.xxx()* functions, has been removed. It's functionality is available in a separate [*ArduboyPlaytune* library](https://github.com/Arduboy/ArduboyPlayTune). By removing these functions, more code space may become available because interrupt routines and other support code was being compiled in even if a sketch didn't make use them. Another benefit is that without the automatic installation of timer interrupt service routines, other audio generating functions and libraries, that need access to the same interrupts, can now be used. Removal of the *tunes* functions is the main API incompatibility with Arduboy V1.1. Sketches written to use *tunes* functions will need some minor modifications in order to make them work with Arduboy2 plus ArduboyPlaytune, [ArduboyTones](https://github.com/MLXXXp/ArduboyTones), or some other audio library. +- Arduboy library V1.1 uses timer 1 for the *tunes* functions. This causes problems when attempting to control the Arduboy's RGB LED using PWM, such as with *setRGBled()*, because it also requires timer 1. Since the *tunes* functionality has been removed from Arduboy2, there are no problems with using the RGB LED (except those caused by the RGB LED being incorrectly installed). Of course, using an external library that uses timer 1, such as *ArduboyPlaytune*, may reintroduce the problems. However, using a library that doesn't use timer 1, such as *ArduboyTones*, is now an option. - The code to generate text output, using *setCursor()*, *print()*, etc., can be removed to free up code space, if a sketch doesn't use any text functions. The *Arduboy2* class includes the text functions but using the *Arduboy2Base* class instead will eliminate them. With text functions included, the font table and some support functions are always compiled in even if not used. The API for using text functions is the same as Arduboy V1.1 with some additional functions added: - *setTextColor()* and *setTextBackground()* allow for printing black text on a white background. - *getCursorX()* and *getCursorY()* allow for determining the current text cursor position. @@ -79,18 +78,23 @@ Note that the audio control feature only sets a flag in EEPROM. Whatever code ac As with most libraries, to use Arduboy2 in your sketch you must include its header file at the start: -`#include ` +```cpp +#include +``` You must then create an Arduboy2 class object: -`Arduboy2 arduboy;` +```cpp +Arduboy2 arduboy; +``` Naming the object *arduboy* has become somewhat of a standard, but you can use a different name if you wish. To initialize the library, you must call its *begin()* function. This is usually done at the start of the sketch's *setup()* function: ```cpp -void setup() { +void setup() +{ arduboy.begin(); // more setup code follows, if required } @@ -110,6 +114,24 @@ Sample sketches have been included with the library as examples of how to use it More information on writing sketches for the Arduboy can be found in the [Arduboy Community Forum](http://community.arduboy.com/). +### Audio control functions + +The library includes an Arduboy2Audio class. This class provides functions to enable and disable (mute) sound and also save the current mute state so that it remains in effect over power cycles and after loading a different sketch. It doesn't contain anything to actually produce sound. + +The Arduboy2Base class, and thus the Arduboy2 class, creates an Arduboy2Audio class object named *audio*, so a sketch doesn't need to create its own Arduboy2Audio object. + +Example: + +```cpp +#include + +Arduboy2 arduboy; + +// Arduboy2Audio functions can be called as follows: + arduboy.audio.on(); + arduboy.audio.off(); +``` + ### Ways to make more code space available to sketches #### Sound effects and music @@ -124,9 +146,17 @@ To eliminate text capability in your sketch, when creating the library object si For example, if the object will be named *arduboy*: -replace `Arduboy2 arduboy;` +Replace -with `Arduboy2Base arduboy;` +```cpp +Arduboy2 arduboy; +``` + +with + +```cpp +Arduboy2Base arduboy; +``` #### Remove boot up features @@ -180,21 +210,37 @@ This saves whatever code *blank()*, *systemButtons()* and *bootLogo()* would use Since the Arduboy2 library can coexist in the Arduino IDE alongside the Arduboy library V1.1, a currently working sketch that uses Arduboy V1.1 doesn't have to be migrated to Arduboy2. However, if you want to switch a sketch to Arduboy2 for further development, in order to take advantage of any of the changes and enhancements, it's generally relatively easy. -The Arduboy2 library, for the most part, is compatible with Arduboy library V1.1 but migrating a sketch to Arduboy2 will require some small changes, and more so if it uses the *"tunes"* functions, such as *tunes.tone()* or *tunes.playScore()*. +The Arduboy2 library, for the most part, is compatible with Arduboy library V1.1 but migrating a sketch to Arduboy2 will require some small changes, and more so if it uses the *tunes* functions, such as *tunes.tone()* or *tunes.playScore()*. ### Required changes -The first thing to do is change the *#include* for the library header file: +The first thing to do is change the `include` for the library header file: -`#include ` becomes `#include ` +```cpp +#include +``` -(If it was *"Arduboy.h"* in quotes, it's still better to change it to *<Arduboy2.h>* in angle brackets). +becomes + +```cpp +#include +``` + +If it was "Arduboy.h" (in quotes), it's still better to change it to <Arduboy2.h> (in angle brackets). The same thing has to be done with creating the library object. (If the object name isn't *arduboy*, keep whatever name is used.): -`Arduboy arduboy;` becomes `Arduboy2 arduboy;` +```cpp +Arduboy arduboy; +``` -If the sketch doesn't use any *"tunes"* functions, there's a good chance this is all that has to be done to make it compile. +becomes + +```cpp +Arduboy2 arduboy; +``` + +If the sketch doesn't use any *tunes* functions, there's a good chance this is all that has to be done to make it compile. ### Sketch uses only *tunes.tone()* for sound @@ -218,7 +264,15 @@ void playTone(unsigned int frequency, unsigned long duration) You then change all *tunes.tone()* calls to *playTone()* calls using the same parameter values. For example: -`arduboy.tunes.tone(1000, 250);` becomes `playTone(1000, 250);` +```cpp + arduboy.tunes.tone(1000, 250); +``` + +becomes + +```cpp + playTone(1000, 250); +``` #### Solution 2: Switch to using the ArduboyTones library @@ -226,7 +280,9 @@ Changing to the *ArduboyTones* library is slightly more complicated. The advanta You have to add an include for the ArduboyTones header file: -`#include ` +```cpp +#include +``` You then have to create an object for the *ArduboyTones* class and pass it a pointer to the Arduboy2 *audio.enabled()* function. This must go after the creation of the Arduboy2 object, like so: @@ -237,9 +293,17 @@ ArduboyTones sound(arduboy.audio.enabled); You then change all Arduboy *tunes.tone()* calls to ArduboyTones *tone()* calls using the same parameter values. For example: -`arduboy.tunes.tone(1000, 250);` becomes `sound.tone(1000, 250);` +```cpp + arduboy.tunes.tone(1000, 250); +``` -See the [ArduboyTones](https://github.com/MLXXXp/ArduboyTones) README.md file for more information on installing and using it. +becomes + +```cpp + sound.tone(1000, 250); +``` + +See the [ArduboyTones](https://github.com/MLXXXp/ArduboyTones) README file for more information on installing and using it. #### Solution 3: Switch to using the ArduboyPlaytune library. @@ -251,7 +315,9 @@ If the sketch uses *tunes.playScore()*, probably the easiest solution is to use You have to add an include for the ArduboyPlaytune header file: -`#include ` +```cpp +#include +``` You then have to create an object for the *ArduboyPlaytune* class and pass it a pointer to the Arduboy2 *audio.enabled()* function. This must go after the creation of the Arduboy2 object, like so: @@ -260,7 +326,7 @@ Arduboy2 arduboy; ArduboyPlaytune tunes(arduboy.audio.enabled); ``` -The sound channels must the be initialzed and assigned to the speaker pins. This code would go in the *setup()* function: +The sound channels must then be initialzed and assigned to the speaker pins. This code would go in the *setup()* function: ```cpp // audio setup @@ -270,7 +336,15 @@ The sound channels must the be initialzed and assigned to the speaker pins. This If you name the ArduboyPlaytune object *tunes* as shown above, then you just have to remove the Arduboy object name from any *tunes* calls. For example: -`arduboy.tunes.playScore(mySong);` becomes `tunes.playScore(mySong);` +```cpp + arduboy.tunes.playScore(mySong); +``` + +becomes + +```cpp + tunes.playScore(mySong); +``` See the [*ArduboyPlaytune* library](https://github.com/Arduboy/ArduboyPlayTune) documentation for more information. diff --git a/extras/Doxyfile b/extras/Doxyfile new file mode 100644 index 0000000..8357062 --- /dev/null +++ b/extras/Doxyfile @@ -0,0 +1,329 @@ +# Doxyfile 1.8.11 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +DOXYFILE_ENCODING = UTF-8 +PROJECT_NAME = "Arduboy2 Library" +PROJECT_NUMBER = +PROJECT_BRIEF = +PROJECT_LOGO = +OUTPUT_DIRECTORY = ./doxygen +CREATE_SUBDIRS = NO +ALLOW_UNICODE_NAMES = NO +OUTPUT_LANGUAGE = English +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = YES +FULL_PATH_NAMES = YES +STRIP_FROM_PATH = +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = NO +QT_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +INHERIT_DOCS = YES +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 2 +ALIASES = +TCL_SUBST = +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +OPTIMIZE_FOR_FORTRAN = NO +OPTIMIZE_OUTPUT_VHDL = NO +EXTENSION_MAPPING = ino=C++ +MARKDOWN_SUPPORT = YES +AUTOLINK_SUPPORT = YES +BUILTIN_STL_SUPPORT = NO +CPP_CLI_SUPPORT = NO +SIP_SUPPORT = NO +IDL_PROPERTY_SUPPORT = YES +DISTRIBUTE_GROUP_DOC = NO +SUBGROUPING = YES +INLINE_GROUPED_CLASSES = NO +INLINE_SIMPLE_STRUCTS = NO +TYPEDEF_HIDES_STRUCT = NO +LOOKUP_CACHE_SIZE = 0 +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_PACKAGE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = NO +EXTRACT_LOCAL_METHODS = NO +EXTRACT_ANON_NSPACES = NO +HIDE_UNDOC_MEMBERS = YES +HIDE_UNDOC_CLASSES = YES +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +HIDE_COMPOUND_REFERENCE= NO +SHOW_INCLUDE_FILES = YES +SHOW_GROUPED_MEMB_INC = NO +FORCE_LOCAL_INCLUDES = NO +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +SORT_BRIEF_DOCS = NO +SORT_MEMBERS_CTORS_1ST = NO +SORT_GROUP_NAMES = NO +SORT_BY_SCOPE_NAME = NO +STRICT_PROTO_MATCHING = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_FILES = YES +SHOW_NAMESPACES = YES +FILE_VERSION_FILTER = +LAYOUT_FILE = +CITE_BIB_FILES = +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = YES +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = ./src ./README.md +INPUT_ENCODING = UTF-8 +FILE_PATTERNS = *.c *.cc *.cxx *.cpp *.c++ *.h *.hh *.hxx *.hpp *.h++ +RECURSIVE = NO +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXCLUDE_SYMBOLS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +FILTER_SOURCE_PATTERNS = +USE_MDFILE_AS_MAINPAGE = ./README.md +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = YES +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = NO +REFERENCES_RELATION = NO +REFERENCES_LINK_SOURCE = YES +SOURCE_TOOLTIPS = YES +USE_HTAGS = NO +VERBATIM_HEADERS = YES +CLANG_ASSISTED_PARSING = NO +CLANG_OPTIONS = +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = YES +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_EXTRA_STYLESHEET = +HTML_EXTRA_FILES = +HTML_COLORSTYLE_HUE = 245 +HTML_COLORSTYLE_SAT = 90 +HTML_COLORSTYLE_GAMMA = 95 +HTML_TIMESTAMP = YES +HTML_DYNAMIC_SECTIONS = YES +HTML_INDEX_NUM_ENTRIES = 100 +GENERATE_DOCSET = NO +DOCSET_FEEDNAME = "Doxygen generated docs" +DOCSET_BUNDLE_ID = org.doxygen.Project +DOCSET_PUBLISHER_ID = org.doxygen.Publisher +DOCSET_PUBLISHER_NAME = Publisher +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +CHM_INDEX_ENCODING = +BINARY_TOC = NO +TOC_EXPAND = NO +GENERATE_QHP = NO +QCH_FILE = +QHP_NAMESPACE = org.doxygen.Project +QHP_VIRTUAL_FOLDER = doc +QHP_CUST_FILTER_NAME = +QHP_CUST_FILTER_ATTRS = +QHP_SECT_FILTER_ATTRS = +QHG_LOCATION = +GENERATE_ECLIPSEHELP = NO +ECLIPSE_DOC_ID = org.doxygen.Project +DISABLE_INDEX = NO +GENERATE_TREEVIEW = YES +ENUM_VALUES_PER_LINE = 4 +TREEVIEW_WIDTH = 250 +EXT_LINKS_IN_WINDOW = NO +FORMULA_FONTSIZE = 10 +FORMULA_TRANSPARENT = YES +USE_MATHJAX = NO +MATHJAX_FORMAT = HTML-CSS +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest +MATHJAX_EXTENSIONS = +MATHJAX_CODEFILE = +SEARCHENGINE = YES +SERVER_BASED_SEARCH = NO +EXTERNAL_SEARCH = NO +SEARCHENGINE_URL = +SEARCHDATA_FILE = searchdata.xml +EXTERNAL_SEARCH_ID = +EXTRA_SEARCH_MAPPINGS = +#--------------------------------------------------------------------------- +# Configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = YES +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4 +EXTRA_PACKAGES = +LATEX_HEADER = +LATEX_FOOTER = +LATEX_EXTRA_STYLESHEET = +LATEX_EXTRA_FILES = +PDF_HYPERLINKS = YES +USE_PDFLATEX = YES +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +LATEX_SOURCE_CODE = NO +LATEX_BIB_STYLE = plain +#--------------------------------------------------------------------------- +# Configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +RTF_SOURCE_CODE = NO +#--------------------------------------------------------------------------- +# Configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_SUBDIR = +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# Configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +XML_OUTPUT = xml +XML_PROGRAMLISTING = YES +#--------------------------------------------------------------------------- +# Configuration options related to the DOCBOOK output +#--------------------------------------------------------------------------- +GENERATE_DOCBOOK = NO +DOCBOOK_OUTPUT = docbook +DOCBOOK_PROGRAMLISTING = NO +#--------------------------------------------------------------------------- +# Configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# Configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration options related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +EXTERNAL_PAGES = YES +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +MSCGEN_PATH = +DIA_PATH = +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = YES +DOT_NUM_THREADS = 0 +DOT_FONTNAME = Helvetica +DOT_FONTSIZE = 10 +DOT_FONTPATH = +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = YES +UML_LIMIT_NUM_FIELDS = 10 +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = NO +CALLER_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +INTERACTIVE_SVG = NO +DOT_PATH = +DOTFILE_DIRS = +MSCFILE_DIRS = +DIAFILE_DIRS = +PLANTUML_JAR_PATH = +PLANTUML_INCLUDE_PATH = +DOT_GRAPH_MAX_NODES = 50 +MAX_DOT_GRAPH_DEPTH = 0 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = YES +GENERATE_LEGEND = YES +DOT_CLEANUP = YES diff --git a/keywords.txt b/keywords.txt index da31116..3bf7c21 100644 --- a/keywords.txt +++ b/keywords.txt @@ -85,13 +85,16 @@ drawSelfMasked KEYWORD2 # Constants (LITERAL1) ####################################### +ARDUBOY_LIB_VER LITERAL1 + +EEPROM_STORAGE_SPACE_START LITERAL1 + HEIGHT LITERAL1 WIDTH LITERAL1 -COLUMN_ADDRESS_END LITERAL1 -PAGE_ADDRESS_END LITERAL1 BLACK LITERAL1 WHITE LITERAL1 +INVERT LITERAL1 A_BUTTON LITERAL1 B_BUTTON LITERAL1 diff --git a/library.properties b/library.properties index fb07125..ac21dc7 100644 --- a/library.properties +++ b/library.properties @@ -3,7 +3,7 @@ version=3.0.0 author=Chris J. Martinez, Kevin Bates, Josh Goebel, Scott Allen, Ross O. Shoger maintainer=Scott Allen saydisp-git@yahoo.ca sentence=An alternative library for use with the Arduboy game system. -paragraph=This is a fork of the Arduboy library, with a main goal of providing ways in which more code space can be freed for use by large sketches. It remains substantially compatible with Arduboy library V1.1, with the main API difference being that the "tones" subclass has been removed and its functionality made available in a separate ArduboyPlaytune library. Removal of "tones" also allows other audio functions and libraries to be used. +paragraph=This is a fork of the Arduboy library, with a main goal of providing ways in which more code space can be freed for use by large sketches. It remains substantially compatible with Arduboy library V1.1, with the main API difference being that the "tones" subclass has been removed and its functionality made available in a separate ArduboyPlaytune library. Removal of "tones" also allows other audio functions and libraries to be used, such as ArduboyTones. category=Other url=https://github.com/MLXXXp/Arduboy2 architectures=avr diff --git a/src/Arduboy2.cpp b/src/Arduboy2.cpp index 88d38cf..d5c047f 100644 --- a/src/Arduboy2.cpp +++ b/src/Arduboy2.cpp @@ -1,3 +1,9 @@ +/** + * @file Arduboy2.cpp + * \brief + * The Arduboy2Base and Arduboy2 classes and support objects and definitions. + */ + #include "Arduboy2.h" #include "ab_logo.c" #include "glcdfont.c" @@ -247,7 +253,7 @@ void Arduboy2Base::drawCircle(int16_t x0, int16_t y0, uint8_t r, uint8_t color) } void Arduboy2Base::drawCircleHelper -(int16_t x0, int16_t y0, uint8_t r, uint8_t cornername, uint8_t color) +(int16_t x0, int16_t y0, uint8_t r, uint8_t corners, uint8_t color) { int16_t f = 1 - r; int16_t ddF_x = 1; @@ -268,22 +274,22 @@ void Arduboy2Base::drawCircleHelper ddF_x += 2; f += ddF_x; - if (cornername & 0x4) + if (corners & 0x4) // lower right { drawPixel(x0 + x, y0 + y, color); drawPixel(x0 + y, y0 + x, color); } - if (cornername & 0x2) + if (corners & 0x2) // upper right { drawPixel(x0 + x, y0 - y, color); drawPixel(x0 + y, y0 - x, color); } - if (cornername & 0x8) + if (corners & 0x8) // lower left { drawPixel(x0 - y, y0 + x, color); drawPixel(x0 - x, y0 + y, color); } - if (cornername & 0x1) + if (corners & 0x1) // upper left { drawPixel(x0 - y, y0 - x, color); drawPixel(x0 - x, y0 - y, color); @@ -298,10 +304,9 @@ void Arduboy2Base::fillCircle(int16_t x0, int16_t y0, uint8_t r, uint8_t color) } void Arduboy2Base::fillCircleHelper -(int16_t x0, int16_t y0, uint8_t r, uint8_t cornername, int16_t delta, +(int16_t x0, int16_t y0, uint8_t r, uint8_t sides, int16_t delta, uint8_t color) { - // used to do circles and roundrects! int16_t f = 1 - r; int16_t ddF_x = 1; int16_t ddF_y = -2 * r; @@ -321,13 +326,13 @@ void Arduboy2Base::fillCircleHelper ddF_x += 2; f += ddF_x; - if (cornername & 0x1) + if (sides & 0x1) // right side { drawFastVLine(x0+x, y0-y, 2*y+1+delta, color); drawFastVLine(x0+y, y0-x, 2*x+1+delta, color); } - if (cornername & 0x2) + if (sides & 0x2) // left side { drawFastVLine(x0-x, y0-y, 2*y+1+delta, color); drawFastVLine(x0-y, y0-x, 2*x+1+delta, color); @@ -841,7 +846,7 @@ void Arduboy2Base::display() paintScreen(sBuffer); } -unsigned char* Arduboy2Base::getBuffer() +uint8_t* Arduboy2Base::getBuffer() { return sBuffer; } @@ -981,11 +986,11 @@ void Arduboy2::setCursor(int16_t x, int16_t y) cursor_y = y; } -uint16_t Arduboy2::getCursorX() { +int16_t Arduboy2::getCursorX() { return cursor_x; } -uint16_t Arduboy2::getCursorY() { +int16_t Arduboy2::getCursorY() { return cursor_y; } diff --git a/src/Arduboy2.h b/src/Arduboy2.h index cee024c..c830a01 100644 --- a/src/Arduboy2.h +++ b/src/Arduboy2.h @@ -1,3 +1,9 @@ +/** + * @file Arduboy2.h + * \brief + * The Arduboy2Base and Arduboy2 classes and support objects and definitions. + */ + #ifndef ARDUBOY2_H #define ARDUBOY2_H @@ -7,10 +13,24 @@ #include #include -// Library version. -// For a version number in the form of x.y.z the value of the define will be -// ((x * 10000) + (y * 100) + (z)) as a decimal number. -// So, it will read as xxxyyzz, with no leading zeros on x. +/** \brief + * Library version + * + * \details + * For a version number in the form of x.y.z the value of the define will be + * ((x * 10000) + (y * 100) + (z)) as a decimal number. + * So, it will read as xxxyyzz, with no leading zeros on x. + * + * A user program can test this value to conditionally compile based on the + * library version. For example: + * + * \code + * // If the library is version 2.1.0 or higher + * #if ARDUBOY_LIB_VER >= 20100 + * // ... code that make use of a new feature added to V2.1.0 + * #endif + * \endcode + */ #define ARDUBOY_LIB_VER 30000 // EEPROM settings @@ -18,18 +38,36 @@ #define EEPROM_BRIGHTNESS 1 #define EEPROM_AUDIO_ON_OFF 2 -// we reserve the first 16 byte of EEPROM for system use -#define EEPROM_STORAGE_SPACE_START 16 // and onward +/** \brief + * Start of EEPROM storage space for sketches. + * + * \details + * An area at the start of EEPROM is reserved for system use. + * This define specifies the first EEPROM location past the system area. + * Sketches can use locations from here to the end of EEPROM space. + */ +#define EEPROM_STORAGE_SPACE_START 16 // eeprom settings above are neded for audio #include "Arduboy2Audio.h" +// If defined, it is safe to draw outside of the screen boundaries. +// Pixels that would exceed the display limits will be ignored. #define PIXEL_SAFE_MODE // pixel colors -#define INVERT 2 //< lit/unlit pixel -#define WHITE 1 //< lit pixel -#define BLACK 0 //< unlit pixel +#define BLACK 0 /**< Color value for an unlit pixel for draw functions. */ +#define WHITE 1 /**< Color value for a lit pixel for draw functions. */ +/** \brief + * Color value to indicate pixels are to be inverted. + * + * \details + * BLACK pixels will become WHITE and WHITE will become BLACK. + * + * \note + * Only function Arduboy2Base::drawBitmap() currently supports this value. + */ +#define INVERT 2 // compare Vcc to 1.1 bandgap #define ADC_VOLTAGE (_BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1)) @@ -37,26 +75,70 @@ #define ADC_TEMP (_BV(REFS0) | _BV(REFS1) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0)) -/// Rectangle for collision functions +/** \brief + * A rectangle object for collision functions. + * + * \details + * The X and Y coordinates specify the top left corner of a rectangle with the + * given width and height. + * + * \see Arduboy2Base::collide(Point, Rect) Arduboy2Base::collide(Rect, Rect) + */ struct Rect { - int16_t x; - int16_t y; - uint8_t width; - uint8_t height; + int16_t x; /**< The X coordinate of the top left corner */ + int16_t y; /**< The Y coordinate of the top left corner */ + uint8_t width; /**< The width of the rectangle */ + uint8_t height; /**< The height of the rectangle */ }; -/// Point for collision functions +/** \brief + * An object to define a single point for collision functions. + * + * \details + * The location of the point is given by X and Y coordinates. + * + * \see Arduboy2Base::collide(Point, Rect) + */ struct Point { - int16_t x; - int16_t y; + int16_t x; /**< The X coordinate of the point */ + int16_t y; /**< The Y coordinate of the point */ }; //================================== //========== Arduboy2Base ========== //================================== +/** \brief + * The main functions provided for writing sketches for the Arduboy, + * _minus_ text output. + * + * This class in inherited by Arduboy2, so if text output functions are + * requred Arduboy2 should be used instead. + * + * \note + * \parblock + * An Arduboy2Audio class object named `audio` will be created by the + * Arduboy2Base class, so there is no need for a sketch itself to create an + * Arduboy2Audio object. Arduboy2Audio functions can be called using the + * Arduboy2 or Arduboy2Base `audio` object. + * + * Example: + * + * \code + * #include + * + * Arduboy2 arduboy; + * + * // Arduboy2Audio functions can be called as follows: + * arduboy.audio.on(); + * arduboy.audio.off(); + * \endcode + * \endparblock + * + * \see Arduboy2 + */ class Arduboy2Base : public Arduboy2Core { friend class Sprites; @@ -64,226 +146,618 @@ class Arduboy2Base : public Arduboy2Core public: Arduboy2Base(); + /** \brief + * An object created to provide audio control functions within this class. + * + * \details + * This object is created to eliminate the need for a sketch to create an + * Arduboy2Audio class object itself. + * + * \see Arduboy2Audio + */ Arduboy2Audio audio; - /// Initialize hardware, boot logo, boot utilities, etc. - /** - * To free up some code space for use by the sketch, you can use "boot()" - * instead of "begin()" to eliminate some of the some of the things that + /** \brief + * Initialize the hardware, display the boot logo, provide boot utilities, etc. + * + * \details + * This function should be called once near the start of the sketch, + * usually in `setup()`, before using any other functions in this class. + * It initializes the display, displays the boot logo, provides "flashlight" + * and system control features and initializes audio control. + * + * \note + * 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 * aren't really required, such as displaying the boot logo. - * - * Look at the source for "begin()" and after calling "boot()" call - * whatever functions "begin()" does that you still want to keep. - * If your sketch uses the speaker, it's probably a good idea to at least - * call "audio.begin()". + * + * \see boot() */ void begin(); - /// Flashlight mode - /** - * Turn the RGB LED and screen fully on. Called in the begin() function. + /** \brief + * Flashlight mode turns the RGB LED and display fully on. * - * Hold the UP button when booting to enable. Press the DOWN button to exit - * or simply turn off your Arduboy. It goes into a tight loop until the - * DOWN button is pressed. + * \details + * Checks if the UP button is pressed and if so turns the RGB LED and all + * display pixels fully on. Pressing the DOWN button will exit flashlight mode. + * + * This function is called by `begin()` and can be called by a sketch + * after `boot()`. + * + * \see begin() boot() */ void flashlight(); - /// Handle buttons held on startup for system control - /** + /** \brief + * Handle buttons held on startup for system control. + * + * \details + * This function is called by `begin()` and can be called by a sketch + * after `boot()`. + * * Hold the B button when booting to enter system control mode. * The B button must be held continuously to remain in this mode. - * Pressing other buttons will perform system control functions: + * Then, pressing other buttons will perform system control functions: * - * UP: Set "sound enabled" in EEPROM - * DOWN: Set "sound disabled" (mute) in EEPROM + * - UP: Set "sound enabled" in EEPROM + * - DOWN: Set "sound disabled" (mute) in EEPROM + * + * \see begin() boot() */ void systemButtons(); - /// Scrolls in the Arduboy logo + /** \brief + * Display the boot logo sequence. + * + * \details + * This function is called by `begin()` and can be called by a sketch + * after `boot()`. + * + * The Arduboy logo scrolls down from the top of the screen to the center + * while the RGB LEDs light in sequence. + * + * \see begin() boot() + */ void bootLogo(); - /// Clears display. + /** \brief + * Clear the display buffer. + * + * \details + * The entire contents of the screen buffer are cleared to BLACK. + */ void clear(); - /// Copies the contents of the screen buffer to the screen. - /** - * X and Y positions on the display are from the top left corner, thus a Y of 64 - * is the bottom of the screen and an X of 128 is the right side of the screen. - * "Color" or "value" means choosing whether a pixel is lit or not - if color is - * 0, the pixel is off (black), if color is 1, the pixel is on (white). + /** \brief + * Copy the contents of the display buffer to the display. + * + * \details + * The contents of the display buffer in RAM are copied to the display and + * will appear on the screen. */ void display(); - /// Sets a single pixel on the screen buffer to white or black. + /** \brief + * Set a single pixel in the display buffer to the specified color. + * + * \param x The X coordinate of the pixel. + * \param y The Y coordinate of the pixel. + * \param color The color of the pixel (optional; defaults to WHITE). + * + * \details + * The single pixel specified location in the display buffer is set to the + * specified color. The values WHITE or BLACK can be used for the color. + * If the `color` parameter isn't included, the pixel will be set to WHITE. + */ void drawPixel(int16_t x, int16_t y, uint8_t color = WHITE); - /// Returns the state of the given pixel in the screen buffer. - /** - * Return value will be 1 if the pixel is on (white) or 0 if the pixel is off (black). + /** \brief + * Returns the state of the given pixel in the screen buffer. + * + * \param x The X coordinate of the pixel. + * \param y The Y coordinate of the pixel. + * + * \return WHITE if the pixel is on or BLACK if the pixel is off. */ uint8_t getPixel(uint8_t x, uint8_t y); - /// Draw a circle of a defined radius. - /** - * Draws a circle in white or black. X and Y are the center point of the circle. + /** \brief + * Draw a circle of a given radius. + * + * \param x0 The X coordinate of the circle's center. + * \param y0 The Y coordinate of the circle's center. + * \param r The radius of the circle in pixels. + * \param color The circle's color (optional; defaults to WHITE). */ void drawCircle(int16_t x0, int16_t y0, uint8_t r, uint8_t color = WHITE); - /// Draws one or more "corners" of a circle. - void drawCircleHelper(int16_t x0, int16_t y0, uint8_t r, uint8_t cornername, uint8_t color = WHITE); + // Draw one or more "corners" of a circle. + // (Not officially part of the API) + void drawCircleHelper(int16_t x0, int16_t y0, uint8_t r, uint8_t corners, uint8_t color = WHITE); - /// Draws a filled-in circle. + /** \brief + * Draw a filled-in circle of a given radius. + * + * \param x0 The X coordinate of the circle's center. + * \param y0 The Y coordinate of the circle's center. + * \param r The radius of the circle in pixels. + * \param color The circle's color (optional; defaults to WHITE). + */ void fillCircle(int16_t x0, int16_t y0, uint8_t r, uint8_t color = WHITE); - /// Draws one or both vertical halves of a filled-in circle. - void fillCircleHelper(int16_t x0, int16_t y0, uint8_t r, uint8_t cornername, int16_t delta, uint8_t color = WHITE); + // Draw one or both vertical halves of a filled-in circle or + // rounded rectangle edge. + // (Not officially part of the API) + void fillCircleHelper(int16_t x0, int16_t y0, uint8_t r, uint8_t sides, int16_t delta, uint8_t color = WHITE); - /// Draws a line between two points. - /** - * Uses Bresenham's algorithm. + /** \brief + * Draw a line between two specified points. + * + * \param x0,x1 The X coordinates of the line ends. + * \param y0,y1 The Y coordinates of the line ends. + * \param color The line's color (optional; defaults to WHITE). + * + * \details + * Draw a line from the start point to the end point using + * Bresenham's algorithm. + * The start and end points can be at any location with respect to the other. */ void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint8_t color = WHITE); - /// Draws a rectangle of a width and height. + /** \brief + * Draw a rectangle of a specified width and height. + * + * \param x The X coordinate of the upper left corner. + * \param y The Y coordinate of the upper left corner. + * \param w The width of the rectangle. + * \param h The height of the rectangle. + * \param color The color of the pixel (optional; defaults to WHITE). + */ void drawRect(int16_t x, int16_t y, uint8_t w, uint8_t h, uint8_t color = WHITE); - /// Draws vertical line. + /** \brief + * Draw a vertical line. + * + * \param x The X coordinate of the upper start point. + * \param y The Y coordinate of the upper start point. + * \param h The height of the line. + * \param color The color of the line (optional; defaults to WHITE). + */ void drawFastVLine(int16_t x, int16_t y, uint8_t h, uint8_t color = WHITE); - /// Draws a horizontal line. + /** \brief + * Draw a horizontal line. + * + * \param x The X coordinate of the left start point. + * \param y The Y coordinate of the left start point. + * \param w The width of the line. + * \param color The color of the line (optional; defaults to WHITE). + */ void drawFastHLine(int16_t x, int16_t y, uint8_t w, uint8_t color = WHITE); - /// Draws a filled-in rectangle. + /** \brief + * Draw a filled-in rectangle of a specified width and height. + * + * \param x The X coordinate of the upper left corner. + * \param y The Y coordinate of the upper left corner. + * \param w The width of the rectangle. + * \param h The height of the rectangle. + * \param color The color of the pixel (optional; defaults to WHITE). + */ void fillRect(int16_t x, int16_t y, uint8_t w, uint8_t h, uint8_t color = WHITE); - /// Fills the screen buffer with white or black. + /** \brief + * Fill the screen buffer with the specified color. + * + * \param color The fill color (optional; defaults to WHITE). + */ void fillScreen(uint8_t color = WHITE); - /// Draws a rectangle with rounded edges. + /** \brief + * Draw a rectangle with rounded corners. + * + * \param x The X coordinate of the left edge. + * \param y The Y coordinate of the top edge. + * \param w The width of the rectangle. + * \param h The height of the rectangle. + * \param r The radius of the semicircles forming the corners. + * \param color The color of the rectangle (optional; defaults to WHITE). + */ void drawRoundRect(int16_t x, int16_t y, uint8_t w, uint8_t h, uint8_t r, uint8_t color = WHITE); - /// Draws a filled-in rectangle with rounded edges. + /** \brief + * Draw a filled-in rectangle with rounded corners. + * + * \param x The X coordinate of the left edge. + * \param y The Y coordinate of the top edge. + * \param w The width of the rectangle. + * \param h The height of the rectangle. + * \param r The radius of the semicircles forming the corners. + * \param color The color of the rectangle (optional; defaults to WHITE). + */ void fillRoundRect(int16_t x, int16_t y, uint8_t w, uint8_t h, uint8_t r, uint8_t color = WHITE); - /// Draws the outline of a triangle. + /** \brief + * Draw a triangle given the coordinates of each corner. + * + * \param x0,x1,x2 The X coordinates of the corners. + * \param y0,y1,y2 The Y coordinates of the corners. + * \param color The triangle's color (optional; defaults to WHITE). + * + * \details + * A triangle is drawn by specifying each of the three corner locations. + * The corners can be at any position with respect to the others. + */ void drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint8_t color = WHITE); - /// Draws a filled-in triangle. + /** \brief + * Draw a filled-in triangle given the coordinates of each corner. + * + * \param x0,x1,x2 The X coordinates of the corners. + * \param y0,y1,y2 The Y coordinates of the corners. + * \param color The triangle's color (optional; defaults to WHITE). + * + * \details + * A triangle is drawn by specifying each of the three corner locations. + * The corners can be at any position with respect to the others. + */ void fillTriangle (int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint8_t color = WHITE); - /// Draws a bitmap from program memory to a specific X/Y + /** \brief + * Draw a bitmap from an array in program memory. + * + * \param x The X coordinate of the top left pixel affected by the bitmap. + * \param y The Y coordinate of the top left pixel affected by the bitmap. + * \param bitmap A pointer to the bitmap array in program memory. + * \param w The width of the bitmap in pixels. + * \param h The height of the bitmap in pixels. + * \param color The color of pixels for bits set to 1 in the bitmap. + * If the value is INVERT, bits set to 1 will invert the + * corresponding pixel. (optional; defaults to WHITE). + * + * \details + * Bits set to 1 in the provided bitmap array will have their corresponding + * pixel set to the specified color. For bits set to 0 in the array, the + * corresponding pixel will be left unchanged. + * + * Each byte in the array specifies a vertical column of 8 pixels, with the + * least significant bit at the top. + * + * The array must be located in program memory by using the PROGMEM modifier. + */ void drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t w, uint8_t h, uint8_t color = WHITE); - /// Draws images that are bit-oriented horizontally. - /** - * This requires a lot of additional CPU power and will draw images slower - * than drawBitmap, where the images are stored in a format that - * allows them to be directly written to the screen. It is - * recommended you use drawBitmap when possible. + /** \brief + * Draw a bitmap from a horizontally oriented array in program memory. + * + * \param x The X coordinate of the top left pixel affected by the bitmap. + * \param y The Y coordinate of the top left pixel affected by the bitmap. + * \param bitmap A pointer to the bitmap array in program memory. + * \param w The width of the bitmap in pixels. + * \param h The height of the bitmap in pixels. + * \param color The color of pixels for bits set to 1 in the bitmap. + * (optional; defaults to WHITE). + * + * \details + * Bits set to 1 in the provided bitmap array will have their corresponding + * pixel set to the specified color. For bits set to 0 in the array, the + * corresponding pixel will be left unchanged. + * + * Each byte in the array specifies a horizontal row of 8 pixels, with the + * most significant bit at the left end of the row. + * + * The array must be located in program memory by using the PROGMEM modifier. + * + * \note + * This function requires a lot of additional CPU power and will draw images + * slower than `drawBitmap()`, which uses bitmaps that are stored in a format + * that allows them to be directly written to the screen. It is recommended + * you use `drawBitmap()` when possible. */ void drawSlowXYBitmap(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t w, uint8_t h, uint8_t color = WHITE); - /// Draw a compressed bitmap - /** - * Draws a bitmap starting at the given coordinates that has been compressed - * using an algorthm implemented by Team A.R.G. + /** \brief + * Draw a bitmap from an array of compressed data. + * + * \param sx The X coordinate of the top left pixel affected by the bitmap. + * \param sy The Y coordinate of the top left pixel affected by the bitmap. + * \param bitmap A pointer to the compressed bitmap array in program memory. + * \param color The color of pixels for bits set to 1 in the bitmap. + * + * \details + * Draw a bitmap starting at the given coordinates from an array that has + * been compressed using an algorthm implemented by Team A.R.G. * For more information see: * https://github.com/TEAMarg/drawCompressed * https://github.com/TEAMarg/Cabi + * + * Bits set to 1 in the provided bitmap array will have their corresponding + * pixel set to the specified color. For bits set to 0 in the array, the + * corresponding pixel will be left unchanged. + * + * The array must be located in program memory by using the PROGMEM modifier. */ void drawCompressed(int16_t sx, int16_t sy, const uint8_t *bitmap, uint8_t color = WHITE); - /// Get a pointer to the display buffer. - unsigned char* getBuffer(); + /** \brief + * Get a pointer to the display buffer in RAM. + * + * \return A pointer to the display buffer array in RAM + * + * \details + * The location of the display buffer in RAM, which is displayed using + * `display()`, can be gotten using this function. The buffer can then be + * read and directly manipulated. + */ + uint8_t* getBuffer(); - /// Seeds the random number generator with entropy from the temperature, voltage reading, and microseconds since boot. - /** - * This method is still most effective when called semi-randomly such - * as after a user hits a button to start a game or other semi-random - * events + /** \brief + * Seed the random number generator with a random value. + * + * \details + * The Arduino random number generator is seeded with a random value + * derrived from entropy from the temperature, voltage reading, and + * microseconds since boot. + * + * This method is still most effective when called after a semi-random time, + * such as after a user hits a button to start a game or other semi-random + * event. */ void initRandomSeed(); - /// Swap the references of two pointers. + // Swap the values of two int16_t variables passed by reference. void swap(int16_t& a, int16_t& b); - /// Sets the frame rate in frames per second. + /** \brief + * Set the frame rate used by the frame control functions. + * + * \param rate The desired frame rate in frames per second. + * + * Set the frame rate, in frames per second, used by `nextFrame()` to update + * frames at a given rate. If this function isn't used, the default rate will + * be 60. + * + * Normally, the frame rate would be set to the desired value once, at the + * start of the game, but it can be changed at any time to alter the frame + * update rate. + * + * \see nextFrame() + */ void setFrameRate(uint8_t rate); - /// Returns "true" if it's time for the next frame. + /** \brief + * Indicate that it's time to render the next frame. + * + * \return `true` if it's time for the next frame. + * + * \details + * When this function returns `true`, the amount of time has elapsed to + * display the next frame, as specified by `setFrameRate()`. + * + * This function will normally be called at the start of the rendering loop + * which would wait for `true` to be returned before rendering and + * displaying the next frame. + * + * example: + * \code + * void loop() { + * if (!arduboy.nextFrame()) { + * return; // go back to the start of the loop + * } + * // render and display the next frame + * } + * \endcode + * + * \see setFrameRate() + */ bool nextFrame(); - /// Returns "true" if the current frame number is evenly divisible by the specified number. - /** - * If called with the same value each time, will return "true" if the given - * number of frames has elapsed since the last frame in which it was "true". + + /** \brief + * Indicate if the specified number of frames has elapsed. + * + * \param frames The desired number of elapsed frames. + * + * \return `true` if the specified number of frames has elapsed. + * + * This function should be called with the same value each time for a given + * event. It will return `true` if the given number of frames has elapsed + * since the previous frame in which it returned `true`. + * + * For example, if you wanted to fire a shot every 5 frames while the A button + * is being held down: + * + * \code + * if (arduboy.everyXframes(5)) { + * if arduboy.pressed(A_BUTTON) { + * fireShot(); + * } + * } + * \endcode + * + * \see setFrameRate() nextFrame() */ bool everyXFrames(uint8_t frames); - /// Returns the load on the CPU as a percentage. - /** - * This is based on how much of the time your app is spending rendering - * frames. This number can be higher than 100 if your app is rendering - * really slowly. + /** \brief + * Return the load on the CPU as a percentage. + * + * \return The load on the CPU as a percentage of the total frame time. + * + * \details + * The returned value gives the time spent processing a frame as a percentage + * the total time allotted for a frame, as determined by the frame rate. + * + * This function normally wouldn't be used in the final program. It is + * intended for use during program development as an aid in helping with + * frame timing. + * + * \note + * The percentage returned can be higher than 100 if more time is spent + * processing a frame than the time allotted per frame. This would indicate + * that the frame rate should be made slower or the frame processing code + * should be optimized to run faster. + * + * \see setFrameRate() nextFrame() */ int cpuLoad(); - /// useful for getting raw approximate voltage values + // Useful for getting raw approximate voltage values. uint16_t rawADC(uint8_t adc_bits); - /// Test if the specified buttons are pressed - /** - * Returns "true" if all the buttons in the provided mask are currently pressed. + /** \brief + * Test if the specified buttons are pressed. + * + * \param buttons A bit mask indicating which buttons to test. * (Can be a single button) - * E.g. `if (pressed(LEFT_BUTTON + A_BUTTON))` + * + * \return `true` if *all* buttons in the provided mask are currently pressed. + * + * \details + * Read the state of the buttons and return `true` if all the buttons in the + * specified mask are being pressed. + * + * Example: `if (pressed(LEFT_BUTTON + A_BUTTON))` + * + * \note + * This function does not perform any button debouncing. */ bool pressed(uint8_t buttons); - /// Test if the specified buttons are not pressed - /** - * Returns "true" if all the buttons in the provided mask are currently released. + /** \brief + * Test if the specified buttons are not pressed. + * + * \param buttons A bit mask indicating which buttons to test. * (Can be a single button) - * E.g. `if (notPressed(LEFT_BUTTON))` + * + * \return `true` if *all* buttons in the provided mask are currently + * released. + * + * \details + * Read the state of the buttons and return `true` if all the buttons in the + * specified mask are currently released. + * + * Example: `if (notPressed(UP_BUTTON))` + * + * \note + * This function does not perform any button debouncing. */ bool notPressed(uint8_t buttons); - /// Poll the hardware buttons and track state over time. - /** - * Should be called either in the main `loop()` or as part of the - * frame system at the start of rendering a frame. + /** \brief + * Poll the buttons and track their state over time. + * + * \details + * Read and save the current state of the buttons and also keep track of the + * button state when this function was previouly called. These states are + * used by the `justPressed()` and `justReleased()` functions to determine + * if a button has changed state between now and the previous call to + * `pollButtons()`. + * + * This function should be called once at the start of each new frame. * * The `justPressed()` and `justReleased()` functions rely on this function. + * + * example: + * \code + * void loop() { + * if (!arduboy.nextFrame()) { + * return; + * } + * arduboy.pollButtons(); + * + * // use justPressed() as necessary to determine if a button was just pressed + * \endcode + * + * \note + * As long as the elapsed time between calls to this function is long + * enough, buttons will be naturally debounced. Calling it once per frame at + * a frame rate of 60 or lower (or possibly somewhat higher), should be + * sufficient. + * + * \see justPressed() justReleased() */ void pollButtons(); - /// Check if a button has just been pressed - /** - * Will return "true" if the given button was pressed between the latest + /** \brief + * Check if a button has just been pressed. + * + * \param button The button to test for. Only one button should be specified. + * + * \return `true` if the specified button has just been pressed. + * + * \details + * Return `true` if the given button was pressed between the latest * call to `pollButtons()` and previous call to `pollButtons()`. - * If the button has been held down over multiple polls this function will - * return "false". This function should only be used to test a single button. + * If the button has been held down over multiple polls, this function will + * return `false`. + * + * There is no need to check for the release of the button since it must have + * been released for this function to return `true` when pressed again. + * + * This function should only be used to test a single button. + * + * \see pollButtons() justReleased() */ bool justPressed(uint8_t button); - /// Check if a button has just been released - /** - * Will return "true" if the given button was released between the latest - * call to `pollButtons()` and previous call to `pollButtons()`. - * If the button has been released over multiple polls this function will - * return "false". This function should only be used to test a single button. + /** \brief + * Check if a button has just been released. + * + * \param button The button to test for. Only one button should be specified. + * + * \return `true` if the specified button has just been released. + * + * \details + * Return `true` if the given button, having previously been pressed, + * was released between the latest call to `pollButtons()` and previous call + * to `pollButtons()`. If the button has remained released over multiple + * polls, this function will return `false`. + * + * There is no need to check for the button having been pressed since it must + * have been previously pressed for this function to return `true` upon + * release. + * + * This function should only be used to test a single button. + * + * \note + * There aren't many cases where this function would be needed. Wanting to + * know if a button has been released, without knowing when it was pressed, + * is uncommon. + * + * \see pollButtons() justPressed() */ bool justReleased(uint8_t button); - /// Test if a point is within a rectangle - /** - * Returns "true" if the point is within the rectangle. + /** \brief + * Test if a point falls within a rectangle + * + * \param point A structure describing the location of the point. + * \param rect A structure describing the location and size of the rectangle. + * + * \return `true` if the specified point is within the specified rectangle. + * + * This function is intended to detemine if an object, whose boundaries are + * are defined by the given rectangle, is in contact with the given point. + * + * \see Point Rect */ bool collide(Point point, Rect rect); - /// Test if a rectangle is intersecting with another rectangle. - /** - * Returns "true" if the first rectangle is intersecting the second. + /** \brief + * Test if a rectangle is intersecting with another rectangle. + * + * \param rect1,rect2 Structures describing the size and locations of the + * rectangles. + * + * \return `true1 if the first rectangle is intersecting the second. + * + * This function is intended to detemine if an object, whose boundaries are + * are defined by the given rectangle, is in contact with another rectangular + * object. + * + * \see Rect */ bool collide(Rect rect1, Rect rect2); @@ -312,44 +786,195 @@ class Arduboy2Base : public Arduboy2Core //========== Arduboy2 ========== //============================== +/** \brief + * The main functions provided for writing sketches for the Arduboy, + * _including_ text output. + * + * \details + * This class is derived from Arduboy2Base. It provides text output functions + * in addition to all the functions inherited from Arduboy2Base. + * + * \see Arduboy2Base + */ class Arduboy2 : public Print, public Arduboy2Base { public: Arduboy2(); - /// Writes a single ASCII character to the screen. + /** \class Print + * \brief + * The Arduino `Print` class is available for writing text to the screen + * buffer. + * + * \details + * For an `Arduboy2` class object, functions provided by the Arduino `Print` + * class can be used to write text to the screen buffer, in the same manner + * as the Arduino `Serial.print()`, etc., functions. + * + * Print will use the `write()` function to actually draw each character + * in the screen buffer. + * + * See: + * https://www.arduino.cc/en/Serial/Print + * + * Example: + * \code + * int value = 42; + * + * arduboy.println("Hello World"); // Prints "Hello World" and then moves the + * // text cursor to the start of the next line + * arduboy.print(value); // Prints "42" + * arduboy.print('\n'); // Moves the text cursor to the start of the next line + * arduboy.print(78, HEX) // Prints "4E" (78 in hexadecimal) + * \endcode + * + * \see Arduboy2::write() + */ + + /** \brief + * Write a single ASCII character at the current text cursor location. + * + * \param c The ASCII value of the character to be written. + * + * \return The number of characters written (will always be 1). + * + * \details + * This is the Arduboy implemetation of the Arduino virtual `write()` + * function. The single ASCII character specified is written to the + * the screen buffer at the current text cursor. The text cursor is then + * moved to the next character position in the screen buffer. This new cursor + * position will depend on the current text size and possibly the current + * wrap mode. + * + * Two special characters are handled: + * + * - The newline character `\n`. This will move the text cursor to the start + * of the next line based on the current text size. + * - The carriage return character `\r`. This character will be ignored. + * + * \note + * This function is rather low level and, although it's available as a public + * function, it wouldn't normally be used. In most cases the Arduino Print + * class should be used for writing text. + * + * \see Print setTextSize() setTextWrap() + */ virtual size_t write(uint8_t); - /// Draws an ASCII character at a point. + /** \brief + * Draw a single ASCII character at the specified location in the screen + * buffer. + * + * \param x The X coordinate, in pixels, for where to draw the character. + * \param y The Y coordinate, in pixels, for where to draw the character. + * \param c The ASCII value of the character to be drawn. + * \param color the forground color of the character. + * \param bg the background color of the character. + * \param size The size of the character to draw. + * + * \details + * The specified ASCII character is drawn starting at the provided + * coordinate. The point specified by the X and Y coordinates will be the + * top left corner of the character. + * + * \note + * This is a low level function used by the `write()` function to draw a + * character. Although it's available as a public function, it wouldn't + * normally be used. In most cases the Arduino Print class should be used for + * writing text. + * + * \see Print write() setTextColor() setTextBackground() setTextSize() + */ void drawChar(int16_t x, int16_t y, unsigned char c, uint8_t color, uint8_t bg, uint8_t size); - /// Sets the location of the text cursor. + /** \brief + * Set the location of the text cursor. + * + * \param x The X coordinate, in pixels, for the new location of the text cursor. + * \param y The Y coordinate, in pixels, for the new location of the text cursor. + * + * \details + * The location of the text cursor is set the the specified coordinates. + * The coordinates are in pixels. Since the coordinates can specify any pixel + * location, the text does not have to be placed on specific rows. + * As with all drawing functions, location 0, 0 is the top left corner of + * the display. The cursor location will be the top left corner of the next + * character written. + */ void setCursor(int16_t x, int16_t y); - /// Get the text cursor X position - uint16_t getCursorX(); + /** \brief + * Get the X coordinate of the current text cursor position. + * + * \return The X coordinate of the current text cursor position. + * + * \details + * The X coordinate returned is a pixel location with 0 indicating the + * leftmost column. + */ + int16_t getCursorX(); - /// Get the text cursor Y position - uint16_t getCursorY(); + /** \brief + * Get the Y coordinate of the current text cursor position. + * + * \return The Y coordinate of the current text cursor position. + * + * \details + * The Y coordinate returned is a pixel location with 0 indicating the + * topmost row. + */ + int16_t getCursorY(); - /// Sets the text foreground color + /** \brief + * Set the text foreground color. + * + * \param color The color to be used for following text. + */ void setTextColor(uint8_t color); - /// Sets the text background color + /** \brief + * Set the text background color. + * + * \param bg The background color to be used for following text. + */ void setTextBackground(uint8_t bg); - /// Set the text size - /** - * Individual ASCII characters are 6x8 pixels - * (5x7 with spacing on two edges). The size is a pixel multiplier, - * so a size of 2 means each character will be 12x16, etc. + /** \brief + * Set the text character size. + * + * \param s The text size multiplier. Must be 1 or higher. + * + * \details + * Setting a text size of 1 will result in standard size characters which + * occupy 6x8 pixels (the result of 5x7 characters with spacing on the + * right and bottom edges). + * + * The value specified is a multiplier. A value of 2 will double the + * size so they will occupy 12x16 pixels. A value of 3 will result in + * 18x24, etc. */ void setTextSize(uint8_t s); - /// Sets whether text will wrap at screen edges. + /** \brief + * Set or disable text wrap mode. + * + * \param w `true` enables text wrap mode. `false` disables it. + * + * \details + * Text wrap mode is enabled by specifying `true`. In wrap mode, the text + * cursor will be moved to the start of the next line (based on the current + * text size) if the following character wouldn't fit entirely at the end of + * the current line. + + * If wrap mode is disabled, characters will continue to be written to the + * same line. A character at the right edge of the screen may only be + * partially displayed and additional characters will be off screen. + */ void setTextWrap(bool w); - /// Clears the display and sets the cursor to 0, 0 + /** \brief + * Clear the display buffer and set the text cursor to location 0, 0 + */ void clear(); protected: diff --git a/src/Arduboy2Audio.cpp b/src/Arduboy2Audio.cpp index 12bd95b..efefef4 100644 --- a/src/Arduboy2Audio.cpp +++ b/src/Arduboy2Audio.cpp @@ -1,3 +1,9 @@ +/** + * @file Arduboy2Audio.cpp + * \brief + * The Arduboy2Audio class for speaker and sound control. + */ + #include "Arduboy2.h" #include "Arduboy2Audio.h" diff --git a/src/Arduboy2Audio.h b/src/Arduboy2Audio.h index 14e8732..8cf19c9 100644 --- a/src/Arduboy2Audio.h +++ b/src/Arduboy2Audio.h @@ -1,16 +1,133 @@ +/** + * @file Arduboy2Audio.h + * \brief + * The Arduboy2Audio class for speaker and sound control. + */ + #ifndef ARDUBOY2_AUDIO_H #define ARDUBOY2_AUDIO_H #include #include +/** \brief + * Provide speaker and sound control. + * + * \details + * This class provides functions to initialize the speaker and control the + * enabling and disabling (muting) of sound. It doesn't provide any functions + * to actually produce sound. + * + * The state of sound muting is stored in system EEPROM and so is retained + * over power cycles. + * + * An Arduboy2Audio class object named `audio` will be created by the + * Arduboy2Base class, so there is no need for a sketch itself to create an + * Arduboy2Audio object. Arduboy2Audio functions can be called using the + * Arduboy2 or Arduboy2Base `audio` object. + * + * Example: + * + * \code + * #include + * + * Arduboy2 arduboy; + * + * // Arduboy2Audio functions can be called as follows: + * arduboy.audio.on(); + * arduboy.audio.off(); + * \endcode + * + * \note + * \parblock + * In order for this class to be fully functional, the external library or + * functions used by a sketch to actually to produce sounds should be compliant + * with this class. This means they should only produce sound if it is enabled, + * or mute the sound if it's disabled. The `enabled()` function can be used + * to determine if sound is enabled or muted. Generally a compliant library + * would accept the `enabled()` function as an initialization parameter and + * then call it as necessary to determine the current state. + * + * For example, the ArduboyTones and ArduboyPlaytune libraries require an + * `enabled()` type function to be passed as a parameter in the constructor, + * like so: + * + * \code + * #include + * #include + * + * Arduboy2 arduboy; + * ArduboyTones sound(arduboy.audio.enabled); + * \endcode + * \endparblock + */ class Arduboy2Audio { public: + /** \brief + * Initialize the speaker based on the current mute setting. + * + * \details + * The speaker is initialized based on the current mute setting saved in + * system EEPROM. This function is called by `Arduboy2Base::begin()` so it + * isn't normally required to call it within a sketch. However, if + * `Arduboy2Core::boot()` is used instead of `Arduboy2Base::begin()` and the + * sketch includes sound, then this function should be called after `boot()`. + */ void static begin(); + + /** \brief + * Turn sound on. + * + * \details + * The system is configured to generate sound. This function sets the sound + * mode only until the unit is powered off. To save the current mode use + * `saveOnOff()`. + * + * \see off() saveOnOff() + */ void static on(); + + /** \brief + * Turn sound off (mute). + * + * \details + * The system is configured to not produce sound (mute). This function sets + * the sound mode only until the unit is powered off. To save the current + * mode use `saveOnOff()`. + * + * \see on() saveOnOff() + */ void static off(); + + /** \brief + * Save the current sound state in EEPROM. + * + * \details + * The current sound state, set by `on()` or `off()`, is saved to the + * reserved system area in EEPROM. This allows the state to carry over between + * power cycles and after uploading a different sketch. + * + * \note + * EEPROM is limited in the number of times it can be written to. Sketches + * should not continuously change and then save the state rapidly. + * + * \see on() off() + */ void static saveOnOff(); + + /** \brief + * Get the current sound state. + * + * \return `true` if sound is currently enabled (not muted). + * + * \details + * This function should be used by code that actually generates sound. + * If `true` is returned, sound can be produced. If `false` is returned, + * sound should be muted. + * + * \see on() off() + */ bool static enabled(); protected: diff --git a/src/Arduboy2Core.cpp b/src/Arduboy2Core.cpp index e83640d..81d6a6e 100644 --- a/src/Arduboy2Core.cpp +++ b/src/Arduboy2Core.cpp @@ -1,3 +1,9 @@ +/** + * @file Arduboy2Core.cpp + * \brief + * The Arduboy2Core class for Arduboy hardware initilization and control. + */ + #include "Arduboy2Core.h" // need to redeclare these here since we declare them static in .h @@ -35,7 +41,7 @@ const uint8_t PROGMEM pinBootProgram[] = { }; const uint8_t PROGMEM lcdBootProgram[] = { - // boot defaults are commented out but left here incase they + // boot defaults are commented out but left here in case they // might prove useful for reference // // Further reading: https://www.adafruit.com/datasheets/SSD1306.pdf @@ -320,7 +326,7 @@ void Arduboy2Core::setRGBled(uint8_t red, uint8_t green, uint8_t blue) #endif } - void Arduboy2Core::digitalWriteRGB(uint8_t red, uint8_t green, uint8_t blue) +void Arduboy2Core::digitalWriteRGB(uint8_t red, uint8_t green, uint8_t blue) { #ifdef ARDUBOY_10 digitalWrite(RED_LED, red); diff --git a/src/Arduboy2Core.h b/src/Arduboy2Core.h index f110c6b..9039c24 100644 --- a/src/Arduboy2Core.h +++ b/src/Arduboy2Core.h @@ -1,3 +1,9 @@ +/** + * @file Arduboy2Core.h + * \brief + * The Arduboy2Core class for Arduboy hardware initilization and control. + */ + #ifndef ARDUBOY2_CORE_H #define ARDUBOY2_CORE_H @@ -11,8 +17,8 @@ // main hardware compile flags #if !defined(ARDUBOY_10) && !defined(AB_DEVKIT) -/// defaults to Arduboy Release 1.0 if not using a boards.txt file -/** +/* defaults to Arduboy Release 1.0 if not using a boards.txt file + * * we default to Arduboy Release 1.0 if a compile flag has not been * passed to us from a boards.txt file * @@ -32,8 +38,8 @@ #define SAFE_MODE //< include safe mode (44 bytes) #endif -#define RGB_ON LOW // for digitially setting an RGB LED on -#define RGB_OFF HIGH // for digitially setting an RGB LED off +#define RGB_ON LOW /**< For digitially setting an RGB LED on using digitalWriteRGB() */ +#define RGB_OFF HIGH /**< For digitially setting an RGB LED off using digitalWriteRGB() */ #ifdef ARDUBOY_10 @@ -41,11 +47,11 @@ #define DC 4 #define RST 6 -#define RED_LED 10 -#define GREEN_LED 11 -#define BLUE_LED 9 -#define TX_LED 30 -#define RX_LED 17 +#define RED_LED 10 /**< The pin number for the red color in the RGB LED. */ +#define GREEN_LED 11 /**< The pin number for the greem color in the RGB LED. */ +#define BLUE_LED 9 /**< The pin number for the blue color in the RGB LED. */ +#define TX_LED 30 /**< The pin number for the transmit indicator LED. */ +#define RX_LED 17 /**< The pin number for the receive indicator LED. */ // pin values for buttons, probably shouldn't use these #define PIN_LEFT_BUTTON A2 @@ -56,15 +62,15 @@ #define PIN_B_BUTTON 8 // bit values for button states -#define LEFT_BUTTON _BV(5) -#define RIGHT_BUTTON _BV(6) -#define UP_BUTTON _BV(7) -#define DOWN_BUTTON _BV(4) -#define A_BUTTON _BV(3) -#define B_BUTTON _BV(2) +#define LEFT_BUTTON _BV(5) /**< The Left button value for functions requiring a bitmask */ +#define RIGHT_BUTTON _BV(6) /**< The Right button value for functions requiring a bitmask */ +#define UP_BUTTON _BV(7) /**< The Up button value for functions requiring a bitmask */ +#define DOWN_BUTTON _BV(4) /**< The Down button value for functions requiring a bitmask */ +#define A_BUTTON _BV(3) /**< The A button value for functions requiring a bitmask */ +#define B_BUTTON _BV(2) /**< The B button value for functions requiring a bitmask */ -#define PIN_SPEAKER_1 5 -#define PIN_SPEAKER_2 13 +#define PIN_SPEAKER_1 5 /**< The pin number of the first lead of the speaker */ +#define PIN_SPEAKER_2 13 /**< The pin number of the second lead of the speaker */ #define PIN_SPEAKER_1_PORT &PORTC #define PIN_SPEAKER_2_PORT &PORTC @@ -127,162 +133,363 @@ // ----- -#define WIDTH 128 -#define HEIGHT 64 +#define WIDTH 128 /**< The width of the display in pixels */ +#define HEIGHT 64 /**< The height of the display in pixels */ #define COLUMN_ADDRESS_END (WIDTH - 1) & 127 // 128 pixels wide #define PAGE_ADDRESS_END ((HEIGHT/8)-1) & 7 // 8 pages high - +/** \brief + * Lower level functions generally dealing directly with the hardware. + * + * \details + * This class is inherited by Arduboy2Base and thus also Arduboy2, so wouldn't + * normally be used directly by a sketch. + */ class Arduboy2Core { public: Arduboy2Core(); - /// allows the CPU to idle between frames - /** - * This puts the CPU in "Idle" sleep mode. You should call this as often - * as you can for the best power savings. The timer 0 overflow interrupt - * will wake up the chip every 1ms - so even at 60 FPS a well written + /** \brief + * Idle the CPU to save power. + * + * \details + * This puts the CPU in _idle_ sleep mode. You should call this as often + * as you can for the best power savings. The timer 0 overflow interrupt + * will wake up the chip every 1ms, so even at 60 FPS a well written * app should be able to sleep maybe half the time in between rendering * it's own frames. - * - * See the Arduboy class nextFrame() for an example of how to use idle() - * in a frame loop. */ void static idle(); - void static LCDDataMode(); //< put the display in data mode + /** \brief + * Put the display into data mode. + * + * \details + * When placed in data mode, data that is sent to the display will be + * considered as data to be displayed. + * + * \note + * This is a low level function that is not intended for general use in a + * sketch. It has been made public and documented for use by derived + * classes. + */ + void static LCDDataMode(); - /// put the display in command mode - /** - * See SSD1306 documents for available commands and command sequences. + /** \brief + * Put the display into command mode. + * + * \details + * When placed in command mode, data that is sent to the display will be + * treated as commands. + * + * See the SSD1306 controller and OLED display documents for available + * commands and command sequences. * * Links: + * * - https://www.adafruit.com/datasheets/SSD1306.pdf - * - http://www.eimodule.com/download/SSD1306-OLED-Controller.pdf + * - http://www.buydisplay.com/download/manual/ER-OLED013-1_Series_Datasheet.pdf + * + * \note + * This is a low level function that is not intended for general use in a + * sketch. It has been made public and documented for use by derived + * classes. + * + * \see sendLCDCommand() */ void static LCDCommandMode(); - uint8_t static width(); //< return display width - uint8_t static height(); // < return display height - - /// get current state of all buttons (bitmask) - /** - * Bit mask that is returned: + /** \brief + * Get the width of the display in pixels. * - * Hi Low - * DevKit 00000000 - reserved - * -DLU-RAB D down - * U up - * 1.0 00000000 L left - * URLDAB-- R right + * \return The width of the display in pixels. * - * Of course you shouldn't worry about bits (they may change with future - * hardware revisions) and should instead use the button defines: - * LEFT_BUTTON, A_BUTTON, UP_BUTTON, etc. + * \note + * In most cases, the defined value `WIDTH` would be better to use instead + * of this function. */ + uint8_t static width(); + /** \brief + * Get the height of the display in pixels. + * + * \return The height of the display in pixels. + * + * \note + * In most cases, the defined value `HEIGHT` would be better to use instead + * of this function. + */ + uint8_t static height(); + + /** \brief + * get current state of all buttons as a bitmask. + * + * \return A bitmask of the state of all the buttons. + * + * \details + * The returned mask contains a bit for each button. For any pressed button, + * its bit will be 1. For released buttons their associated bits will be 0. + * + * The following defined mask values should be used for the buttons: + * + * LEFT_BUTTON, RIGHT_BUTTON, UP_BUTTON, DOWN_BUTTON, A_BUTTON, B_BUTTON + */ uint8_t static buttonsState(); - // paints 8 pixels (vertically) from a single byte - // - 1 is lit, 0 is unlit - // - // NOTE: You probably wouldn't actually use this, you'd build something - // higher level that does it's own calls to SPI.transfer(). It's - // included for completeness since it seems there should be some very - // rudimentary low-level draw function in the core that supports the - // minimum unit that the hardware allows (which is a strip of 8 pixels) - // - // This routine starts in the top left and then across the screen. - // After each "page" (row) of 8 pixels is drawn it will shift down - // to start drawing the next page. To paint the full screen you call - // this function 1,024 times. - // - // Example: - // - // X = painted pixels, . = unpainted - // - // blank() paint8Pixels() 0xFF, 0, 0x0F, 0, 0xF0 - // v TOP LEFT corner (8x9) v TOP LEFT corner - // ........ (page 1) X...X... (page 1) - // ........ X...X... - // ........ X...X... - // ........ X...X... - // ........ X.X..... - // ........ X.X..... - // ........ X.X..... - // ........ (end of page 1) X.X..... (end of page 1) - // ........ (page 2) ........ (page 2) + /** \brief + * Paint 8 pixels vertically to the display. + * + * \param pixels A byte whose bits specify a vertical column of 8 pixels. + * + * \details + * A byte representing a vertical column of 8 pixels is written to the + * display at the current page and column address. The address is then + * incremented. The page/column address will wrap to the start of the + * display (the top left) when it increments past the end (lower right). + * + * The least significant bit represents the top pixel in the column. + * A bit set to 1 is lit, 0 is unlit. + * + * Example: + * + * X = lit pixels, . = unlit pixels + * + * blank() paint8Pixels() 0xFF, 0, 0xF0, 0, 0x0F + * v TOP LEFT corner (8x9) v TOP LEFT corner + * . . . . . . . . (page 1) X . . . X . . . (page 1) + * . . . . . . . . X . . . X . . . + * . . . . . . . . X . . . X . . . + * . . . . . . . . X . . . X . . . + * . . . . . . . . X . X . . . . . + * . . . . . . . . X . X . . . . . + * . . . . . . . . X . X . . . . . + * . . . . . . . . (end of page 1) X . X . . . . . (end of page 1) + * . . . . . . . . (page 2) . . . . . . . . (page 2) + */ void static paint8Pixels(uint8_t pixels); - /// paints an entire image directly to hardware (from PROGMEM) - /* - * Each byte will be 8 vertical pixels, painted in the same order as - * explained above in paint8Pixels. + /** \brief + * Paints an entire image directly to the display from program memory. + * + * \param image A byte array in program memory representing the entire + * contents of the display. + * + * \details + * The contents of the specified array in program memory is written to the + * display. Each byte in the array represents a vertical column of 8 pixels + * with the least significant bit at the top. The bytes are written starting + * at the top left, progressing horizontally and wrapping at the end of each + * row, to the bottom right. The size of the array must exactly match the + * number of pixels in the entire display. + * + * \see paint8Pixels() */ void static paintScreen(const uint8_t *image); - /// paints an entire image directly to hardware (from RAM) - /* - * Each byte will be 8 vertical pixels, painted in the same order as - * explained above in paint8Pixels. + /** \brief + * Paints an entire image directly to the display from an array in RAM. + * + * \param image A byte array in RAM representing the entire contents of + * the display. + * + * \details + * The contents of the specified array in RAM is written to the display. + * Each byte in the array represents a vertical column of 8 pixels with + * the least significant bit at the top. The bytes are written starting + * at the top left, progressing horizontally and wrapping at the end of + * each row, to the bottom right. The size of the array must exactly + * match the number of pixels in the entire display. + * + * \see paint8Pixels() */ void static paintScreen(uint8_t image[]); - /// paints a blank (black) screen to hardware + /** \brief + * Blank the display screen by setting all pixels off. + * + * \details + * All pixels on the screen will be written with a value of 0 to turn + * them off. + */ void static blank(); - /// invert the display or set to normal - /** - * when inverted, a pixel set to 0 will be on + /** \brief + * Invert the entire display or set it back to normal. + * + * \param inverse `true` will invert the display. `false` will set the + * display to no-inverted. + * + * Calling this function with a value of `true` will set the display to + * inverted mode. A pixel with a value of 0 will be on and a pixel set to 1 + * will be off. + * + * Once in inverted mode, the display will remain this way + * until it is set back to non-inverted mode by calling this function with + * `false`. */ void static invert(bool inverse); - /// turn all display pixels on, or display the buffer contents - /** - * when set to all pixels on, the display buffer will be - * ignored but not altered + /** \brief + * Turn all display pixels on or display the buffer contents. + * + * \param on `true` turns all pixels on. `false` displays the contents + * of the hardware display buffer. + * + * \details + * Calling this function with a value of `true` will override the contents + * of the hardware display buffer and turn all pixels on. The contents of + * the hardware buffer will remain unchanged. + * + * Calling this function with a value of `false` will set the normal state + * of displaying the contents of the hardware display buffer. + * + * \note + * All pixels will be lit even if the display is in inverted mode. + * + * \see invert() */ void static allPixelsOn(bool on); - /// flip the display vertically or set to normal + /** \brief + * Flip the display vertically or set it back to normal. + * + * \param flipped `true` will set vertical flip mode. `false` will set + * normal vertical orientation. + * + * \details + * Calling this function with a value of `true` will cause the Y coordinate + * to start at the bottom edge of the display instead of the top, + * effectively flipping the display vertically. + * + * Once in vertical flip mode, it will remain this way until normal + * vertical mode is set by calling this function with a value of `false`. + * + * \see flipHorizontal() + */ void static flipVertical(bool flipped); - /// flip the display horizontally or set to normal + /** \brief + * Flip the display horizontally or set it back to normal. + * + * \param flipped `true` will set horizontal flip mode. `false` will set + * normal horizontal orientation. + * + * \details + * Calling this function with a value of `true` will cause the X coordinate + * to start at the left edge of the display instead of the right, + * effectively flipping the display horizontally. + * + * Once in horizontal flip mode, it will remain this way until normal + * horizontal mode is set by calling this function with a value of `false`. + * + * \see flipVertical() + */ void static flipHorizontal(bool flipped); - /// send a single byte command to the OLED + /** \brief + * Send a single command byte to the display. + * + * \param command The command byte to send to the display. + * + * The display will be set to command mode then the specified command + * byte will be sent. The display will then be set to data mode. + * Multi-byte commands can be sent by calling this function multiple times. + * + * \note + * Sending improper commands to the display can place it into invalid or + * unexpected states, possibly even causing physical damage. + */ void static sendLCDCommand(uint8_t command); - /// set the light output of the RGB LED - /** - * The brightness of each LED can be set to a value from - * 0 (fully off) to 255 (fully on). + /** \brief + * Set the light output of the RGB LED. + * + * \param red,green,blue The brightness value for each LED. + * + * \details + * The RGB LED is actually individual red, green and blue LEDs placed + * very close together in a single package. By setting the brightness of + * each LED, the RGB LED can show various colors and intensities. + * The brightness of each LED can be set to a value from 0 (fully off) + * to 255 (fully on). + * + * \note + * Certain libraries that take control of the hardware timers may interfere + * with the ability of this function to properly control the RGB LED. + *_ArduboyPlaytune_ is one such library known to do this. + * The digitalWriteRGB() function will still work properly in this case. + * + * \note + * Many of the Kickstarter Arduboys were accidentally shipped with the + * RGB LED installed incorrectly. For these units, the green LED cannot be + * lit. As long as the green led is set to off, setting the red LED will + * actually control the blue LED and setting the blue LED will actually + * control the red LED. If the green LED is turned fully on, none of the + * LEDs will light. + * + * \see digitalWriteRGB() */ void static setRGBled(uint8_t red, uint8_t green, uint8_t blue); - /// set the RGB LEDs digitally, to either fully on or fully off - /** - * Use value RGB_ON or RGB_OFF for each color of LED. + /** \brief + * Set the RGB LEDs digitally, to either fully on or fully off. + * + * \param red,green,blue Use value RGB_ON or RGB_OFF to set each LED. + * + * \details + * The RGB LED is actually individual red, green and blue LEDs placed + * very close together in a single package. This function will set each + * LED either on or off, to set the RGB LED to 7 different colors at their + * highest brightness or turn it off. + * + * The colors are as follows: + * + * RED LED GREEN_LED BLUE_LED COLOR + * ------- --------- -------- ----- + * RGB_OFF RGB_OFF RGB_OFF OFF + * RGB_OFF RGB_OFF RGB_ON Blue + * RGB_OFF RGB_ON RGB_OFF Green + * RGB_OFF RGB_ON RGB_ON Cyan + * RGB_ON RGB_OFF RGB_OFF Red + * RGB_ON RGB_OFF RGB_ON Magenta + * RGB_ON RGB_ON RGB_OFF Yellow + * RGB_ON RGB_ON RGB_ON White + * + * \note + * Many of the Kickstarter Arduboys were accidentally shipped with the + * RGB LED installed incorrectly. For these units, the green LED cannot be + * lit. As long as the green led is set to off, turning on the red LED will + * actually light the blue LED and turning on the blue LED will actually + * light the red LED. If the green LED is turned on, none of the LEDs + * will light. + * + * \see setRGBled() */ void static digitalWriteRGB(uint8_t red, uint8_t green, uint8_t blue); - /// boots the hardware - /** - * - sets input/output/pullup mode for pins - * - powers up the OLED screen and initializes it properly - * - sets up power saving - * - kicks CPU down to 8Mhz if needed - * - allows Safe mode to be entered + /** \brief + * Initialize the Arduboy's hardware. + * + * \details + * This function initializes the display, buttons, etc. + * + * This function is called by begin() so isn't normally called within a + * sketch. However, in order to free up some code space, by eliminating + * some of the start up features, it can be called in place of begin(). + * The functions that begin() would call after boot() can then be called + * to add back in some of the start up features, if desired. + * See the README file or documentation on the main page for more details. + * + * \see Arduboy2Base::begin() */ void static boot(); protected: - /// Safe mode - /** + /* * Safe Mode is engaged by holding down both the LEFT button and UP button - * when plugging the device into USB. It puts your device into a tight + * when plugging the device into USB. It puts your device into a tight * loop and allows it to be reprogrammed even if you have uploaded a very * broken sketch that interferes with the normal USB triggered auto-reboot * functionality of the device. diff --git a/src/Sprites.cpp b/src/Sprites.cpp index e16538f..d4b833e 100644 --- a/src/Sprites.cpp +++ b/src/Sprites.cpp @@ -1,3 +1,9 @@ +/** + * @file Sprites.cpp + * \brief + * A class for drawing animated sprites from image and mask bitmaps. + */ + #include "Sprites.h" void Sprites::drawExternalMask(int16_t x, int16_t y, const uint8_t *bitmap, diff --git a/src/Sprites.h b/src/Sprites.h index d9400fd..58a738b 100644 --- a/src/Sprites.h +++ b/src/Sprites.h @@ -1,3 +1,9 @@ +/** + * @file Sprites.h + * \brief + * A class for drawing animated sprites from image and mask bitmaps. + */ + #ifndef Sprites_h #define Sprites_h @@ -11,116 +17,211 @@ #define SPRITE_IS_MASK_ERASE 251 #define SPRITE_AUTO_MODE 255 +/** \brief + * A class for drawing animated sprites from image and mask bitmaps. + * + * \details + * The functions in this class will draw to the screen buffer an image + * contained in an array located in program memory. A mask can also be + * specified or implied, which dictates how existing pixels in the buffer, + * within the image boundaries, will be affected. + * + * A sprite or mask array contains one or more "frames". Each frame is intended + * to show whatever the sprite represents in a different position, such as the + * various poses for a running or jumping character. By specifying a different + * frame each time the sprite is drawn, it can be animated. + * + * Each array begins with values for the width and height of the sprite, in + * pixels. The width can be any value. The height must be a multiple of + * 8 pixels, but with proper masking, a sprite of any height can be created. + * + * After the width and height values, the remainder of the array contains the + * image and/or mask data for each frame. Each byte represents a vertical + * column of 8 pixels with the least significant bit (bit 0) at the top. + * The bytes are drawn as 8 pixel high rows from left to right, top to bottom. + * When the end of a row is reached, as specified by the width value, the next + * byte in the array will be the start of the next row. + * + * Data for each frame after the first one immediately follows the previous + * frame. Frame numbers start at 0. + */ class Sprites { public: - /// drawExternalMask() uses a separate mask to mask image (MASKED) - /// - /// image mask before after - /// - /// ..... .OOO. ..... ..... - /// ..O.. OOOOO ..... ..O.. - /// OO.OO OO.OO ..... OO.OO - /// ..O.. OOOOO ..... ..O.. - /// ..... .OOO. ..... ..... - /// - /// image mask before after - /// - /// ..... .OOO. OOOOO O...O - /// ..O.. OOOOO OOOOO ..O.. - /// OO.OO OOOOO OOOOO OO.OO - /// ..O.. OOOOO OOOOO ..O.. - /// ..... .OOO. OOOOO O...O - /// + /** \brief + * Draw a sprite using a separate image and mask array. + * + * \param x,y The coordinates of the top left pixel location. + * \param bitmap A pointer to the array containing the image frames. + * \param mask A pointer to the array containing the mask frames. + * \param frame The frame number of the image to draw. + * \param mask_frame The frame number for the mask to use (can be different + * from the image frame number). + * + * \details + * An array containing the image frames, and another array containing + * corresponding mask frames, are used to draw a sprite. + * + * Bits set to 1 in the mask indicate that the pixel will be set to the + * value of the corresponding image bit. Bits set to 0 in the mask will be + * left unchanged. + * + * image mask before after + * + * ..... .OOO. ..... ..... + * ..O.. OOOOO ..... ..O.. + * OO.OO OO.OO ..... OO.OO + * ..O.. OOOOO ..... ..O.. + * ..... .OOO. ..... ..... + * + * image mask before after + * + * ..... .OOO. OOOOO O...O + * ..O.. OOOOO OOOOO ..O.. + * OO.OO OOOOO OOOOO OO.OO + * ..O.. OOOOO OOOOO ..O.. + * ..... .OOO. OOOOO O...O + */ void drawExternalMask(int16_t x, int16_t y, const uint8_t *bitmap, const uint8_t *mask, uint8_t frame, uint8_t mask_frame); - /// drawPlusMask() has the same behavior as `drawExternalMask()` except - /// the data is arranged in byte tuples interposing the mask right along - /// with the image data (SPRITE_PLUS_MASK) - /// - /// typical image data (8 bytes): - /// [I][I][I][I][I][I][I][I] - /// - /// interposed image/mask data (8 byes): - /// [I][M][I][M][I][M][I][M] - /// - /// The byte order does not change, just for every image byte you mix - /// in it's matching mask byte. Softare tools make easy work of this. - /// - /// See: https://github.com/yyyc514/img2ard - /// + /** \brief + * Draw a sprite using an array containing both image and mask values. + * + * \param x,y The coordinates of the top left pixel location. + * \param bitmap A pointer to the array containing the image/mask frames. + * \param frame The frame number of the image to draw. + * + * \details + * An array containing combined image and mask data is used to draw a + * sprite. Bytes are given in pairs with the first byte representing the + * image pixels and the second byte specifying the corresponding mask. + * The width given in the array still specifies the image width, so each + * row of image and mask bytes will be twice the width value. + * + * Bits set to 1 in the mask indicate that the pixel will be set to the + * value of the corresponding image bit. Bits set to 0 in the mask will be + * left unchanged. + * + * image mask before after + * + * ..... .OOO. ..... ..... + * ..O.. OOOOO ..... ..O.. + * OO.OO OO.OO ..... OO.OO + * ..O.. OOOOO ..... ..O.. + * ..... .OOO. ..... ..... + * + * image mask before after + * + * ..... .OOO. OOOOO O...O + * ..O.. OOOOO OOOOO ..O.. + * OO.OO OOOOO OOOOO OO.OO + * ..O.. OOOOO OOOOO ..O.. + * ..... .OOO. OOOOO O...O + */ void drawPlusMask(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t frame); - /// drawOverwrite() replaces the existing content completely (UNMASKED) - /// - /// image before after - /// - /// ..... ..... ..... - /// ..O.. ..... ..O.. - /// OO.OO ..... OO.OO - /// ..O.. ..... ..O.. - /// ..... ..... ..... - /// - /// image before after - /// - /// ..... OOOOO ..... - /// ..O.. OOOOO ..O.. - /// OO.OO OOOOO OO.OO - /// ..O.. OOOOO ..O.. - /// ..... OOOOO ..... - /// + /** \brief + * Draw a sprite by replacing the existing content completely. + * + * \param x,y The coordinates of the top left pixel location. + * \param bitmap A pointer to the array containing the image frames. + * \param frame The frame number of the image to draw. + * + * \details + * A sprite is drawn by overwriting the pixels in the buffer with the data + * from the specified frame in the array. No masking is done. A bit set + * to 1 in the frame will set the pixel to 1 in the buffer, and a 0 in the + * array will set a 0 in the buffer. + * + * image before after + * + * ..... ..... ..... + * ..O.. ..... ..O.. + * OO.OO ..... OO.OO + * ..O.. ..... ..O.. + * ..... ..... ..... + * + * image before after + * + * ..... OOOOO ..... + * ..O.. OOOOO ..O.. + * OO.OO OOOOO OO.OO + * ..O.. OOOOO ..O.. + * ..... OOOOO ..... + */ void drawOverwrite(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t frame); - /// drawErase() removes the lit pixels in the image from the display - /// (SPRITE_IS_MASK_ERASE) - /// - /// image before after - /// - /// ..... ..... ..... - /// ..O.. ..... ..... - /// OO.OO ..... ..... - /// ..O.. ..... ..... - /// ..... ..... ..... - /// - /// image before after - /// - /// ..... OOOOO OOOOO - /// ..O.. OOOOO OO.OO - /// OO.OO OOOOO ..O.. - /// ..O.. OOOOO OO.OO - /// ..... OOOOO OOOOO - /// + /** \brief + * "Erase" a sprite. + * + * \param x,y The coordinates of the top left pixel location. + * \param bitmap A pointer to the array containing the image frames. + * \param frame The frame number of the image to erase. + * + * \details + * The data from the specified frame in the array is used to erase a + * sprite. To "erase" a sprite, bits set to 1 in the frame will set the + * corresponding pixel in the buffer to 0. Frame bits set to 0 will remain + * unchanged in the buffer. + * + * image before after + * + * ..... ..... ..... + * ..O.. ..... ..... + * OO.OO ..... ..... + * ..O.. ..... ..... + * ..... ..... ..... + * + * image before after + * + * ..... OOOOO OOOOO + * ..O.. OOOOO OO.OO + * OO.OO OOOOO ..O.. + * ..O.. OOOOO OO.OO + * ..... OOOOO OOOOO + */ void drawErase(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t frame); - /// drawSelfMasked() only draws lit pixels, black pixels in - /// your image are treated as "transparent" (SPRITE_IS_MASK) - /// - /// image before after - /// - /// ..... ..... ..... - /// ..O.. ..... ..O.. - /// OO.OO ..... OO.OO - /// ..O.. ..... ..O.. - /// ..... ..... ..... - /// - /// image before after - /// - /// ..... OOOOO OOOOO (no change because all pixels were - /// ..O.. OOOOO OOOOO already white) - /// OO.OO OOOOO OOOOO - /// ..O.. OOOOO OOOOO - /// ..... OOOOO OOOOO - /// + /** \brief + * Draw a sprite using only the bits set to 1. + * + * \param x,y The coordinates of the top left pixel location. + * \param bitmap A pointer to the array containing the image frames. + * \param frame The frame number of the image to draw. + * + * \details + * Bits set to 1 in the frame will be used to draw the sprite by setting + * the corresponding pixel in the buffer to 1. Bits set to 0 in the frame + * will remain unchanged in the buffer. + * + * image before after + * + * ..... ..... ..... + * ..O.. ..... ..O.. + * OO.OO ..... OO.OO + * ..O.. ..... ..O.. + * ..... ..... ..... + * + * image before after + * + * ..... OOOOO OOOOO (no change because all pixels were + * ..O.. OOOOO OOOOO already white) + * OO.OO OOOOO OOOOO + * ..O.. OOOOO OOOOO + * ..... OOOOO OOOOO + */ void drawSelfMasked(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t frame); - /// Master function. Needs to be abstracted into separate function for - /// every render type + // Master function. Needs to be abstracted into separate function for + // every render type. + // (Not officially part of the API) void draw(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t frame, const uint8_t *mask, uint8_t sprite_frame, uint8_t drawMode); + // (Not officially part of the API) void drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, const uint8_t *mask, int8_t w, int8_t h, uint8_t draw_mode); diff --git a/src/ab_logo.c b/src/ab_logo.c index 3718e5c..4041df2 100644 --- a/src/ab_logo.c +++ b/src/ab_logo.c @@ -1,3 +1,9 @@ +/** + * @file ab_logo.c + * \brief + * The ARDUBOY logo bitmap. + */ + #include #ifndef ARDUBOY_LOGO_CREATED diff --git a/src/glcdfont.c b/src/glcdfont.c index f8b3e86..2164571 100644 --- a/src/glcdfont.c +++ b/src/glcdfont.c @@ -1,3 +1,9 @@ +/** + * @file glcdfont.c + * \brief + * The font definitions used to display text characters. + */ + #include #include