2016-06-27 22:52:10 +00:00
|
|
|
#ifndef ARDUBOY2_H
|
|
|
|
#define ARDUBOY2_H
|
2015-05-01 05:26:58 +00:00
|
|
|
|
2016-10-20 00:23:34 +00:00
|
|
|
#include <Arduino.h>
|
2016-06-27 22:52:10 +00:00
|
|
|
#include "ArduboyCore.h"
|
2016-10-20 00:23:34 +00:00
|
|
|
#include "Sprites.h"
|
2015-05-01 05:26:58 +00:00
|
|
|
#include <Print.h>
|
|
|
|
#include <limits.h>
|
|
|
|
|
2016-03-01 21:19:27 +00:00
|
|
|
// Library version.
|
|
|
|
// For a version number in the form of x.y.z the value of the define will be
|
|
|
|
// ((x * 10000) + (y * 100) + (z)) as a decimal number.
|
|
|
|
// So, it will read as xxxyyzz, with no leading zeros on x.
|
2016-10-20 00:23:34 +00:00
|
|
|
#define ARDUBOY_LIB_VER 20100
|
2016-03-01 21:19:27 +00:00
|
|
|
|
2015-05-01 05:26:58 +00:00
|
|
|
// EEPROM settings
|
|
|
|
#define EEPROM_VERSION 0
|
|
|
|
#define EEPROM_BRIGHTNESS 1
|
|
|
|
#define EEPROM_AUDIO_ON_OFF 2
|
|
|
|
|
|
|
|
// we reserve the first 16 byte of EEPROM for system use
|
|
|
|
#define EEPROM_STORAGE_SPACE_START 16 // and onward
|
|
|
|
|
|
|
|
// eeprom settings above are neded for audio
|
2016-06-27 22:52:10 +00:00
|
|
|
#include "ArduboyAudio.h"
|
2015-05-01 05:26:58 +00:00
|
|
|
|
|
|
|
#define PIXEL_SAFE_MODE
|
|
|
|
|
2016-02-21 06:51:40 +00:00
|
|
|
// pixel colors
|
|
|
|
#define INVERT 2 //< lit/unlit pixel
|
|
|
|
#define WHITE 1 //< lit pixel
|
|
|
|
#define BLACK 0 //< unlit pixel
|
|
|
|
|
2015-05-01 05:26:58 +00:00
|
|
|
// compare Vcc to 1.1 bandgap
|
|
|
|
#define ADC_VOLTAGE (_BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1))
|
|
|
|
// compare temperature to 2.5 internal reference and _BV(MUX5)
|
|
|
|
#define ADC_TEMP (_BV(REFS0) | _BV(REFS1) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0))
|
|
|
|
|
2016-02-11 13:57:06 +00:00
|
|
|
|
2016-10-20 00:23:34 +00:00
|
|
|
/// Rectangle for collision functions
|
|
|
|
struct Rect
|
|
|
|
{
|
|
|
|
int16_t x;
|
|
|
|
int16_t y;
|
|
|
|
uint8_t width;
|
|
|
|
uint8_t height;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Point for collision functions
|
|
|
|
struct Point
|
|
|
|
{
|
|
|
|
int16_t x;
|
|
|
|
int16_t y;
|
|
|
|
};
|
|
|
|
|
2016-05-27 21:43:58 +00:00
|
|
|
//==================================
|
|
|
|
//========== Arduboy2Base ==========
|
|
|
|
//==================================
|
|
|
|
|
|
|
|
class Arduboy2Base : public ArduboyCore
|
2015-05-01 05:26:58 +00:00
|
|
|
{
|
2016-10-20 17:28:29 +00:00
|
|
|
friend class Sprites;
|
|
|
|
|
|
|
|
public:
|
2016-05-27 21:43:58 +00:00
|
|
|
Arduboy2Base();
|
|
|
|
|
|
|
|
ArduboyAudio audio;
|
2015-05-01 05:26:58 +00:00
|
|
|
|
2016-02-20 19:54:06 +00:00
|
|
|
/// Initialize hardware, boot logo, boot utilities, etc.
|
2016-02-20 19:49:54 +00:00
|
|
|
/**
|
2016-05-27 21:43:58 +00:00
|
|
|
* To free up some code space for use by the sketch, you can use "boot()"
|
|
|
|
* instead of "begin()" to eliminate some of the some of the things that
|
|
|
|
* aren't really required, such as displaying the boot logo.
|
|
|
|
*
|
|
|
|
* Look at the source for "begin()" and after calling "boot()" call
|
|
|
|
* whatever functions "begin()" does that you still want to keep.
|
|
|
|
* If your sketch uses the speaker, it's probably a good idea to at least
|
|
|
|
* call "audio.begin()".
|
2016-02-20 19:54:06 +00:00
|
|
|
*/
|
2016-05-27 21:43:58 +00:00
|
|
|
void begin();
|
2015-05-01 05:26:58 +00:00
|
|
|
|
2016-02-20 19:43:36 +00:00
|
|
|
/// Flashlight mode
|
|
|
|
/**
|
2016-06-15 17:25:57 +00:00
|
|
|
* Turn the RGB LED and screen fully on. Called in the begin() function.
|
|
|
|
*
|
|
|
|
* Hold the UP button when booting to enable. Press the DOWN button to exit
|
|
|
|
* or simply turn off your Arduboy. It goes into a tight loop until the
|
|
|
|
* DOWN button is pressed.
|
2016-02-20 19:43:36 +00:00
|
|
|
*/
|
|
|
|
void flashlight();
|
|
|
|
|
2016-06-13 18:21:45 +00:00
|
|
|
/// Handle buttons held on startup for system control
|
|
|
|
/**
|
|
|
|
* Hold the B button when booting to enter system control mode.
|
|
|
|
* The B button must be held continuously to remain in this mode.
|
|
|
|
* Pressing other buttons will perform system control functions:
|
|
|
|
*
|
|
|
|
* UP: Set "sound enabled" in EEPROM
|
|
|
|
* DOWN: Set "sound disabled" (mute) in EEPROM
|
|
|
|
*/
|
|
|
|
void systemButtons();
|
|
|
|
|
|
|
|
/// Scrolls in the Arduboy logo
|
|
|
|
void bootLogo();
|
|
|
|
|
2015-05-01 05:26:58 +00:00
|
|
|
/// Clears display.
|
|
|
|
void clear();
|
|
|
|
|
|
|
|
/// Copies the contents of the screen buffer to the screen.
|
|
|
|
/**
|
|
|
|
* X and Y positions on the display are from the top left corner, thus a Y of 64
|
|
|
|
* is the bottom of the screen and an X of 128 is the right side of the screen.
|
|
|
|
* "Color" or "value" means choosing whether a pixel is lit or not - if color is
|
|
|
|
* 0, the pixel is off (black), if color is 1, the pixel is on (white).
|
|
|
|
*/
|
|
|
|
void display();
|
|
|
|
|
|
|
|
/// Sets a single pixel on the screen buffer to white or black.
|
2016-09-14 21:50:05 +00:00
|
|
|
void drawPixel(int16_t x, int16_t y, uint8_t color = WHITE);
|
2015-05-01 05:26:58 +00:00
|
|
|
|
2016-06-27 21:04:01 +00:00
|
|
|
/// Returns the state of the given pixel in the screen buffer.
|
|
|
|
/**
|
|
|
|
* Return value will be 1 if the pixel is on (white) or 0 if the pixel is off (black).
|
|
|
|
*/
|
2015-05-01 05:26:58 +00:00
|
|
|
uint8_t getPixel(uint8_t x, uint8_t y);
|
|
|
|
|
|
|
|
/// Draw a circle of a defined radius.
|
|
|
|
/**
|
|
|
|
* Draws a circle in white or black. X and Y are the center point of the circle.
|
|
|
|
*/
|
2016-06-27 21:04:01 +00:00
|
|
|
void drawCircle(int16_t x0, int16_t y0, uint8_t r, uint8_t color = WHITE);
|
2015-05-01 05:26:58 +00:00
|
|
|
|
|
|
|
/// Draws one or more "corners" of a circle.
|
2016-06-27 21:04:01 +00:00
|
|
|
void drawCircleHelper(int16_t x0, int16_t y0, uint8_t r, uint8_t cornername, uint8_t color = WHITE);
|
2015-05-01 05:26:58 +00:00
|
|
|
|
|
|
|
/// Draws a filled-in circle.
|
2016-06-27 21:04:01 +00:00
|
|
|
void fillCircle(int16_t x0, int16_t y0, uint8_t r, uint8_t color = WHITE);
|
2015-05-01 05:26:58 +00:00
|
|
|
|
|
|
|
/// Draws one or both vertical halves of a filled-in circle.
|
2016-06-27 21:04:01 +00:00
|
|
|
void fillCircleHelper(int16_t x0, int16_t y0, uint8_t r, uint8_t cornername, int16_t delta, uint8_t color = WHITE);
|
2015-05-01 05:26:58 +00:00
|
|
|
|
|
|
|
/// Draws a line between two points.
|
|
|
|
/**
|
|
|
|
* Uses Bresenham's algorithm.
|
|
|
|
*/
|
2016-06-27 21:04:01 +00:00
|
|
|
void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint8_t color = WHITE);
|
2015-05-01 05:26:58 +00:00
|
|
|
|
|
|
|
/// Draws a rectangle of a width and height.
|
2016-06-27 21:04:01 +00:00
|
|
|
void drawRect(int16_t x, int16_t y, uint8_t w, uint8_t h, uint8_t color = WHITE);
|
2015-05-01 05:26:58 +00:00
|
|
|
|
|
|
|
/// Draws vertical line.
|
2016-06-27 21:04:01 +00:00
|
|
|
void drawFastVLine(int16_t x, int16_t y, uint8_t h, uint8_t color = WHITE);
|
2015-05-01 05:26:58 +00:00
|
|
|
|
|
|
|
/// Draws a horizontal line.
|
2016-06-27 21:04:01 +00:00
|
|
|
void drawFastHLine(int16_t x, int16_t y, uint8_t w, uint8_t color = WHITE);
|
2015-05-01 05:26:58 +00:00
|
|
|
|
|
|
|
/// Draws a filled-in rectangle.
|
2016-06-27 21:04:01 +00:00
|
|
|
void fillRect(int16_t x, int16_t y, uint8_t w, uint8_t h, uint8_t color = WHITE);
|
2015-05-01 05:26:58 +00:00
|
|
|
|
|
|
|
/// Fills the screen buffer with white or black.
|
2016-06-27 21:04:01 +00:00
|
|
|
void fillScreen(uint8_t color = WHITE);
|
2015-05-01 05:26:58 +00:00
|
|
|
|
|
|
|
/// Draws a rectangle with rounded edges.
|
2016-06-27 21:04:01 +00:00
|
|
|
void drawRoundRect(int16_t x, int16_t y, uint8_t w, uint8_t h, uint8_t r, uint8_t color = WHITE);
|
2015-05-01 05:26:58 +00:00
|
|
|
|
|
|
|
/// Draws a filled-in rectangle with rounded edges.
|
2016-06-27 21:04:01 +00:00
|
|
|
void fillRoundRect(int16_t x, int16_t y, uint8_t w, uint8_t h, uint8_t r, uint8_t color = WHITE);
|
2015-05-01 05:26:58 +00:00
|
|
|
|
|
|
|
/// Draws the outline of a triangle.
|
2016-06-27 21:04:01 +00:00
|
|
|
void drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint8_t color = WHITE);
|
2015-05-01 05:26:58 +00:00
|
|
|
|
|
|
|
/// Draws a filled-in triangle.
|
2016-06-27 21:04:01 +00:00
|
|
|
void fillTriangle (int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint8_t color = WHITE);
|
2015-05-01 05:26:58 +00:00
|
|
|
|
|
|
|
/// Draws a bitmap from program memory to a specific X/Y
|
2016-06-27 21:04:01 +00:00
|
|
|
void drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t w, uint8_t h, uint8_t color = WHITE);
|
2015-05-01 05:26:58 +00:00
|
|
|
|
|
|
|
/// Draws images that are bit-oriented horizontally.
|
|
|
|
/**
|
|
|
|
* This requires a lot of additional CPU power and will draw images slower
|
|
|
|
* than drawBitmap, where the images are stored in a format that
|
|
|
|
* allows them to be directly written to the screen. It is
|
|
|
|
* recommended you use drawBitmap when possible.
|
|
|
|
*/
|
2016-06-27 21:04:01 +00:00
|
|
|
void drawSlowXYBitmap(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t w, uint8_t h, uint8_t color = WHITE);
|
2015-05-01 05:26:58 +00:00
|
|
|
|
2016-10-20 00:23:34 +00:00
|
|
|
/// Draw a compressed bitmap
|
|
|
|
/**
|
|
|
|
* Draws a bitmap starting at the given coordinates that has been compressed
|
|
|
|
* using an algorthm implemented by Team A.R.G.
|
|
|
|
* For more information see:
|
|
|
|
* https://github.com/TEAMarg/drawCompressed
|
|
|
|
* https://github.com/TEAMarg/Cabi
|
|
|
|
*/
|
|
|
|
void drawCompressed(int16_t sx, int16_t sy, const uint8_t *bitmap, uint8_t color = WHITE);
|
|
|
|
|
2016-05-27 21:43:58 +00:00
|
|
|
/// Get a pointer to the display buffer.
|
2015-05-01 05:26:58 +00:00
|
|
|
unsigned char* getBuffer();
|
|
|
|
|
|
|
|
/// Seeds the random number generator with entropy from the temperature, voltage reading, and microseconds since boot.
|
|
|
|
/**
|
|
|
|
* This method is still most effective when called semi-randomly such
|
|
|
|
* as after a user hits a button to start a game or other semi-random
|
|
|
|
* events
|
|
|
|
*/
|
|
|
|
void initRandomSeed();
|
|
|
|
|
|
|
|
/// Swap the references of two pointers.
|
|
|
|
void swap(int16_t& a, int16_t& b);
|
|
|
|
|
2016-06-27 21:04:01 +00:00
|
|
|
/// Sets the frame rate in frames per second.
|
2015-05-01 05:26:58 +00:00
|
|
|
void setFrameRate(uint8_t rate);
|
2016-06-27 21:04:01 +00:00
|
|
|
|
|
|
|
/// Returns "true" if it's time for the next frame.
|
2015-05-01 05:26:58 +00:00
|
|
|
bool nextFrame();
|
2016-06-27 21:04:01 +00:00
|
|
|
|
|
|
|
/// Returns "true" if the current frame number is evenly divisible by the specified number.
|
|
|
|
/**
|
|
|
|
* If called with the same value each time, will return "true" if the given
|
|
|
|
* number of frames has elapsed since the last frame in which it was "true".
|
|
|
|
*/
|
2015-05-01 05:26:58 +00:00
|
|
|
bool everyXFrames(uint8_t frames);
|
2016-02-20 19:43:14 +00:00
|
|
|
|
2015-05-01 05:26:58 +00:00
|
|
|
/// Returns the load on the CPU as a percentage.
|
|
|
|
/**
|
2016-06-27 21:04:01 +00:00
|
|
|
* This is based on how much of the time your app is spending rendering
|
2015-05-01 05:26:58 +00:00
|
|
|
* frames. This number can be higher than 100 if your app is rendering
|
|
|
|
* really slowly.
|
|
|
|
*/
|
|
|
|
int cpuLoad();
|
2016-02-20 19:43:14 +00:00
|
|
|
|
2015-05-01 05:26:58 +00:00
|
|
|
/// useful for getting raw approximate voltage values
|
2016-06-15 18:15:47 +00:00
|
|
|
uint16_t rawADC(uint8_t adc_bits);
|
2015-05-01 05:26:58 +00:00
|
|
|
|
2016-10-20 00:23:34 +00:00
|
|
|
/// Test if the specified buttons are pressed
|
|
|
|
/**
|
|
|
|
* Returns "true" if all the buttons in the provided mask are currently pressed.
|
|
|
|
* (Can be a single button)
|
|
|
|
* E.g. `if (pressed(LEFT_BUTTON + A_BUTTON))`
|
|
|
|
*/
|
|
|
|
bool pressed(uint8_t buttons);
|
|
|
|
|
|
|
|
/// Test if the specified buttons are not pressed
|
|
|
|
/**
|
|
|
|
* Returns "true" if all the buttons in the provided mask are currently released.
|
|
|
|
* (Can be a single button)
|
|
|
|
* E.g. `if (notPressed(LEFT_BUTTON))`
|
|
|
|
*/
|
|
|
|
bool notPressed(uint8_t buttons);
|
|
|
|
|
|
|
|
/// Poll the hardware buttons and track state over time.
|
|
|
|
/**
|
|
|
|
* Should be called either in the main `loop()` or as part of the
|
|
|
|
* frame system at the start of rendering a frame.
|
|
|
|
*
|
|
|
|
* The `justPressed()` and `justReleased()` functions rely on this function.
|
|
|
|
*/
|
|
|
|
void pollButtons();
|
|
|
|
|
|
|
|
/// Check if a button has just been pressed
|
|
|
|
/**
|
|
|
|
* Will return "true" if the given button was pressed between the latest
|
|
|
|
* call to `pollButtons()` and previous call to `pollButtons()`.
|
|
|
|
* If the button has been held down over multiple polls this function will
|
|
|
|
* return "false". This function should only be used to test a single button.
|
|
|
|
*/
|
|
|
|
bool justPressed(uint8_t button);
|
|
|
|
|
|
|
|
/// Check if a button has just been released
|
|
|
|
/**
|
|
|
|
* Will return "true" if the given button was released between the latest
|
|
|
|
* call to `pollButtons()` and previous call to `pollButtons()`.
|
|
|
|
* If the button has been released over multiple polls this function will
|
|
|
|
* return "false". This function should only be used to test a single button.
|
|
|
|
*/
|
|
|
|
bool justReleased(uint8_t button);
|
|
|
|
|
|
|
|
/// Test if a point is within a rectangle
|
|
|
|
/**
|
|
|
|
* Returns "true" if the point is within the rectangle.
|
|
|
|
*/
|
|
|
|
bool collide(Point point, Rect rect);
|
|
|
|
|
|
|
|
/// Test if a rectangle is intersecting with another rectangle.
|
|
|
|
/**
|
|
|
|
* Returns "true" if the first rectangle is intersecting the second.
|
|
|
|
*/
|
|
|
|
bool collide(Rect rect1, Rect rect2);
|
|
|
|
|
2016-10-20 17:28:29 +00:00
|
|
|
protected:
|
2016-06-13 18:21:45 +00:00
|
|
|
// helper function for sound enable/disable system control
|
|
|
|
void sysCtrlSound(uint8_t buttons, uint8_t led, uint8_t eeVal);
|
|
|
|
|
2016-06-27 21:04:01 +00:00
|
|
|
// Screen buffer
|
2016-06-30 23:59:56 +00:00
|
|
|
static uint8_t sBuffer[(HEIGHT*WIDTH)/8];
|
|
|
|
|
2016-10-20 00:23:34 +00:00
|
|
|
// For button handling
|
|
|
|
uint8_t currentButtonState;
|
|
|
|
uint8_t previousButtonState;
|
|
|
|
|
2016-06-30 23:59:56 +00:00
|
|
|
// For frame funcions
|
|
|
|
uint16_t frameCount;
|
|
|
|
uint8_t eachFrameMillis;
|
2016-09-15 22:12:27 +00:00
|
|
|
unsigned long lastFrameStart;
|
|
|
|
unsigned long nextFrameStart;
|
2016-06-30 23:59:56 +00:00
|
|
|
bool post_render;
|
|
|
|
uint8_t lastFrameDurationMs;
|
2016-05-27 21:43:58 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
//==============================
|
|
|
|
//========== Arduboy2 ==========
|
|
|
|
//==============================
|
|
|
|
|
|
|
|
class Arduboy2 : public Print, public Arduboy2Base
|
|
|
|
{
|
2016-10-20 17:28:29 +00:00
|
|
|
public:
|
2016-05-27 21:43:58 +00:00
|
|
|
Arduboy2();
|
|
|
|
|
|
|
|
/// Writes a single ASCII character to the screen.
|
|
|
|
virtual size_t write(uint8_t);
|
|
|
|
|
|
|
|
/// Draws an ASCII character at a point.
|
|
|
|
void drawChar(int16_t x, int16_t y, unsigned char c, uint8_t color, uint8_t bg, uint8_t size);
|
|
|
|
|
|
|
|
/// Sets the location of the text cursor.
|
|
|
|
void setCursor(int16_t x, int16_t y);
|
|
|
|
|
|
|
|
/// Get the text cursor X position
|
|
|
|
uint16_t getCursorX();
|
|
|
|
|
|
|
|
/// Get the text cursor Y position
|
|
|
|
uint16_t getCursorY();
|
2015-05-01 05:26:58 +00:00
|
|
|
|
2016-05-27 21:43:58 +00:00
|
|
|
/// Sets the text foreground color
|
|
|
|
void setTextColor(uint8_t color);
|
|
|
|
|
|
|
|
/// Sets the text background color
|
|
|
|
void setTextBackground(uint8_t bg);
|
|
|
|
|
|
|
|
/// Set the text size
|
|
|
|
/**
|
|
|
|
* Individual ASCII characters are 6x8 pixels
|
|
|
|
* (5x7 with spacing on two edges). The size is a pixel multiplier,
|
|
|
|
* so a size of 2 means each character will be 12x16, etc.
|
|
|
|
*/
|
|
|
|
void setTextSize(uint8_t s);
|
|
|
|
|
|
|
|
/// Sets whether text will wrap at screen edges.
|
2016-06-15 18:15:47 +00:00
|
|
|
void setTextWrap(bool w);
|
2016-05-27 21:43:58 +00:00
|
|
|
|
|
|
|
/// Clears the display and sets the cursor to 0, 0
|
|
|
|
void clear();
|
2015-05-01 05:26:58 +00:00
|
|
|
|
2016-10-20 17:28:29 +00:00
|
|
|
protected:
|
2015-05-01 05:26:58 +00:00
|
|
|
int16_t cursor_x;
|
|
|
|
int16_t cursor_y;
|
2016-05-27 21:43:58 +00:00
|
|
|
uint8_t textColor;
|
|
|
|
uint8_t textBackground;
|
|
|
|
uint8_t textSize;
|
2016-06-27 21:04:01 +00:00
|
|
|
bool textWrap;
|
2015-05-01 05:26:58 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|
2016-05-27 21:43:58 +00:00
|
|
|
|