mirror of https://github.com/MLXXXp/Arduboy2.git
Compare commits
184 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
bc460a2cff | |
|
|
ca1c3ae024 | |
|
|
031e9164aa | |
|
|
7f456cff69 | |
|
|
2374247788 | |
|
|
98afc7229f | |
|
|
4f0d802d50 | |
|
|
ccedf84434 | |
|
|
279fd9d0f4 | |
|
|
36cbdc734c | |
|
|
ab4df7c77a | |
|
|
b4b4d45009 | |
|
|
7dc88bed30 | |
|
|
191e9a2e45 | |
|
|
014e6e0a8b | |
|
|
500d81abb7 | |
|
|
2baca75689 | |
|
|
2f1c515672 | |
|
|
98f03773b2 | |
|
|
4698dd276e | |
|
|
e78e7c9d55 | |
|
|
1264edc748 | |
|
|
aaf4159274 | |
|
|
86169a0027 | |
|
|
58a35e2ad9 | |
|
|
bbebec346d | |
|
|
350a6ee629 | |
|
|
7fcbd35266 | |
|
|
5d154f817a | |
|
|
f1009abd7b | |
|
|
8fc6eee194 | |
|
|
f0be8ad3b4 | |
|
|
ecb74632ba | |
|
|
13130f368a | |
|
|
2491e639aa | |
|
|
32d23b7984 | |
|
|
e0ade6ca99 | |
|
|
4530325412 | |
|
|
d7758249fa | |
|
|
5563599c6d | |
|
|
30fb448db5 | |
|
|
a04edf24c1 | |
|
|
b668114475 | |
|
|
c74438e377 | |
|
|
566557eab3 | |
|
|
3345198d3d | |
|
|
1bcf707616 | |
|
|
568a15ff87 | |
|
|
966c2125f1 | |
|
|
355e2d2081 | |
|
|
2d04cf60e1 | |
|
|
6a8041f2fa | |
|
|
205e84eae6 | |
|
|
0adb83693a | |
|
|
53096d87bf | |
|
|
b854e2295f | |
|
|
4f884f4ed2 | |
|
|
3f9e86ab99 | |
|
|
4e513a15d0 | |
|
|
bc4e0ed0b5 | |
|
|
891f68a0be | |
|
|
2fbde21e66 | |
|
|
a31e5091d6 | |
|
|
096aaac8dd | |
|
|
903cfd9414 | |
|
|
b40e3b9c57 | |
|
|
6ded14fb0e | |
|
|
974f5298ee | |
|
|
c87f512b53 | |
|
|
195d3e5cde | |
|
|
2941ed100f | |
|
|
1d49ce5df8 | |
|
|
d5b4a45706 | |
|
|
1f86208163 | |
|
|
bc63e39931 | |
|
|
54d47ec04e | |
|
|
0eae58c760 | |
|
|
4c2e412985 | |
|
|
58ae256412 | |
|
|
928c40813d | |
|
|
b8c1cb742a | |
|
|
15db34cab2 | |
|
|
674ac8a774 | |
|
|
9a13011474 | |
|
|
a43e745250 | |
|
|
da2c7e3d35 | |
|
|
53b50a9766 | |
|
|
d76eb15c51 | |
|
|
c00fee0a78 | |
|
|
fb77929126 | |
|
|
eb041d24f8 | |
|
|
53ea8188d5 | |
|
|
460e768ea9 | |
|
|
4788b1ab01 | |
|
|
d356be4e13 | |
|
|
6e1c47cbe0 | |
|
|
bd726fc112 | |
|
|
d44b89e01f | |
|
|
6f6849a5bb | |
|
|
f8f46de06d | |
|
|
d6336803a2 | |
|
|
93c33f6ad6 | |
|
|
5e58d9b6a8 | |
|
|
b159b3751b | |
|
|
6360eb2b37 | |
|
|
383bdfc144 | |
|
|
420b958208 | |
|
|
5370409875 | |
|
|
6416166ae7 | |
|
|
4478b1fe0a | |
|
|
1bb4726ed0 | |
|
|
fe30863dbe | |
|
|
6ab6b83e2c | |
|
|
fd614ab586 | |
|
|
e6e82bf336 | |
|
|
46ecb2dd78 | |
|
|
b121d19b77 | |
|
|
bd5b470294 | |
|
|
6074f9fc56 | |
|
|
427c1d53f2 | |
|
|
342186281a | |
|
|
3c4915b0d5 | |
|
|
a01ceffb20 | |
|
|
babf6893c8 | |
|
|
b4d8fd8d6f | |
|
|
606c80268b | |
|
|
5d428a3a33 | |
|
|
520be03d59 | |
|
|
3aa015b997 | |
|
|
dac16d5e36 | |
|
|
e235f26def | |
|
|
50df1a221b | |
|
|
6f9056f99c | |
|
|
554c21f759 | |
|
|
e1cce03580 | |
|
|
ab1a7b3bdd | |
|
|
fc61d180d9 | |
|
|
9bfb499169 | |
|
|
96b53875b5 | |
|
|
ae8e284d41 | |
|
|
6e13fc019f | |
|
|
1280160f89 | |
|
|
5877208a57 | |
|
|
6050dda391 | |
|
|
449532f1e9 | |
|
|
79f24c47cc | |
|
|
cfb5e89d5c | |
|
|
3572a013e1 | |
|
|
14d5877dae | |
|
|
f294a045e0 | |
|
|
1e7f251ce0 | |
|
|
4ff6973a4b | |
|
|
cf648850c4 | |
|
|
db50dfce87 | |
|
|
b560ff9f60 | |
|
|
2851dcf4cc | |
|
|
f07f2267b2 | |
|
|
2760d87194 | |
|
|
b4707dc546 | |
|
|
2cbe4afa08 | |
|
|
6c297fab1e | |
|
|
de17257029 | |
|
|
2fede9cb86 | |
|
|
8125862bfe | |
|
|
3e82f484a2 | |
|
|
4607f087a2 | |
|
|
388f8abb9f | |
|
|
7dfb4f14f7 | |
|
|
a9271a335d | |
|
|
e00acd4d06 | |
|
|
e5a7dc5982 | |
|
|
0b0c111757 | |
|
|
d89a2bd590 | |
|
|
867f2d000c | |
|
|
0cb37455c6 | |
|
|
40a028e5a1 | |
|
|
9d2559c248 | |
|
|
f763263d2b | |
|
|
f9dc4cb0e5 | |
|
|
88d5226042 | |
|
|
72ae94aca1 | |
|
|
7a1a295010 | |
|
|
15d1b0dab4 | |
|
|
fd4cef7025 |
|
|
@ -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/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
# Commit message style
|
||||
When submitting changes via a pull request, or any other means, please format commit messages using ["50/72" guidelines, as suggested by Tim Pope](https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
|
||||
|
||||
## Summary:
|
||||
- Maximum 50 character first "title" line, written as a capitalized [imperative sentence](http://examples.yourdictionary.com/imperative-sentence-examples.html).
|
||||
- If necessary, more detailed explanatory paragraphs following a blank line, with lines wrapped at maximum 72 characters.
|
||||
- If used, bullet points have a "hanging indent".
|
||||
|
||||
## Example 1:
|
||||
```
|
||||
Make state variables used by pollButtons() public
|
||||
|
||||
The variables currentButtonState and previousButtonState used by
|
||||
pollButtons(), justPressed() and justReleased() have been made public.
|
||||
This allows them to be manipulated if circumstances require it.
|
||||
|
||||
The documentation added for previousButtonState includes an example.
|
||||
```
|
||||
|
||||
## Example 2:
|
||||
```
|
||||
Refactor text code and add char size functions
|
||||
|
||||
- Functions write() and drawChar() were refactored for smaller code
|
||||
size and to make text wrapping operate more like what would normally
|
||||
be expected.
|
||||
|
||||
- A new flag variable, textRaw, has been added, along with functions
|
||||
setTextRawMode() and getTextRawMode() to set and read it.
|
||||
```
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
# Individual Contributors
|
||||
|
||||
- Kevin "Arduboy" Bates (@Arduboy)
|
||||
- arduboychris (@arduboychris)
|
||||
- Ross (@rogosher)
|
||||
- Andrew (@ace-dent)
|
||||
- Josh Goebel (@yyyc514)
|
||||
- Scott Allen (@MLXXXp)
|
||||
|
||||
|
||||
# Included code from other open source projects
|
||||
|
||||
- Original SSD1306 library
|
||||
https://github.com/adafruit/Adafruit_SSD1306
|
||||
BSD License
|
||||
Copyright (c) 2012, Adafruit Industries
|
||||
|
||||
274
LICENSE.txt
274
LICENSE.txt
|
|
@ -1,14 +1,32 @@
|
|||
Software License Agreement (BSD License)
|
||||
/**
|
||||
\page licenses Software License Agreements
|
||||
\verbatim
|
||||
|
||||
Software License Agreements
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Licensed under the BSD 3-clause license:
|
||||
|
||||
Arduboy2 library:
|
||||
Copyright (c) 2016-2021, Scott Allen
|
||||
All rights reserved.
|
||||
|
||||
The Arduboy2 library was forked from the Arduboy library:
|
||||
https://github.com/Arduboy/Arduboy
|
||||
Copyright (c) 2016, Kevin "Arduboy" Bates
|
||||
Copyright (c) 2016, Chris Martinez
|
||||
Copyright (c) 2016, Josh Goebel
|
||||
Copyright (c) 2016, Scott Allen
|
||||
All rights reserved.
|
||||
|
||||
Please see CONTRIBUTORS.md for license information and copyright
|
||||
notices for any libraries we built on or redistribute.
|
||||
- which is in turn partially based on the Adafruit_SSD1306 library
|
||||
https://github.com/adafruit/Adafruit_SSD1306
|
||||
Copyright (c) 2012, Adafruit Industries
|
||||
All rights reserved.
|
||||
|
||||
SetSystemEEPROM example sketch:
|
||||
Copyright (c) 2018-2020, Scott Allen
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
|
@ -31,3 +49,253 @@ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Licensed under the BSD 2-clause license:
|
||||
|
||||
Portions of the Arduboy library, and thus portions of the Arduboy2 library,
|
||||
based on the Adafruit-GFX library:
|
||||
https://github.com/adafruit/Adafruit-GFX-Library
|
||||
Copyright (c) 2012 Adafruit Industries
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Licensed under the MIT license:
|
||||
|
||||
Code from ArduboyExtra:
|
||||
https://github.com/yyyc514/ArduboyExtra
|
||||
Copyright (c) 2015 Josh Goebel
|
||||
|
||||
Code for drawing compressed bitmaps:
|
||||
Copyright (c) 2016 TEAM a.r.g.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Licensed under the GNU LGPL license:
|
||||
https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
|
||||
|
||||
ArduBreakout example sketch:
|
||||
Original work:
|
||||
Copyright (c) 2011 Sebastian Goscik
|
||||
All rights reserved.
|
||||
Modified work:
|
||||
Copyright (c) 2016 Scott Allen
|
||||
All rights reserved.
|
||||
|
||||
Buttons and HelloWorld example sketches:
|
||||
Copyright (c) 2015 David Martinez
|
||||
All rights reserved.
|
||||
|
||||
This work is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Licensed under the zlib license:
|
||||
|
||||
LodePNG
|
||||
https://github.com/lvandeve/lodepng
|
||||
Copyright (c) 2005-2020 Lode Vandevenne
|
||||
(Used by the Cabi program)
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Placed in the public domain using Creative Commons CC0:
|
||||
https://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
BeepDemo example sketch:
|
||||
By Scott Allen
|
||||
|
||||
FontDemo example sketch:
|
||||
By Scott Allen
|
||||
|
||||
RGBled example sketch:
|
||||
By Scott Allen
|
||||
|
||||
Cabi PNG file converter program:
|
||||
By zep
|
||||
|
||||
Creative Commons Legal Code
|
||||
|
||||
CC0 1.0 Universal
|
||||
|
||||
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
|
||||
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
|
||||
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
|
||||
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
|
||||
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
|
||||
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
|
||||
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
|
||||
HEREUNDER.
|
||||
|
||||
Statement of Purpose
|
||||
|
||||
The laws of most jurisdictions throughout the world automatically confer
|
||||
exclusive Copyright and Related Rights (defined below) upon the creator
|
||||
and subsequent owner(s) (each and all, an "owner") of an original work of
|
||||
authorship and/or a database (each, a "Work").
|
||||
|
||||
Certain owners wish to permanently relinquish those rights to a Work for
|
||||
the purpose of contributing to a commons of creative, cultural and
|
||||
scientific works ("Commons") that the public can reliably and without fear
|
||||
of later claims of infringement build upon, modify, incorporate in other
|
||||
works, reuse and redistribute as freely as possible in any form whatsoever
|
||||
and for any purposes, including without limitation commercial purposes.
|
||||
These owners may contribute to the Commons to promote the ideal of a free
|
||||
culture and the further production of creative, cultural and scientific
|
||||
works, or to gain reputation or greater distribution for their Work in
|
||||
part through the use and efforts of others.
|
||||
|
||||
For these and/or other purposes and motivations, and without any
|
||||
expectation of additional consideration or compensation, the person
|
||||
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
|
||||
is an owner of Copyright and Related Rights in the Work, voluntarily
|
||||
elects to apply CC0 to the Work and publicly distribute the Work under its
|
||||
terms, with knowledge of his or her Copyright and Related Rights in the
|
||||
Work and the meaning and intended legal effect of CC0 on those rights.
|
||||
|
||||
1. Copyright and Related Rights. A Work made available under CC0 may be
|
||||
protected by copyright and related or neighboring rights ("Copyright and
|
||||
Related Rights"). Copyright and Related Rights include, but are not
|
||||
limited to, the following:
|
||||
|
||||
i. the right to reproduce, adapt, distribute, perform, display,
|
||||
communicate, and translate a Work;
|
||||
ii. moral rights retained by the original author(s) and/or performer(s);
|
||||
iii. publicity and privacy rights pertaining to a person's image or
|
||||
likeness depicted in a Work;
|
||||
iv. rights protecting against unfair competition in regards to a Work,
|
||||
subject to the limitations in paragraph 4(a), below;
|
||||
v. rights protecting the extraction, dissemination, use and reuse of data
|
||||
in a Work;
|
||||
vi. database rights (such as those arising under Directive 96/9/EC of the
|
||||
European Parliament and of the Council of 11 March 1996 on the legal
|
||||
protection of databases, and under any national implementation
|
||||
thereof, including any amended or successor version of such
|
||||
directive); and
|
||||
vii. other similar, equivalent or corresponding rights throughout the
|
||||
world based on applicable law or treaty, and any national
|
||||
implementations thereof.
|
||||
|
||||
2. Waiver. To the greatest extent permitted by, but not in contravention
|
||||
of, applicable law, Affirmer hereby overtly, fully, permanently,
|
||||
irrevocably and unconditionally waives, abandons, and surrenders all of
|
||||
Affirmer's Copyright and Related Rights and associated claims and causes
|
||||
of action, whether now known or unknown (including existing as well as
|
||||
future claims and causes of action), in the Work (i) in all territories
|
||||
worldwide, (ii) for the maximum duration provided by applicable law or
|
||||
treaty (including future time extensions), (iii) in any current or future
|
||||
medium and for any number of copies, and (iv) for any purpose whatsoever,
|
||||
including without limitation commercial, advertising or promotional
|
||||
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
|
||||
member of the public at large and to the detriment of Affirmer's heirs and
|
||||
successors, fully intending that such Waiver shall not be subject to
|
||||
revocation, rescission, cancellation, termination, or any other legal or
|
||||
equitable action to disrupt the quiet enjoyment of the Work by the public
|
||||
as contemplated by Affirmer's express Statement of Purpose.
|
||||
|
||||
3. Public License Fallback. Should any part of the Waiver for any reason
|
||||
be judged legally invalid or ineffective under applicable law, then the
|
||||
Waiver shall be preserved to the maximum extent permitted taking into
|
||||
account Affirmer's express Statement of Purpose. In addition, to the
|
||||
extent the Waiver is so judged Affirmer hereby grants to each affected
|
||||
person a royalty-free, non transferable, non sublicensable, non exclusive,
|
||||
irrevocable and unconditional license to exercise Affirmer's Copyright and
|
||||
Related Rights in the Work (i) in all territories worldwide, (ii) for the
|
||||
maximum duration provided by applicable law or treaty (including future
|
||||
time extensions), (iii) in any current or future medium and for any number
|
||||
of copies, and (iv) for any purpose whatsoever, including without
|
||||
limitation commercial, advertising or promotional purposes (the
|
||||
"License"). The License shall be deemed effective as of the date CC0 was
|
||||
applied by Affirmer to the Work. Should any part of the License for any
|
||||
reason be judged legally invalid or ineffective under applicable law, such
|
||||
partial invalidity or ineffectiveness shall not invalidate the remainder
|
||||
of the License, and in such case Affirmer hereby affirms that he or she
|
||||
will not (i) exercise any of his or her remaining Copyright and Related
|
||||
Rights in the Work or (ii) assert any associated claims and causes of
|
||||
action with respect to the Work, in either case contrary to Affirmer's
|
||||
express Statement of Purpose.
|
||||
|
||||
4. Limitations and Disclaimers.
|
||||
|
||||
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
||||
surrendered, licensed or otherwise affected by this document.
|
||||
b. Affirmer offers the Work as-is and makes no representations or
|
||||
warranties of any kind concerning the Work, express, implied,
|
||||
statutory or otherwise, including without limitation warranties of
|
||||
title, merchantability, fitness for a particular purpose, non
|
||||
infringement, or the absence of latent or other defects, accuracy, or
|
||||
the present or absence of errors, whether or not discoverable, all to
|
||||
the greatest extent permissible under applicable law.
|
||||
c. Affirmer disclaims responsibility for clearing rights of other persons
|
||||
that may apply to the Work or any use thereof, including without
|
||||
limitation any person's Copyright and Related Rights in the Work.
|
||||
Further, Affirmer disclaims responsibility for obtaining any necessary
|
||||
consents, permissions or other rights required for any use of the
|
||||
Work.
|
||||
d. Affirmer understands and acknowledges that Creative Commons is not a
|
||||
party to this document and has no duty or obligation with respect to
|
||||
this CC0 or use of the Work.
|
||||
|
||||
===============================================================================
|
||||
\endverbatim
|
||||
*/
|
||||
|
|
|
|||
382
README.md
382
README.md
|
|
@ -1,41 +1,37 @@
|
|||
#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 Arduboy2 library is maintained in a git repository hosted on [GitHub](https://github.com/) at:
|
||||
|
||||
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.
|
||||
https://github.com/MLXXXp/Arduboy2
|
||||
|
||||
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 original *Arduboy* library is no longer being maintained.
|
||||
|
||||
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.
|
||||
|
||||
For notes on the differences between the *Arduboy2* library and the original *Arduboy* library, and for information on migrating a sketch currently using the *Arduboy* library, see the sections at the end of this document.
|
||||
|
||||
## Library documentation
|
||||
|
||||
Comments in the library header files are formatted for the [Doxygen](https://www.doxygen.nl/) document generation system. The HTML files generated using the configuration file _extras/Doxyfile_ can be found at:
|
||||
|
||||
https://MLXXXp.github.io/documents/Arduino/libraries/Arduboy2/Doxygen/html/index.html
|
||||
|
||||
A generated PDF file can be found at:
|
||||
|
||||
https://MLXXXp.github.io/documents/Arduino/libraries/Arduboy2/Doxygen/pdf/Arduboy2.pdf
|
||||
|
||||
## 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)
|
||||
|
||||
## 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.
|
||||
|
||||
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 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.
|
||||
- The *clear()* function will now reset the text cursor to home position 0, 0.
|
||||
- In Arduboy V1.1, the *nextFrame()* function contains a bug which results in the actual frame rate possibly being slower than what is set, and varying depending on the load that the sketch is placing on the CPU to generate a frame. This bug has been corrected but will result in sketches ported from Arduboy V1.1 possibly running faster and needing some "tweaking" to slow them back down. New sketches developed specifically using Arduboy2 won't have problems with this.
|
||||
- A new feature has been added which allows the *audio on/off* flag in system EEPROM to be configured by the user when the sketch starts. The flag is used by the Arduboy and Arduboy2 *audio* subclass, along with external sound functions and libraries, to provide a standardized sound mute capability. This feature is described in more detail later in this document.
|
||||
- The *color* parameter, which is the last parameter for most of the drawing functions, has been made optional and will default to WHITE if not included in the call. This doesn't save any code but has been added as a convenience, since most drawing functions are called with WHITE specified.
|
||||
- A new function *digitalWriteRGB()* has been added to control the RGB LED digitally instead of using PWM. This uses less code if just turning the RGB LEDs fully on or off is all that's required.
|
||||
- The *beginNoLogo()* function is not included. This function could be used in Arduboy V1.1 in place of *begin()* to suppress the displaying of the ARDUBOY logo and thus free up the code that it required. Instead, Arduboy2 allows a sketch to call *boot()* and then add in any extra features that *begin()* provides by calling their functions directly after *boot()*, if desired.
|
||||
- The *ArduboyCore* and *ArduboyAudio* base classes, previously only available to, and used to derive, the *Arduboy* class, have been made publicly available for the benefit of developers who may wish to use them as the base of an entirely new library. This change doesn't affect the existing API.
|
||||
[Installing Additional Arduino Libraries - Using the Library Manager](https://www.arduino.cc/en/Guide/Libraries#toc3)
|
||||
|
||||
## Start up features
|
||||
|
||||
|
|
@ -45,22 +41,25 @@ The *begin()* function, used to initialize the library, includes features that a
|
|||
|
||||
At the start of the sketch, the **ARDUBOY** logo scrolls down from the top of the screen to the center.
|
||||
|
||||
The RGB LED lights red then green then blue while the logo is scrolling. (If your Arduboy is one of those that has the RGB LED installed incorrectly, then it will light blue then off then red). This pattern is different than with Arduboy V1.1, which lit and then faded red (or blue if the LED is incorrectly installed).
|
||||
The RGB LED lights red then green then blue while the logo is scrolling. (If your Arduboy is one of those that has the RGB LED installed incorrectly, then it will light blue then off then red). For users who do not wish to have the RGB LED flash during the boot logo sequence, a flag can be set in system EEPROM to have it remain off. The included *SetSystemEEPROM* example sketch can be used to set this flag.
|
||||
|
||||
Once the logo display completes, the sketch continues.
|
||||
A user settable *unit name* can be saved in system EEPROM memory. If set, this name will be briefly displayed at the bottom of the boot logo screen, after the logo stops scrolling down. This feature is only available if the *Arduboy2* class is used, not the *Arduboy2Base* class. This is because it requires the text display functions, which are only available in the *Arduboy2* class. A flag in system EEPROM controls whether or not the *unit name* is displayed on the boot logo screen, regardless of whether the *unit name* itself has been set. The included *SetSystemEEPROM* example sketch can be used to set both the *unit name* and this flag.
|
||||
|
||||
Once the logo display sequence completes, the sketch continues.
|
||||
|
||||
**Note:**
|
||||
|
||||
- For developers who wish to quickly begin testing, or impatient users who want to go strait to playing their game, the boot logo sequence can be bypassed by holding the *RIGHT* button while powering up, and then releasing it. Alternatively, the *RIGHT* button can be pressed while the logo is scrolling down.
|
||||
- For users who wish to always disable the displaying of the boot logo sequence on boot up, a flag in system EEPROM is available for this. The included *SetSystemEEPROM* example sketch can be used to set this flag.
|
||||
|
||||
### "Flashlight" mode
|
||||
|
||||
If the *UP* button is pressed and held when the Arduboy is powered on, it enters *flashlight* mode. This turns the RGB LED fully on, and all the pixels of the screen are lit, resulting in a bright white light suitable as a small flashlight. (For an incorrect RGB LED, only the screen will light). To exit *flashlight* mode, press the *DOWN* button to continue with the sketch.
|
||||
If the *UP* button is pressed and held when the Arduboy is powered on, it enters *flashlight* mode. This turns the RGB LED fully on, and all the pixels of the screen are lit, resulting in a bright white light suitable as a small flashlight. (For an incorrect RGB LED, only the screen will light). To exit *flashlight* mode the Arduboy must be restarted.
|
||||
|
||||
*Flashlight* mode is also sometimes useful to allow uploading of new sketches, in case the sketch currently loaded uses a large amount of RAM which creates a bootloader problem.
|
||||
|
||||
Lighting the screen is new to Arduboy2. Arduboy library V1.1 only lights the RGB LED.
|
||||
|
||||
### Audio mute control
|
||||
|
||||
This feature is new to the Arduboy2 library. It's not available in Arduboy library V1.1.
|
||||
|
||||
Pressing and holding the *B* button when powering on will enter *System Control* mode. The RGB LED will light blue (red for an incorrect LED) to indicate that you are in *system control* mode. You must continue to hold the *B* button to remain in this mode. The only *system control* function currently implemented is *audio mute control*.
|
||||
|
||||
Pressing the *UP* button (while still holding *B*) will set a flag in system EEPROM indicating *audio enabled*. The RGB LED will flash green once (off for an incorrect LED) to indicate this action.
|
||||
|
|
@ -75,18 +74,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 <Arduboy2.h>`
|
||||
```cpp
|
||||
#include <Arduboy2.h>
|
||||
```
|
||||
|
||||
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
|
||||
}
|
||||
|
|
@ -94,107 +98,257 @@ void setup() {
|
|||
|
||||
The rest of the Arduboy2 functions will now be available for use.
|
||||
|
||||
If you wish to use the Sprites class functions you must create a Sprites object:
|
||||
|
||||
```cpp
|
||||
Sprites sprites;
|
||||
```
|
||||
|
||||
Sample sketches have been included with the library as examples of how to use it. To load an example, for examination and uploading to the Arduboy, using the Arduino IDE menus select:
|
||||
|
||||
`File > Examples > Arduboy2`
|
||||
|
||||
More information on writing sketches for the Arduboy can be found in the [Arduboy Community Forum](http://community.arduboy.com/).
|
||||
More information on writing sketches for the Arduboy can be found in the [Arduboy Community Forum](https://community.arduboy.com/).
|
||||
|
||||
### Using EEPROM in a sketch <- THIS IS IMPORTANT!
|
||||
|
||||
The Arduboy2 library reserves an area at the start of EEPROM for storing system information, such as the current audio mute state and the Unit Name and Unit ID. A sketch **MUST NOT** use this reserved area for its own purposes. A sketch may use any EEPROM past this reserved area. The first EEPROM address available for sketch use is given as the defined value *EEPROM_STORAGE_SPACE_START*
|
||||
|
||||
### 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.h>
|
||||
|
||||
Arduboy2 arduboy;
|
||||
|
||||
// Arduboy2Audio functions can be called as follows:
|
||||
arduboy.audio.on();
|
||||
arduboy.audio.off();
|
||||
```
|
||||
|
||||
### Simple tone generation
|
||||
|
||||
The *BeepPin1* and *BeepPin2* classes are available to generate simple square wave tones using speaker pin 1 and speaker pin 2 respectively. These classes are documented in file *Arduboy2Beep.h*. Also, *BeepDemo* is included as one of the example sketches, which demonstrates basic use.
|
||||
|
||||
NOTE: These functions will not work with a DevKit Arduboy because the speaker pins used cannot be directly controlled by a timer/counter. "Dummy" functions are provided so a sketch will compile and work properly but no sound will be produced.
|
||||
|
||||
### Ways to make more code space available to sketches
|
||||
|
||||
#### Sound effects and music
|
||||
|
||||
Arduboy2 will automatically use less code than Arduboy V1.1 because it doesn't include the *tunes* subclass. If your sketch doesn't have sound, more code is available than with Arduboy V1.1. If you want your sketch to have sound, then using the *ArduboyTones* library will be more code efficient than using *ArduboyPlaytune*. *ArduboyTones* even produces less code than the [Arduino built in *tone()* function](https://www.arduino.cc/en/Reference/Tone). You'll have to decide on the appropriate library or functions you use to generate sound, based on the features required and how much memory you want it to use.
|
||||
If all you want is to play single tones, using the built in *BeepPin1* or *BeepPin2* classes will be very efficient.
|
||||
|
||||
If you want to be able to play sequences of tones or background music, using the [*ArduboyTones*](https://github.com/MLXXXp/ArduboyTones) library will be more code efficient than using [*ArduboyPlaytune*](https://github.com/Arduboy/ArduboyPlayTune) or most other sound libraries compatible with the Arduboy. *ArduboyTones* even produces less code than the [Arduino built in *tone()* function](https://www.arduino.cc/en/Reference/Tone). You'll have to decide on the appropriate library or functions you use to generate sound, based on the features required and how much memory you want it to use.
|
||||
|
||||
#### Remove the text functions
|
||||
|
||||
If your sketch doesn't use any of the functions for displaying text, such as *setCursor()* and *print()*, you can remove them. You could do this if your sketch generates whatever text it requires by some other means. Removing the text functions frees up code by not including the font table and some code that is always pulled in by inheriting the [Arduino *Print* class](http://playground.arduino.cc/Code/Printclass).
|
||||
If your sketch doesn't use any of the functions for displaying text, such as *setCursor()* and *print()*, you can remove them. You could do this if your sketch generates whatever text it requires by some other means. Removing the text functions frees up code by not including the font table and some code that is always pulled in by inheriting the [Arduino *Print* class](https://playground.arduino.cc/Code/Printclass/).
|
||||
|
||||
To eliminate text capability in your sketch, when creating the library object simply use the *Arduboy2Base* class instead of *Arduboy2*:
|
||||
|
||||
For example, if the object will be named *arduboy*:
|
||||
|
||||
replace `Arduboy2 arduboy;`
|
||||
|
||||
with `Arduboy2Base arduboy;`
|
||||
|
||||
#### Remove boot up features
|
||||
|
||||
As previously described, the *begin()* function includes features that are intended to be available to all sketches during boot up. However, if you're looking to gain some code space, you can call *boot()* instead of *begin()*. This will initialize the system but not include any of the extra boot up features. If desired, you can then add back in any of these features by calling the functions that perform them. You will have to trade off between the desirability of having a feature and how much memory you can recover by not including it.
|
||||
|
||||
A good way to use *boot()* instead of *begin()* is to copy the code from the body of the *begin()* function, in file *Arduboy2.cpp*, into your sketch and then edit it to retain the *boot()* call and any feature calls desired.
|
||||
|
||||
As of this writing, the begin function is:
|
||||
Replace
|
||||
|
||||
```cpp
|
||||
void Arduboy2Base::begin()
|
||||
Arduboy2 arduboy;
|
||||
```
|
||||
|
||||
with
|
||||
|
||||
```cpp
|
||||
Arduboy2Base arduboy;
|
||||
```
|
||||
|
||||
#### Substitute or remove boot up features
|
||||
|
||||
As previously described in the _Start up features_ section, the *begin()* function includes features that are intended to be available to all sketches during boot up. However, if you're looking to gain some code space, you can call *boot()* instead of *begin()*. This will initialize the system but not include any of the extra boot up features. You can then add back in any of these features by calling the functions that perform them. You will have to trade off between the desirability of having a feature and how much memory you can recover by not including it.
|
||||
|
||||
You should at least call either *flashlight()* or *safeMode()* as a safeguard to allow uploading a new sketch when the bootloader "magic key" problem is an issue.
|
||||
|
||||
Here is a template that provides the equivalent of *begin()*
|
||||
|
||||
```cpp
|
||||
void setup()
|
||||
{
|
||||
boot(); // raw hardware
|
||||
// Required to initialize the hardware.
|
||||
arduboy.boot();
|
||||
|
||||
blank(); // blank the display
|
||||
// This clears the display. (The screen buffer will be all zeros)
|
||||
// It may not be needed if something clears the display later on but
|
||||
// "garbage" will be displayed if systemButtons() is used without it.
|
||||
arduboy.display();
|
||||
|
||||
flashlight(); // light the RGB LED and screen if UP button is being held.
|
||||
// flashlight() or safeMode() should always be included to provide
|
||||
// a method of recovering from the bootloader "magic key" problem.
|
||||
arduboy.flashlight();
|
||||
// arduboy.safeMode();
|
||||
|
||||
// check for and handle buttons held during start up for system control
|
||||
systemButtons();
|
||||
// This allows sound to be turned on or muted. If the sketch provides
|
||||
// its own way of toggling sound, or doesn't produce any sound, this
|
||||
// function may not be required.
|
||||
arduboy.systemButtons();
|
||||
|
||||
bootLogo();
|
||||
// This is required to initialize the speaker. It's not needed if
|
||||
// the sketch doesn't produce any sounds.
|
||||
arduboy.audio.begin();
|
||||
|
||||
// This displays the boot logo sequence but note that the logo can
|
||||
// be suppressed by the user, by pressing the RIGHT button or using
|
||||
// a system EEPROM setting. If not removed entirely, an alternative
|
||||
// bootLogo...() function may save some memory.
|
||||
arduboy.bootLogo();
|
||||
// arduboy.bootLogoCompressed();
|
||||
// arduboy.bootLogoSpritesSelfMasked();
|
||||
// arduboy.bootLogoSpritesOverwrite();
|
||||
// arduboy.bootLogoSpritesBSelfMasked();
|
||||
// arduboy.bootLogoSpritesBOverwrite();
|
||||
// arduboy.bootLogoText();
|
||||
|
||||
// Wait for all buttons to be released, in case a pressed one might
|
||||
// cause problems by being acted upon when the actual sketch code
|
||||
// starts. If neither systemButtons() nor bootLogo() is kept, this
|
||||
// function isn't required.
|
||||
arduboy.waitNoButtons();
|
||||
|
||||
// Additional setup code...
|
||||
|
||||
audio.begin();
|
||||
}
|
||||
```
|
||||
|
||||
To incorporate it into your sketch just keep *boot()* and whatever feature calls are desired, if any. Comment out or delete the rest. Remember to add the class object name in front of each function call, since they're now being called from outside the class itself. If your sketch uses sound, it's a good idea to keep the call to *audio.begin()*.
|
||||
There are a few functions provided that are roughly equivalent to the standard functions used by *begin()* but which use less code space.
|
||||
|
||||
For example: Let's say a sketch has its own code to enable, disable and save the *audio on/off* setting, and wants to keep the *flashlight* function. In *setup()* it could replace *begin()* with:
|
||||
- *bootLogoCompressed()*, *bootLogoSpritesSelfMasked()*, *bootLogoSpritesOverwrite()*, *bootLogoSpritesBSelfMasked()* and *bootLogoSpritesBOverwrite()* will do the same as *bootLogo()* but will use *drawCompressed()*, or *Sprites* / *SpritesB* class *drawSelfMasked()* or *drawOverwrite()* functions respectively, instead of *drawBitmap()*, to render the logo. If the sketch uses one of these functions, then using the boot logo function that also uses it may reduce code size. It's best to try each of them to see which one produces the smallest size.
|
||||
- *bootLogoText()* can be used in place *bootLogo()* in the case where the sketch uses text functions. It renders the logo as text instead of as a bitmap (so doesn't look as good).
|
||||
- *safeMode()* can be used in place of *flashlight()* as a safeguard to allow uploading a new sketch when the bootloader "magic key" problem is an issue. It only lights the red RGB LED, so you don't get the bright light that is the primary purpose of *flashlight()*.
|
||||
|
||||
It is also possible to replace the boot logo drawing function with one that uses a different bitmap rendering function used elsewhere in your sketch. This may save memory by using this bitmap function for the logo, instead of the logo using a separate function that only ends up being used once. For example, if you use the *ArdBitmap* library's *drawCompressed()* function in your sketch, you could convert the **ARDUBOY** logo to *Ardbitmap* compressed format, and create *drawLogoArdCompressed()* and *bootLogoArdCompressed()* functions:
|
||||
|
||||
```cpp
|
||||
arduboy.boot(); // raw hardware
|
||||
void drawLogoArdCompressed(int16_t y)
|
||||
{
|
||||
ardbitmap.drawCompressed(20, y, arduboy_logo_ardbitmap,
|
||||
WHITE, ALIGN_CENTER, MIRROR_NONE);
|
||||
}
|
||||
|
||||
// *** This particular sketch clears the display soon, so it doesn't need this:
|
||||
// blank(); // blank the display
|
||||
void bootLogoArdCompressed()
|
||||
{
|
||||
if (arduboy.bootLogoShell(drawLogoArdCompressed))
|
||||
{
|
||||
arduboy.bootLogoExtra();
|
||||
}
|
||||
}
|
||||
|
||||
arduboy.flashlight(); // light the RGB LED and screen if UP button is being held.
|
||||
void setup()
|
||||
{
|
||||
arduboy.beginDoFirst();
|
||||
bootLogoArdCompressed();
|
||||
arduboy.waitNoButtons();
|
||||
|
||||
// check for and handle buttons held during start up for system control
|
||||
// systemButtons();
|
||||
// Additional setup code...
|
||||
|
||||
// bootLogo();
|
||||
|
||||
arduboy.audio.begin();
|
||||
}
|
||||
```
|
||||
|
||||
This saves whatever code *blank()*, *systemButtons()* and *bootLogo()* would use.
|
||||
The **ARDUBOY** logo, in PNG format, is included in the library repository as file:
|
||||
|
||||
`extras/assets/arduboy_logo.png`
|
||||
|
||||
#### Use the SpritesB class instead of Sprites
|
||||
|
||||
The *SpritesB* class has functions identical to the *Sprites* class. The difference is that *SpritesB* is optimized for small code size rather than execution speed. If you want to use the sprites functions, and the slower speed of *SpritesB* doesn't affect your sketch, you may be able to use it to gain some code space.
|
||||
|
||||
Even if the speed is acceptable when using *SpritesB*, you should still try using *Sprites*. In some cases *Sprites* will produce less code than *SpritesB*, notably when only one of the functions is used.
|
||||
|
||||
You can easily switch between using *Sprites* or *SpritesB* by using one or the other to create an object instance:
|
||||
|
||||
```cpp
|
||||
Sprites sprites; // Use this to optimize for execution speed
|
||||
SpritesB sprites; // Use this to (likely) optimize for code size
|
||||
```
|
||||
|
||||
#### Eliminate the USB stack code
|
||||
|
||||
**Warning:** Although this will free up a fair amount of code and some RAM space, without an active USB interface uploader programs will be unable to automatically force a reset to invoke the bootloader. This means the user will have to manually initiate a reset in order to upload a new sketch. This can be an inconvenience or even frustrating for a user, due to the fact that timing the sequence can sometimes be tricky. Therefore, using this technique should be considered as a last resort. If it is used, the sketch documentation should state clearly what will be involved to upload a new sketch.
|
||||
|
||||
The *ARDUBOY_NO_USB* macro is used to eliminate the USB code. The *exitToBootloader()* function is available to make it easier for a user to invoke the bootloader. For more details, see the documentation provided for these.
|
||||
|
||||
----------
|
||||
|
||||
## What's different from Arduboy library V1.1
|
||||
|
||||
(These notes apply to when the *Arduboy2* library was first released. There will have been many additional changes, enhancements and features added to *Arduboy2* since then.)
|
||||
|
||||
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 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.
|
||||
- The *clear()* function will now reset the text cursor to home position 0, 0.
|
||||
- A new feature has been added which allows the *audio on/off* flag in system EEPROM to be configured by the user when the sketch starts. The flag is used by the Arduboy and Arduboy2 *audio* subclass, along with external sound functions and libraries, to provide a standardized sound mute capability. See the information above, under the heading *Audio mute control*, for more details.
|
||||
- The *color* parameter, which is the last parameter for most of the drawing functions, has been made optional and will default to WHITE if not included in the call. This doesn't save any code but has been added as a convenience, since most drawing functions are called with WHITE specified.
|
||||
- A new function *digitalWriteRGB()* has been added to control the RGB LED digitally instead of using PWM. This uses less code if just turning the RGB LEDs fully on or off is all that's required.
|
||||
- The *beginNoLogo()* function is not included. This function could be used in Arduboy V1.1 in place of *begin()* to suppress the displaying of the ARDUBOY logo and thus free up the code that it required. Instead, Arduboy2 allows a sketch to call *boot()* and then add in any extra features that *begin()* provides by calling their functions directly after *boot()*, if desired.
|
||||
- The *ArduboyCore* and *ArduboyAudio* base classes, previously only available to, and used to derive, the *Arduboy* class, have been made publicly available for the benefit of developers who may wish to use them as the base of an entirely new library. This change doesn't affect the existing API.
|
||||
|
||||
As of version 2.1.0 functionality from the Team A.R.G. *Arglib* library has been added:
|
||||
|
||||
- The sprite drawing functions, collision detection functions, and button handling functions that Team A.R.G. incorporated from the [ArduboyExtra](https://github.com/yyyc514/ArduboyExtra) project. The *poll()* function was renamed *pollButtons()* for clarity. The *Sprites* class doesn't require a parameter for the constructor, whereas in *Arglib* a pointer to an Arduboy class object is required.
|
||||
- The *drawCompressed()* function, which allows compressed bitmaps to be drawn. Saving bitmaps in compressed form may reduce overall sketch size.
|
||||
|
||||
Team A.R.G. has now migrated all of their games and demos to use the Arduboy2 library.
|
||||
|
||||
## Migrating a sketch from Arduboy library V1.1 to Arduboy2
|
||||
|
||||
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 <Arduboy.h>` becomes `#include <Ardbuoy2.h>`
|
||||
```cpp
|
||||
#include <Arduboy.h>
|
||||
```
|
||||
|
||||
(If it was *"Arduboy.h"* in quotes, it's still better to change it to *<Ardbuoy2.h>* in angle brackets).
|
||||
becomes
|
||||
|
||||
```cpp
|
||||
#include <Arduboy2.h>
|
||||
```
|
||||
|
||||
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
|
||||
|
||||
### Sketch now runs too fast
|
||||
```cpp
|
||||
Arduboy2 arduboy;
|
||||
```
|
||||
|
||||
If the sketch uses the *nextFrame()* function to maintain a steady speed, you may find that it now runs too fast (because of a bug in Arduboy V1.1 that has been fixed in Arduboy2). The solution may be to just specify a lower value in the call to *setFrameRate()*. Otherwise, the changes required will depend on the particular sketch, based on the fact that frame rates now work properly.
|
||||
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
|
||||
### Sketch uses only tunes.tone() for sound
|
||||
|
||||
If the sketch has sound but only uses *tunes.tone()*, solutions are:
|
||||
|
||||
#### Solution 1: Switch to using Arduino *tone()*
|
||||
#### Solution 1: Switch to using Arduino tone()
|
||||
|
||||
An easy change is to use the Arduino built in *tone()* function. You can add a function to the sketch that wraps *tone()* so that it works like *tunes.tone()*, like so:
|
||||
|
||||
|
|
@ -212,7 +366,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
|
||||
|
||||
|
|
@ -220,7 +382,9 @@ Changing to the *ArduboyTones* library is slightly more complicated. The advanta
|
|||
|
||||
You have to add an include for the ArduboyTones header file:
|
||||
|
||||
`#include <ArduboyTones.h>`
|
||||
```cpp
|
||||
#include <ArduboyTones.h>
|
||||
```
|
||||
|
||||
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:
|
||||
|
||||
|
|
@ -231,21 +395,31 @@ 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.
|
||||
|
||||
See the following for how to do this:
|
||||
|
||||
### Sketch uses *tunes.playScore()*
|
||||
### Sketch uses tunes.playScore()
|
||||
|
||||
If the sketch uses *tunes.playScore()*, probably the easiest solution is to use the *ArduboyPlaytune* library. *ArduboyPlaytune* is essentially the code that was in the Arduboy V1.1 *tunes* subclass, which has been removed from Arduboy2. It's been cleaned up and a few enhancements have been added, but all the Arduboy V1.1 *tunes* functions are available.
|
||||
|
||||
You have to add an include for the ArduboyPlaytune header file:
|
||||
|
||||
`#include <ArduboyPlaytune.h>`
|
||||
```cpp
|
||||
#include <ArduboyPlaytune.h>
|
||||
```
|
||||
|
||||
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:
|
||||
|
||||
|
|
@ -254,17 +428,32 @@ 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 initialized and assigned to the speaker pins. This code would go in the *setup()* function:
|
||||
|
||||
```cpp
|
||||
// audio setup
|
||||
tunes.initChannel(PIN_SPEAKER_1);
|
||||
#ifndef AB_DEVKIT
|
||||
// if not a DevKit
|
||||
tunes.initChannel(PIN_SPEAKER_2);
|
||||
#else
|
||||
// if it's a DevKit
|
||||
tunes.initChannel(PIN_SPEAKER_1); // use the same pin for both channels
|
||||
tunes.toneMutesScore(true); // mute the score when a tone is sounding
|
||||
#endif
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
|
|
@ -272,5 +461,16 @@ If you don't need to play scores containing two parts, and don't require tones t
|
|||
|
||||
The benefit of using *ArduboyTones* would be reduced code size and possibly easier addition of new sequences without the need of a MIDI to Playtune format converter.
|
||||
|
||||
### Sketch uses the beginNoLogo() function instead of begin()
|
||||
|
||||
The *beginNoLogo()* function has been removed. *beginNoLogo()* can be replaced with *begin()*, since users can choose to suppress the logo sequence using the *RIGHT* button or by setting a flag in system EEPROM.
|
||||
|
||||
If using *begin()* results in the sketch program memory size being too large, *beginDoFirst()* or *boot()* can be used with additional functions following it to add back in desired boot functionality. See the information above, under the heading *Substitute or remove boot up features*, for more details. Assuming the object is named *arduboy*, an equivalent replacement for *beginNoLogo()* would be:
|
||||
|
||||
```cpp
|
||||
arduboy.beginDoFirst();
|
||||
arduboy.waitNoButtons();
|
||||
```
|
||||
|
||||
----------
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,9 @@
|
|||
Copyright (C) 2011 Sebastian Goscik
|
||||
All rights reserved.
|
||||
|
||||
Modifications by Scott Allen 2016, 2018, 2020
|
||||
after previous changes by person(s) unknown.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
|
|
@ -10,27 +13,49 @@
|
|||
*/
|
||||
|
||||
#include <Arduboy2.h>
|
||||
#include "breakout_bitmaps.h"
|
||||
|
||||
// block in EEPROM to save high scores
|
||||
#define EE_FILE 2
|
||||
|
||||
// EEPROM space used: 35 bytes (7*(3+2)) starting at
|
||||
// EEPROM_STORAGE_SPACE_START + (EE_FILE * 35)
|
||||
|
||||
Arduboy2 arduboy;
|
||||
BeepPin1 beep;
|
||||
|
||||
constexpr uint8_t frameRate = 40; // Frame rate in frames per second
|
||||
|
||||
// Tone frequencies. Converted to count values for the beep class
|
||||
constexpr uint16_t tonePaddle = beep.freq(200); // Ball hits paddle
|
||||
constexpr uint16_t toneBrick = beep.freq(261); // Ball hits a brick
|
||||
constexpr uint16_t toneEdge = beep.freq(523); // Ball hits top or sides
|
||||
constexpr uint16_t toneMiss = beep.freq(175); // Ball misses paddle, lose life
|
||||
constexpr uint16_t toneInitialsChange = beep.freq(523); // Change initials
|
||||
constexpr uint16_t toneInitialsMove = beep.freq(1046); // Select initials
|
||||
// Tone durations
|
||||
constexpr uint8_t toneTimeBeep = 250 / (1000 / frameRate); // Game (frames)
|
||||
constexpr uint16_t toneTimeMiss = 500; // Miss paddle (milliseconds)
|
||||
constexpr uint16_t toneTimeInitials = 80; // Initials entry (milliseconds)
|
||||
|
||||
|
||||
constexpr unsigned int columns = 13; //Columns of bricks
|
||||
constexpr unsigned int rows = 4; //Rows of bricks
|
||||
|
||||
const unsigned int COLUMNS = 13; //Columns of bricks
|
||||
const unsigned int ROWS = 4; //Rows of bricks
|
||||
int dx = -1; //Initial movement of ball
|
||||
int dy = -1; //Initial movement of ball
|
||||
int xb; //Balls starting possition
|
||||
int yb; //Balls starting possition
|
||||
int xb; //Ball's starting position
|
||||
int yb; //Ball's starting position
|
||||
boolean released; //If the ball has been released by the player
|
||||
boolean paused = false; //If the game has been paused
|
||||
byte xPaddle; //X position of paddle
|
||||
boolean isHit[ROWS][COLUMNS]; //Array of if bricks are hit or not
|
||||
boolean isHit[rows][columns]; //Array of if bricks are hit or not
|
||||
boolean bounced=false; //Used to fix double bounce glitch
|
||||
byte lives = 3; //Amount of lives
|
||||
byte level = 1; //Current level
|
||||
unsigned int score=0; //Score for the game
|
||||
unsigned int brickCount; //Amount of bricks hit
|
||||
byte pad,pad2,pad3; //Button press buffer used to stop pause repeating
|
||||
byte oldpad,oldpad2,oldpad3;
|
||||
boolean pad, pad2, pad3; //Button press buffer used to stop pause repeating
|
||||
boolean oldpad, oldpad2, oldpad3;
|
||||
char text_buffer[16]; //General string buffer
|
||||
boolean start=false; //If in menu or in game
|
||||
boolean initialDraw=false;//If the inital draw has happened
|
||||
|
|
@ -53,7 +78,9 @@ byte tick;
|
|||
void setup()
|
||||
{
|
||||
arduboy.begin();
|
||||
arduboy.setFrameRate(25);
|
||||
beep.begin();
|
||||
arduboy.setFrameRate(frameRate);
|
||||
arduboy.initRandomSeed();
|
||||
}
|
||||
|
||||
void loop()
|
||||
|
|
@ -62,6 +89,9 @@ void loop()
|
|||
if (!(arduboy.nextFrame()))
|
||||
return;
|
||||
|
||||
// Handle the timing and stopping of tones
|
||||
beep.timer();
|
||||
|
||||
//Title screen loop switches from title screen
|
||||
//and high scores until FIRE is pressed
|
||||
while (!start)
|
||||
|
|
@ -69,7 +99,7 @@ void loop()
|
|||
start = titleScreen();
|
||||
if (!start)
|
||||
{
|
||||
start = displayHighScores(2);
|
||||
start = displayHighScores(EE_FILE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -80,8 +110,10 @@ void loop()
|
|||
arduboy.clear();
|
||||
//Selects Font
|
||||
//Draws the new level
|
||||
newLevel();
|
||||
level = 1;
|
||||
initialDraw=true;
|
||||
newLevel();
|
||||
score = 0;
|
||||
}
|
||||
|
||||
if (lives>0)
|
||||
|
|
@ -91,16 +123,16 @@ void loop()
|
|||
//Pause game if FIRE pressed
|
||||
pad = arduboy.pressed(A_BUTTON) || arduboy.pressed(B_BUTTON);
|
||||
|
||||
if(pad >1 && oldpad==0 && released)
|
||||
if(pad == true && oldpad == false && released)
|
||||
{
|
||||
oldpad2=0; //Forces pad loop 2 to run once
|
||||
oldpad2 = false; //Forces pad loop 2 to run once
|
||||
pause();
|
||||
}
|
||||
|
||||
oldpad=pad;
|
||||
oldpad = pad;
|
||||
drawBall();
|
||||
|
||||
if(brickCount == ROWS * COLUMNS)
|
||||
if(brickCount == rows * columns)
|
||||
{
|
||||
level++;
|
||||
newLevel();
|
||||
|
|
@ -111,14 +143,13 @@ void loop()
|
|||
drawGameOver();
|
||||
if (score > 0)
|
||||
{
|
||||
enterHighScore(2);
|
||||
enterHighScore(EE_FILE);
|
||||
}
|
||||
|
||||
arduboy.clear();
|
||||
initialDraw=false;
|
||||
start=false;
|
||||
lives=3;
|
||||
score=0;
|
||||
newLevel();
|
||||
}
|
||||
|
||||
|
|
@ -152,12 +183,15 @@ void moveBall()
|
|||
if(released)
|
||||
{
|
||||
//Move ball
|
||||
if (abs(dx)==2) {
|
||||
if (abs(dx)==2)
|
||||
{
|
||||
xb += dx/2;
|
||||
// 2x speed is really 1.5 speed
|
||||
if (tick%2==0)
|
||||
xb += dx/2;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
xb += dx;
|
||||
}
|
||||
yb=yb + dy;
|
||||
|
|
@ -173,19 +207,18 @@ void moveBall()
|
|||
{
|
||||
yb = 2;
|
||||
dy = -dy;
|
||||
playTone(523, 250);
|
||||
playTone(toneEdge, toneTimeBeep);
|
||||
}
|
||||
|
||||
//Lose a life if bottom edge hit
|
||||
if (yb >= 64)
|
||||
{
|
||||
arduboy.drawRect(xPaddle, 63, 11, 1, 0);
|
||||
arduboy.drawRect(xPaddle, 63, 11, 1, BLACK);
|
||||
xPaddle = 54;
|
||||
yb=60;
|
||||
released = false;
|
||||
lives--;
|
||||
drawLives();
|
||||
playTone(175, 250);
|
||||
playToneTimed(toneMiss, toneTimeMiss);
|
||||
if (random(0, 2) == 0)
|
||||
{
|
||||
dx = 1;
|
||||
|
|
@ -201,7 +234,7 @@ void moveBall()
|
|||
{
|
||||
xb = 2;
|
||||
dx = -dx;
|
||||
playTone(523, 250);
|
||||
playTone(toneEdge, toneTimeBeep);
|
||||
}
|
||||
|
||||
//Bounce off right side
|
||||
|
|
@ -209,7 +242,7 @@ void moveBall()
|
|||
{
|
||||
xb = WIDTH - 4;
|
||||
dx = -dx;
|
||||
playTone(523, 250);
|
||||
playTone(toneEdge, toneTimeBeep);
|
||||
}
|
||||
|
||||
//Bounce off paddle
|
||||
|
|
@ -218,16 +251,17 @@ void moveBall()
|
|||
dy = -dy;
|
||||
dx = ((xb-(xPaddle+6))/3); //Applies spin on the ball
|
||||
// prevent straight bounce
|
||||
if (dx == 0) {
|
||||
dx = (random(0,2) == 1) ? 1 : -1;
|
||||
if (dx == 0)
|
||||
{
|
||||
dx = (random(0, 2) == 1) ? 1 : -1;
|
||||
}
|
||||
playTone(200, 250);
|
||||
playTone(tonePaddle, toneTimeBeep);
|
||||
}
|
||||
|
||||
//Bounce off Bricks
|
||||
for (byte row = 0; row < ROWS; row++)
|
||||
for (byte row = 0; row < rows; row++)
|
||||
{
|
||||
for (byte column = 0; column < COLUMNS; column++)
|
||||
for (byte column = 0; column < columns; column++)
|
||||
{
|
||||
if (!isHit[row][column])
|
||||
{
|
||||
|
|
@ -237,14 +271,14 @@ void moveBall()
|
|||
topBrick = 6 * row + 1;
|
||||
bottomBrick = 6 * row + 7;
|
||||
|
||||
//If A collison has occured
|
||||
//If A collision has occurred
|
||||
if (topBall <= bottomBrick && bottomBall >= topBrick &&
|
||||
leftBall <= rightBrick && rightBall >= leftBrick)
|
||||
{
|
||||
Score();
|
||||
brickCount++;
|
||||
isHit[row][column] = true;
|
||||
arduboy.drawRect(10*column, 2+6*row, 8, 4, 0);
|
||||
arduboy.drawRect(10*column, 2+6*row, 8, 4, BLACK);
|
||||
|
||||
//Vertical collision
|
||||
if (bottomBall > bottomBrick || topBall < topBrick)
|
||||
|
|
@ -255,11 +289,11 @@ void moveBall()
|
|||
dy =- dy;
|
||||
yb += dy;
|
||||
bounced = true;
|
||||
playTone(261, 250);
|
||||
playTone(toneBrick, toneTimeBeep);
|
||||
}
|
||||
}
|
||||
|
||||
//Hoizontal collision
|
||||
//Horizontal collision
|
||||
if (leftBall < leftBrick || rightBall > rightBrick)
|
||||
{
|
||||
//Only bounce once brick each ball move
|
||||
|
|
@ -268,7 +302,7 @@ void moveBall()
|
|||
dx =- dx;
|
||||
xb += dx;
|
||||
bounced = true;
|
||||
playTone(261, 250);
|
||||
playTone(toneBrick, toneTimeBeep);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -285,9 +319,9 @@ void moveBall()
|
|||
|
||||
//Release ball if FIRE pressed
|
||||
pad3 = arduboy.pressed(A_BUTTON) || arduboy.pressed(B_BUTTON);
|
||||
if (pad3 == 1 && oldpad3 == 0)
|
||||
if (pad3 == true && oldpad3 == false)
|
||||
{
|
||||
released=true;
|
||||
released = true;
|
||||
|
||||
//Apply random direction to ball on release
|
||||
if (random(0, 2) == 0)
|
||||
|
|
@ -307,89 +341,80 @@ void moveBall()
|
|||
|
||||
void drawBall()
|
||||
{
|
||||
// arduboy.setCursor(0,0);
|
||||
// arduboy.print(arduboy.cpuLoad());
|
||||
// arduboy.print(" ");
|
||||
arduboy.drawPixel(xb, yb, 0);
|
||||
arduboy.drawPixel(xb+1, yb, 0);
|
||||
arduboy.drawPixel(xb, yb+1, 0);
|
||||
arduboy.drawPixel(xb+1, yb+1, 0);
|
||||
arduboy.drawPixel(xb, yb, BLACK);
|
||||
arduboy.drawPixel(xb+1, yb, BLACK);
|
||||
arduboy.drawPixel(xb, yb+1, BLACK);
|
||||
arduboy.drawPixel(xb+1, yb+1, BLACK);
|
||||
|
||||
moveBall();
|
||||
|
||||
arduboy.drawPixel(xb, yb, 1);
|
||||
arduboy.drawPixel(xb+1, yb, 1);
|
||||
arduboy.drawPixel(xb, yb+1, 1);
|
||||
arduboy.drawPixel(xb+1, yb+1, 1);
|
||||
arduboy.drawPixel(xb, yb, WHITE);
|
||||
arduboy.drawPixel(xb+1, yb, WHITE);
|
||||
arduboy.drawPixel(xb, yb+1, WHITE);
|
||||
arduboy.drawPixel(xb+1, yb+1, WHITE);
|
||||
}
|
||||
|
||||
void drawPaddle()
|
||||
{
|
||||
arduboy.drawRect(xPaddle, 63, 11, 1, 0);
|
||||
arduboy.drawRect(xPaddle, 63, 11, 1, BLACK);
|
||||
movePaddle();
|
||||
arduboy.drawRect(xPaddle, 63, 11, 1, 1);
|
||||
}
|
||||
|
||||
void drawLives()
|
||||
{
|
||||
sprintf(text_buffer, "LIVES:%u", lives);
|
||||
arduboy.setCursor(0, 90);
|
||||
arduboy.print(text_buffer);
|
||||
arduboy.drawRect(xPaddle, 63, 11, 1, WHITE);
|
||||
}
|
||||
|
||||
void drawGameOver()
|
||||
{
|
||||
arduboy.drawPixel(xb, yb, 0);
|
||||
arduboy.drawPixel(xb+1, yb, 0);
|
||||
arduboy.drawPixel(xb, yb+1, 0);
|
||||
arduboy.drawPixel(xb+1, yb+1, 0);
|
||||
arduboy.setCursor(52, 42);
|
||||
arduboy.print( "Game");
|
||||
arduboy.setCursor(52, 54);
|
||||
arduboy.print("Over");
|
||||
arduboy.drawPixel(xb, yb, BLACK);
|
||||
arduboy.drawPixel(xb+1, yb, BLACK);
|
||||
arduboy.drawPixel(xb, yb+1, BLACK);
|
||||
arduboy.drawPixel(xb+1, yb+1, BLACK);
|
||||
arduboy.setCursor(37, 42);
|
||||
arduboy.print("Game Over");
|
||||
arduboy.setCursor(31, 56);
|
||||
arduboy.print("Score: ");
|
||||
arduboy.print(score);
|
||||
arduboy.display();
|
||||
delay(4000);
|
||||
arduboy.delayShort(4000);
|
||||
}
|
||||
|
||||
void pause()
|
||||
{
|
||||
paused = true;
|
||||
//Stop tone if playing
|
||||
beep.noTone();
|
||||
//Draw pause to the screen
|
||||
arduboy.setCursor(52, 45);
|
||||
arduboy.print("PAUSE");
|
||||
arduboy.display();
|
||||
while (paused)
|
||||
{
|
||||
delay(150);
|
||||
arduboy.delayShort(150);
|
||||
//Unpause if FIRE is pressed
|
||||
pad2 = arduboy.pressed(A_BUTTON) || arduboy.pressed(B_BUTTON);
|
||||
if (pad2 > 1 && oldpad2 == 0 && released)
|
||||
if (pad2 == true && oldpad2 == false && released)
|
||||
{
|
||||
arduboy.fillRect(52, 45, 30, 11, 0);
|
||||
arduboy.fillRect(52, 45, 30, 11, BLACK);
|
||||
|
||||
paused=false;
|
||||
}
|
||||
oldpad2=pad2;
|
||||
oldpad2 = pad2;
|
||||
}
|
||||
}
|
||||
|
||||
void Score()
|
||||
{
|
||||
score += (level*10);
|
||||
sprintf(text_buffer, "SCORE:%u", score);
|
||||
arduboy.setCursor(80, 90);
|
||||
arduboy.print(text_buffer);
|
||||
}
|
||||
|
||||
void newLevel(){
|
||||
void newLevel()
|
||||
{
|
||||
//Undraw paddle
|
||||
arduboy.drawRect(xPaddle, 63, 11, 1, 0);
|
||||
arduboy.drawRect(xPaddle, 63, 11, 1, BLACK);
|
||||
|
||||
//Undraw ball
|
||||
arduboy.drawPixel(xb, yb, 0);
|
||||
arduboy.drawPixel(xb+1, yb, 0);
|
||||
arduboy.drawPixel(xb, yb+1, 0);
|
||||
arduboy.drawPixel(xb+1, yb+1, 0);
|
||||
arduboy.drawPixel(xb, yb, BLACK);
|
||||
arduboy.drawPixel(xb+1, yb, BLACK);
|
||||
arduboy.drawPixel(xb, yb+1, BLACK);
|
||||
arduboy.drawPixel(xb+1, yb+1, BLACK);
|
||||
|
||||
//Alter various variables to reset the game
|
||||
xPaddle = 54;
|
||||
|
|
@ -398,21 +423,23 @@ void newLevel(){
|
|||
released = false;
|
||||
|
||||
//Draws new bricks and resets their values
|
||||
for (byte row = 0; row < 4; row++) {
|
||||
for (byte row = 0; row < 4; row++)
|
||||
{
|
||||
for (byte column = 0; column < 13; column++)
|
||||
{
|
||||
isHit[row][column] = false;
|
||||
arduboy.drawRect(10*column, 2+6*row, 8, 4, 1);
|
||||
arduboy.drawRect(10*column, 2+6*row, 8, 4, WHITE);
|
||||
}
|
||||
}
|
||||
|
||||
//Draws the initial lives
|
||||
drawLives();
|
||||
|
||||
//Draws the initial score
|
||||
sprintf(text_buffer, "SCORE:%u", score);
|
||||
arduboy.setCursor(80, 90);
|
||||
arduboy.print(text_buffer);
|
||||
if (!initialDraw)
|
||||
{
|
||||
arduboy.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
arduboy.display();
|
||||
}
|
||||
}
|
||||
|
||||
//Used to delay images while reading button input
|
||||
|
|
@ -420,11 +447,11 @@ boolean pollFireButton(int n)
|
|||
{
|
||||
for(int i = 0; i < n; i++)
|
||||
{
|
||||
delay(15);
|
||||
arduboy.delayShort(15);
|
||||
pad = arduboy.pressed(A_BUTTON) || arduboy.pressed(B_BUTTON);
|
||||
if(pad == 1 && oldpad == 0)
|
||||
if(pad == true && oldpad == false)
|
||||
{
|
||||
oldpad3 = 1; //Forces pad loop 3 to run once
|
||||
oldpad3 = true; //Forces pad loop 3 to run once
|
||||
return true;
|
||||
}
|
||||
oldpad = pad;
|
||||
|
|
@ -432,24 +459,24 @@ boolean pollFireButton(int n)
|
|||
return false;
|
||||
}
|
||||
|
||||
//Function by nootropic design to display highscores
|
||||
//Function by nootropic design to display high scores
|
||||
boolean displayHighScores(byte file)
|
||||
{
|
||||
byte y = 10;
|
||||
byte y = 8;
|
||||
byte x = 24;
|
||||
// Each block of EEPROM has 10 high scores, and each high score entry
|
||||
// Each block of EEPROM has 7 high scores, and each high score entry
|
||||
// is 5 bytes long: 3 bytes for initials and two bytes for score.
|
||||
int address = file*10*5;
|
||||
int address = file * 7 * 5 + EEPROM_STORAGE_SPACE_START;
|
||||
byte hi, lo;
|
||||
arduboy.clear();
|
||||
arduboy.setCursor(32, 0);
|
||||
arduboy.print("HIGH SCORES");
|
||||
arduboy.display();
|
||||
|
||||
for(int i = 0; i < 10; i++)
|
||||
for(int i = 0; i < 7; i++)
|
||||
{
|
||||
sprintf(text_buffer, "%2d", i+1);
|
||||
arduboy.setCursor(x,y+(i*8));
|
||||
arduboy.setCursor(x, y+(i*8));
|
||||
arduboy.print(text_buffer);
|
||||
arduboy.display();
|
||||
hi = EEPROM.read(address + (5*i));
|
||||
|
|
@ -488,9 +515,9 @@ boolean titleScreen()
|
|||
{
|
||||
//Clears the screen
|
||||
arduboy.clear();
|
||||
arduboy.setCursor(16,22);
|
||||
arduboy.setCursor(16, 22);
|
||||
arduboy.setTextSize(2);
|
||||
arduboy.print("ARAKNOID");
|
||||
arduboy.print("BREAKOUT");
|
||||
arduboy.setTextSize(1);
|
||||
arduboy.display();
|
||||
if (pollFireButton(25))
|
||||
|
|
@ -502,7 +529,6 @@ boolean titleScreen()
|
|||
for(byte i = 0; i < 5; i++)
|
||||
{
|
||||
//Draws "Press FIRE"
|
||||
//arduboy.bitmap(31, 53, fire); arduboy.display();
|
||||
arduboy.setCursor(31, 53);
|
||||
arduboy.print("PRESS FIRE!");
|
||||
arduboy.display();
|
||||
|
|
@ -511,15 +537,12 @@ boolean titleScreen()
|
|||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//Removes "Press FIRE"
|
||||
arduboy.clear();
|
||||
arduboy.setCursor(16,22);
|
||||
arduboy.setTextSize(2);
|
||||
arduboy.print("ARAKNOID");
|
||||
arduboy.setTextSize(1);
|
||||
arduboy.setCursor(31, 53);
|
||||
arduboy.print(" ");
|
||||
arduboy.display();
|
||||
|
||||
arduboy.display();
|
||||
if (pollFireButton(25))
|
||||
{
|
||||
return true;
|
||||
|
|
@ -532,7 +555,7 @@ boolean titleScreen()
|
|||
//Function by nootropic design to add high scores
|
||||
void enterInitials()
|
||||
{
|
||||
char index = 0;
|
||||
byte index = 0;
|
||||
|
||||
arduboy.clear();
|
||||
|
||||
|
|
@ -545,7 +568,7 @@ void enterInitials()
|
|||
arduboy.display();
|
||||
arduboy.clear();
|
||||
|
||||
arduboy.setCursor(16,0);
|
||||
arduboy.setCursor(16, 0);
|
||||
arduboy.print("HIGH SCORE");
|
||||
sprintf(text_buffer, "%u", score);
|
||||
arduboy.setCursor(88, 0);
|
||||
|
|
@ -558,39 +581,34 @@ void enterInitials()
|
|||
arduboy.print(initials[2]);
|
||||
for(byte i = 0; i < 3; i++)
|
||||
{
|
||||
arduboy.drawLine(56 + (i*8), 27, 56 + (i*8) + 6, 27, 1);
|
||||
arduboy.drawLine(56 + (i*8), 27, 56 + (i*8) + 6, 27, WHITE);
|
||||
}
|
||||
arduboy.drawLine(56, 28, 88, 28, 0);
|
||||
arduboy.drawLine(56 + (index*8), 28, 56 + (index*8) + 6, 28, 1);
|
||||
delay(150);
|
||||
arduboy.drawLine(56, 28, 88, 28, BLACK);
|
||||
arduboy.drawLine(56 + (index*8), 28, 56 + (index*8) + 6, 28, WHITE);
|
||||
arduboy.delayShort(70);
|
||||
|
||||
if (arduboy.pressed(LEFT_BUTTON) || arduboy.pressed(B_BUTTON))
|
||||
{
|
||||
index--;
|
||||
if (index < 0)
|
||||
if (index > 0)
|
||||
{
|
||||
index = 0;
|
||||
} else
|
||||
{
|
||||
playTone(1046, 250);
|
||||
index--;
|
||||
playToneTimed(toneInitialsMove, toneTimeInitials);
|
||||
}
|
||||
}
|
||||
|
||||
if (arduboy.pressed(RIGHT_BUTTON))
|
||||
{
|
||||
index++;
|
||||
if (index > 2)
|
||||
if (index < 2)
|
||||
{
|
||||
index = 2;
|
||||
} else {
|
||||
playTone(1046, 250);
|
||||
index++;
|
||||
playToneTimed(toneInitialsMove, toneTimeInitials);
|
||||
}
|
||||
}
|
||||
|
||||
if (arduboy.pressed(DOWN_BUTTON))
|
||||
if (arduboy.pressed(UP_BUTTON))
|
||||
{
|
||||
initials[index]++;
|
||||
playTone(523, 250);
|
||||
playToneTimed(toneInitialsChange, toneTimeInitials);
|
||||
// A-Z 0-9 :-? !-/ ' '
|
||||
if (initials[index] == '0')
|
||||
{
|
||||
|
|
@ -610,32 +628,37 @@ void enterInitials()
|
|||
}
|
||||
}
|
||||
|
||||
if (arduboy.pressed(UP_BUTTON))
|
||||
if (arduboy.pressed(DOWN_BUTTON))
|
||||
{
|
||||
initials[index]--;
|
||||
playTone(523, 250);
|
||||
if (initials[index] == ' ') {
|
||||
playToneTimed(toneInitialsChange, toneTimeInitials);
|
||||
if (initials[index] == ' ')
|
||||
{
|
||||
initials[index] = '?';
|
||||
}
|
||||
if (initials[index] == '/') {
|
||||
if (initials[index] == '/')
|
||||
{
|
||||
initials[index] = 'Z';
|
||||
}
|
||||
if (initials[index] == 31) {
|
||||
if (initials[index] == 31)
|
||||
{
|
||||
initials[index] = '/';
|
||||
}
|
||||
if (initials[index] == '@') {
|
||||
if (initials[index] == '@')
|
||||
{
|
||||
initials[index] = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
if (arduboy.pressed(A_BUTTON))
|
||||
{
|
||||
playToneTimed(toneInitialsMove, toneTimeInitials);
|
||||
if (index < 2)
|
||||
{
|
||||
index++;
|
||||
playTone(1046, 250);
|
||||
} else {
|
||||
playTone(1046, 250);
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -645,15 +668,15 @@ void enterInitials()
|
|||
|
||||
void enterHighScore(byte file)
|
||||
{
|
||||
// Each block of EEPROM has 10 high scores, and each high score entry
|
||||
// Each block of EEPROM has 7 high scores, and each high score entry
|
||||
// is 5 bytes long: 3 bytes for initials and two bytes for score.
|
||||
int address = file * 10 * 5;
|
||||
int address = file * 7 * 5 + EEPROM_STORAGE_SPACE_START;
|
||||
byte hi, lo;
|
||||
char tmpInitials[3];
|
||||
unsigned int tmpScore = 0;
|
||||
|
||||
// High score processing
|
||||
for(byte i = 0; i < 10; i++)
|
||||
for(byte i = 0; i < 7; i++)
|
||||
{
|
||||
hi = EEPROM.read(address + (5*i));
|
||||
lo = EEPROM.read(address + (5*i) + 1);
|
||||
|
|
@ -662,14 +685,15 @@ void enterHighScore(byte file)
|
|||
// The values are uninitialized, so treat this entry
|
||||
// as a score of 0.
|
||||
tmpScore = 0;
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
tmpScore = (hi << 8) | lo;
|
||||
}
|
||||
if (score > tmpScore)
|
||||
{
|
||||
enterInitials();
|
||||
for(byte j=i;j<10;j++)
|
||||
for(byte j = i; j < 7; j++)
|
||||
{
|
||||
hi = EEPROM.read(address + (5*j));
|
||||
lo = EEPROM.read(address + (5*j) + 1);
|
||||
|
|
@ -688,11 +712,11 @@ void enterHighScore(byte file)
|
|||
tmpInitials[2] = (char)EEPROM.read(address + (5*j) + 4);
|
||||
|
||||
// write score and initials to current slot
|
||||
EEPROM.write(address + (5*j), ((score >> 8) & 0xFF));
|
||||
EEPROM.write(address + (5*j) + 1, (score & 0xFF));
|
||||
EEPROM.write(address + (5*j) + 2, initials[0]);
|
||||
EEPROM.write(address + (5*j) + 3, initials[1]);
|
||||
EEPROM.write(address + (5*j) + 4, initials[2]);
|
||||
EEPROM.update(address + (5*j), ((score >> 8) & 0xFF));
|
||||
EEPROM.update(address + (5*j) + 1, (score & 0xFF));
|
||||
EEPROM.update(address + (5*j) + 2, initials[0]);
|
||||
EEPROM.update(address + (5*j) + 3, initials[1]);
|
||||
EEPROM.update(address + (5*j) + 4, initials[2]);
|
||||
|
||||
// tmpScore and tmpInitials now hold what we want to
|
||||
//write in the next slot.
|
||||
|
|
@ -712,12 +736,20 @@ void enterHighScore(byte file)
|
|||
}
|
||||
}
|
||||
|
||||
// Wrap the Arduino tone() function so that the pin doesn't have to be
|
||||
// specified each time. Also, don't play if audio is set to off.
|
||||
void playTone(unsigned int frequency, unsigned long duration)
|
||||
// Play a tone at a frequency corresponding to the specified precomputed count,
|
||||
// for the specified number of frames.
|
||||
void playTone(uint16_t count, uint8_t frames)
|
||||
{
|
||||
if (arduboy.audio.enabled() == true)
|
||||
{
|
||||
tone(PIN_SPEAKER_1, frequency, duration);
|
||||
}
|
||||
beep.tone(count, frames);
|
||||
}
|
||||
|
||||
// Play a tone at a frequency corresponding to the specified precomputed count,
|
||||
// for the specified duration in milliseconds, using a delay.
|
||||
// Used when beep.timer() isn't being called.
|
||||
void playToneTimed(uint16_t count, uint16_t duration)
|
||||
{
|
||||
beep.tone(count);
|
||||
arduboy.delayShort(duration);
|
||||
beep.noTone();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,124 +0,0 @@
|
|||
#include "breakout_bitmaps.h"
|
||||
|
||||
PROGMEM const unsigned char title[] =
|
||||
{
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x07,0xFF,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xE0,0x00,
|
||||
0x00,0x08,0x00,0x60,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x03,0xF4,0x10,0x00,
|
||||
0x00,0x0B,0xFF,0x10,0x00,0x00,0x00,0x20,0x80,0x00,0x00,0x04,0x09,0xD0,0x00,
|
||||
0x00,0x0B,0x83,0xD0,0x00,0x00,0x00,0x2E,0xB8,0x00,0x00,0x05,0xE1,0xD0,0x00,
|
||||
0x00,0x0B,0x83,0xD0,0x00,0x00,0x00,0x2E,0x44,0x00,0x00,0x05,0xE1,0xD0,0x00,
|
||||
0x00,0x0B,0x83,0xD0,0x00,0x00,0x00,0x2E,0x34,0x00,0x00,0x05,0xE1,0xD0,0x00,
|
||||
0x00,0x0B,0x83,0xCF,0xFF,0xF9,0xFF,0xAE,0x35,0xFF,0x7C,0xF9,0xE1,0xD0,0x00,
|
||||
0x00,0x0B,0x83,0xC0,0x00,0x06,0x00,0x4E,0x66,0x00,0x83,0x01,0xE1,0xD0,0x00,
|
||||
0x00,0x0B,0xFF,0x13,0xE7,0xF0,0xFF,0x0F,0xE0,0x7E,0x38,0x73,0xF9,0xD0,0x00,
|
||||
0x00,0x0B,0xFF,0x13,0xE7,0xF0,0xFF,0x0F,0xC0,0x7E,0x38,0x73,0xF9,0xD0,0x00,
|
||||
0x00,0x0B,0x83,0xDC,0x0E,0x0C,0x01,0xCF,0x80,0xE1,0x38,0x71,0xE1,0xD0,0x00,
|
||||
0x00,0x0B,0x83,0xDC,0xCE,0x0C,0x01,0xCF,0xC0,0xE1,0x38,0x71,0xE1,0xD0,0x00,
|
||||
0x00,0x0B,0x83,0xDD,0x2F,0xF0,0x7F,0xCE,0xE0,0xE1,0x38,0x71,0xE0,0x10,0x00,
|
||||
0x00,0x0B,0x83,0xDD,0x2F,0xF0,0xFF,0xCE,0x70,0xE1,0x38,0x71,0xE0,0x10,0x00,
|
||||
0x00,0x0B,0x83,0xDD,0x2E,0x00,0x81,0xCE,0x38,0xE1,0x38,0x71,0xE1,0xD0,0x00,
|
||||
0x00,0x0B,0xFF,0x1D,0x27,0xFC,0xFE,0xCE,0x1C,0x7E,0x1F,0xC4,0x79,0xD0,0x00,
|
||||
0x00,0x0B,0xFF,0x1D,0x17,0xFC,0x7E,0xCE,0x0C,0x7E,0x1F,0xCA,0x79,0xD0,0x00,
|
||||
0x00,0x08,0x00,0x41,0x10,0x01,0x00,0x00,0xE1,0x00,0xC0,0x11,0x00,0x10,0x00,
|
||||
0x00,0x07,0xFF,0xBE,0x0F,0xFE,0xFF,0xFF,0x1E,0xFF,0x3F,0xE0,0xFF,0xE0,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x04,0x04,0x10,0x03,0x8A,0x10,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x04,0x00,0x00,0x02,0x08,0x80,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0xF3,0x35,0x54,0xD7,0x63,0x1A,0xD7,0x60,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x95,0x46,0x54,0x95,0x52,0x2A,0x95,0x50,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x93,0x35,0x25,0x97,0x53,0x9A,0x57,0x50,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0xF0,0x06,0x04,0x00,0x04,0x00,0x38,0x00,0x0A,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x88,0x09,0x04,0x00,0x20,0x00,0x44,0x00,0x02,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0xF2,0x84,0x27,0x31,0xB5,0x98,0x40,0xC6,0x6A,0x80,0x00,0x00,
|
||||
0x00,0x00,0x00,0x8A,0x82,0x54,0x8A,0x24,0x54,0x4D,0x28,0x8B,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x8A,0x89,0x44,0xA8,0xA5,0x54,0x45,0x22,0x8A,0x80,0x00,0x00,
|
||||
0x00,0x00,0x00,0xF1,0x06,0x37,0x1B,0x14,0xD4,0x3C,0xCC,0x6A,0x80,0x00,0x00,
|
||||
0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
};
|
||||
|
||||
PROGMEM const unsigned char fire[] =
|
||||
{
|
||||
57,8,
|
||||
0xF8,0x00,0x00,0x00,0x3D,0xEF,0x8F,0x80,
|
||||
0xCC,0x00,0x00,0x00,0x60,0xCC,0xD8,0x00,
|
||||
0xCC,0x00,0x00,0x00,0x60,0xCC,0xD8,0x00,
|
||||
0xF9,0x67,0x1E,0x78,0x78,0xCF,0x9F,0x00,
|
||||
0xC1,0x8C,0xA0,0x80,0x60,0xCC,0xD8,0x00,
|
||||
0xC1,0x8F,0x1C,0x70,0x60,0xCC,0xD8,0x00,
|
||||
0xC1,0x8C,0x02,0x08,0x60,0xCC,0xDF,0x80,
|
||||
0xC1,0x87,0xBC,0xF0,0x61,0xEC,0xCF,0x80,
|
||||
};
|
||||
|
||||
PROGMEM const unsigned char arrow[] =
|
||||
{
|
||||
5,5,
|
||||
0x20,
|
||||
0x10,
|
||||
0xF8,
|
||||
0x10,
|
||||
0x20,
|
||||
};
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
#ifndef BREAKOUT_BITMAPS_H
|
||||
#define BREAKOUT_BITMAPS_H
|
||||
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
extern const unsigned char fire[];
|
||||
extern const unsigned char title[];
|
||||
extern const unsigned char arrow[];
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
BeepDemo.ino
|
||||
|
||||
This sketch provides an example of using the Arduboy2 library's BeepPin1 class
|
||||
to play simple tones.
|
||||
*/
|
||||
|
||||
/*
|
||||
Written in 2018 by Scott Allen saydisp-git@yahoo.ca
|
||||
|
||||
To the extent possible under law, the author(s) have dedicated all copyright
|
||||
and related and neighboring rights to this software to the public domain
|
||||
worldwide. This software is distributed without any warranty.
|
||||
|
||||
You should have received a copy of the CC0 Public Domain Dedication along with
|
||||
this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
*/
|
||||
|
||||
// Comments are only provided for code dealing with tone generation or control.
|
||||
|
||||
#include <Arduboy2.h>
|
||||
// There's no need to #include <Arduboy2Beep.h>
|
||||
// It will be included in Arduboy2.h
|
||||
|
||||
Arduboy2 arduboy;
|
||||
|
||||
BeepPin1 beep; // Create a class instance for speaker pin 1
|
||||
//BeepPin2 beep; // For speaker pin 2, use this line instead of the line above
|
||||
|
||||
int objectX = 0;
|
||||
|
||||
char displayText[60];
|
||||
|
||||
void setup() {
|
||||
arduboy.begin();
|
||||
arduboy.setFrameRate(25);
|
||||
|
||||
beep.begin(); // Set up the hardware for playing tones
|
||||
|
||||
commandText("none - Press buttons");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (!arduboy.nextFrame()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The timer() function is called once per frame, so duration values will be
|
||||
// the number of frames that the tone plays for.
|
||||
// At 25 frames per second each frame will be 40ms.
|
||||
beep.timer(); // handle tone duration
|
||||
|
||||
arduboy.pollButtons();
|
||||
|
||||
arduboy.clear();
|
||||
|
||||
if (arduboy.justPressed(LEFT_BUTTON)) {
|
||||
// Play a 523.251Hz tone (piano note C5) for 5 frames (200ms at 25 FPS)
|
||||
// beep.freq(523.251) is used to convert 523.251Hz to the required count
|
||||
beep.tone(beep.freq(523.251), 5);
|
||||
|
||||
commandText("beep.tone(\n beep.freq(523.251),\n 5)");
|
||||
}
|
||||
|
||||
if (arduboy.justPressed(UP_BUTTON)) {
|
||||
// Play a 587.330Hz tone (piano note D5) for 15 frames (600ms at 25 FPS)
|
||||
beep.tone(beep.freq(587.330), 15);
|
||||
|
||||
commandText("beep.tone(\n beep.freq(587.330),\n 15)");
|
||||
}
|
||||
|
||||
if (arduboy.justPressed(RIGHT_BUTTON)) {
|
||||
// Play a 659.255Hz tone (piano note E5) for 50 frames (2s at 25 FPS)
|
||||
beep.tone(beep.freq(659.255), 50);
|
||||
|
||||
commandText("beep.tone(\n beep.freq(659.255),\n 50)");
|
||||
}
|
||||
|
||||
if (arduboy.justPressed(DOWN_BUTTON)) {
|
||||
// Play a 698.456Hz tone (piano note F5) until stopped
|
||||
// or replaced by another tone
|
||||
beep.tone(beep.freq(698.456));
|
||||
|
||||
commandText("beep.tone(\n beep.freq(698.456))");
|
||||
}
|
||||
|
||||
if (arduboy.justPressed(A_BUTTON)) {
|
||||
// For short tones with a duration less than a frame time,
|
||||
// or when timer() isn't being used, such as in a menu,
|
||||
// a continuous tone can be played and then stopped after a delay
|
||||
// but note that no other work will be done during the delay.
|
||||
beep.tone(beep.freq(1000)); // Play a 1000Hz tone until stopped
|
||||
arduboy.delayShort(30); // Delay for 30ms
|
||||
beep.noTone(); // Stop the tone
|
||||
|
||||
commandText("beep.tone(\n beep.freq(1000))\n(delay 30ms)\nbeep.noTone()");
|
||||
}
|
||||
|
||||
if (arduboy.justPressed(B_BUTTON)) {
|
||||
beep.noTone(); // Stop the tone if one is playing
|
||||
|
||||
commandText("beep.noTone()");
|
||||
}
|
||||
|
||||
arduboy.println(F("Last command:"));
|
||||
arduboy.print(displayText);
|
||||
|
||||
// The Arduboy2 class's audio subclass controls sound muting.
|
||||
// For this sketch, mute or unmute can be set using the "System Control"
|
||||
// start up feature. (Hold B while powering up then, while still holding B,
|
||||
// press UP to enable sound or DOWN for mute.)
|
||||
if (!arduboy.audio.enabled()) {
|
||||
arduboy.setCursor(22, 40);
|
||||
arduboy.print(F("Sound is MUTED"));
|
||||
}
|
||||
|
||||
arduboy.setCursor(0, 48);
|
||||
// The "duration" variable can be tested for non-zero to determine if a
|
||||
// timed tone is currently playing.
|
||||
if (beep.duration != 0) {
|
||||
arduboy.print(F("A tone is playing"));
|
||||
}
|
||||
else {
|
||||
arduboy.print(F("Continuous tone or\nno tone playing"));
|
||||
}
|
||||
|
||||
arduboy.drawRect(objectX, 40, 6, 6);
|
||||
if (++objectX == WIDTH - 6) {
|
||||
objectX = 0;
|
||||
}
|
||||
|
||||
arduboy.display();
|
||||
}
|
||||
|
||||
void commandText(const char* text) {
|
||||
strncpy(displayText, text, sizeof displayText);
|
||||
displayText[sizeof displayText - 1] = '\0';
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
Creative Commons Legal Code
|
||||
|
||||
CC0 1.0 Universal
|
||||
|
||||
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
|
||||
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
|
||||
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
|
||||
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
|
||||
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
|
||||
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
|
||||
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
|
||||
HEREUNDER.
|
||||
|
||||
Statement of Purpose
|
||||
|
||||
The laws of most jurisdictions throughout the world automatically confer
|
||||
exclusive Copyright and Related Rights (defined below) upon the creator
|
||||
and subsequent owner(s) (each and all, an "owner") of an original work of
|
||||
authorship and/or a database (each, a "Work").
|
||||
|
||||
Certain owners wish to permanently relinquish those rights to a Work for
|
||||
the purpose of contributing to a commons of creative, cultural and
|
||||
scientific works ("Commons") that the public can reliably and without fear
|
||||
of later claims of infringement build upon, modify, incorporate in other
|
||||
works, reuse and redistribute as freely as possible in any form whatsoever
|
||||
and for any purposes, including without limitation commercial purposes.
|
||||
These owners may contribute to the Commons to promote the ideal of a free
|
||||
culture and the further production of creative, cultural and scientific
|
||||
works, or to gain reputation or greater distribution for their Work in
|
||||
part through the use and efforts of others.
|
||||
|
||||
For these and/or other purposes and motivations, and without any
|
||||
expectation of additional consideration or compensation, the person
|
||||
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
|
||||
is an owner of Copyright and Related Rights in the Work, voluntarily
|
||||
elects to apply CC0 to the Work and publicly distribute the Work under its
|
||||
terms, with knowledge of his or her Copyright and Related Rights in the
|
||||
Work and the meaning and intended legal effect of CC0 on those rights.
|
||||
|
||||
1. Copyright and Related Rights. A Work made available under CC0 may be
|
||||
protected by copyright and related or neighboring rights ("Copyright and
|
||||
Related Rights"). Copyright and Related Rights include, but are not
|
||||
limited to, the following:
|
||||
|
||||
i. the right to reproduce, adapt, distribute, perform, display,
|
||||
communicate, and translate a Work;
|
||||
ii. moral rights retained by the original author(s) and/or performer(s);
|
||||
iii. publicity and privacy rights pertaining to a person's image or
|
||||
likeness depicted in a Work;
|
||||
iv. rights protecting against unfair competition in regards to a Work,
|
||||
subject to the limitations in paragraph 4(a), below;
|
||||
v. rights protecting the extraction, dissemination, use and reuse of data
|
||||
in a Work;
|
||||
vi. database rights (such as those arising under Directive 96/9/EC of the
|
||||
European Parliament and of the Council of 11 March 1996 on the legal
|
||||
protection of databases, and under any national implementation
|
||||
thereof, including any amended or successor version of such
|
||||
directive); and
|
||||
vii. other similar, equivalent or corresponding rights throughout the
|
||||
world based on applicable law or treaty, and any national
|
||||
implementations thereof.
|
||||
|
||||
2. Waiver. To the greatest extent permitted by, but not in contravention
|
||||
of, applicable law, Affirmer hereby overtly, fully, permanently,
|
||||
irrevocably and unconditionally waives, abandons, and surrenders all of
|
||||
Affirmer's Copyright and Related Rights and associated claims and causes
|
||||
of action, whether now known or unknown (including existing as well as
|
||||
future claims and causes of action), in the Work (i) in all territories
|
||||
worldwide, (ii) for the maximum duration provided by applicable law or
|
||||
treaty (including future time extensions), (iii) in any current or future
|
||||
medium and for any number of copies, and (iv) for any purpose whatsoever,
|
||||
including without limitation commercial, advertising or promotional
|
||||
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
|
||||
member of the public at large and to the detriment of Affirmer's heirs and
|
||||
successors, fully intending that such Waiver shall not be subject to
|
||||
revocation, rescission, cancellation, termination, or any other legal or
|
||||
equitable action to disrupt the quiet enjoyment of the Work by the public
|
||||
as contemplated by Affirmer's express Statement of Purpose.
|
||||
|
||||
3. Public License Fallback. Should any part of the Waiver for any reason
|
||||
be judged legally invalid or ineffective under applicable law, then the
|
||||
Waiver shall be preserved to the maximum extent permitted taking into
|
||||
account Affirmer's express Statement of Purpose. In addition, to the
|
||||
extent the Waiver is so judged Affirmer hereby grants to each affected
|
||||
person a royalty-free, non transferable, non sublicensable, non exclusive,
|
||||
irrevocable and unconditional license to exercise Affirmer's Copyright and
|
||||
Related Rights in the Work (i) in all territories worldwide, (ii) for the
|
||||
maximum duration provided by applicable law or treaty (including future
|
||||
time extensions), (iii) in any current or future medium and for any number
|
||||
of copies, and (iv) for any purpose whatsoever, including without
|
||||
limitation commercial, advertising or promotional purposes (the
|
||||
"License"). The License shall be deemed effective as of the date CC0 was
|
||||
applied by Affirmer to the Work. Should any part of the License for any
|
||||
reason be judged legally invalid or ineffective under applicable law, such
|
||||
partial invalidity or ineffectiveness shall not invalidate the remainder
|
||||
of the License, and in such case Affirmer hereby affirms that he or she
|
||||
will not (i) exercise any of his or her remaining Copyright and Related
|
||||
Rights in the Work or (ii) assert any associated claims and causes of
|
||||
action with respect to the Work, in either case contrary to Affirmer's
|
||||
express Statement of Purpose.
|
||||
|
||||
4. Limitations and Disclaimers.
|
||||
|
||||
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
||||
surrendered, licensed or otherwise affected by this document.
|
||||
b. Affirmer offers the Work as-is and makes no representations or
|
||||
warranties of any kind concerning the Work, express, implied,
|
||||
statutory or otherwise, including without limitation warranties of
|
||||
title, merchantability, fitness for a particular purpose, non
|
||||
infringement, or the absence of latent or other defects, accuracy, or
|
||||
the present or absence of errors, whether or not discoverable, all to
|
||||
the greatest extent permissible under applicable law.
|
||||
c. Affirmer disclaims responsibility for clearing rights of other persons
|
||||
that may apply to the Work or any use thereof, including without
|
||||
limitation any person's Copyright and Related Rights in the Work.
|
||||
Further, Affirmer disclaims responsibility for obtaining any necessary
|
||||
consents, permissions or other rights required for any use of the
|
||||
Work.
|
||||
d. Affirmer understands and acknowledges that Creative Commons is not a
|
||||
party to this document and has no duty or obligation with respect to
|
||||
this CC0 or use of the Work.
|
||||
|
||||
|
|
@ -22,10 +22,10 @@ char title[] = "Press Buttons!";
|
|||
byte x;
|
||||
byte y;
|
||||
|
||||
// Width of each charcter including inter-character space
|
||||
// Width of each character including inter-character space
|
||||
#define CHAR_WIDTH 6
|
||||
|
||||
// Height of each charater
|
||||
// Height of each character
|
||||
#define CHAR_HEIGHT 8
|
||||
|
||||
// To get the number of characters, we subtract 1 from the length of
|
||||
|
|
@ -49,7 +49,7 @@ void setup() {
|
|||
//initiate arduboy instance
|
||||
arduboy.begin();
|
||||
|
||||
// here we set the framerate to 30, we do not need to run at default 60 and
|
||||
// here we set the frame rate to 30, we do not need to run at default 60 and
|
||||
// it saves us battery life.
|
||||
arduboy.setFrameRate(30);
|
||||
|
||||
|
|
@ -101,6 +101,6 @@ void loop() {
|
|||
// then we print to screen what is stored in our title variable we declared earlier
|
||||
arduboy.print(title);
|
||||
|
||||
// then we finaly we tell the arduboy to display what we just wrote to the display.
|
||||
// then we finally we tell the arduboy to display what we just wrote to the display.
|
||||
arduboy.display();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
Buttons
|
||||
=======
|
||||
|
||||
A an example that demonstrates how to capture input from the buttons.
|
||||
An example that demonstrates how to capture input from the buttons.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,122 @@
|
|||
Creative Commons Legal Code
|
||||
|
||||
CC0 1.0 Universal
|
||||
|
||||
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
|
||||
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
|
||||
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
|
||||
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
|
||||
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
|
||||
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
|
||||
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
|
||||
HEREUNDER.
|
||||
|
||||
Statement of Purpose
|
||||
|
||||
The laws of most jurisdictions throughout the world automatically confer
|
||||
exclusive Copyright and Related Rights (defined below) upon the creator
|
||||
and subsequent owner(s) (each and all, an "owner") of an original work of
|
||||
authorship and/or a database (each, a "Work").
|
||||
|
||||
Certain owners wish to permanently relinquish those rights to a Work for
|
||||
the purpose of contributing to a commons of creative, cultural and
|
||||
scientific works ("Commons") that the public can reliably and without fear
|
||||
of later claims of infringement build upon, modify, incorporate in other
|
||||
works, reuse and redistribute as freely as possible in any form whatsoever
|
||||
and for any purposes, including without limitation commercial purposes.
|
||||
These owners may contribute to the Commons to promote the ideal of a free
|
||||
culture and the further production of creative, cultural and scientific
|
||||
works, or to gain reputation or greater distribution for their Work in
|
||||
part through the use and efforts of others.
|
||||
|
||||
For these and/or other purposes and motivations, and without any
|
||||
expectation of additional consideration or compensation, the person
|
||||
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
|
||||
is an owner of Copyright and Related Rights in the Work, voluntarily
|
||||
elects to apply CC0 to the Work and publicly distribute the Work under its
|
||||
terms, with knowledge of his or her Copyright and Related Rights in the
|
||||
Work and the meaning and intended legal effect of CC0 on those rights.
|
||||
|
||||
1. Copyright and Related Rights. A Work made available under CC0 may be
|
||||
protected by copyright and related or neighboring rights ("Copyright and
|
||||
Related Rights"). Copyright and Related Rights include, but are not
|
||||
limited to, the following:
|
||||
|
||||
i. the right to reproduce, adapt, distribute, perform, display,
|
||||
communicate, and translate a Work;
|
||||
ii. moral rights retained by the original author(s) and/or performer(s);
|
||||
iii. publicity and privacy rights pertaining to a person's image or
|
||||
likeness depicted in a Work;
|
||||
iv. rights protecting against unfair competition in regards to a Work,
|
||||
subject to the limitations in paragraph 4(a), below;
|
||||
v. rights protecting the extraction, dissemination, use and reuse of data
|
||||
in a Work;
|
||||
vi. database rights (such as those arising under Directive 96/9/EC of the
|
||||
European Parliament and of the Council of 11 March 1996 on the legal
|
||||
protection of databases, and under any national implementation
|
||||
thereof, including any amended or successor version of such
|
||||
directive); and
|
||||
vii. other similar, equivalent or corresponding rights throughout the
|
||||
world based on applicable law or treaty, and any national
|
||||
implementations thereof.
|
||||
|
||||
2. Waiver. To the greatest extent permitted by, but not in contravention
|
||||
of, applicable law, Affirmer hereby overtly, fully, permanently,
|
||||
irrevocably and unconditionally waives, abandons, and surrenders all of
|
||||
Affirmer's Copyright and Related Rights and associated claims and causes
|
||||
of action, whether now known or unknown (including existing as well as
|
||||
future claims and causes of action), in the Work (i) in all territories
|
||||
worldwide, (ii) for the maximum duration provided by applicable law or
|
||||
treaty (including future time extensions), (iii) in any current or future
|
||||
medium and for any number of copies, and (iv) for any purpose whatsoever,
|
||||
including without limitation commercial, advertising or promotional
|
||||
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
|
||||
member of the public at large and to the detriment of Affirmer's heirs and
|
||||
successors, fully intending that such Waiver shall not be subject to
|
||||
revocation, rescission, cancellation, termination, or any other legal or
|
||||
equitable action to disrupt the quiet enjoyment of the Work by the public
|
||||
as contemplated by Affirmer's express Statement of Purpose.
|
||||
|
||||
3. Public License Fallback. Should any part of the Waiver for any reason
|
||||
be judged legally invalid or ineffective under applicable law, then the
|
||||
Waiver shall be preserved to the maximum extent permitted taking into
|
||||
account Affirmer's express Statement of Purpose. In addition, to the
|
||||
extent the Waiver is so judged Affirmer hereby grants to each affected
|
||||
person a royalty-free, non transferable, non sublicensable, non exclusive,
|
||||
irrevocable and unconditional license to exercise Affirmer's Copyright and
|
||||
Related Rights in the Work (i) in all territories worldwide, (ii) for the
|
||||
maximum duration provided by applicable law or treaty (including future
|
||||
time extensions), (iii) in any current or future medium and for any number
|
||||
of copies, and (iv) for any purpose whatsoever, including without
|
||||
limitation commercial, advertising or promotional purposes (the
|
||||
"License"). The License shall be deemed effective as of the date CC0 was
|
||||
applied by Affirmer to the Work. Should any part of the License for any
|
||||
reason be judged legally invalid or ineffective under applicable law, such
|
||||
partial invalidity or ineffectiveness shall not invalidate the remainder
|
||||
of the License, and in such case Affirmer hereby affirms that he or she
|
||||
will not (i) exercise any of his or her remaining Copyright and Related
|
||||
Rights in the Work or (ii) assert any associated claims and causes of
|
||||
action with respect to the Work, in either case contrary to Affirmer's
|
||||
express Statement of Purpose.
|
||||
|
||||
4. Limitations and Disclaimers.
|
||||
|
||||
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
||||
surrendered, licensed or otherwise affected by this document.
|
||||
b. Affirmer offers the Work as-is and makes no representations or
|
||||
warranties of any kind concerning the Work, express, implied,
|
||||
statutory or otherwise, including without limitation warranties of
|
||||
title, merchantability, fitness for a particular purpose, non
|
||||
infringement, or the absence of latent or other defects, accuracy, or
|
||||
the present or absence of errors, whether or not discoverable, all to
|
||||
the greatest extent permissible under applicable law.
|
||||
c. Affirmer disclaims responsibility for clearing rights of other persons
|
||||
that may apply to the Work or any use thereof, including without
|
||||
limitation any person's Copyright and Related Rights in the Work.
|
||||
Further, Affirmer disclaims responsibility for obtaining any necessary
|
||||
consents, permissions or other rights required for any use of the
|
||||
Work.
|
||||
d. Affirmer understands and acknowledges that Creative Commons is not a
|
||||
party to this document and has no duty or obligation with respect to
|
||||
this CC0 or use of the Work.
|
||||
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
FontDemo.ino
|
||||
|
||||
This sketch draws all the characters of the library's font as a 16 x 16 block.
|
||||
The bottom half of the block will be initially off screen. An information
|
||||
overlay will be drawn on top of the block showing the X and Y cursor position
|
||||
of the start of the block, the current text wrap state and the current text
|
||||
raw mode state.
|
||||
|
||||
The block can be moved around and off the screen using the direction buttons,
|
||||
to view all the characters and show how the wrap and raw modes behave.
|
||||
|
||||
Controls:
|
||||
Direction Buttons: Move the block 1 pixel.
|
||||
Hold A with Direction Buttons: Continuously move the block.
|
||||
B Button: Toggle text raw mode on and off.
|
||||
Hold A, press B: Toggle text wrap mode on and off.
|
||||
*/
|
||||
|
||||
/*
|
||||
Written in September 2020 by Scott Allen saydisp-git@yahoo.ca
|
||||
|
||||
To the extent possible under law, the author(s) have dedicated all copyright
|
||||
and related and neighboring rights to this software to the public domain
|
||||
worldwide. This software is distributed without any warranty.
|
||||
|
||||
You should have received a copy of the CC0 Public Domain Dedication along with
|
||||
this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
*/
|
||||
|
||||
#include <Arduboy2.h>
|
||||
|
||||
Arduboy2 arduboy;
|
||||
|
||||
constexpr uint8_t charWidth = arduboy.getCharacterWidth() + arduboy.getCharacterSpacing();
|
||||
constexpr uint8_t charHeight = arduboy.getCharacterHeight() + arduboy.getLineSpacing();
|
||||
constexpr uint16_t infoX = charWidth * 8;
|
||||
constexpr uint16_t infoY = charHeight * 2;
|
||||
constexpr uint8_t infoWidth = charWidth * 5;
|
||||
constexpr uint8_t infoBorder = 1;
|
||||
|
||||
int16_t xPos = 0;
|
||||
int16_t yPos = 0;
|
||||
|
||||
void setup() {
|
||||
arduboy.begin();
|
||||
arduboy.setFrameRate(20);
|
||||
|
||||
arduboy.clear();
|
||||
arduboy.print(F("DISPLAY AND MOVE FONT\n\n"
|
||||
" Dpad: move 1\n"
|
||||
"A + Dpad: repeat move\n"
|
||||
" B: toggle raw\n"
|
||||
" A + B: toggle wrap\n\n"
|
||||
" Press A to start"));
|
||||
arduboy.display();
|
||||
|
||||
while (!arduboy.pressed(A_BUTTON)) {
|
||||
arduboy.idle();
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (!arduboy.nextFrame()) {
|
||||
return;
|
||||
}
|
||||
|
||||
arduboy.pollButtons();
|
||||
|
||||
if (arduboy.justPressed(B_BUTTON)) {
|
||||
if (arduboy.pressed(A_BUTTON)) {
|
||||
arduboy.setTextWrap(!arduboy.getTextWrap());
|
||||
}
|
||||
else {
|
||||
arduboy.setTextRawMode(!arduboy.getTextRawMode());
|
||||
}
|
||||
}
|
||||
|
||||
if (arduboy.justPressed(UP_BUTTON) ||
|
||||
arduboy.pressed(UP_BUTTON + A_BUTTON)) {
|
||||
--yPos;
|
||||
}
|
||||
if (arduboy.justPressed(DOWN_BUTTON) ||
|
||||
arduboy.pressed(DOWN_BUTTON + A_BUTTON)) {
|
||||
++yPos;
|
||||
}
|
||||
if (arduboy.justPressed(LEFT_BUTTON) ||
|
||||
arduboy.pressed(LEFT_BUTTON | A_BUTTON)) {
|
||||
--xPos;
|
||||
}
|
||||
if (arduboy.justPressed(RIGHT_BUTTON) ||
|
||||
arduboy.pressed(RIGHT_BUTTON | A_BUTTON)) {
|
||||
++xPos;
|
||||
}
|
||||
|
||||
arduboy.clear();
|
||||
|
||||
char code = 0;
|
||||
for (uint8_t i = 0; i < 16; ++i) {
|
||||
arduboy.setCursor(xPos, yPos + (charHeight * i));
|
||||
for (uint8_t j = 0; j < 16; ++j) {
|
||||
arduboy.print(code);
|
||||
++code;
|
||||
}
|
||||
}
|
||||
|
||||
arduboy.fillRect(infoX - infoBorder, infoY - infoBorder,
|
||||
infoWidth + infoBorder, charHeight * 4 + infoBorder);
|
||||
arduboy.setTextColor(BLACK);
|
||||
arduboy.setTextBackground(WHITE);
|
||||
arduboy.setCursor(infoX, infoY);
|
||||
arduboy.print(F("X:"));
|
||||
arduboy.print(xPos);
|
||||
arduboy.setCursor(infoX, infoY + charHeight);
|
||||
arduboy.print(F("Y:"));
|
||||
arduboy.print(yPos);
|
||||
arduboy.setCursor(infoX, infoY + (charHeight * 2));
|
||||
arduboy.print(F("W:"));
|
||||
arduboy.print(arduboy.getTextWrap() ? F("Yes") : F("No"));
|
||||
arduboy.setCursor(infoX, infoY + (charHeight * 3));
|
||||
arduboy.print(F("R:"));
|
||||
arduboy.print(arduboy.getTextRawMode() ? F("Yes") : F("No"));
|
||||
arduboy.setTextColor(WHITE);
|
||||
arduboy.setTextBackground(BLACK);
|
||||
|
||||
arduboy.display();
|
||||
}
|
||||
|
|
@ -23,7 +23,7 @@ void setup() {
|
|||
// initiate arduboy instance
|
||||
arduboy.begin();
|
||||
|
||||
// here we set the framerate to 15, we do not need to run at
|
||||
// here we set the frame rate to 15, we do not need to run at
|
||||
// default 60 and it saves us battery life
|
||||
arduboy.setFrameRate(15);
|
||||
}
|
||||
|
|
@ -46,6 +46,6 @@ void loop() {
|
|||
// then we print to screen what is in the Quotation marks ""
|
||||
arduboy.print(F("Hello, world!"));
|
||||
|
||||
// then we finaly we tell the arduboy to display what we just wrote to the display
|
||||
// then we finally we tell the arduboy to display what we just wrote to the display
|
||||
arduboy.display();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,169 +12,119 @@ The screen is inverted when sound is muted.
|
|||
|
||||
The B button will turn sound back on if it's muted.
|
||||
|
||||
Note: The score that is played contains three parts.
|
||||
The ArduboyPlaytune library can only play the first two
|
||||
parts and ignores the third, so it sounds a bit strange
|
||||
in some places. With the DevKit, only the first part plays.
|
||||
|
||||
The score that is played contains two parts.
|
||||
With the DevKit only one part is played.
|
||||
***************************************************************/
|
||||
|
||||
#include <Arduboy2.h>
|
||||
#include <ArduboyPlaytune.h>
|
||||
|
||||
const byte PROGMEM score [] = {
|
||||
// Sinfonia No.12 in A major BWV.798 J.S.Bach
|
||||
// Conductor Track
|
||||
7,208, 0x90,0x45, 0x91,0x39, 1,77, 0x80, 0x81, 0x90,0x44, 0,166, 0x80, 0x90,0x45, 0,166, 0x80, 0x90,0x47,
|
||||
0x91,0x38, 1,77, 0x80, 0x81, 0x90,0x45, 0,166, 0x80, 0x90,0x44, 0,166, 0x80, 0x90,0x45, 0x91,0x36, 1,77,
|
||||
0x81, 1,77, 0x91,0x31, 0,166, 0x80, 0x90,0x47, 0,166, 0x80, 0x81, 0x90,0x44, 0,166, 0x80, 0x90,0x45,
|
||||
0,166, 0x80, 0x90,0x47, 0x91,0x32, 0,166, 0x80, 0x90,0x40, 0,166, 0x80, 0x81, 0x90,0x49, 0,166, 0x80,
|
||||
0x90,0x40, 0,166, 0x80, 0x90,0x4A, 0x91,0x34, 0,166, 0x80, 0x90,0x40, 0,166, 0x80, 0x81, 0x90,0x4C, 1,77,
|
||||
0x80, 0x90,0x49, 0x91,0x2D, 0,166, 0x80, 0x90,0x47, 0,166, 0x80, 0x81, 0x90,0x45, 0x91,0x39, 0,166, 0x80,
|
||||
0x90,0x47, 0,166, 0x80, 0x81, 0x90,0x49, 0x91,0x38, 0,166, 0x80, 0x90,0x4B, 0,166, 0x80, 0x81, 0x90,0x4C,
|
||||
0x91,0x36, 0,166, 0x80, 0x90,0x4E, 0,166, 0x80, 0x81, 0x90,0x50, 0x91,0x34, 0x92,0x40, 0,166, 0x80, 0x90,0x51,
|
||||
0,166, 0x80, 0x81, 0x82, 0x90,0x53, 0x91,0x3F, 0,166, 0x81, 0x91,0x40, 0,166, 0x81, 0x91,0x3F, 0x92,0x42,
|
||||
0,166, 0x80, 0x90,0x51, 0,166, 0x80, 0x81, 0x82, 0x90,0x50, 0x91,0x40, 0,166, 0x80, 0x81, 0x90,0x4E, 0x91,0x3F,
|
||||
0,166, 0x80, 0x81, 0x90,0x4C, 0x91,0x3D, 0x92,0x40, 0,166, 0x80, 0x90,0x4B, 0,166, 0x80, 0x81, 0x90,0x49,
|
||||
0,166, 0x80, 0x90,0x47, 0,166, 0x80, 0x90,0x4C, 0x91,0x38, 0,166, 0x82, 0x92,0x42, 0,166, 0x81, 0x82,
|
||||
0x91,0x3F, 0,166, 0x81, 0x91,0x40, 0,166, 0x81, 0x91,0x42, 0x92,0x39, 0,166, 0x81, 0x91,0x3B, 0,166,
|
||||
0x81, 0x82, 0x91,0x44, 0,166, 0x81, 0x91,0x3B, 0,166, 0x80, 0x81, 0x90,0x45, 0x91,0x4B, 0x92,0x3B, 0,166,
|
||||
0x80, 0x82, 0x90,0x3B, 0,166, 0x80, 0x90,0x47, 1,77, 0x80, 0x81, 0x90,0x4C, 0x91,0x44, 0x92,0x40, 0,166,
|
||||
0x81, 0x91,0x45, 0,166, 0x80, 0x81, 0x82, 0x90,0x4A, 0x91,0x47, 0,166, 0x80, 0x81, 0x90,0x49, 0x91,0x45, 0,166,
|
||||
0x80, 0x81, 0x90,0x4A, 0x91,0x44, 0,166, 0x80, 0x81, 0x90,0x4C, 0x91,0x42, 0,166, 0x80, 0x81, 0x90,0x4E, 0x91,0x40,
|
||||
0,166, 0x80, 0x81, 0x90,0x50, 0x91,0x3E, 0,166, 0x80, 0x81, 0x90,0x51, 0x91,0x3D, 0x92,0x39, 0,166, 0x81,
|
||||
0x91,0x49, 0,166, 0x81, 0x82, 0x91,0x4E, 0x92,0x38, 0,166, 0x80, 0x82, 0x90,0x51, 0x92,0x39, 0,166, 0x80,
|
||||
0x82, 0x90,0x50, 0x92,0x3B, 0,166, 0x81, 0x91,0x4B, 0,166, 0x81, 0x82, 0x91,0x4C, 0x92,0x39, 0,166, 0x80,
|
||||
0x82, 0x90,0x50, 0x92,0x38, 0,166, 0x80, 0x82, 0x90,0x4E, 0x92,0x39, 0,166, 0x81, 0x91,0x49, 0,166, 0x81,
|
||||
0x91,0x4A, 0,166, 0x80, 0x90,0x4E, 0,166, 0x80, 0x90,0x4C, 0,166, 0x81, 0x82, 0x91,0x47, 0x92,0x3B, 0,166,
|
||||
0x81, 0x82, 0x91,0x49, 0x92,0x38, 0,166, 0x80, 0x82, 0x90,0x4C, 0x92,0x39, 0,166, 0x80, 0x81, 0x82, 0x90,0x3B,
|
||||
0x91,0x4A, 0x92,0x44, 0,166, 0x80, 0x90,0x34, 0,166, 0x80, 0x81, 0x82, 0x90,0x3D, 0x91,0x49, 0x92,0x45, 0,166,
|
||||
0x80, 0x90,0x34, 0,166, 0x80, 0x81, 0x90,0x3E, 0x91,0x47, 0,166, 0x80, 0x90,0x34, 0,166, 0x80, 0x82, 0x90,0x44,
|
||||
0x92,0x40, 1,77, 0x80, 0x81, 0x82, 0x90,0x3D, 0x91,0x45, 0,166, 0x80, 0x90,0x3B, 0,166, 0x80, 0x90,0x39,
|
||||
0x92,0x49, 0,166, 0x80, 0x90,0x3B, 0,166, 0x80, 0x82, 0x90,0x3D, 0x92,0x4E, 0,166, 0x80, 0x90,0x3F, 0,166,
|
||||
0x80, 0x81, 0x90,0x45, 0x91,0x40, 0,166, 0x81, 0x91,0x42, 0,166, 0x80, 0x81, 0x90,0x44, 0x91,0x3B, 0,166,
|
||||
0x81, 0x91,0x39, 0,166, 0x81, 0x82, 0x91,0x47, 0x92,0x38, 0,166, 0x82, 0x92,0x39, 0,166, 0x81, 0x82, 0x91,0x4C,
|
||||
0x92,0x3B, 0,166, 0x82, 0x92,0x3D, 0,166, 0x80, 0x82, 0x90,0x44, 0x92,0x3F, 0,166, 0x82, 0x92,0x40, 0,166,
|
||||
0x80, 0x82, 0x90,0x42, 0x92,0x39, 0,166, 0x82, 0x92,0x38, 0,166, 0x81, 0x82, 0x91,0x4B, 0x92,0x36, 0,166,
|
||||
0x81, 0x82, 0x91,0x4C, 0x92,0x38, 0,166, 0x81, 0x82, 0x91,0x4E, 0x92,0x39, 0,166, 0x82, 0x92,0x38, 0,166,
|
||||
0x81, 0x82, 0x91,0x4C, 0x92,0x39, 0,166, 0x81, 0x82, 0x91,0x4B, 0x92,0x3B, 0,166, 0x80, 0x81, 0x82, 0x90,0x4C,
|
||||
0x91,0x38, 0,166, 0x92,0x4B, 0,166, 0x81, 0x82, 0x91,0x49, 0x92,0x39, 0,166, 0x81, 0x82, 0x91,0x47, 0x92,0x3B,
|
||||
0,166, 0x81, 0x82, 0x91,0x45, 0x92,0x3D, 0,166, 0x80, 0x81, 0x90,0x4E, 0x91,0x44, 0,166, 0x80, 0x81, 0x90,0x4B,
|
||||
0x91,0x42, 0,166, 0x80, 0x81, 0x90,0x4C, 0x91,0x40, 0,166, 0x80, 0x81, 0x90,0x4E, 0x91,0x3F, 0,166, 0x80,
|
||||
0x82, 0x90,0x47, 0x92,0x3B, 0,166, 0x80, 0x81, 0x82, 0x90,0x50, 0x91,0x39, 0x92,0x40, 0,166, 0x80, 0x81, 0x90,0x47,
|
||||
0x91,0x38, 0,166, 0x80, 0x81, 0x90,0x51, 0x91,0x36, 0,166, 0x80, 0x90,0x47, 0,166, 0x80, 0x81, 0x82, 0x90,0x53,
|
||||
0x91,0x3F, 0x92,0x3B, 1,77, 0x80, 0x81, 0x82, 0x90,0x50, 0x91,0x34, 0x92,0x40, 0,166, 0x80, 0x90,0x51, 0,166,
|
||||
0x80, 0x90,0x53, 0,166, 0x80, 0x90,0x51, 0,166, 0x80, 0x81, 0x82, 0x90,0x50, 0,166, 0x80, 0x90,0x4E, 0x91,0x39,
|
||||
0,166, 0x80, 0x81, 0x90,0x4C, 0x91,0x38, 0,166, 0x80, 0x81, 0x90,0x4A, 0x91,0x36, 0,166, 0x80, 0x81, 0x90,0x49,
|
||||
0x91,0x35, 0,166, 0x81, 0x91,0x31, 0,166, 0x81, 0x91,0x44, 0x92,0x36, 0,166, 0x81, 0x82, 0x91,0x45, 0x92,0x31,
|
||||
0,166, 0x81, 0x82, 0x91,0x47, 0x92,0x38, 0,166, 0x82, 0x92,0x31, 0,166, 0x81, 0x82, 0x91,0x45, 0x92,0x35,
|
||||
0,166, 0x81, 0x82, 0x91,0x44, 0x92,0x31, 0,166, 0x81, 0x82, 0x91,0x45, 0x92,0x36, 0,166, 0x82, 0x92,0x31,
|
||||
0,166, 0x80, 0x82, 0x90,0x38, 0x92,0x49, 0,166, 0x80, 0x82, 0x90,0x31, 0x92,0x4A, 0,166, 0x80, 0x82, 0x90,0x36,
|
||||
0x92,0x4C, 0,166, 0x80, 0x90,0x31, 0,166, 0x80, 0x82, 0x90,0x34, 0x92,0x4A, 0,166, 0x80, 0x82, 0x90,0x31,
|
||||
0x92,0x49, 0,166, 0x80, 0x82, 0x90,0x33, 0x92,0x47, 0,166, 0x80, 0x90,0x2F, 0,166, 0x80, 0x81, 0x90,0x34,
|
||||
0x91,0x42, 0,166, 0x80, 0x81, 0x90,0x2F, 0x91,0x44, 0,166, 0x80, 0x81, 0x90,0x36, 0x91,0x45, 0,166, 0x80,
|
||||
0x90,0x2F, 0,166, 0x80, 0x81, 0x90,0x33, 0x91,0x44, 0,166, 0x80, 0x81, 0x90,0x2F, 0x91,0x42, 0,166, 0x80,
|
||||
0x81, 0x90,0x44, 0x91,0x34, 0,166, 0x81, 0x91,0x2F, 0,166, 0x81, 0x82, 0x91,0x47, 0x92,0x36, 0,166, 0x81,
|
||||
0x82, 0x91,0x49, 0x92,0x2F, 0,166, 0x81, 0x82, 0x91,0x4A, 0x92,0x34, 0,166, 0x82, 0x92,0x2F, 0,166, 0x81,
|
||||
0x82, 0x91,0x49, 0x92,0x32, 0,166, 0x81, 0x82, 0x91,0x47, 0x92,0x2F, 0,166, 0x81, 0x82, 0x91,0x45, 0x92,0x31,
|
||||
0,166, 0x82, 0x92,0x2D, 0,166, 0x80, 0x82, 0x90,0x32, 0x92,0x41, 0,166, 0x80, 0x82, 0x90,0x42, 0x92,0x2D,
|
||||
0,166, 0x80, 0x82, 0x90,0x44, 0x92,0x34, 0,166, 0x82, 0x92,0x2D, 0,166, 0x80, 0x82, 0x90,0x42, 0x92,0x31,
|
||||
0,166, 0x80, 0x82, 0x90,0x2D, 0x92,0x41, 0,166, 0x80, 0x82, 0x90,0x42, 0x92,0x32, 0,166, 0x82, 0x92,0x2D,
|
||||
0,166, 0x81, 0x82, 0x91,0x34, 0x92,0x45, 0,166, 0x81, 0x82, 0x91,0x2D, 0x92,0x47, 0,166, 0x81, 0x82, 0x91,0x32,
|
||||
0x92,0x49, 0,166, 0x81, 0x91,0x2D, 0,166, 0x81, 0x82, 0x91,0x31, 0x92,0x47, 0,166, 0x81, 0x82, 0x91,0x2D,
|
||||
0x92,0x45, 0,166, 0x81, 0x82, 0x91,0x30, 0x92,0x44, 0,166, 0x81, 0x91,0x2C, 0,166, 0x80, 0x81, 0x90,0x31,
|
||||
0x91,0x3F, 0,166, 0x80, 0x81, 0x90,0x2C, 0x91,0x41, 0,166, 0x80, 0x81, 0x90,0x33, 0x91,0x42, 0,166, 0x80,
|
||||
0x90,0x2C, 0,166, 0x80, 0x81, 0x90,0x30, 0x91,0x41, 0,166, 0x80, 0x81, 0x90,0x2C, 0x91,0x3F, 0,166, 0x80,
|
||||
0x81, 0x90,0x31, 0x91,0x41, 1,77, 0x81, 0x82, 0x91,0x44, 0x92,0x41, 0,166, 0x81, 0x82, 0x91,0x45, 0x92,0x42,
|
||||
0,166, 0x81, 0x82, 0x91,0x47, 0x92,0x44, 1,77, 0x81, 0x82, 0x91,0x45, 0x92,0x42, 0,166, 0x81, 0x82, 0x91,0x44,
|
||||
0x92,0x41, 0,166, 0x81, 0x82, 0x91,0x45, 0x92,0x42, 1,77, 0x81, 0x91,0x46, 0,166, 0x81, 0x91,0x48, 0,166,
|
||||
0x81, 0x82, 0x91,0x49, 0x92,0x40, 1,77, 0x81, 0x91,0x48, 0,166, 0x81, 0x91,0x46, 0,166, 0x81, 0x82, 0x91,0x3F,
|
||||
0x92,0x48, 1,77, 0x82, 0x92,0x48, 0,166, 0x82, 0x92,0x49, 0,166, 0x81, 0x82, 0x91,0x4B, 0x92,0x42, 1,77,
|
||||
0x81, 0x91,0x49, 0,166, 0x81, 0x91,0x48, 0,166, 0x80, 0x81, 0x90,0x49, 0,166, 0x91,0x3E, 0,166, 0x80,
|
||||
0x81, 0x90,0x44, 0x91,0x3D, 0,166, 0x80, 0x81, 0x90,0x45, 0x91,0x3B, 0,166, 0x80, 0x81, 0x82, 0x90,0x47, 0x91,0x3D,
|
||||
0x92,0x41, 0,166, 0x81, 0x91,0x39, 0,166, 0x80, 0x81, 0x90,0x45, 0x91,0x3B, 0,166, 0x80, 0x81, 0x90,0x44,
|
||||
0x91,0x3D, 0,166, 0x80, 0x81, 0x82, 0x90,0x45, 0x91,0x42, 0x92,0x36, 0,166, 0x80, 0x81, 0x90,0x42, 0,166,
|
||||
0x80, 0x82, 0x90,0x44, 0x91,0x35, 0,166, 0x80, 0x81, 0x90,0x45, 0x91,0x36, 0,166, 0x80, 0x81, 0x90,0x47, 0x91,0x38,
|
||||
0,166, 0x80, 0x90,0x49, 0,166, 0x80, 0x81, 0x90,0x4A, 0x91,0x36, 0,166, 0x80, 0x81, 0x90,0x4C, 0x91,0x35,
|
||||
0,166, 0x80, 0x81, 0x90,0x4A, 0x91,0x36, 0,166, 0x92,0x49, 0,166, 0x82, 0x92,0x47, 0,166, 0x80, 0x90,0x4A,
|
||||
0,166, 0x80, 0x90,0x49, 0,166, 0x81, 0x82, 0x91,0x47, 0x92,0x38, 0,166, 0x81, 0x82, 0x91,0x45, 0x92,0x35,
|
||||
0,166, 0x80, 0x82, 0x90,0x49, 0x92,0x36, 0,166, 0x80, 0x81, 0x82, 0x90,0x38, 0x91,0x47, 0x92,0x41, 0,166,
|
||||
0x80, 0x90,0x31, 0,166, 0x80, 0x81, 0x82, 0x90,0x39, 0x91,0x42, 0x92,0x45, 0,166, 0x80, 0x90,0x31, 0,166,
|
||||
0x80, 0x82, 0x90,0x3B, 0x92,0x44, 0,166, 0x80, 0x90,0x31, 0,166, 0x80, 0x81, 0x90,0x3D, 0x91,0x41, 0,166,
|
||||
0x80, 0x90,0x3B, 0,166, 0x80, 0x81, 0x82, 0x90,0x39, 0x91,0x42, 0,166, 0x80, 0x90,0x3B, 0,166, 0x80, 0x90,0x3D,
|
||||
0x92,0x49, 0,166, 0x80, 0x90,0x3B, 0,166, 0x80, 0x82, 0x90,0x39, 0x92,0x4E, 0,166, 0x80, 0x90,0x38, 0,166,
|
||||
0x80, 0x81, 0x90,0x36, 0x91,0x45, 0,166, 0x80, 0x90,0x34, 0,166, 0x80, 0x81, 0x90,0x4A, 0x91,0x3B, 0,166,
|
||||
0x81, 0x91,0x3D, 0,166, 0x81, 0x82, 0x91,0x44, 0x92,0x3E, 0,166, 0x82, 0x92,0x3D, 0,166, 0x81, 0x82, 0x91,0x50,
|
||||
0x92,0x3B, 0,166, 0x82, 0x92,0x39, 0,166, 0x80, 0x82, 0x90,0x44, 0x92,0x38, 0,166, 0x82, 0x92,0x36, 0,166,
|
||||
0x80, 0x82, 0x90,0x4C, 0x92,0x3D, 0,166, 0x82, 0x92,0x3E, 0,166, 0x81, 0x82, 0x91,0x49, 0x92,0x40, 0,166,
|
||||
0x82, 0x92,0x3E, 0,166, 0x81, 0x82, 0x91,0x51, 0x92,0x3D, 0,166, 0x82, 0x92,0x3B, 0,166, 0x80, 0x82, 0x90,0x49,
|
||||
0x92,0x39, 0,166, 0x82, 0x92,0x38, 0,166, 0x80, 0x82, 0x90,0x3F, 0x92,0x4E, 0,166, 0x80, 0x90,0x40, 0,166,
|
||||
0x80, 0x81, 0x90,0x42, 0x91,0x4B, 0,166, 0x80, 0x90,0x40, 0,166, 0x80, 0x81, 0x90,0x3F, 0x91,0x53, 0,166,
|
||||
0x80, 0x90,0x3D, 0,166, 0x80, 0x81, 0x90,0x3B, 0x91,0x51, 0,166, 0x80, 0x90,0x39, 0,166, 0x80, 0x81, 0x90,0x50,
|
||||
0x91,0x40, 1,77, 0x80, 0x82, 0x90,0x50, 0x92,0x47, 0,166, 0x80, 0x82, 0x90,0x51, 0x92,0x49, 0,166, 0x80,
|
||||
0x82, 0x90,0x53, 0x92,0x4A, 1,77, 0x80, 0x82, 0x90,0x51, 0x92,0x49, 0,166, 0x80, 0x82, 0x90,0x50, 0x92,0x47,
|
||||
0,166, 0x80, 0x82, 0x90,0x51, 0x92,0x49, 1,77, 0x82, 0x92,0x49, 0,166, 0x82, 0x92,0x4B, 0,166, 0x80,
|
||||
0x82, 0x90,0x50, 0x92,0x4C, 1,77, 0x82, 0x92,0x4B, 0,166, 0x82, 0x92,0x49, 0,166, 0x80, 0x82, 0x90,0x4E,
|
||||
0x92,0x4B, 1,77, 0x82, 0x92,0x4B, 0,166, 0x82, 0x92,0x4C, 0,166, 0x80, 0x82, 0x90,0x51, 0x92,0x4E, 1,77,
|
||||
0x82, 0x92,0x4C, 0,166, 0x82, 0x92,0x4B, 0,166, 0x82, 0x92,0x4C, 0,166, 0x81, 0x91,0x3D, 0,166, 0x80,
|
||||
0x81, 0x90,0x50, 0x91,0x3B, 0,166, 0x80, 0x81, 0x90,0x51, 0x91,0x39, 0,166, 0x80, 0x81, 0x90,0x53, 0x91,0x38,
|
||||
0,166, 0x80, 0x81, 0x90,0x51, 0x91,0x36, 0,166, 0x80, 0x81, 0x90,0x50, 0x91,0x34, 0,166, 0x80, 0x81, 0x90,0x4E,
|
||||
0x91,0x32, 0,166, 0x80, 0x81, 0x82, 0x90,0x4C, 0x91,0x31, 0,166, 0x80, 0x81, 0x90,0x4A, 0x91,0x39, 0,166,
|
||||
0x80, 0x81, 0x90,0x49, 0x91,0x32, 0,166, 0x80, 0x81, 0x90,0x47, 0x91,0x39, 0,166, 0x80, 0x81, 0x90,0x45, 0x91,0x34,
|
||||
0,166, 0x80, 0x81, 0x90,0x49, 0x91,0x39, 0,166, 0x80, 0x81, 0x90,0x4C, 0x91,0x31, 0,166, 0x80, 0x81, 0x90,0x4F,
|
||||
0x91,0x39, 0,166, 0x80, 0x81, 0x90,0x32, 0x91,0x4E, 0,166, 0x80, 0x90,0x39, 0,166, 0x80, 0x90,0x34, 0x92,0x45,
|
||||
0,166, 0x80, 0x82, 0x90,0x39, 0x92,0x47, 0,166, 0x80, 0x82, 0x90,0x32, 0x92,0x49, 0,166, 0x80, 0x90,0x39,
|
||||
0,166, 0x80, 0x82, 0x90,0x31, 0x92,0x47, 0,166, 0x80, 0x82, 0x90,0x39, 0x92,0x45, 0,166, 0x80, 0x82, 0x90,0x2F,
|
||||
0x92,0x44, 0,166, 0x80, 0x90,0x38, 0,166, 0x80, 0x81, 0x90,0x31, 0x91,0x4A, 0,166, 0x80, 0x81, 0x90,0x38,
|
||||
0x91,0x4C, 0,166, 0x80, 0x81, 0x90,0x32, 0x91,0x4E, 0,166, 0x80, 0x90,0x38, 0,166, 0x80, 0x81, 0x90,0x2F,
|
||||
0x91,0x4C, 0,166, 0x80, 0x81, 0x90,0x38, 0x91,0x4A, 0,166, 0x80, 0x81, 0x90,0x4C, 0x91,0x31, 0,166, 0x81,
|
||||
0x91,0x38, 0,166, 0x81, 0x82, 0x91,0x44, 0x92,0x32, 0,166, 0x81, 0x82, 0x91,0x45, 0x92,0x38, 0,166, 0x81,
|
||||
0x82, 0x91,0x47, 0x92,0x31, 0,166, 0x82, 0x92,0x38, 0,166, 0x81, 0x82, 0x91,0x45, 0x92,0x2F, 0,166, 0x81,
|
||||
0x82, 0x91,0x44, 0x92,0x38, 0,166, 0x81, 0x82, 0x91,0x42, 0x92,0x2E, 0,166, 0x82, 0x92,0x36, 0,166, 0x80,
|
||||
0x82, 0x90,0x49, 0x92,0x2F, 0,166, 0x80, 0x82, 0x90,0x4A, 0x92,0x36, 0,166, 0x80, 0x82, 0x90,0x4C, 0x92,0x31,
|
||||
0,166, 0x82, 0x92,0x36, 0,166, 0x80, 0x82, 0x90,0x4A, 0x92,0x2E, 0,166, 0x80, 0x82, 0x90,0x49, 0x92,0x36,
|
||||
0,166, 0x80, 0x82, 0x90,0x4A, 0x92,0x2F, 0,166, 0x82, 0x92,0x36, 0,166, 0x81, 0x82, 0x91,0x42, 0x92,0x31,
|
||||
0,166, 0x81, 0x82, 0x91,0x44, 0x92,0x36, 0,166, 0x81, 0x82, 0x91,0x45, 0x92,0x2F, 0,166, 0x82, 0x92,0x36,
|
||||
0,166, 0x81, 0x82, 0x91,0x44, 0x92,0x2D, 0,166, 0x81, 0x82, 0x91,0x42, 0x92,0x36, 0,166, 0x81, 0x82, 0x91,0x2C,
|
||||
0x92,0x40, 0,166, 0x81, 0x91,0x34, 0,166, 0x80, 0x81, 0x90,0x47, 0x91,0x28, 0,166, 0x80, 0x81, 0x90,0x49,
|
||||
0x91,0x34, 0,166, 0x80, 0x81, 0x90,0x4A, 0x91,0x2A, 0,166, 0x81, 0x91,0x34, 0,166, 0x80, 0x81, 0x90,0x49,
|
||||
0x91,0x2C, 0,166, 0x80, 0x81, 0x90,0x47, 0x91,0x34, 0,166, 0x80, 0x81, 0x90,0x49, 0x91,0x2D, 0,166, 0x80,
|
||||
0x90,0x45, 0,166, 0x80, 0x81, 0x82, 0x90,0x4E, 0x91,0x2C, 0,166, 0x81, 0x91,0x45, 0x92,0x2D, 0,166, 0x81,
|
||||
0x82, 0x91,0x44, 0x92,0x2F, 0,166, 0x80, 0x90,0x4B, 0,166, 0x80, 0x82, 0x90,0x4C, 0x92,0x2D, 0,166, 0x81,
|
||||
0x82, 0x91,0x44, 0x92,0x2C, 0,166, 0x81, 0x82, 0x91,0x42, 0x92,0x2D, 0,166, 0x80, 0x90,0x49, 0,166, 0x80,
|
||||
0x90,0x4A, 0,166, 0x81, 0x91,0x42, 0,166, 0x81, 0x91,0x40, 0,166, 0x80, 0x82, 0x90,0x47, 0x92,0x2F, 0,166,
|
||||
0x80, 0x82, 0x90,0x49, 0x92,0x2C, 0,166, 0x81, 0x82, 0x91,0x2D, 0x92,0x40, 0,166, 0x80, 0x81, 0x82, 0x90,0x2F,
|
||||
0x91,0x44, 0x92,0x3E, 0,166, 0x80, 0x90,0x28, 0,166, 0x80, 0x81, 0x82, 0x90,0x31, 0x91,0x3D, 0x92,0x45, 0,166,
|
||||
0x80, 0x90,0x28, 0,166, 0x80, 0x81, 0x90,0x32, 0x91,0x3B, 0,166, 0x80, 0x90,0x28, 0,166, 0x80, 0x82, 0x90,0x34,
|
||||
0x92,0x44, 1,77, 0x80, 0x81, 0x82, 0x90,0x31, 0x91,0x45, 0x92,0x40, 0,166, 0x82, 0x92,0x3D, 0,166, 0x80,
|
||||
0x81, 0x82, 0x90,0x36, 0x91,0x44, 0x92,0x3E, 0,166, 0x81, 0x91,0x45, 0,166, 0x81, 0x91,0x47, 0,166, 0x82,
|
||||
0x92,0x3B, 0,166, 0x80, 0x81, 0x82, 0x90,0x35, 0x91,0x45, 0x92,0x3D, 0,166, 0x81, 0x91,0x44, 0,166, 0x80,
|
||||
0x81, 0x90,0x45, 0x91,0x36, 0,166, 0x82, 0x92,0x39, 0,166, 0x82, 0x92,0x3B, 0,166, 0x82, 0x92,0x38, 0,166,
|
||||
0x82, 0x92,0x39, 0,166, 0x80, 0x90,0x47, 0,166, 0x80, 0x81, 0x90,0x44, 0x91,0x34, 0,166, 0x80, 0x90,0x45,
|
||||
0,166, 0x80, 0x81, 0x90,0x47, 0x91,0x32, 0,166, 0x80, 0x82, 0x90,0x38, 0x92,0x40, 0,166, 0x80, 0x81, 0x82,
|
||||
0x90,0x49, 0x91,0x31, 0x92,0x39, 0,166, 0x80, 0x90,0x40, 0,166, 0x80, 0x81, 0x90,0x4A, 0x91,0x2F, 0,166,
|
||||
0x80, 0x90,0x40, 0,166, 0x80, 0x81, 0x82, 0x90,0x4C, 0x91,0x34, 0x92,0x38, 1,77, 0x80, 0x81, 0x82, 0x90,0x49,
|
||||
0x91,0x39, 0x92,0x2D, 0,166, 0x80, 0x90,0x47, 0,166, 0x80, 0x81, 0x90,0x45, 0x91,0x3D, 0,166, 0x80, 0x90,0x47,
|
||||
0,166, 0x80, 0x81, 0x82, 0x90,0x49, 0x91,0x42, 0,166, 0x80, 0x90,0x4B, 0,166, 0x80, 0x90,0x4C, 0x92,0x39,
|
||||
0,166, 0x80, 0x90,0x4E, 0,166, 0x80, 0x82, 0x90,0x47, 0x92,0x38, 0,166, 0x80, 0x90,0x45, 0,166, 0x80,
|
||||
0x81, 0x90,0x44, 0x91,0x3B, 0,166, 0x80, 0x90,0x45, 0,166, 0x80, 0x81, 0x90,0x47, 0x91,0x40, 0,166, 0x80,
|
||||
0x90,0x49, 0,166, 0x80, 0x82, 0x90,0x4A, 0x92,0x38, 0,166, 0x80, 0x90,0x4C, 0,166, 0x80, 0x82, 0x90,0x45,
|
||||
0x92,0x36, 0,166, 0x80, 0x90,0x44, 0,166, 0x80, 0x81, 0x90,0x42, 0x91,0x39, 0,166, 0x80, 0x90,0x44, 0,166,
|
||||
0x80, 0x81, 0x90,0x45, 0x91,0x3E, 0,166, 0x80, 0x90,0x47, 0,166, 0x80, 0x82, 0x90,0x49, 0x92,0x36, 0,166,
|
||||
0x80, 0x90,0x4A, 0,166, 0x80, 0x82, 0x90,0x44, 0x92,0x34, 0,166, 0x80, 0x90,0x47, 0,166, 0x80, 0x81, 0x90,0x44,
|
||||
0x91,0x3B, 0,166, 0x80, 0x81, 0x90,0x3D, 0x91,0x40, 0,166, 0x80, 0x81, 0x90,0x4C, 0x91,0x3E, 1,77, 0x81,
|
||||
0x91,0x3D, 0,166, 0x81, 0x91,0x3B, 0,166, 0x81, 0x91,0x3D, 0,166, 0x80, 0x90,0x4C, 0,166, 0x80, 0x81,
|
||||
0x90,0x49, 0x91,0x39, 0,166, 0x80, 0x81, 0x90,0x45, 0x91,0x3B, 0,166, 0x80, 0x81, 0x90,0x51, 0x91,0x3D, 1,77,
|
||||
0x81, 0x91,0x3B, 0,166, 0x81, 0x91,0x39, 0,166, 0x81, 0x91,0x3B, 0,166, 0x80, 0x90,0x47, 0,166, 0x80,
|
||||
0x81, 0x90,0x4A, 0x91,0x38, 0,166, 0x80, 0x81, 0x90,0x4E, 0x91,0x39, 0,166, 0x80, 0x81, 0x90,0x50, 0x91,0x3B,
|
||||
1,77, 0x81, 0x91,0x39, 0,166, 0x81, 0x91,0x38, 0,166, 0x81, 0x91,0x39, 0,166, 0x80, 0x90,0x45, 0,166,
|
||||
0x80, 0x81, 0x90,0x49, 0x91,0x36, 0,166, 0x80, 0x81, 0x90,0x4C, 0x91,0x38, 0,166, 0x80, 0x81, 0x90,0x4E, 0x91,0x39,
|
||||
1,77, 0x81, 0x91,0x38, 0,166, 0x81, 0x91,0x36, 0,166, 0x81, 0x91,0x38, 0,166, 0x80, 0x82, 0x90,0x4C,
|
||||
0x92,0x34, 0,166, 0x80, 0x81, 0x82, 0x90,0x4B, 0x91,0x38, 0,166, 0x80, 0x81, 0x90,0x4C, 0x91,0x3B, 0,166,
|
||||
0x80, 0x81, 0x90,0x4E, 0x91,0x45, 0x92,0x3C, 0,166, 0x82, 0x92,0x38, 0,166, 0x80, 0x81, 0x82, 0x90,0x39, 0,166,
|
||||
0x80, 0x90,0x33, 0,166, 0x80, 0x90,0x49, 0x91,0x45, 0x92,0x34, 0,13, 1,29, 0,246, 0x80, 0x81, 0x90,0x4A,
|
||||
0x91,0x47, 0,53, 0,141, 0x80, 0x81, 0x82, 0x90,0x47, 0x91,0x44, 0x92,0x28, 0,95, 1,77, 0,202,
|
||||
0x80, 0x81, 0x90,0x45, 0,91, 0,136, 0x80, 0x82, 0x90,0x45, 0x91,0x2D, 7,83, 0x80, 0x81, 0xf0};
|
||||
// 2 Part Inventions No. 3 - J.S. Bach
|
||||
const byte score[] PROGMEM = {
|
||||
2,154, 0x90,62, 0,166, 0x90,64, 0,166, 0x90,66, 0,166, 0x90,64, 0,166,
|
||||
0x90,67, 0,166, 0x90,66, 0,166, 0x90,64, 0,166, 0x90,62, 0,166, 0x90,69,
|
||||
0,166, 0x90,67, 0,166, 0x90,66, 0,166, 0x90,64, 0,166, 0x91,50, 0x90,66,
|
||||
0,166, 0x91,52, 0x90,62, 0,166, 0x91,54, 0x90,69, 0,166, 0x91,52, 0,166,
|
||||
0x90,71, 0x91,55, 0,166, 0x91,54, 0,166, 0x90,73, 0x91,52, 0,55, 0x90,71,
|
||||
0,55, 0x90,73, 0,55, 0x91,50, 0x90,74, 0,166, 0x91,57, 0x90,73, 0,83,
|
||||
0x90,74, 0,83, 0x91,55, 0x90,73, 0,166, 0x91,54, 0x90,71, 0,83, 0x90,69,
|
||||
0,83, 0x91,52, 0,125, 0x80, 0,41, 0x90,73, 0x91,54, 0,166, 0x90,74, 0x91,50,
|
||||
0,166, 0x90,76, 0x91,57, 0,166, 0x90,73, 0,166, 0x91,45, 0x90,78, 0,166,
|
||||
0x90,74, 0,166, 0x91,57, 0x90,73, 0,166, 0x90,71, 0,138, 0x81, 0,27, 0x91,57,
|
||||
0x90,76, 0,166, 0x90,73, 0,166, 0x91,45, 0x90,74, 0,166, 0x90,71, 0,166,
|
||||
0x91,57, 0x90,69, 0,166, 0x90,68, 0,138, 0x81, 0,27, 0x91,57, 0x90,76, 0,166,
|
||||
0x90,73, 0,166, 0x91,45, 0x90,78, 0,166, 0x90,74, 0,166, 0x91,57, 0x90,73,
|
||||
0,166, 0x90,71, 0,138, 0x81, 0,27, 0x91,57, 0x90,76, 0,166, 0x90,73, 0,166,
|
||||
0x91,45, 0x90,74, 0,166, 0x90,71, 0,166, 0x91,57, 0x90,69, 0,166, 0x90,68,
|
||||
0,138, 0x81, 0,27, 0x91,57, 0x90,73, 0,166, 0x90,71, 0,166, 0x91,59, 0x90,74,
|
||||
0,166, 0x90,73, 0,166, 0x91,61, 0x90,71, 0,166, 0x90,69, 0,166, 0x91,62,
|
||||
0x90,78, 0,166, 0x91,61, 0,166, 0x90,68, 0x91,64, 0,166, 0x91,62, 0,166,
|
||||
0x90,69, 0x91,61, 0,166, 0x91,59, 0,166, 0x91,61, 0,27, 0x80, 0,27, 0x90,71,
|
||||
0,55, 0x90,69, 0,55, 0x91,62, 0x90,68, 0,55, 0x90,69, 0,55, 0x90,71,
|
||||
0,27, 0x80, 0,27, 0x90,71, 0x91,64, 1,77, 0x91,52, 0,166, 0x90,69, 0,166,
|
||||
0x91,57, 0x90,69, 0,166, 0x91,52, 0,166, 0x91,54, 0,166, 0x91,56, 0,166,
|
||||
0x91,57, 0x80, 0,166, 0x91,59, 0,166, 0x91,61, 0,166, 0x91,59, 0,166, 0x90,76,
|
||||
0x91,62, 0,166, 0x91,61, 0,166, 0x90,81, 0x91,59, 0,166, 0x91,57, 0,166,
|
||||
0x91,64, 0,166, 0x90,71, 0,166, 0x91,52, 0x90,73, 0,166, 0x90,75, 0,166,
|
||||
0x90,76, 0x81, 0,166, 0x90,78, 0,166, 0x90,79, 0,166, 0x90,78, 0,166, 0x91,59,
|
||||
0x90,81, 0,166, 0x90,79, 0,166, 0x91,64, 0x90,78, 0,166, 0x90,76, 0,166,
|
||||
0x90,83, 0,166, 0x91,54, 0,166, 0x90,71, 0x91,56, 0,166, 0x91,58, 0,166,
|
||||
0x91,59, 0x80, 0,166, 0x91,61, 0,166, 0x91,62, 0,166, 0x91,61, 0,166, 0x90,66,
|
||||
0x91,64, 0,166, 0x91,62, 0,166, 0x90,71, 0x91,61, 0,166, 0x91,59, 0,166,
|
||||
0x91,66, 0,166, 0x90,70, 0,166, 0x91,54, 0x90,71, 0,166, 0x90,73, 0,166,
|
||||
0x91,64, 0x90,74, 0,166, 0x90,76, 0,166, 0x91,62, 0x90,78, 0,166, 0x90,76,
|
||||
0,166, 0x91,71, 0x90,79, 0,166, 0x91,70, 0x90,78, 0,166, 0x91,71, 0x90,76,
|
||||
0,166, 0x90,74, 0,166, 0x91,61, 0x90,76, 0,166, 0x90,74, 0,166, 0x91,70,
|
||||
0x90,78, 0,166, 0x91,68, 0x90,76, 0,166, 0x91,70, 0x90,74, 0,166, 0x90,73,
|
||||
0,166, 0x91,71, 0x90,74, 0,166, 0x91,69, 0x90,73, 0,166, 0x91,67, 0x90,76,
|
||||
0,166, 0x91,66, 0x90,74, 0,166, 0x91,64, 0x90,73, 0,166, 0x91,62, 0x90,71,
|
||||
0,166, 0x91,64, 0x90,73, 0,166, 0x91,62, 0,166, 0x90,70, 0x91,66, 0,83,
|
||||
0x90,68, 0,83, 0x91,64, 0x90,70, 0,166, 0x91,62, 0x90,71, 0,166, 0x91,61,
|
||||
0,166, 0x91,62, 0,166, 0x90,73, 0x91,64, 0,138, 0x80, 0,27, 0x90,73, 0x91,66,
|
||||
0,83, 0x90,74, 0,83, 0x90,73, 0,166, 0x91,54, 0,166, 0x90,71, 0,166,
|
||||
0x91,59, 0,166, 0x90,66, 0,166, 0x91,54, 0x90,68, 0,166, 0x90,70, 0,166,
|
||||
0x91,50, 0x90,71, 0,166, 0x90,73, 0,166, 0x91,47, 0x90,74, 0,166, 0x90,73,
|
||||
0,166, 0x90,76, 0,166, 0x90,74, 0,166, 0x90,73, 0x81, 0,166, 0x90,71, 0,166,
|
||||
0x90,79, 0,166, 0x91,47, 0,166, 0x91,49, 0,166, 0x91,51, 0,166, 0x91,52,
|
||||
0,166, 0x91,54, 0,166, 0x91,55, 0,166, 0x91,54, 0,166, 0x91,57, 0,166,
|
||||
0x91,55, 0,166, 0x91,54, 0,166, 0x91,52, 0,166, 0x91,57, 0,138, 0x80, 0,27,
|
||||
0x90,64, 0,166, 0x90,66, 0,166, 0x90,68, 0,166, 0x90,69, 0,166, 0x90,71,
|
||||
0,166, 0x90,73, 0,166, 0x90,71, 0,166, 0x90,74, 0,166, 0x90,73, 0,166,
|
||||
0x90,71, 0,166, 0x90,69, 0,166, 0x90,78, 0,138, 0x81, 0,27, 0x91,45, 0,166,
|
||||
0x91,47, 0,166, 0x91,49, 0,166, 0x91,50, 0,166, 0x91,52, 0,166, 0x91,54,
|
||||
0,166, 0x91,52, 0,166, 0x91,55, 0,166, 0x91,54, 0,166, 0x91,52, 0,166,
|
||||
0x91,50, 0,166, 0x91,56, 0,138, 0x80, 0,27, 0x90,71, 0,166, 0x90,76, 0,166,
|
||||
0x91,52, 0x90,74, 0,166, 0x91,54, 0x90,73, 0,166, 0x91,56, 0x90,71, 0,166,
|
||||
0x91,57, 0x90,73, 0,166, 0x91,56, 0x90,71, 0,166, 0x91,54, 0x90,74, 0,166,
|
||||
0x91,52, 0x90,73, 0,166, 0x91,50, 0x90,71, 0,166, 0x91,54, 0x90,69, 0,166,
|
||||
0x91,52, 0x90,68, 0,83, 0x90,69, 0,83, 0x91,50, 0x90,68, 0,166, 0x91,49,
|
||||
0x90,64, 0,166, 0x91,47, 0,166, 0x90,69, 0x91,49, 0,166, 0x90,71, 0x91,45,
|
||||
0,166, 0x90,73, 0x91,57, 0,166, 0x90,71, 0,166, 0x91,54, 0x90,74, 0,166,
|
||||
0x90,73, 0,166, 0x91,49, 0x90,71, 0,166, 0x90,69, 0,166, 0x91,50, 0x90,78,
|
||||
0,166, 0x91,49, 0,166, 0x91,52, 0,166, 0x90,68, 0x91,50, 0,166, 0x90,69,
|
||||
0x91,49, 0,166, 0x90,68, 0x91,47, 0,166, 0x90,69, 0x91,49, 0,166, 0x90,74,
|
||||
0x91,50, 0,166, 0x90,71, 0x91,52, 1,77, 0x91,40, 0,166, 0x90,69, 0,138,
|
||||
0x80, 0,27, 0x90,69, 0x91,45, 0,166, 0x91,49, 0,166, 0x91,50, 0,166, 0x90,73,
|
||||
0x91,52, 0,166, 0x90,74, 0x91,54, 0,166, 0x90,76, 0x91,55, 0,166, 0x90,66,
|
||||
0x91,57, 0,166, 0x91,55, 0,166, 0x90,67, 0x91,59, 0,166, 0x91,57, 0,166,
|
||||
0x90,71, 0x91,55, 0,83, 0x90,69, 0,83, 0x91,54, 0x90,67, 0,83, 0x90,69,
|
||||
0,83, 0x91,55, 0x90,71, 0,166, 0x91,54, 0,166, 0x90,74, 0x91,57, 0,83,
|
||||
0x90,73, 0,83, 0x91,55, 0x90,71, 0,83, 0x90,73, 0,83, 0x91,54, 0x90,74,
|
||||
0,166, 0x91,52, 0,166, 0x91,54, 0,166, 0x90,73, 0x91,52, 0,166, 0x90,76,
|
||||
0x91,55, 0,166, 0x90,74, 0x91,54, 0,166, 0x90,73, 0x91,52, 0,166, 0x90,74,
|
||||
0x91,50, 0,166, 0x90,76, 0x91,57, 0,166, 0x90,74, 0,166, 0x91,45, 0x90,73,
|
||||
0,166, 0x90,71, 0,166, 0x90,69, 0x81, 0,166, 0x90,67, 0,166, 0x90,66, 0,166,
|
||||
0x90,64, 0,166, 0x90,67, 0,166, 0x90,66, 0,166, 0x90,64, 0,166, 0x90,62,
|
||||
0,166, 0x90,69, 0,166, 0x90,67, 0,166, 0x90,66, 0,166, 0x90,64, 0,166,
|
||||
0x91,50, 0x90,66, 0,166, 0x91,52, 0x90,62, 0,166, 0x91,54, 0x90,69, 0,166,
|
||||
0x91,52, 0,166, 0x90,71, 0x91,55, 0,166, 0x91,54, 0,166, 0x90,73, 0x91,52,
|
||||
0,55, 0x90,71, 0,55, 0x90,73, 0,55, 0x91,50, 0x90,74, 0,166, 0x91,57,
|
||||
0x90,73, 0,83, 0x90,74, 0,83, 0x91,55, 0x90,73, 0,166, 0x91,54, 0x90,71,
|
||||
0,83, 0x90,69, 0,83, 0x91,52, 0,125, 0x80, 0,41, 0x90,74, 0x91,54, 0,166,
|
||||
0x91,50, 0,138, 0x80, 0,27, 0x90,74, 0x91,57, 0,166, 0x91,54, 0,166, 0x90,62,
|
||||
0x91,59, 0,166, 0x91,55, 0,166, 0x90,74, 0x91,54, 0,166, 0x91,52, 0,138,
|
||||
0x80, 0,27, 0x90,74, 0x91,57, 0,166, 0x91,54, 0,166, 0x90,62, 0x91,55, 0,166,
|
||||
0x91,52, 0,166, 0x90,74, 0x91,50, 0,166, 0x91,49, 0,138, 0x80, 0,27, 0x90,74,
|
||||
0x91,57, 0,166, 0x91,54, 0,166, 0x90,62, 0x91,59, 0,166, 0x91,55, 0,166,
|
||||
0x90,74, 0x91,54, 0,166, 0x91,52, 0,138, 0x80, 0,27, 0x90,74, 0x91,57, 0,166,
|
||||
0x91,54, 0,166, 0x90,62, 0x91,55, 0,166, 0x91,52, 0,166, 0x90,74, 0x91,50,
|
||||
0,166, 0x90,76, 0x91,49, 0,166, 0x90,78, 0x91,50, 0,166, 0x90,76, 0,166,
|
||||
0x91,52, 0x90,79, 0,166, 0x90,78, 0,166, 0x91,54, 0x90,76, 0,166, 0x90,74,
|
||||
0,166, 0x91,55, 0x90,83, 0,166, 0x91,54, 0,166, 0x90,73, 0x91,57, 0,166,
|
||||
0x91,55, 0,166, 0x90,74, 0x91,54, 0,166, 0x91,52, 0,166, 0x91,54, 0,27,
|
||||
0x80, 0,27, 0x90,76, 0,55, 0x90,74, 0,55, 0x91,55, 0x90,73, 0,55, 0x90,74,
|
||||
0,55, 0x90,76, 0,41, 0x80, 0,13, 0x90,76, 0x91,57, 1,77, 0x91,45, 0,166,
|
||||
0x90,74, 0,138, 0x80, 0,27, 0x90,74, 0x91,47, 0,166, 0x91,45, 0,166, 0x90,62,
|
||||
0x91,48, 0,166, 0x91,47, 0,166, 0x90,67, 0x91,45, 0,166, 0x91,43, 0,166,
|
||||
0x91,50, 0,166, 0x90,57, 0,166, 0x90,59, 0,166, 0x90,61, 0,166, 0x90,62,
|
||||
0,166, 0x90,64, 0,166, 0x90,66, 0,138, 0x81, 0,27, 0x91,49, 0x90,64, 0,166,
|
||||
0x91,47, 0x90,67, 0,166, 0x91,45, 0x90,66, 0,166, 0x91,43, 0x90,64, 0,166,
|
||||
0x91,42, 0x90,62, 0,166, 0x91,43, 0x90,71, 0,166, 0x91,42, 0,166, 0x91,45,
|
||||
0,166, 0x90,61, 0x91,43, 0,166, 0x90,62, 0x91,42, 0,166, 0x90,61, 0x91,40,
|
||||
0,166, 0x90,62, 0x91,42, 0,166, 0x90,67, 0x91,43, 0,166, 0x90,64, 0x91,45,
|
||||
1,244, 0x90,62, 0,138, 0x80, 0,27, 0x90,62, 0x91,38, 7,208, 0x80, 0x81,
|
||||
0xf0
|
||||
};
|
||||
|
||||
Arduboy2 arduboy;
|
||||
ArduboyPlaytune tunes(arduboy.audio.enabled);
|
||||
|
|
@ -183,7 +133,7 @@ void setup()
|
|||
{
|
||||
arduboy.begin();
|
||||
|
||||
arduboy.setFrameRate(10);
|
||||
arduboy.setFrameRate(25);
|
||||
arduboy.setTextSize(3);
|
||||
|
||||
// audio setup
|
||||
|
|
@ -192,7 +142,7 @@ void setup()
|
|||
// if not a DevKit
|
||||
tunes.initChannel(PIN_SPEAKER_2);
|
||||
#else
|
||||
// if it's a Devkit
|
||||
// if it's a DevKit
|
||||
tunes.initChannel(PIN_SPEAKER_1); // use the same pin for both channels
|
||||
tunes.toneMutesScore(true); // mute the score when a tone is sounding
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,122 @@
|
|||
Creative Commons Legal Code
|
||||
|
||||
CC0 1.0 Universal
|
||||
|
||||
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
|
||||
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
|
||||
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
|
||||
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
|
||||
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
|
||||
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
|
||||
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
|
||||
HEREUNDER.
|
||||
|
||||
Statement of Purpose
|
||||
|
||||
The laws of most jurisdictions throughout the world automatically confer
|
||||
exclusive Copyright and Related Rights (defined below) upon the creator
|
||||
and subsequent owner(s) (each and all, an "owner") of an original work of
|
||||
authorship and/or a database (each, a "Work").
|
||||
|
||||
Certain owners wish to permanently relinquish those rights to a Work for
|
||||
the purpose of contributing to a commons of creative, cultural and
|
||||
scientific works ("Commons") that the public can reliably and without fear
|
||||
of later claims of infringement build upon, modify, incorporate in other
|
||||
works, reuse and redistribute as freely as possible in any form whatsoever
|
||||
and for any purposes, including without limitation commercial purposes.
|
||||
These owners may contribute to the Commons to promote the ideal of a free
|
||||
culture and the further production of creative, cultural and scientific
|
||||
works, or to gain reputation or greater distribution for their Work in
|
||||
part through the use and efforts of others.
|
||||
|
||||
For these and/or other purposes and motivations, and without any
|
||||
expectation of additional consideration or compensation, the person
|
||||
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
|
||||
is an owner of Copyright and Related Rights in the Work, voluntarily
|
||||
elects to apply CC0 to the Work and publicly distribute the Work under its
|
||||
terms, with knowledge of his or her Copyright and Related Rights in the
|
||||
Work and the meaning and intended legal effect of CC0 on those rights.
|
||||
|
||||
1. Copyright and Related Rights. A Work made available under CC0 may be
|
||||
protected by copyright and related or neighboring rights ("Copyright and
|
||||
Related Rights"). Copyright and Related Rights include, but are not
|
||||
limited to, the following:
|
||||
|
||||
i. the right to reproduce, adapt, distribute, perform, display,
|
||||
communicate, and translate a Work;
|
||||
ii. moral rights retained by the original author(s) and/or performer(s);
|
||||
iii. publicity and privacy rights pertaining to a person's image or
|
||||
likeness depicted in a Work;
|
||||
iv. rights protecting against unfair competition in regards to a Work,
|
||||
subject to the limitations in paragraph 4(a), below;
|
||||
v. rights protecting the extraction, dissemination, use and reuse of data
|
||||
in a Work;
|
||||
vi. database rights (such as those arising under Directive 96/9/EC of the
|
||||
European Parliament and of the Council of 11 March 1996 on the legal
|
||||
protection of databases, and under any national implementation
|
||||
thereof, including any amended or successor version of such
|
||||
directive); and
|
||||
vii. other similar, equivalent or corresponding rights throughout the
|
||||
world based on applicable law or treaty, and any national
|
||||
implementations thereof.
|
||||
|
||||
2. Waiver. To the greatest extent permitted by, but not in contravention
|
||||
of, applicable law, Affirmer hereby overtly, fully, permanently,
|
||||
irrevocably and unconditionally waives, abandons, and surrenders all of
|
||||
Affirmer's Copyright and Related Rights and associated claims and causes
|
||||
of action, whether now known or unknown (including existing as well as
|
||||
future claims and causes of action), in the Work (i) in all territories
|
||||
worldwide, (ii) for the maximum duration provided by applicable law or
|
||||
treaty (including future time extensions), (iii) in any current or future
|
||||
medium and for any number of copies, and (iv) for any purpose whatsoever,
|
||||
including without limitation commercial, advertising or promotional
|
||||
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
|
||||
member of the public at large and to the detriment of Affirmer's heirs and
|
||||
successors, fully intending that such Waiver shall not be subject to
|
||||
revocation, rescission, cancellation, termination, or any other legal or
|
||||
equitable action to disrupt the quiet enjoyment of the Work by the public
|
||||
as contemplated by Affirmer's express Statement of Purpose.
|
||||
|
||||
3. Public License Fallback. Should any part of the Waiver for any reason
|
||||
be judged legally invalid or ineffective under applicable law, then the
|
||||
Waiver shall be preserved to the maximum extent permitted taking into
|
||||
account Affirmer's express Statement of Purpose. In addition, to the
|
||||
extent the Waiver is so judged Affirmer hereby grants to each affected
|
||||
person a royalty-free, non transferable, non sublicensable, non exclusive,
|
||||
irrevocable and unconditional license to exercise Affirmer's Copyright and
|
||||
Related Rights in the Work (i) in all territories worldwide, (ii) for the
|
||||
maximum duration provided by applicable law or treaty (including future
|
||||
time extensions), (iii) in any current or future medium and for any number
|
||||
of copies, and (iv) for any purpose whatsoever, including without
|
||||
limitation commercial, advertising or promotional purposes (the
|
||||
"License"). The License shall be deemed effective as of the date CC0 was
|
||||
applied by Affirmer to the Work. Should any part of the License for any
|
||||
reason be judged legally invalid or ineffective under applicable law, such
|
||||
partial invalidity or ineffectiveness shall not invalidate the remainder
|
||||
of the License, and in such case Affirmer hereby affirms that he or she
|
||||
will not (i) exercise any of his or her remaining Copyright and Related
|
||||
Rights in the Work or (ii) assert any associated claims and causes of
|
||||
action with respect to the Work, in either case contrary to Affirmer's
|
||||
express Statement of Purpose.
|
||||
|
||||
4. Limitations and Disclaimers.
|
||||
|
||||
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
||||
surrendered, licensed or otherwise affected by this document.
|
||||
b. Affirmer offers the Work as-is and makes no representations or
|
||||
warranties of any kind concerning the Work, express, implied,
|
||||
statutory or otherwise, including without limitation warranties of
|
||||
title, merchantability, fitness for a particular purpose, non
|
||||
infringement, or the absence of latent or other defects, accuracy, or
|
||||
the present or absence of errors, whether or not discoverable, all to
|
||||
the greatest extent permissible under applicable law.
|
||||
c. Affirmer disclaims responsibility for clearing rights of other persons
|
||||
that may apply to the Work or any use thereof, including without
|
||||
limitation any person's Copyright and Related Rights in the Work.
|
||||
Further, Affirmer disclaims responsibility for obtaining any necessary
|
||||
consents, permissions or other rights required for any use of the
|
||||
Work.
|
||||
d. Affirmer understands and acknowledges that Creative Commons is not a
|
||||
party to this document and has no duty or obligation with respect to
|
||||
this CC0 or use of the Work.
|
||||
|
||||
|
|
@ -0,0 +1,362 @@
|
|||
/*
|
||||
RGBled
|
||||
|
||||
This sketch demonstrates controlling the Arduboy's RGB LED,
|
||||
in both analog and digital modes.
|
||||
*/
|
||||
|
||||
/*
|
||||
Written in 2018 by Scott Allen saydisp-git@yahoo.ca
|
||||
|
||||
To the extent possible under law, the author(s) have dedicated all copyright
|
||||
and related and neighboring rights to this software to the public domain
|
||||
worldwide. This software is distributed without any warranty.
|
||||
|
||||
You should have received a copy of the CC0 Public Domain Dedication along with
|
||||
this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
*/
|
||||
|
||||
#include <Arduboy2.h>
|
||||
|
||||
// The frame rate determines the button auto-repeat rate
|
||||
#define FRAME_RATE 25
|
||||
|
||||
// The increment/decrement amount when auto-repeating
|
||||
#define REPEAT_AMOUNT 3
|
||||
|
||||
// Delay time before button auto-repeat starts, in milliseconds
|
||||
#define REPEAT_DELAY 700
|
||||
|
||||
// Calculation of the number of frames to wait before button auto-repeat starts
|
||||
#define DELAY_FRAMES (REPEAT_DELAY / (1000 / FRAME_RATE))
|
||||
|
||||
#define ANALOG false
|
||||
#define DIGITAL true
|
||||
|
||||
#define ANALOG_MAX 255
|
||||
|
||||
// Color array index
|
||||
enum class Color {
|
||||
RED,
|
||||
GREEN,
|
||||
BLUE,
|
||||
COUNT
|
||||
};
|
||||
|
||||
// Map LED color index to LED name
|
||||
const byte LEDpin[(byte)(Color::COUNT)] = {
|
||||
RED_LED,
|
||||
GREEN_LED,
|
||||
BLUE_LED
|
||||
};
|
||||
|
||||
Arduboy2 arduboy;
|
||||
|
||||
// Analog LED values
|
||||
byte analogValue[3] = { 0, 0, 0};
|
||||
// Digital LED states
|
||||
byte digitalState[3] = { RGB_OFF, RGB_OFF, RGB_OFF };
|
||||
|
||||
byte analogSelected = (byte)(Color::RED);
|
||||
byte digitalSelected = (byte)(Color::RED);
|
||||
|
||||
boolean controlMode = ANALOG;
|
||||
|
||||
// Button repeat handling
|
||||
unsigned int delayCount = 0;
|
||||
boolean repeating = false;
|
||||
|
||||
// ============================= SETUP ===================================
|
||||
void setup() {
|
||||
arduboy.begin();
|
||||
arduboy.setFrameRate(FRAME_RATE);
|
||||
analogSet();
|
||||
}
|
||||
// =======================================================================
|
||||
|
||||
|
||||
// =========================== MAIN LOOP =================================
|
||||
void loop() {
|
||||
if (!arduboy.nextFrame()) {
|
||||
return;
|
||||
}
|
||||
|
||||
arduboy.pollButtons();
|
||||
|
||||
// Toggle analog/digital control mode
|
||||
if (arduboy.justPressed(A_BUTTON)) {
|
||||
if ((controlMode = !controlMode) == DIGITAL) {
|
||||
arduboy.freeRGBled();
|
||||
digitalSet();
|
||||
}
|
||||
else {
|
||||
analogSet();
|
||||
}
|
||||
}
|
||||
|
||||
// Reset to Analog mode and all LEDs off
|
||||
if (arduboy.justPressed(B_BUTTON)) {
|
||||
reset();
|
||||
}
|
||||
|
||||
// Handle D-pad buttons for current mode
|
||||
if (controlMode == ANALOG) {
|
||||
modeAnalog();
|
||||
}
|
||||
else {
|
||||
modeDigital();
|
||||
}
|
||||
|
||||
// Handle delay before button auto-repeat starts
|
||||
if ((delayCount != 0) && (--delayCount == 0)) {
|
||||
repeating = true;
|
||||
}
|
||||
|
||||
renderScreen(); // Render and display the entire screen
|
||||
}
|
||||
// =======================================================================
|
||||
|
||||
|
||||
// Analog control
|
||||
void modeAnalog() {
|
||||
if (arduboy.justPressed(RIGHT_BUTTON)) {
|
||||
valueInc(1);
|
||||
startButtonDelay();
|
||||
}
|
||||
else if (arduboy.justPressed(LEFT_BUTTON)) {
|
||||
valueDec(1);
|
||||
startButtonDelay();
|
||||
}
|
||||
else if (repeating && arduboy.pressed(RIGHT_BUTTON)) {
|
||||
valueInc(REPEAT_AMOUNT);
|
||||
}
|
||||
else if (repeating && arduboy.pressed(LEFT_BUTTON)) {
|
||||
valueDec(REPEAT_AMOUNT);
|
||||
}
|
||||
else if (arduboy.justPressed(DOWN_BUTTON)) {
|
||||
analogSelectInc();
|
||||
}
|
||||
else if (arduboy.justPressed(UP_BUTTON)) {
|
||||
analogSelectDec();
|
||||
}
|
||||
else if (repeating) {
|
||||
stopButtonRepeat();
|
||||
}
|
||||
}
|
||||
|
||||
// Digital control
|
||||
void modeDigital() {
|
||||
if (arduboy.justPressed(RIGHT_BUTTON) || arduboy.justPressed(LEFT_BUTTON)) {
|
||||
digitalState[digitalSelected] = (digitalState[digitalSelected] == RGB_ON) ?
|
||||
RGB_OFF : RGB_ON;
|
||||
arduboy.digitalWriteRGB(LEDpin[digitalSelected],
|
||||
digitalState[digitalSelected]);
|
||||
}
|
||||
else if (arduboy.justPressed(DOWN_BUTTON)) {
|
||||
digitalSelectInc();
|
||||
}
|
||||
else if (arduboy.justPressed(UP_BUTTON)) {
|
||||
digitalSelectDec();
|
||||
}
|
||||
}
|
||||
|
||||
// Reset to analog mode and turn all LEDs off
|
||||
void reset() {
|
||||
digitalState[(byte)(Color::RED)] = RGB_OFF;
|
||||
digitalState[(byte)(Color::GREEN)] = RGB_OFF;
|
||||
digitalState[(byte)(Color::BLUE)] = RGB_OFF;
|
||||
digitalSet();
|
||||
|
||||
analogValue[(byte)(Color::RED)] = 0;
|
||||
analogValue[(byte)(Color::GREEN)] = 0;
|
||||
analogValue[(byte)(Color::BLUE)] = 0;
|
||||
analogSet();
|
||||
|
||||
digitalSelected = (byte)(Color::RED);
|
||||
analogSelected = (byte)(Color::RED);
|
||||
|
||||
controlMode = ANALOG;
|
||||
}
|
||||
|
||||
// Increment the selected analog LED value by the specified amount
|
||||
// and update the LED
|
||||
void valueInc(byte amount) {
|
||||
if ((ANALOG_MAX - analogValue[analogSelected]) <= amount) {
|
||||
analogValue[analogSelected] = ANALOG_MAX;
|
||||
}
|
||||
else {
|
||||
analogValue[analogSelected] += amount;
|
||||
}
|
||||
|
||||
arduboy.setRGBled(LEDpin[analogSelected], analogValue[analogSelected]);
|
||||
}
|
||||
|
||||
// Decrement the selected analog LED value by the specified amount
|
||||
// and update the LED
|
||||
void valueDec(byte amount) {
|
||||
if (analogValue[analogSelected] <= amount) {
|
||||
analogValue[analogSelected] = 0;
|
||||
}
|
||||
else {
|
||||
analogValue[analogSelected] -= amount;
|
||||
}
|
||||
|
||||
arduboy.setRGBled(LEDpin[analogSelected], analogValue[analogSelected]);
|
||||
}
|
||||
|
||||
// Select the next analog color index with wrap
|
||||
void analogSelectInc() {
|
||||
selectInc(analogSelected);
|
||||
}
|
||||
|
||||
// Select the previous analog color index with wrap
|
||||
void analogSelectDec() {
|
||||
selectDec(analogSelected);
|
||||
}
|
||||
|
||||
// Select the next digital color index with wrap
|
||||
void digitalSelectInc() {
|
||||
selectInc(digitalSelected);
|
||||
}
|
||||
|
||||
// Select the previous digital color index with wrap
|
||||
void digitalSelectDec() {
|
||||
selectDec(digitalSelected);
|
||||
}
|
||||
|
||||
// Select the next color index with wrap
|
||||
void selectInc(byte &index) {
|
||||
if (++index == (byte)(Color::COUNT)) {
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Select the previous color index with wrap
|
||||
void selectDec(byte &index) {
|
||||
if (index == 0) {
|
||||
index = ((byte)(Color::COUNT) - 1);
|
||||
}
|
||||
else {
|
||||
index--;
|
||||
}
|
||||
}
|
||||
|
||||
// Update all LEDs in analog mode
|
||||
void analogSet() {
|
||||
arduboy.setRGBled(analogValue[(byte)(Color::RED)],
|
||||
analogValue[(byte)(Color::GREEN)],
|
||||
analogValue[(byte)(Color::BLUE)]);
|
||||
}
|
||||
|
||||
// Update all LEDs in digital mode
|
||||
void digitalSet() {
|
||||
arduboy.digitalWriteRGB(digitalState[(byte)(Color::RED)],
|
||||
digitalState[(byte)(Color::GREEN)],
|
||||
digitalState[(byte)(Color::BLUE)]);
|
||||
}
|
||||
|
||||
// Start the button auto-repeat delay
|
||||
void startButtonDelay() {
|
||||
delayCount = DELAY_FRAMES;
|
||||
repeating = false;
|
||||
}
|
||||
|
||||
// Stop the button auto-repeat or delay
|
||||
void stopButtonRepeat() {
|
||||
delayCount = 0;
|
||||
repeating = false;
|
||||
}
|
||||
|
||||
// Render and display the screen
|
||||
void renderScreen() {
|
||||
arduboy.setCursor(12, 0);
|
||||
arduboy.print(F("RGB LED"));
|
||||
arduboy.setCursor(15, 56);
|
||||
arduboy.print(F("A:Mode B:Reset"));
|
||||
arduboy.setCursor(74, 0);
|
||||
|
||||
if (controlMode == ANALOG) {
|
||||
arduboy.print(F(" Analog"));
|
||||
drawAnalog(9, Color::RED, "Red:");
|
||||
drawAnalog(25, Color::GREEN, "Green:");
|
||||
drawAnalog(41, Color::BLUE, "Blue:");
|
||||
}
|
||||
else { // Digital
|
||||
arduboy.print(F("Digital"));
|
||||
drawDigital(9, Color::RED, "Red:");
|
||||
drawDigital(25, Color::GREEN, "Green:");
|
||||
drawDigital(41, Color::BLUE, "Blue:");
|
||||
}
|
||||
|
||||
arduboy.display(CLEAR_BUFFER);
|
||||
}
|
||||
|
||||
// Draw the information for one analog color
|
||||
void drawAnalog(int y, Color color, const char* name) {
|
||||
byte value = analogValue[(byte)color];
|
||||
|
||||
arduboy.setCursor(0, y);
|
||||
arduboy.print(name);
|
||||
arduboy.setCursor(42, y);
|
||||
printValue(value);
|
||||
if (analogSelected == (byte)color) {
|
||||
arduboy.print(F(" <--"));
|
||||
}
|
||||
drawBar(y + 8, color, value);
|
||||
}
|
||||
|
||||
// Draw the value bar for an analog color
|
||||
void drawBar(int y, Color color, byte value) {
|
||||
byte barLength = value / 2;
|
||||
|
||||
if (barLength == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (analogSelected == (byte)color) {
|
||||
arduboy.fillRect(0, y, barLength, 5);
|
||||
}
|
||||
else {
|
||||
arduboy.drawRect(0, y, barLength, 5);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the information for one digital color
|
||||
void drawDigital(int y, Color color, const char* name) {
|
||||
byte state = digitalState[(byte)color];
|
||||
|
||||
arduboy.setCursor(34, y + 3);
|
||||
arduboy.print(name);
|
||||
arduboy.setCursor(76, y + 3);
|
||||
if (state == RGB_ON) {
|
||||
arduboy.print(F("ON "));
|
||||
arduboy.fillCircle(22, y + 6, 4);
|
||||
}
|
||||
else {
|
||||
arduboy.print(F("OFF"));
|
||||
arduboy.drawCircle(22, y + 6, 4);
|
||||
}
|
||||
|
||||
if (digitalSelected == (byte)color) {
|
||||
arduboy.print(F(" <--"));
|
||||
arduboy.drawRect(16, y, 13, 13);
|
||||
}
|
||||
}
|
||||
|
||||
// Print a byte in decimal and hex
|
||||
void printValue(byte val) {
|
||||
if (val < 100) {
|
||||
arduboy.print(' ');
|
||||
}
|
||||
if (val < 10) {
|
||||
arduboy.print(' ');
|
||||
}
|
||||
arduboy.print(val);
|
||||
|
||||
arduboy.print(F(" 0x"));
|
||||
if (val < 0x10) {
|
||||
arduboy.print('0');
|
||||
}
|
||||
arduboy.print(val, HEX);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,332 @@
|
|||
# Doxyfile 1.8.18
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Project related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = "Arduboy2 Library"
|
||||
PROJECT_NUMBER = 6.0.0
|
||||
PROJECT_BRIEF =
|
||||
PROJECT_LOGO =
|
||||
OUTPUT_DIRECTORY = doxygen
|
||||
CREATE_SUBDIRS = NO
|
||||
ALLOW_UNICODE_NAMES = NO
|
||||
OUTPUT_LANGUAGE = English
|
||||
OUTPUT_TEXT_DIRECTION = None
|
||||
BRIEF_MEMBER_DESC = YES
|
||||
REPEAT_BRIEF = YES
|
||||
ABBREVIATE_BRIEF =
|
||||
ALWAYS_DETAILED_SEC = NO
|
||||
INLINE_INHERITED_MEMB = YES
|
||||
FULL_PATH_NAMES = YES
|
||||
STRIP_FROM_PATH = src
|
||||
STRIP_FROM_INC_PATH =
|
||||
SHORT_NAMES = NO
|
||||
JAVADOC_AUTOBRIEF = NO
|
||||
JAVADOC_BANNER = NO
|
||||
QT_AUTOBRIEF = NO
|
||||
MULTILINE_CPP_IS_BRIEF = NO
|
||||
INHERIT_DOCS = YES
|
||||
SEPARATE_MEMBER_PAGES = NO
|
||||
TAB_SIZE = 2
|
||||
ALIASES =
|
||||
OPTIMIZE_OUTPUT_FOR_C = NO
|
||||
OPTIMIZE_OUTPUT_JAVA = NO
|
||||
OPTIMIZE_FOR_FORTRAN = NO
|
||||
OPTIMIZE_OUTPUT_VHDL = NO
|
||||
OPTIMIZE_OUTPUT_SLICE = NO
|
||||
EXTENSION_MAPPING =
|
||||
MARKDOWN_SUPPORT = YES
|
||||
TOC_INCLUDE_HEADINGS = 5
|
||||
AUTOLINK_SUPPORT = YES
|
||||
BUILTIN_STL_SUPPORT = NO
|
||||
CPP_CLI_SUPPORT = NO
|
||||
SIP_SUPPORT = NO
|
||||
IDL_PROPERTY_SUPPORT = YES
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
GROUP_NESTED_COMPOUNDS = 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_PRIV_VIRTUAL = NO
|
||||
EXTRACT_PACKAGE = NO
|
||||
EXTRACT_STATIC = YES
|
||||
EXTRACT_LOCAL_CLASSES = NO
|
||||
EXTRACT_LOCAL_METHODS = NO
|
||||
EXTRACT_ANON_NSPACES = NO
|
||||
HIDE_UNDOC_MEMBERS = YES
|
||||
HIDE_UNDOC_CLASSES = YES
|
||||
HIDE_FRIEND_COMPOUNDS = YES
|
||||
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_AS_ERROR = YES
|
||||
WARN_FORMAT = "$file:$line: $text"
|
||||
WARN_LOGFILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
INPUT = src \
|
||||
README.md \
|
||||
LICENSE.txt
|
||||
INPUT_ENCODING = UTF-8
|
||||
FILE_PATTERNS = *.cpp \
|
||||
*.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 =
|
||||
CLANG_DATABASE_PATH =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the alphabetical class index
|
||||
#---------------------------------------------------------------------------
|
||||
ALPHABETICAL_INDEX = NO
|
||||
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_MENUS = NO
|
||||
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
|
||||
HTML_FORMULA_FORMAT = png
|
||||
FORMULA_FONTSIZE = 10
|
||||
FORMULA_TRANSPARENT = YES
|
||||
FORMULA_MACROFILE =
|
||||
USE_MATHJAX = NO
|
||||
MATHJAX_FORMAT = HTML-CSS
|
||||
MATHJAX_RELPATH = https://cdn.jsdelivr.net/npm/mathjax@2
|
||||
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 =
|
||||
MAKEINDEX_CMD_NAME = makeindex
|
||||
LATEX_MAKEINDEX_CMD = 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
|
||||
LATEX_TIMESTAMP = YES
|
||||
LATEX_EMOJI_DIRECTORY =
|
||||
#---------------------------------------------------------------------------
|
||||
# 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
|
||||
XML_NS_MEMB_FILE_SCOPE = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# 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
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
CLASS_DIAGRAMS = YES
|
||||
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 = NO
|
||||
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_CFG_FILE =
|
||||
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
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 238 B |
Binary file not shown.
|
Before Width: | Height: | Size: 434 B After Width: | Height: | Size: 343 B |
|
|
@ -0,0 +1,122 @@
|
|||
Creative Commons Legal Code
|
||||
|
||||
CC0 1.0 Universal
|
||||
|
||||
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
|
||||
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
|
||||
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
|
||||
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
|
||||
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
|
||||
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
|
||||
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
|
||||
HEREUNDER.
|
||||
|
||||
Statement of Purpose
|
||||
|
||||
The laws of most jurisdictions throughout the world automatically confer
|
||||
exclusive Copyright and Related Rights (defined below) upon the creator
|
||||
and subsequent owner(s) (each and all, an "owner") of an original work of
|
||||
authorship and/or a database (each, a "Work").
|
||||
|
||||
Certain owners wish to permanently relinquish those rights to a Work for
|
||||
the purpose of contributing to a commons of creative, cultural and
|
||||
scientific works ("Commons") that the public can reliably and without fear
|
||||
of later claims of infringement build upon, modify, incorporate in other
|
||||
works, reuse and redistribute as freely as possible in any form whatsoever
|
||||
and for any purposes, including without limitation commercial purposes.
|
||||
These owners may contribute to the Commons to promote the ideal of a free
|
||||
culture and the further production of creative, cultural and scientific
|
||||
works, or to gain reputation or greater distribution for their Work in
|
||||
part through the use and efforts of others.
|
||||
|
||||
For these and/or other purposes and motivations, and without any
|
||||
expectation of additional consideration or compensation, the person
|
||||
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
|
||||
is an owner of Copyright and Related Rights in the Work, voluntarily
|
||||
elects to apply CC0 to the Work and publicly distribute the Work under its
|
||||
terms, with knowledge of his or her Copyright and Related Rights in the
|
||||
Work and the meaning and intended legal effect of CC0 on those rights.
|
||||
|
||||
1. Copyright and Related Rights. A Work made available under CC0 may be
|
||||
protected by copyright and related or neighboring rights ("Copyright and
|
||||
Related Rights"). Copyright and Related Rights include, but are not
|
||||
limited to, the following:
|
||||
|
||||
i. the right to reproduce, adapt, distribute, perform, display,
|
||||
communicate, and translate a Work;
|
||||
ii. moral rights retained by the original author(s) and/or performer(s);
|
||||
iii. publicity and privacy rights pertaining to a person's image or
|
||||
likeness depicted in a Work;
|
||||
iv. rights protecting against unfair competition in regards to a Work,
|
||||
subject to the limitations in paragraph 4(a), below;
|
||||
v. rights protecting the extraction, dissemination, use and reuse of data
|
||||
in a Work;
|
||||
vi. database rights (such as those arising under Directive 96/9/EC of the
|
||||
European Parliament and of the Council of 11 March 1996 on the legal
|
||||
protection of databases, and under any national implementation
|
||||
thereof, including any amended or successor version of such
|
||||
directive); and
|
||||
vii. other similar, equivalent or corresponding rights throughout the
|
||||
world based on applicable law or treaty, and any national
|
||||
implementations thereof.
|
||||
|
||||
2. Waiver. To the greatest extent permitted by, but not in contravention
|
||||
of, applicable law, Affirmer hereby overtly, fully, permanently,
|
||||
irrevocably and unconditionally waives, abandons, and surrenders all of
|
||||
Affirmer's Copyright and Related Rights and associated claims and causes
|
||||
of action, whether now known or unknown (including existing as well as
|
||||
future claims and causes of action), in the Work (i) in all territories
|
||||
worldwide, (ii) for the maximum duration provided by applicable law or
|
||||
treaty (including future time extensions), (iii) in any current or future
|
||||
medium and for any number of copies, and (iv) for any purpose whatsoever,
|
||||
including without limitation commercial, advertising or promotional
|
||||
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
|
||||
member of the public at large and to the detriment of Affirmer's heirs and
|
||||
successors, fully intending that such Waiver shall not be subject to
|
||||
revocation, rescission, cancellation, termination, or any other legal or
|
||||
equitable action to disrupt the quiet enjoyment of the Work by the public
|
||||
as contemplated by Affirmer's express Statement of Purpose.
|
||||
|
||||
3. Public License Fallback. Should any part of the Waiver for any reason
|
||||
be judged legally invalid or ineffective under applicable law, then the
|
||||
Waiver shall be preserved to the maximum extent permitted taking into
|
||||
account Affirmer's express Statement of Purpose. In addition, to the
|
||||
extent the Waiver is so judged Affirmer hereby grants to each affected
|
||||
person a royalty-free, non transferable, non sublicensable, non exclusive,
|
||||
irrevocable and unconditional license to exercise Affirmer's Copyright and
|
||||
Related Rights in the Work (i) in all territories worldwide, (ii) for the
|
||||
maximum duration provided by applicable law or treaty (including future
|
||||
time extensions), (iii) in any current or future medium and for any number
|
||||
of copies, and (iv) for any purpose whatsoever, including without
|
||||
limitation commercial, advertising or promotional purposes (the
|
||||
"License"). The License shall be deemed effective as of the date CC0 was
|
||||
applied by Affirmer to the Work. Should any part of the License for any
|
||||
reason be judged legally invalid or ineffective under applicable law, such
|
||||
partial invalidity or ineffectiveness shall not invalidate the remainder
|
||||
of the License, and in such case Affirmer hereby affirms that he or she
|
||||
will not (i) exercise any of his or her remaining Copyright and Related
|
||||
Rights in the Work or (ii) assert any associated claims and causes of
|
||||
action with respect to the Work, in either case contrary to Affirmer's
|
||||
express Statement of Purpose.
|
||||
|
||||
4. Limitations and Disclaimers.
|
||||
|
||||
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
||||
surrendered, licensed or otherwise affected by this document.
|
||||
b. Affirmer offers the Work as-is and makes no representations or
|
||||
warranties of any kind concerning the Work, express, implied,
|
||||
statutory or otherwise, including without limitation warranties of
|
||||
title, merchantability, fitness for a particular purpose, non
|
||||
infringement, or the absence of latent or other defects, accuracy, or
|
||||
the present or absence of errors, whether or not discoverable, all to
|
||||
the greatest extent permissible under applicable law.
|
||||
c. Affirmer disclaims responsibility for clearing rights of other persons
|
||||
that may apply to the Work or any use thereof, including without
|
||||
limitation any person's Copyright and Related Rights in the Work.
|
||||
Further, Affirmer disclaims responsibility for obtaining any necessary
|
||||
consents, permissions or other rights required for any use of the
|
||||
Work.
|
||||
d. Affirmer understands and acknowledges that Creative Commons is not a
|
||||
party to this document and has no duty or obligation with respect to
|
||||
this CC0 or use of the Work.
|
||||
|
||||
|
|
@ -0,0 +1,206 @@
|
|||
# Cabi - Compress Arduboy Image
|
||||
|
||||
A command line program to read a PNG (Portable Network Graphics) file
|
||||
containing a bitmap image, compress it using RLE encoding and convert it to
|
||||
C/C++ code suitable for use with the Team A.R.G. *drawCompressed()* function.
|
||||
This function is included in the Arduboy2 library.
|
||||
|
||||
Written by zep
|
||||
|
||||
https://www.lexaloffle.com/bbs/?uid=1
|
||||
|
||||
https://twitter.com/lexaloffle
|
||||
|
||||
Contributed to Team A.R.G.
|
||||
|
||||
This program uses code from the LodePNG project by Lode Vandevenne to read
|
||||
and decode PNG files.
|
||||
|
||||
https://github.com/lvandeve/lodepng
|
||||
|
||||
This version of Cabi is maintained as part of the Arduboy2 library so that it
|
||||
remains available since the demise of Team A.R.G.
|
||||
|
||||
## Building the program
|
||||
|
||||
Pre-built executable code is not provided due to the difficulty of maintaining
|
||||
versions for all the many operating systems that it could be run on.
|
||||
|
||||
The code is written in C and should compile properly using any ANSI C99
|
||||
compatible compiler, such as (but not limited to) gcc or clang.
|
||||
|
||||
### Build examples
|
||||
|
||||
To build from a copy of the cabi directory tree provided, while in the base
|
||||
directory containing cabi.c use:
|
||||
|
||||
`gcc cabi.c lodepng/lodepng.c -o cabi`
|
||||
|
||||
or
|
||||
|
||||
`clang cabi.c lodepng/lodepng.c -o cabi`
|
||||
|
||||
|
||||
For Windows, it may be more desirable to name the program `CABI.EXE` by using:
|
||||
|
||||
`-o CABI.EXE`
|
||||
|
||||
Compiler options for optimization, etc. (such as -O2 or -Os) can be added if
|
||||
desired but likely won't make much difference for most uses.
|
||||
|
||||
## Usage
|
||||
|
||||
The binary executable file (cabi or CABI.EXE) should be placed somewhere in the
|
||||
path for executables on the operating system used, or else include the path as
|
||||
part of the command given.
|
||||
|
||||
Running Cabi without any parameters will just output a brief program
|
||||
description and the usage syntax:
|
||||
|
||||
```text
|
||||
cabi - Compress Arduboy Image
|
||||
Convert a PNG file into RLE encoded C/C++ source
|
||||
for use with Arduboy2 drawCompressed()
|
||||
|
||||
usage: cabi in.png [array_name_prefix]
|
||||
```
|
||||
|
||||
For `in.png` substitute the name of the PNG file to be converted. If the file
|
||||
isn't in the current directory, the full path and name can be specified.
|
||||
|
||||
For `[array_name_prefix]` an optional prefix for the names of the arrays created
|
||||
can be given. If this parameter isn't provided, `compressed_image` will be used
|
||||
for the prefix.
|
||||
|
||||
If the program is unable to produce proper output, an error message will be
|
||||
given and a non-zero exit code will be returned.
|
||||
|
||||
## Input file decoding
|
||||
|
||||
The input file should be a PNG file containing the image to be converted.
|
||||
The height of the image must be a multiple of 8 pixels (8, 16, 24, 32, ...).
|
||||
The width can be any size.
|
||||
|
||||
The image will be translated to a raw array of 32 bit RGBA (Red, Green, Blue,
|
||||
Alpha) pixels internally before being processed to output. Ideally, pixels that
|
||||
are to be drawn (represented as a 1 in the image output) should be fully white.
|
||||
Non-drawn (0) pixels should be fully black. Pixels intended to be masked out of
|
||||
the image (represented as a 0 in both the image and mask output), should be
|
||||
fully transparent and their color doesn't matter.
|
||||
|
||||
However, after translation to RGBA, any pixel with an alpha (opaqueness) value
|
||||
of 127 or less will be set as non-drawn (0) for both the image and the mask.
|
||||
For the image, after the alpha value is first taken into account, pixels with a
|
||||
red color value greater than 127 will be set as drawn (1) and others will be
|
||||
set as non-drawn (0). For the mask, only the alpha value is used and red is
|
||||
ignored. Green and blue color values are ignored for both image and mask.
|
||||
|
||||
### To summarize:
|
||||
|
||||
For the image:
|
||||
|
||||
Green and blue are ignored.
|
||||
|
||||
| Alpha | Red | Output |
|
||||
|:------:|:-------:|:------:|
|
||||
| <= 127 | <= 127 | 0 |
|
||||
| <= 127 | > 127 | 0 |
|
||||
| > 127 | <= 127 | 0 |
|
||||
| > 127 | > 127 | 1 |
|
||||
|
||||
For the mask:
|
||||
|
||||
Red, green and blue are ignored.
|
||||
|
||||
| Alpha | Output |
|
||||
|:------:|:------:|
|
||||
| <= 127 | 0 |
|
||||
| > 127 | 1 |
|
||||
|
||||
## Output
|
||||
|
||||
Cabi will send all output to `stdout`, which is usually the console unless
|
||||
redirected. To save the output, you may be able to copy and paste it into your
|
||||
editor, or you can redirect `stdout` to a file for importing. For example:
|
||||
|
||||
`cabi PlayerSprite.png PlayerSprite > PlayerSprite.out`
|
||||
|
||||
If conversion is successful, the output will be text representing C/C++ code
|
||||
for two arrays, an image and a mask, that can be included in a sketch for use
|
||||
by the *drawCompressed()* function. The image array will be named the same as
|
||||
the prefix. The mask name will be the prefix with `_mask` appended to it.
|
||||
|
||||
Along with the actual array text, a comment will be included before each array
|
||||
giving the input file name used and the dimensions of the image. A comment
|
||||
included after each array will give the size of the array and the compression
|
||||
ratio compared to the non-compressed equivalent (although the ratio is based
|
||||
on the compressed array including two bytes for the bitmap dimensions compared
|
||||
to a non-compressed array without bitmap dimensions).
|
||||
|
||||
Note that it's possible that the "compressed" array will actually end up
|
||||
larger than the equivalent non-compressed one would. This is indicated by
|
||||
a compression ratio greater than 1. The ratio should be noted and taken into
|
||||
account when determining whether using Cabi compressed bitmaps is suitable for
|
||||
the intended purpose.
|
||||
|
||||
If masking isn't required, the mask array can be ignored or deleted.
|
||||
|
||||
Note that the usage message or any error message will also be sent to `stdout`,
|
||||
rather than `stderr`. Therefore, if you redirect the output to a file, in this
|
||||
case the file will contain only that text.
|
||||
|
||||
## Using the output with *drawCompressed()*
|
||||
|
||||
The Arduboy2 *drawCompressed()* function doesn't natively handle a mask for
|
||||
"transparent" pixels in an image. However, masking can be accomplished by
|
||||
calling *drawCompressed()* twice with the same coordinates. The first call
|
||||
specifies the mask array and the color BLACK. The second call specifies the
|
||||
image array and the color WHITE.
|
||||
|
||||
An example PNG bitmap named `sample.png` is included with the program. Here is
|
||||
an example Arduboy sketch that draws this bitmap with masking, using the Cabi
|
||||
output imported into the sketch.
|
||||
|
||||
```cpp
|
||||
#include <Arduboy2.h>
|
||||
|
||||
Arduboy2 arduboy;
|
||||
|
||||
// ===== Cabi output =====
|
||||
// sample.png width: 32 height: 32
|
||||
const PROGMEM uint8_t sample[] = {
|
||||
0x1f,0x1f,0x68,0x93,0xca,0x39,0xe5,0x9c,0x72,0xca,0xe9,0x74,0x4b,0x25,0x95,0xdc,
|
||||
0x6e,0xb7,0xdb,0xed,0x56,0x49,0x65,0xb7,0x4a,0x3a,0xa9,0xac,0x92,0x4e,0x3a,0xa9,
|
||||
0x74,0x94,0x8c,0x6a,0xbb,0xdd,0x6e,0xb7,0x8c,0x76,0xbb,0xdd,0x6e,0xb7,0xdb,0xed,
|
||||
0x76,0xbb,0xdd,0xf2,0xf1,0xa6,0xb7,0x52,0x79,0xc5,0xa4,0xbc,0x92,0x76,0x1d,0x2f,
|
||||
0x9f,0xdd,0x6e,0xb7,0xdb,0xed,0x76,0xbb,0xdd,0x6e,0xb7,0x8c,0xf4,0xd9,0x15,0x23,
|
||||
0x65,0x5a,0x49,0x27,0x9d,0x54,0x56,0x49,0x27,0x95,0xdd,0x2a,0xa9,0xec,0x76,0xbb,
|
||||
0xdd,0x6e,0x97,0x4a,0x2a,0xb9,0x54,0xce,0x39,0xe5,0x94,0x73,0xca,0x39,0x25,0xa3,
|
||||
0x05
|
||||
};
|
||||
// bytes:113 ratio: 0.883
|
||||
|
||||
const PROGMEM uint8_t sample_mask[] = {
|
||||
0x1f,0x1f,0x68,0x93,0xca,0x39,0x25,0x95,0xdc,0xa6,0xd3,0xa1,0x35,0x9d,0x4e,0x6f,
|
||||
0x95,0x54,0xd2,0x39,0xa9,0x74,0x94,0xe8,0xb4,0xdb,0xed,0x76,0xbb,0xdd,0x6e,0xb7,
|
||||
0xdb,0xed,0x16,0x8f,0x8a,0x49,0xe1,0xd1,0x6e,0xb7,0xdb,0xed,0x76,0xbb,0xdd,0x6e,
|
||||
0xb7,0x5b,0x74,0x52,0xa6,0x95,0x74,0x4e,0x2a,0xa9,0xec,0x3a,0x9d,0x0e,0xad,0xe9,
|
||||
0x74,0x76,0xa9,0xa4,0x72,0x4e,0xc9,0x68,0x01
|
||||
};
|
||||
// bytes:73 ratio: 0.570
|
||||
// =======================
|
||||
|
||||
void setup() {
|
||||
arduboy.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
arduboy.clear();
|
||||
|
||||
arduboy.drawCompressed(20, 10, sample_mask, BLACK);
|
||||
arduboy.drawCompressed(20, 10, sample, WHITE);
|
||||
|
||||
arduboy.display();
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -0,0 +1,385 @@
|
|||
/*
|
||||
cabi - Compress Arduboy Image
|
||||
|
||||
A command line program to read a PNG file containing a bitmap image, compress
|
||||
it using RLE encoding and convert it to C/C++ code suitable for use with the
|
||||
Team A.R.G. drawCompressed() function. This function is included in the
|
||||
Arduboy2 library.
|
||||
|
||||
Written by zep
|
||||
https://www.lexaloffle.com/bbs/?uid=1
|
||||
https://twitter.com/lexaloffle
|
||||
Contributed to Team A.R.G.
|
||||
|
||||
Modifications by Scott Allen - July 2020, September 2020
|
||||
|
||||
To the extent possible under law, the author(s) have dedicated all copyright
|
||||
and related and neighboring rights to this software to the public domain
|
||||
worldwide. This software is distributed without any warranty.
|
||||
|
||||
You should have received a copy of the CC0 Public Domain Dedication along with
|
||||
this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
|
||||
Usage:
|
||||
cabi in.png [array_name_prefix]
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <memory.h>
|
||||
#include "lodepng/lodepng.h"
|
||||
|
||||
// alternative pixel order mapping
|
||||
//#define READING_ORDER 1
|
||||
|
||||
unsigned reading_order = 0;
|
||||
|
||||
// one byte encodes a 1x8 stick; low byte at top
|
||||
|
||||
|
||||
|
||||
// for testing
|
||||
void draw_sprite_ascii(const uint8_t *dat, unsigned w, unsigned h)
|
||||
{
|
||||
unsigned x, y;
|
||||
unsigned row, bit;
|
||||
|
||||
for (y = 0; y < h; y ++)
|
||||
{
|
||||
row = y/8;
|
||||
bit = y&7;
|
||||
|
||||
for (x = 0; x < w; x++)
|
||||
{
|
||||
if (dat[x + (row*w)] & (1 << bit))
|
||||
printf("#");
|
||||
else
|
||||
printf(".");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// :: Decompress
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// compression / decompression session state
|
||||
|
||||
typedef struct CSESSION{
|
||||
unsigned byte;
|
||||
unsigned bit;
|
||||
const uint8_t *src;
|
||||
uint8_t *dest;
|
||||
unsigned src_pos;
|
||||
unsigned out_pos;
|
||||
unsigned w, h;
|
||||
}CSESSION;
|
||||
static CSESSION cs;
|
||||
|
||||
// get an n-bit number from the compressed data stream
|
||||
static unsigned getval(unsigned bits)
|
||||
{
|
||||
unsigned val = 0;
|
||||
unsigned i;
|
||||
for (i = 0; i < bits; i++)
|
||||
{
|
||||
if (cs.bit == 0x100)
|
||||
{
|
||||
cs.bit = 0x1;
|
||||
cs.byte = cs.src[cs.src_pos];
|
||||
cs.src_pos ++;
|
||||
}
|
||||
if (cs.byte & cs.bit)
|
||||
val += (1 << i);
|
||||
cs.bit <<= 1;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
// decompress_rle
|
||||
// if not NULL, w and h give back the size of the sprite.
|
||||
void draw_compressed_sprite_ascii(const uint8_t *src)
|
||||
{
|
||||
unsigned col;
|
||||
unsigned bl, len;
|
||||
unsigned i;
|
||||
unsigned w, h;
|
||||
unsigned x, y;
|
||||
unsigned total = 0;
|
||||
|
||||
memset(&cs, 0, sizeof(cs));
|
||||
cs.src = src;
|
||||
cs.bit = 0x100;
|
||||
cs.src_pos = 0;
|
||||
|
||||
// header
|
||||
|
||||
w = getval(8) + 1;
|
||||
h = getval(8) + 1;
|
||||
col = getval(1); // starting colour
|
||||
|
||||
x = y = 0;
|
||||
|
||||
while (y < h)
|
||||
{
|
||||
bl = 1;
|
||||
while (!getval(1))
|
||||
bl += 2;
|
||||
|
||||
len = getval(bl)+1; // span length
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
//if ((x%8) == 0) // every 8th bit (format test)
|
||||
printf("%s", col ? "#":".");
|
||||
|
||||
if (col) total++;
|
||||
x++;
|
||||
if (x >= w)
|
||||
{
|
||||
printf("\n");
|
||||
y ++;
|
||||
x = 0;
|
||||
}
|
||||
|
||||
//if ((x+y*w)%(w*8) == 0) printf("\n"); // print every 8th line (format test)
|
||||
|
||||
}
|
||||
|
||||
col = 1-col; // toggle
|
||||
}
|
||||
printf("\ntotal: %u\n", total);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// :: Compress
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
getcol
|
||||
|
||||
pos is the index of the pixel: 0 .. w*h-1
|
||||
*/
|
||||
static unsigned getcol(unsigned pos)
|
||||
{
|
||||
unsigned x, y;
|
||||
|
||||
// display order
|
||||
|
||||
if (reading_order == 0)
|
||||
{
|
||||
if (cs.src[pos/8] & (1 << (pos&7))) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// reading order (compresses slightly better but harder to optimize sprite blit)
|
||||
// or use this after loading png into display order (no need for extra conversion)
|
||||
|
||||
x = (pos % cs.w);
|
||||
y = (pos / cs.w);
|
||||
if (cs.src[x + ((y/8)*cs.w)] & (1 << (y&7))) return 1;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static unsigned find_rlen(unsigned pos, unsigned plen)
|
||||
{
|
||||
unsigned col;
|
||||
unsigned pos0;
|
||||
|
||||
col = getcol(pos);
|
||||
pos0 = pos;
|
||||
|
||||
while(getcol(pos) == col && pos < plen)
|
||||
pos ++;
|
||||
|
||||
return pos-pos0;
|
||||
}
|
||||
|
||||
// write a bit to the stream. non-zero val means 1, otherwise 0.
|
||||
static void putbit(unsigned val)
|
||||
{
|
||||
if (val) cs.byte |= cs.bit;
|
||||
cs.bit <<= 1;
|
||||
if (cs.bit == 0x100)
|
||||
{
|
||||
//output byte
|
||||
if (cs.out_pos != 0) printf(",");
|
||||
if (cs.out_pos % 16 == 0) printf("\n");
|
||||
printf("0x%02x", cs.byte);
|
||||
|
||||
cs.out_pos ++;
|
||||
cs.bit = 0x1;
|
||||
cs.byte = 0;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// write an n-bit (bits) number (val) to the output steam
|
||||
static void putval(unsigned val, unsigned bits)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
if (bits <= 0) return;
|
||||
for (i = 0; i < bits; i++)
|
||||
putbit(val & (1 << i));
|
||||
}
|
||||
|
||||
// write a span length
|
||||
// a string of bits encoding the number of bits needed to encode the length,
|
||||
// and then the length.
|
||||
static void putsplen(unsigned len)
|
||||
{
|
||||
unsigned blen = 1; // how bits needed to encode length
|
||||
while ((unsigned)(1 << blen) <= len) {
|
||||
blen += 2;
|
||||
}
|
||||
// write number of bits (1-terminated string of zeroes)
|
||||
putval(0,(blen-1)/2);
|
||||
putval(1,1); // terminator
|
||||
// write length
|
||||
putval(len, blen);
|
||||
}
|
||||
|
||||
/*
|
||||
comp
|
||||
|
||||
compress plen 1-bit pixels from src to dest
|
||||
|
||||
*/
|
||||
unsigned compress_rle(const uint8_t *src, unsigned w, unsigned h, char *prefix, char *suffix)
|
||||
{
|
||||
unsigned pos;
|
||||
unsigned rlen;
|
||||
|
||||
printf("const PROGMEM uint8_t %s%s[] = {", prefix, suffix);
|
||||
fflush(stdout);
|
||||
|
||||
memset(&cs, 0, sizeof(cs));
|
||||
cs.src = src;
|
||||
cs.bit = 1;
|
||||
cs.w = w;
|
||||
cs.h = h;
|
||||
|
||||
// header
|
||||
putval(w-1, 8);
|
||||
putval(h-1, 8);
|
||||
putval(getcol(0), 1); // first colour
|
||||
|
||||
pos = 0;
|
||||
|
||||
// span data
|
||||
|
||||
while (pos < w*h)
|
||||
{
|
||||
rlen = find_rlen(pos, w*h);
|
||||
pos += rlen;
|
||||
putsplen(rlen-1);
|
||||
}
|
||||
|
||||
// pad with zeros and flush
|
||||
while (cs.bit != 0x1)
|
||||
putbit(0);
|
||||
|
||||
printf("\n};\n");
|
||||
|
||||
return cs.out_pos; // bytes
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
unsigned compressed_len;
|
||||
unsigned w, h;
|
||||
unsigned char *bmp = NULL;
|
||||
unsigned char *bmp0 = NULL;
|
||||
unsigned char *bmp1 = NULL;
|
||||
unsigned result;
|
||||
unsigned rawlen;
|
||||
unsigned x, y;
|
||||
unsigned row, bit;
|
||||
char default_prefix[] = "compressed_image";
|
||||
char *prefix = default_prefix;
|
||||
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
printf("cabi - Compress Arduboy Image\n");
|
||||
printf("Convert a PNG file into RLE encoded C/C++ source\n");
|
||||
printf("for use with Arduboy2 drawCompressed()\n\n");
|
||||
|
||||
printf("usage: cabi in.png [array_name_prefix]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (argc >= 3) {
|
||||
prefix = argv[2];
|
||||
}
|
||||
|
||||
result = lodepng_decode32_file(&bmp, &w, &h, argv[1]);
|
||||
|
||||
if (result != 0) {
|
||||
printf("error %u: file %s: %s\n", result, argv[1], lodepng_error_text(result));
|
||||
free(bmp);
|
||||
exit(result);
|
||||
}
|
||||
|
||||
if (h % 8 != 0) {
|
||||
printf("error 120: file %s: image height must be a multiple of 8 but is %u\n", argv[1], h);
|
||||
free(bmp);
|
||||
exit(120);
|
||||
}
|
||||
|
||||
// generate sprite and mask
|
||||
|
||||
rawlen = w * (h+7) / 8;
|
||||
|
||||
bmp0 = (unsigned char *)malloc(rawlen); memset(bmp0, 0, rawlen);
|
||||
bmp1 = (unsigned char *)malloc(rawlen); memset(bmp1, 0, rawlen);
|
||||
|
||||
printf("// %s width: %u height: %u\n", argv[1], w, h);
|
||||
|
||||
for (y = 0; y < h; y++)
|
||||
{
|
||||
for (x = 0; x < w; x++)
|
||||
{
|
||||
row = y/8;
|
||||
bit = y&7;
|
||||
|
||||
if (bmp[(x+y*w)*4 + 3] > 127) // need to be opaque to count
|
||||
if (bmp[(x+y*w)*4 + 0] > 127)
|
||||
{
|
||||
// set sprite
|
||||
bmp0[x + (row*w)] |= (1 << bit);
|
||||
}
|
||||
|
||||
if (bmp[(x+y*w)*4 + 3] > 127)
|
||||
{
|
||||
// set mask
|
||||
bmp1[x + (row*w)] |= (1 << bit);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
compressed_len = compress_rle(bmp0, w, h, prefix, "");
|
||||
printf("// bytes:%u ratio: %3.3f\n\n", compressed_len, (float)(compressed_len * 8)/ (float)(w*h));
|
||||
|
||||
compressed_len = compress_rle(bmp1, w, h, prefix, "_mask");
|
||||
printf("// bytes:%u ratio: %3.3f\n\n", compressed_len, (float)(compressed_len * 8)/ (float)(w*h));
|
||||
|
||||
|
||||
free(bmp);
|
||||
free(bmp0);
|
||||
free(bmp1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
Copyright (c) 2005-2018 Lode Vandevenne
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
After Width: | Height: | Size: 199 B |
|
|
@ -1,22 +1,22 @@
|
|||
# File Descriptions
|
||||
|
||||
Documentation for files contained in this repository which aren't self explanatory.
|
||||
Documentation for files contained in this repository that aren't self explanatory.
|
||||
|
||||
### /library.properties
|
||||
|
||||
Provides information so that this library can be installed and updated in the Arduino IDE using the [Library Manager](https://www.arduino.cc/en/Guide/Libraries#toc3).
|
||||
|
||||
The value of *version* must be set to the latest stable tagged release. This should be changed and commited just before tagging the new release.
|
||||
The value of *version* must be set to the latest stable tagged release. This should be changed and committed just before tagging the new release.
|
||||
|
||||
See the [Arduino IDE 1.5: Library specification](https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification) for details.
|
||||
See the [Arduino IDE 1.5: Library specification](https://arduino.github.io/arduino-cli/library-specification/) for details.
|
||||
|
||||
### /library.json
|
||||
|
||||
This JSON file is a manifest used by the [PlatformIO IDE](http://platformio.org/) to make this library available in its [Library Manager](http://docs.platformio.org/en/latest/librarymanager/index.html).
|
||||
This JSON file is a manifest used by the [PlatformIO IDE](https://platformio.org/) to make this library available in its [Library Manager](https://docs.platformio.org/en/latest/librarymanager/index.html).
|
||||
|
||||
The value of *version* must be set to the latest stable tagged release. This should be changed and commited just before tagging the new release.
|
||||
The value of *version* must be set to the latest stable tagged release. This should be changed and committed just before tagging the new release.
|
||||
|
||||
See the [PlatformIO library.json](http://docs.platformio.org/en/latest/librarymanager/config.html) documentation for details.
|
||||
See the [PlatformIO library.json](https://docs.platformio.org/en/latest/librarymanager/config.html) documentation for details.
|
||||
|
||||
### /extras/assets/arduboy_logo.png<br>/extras/assets/arduboy_screen.png
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
The following files contain the Arduboy2 library version number.
|
||||
They must be updated to match the release tag before a new version is released.
|
||||
|
||||
library.properties
|
||||
version=
|
||||
|
||||
library.json
|
||||
"version":
|
||||
|
||||
src/Arduboy2.h
|
||||
#define ARDUBOY_LIB_VER
|
||||
|
||||
extras/Doxyfile
|
||||
PROJECT_NUMBER =
|
||||
|
||||
102
keywords.txt
102
keywords.txt
|
|
@ -1,5 +1,5 @@
|
|||
#######################################
|
||||
# Syntax Coloring Map For Arduboy
|
||||
# Syntax Coloring Map For Arduboy2
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
|
|
@ -8,24 +8,44 @@
|
|||
|
||||
Arduboy2 KEYWORD1
|
||||
Arduboy2Base KEYWORD1
|
||||
BeepPin1 KEYWORD1
|
||||
BeepPin2 KEYWORD1
|
||||
Point KEYWORD1
|
||||
Rect KEYWORD1
|
||||
Sprites KEYWORD1
|
||||
SpritesB KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
allPixelsOn KEYWORD2
|
||||
anyPressed KEYWORD2
|
||||
begin KEYWORD2
|
||||
blank KEYWORD2
|
||||
boot KEYWORD2
|
||||
bootLogo KEYWORD2
|
||||
bootLogoCompressed KEYWORD2
|
||||
bootLogoExtra KEYWORD2
|
||||
bootLogoShell KEYWORD2
|
||||
bootLogoSpritesBOverwrite KEYWORD2
|
||||
bootLogoSpritesBSelfMasked KEYWORD2
|
||||
bootLogoSpritesOverwrite KEYWORD2
|
||||
bootLogoSpritesSelfMasked KEYWORD2
|
||||
bootLogoText KEYWORD2
|
||||
buttonsState KEYWORD2
|
||||
clear KEYWORD2
|
||||
collide KEYWORD2
|
||||
cpuLoad KEYWORD2
|
||||
delayShort KEYWORD2
|
||||
digitalWriteRGB KEYWORD2
|
||||
display KEYWORD2
|
||||
displayOff KEYWORD2
|
||||
displayOn KEYWORD2
|
||||
drawBitmap KEYWORD2
|
||||
drawChar KEYWORD2
|
||||
drawCircle KEYWORD2
|
||||
drawCompressed KEYWORD2
|
||||
drawFastHLine KEYWORD2
|
||||
drawFastVLine KEYWORD2
|
||||
drawLine KEYWORD2
|
||||
|
|
@ -36,6 +56,7 @@ drawSlowXYBitmap KEYWORD2
|
|||
drawTriangle KEYWORD2
|
||||
enabled KEYWORD2
|
||||
everyXFrames KEYWORD2
|
||||
exitToBootloader KEYWORD2
|
||||
fillCircle KEYWORD2
|
||||
fillRect KEYWORD2
|
||||
fillRoundRect KEYWORD2
|
||||
|
|
@ -44,42 +65,113 @@ fillTriangle KEYWORD2
|
|||
flashlight KEYWORD2
|
||||
flipVertical KEYWORD2
|
||||
flipHorizontal KEYWORD2
|
||||
freeRGBled KEYWORD2
|
||||
generateRandomSeed KEYWORD2
|
||||
getBuffer KEYWORD2
|
||||
getCharacterHeight KEYWORD2
|
||||
getCharacterSpacing KEYWORD2
|
||||
getCharacterWidth KEYWORD2
|
||||
getCursorX KEYWORD2
|
||||
getCursorY KEYWORD2
|
||||
getLineSpacing KEYWORD2
|
||||
getPixel KEYWORD2
|
||||
getTextBackground KEYWORD2
|
||||
getTextColor KEYWORD2
|
||||
getTextRawMode KEYWORD2
|
||||
getTextSize KEYWORD2
|
||||
getTextWrap KEYWORD2
|
||||
height KEYWORD2
|
||||
idle KEYWORD2
|
||||
initRandomSeed KEYWORD2
|
||||
invert KEYWORD2
|
||||
justPressed KEYWORD2
|
||||
justReleased KEYWORD2
|
||||
nextFrame KEYWORD2
|
||||
nextFrameDEV KEYWORD2
|
||||
notPressed KEYWORD2
|
||||
off KEYWORD2
|
||||
on KEYWORD2
|
||||
paint8Pixels KEYWORD2
|
||||
paintScreen KEYWORD2
|
||||
pollButtons KEYWORD2
|
||||
pressed KEYWORD2
|
||||
readShowBootLogoFlag KEYWORD2
|
||||
readShowBootLogoLEDsFlag KEYWORD2
|
||||
readShowUnitNameFlag KEYWORD2
|
||||
readUnitID KEYWORD2
|
||||
readUnitName KEYWORD2
|
||||
safeMode KEYWORD2
|
||||
saveOnOff KEYWORD2
|
||||
setCursor KEYWORD2
|
||||
setCursorX KEYWORD2
|
||||
setCursorY KEYWORD2
|
||||
setFrameDuration KEYWORD2
|
||||
setFrameRate KEYWORD2
|
||||
setRGBled KEYWORD2
|
||||
setTextColor KEYWORD2
|
||||
setTextBackground KEYWORD2
|
||||
setTextColor KEYWORD2
|
||||
setTextRawMode KEYWORD2
|
||||
setTextSize KEYWORD2
|
||||
setTextWrap KEYWORD2
|
||||
SPItransfer KEYWORD2
|
||||
SPItransferAndRead KEYWORD2
|
||||
systemButtons KEYWORD2
|
||||
toggle KEYWORD2
|
||||
waitNoButtons KEYWORD2
|
||||
width KEYWORD2
|
||||
writeShowBootLogoFlag KEYWORD2
|
||||
writeShowBootLogoLEDsFlag KEYWORD2
|
||||
writeShowUnitNameFlag KEYWORD2
|
||||
writeUnitID KEYWORD2
|
||||
writeUnitName KEYWORD2
|
||||
|
||||
# Arduboy2Beep classes
|
||||
freq KEYWORD2
|
||||
noTone KEYWORD2
|
||||
timer KEYWORD2
|
||||
tone KEYWORD2
|
||||
|
||||
# Sprites class
|
||||
drawErase KEYWORD2
|
||||
drawExternalMask KEYWORD2
|
||||
drawOverwrite KEYWORD2
|
||||
drawPlusMask KEYWORD2
|
||||
drawSelfMasked KEYWORD2
|
||||
|
||||
##### Public variables #####
|
||||
|
||||
audio KEYWORD2
|
||||
arduboy_logo KEYWORD2
|
||||
arduboy_logo_compressed KEYWORD2
|
||||
arduboy_logo_sprite KEYWORD2
|
||||
currentButtonState KEYWORD2
|
||||
font5x7 KEYWORD2
|
||||
frameCount KEYWORD2
|
||||
previousButtonState KEYWORD2
|
||||
sBuffer KEYWORD2
|
||||
|
||||
# Arduboy2Beep classes
|
||||
duration KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
|
||||
ARDUBOY_LIB_VER LITERAL1
|
||||
|
||||
ARDUBOY_UNIT_NAME_LEN LITERAL1
|
||||
ARDUBOY_UNIT_NAME_BUFFER_SIZE LITERAL1
|
||||
|
||||
EEPROM_STORAGE_SPACE_START LITERAL1
|
||||
|
||||
HEIGHT LITERAL1
|
||||
WIDTH LITERAL1
|
||||
COLUMN_ADDRESS_END LITERAL1
|
||||
PAGE_ADDRESS_END LITERAL1
|
||||
|
||||
BLACK LITERAL1
|
||||
WHITE LITERAL1
|
||||
INVERT LITERAL1
|
||||
|
||||
CLEAR_BUFFER LITERAL1
|
||||
|
||||
A_BUTTON LITERAL1
|
||||
B_BUTTON LITERAL1
|
||||
|
|
@ -98,3 +190,5 @@ RED_LED LITERAL1
|
|||
RGB_OFF LITERAL1
|
||||
RGB_ON LITERAL1
|
||||
|
||||
ARDUBOY_NO_USB LITERAL1
|
||||
|
||||
|
|
|
|||
|
|
@ -7,8 +7,11 @@
|
|||
"type": "git",
|
||||
"url": "https://github.com/MLXXXp/Arduboy2.git"
|
||||
},
|
||||
"version": "2.0.1",
|
||||
"exclude": "extras",
|
||||
"version": "6.0.0",
|
||||
"export":
|
||||
{
|
||||
"exclude": "extras"
|
||||
},
|
||||
"frameworks": "arduino",
|
||||
"platforms": "atmelavr"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
name=Arduboy2
|
||||
version=2.0.1
|
||||
version=6.0.0
|
||||
author=Chris J. Martinez, Kevin Bates, Josh Goebel, Scott Allen, Ross O. Shoger
|
||||
maintainer=Scott Allen saydisp-git@yahoo.ca
|
||||
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
|
||||
|
|
|
|||
1122
src/Arduboy2.cpp
1122
src/Arduboy2.cpp
File diff suppressed because it is too large
Load Diff
2384
src/Arduboy2.h
2384
src/Arduboy2.h
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,59 @@
|
|||
/**
|
||||
* @file Arduboy2Audio.cpp
|
||||
* \brief
|
||||
* The Arduboy2Audio class for speaker and sound control.
|
||||
*/
|
||||
|
||||
#include "Arduboy2.h"
|
||||
|
||||
bool Arduboy2Audio::audio_enabled = false;
|
||||
|
||||
void Arduboy2Audio::on()
|
||||
{
|
||||
// fire up audio pins by seting them as outputs
|
||||
#ifdef ARDUBOY_10
|
||||
bitSet(SPEAKER_1_DDR, SPEAKER_1_BIT);
|
||||
bitSet(SPEAKER_2_DDR, SPEAKER_2_BIT);
|
||||
#else
|
||||
bitSet(SPEAKER_1_DDR, SPEAKER_1_BIT);
|
||||
#endif
|
||||
audio_enabled = true;
|
||||
}
|
||||
|
||||
void Arduboy2Audio::off()
|
||||
{
|
||||
audio_enabled = false;
|
||||
// shut off audio pins by setting them as inputs
|
||||
#ifdef ARDUBOY_10
|
||||
bitClear(SPEAKER_1_DDR, SPEAKER_1_BIT);
|
||||
bitClear(SPEAKER_2_DDR, SPEAKER_2_BIT);
|
||||
#else
|
||||
bitClear(SPEAKER_1_DDR, SPEAKER_1_BIT);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Arduboy2Audio::toggle()
|
||||
{
|
||||
if (audio_enabled)
|
||||
off();
|
||||
else
|
||||
on();
|
||||
}
|
||||
|
||||
void Arduboy2Audio::saveOnOff()
|
||||
{
|
||||
EEPROM.update(Arduboy2Base::eepromAudioOnOff, audio_enabled);
|
||||
}
|
||||
|
||||
void Arduboy2Audio::begin()
|
||||
{
|
||||
if (EEPROM.read(Arduboy2Base::eepromAudioOnOff))
|
||||
on();
|
||||
else
|
||||
off();
|
||||
}
|
||||
|
||||
bool Arduboy2Audio::enabled()
|
||||
{
|
||||
return audio_enabled;
|
||||
}
|
||||
|
|
@ -0,0 +1,158 @@
|
|||
/**
|
||||
* @file Arduboy2Audio.h
|
||||
* \brief
|
||||
* The Arduboy2Audio class for speaker and sound control.
|
||||
*/
|
||||
|
||||
#ifndef ARDUBOY2_AUDIO_H
|
||||
#define ARDUBOY2_AUDIO_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <EEPROM.h>
|
||||
|
||||
/** \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{.cpp}
|
||||
* #include <Arduboy2.h>
|
||||
*
|
||||
* 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{.cpp}
|
||||
* #include <Arduboy2.h>
|
||||
* #include <ArduboyTones.h>
|
||||
*
|
||||
* Arduboy2 arduboy;
|
||||
* ArduboyTones sound(arduboy.audio.enabled);
|
||||
* \endcode
|
||||
* \endparblock
|
||||
*
|
||||
* \note
|
||||
* \parblock
|
||||
* A friend class named _Arduboy2Ex_ is declared by this class. The intention
|
||||
* is to allow a sketch to create an _Arduboy2Ex_ class which would have access
|
||||
* to the private and protected members of the Arduboy2Audio class. It is hoped
|
||||
* that this may eliminate the need to create an entire local copy of the
|
||||
* library, in order to extend the functionality, in most circumstances.
|
||||
* \endparblock
|
||||
*/
|
||||
class Arduboy2Audio
|
||||
{
|
||||
friend class Arduboy2Ex;
|
||||
|
||||
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.
|
||||
*/
|
||||
static void 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() toggle() saveOnOff()
|
||||
*/
|
||||
static void 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() toggle() saveOnOff()
|
||||
*/
|
||||
static void off();
|
||||
|
||||
/** \brief
|
||||
* Toggle the sound on/off state.
|
||||
*
|
||||
* \details
|
||||
* If the system is configured for sound on, it will be changed to sound off
|
||||
* (mute). If sound is off, it will be changed to on. This function sets
|
||||
* the sound mode only until the unit is powered off. To save the current
|
||||
* mode use `saveOnOff()`.
|
||||
*
|
||||
* \see on() off() saveOnOff()
|
||||
*/
|
||||
static void toggle();
|
||||
|
||||
/** \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() toggle()
|
||||
*/
|
||||
static void 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() toggle()
|
||||
*/
|
||||
static bool enabled();
|
||||
|
||||
protected:
|
||||
static bool audio_enabled;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
/**
|
||||
* @file Arduboy2Beep.cpp
|
||||
* \brief
|
||||
* Classes to generate simple square wave tones on the Arduboy speaker pins.
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "Arduboy2Beep.h"
|
||||
|
||||
#ifndef AB_DEVKIT
|
||||
|
||||
// Speaker pin 1, Timer 3A, Port C bit 6, Arduino pin 5
|
||||
|
||||
uint8_t BeepPin1::duration = 0;
|
||||
|
||||
void BeepPin1::begin()
|
||||
{
|
||||
TCCR3A = 0;
|
||||
TCCR3B = (bit(WGM32) | bit(CS31)); // CTC mode. Divide by 8 clock prescale
|
||||
}
|
||||
|
||||
void BeepPin1::tone(uint16_t count)
|
||||
{
|
||||
tone(count, 0);
|
||||
}
|
||||
|
||||
void BeepPin1::tone(uint16_t count, uint8_t dur)
|
||||
{
|
||||
duration = dur;
|
||||
TCCR3A = bit(COM3A0); // set toggle on compare mode (which connects the pin)
|
||||
OCR3A = count; // load the count (16 bits), which determines the frequency
|
||||
}
|
||||
|
||||
void BeepPin1::timer()
|
||||
{
|
||||
if (duration && (--duration == 0)) {
|
||||
TCCR3A = 0; // set normal mode (which disconnects the pin)
|
||||
}
|
||||
}
|
||||
|
||||
void BeepPin1::noTone()
|
||||
{
|
||||
duration = 0;
|
||||
TCCR3A = 0; // set normal mode (which disconnects the pin)
|
||||
}
|
||||
|
||||
|
||||
// Speaker pin 2, Timer 4A, Port C bit 7, Arduino pin 13
|
||||
|
||||
uint8_t BeepPin2::duration = 0;
|
||||
|
||||
void BeepPin2::begin()
|
||||
{
|
||||
TCCR4A = 0; // normal mode. Disable PWM
|
||||
TCCR4B = bit(CS43); // divide by 128 clock prescale
|
||||
TCCR4D = 0; // normal mode
|
||||
TC4H = 0; // toggle pin at count = 0
|
||||
OCR4A = 0; // "
|
||||
}
|
||||
|
||||
void BeepPin2::tone(uint16_t count)
|
||||
{
|
||||
tone(count, 0);
|
||||
}
|
||||
|
||||
void BeepPin2::tone(uint16_t count, uint8_t dur)
|
||||
{
|
||||
duration = dur;
|
||||
TCCR4A = bit(COM4A0); // set toggle on compare mode (which connects the pin)
|
||||
TC4H = highByte(count); // load the count (10 bits),
|
||||
OCR4C = lowByte(count); // which determines the frequency
|
||||
}
|
||||
|
||||
void BeepPin2::timer()
|
||||
{
|
||||
if (duration && (--duration == 0)) {
|
||||
TCCR4A = 0; // set normal mode (which disconnects the pin)
|
||||
}
|
||||
}
|
||||
|
||||
void BeepPin2::noTone()
|
||||
{
|
||||
duration = 0;
|
||||
TCCR4A = 0; // set normal mode (which disconnects the pin)
|
||||
}
|
||||
|
||||
|
||||
#else /* AB_DEVKIT */
|
||||
|
||||
// *** The pins used for the speaker on the DevKit cannot be directly
|
||||
// controlled by a timer/counter. The following "dummy" functions will
|
||||
// compile and operate properly but no sound will be produced
|
||||
|
||||
uint8_t BeepPin1::duration = 0;
|
||||
|
||||
void BeepPin1::begin()
|
||||
{
|
||||
}
|
||||
|
||||
void BeepPin1::tone(uint16_t count)
|
||||
{
|
||||
tone(count, 0);
|
||||
}
|
||||
|
||||
void BeepPin1::tone(uint16_t count, uint8_t dur)
|
||||
{
|
||||
(void) count; // parameter not used
|
||||
|
||||
duration = dur;
|
||||
}
|
||||
|
||||
void BeepPin1::timer()
|
||||
{
|
||||
if (duration) {
|
||||
--duration;
|
||||
}
|
||||
}
|
||||
|
||||
void BeepPin1::noTone()
|
||||
{
|
||||
duration = 0;
|
||||
}
|
||||
|
||||
|
||||
uint8_t BeepPin2::duration = 0;
|
||||
|
||||
void BeepPin2::begin()
|
||||
{
|
||||
}
|
||||
|
||||
void BeepPin2::tone(uint16_t count)
|
||||
{
|
||||
tone(count, 0);
|
||||
}
|
||||
|
||||
void BeepPin2::tone(uint16_t count, uint8_t dur)
|
||||
{
|
||||
(void) count; // parameter not used
|
||||
|
||||
duration = dur;
|
||||
}
|
||||
|
||||
void BeepPin2::timer()
|
||||
{
|
||||
if (duration) {
|
||||
--duration;
|
||||
}
|
||||
}
|
||||
|
||||
void BeepPin2::noTone()
|
||||
{
|
||||
duration = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,362 @@
|
|||
/**
|
||||
* @file Arduboy2Beep.h
|
||||
* \brief
|
||||
* Classes to generate simple square wave tones on the Arduboy speaker pins.
|
||||
*/
|
||||
|
||||
#ifndef ARDUBOY2_BEEP_H
|
||||
#define ARDUBOY2_BEEP_H
|
||||
|
||||
/** \brief
|
||||
* Play simple square wave tones using speaker pin 1.
|
||||
*
|
||||
* \note
|
||||
* Class `BeepPin2` provides identical functions for playing tones on speaker
|
||||
* pin 2. Both classes can be used in the same sketch to allow playing
|
||||
* two tones at the same time. To do this, the `begin()` and `timer()`
|
||||
* functions of both classes must be used.
|
||||
*
|
||||
* \details
|
||||
* This class can be used to play square wave tones on speaker pin 1.
|
||||
* The functions are designed to produce very small and efficient code.
|
||||
*
|
||||
* A tone can be set to play for a given duration, or continuously until
|
||||
* stopped or replaced by a new tone. No interrupts are used. A tone is
|
||||
* generated by a hardware timer/counter directly toggling the pin,
|
||||
* so once started, no CPU cycles are used to actually play the tone.
|
||||
* The program continues to run while a tone is playing. However, a small
|
||||
* amount of code is required to time and stop a tone after a given duration.
|
||||
*
|
||||
* Tone frequencies can range from 15.26Hz to 1000000Hz.
|
||||
*
|
||||
* Although there's no specific code to handle mute control, the
|
||||
* `Arduboy2Audio` class will work since it has code to mute sound by setting
|
||||
* the speaker pins to input mode and unmute by setting the pins as outputs.
|
||||
* The `BeepPin1` class doesn't interfere with this operation.
|
||||
*
|
||||
* In order to avoid needing to use interrupts, the duration of tones is timed
|
||||
* by calling the `timer()` function continuously at a fixed interval.
|
||||
* The duration of a tone is given by specifying the number of times `timer()`
|
||||
* will be called before stopping the tone.
|
||||
*
|
||||
* For sketches that use `Arduboy2::nextFrame()`, or some other method to
|
||||
* generate frames at a fixed rate, `timer()` can be called once per frame.
|
||||
* Tone durations will then be given as the number of frames to play the tone
|
||||
* for. For example, with a rate of 60 frames per second a duration of 30
|
||||
* would be used to play a tone for half a second.
|
||||
*
|
||||
* The variable named #duration is the counter that times the duration of a
|
||||
* tone. A sketch can determine if a tone is currently playing by testing if
|
||||
* the #duration variable is non-zero (assuming it's a timed tone, not a
|
||||
* continuous tone).
|
||||
*
|
||||
* To keep the code small and efficient, the frequency of a tone is specified
|
||||
* by the actual count value to be loaded into to timer/counter peripheral.
|
||||
* The frequency will be determined by the count provided and the clock rate
|
||||
* of the timer/counter. In order to allow a tone's frequency to be specified
|
||||
* in hertz (cycles per second) the `freq()` helper function is provided,
|
||||
* which converts a given frequency to the required count value.
|
||||
*
|
||||
* NOTE that it is intended that `freq()` only be called with constant values.
|
||||
* If `freq()` is called with a variable, code to perform floating point math
|
||||
* will be included in the sketch, which will likely greatly increase the
|
||||
* sketch's code size unless the sketch also uses floating point math for
|
||||
* other purposes.
|
||||
*
|
||||
* The formulas for frequency/count conversion are:
|
||||
*
|
||||
* count=(1000000/frequency)-1
|
||||
* frequency=1000000/(count+1)
|
||||
*
|
||||
* Counts must be between 0 and 65535.
|
||||
*
|
||||
* All members of the class are static, so it's not necessary to create an
|
||||
* instance of the class in order to use it. However, creating an instance
|
||||
* doesn't produce any more code and it may make the source code smaller and
|
||||
* make it easier to switch to the `BeepPin2` class if it becomes necessary.
|
||||
*
|
||||
* The following is a basic example sketch, which will generate a tone when
|
||||
* a button is pressed.
|
||||
*
|
||||
* \code{.cpp}
|
||||
* #include <Arduboy2.h>
|
||||
* // There's no need to #include <Arduboy2Beep.h>
|
||||
* // It will be included in Arduboy2.h
|
||||
*
|
||||
* Arduboy2 arduboy;
|
||||
* BeepPin1 beep; // class instance for speaker pin 1
|
||||
*
|
||||
* void setup() {
|
||||
* arduboy.begin();
|
||||
* arduboy.setFrameRate(50);
|
||||
* beep.begin(); // set up the hardware for playing tones
|
||||
* }
|
||||
*
|
||||
* void loop() {
|
||||
* if (!arduboy.nextFrame()) {
|
||||
* return;
|
||||
* }
|
||||
*
|
||||
* beep.timer(); // handle tone duration
|
||||
*
|
||||
* arduboy.pollButtons();
|
||||
*
|
||||
* if (arduboy.justPressed(A_BUTTON)) {
|
||||
* // play a 1000Hz tone for 100 frames (2 seconds at 50 FPS)
|
||||
* // beep.freq(1000) is used to convert 1000Hz to the required count
|
||||
* beep.tone(beep.freq(1000), 100);
|
||||
* }
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* \note
|
||||
* These functions, and the equivalents in class `BeepPin2`, will not work with
|
||||
* a DevKit Arduboy because the speaker pins used cannot be directly controlled
|
||||
* by a timer/counter. "Dummy" functions are provided so a sketch will compile
|
||||
* and work properly but no sound will be produced.
|
||||
*
|
||||
* \see BeepPin2
|
||||
*/
|
||||
class BeepPin1
|
||||
{
|
||||
public:
|
||||
|
||||
/** \brief
|
||||
* The counter used by the `timer()` function to time the duration of a tone.
|
||||
*
|
||||
* \details
|
||||
* This variable is set by the `dur` parameter of the `tone()` function.
|
||||
* It is then decremented each time the `timer()` function is called, if its
|
||||
* value isn't 0. When `timer()` decrements it to 0, a tone that is playing
|
||||
* will be stopped.
|
||||
*
|
||||
* A sketch can determine if a tone is currently playing by testing if
|
||||
* this variable is non-zero (assuming it's a timed tone, not a continuous
|
||||
* tone).
|
||||
*
|
||||
* Example:
|
||||
* \code{.cpp}
|
||||
* beep.tone(beep.freq(1000), 15);
|
||||
* while (beep.duration != 0) { } // wait for the tone to stop playing
|
||||
* \endcode
|
||||
*
|
||||
* It can also be manipulated directly by the sketch, although this should
|
||||
* seldom be necessary.
|
||||
*/
|
||||
static uint8_t duration;
|
||||
|
||||
/** \brief
|
||||
* Set up the hardware.
|
||||
*
|
||||
* \details
|
||||
* Prepare the hardware for playing tones.
|
||||
* This function must be called (usually in `setup()`) before using any of
|
||||
* the other functions in this class.
|
||||
*/
|
||||
static void begin();
|
||||
|
||||
/** \brief
|
||||
* Play a tone continually, until replaced by a new tone or stopped.
|
||||
*
|
||||
* \param count The count to be loaded into the timer/counter to play
|
||||
* the desired frequency.
|
||||
*
|
||||
* \details
|
||||
* A tone is played indefinitely, until replaced by another tone or stopped
|
||||
* using `noTone()`.
|
||||
*
|
||||
* The tone's frequency is determined by the specified count, which is loaded
|
||||
* into the timer/counter that generates the tone. A desired frequency can be
|
||||
* converted into the required count value using the `freq()` function.
|
||||
*
|
||||
* \see freq() timer() noTone()
|
||||
*/
|
||||
static void tone(uint16_t count);
|
||||
|
||||
/** \brief
|
||||
* Play a tone for a given duration.
|
||||
*
|
||||
* \param count The count to be loaded into the timer/counter to play
|
||||
* the desired frequency.
|
||||
* \param dur The duration of the tone, used by `timer()`.
|
||||
*
|
||||
* \details
|
||||
* A tone is played for the specified duration, or until replaced by another
|
||||
* tone or stopped using `noTone()`.
|
||||
*
|
||||
* The tone's frequency is determined by the specified count, which is loaded
|
||||
* into the timer/counter that generates the tone. A desired frequency can be
|
||||
* converted into the required count value using the `freq()` function.
|
||||
*
|
||||
* The duration value is the number of times the `timer()` function must be
|
||||
* called before the tone is stopped.
|
||||
*
|
||||
* \see freq() timer() noTone()
|
||||
*/
|
||||
static void tone(uint16_t count, uint8_t dur);
|
||||
|
||||
/** \brief
|
||||
* Handle the duration that a tone plays for.
|
||||
*
|
||||
* \details
|
||||
* This function must be called at a constant interval, which would normally
|
||||
* be once per frame, in order to stop a tone after the desired tone duration
|
||||
* has elapsed.
|
||||
*
|
||||
* If the value of the `duration` variable is not 0, it will be decremented.
|
||||
* When the `duration` variable is decremented to 0, a playing tone will be
|
||||
* stopped.
|
||||
*/
|
||||
static void timer();
|
||||
|
||||
/** \brief
|
||||
* Stop a tone that is playing.
|
||||
*
|
||||
* \details
|
||||
* If a tone is playing it will be stopped. It's safe to call this function
|
||||
* even if a tone isn't currently playing.
|
||||
*
|
||||
* \see tone()
|
||||
*/
|
||||
static void noTone();
|
||||
|
||||
/** \brief
|
||||
* Convert a frequency to the required count.
|
||||
*
|
||||
* \param hz The frequency, in hertz (cycles per second), to be converted
|
||||
* to a count.
|
||||
*
|
||||
* \return The required count to be loaded into the timer/counter for the
|
||||
* given frequency.
|
||||
*
|
||||
* \details
|
||||
* This helper function will convert a desired tone frequency to the closest
|
||||
* value required by the `tone()` function's `count` parameter.
|
||||
* The calculated count is rounded up or down to the nearest integer,
|
||||
* if necessary.
|
||||
*
|
||||
* Example:
|
||||
* \code{.cpp}
|
||||
* beep.tone(beep.freq(440)); // play a 440Hz tone until stopped or replaced
|
||||
* \endcode
|
||||
*
|
||||
* \note
|
||||
* It is intended that `freq()` only be called with constant values.
|
||||
* If `freq()` is called with a variable, code to perform floating point math
|
||||
* will be included in the sketch, which will likely greatly increase the
|
||||
* sketch's code size unless the sketch also uses floating point math for
|
||||
* other purposes.
|
||||
*/
|
||||
static constexpr uint16_t freq(const float hz)
|
||||
{
|
||||
return (uint16_t) (((F_CPU / 8 / 2) + (hz / 2)) / hz) - 1;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** \brief
|
||||
* Play simple square wave tones using speaker pin 2.
|
||||
*
|
||||
* \details
|
||||
* This class contains the same functions as class `BeepPin1` except they use
|
||||
* speaker pin 2 instead of speaker pin 1.
|
||||
*
|
||||
* Using `BeepPin1` is more desirable, as it uses a 16 bit Timer, which can
|
||||
* produce a greater frequency range and resolution than the 10 bit Timer
|
||||
* used by `BeepPin2`. However, if the sketch also includes other sound
|
||||
* generating code that uses speaker pin 1, `BeepPin2` can be used to avoid
|
||||
* conflict.
|
||||
*
|
||||
* Tone frequencies on speaker pin 2 can range from 61.04Hz to 15625Hz using
|
||||
* allowed counts from 3 to 1023.
|
||||
*
|
||||
* The formulas for frequency/count conversion are:
|
||||
*
|
||||
* count=(62500/frequency)-1
|
||||
* frequency=62500/(count+1)
|
||||
*
|
||||
* See the documentation for `BeepPin1` for more details.
|
||||
*
|
||||
* \see BeepPin1
|
||||
*/
|
||||
class BeepPin2
|
||||
{
|
||||
public:
|
||||
|
||||
/** \brief
|
||||
* The counter used by the `timer()` function to time the duration of a tone
|
||||
* played on speaker pin 2.
|
||||
*
|
||||
* \details
|
||||
* For details see `BeepPin1::duration`.
|
||||
*/
|
||||
static uint8_t duration;
|
||||
|
||||
/** \brief
|
||||
* Set up the hardware for playing tones using speaker pin 2.
|
||||
*
|
||||
* \details
|
||||
* For details see `BeepPin1::begin()`.
|
||||
*/
|
||||
static void begin();
|
||||
|
||||
/** \brief
|
||||
* Play a tone on speaker pin 2 continually, until replaced by a new tone
|
||||
* or stopped.
|
||||
*
|
||||
* \param count The count to be loaded into the timer/counter to play
|
||||
* the desired frequency.
|
||||
*
|
||||
* \details
|
||||
* For details see `BeepPin1::tone(uint16_t)`.
|
||||
*/
|
||||
static void tone(uint16_t count);
|
||||
|
||||
/** \brief
|
||||
* Play a tone on speaker pin 2 for a given duration.
|
||||
*
|
||||
* \param count The count to be loaded into the timer/counter to play
|
||||
* the desired frequency.
|
||||
* \param dur The duration of the tone, used by `timer()`.
|
||||
*
|
||||
* \details
|
||||
* For details see `BeepPin1::tone(uint16_t, uint8_t)`.
|
||||
*/
|
||||
static void tone(uint16_t count, uint8_t dur);
|
||||
|
||||
/** \brief
|
||||
* Handle the duration that a tone on speaker pin 2 plays for.
|
||||
*
|
||||
* \details
|
||||
* For details see `BeepPin1::timer()`.
|
||||
*/
|
||||
static void timer();
|
||||
|
||||
/** \brief
|
||||
* Stop a tone that is playing on speaker pin 2.
|
||||
*
|
||||
* \details
|
||||
* For details see `BeepPin1::noTone()`.
|
||||
*/
|
||||
static void noTone();
|
||||
|
||||
/** \brief
|
||||
* Convert a frequency to the required count for speaker pin 2.
|
||||
*
|
||||
* \param hz The frequency, in hertz (cycles per second), to be converted
|
||||
* to a count.
|
||||
*
|
||||
* \return The required count to be loaded into the timer/counter for the
|
||||
* given frequency.
|
||||
*
|
||||
* \details
|
||||
* For details see `BeepPin1::freq()`.
|
||||
*/
|
||||
static constexpr uint16_t freq(const float hz)
|
||||
{
|
||||
return (uint16_t) (((F_CPU / 128 / 2) + (hz / 2)) / hz) - 1;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,660 @@
|
|||
/**
|
||||
* @file Arduboy2Core.cpp
|
||||
* \brief
|
||||
* The Arduboy2Core class for Arduboy hardware initilization and control.
|
||||
*/
|
||||
|
||||
#include "Arduboy2Core.h"
|
||||
|
||||
#include <avr/wdt.h>
|
||||
|
||||
|
||||
//========================================
|
||||
//========== class Arduboy2Core ==========
|
||||
//========================================
|
||||
|
||||
// Commands sent to the OLED display to initialize it
|
||||
const PROGMEM uint8_t Arduboy2Core::lcdBootProgram[] = {
|
||||
// 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
|
||||
//
|
||||
// Display Off
|
||||
// 0xAE,
|
||||
|
||||
// Set Display Clock Divisor v = 0xF0
|
||||
// default is 0x80
|
||||
0xD5, 0xF0,
|
||||
|
||||
// Set Multiplex Ratio v = 0x3F
|
||||
// 0xA8, 0x3F,
|
||||
|
||||
// Set Display Offset v = 0
|
||||
// 0xD3, 0x00,
|
||||
|
||||
// Set Start Line (0)
|
||||
// 0x40,
|
||||
|
||||
// Charge Pump Setting v = enable (0x14)
|
||||
// default is disabled
|
||||
0x8D, 0x14,
|
||||
|
||||
// Set Segment Re-map (A0) | (b0001)
|
||||
// default is (b0000)
|
||||
0xA1,
|
||||
|
||||
// Set COM Output Scan Direction
|
||||
0xC8,
|
||||
|
||||
// Set COM Pins v
|
||||
// 0xDA, 0x12,
|
||||
|
||||
// Set Contrast v = 0xCF
|
||||
0x81, 0xCF,
|
||||
|
||||
// Set Precharge = 0xF1
|
||||
0xD9, 0xF1,
|
||||
|
||||
// Set VCom Detect
|
||||
// 0xDB, 0x40,
|
||||
|
||||
// Entire Display ON
|
||||
// 0xA4,
|
||||
|
||||
// Set normal/inverse display
|
||||
// 0xA6,
|
||||
|
||||
// Display On
|
||||
0xAF,
|
||||
|
||||
// set display mode = horizontal addressing mode (0x00)
|
||||
0x20, 0x00,
|
||||
|
||||
// set col address range
|
||||
// 0x21, 0x00, COLUMN_ADDRESS_END,
|
||||
|
||||
// set page address range
|
||||
// 0x22, 0x00, PAGE_ADDRESS_END
|
||||
};
|
||||
|
||||
void Arduboy2Core::boot()
|
||||
{
|
||||
#ifdef ARDUBOY_SET_CPU_8MHZ
|
||||
// ARDUBOY_SET_CPU_8MHZ will be set by the IDE using boards.txt
|
||||
setCPUSpeed8MHz();
|
||||
#endif
|
||||
|
||||
// Select the ADC input here so a delay isn't required in generateRandomSeed()
|
||||
ADMUX = RAND_SEED_IN_ADMUX;
|
||||
|
||||
bootPins();
|
||||
bootSPI();
|
||||
bootOLED();
|
||||
bootPowerSaving();
|
||||
}
|
||||
|
||||
#ifdef ARDUBOY_SET_CPU_8MHZ
|
||||
// If we're compiling for 8MHz we need to slow the CPU down because the
|
||||
// hardware clock on the Arduboy is 16MHz.
|
||||
// We also need to readjust the PLL prescaler because the Arduino USB code
|
||||
// likely will have incorrectly set it for an 8MHz hardware clock.
|
||||
void Arduboy2Core::setCPUSpeed8MHz()
|
||||
{
|
||||
uint8_t oldSREG = SREG;
|
||||
cli(); // suspend interrupts
|
||||
PLLCSR = _BV(PINDIV); // dissable the PLL and set prescale for 16MHz)
|
||||
CLKPR = _BV(CLKPCE); // allow reprogramming clock
|
||||
CLKPR = 1; // set clock divisor to 2 (0b0001)
|
||||
PLLCSR = _BV(PLLE) | _BV(PINDIV); // enable the PLL (with 16MHz prescale)
|
||||
SREG = oldSREG; // restore interrupts
|
||||
}
|
||||
#endif
|
||||
|
||||
// Pins are set to the proper modes and levels for the specific hardware.
|
||||
// This routine must be modified if any pins are moved to a different port
|
||||
void Arduboy2Core::bootPins()
|
||||
{
|
||||
#ifdef ARDUBOY_10
|
||||
|
||||
// Port B INPUT_PULLUP or HIGH
|
||||
PORTB |= _BV(RED_LED_BIT) | _BV(GREEN_LED_BIT) | _BV(BLUE_LED_BIT) |
|
||||
_BV(B_BUTTON_BIT);
|
||||
// Port B INPUT or LOW (none)
|
||||
// Port B inputs
|
||||
DDRB &= ~(_BV(B_BUTTON_BIT) | _BV(SPI_MISO_BIT));
|
||||
// Port B outputs
|
||||
DDRB |= _BV(RED_LED_BIT) | _BV(GREEN_LED_BIT) | _BV(BLUE_LED_BIT) |
|
||||
_BV(SPI_MOSI_BIT) | _BV(SPI_SCK_BIT) | _BV(SPI_SS_BIT);
|
||||
|
||||
// Port C
|
||||
// Speaker: Not set here. Controlled by audio class
|
||||
|
||||
// Port D INPUT_PULLUP or HIGH
|
||||
PORTD |= _BV(CS_BIT);
|
||||
// Port D INPUT or LOW
|
||||
PORTD &= ~(_BV(RST_BIT));
|
||||
// Port D inputs (none)
|
||||
// Port D outputs
|
||||
DDRD |= _BV(RST_BIT) | _BV(CS_BIT) | _BV(DC_BIT);
|
||||
|
||||
// Port E INPUT_PULLUP or HIGH
|
||||
PORTE |= _BV(A_BUTTON_BIT);
|
||||
// Port E INPUT or LOW (none)
|
||||
// Port E inputs
|
||||
DDRE &= ~(_BV(A_BUTTON_BIT));
|
||||
// Port E outputs (none)
|
||||
|
||||
// Port F INPUT_PULLUP or HIGH
|
||||
PORTF |= _BV(LEFT_BUTTON_BIT) | _BV(RIGHT_BUTTON_BIT) |
|
||||
_BV(UP_BUTTON_BIT) | _BV(DOWN_BUTTON_BIT);
|
||||
// Port F INPUT or LOW
|
||||
PORTF &= ~(_BV(RAND_SEED_IN_BIT));
|
||||
// Port F inputs
|
||||
DDRF &= ~(_BV(LEFT_BUTTON_BIT) | _BV(RIGHT_BUTTON_BIT) |
|
||||
_BV(UP_BUTTON_BIT) | _BV(DOWN_BUTTON_BIT) |
|
||||
_BV(RAND_SEED_IN_BIT));
|
||||
// Port F outputs (none)
|
||||
|
||||
#elif defined(AB_DEVKIT)
|
||||
|
||||
// Port B INPUT_PULLUP or HIGH
|
||||
PORTB |= _BV(LEFT_BUTTON_BIT) | _BV(UP_BUTTON_BIT) | _BV(DOWN_BUTTON_BIT) |
|
||||
_BV(BLUE_LED_BIT);
|
||||
// Port B INPUT or LOW (none)
|
||||
// Port B inputs
|
||||
DDRB &= ~(_BV(LEFT_BUTTON_BIT) | _BV(UP_BUTTON_BIT) | _BV(DOWN_BUTTON_BIT) |
|
||||
_BV(SPI_MISO_BIT));
|
||||
// Port B outputs
|
||||
DDRB |= _BV(SPI_MOSI_BIT) | _BV(SPI_SCK_BIT) | _BV(SPI_SS_BIT) |
|
||||
_BV(BLUE_LED_BIT);
|
||||
|
||||
// Port C INPUT_PULLUP or HIGH
|
||||
PORTC |= _BV(RIGHT_BUTTON_BIT);
|
||||
// Port C INPUT or LOW (none)
|
||||
// Port C inputs
|
||||
DDRC &= ~(_BV(RIGHT_BUTTON_BIT));
|
||||
// Port C outputs (none)
|
||||
|
||||
// Port D INPUT_PULLUP or HIGH
|
||||
PORTD |= _BV(CS_BIT);
|
||||
// Port D INPUT or LOW
|
||||
PORTD &= ~(_BV(RST_BIT));
|
||||
// Port D inputs (none)
|
||||
// Port D outputs
|
||||
DDRD |= _BV(RST_BIT) | _BV(CS_BIT) | _BV(DC_BIT);
|
||||
|
||||
// Port E (none)
|
||||
|
||||
// Port F INPUT_PULLUP or HIGH
|
||||
PORTF |= _BV(A_BUTTON_BIT) | _BV(B_BUTTON_BIT);
|
||||
// Port F INPUT or LOW
|
||||
PORTF &= ~(_BV(RAND_SEED_IN_BIT));
|
||||
// Port F inputs
|
||||
DDRF &= ~(_BV(A_BUTTON_BIT) | _BV(B_BUTTON_BIT) | _BV(RAND_SEED_IN_BIT));
|
||||
// Port F outputs (none)
|
||||
// Speaker: Not set here. Controlled by audio class
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void Arduboy2Core::bootOLED()
|
||||
{
|
||||
// reset the display
|
||||
delayShort(5); // reset pin should be low here. let it stay low a while
|
||||
bitSet(RST_PORT, RST_BIT); // set high to come out of reset
|
||||
delayShort(5); // wait a while
|
||||
|
||||
// select the display (permanently, since nothing else is using SPI)
|
||||
bitClear(CS_PORT, CS_BIT);
|
||||
|
||||
// run our customized boot-up command sequence against the
|
||||
// OLED to initialize it properly for Arduboy
|
||||
LCDCommandMode();
|
||||
for (uint8_t i = 0; i < sizeof(lcdBootProgram); i++) {
|
||||
SPItransfer(pgm_read_byte(lcdBootProgram + i));
|
||||
}
|
||||
LCDDataMode();
|
||||
}
|
||||
|
||||
void Arduboy2Core::LCDDataMode()
|
||||
{
|
||||
bitSet(DC_PORT, DC_BIT);
|
||||
}
|
||||
|
||||
void Arduboy2Core::LCDCommandMode()
|
||||
{
|
||||
bitClear(DC_PORT, DC_BIT);
|
||||
}
|
||||
|
||||
// Initialize the SPI interface for the display
|
||||
void Arduboy2Core::bootSPI()
|
||||
{
|
||||
// master, mode 0, MSB first, CPU clock / 2 (8MHz)
|
||||
SPCR = _BV(SPE) | _BV(MSTR);
|
||||
SPSR = _BV(SPI2X);
|
||||
}
|
||||
|
||||
// Write to the SPI bus (MOSI pin)
|
||||
void Arduboy2Core::SPItransfer(uint8_t data)
|
||||
{
|
||||
SPDR = data;
|
||||
/*
|
||||
* The following NOP introduces a small delay that can prevent the wait
|
||||
* loop from iterating when running at the maximum speed. This gives
|
||||
* about 10% more speed, even if it seems counter-intuitive. At lower
|
||||
* speeds it is unnoticed.
|
||||
*/
|
||||
asm volatile("nop");
|
||||
while (!(SPSR & _BV(SPIF))) { } // wait
|
||||
}
|
||||
|
||||
// Write to and read from the SPI bus (out to MOSI pin, in from MISO pin)
|
||||
uint8_t Arduboy2Core::SPItransferAndRead(uint8_t data)
|
||||
{
|
||||
SPItransfer(data);
|
||||
return SPDR;
|
||||
}
|
||||
|
||||
void Arduboy2Core::safeMode()
|
||||
{
|
||||
if (buttonsState() == UP_BUTTON)
|
||||
{
|
||||
digitalWriteRGB(RED_LED, RGB_ON);
|
||||
|
||||
#ifndef ARDUBOY_CORE // for Arduboy core timer 0 should remain enabled
|
||||
// prevent the bootloader magic number from being overwritten by timer 0
|
||||
// when a timer variable overlaps the magic number location
|
||||
power_timer0_disable();
|
||||
#endif
|
||||
|
||||
while (true) { }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Power Management */
|
||||
|
||||
void Arduboy2Core::idle()
|
||||
{
|
||||
SMCR = _BV(SE); // select idle mode and enable sleeping
|
||||
sleep_cpu();
|
||||
SMCR = 0; // disable sleeping
|
||||
}
|
||||
|
||||
void Arduboy2Core::bootPowerSaving()
|
||||
{
|
||||
// disable Two Wire Interface (I2C) and the ADC
|
||||
// All other bits will be written with 0 so will be enabled
|
||||
PRR0 = _BV(PRTWI) | _BV(PRADC);
|
||||
// disable USART1
|
||||
PRR1 |= _BV(PRUSART1);
|
||||
}
|
||||
|
||||
// Shut down the display
|
||||
void Arduboy2Core::displayOff()
|
||||
{
|
||||
LCDCommandMode();
|
||||
SPItransfer(0xAE); // display off
|
||||
SPItransfer(0x8D); // charge pump:
|
||||
SPItransfer(0x10); // disable
|
||||
delayShort(250);
|
||||
bitClear(RST_PORT, RST_BIT); // set display reset pin low (reset state)
|
||||
}
|
||||
|
||||
// Restart the display after a displayOff()
|
||||
void Arduboy2Core::displayOn()
|
||||
{
|
||||
bootOLED();
|
||||
}
|
||||
|
||||
|
||||
/* Drawing */
|
||||
|
||||
void Arduboy2Core::paint8Pixels(uint8_t pixels)
|
||||
{
|
||||
SPItransfer(pixels);
|
||||
}
|
||||
|
||||
void Arduboy2Core::paintScreen(const uint8_t *image)
|
||||
{
|
||||
for (int i = 0; i < (HEIGHT*WIDTH)/8; i++)
|
||||
{
|
||||
SPItransfer(pgm_read_byte(image + i));
|
||||
}
|
||||
}
|
||||
|
||||
// paint from a memory buffer, this should be FAST as it's likely what
|
||||
// will be used by any buffer based subclass
|
||||
//
|
||||
// The following assembly code runs "open loop". It relies on instruction
|
||||
// execution times to allow time for each byte of data to be clocked out.
|
||||
// It is specifically tuned for a 16MHz CPU clock and SPI clocking at 8MHz.
|
||||
void Arduboy2Core::paintScreen(uint8_t image[], bool clear)
|
||||
{
|
||||
uint16_t count;
|
||||
|
||||
asm volatile (
|
||||
" ldi %A[count], %[len_lsb] \n\t" //for (len = WIDTH * HEIGHT / 8)
|
||||
" ldi %B[count], %[len_msb] \n\t"
|
||||
"1: ld __tmp_reg__, %a[ptr] ;2 \n\t" //tmp = *(image)
|
||||
" out %[spdr], __tmp_reg__ ;1 \n\t" //SPDR = tmp
|
||||
" cpse %[clear], __zero_reg__ ;1/2 \n\t" //if (clear) tmp = 0;
|
||||
" mov __tmp_reg__, __zero_reg__ ;1 \n\t"
|
||||
"2: sbiw %A[count], 1 ;2 \n\t" //len --
|
||||
" sbrc %A[count], 0 ;1/2 \n\t" //loop twice for cheap delay
|
||||
" rjmp 2b ;2 \n\t"
|
||||
" st %a[ptr]+, __tmp_reg__ ;2 \n\t" //*(image++) = tmp
|
||||
" brne 1b ;1/2 :18 \n\t" //len > 0
|
||||
" in __tmp_reg__, %[spsr] \n\t" //read SPSR to clear SPIF
|
||||
: [ptr] "+&e" (image),
|
||||
[count] "=&w" (count)
|
||||
: [spdr] "I" (_SFR_IO_ADDR(SPDR)),
|
||||
[spsr] "I" (_SFR_IO_ADDR(SPSR)),
|
||||
[len_msb] "M" (WIDTH * (HEIGHT / 8 * 2) >> 8), // 8: pixels per byte
|
||||
[len_lsb] "M" (WIDTH * (HEIGHT / 8 * 2) & 0xFF), // 2: for delay loop multiplier
|
||||
[clear] "r" (clear)
|
||||
);
|
||||
}
|
||||
#if 0
|
||||
// For reference, this is the "closed loop" C++ version of paintScreen()
|
||||
// used prior to the above version.
|
||||
void Arduboy2Core::paintScreen(uint8_t image[], bool clear)
|
||||
{
|
||||
uint8_t c;
|
||||
int i = 0;
|
||||
|
||||
if (clear)
|
||||
{
|
||||
SPDR = image[i]; // set the first SPI data byte to get things started
|
||||
image[i++] = 0; // clear the first image byte
|
||||
}
|
||||
else
|
||||
SPDR = image[i++];
|
||||
|
||||
// the code to iterate the loop and get the next byte from the buffer is
|
||||
// executed while the previous byte is being sent out by the SPI controller
|
||||
while (i < (HEIGHT * WIDTH) / 8)
|
||||
{
|
||||
// get the next byte. It's put in a local variable so it can be sent as
|
||||
// as soon as possible after the sending of the previous byte has completed
|
||||
if (clear)
|
||||
{
|
||||
c = image[i];
|
||||
// clear the byte in the image buffer
|
||||
image[i++] = 0;
|
||||
}
|
||||
else
|
||||
c = image[i++];
|
||||
|
||||
while (!(SPSR & _BV(SPIF))) { } // wait for the previous byte to be sent
|
||||
|
||||
// put the next byte in the SPI data register. The SPI controller will
|
||||
// clock it out while the loop continues and gets the next byte ready
|
||||
SPDR = c;
|
||||
}
|
||||
while (!(SPSR & _BV(SPIF))) { } // wait for the last byte to be sent
|
||||
}
|
||||
#endif
|
||||
|
||||
void Arduboy2Core::blank()
|
||||
{
|
||||
for (int i = 0; i < (HEIGHT*WIDTH)/8; i++)
|
||||
SPItransfer(0x00);
|
||||
}
|
||||
|
||||
void Arduboy2Core::sendLCDCommand(uint8_t command)
|
||||
{
|
||||
LCDCommandMode();
|
||||
SPItransfer(command);
|
||||
LCDDataMode();
|
||||
}
|
||||
|
||||
// invert the display or set to normal
|
||||
// when inverted, a pixel set to 0 will be on
|
||||
void Arduboy2Core::invert(bool inverse)
|
||||
{
|
||||
sendLCDCommand(inverse ? OLED_PIXELS_INVERTED : OLED_PIXELS_NORMAL);
|
||||
}
|
||||
|
||||
// turn all display pixels on, ignoring buffer contents
|
||||
// or set to normal buffer display
|
||||
void Arduboy2Core::allPixelsOn(bool on)
|
||||
{
|
||||
sendLCDCommand(on ? OLED_ALL_PIXELS_ON : OLED_PIXELS_FROM_RAM);
|
||||
}
|
||||
|
||||
// flip the display vertically or set to normal
|
||||
void Arduboy2Core::flipVertical(bool flipped)
|
||||
{
|
||||
sendLCDCommand(flipped ? OLED_VERTICAL_FLIPPED : OLED_VERTICAL_NORMAL);
|
||||
}
|
||||
|
||||
// flip the display horizontally or set to normal
|
||||
void Arduboy2Core::flipHorizontal(bool flipped)
|
||||
{
|
||||
sendLCDCommand(flipped ? OLED_HORIZ_FLIPPED : OLED_HORIZ_NORMAL);
|
||||
}
|
||||
|
||||
/* RGB LED */
|
||||
|
||||
void Arduboy2Core::setRGBled(uint8_t red, uint8_t green, uint8_t blue)
|
||||
{
|
||||
#ifdef ARDUBOY_10 // RGB, all the pretty colors
|
||||
// timer 0: Fast PWM, OC0A clear on compare / set at top
|
||||
// We must stay in Fast PWM mode because timer 0 is used for system timing.
|
||||
// We can't use "inverted" mode because it won't allow full shut off.
|
||||
TCCR0A = _BV(COM0A1) | _BV(WGM01) | _BV(WGM00);
|
||||
OCR0A = 255 - green;
|
||||
// timer 1: Phase correct PWM 8 bit
|
||||
// OC1A and OC1B set on up-counting / clear on down-counting (inverted). This
|
||||
// allows the value to be directly loaded into the OCR with common anode LED.
|
||||
TCCR1A = _BV(COM1A1) | _BV(COM1A0) | _BV(COM1B1) | _BV(COM1B0) | _BV(WGM10);
|
||||
OCR1AL = blue;
|
||||
OCR1BL = red;
|
||||
#elif defined(AB_DEVKIT)
|
||||
// only blue on DevKit, which is not PWM capable
|
||||
(void)red; // parameter unused
|
||||
(void)green; // parameter unused
|
||||
bitWrite(BLUE_LED_PORT, BLUE_LED_BIT, blue ? RGB_ON : RGB_OFF);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Arduboy2Core::setRGBled(uint8_t color, uint8_t val)
|
||||
{
|
||||
#ifdef ARDUBOY_10
|
||||
if (color == RED_LED)
|
||||
{
|
||||
OCR1BL = val;
|
||||
}
|
||||
else if (color == GREEN_LED)
|
||||
{
|
||||
OCR0A = 255 - val;
|
||||
}
|
||||
else if (color == BLUE_LED)
|
||||
{
|
||||
OCR1AL = val;
|
||||
}
|
||||
#elif defined(AB_DEVKIT)
|
||||
// only blue on DevKit, which is not PWM capable
|
||||
if (color == BLUE_LED)
|
||||
{
|
||||
bitWrite(BLUE_LED_PORT, BLUE_LED_BIT, val ? RGB_ON : RGB_OFF);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Arduboy2Core::freeRGBled()
|
||||
{
|
||||
#ifdef ARDUBOY_10
|
||||
// clear the COM bits to return the pins to normal I/O mode
|
||||
TCCR0A = _BV(WGM01) | _BV(WGM00);
|
||||
TCCR1A = _BV(WGM10);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Arduboy2Core::digitalWriteRGB(uint8_t red, uint8_t green, uint8_t blue)
|
||||
{
|
||||
#ifdef ARDUBOY_10
|
||||
bitWrite(RED_LED_PORT, RED_LED_BIT, red);
|
||||
bitWrite(GREEN_LED_PORT, GREEN_LED_BIT, green);
|
||||
bitWrite(BLUE_LED_PORT, BLUE_LED_BIT, blue);
|
||||
#elif defined(AB_DEVKIT)
|
||||
// only blue on DevKit
|
||||
(void)red; // parameter unused
|
||||
(void)green; // parameter unused
|
||||
bitWrite(BLUE_LED_PORT, BLUE_LED_BIT, blue);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Arduboy2Core::digitalWriteRGB(uint8_t color, uint8_t val)
|
||||
{
|
||||
#ifdef ARDUBOY_10
|
||||
if (color == RED_LED)
|
||||
{
|
||||
bitWrite(RED_LED_PORT, RED_LED_BIT, val);
|
||||
}
|
||||
else if (color == GREEN_LED)
|
||||
{
|
||||
bitWrite(GREEN_LED_PORT, GREEN_LED_BIT, val);
|
||||
}
|
||||
else if (color == BLUE_LED)
|
||||
{
|
||||
bitWrite(BLUE_LED_PORT, BLUE_LED_BIT, val);
|
||||
}
|
||||
#elif defined(AB_DEVKIT)
|
||||
// only blue on DevKit
|
||||
if (color == BLUE_LED)
|
||||
{
|
||||
bitWrite(BLUE_LED_PORT, BLUE_LED_BIT, val);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Buttons */
|
||||
|
||||
uint8_t Arduboy2Core::buttonsState()
|
||||
{
|
||||
uint8_t buttons;
|
||||
|
||||
#ifdef ARDUBOY_10
|
||||
// up, right, left, down
|
||||
buttons = ((~PINF) &
|
||||
(_BV(UP_BUTTON_BIT) | _BV(RIGHT_BUTTON_BIT) |
|
||||
_BV(LEFT_BUTTON_BIT) | _BV(DOWN_BUTTON_BIT)));
|
||||
// A
|
||||
if (bitRead(A_BUTTON_PORTIN, A_BUTTON_BIT) == 0) { buttons |= A_BUTTON; }
|
||||
// B
|
||||
if (bitRead(B_BUTTON_PORTIN, B_BUTTON_BIT) == 0) { buttons |= B_BUTTON; }
|
||||
#elif defined(AB_DEVKIT)
|
||||
// down, left, up
|
||||
buttons = ((~PINB) &
|
||||
(_BV(DOWN_BUTTON_BIT) | _BV(LEFT_BUTTON_BIT) | _BV(UP_BUTTON_BIT)));
|
||||
// right
|
||||
if (bitRead(RIGHT_BUTTON_PORTIN, RIGHT_BUTTON_BIT) == 0) { buttons |= RIGHT_BUTTON; }
|
||||
// A
|
||||
if (bitRead(A_BUTTON_PORTIN, A_BUTTON_BIT) == 0) { buttons |= A_BUTTON; }
|
||||
// B
|
||||
if (bitRead(B_BUTTON_PORTIN, B_BUTTON_BIT) == 0) { buttons |= B_BUTTON; }
|
||||
#endif
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
unsigned long Arduboy2Core::generateRandomSeed()
|
||||
{
|
||||
unsigned long seed;
|
||||
|
||||
power_adc_enable(); // ADC on
|
||||
|
||||
// do an ADC read from an unconnected input pin
|
||||
ADCSRA |= _BV(ADSC); // start conversion (ADMUX has been pre-set in boot())
|
||||
while (bit_is_set(ADCSRA, ADSC)) { } // wait for conversion complete
|
||||
|
||||
seed = ((unsigned long)ADC << 16) + micros();
|
||||
|
||||
power_adc_disable(); // ADC off
|
||||
|
||||
return seed;
|
||||
}
|
||||
|
||||
// delay in ms with 16 bit duration
|
||||
void Arduboy2Core::delayShort(uint16_t ms)
|
||||
{
|
||||
delay((unsigned long) ms);
|
||||
}
|
||||
|
||||
void Arduboy2Core::exitToBootloader()
|
||||
{
|
||||
cli();
|
||||
// set bootloader magic key
|
||||
// storing two uint8_t instead of one uint16_t saves an instruction
|
||||
// when high and low bytes of the magic key are the same
|
||||
*(uint8_t *)MAGIC_KEY_POS = lowByte(MAGIC_KEY);
|
||||
*(uint8_t *)(MAGIC_KEY_POS + 1) = highByte(MAGIC_KEY);
|
||||
// enable watchdog timer reset, with 16ms timeout
|
||||
wdt_reset();
|
||||
WDTCSR = (_BV(WDCE) | _BV(WDE));
|
||||
WDTCSR = _BV(WDE);
|
||||
while (true) { }
|
||||
}
|
||||
|
||||
|
||||
//=========================================
|
||||
//========== class Arduboy2NoUSB ==========
|
||||
//=========================================
|
||||
|
||||
void Arduboy2NoUSB::mainNoUSB()
|
||||
{
|
||||
// disable USB
|
||||
UDCON = _BV(DETACH);
|
||||
UDIEN = 0;
|
||||
UDINT = 0;
|
||||
USBCON = _BV(FRZCLK);
|
||||
UHWCON = 0;
|
||||
power_usb_disable();
|
||||
|
||||
init();
|
||||
|
||||
// This would normally be done in the USB code that uses the TX and RX LEDs
|
||||
TX_RX_LED_INIT;
|
||||
TXLED0;
|
||||
RXLED0;
|
||||
|
||||
// Set the DOWN button pin for INPUT_PULLUP
|
||||
bitSet(DOWN_BUTTON_PORT, DOWN_BUTTON_BIT);
|
||||
bitClear(DOWN_BUTTON_DDR, DOWN_BUTTON_BIT);
|
||||
|
||||
// Delay to give time for the pin to be pulled high if it was floating
|
||||
Arduboy2Core::delayShort(10);
|
||||
|
||||
// if the DOWN button is pressed
|
||||
if (bitRead(DOWN_BUTTON_PORTIN, DOWN_BUTTON_BIT) == 0) {
|
||||
Arduboy2Core::exitToBootloader();
|
||||
}
|
||||
|
||||
// The remainder is a copy of the Arduino main() function with the
|
||||
// USB code and other unneeded code commented out.
|
||||
// init() was called above.
|
||||
// The call to function initVariant() is commented out to fix compiler
|
||||
// error: "multiple definition of 'main'".
|
||||
// The return statement is removed since this function is type void.
|
||||
|
||||
// init();
|
||||
|
||||
// initVariant();
|
||||
|
||||
//#if defined(USBCON)
|
||||
// USBDevice.attach();
|
||||
//#endif
|
||||
|
||||
setup();
|
||||
|
||||
for (;;) {
|
||||
loop();
|
||||
// if (serialEventRun) serialEventRun();
|
||||
}
|
||||
|
||||
// return 0;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,899 @@
|
|||
/**
|
||||
* @file Arduboy2Core.h
|
||||
* \brief
|
||||
* The Arduboy2Core class for Arduboy hardware initilization and control.
|
||||
*/
|
||||
|
||||
#ifndef ARDUBOY2_CORE_H
|
||||
#define ARDUBOY2_CORE_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <avr/power.h>
|
||||
#include <avr/sleep.h>
|
||||
|
||||
|
||||
// main hardware compile flags
|
||||
|
||||
#if !defined(ARDUBOY_10) && !defined(AB_DEVKIT)
|
||||
/* 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
|
||||
*
|
||||
* if you wish to compile for the devkit without using a boards.txt
|
||||
* file simply comment out the ARDUBOY_10 define and uncomment
|
||||
* the AB_DEVKIT define like this:
|
||||
*
|
||||
* // #define ARDUBOY_10
|
||||
* #define AB_DEVKIT
|
||||
*/
|
||||
#define ARDUBOY_10 //< compile for the production Arduboy v1.0
|
||||
// #define AB_DEVKIT //< compile for the official dev kit
|
||||
#endif
|
||||
|
||||
#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() */
|
||||
|
||||
// ----- Arduboy pins -----
|
||||
#ifdef ARDUBOY_10
|
||||
|
||||
#define PIN_CS 12 // Display CS Arduino pin number
|
||||
#define CS_PORT PORTD // Display CS port
|
||||
#define CS_BIT PORTD6 // Display CS physical bit number
|
||||
|
||||
#define PIN_DC 4 // Display D/C Arduino pin number
|
||||
#define DC_PORT PORTD // Display D/C port
|
||||
#define DC_BIT PORTD4 // Display D/C physical bit number
|
||||
|
||||
#define PIN_RST 6 // Display reset Arduino pin number
|
||||
#define RST_PORT PORTD // Display reset port
|
||||
#define RST_BIT PORTD7 // Display reset physical bit number
|
||||
|
||||
#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 RED_LED_PORT PORTB
|
||||
#define RED_LED_BIT PORTB6
|
||||
|
||||
#define GREEN_LED_PORT PORTB
|
||||
#define GREEN_LED_BIT PORTB7
|
||||
|
||||
#define BLUE_LED_PORT PORTB
|
||||
#define BLUE_LED_BIT PORTB5
|
||||
|
||||
// bit values for button states
|
||||
// these are determined by the buttonsState() function
|
||||
#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_LEFT_BUTTON A2
|
||||
#define LEFT_BUTTON_PORT PORTF
|
||||
#define LEFT_BUTTON_PORTIN PINF
|
||||
#define LEFT_BUTTON_DDR DDRF
|
||||
#define LEFT_BUTTON_BIT PORTF5
|
||||
|
||||
#define PIN_RIGHT_BUTTON A1
|
||||
#define RIGHT_BUTTON_PORT PORTF
|
||||
#define RIGHT_BUTTON_PORTIN PINF
|
||||
#define RIGHT_BUTTON_DDR DDRF
|
||||
#define RIGHT_BUTTON_BIT PORTF6
|
||||
|
||||
#define PIN_UP_BUTTON A0
|
||||
#define UP_BUTTON_PORT PORTF
|
||||
#define UP_BUTTON_PORTIN PINF
|
||||
#define UP_BUTTON_DDR DDRF
|
||||
#define UP_BUTTON_BIT PORTF7
|
||||
|
||||
#define PIN_DOWN_BUTTON A3
|
||||
#define DOWN_BUTTON_PORT PORTF
|
||||
#define DOWN_BUTTON_PORTIN PINF
|
||||
#define DOWN_BUTTON_DDR DDRF
|
||||
#define DOWN_BUTTON_BIT PORTF4
|
||||
|
||||
#define PIN_A_BUTTON 7
|
||||
#define A_BUTTON_PORT PORTE
|
||||
#define A_BUTTON_PORTIN PINE
|
||||
#define A_BUTTON_DDR DDRE
|
||||
#define A_BUTTON_BIT PORTE6
|
||||
|
||||
#define PIN_B_BUTTON 8
|
||||
#define B_BUTTON_PORT PORTB
|
||||
#define B_BUTTON_PORTIN PINB
|
||||
#define B_BUTTON_DDR DDRB
|
||||
#define B_BUTTON_BIT PORTB4
|
||||
|
||||
#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 SPEAKER_1_PORT PORTC
|
||||
#define SPEAKER_1_DDR DDRC
|
||||
#define SPEAKER_1_BIT PORTC6
|
||||
|
||||
#define SPEAKER_2_PORT PORTC
|
||||
#define SPEAKER_2_DDR DDRC
|
||||
#define SPEAKER_2_BIT PORTC7
|
||||
// -----------------------
|
||||
|
||||
// ----- DevKit pins -----
|
||||
#elif defined(AB_DEVKIT)
|
||||
|
||||
#define PIN_CS 6 // Display CS Arduino pin number
|
||||
#define CS_PORT PORTD // Display CS port
|
||||
#define CS_BIT PORTD7 // Display CS physical bit number
|
||||
|
||||
#define PIN_DC 4 // Display D/C Arduino pin number
|
||||
#define DC_PORT PORTD // Display D/C port
|
||||
#define DC_BIT PORTD4 // Display D/C physical bit number
|
||||
|
||||
#define PIN_RST 12 // Display reset Arduino pin number
|
||||
#define RST_PORT PORTD // Display reset port
|
||||
#define RST_BIT PORTD6 // Display reset physical bit number
|
||||
|
||||
// map all LEDs to the single TX LED on DEVKIT
|
||||
#define RED_LED 17
|
||||
#define GREEN_LED 17
|
||||
#define BLUE_LED 17
|
||||
|
||||
#define BLUE_LED_PORT PORTB
|
||||
#define BLUE_LED_BIT PORTB0
|
||||
|
||||
// bit values for button states
|
||||
// these are determined by the buttonsState() function
|
||||
#define LEFT_BUTTON _BV(5)
|
||||
#define RIGHT_BUTTON _BV(2)
|
||||
#define UP_BUTTON _BV(4)
|
||||
#define DOWN_BUTTON _BV(6)
|
||||
#define A_BUTTON _BV(1)
|
||||
#define B_BUTTON _BV(0)
|
||||
|
||||
// pin values for buttons, probably shouldn't use these
|
||||
#define PIN_LEFT_BUTTON 9
|
||||
#define LEFT_BUTTON_PORT PORTB
|
||||
#define LEFT_BUTTON_PORTIN PINB
|
||||
#define LEFT_BUTTON_DDR DDRB
|
||||
#define LEFT_BUTTON_BIT PORTB5
|
||||
|
||||
#define PIN_RIGHT_BUTTON 5
|
||||
#define RIGHT_BUTTON_PORT PORTC
|
||||
#define RIGHT_BUTTON_PORTIN PINC
|
||||
#define RIGHT_BUTTON_DDR DDRC
|
||||
#define RIGHT_BUTTON_BIT PORTC6
|
||||
|
||||
#define PIN_UP_BUTTON 8
|
||||
#define UP_BUTTON_PORT PORTB
|
||||
#define UP_BUTTON_PORTIN PINB
|
||||
#define UP_BUTTON_DDR DDRB
|
||||
#define UP_BUTTON_BIT PORTB4
|
||||
|
||||
#define PIN_DOWN_BUTTON 10
|
||||
#define DOWN_BUTTON_PORT PORTB
|
||||
#define DOWN_BUTTON_PORTIN PINB
|
||||
#define DOWN_BUTTON_DDR DDRB
|
||||
#define DOWN_BUTTON_BIT PORTB6
|
||||
|
||||
#define PIN_A_BUTTON A0
|
||||
#define A_BUTTON_PORT PORTF
|
||||
#define A_BUTTON_PORTIN PINF
|
||||
#define A_BUTTON_DDR DDRF
|
||||
#define A_BUTTON_BIT PORTF7
|
||||
|
||||
#define PIN_B_BUTTON A1
|
||||
#define B_BUTTON_PORT PORTF
|
||||
#define B_BUTTON_PORTIN PINF
|
||||
#define B_BUTTON_DDR DDRF
|
||||
#define B_BUTTON_BIT PORTF6
|
||||
|
||||
#define PIN_SPEAKER_1 A2
|
||||
#define SPEAKER_1_PORT PORTF
|
||||
#define SPEAKER_1_DDR DDRF
|
||||
#define SPEAKER_1_BIT PORTF5
|
||||
// SPEAKER_2 is purposely not defined for DEVKIT as it could potentially
|
||||
// be dangerous and fry your hardware (because of the devkit wiring).
|
||||
//
|
||||
// Reference: https://github.com/Arduboy/Arduboy/issues/108
|
||||
|
||||
#endif
|
||||
// --------------------
|
||||
|
||||
// ----- Pins common on Arduboy and DevKit -----
|
||||
|
||||
// Unconnected analog input used for noise by generateRandomSeed()
|
||||
#define RAND_SEED_IN A4
|
||||
#define RAND_SEED_IN_PORT PORTF
|
||||
#define RAND_SEED_IN_BIT PORTF1
|
||||
// Value for ADMUX to read the random seed pin: 2.56V reference, ADC1
|
||||
#define RAND_SEED_IN_ADMUX (_BV(REFS0) | _BV(REFS1) | _BV(MUX0))
|
||||
|
||||
// SPI interface
|
||||
#define SPI_MISO_PORT PORTB
|
||||
#define SPI_MISO_BIT PORTB3
|
||||
|
||||
#define SPI_MOSI_PORT PORTB
|
||||
#define SPI_MOSI_BIT PORTB2
|
||||
|
||||
#define SPI_SCK_PORT PORTB
|
||||
#define SPI_SCK_BIT PORTB1
|
||||
|
||||
#define SPI_SS_PORT PORTB
|
||||
#define SPI_SS_BIT PORTB0
|
||||
// --------------------
|
||||
|
||||
// OLED hardware (SSD1306)
|
||||
|
||||
#define OLED_PIXELS_INVERTED 0xA7 // All pixels inverted
|
||||
#define OLED_PIXELS_NORMAL 0xA6 // All pixels normal
|
||||
|
||||
#define OLED_ALL_PIXELS_ON 0xA5 // all pixels on
|
||||
#define OLED_PIXELS_FROM_RAM 0xA4 // pixels mapped to display RAM contents
|
||||
|
||||
#define OLED_VERTICAL_FLIPPED 0xC0 // reversed COM scan direction
|
||||
#define OLED_VERTICAL_NORMAL 0xC8 // normal COM scan direction
|
||||
|
||||
#define OLED_HORIZ_FLIPPED 0xA0 // reversed segment re-map
|
||||
#define OLED_HORIZ_NORMAL 0xA1 // normal segment re-map
|
||||
|
||||
// -----
|
||||
|
||||
#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
|
||||
* Eliminate the USB stack to free up code space.
|
||||
*
|
||||
* \warning
|
||||
* Removing the USB code will make it impossible for sketch uploader
|
||||
* programs to automatically force a reset into the bootloader!
|
||||
* This means that a user will manually have to invoke a reset in order to
|
||||
* upload a new sketch, after one without USB has be been installed.
|
||||
* Be aware that the timing for the point that a reset must be initiated can
|
||||
* be tricky, which could lead to some frustration on the user's part.
|
||||
*
|
||||
* \details
|
||||
* \parblock
|
||||
* This macro will cause the USB code, normally included in the sketch as part
|
||||
* of the standard Arduino environment, to be eliminated. This will free up a
|
||||
* fair amount of program space, and some RAM space as well, at the expense of
|
||||
* disabling all USB functionality within the sketch (except as power input).
|
||||
*
|
||||
* The macro should be placed before the `setup()` function definition:
|
||||
*
|
||||
* \code{.cpp}
|
||||
* #include <Arduboy2.h>
|
||||
*
|
||||
* Arduboy2 arduboy;
|
||||
*
|
||||
* // (Other variable declarations, etc.)
|
||||
*
|
||||
* // Eliminate the USB stack
|
||||
* ARDUBOY_NO_USB
|
||||
*
|
||||
* void setup() {
|
||||
* arduboy.begin();
|
||||
* // any additional setup code
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* As stated in the warning above, without the USB code an uploader program
|
||||
* will be unable to automatically force a reset into the bootloader to upload
|
||||
* a new sketch. The user will have to manually invoke a reset. In addition to
|
||||
* eliminating the USB code, this macro will check if the DOWN button is held
|
||||
* when the sketch first starts and, if so, will call `exitToBootloader()` to
|
||||
* start the bootloader for uploading. This makes it easier for the user than
|
||||
* having to press the reset button.
|
||||
*
|
||||
* However, to make it even more convenient for a user to invoke the bootloader
|
||||
* it is highly recommended that a sketch using this macro include a menu or
|
||||
* prompt that allows the user to press the DOWN button within the sketch,
|
||||
* which should cause `exitToBootloader()` to be called.
|
||||
*
|
||||
* At a minimum, the documentation for the sketch should clearly state that a
|
||||
* manual reset will be required, and give detailed instructions on what the
|
||||
* user must do to upload a new sketch.
|
||||
* \endparblock
|
||||
*
|
||||
* \see Arduboy2Core::exitToBootloader()
|
||||
*/
|
||||
#define ARDUBOY_NO_USB int main() __attribute__ ((OS_main)); \
|
||||
int main() { \
|
||||
Arduboy2NoUSB::mainNoUSB(); \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
// A replacement for the Arduino main() function that eliminates the USB code.
|
||||
// Used by the ARDUBOY_NO_USB macro.
|
||||
class Arduboy2NoUSB
|
||||
{
|
||||
friend int main();
|
||||
|
||||
private:
|
||||
static void mainNoUSB();
|
||||
};
|
||||
|
||||
|
||||
/** \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.
|
||||
*
|
||||
* \note
|
||||
* A friend class named _Arduboy2Ex_ is declared by this class. The intention
|
||||
* is to allow a sketch to create an _Arduboy2Ex_ class which would have access
|
||||
* to the private and protected members of the Arduboy2Core class. It is hoped
|
||||
* that this may eliminate the need to create an entire local copy of the
|
||||
* library, in order to extend the functionality, in most circumstances.
|
||||
*/
|
||||
class Arduboy2Core : public Arduboy2NoUSB
|
||||
{
|
||||
friend class Arduboy2Ex;
|
||||
|
||||
public:
|
||||
|
||||
/** \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.
|
||||
*/
|
||||
static void idle();
|
||||
|
||||
/** \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.
|
||||
*
|
||||
* \see LCDCommandMode() SPItransfer()
|
||||
*/
|
||||
static void LCDDataMode();
|
||||
|
||||
/** \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.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 LCDDataMode() sendLCDCommand() SPItransfer()
|
||||
*/
|
||||
static void LCDCommandMode();
|
||||
|
||||
/** \brief
|
||||
* Transfer a byte to the display.
|
||||
*
|
||||
* \param data The byte to be sent to the display.
|
||||
*
|
||||
* \details
|
||||
* Transfer one byte to the display over the SPI port and wait for the
|
||||
* transfer to complete. The byte will either be interpreted as a command
|
||||
* or as data to be placed on the screen, depending on the command/data
|
||||
* mode.
|
||||
*
|
||||
* \see LCDDataMode() LCDCommandMode() sendLCDCommand() SPItransferAndRead()
|
||||
*/
|
||||
static void SPItransfer(uint8_t data);
|
||||
|
||||
/** \brief
|
||||
* Transfer a byte to, and read a byte from, the SPI bus.
|
||||
*
|
||||
* \param data The byte to be sent.
|
||||
*
|
||||
* \return The byte that was received.
|
||||
*
|
||||
* \details
|
||||
* This function does the same as the `SPItransfer()` function but also
|
||||
* reads and returns the byte of data that was received during the
|
||||
* transfer.
|
||||
*
|
||||
* This function is of no use for a standard Arduboy, since only the
|
||||
* display is connected to the SPI bus and data cannot be received from
|
||||
* the display. It has been provided for use with homemade or expanded
|
||||
* units that have had additional peripherals added to the SPI bus that
|
||||
* are capable of sending data.
|
||||
*
|
||||
* \see SPItransfer()
|
||||
*/
|
||||
static uint8_t SPItransferAndRead(uint8_t data);
|
||||
|
||||
/** \brief
|
||||
* Turn the display off.
|
||||
*
|
||||
* \details
|
||||
* The display will clear and be put into a low power mode. This can be
|
||||
* used to extend battery life when a game is paused or when a sketch
|
||||
* doesn't require anything to be displayed for a relatively long period
|
||||
* of time.
|
||||
*
|
||||
* \see displayOn()
|
||||
*/
|
||||
static void displayOff();
|
||||
|
||||
/** \brief
|
||||
* Turn the display on.
|
||||
*
|
||||
* \details
|
||||
* Used to power up and reinitialize the display after calling
|
||||
* `displayOff()`.
|
||||
*
|
||||
* \note
|
||||
* The previous call to `displayOff()` will have caused the display's
|
||||
* buffer contents to be lost. The display will have to be re-painted,
|
||||
* which is usually done by calling `display()`.
|
||||
*
|
||||
* \see displayOff()
|
||||
*/
|
||||
static void displayOn();
|
||||
|
||||
/** \brief
|
||||
* Get the width of the display in pixels.
|
||||
*
|
||||
* \return The width of the display in pixels.
|
||||
*/
|
||||
static constexpr uint8_t width() { return WIDTH; }
|
||||
|
||||
/** \brief
|
||||
* Get the height of the display in pixels.
|
||||
*
|
||||
* \return The height of the display in pixels.
|
||||
*/
|
||||
static constexpr uint8_t height() { return HEIGHT; }
|
||||
|
||||
/** \brief
|
||||
* Get the 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
|
||||
*/
|
||||
static uint8_t buttonsState();
|
||||
|
||||
/** \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)
|
||||
*/
|
||||
static void paint8Pixels(uint8_t pixels);
|
||||
|
||||
/** \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()
|
||||
*/
|
||||
static void paintScreen(const uint8_t *image);
|
||||
|
||||
/** \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.
|
||||
* \param clear If `true` the array in RAM will be cleared to zeros upon
|
||||
* return from this function. If `false` the RAM buffer will remain
|
||||
* unchanged. (optional; defaults to `false`)
|
||||
*
|
||||
* \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.
|
||||
*
|
||||
* If parameter `clear` is set to `true` the RAM array will be cleared to
|
||||
* zeros after its contents are written to the display.
|
||||
*
|
||||
* \see paint8Pixels()
|
||||
*/
|
||||
static void paintScreen(uint8_t image[], bool clear = false);
|
||||
|
||||
/** \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.
|
||||
*/
|
||||
static void blank();
|
||||
|
||||
/** \brief
|
||||
* Invert the entire display or set it back to normal.
|
||||
*
|
||||
* \param inverse `true` will invert the display. `false` will set the
|
||||
* display to non-inverted.
|
||||
*
|
||||
* \details
|
||||
* 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`.
|
||||
*/
|
||||
static void invert(bool inverse);
|
||||
|
||||
/** \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()
|
||||
*/
|
||||
static void allPixelsOn(bool on);
|
||||
|
||||
/** \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()
|
||||
*/
|
||||
static void flipVertical(bool flipped);
|
||||
|
||||
/** \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()
|
||||
*/
|
||||
static void flipHorizontal(bool flipped);
|
||||
|
||||
/** \brief
|
||||
* Send a single command byte to the display.
|
||||
*
|
||||
* \param command The command byte to send to the display.
|
||||
*
|
||||
* \details
|
||||
* 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.
|
||||
*/
|
||||
static void sendLCDCommand(uint8_t command);
|
||||
|
||||
/** \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
|
||||
* \parblock
|
||||
* 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.
|
||||
* \endparblock
|
||||
*
|
||||
* \note
|
||||
* \parblock
|
||||
* 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.
|
||||
* \endparblock
|
||||
*
|
||||
* \see setRGBled(uint8_t, uint8_t) digitalWriteRGB() freeRGBled()
|
||||
*/
|
||||
static void setRGBled(uint8_t red, uint8_t green, uint8_t blue);
|
||||
|
||||
/** \brief
|
||||
* Set the brightness of one of the RGB LEDs without affecting the others.
|
||||
*
|
||||
* \param color The name of the LED to set. The value given should be one
|
||||
* of RED_LED, GREEN_LED or BLUE_LED.
|
||||
*
|
||||
* \param val The brightness value for the LED, from 0 to 255.
|
||||
*
|
||||
* \note
|
||||
* In order to use this function, the 3 parameter version must first be
|
||||
* called at least once, in order to initialize the hardware.
|
||||
*
|
||||
* \details
|
||||
* This 2 parameter version of the function will set the brightness of a
|
||||
* single LED within the RGB LED without affecting the current brightness
|
||||
* of the other two. See the description of the 3 parameter version of this
|
||||
* function for more details on the RGB LED.
|
||||
*
|
||||
* \see setRGBled(uint8_t, uint8_t, uint8_t) digitalWriteRGB() freeRGBled()
|
||||
*/
|
||||
static void setRGBled(uint8_t color, uint8_t val);
|
||||
|
||||
|
||||
/** \brief
|
||||
* Relinquish analog control of the RGB LED.
|
||||
*
|
||||
* \details
|
||||
* Using the RGB LED in analog mode prevents further use of the LED in
|
||||
* digital mode. This function will restore the pins used for the LED, so
|
||||
* it can be used in digital mode.
|
||||
*
|
||||
* \see digitalWriteRGB() setRGBled()
|
||||
*/
|
||||
static void freeRGBled();
|
||||
|
||||
/** \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 3 parameter version of the
|
||||
* 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
|
||||
* \parblock
|
||||
* Using the RGB LED in analog mode will prevent digital control of the
|
||||
* LED. To restore the ability to control the LED digitally, use the
|
||||
* `freeRGBled()` function.
|
||||
* \endparblock
|
||||
*
|
||||
* \note
|
||||
* \parblock
|
||||
* 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.
|
||||
* \endparblock
|
||||
*
|
||||
* \see digitalWriteRGB(uint8_t, uint8_t) setRGBled() freeRGBled()
|
||||
*/
|
||||
static void digitalWriteRGB(uint8_t red, uint8_t green, uint8_t blue);
|
||||
|
||||
/** \brief
|
||||
* Set one of the RGB LEDs digitally, to either fully on or fully off.
|
||||
*
|
||||
* \param color The name of the LED to set. The value given should be one
|
||||
* of RED_LED, GREEN_LED or BLUE_LED.
|
||||
*
|
||||
* \param val Indicates whether to turn the specified LED on or off.
|
||||
* The value given should be RGB_ON or RGB_OFF.
|
||||
*
|
||||
* \details
|
||||
* This 2 parameter version of the function will set a single LED within
|
||||
* the RGB LED either fully on or fully off. See the description of the
|
||||
* 3 parameter version of this function for more details on the RGB LED.
|
||||
*
|
||||
* \see digitalWriteRGB(uint8_t, uint8_t, uint8_t) setRGBled() freeRGBled()
|
||||
*/
|
||||
static void digitalWriteRGB(uint8_t color, uint8_t val);
|
||||
|
||||
/** \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 as space permits.
|
||||
*
|
||||
* See the README file or main page, in section
|
||||
* _Substitute or remove boot up features_, for more details.
|
||||
*
|
||||
* \warning
|
||||
* If this function is used, it is recommended that at least `flashlight()`
|
||||
* or `safeMode()` be called after it to provide a means to upload a new
|
||||
* sketch if the bootloader "magic number" problem is encountered.
|
||||
*
|
||||
* \see Arduboy2::begin() Arduboy2Base::flashlight() safeMode()
|
||||
*/
|
||||
static void boot();
|
||||
|
||||
/** \brief
|
||||
* Allow upload when the bootloader "magic number" could be corrupted.
|
||||
*
|
||||
* \details
|
||||
* If the UP button is held when this function is entered, the RGB LED
|
||||
* will be lit and timer 0 will be disabled, then the sketch will remain
|
||||
* in a tight loop. This is to address a problem with uploading a new
|
||||
* sketch, for sketches that interfere with the bootloader "magic number".
|
||||
* The problem occurs with certain sketches that use large amounts of RAM.
|
||||
*
|
||||
* This function should be called after `boot()` in sketches that don't
|
||||
* call `flashlight()`.
|
||||
*
|
||||
* It is intended to replace the `flashlight()` function when more
|
||||
* program space is required. If possible, it is more desirable to use
|
||||
* `flashlight()`, so that the actual flashlight feature isn't lost.
|
||||
*
|
||||
* \see Arduboy2Base::flashlight() boot()
|
||||
*/
|
||||
static void safeMode();
|
||||
|
||||
/** \brief
|
||||
* Create a seed suitable for use with a pseudorandom number generator.
|
||||
*
|
||||
* \return A random value that can be used to seed a
|
||||
* pseudorandom number generator.
|
||||
*
|
||||
* \details
|
||||
* The returned value will be a random value derived from entropy from an
|
||||
* ADC reading of a floating pin combined with the microseconds since boot.
|
||||
*
|
||||
* \note
|
||||
* This function will be more effective if called after a semi-random time,
|
||||
* such as after waiting for the user to press a button to start a game, or
|
||||
* another event that takes a variable amount of time after boot.
|
||||
*
|
||||
* \see Arduboy2Base::initRandomSeed()
|
||||
*/
|
||||
static unsigned long generateRandomSeed();
|
||||
|
||||
/** \brief
|
||||
* Delay for the number of milliseconds, specified as a 16 bit value.
|
||||
*
|
||||
* \param ms The delay in milliseconds.
|
||||
*
|
||||
* \details
|
||||
* This function works the same as the Arduino `delay()` function except
|
||||
* the provided value is 16 bits long, so the maximum delay allowed is
|
||||
* 65535 milliseconds (about 65.5 seconds). Using this function instead
|
||||
* of Arduino `delay()` will save a few bytes of code.
|
||||
*/
|
||||
static void delayShort(uint16_t ms) __attribute__ ((noinline));
|
||||
|
||||
/** \brief
|
||||
* Exit the sketch and start the bootloader
|
||||
*
|
||||
* \details
|
||||
* The sketch will exit and the bootloader will be started in command mode.
|
||||
* The effect will be similar to pressing the reset button.
|
||||
*
|
||||
* This function is intended to be used to allow uploading a new sketch,
|
||||
* when the USB code has been removed to gain more code space.
|
||||
* Ideally, the sketch would present a "New Sketch Upload" menu or prompt
|
||||
* telling the user to "Press and hold the DOWN button when the procedure
|
||||
* to upload a new sketch has been initiated". The sketch would then wait
|
||||
* for the DOWN button to be pressed and then call this function.
|
||||
*
|
||||
* \see ARDUBOY_NO_USB
|
||||
*/
|
||||
static void exitToBootloader();
|
||||
|
||||
protected:
|
||||
// internals
|
||||
static void setCPUSpeed8MHz();
|
||||
static void bootSPI();
|
||||
static void bootOLED();
|
||||
static void bootPins();
|
||||
static void bootPowerSaving();
|
||||
|
||||
static const PROGMEM uint8_t lcdBootProgram[];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,341 @@
|
|||
/**
|
||||
* @file Arduboy2Data.cpp
|
||||
* \brief
|
||||
* Constant data definintions for the Arduboy2 and Arduboy2Base classes.
|
||||
*/
|
||||
|
||||
#include "Arduboy2.h"
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
// arduboy_logo.png
|
||||
// drawBitmap() format
|
||||
// 88x16 px (176 bytes)
|
||||
const PROGMEM uint8_t Arduboy2Base::arduboy_logo[] = {
|
||||
0xF0, 0xF8, 0x9C, 0x8E, 0x87, 0x83, 0x87, 0x8E, 0x9C, 0xF8,
|
||||
0xF0, 0x00, 0x00, 0xFE, 0xFF, 0x03, 0x03, 0x03, 0x03, 0x03,
|
||||
0x07, 0x0E, 0xFC, 0xF8, 0x00, 0x00, 0xFE, 0xFF, 0x03, 0x03,
|
||||
0x03, 0x03, 0x03, 0x07, 0x0E, 0xFC, 0xF8, 0x00, 0x00, 0xFF,
|
||||
0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
|
||||
0x00, 0x00, 0xFE, 0xFF, 0x83, 0x83, 0x83, 0x83, 0x83, 0xC7,
|
||||
0xEE, 0x7C, 0x38, 0x00, 0x00, 0xF8, 0xFC, 0x0E, 0x07, 0x03,
|
||||
0x03, 0x03, 0x07, 0x0E, 0xFC, 0xF8, 0x00, 0x00, 0x3F, 0x7F,
|
||||
0xE0, 0xC0, 0x80, 0x80, 0xC0, 0xE0, 0x7F, 0x3F, 0xFF, 0xFF,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFF, 0xFF, 0x00,
|
||||
0x00, 0xFF, 0xFF, 0x0C, 0x0C, 0x0C, 0x0C, 0x1C, 0x3E, 0x77,
|
||||
0xE3, 0xC1, 0x00, 0x00, 0x7F, 0xFF, 0xC0, 0xC0, 0xC0, 0xC0,
|
||||
0xC0, 0xE0, 0x70, 0x3F, 0x1F, 0x00, 0x00, 0x1F, 0x3F, 0x70,
|
||||
0xE0, 0xC0, 0xC0, 0xC0, 0xE0, 0x70, 0x3F, 0x1F, 0x00, 0x00,
|
||||
0x7F, 0xFF, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xE3, 0x77, 0x3E,
|
||||
0x1C, 0x00, 0x00, 0x1F, 0x3F, 0x70, 0xE0, 0xC0, 0xC0, 0xC0,
|
||||
0xE0, 0x70, 0x3F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||
0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
// arduboy_logo.png
|
||||
// drawCompressed() format
|
||||
// 88x16 px (151 bytes)
|
||||
const PROGMEM uint8_t Arduboy2Base::arduboy_logo_compressed[] = {
|
||||
0x57, 0x0F, 0x9C, 0x53, 0x72, 0x75, 0x29, 0xE5, 0x9C, 0x92,
|
||||
0xCE, 0x95, 0x52, 0xAD, 0x4E, 0x49, 0xE7, 0x08, 0x09, 0xED,
|
||||
0x76, 0xBB, 0xDD, 0x2A, 0xAB, 0xAC, 0x55, 0x92, 0x90, 0xD0,
|
||||
0x6E, 0xB7, 0xDB, 0xAD, 0xB2, 0xCA, 0x5A, 0x25, 0xF9, 0xF8,
|
||||
0xF0, 0xC6, 0x47, 0x48, 0x28, 0x95, 0x54, 0x52, 0x49, 0x25,
|
||||
0x9D, 0x3A, 0x95, 0x5A, 0x3A, 0x45, 0x2A, 0xB7, 0x29, 0xA7,
|
||||
0xE4, 0x76, 0xBB, 0x55, 0x56, 0x59, 0xAB, 0x24, 0x9F, 0x5D,
|
||||
0x5B, 0x65, 0xD7, 0xE9, 0xEC, 0x92, 0x29, 0x3B, 0xA1, 0x4E,
|
||||
0xA7, 0xD3, 0xE9, 0x74, 0x9A, 0x8F, 0x8F, 0xEF, 0xED, 0x76,
|
||||
0xBB, 0x55, 0x4E, 0xAE, 0x52, 0xAD, 0x9C, 0x9C, 0x4F, 0xE7,
|
||||
0xED, 0x76, 0xBB, 0xDD, 0x2E, 0x95, 0x53, 0xD9, 0x25, 0xA5,
|
||||
0x54, 0xD6, 0x2A, 0xAB, 0xEC, 0x76, 0xBB, 0x54, 0x4E, 0x65,
|
||||
0x97, 0x94, 0x3A, 0x22, 0xA9, 0xA4, 0x92, 0x4A, 0x2A, 0xE9,
|
||||
0x94, 0x4D, 0x2D, 0x9D, 0xA2, 0x94, 0xCA, 0x5A, 0x65, 0x95,
|
||||
0xDD, 0x6E, 0x97, 0xCA, 0xA9, 0xEC, 0x12, 0x55, 0x69, 0x42,
|
||||
0x7A
|
||||
};
|
||||
|
||||
// arduboy_logo.png
|
||||
// Sprites::drawSelfMasked() format
|
||||
// 88x16 px (178 bytes)
|
||||
const PROGMEM uint8_t Arduboy2Base::arduboy_logo_sprite[] = {
|
||||
88, 16,
|
||||
0xF0, 0xF8, 0x9C, 0x8E, 0x87, 0x83, 0x87, 0x8E, 0x9C, 0xF8,
|
||||
0xF0, 0x00, 0x00, 0xFE, 0xFF, 0x03, 0x03, 0x03, 0x03, 0x03,
|
||||
0x07, 0x0E, 0xFC, 0xF8, 0x00, 0x00, 0xFE, 0xFF, 0x03, 0x03,
|
||||
0x03, 0x03, 0x03, 0x07, 0x0E, 0xFC, 0xF8, 0x00, 0x00, 0xFF,
|
||||
0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
|
||||
0x00, 0x00, 0xFE, 0xFF, 0x83, 0x83, 0x83, 0x83, 0x83, 0xC7,
|
||||
0xEE, 0x7C, 0x38, 0x00, 0x00, 0xF8, 0xFC, 0x0E, 0x07, 0x03,
|
||||
0x03, 0x03, 0x07, 0x0E, 0xFC, 0xF8, 0x00, 0x00, 0x3F, 0x7F,
|
||||
0xE0, 0xC0, 0x80, 0x80, 0xC0, 0xE0, 0x7F, 0x3F, 0xFF, 0xFF,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFF, 0xFF, 0x00,
|
||||
0x00, 0xFF, 0xFF, 0x0C, 0x0C, 0x0C, 0x0C, 0x1C, 0x3E, 0x77,
|
||||
0xE3, 0xC1, 0x00, 0x00, 0x7F, 0xFF, 0xC0, 0xC0, 0xC0, 0xC0,
|
||||
0xC0, 0xE0, 0x70, 0x3F, 0x1F, 0x00, 0x00, 0x1F, 0x3F, 0x70,
|
||||
0xE0, 0xC0, 0xC0, 0xC0, 0xE0, 0x70, 0x3F, 0x1F, 0x00, 0x00,
|
||||
0x7F, 0xFF, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xE3, 0x77, 0x3E,
|
||||
0x1C, 0x00, 0x00, 0x1F, 0x3F, 0x70, 0xE0, 0xC0, 0xC0, 0xC0,
|
||||
0xE0, 0x70, 0x3F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||
0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
// ASCII based 5x7 font
|
||||
// IBM PC code page 437
|
||||
const PROGMEM uint8_t Arduboy2::font5x7[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x3E, 0x5B, 0x4F, 0x5B, 0x3E,
|
||||
0x3E, 0x6B, 0x4F, 0x6B, 0x3E,
|
||||
0x1C, 0x3E, 0x7C, 0x3E, 0x1C,
|
||||
0x18, 0x3C, 0x7E, 0x3C, 0x18,
|
||||
0x1C, 0x57, 0x7D, 0x57, 0x1C,
|
||||
0x1C, 0x5E, 0x7F, 0x5E, 0x1C,
|
||||
0x00, 0x18, 0x3C, 0x18, 0x00,
|
||||
0xFF, 0xE7, 0xC3, 0xE7, 0xFF,
|
||||
0x00, 0x18, 0x24, 0x18, 0x00,
|
||||
0xFF, 0xE7, 0xDB, 0xE7, 0xFF,
|
||||
0x30, 0x48, 0x3A, 0x06, 0x0E,
|
||||
0x26, 0x29, 0x79, 0x29, 0x26,
|
||||
0x40, 0x7F, 0x05, 0x05, 0x07,
|
||||
0x40, 0x7F, 0x05, 0x25, 0x3F,
|
||||
0x5A, 0x3C, 0xE7, 0x3C, 0x5A,
|
||||
0x7F, 0x3E, 0x1C, 0x1C, 0x08,
|
||||
0x08, 0x1C, 0x1C, 0x3E, 0x7F,
|
||||
0x14, 0x22, 0x7F, 0x22, 0x14,
|
||||
0x5F, 0x5F, 0x00, 0x5F, 0x5F,
|
||||
0x06, 0x09, 0x7F, 0x01, 0x7F,
|
||||
0x00, 0x66, 0x89, 0x95, 0x6A,
|
||||
0x60, 0x60, 0x60, 0x60, 0x60,
|
||||
0x94, 0xA2, 0xFF, 0xA2, 0x94,
|
||||
0x08, 0x04, 0x7E, 0x04, 0x08,
|
||||
0x10, 0x20, 0x7E, 0x20, 0x10,
|
||||
0x08, 0x08, 0x2A, 0x1C, 0x08,
|
||||
0x08, 0x1C, 0x2A, 0x08, 0x08,
|
||||
0x1E, 0x10, 0x10, 0x10, 0x10,
|
||||
0x0C, 0x1E, 0x0C, 0x1E, 0x0C,
|
||||
0x30, 0x38, 0x3E, 0x38, 0x30,
|
||||
0x06, 0x0E, 0x3E, 0x0E, 0x06,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x5F, 0x00, 0x00,
|
||||
0x00, 0x07, 0x00, 0x07, 0x00,
|
||||
0x14, 0x7F, 0x14, 0x7F, 0x14,
|
||||
0x24, 0x2A, 0x7F, 0x2A, 0x12,
|
||||
0x23, 0x13, 0x08, 0x64, 0x62,
|
||||
0x36, 0x49, 0x56, 0x20, 0x50,
|
||||
0x00, 0x08, 0x07, 0x03, 0x00,
|
||||
0x00, 0x1C, 0x22, 0x41, 0x00,
|
||||
0x00, 0x41, 0x22, 0x1C, 0x00,
|
||||
0x2A, 0x1C, 0x7F, 0x1C, 0x2A,
|
||||
0x08, 0x08, 0x3E, 0x08, 0x08,
|
||||
0x00, 0x80, 0x70, 0x30, 0x00,
|
||||
0x08, 0x08, 0x08, 0x08, 0x08,
|
||||
0x00, 0x00, 0x60, 0x60, 0x00,
|
||||
0x20, 0x10, 0x08, 0x04, 0x02,
|
||||
0x3E, 0x51, 0x49, 0x45, 0x3E,
|
||||
0x00, 0x42, 0x7F, 0x40, 0x00,
|
||||
0x72, 0x49, 0x49, 0x49, 0x46,
|
||||
0x21, 0x41, 0x49, 0x4D, 0x33,
|
||||
0x18, 0x14, 0x12, 0x7F, 0x10,
|
||||
0x27, 0x45, 0x45, 0x45, 0x39,
|
||||
0x3C, 0x4A, 0x49, 0x49, 0x31,
|
||||
0x41, 0x21, 0x11, 0x09, 0x07,
|
||||
0x36, 0x49, 0x49, 0x49, 0x36,
|
||||
0x46, 0x49, 0x49, 0x29, 0x1E,
|
||||
0x00, 0x00, 0x14, 0x00, 0x00,
|
||||
0x00, 0x40, 0x34, 0x00, 0x00,
|
||||
0x00, 0x08, 0x14, 0x22, 0x41,
|
||||
0x14, 0x14, 0x14, 0x14, 0x14,
|
||||
0x00, 0x41, 0x22, 0x14, 0x08,
|
||||
0x02, 0x01, 0x59, 0x09, 0x06,
|
||||
0x3E, 0x41, 0x5D, 0x59, 0x4E,
|
||||
0x7C, 0x12, 0x11, 0x12, 0x7C,
|
||||
0x7F, 0x49, 0x49, 0x49, 0x36,
|
||||
0x3E, 0x41, 0x41, 0x41, 0x22,
|
||||
0x7F, 0x41, 0x41, 0x41, 0x3E,
|
||||
0x7F, 0x49, 0x49, 0x49, 0x41,
|
||||
0x7F, 0x09, 0x09, 0x09, 0x01,
|
||||
0x3E, 0x41, 0x41, 0x51, 0x73,
|
||||
0x7F, 0x08, 0x08, 0x08, 0x7F,
|
||||
0x00, 0x41, 0x7F, 0x41, 0x00,
|
||||
0x20, 0x40, 0x41, 0x3F, 0x01,
|
||||
0x7F, 0x08, 0x14, 0x22, 0x41,
|
||||
0x7F, 0x40, 0x40, 0x40, 0x40,
|
||||
0x7F, 0x02, 0x1C, 0x02, 0x7F,
|
||||
0x7F, 0x04, 0x08, 0x10, 0x7F,
|
||||
0x3E, 0x41, 0x41, 0x41, 0x3E,
|
||||
0x7F, 0x09, 0x09, 0x09, 0x06,
|
||||
0x3E, 0x41, 0x51, 0x21, 0x5E,
|
||||
0x7F, 0x09, 0x19, 0x29, 0x46,
|
||||
0x26, 0x49, 0x49, 0x49, 0x32,
|
||||
0x03, 0x01, 0x7F, 0x01, 0x03,
|
||||
0x3F, 0x40, 0x40, 0x40, 0x3F,
|
||||
0x1F, 0x20, 0x40, 0x20, 0x1F,
|
||||
0x3F, 0x40, 0x38, 0x40, 0x3F,
|
||||
0x63, 0x14, 0x08, 0x14, 0x63,
|
||||
0x03, 0x04, 0x78, 0x04, 0x03,
|
||||
0x61, 0x59, 0x49, 0x4D, 0x43,
|
||||
0x00, 0x7F, 0x41, 0x41, 0x41,
|
||||
0x02, 0x04, 0x08, 0x10, 0x20,
|
||||
0x00, 0x41, 0x41, 0x41, 0x7F,
|
||||
0x04, 0x02, 0x01, 0x02, 0x04,
|
||||
0x40, 0x40, 0x40, 0x40, 0x40,
|
||||
0x00, 0x03, 0x07, 0x08, 0x00,
|
||||
0x20, 0x54, 0x54, 0x78, 0x40,
|
||||
0x7F, 0x28, 0x44, 0x44, 0x38,
|
||||
0x38, 0x44, 0x44, 0x44, 0x28,
|
||||
0x38, 0x44, 0x44, 0x28, 0x7F,
|
||||
0x38, 0x54, 0x54, 0x54, 0x18,
|
||||
0x00, 0x08, 0x7E, 0x09, 0x02,
|
||||
0x18, 0xA4, 0xA4, 0x9C, 0x78,
|
||||
0x7F, 0x08, 0x04, 0x04, 0x78,
|
||||
0x00, 0x44, 0x7D, 0x40, 0x00,
|
||||
0x20, 0x40, 0x40, 0x3D, 0x00,
|
||||
0x7F, 0x10, 0x28, 0x44, 0x00,
|
||||
0x00, 0x41, 0x7F, 0x40, 0x00,
|
||||
0x7C, 0x04, 0x78, 0x04, 0x78,
|
||||
0x7C, 0x08, 0x04, 0x04, 0x78,
|
||||
0x38, 0x44, 0x44, 0x44, 0x38,
|
||||
0xFC, 0x18, 0x24, 0x24, 0x18,
|
||||
0x18, 0x24, 0x24, 0x18, 0xFC,
|
||||
0x7C, 0x08, 0x04, 0x04, 0x08,
|
||||
0x48, 0x54, 0x54, 0x54, 0x24,
|
||||
0x04, 0x04, 0x3F, 0x44, 0x24,
|
||||
0x3C, 0x40, 0x40, 0x20, 0x7C,
|
||||
0x1C, 0x20, 0x40, 0x20, 0x1C,
|
||||
0x3C, 0x40, 0x30, 0x40, 0x3C,
|
||||
0x44, 0x28, 0x10, 0x28, 0x44,
|
||||
0x4C, 0x90, 0x90, 0x90, 0x7C,
|
||||
0x44, 0x64, 0x54, 0x4C, 0x44,
|
||||
0x00, 0x08, 0x36, 0x41, 0x00,
|
||||
0x00, 0x00, 0x77, 0x00, 0x00,
|
||||
0x00, 0x41, 0x36, 0x08, 0x00,
|
||||
0x02, 0x01, 0x02, 0x04, 0x02,
|
||||
0x3C, 0x26, 0x23, 0x26, 0x3C,
|
||||
0x1E, 0xA1, 0xA1, 0x61, 0x12,
|
||||
0x3A, 0x40, 0x40, 0x20, 0x7A,
|
||||
0x38, 0x54, 0x54, 0x55, 0x59,
|
||||
0x21, 0x55, 0x55, 0x79, 0x41,
|
||||
0x21, 0x54, 0x54, 0x78, 0x41,
|
||||
0x21, 0x55, 0x54, 0x78, 0x40,
|
||||
0x20, 0x54, 0x55, 0x79, 0x40,
|
||||
0x0C, 0x1E, 0x52, 0x72, 0x12,
|
||||
0x39, 0x55, 0x55, 0x55, 0x59,
|
||||
0x39, 0x54, 0x54, 0x54, 0x59,
|
||||
0x39, 0x55, 0x54, 0x54, 0x58,
|
||||
0x00, 0x00, 0x45, 0x7C, 0x41,
|
||||
0x00, 0x02, 0x45, 0x7D, 0x42,
|
||||
0x00, 0x01, 0x45, 0x7C, 0x40,
|
||||
0xF0, 0x29, 0x24, 0x29, 0xF0,
|
||||
0xF0, 0x28, 0x25, 0x28, 0xF0,
|
||||
0x7C, 0x54, 0x55, 0x45, 0x00,
|
||||
0x20, 0x54, 0x54, 0x7C, 0x54,
|
||||
0x7C, 0x0A, 0x09, 0x7F, 0x49,
|
||||
0x32, 0x49, 0x49, 0x49, 0x32,
|
||||
0x32, 0x48, 0x48, 0x48, 0x32,
|
||||
0x32, 0x4A, 0x48, 0x48, 0x30,
|
||||
0x3A, 0x41, 0x41, 0x21, 0x7A,
|
||||
0x3A, 0x42, 0x40, 0x20, 0x78,
|
||||
0x00, 0x9D, 0xA0, 0xA0, 0x7D,
|
||||
0x39, 0x44, 0x44, 0x44, 0x39,
|
||||
0x3D, 0x40, 0x40, 0x40, 0x3D,
|
||||
0x3C, 0x24, 0xFF, 0x24, 0x24,
|
||||
0x48, 0x7E, 0x49, 0x43, 0x66,
|
||||
0x2B, 0x2F, 0xFC, 0x2F, 0x2B,
|
||||
0xFF, 0x09, 0x29, 0xF6, 0x20,
|
||||
0xC0, 0x88, 0x7E, 0x09, 0x03,
|
||||
0x20, 0x54, 0x54, 0x79, 0x41,
|
||||
0x00, 0x00, 0x44, 0x7D, 0x41,
|
||||
0x30, 0x48, 0x48, 0x4A, 0x32,
|
||||
0x38, 0x40, 0x40, 0x22, 0x7A,
|
||||
0x00, 0x7A, 0x0A, 0x0A, 0x72,
|
||||
0x7D, 0x0D, 0x19, 0x31, 0x7D,
|
||||
0x26, 0x29, 0x29, 0x2F, 0x28,
|
||||
0x26, 0x29, 0x29, 0x29, 0x26,
|
||||
0x30, 0x48, 0x4D, 0x40, 0x20,
|
||||
0x38, 0x08, 0x08, 0x08, 0x08,
|
||||
0x08, 0x08, 0x08, 0x08, 0x38,
|
||||
0x2F, 0x10, 0xC8, 0xAC, 0xBA,
|
||||
0x2F, 0x10, 0x28, 0x34, 0xFA,
|
||||
0x00, 0x00, 0x7B, 0x00, 0x00,
|
||||
0x08, 0x14, 0x2A, 0x14, 0x22,
|
||||
0x22, 0x14, 0x2A, 0x14, 0x08,
|
||||
0x95, 0x00, 0x22, 0x00, 0x95,
|
||||
0xAA, 0x00, 0x55, 0x00, 0xAA,
|
||||
0xAA, 0x55, 0xAA, 0x55, 0xAA,
|
||||
0x00, 0x00, 0x00, 0xFF, 0x00,
|
||||
0x10, 0x10, 0x10, 0xFF, 0x00,
|
||||
0x14, 0x14, 0x14, 0xFF, 0x00,
|
||||
0x10, 0x10, 0xFF, 0x00, 0xFF,
|
||||
0x10, 0x10, 0xF0, 0x10, 0xF0,
|
||||
0x14, 0x14, 0x14, 0xFC, 0x00,
|
||||
0x14, 0x14, 0xF7, 0x00, 0xFF,
|
||||
0x00, 0x00, 0xFF, 0x00, 0xFF,
|
||||
0x14, 0x14, 0xF4, 0x04, 0xFC,
|
||||
0x14, 0x14, 0x17, 0x10, 0x1F,
|
||||
0x10, 0x10, 0x1F, 0x10, 0x1F,
|
||||
0x14, 0x14, 0x14, 0x1F, 0x00,
|
||||
0x10, 0x10, 0x10, 0xF0, 0x00,
|
||||
0x00, 0x00, 0x00, 0x1F, 0x10,
|
||||
0x10, 0x10, 0x10, 0x1F, 0x10,
|
||||
0x10, 0x10, 0x10, 0xF0, 0x10,
|
||||
0x00, 0x00, 0x00, 0xFF, 0x10,
|
||||
0x10, 0x10, 0x10, 0x10, 0x10,
|
||||
0x10, 0x10, 0x10, 0xFF, 0x10,
|
||||
0x00, 0x00, 0x00, 0xFF, 0x14,
|
||||
0x00, 0x00, 0xFF, 0x00, 0xFF,
|
||||
0x00, 0x00, 0x1F, 0x10, 0x17,
|
||||
0x00, 0x00, 0xFC, 0x04, 0xF4,
|
||||
0x14, 0x14, 0x17, 0x10, 0x17,
|
||||
0x14, 0x14, 0xF4, 0x04, 0xF4,
|
||||
0x00, 0x00, 0xFF, 0x00, 0xF7,
|
||||
0x14, 0x14, 0x14, 0x14, 0x14,
|
||||
0x14, 0x14, 0xF7, 0x00, 0xF7,
|
||||
0x14, 0x14, 0x14, 0x17, 0x14,
|
||||
0x10, 0x10, 0x1F, 0x10, 0x1F,
|
||||
0x14, 0x14, 0x14, 0xF4, 0x14,
|
||||
0x10, 0x10, 0xF0, 0x10, 0xF0,
|
||||
0x00, 0x00, 0x1F, 0x10, 0x1F,
|
||||
0x00, 0x00, 0x00, 0x1F, 0x14,
|
||||
0x00, 0x00, 0x00, 0xFC, 0x14,
|
||||
0x00, 0x00, 0xF0, 0x10, 0xF0,
|
||||
0x10, 0x10, 0xFF, 0x10, 0xFF,
|
||||
0x14, 0x14, 0x14, 0xFF, 0x14,
|
||||
0x10, 0x10, 0x10, 0x1F, 0x00,
|
||||
0x00, 0x00, 0x00, 0xF0, 0x10,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
|
||||
0xFF, 0xFF, 0xFF, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xFF, 0xFF,
|
||||
0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
|
||||
0x38, 0x44, 0x44, 0x38, 0x44,
|
||||
0x7C, 0x2A, 0x2A, 0x3E, 0x14,
|
||||
0x7E, 0x02, 0x02, 0x06, 0x06,
|
||||
0x02, 0x7E, 0x02, 0x7E, 0x02,
|
||||
0x63, 0x55, 0x49, 0x41, 0x63,
|
||||
0x38, 0x44, 0x44, 0x3C, 0x04,
|
||||
0x40, 0x7E, 0x20, 0x1E, 0x20,
|
||||
0x06, 0x02, 0x7E, 0x02, 0x02,
|
||||
0x99, 0xA5, 0xE7, 0xA5, 0x99,
|
||||
0x1C, 0x2A, 0x49, 0x2A, 0x1C,
|
||||
0x4C, 0x72, 0x01, 0x72, 0x4C,
|
||||
0x30, 0x4A, 0x4D, 0x4D, 0x30,
|
||||
0x30, 0x48, 0x78, 0x48, 0x30,
|
||||
0xBC, 0x62, 0x5A, 0x46, 0x3D,
|
||||
0x3E, 0x49, 0x49, 0x49, 0x00,
|
||||
0x7E, 0x01, 0x01, 0x01, 0x7E,
|
||||
0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
|
||||
0x44, 0x44, 0x5F, 0x44, 0x44,
|
||||
0x40, 0x51, 0x4A, 0x44, 0x40,
|
||||
0x40, 0x44, 0x4A, 0x51, 0x40,
|
||||
0x00, 0x00, 0xFF, 0x01, 0x03,
|
||||
0xE0, 0x80, 0xFF, 0x00, 0x00,
|
||||
0x08, 0x08, 0x6B, 0x6B, 0x08,
|
||||
0x36, 0x12, 0x36, 0x24, 0x36,
|
||||
0x06, 0x0F, 0x09, 0x0F, 0x06,
|
||||
0x00, 0x00, 0x18, 0x18, 0x00,
|
||||
0x00, 0x00, 0x10, 0x10, 0x00,
|
||||
0x30, 0x40, 0xFF, 0x01, 0x01,
|
||||
0x00, 0x1F, 0x01, 0x01, 0x1E,
|
||||
0x00, 0x19, 0x1D, 0x17, 0x12,
|
||||
0x00, 0x3C, 0x3C, 0x3C, 0x3C,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
#include "Arduboy2.h"
|
||||
#include "ArduboyAudio.h"
|
||||
|
||||
bool ArduboyAudio::audio_enabled = false;
|
||||
|
||||
void ArduboyAudio::on()
|
||||
{
|
||||
// fire up audio pins
|
||||
#ifdef ARDUBOY_10
|
||||
pinMode(PIN_SPEAKER_1, OUTPUT);
|
||||
pinMode(PIN_SPEAKER_2, OUTPUT);
|
||||
#else
|
||||
pinMode(PIN_SPEAKER_1, OUTPUT);
|
||||
#endif
|
||||
audio_enabled = true;
|
||||
}
|
||||
|
||||
void ArduboyAudio::off()
|
||||
{
|
||||
audio_enabled = false;
|
||||
// shut off audio pins
|
||||
#ifdef ARDUBOY_10
|
||||
pinMode(PIN_SPEAKER_1, INPUT);
|
||||
pinMode(PIN_SPEAKER_2, INPUT);
|
||||
#else
|
||||
pinMode(PIN_SPEAKER_1, INPUT);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ArduboyAudio::saveOnOff()
|
||||
{
|
||||
EEPROM.update(EEPROM_AUDIO_ON_OFF, audio_enabled);
|
||||
}
|
||||
|
||||
void ArduboyAudio::begin()
|
||||
{
|
||||
if (EEPROM.read(EEPROM_AUDIO_ON_OFF))
|
||||
on();
|
||||
}
|
||||
|
||||
bool ArduboyAudio::enabled()
|
||||
{
|
||||
return audio_enabled;
|
||||
}
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
#ifndef ARDUBOY_AUDIO_H
|
||||
#define ARDUBOY_AUDIO_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <EEPROM.h>
|
||||
|
||||
class ArduboyAudio
|
||||
{
|
||||
public:
|
||||
void static begin();
|
||||
void static on();
|
||||
void static off();
|
||||
void static saveOnOff();
|
||||
bool static enabled();
|
||||
|
||||
protected:
|
||||
bool static audio_enabled;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,358 +0,0 @@
|
|||
#include "ArduboyCore.h"
|
||||
|
||||
// need to redeclare these here since we declare them static in .h
|
||||
volatile uint8_t *ArduboyCore::csport, *ArduboyCore::dcport;
|
||||
uint8_t ArduboyCore::cspinmask, ArduboyCore::dcpinmask;
|
||||
|
||||
const uint8_t PROGMEM pinBootProgram[] = {
|
||||
// buttons
|
||||
PIN_LEFT_BUTTON, INPUT_PULLUP,
|
||||
PIN_RIGHT_BUTTON, INPUT_PULLUP,
|
||||
PIN_UP_BUTTON, INPUT_PULLUP,
|
||||
PIN_DOWN_BUTTON, INPUT_PULLUP,
|
||||
PIN_A_BUTTON, INPUT_PULLUP,
|
||||
PIN_B_BUTTON, INPUT_PULLUP,
|
||||
|
||||
// RGB LED (or single blue LED on the DevKit)
|
||||
#ifdef ARDUBOY_10
|
||||
RED_LED, INPUT_PULLUP, // set INPUT_PULLUP to make the pin high when
|
||||
RED_LED, OUTPUT, // set to OUTPUT
|
||||
GREEN_LED, INPUT_PULLUP,
|
||||
GREEN_LED, OUTPUT,
|
||||
#endif
|
||||
BLUE_LED, INPUT_PULLUP,
|
||||
BLUE_LED, OUTPUT,
|
||||
|
||||
// audio is specifically not included here as those pins are handled
|
||||
// separately by `audio.begin()`, `audio.on()` and `audio.off()` in order
|
||||
// to respect the EEPROM audio settings
|
||||
|
||||
// OLED SPI
|
||||
DC, OUTPUT,
|
||||
CS, OUTPUT,
|
||||
RST, OUTPUT,
|
||||
0
|
||||
};
|
||||
|
||||
const uint8_t PROGMEM lcdBootProgram[] = {
|
||||
// boot defaults are commented out but left here incase they
|
||||
// might prove useful for reference
|
||||
//
|
||||
// Further reading: https://www.adafruit.com/datasheets/SSD1306.pdf
|
||||
//
|
||||
// Display Off
|
||||
// 0xAE,
|
||||
|
||||
// Set Display Clock Divisor v = 0xF0
|
||||
// default is 0x80
|
||||
0xD5, 0xF0,
|
||||
|
||||
// Set Multiplex Ratio v = 0x3F
|
||||
// 0xA8, 0x3F,
|
||||
|
||||
// Set Display Offset v = 0
|
||||
// 0xD3, 0x00,
|
||||
|
||||
// Set Start Line (0)
|
||||
// 0x40,
|
||||
|
||||
// Charge Pump Setting v = enable (0x14)
|
||||
// default is disabled
|
||||
0x8D, 0x14,
|
||||
|
||||
// Set Segment Re-map (A0) | (b0001)
|
||||
// default is (b0000)
|
||||
0xA1,
|
||||
|
||||
// Set COM Output Scan Direction
|
||||
0xC8,
|
||||
|
||||
// Set COM Pins v
|
||||
// 0xDA, 0x12,
|
||||
|
||||
// Set Contrast v = 0xCF
|
||||
0x81, 0xCF,
|
||||
|
||||
// Set Precharge = 0xF1
|
||||
0xD9, 0xF1,
|
||||
|
||||
// Set VCom Detect
|
||||
// 0xDB, 0x40,
|
||||
|
||||
// Entire Display ON
|
||||
// 0xA4,
|
||||
|
||||
// Set normal/inverse display
|
||||
// 0xA6,
|
||||
|
||||
// Display On
|
||||
0xAF,
|
||||
|
||||
// set display mode = horizontal addressing mode (0x00)
|
||||
0x20, 0x00,
|
||||
|
||||
// set col address range
|
||||
// 0x21, 0x00, COLUMN_ADDRESS_END,
|
||||
|
||||
// set page address range
|
||||
// 0x22, 0x00, PAGE_ADDRESS_END
|
||||
};
|
||||
|
||||
|
||||
ArduboyCore::ArduboyCore() {}
|
||||
|
||||
void ArduboyCore::boot()
|
||||
{
|
||||
#ifdef ARDUBOY_SET_CPU_8MHZ
|
||||
// ARDUBOY_SET_CPU_8MHZ will be set by the IDE using boards.txt
|
||||
setCPUSpeed8MHz();
|
||||
#endif
|
||||
|
||||
SPI.begin();
|
||||
bootPins();
|
||||
bootOLED();
|
||||
|
||||
#ifdef SAFE_MODE
|
||||
if (buttonsState() == (LEFT_BUTTON | UP_BUTTON))
|
||||
safeMode();
|
||||
#endif
|
||||
|
||||
bootPowerSaving();
|
||||
}
|
||||
|
||||
#ifdef ARDUBOY_SET_CPU_8MHZ
|
||||
// If we're compiling for 8MHz we need to slow the CPU down because the
|
||||
// hardware clock on the Arduboy is 16MHz.
|
||||
// We also need to readjust the PLL prescaler because the Arduino USB code
|
||||
// likely will have incorrectly set it for an 8MHz hardware clock.
|
||||
void ArduboyCore::setCPUSpeed8MHz()
|
||||
{
|
||||
uint8_t oldSREG = SREG;
|
||||
cli(); // suspend interrupts
|
||||
PLLCSR = _BV(PINDIV); // dissable the PLL and set prescale for 16MHz)
|
||||
CLKPR = _BV(CLKPCE); // allow reprogramming clock
|
||||
CLKPR = 1; // set clock divisor to 2 (0b0001)
|
||||
PLLCSR = _BV(PLLE) | _BV(PINDIV); // enable the PLL (with 16MHz prescale)
|
||||
SREG = oldSREG; // restore interrupts
|
||||
}
|
||||
#endif
|
||||
|
||||
void ArduboyCore::bootPins()
|
||||
{
|
||||
uint8_t pin, mode;
|
||||
const uint8_t *i = pinBootProgram;
|
||||
|
||||
while(true) {
|
||||
pin = pgm_read_byte(i++);
|
||||
mode = pgm_read_byte(i++);
|
||||
if (pin==0) break;
|
||||
pinMode(pin, mode);
|
||||
}
|
||||
|
||||
digitalWrite(RST, HIGH);
|
||||
delay(1); // VDD (3.3V) goes high at start, lets just chill for a ms
|
||||
digitalWrite(RST, LOW); // bring reset low
|
||||
delay(10); // wait 10ms
|
||||
digitalWrite(RST, HIGH); // bring out of reset
|
||||
}
|
||||
|
||||
void ArduboyCore::bootOLED()
|
||||
{
|
||||
// setup the ports we need to talk to the OLED
|
||||
csport = portOutputRegister(digitalPinToPort(CS));
|
||||
cspinmask = digitalPinToBitMask(CS);
|
||||
dcport = portOutputRegister(digitalPinToPort(DC));
|
||||
dcpinmask = digitalPinToBitMask(DC);
|
||||
|
||||
SPI.setClockDivider(SPI_CLOCK_DIV2);
|
||||
|
||||
LCDCommandMode();
|
||||
// run our customized boot-up command sequence against the
|
||||
// OLED to initialize it properly for Arduboy
|
||||
for (int8_t i=0; i < sizeof(lcdBootProgram); i++) {
|
||||
SPI.transfer(pgm_read_byte(lcdBootProgram + i));
|
||||
}
|
||||
LCDDataMode();
|
||||
}
|
||||
|
||||
void ArduboyCore::LCDDataMode()
|
||||
{
|
||||
*dcport |= dcpinmask;
|
||||
*csport &= ~cspinmask;
|
||||
}
|
||||
|
||||
void ArduboyCore::LCDCommandMode()
|
||||
{
|
||||
*csport |= cspinmask;
|
||||
*dcport &= ~dcpinmask;
|
||||
*csport &= ~cspinmask;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ArduboyCore::safeMode()
|
||||
{
|
||||
blank(); // too avoid random gibberish
|
||||
while (true) {
|
||||
asm volatile("nop \n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Power Management */
|
||||
|
||||
void ArduboyCore::idle()
|
||||
{
|
||||
set_sleep_mode(SLEEP_MODE_IDLE);
|
||||
sleep_mode();
|
||||
}
|
||||
|
||||
void ArduboyCore::bootPowerSaving()
|
||||
{
|
||||
power_adc_disable();
|
||||
power_usart0_disable();
|
||||
power_twi_disable();
|
||||
// timer 0 is for millis()
|
||||
// timers 1 and 3 are for music and sounds
|
||||
power_timer2_disable();
|
||||
power_usart1_disable();
|
||||
// we need USB, for now (to allow triggered reboots to reprogram)
|
||||
// power_usb_disable()
|
||||
}
|
||||
|
||||
uint8_t ArduboyCore::width() { return WIDTH; }
|
||||
|
||||
uint8_t ArduboyCore::height() { return HEIGHT; }
|
||||
|
||||
|
||||
/* Drawing */
|
||||
|
||||
void ArduboyCore::paint8Pixels(uint8_t pixels)
|
||||
{
|
||||
SPI.transfer(pixels);
|
||||
}
|
||||
|
||||
void ArduboyCore::paintScreen(const uint8_t *image)
|
||||
{
|
||||
for (int i = 0; i < (HEIGHT*WIDTH)/8; i++)
|
||||
{
|
||||
SPI.transfer(pgm_read_byte(image + i));
|
||||
}
|
||||
}
|
||||
|
||||
// paint from a memory buffer, this should be FAST as it's likely what
|
||||
// will be used by any buffer based subclass
|
||||
void ArduboyCore::paintScreen(uint8_t image[])
|
||||
{
|
||||
uint8_t c;
|
||||
int i = 0;
|
||||
|
||||
SPDR = image[i++]; // set the first SPI data byte to get things started
|
||||
|
||||
// the code to iterate the loop and get the next byte from the buffer is
|
||||
// executed while the previous byte is being sent out by the SPI controller
|
||||
while (i < (HEIGHT * WIDTH) / 8)
|
||||
{
|
||||
// get the next byte. It's put in a local variable so it can be sent as
|
||||
// as soon as possible after the sending of the previous byte has completed
|
||||
c = image[i++];
|
||||
|
||||
while (!(SPSR & _BV(SPIF))) { } // wait for the previous byte to be sent
|
||||
|
||||
// put the next byte in the SPI data register. The SPI controller will
|
||||
// clock it out while the loop continues and gets the next byte ready
|
||||
SPDR = c;
|
||||
}
|
||||
while (!(SPSR & _BV(SPIF))) { } // wait for the last byte to be sent
|
||||
}
|
||||
|
||||
void ArduboyCore::blank()
|
||||
{
|
||||
for (int i = 0; i < (HEIGHT*WIDTH)/8; i++)
|
||||
SPI.transfer(0x00);
|
||||
}
|
||||
|
||||
void ArduboyCore::sendLCDCommand(uint8_t command)
|
||||
{
|
||||
LCDCommandMode();
|
||||
SPI.transfer(command);
|
||||
LCDDataMode();
|
||||
}
|
||||
|
||||
// invert the display or set to normal
|
||||
// when inverted, a pixel set to 0 will be on
|
||||
void ArduboyCore::invert(bool inverse)
|
||||
{
|
||||
sendLCDCommand(inverse ? OLED_PIXELS_INVERTED : OLED_PIXELS_NORMAL);
|
||||
}
|
||||
|
||||
// turn all display pixels on, ignoring buffer contents
|
||||
// or set to normal buffer display
|
||||
void ArduboyCore::allPixelsOn(bool on)
|
||||
{
|
||||
sendLCDCommand(on ? OLED_ALL_PIXELS_ON : OLED_PIXELS_FROM_RAM);
|
||||
}
|
||||
|
||||
// flip the display vertically or set to normal
|
||||
void ArduboyCore::flipVertical(bool flipped)
|
||||
{
|
||||
sendLCDCommand(flipped ? OLED_VERTICAL_FLIPPED : OLED_VERTICAL_NORMAL);
|
||||
}
|
||||
|
||||
// flip the display horizontally or set to normal
|
||||
void ArduboyCore::flipHorizontal(bool flipped)
|
||||
{
|
||||
sendLCDCommand(flipped ? OLED_HORIZ_FLIPPED : OLED_HORIZ_NORMAL);
|
||||
}
|
||||
|
||||
/* RGB LED */
|
||||
|
||||
void ArduboyCore::setRGBled(uint8_t red, uint8_t green, uint8_t blue)
|
||||
{
|
||||
#ifdef ARDUBOY_10 // RGB, all the pretty colors
|
||||
// inversion is necessary because these are common annode LEDs
|
||||
analogWrite(RED_LED, 255 - red);
|
||||
analogWrite(GREEN_LED, 255 - green);
|
||||
analogWrite(BLUE_LED, 255 - blue);
|
||||
#elif defined(AB_DEVKIT)
|
||||
// only blue on devkit
|
||||
digitalWrite(BLUE_LED, ~blue);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ArduboyCore::digitalWriteRGB(uint8_t red, uint8_t green, uint8_t blue)
|
||||
{
|
||||
#ifdef ARDUBOY_10
|
||||
digitalWrite(RED_LED, red);
|
||||
digitalWrite(GREEN_LED, green);
|
||||
digitalWrite(BLUE_LED, blue);
|
||||
#elif defined(AB_DEVKIT)
|
||||
digitalWrite(BLUE_LED, blue);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Buttons */
|
||||
|
||||
uint8_t ArduboyCore::buttonsState()
|
||||
{
|
||||
uint8_t buttons;
|
||||
|
||||
// using ports here is ~100 bytes smaller than digitalRead()
|
||||
#ifdef AB_DEVKIT
|
||||
// down, left, up
|
||||
buttons = ((~PINB) & B01110000);
|
||||
// right button
|
||||
buttons = buttons | (((~PINC) & B01000000) >> 4);
|
||||
// A and B
|
||||
buttons = buttons | (((~PINF) & B11000000) >> 6);
|
||||
#elif defined(ARDUBOY_10)
|
||||
// down, up, left right
|
||||
buttons = ((~PINF) & B11110000);
|
||||
// A (left)
|
||||
buttons = buttons | (((~PINE) & B01000000) >> 3);
|
||||
// B (right)
|
||||
buttons = buttons | (((~PINB) & B00010000) >> 2);
|
||||
#endif
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
|
@ -1,308 +0,0 @@
|
|||
#ifndef ARDUBOY_CORE_H
|
||||
#define ARDUBOY_CORE_H
|
||||
|
||||
#include <avr/power.h>
|
||||
#include <SPI.h>
|
||||
#include <avr/sleep.h>
|
||||
#include <limits.h>
|
||||
|
||||
|
||||
// main hardware compile flags
|
||||
|
||||
#if !defined(ARDUBOY_10) && !defined(AB_DEVKIT)
|
||||
/// 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
|
||||
*
|
||||
* if you wish to compile for the devkit without using a boards.txt
|
||||
* file simply comment out the ARDUBOY_10 define and uncomment
|
||||
* the AB_DEVKIT define like this:
|
||||
*
|
||||
* // #define ARDUBOY_10
|
||||
* #define AB_DEVKIT
|
||||
*/
|
||||
#define ARDUBOY_10 //< compile for the production Arduboy v1.0
|
||||
// #define AB_DEVKIT //< compile for the official dev kit
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef AB_DEVKIT
|
||||
#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
|
||||
|
||||
#ifdef ARDUBOY_10
|
||||
|
||||
#define CS 12
|
||||
#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
|
||||
|
||||
// pin values for buttons, probably shouldn't use these
|
||||
#define PIN_LEFT_BUTTON A2
|
||||
#define PIN_RIGHT_BUTTON A1
|
||||
#define PIN_UP_BUTTON A0
|
||||
#define PIN_DOWN_BUTTON A3
|
||||
#define PIN_A_BUTTON 7
|
||||
#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 PIN_SPEAKER_1 5
|
||||
#define PIN_SPEAKER_2 13
|
||||
|
||||
#define PIN_SPEAKER_1_PORT &PORTC
|
||||
#define PIN_SPEAKER_2_PORT &PORTC
|
||||
|
||||
#define PIN_SPEAKER_1_BITMASK _BV(6)
|
||||
#define PIN_SPEAKER_2_BITMASK _BV(7)
|
||||
|
||||
#elif defined(AB_DEVKIT)
|
||||
|
||||
#define CS 6
|
||||
#define DC 4
|
||||
#define RST 12
|
||||
|
||||
// map all LEDs to the single TX LED on DEVKIT
|
||||
#define RED_LED 17
|
||||
#define GREEN_LED 17
|
||||
#define BLUE_LED 17
|
||||
#define TX_LED 17
|
||||
#define RX_LED 17
|
||||
|
||||
// pin values for buttons, probably shouldn't use these
|
||||
#define PIN_LEFT_BUTTON 9
|
||||
#define PIN_RIGHT_BUTTON 5
|
||||
#define PIN_UP_BUTTON 8
|
||||
#define PIN_DOWN_BUTTON 10
|
||||
#define PIN_A_BUTTON A0
|
||||
#define PIN_B_BUTTON A1
|
||||
|
||||
// bit values for button states
|
||||
#define LEFT_BUTTON _BV(5)
|
||||
#define RIGHT_BUTTON _BV(2)
|
||||
#define UP_BUTTON _BV(4)
|
||||
#define DOWN_BUTTON _BV(6)
|
||||
#define A_BUTTON _BV(1)
|
||||
#define B_BUTTON _BV(0)
|
||||
|
||||
#define PIN_SPEAKER_1 A2
|
||||
#define PIN_SPEAKER_1_PORT &PORTF
|
||||
#define PIN_SPEAKER_1_BITMASK _BV(5)
|
||||
// SPEAKER_2 is purposely not defined for DEVKIT as it could potentially
|
||||
// be dangerous and fry your hardware (because of the devkit wiring).
|
||||
//
|
||||
// Reference: https://github.com/Arduboy/Arduboy/issues/108
|
||||
|
||||
#endif
|
||||
|
||||
// OLED hardware (SSD1306)
|
||||
|
||||
#define OLED_PIXELS_INVERTED 0xA7 // All pixels inverted
|
||||
#define OLED_PIXELS_NORMAL 0xA6 // All pixels normal
|
||||
|
||||
#define OLED_ALL_PIXELS_ON 0xA5 // all pixels on
|
||||
#define OLED_PIXELS_FROM_RAM 0xA4 // pixels mapped to display RAM contents
|
||||
|
||||
#define OLED_VERTICAL_FLIPPED 0xC0 // reversed COM scan direction
|
||||
#define OLED_VERTICAL_NORMAL 0xC8 // normal COM scan direction
|
||||
|
||||
#define OLED_HORIZ_FLIPPED 0xA0 // reversed segment re-map
|
||||
#define OLED_HORIZ_NORMAL 0xA1 // normal segment re-map
|
||||
|
||||
// -----
|
||||
|
||||
#define WIDTH 128
|
||||
#define HEIGHT 64
|
||||
|
||||
#define COLUMN_ADDRESS_END (WIDTH - 1) & 127 // 128 pixels wide
|
||||
#define PAGE_ADDRESS_END ((HEIGHT/8)-1) & 7 // 8 pages high
|
||||
|
||||
|
||||
class ArduboyCore
|
||||
{
|
||||
public:
|
||||
ArduboyCore();
|
||||
|
||||
/// 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
|
||||
* 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
|
||||
|
||||
/// put the display in command mode
|
||||
/**
|
||||
* See SSD1306 documents for available commands and command sequences.
|
||||
*
|
||||
* Links:
|
||||
* - https://www.adafruit.com/datasheets/SSD1306.pdf
|
||||
* - http://www.eimodule.com/download/SSD1306-OLED-Controller.pdf
|
||||
*/
|
||||
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:
|
||||
*
|
||||
* Hi Low
|
||||
* DevKit 00000000 - reserved
|
||||
* -DLU-RAB D down
|
||||
* U up
|
||||
* 1.0 00000000 L left
|
||||
* URLDAB-- R right
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
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)
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
void static paintScreen(uint8_t image[]);
|
||||
|
||||
/// paints a blank (black) screen to hardware
|
||||
void static blank();
|
||||
|
||||
/// invert the display or set to normal
|
||||
/**
|
||||
* when inverted, a pixel set to 0 will be on
|
||||
*/
|
||||
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
|
||||
*/
|
||||
void static allPixelsOn(bool on);
|
||||
|
||||
/// flip the display vertically or set to normal
|
||||
void static flipVertical(bool flipped);
|
||||
|
||||
/// flip the display horizontally or set to normal
|
||||
void static flipHorizontal(bool flipped);
|
||||
|
||||
/// send a single byte command to the OLED
|
||||
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).
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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
|
||||
* 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.
|
||||
*
|
||||
* This is most useful on Devkits because they lack a built-in reset
|
||||
* button.
|
||||
*/
|
||||
void static inline safeMode() __attribute__((always_inline));
|
||||
|
||||
// internals
|
||||
void static inline setCPUSpeed8MHz() __attribute__((always_inline));
|
||||
void static inline bootOLED() __attribute__((always_inline));
|
||||
void static inline bootPins() __attribute__((always_inline));
|
||||
void static inline bootPowerSaving() __attribute__((always_inline));
|
||||
|
||||
|
||||
private:
|
||||
volatile static uint8_t *csport, *dcport;
|
||||
uint8_t static cspinmask, dcpinmask;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,364 @@
|
|||
/**
|
||||
* @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,
|
||||
const uint8_t *mask, uint8_t frame, uint8_t mask_frame)
|
||||
{
|
||||
draw(x, y, bitmap, frame, mask, mask_frame, SPRITE_MASKED);
|
||||
}
|
||||
|
||||
void Sprites::drawOverwrite(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t frame)
|
||||
{
|
||||
draw(x, y, bitmap, frame, NULL, 0, SPRITE_OVERWRITE);
|
||||
}
|
||||
|
||||
void Sprites::drawErase(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t frame)
|
||||
{
|
||||
draw(x, y, bitmap, frame, NULL, 0, SPRITE_IS_MASK_ERASE);
|
||||
}
|
||||
|
||||
void Sprites::drawSelfMasked(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t frame)
|
||||
{
|
||||
draw(x, y, bitmap, frame, NULL, 0, SPRITE_IS_MASK);
|
||||
}
|
||||
|
||||
void Sprites::drawPlusMask(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t frame)
|
||||
{
|
||||
draw(x, y, bitmap, frame, NULL, 0, SPRITE_PLUS_MASK);
|
||||
}
|
||||
|
||||
|
||||
//common functions
|
||||
void Sprites::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)
|
||||
{
|
||||
unsigned int frame_offset;
|
||||
|
||||
if (bitmap == NULL)
|
||||
return;
|
||||
|
||||
uint8_t width = pgm_read_byte(bitmap);
|
||||
uint8_t height = pgm_read_byte(++bitmap);
|
||||
bitmap++;
|
||||
if (frame > 0 || sprite_frame > 0) {
|
||||
frame_offset = (width * ( height / 8 + ( height % 8 == 0 ? 0 : 1)));
|
||||
// sprite plus mask uses twice as much space for each frame
|
||||
if (drawMode == SPRITE_PLUS_MASK) {
|
||||
frame_offset *= 2;
|
||||
} else if (mask != NULL) {
|
||||
mask += sprite_frame * frame_offset;
|
||||
}
|
||||
bitmap += frame * frame_offset;
|
||||
}
|
||||
|
||||
// if we're detecting the draw mode then base it on whether a mask
|
||||
// was passed as a separate object
|
||||
if (drawMode == SPRITE_AUTO_MODE) {
|
||||
drawMode = mask == NULL ? SPRITE_UNMASKED : SPRITE_MASKED;
|
||||
}
|
||||
|
||||
drawBitmap(x, y, bitmap, mask, width, height, drawMode);
|
||||
}
|
||||
|
||||
void Sprites::drawBitmap(int16_t x, int16_t y,
|
||||
const uint8_t *bitmap, const uint8_t *mask,
|
||||
uint8_t w, uint8_t h, uint8_t draw_mode)
|
||||
{
|
||||
// no need to draw at all of we're offscreen
|
||||
if (x + w <= 0 || x > WIDTH - 1 || y + h <= 0 || y > HEIGHT - 1)
|
||||
return;
|
||||
|
||||
if (bitmap == NULL)
|
||||
return;
|
||||
|
||||
// xOffset technically doesn't need to be 16 bit but the math operations
|
||||
// are measurably faster if it is
|
||||
uint16_t xOffset, ofs;
|
||||
int8_t yOffset = y & 7;
|
||||
int8_t sRow = y / 8;
|
||||
uint8_t loop_h, start_h, rendered_width;
|
||||
|
||||
if (y < 0 && yOffset > 0) {
|
||||
sRow--;
|
||||
}
|
||||
|
||||
// if the left side of the render is offscreen skip those loops
|
||||
if (x < 0) {
|
||||
xOffset = abs(x);
|
||||
} else {
|
||||
xOffset = 0;
|
||||
}
|
||||
|
||||
// if the right side of the render is offscreen skip those loops
|
||||
if (x + w > WIDTH - 1) {
|
||||
rendered_width = ((WIDTH - x) - xOffset);
|
||||
} else {
|
||||
rendered_width = (w - xOffset);
|
||||
}
|
||||
|
||||
// if the top side of the render is offscreen skip those loops
|
||||
if (sRow < -1) {
|
||||
start_h = abs(sRow) - 1;
|
||||
} else {
|
||||
start_h = 0;
|
||||
}
|
||||
|
||||
loop_h = h / 8 + (h % 8 > 0 ? 1 : 0); // divide, then round up
|
||||
|
||||
// if (sRow + loop_h - 1 > (HEIGHT/8)-1)
|
||||
if (sRow + loop_h > (HEIGHT / 8)) {
|
||||
loop_h = (HEIGHT / 8) - sRow;
|
||||
}
|
||||
|
||||
// prepare variables for loops later so we can compare with 0
|
||||
// instead of comparing two variables
|
||||
loop_h -= start_h;
|
||||
|
||||
sRow += start_h;
|
||||
ofs = (sRow * WIDTH) + x + xOffset;
|
||||
uint8_t *bofs = (uint8_t *)bitmap + (start_h * w) + xOffset;
|
||||
uint8_t data;
|
||||
|
||||
uint8_t mul_amt = 1 << yOffset;
|
||||
uint16_t mask_data;
|
||||
uint16_t bitmap_data;
|
||||
|
||||
switch (draw_mode) {
|
||||
case SPRITE_UNMASKED:
|
||||
// we only want to mask the 8 bits of our own sprite, so we can
|
||||
// calculate the mask before the start of the loop
|
||||
mask_data = ~(0xFF * mul_amt);
|
||||
// really if yOffset = 0 you have a faster case here that could be
|
||||
// optimized
|
||||
for (uint8_t a = 0; a < loop_h; a++) {
|
||||
for (uint8_t iCol = 0; iCol < rendered_width; iCol++) {
|
||||
bitmap_data = pgm_read_byte(bofs) * mul_amt;
|
||||
|
||||
if (sRow >= 0) {
|
||||
data = Arduboy2Base::sBuffer[ofs];
|
||||
data &= (uint8_t)(mask_data);
|
||||
data |= (uint8_t)(bitmap_data);
|
||||
Arduboy2Base::sBuffer[ofs] = data;
|
||||
}
|
||||
if (yOffset != 0 && sRow < 7) {
|
||||
const size_t index = static_cast<uint16_t>(ofs + WIDTH);
|
||||
data = Arduboy2Base::sBuffer[index];
|
||||
data &= (uint8_t)(mask_data >> 8);
|
||||
data |= (uint8_t)(bitmap_data >> 8);
|
||||
Arduboy2Base::sBuffer[index] = data;
|
||||
}
|
||||
ofs++;
|
||||
bofs++;
|
||||
}
|
||||
sRow++;
|
||||
bofs += w - rendered_width;
|
||||
ofs += WIDTH - rendered_width;
|
||||
}
|
||||
break;
|
||||
|
||||
case SPRITE_IS_MASK:
|
||||
for (uint8_t a = 0; a < loop_h; a++) {
|
||||
for (uint8_t iCol = 0; iCol < rendered_width; iCol++) {
|
||||
bitmap_data = pgm_read_byte(bofs) * mul_amt;
|
||||
if (sRow >= 0) {
|
||||
Arduboy2Base::sBuffer[ofs] |= (uint8_t)(bitmap_data);
|
||||
}
|
||||
if (yOffset != 0 && sRow < 7) {
|
||||
const size_t index = static_cast<uint16_t>(ofs + WIDTH);
|
||||
Arduboy2Base::sBuffer[index] |= (uint8_t)(bitmap_data >> 8);
|
||||
}
|
||||
ofs++;
|
||||
bofs++;
|
||||
}
|
||||
sRow++;
|
||||
bofs += w - rendered_width;
|
||||
ofs += WIDTH - rendered_width;
|
||||
}
|
||||
break;
|
||||
|
||||
case SPRITE_IS_MASK_ERASE:
|
||||
for (uint8_t a = 0; a < loop_h; a++) {
|
||||
for (uint8_t iCol = 0; iCol < rendered_width; iCol++) {
|
||||
bitmap_data = pgm_read_byte(bofs) * mul_amt;
|
||||
if (sRow >= 0) {
|
||||
Arduboy2Base::sBuffer[ofs] &= ~(uint8_t)(bitmap_data);
|
||||
}
|
||||
if (yOffset != 0 && sRow < 7) {
|
||||
const size_t index = static_cast<uint16_t>(ofs + WIDTH);
|
||||
Arduboy2Base::sBuffer[index] &= ~(uint8_t)(bitmap_data >> 8);
|
||||
}
|
||||
ofs++;
|
||||
bofs++;
|
||||
}
|
||||
sRow++;
|
||||
bofs += w - rendered_width;
|
||||
ofs += WIDTH - rendered_width;
|
||||
}
|
||||
break;
|
||||
|
||||
case SPRITE_MASKED:
|
||||
uint8_t *mask_ofs;
|
||||
mask_ofs = (uint8_t *)mask + (start_h * w) + xOffset;
|
||||
for (uint8_t a = 0; a < loop_h; a++) {
|
||||
for (uint8_t iCol = 0; iCol < rendered_width; iCol++) {
|
||||
// NOTE: you might think in the yOffset==0 case that this results
|
||||
// in more effort, but in all my testing the compiler was forcing
|
||||
// 16-bit math to happen here anyways, so this isn't actually
|
||||
// compiling to more code than it otherwise would. If the offset
|
||||
// is 0 the high part of the word will just never be used.
|
||||
|
||||
// load data and bit shift
|
||||
// mask needs to be bit flipped
|
||||
mask_data = ~(pgm_read_byte(mask_ofs) * mul_amt);
|
||||
bitmap_data = pgm_read_byte(bofs) * mul_amt;
|
||||
|
||||
if (sRow >= 0) {
|
||||
data = Arduboy2Base::sBuffer[ofs];
|
||||
data &= (uint8_t)(mask_data);
|
||||
data |= (uint8_t)(bitmap_data);
|
||||
Arduboy2Base::sBuffer[ofs] = data;
|
||||
}
|
||||
if (yOffset != 0 && sRow < 7) {
|
||||
const size_t index = static_cast<uint16_t>(ofs + WIDTH);
|
||||
data = Arduboy2Base::sBuffer[index];
|
||||
data &= (uint8_t)(mask_data >> 8);
|
||||
data |= (uint8_t)(bitmap_data >> 8);
|
||||
Arduboy2Base::sBuffer[index] = data;
|
||||
}
|
||||
ofs++;
|
||||
mask_ofs++;
|
||||
bofs++;
|
||||
}
|
||||
sRow++;
|
||||
bofs += w - rendered_width;
|
||||
mask_ofs += w - rendered_width;
|
||||
ofs += WIDTH - rendered_width;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case SPRITE_PLUS_MASK:
|
||||
// *2 because we use double the bits (mask + bitmap)
|
||||
bofs = (uint8_t *)(bitmap + ((start_h * w) + xOffset) * 2);
|
||||
|
||||
uint8_t xi = rendered_width; // counter for x loop below
|
||||
|
||||
asm volatile(
|
||||
"push r28\n" // save Y
|
||||
"push r29\n"
|
||||
"movw r28, %[buffer_ofs]\n" // Y = buffer_ofs_2
|
||||
"adiw r28, 63\n" // buffer_ofs_2 = buffer_ofs + 128
|
||||
"adiw r28, 63\n"
|
||||
"adiw r28, 2\n"
|
||||
"loop_y:\n"
|
||||
"loop_x:\n"
|
||||
// load bitmap and mask data
|
||||
"lpm %A[bitmap_data], Z+\n"
|
||||
"lpm %A[mask_data], Z+\n"
|
||||
|
||||
// shift mask and buffer data
|
||||
"tst %[yOffset]\n"
|
||||
"breq skip_shifting\n"
|
||||
"mul %A[bitmap_data], %[mul_amt]\n"
|
||||
"movw %[bitmap_data], r0\n"
|
||||
"mul %A[mask_data], %[mul_amt]\n"
|
||||
"movw %[mask_data], r0\n"
|
||||
|
||||
// SECOND PAGE
|
||||
// if yOffset != 0 && sRow < 7
|
||||
"cpi %[sRow], 7\n"
|
||||
"brge end_second_page\n"
|
||||
// then
|
||||
"ld %[data], Y\n"
|
||||
"com %B[mask_data]\n" // invert high byte of mask
|
||||
"and %[data], %B[mask_data]\n"
|
||||
"or %[data], %B[bitmap_data]\n"
|
||||
// update buffer, increment
|
||||
"st Y+, %[data]\n"
|
||||
|
||||
"end_second_page:\n"
|
||||
"skip_shifting:\n"
|
||||
|
||||
// FIRST PAGE
|
||||
// if sRow >= 0
|
||||
"tst %[sRow]\n"
|
||||
"brmi skip_first_page\n"
|
||||
"ld %[data], %a[buffer_ofs]\n"
|
||||
// then
|
||||
"com %A[mask_data]\n"
|
||||
"and %[data], %A[mask_data]\n"
|
||||
"or %[data], %A[bitmap_data]\n"
|
||||
// update buffer, increment
|
||||
"st %a[buffer_ofs]+, %[data]\n"
|
||||
"jmp end_first_page\n"
|
||||
|
||||
"skip_first_page:\n"
|
||||
// since no ST Z+ when skipped we need to do this manually
|
||||
"adiw %[buffer_ofs], 1\n"
|
||||
|
||||
"end_first_page:\n"
|
||||
|
||||
// "x_loop_next:\n"
|
||||
"dec %[xi]\n"
|
||||
"brne loop_x\n"
|
||||
|
||||
// increment y
|
||||
"next_loop_y:\n"
|
||||
"dec %[yi]\n"
|
||||
"breq finished\n"
|
||||
"mov %[xi], %[x_count]\n" // reset x counter
|
||||
// sRow++;
|
||||
"inc %[sRow]\n"
|
||||
"clr __zero_reg__\n"
|
||||
// sprite_ofs += (w - rendered_width) * 2;
|
||||
"add %A[sprite_ofs], %A[sprite_ofs_jump]\n"
|
||||
"adc %B[sprite_ofs], __zero_reg__\n"
|
||||
// buffer_ofs += WIDTH - rendered_width;
|
||||
"add %A[buffer_ofs], %A[buffer_ofs_jump]\n"
|
||||
"adc %B[buffer_ofs], __zero_reg__\n"
|
||||
// buffer_ofs_page_2 += WIDTH - rendered_width;
|
||||
"add r28, %A[buffer_ofs_jump]\n"
|
||||
"adc r29, __zero_reg__\n"
|
||||
|
||||
"rjmp loop_y\n"
|
||||
"finished:\n"
|
||||
// put the Y register back in place
|
||||
"pop r29\n"
|
||||
"pop r28\n"
|
||||
"clr __zero_reg__\n" // just in case
|
||||
: [xi] "+&a" (xi),
|
||||
[yi] "+&a" (loop_h),
|
||||
[sRow] "+&a" (sRow), // CPI requires an upper register (r16-r23)
|
||||
[data] "=&l" (data),
|
||||
[mask_data] "=&l" (mask_data),
|
||||
[bitmap_data] "=&l" (bitmap_data)
|
||||
:
|
||||
[screen_width] "M" (WIDTH),
|
||||
[x_count] "l" (rendered_width), // lower register
|
||||
[sprite_ofs] "z" (bofs),
|
||||
[buffer_ofs] "x" (Arduboy2Base::sBuffer+ofs),
|
||||
[buffer_ofs_jump] "a" (WIDTH-rendered_width), // upper reg (r16-r23)
|
||||
[sprite_ofs_jump] "a" ((w-rendered_width)*2), // upper reg (r16-r23)
|
||||
|
||||
// [sprite_ofs_jump] "r" (0),
|
||||
[yOffset] "l" (yOffset), // lower register
|
||||
[mul_amt] "l" (mul_amt) // lower register
|
||||
// NOTE: We also clobber r28 and r29 (y) but sometimes the compiler
|
||||
// won't allow us, so in order to make this work we don't tell it
|
||||
// that we clobber them. Instead, we push/pop to preserve them.
|
||||
// Then we need to guarantee that the the compiler doesn't put one of
|
||||
// our own variables into r28/r29.
|
||||
// We do that by specifying all the inputs and outputs use either
|
||||
// lower registers (l) or simple (r16-r23) upper registers (a).
|
||||
: // pushes/clobbers/pops r28 and r29 (y)
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,260 @@
|
|||
/**
|
||||
* @file Sprites.h
|
||||
* \brief
|
||||
* A class for drawing animated sprites from image and mask bitmaps.
|
||||
*/
|
||||
|
||||
#ifndef Sprites_h
|
||||
#define Sprites_h
|
||||
|
||||
#include "Arduboy2.h"
|
||||
#include "SpritesCommon.h"
|
||||
|
||||
/** \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 image 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.
|
||||
*
|
||||
* For a separate mask array, as is used with `drawExternalMask()`, the width
|
||||
* and height are not included but must contain data of the same dimensions
|
||||
* as the corresponding image array.
|
||||
*
|
||||
* Following the width and height values for an image array, or from the
|
||||
* beginning of a separate mask array, 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.
|
||||
*
|
||||
* \note
|
||||
* \parblock
|
||||
* A separate `SpritesB` class is available as an alternative to this class.
|
||||
* The only difference is that the `SpritesB` class is optimized for small
|
||||
* code size rather than for execution speed. One or the other can be used
|
||||
* depending on whether size or speed is more important.
|
||||
*
|
||||
* Even if the speed is acceptable when using `SpritesB`, you should still try
|
||||
* using `Sprites`. In some cases `Sprites` will produce less code than
|
||||
* `SpritesB`, notably when only one of the functions is used.
|
||||
*
|
||||
* You can easily switch between using the `Sprites` class or the `SpritesB`
|
||||
* class by using one or the other to create an object instance:
|
||||
*
|
||||
* \code{.cpp}
|
||||
* Sprites sprites; // Use this to optimize for execution speed
|
||||
* SpritesB sprites; // Use this to (likely) optimize for code size
|
||||
* \endcode
|
||||
* \endparblock
|
||||
*
|
||||
* \note
|
||||
* \parblock
|
||||
* In the example patterns given in each Sprites function description,
|
||||
* a # character represents a bit set to 1 and
|
||||
* a - character represents a bit set to 0.
|
||||
* \endparblock
|
||||
*
|
||||
* \see SpritesB
|
||||
*/
|
||||
class Sprites
|
||||
{
|
||||
public:
|
||||
/** \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.
|
||||
*
|
||||
* For the mask array, the width and height are not included but must
|
||||
* contain data of the same dimensions as the corresponding image array.
|
||||
*
|
||||
* 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 (# = 1, - = 0)
|
||||
*
|
||||
* ----- -###- ----- -----
|
||||
* --#-- ##### ----- --#--
|
||||
* ##-## ##-## ----- ##-##
|
||||
* --#-- ##### ----- --#--
|
||||
* ----- -###- ----- -----
|
||||
*
|
||||
* image mask before after
|
||||
*
|
||||
* ----- -###- ##### #---#
|
||||
* --#-- ##### ##### --#--
|
||||
* ##-## ##### ##### ##-##
|
||||
* --#-- ##### ##### --#--
|
||||
* ----- -###- ##### #---#
|
||||
*/
|
||||
static void drawExternalMask(int16_t x, int16_t y, const uint8_t *bitmap,
|
||||
const uint8_t *mask, uint8_t frame, uint8_t mask_frame);
|
||||
|
||||
/** \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 (# = 1, - = 0)
|
||||
*
|
||||
* ----- -###- ----- -----
|
||||
* --#-- ##### ----- --#--
|
||||
* ##-## ##-## ----- ##-##
|
||||
* --#-- ##### ----- --#--
|
||||
* ----- -###- ----- -----
|
||||
*
|
||||
* image mask before after
|
||||
*
|
||||
* ----- -###- ##### #---#
|
||||
* --#-- ##### ##### --#--
|
||||
* ##-## ##### ##### ##-##
|
||||
* --#-- ##### ##### --#--
|
||||
* ----- -###- ##### #---#
|
||||
*/
|
||||
static void drawPlusMask(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t frame);
|
||||
|
||||
/** \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 (# = 1, - = 0)
|
||||
*
|
||||
* ----- ----- -----
|
||||
* --#-- ----- --#--
|
||||
* ##-## ----- ##-##
|
||||
* --#-- ----- --#--
|
||||
* ----- ----- -----
|
||||
*
|
||||
* image before after
|
||||
*
|
||||
* ----- ##### -----
|
||||
* --#-- ##### --#--
|
||||
* ##-## ##### ##-##
|
||||
* --#-- ##### --#--
|
||||
* ----- ##### -----
|
||||
*/
|
||||
static void drawOverwrite(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t frame);
|
||||
|
||||
/** \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 (# = 1, - = 0)
|
||||
*
|
||||
* ----- ----- -----
|
||||
* --#-- ----- -----
|
||||
* ##-## ----- -----
|
||||
* --#-- ----- -----
|
||||
* ----- ----- -----
|
||||
*
|
||||
* image before after
|
||||
*
|
||||
* ----- ##### #####
|
||||
* --#-- ##### ##-##
|
||||
* ##-## ##### --#--
|
||||
* --#-- ##### ##-##
|
||||
* ----- ##### #####
|
||||
*/
|
||||
static void drawErase(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t frame);
|
||||
|
||||
/** \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 (# = 1, - = 0)
|
||||
*
|
||||
* ----- ----- -----
|
||||
* --#-- ----- --#--
|
||||
* ##-## ----- ##-##
|
||||
* --#-- ----- --#--
|
||||
* ----- ----- -----
|
||||
*
|
||||
* image before after
|
||||
*
|
||||
* ----- ##### ##### (no change because all pixels were
|
||||
* --#-- ##### ##### already white)
|
||||
* ##-## ##### #####
|
||||
* --#-- ##### #####
|
||||
* ----- ##### #####
|
||||
*/
|
||||
static 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.
|
||||
// (Not officially part of the API)
|
||||
static 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)
|
||||
static void drawBitmap(int16_t x, int16_t y,
|
||||
const uint8_t *bitmap, const uint8_t *mask,
|
||||
uint8_t w, uint8_t h, uint8_t draw_mode);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,177 @@
|
|||
/**
|
||||
* @file SpritesB.cpp
|
||||
* \brief
|
||||
* A class for drawing animated sprites from image and mask bitmaps.
|
||||
* Optimized for small code size.
|
||||
*/
|
||||
|
||||
#include "SpritesB.h"
|
||||
|
||||
void SpritesB::drawExternalMask(int16_t x, int16_t y, const uint8_t *bitmap,
|
||||
const uint8_t *mask, uint8_t frame, uint8_t mask_frame)
|
||||
{
|
||||
draw(x, y, bitmap, frame, mask, mask_frame, SPRITE_MASKED);
|
||||
}
|
||||
|
||||
void SpritesB::drawOverwrite(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t frame)
|
||||
{
|
||||
draw(x, y, bitmap, frame, NULL, 0, SPRITE_OVERWRITE);
|
||||
}
|
||||
|
||||
void SpritesB::drawErase(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t frame)
|
||||
{
|
||||
draw(x, y, bitmap, frame, NULL, 0, SPRITE_IS_MASK_ERASE);
|
||||
}
|
||||
|
||||
void SpritesB::drawSelfMasked(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t frame)
|
||||
{
|
||||
draw(x, y, bitmap, frame, NULL, 0, SPRITE_IS_MASK);
|
||||
}
|
||||
|
||||
void SpritesB::drawPlusMask(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t frame)
|
||||
{
|
||||
draw(x, y, bitmap, frame, NULL, 0, SPRITE_PLUS_MASK);
|
||||
}
|
||||
|
||||
|
||||
//common functions
|
||||
void SpritesB::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)
|
||||
{
|
||||
unsigned int frame_offset;
|
||||
|
||||
if (bitmap == NULL)
|
||||
return;
|
||||
|
||||
uint8_t width = pgm_read_byte(bitmap);
|
||||
uint8_t height = pgm_read_byte(++bitmap);
|
||||
bitmap++;
|
||||
if (frame > 0 || sprite_frame > 0) {
|
||||
frame_offset = (width * ( height / 8 + ( height % 8 == 0 ? 0 : 1)));
|
||||
// sprite plus mask uses twice as much space for each frame
|
||||
if (drawMode == SPRITE_PLUS_MASK) {
|
||||
frame_offset *= 2;
|
||||
} else if (mask != NULL) {
|
||||
mask += sprite_frame * frame_offset;
|
||||
}
|
||||
bitmap += frame * frame_offset;
|
||||
}
|
||||
|
||||
// if we're detecting the draw mode then base it on whether a mask
|
||||
// was passed as a separate object
|
||||
if (drawMode == SPRITE_AUTO_MODE) {
|
||||
drawMode = mask == NULL ? SPRITE_UNMASKED : SPRITE_MASKED;
|
||||
}
|
||||
|
||||
drawBitmap(x, y, bitmap, mask, width, height, drawMode);
|
||||
}
|
||||
|
||||
void SpritesB::drawBitmap(int16_t x, int16_t y,
|
||||
const uint8_t *bitmap, const uint8_t *mask,
|
||||
uint8_t w, uint8_t h, uint8_t draw_mode)
|
||||
{
|
||||
// no need to draw at all of we're offscreen
|
||||
if (x + w <= 0 || x > WIDTH - 1 || y + h <= 0 || y > HEIGHT - 1)
|
||||
return;
|
||||
|
||||
if (bitmap == NULL)
|
||||
return;
|
||||
|
||||
// xOffset technically doesn't need to be 16 bit but the math operations
|
||||
// are measurably faster if it is
|
||||
uint16_t xOffset, ofs;
|
||||
int8_t yOffset = y & 7;
|
||||
int8_t sRow = y / 8;
|
||||
uint8_t loop_h, start_h, rendered_width;
|
||||
|
||||
if (y < 0 && yOffset > 0) {
|
||||
sRow--;
|
||||
}
|
||||
|
||||
// if the left side of the render is offscreen skip those loops
|
||||
if (x < 0) {
|
||||
xOffset = abs(x);
|
||||
} else {
|
||||
xOffset = 0;
|
||||
}
|
||||
|
||||
// if the right side of the render is offscreen skip those loops
|
||||
if (x + w > WIDTH - 1) {
|
||||
rendered_width = ((WIDTH - x) - xOffset);
|
||||
} else {
|
||||
rendered_width = (w - xOffset);
|
||||
}
|
||||
|
||||
// if the top side of the render is offscreen skip those loops
|
||||
if (sRow < -1) {
|
||||
start_h = abs(sRow) - 1;
|
||||
} else {
|
||||
start_h = 0;
|
||||
}
|
||||
|
||||
loop_h = h / 8 + (h % 8 > 0 ? 1 : 0); // divide, then round up
|
||||
|
||||
// if (sRow + loop_h - 1 > (HEIGHT/8)-1)
|
||||
if (sRow + loop_h > (HEIGHT / 8)) {
|
||||
loop_h = (HEIGHT / 8) - sRow;
|
||||
}
|
||||
|
||||
// prepare variables for loops later so we can compare with 0
|
||||
// instead of comparing two variables
|
||||
loop_h -= start_h;
|
||||
|
||||
sRow += start_h;
|
||||
ofs = (sRow * WIDTH) + x + xOffset;
|
||||
|
||||
uint8_t mul_amt = 1 << yOffset;
|
||||
uint16_t mask_data;
|
||||
uint16_t bitmap_data;
|
||||
|
||||
const uint8_t ofs_step = draw_mode == SPRITE_PLUS_MASK ? 2 : 1;
|
||||
const uint8_t ofs_stride = (w - rendered_width)*ofs_step;
|
||||
const uint16_t initial_bofs = ((start_h * w) + xOffset)*ofs_step;
|
||||
|
||||
const uint8_t *bofs = bitmap + initial_bofs;
|
||||
const uint8_t *mask_ofs = !mask ? bitmap : mask;
|
||||
mask_ofs += initial_bofs + ofs_step - 1;
|
||||
|
||||
for (uint8_t a = 0; a < loop_h; a++) {
|
||||
for (uint8_t iCol = 0; iCol < rendered_width; iCol++) {
|
||||
uint8_t data;
|
||||
|
||||
bitmap_data = pgm_read_byte(bofs) * mul_amt;
|
||||
mask_data = ~bitmap_data;
|
||||
|
||||
if (draw_mode == SPRITE_UNMASKED) {
|
||||
mask_data = ~(0xFF * mul_amt);
|
||||
} else if (draw_mode == SPRITE_IS_MASK_ERASE) {
|
||||
bitmap_data = 0;
|
||||
} else {
|
||||
mask_data = ~(pgm_read_byte(mask_ofs) * mul_amt);
|
||||
}
|
||||
|
||||
if (sRow >= 0) {
|
||||
data = Arduboy2Base::sBuffer[ofs];
|
||||
data &= (uint8_t)(mask_data);
|
||||
data |= (uint8_t)(bitmap_data);
|
||||
Arduboy2Base::sBuffer[ofs] = data;
|
||||
}
|
||||
if (yOffset != 0 && sRow < 7) {
|
||||
const size_t index = static_cast<uint16_t>(ofs + WIDTH);
|
||||
data = Arduboy2Base::sBuffer[index];
|
||||
data &= (uint8_t)(mask_data >> 8);
|
||||
data |= (uint8_t)(bitmap_data >> 8);
|
||||
Arduboy2Base::sBuffer[index] = data;
|
||||
}
|
||||
ofs++;
|
||||
mask_ofs += ofs_step;
|
||||
bofs += ofs_step;
|
||||
}
|
||||
sRow++;
|
||||
bofs += ofs_stride;
|
||||
mask_ofs += ofs_stride;
|
||||
ofs += WIDTH - rendered_width;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
/**
|
||||
* @file SpritesB.h
|
||||
* \brief
|
||||
* A class for drawing animated sprites from image and mask bitmaps.
|
||||
* Optimized for small code size.
|
||||
*/
|
||||
|
||||
#ifndef SpritesB_h
|
||||
#define SpritesB_h
|
||||
|
||||
#include "Arduboy2.h"
|
||||
#include "SpritesCommon.h"
|
||||
|
||||
/** \brief
|
||||
* A class for drawing animated sprites from image and mask bitmaps.
|
||||
* Optimized for small code size.
|
||||
*
|
||||
* \details
|
||||
* The functions in this class are identical to the `Sprites` class. The only
|
||||
* difference is that the functions in this class are optimized for smaller
|
||||
* code size rather than execution speed.
|
||||
*
|
||||
* See the `Sprites` class documentation for details on the use of the
|
||||
* functions in this class.
|
||||
*
|
||||
* Even if the speed is acceptable when using `SpritesB`, you should still try
|
||||
* using `Sprites`. In some cases `Sprites` will produce less code than
|
||||
* `SpritesB`, notably when only one of the functions is used.
|
||||
*
|
||||
* You can easily switch between using the `Sprites` class or the `SpritesB`
|
||||
* class by using one or the other to create an object instance:
|
||||
*
|
||||
* \code{.cpp}
|
||||
* Sprites sprites; // Use this to optimize for execution speed
|
||||
* SpritesB sprites; // Use this to (likely) optimize for code size
|
||||
* \endcode
|
||||
*
|
||||
* \see Sprites
|
||||
*/
|
||||
class SpritesB
|
||||
{
|
||||
public:
|
||||
/** \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).
|
||||
*
|
||||
* \see Sprites::drawExternalMask()
|
||||
*/
|
||||
static void drawExternalMask(int16_t x, int16_t y, const uint8_t *bitmap,
|
||||
const uint8_t *mask, uint8_t frame, uint8_t mask_frame);
|
||||
|
||||
/** \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.
|
||||
*
|
||||
* \see Sprites::drawPlusMask()
|
||||
*/
|
||||
static void drawPlusMask(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t frame);
|
||||
|
||||
/** \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.
|
||||
*
|
||||
* \see Sprites::drawOverwrite()
|
||||
*/
|
||||
static void drawOverwrite(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t frame);
|
||||
|
||||
/** \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.
|
||||
*
|
||||
* \see Sprites::drawErase()
|
||||
*/
|
||||
static void drawErase(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t frame);
|
||||
|
||||
/** \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.
|
||||
*
|
||||
* \see Sprites::drawSelfMasked()
|
||||
*/
|
||||
static 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.
|
||||
// (Not officially part of the API)
|
||||
static 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)
|
||||
static void drawBitmap(int16_t x, int16_t y,
|
||||
const uint8_t *bitmap, const uint8_t *mask,
|
||||
uint8_t w, uint8_t h, uint8_t draw_mode);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
/**
|
||||
* @file SpritesCommon.h
|
||||
* \brief
|
||||
* Common header file for sprite functions.
|
||||
*/
|
||||
|
||||
#ifndef SpritesCommon_h
|
||||
#define SpritesCommon_h
|
||||
|
||||
#define SPRITE_MASKED 1
|
||||
#define SPRITE_UNMASKED 2
|
||||
#define SPRITE_OVERWRITE 2
|
||||
#define SPRITE_PLUS_MASK 3
|
||||
#define SPRITE_IS_MASK 250
|
||||
#define SPRITE_IS_MASK_ERASE 251
|
||||
#define SPRITE_AUTO_MODE 255
|
||||
|
||||
#endif
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
#include <avr/pgmspace.h>
|
||||
|
||||
#ifndef ARDUBOY_LOGO_CREATED
|
||||
#define ARDUBOY_LOGO_CREATED
|
||||
|
||||
// arduboy_logo.png
|
||||
// 88x16
|
||||
PROGMEM const unsigned char arduboy_logo[] = {
|
||||
0xF0, 0xF8, 0x9C, 0x8E, 0x87, 0x83, 0x87, 0x8E, 0x9C, 0xF8,
|
||||
0xF0, 0x00, 0x00, 0xFE, 0xFF, 0x03, 0x03, 0x03, 0x03, 0x03,
|
||||
0x07, 0x0E, 0xFC, 0xF8, 0x00, 0x00, 0xFE, 0xFF, 0x03, 0x03,
|
||||
0x03, 0x03, 0x03, 0x07, 0x0E, 0xFC, 0xF8, 0x00, 0x00, 0xFF,
|
||||
0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
|
||||
0x00, 0x00, 0xFE, 0xFF, 0x83, 0x83, 0x83, 0x83, 0x83, 0xC7,
|
||||
0xEE, 0x7C, 0x38, 0x00, 0x00, 0xF8, 0xFC, 0x0E, 0x07, 0x03,
|
||||
0x03, 0x03, 0x07, 0x0E, 0xFC, 0xF8, 0x00, 0x00, 0x3F, 0x7F,
|
||||
0xE0, 0xC0, 0x80, 0x80, 0xC0, 0xE0, 0x7F, 0x3F, 0xFF, 0xFF,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFF, 0xFF, 0x00,
|
||||
0x00, 0xFF, 0xFF, 0x0C, 0x0C, 0x0C, 0x0C, 0x1C, 0x3E, 0x77,
|
||||
0xE3, 0xC1, 0x00, 0x00, 0x7F, 0xFF, 0xC0, 0xC0, 0xC0, 0xC0,
|
||||
0xC0, 0xE0, 0x70, 0x3F, 0x1F, 0x00, 0x00, 0x1F, 0x3F, 0x70,
|
||||
0xE0, 0xC0, 0xC0, 0xC0, 0xE0, 0x70, 0x3F, 0x1F, 0x00, 0x00,
|
||||
0x7F, 0xFF, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xE3, 0x77, 0x3E,
|
||||
0x1C, 0x00, 0x00, 0x1F, 0x3F, 0x70, 0xE0, 0xC0, 0xC0, 0xC0,
|
||||
0xE0, 0x70, 0x3F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||
0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
268
src/glcdfont.c
268
src/glcdfont.c
|
|
@ -1,268 +0,0 @@
|
|||
#include <avr/io.h>
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
#ifndef FONT5X7_H
|
||||
#define FONT5X7_H
|
||||
|
||||
// standard ascii 5x7 font
|
||||
const static unsigned char font[] PROGMEM =
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x3E, 0x5B, 0x4F, 0x5B, 0x3E,
|
||||
0x3E, 0x6B, 0x4F, 0x6B, 0x3E,
|
||||
0x1C, 0x3E, 0x7C, 0x3E, 0x1C,
|
||||
0x18, 0x3C, 0x7E, 0x3C, 0x18,
|
||||
0x1C, 0x57, 0x7D, 0x57, 0x1C,
|
||||
0x1C, 0x5E, 0x7F, 0x5E, 0x1C,
|
||||
0x00, 0x18, 0x3C, 0x18, 0x00,
|
||||
0xFF, 0xE7, 0xC3, 0xE7, 0xFF,
|
||||
0x00, 0x18, 0x24, 0x18, 0x00,
|
||||
0xFF, 0xE7, 0xDB, 0xE7, 0xFF,
|
||||
0x30, 0x48, 0x3A, 0x06, 0x0E,
|
||||
0x26, 0x29, 0x79, 0x29, 0x26,
|
||||
0x40, 0x7F, 0x05, 0x05, 0x07,
|
||||
0x40, 0x7F, 0x05, 0x25, 0x3F,
|
||||
0x5A, 0x3C, 0xE7, 0x3C, 0x5A,
|
||||
0x7F, 0x3E, 0x1C, 0x1C, 0x08,
|
||||
0x08, 0x1C, 0x1C, 0x3E, 0x7F,
|
||||
0x14, 0x22, 0x7F, 0x22, 0x14,
|
||||
0x5F, 0x5F, 0x00, 0x5F, 0x5F,
|
||||
0x06, 0x09, 0x7F, 0x01, 0x7F,
|
||||
0x00, 0x66, 0x89, 0x95, 0x6A,
|
||||
0x60, 0x60, 0x60, 0x60, 0x60,
|
||||
0x94, 0xA2, 0xFF, 0xA2, 0x94,
|
||||
0x08, 0x04, 0x7E, 0x04, 0x08,
|
||||
0x10, 0x20, 0x7E, 0x20, 0x10,
|
||||
0x08, 0x08, 0x2A, 0x1C, 0x08,
|
||||
0x08, 0x1C, 0x2A, 0x08, 0x08,
|
||||
0x1E, 0x10, 0x10, 0x10, 0x10,
|
||||
0x0C, 0x1E, 0x0C, 0x1E, 0x0C,
|
||||
0x30, 0x38, 0x3E, 0x38, 0x30,
|
||||
0x06, 0x0E, 0x3E, 0x0E, 0x06,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x5F, 0x00, 0x00,
|
||||
0x00, 0x07, 0x00, 0x07, 0x00,
|
||||
0x14, 0x7F, 0x14, 0x7F, 0x14,
|
||||
0x24, 0x2A, 0x7F, 0x2A, 0x12,
|
||||
0x23, 0x13, 0x08, 0x64, 0x62,
|
||||
0x36, 0x49, 0x56, 0x20, 0x50,
|
||||
0x00, 0x08, 0x07, 0x03, 0x00,
|
||||
0x00, 0x1C, 0x22, 0x41, 0x00,
|
||||
0x00, 0x41, 0x22, 0x1C, 0x00,
|
||||
0x2A, 0x1C, 0x7F, 0x1C, 0x2A,
|
||||
0x08, 0x08, 0x3E, 0x08, 0x08,
|
||||
0x00, 0x80, 0x70, 0x30, 0x00,
|
||||
0x08, 0x08, 0x08, 0x08, 0x08,
|
||||
0x00, 0x00, 0x60, 0x60, 0x00,
|
||||
0x20, 0x10, 0x08, 0x04, 0x02,
|
||||
0x3E, 0x51, 0x49, 0x45, 0x3E,
|
||||
0x00, 0x42, 0x7F, 0x40, 0x00,
|
||||
0x72, 0x49, 0x49, 0x49, 0x46,
|
||||
0x21, 0x41, 0x49, 0x4D, 0x33,
|
||||
0x18, 0x14, 0x12, 0x7F, 0x10,
|
||||
0x27, 0x45, 0x45, 0x45, 0x39,
|
||||
0x3C, 0x4A, 0x49, 0x49, 0x31,
|
||||
0x41, 0x21, 0x11, 0x09, 0x07,
|
||||
0x36, 0x49, 0x49, 0x49, 0x36,
|
||||
0x46, 0x49, 0x49, 0x29, 0x1E,
|
||||
0x00, 0x00, 0x14, 0x00, 0x00,
|
||||
0x00, 0x40, 0x34, 0x00, 0x00,
|
||||
0x00, 0x08, 0x14, 0x22, 0x41,
|
||||
0x14, 0x14, 0x14, 0x14, 0x14,
|
||||
0x00, 0x41, 0x22, 0x14, 0x08,
|
||||
0x02, 0x01, 0x59, 0x09, 0x06,
|
||||
0x3E, 0x41, 0x5D, 0x59, 0x4E,
|
||||
0x7C, 0x12, 0x11, 0x12, 0x7C,
|
||||
0x7F, 0x49, 0x49, 0x49, 0x36,
|
||||
0x3E, 0x41, 0x41, 0x41, 0x22,
|
||||
0x7F, 0x41, 0x41, 0x41, 0x3E,
|
||||
0x7F, 0x49, 0x49, 0x49, 0x41,
|
||||
0x7F, 0x09, 0x09, 0x09, 0x01,
|
||||
0x3E, 0x41, 0x41, 0x51, 0x73,
|
||||
0x7F, 0x08, 0x08, 0x08, 0x7F,
|
||||
0x00, 0x41, 0x7F, 0x41, 0x00,
|
||||
0x20, 0x40, 0x41, 0x3F, 0x01,
|
||||
0x7F, 0x08, 0x14, 0x22, 0x41,
|
||||
0x7F, 0x40, 0x40, 0x40, 0x40,
|
||||
0x7F, 0x02, 0x1C, 0x02, 0x7F,
|
||||
0x7F, 0x04, 0x08, 0x10, 0x7F,
|
||||
0x3E, 0x41, 0x41, 0x41, 0x3E,
|
||||
0x7F, 0x09, 0x09, 0x09, 0x06,
|
||||
0x3E, 0x41, 0x51, 0x21, 0x5E,
|
||||
0x7F, 0x09, 0x19, 0x29, 0x46,
|
||||
0x26, 0x49, 0x49, 0x49, 0x32,
|
||||
0x03, 0x01, 0x7F, 0x01, 0x03,
|
||||
0x3F, 0x40, 0x40, 0x40, 0x3F,
|
||||
0x1F, 0x20, 0x40, 0x20, 0x1F,
|
||||
0x3F, 0x40, 0x38, 0x40, 0x3F,
|
||||
0x63, 0x14, 0x08, 0x14, 0x63,
|
||||
0x03, 0x04, 0x78, 0x04, 0x03,
|
||||
0x61, 0x59, 0x49, 0x4D, 0x43,
|
||||
0x00, 0x7F, 0x41, 0x41, 0x41,
|
||||
0x02, 0x04, 0x08, 0x10, 0x20,
|
||||
0x00, 0x41, 0x41, 0x41, 0x7F,
|
||||
0x04, 0x02, 0x01, 0x02, 0x04,
|
||||
0x40, 0x40, 0x40, 0x40, 0x40,
|
||||
0x00, 0x03, 0x07, 0x08, 0x00,
|
||||
0x20, 0x54, 0x54, 0x78, 0x40,
|
||||
0x7F, 0x28, 0x44, 0x44, 0x38,
|
||||
0x38, 0x44, 0x44, 0x44, 0x28,
|
||||
0x38, 0x44, 0x44, 0x28, 0x7F,
|
||||
0x38, 0x54, 0x54, 0x54, 0x18,
|
||||
0x00, 0x08, 0x7E, 0x09, 0x02,
|
||||
0x18, 0xA4, 0xA4, 0x9C, 0x78,
|
||||
0x7F, 0x08, 0x04, 0x04, 0x78,
|
||||
0x00, 0x44, 0x7D, 0x40, 0x00,
|
||||
0x20, 0x40, 0x40, 0x3D, 0x00,
|
||||
0x7F, 0x10, 0x28, 0x44, 0x00,
|
||||
0x00, 0x41, 0x7F, 0x40, 0x00,
|
||||
0x7C, 0x04, 0x78, 0x04, 0x78,
|
||||
0x7C, 0x08, 0x04, 0x04, 0x78,
|
||||
0x38, 0x44, 0x44, 0x44, 0x38,
|
||||
0xFC, 0x18, 0x24, 0x24, 0x18,
|
||||
0x18, 0x24, 0x24, 0x18, 0xFC,
|
||||
0x7C, 0x08, 0x04, 0x04, 0x08,
|
||||
0x48, 0x54, 0x54, 0x54, 0x24,
|
||||
0x04, 0x04, 0x3F, 0x44, 0x24,
|
||||
0x3C, 0x40, 0x40, 0x20, 0x7C,
|
||||
0x1C, 0x20, 0x40, 0x20, 0x1C,
|
||||
0x3C, 0x40, 0x30, 0x40, 0x3C,
|
||||
0x44, 0x28, 0x10, 0x28, 0x44,
|
||||
0x4C, 0x90, 0x90, 0x90, 0x7C,
|
||||
0x44, 0x64, 0x54, 0x4C, 0x44,
|
||||
0x00, 0x08, 0x36, 0x41, 0x00,
|
||||
0x00, 0x00, 0x77, 0x00, 0x00,
|
||||
0x00, 0x41, 0x36, 0x08, 0x00,
|
||||
0x02, 0x01, 0x02, 0x04, 0x02,
|
||||
0x3C, 0x26, 0x23, 0x26, 0x3C,
|
||||
0x1E, 0xA1, 0xA1, 0x61, 0x12,
|
||||
0x3A, 0x40, 0x40, 0x20, 0x7A,
|
||||
0x38, 0x54, 0x54, 0x55, 0x59,
|
||||
0x21, 0x55, 0x55, 0x79, 0x41,
|
||||
0x21, 0x54, 0x54, 0x78, 0x41,
|
||||
0x21, 0x55, 0x54, 0x78, 0x40,
|
||||
0x20, 0x54, 0x55, 0x79, 0x40,
|
||||
0x0C, 0x1E, 0x52, 0x72, 0x12,
|
||||
0x39, 0x55, 0x55, 0x55, 0x59,
|
||||
0x39, 0x54, 0x54, 0x54, 0x59,
|
||||
0x39, 0x55, 0x54, 0x54, 0x58,
|
||||
0x00, 0x00, 0x45, 0x7C, 0x41,
|
||||
0x00, 0x02, 0x45, 0x7D, 0x42,
|
||||
0x00, 0x01, 0x45, 0x7C, 0x40,
|
||||
0xF0, 0x29, 0x24, 0x29, 0xF0,
|
||||
0xF0, 0x28, 0x25, 0x28, 0xF0,
|
||||
0x7C, 0x54, 0x55, 0x45, 0x00,
|
||||
0x20, 0x54, 0x54, 0x7C, 0x54,
|
||||
0x7C, 0x0A, 0x09, 0x7F, 0x49,
|
||||
0x32, 0x49, 0x49, 0x49, 0x32,
|
||||
0x32, 0x48, 0x48, 0x48, 0x32,
|
||||
0x32, 0x4A, 0x48, 0x48, 0x30,
|
||||
0x3A, 0x41, 0x41, 0x21, 0x7A,
|
||||
0x3A, 0x42, 0x40, 0x20, 0x78,
|
||||
0x00, 0x9D, 0xA0, 0xA0, 0x7D,
|
||||
0x39, 0x44, 0x44, 0x44, 0x39,
|
||||
0x3D, 0x40, 0x40, 0x40, 0x3D,
|
||||
0x3C, 0x24, 0xFF, 0x24, 0x24,
|
||||
0x48, 0x7E, 0x49, 0x43, 0x66,
|
||||
0x2B, 0x2F, 0xFC, 0x2F, 0x2B,
|
||||
0xFF, 0x09, 0x29, 0xF6, 0x20,
|
||||
0xC0, 0x88, 0x7E, 0x09, 0x03,
|
||||
0x20, 0x54, 0x54, 0x79, 0x41,
|
||||
0x00, 0x00, 0x44, 0x7D, 0x41,
|
||||
0x30, 0x48, 0x48, 0x4A, 0x32,
|
||||
0x38, 0x40, 0x40, 0x22, 0x7A,
|
||||
0x00, 0x7A, 0x0A, 0x0A, 0x72,
|
||||
0x7D, 0x0D, 0x19, 0x31, 0x7D,
|
||||
0x26, 0x29, 0x29, 0x2F, 0x28,
|
||||
0x26, 0x29, 0x29, 0x29, 0x26,
|
||||
0x30, 0x48, 0x4D, 0x40, 0x20,
|
||||
0x38, 0x08, 0x08, 0x08, 0x08,
|
||||
0x08, 0x08, 0x08, 0x08, 0x38,
|
||||
0x2F, 0x10, 0xC8, 0xAC, 0xBA,
|
||||
0x2F, 0x10, 0x28, 0x34, 0xFA,
|
||||
0x00, 0x00, 0x7B, 0x00, 0x00,
|
||||
0x08, 0x14, 0x2A, 0x14, 0x22,
|
||||
0x22, 0x14, 0x2A, 0x14, 0x08,
|
||||
0x95, 0x00, 0x22, 0x00, 0x95,
|
||||
0xAA, 0x00, 0x55, 0x00, 0xAA,
|
||||
0xAA, 0x55, 0xAA, 0x55, 0xAA,
|
||||
0x00, 0x00, 0x00, 0xFF, 0x00,
|
||||
0x10, 0x10, 0x10, 0xFF, 0x00,
|
||||
0x14, 0x14, 0x14, 0xFF, 0x00,
|
||||
0x10, 0x10, 0xFF, 0x00, 0xFF,
|
||||
0x10, 0x10, 0xF0, 0x10, 0xF0,
|
||||
0x14, 0x14, 0x14, 0xFC, 0x00,
|
||||
0x14, 0x14, 0xF7, 0x00, 0xFF,
|
||||
0x00, 0x00, 0xFF, 0x00, 0xFF,
|
||||
0x14, 0x14, 0xF4, 0x04, 0xFC,
|
||||
0x14, 0x14, 0x17, 0x10, 0x1F,
|
||||
0x10, 0x10, 0x1F, 0x10, 0x1F,
|
||||
0x14, 0x14, 0x14, 0x1F, 0x00,
|
||||
0x10, 0x10, 0x10, 0xF0, 0x00,
|
||||
0x00, 0x00, 0x00, 0x1F, 0x10,
|
||||
0x10, 0x10, 0x10, 0x1F, 0x10,
|
||||
0x10, 0x10, 0x10, 0xF0, 0x10,
|
||||
0x00, 0x00, 0x00, 0xFF, 0x10,
|
||||
0x10, 0x10, 0x10, 0x10, 0x10,
|
||||
0x10, 0x10, 0x10, 0xFF, 0x10,
|
||||
0x00, 0x00, 0x00, 0xFF, 0x14,
|
||||
0x00, 0x00, 0xFF, 0x00, 0xFF,
|
||||
0x00, 0x00, 0x1F, 0x10, 0x17,
|
||||
0x00, 0x00, 0xFC, 0x04, 0xF4,
|
||||
0x14, 0x14, 0x17, 0x10, 0x17,
|
||||
0x14, 0x14, 0xF4, 0x04, 0xF4,
|
||||
0x00, 0x00, 0xFF, 0x00, 0xF7,
|
||||
0x14, 0x14, 0x14, 0x14, 0x14,
|
||||
0x14, 0x14, 0xF7, 0x00, 0xF7,
|
||||
0x14, 0x14, 0x14, 0x17, 0x14,
|
||||
0x10, 0x10, 0x1F, 0x10, 0x1F,
|
||||
0x14, 0x14, 0x14, 0xF4, 0x14,
|
||||
0x10, 0x10, 0xF0, 0x10, 0xF0,
|
||||
0x00, 0x00, 0x1F, 0x10, 0x1F,
|
||||
0x00, 0x00, 0x00, 0x1F, 0x14,
|
||||
0x00, 0x00, 0x00, 0xFC, 0x14,
|
||||
0x00, 0x00, 0xF0, 0x10, 0xF0,
|
||||
0x10, 0x10, 0xFF, 0x10, 0xFF,
|
||||
0x14, 0x14, 0x14, 0xFF, 0x14,
|
||||
0x10, 0x10, 0x10, 0x1F, 0x00,
|
||||
0x00, 0x00, 0x00, 0xF0, 0x10,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
|
||||
0xFF, 0xFF, 0xFF, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xFF, 0xFF,
|
||||
0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
|
||||
0x38, 0x44, 0x44, 0x38, 0x44,
|
||||
0x7C, 0x2A, 0x2A, 0x3E, 0x14,
|
||||
0x7E, 0x02, 0x02, 0x06, 0x06,
|
||||
0x02, 0x7E, 0x02, 0x7E, 0x02,
|
||||
0x63, 0x55, 0x49, 0x41, 0x63,
|
||||
0x38, 0x44, 0x44, 0x3C, 0x04,
|
||||
0x40, 0x7E, 0x20, 0x1E, 0x20,
|
||||
0x06, 0x02, 0x7E, 0x02, 0x02,
|
||||
0x99, 0xA5, 0xE7, 0xA5, 0x99,
|
||||
0x1C, 0x2A, 0x49, 0x2A, 0x1C,
|
||||
0x4C, 0x72, 0x01, 0x72, 0x4C,
|
||||
0x30, 0x4A, 0x4D, 0x4D, 0x30,
|
||||
0x30, 0x48, 0x78, 0x48, 0x30,
|
||||
0xBC, 0x62, 0x5A, 0x46, 0x3D,
|
||||
0x3E, 0x49, 0x49, 0x49, 0x00,
|
||||
0x7E, 0x01, 0x01, 0x01, 0x7E,
|
||||
0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
|
||||
0x44, 0x44, 0x5F, 0x44, 0x44,
|
||||
0x40, 0x51, 0x4A, 0x44, 0x40,
|
||||
0x40, 0x44, 0x4A, 0x51, 0x40,
|
||||
0x00, 0x00, 0xFF, 0x01, 0x03,
|
||||
0xE0, 0x80, 0xFF, 0x00, 0x00,
|
||||
0x08, 0x08, 0x6B, 0x6B, 0x08,
|
||||
0x36, 0x12, 0x36, 0x24, 0x36,
|
||||
0x06, 0x0F, 0x09, 0x0F, 0x06,
|
||||
0x00, 0x00, 0x18, 0x18, 0x00,
|
||||
0x00, 0x00, 0x10, 0x10, 0x00,
|
||||
0x30, 0x40, 0xFF, 0x01, 0x01,
|
||||
0x00, 0x1F, 0x01, 0x01, 0x1E,
|
||||
0x00, 0x19, 0x1D, 0x17, 0x12,
|
||||
0x00, 0x3C, 0x3C, 0x3C, 0x3C,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
#endif
|
||||
Loading…
Reference in New Issue