forked from rveilleux/ard-drivin
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ArduboyRem.h
359 lines (283 loc) · 11.6 KB
/
ArduboyRem.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
#ifndef ARDUBOY2_H
#define ARDUBOY2_H
#include "ArduboyCoreRem.h"
#include <Print.h>
#include <limits.h>
// 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.
#define ARDUBOY_LIB_VER 20100
// 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
//#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-variable"
#include "ArduboyAudioRem.h"
//#pragma GCC diagnostic pop
#define PIXEL_SAFE_MODE
// pixel colors
#define GRAY 2 //< alternate lit/unlit
#define WHITE 1 //< lit pixel
#define BLACK 0 //< unlit pixel
// 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))
/// 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;
};
//==================================
//========== ArduboyBaseRem ==========
//==================================
class ArduboyBaseRem : public ArduboyCoreRem
{
public:
ArduboyBaseRem();
ArduboyAudioRem audio;
/// Flashlight mode
/**
* 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.
*/
void flashlight();
/// 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();
/// 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.
void drawPixel(int16_t x, int16_t y, uint8_t color = WHITE) const;
/// Fast opaque unclipped: draw a full vertical byte (8 pixels) without any checks
/// Warning: 'y' is not a pixel coordinate: it represents (y / 8), always aligned on a full byte.
void inline drawByte(uint8_t x, uint8_t y, uint8_t color) const {
sBuffer[(y*WIDTH) + x] = color;
}
/// 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).
*/
uint8_t getPixel(uint8_t x, uint8_t y) const;
/// Draw a circle of a defined radius.
/**
* Draws a circle in white or black. X and Y are the center point of the circle.
*/
void drawCircle(int16_t x0, int16_t y0, uint8_t r, uint8_t color = WHITE);
/// Draws one or more "corners" of a circle.
void drawCircleHelper(int16_t x0, int16_t y0, uint8_t r, uint8_t cornername, uint8_t color = WHITE);
/// Draws a filled-in circle.
void fillCircle(int16_t x0, int16_t y0, uint8_t r, uint8_t color = WHITE);
/// Draws one or both vertical halves of a filled-in circle.
void fillCircleHelper(int16_t x0, int16_t y0, uint8_t r, uint8_t cornername, int16_t delta, uint8_t color = WHITE);
/// Draws a line between two points.
/**
* Uses Bresenham's algorithm.
*/
void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint8_t color = WHITE);
/// Draws a rectangle of a width and height.
void drawRect(int16_t x, int16_t y, uint8_t w, uint8_t h, uint8_t color = WHITE);
/// Draws vertical line.
void drawFastVLine(int16_t x, int16_t y, uint8_t h, uint8_t color = WHITE);
/// Draws a horizontal line.
void drawFastHLine(int16_t x, uint8_t y, int16_t w, uint8_t color = WHITE);
/// Draws a filled-in rectangle.
void fillRect(int16_t x, int16_t y, uint8_t w, uint8_t h, uint8_t color = WHITE);
/// Fills the screen buffer with white or black.
void fillScreen(uint8_t color = WHITE);
/// Draws a rectangle with rounded edges.
void drawRoundRect(int16_t x, int16_t y, uint8_t w, uint8_t h, uint8_t r, uint8_t color = WHITE);
/// Draws a filled-in rectangle with rounded edges.
void fillRoundRect(int16_t x, int16_t y, uint8_t w, uint8_t h, uint8_t r, uint8_t color = WHITE);
/// Draws the outline of a triangle.
void drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint8_t color = WHITE);
/// Draws a filled-in triangle.
void fillTriangle (int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint8_t color = WHITE);
/// Draws a bitmap from program memory to a specific X/Y
void drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t w, uint8_t h);
/// Draws a mask bitmap from program memory to a specific X/Y
void drawMaskBitmap(int8_t x, int8_t y, const uint8_t *bitmap, uint8_t hflip = 0);
/// Draws a 2-bit grayscale bitmap from program memory to a specific X/Y
void drawGrayBitmap(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t w, uint8_t h);
/// Draws a bitmap from program memory to a specific X/Y
/// Restriction: always 'y' aligned on a byte, and always a multiple of 8 in height, and always opaque
void drawTurboBitmap(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t w, uint8_t h);
/// 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.
*/
void drawSlowXYBitmap(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t w, uint8_t h, uint8_t color = WHITE);
/// Draw a compressed bitmap
/**
* Draws a bitmap starting at the given coordinates that has been compressed
* using an algorthm implemented by Team A.R.G.
* 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);
/// Get a pointer to the display buffer.
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);
/// Sets the frame rate in frames per second. The parameter needs to be (1000000/fps)
void setFrameRate(uint16_t rate);
/// Returns "true" if it's time for the next frame.
void nextFrame();
/// Returns the load on the CPU as a percentage.
/**
* This is based on how much of the time your app is spending rendering
* frames. This number can be higher than 100 if your app is rendering
* really slowly.
*/
int cpuLoad();
/// useful for getting raw approximate voltage values
uint16_t rawADC(uint8_t adc_bits);
/// Test if the specified buttons are pressed
/**
* Returns "true" if all the buttons in the provided mask are currently pressed.
* (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);
public:
// helper function for sound enable/disable system control
void sysCtrlSound(uint8_t buttons, uint8_t led, uint8_t eeVal);
// Screen buffer with one row of 8 pixels of waste at the bottom for faster bitmap clipping
static uint8_t sBuffer[((HEIGHT+8)*WIDTH)/8];
// For button handling
uint8_t currentButtonState;
uint8_t previousButtonState;
// For frame funcions
uint16_t eachFrameMicros;
uint16_t nextFrameStart;
};
//==============================
//========== ArduboyRem ==========
//==============================
class ArduboyRem : public Print, public ArduboyBaseRem
{
public:
ArduboyRem();
/// Writes a single ASCII character to the screen.
virtual size_t write(uint8_t);
/// Draws an ASCII character at a point.
void drawChar(uint8_t x, uint8_t y, unsigned char c) const;
void drawChar(uint8_t x, uint8_t y, unsigned char c, uint8_t color, uint8_t bg, uint8_t size) const {
drawChar(x, y, c);
}
/// Print a byte number padded with zero (i.e.: '00', '07', '99'..)
void printBytePadded(uint8_t x, uint8_t y, byte num) const;
/// Sets the location of the text cursor.
void setCursor(uint8_t x, uint8_t y);
/// Get the text cursor X position
uint8_t getCursorX() const;
/// Get the text cursor Y position
uint8_t getCursorY() const;
/// 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.
void setTextWrap(bool w);
/// Clears the display and sets the cursor to 0, 0
void clear();
protected:
uint8_t cursor_x;
uint8_t cursor_y;
uint8_t textColor;
uint8_t textBackground;
uint8_t textSize;
bool textWrap;
};
#endif