Arduboy2 Library  6.0.0
Arduboy2.cpp
Go to the documentation of this file.
1 
7 #include "Arduboy2.h"
8 
9 //========================================
10 //========== class Arduboy2Base ==========
11 //========================================
12 
13 uint8_t Arduboy2Base::sBuffer[];
14 
15 uint16_t Arduboy2Base::frameCount = 0;
16 
19 
20 uint8_t Arduboy2Base::eachFrameMillis = 16;
21 uint8_t Arduboy2Base::thisFrameStart;
22 uint8_t Arduboy2Base::lastFrameDurationMs;
23 bool Arduboy2Base::justRendered = false;
24 
25 // functions called here should be public so users can create their
26 // own init functions if they need different behavior than `begin`
27 // provides by default.
28 //
29 // This code and it's documentation should be kept in sync with
30 // Aruduboy2::begin()
32 {
33  beginDoFirst();
34 
35  bootLogo();
36  // alternative logo functions. Work the same as bootLogo() but may reduce
37  // memory size if the sketch uses the same bitmap drawing function or
38  // `Sprites`/`SpritesB` class
39 // bootLogoCompressed();
40 // bootLogoSpritesSelfMasked();
41 // bootLogoSpritesOverwrite();
42 // bootLogoSpritesBSelfMasked();
43 // bootLogoSpritesBOverwrite();
44 
45  waitNoButtons(); // wait for all buttons to be released
46 }
47 
49 {
50  boot(); // raw hardware
51 
52  display(); // blank the display (sBuffer is global, so cleared automatically)
53 
54  flashlight(); // light the RGB LED and screen if UP button is being held.
55 
56  // check for and handle buttons held during start up for system control
57  systemButtons();
58 
59  audio.begin();
60 }
61 
63 {
64  if (!pressed(UP_BUTTON)) {
65  return;
66  }
67 
68  sendLCDCommand(OLED_ALL_PIXELS_ON); // smaller than allPixelsOn()
70 
71 #ifndef ARDUBOY_CORE // for Arduboy core timer 0 should remain enabled
72  // prevent the bootloader magic number from being overwritten by timer 0
73  // when a timer variable overlaps the magic number location, for when
74  // flashlight mode is used for upload problem recovery
75  power_timer0_disable();
76 #endif
77 
78  while (true) {
79  idle();
80  }
81 }
82 
84 {
85  while (pressed(B_BUTTON)) {
86  digitalWriteRGB(BLUE_LED, RGB_ON); // turn on blue LED
87  sysCtrlSound(UP_BUTTON + B_BUTTON, GREEN_LED, 0xff);
88  sysCtrlSound(DOWN_BUTTON + B_BUTTON, RED_LED, 0);
89  delayShort(200);
90  }
91 
92  digitalWriteRGB(BLUE_LED, RGB_OFF); // turn off blue LED
93 }
94 
95 void Arduboy2Base::sysCtrlSound(uint8_t buttons, uint8_t led, uint8_t eeVal)
96 {
97  if (pressed(buttons)) {
98  digitalWriteRGB(BLUE_LED, RGB_OFF); // turn off blue LED
99  delayShort(200);
100  digitalWriteRGB(led, RGB_ON); // turn on "acknowledge" LED
101  EEPROM.update(eepromAudioOnOff, eeVal);
102  delayShort(500);
103  digitalWriteRGB(led, RGB_OFF); // turn off "acknowledge" LED
104 
105  while (pressed(buttons)) { } // Wait for button release
106  }
107 }
108 
110 {
111  bootLogoShell(drawLogoBitmap);
112 }
113 
114 void Arduboy2Base::drawLogoBitmap(int16_t y)
115 {
116  drawBitmap(20, y, arduboy_logo, 88, 16);
117 }
118 
120 {
121  bootLogoShell(drawLogoCompressed);
122 }
123 
124 void Arduboy2Base::drawLogoCompressed(int16_t y)
125 {
127 }
128 
130 {
131  bootLogoShell(drawLogoSpritesSelfMasked);
132 }
133 
134 void Arduboy2Base::drawLogoSpritesSelfMasked(int16_t y)
135 {
137 }
138 
140 {
141  bootLogoShell(drawLogoSpritesOverwrite);
142 }
143 
144 void Arduboy2Base::drawLogoSpritesOverwrite(int16_t y)
145 {
147 }
148 
150 {
151  bootLogoShell(drawLogoSpritesBSelfMasked);
152 }
153 
154 void Arduboy2Base::drawLogoSpritesBSelfMasked(int16_t y)
155 {
157 }
158 
160 {
161  bootLogoShell(drawLogoSpritesBOverwrite);
162 }
163 
164 void Arduboy2Base::drawLogoSpritesBOverwrite(int16_t y)
165 {
167 }
168 
169 // bootLogoText() should be kept in sync with bootLogoShell()
170 // if changes are made to one, equivalent changes should be made to the other
171 bool Arduboy2Base::bootLogoShell(void (&drawLogo)(int16_t))
172 {
173  bool showLEDs = readShowBootLogoLEDsFlag();
174 
175  if (!readShowBootLogoFlag()) {
176  return false;
177  }
178 
179  if (showLEDs) {
181  }
182 
183  for (int16_t y = -15; y <= 24; y++) {
184  if (pressed(RIGHT_BUTTON)) {
185  digitalWriteRGB(RGB_OFF, RGB_OFF, RGB_OFF); // all LEDs off
186  return false;
187  }
188 
189  if (showLEDs && y == 4) {
190  digitalWriteRGB(RED_LED, RGB_OFF); // red LED off
191  digitalWriteRGB(GREEN_LED, RGB_ON); // green LED on
192  }
193 
194  // Using display(CLEAR_BUFFER) instead of clear() may save code space.
195  // The extra time it takes to repaint the previous logo isn't an issue.
197  (*drawLogo)(y); // call the function that actually draws the logo
198  display();
199  delayShort(15);
200  }
201 
202  if (showLEDs) {
203  digitalWriteRGB(GREEN_LED, RGB_OFF); // green LED off
204  digitalWriteRGB(BLUE_LED, RGB_ON); // blue LED on
205  }
206  delayShort(400);
208 
209  return true;
210 }
211 
212 // wait for all buttons to be released
214 {
215  do {
216  delayShort(50); // simple button debounce
217  } while (buttonsState());
218 }
219 
220 /* Frame management */
221 
222 void Arduboy2Base::setFrameRate(uint8_t rate)
223 {
224  eachFrameMillis = 1000 / rate;
225 }
226 
227 void Arduboy2Base::setFrameDuration(uint8_t duration)
228 {
229  eachFrameMillis = duration;
230 }
231 
232 bool Arduboy2Base::everyXFrames(uint8_t frames)
233 {
234  return frameCount % frames == 0;
235 }
236 
238 {
239  uint8_t now = (uint8_t) millis();
240  uint8_t frameDurationMs = now - thisFrameStart;
241 
242  if (justRendered) {
243  lastFrameDurationMs = frameDurationMs;
244  justRendered = false;
245  return false;
246  }
247  else if (frameDurationMs < eachFrameMillis) {
248  // Only idle if at least a full millisecond remains, since idle() may
249  // sleep the processor until the next millisecond timer interrupt.
250  if (++frameDurationMs < eachFrameMillis) {
251  idle();
252  }
253 
254  return false;
255  }
256 
257  // pre-render
258  justRendered = true;
259  thisFrameStart = now;
260  frameCount++;
261 
262  return true;
263 }
264 
266 {
267  bool ret = nextFrame();
268 
269  if (ret) {
270  if (lastFrameDurationMs > eachFrameMillis)
271  TXLED1;
272  else
273  TXLED0;
274  }
275  return ret;
276 }
277 
279 {
280  return lastFrameDurationMs*100 / eachFrameMillis;
281 }
282 
284 {
285  randomSeed(generateRandomSeed());
286 }
287 
288 /* Graphics */
289 
291 {
292  fillScreen(BLACK);
293 }
294 
295 void Arduboy2Base::drawPixel(int16_t x, int16_t y, uint8_t color)
296 {
297  if (x < 0 || x > (WIDTH-1) || y < 0 || y > (HEIGHT-1))
298  {
299  return;
300  }
301 
302  uint16_t row_offset;
303  uint8_t bit;
304 
305  asm volatile
306  (
307  // bit = 1 << (y & 7)
308  "ldi %[bit], 1 \n" //bit = 1;
309  "sbrc %[y], 1 \n" //if (y & _BV(1)) bit = 4;
310  "ldi %[bit], 4 \n"
311  "sbrc %[y], 0 \n" //if (y & _BV(0)) bit = bit << 1;
312  "lsl %[bit] \n"
313  "sbrc %[y], 2 \n" //if (y & _BV(2)) bit = (bit << 4) | (bit >> 4);
314  "swap %[bit] \n"
315  //row_offset = y / 8 * WIDTH + x;
316  "andi %A[y], 0xf8 \n" //row_offset = (y & 0xF8) * WIDTH / 8
317  "mul %[width_offset], %A[y] \n"
318  "movw %[row_offset], r0 \n"
319  "clr __zero_reg__ \n"
320  "add %A[row_offset], %[x] \n" //row_offset += x
321 #if WIDTH != 128
322  "adc %B[row_offset], __zero_reg__ \n" // only non 128 width can overflow
323 #endif
324  : [row_offset] "=&x" (row_offset), // upper register (ANDI)
325  [bit] "=&d" (bit), // upper register (LDI)
326  [y] "+d" (y) // upper register (ANDI), must be writable
327  : [width_offset] "r" ((uint8_t)(WIDTH/8)),
328  [x] "r" ((uint8_t)x)
329  :
330  );
331  uint8_t data = sBuffer[row_offset] | bit;
332  if (!(color & _BV(0))) data ^= bit;
333  sBuffer[row_offset] = data;
334 }
335 #if 0
336 // For reference, this is the C++ equivalent
337 void Arduboy2Base::drawPixel(int16_t x, int16_t y, uint8_t color)
338 {
339  if (x < 0 || x > (WIDTH-1) || y < 0 || y > (HEIGHT-1))
340  {
341  return;
342  }
343 
344  uint16_t row_offset;
345  uint8_t bit;
346 
347  bit = 1 << (y & 7);
348  row_offset = (y & 0xF8) * WIDTH / 8 + x;
349  uint8_t data = sBuffer[row_offset] | bit;
350  if (!color) data ^= bit;
351  sBuffer[row_offset] = data;
352 }
353 #endif
354 
355 uint8_t Arduboy2Base::getPixel(uint8_t x, uint8_t y)
356 {
357  uint8_t row = y / 8;
358  uint8_t bit_position = y % 8;
359  return (sBuffer[(row*WIDTH) + x] & _BV(bit_position)) >> bit_position;
360 }
361 
362 void Arduboy2Base::drawCircle(int16_t x0, int16_t y0, uint8_t r, uint8_t color)
363 {
364  int16_t f = 1 - r;
365  int16_t ddF_x = 1;
366  int16_t ddF_y = -2 * r;
367  int16_t x = 0;
368  int16_t y = r;
369 
370  drawPixel(x0, y0+r, color);
371  drawPixel(x0, y0-r, color);
372  drawPixel(x0+r, y0, color);
373  drawPixel(x0-r, y0, color);
374 
375  while (x<y)
376  {
377  if (f >= 0)
378  {
379  y--;
380  ddF_y += 2;
381  f += ddF_y;
382  }
383 
384  x++;
385  ddF_x += 2;
386  f += ddF_x;
387 
388  drawPixel(x0 + x, y0 + y, color);
389  drawPixel(x0 - x, y0 + y, color);
390  drawPixel(x0 + x, y0 - y, color);
391  drawPixel(x0 - x, y0 - y, color);
392  drawPixel(x0 + y, y0 + x, color);
393  drawPixel(x0 - y, y0 + x, color);
394  drawPixel(x0 + y, y0 - x, color);
395  drawPixel(x0 - y, y0 - x, color);
396  }
397 }
398 
399 void Arduboy2Base::drawCircleHelper
400 (int16_t x0, int16_t y0, uint8_t r, uint8_t corners, uint8_t color)
401 {
402  int16_t f = 1 - r;
403  int16_t ddF_x = 1;
404  int16_t ddF_y = -2 * r;
405  int16_t x = 0;
406  int16_t y = r;
407 
408  while (x<y)
409  {
410  if (f >= 0)
411  {
412  y--;
413  ddF_y += 2;
414  f += ddF_y;
415  }
416 
417  x++;
418  ddF_x += 2;
419  f += ddF_x;
420 
421  if (corners & 0x4) // lower right
422  {
423  drawPixel(x0 + x, y0 + y, color);
424  drawPixel(x0 + y, y0 + x, color);
425  }
426  if (corners & 0x2) // upper right
427  {
428  drawPixel(x0 + x, y0 - y, color);
429  drawPixel(x0 + y, y0 - x, color);
430  }
431  if (corners & 0x8) // lower left
432  {
433  drawPixel(x0 - y, y0 + x, color);
434  drawPixel(x0 - x, y0 + y, color);
435  }
436  if (corners & 0x1) // upper left
437  {
438  drawPixel(x0 - y, y0 - x, color);
439  drawPixel(x0 - x, y0 - y, color);
440  }
441  }
442 }
443 
444 void Arduboy2Base::fillCircle(int16_t x0, int16_t y0, uint8_t r, uint8_t color)
445 {
446  drawFastVLine(x0, y0-r, 2*r+1, color);
447  fillCircleHelper(x0, y0, r, 3, 0, color);
448 }
449 
450 void Arduboy2Base::fillCircleHelper
451 (int16_t x0, int16_t y0, uint8_t r, uint8_t sides, int16_t delta,
452  uint8_t color)
453 {
454  int16_t f = 1 - r;
455  int16_t ddF_x = 1;
456  int16_t ddF_y = -2 * r;
457  int16_t x = 0;
458  int16_t y = r;
459 
460  while (x < y)
461  {
462  if (f >= 0)
463  {
464  y--;
465  ddF_y += 2;
466  f += ddF_y;
467  }
468 
469  x++;
470  ddF_x += 2;
471  f += ddF_x;
472 
473  if (sides & 0x1) // right side
474  {
475  drawFastVLine(x0+x, y0-y, 2*y+1+delta, color);
476  drawFastVLine(x0+y, y0-x, 2*x+1+delta, color);
477  }
478 
479  if (sides & 0x2) // left side
480  {
481  drawFastVLine(x0-x, y0-y, 2*y+1+delta, color);
482  drawFastVLine(x0-y, y0-x, 2*x+1+delta, color);
483  }
484  }
485 }
486 
488 (int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint8_t color)
489 {
490  // bresenham's algorithm - thx wikpedia
491  bool steep = abs(y1 - y0) > abs(x1 - x0);
492  if (steep) {
493  swapInt16(x0, y0);
494  swapInt16(x1, y1);
495  }
496 
497  if (x0 > x1) {
498  swapInt16(x0, x1);
499  swapInt16(y0, y1);
500  }
501 
502  int16_t dx, dy;
503  dx = x1 - x0;
504  dy = abs(y1 - y0);
505 
506  int16_t err = dx / 2;
507  int8_t ystep;
508 
509  if (y0 < y1)
510  {
511  ystep = 1;
512  }
513  else
514  {
515  ystep = -1;
516  }
517 
518  for (; x0 <= x1; x0++)
519  {
520  if (steep)
521  {
522  drawPixel(y0, x0, color);
523  }
524  else
525  {
526  drawPixel(x0, y0, color);
527  }
528 
529  err -= dy;
530  if (err < 0)
531  {
532  y0 += ystep;
533  err += dx;
534  }
535  }
536 }
537 
539 (int16_t x, int16_t y, uint8_t w, uint8_t h, uint8_t color)
540 {
541  drawFastHLine(x, y, w, color);
542  drawFastHLine(x, y+h-1, w, color);
543  drawFastVLine(x, y, h, color);
544  drawFastVLine(x+w-1, y, h, color);
545 }
546 
548 (int16_t x, int16_t y, uint8_t h, uint8_t color)
549 {
550  int end = y+h;
551  for (int a = max(0,y); a < min(end,HEIGHT); a++)
552  {
553  drawPixel(x,a,color);
554  }
555 }
556 
558 (int16_t x, int16_t y, uint8_t w, uint8_t color)
559 {
560  int16_t xEnd; // last x point + 1
561 
562  // Do y bounds checks
563  if (y < 0 || y >= HEIGHT)
564  return;
565 
566  xEnd = x + w;
567 
568  // Check if the entire line is not on the display
569  if (xEnd <= 0 || x >= WIDTH)
570  return;
571 
572  // Don't start before the left edge
573  if (x < 0)
574  x = 0;
575 
576  // Don't end past the right edge
577  if (xEnd > WIDTH)
578  xEnd = WIDTH;
579 
580  // calculate actual width (even if unchanged)
581  w = xEnd - x;
582 
583  // buffer pointer plus row offset + x offset
584  register uint8_t *pBuf = sBuffer + ((y / 8) * WIDTH) + x;
585 
586  // pixel mask
587  register uint8_t mask = 1 << (y & 7);
588 
589  switch (color)
590  {
591  case WHITE:
592  while (w--)
593  {
594  *pBuf++ |= mask;
595  }
596  break;
597 
598  case BLACK:
599  mask = ~mask;
600  while (w--)
601  {
602  *pBuf++ &= mask;
603  }
604  break;
605  }
606 }
607 
609 (int16_t x, int16_t y, uint8_t w, uint8_t h, uint8_t color)
610 {
611  // stupidest version - update in subclasses if desired!
612  for (int16_t i=x; i<x+w; i++)
613  {
614  drawFastVLine(i, y, h, color);
615  }
616 }
617 
618 void Arduboy2Base::fillScreen(uint8_t color)
619 {
620  // C version:
621  //
622  // if (color != BLACK)
623  // {
624  // color = 0xFF; // all pixels on
625  // }
626  // for (int16_t i = 0; i < WIDTH * HEIGTH / 8; i++)
627  // {
628  // sBuffer[i] = color;
629  // }
630 
631  // This asm version is hard coded for 1024 bytes. It doesn't use the defined
632  // WIDTH and HEIGHT values. It will have to be modified for a different
633  // screen buffer size.
634  // It also assumes color value for BLACK is 0.
635 
636  // local variable for screen buffer pointer,
637  // which can be declared a read-write operand
638  uint8_t* bPtr = sBuffer;
639 
640  asm volatile
641  (
642  // if value is zero, skip assigning to 0xff
643  "cpse %[color], __zero_reg__\n"
644  "ldi %[color], 0xFF\n"
645  // counter = 0
646  "clr __tmp_reg__\n"
647  "1:\n"
648  // (4x) push zero into screen buffer,
649  // then increment buffer position
650  "st Z+, %[color]\n"
651  "st Z+, %[color]\n"
652  "st Z+, %[color]\n"
653  "st Z+, %[color]\n"
654  // increase counter
655  "inc __tmp_reg__\n"
656  // repeat for 256 loops
657  // (until counter rolls over back to 0)
658  "brne 1b\n"
659  : [color] "+d" (color),
660  "+z" (bPtr)
661  :
662  :
663  );
664 }
665 
667 (int16_t x, int16_t y, uint8_t w, uint8_t h, uint8_t r, uint8_t color)
668 {
669  // smarter version
670  drawFastHLine(x+r, y, w-2*r, color); // Top
671  drawFastHLine(x+r, y+h-1, w-2*r, color); // Bottom
672  drawFastVLine(x, y+r, h-2*r, color); // Left
673  drawFastVLine(x+w-1, y+r, h-2*r, color); // Right
674  // draw four corners
675  drawCircleHelper(x+r, y+r, r, 1, color);
676  drawCircleHelper(x+w-r-1, y+r, r, 2, color);
677  drawCircleHelper(x+w-r-1, y+h-r-1, r, 4, color);
678  drawCircleHelper(x+r, y+h-r-1, r, 8, color);
679 }
680 
682 (int16_t x, int16_t y, uint8_t w, uint8_t h, uint8_t r, uint8_t color)
683 {
684  // smarter version
685  fillRect(x+r, y, w-2*r, h, color);
686 
687  // draw four corners
688  fillCircleHelper(x+w-r-1, y+r, r, 1, h-2*r-1, color);
689  fillCircleHelper(x+r, y+r, r, 2, h-2*r-1, color);
690 }
691 
693 (int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint8_t color)
694 {
695  drawLine(x0, y0, x1, y1, color);
696  drawLine(x1, y1, x2, y2, color);
697  drawLine(x2, y2, x0, y0, color);
698 }
699 
701 (int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint8_t color)
702 {
703 
704  int16_t a, b, y, last;
705  // Sort coordinates by Y order (y2 >= y1 >= y0)
706  if (y0 > y1)
707  {
708  swapInt16(y0, y1); swapInt16(x0, x1);
709  }
710  if (y1 > y2)
711  {
712  swapInt16(y2, y1); swapInt16(x2, x1);
713  }
714  if (y0 > y1)
715  {
716  swapInt16(y0, y1); swapInt16(x0, x1);
717  }
718 
719  if(y0 == y2)
720  { // Handle awkward all-on-same-line case as its own thing
721  a = b = x0;
722  if(x1 < a)
723  {
724  a = x1;
725  }
726  else if(x1 > b)
727  {
728  b = x1;
729  }
730  if(x2 < a)
731  {
732  a = x2;
733  }
734  else if(x2 > b)
735  {
736  b = x2;
737  }
738  drawFastHLine(a, y0, b-a+1, color);
739  return;
740  }
741 
742  int16_t dx01 = x1 - x0,
743  dy01 = y1 - y0,
744  dx02 = x2 - x0,
745  dy02 = y2 - y0,
746  dx12 = x2 - x1,
747  dy12 = y2 - y1,
748  sa = 0,
749  sb = 0;
750 
751  // For upper part of triangle, find scanline crossings for segments
752  // 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1
753  // is included here (and second loop will be skipped, avoiding a /0
754  // error there), otherwise scanline y1 is skipped here and handled
755  // in the second loop...which also avoids a /0 error here if y0=y1
756  // (flat-topped triangle).
757  if (y1 == y2)
758  {
759  last = y1; // Include y1 scanline
760  }
761  else
762  {
763  last = y1-1; // Skip it
764  }
765 
766 
767  for(y = y0; y <= last; y++)
768  {
769  a = x0 + sa / dy01;
770  b = x0 + sb / dy02;
771  sa += dx01;
772  sb += dx02;
773 
774  if(a > b)
775  {
776  swapInt16(a,b);
777  }
778 
779  drawFastHLine(a, y, b-a+1, color);
780  }
781 
782  // For lower part of triangle, find scanline crossings for segments
783  // 0-2 and 1-2. This loop is skipped if y1=y2.
784  sa = dx12 * (y - y1);
785  sb = dx02 * (y - y0);
786 
787  for(; y <= y2; y++)
788  {
789  a = x1 + sa / dy12;
790  b = x0 + sb / dy02;
791  sa += dx12;
792  sb += dx02;
793 
794  if(a > b)
795  {
796  swapInt16(a,b);
797  }
798 
799  drawFastHLine(a, y, b-a+1, color);
800  }
801 }
802 
804 (int16_t x, int16_t y, const uint8_t *bitmap, uint8_t w, uint8_t h,
805  uint8_t color)
806 {
807  // no need to draw at all if we're offscreen
808  if (x + w <= 0 || x > WIDTH - 1 || y + h <= 0 || y > HEIGHT - 1)
809  return;
810 
811  int yOffset = abs(y) % 8;
812  int sRow = y / 8;
813  if (y < 0) {
814  sRow--;
815  yOffset = 8 - yOffset;
816  }
817  int rows = h/8;
818  if (h%8!=0) rows++;
819  for (int a = 0; a < rows; a++) {
820  int bRow = sRow + a;
821  if (bRow > (HEIGHT/8)-1) break;
822  if (bRow > -2) {
823  for (int iCol = 0; iCol<w; iCol++) {
824  if (iCol + x > (WIDTH-1)) break;
825  if (iCol + x >= 0) {
826  if (bRow >= 0) {
827  if (color == WHITE)
828  sBuffer[(bRow*WIDTH) + x + iCol] |= pgm_read_byte(bitmap+(a*w)+iCol) << yOffset;
829  else if (color == BLACK)
830  sBuffer[(bRow*WIDTH) + x + iCol] &= ~(pgm_read_byte(bitmap+(a*w)+iCol) << yOffset);
831  else
832  sBuffer[(bRow*WIDTH) + x + iCol] ^= pgm_read_byte(bitmap+(a*w)+iCol) << yOffset;
833  }
834  if (yOffset && bRow<(HEIGHT/8)-1 && bRow > -2) {
835  if (color == WHITE)
836  sBuffer[((bRow+1)*WIDTH) + x + iCol] |= pgm_read_byte(bitmap+(a*w)+iCol) >> (8-yOffset);
837  else if (color == BLACK)
838  sBuffer[((bRow+1)*WIDTH) + x + iCol] &= ~(pgm_read_byte(bitmap+(a*w)+iCol) >> (8-yOffset));
839  else
840  sBuffer[((bRow+1)*WIDTH) + x + iCol] ^= pgm_read_byte(bitmap+(a*w)+iCol) >> (8-yOffset);
841  }
842  }
843  }
844  }
845  }
846 }
847 
848 
850 (int16_t x, int16_t y, const uint8_t *bitmap, uint8_t w, uint8_t h, uint8_t color)
851 {
852  // no need to draw at all of we're offscreen
853  if (x + w <= 0 || x > WIDTH - 1 || y + h <= 0 || y > HEIGHT - 1)
854  return;
855 
856  int16_t xi, yi, byteWidth = (w + 7) / 8;
857  for(yi = 0; yi < h; yi++) {
858  for(xi = 0; xi < w; xi++ ) {
859  if(pgm_read_byte(bitmap + yi * byteWidth + xi / 8) & (128 >> (xi & 7))) {
860  drawPixel(x + xi, y + yi, color);
861  }
862  }
863  }
864 }
865 
866 // Helper for drawCompressed()
867 class Arduboy2Base::BitStreamReader
868 {
869  private:
870  const uint8_t *source;
871  uint16_t sourceIndex;
872  uint8_t bitBuffer;
873  uint8_t byteBuffer;
874 
875  public:
876  BitStreamReader(const uint8_t *bitmap)
877  : source(bitmap), sourceIndex(), bitBuffer(), byteBuffer()
878  {
879  }
880 
881  uint16_t readBits(uint16_t bitCount)
882  {
883  uint16_t result = 0;
884  for (uint16_t i = 0; i < bitCount; i++)
885  {
886  if (bitBuffer == 0)
887  {
888  bitBuffer = 0x1;
889  byteBuffer = pgm_read_byte(&source[sourceIndex]);
890  ++sourceIndex;
891  }
892 
893  if ((byteBuffer & bitBuffer) != 0)
894  result |= (1 << i);
895 
896  bitBuffer <<= 1;
897  }
898  return result;
899  }
900 };
901 
902 void Arduboy2Base::drawCompressed(int16_t sx, int16_t sy, const uint8_t *bitmap, uint8_t color)
903 {
904  // set up decompress state
905  BitStreamReader cs(bitmap);
906 
907  // read header
908  int width = (int)cs.readBits(8) + 1;
909  int height = (int)cs.readBits(8) + 1;
910  uint8_t spanColour = (uint8_t)cs.readBits(1); // starting colour
911 
912  // no need to draw at all if we're offscreen
913  if ((sx + width <= 0) || (sx > WIDTH - 1) || (sy + height <= 0) || (sy > HEIGHT - 1))
914  return;
915 
916  // sy = sy - (frame * height);
917  int yOffset = abs(sy) % 8;
918  int startRow = sy / 8;
919  if (sy < 0) {
920  startRow--;
921  yOffset = 8 - yOffset;
922  }
923  int rows = height / 8;
924  if ((height % 8) != 0)
925  ++rows;
926 
927  int rowOffset = 0; // +(frame*rows);
928  int columnOffset = 0;
929 
930  uint8_t byte = 0x00;
931  uint8_t bit = 0x01;
932  while (rowOffset < rows) // + (frame*rows))
933  {
934  uint16_t bitLength = 1;
935  while (cs.readBits(1) == 0)
936  bitLength += 2;
937 
938  uint16_t len = cs.readBits(bitLength) + 1; // span length
939 
940  // draw the span
941  for (uint16_t i = 0; i < len; ++i)
942  {
943  if (spanColour != 0)
944  byte |= bit;
945  bit <<= 1;
946 
947  if (bit == 0) // reached end of byte
948  {
949  // draw
950  int bRow = startRow + rowOffset;
951 
952  //if (byte) // possible optimisation
953  if ((bRow <= (HEIGHT / 8) - 1) && (bRow > -2) &&
954  (columnOffset + sx <= (WIDTH - 1)) && (columnOffset + sx >= 0))
955  {
956  int16_t offset = (bRow * WIDTH) + sx + columnOffset;
957  if (bRow >= 0)
958  {
959  int16_t index = offset;
960  uint8_t value = byte << yOffset;
961 
962  if (color != 0)
963  sBuffer[index] |= value;
964  else
965  sBuffer[index] &= ~value;
966  }
967  if ((yOffset != 0) && (bRow < (HEIGHT / 8) - 1))
968  {
969  int16_t index = offset + WIDTH;
970  uint8_t value = byte >> (8 - yOffset);
971 
972  if (color != 0)
973  sBuffer[index] |= value;
974  else
975  sBuffer[index] &= ~value;
976  }
977  }
978 
979  // iterate
980  ++columnOffset;
981  if (columnOffset >= width)
982  {
983  columnOffset = 0;
984  ++rowOffset;
985  }
986 
987  // reset byte
988  byte = 0x00;
989  bit = 0x01;
990  }
991  }
992 
993  spanColour ^= 0x01; // toggle colour bit (bit 0) for next span
994  }
995 }
996 
998 {
1000 }
1001 
1002 void Arduboy2Base::display(bool clear)
1003 {
1005 }
1006 
1008 {
1009  return sBuffer;
1010 }
1011 
1012 bool Arduboy2Base::pressed(uint8_t buttons)
1013 {
1014  return (buttonsState() & buttons) == buttons;
1015 }
1016 
1017 bool Arduboy2Base::anyPressed(uint8_t buttons)
1018 {
1019  return (buttonsState() & buttons) != 0;
1020 }
1021 
1022 bool Arduboy2Base::notPressed(uint8_t buttons)
1023 {
1024  return (buttonsState() & buttons) == 0;
1025 }
1026 
1028 {
1031 }
1032 
1033 bool Arduboy2Base::justPressed(uint8_t button)
1034 {
1035  return (!(previousButtonState & button) && (currentButtonState & button));
1036 }
1037 
1038 bool Arduboy2Base::justReleased(uint8_t button)
1039 {
1040  return ((previousButtonState & button) && !(currentButtonState & button));
1041 }
1042 
1044 {
1045  return ((point.x >= rect.x) && (point.x < rect.x + rect.width) &&
1046  (point.y >= rect.y) && (point.y < rect.y + rect.height));
1047 }
1048 
1049 bool Arduboy2Base::collide(Rect rect1, Rect rect2)
1050 {
1051  return !(rect2.x >= rect1.x + rect1.width ||
1052  rect2.x + rect2.width <= rect1.x ||
1053  rect2.y >= rect1.y + rect1.height ||
1054  rect2.y + rect2.height <= rect1.y);
1055 }
1056 
1058 {
1059  return EEPROM.read(eepromUnitID) |
1060  (((uint16_t)(EEPROM.read(eepromUnitID + 1))) << 8);
1061 }
1062 
1063 void Arduboy2Base::writeUnitID(uint16_t id)
1064 {
1065  EEPROM.update(eepromUnitID, (uint8_t)(id & 0xff));
1066  EEPROM.update(eepromUnitID + 1, (uint8_t)(id >> 8));
1067 }
1068 
1069 uint8_t Arduboy2Base::readUnitName(char* name)
1070 {
1071  char val;
1072  uint8_t dest;
1073  uint8_t src = eepromUnitName;
1074 
1075  for (dest = 0; dest < ARDUBOY_UNIT_NAME_LEN; dest++)
1076  {
1077  val = EEPROM.read(src);
1078  name[dest] = val;
1079  src++;
1080  if (val == 0x00 || (byte)val == 0xFF) {
1081  break;
1082  }
1083  }
1084 
1085  name[dest] = 0x00;
1086  return dest;
1087 }
1088 
1089 void Arduboy2Base::writeUnitName(const char* name)
1090 {
1091  bool done = false;
1092  uint8_t dest = eepromUnitName;
1093 
1094  for (uint8_t src = 0; src < ARDUBOY_UNIT_NAME_LEN; src++)
1095  {
1096  if (name[src] == 0x00) {
1097  done = true;
1098  }
1099  // write character or 0 pad if finished
1100  EEPROM.update(dest, done ? 0x00 : name[src]);
1101  dest++;
1102  }
1103 }
1104 
1106 {
1107  return (EEPROM.read(eepromSysFlags) & sysFlagShowLogoMask);
1108 }
1109 
1111 {
1112  uint8_t flags = EEPROM.read(eepromSysFlags);
1113 
1114  bitWrite(flags, sysFlagShowLogoBit, val);
1115  EEPROM.update(eepromSysFlags, flags);
1116 }
1117 
1119 {
1120  return (EEPROM.read(eepromSysFlags) & sysFlagUnameMask);
1121 }
1122 
1124 {
1125  uint8_t flags = EEPROM.read(eepromSysFlags);
1126 
1127  bitWrite(flags, sysFlagUnameBit, val);
1128  EEPROM.update(eepromSysFlags, flags);
1129 }
1130 
1132 {
1133  return (EEPROM.read(eepromSysFlags) & sysFlagShowLogoLEDsMask);
1134 }
1135 
1137 {
1138  uint8_t flags = EEPROM.read(eepromSysFlags);
1139 
1140  bitWrite(flags, sysFlagShowLogoLEDsBit, val);
1141  EEPROM.update(eepromSysFlags, flags);
1142 }
1143 
1144 void Arduboy2Base::swapInt16(int16_t& a, int16_t& b)
1145 {
1146  int16_t temp = a;
1147  a = b;
1148  b = temp;
1149 }
1150 
1151 
1152 //====================================
1153 //========== class Arduboy2 ==========
1154 //====================================
1155 
1156 int16_t Arduboy2::cursor_x = 0;
1157 int16_t Arduboy2::cursor_y = 0;
1158 uint8_t Arduboy2::textColor = WHITE;
1159 uint8_t Arduboy2::textBackground = BLACK;
1160 uint8_t Arduboy2::textSize = 1;
1161 bool Arduboy2::textWrap = false;
1162 bool Arduboy2::textRaw = false;
1163 
1164 // functions called here should be public so users can create their
1165 // own init functions if they need different behavior than `begin`
1166 // provides by default.
1167 //
1168 // This code and it's documentation should be kept in sync with
1169 // Aruduboy2Base::begin()
1171 {
1172  beginDoFirst();
1173 
1174  bootLogo();
1175  // alternative logo functions. Work the same as bootLogo() but may reduce
1176  // memory size if the sketch uses the same bitmap drawing function or
1177  // `Sprites`/`SpritesB` class
1178 // bootLogoCompressed();
1179 // bootLogoSpritesSelfMasked();
1180 // bootLogoSpritesOverwrite();
1181 // bootLogoSpritesBSelfMasked();
1182 // bootLogoSpritesBOverwrite();
1183 
1184  waitNoButtons();
1185 }
1186 
1188 {
1189  if (bootLogoShell(drawLogoBitmap))
1190  {
1191  bootLogoExtra();
1192  }
1193 }
1194 
1196 {
1197  if (bootLogoShell(drawLogoCompressed))
1198  {
1199  bootLogoExtra();
1200  }
1201 }
1202 
1204 {
1205  if (bootLogoShell(drawLogoSpritesSelfMasked))
1206  {
1207  bootLogoExtra();
1208  }
1209 }
1210 
1212 {
1213  if (bootLogoShell(drawLogoSpritesOverwrite))
1214  {
1215  bootLogoExtra();
1216  }
1217 }
1218 
1220 {
1221  if (bootLogoShell(drawLogoSpritesBSelfMasked))
1222  {
1223  bootLogoExtra();
1224  }
1225 }
1226 
1228 {
1229  if (bootLogoShell(drawLogoSpritesBOverwrite))
1230  {
1231  bootLogoExtra();
1232  }
1233 }
1234 
1235 // bootLogoText() should be kept in sync with bootLogoShell()
1236 // if changes are made to one, equivalent changes should be made to the other
1238 {
1239  bool showLEDs = readShowBootLogoLEDsFlag();
1240 
1241  if (!readShowBootLogoFlag()) {
1242  return;
1243  }
1244 
1245  if (showLEDs) {
1247  }
1248 
1249  for (int16_t y = -15; y <= 24; y++) {
1250  if (pressed(RIGHT_BUTTON)) {
1251  digitalWriteRGB(RGB_OFF, RGB_OFF, RGB_OFF); // all LEDs off
1252  return;
1253  }
1254 
1255  if (showLEDs && y == 4) {
1256  digitalWriteRGB(RED_LED, RGB_OFF); // red LED off
1257  digitalWriteRGB(GREEN_LED, RGB_ON); // green LED on
1258  }
1259 
1260  // Using display(CLEAR_BUFFER) instead of clear() may save code space.
1261  // The extra time it takes to repaint the previous logo isn't an issue.
1263  cursor_x = 23;
1264  cursor_y = y;
1265  textSize = 2;
1266  print(F("ARDUBOY"));
1267  textSize = 1;
1268  display();
1269  delayShort(11);
1270  }
1271 
1272  if (showLEDs) {
1273  digitalWriteRGB(GREEN_LED, RGB_OFF); // green LED off
1274  digitalWriteRGB(BLUE_LED, RGB_ON); // blue LED on
1275  }
1276  delayShort(400);
1278 
1279  bootLogoExtra();
1280 }
1281 
1283 {
1284  uint8_t c;
1285 
1286  if (!readShowUnitNameFlag())
1287  {
1288  return;
1289  }
1290 
1291  c = EEPROM.read(eepromUnitName);
1292 
1293  if (c != 0xFF && c != 0x00)
1294  {
1295  uint8_t i = eepromUnitName;
1296  cursor_x = 50;
1297  cursor_y = 56;
1298 
1299  do
1300  {
1301  write(c);
1302  c = EEPROM.read(++i);
1303  }
1304  while (i < eepromUnitName + ARDUBOY_UNIT_NAME_LEN);
1305 
1306  display();
1307  delayShort(1000);
1308  }
1309 }
1310 
1311 size_t Arduboy2::write(uint8_t c)
1312 {
1313  if ((c == '\r') && !textRaw)
1314  {
1315  return 1;
1316  }
1317 
1318  if (((c == '\n') && !textRaw) ||
1319  (textWrap && (cursor_x > (WIDTH - (characterWidth * textSize)))))
1320  {
1321  cursor_x = 0;
1322  cursor_y += fullCharacterHeight * textSize;
1323  }
1324 
1325  if ((c != '\n') || textRaw)
1326  {
1327  drawChar(cursor_x, cursor_y, c, textColor, textBackground, textSize);
1328  cursor_x += fullCharacterWidth * textSize;
1329  }
1330 
1331  return 1;
1332 }
1333 
1335  (int16_t x, int16_t y, uint8_t c, uint8_t color, uint8_t bg, uint8_t size)
1336 {
1337 // It is assumed that rendering characters fully off screen will be rare,
1338 // so let drawPixel() handle off screen checks, to reduce code size at the
1339 // expense of slower off screen character handling.
1340 #if 0
1341  if ((x >= WIDTH) || // Clip right
1342  (y >= HEIGHT) || // Clip bottom
1343  ((x + characterWidth * size - 1) < 0) || // Clip left
1344  ((y + characterHeight * size - 1) < 0) // Clip top
1345  )
1346  {
1347  return;
1348  }
1349 #endif
1350 
1351  bool drawBackground = bg != color;
1352  const uint8_t* bitmap =
1353  &font5x7[c * characterWidth * ((characterHeight + 8 - 1) / 8)];
1354 
1355  for (uint8_t i = 0; i < fullCharacterWidth; i++)
1356  {
1357  uint8_t column;
1358 
1359  if (characterHeight <= 8)
1360  {
1361  column = (i < characterWidth) ? pgm_read_byte(bitmap++) : 0;
1362  }
1363  else
1364  {
1365  column = 0;
1366  }
1367 
1368  // draw the character by columns. Top to bottom, left to right
1369  // including character spacing on the right
1370  for (uint8_t j = 0; j < characterHeight; j++)
1371  {
1372  if (characterHeight > 8)
1373  {
1374  // at this point variable "column" will be 0, either from initialization
1375  // or by having eight 0 bits shifted in by the >>= operation below
1376  if ((j % 8 == 0) && (i < characterWidth))
1377  {
1378  column = pgm_read_byte(bitmap++);
1379  }
1380  }
1381 
1382  // pixelIsSet should be a bool but at the time of writing,
1383  // the GCC AVR compiler generates less code if it's a uint8_t
1384  uint8_t pixelIsSet = column & 0x01;
1385 
1386  if (pixelIsSet || drawBackground)
1387  {
1388  for (uint8_t a = 0; a < size; a++)
1389  {
1390  for (uint8_t b = 0; b < size; b++)
1391  {
1392  drawPixel(x + (i * size) + a, y + (j * size) + b,
1393  pixelIsSet ? color : bg);
1394  }
1395  }
1396  }
1397  column >>= 1;
1398  }
1399 
1400  // draw the inter-line spacing pixels for this column if required
1401  if (drawBackground)
1402  {
1403  for (uint8_t j = characterHeight; j < fullCharacterHeight; j++)
1404  {
1405  for (uint8_t a = 0; a < size; a++)
1406  {
1407  for (uint8_t b = 0; b < size; b++)
1408  {
1409  drawPixel(x + (i * size) + a, y + (j * size) + b, bg);
1410  }
1411  }
1412  }
1413  }
1414  }
1415 }
1416 
1417 void Arduboy2::setCursor(int16_t x, int16_t y)
1418 {
1419  cursor_x = x;
1420  cursor_y = y;
1421 }
1422 
1423 void Arduboy2::setCursorX(int16_t x)
1424 {
1425  cursor_x = x;
1426 }
1427 
1428 void Arduboy2::setCursorY(int16_t y)
1429 {
1430  cursor_y = y;
1431 }
1432 
1434 {
1435  return cursor_x;
1436 }
1437 
1439 {
1440  return cursor_y;
1441 }
1442 
1443 void Arduboy2::setTextColor(uint8_t color)
1444 {
1445  textColor = color;
1446 }
1447 
1449 {
1450  return textColor;
1451 }
1452 
1454 {
1455  textBackground = bg;
1456 }
1457 
1459 {
1460  return textBackground;
1461 }
1462 
1463 void Arduboy2::setTextSize(uint8_t s)
1464 {
1465  // size must always be 1 or higher
1466  textSize = max(1, s);
1467 }
1468 
1470 {
1471  return textSize;
1472 }
1473 
1475 {
1476  textWrap = w;
1477 }
1478 
1480 {
1481  return textWrap;
1482 }
1483 
1485 {
1486  textRaw = raw;
1487 }
1488 
1490 {
1491  return textRaw;
1492 }
1493 
1495 {
1497  cursor_x = cursor_y = 0;
1498 }
1499 
Arduboy2Base::drawFastVLine
static void drawFastVLine(int16_t x, int16_t y, uint8_t h, uint8_t color=WHITE)
Draw a vertical line.
Definition: Arduboy2.cpp:548
Arduboy2Core::boot
static void boot()
Initialize the Arduboy's hardware.
Definition: Arduboy2Core.cpp:81
Arduboy2Base::display
static void display()
Copy the contents of the display buffer to the display.
Definition: Arduboy2.cpp:997
Arduboy2Base::fillRect
static void fillRect(int16_t x, int16_t y, uint8_t w, uint8_t h, uint8_t color=WHITE)
Draw a filled-in rectangle of a specified width and height.
Definition: Arduboy2.cpp:609
Arduboy2Base::previousButtonState
static uint8_t previousButtonState
Used by pollButtons() to hold the previous button state.
Definition: Arduboy2.h:1451
Arduboy2Base::pollButtons
static void pollButtons()
Poll the buttons and track their state over time.
Definition: Arduboy2.cpp:1027
Arduboy2Base::bootLogoSpritesSelfMasked
static void bootLogoSpritesSelfMasked()
Display the boot logo sequence using Sprites::drawSelfMasked().
Definition: Arduboy2.cpp:129
Arduboy2Core::sendLCDCommand
static void sendLCDCommand(uint8_t command)
Send a single command byte to the display.
Definition: Arduboy2Core.cpp:406
Arduboy2Base::drawRoundRect
static void drawRoundRect(int16_t x, int16_t y, uint8_t w, uint8_t h, uint8_t r, uint8_t color=WHITE)
Draw a rectangle with rounded corners.
Definition: Arduboy2.cpp:667
Arduboy2Base::drawLine
static void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint8_t color=WHITE)
Draw a line between two specified points.
Definition: Arduboy2.cpp:488
Arduboy2Base::fillTriangle
static void fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint8_t color=WHITE)
Draw a filled-in triangle given the coordinates of each corner.
Definition: Arduboy2.cpp:701
Arduboy2Base::drawTriangle
static void drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint8_t color=WHITE)
Draw a triangle given the coordinates of each corner.
Definition: Arduboy2.cpp:693
Arduboy2::bootLogoSpritesBOverwrite
void bootLogoSpritesBOverwrite()
Display the boot logo sequence using SpritesB::drawOverwrite().
Definition: Arduboy2.cpp:1227
WHITE
#define WHITE
Definition: Arduboy2.h:79
Arduboy2Base::everyXFrames
static bool everyXFrames(uint8_t frames)
Indicate if the specified number of frames has elapsed.
Definition: Arduboy2.cpp:232
RIGHT_BUTTON
#define RIGHT_BUTTON
Definition: Arduboy2Core.h:68
Arduboy2Base::initRandomSeed
static void initRandomSeed()
Seed the random number generator with a random value.
Definition: Arduboy2.cpp:283
Arduboy2Base::justPressed
static bool justPressed(uint8_t button)
Check if a button has just been pressed.
Definition: Arduboy2.cpp:1033
Arduboy2Base::drawCircle
static void drawCircle(int16_t x0, int16_t y0, uint8_t r, uint8_t color=WHITE)
Draw a circle of a given radius.
Definition: Arduboy2.cpp:362
Arduboy2Base::clear
static void clear()
Clear the display buffer.
Definition: Arduboy2.cpp:290
Point::x
int16_t x
Definition: Arduboy2.h:148
DOWN_BUTTON
#define DOWN_BUTTON
Definition: Arduboy2Core.h:70
RGB_OFF
#define RGB_OFF
Definition: Arduboy2Core.h:35
Arduboy2Base::currentButtonState
static uint8_t currentButtonState
Used by pollButtons() to hold the current button state.
Definition: Arduboy2.h:1395
Arduboy2::getTextBackground
static uint8_t getTextBackground()
Get the currently set text background color.
Definition: Arduboy2.cpp:1458
Arduboy2Base::drawCompressed
static void drawCompressed(int16_t sx, int16_t sy, const uint8_t *bitmap, uint8_t color=WHITE)
Draw a bitmap from an array of compressed data.
Definition: Arduboy2.cpp:902
Arduboy2::setTextBackground
static void setTextBackground(uint8_t bg)
Set the text background color.
Definition: Arduboy2.cpp:1453
Arduboy2::setTextColor
static void setTextColor(uint8_t color)
Set the text foreground color.
Definition: Arduboy2.cpp:1443
CLEAR_BUFFER
#define CLEAR_BUFFER
Definition: Arduboy2.h:91
Arduboy2::bootLogoSpritesSelfMasked
void bootLogoSpritesSelfMasked()
Display the boot logo sequence using Sprites::drawSelfMasked().
Definition: Arduboy2.cpp:1203
Arduboy2Core::idle
static void idle()
Idle the CPU to save power.
Definition: Arduboy2Core.cpp:278
Arduboy2Base::drawPixel
static void drawPixel(int16_t x, int16_t y, uint8_t color=WHITE)
Set a single pixel in the display buffer to the specified color.
Definition: Arduboy2.cpp:295
Point::y
int16_t y
Definition: Arduboy2.h:149
Arduboy2Base::cpuLoad
static int cpuLoad()
Return the load on the CPU as a percentage.
Definition: Arduboy2.cpp:278
BLUE_LED
#define BLUE_LED
Definition: Arduboy2Core.h:54
Arduboy2Base::sBuffer
static uint8_t sBuffer[(HEIGHT *WIDTH)/8]
The display buffer array in RAM.
Definition: Arduboy2.h:1465
Arduboy2Base::nextFrameDEV
static bool nextFrameDEV()
Indicate that it's time to render the next frame, and visually indicate if the code is running slower...
Definition: Arduboy2.cpp:265
Arduboy2Core::generateRandomSeed
static unsigned long generateRandomSeed()
Create a seed suitable for use with a pseudorandom number generator.
Definition: Arduboy2Core.cpp:564
Arduboy2Base::writeShowBootLogoFlag
static void writeShowBootLogoFlag(bool val)
Write the "Show Boot Logo" flag in system EEPROM.
Definition: Arduboy2.cpp:1110
Arduboy2Base::writeUnitID
static void writeUnitID(uint16_t id)
Write a unit ID to system EEPROM.
Definition: Arduboy2.cpp:1063
Arduboy2Base::collide
static bool collide(Point point, Rect rect)
Test if a point falls within a rectangle.
Definition: Arduboy2.cpp:1043
Arduboy2::write
virtual size_t write(uint8_t)
Write a single character at the current text cursor position.
Definition: Arduboy2.cpp:1311
Arduboy2::setTextWrap
static void setTextWrap(bool w)
Set or disable text wrap mode.
Definition: Arduboy2.cpp:1474
Rect::y
int16_t y
Definition: Arduboy2.h:111
B_BUTTON
#define B_BUTTON
Definition: Arduboy2Core.h:72
Arduboy2::bootLogoSpritesBSelfMasked
void bootLogoSpritesBSelfMasked()
Display the boot logo sequence using SpritesB::drawSelfMasked().
Definition: Arduboy2.cpp:1219
Arduboy2::setTextRawMode
static void setTextRawMode(bool raw)
Set or disable text raw mode, allowing special characters to be displayed.
Definition: Arduboy2.cpp:1484
Arduboy2Core::paintScreen
static void paintScreen(const uint8_t *image)
Paints an entire image directly to the display from program memory.
Definition: Arduboy2Core.cpp:319
GREEN_LED
#define GREEN_LED
Definition: Arduboy2Core.h:53
Arduboy2Core::height
static constexpr uint8_t height()
Get the height of the display in pixels.
Definition: Arduboy2Core.h:471
RGB_ON
#define RGB_ON
Definition: Arduboy2Core.h:34
Arduboy2Base::drawRect
static void drawRect(int16_t x, int16_t y, uint8_t w, uint8_t h, uint8_t color=WHITE)
Draw a rectangle of a specified width and height.
Definition: Arduboy2.cpp:539
Arduboy2Core::width
static constexpr uint8_t width()
Get the width of the display in pixels.
Definition: Arduboy2Core.h:464
Arduboy2Base::bootLogoCompressed
static void bootLogoCompressed()
Display the boot logo sequence using drawCompressed().
Definition: Arduboy2.cpp:119
Arduboy2::font5x7
static const PROGMEM uint8_t font5x7[]
The font used for text functions.
Definition: Arduboy2.h:2208
Arduboy2Base::audio
static Arduboy2Audio audio
An object created to provide audio control functions within this class.
Definition: Arduboy2.h:227
Arduboy2Base::drawSlowXYBitmap
static void drawSlowXYBitmap(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t w, uint8_t h, uint8_t color=WHITE)
Draw a bitmap from a horizontally oriented array in program memory.
Definition: Arduboy2.cpp:850
Arduboy2Base::nextFrame
static bool nextFrame()
Indicate that it's time to render the next frame.
Definition: Arduboy2.cpp:237
Arduboy2Base::notPressed
static bool notPressed(uint8_t buttons)
Test if the specified buttons are not pressed.
Definition: Arduboy2.cpp:1022
Rect::width
uint8_t width
Definition: Arduboy2.h:112
WIDTH
#define WIDTH
Definition: Arduboy2Core.h:242
Arduboy2Base::arduboy_logo_sprite
static const PROGMEM uint8_t arduboy_logo_sprite[]
The bitmap for the ARDUBOY logo in Sprites class drawSelfMasked() or drawOverwrite() format.
Definition: Arduboy2.h:1488
Arduboy2Base::drawBitmap
static void drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t w, uint8_t h, uint8_t color=WHITE)
Draw a bitmap from an array in program memory.
Definition: Arduboy2.cpp:804
Arduboy2Base::bootLogoSpritesBOverwrite
static void bootLogoSpritesBOverwrite()
Display the boot logo sequence using SpritesB::drawOverwrite().
Definition: Arduboy2.cpp:159
Arduboy2Base::fillRoundRect
static void fillRoundRect(int16_t x, int16_t y, uint8_t w, uint8_t h, uint8_t r, uint8_t color=WHITE)
Draw a filled-in rectangle with rounded corners.
Definition: Arduboy2.cpp:682
Arduboy2::bootLogoSpritesOverwrite
void bootLogoSpritesOverwrite()
Display the boot logo sequence using Sprites::drawOverwrite().
Definition: Arduboy2.cpp:1211
Arduboy2Base::getBuffer
static uint8_t * getBuffer()
Get a pointer to the display buffer in RAM.
Definition: Arduboy2.cpp:1007
Arduboy2::begin
void begin()
Initialize the hardware, display the boot logo, provide boot utilities, etc.
Definition: Arduboy2.cpp:1170
Arduboy2Base::frameCount
static uint16_t frameCount
A counter which is incremented once per frame.
Definition: Arduboy2.h:1381
Arduboy2Base::pressed
static bool pressed(uint8_t buttons)
Test if the all of the specified buttons are pressed.
Definition: Arduboy2.cpp:1012
Arduboy2Base::bootLogoSpritesBSelfMasked
static void bootLogoSpritesBSelfMasked()
Display the boot logo sequence using SpritesB::drawSelfMasked().
Definition: Arduboy2.cpp:149
Arduboy2Base::getPixel
static uint8_t getPixel(uint8_t x, uint8_t y)
Returns the state of the given pixel in the screen buffer.
Definition: Arduboy2.cpp:355
Arduboy2::bootLogo
void bootLogo()
Display the boot logo sequence using drawBitmap().
Definition: Arduboy2.cpp:1187
Point
An object to define a single point for collision functions.
Definition: Arduboy2.h:147
Arduboy2::clear
static void clear()
Clear the display buffer and set the text cursor to location 0, 0.
Definition: Arduboy2.cpp:1494
Arduboy2Core::buttonsState
static uint8_t buttonsState()
Get the current state of all buttons as a bitmask.
Definition: Arduboy2Core.cpp:536
Arduboy2::getTextSize
static uint8_t getTextSize()
Get the currently set text size.
Definition: Arduboy2.cpp:1469
Arduboy2Base::begin
static void begin()
Initialize the hardware, display the boot logo, provide boot utilities, etc.
Definition: Arduboy2.cpp:31
Arduboy2::getCursorX
static int16_t getCursorX()
Get the X coordinate of the current text cursor position.
Definition: Arduboy2.cpp:1433
Arduboy2Base::setFrameDuration
static void setFrameDuration(uint8_t duration)
Set the frame rate, used by the frame control functions, by giving the duration of each frame.
Definition: Arduboy2.cpp:227
Arduboy2Base::bootLogoSpritesOverwrite
static void bootLogoSpritesOverwrite()
Display the boot logo sequence using Sprites::drawOverwrite().
Definition: Arduboy2.cpp:139
Arduboy2Base::arduboy_logo_compressed
static const PROGMEM uint8_t arduboy_logo_compressed[]
The bitmap for the ARDUBOY logo in drawCompressed() format.
Definition: Arduboy2.h:1479
Arduboy2Base::anyPressed
static bool anyPressed(uint8_t buttons)
Test if any of the specified buttons are pressed.
Definition: Arduboy2.cpp:1017
ARDUBOY_UNIT_NAME_LEN
#define ARDUBOY_UNIT_NAME_LEN
The maximum number of characters in an unterminated unit name.
Definition: Arduboy2.h:52
Arduboy2Base::bootLogo
static void bootLogo()
Display the boot logo sequence using drawBitmap().
Definition: Arduboy2.cpp:109
Arduboy2Base::readUnitName
static uint8_t readUnitName(char *name)
Read the unit name from system EEPROM.
Definition: Arduboy2.cpp:1069
Arduboy2::bootLogoText
void bootLogoText()
Display the boot logo sequence using printed text instead of a bitmap.
Definition: Arduboy2.cpp:1237
Arduboy2Base::flashlight
static void flashlight()
Turn the RGB LED and display fully on to act as a small flashlight/torch.
Definition: Arduboy2.cpp:62
Arduboy2Base::fillCircle
static void fillCircle(int16_t x0, int16_t y0, uint8_t r, uint8_t color=WHITE)
Draw a filled-in circle of a given radius.
Definition: Arduboy2.cpp:444
UP_BUTTON
#define UP_BUTTON
Definition: Arduboy2Core.h:69
Arduboy2Base::readShowBootLogoFlag
static bool readShowBootLogoFlag()
Read the "Show Boot Logo" flag in system EEPROM.
Definition: Arduboy2.cpp:1105
Arduboy2::bootLogoCompressed
void bootLogoCompressed()
Display the boot logo sequence using drawCompressed().
Definition: Arduboy2.cpp:1195
Arduboy2::setTextSize
static void setTextSize(uint8_t s)
Set the text character size.
Definition: Arduboy2.cpp:1463
Arduboy2::setCursor
static void setCursor(int16_t x, int16_t y)
Set the location of the text cursor.
Definition: Arduboy2.cpp:1417
Arduboy2::setCursorY
static void setCursorY(int16_t y)
Set the Y coordinate of the text cursor location.
Definition: Arduboy2.cpp:1428
Arduboy2Core::digitalWriteRGB
static void digitalWriteRGB(uint8_t red, uint8_t green, uint8_t blue)
Set the RGB LEDs digitally, to either fully on or fully off.
Definition: Arduboy2Core.cpp:496
Arduboy2::getTextColor
static uint8_t getTextColor()
Get the currently set text foreground color.
Definition: Arduboy2.cpp:1448
Sprites::drawOverwrite
static void drawOverwrite(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t frame)
Draw a sprite by replacing the existing content completely.
Definition: Sprites.cpp:15
Arduboy2.h
The Arduboy2Base and Arduboy2 classes and support objects and definitions.
Arduboy2::setCursorX
static void setCursorX(int16_t x)
Set the X coordinate of the text cursor location.
Definition: Arduboy2.cpp:1423
RED_LED
#define RED_LED
Definition: Arduboy2Core.h:52
Arduboy2Audio::begin
static void begin()
Initialize the speaker based on the current mute setting.
Definition: Arduboy2Audio.cpp:48
Rect::x
int16_t x
Definition: Arduboy2.h:110
Arduboy2Core::delayShort
static void delayShort(uint16_t ms) __attribute__((noinline))
Delay for the number of milliseconds, specified as a 16 bit value.
Definition: Arduboy2Core.cpp:582
BLACK
#define BLACK
Definition: Arduboy2.h:78
Arduboy2Base::waitNoButtons
static void waitNoButtons()
Wait until all buttons have been released.
Definition: Arduboy2.cpp:213
Arduboy2::getTextWrap
static bool getTextWrap()
Get the currently set text wrap mode.
Definition: Arduboy2.cpp:1479
Arduboy2Base::readUnitID
static uint16_t readUnitID()
Read the unit ID from system EEPROM.
Definition: Arduboy2.cpp:1057
Arduboy2Base::systemButtons
static void systemButtons()
Handle buttons held on startup for system control.
Definition: Arduboy2.cpp:83
Arduboy2::drawChar
static void drawChar(int16_t x, int16_t y, uint8_t c, uint8_t color, uint8_t bg, uint8_t size)
Draw a single character at the specified location in the screen buffer.
Definition: Arduboy2.cpp:1335
Arduboy2Base::readShowBootLogoLEDsFlag
static bool readShowBootLogoLEDsFlag()
Read the "Show LEDs with boot logo" flag in system EEPROM.
Definition: Arduboy2.cpp:1131
Arduboy2Base::readShowUnitNameFlag
static bool readShowUnitNameFlag()
Read the "Show Unit Name" flag in system EEPROM.
Definition: Arduboy2.cpp:1118
Rect::height
uint8_t height
Definition: Arduboy2.h:113
Arduboy2Base::setFrameRate
static void setFrameRate(uint8_t rate)
Set the frame rate used by the frame control functions.
Definition: Arduboy2.cpp:222
Sprites::drawSelfMasked
static void drawSelfMasked(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t frame)
Draw a sprite using only the bits set to 1.
Definition: Sprites.cpp:25
Arduboy2Base::drawFastHLine
static void drawFastHLine(int16_t x, int16_t y, uint8_t w, uint8_t color=WHITE)
Draw a horizontal line.
Definition: Arduboy2.cpp:558
Arduboy2Base::writeShowBootLogoLEDsFlag
static void writeShowBootLogoLEDsFlag(bool val)
Write the "Show LEDs with boot logo" flag in system EEPROM.
Definition: Arduboy2.cpp:1136
Rect
A rectangle object for collision functions.
Definition: Arduboy2.h:109
Arduboy2Base::writeUnitName
static void writeUnitName(const char *name)
Write a unit name to system EEPROM.
Definition: Arduboy2.cpp:1089
Arduboy2Base::fillScreen
static void fillScreen(uint8_t color=WHITE)
Fill the screen buffer with the specified color.
Definition: Arduboy2.cpp:618
Arduboy2Base::justReleased
static bool justReleased(uint8_t button)
Check if a button has just been released.
Definition: Arduboy2.cpp:1038
SpritesB::drawSelfMasked
static void drawSelfMasked(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t frame)
Draw a sprite using only the bits set to 1.
Definition: SpritesB.cpp:26
HEIGHT
#define HEIGHT
Definition: Arduboy2Core.h:243
Arduboy2Base::writeShowUnitNameFlag
static void writeShowUnitNameFlag(bool val)
Write the "Show Unit Name" flag in system EEPROM.
Definition: Arduboy2.cpp:1123
Arduboy2Base::arduboy_logo
static const PROGMEM uint8_t arduboy_logo[]
The bitmap for the ARDUBOY logo in drawBitmap() format.
Definition: Arduboy2.h:1472
Arduboy2::getCursorY
static int16_t getCursorY()
Get the Y coordinate of the current text cursor position.
Definition: Arduboy2.cpp:1438
Arduboy2Base::beginDoFirst
static void beginDoFirst()
Helper function that calls the inital functions used by begin()
Definition: Arduboy2.cpp:48
Arduboy2::getTextRawMode
static bool getTextRawMode()
Get the current state of text raw mode.
Definition: Arduboy2.cpp:1489
Arduboy2::bootLogoExtra
void bootLogoExtra()
Show the unit name at the bottom of the boot logo screen.
Definition: Arduboy2.cpp:1282
SpritesB::drawOverwrite
static void drawOverwrite(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t frame)
Draw a sprite by replacing the existing content completely.
Definition: SpritesB.cpp:16
Arduboy2Base::bootLogoShell
static bool bootLogoShell(void(&drawLogo)(int16_t))
Display the boot logo sequence using the provided function.
Definition: Arduboy2.cpp:171