From 75b7421999e92a5463317bcec4dc9cf3a9796da5 Mon Sep 17 00:00:00 2001 From: "Mr.Blinky" Date: Sun, 5 Dec 2021 21:43:40 +0100 Subject: [PATCH] Miscellaneous updates remove sparkfun name from IDE option menu add Arduboy2 library version 6.0.0 changes add SH1106 I2C display support to Arduboy and Arduboy2 library Thanks to @evgenykzz2 add experimental code for extra X and Y buttons to Arduboy2 library add alternate wiring support to Arduboy2beep Thanks to @menehune23 update Arduboy2 library HardwareTest sketch add link to Cathy3K Repo in bootloader folder add contrast option to IDE option menu --- board-package-source/boards.txt | 66 +- board-package-source/bootloaders/readme.md | 3 + .../libraries/Arduboy/src/core/core.cpp | 70 +- .../libraries/Arduboy/src/core/core.h | 6 +- .../libraries/Arduboy2/CONTRIBUTING.md | 30 + .../libraries/Arduboy2/LICENSE.txt | 8 +- .../libraries/Arduboy2/README.md | 135 ++-- .../examples/ArduBreakout/ArduBreakout.ino | 10 +- .../Arduboy2/examples/BeepDemo/BeepDemo.ino | 4 +- .../Arduboy2/examples/Buttons/Buttons.ino | 8 +- .../Arduboy2/examples/Buttons/README.md | 2 +- .../Arduboy2/examples/FontDemo/COPYING | 122 ++++ .../Arduboy2/examples/FontDemo/FontDemo.ino | 127 ++++ .../examples/HardwareTest/HardwareTest.ino | 9 +- .../examples/HelloWorld/HelloWorld.ino | 4 +- .../Arduboy2/examples/RGBled/RGBled.ino | 2 +- .../libraries/Arduboy2/extras/Doxyfile | 2 +- .../Arduboy2/extras/assets/arduboy_logo.png | Bin 1615 -> 238 bytes .../Arduboy2/extras/assets/arduboy_screen.png | Bin 434 -> 343 bytes .../libraries/Arduboy2/extras/cabi/README.md | 11 +- .../libraries/Arduboy2/extras/cabi/cabi.c | 8 +- .../libraries/Arduboy2/extras/cabi/sample.png | Bin 280 -> 199 bytes .../Arduboy2/extras/docs/FILE_DESCRIPTIONS.md | 4 +- .../libraries/Arduboy2/keywords.txt | 22 + .../libraries/Arduboy2/library.json | 2 +- .../libraries/Arduboy2/library.properties | 2 +- .../libraries/Arduboy2/src/Arduboy2.cpp | 372 +++++++---- .../libraries/Arduboy2/src/Arduboy2.h | 622 ++++++++++++++---- .../libraries/Arduboy2/src/Arduboy2Audio.h | 7 +- .../libraries/Arduboy2/src/Arduboy2Beep.cpp | 19 +- .../libraries/Arduboy2/src/Arduboy2Core.cpp | 264 +++++--- .../libraries/Arduboy2/src/Arduboy2Core.h | 79 ++- .../libraries/Arduboy2/src/Arduboy2Data.cpp | 6 +- .../libraries/Arduboy2/src/ab_logo.c | 83 --- .../libraries/Arduboy2/src/glcdfont.c | 274 -------- .../libraries/ArduboyFX/src/ArduboyFX.cpp | 2 +- 36 files changed, 1525 insertions(+), 860 deletions(-) create mode 100644 board-package-source/bootloaders/readme.md create mode 100644 board-package-source/libraries/Arduboy2/CONTRIBUTING.md create mode 100644 board-package-source/libraries/Arduboy2/examples/FontDemo/COPYING create mode 100644 board-package-source/libraries/Arduboy2/examples/FontDemo/FontDemo.ino delete mode 100644 board-package-source/libraries/Arduboy2/src/ab_logo.c delete mode 100644 board-package-source/libraries/Arduboy2/src/glcdfont.c diff --git a/board-package-source/boards.txt b/board-package-source/boards.txt index 47cc889..081114c 100644 --- a/board-package-source/boards.txt +++ b/board-package-source/boards.txt @@ -1,9 +1,10 @@ # Board definitions for Arduboy production v1.0, DevkKit and homemade versions -# using Leonardo, Micro and Sparkfun Pro Micro boards. +# using Leonardo, Micro and (Sparkfun) Pro Micro boards. menu.based_on=Based on menu.core=Core menu.display=Display +menu.contrast=Display contrast menu.boot=Bootloader menu.flashselect=Flash select @@ -85,8 +86,8 @@ arduboy-homemade.menu.based_on.micro.org_bootloader_file=caterina/Caterina-Micro arduboy-homemade.menu.based_on.micro.c3k_bootloader_file=cathy3k/arduboy3k-bootloader-menu-micro{bootloader_display}{bootloader_flashselect}.hex arduboy-homemade.menu.based_on.micro.c3kg_bootloader_file=cathy3k/arduboy3k-bootloader-game-micro{bootloader_display}{bootloader_flashselect}.hex -# SparkFun Pro Micro 5V # -arduboy-homemade.menu.based_on.promicro=SparkFun Pro Micro 5V - Standard wiring +# (SparkFun) Pro Micro 5V # +arduboy-homemade.menu.based_on.promicro=Pro Micro 5V - Standard wiring #arduboy-homemade.menu.based_on.promicro.build.vid=0x1b4f #arduboy-homemade.menu.based_on.promicro.build.pid=0x9206 #using Leonardo vid,pid for driver simplicity @@ -99,7 +100,7 @@ arduboy-homemade.menu.based_on.promicro.org_bootloader_file=caterina/Caterina-pr arduboy-homemade.menu.based_on.promicro.c3k_bootloader_file=cathy3k/arduboy3k-bootloader-menu{bootloader_display}{bootloader_flashselect}.hex arduboy-homemade.menu.based_on.promicro.c3kg_bootloader_file=cathy3k/arduboy3k-bootloader-game{bootloader_display}{bootloader_flashselect}.hex -arduboy-homemade.menu.based_on.promicro_alt=SparkFun Pro Micro 5V - Alternate wiring +arduboy-homemade.menu.based_on.promicro_alt=Pro Micro 5V - Alternate wiring #arduboy-homemade.menu.based_on.promicro_alt.build.vid=0x1b4f #arduboy-homemade.menu.based_on.promicro_alt.build.pid=0x9206 #using Leonardo vid,pid for driver simplicity @@ -141,97 +142,103 @@ arduboy-homemade.menu.display.sh1106=SH1106 arduboy-homemade.menu.display.sh1106.build.display=-sh1106 arduboy-homemade.menu.display.sh1106.usb_product_postfix=1106 arduboy-homemade.menu.display.sh1106.bootloader_display=-sh1106 -arduboy-homemade.menu.display.sh1106.build.extra_flags=-DARDUBOY_10 -DOLED_SH1106 {build.flash_cs} {build.usb_flags} +arduboy-homemade.menu.display.sh1106.build.extra_flags=-DARDUBOY_10 -DOLED_SH1106 {build.flash_cs} {build.contrast} {build.usb_flags} + +arduboy-homemade.menu.display.sh1106i2c=SH1106-I2C (2 Mbps) +arduboy-homemade.menu.display.sh1106i2c.build.display=-sh1106i2c +arduboy-homemade.menu.display.sh1106i2c.usb_product_postfix=I2C +arduboy-homemade.menu.display.sh1106i2c.bootloader_display= +arduboy-homemade.menu.display.sh1106i2c.build.extra_flags=-DARDUBOY_10 -DOLED_SH1106_I2C {build.flash_cs} {build.contrast} {build.usb_flags} arduboy-homemade.menu.display.ssd1306=SSD1306 arduboy-homemade.menu.display.ssd1306.build.display=-ssd1306 arduboy-homemade.menu.display.ssd1306.usb_product_postfix=1306 arduboy-homemade.menu.display.ssd1306.bootloader_display= -arduboy-homemade.menu.display.ssd1306.build.extra_flags=-DARDUBOY_10 -DOLED_SSD1306 {build.flash_cs} {build.usb_flags} +arduboy-homemade.menu.display.ssd1306.build.extra_flags=-DARDUBOY_10 -DOLED_SSD1306 {build.flash_cs} {build.contrast} {build.usb_flags} arduboy-homemade.menu.display.ssd1306i2c=SSD1306-I2C (2 Mbps) arduboy-homemade.menu.display.ssd1306i2c.build.display=-ssd1306i2c arduboy-homemade.menu.display.ssd1306i2c.usb_product_postfix=I2C arduboy-homemade.menu.display.ssd1306i2c.bootloader_display= -arduboy-homemade.menu.display.ssd1306i2c.build.extra_flags=-DARDUBOY_10 -DOLED_SSD1306_I2C {build.flash_cs} {build.usb_flags} +arduboy-homemade.menu.display.ssd1306i2c.build.extra_flags=-DARDUBOY_10 -DOLED_SSD1306_I2C {build.flash_cs} {build.contrast} {build.usb_flags} arduboy-homemade.menu.display.ssd1306i2cx=SSD1306-I2C (2.66 Mbps) arduboy-homemade.menu.display.ssd1306i2cx.build.display=-ssd1306i2cf arduboy-homemade.menu.display.ssd1306i2cx.usb_product_postfix=I2CX arduboy-homemade.menu.display.ssd1306i2cx.bootloader_display= -arduboy-homemade.menu.display.ssd1306i2cx.build.extra_flags=-DARDUBOY_10 -DOLED_SSD1306_I2CX {build.flash_cs} {build.usb_flags} +arduboy-homemade.menu.display.ssd1306i2cx.build.extra_flags=-DARDUBOY_10 -DOLED_SSD1306_I2CX {build.flash_cs} {build.contrast} {build.usb_flags} arduboy-homemade.menu.display.ssd1309=SSD1309 arduboy-homemade.menu.display.ssd1309.build.display=-ssd1309 arduboy-homemade.menu.display.ssd1309.usb_product_postfix=1309 arduboy-homemade.menu.display.ssd1309.bootloader_display= -arduboy-homemade.menu.display.ssd1309.build.extra_flags=-DARDUBOY_10 -DOLED_SSD1309 {build.flash_cs} {build.usb_flags} +arduboy-homemade.menu.display.ssd1309.build.extra_flags=-DARDUBOY_10 -DOLED_SSD1309 {build.flash_cs} {build.contrast} {build.usb_flags} arduboy-homemade.menu.display.64x128on96x96=SSD1327/29 (128x64 on 96x96) arduboy-homemade.menu.display.64x128on96x96.build.display=-128x64-on-96x96 arduboy-homemade.menu.display.64x128on96x96.usb_product_postfix=9696 arduboy-homemade.menu.display.64x128on96x96.bootloader_display=-ssd132x-96x96 -arduboy-homemade.menu.display.64x128on96x96.build.extra_flags=-DARDUBOY_10 -DOLED_128X64_ON_96X96 {build.flash_cs} {build.usb_flags} +arduboy-homemade.menu.display.64x128on96x96.build.extra_flags=-DARDUBOY_10 -DOLED_128X64_ON_96X96 {build.flash_cs} {build.contrast} {build.usb_flags} arduboy-homemade.menu.display.64x128on128x96=SSD1327/29 (128x64 on 128x96) arduboy-homemade.menu.display.64x128on128x96.build.display=-128x64-on-128x96 arduboy-homemade.menu.display.64x128on128x96.usb_product_postfix=12896 arduboy-homemade.menu.display.64x128on128x96.bootloader_display=-ssd132x-128x96 -arduboy-homemade.menu.display.64x128on128x96.build.extra_flags=-DARDUBOY_10 -DOLED_128X64_ON_128X96 {build.flash_cs} {build.usb_flags} +arduboy-homemade.menu.display.64x128on128x96.build.extra_flags=-DARDUBOY_10 -DOLED_128X64_ON_128X96 {build.flash_cs} {build.contrast} {build.usb_flags} arduboy-homemade.menu.display.64x128on128x128=SSD1327/29 (128x64 on 128x128) arduboy-homemade.menu.display.64x128on128x128.build.display=-128x64-on-128x128 arduboy-homemade.menu.display.64x128on128x128.usb_product_postfix=128128 arduboy-homemade.menu.display.64x128on128x128.bootloader_display=-ssd132x-128x128 -arduboy-homemade.menu.display.64x128on128x128.build.extra_flags=-DARDUBOY_10 -DOLED_128X64_ON_128X128 {build.flash_cs} {build.usb_flags} +arduboy-homemade.menu.display.64x128on128x128.build.extra_flags=-DARDUBOY_10 -DOLED_128X64_ON_128X128 {build.flash_cs} {build.contrast} {build.usb_flags} arduboy-homemade.menu.display.128x64on128x128=SSD1327/29 (64x128 on 128x128) arduboy-homemade.menu.display.128x64on128x128.build.display=-64x128-on-128x128 arduboy-homemade.menu.display.128x64on128x128.usb_product_postfix=64128 arduboy-homemade.menu.display.128x64on128x128.bootloader_display=-ssd132x-128x128 -arduboy-homemade.menu.display.128x64on128x128.build.extra_flags=-DARDUBOY_10 -DOLED_64X128_ON_128X128 {build.flash_cs} {build.usb_flags} +arduboy-homemade.menu.display.128x64on128x128.build.extra_flags=-DARDUBOY_10 -DOLED_64X128_ON_128X128 {build.flash_cs} {build.contrast} {build.usb_flags} arduboy-homemade.menu.display.96x96=SSD1327/29 (96x96) arduboy-homemade.menu.display.96x96.build.display=-96x96 arduboy-homemade.menu.display.96x96.usb_product_postfix=9696 arduboy-homemade.menu.display.96x96.bootloader_display=-ssd132x-96x96 -arduboy-homemade.menu.display.96x96.build.extra_flags=-DARDUBOY_10 -DOLED_96X96 {build.flash_cs} {build.usb_flags} +arduboy-homemade.menu.display.96x96.build.extra_flags=-DARDUBOY_10 -DOLED_96X96 {build.flash_cs} {build.contrast} {build.usb_flags} arduboy-homemade.menu.display.96x96on128x128=SSD1327/29 (96x96 on 128x128) arduboy-homemade.menu.display.96x96on128x128.build.display=-96x96-on-128x128 arduboy-homemade.menu.display.96x96on128x128.usb_product_postfix=128128 arduboy-homemade.menu.display.96x96on128x128.bootloader_display=-ssd132x-128x128 -arduboy-homemade.menu.display.96x96on128x128.build.extra_flags=-DARDUBOY_10 -DOLED_96X96_ON_128X128 {build.flash_cs} {build.usb_flags} +arduboy-homemade.menu.display.96x96on128x128.build.extra_flags=-DARDUBOY_10 -DOLED_96X96_ON_128X128 {build.flash_cs} {build.contrast} {build.usb_flags} arduboy-homemade.menu.display.128x96=SSD1327/29 (128x96) arduboy-homemade.menu.display.128x96.build.display=-128x96 arduboy-homemade.menu.display.128x96.usb_product_postfix=12896 arduboy-homemade.menu.display.128x96.bootloader_display=-ssd132x-128x96 -arduboy-homemade.menu.display.128x96.build.extra_flags=-DARDUBOY_10 -DOLED_128X96 {build.flash_cs} {build.usb_flags} +arduboy-homemade.menu.display.128x96.build.extra_flags=-DARDUBOY_10 -DOLED_128X96 {build.flash_cs} {build.contrast} {build.usb_flags} arduboy-homemade.menu.display.128x96on128x128=SSD1327/29 (128x96 on 128x128) arduboy-homemade.menu.display.128x96on128x128.build.display=-128x96-on-128x128 arduboy-homemade.menu.display.128x96on128x128.usb_product_postfix=128128 arduboy-homemade.menu.display.128x96on128x128.bootloader_display=-ssd132x-128x128 -arduboy-homemade.menu.display.128x96on128x128.build.extra_flags=-DARDUBOY_10 -DOLED_128X96_ON_128X128 {build.flash_cs} {build.usb_flags} +arduboy-homemade.menu.display.128x96on128x128.build.extra_flags=-DARDUBOY_10 -DOLED_128X96_ON_128X128 {build.flash_cs} {build.contrast} {build.usb_flags} arduboy-homemade.menu.display.128x128=SSD1327/29 (128x128) arduboy-homemade.menu.display.128x128.build.display=-128x128 arduboy-homemade.menu.display.128x128.usb_product_postfix=128128 arduboy-homemade.menu.display.128x128.bootloader_display=-ssd132x-128x128 -arduboy-homemade.menu.display.128x128.build.extra_flags=-DARDUBOY_10 -DOLED_128X128 {build.flash_cs} {build.usb_flags} +arduboy-homemade.menu.display.128x128.build.extra_flags=-DARDUBOY_10 -DOLED_128X128 {build.flash_cs} {build.contrast} {build.usb_flags} arduboy-homemade.menu.display.st7565=LCD ST7565 (backlit) arduboy-homemade.menu.display.st7565.build.display=-st7565 arduboy-homemade.menu.display.st7565.usb_product_postfix=lcd arduboy-homemade.menu.display.st7565.bootloader_display=-st7565 -arduboy-homemade.menu.display.st7565.build.extra_flags=-DARDUBOY_10 -DLCD_ST7565 {build.flash_cs} {build.usb_flags} +arduboy-homemade.menu.display.st7565.build.extra_flags=-DARDUBOY_10 -DLCD_ST7565 {build.flash_cs} {build.contrast} {build.usb_flags} arduboy-homemade.menu.display.gu12864_800b=GU12864-800B arduboy-homemade.menu.display.gu12864_800b.build.display=-gu12864 arduboy-homemade.menu.display.gu12864_800b.usb_product_postfix=vfd arduboy-homemade.menu.display.gu12864_800b.bootloader_display=-gu12864 -arduboy-homemade.menu.display.gu12864_800b.build.extra_flags=-DARDUBOY_10 -DGU12864_800B {build.flash_cs} {build.usb_flags} +arduboy-homemade.menu.display.gu12864_800b.build.extra_flags=-DARDUBOY_10 -DGU12864_800B {build.flash_cs} {build.contrast} {build.usb_flags} # External flash chip select pin # @@ -245,11 +252,28 @@ arduboy-homemade.menu.flashselect.rx.build.flash_cs=-DCART_CS_RX arduboy-homemade.menu.flashselect.rx.build.flashselect= arduboy-homemade.menu.flashselect.rx.bootloader_flashselect= +# Display contrast adjustment # + +arduboy-homemade.menu.contrast.normal=Normal +arduboy-homemade.menu.contrast.normal.build.contrast= + +arduboy-homemade.menu.contrast.dimmed=Dimmed +arduboy-homemade.menu.contrast.dimmed.build.contrast=-DOLED_CONTRAST=0x7F + +arduboy-homemade.menu.contrast.low=Low +arduboy-homemade.menu.contrast.low.build.contrast=-DOLED_CONTRAST=0x2F + +arduboy-homemade.menu.contrast.lowest=Lowest +arduboy-homemade.menu.contrast.lowest.build.contrast=-DOLED_CONTRAST=0x00 + +arduboy-homemade.menu.contrast.highest=Highest +arduboy-homemade.menu.contrast.highest.build.contrast=-DOLED_CONTRAST=0xFF + ################################################################################ # Arduboy board ################################################################################ -arduboy.name=Arduboy +arduboy.name=Arduboy (FX) #Arduino Leonardo arduboy.vid.0=0x2341 diff --git a/board-package-source/bootloaders/readme.md b/board-package-source/bootloaders/readme.md new file mode 100644 index 0000000..a71126f --- /dev/null +++ b/board-package-source/bootloaders/readme.md @@ -0,0 +1,3 @@ +Source to build the Cathy3K bootloaders can be found at: + +https://github.com/MrBlinky/cathy3k \ No newline at end of file diff --git a/board-package-source/libraries/Arduboy/src/core/core.cpp b/board-package-source/libraries/Arduboy/src/core/core.cpp index 9ea891d..b092eb0 100644 --- a/board-package-source/libraries/Arduboy/src/core/core.cpp +++ b/board-package-source/libraries/Arduboy/src/core/core.cpp @@ -15,7 +15,7 @@ const uint8_t PROGMEM pinBootProgram[] = { PIN_A_BUTTON, INPUT_PULLUP, PIN_B_BUTTON, INPUT_PULLUP, -#if (defined(OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX)) +#if (defined(OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX) || (OLED_SH1106_I2C)) //I2C SDA, INPUT, SCL, INPUT, @@ -40,7 +40,7 @@ const uint8_t PROGMEM lcdBootProgram[] = { 0x47, // set brightness 0x64, 0x00, // set x position 0 0x84, // address mode set: X increment -#elif OLED_SH1106 +#elif defined(OLED_SH1106) || defined(OLED_SH1106_I2C) 0x8D, 0x14, // Charge Pump Setting v = enable (0x14) 0xA1, // Set Segment Re-map 0xC8, // Set COM Output Scan Direction @@ -245,16 +245,30 @@ void ArduboyCore::displayWrite(uint8_t data) void ArduboyCore::bootLCD() { -#if defined(OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX) +#if defined(OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX) || (OLED_SH1106_I2C) i2c_start(SSD1306_I2C_CMD); for (uint8_t i = 0; i < sizeof(lcdBootProgram); i++) i2c_sendByte(pgm_read_byte(lcdBootProgram + i)); i2c_stop(); + #if defined(OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX) i2c_start(SSD1306_I2C_DATA); for (uint16_t i = 0; i < WIDTH * HEIGHT / 8; i++) i2c_sendByte(0); i2c_stop(); -#else + #else + for (int page = 0; page < HEIGHT/8; page++) + { + i2c_start(SSD1306_I2C_CMD); + i2c_sendByte(OLED_SET_PAGE_ADDRESS + page); // set page + i2c_sendByte(OLED_SET_COLUMN_ADDRESS_HI); // only reset hi nibble to zero + i2c_stop(); + i2c_start(SSD1306_I2C_DATA); + for (int i = 0; i < WIDTH; i++) + i2c_sendByte(0); + i2c_stop(); + } + #endif +#else // setup the ports we need to talk to the OLED csport = portOutputRegister(digitalPinToPort(CS)); cspinmask = digitalPinToBitMask(CS); @@ -317,7 +331,7 @@ void ArduboyCore::LCDCommandMode() // *csport &= ~cspinmask; CS set once at bootLCD } -#if defined(OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX) +#if defined(OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX) || (OLED_SH1106_I2C) void ArduboyCore::i2c_start(uint8_t mode) { I2C_SDA_LOW(); // disable posible internal pullup, ensure SDA low on enabling output @@ -401,11 +415,11 @@ uint8_t ArduboyCore::height() { return HEIGHT; } void ArduboyCore::paint8Pixels(uint8_t pixels) { -#if defined(OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX) +#if defined(OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX) || (OLED_SH1106_I2C) i2c_start(SSD1306_I2C_DATA); i2c_sendByte(pixels); i2c_stop(); -#else +#else SPI.transfer(pixels); #endif } @@ -434,6 +448,19 @@ void ArduboyCore::paintScreen(const unsigned char *image) for (int i = 0; i < (HEIGHT * WIDTH) / 8; i++) i2c_sendByte(pgm_read_byte(image+i)); i2c_stop(); +#elif defined (OLED_SH1106_I2C) + for (int page = 0; page < HEIGHT/8; page++) + { + i2c_start(SSD1306_I2C_CMD); + i2c_sendByte(OLED_SET_PAGE_ADDRESS + page); // set page + i2c_sendByte(OLED_SET_COLUMN_ADDRESS_HI); // only reset hi nibble to zero + i2c_stop(); + const uint8_t *line = image + page*WIDTH; + i2c_start(SSD1306_I2C_DATA); + for (int i = 0; i < WIDTH; i++) + i2c_sendByte(pgm_read_byte(line+i)); + i2c_stop(); + } #elif defined(OLED_SH1106) || defined(LCD_ST7565) for (uint8_t i = 0; i < HEIGHT / 8; i++) { @@ -636,7 +663,18 @@ void ArduboyCore::paintScreen(unsigned char image[]) ); #endif i2c_stop(); - +#elif defined (OLED_SH1106_I2C) + for (int page = 0; page < HEIGHT/8; page++) + { + i2c_start(SSD1306_I2C_CMD); + i2c_sendByte(OLED_SET_PAGE_ADDRESS + page); // set page + i2c_sendByte(OLED_SET_COLUMN_ADDRESS_HI); + i2c_stop(); + i2c_start(SSD1306_I2C_DATA); + for (int i = 0; i < WIDTH; i++) + i2c_sendByte(*(image++)); + i2c_stop(); + } #elif defined(OLED_SH1106) || defined(LCD_ST7565) for (uint8_t i = 0; i < HEIGHT / 8; i++) { @@ -777,7 +815,19 @@ void ArduboyCore::blank() for (int i = 0; i < (HEIGHT * WIDTH) / 8; i++) i2c_sendByte(0); i2c_stop(); -#else +#elif defined (OLED_SH1106_I2C) + for (int page = 0; page < HEIGHT/8; page++) + { + i2c_start(SSD1306_I2C_CMD); + i2c_sendByte(OLED_SET_PAGE_ADDRESS + page); // set page + i2c_sendByte(OLED_SET_COLUMN_ADDRESS_HI); // only reset hi nibble to zero + i2c_stop(); + i2c_start(SSD1306_I2C_DATA); + for (int i = 0; i < WIDTH; i++) + i2c_sendByte(0); + i2c_stop(); + } +#else #if defined (OLED_SH1106) for (int i = 0; i < (HEIGHT * 132) / 8; i++) #elif defined(OLED_96X96) || defined(OLED_128X96) || defined(OLED_128X128) || defined(OLED_128X64_ON_128X96) || defined(OLED_128X64_ON_128X128)|| defined(OLED_128X96_ON_128X128) || defined(OLED_96X96_ON_128X128) || defined(OLED_64X128_ON_128X128) @@ -791,7 +841,7 @@ void ArduboyCore::blank() void ArduboyCore::sendLCDCommand(uint8_t command) { -#if defined(OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX) +#if defined(OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX) || (OLED_SH1106_I2C) i2c_start(SSD1306_I2C_CMD); i2c_sendByte(command); i2c_stop(); diff --git a/board-package-source/libraries/Arduboy/src/core/core.h b/board-package-source/libraries/Arduboy/src/core/core.h index a576abd..27b7a30 100644 --- a/board-package-source/libraries/Arduboy/src/core/core.h +++ b/board-package-source/libraries/Arduboy/src/core/core.h @@ -43,7 +43,7 @@ #define RST 6 #endif #define DC 4 -#if defined (OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX) +#if defined (OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX) || (OLED_SH1106_I2C) //bitbanged I2C pins #define I2C_PORT PORTD #define I2C_DDR DDRD @@ -166,7 +166,7 @@ #define OLED_VERTICAL_NORMAL 0xC8 // normal COM scan direction (Same for SH1106) #define OLED_SET_PAGE_ADDRESS 0xB0 // (Same for SH1106) -#if defined OLED_SH1106 +#if defined(OLED_SH1106) || defined(OLED_SH1106_I2C) #define OLED_SET_COLUMN_ADDRESS_LO 0x02 //SH1106: 1st pixel starts on column 2 #else #define OLED_SET_COLUMN_ADDRESS_LO 0x00 @@ -231,7 +231,7 @@ public: */ void static LCDCommandMode(); -#if defined (OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX) +#if defined (OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX) || (OLED_SH1106_I2C) void static i2c_start(uint8_t mode); void static inline i2c_stop() __attribute__((always_inline)) diff --git a/board-package-source/libraries/Arduboy2/CONTRIBUTING.md b/board-package-source/libraries/Arduboy2/CONTRIBUTING.md new file mode 100644 index 0000000..dcaa94f --- /dev/null +++ b/board-package-source/libraries/Arduboy2/CONTRIBUTING.md @@ -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. +``` \ No newline at end of file diff --git a/board-package-source/libraries/Arduboy2/LICENSE.txt b/board-package-source/libraries/Arduboy2/LICENSE.txt index 3fc9077..b65d51a 100644 --- a/board-package-source/libraries/Arduboy2/LICENSE.txt +++ b/board-package-source/libraries/Arduboy2/LICENSE.txt @@ -8,7 +8,7 @@ Software License Agreements Licensed under the BSD 3-clause license: Arduboy2 library: -Copyright (c) 2016-2020, Scott Allen +Copyright (c) 2016-2021, Scott Allen All rights reserved. The Arduboy2 library was forked from the Arduboy library: @@ -18,7 +18,8 @@ Copyright (c) 2016, Chris Martinez Copyright (c) 2016, Josh Goebel Copyright (c) 2016, Scott Allen All rights reserved. -which is in turn partially based on the Adafruit_SSD1306 library + +- 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. @@ -164,6 +165,9 @@ 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 diff --git a/board-package-source/libraries/Arduboy2/README.md b/board-package-source/libraries/Arduboy2/README.md index 0a6d151..6748cde 100644 --- a/board-package-source/libraries/Arduboy2/README.md +++ b/board-package-source/libraries/Arduboy2/README.md @@ -6,7 +6,7 @@ The original Arduboy2 library is maintained in a git repository hosted on [GitHu 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 **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. @@ -49,9 +49,10 @@ A user settable *unit name* can be saved in system EEPROM memory. If set, this n Once the logo display sequence completes, the sketch continues. -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. +**Note:** -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. +- 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 @@ -167,63 +168,99 @@ with Arduboy2Base arduboy; ``` -#### Remove boot up features +#### Substitute or 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. +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. -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. +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. -As of this writing, the begin function is: +Here is a template that provides the equivalent of *begin()* ```cpp -void Arduboy2Base::begin() +void setup() { - boot(); // raw hardware + // Required to initialize the hardware. + arduboy.boot(); - display(); // blank the display (sBuffer is global, so cleared automatically) + // 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(); - audio.begin(); + // This is required to initialize the speaker. It's not needed if + // the sketch doesn't produce any sounds. + arduboy.audio.begin(); - bootLogo(); + // 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... - waitNoButtons(); // wait for all buttons to be released } ``` -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()*. - -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: - -```cpp - arduboy.boot(); // raw hardware - -// *** This particular sketch clears the display soon, so it doesn't need this: -// display(); // blank the display (sBuffer is global, so cleared automatically) - - arduboy.flashlight(); // light the RGB LED and screen if UP button is being held. - - // check for and handle buttons held during start up for system control -// systemButtons(); - - arduboy.audio.begin(); - -// bootLogo(); - -// waitNoButtons(); // wait for all buttons to be released -``` - -This saves whatever code *display()*, *systemButtons()*, *bootLogo()* and *waitNoButtons()* would use. - There are a few functions provided that are roughly equivalent to the standard functions used by *begin()* but which use less code space. -- *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 *drawBitmask()*, 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. +- *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()* for cases where it's needed 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()*. +- *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 +void drawLogoArdCompressed(int16_t y) +{ + ardbitmap.drawCompressed(20, y, arduboy_logo_ardbitmap, + WHITE, ALIGN_CENTER, MIRROR_NONE); +} + +void bootLogoArdCompressed() +{ + if (arduboy.bootLogoShell(drawLogoArdCompressed)) + { + arduboy.bootLogoExtra(); + } +} + +void setup() +{ + arduboy.beginDoFirst(); + bootLogoArdCompressed(); + arduboy.waitNoButtons(); + +// Additional setup code... + +} +``` + +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 @@ -248,6 +285,8 @@ The *ARDUBOY_NO_USB* macro is used to eliminate the USB code. The *exitToBootloa ## 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: @@ -391,7 +430,7 @@ Arduboy2 arduboy; ArduboyPlaytune tunes(arduboy.audio.enabled); ``` -The sound channels must then 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 @@ -426,13 +465,13 @@ The benefit of using *ArduboyTones* would be reduced code size and possibly easi ### Sketch uses the beginNoLogo() function instead of begin() -The *beginNoLogo()* function has been removed. Instead, *boot()* can be used with additional functions following it to add back in desired boot functionality. See the information above, under the heading *Remove boot up features*, for more details. Assuming the object is named *arduboy*, a direct replacement for *beginNoLogo()* would be: +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.boot(); - arduboy.display(); - arduboy.flashlight(); - arduboy.audio.begin(); + arduboy.beginDoFirst(); + arduboy.waitNoButtons(); ``` ---------- diff --git a/board-package-source/libraries/Arduboy2/examples/ArduBreakout/ArduBreakout.ino b/board-package-source/libraries/Arduboy2/examples/ArduBreakout/ArduBreakout.ino index d152180..daf55d1 100644 --- a/board-package-source/libraries/Arduboy2/examples/ArduBreakout/ArduBreakout.ino +++ b/board-package-source/libraries/Arduboy2/examples/ArduBreakout/ArduBreakout.ino @@ -271,7 +271,7 @@ 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) { @@ -293,7 +293,7 @@ void moveBall() } } - //Hoizontal collision + //Horizontal collision if (leftBall < leftBrick || rightBall > rightBrick) { //Only bounce once brick each ball move @@ -459,7 +459,7 @@ 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 = 8; @@ -736,14 +736,14 @@ void enterHighScore(byte file) } } -// Play a tone at a frequency coresponding to the specified precomputed count, +// 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) { beep.tone(count, frames); } -// Play a tone at a frequency coresponding to the specified precomputed count, +// 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) diff --git a/board-package-source/libraries/Arduboy2/examples/BeepDemo/BeepDemo.ino b/board-package-source/libraries/Arduboy2/examples/BeepDemo/BeepDemo.ino index 7df55d7..436d678 100644 --- a/board-package-source/libraries/Arduboy2/examples/BeepDemo/BeepDemo.ino +++ b/board-package-source/libraries/Arduboy2/examples/BeepDemo/BeepDemo.ino @@ -52,6 +52,8 @@ void loop() { 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 @@ -127,7 +129,7 @@ void loop() { objectX = 0; } - arduboy.display(CLEAR_BUFFER); + arduboy.display(); } void commandText(const char* text) { diff --git a/board-package-source/libraries/Arduboy2/examples/Buttons/Buttons.ino b/board-package-source/libraries/Arduboy2/examples/Buttons/Buttons.ino index 557df65..1e508a2 100644 --- a/board-package-source/libraries/Arduboy2/examples/Buttons/Buttons.ino +++ b/board-package-source/libraries/Arduboy2/examples/Buttons/Buttons.ino @@ -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(); } diff --git a/board-package-source/libraries/Arduboy2/examples/Buttons/README.md b/board-package-source/libraries/Arduboy2/examples/Buttons/README.md index 0b6dc80..15d2d73 100644 --- a/board-package-source/libraries/Arduboy2/examples/Buttons/README.md +++ b/board-package-source/libraries/Arduboy2/examples/Buttons/README.md @@ -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. diff --git a/board-package-source/libraries/Arduboy2/examples/FontDemo/COPYING b/board-package-source/libraries/Arduboy2/examples/FontDemo/COPYING new file mode 100644 index 0000000..6ca207e --- /dev/null +++ b/board-package-source/libraries/Arduboy2/examples/FontDemo/COPYING @@ -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. + diff --git a/board-package-source/libraries/Arduboy2/examples/FontDemo/FontDemo.ino b/board-package-source/libraries/Arduboy2/examples/FontDemo/FontDemo.ino new file mode 100644 index 0000000..c72b400 --- /dev/null +++ b/board-package-source/libraries/Arduboy2/examples/FontDemo/FontDemo.ino @@ -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 . +*/ + +#include + +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(); +} diff --git a/board-package-source/libraries/Arduboy2/examples/HardwareTest/HardwareTest.ino b/board-package-source/libraries/Arduboy2/examples/HardwareTest/HardwareTest.ino index cd59421..15d450e 100644 --- a/board-package-source/libraries/Arduboy2/examples/HardwareTest/HardwareTest.ino +++ b/board-package-source/libraries/Arduboy2/examples/HardwareTest/HardwareTest.ino @@ -1,5 +1,5 @@ /******************************************************************************* - Arduboy hardware test toy v1.0 September 2017 by Mr.Blinky + Arduboy hardware test toy v1.1 Sep. 2017 - Nov.2021 by Mr.Blinky *******************************************************************************/ #include @@ -14,6 +14,7 @@ Sprites sprites; void setup() { arduboy.begin(); + arduboy.setRGBled(0,0,0); arduboy.setFrameRate(FRAMERATE); arduboy.audio.on; } @@ -110,6 +111,8 @@ void loop() arduboy.setRGBled(pgm_read_byte(rgbValues + rgbLed.red), pgm_read_byte(rgbValues + rgbLed.green), pgm_read_byte(rgbValues + rgbLed.blue)); rxled_on ? RXLED1 : RXLED0; txled_on ? TXLED1 : TXLED0; + SPEAKER_1_PORT &= ~_BV(SPEAKER_1_BIT); + SPEAKER_2_PORT |= _BV(SPEAKER_2_BIT); for (int i = 0; i < 50; i++) { speaker1_on ? SPEAKER_1_PORT ^= _BV(SPEAKER_1_BIT) : SPEAKER_1_PORT &= ~_BV(SPEAKER_1_BIT); @@ -117,7 +120,9 @@ void loop() speaker2_on ? SPEAKER_2_PORT ^= _BV(SPEAKER_2_BIT) : SPEAKER_2_PORT |= _BV(SPEAKER_2_BIT); #endif delayMicroseconds(300); - } + } + SPEAKER_1_PORT &= ~_BV(SPEAKER_1_BIT); + SPEAKER_2_PORT &= ~_BV(SPEAKER_2_BIT); hardwareChange = false; } } diff --git a/board-package-source/libraries/Arduboy2/examples/HelloWorld/HelloWorld.ino b/board-package-source/libraries/Arduboy2/examples/HelloWorld/HelloWorld.ino index c067bf3..f51f0bf 100644 --- a/board-package-source/libraries/Arduboy2/examples/HelloWorld/HelloWorld.ino +++ b/board-package-source/libraries/Arduboy2/examples/HelloWorld/HelloWorld.ino @@ -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(); } diff --git a/board-package-source/libraries/Arduboy2/examples/RGBled/RGBled.ino b/board-package-source/libraries/Arduboy2/examples/RGBled/RGBled.ino index 89b213d..48f16ad 100644 --- a/board-package-source/libraries/Arduboy2/examples/RGBled/RGBled.ino +++ b/board-package-source/libraries/Arduboy2/examples/RGBled/RGBled.ino @@ -321,7 +321,7 @@ void drawBar(int y, Color color, byte value) { } } -// Draw the informaton for one digital color +// Draw the information for one digital color void drawDigital(int y, Color color, const char* name) { byte state = digitalState[(byte)color]; diff --git a/board-package-source/libraries/Arduboy2/extras/Doxyfile b/board-package-source/libraries/Arduboy2/extras/Doxyfile index 195b247..708a6e0 100644 --- a/board-package-source/libraries/Arduboy2/extras/Doxyfile +++ b/board-package-source/libraries/Arduboy2/extras/Doxyfile @@ -5,7 +5,7 @@ #--------------------------------------------------------------------------- DOXYFILE_ENCODING = UTF-8 PROJECT_NAME = "Arduboy2 Library" -PROJECT_NUMBER = 5.3.0 +PROJECT_NUMBER = 6.0.0 PROJECT_BRIEF = PROJECT_LOGO = OUTPUT_DIRECTORY = doxygen diff --git a/board-package-source/libraries/Arduboy2/extras/assets/arduboy_logo.png b/board-package-source/libraries/Arduboy2/extras/assets/arduboy_logo.png index f79c81c8a405643b8f960236e7b4c996205dc0bf..d3a71dea3b05e81cb81e969bdf5e829a66e0bb78 100644 GIT binary patch delta 221 zcmV<303!d-4DJDt8Gi-<005GnxHSL(0JTX(K~#8Ng!0*J-qyjRxy`eZSqD2L58O{#I`VQEBK5238x4sOyW5 z;kFjh&x?=Yf=kY0uzc+GbNmJqlahG=;B^cJ>qq6B^Xs?`M&9rUBiAt+?0-g7>(BwW00000NkvXXu0mjfu3cpK literal 1615 zcmeAS@N?(olHy`uVBq!ia0vp^5kM@!!2~2_|L7+HDaPU;cPEB*=VV?2Ih+L^k;M!Q z+`=Ht$S`Y;1Oo$$N@hqzNrbPDRdRl=USdjqQmS4>ZUIm=1A|S46_A;mT9T+xk(-lO zY*k^a1Xf`MWP^nDl@!2AO0sR0B76fBob!uP6-@O^^bC~jxD*r=Y>HCStb$zJpxS{v zTcwPWk^(Dz{qpj1y>er{{GxPyLrY6beFGzXBO_g)3f?~)Z${GHakLamPfGmil0TlFB0htx4IT0?IzyJmN!otEvAFBkqM(6yT z{G#B3#NBLsNs~0+5VzQEFmI zeo;t%evTd37r7v=f-x{J0wWMz1yr+*J}4g{mRGZw=4-g8o_y}FS$t~dWF!5T4=(9Wp82xE zZpLZTnJ;(zDSY+eYsoXttz6e#OSJauF1@&ZpVrH#3Jq6waRmIVImvY>VGh^g*YltL zw5%21Fje%x?)w}!=gxmtKlN5?equDsrJpi>YjhWU3#f?}U|ZZDb$`RvEldWIFJDYq zV|z98&DJ<2c_x3$eTtV2a%wM~m3}&@{J%*J_q~^ke+c`o*JToZ@nKb!<=@%UH~FM3 z+oGE~^Ni0+w@*xMxH%s-Ua~#;>Q=C2 z->Erkwk3C$@-+N9`P}sFO6HEMyd|~`-9K0kuD7WA{)AywvDa~dwTuQup90^{%Z@GP zDhOkIVgEDZ_PnPI-~Jo?UGVwzNdpFkW$#Q^O`q({@MJDS!kFVdQ&MBb@06immD*ylh delta 419 zcmV;U0bKsq0)qlPk-u9by0SRbS`+(ipb3skOAPIk^NK*(^P6hxWM%SY8T7 ze?cu_@6P6T<_@sWfqYb?lw{v>T+Zs*N|-0xd7jrYrM(H8ZfawU_Sa|Au*>!`&iJht zJm?uPTAjP?^0(QvjIyPaa?W*2&bgbd2?GEC0000002}}S0002~j~|ouxnY=o`Skz* N002ovPDHLkV1i|<#{vKV diff --git a/board-package-source/libraries/Arduboy2/extras/cabi/README.md b/board-package-source/libraries/Arduboy2/extras/cabi/README.md index b6b8462..f68be19 100644 --- a/board-package-source/libraries/Arduboy2/extras/cabi/README.md +++ b/board-package-source/libraries/Arduboy2/extras/cabi/README.md @@ -77,10 +77,13 @@ 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 -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. +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. diff --git a/board-package-source/libraries/Arduboy2/extras/cabi/cabi.c b/board-package-source/libraries/Arduboy2/extras/cabi/cabi.c index ae88575..31f1bca 100644 --- a/board-package-source/libraries/Arduboy2/extras/cabi/cabi.c +++ b/board-package-source/libraries/Arduboy2/extras/cabi/cabi.c @@ -11,7 +11,7 @@ https://www.lexaloffle.com/bbs/?uid=1 https://twitter.com/lexaloffle Contributed to Team A.R.G. -Modifications by Scott Allen - July 2016 +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 @@ -332,6 +332,12 @@ int main(int argc, char **argv) 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; diff --git a/board-package-source/libraries/Arduboy2/extras/cabi/sample.png b/board-package-source/libraries/Arduboy2/extras/cabi/sample.png index be58c404daf0855cbf828ba0bfd2ffe2778a24f5..5416d4ab31a6491a4dc19d1f7e8dc260ad495d79 100644 GIT binary patch delta 171 zcmV;c095~&0>=T6B!7-cL_t(|UhS8`3IHGoL;L@quA>)e4Rq_^z-xOMXj_c-qZTjT zR04B3G^;uY!jyt3xOFo`W{LrL5C9N{1ONr`Vh#X`A$Fg@Q)mEi7cOmP2MTp&n9Bh| zc7TMm5g_UxfB_hQnFIDwjK;BW8RZayb&R?YCH)nN&GAzRJ|v|$6Iio>z}yqf{NdCd Z&kw$K`&rwKo?QR{002ovPDHLkV1ghqMcV)X delta 252 zcmV$n6VQ?c7x@M$)2m(Hp^+ndVT^r)Q%~GW9UNw0000 sentence=An alternative library for use with the Arduboy game system. diff --git a/board-package-source/libraries/Arduboy2/src/Arduboy2.cpp b/board-package-source/libraries/Arduboy2/src/Arduboy2.cpp index 4964fca..d8d8501 100644 --- a/board-package-source/libraries/Arduboy2/src/Arduboy2.cpp +++ b/board-package-source/libraries/Arduboy2/src/Arduboy2.cpp @@ -10,37 +10,32 @@ //========== class Arduboy2Base ========== //======================================== - uint8_t Arduboy2Base::sBuffer[]; +uint8_t Arduboy2Base::sBuffer[]; - uint8_t Arduboy2Base::currentButtonState = 0; - uint8_t Arduboy2Base::previousButtonState = 0; - // frame management - uint16_t Arduboy2Base::frameCount = 0; - uint8_t Arduboy2Base::eachFrameMillis = 16; - uint8_t Arduboy2Base::thisFrameStart; - uint8_t Arduboy2Base::lastFrameDurationMs; - bool Arduboy2Base::justRendered = false; +uint16_t Arduboy2Base::frameCount = 0; + +uint8_t Arduboy2Base::currentButtonState = 0; +uint8_t Arduboy2Base::previousButtonState = 0; + +uint8_t Arduboy2Base::eachFrameMillis = 16; +uint8_t Arduboy2Base::thisFrameStart; +uint8_t Arduboy2Base::lastFrameDurationMs; +bool Arduboy2Base::justRendered = false; // functions called here should be public so users can create their // own init functions if they need different behavior than `begin` -// provides by default +// provides by default. +// +// This code and it's documentation should be kept in sync with +// Aruduboy2::begin() void Arduboy2Base::begin() { - boot(); // raw hardware - - //using CLEAR_BUFFER so a sketch can be optimized when using CLEAR_BUFFER exclusivly - display(CLEAR_BUFFER); //sBuffer is global, so cleared automatically. - - flashlight(); // light the RGB LED and screen if UP button is being held. - - // check for and handle buttons held during start up for system control - systemButtons(); - - audio.begin(); + beginDoFirst(); bootLogo(); // alternative logo functions. Work the same as bootLogo() but may reduce - // memory size if the sketch uses the same bitmap drawing function + // memory size if the sketch uses the same bitmap drawing function or + // `Sprites`/`SpritesB` class // bootLogoCompressed(); // bootLogoSpritesSelfMasked(); // bootLogoSpritesOverwrite(); @@ -50,6 +45,20 @@ void Arduboy2Base::begin() waitNoButtons(); // wait for all buttons to be released } +void Arduboy2Base::beginDoFirst() +{ + boot(); // raw hardware + + display(); // blank the display (sBuffer is global, so cleared automatically) + + flashlight(); // light the RGB LED and screen if UP button is being held. + + // check for and handle buttons held during start up for system control + systemButtons(); + + audio.begin(); +} + void Arduboy2Base::flashlight() { if (!pressed(UP_BUTTON)) { @@ -60,7 +69,9 @@ void Arduboy2Base::flashlight() #else sendLCDCommand(OLED_ALL_PIXELS_ON); // smaller than allPixelsOn() #endif - digitalWriteRGB(RGB_ON, RGB_ON, RGB_ON); + setRGBledRedOn(); + setRGBledGreenOn(); + setRGBledBlueOn(); // prevent the bootloader magic number from being overwritten by timer 0 // when a timer variable overlaps the magic number location, for when @@ -75,19 +86,19 @@ void Arduboy2Base::flashlight() void Arduboy2Base::systemButtons() { while (pressed(B_BUTTON)) { - digitalWriteRGB(BLUE_LED, RGB_ON); // turn on blue LED + setRGBledBlueOn(); sysCtrlSound(UP_BUTTON + B_BUTTON, GREEN_LED, 0xff); sysCtrlSound(DOWN_BUTTON + B_BUTTON, RED_LED, 0); delayByte(200); } - digitalWriteRGB(BLUE_LED, RGB_OFF); // turn off blue LED + setRGBledBlueOff(); } void Arduboy2Base::sysCtrlSound(uint8_t buttons, uint8_t led, uint8_t eeVal) { if (pressed(buttons)) { - digitalWriteRGB(BLUE_LED, RGB_OFF); // turn off blue LED + setRGBledBlueOff(); delayByte(200); digitalWriteRGB(led, RGB_ON); // turn on "acknowledge" LED EEPROM.update(eepromAudioOnOff, eeVal); @@ -160,35 +171,29 @@ void Arduboy2Base::drawLogoSpritesBOverwrite(int16_t y) // bootLogoText() should be kept in sync with bootLogoShell() // if changes are made to one, equivalent changes should be made to the other -void Arduboy2Base::bootLogoShell(void (*drawLogo)(int16_t)) +bool Arduboy2Base::bootLogoShell(void (&drawLogo)(int16_t)) { bool showLEDs = readShowBootLogoLEDsFlag(); if (!readShowBootLogoFlag()) { - return; + return false; } if (showLEDs) { - #if defined(LCD_ST7565) - digitalWriteRGB(RGB_ON, RGB_OFF, RGB_OFF); - #else - digitalWriteRGB(RED_LED, RGB_ON); - #endif + setRGBledRedOn(); } for (int16_t y = -15; y <= 24; y++) { if (pressed(RIGHT_BUTTON)) { - digitalWriteRGB(RGB_OFF, RGB_OFF, RGB_OFF); // all LEDs off - return; + setRGBledRedOff(); + setRGBledGreenOff(); + //setRGBledblueOff(); // Blue LED not turned on inside loop + return false; } if (showLEDs && y == 4) { - #if defined(LCD_ST7565) - digitalWriteRGB(RGB_OFF, RGB_ON, RGB_OFF); - #else - digitalWriteRGB(RED_LED, RGB_OFF); // red LED off - digitalWriteRGB(GREEN_LED, RGB_ON); // green LED on - #endif + setRGBledRedOff(); + setRGBledGreenOn(); } // Using display(CLEAR_BUFFER) instead of clear() may save code space. @@ -200,27 +205,17 @@ void Arduboy2Base::bootLogoShell(void (*drawLogo)(int16_t)) } if (showLEDs) { - #if defined(LCD_ST7565) - digitalWriteRGB(RGB_OFF, RGB_OFF, RGB_ON); - #else - digitalWriteRGB(GREEN_LED, RGB_OFF); // green LED off - digitalWriteRGB(BLUE_LED, RGB_ON); // blue LED on - #endif + setRGBledGreenOff(); + setRGBledBlueOn(); } delayShort(400); - #if defined(LCD_ST7565) - digitalWriteRGB(RGB_OFF, RGB_OFF, RGB_OFF); - #else - digitalWriteRGB(BLUE_LED, RGB_OFF); - #endif - bootLogoExtra(); + setRGBledBlueOff(); + return true; } -// Virtual function overridden by derived class -void Arduboy2Base::bootLogoExtra() { } - // wait for all buttons to be released -void Arduboy2Base::waitNoButtons() { +void Arduboy2Base::waitNoButtons() +{ do { delayByte(50); // simple button debounce } while (buttonsState()); @@ -319,12 +314,10 @@ void Arduboy2Base::clear() void Arduboy2Base::drawPixel(int16_t x, int16_t y, uint8_t color) { - #ifdef PIXEL_SAFE_MODE if (x < 0 || x > (WIDTH-1) || y < 0 || y > (HEIGHT-1)) { return; } - #endif uint16_t row_offset; uint8_t bit; @@ -644,7 +637,7 @@ void Arduboy2Base::fillScreen(uint8_t color) // { // color = 0xFF; // all pixels on // } - // for (int16_t i = 0; i < WIDTH * HEIGTH / 8; i++) + // for (int16_t i = 0; i < WIDTH * HEIGHT / 8; i++) // { // sBuffer[i] = color; // } @@ -837,8 +830,7 @@ void Arduboy2Base::drawBitmap int8_t yOffset = y & 7; int8_t sRow = y >> 3; - uint8_t rows = h >> 3; - if (h % 8 != 0) rows++; + uint8_t rows = (h+7) >> 3; for (int a = 0; a < rows; a++) { int bRow = sRow + a; if (bRow > (HEIGHT/8)-1) break; @@ -887,17 +879,18 @@ void Arduboy2Base::drawSlowXYBitmap } } - // Helper for drawCompressed() -struct Arduboy2Base::BitStreamReader +class Arduboy2Base::BitStreamReader { + private: const uint8_t *source; uint16_t sourceIndex; uint8_t bitBuffer; uint8_t byteBuffer; - BitStreamReader(const uint8_t *source) - : source(source), sourceIndex(), bitBuffer(), byteBuffer() + public: + BitStreamReader(const uint8_t *bitmap) + : source(bitmap), sourceIndex(), bitBuffer(), byteBuffer() { } @@ -906,17 +899,17 @@ struct Arduboy2Base::BitStreamReader uint16_t result = 0; for (uint8_t i = 0; i < bitCount; i++) { - if (this->bitBuffer == 0) + if (bitBuffer == 0) { - this->bitBuffer = 0x1; - this->byteBuffer = pgm_read_byte(&this->source[this->sourceIndex]); - ++this->sourceIndex; + bitBuffer = 0x1; + byteBuffer = pgm_read_byte(&source[sourceIndex]); + ++sourceIndex; } - if ((this->byteBuffer & this->bitBuffer) != 0) + if ((byteBuffer & bitBuffer) != 0) result |= (1 << i); - this->bitBuffer += this->bitBuffer; + bitBuffer += bitBuffer; } return result; } @@ -925,7 +918,7 @@ struct Arduboy2Base::BitStreamReader void Arduboy2Base::drawCompressed(int16_t sx, int16_t sy, const uint8_t *bitmap, uint8_t color) { // set up decompress state - BitStreamReader cs = BitStreamReader(bitmap); + BitStreamReader cs(bitmap); // read header int width = (int)cs.readBits(8) + 1; @@ -1176,14 +1169,84 @@ void Arduboy2Base::swapInt16(int16_t& a, int16_t& b) //========== class Arduboy2 ========== //==================================== - int16_t Arduboy2::cursor_x = 0; - int16_t Arduboy2::cursor_y = 0; - uint8_t Arduboy2::textColor = 1; - uint8_t Arduboy2::textBackground = 0; - uint8_t Arduboy2::textSize = 1; - bool Arduboy2::textWrap = false; - //bool Arduboy2::textRaw = false; +int16_t Arduboy2::cursor_x = 0; +int16_t Arduboy2::cursor_y = 0; +uint8_t Arduboy2::textColor = WHITE; +uint8_t Arduboy2::textBackground = BLACK; +uint8_t Arduboy2::textSize = 1; +bool Arduboy2::textWrap = false; +bool Arduboy2::textRaw = false; +// functions called here should be public so users can create their +// own init functions if they need different behavior than `begin` +// provides by default. +// +// This code and it's documentation should be kept in sync with +// Aruduboy2Base::begin() +void Arduboy2::begin() +{ + beginDoFirst(); + + bootLogo(); + // alternative logo functions. Work the same as bootLogo() but may reduce + // memory size if the sketch uses the same bitmap drawing function or + // `Sprites`/`SpritesB` class +// bootLogoCompressed(); +// bootLogoSpritesSelfMasked(); +// bootLogoSpritesOverwrite(); +// bootLogoSpritesBSelfMasked(); +// bootLogoSpritesBOverwrite(); + + waitNoButtons(); +} + +void Arduboy2::bootLogo() +{ + if (bootLogoShell(drawLogoBitmap)) + { + bootLogoExtra(); + } +} + +void Arduboy2::bootLogoCompressed() +{ + if (bootLogoShell(drawLogoCompressed)) + { + bootLogoExtra(); + } +} + +void Arduboy2::bootLogoSpritesSelfMasked() +{ + if (bootLogoShell(drawLogoSpritesSelfMasked)) + { + bootLogoExtra(); + } +} + +void Arduboy2::bootLogoSpritesOverwrite() +{ + if (bootLogoShell(drawLogoSpritesOverwrite)) + { + bootLogoExtra(); + } +} + +void Arduboy2::bootLogoSpritesBSelfMasked() +{ + if (bootLogoShell(drawLogoSpritesBSelfMasked)) + { + bootLogoExtra(); + } +} + +void Arduboy2::bootLogoSpritesBOverwrite() +{ + if (bootLogoShell(drawLogoSpritesBOverwrite)) + { + bootLogoExtra(); + } +} // bootLogoText() should be kept in sync with bootLogoShell() // if changes are made to one, equivalent changes should be made to the other @@ -1196,26 +1259,20 @@ void Arduboy2::bootLogoText() } if (showLEDs) { - #if defined(LCD_ST7565) - digitalWriteRGB(RGB_ON, RGB_OFF, RGB_OFF); - #else - digitalWriteRGB(RED_LED, RGB_ON); - #endif + setRGBledRedOn(); } for (int8_t y = -16; y <= 24; y++) { if (pressed(RIGHT_BUTTON)) { - digitalWriteRGB(RGB_OFF, RGB_OFF, RGB_OFF); // all LEDs off + setRGBledRedOff(); + setRGBledGreenOff(); + //setRGBledBlueOff(); //not turned on inside loop return; } if (showLEDs && y == 4) { - #if defined(LCD_ST7565) - digitalWriteRGB(RGB_OFF, RGB_ON, RGB_OFF); - #else - digitalWriteRGB(RED_LED, RGB_OFF); // red LED off - digitalWriteRGB(GREEN_LED, RGB_ON); // green LED on - #endif + setRGBledRedOff(); + setRGBledGreenOn(); } // Using display(CLEAR_BUFFER) instead of clear() may save code space. @@ -1231,20 +1288,11 @@ void Arduboy2::bootLogoText() } if (showLEDs) { - #if defined(LCD_ST7565) - digitalWriteRGB(RGB_OFF, RGB_OFF, RGB_ON); - #else - digitalWriteRGB(GREEN_LED, RGB_OFF); // green LED off - digitalWriteRGB(BLUE_LED, RGB_ON); // blue LED on - #endif + setRGBledGreenOff(); + setRGBledBlueOn(); } delayShort(400); - #if defined(LCD_ST7565) - digitalWriteRGB(RGB_OFF, RGB_OFF, RGB_OFF); - #else - digitalWriteRGB(BLUE_LED, RGB_OFF); - #endif - + setRGBledBlueOff(); bootLogoExtra(); } @@ -1279,64 +1327,106 @@ void Arduboy2::bootLogoExtra() size_t Arduboy2::write(uint8_t c) { - if (c == '\n') + if ((c == '\r') && !textRaw) + { + return 1; + } + + if (((c == '\n') && !textRaw) || + (textWrap && (cursor_x > (WIDTH - (characterWidth * textSize))))) { - cursor_y += textSize * 8; cursor_x = 0; + cursor_y += fullCharacterHeight * textSize; } - else if (c == '\r') - { - // skip em - } - else + + if ((c != '\n') || textRaw) { drawChar(cursor_x, cursor_y, c, textColor, textBackground, textSize); - cursor_x += textSize * 6; - if (textWrap && (cursor_x > (WIDTH - textSize * 6))) - { - // calling ourselves recursively for 'newline' is - // 12 bytes smaller than doing the same math here - write('\n'); - } + cursor_x += fullCharacterWidth * textSize; } + return 1; } void Arduboy2::drawChar - (int16_t x, int16_t y, unsigned char c, uint8_t color, uint8_t bg, uint8_t size) + (int16_t x, int16_t y, uint8_t c, uint8_t color, uint8_t bg, uint8_t size) { - uint8_t line; - bool draw_background = bg != color; - const uint8_t* bitmap = font5x7 + c * 5; - +// It is assumed that rendering characters fully off screen will be rare, +// so let drawPixel() handle off screen checks, to reduce code size at the +// expense of slower off screen character handling. +#if 0 if ((x >= WIDTH) || // Clip right (y >= HEIGHT) || // Clip bottom - ((x + 5 * size - 1) < 0) || // Clip left - ((y + 8 * size - 1) < 0) // Clip top + ((x + characterWidth * size - 1) < 0) || // Clip left + ((y + characterHeight * size - 1) < 0) // Clip top ) { return; } +#endif - for (uint8_t i = 0; i < 6; i++ ) + bool drawBackground = bg != color; + const uint8_t* bitmap = + &font5x7[c * characterWidth * ((characterHeight + 8 - 1) / 8)]; + + for (uint8_t i = 0; i < fullCharacterWidth; i++) { - line = pgm_read_byte(bitmap++); - if (i == 5) { - line = 0x0; + uint8_t column; + + if (characterHeight <= 8) + { + column = (i < characterWidth) ? pgm_read_byte(bitmap++) : 0; + } + else + { + column = 0; } - for (uint8_t j = 0; j < 8; j++) + // draw the character by columns. Top to bottom, left to right + // including character spacing on the right + for (uint8_t j = 0; j < characterHeight; j++) { - uint8_t draw_color = (line & 0x1) ? color : bg; + if (characterHeight > 8) + { + // at this point variable "column" will be 0, either from initialization + // or by having eight 0 bits shifted in by the >>= operation below + if ((j % 8 == 0) && (i < characterWidth)) + { + column = pgm_read_byte(bitmap++); + } + } - if (draw_color || draw_background) { - for (uint8_t a = 0; a < size; a++ ) { - for (uint8_t b = 0; b < size; b++ ) { - drawPixel(x + (i * size) + a, y + (j * size) + b, draw_color); + // pixelIsSet should be a bool but at the time of writing, + // the GCC AVR compiler generates less code if it's a uint8_t + uint8_t pixelIsSet = column & 0x01; + + if (pixelIsSet || drawBackground) + { + for (uint8_t a = 0; a < size; a++) + { + for (uint8_t b = 0; b < size; b++) + { + drawPixel(x + (i * size) + a, y + (j * size) + b, + pixelIsSet ? color : bg); + } + } + } + column >>= 1; + } + + // draw the inter-line spacing pixels for this column if required + if (drawBackground) + { + for (uint8_t j = characterHeight; j < fullCharacterHeight; j++) + { + for (uint8_t a = 0; a < size; a++) + { + for (uint8_t b = 0; b < size; b++) + { + drawPixel(x + (i * size) + a, y + (j * size) + b, bg); } } } - line >>= 1; } } } @@ -1408,6 +1498,16 @@ bool Arduboy2::getTextWrap() return textWrap; } +void Arduboy2::setTextRawMode(bool raw) +{ + textRaw = raw; +} + +bool Arduboy2::getTextRawMode() +{ + return textRaw; +} + void Arduboy2::clear() { Arduboy2Base::clear(); diff --git a/board-package-source/libraries/Arduboy2/src/Arduboy2.h b/board-package-source/libraries/Arduboy2/src/Arduboy2.h index 4e60da5..f14ce1e 100644 --- a/board-package-source/libraries/Arduboy2/src/Arduboy2.h +++ b/board-package-source/libraries/Arduboy2/src/Arduboy2.h @@ -34,7 +34,7 @@ * #endif * \endcode */ -#define ARDUBOY_LIB_VER 50300 +#define ARDUBOY_LIB_VER 60000 // EEPROM settings /** \brief @@ -74,10 +74,6 @@ */ #define EEPROM_STORAGE_SPACE_START 16 -// If defined, it is safe to draw outside of the screen boundaries. -// Pixels that would exceed the display limits will be ignored. -#define PIXEL_SAFE_MODE - // pixel colors #define BLACK 0 /**< Color value for an unlit pixel for draw functions. */ #define WHITE 1 /**< Color value for a lit pixel for draw functions. */ @@ -218,7 +214,6 @@ class Arduboy2Base : public Arduboy2Core friend class Arduboy2Audio; public: - //Arduboy2Base(); /** \brief * An object created to provide audio control functions within this class. @@ -229,7 +224,7 @@ class Arduboy2Base : public Arduboy2Core * * \see Arduboy2Audio */ - static Arduboy2Audio audio; + static Arduboy2Audio audio; /** \brief * Initialize the hardware, display the boot logo, provide boot utilities, etc. @@ -241,14 +236,43 @@ class Arduboy2Base : public Arduboy2Core * and system control features and initializes audio control. * * \note - * To free up some code space for use by the sketch, `boot()` can be used - * instead of `begin()` to allow the elimination of some of the things that - * aren't really required, such as displaying the boot logo. + * \parblock + * If it becomes necessary to free up some code space for use by the sketch, + * `boot()` can be used instead of `begin()` to allow the elimination of + * some of the things that aren't absolutely required. + * + * See the README file or main page, in section + * _Substitute or remove boot up features_, for more details. + * \endparblock * * \see boot() */ static void begin(); + /** \brief + * Helper function that calls the inital functions used by `begin()` + * + * \details + * This function calls all the functions used by `begin()` up to the point of + * calling `bootLogo()`. It could be called by a sketch to make it easy to + * use one of the alternative `bootLogo...()` functions or a user provided + * one. + * + * For example, if a sketch uses `Sprites` class functions but doesn't use + * `drawBitmap()`, some program space may be saved by using the following in + * place of `begin()`: + * + * \code{.cpp} + * arduboy.beginDoFirst(); + * arduboy.bootLogoSpritesSelfMasked(); // or: + * //arduboy.bootLogoSpritesOverwrite(); // (whatever saves more memory) + * arduboy.waitNoButtons(); + * \endcode + * + * \see begin() boot() + */ + static void beginDoFirst(); + /** \brief * Turn the RGB LED and display fully on to act as a small flashlight/torch. * @@ -257,8 +281,8 @@ class Arduboy2Base : public Arduboy2Core * display pixels fully on. If the UP button is detected, this function * does not exit. The Arduboy must be restarted after flashlight mode is used. * - * This function is called by `begin()` and can be called by a sketch - * after `boot()`. + * This function is called by `begin()` and should be called by a sketch + * after `boot()` unless `safeMode()` is called instead. * * \note * \parblock @@ -267,10 +291,9 @@ class Arduboy2Base : public Arduboy2Core * This problem occurs with certain sketches that use large amounts of RAM. * Being in flashlight mode when uploading a new sketch can fix this problem. * - * Therefore, for sketches that potentially could cause this problem, and use - * `boot()` instead of `begin()`, it is recommended that a call to - * `flashlight()` be included after calling `boot()`. If program space is - * limited, `safeMode()` can be used instead of `flashlight()`. + * Therefore, for sketches that use `boot()` instead of `begin()`, a call to + * `flashlight()` should be included after calling `boot()`. If program space + * is limited, `safeMode()` can be used instead of `flashlight()`. * \endparblock * * \see begin() boot() safeMode() @@ -335,7 +358,7 @@ class Arduboy2Base : public Arduboy2Core * * \see bootLogo() begin() boot() Sprites */ - void bootLogoSpritesSelfMasked(); + static void bootLogoSpritesSelfMasked(); /** \brief * Display the boot logo sequence using `Sprites::drawOverwrite()`. @@ -374,11 +397,14 @@ class Arduboy2Base : public Arduboy2Core static void bootLogoSpritesBOverwrite(); /** \brief - * Display the boot logo sequence using the provided function + * Display the boot logo sequence using the provided function. * * \param drawLogo A reference to a function which will draw the boot logo * at the given Y position. * + * \return `true` if the sequence runs to completion. `false` if the sequence + * is aborted or bypassed. + * * \details * This common function executes the sequence to display the boot logo. * It is called by `bootLogo()` and other similar functions which provide it @@ -414,11 +440,7 @@ class Arduboy2Base : public Arduboy2Core * * \see bootLogo() boot() Arduboy2::bootLogoExtra() */ - static void bootLogoShell(void (*drawLogo)(int16_t)); - - // Called by bootLogoShell() to allow derived classes to display additional - // information after the logo stops scrolling down. - static void bootLogoExtra(); + static bool bootLogoShell(void (&drawLogo)(int16_t)); /** \brief * Wait until all buttons have been released. @@ -445,10 +467,19 @@ class Arduboy2Base : public Arduboy2Core * \details * The entire contents of the screen buffer are cleared to BLACK. * - * \see display(bool) + * \see display(bool) fillScreen() */ static void clear(); + /** \brief + * Fill the screen buffer with the specified color. + * + * \param color The fill color (optional; defaults to WHITE). + * + * \see clear() + */ + static void fillScreen(uint8_t color = WHITE); + /** \brief * Copy the contents of the display buffer to the display. * @@ -511,6 +542,8 @@ class Arduboy2Base : public Arduboy2Core * \param y0 The Y coordinate of the circle's center. * \param r The radius of the circle in pixels. * \param color The circle's color (optional; defaults to WHITE). + * + * \see fillCircle() */ static void drawCircle(int16_t x0, int16_t y0, uint8_t r, uint8_t color = WHITE); @@ -521,6 +554,8 @@ class Arduboy2Base : public Arduboy2Core * \param y0 The Y coordinate of the circle's center. * \param r The radius of the circle in pixels. * \param color The circle's color (optional; defaults to WHITE). + * + * \see drawCircle() */ static void fillCircle(int16_t x0, int16_t y0, uint8_t r, uint8_t color = WHITE); @@ -535,20 +570,11 @@ class Arduboy2Base : public Arduboy2Core * Draw a line from the start point to the end point using * Bresenham's algorithm. * The start and end points can be at any location with respect to the other. + * + * \see drawFastHLine() drawFastVLine() */ static void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint8_t color = WHITE); - /** \brief - * Draw a rectangle of a specified width and height. - * - * \param x The X coordinate of the upper left corner. - * \param y The Y coordinate of the upper left corner. - * \param w The width of the rectangle. - * \param h The height of the rectangle. - * \param color The color of the pixel (optional; defaults to WHITE). - */ - static void drawRect(int16_t x, int16_t y, uint8_t w, uint8_t h, uint8_t color = WHITE); - /** \brief * Draw a vertical line. * @@ -556,6 +582,8 @@ class Arduboy2Base : public Arduboy2Core * \param y The Y coordinate of the upper start point. * \param h The height of the line. * \param color The color of the line (optional; defaults to WHITE). + * + * \see drawFastHLine() drawLine() */ static void drawFastVLine(int16_t x, int16_t y, uint8_t h, uint8_t color = WHITE); @@ -566,9 +594,24 @@ class Arduboy2Base : public Arduboy2Core * \param y The Y coordinate of the left start point. * \param w The width of the line. * \param color The color of the line (optional; defaults to WHITE). + * + * \see drawFastVLine() drawLine() */ static void drawFastHLine(int16_t x, int16_t y, uint8_t w, uint8_t color = WHITE); + /** \brief + * Draw a rectangle of a specified width and height. + * + * \param x The X coordinate of the upper left corner. + * \param y The Y coordinate of the upper left corner. + * \param w The width of the rectangle. + * \param h The height of the rectangle. + * \param color The color of the pixel (optional; defaults to WHITE). + * + * \see fillRect() drawRoundRect() fillRoundRect() + */ + static void drawRect(int16_t x, int16_t y, uint8_t w, uint8_t h, uint8_t color = WHITE); + /** \brief * Draw a filled-in rectangle of a specified width and height. * @@ -577,16 +620,11 @@ class Arduboy2Base : public Arduboy2Core * \param w The width of the rectangle. * \param h The height of the rectangle. * \param color The color of the pixel (optional; defaults to WHITE). + * + * \see drawRect() drawRoundRect() fillRoundRect() */ static void fillRect(int16_t x, int16_t y, uint8_t w, uint8_t h, uint8_t color = WHITE); - /** \brief - * Fill the screen buffer with the specified color. - * - * \param color The fill color (optional; defaults to WHITE). - */ - static void fillScreen(uint8_t color = WHITE); - /** \brief * Draw a rectangle with rounded corners. * @@ -596,6 +634,8 @@ class Arduboy2Base : public Arduboy2Core * \param h The height of the rectangle. * \param r The radius of the semicircles forming the corners. * \param color The color of the rectangle (optional; defaults to WHITE). + * + * \see fillRoundRect() drawRect() fillRect() */ static void drawRoundRect(int16_t x, int16_t y, uint8_t w, uint8_t h, uint8_t r, uint8_t color = WHITE); @@ -608,6 +648,8 @@ class Arduboy2Base : public Arduboy2Core * \param h The height of the rectangle. * \param r The radius of the semicircles forming the corners. * \param color The color of the rectangle (optional; defaults to WHITE). + * + * \see drawRoundRect() drawRect() fillRect() */ static void fillRoundRect(int16_t x, int16_t y, uint8_t w, uint8_t h, uint8_t r, uint8_t color = WHITE); @@ -621,6 +663,8 @@ class Arduboy2Base : public Arduboy2Core * \details * A triangle is drawn by specifying each of the three corner locations. * The corners can be at any position with respect to the others. + * + * \see fillTriangle() */ 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); @@ -634,8 +678,10 @@ class Arduboy2Base : public Arduboy2Core * \details * A triangle is drawn by specifying each of the three corner locations. * The corners can be at any position with respect to the others. + * + * \see drawTriangle() */ - 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); + 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); /** \brief * Draw a bitmap from an array in program memory. @@ -644,7 +690,7 @@ class Arduboy2Base : public Arduboy2Core * \param y The Y coordinate of the top left pixel affected by the bitmap. * \param bitmap A pointer to the bitmap array in program memory. * \param w The width of the bitmap in pixels. - * \param h The height of the bitmap in pixels. + * \param h The height of the bitmap in pixels. Must be a multiple of 8. * \param color The color of pixels for bits set to 1 in the bitmap. * If the value is INVERT, bits set to 1 will invert the * corresponding pixel. (optional; defaults to WHITE). @@ -655,9 +701,12 @@ class Arduboy2Base : public Arduboy2Core * corresponding pixel will be left unchanged. * * Each byte in the array specifies a vertical column of 8 pixels, with the - * least significant bit at the top. + * least significant bit at the top. The height of the image must be a + * multiple of 8 pixels (8, 16, 24, 32, ...). The width can be any size. * * The array must be located in program memory by using the PROGMEM modifier. + * + * \see drawCompressed() drawSlowXYBitmap() Sprites */ static void drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t w, uint8_t h, uint8_t color = WHITE); @@ -687,6 +736,8 @@ class Arduboy2Base : public Arduboy2Core * slower than `drawBitmap()`, which uses bitmaps that are stored in a format * that allows them to be directly written to the screen. It is recommended * you use `drawBitmap()` when possible. + * + * \see drawBitmap() drawCompressed() */ static void drawSlowXYBitmap(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t w, uint8_t h, uint8_t color = WHITE); @@ -703,6 +754,9 @@ class Arduboy2Base : public Arduboy2Core * Draw a bitmap starting at the given coordinates using an array that has * been compressed using an RLE algorthm implemented by Team A.R.G. * + * The height of the image must be a multiple of 8 pixels (8, 16, 24, + * 32, ...). The width can be any size. + * * Bits set to 1 in the provided bitmap array (after decoding) will have * their corresponding pixel set to the specified color. For bits set to 0 * in the array, the corresponding pixel will be left unchanged. @@ -713,6 +767,8 @@ class Arduboy2Base : public Arduboy2Core * C source code for a command line program named `Cabi`, which can convert * a PNG bitmap image file to source code suitable for use with * `drawCompressed()`, is included in the `extras` directory of the library. + * + * \see drawBitmap() drawSlowXYBitmap() */ static void drawCompressed(int16_t sx, int16_t sy, const uint8_t *bitmap, uint8_t color = WHITE); @@ -759,7 +815,7 @@ class Arduboy2Base : public Arduboy2Core * \details * Set the frame rate, in frames per second, used by `nextFrame()` to update * frames at a given rate. If this function or `setFrameDuration()` - * isn't used, the default rate will be 60 (actually 62.5, see note below). + * isn't used, the default rate will be 60 (actually 62.5; see note below). * * Normally, the frame rate would be set to the desired value once, at the * start of the game, but it can be changed at any time to alter the frame @@ -806,7 +862,8 @@ class Arduboy2Base : public Arduboy2Core * * \details * When this function returns `true`, the amount of time has elapsed to - * display the next frame, as specified by `setFrameRate()`. + * display the next frame, as specified by `setFrameRate()` or + * `setFrameDuration()`. * * This function will normally be called at the start of the rendering loop * which would wait for `true` to be returned before rendering and @@ -838,18 +895,20 @@ class Arduboy2Base : public Arduboy2Core * development of a sketch. It does the same thing as `nextFrame()` but * additionally will light the yellow TX LED (at the bottom, to the left * of the USB connector) whenever a frame takes longer to generate than the - * time allotted per frame, as determined by the `setFrameRate()` function. + * time allotted per frame, as determined by the `setFrameRate()` or + * `setFrameDuration()` function. * * Therefore, whenever the TX LED comes on (while not communicating over * USB), it indicates that the sketch is running slower than the desired - * rate set by `setFrameRate()`. In this case the developer may wish to set - * a slower frame rate, or reduce or optimize the code for such frames. + * rate set by `setFrameRate()` or `setFrameDuration()`. In this case the + * developer may wish to set a slower frame rate, or reduce or optimize the + * code for such frames. * * \note * Once a sketch is ready for release, it would be expected that * `nextFrameDEV()` calls be restored to `nextFrame()`. * - * \see nextFrame() cpuLoad() setFrameRate() + * \see nextFrame() cpuLoad() setFrameRate() setFrameDuration() */ static bool nextFrameDEV(); @@ -876,7 +935,7 @@ class Arduboy2Base : public Arduboy2Core * } * \endcode * - * \see setFrameRate() nextFrame() + * \see setFrameRate() setFrameDuration() nextFrame() */ static bool everyXFrames(uint8_t frames); @@ -899,7 +958,7 @@ class Arduboy2Base : public Arduboy2Core * that the frame rate should be made slower or the frame processing code * should be optimized to run faster. * - * \see setFrameRate() nextFrame() + * \see nextFrameDEV() setFrameRate() setFrameDuration() nextFrame() */ static int cpuLoad(); @@ -973,7 +1032,7 @@ class Arduboy2Base : public Arduboy2Core * * \details * Read and save the current state of the buttons and also keep track of the - * button state when this function was previouly called. These states are + * button state when this function was previously called. These states are * used by the `justPressed()` and `justReleased()` functions to determine * if a button has changed state between now and the previous call to * `pollButtons()`. @@ -999,7 +1058,7 @@ class Arduboy2Base : public Arduboy2Core * a frame rate of 60 or lower (or possibly somewhat higher), should be * sufficient. * - * \see justPressed() justReleased() + * \see justPressed() justReleased() currentButtonState previousButtonState */ static void pollButtons(); @@ -1321,6 +1380,76 @@ class Arduboy2Base : public Arduboy2Core */ static uint16_t frameCount; + /** \brief + * Used by `pollButtons()` to hold the current button state. + * + * \details + * Holds the last button state read by the `pollButtons()` function. + * + * A sketch normally does not need to read or manipulate this variable and + * just lets `pollButtons()` handle it. Access to it is provided for special + * circumstances. See `previousButtonState` for further discussion. + * + * \see previousButtonState pollButtons() justPressed() justReleased() + */ + static uint8_t currentButtonState; + + /** \brief + * Used by `pollButtons()` to hold the previous button state. + * + * \details + * Holds the button state saved by the `pollButtons()` function from the + * previous to last call to it. + * + * A sketch normally does not need to read or manipulate this variable and + * just lets `pollButtons()` handle it. Access to it is provided for special + * circumstances. + * + * For example, the time between calls to `pollButtons()` must be long + * enough to allow sufficient time to "debounce" the buttons. + * `pollButtons()` is normally called once every frame but at a high frame + * rate the time between frames may be too short for this. Calling + * `pollButtons()` every 2nd frame could provide a long enough time but + * then a call to `justPressed()` in each frame would make it look like a + * button was pressed twice. To remedy this, after `justPressed()` detects + * a press, `previousButtonState` could be modified to acknowledge the + * button press. + * + * \code{.cpp} + * void setup() { + * arduboy.begin(); + * arduboy.setFrameRate(120); // too fast for button debounce + * } + * + * void loop() { + * if (!arduboy.nextFrame()) { + * return; + * } + * + * if (arduboy.everyXFrames(2)) { // only poll every 2nd frame + * arduboy.pollButtons(); // to slow down poll frequency + * } + * + * if (justPressedOnce(A_BUTTON)) { + * // handle button press as normal... + * } + * + * // remainder of loop() code... + * } + * + * bool justPressedOnce(uint8_t button) { + * bool pressed = arduboy.justPressed(button); + * if (pressed) { + * arduboy.previousButtonState |= button; // set state as pressed + * } + * return pressed; + * } + * \endcode + * + * \see currentButtonState pollButtons() justPressed() justReleased() + */ + static uint8_t previousButtonState; + /** \brief * The display buffer array in RAM. * @@ -1385,15 +1514,11 @@ class Arduboy2Base : public Arduboy2Core // swap the values of two int16_t variables passed by reference static void swapInt16(int16_t& a, int16_t& b); - // For button handling - static uint8_t currentButtonState; - static uint8_t previousButtonState; - // For frame functions static uint8_t eachFrameMillis; static uint8_t thisFrameStart; - static bool justRendered; static uint8_t lastFrameDurationMs; + static bool justRendered; // ----- Map of EEPROM addresses for system use----- @@ -1413,7 +1538,7 @@ class Arduboy2Base : public Arduboy2Core static constexpr uint16_t eepromUnitName = 10; // -- User EEPROM space starts at address 16 -- - // --- map of the bits in the eepromSysFlags byte -- + // --- Map of the bits in the eepromSysFlags byte -- // Display the unit name on the logo screen static constexpr uint8_t sysFlagUnameBit = 0; static constexpr uint8_t sysFlagUnameMask = _BV(sysFlagUnameBit); @@ -1465,15 +1590,18 @@ class Arduboy2 : public Print, public Arduboy2Base * * Print will use the `write()` function to actually draw each character * in the screen buffer, using the library's `font5x7` font. - * Two character values are handled specially (and thus the font symbols that - * they represent can't be displayed): + * Two character values are handled specially: * - * - ASCII newline or line feed (`\n`, 0x0A, inverse white circle). + * - ASCII newline/line feed (`\n`, 0x0A, inverse white circle). * This will move the text cursor position to the start of the next line, * based on the current text size. * - ASCII carriage return (`\r`, 0x0D, musical eighth note). * This character will be ignored. * + * To override the special handling of the above values, to allow the + * characters they represent to be printed, text _raw_ mode can be selected + * using the `setTextRawMode()` function. + * * See: * https://www.arduino.cc/reference/en/language/functions/communication/serial/print/ * @@ -1481,18 +1609,127 @@ class Arduboy2 : public Print, public Arduboy2Base * \code{.cpp} * int value = 42; * - * arduboy.println("Hello World"); // Prints "Hello World" and then moves the + * arduboy.println("Hello World"); // Prints "Hello World" and then sets the * // text cursor to the start of the next line - * arduboy.print(value); // Prints "42" - * arduboy.print('\n'); // Moves the text cursor to the start of the next line - * arduboy.print(78, HEX); // Prints "4E" (78 in hexadecimal) - * arduboy.print("\x03\xEA"); // Prints a heart symbol and a Greek uppercase omega + * arduboy.print(value); // Prints "42" + * arduboy.print('\n'); // Sets the text cursor to the start of the next line + * arduboy.print(78, HEX); // Prints "4E" (78 in hexadecimal) + * arduboy.print("\x03\xEA"); // Prints a heart symbol and a Greek uppercase omega + * + * arduboy.setTextRawMode(true); // Set text "raw" mode + * arduboy.print("\r\n") // Prints a "musical eighth note" + * // followed by an "inverse white circle" + * // because we're in "raw" mode + * arduboy.setTextRawMode(false); // Exit text "raw" mode * \endcode * - * \see Arduboy2::write() Arduboy2::font5x7 + * \see Arduboy2::setTextSize() Arduboy2::setTextColor() + * Arduboy2::setTextBackground() Arduboy2::setTextWrap() + * Arduboy2::setTextRawMode() Arduboy2::write() Arduboy2::font5x7 */ using Print::write; + /** \brief + * Initialize the hardware, display the boot logo, provide boot utilities, etc. + * + * \details + * This function should be called once near the start of the sketch, + * usually in `setup()`, before using any other functions in this class. + * It initializes the display, displays the boot logo, provides "flashlight" + * and system control features and initializes audio control. + * + * \note + * \parblock + * If it becomes necessary to free up some code space for use by the sketch, + * `boot()` can be used instead of `begin()` to allow the elimination of + * some of the things that aren't absolutely required. + * + * See the README file or main page, in section + * _Substitute or remove boot up features_, for more details. + * \endparblock + * + * \see boot() + */ + void begin(); + + /** \brief + * Display the boot logo sequence using `drawBitmap()`. + * + * \details + * This function is called by `begin()` and can be called by a sketch + * after `boot()`. + * + * The Arduboy logo scrolls down from the top of the screen to the center + * while the RGB LEDs light in sequence. + * + * The `bootLogoShell()` helper function is used to perform the actual + * sequence. The documentation for `bootLogoShell()` provides details on how + * it operates. + * + * \see begin() boot() bootLogoShell() Arduboy2::bootLogoText() + */ + void bootLogo(); + + /** \brief + * Display the boot logo sequence using `drawCompressed()`. + * + * \details + * This function can be called by a sketch after `boot()` as an alternative to + * `bootLogo()`. This may reduce code size if the sketch itself uses + * `drawCompressed()`. + * + * \see bootLogo() begin() boot() + */ + void bootLogoCompressed(); + + /** \brief + * Display the boot logo sequence using `Sprites::drawSelfMasked()`. + * + * \details + * This function can be called by a sketch after `boot()` as an alternative to + * `bootLogo()`. This may reduce code size if the sketch itself uses + * `Sprites` class functions. + * + * \see bootLogo() begin() boot() Sprites + */ + void bootLogoSpritesSelfMasked(); + + /** \brief + * Display the boot logo sequence using `Sprites::drawOverwrite()`. + * + * \details + * This function can be called by a sketch after `boot()` as an alternative to + * `bootLogo()`. This may reduce code size if the sketch itself uses + * `Sprites` class functions. + * + * \see bootLogo() begin() boot() Sprites + */ + void bootLogoSpritesOverwrite(); + + /** \brief + * Display the boot logo sequence using `SpritesB::drawSelfMasked()`. + * + * \details + * This function can be called by a sketch after `boot()` as an alternative to + * `bootLogo()`. This may reduce code size if the sketch itself uses + * `SpritesB` class functions. + * + * \see bootLogo() begin() boot() SpritesB + */ + void bootLogoSpritesBSelfMasked(); + + /** \brief + * Display the boot logo sequence using `SpritesB::drawOverwrite()`. + * + * \details + * This function can be called by a sketch after `boot()` as an alternative to + * `bootLogo()`. This may reduce code size if the sketch itself uses + * `SpritesB` class functions. + * + * \see bootLogo() begin() boot() SpritesB + */ + void bootLogoSpritesBOverwrite(); + /** \brief * Display the boot logo sequence using printed text instead of a bitmap. * @@ -1528,7 +1765,8 @@ class Arduboy2 : public Print, public Arduboy2Base * Show the unit name at the bottom of the boot logo screen. * * \details - * This function is called by `bootLogoShell()` and `bootLogoText()`. + * This function is called by the `bootLogo...()` functions if the logo + * sequence runs to completion. * * If a unit name has been saved in system EEPROM, it will be displayed at * the bottom of the screen. This function pauses for a short time to allow @@ -1537,14 +1775,16 @@ class Arduboy2 : public Print, public Arduboy2Base * If the "Show Unit Name" flag in system EEPROM is cleared, this function * will return without showing the unit name or pausing. * - * \note * This function would not normally be called directly from within a sketch - * itself. + * except from a sketch provided `bootlogo...()` function that renders the + * boot logo using a function that's not part of the Arduboy2 library. + * The README file or main page describes how this would be done, at the + * end of the _Substitute or remove boot up features_ section. * * \see readUnitName() writeUnitName() bootLogo() bootLogoShell() * bootLogoText() writeShowUnitNameFlag() begin() */ - virtual void bootLogoExtra(); + void bootLogoExtra(); /** \brief * Write a single character at the current text cursor position. @@ -1556,27 +1796,31 @@ class Arduboy2 : public Print, public Arduboy2Base * \details * This is the Arduboy implemetation of the Arduino virtual `write()` * function. The single character specified is written to the the screen - * buffer at the current text cursor position. The text cursor is then - * moved to the next character position in the screen buffer. This new cursor - * position will depend on the current text size and possibly the current - * wrap mode. + * buffer at the current text cursor position or possibly the start of the + * next line if text wrap mode is on. The text cursor is then set to the + * next character position. * * Characters are rendered using the library's `font5x7` font. - * Two character values are handled specially (and thus the font symbols that - * they represent can't be displayed): + * Two character values are handled specially: * - * - ASCII newline or line feed (`\n`, 0x0A, inverse white circle). + * - ASCII newline/line feed (`\n`, 0x0A, inverse white circle). * This will move the text cursor position to the start of the next line, * based on the current text size. * - ASCII carriage return (`\r`, 0x0D, musical eighth note). * This character will be ignored. * + * To override the special handling of the above values, to allow the + * characters they represent to be printed, text _raw_ mode can be selected + * using the `setTextRawMode()` function. + * + * * \note * This function is rather low level and, although it's available as a public * function, it wouldn't normally be used. In most cases the Arduino Print * class should be used for writing text. * - * \see Print setTextSize() setTextWrap() drawChar() + * \see Print setTextSize() setTextColor() setTextBackground() setTextWrap() + * setTextRawMode() drawChar() font5x7 */ virtual size_t write(uint8_t); @@ -1592,9 +1836,9 @@ class Arduboy2 : public Print, public Arduboy2Base * \param size The size of the character to draw. * * \details - * The specified character is drawn starting at the provided - * coordinate. The point specified by the X and Y coordinates will be the - * top left corner of the character. The character will be rendered using the + * The specified character is drawn starting at the provided coordinate. + * The point specified by the X and Y coordinates will be the top left + * corner of the character. The character will be rendered using the * library's `font5x7` font. * * \note @@ -1603,10 +1847,9 @@ class Arduboy2 : public Print, public Arduboy2Base * normally be used. In most cases the Arduino Print class should be used for * writing text. * - * \see Print write() setTextColor() setTextBackground() setTextSize() - * font5x7 + * \see Print write() font5x7 */ - static void drawChar(int16_t x, int16_t y, unsigned char c, uint8_t color, uint8_t bg, uint8_t size); + static void drawChar(int16_t x, int16_t y, uint8_t c, uint8_t color, uint8_t bg, uint8_t size); /** \brief * Set the location of the text cursor. @@ -1688,6 +1931,7 @@ class Arduboy2 : public Print, public Arduboy2Base * Set the text foreground color. * * \param color The color to be used for following text. + * The values `WHITE` or `BLACK` should be used. * * \see setTextBackground() getTextColor() */ @@ -1698,7 +1942,7 @@ class Arduboy2 : public Print, public Arduboy2Base * * \return The color that will be used to display any following text. * - * \see setTextColor() + * \see setTextColor() getTextBackground() */ static uint8_t getTextColor(); @@ -1706,6 +1950,15 @@ class Arduboy2 : public Print, public Arduboy2Base * Set the text background color. * * \param bg The background color to be used for following text. + * The values `WHITE` or `BLACK` should be used. + * + * The background pixels of following characters will be set to the + * specified color. + * + * However, if the background color is set to be the same as the text color, + * the background will be transparent. Only the foreground pixels will be + * drawn. The background pixels will remain as they were before the character + * was drawn. * * \see setTextColor() getTextBackground() */ @@ -1716,7 +1969,7 @@ class Arduboy2 : public Print, public Arduboy2Base * * \return The background color that will be used to display any following text. * - * \see setTextBackground() + * \see setTextBackground() getTextColor() */ static uint8_t getTextBackground(); @@ -1726,15 +1979,13 @@ class Arduboy2 : public Print, public Arduboy2Base * \param s The text size multiplier. Must be 1 or higher. * * \details - * Setting a text size of 1 will result in standard size characters which - * occupy 6x8 pixels (the result of 5x7 characters with spacing on the - * right and bottom edges). + * Setting a text size of 1 will result in standard size characters with + * one pixel for each bit in the bitmap for a character. The value specified + * is a multiplier. A value of 2 will double the width and height. + * A value of 3 will triple the dimensions, etc. * - * The value specified is a multiplier. A value of 2 will double the - * size so they will occupy 12x16 pixels. A value of 3 will result in - * 18x24, etc. - * - * \see getTextSize() + * \see getTextSize() getCharacterWidth() getCharacterHeight() + * getCharacterSpacing() getLineSpacing() font5x7 */ static void setTextSize(uint8_t s); @@ -1743,7 +1994,8 @@ class Arduboy2 : public Print, public Arduboy2Base * * \return The size that will be used for any following text. * - * \see setTextSize() + * \see setTextSize() getCharacterWidth() getCharacterHeight() + * getCharacterSpacing() getLineSpacing() font5x7 */ static uint8_t getTextSize(); @@ -1753,14 +2005,15 @@ class Arduboy2 : public Print, public Arduboy2Base * \param w `true` enables text wrap mode. `false` disables it. * * \details - * Text wrap mode is enabled by specifying `true`. In wrap mode, the text - * cursor will be moved to the start of the next line (based on the current - * text size) if the following character wouldn't fit entirely at the end of - * the current line. + * Text wrap mode is enabled by specifying `true`. In wrap mode, if a + * character to be drawn would end up partially or fully past the right edge + * of the screen (based on the current text size), it will be placed at the + * start of the next line. The text cursor will be adjusted accordingly. * - * If wrap mode is disabled, characters will continue to be written to the - * same line. A character at the right edge of the screen may only be - * partially displayed and additional characters will be off screen. + * If wrap mode is disabled, characters will always be written at the current + * text cursor position. A character near the right edge of the screen may + * only be partially displayed and characters drawn at a position past the + * right edge of the screen will remain off screen. * * \see getTextWrap() */ @@ -1776,10 +2029,137 @@ class Arduboy2 : public Print, public Arduboy2Base static bool getTextWrap(); /** \brief - * Clear the display buffer and set the text cursor to location 0, 0 + * Set or disable text raw mode, allowing special characters to be displayed. + * + * \param raw `true` enables text raw mode. `false` disables it. + * + * \details + * In text _raw_ mode, character values that would normally be treated + * specially will instead be displayed. The special characters are: + * + * - ASCII newline/line feed (`\n`, 0x0A, inverse white circle). + * - ASCII carriage return (`\r`, 0x0D, musical eighth note). + * + * All other characters can be displayed regardless of whether raw mode + * is enabled or not. + * + * \see getTextRawMode() Print + */ + static void setTextRawMode(bool raw); + + /** \brief + * Get the current state of text raw mode. + * + * \return `true` if text raw mode is enabled, `false` if disabled. + * + * \see setTextRawMode() + */ + static bool getTextRawMode(); + + /** \brief + * Clear the display buffer and set the text cursor to location 0, 0. */ static void clear(); + /** \brief + * Get the width, in pixels, of a character in the library's font. + * + * \param textSize The text size the character would be drawn at + * (optional; defaults to 1). + * + * \return The width, in pixels, that a character will occupy, not including + * inter-character spacing. + * + * \details + * Returns the width, in pixels, occupied by a character in the font used by + * the library for text functions. The result will be based on the provided + * text size, or size 1 if not included. Since the font is monospaced, all + * characters will occupy the same width for a given text size. + * + * The width does not include the spacing added after each character by the + * library text functions. The `getCharacterSpacing()` function can be used + * to obtain the character spacing value. + * + * \see getCharacterHeight() getCharacterSpacing() + * getTextSize() setTextSize() font5x7 + */ + static constexpr uint8_t getCharacterWidth(uint8_t textSize = 1) + { + return characterWidth * textSize; + } + + /** \brief + * Get the number of pixels added after each character to provide spacing. + * + * \param textSize The text size the character would be drawn at + * (optional; defaults to 1). + * + * \return The number of pixels of space added after each character. + * + * \details + * Returns the number of pixels added to the right of each character, + * to provide spacing, when drawn by the library text functions. + * The result will be based on the provided text size, or size 1 if not + * included. + * + * \see getCharacterWidth() getLineSpacing() + * getTextSize() setTextSize() font5x7 + */ + static constexpr uint8_t getCharacterSpacing(uint8_t textSize = 1) + { + return characterSpacing * textSize; + } + + /** \brief + * Get the height, in pixels, of a character in the library's font. + * + * \param textSize The text size the character would be drawn at + * (optional; defaults to 1). + * + * \return The height, in pixels, that a character will occupy. + * + * \details + * Returns the height, in pixels, that a character will occupy when drawn + * using the library text functions. The result will be based on the + * provided text size, or size 1 if not included. + * + * \see getCharacterWidth() getLineSpacing() + * getTextSize() setTextSize() font5x7 + */ + static constexpr uint8_t getCharacterHeight(uint8_t textSize = 1) + { + return characterHeight * textSize; + } + + /** \brief + * Get the number of pixels added below each character to provide + * line spacing. + * + * \param textSize The text size the character would be drawn at + * (optional; defaults to 1). + * + * \return The number of pixels of space added below each character. + * + * \details + * Returns the number of pixels added below each character, to provide + * spacing for wrapped lines, when drawn by the library text functions. + * The result will be based on the provided text size, or size 1 if + * not included. + * + * \note + * For this library, the value returned will be 0 because no spacing is added + * between lines. This function is included so that it can be used to write + * code that would be easily portable for use with a suite of equivalent + * functions that rendered text with added line spacing. + * + * \see getCharacterHeight() getCharacterSpacing() + * getTextSize() setTextSize() font5x7 + */ + static constexpr uint8_t getLineSpacing(uint8_t textSize = 1) + { + return lineSpacing * textSize; + } + /** \brief * The font used for text functions. * @@ -1793,7 +2173,7 @@ class Arduboy2 : public Print, public Arduboy2Base * The character set represented is code page 437, also known as OEM 437, * OEM-US, PC-8 or DOS Latin US. This is an 8 bit set which includes all * printable ASCII characters plus many accented characters, symbols and - * line drawing characters. + * line drawing characters. * * The data for this font is from file `glcdfont.c` in the * [Adafruit GFX graphics library](https://github.com/adafruit/Adafruit-GFX-Library). @@ -1808,17 +2188,22 @@ class Arduboy2 : public Print, public Arduboy2Base * \note * \parblock * The library's text functions, except `drawChar()`, handle two character - * values specially (and thus the font symbols that they represent can't be - * displayed using these functions): + * values specially: * - * - ASCII newline or line feed (`\n`, 0x0A, inverse white circle). + * - ASCII newline/line feed (`\n`, 0x0A, inverse white circle). * This will move the text cursor position to the start of the next line, * based on the current text size. * - ASCII carriage return (`\r`, 0x0D, musical eighth note). * This character will be ignored. + * + * To override the special handling of the above values, to allow the + * characters they represent to be printed, text _raw_ mode can be selected + * using the `setTextRawMode()` function. * \endparblock * - * \see Print write() readUnitName() writeUnitName() + * \see Print write() drawChar() setTextRawMode() + * getCharacterWidth() getCharacterHeight() + * getCharacterSpacing() getLineSpacing() readUnitName() writeUnitName() */ static const PROGMEM uint8_t font5x7[]; @@ -1829,6 +2214,19 @@ class Arduboy2 : public Print, public Arduboy2Base static uint8_t textBackground; static uint8_t textSize; static bool textWrap; + static bool textRaw; + + // Width and height of a font5x7 character + // (not including inter-character spacing) + static constexpr uint8_t characterWidth = 5; + static constexpr uint8_t characterHeight = 8; + // Width of inter-character spacing + static constexpr uint8_t characterSpacing = 1; + // Height of inter-line spacing + static constexpr uint8_t lineSpacing = 0; + // Character sizes including spacing + static constexpr uint8_t fullCharacterWidth = characterWidth + characterSpacing; + static constexpr uint8_t fullCharacterHeight = characterHeight + lineSpacing; }; extern volatile unsigned long timer0_millis; diff --git a/board-package-source/libraries/Arduboy2/src/Arduboy2Audio.h b/board-package-source/libraries/Arduboy2/src/Arduboy2Audio.h index c7c8035..d359831 100644 --- a/board-package-source/libraries/Arduboy2/src/Arduboy2Audio.h +++ b/board-package-source/libraries/Arduboy2/src/Arduboy2Audio.h @@ -80,11 +80,8 @@ class Arduboy2Audio * * \details * The speaker is initialized based on the current mute setting saved in - * system EEPROM. This function is called by `Arduboy2Base::begin()` so it - * isn't normally required to call it within a sketch. However, if - * `Arduboy2Core::boot()` is used instead of `Arduboy2Base::begin()` and the - * sketch includes sound, then this function should be called after `boot()`. - */ + * system EEPROM. + */ static void begin(); /** \brief diff --git a/board-package-source/libraries/Arduboy2/src/Arduboy2Beep.cpp b/board-package-source/libraries/Arduboy2/src/Arduboy2Beep.cpp index b1e86fd..10cdb01 100644 --- a/board-package-source/libraries/Arduboy2/src/Arduboy2Beep.cpp +++ b/board-package-source/libraries/Arduboy2/src/Arduboy2Beep.cpp @@ -45,7 +45,7 @@ void BeepPin1::noTone() } -// Speaker pin 2, Timer 4A, Port C bit 7, Arduino pin 13 +// Speaker pin 2, Timer 4A, Port C bit 7, Arduino pin 13 or Port D bit 7, Arduino pin 6 for alternate wiring uint8_t BeepPin2::duration = 0; @@ -53,6 +53,9 @@ void BeepPin2::begin() { TCCR4A = 0; // normal mode. Disable PWM TCCR4B = bit(CS43); // divide by 128 clock prescale + #ifdef AB_ALTERNATE_WIRING + TCCR4C = 0; // normal mode + #endif TCCR4D = 0; // normal mode TC4H = 0; // toggle pin at count = 0 OCR4A = 0; // " @@ -66,22 +69,30 @@ void BeepPin2::tone(uint16_t count) 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), + #ifdef AB_ALTERNATE_WIRING + TCCR4C = bit(COM4D0); // set toggle on compare mode (which connects pin 6) + #else + TCCR4A = bit(COM4A0); // set toggle on compare mode (which connects pin 13) + #endif + 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) + noTone(); } } void BeepPin2::noTone() { duration = 0; + #ifdef AB_ALTERNATE_WIRING + TCCR4C = 0; // set normal mode (which disconnects the pin) + #else TCCR4A = 0; // set normal mode (which disconnects the pin) + #endif } diff --git a/board-package-source/libraries/Arduboy2/src/Arduboy2Core.cpp b/board-package-source/libraries/Arduboy2/src/Arduboy2Core.cpp index 588337e..f26a724 100644 --- a/board-package-source/libraries/Arduboy2/src/Arduboy2Core.cpp +++ b/board-package-source/libraries/Arduboy2/src/Arduboy2Core.cpp @@ -8,13 +8,14 @@ #include +#ifndef OLED_CONTRAST +# define OLED_CONTRAST 0xCF +#endif //======================================== //========== class Arduboy2Core ========== //======================================== -Arduboy2Core::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 @@ -27,13 +28,13 @@ const PROGMEM uint8_t Arduboy2Core::lcdBootProgram[] = { 0x47, // set brightness 0x64, 0x00, // set x position 0 0x84, // address mode set: X increment -#elif defined(OLED_SH1106) +#elif defined(OLED_SH1106) || (OLED_SH1106_I2C) 0x8D, 0x14, // Charge Pump Setting v = enable (0x14) 0xA1, // Set Segment Re-map 0xC8, // Set COM Output Scan Direction - 0x81, 0xCF, // Set Contrast v = 0xCF + 0x81, OLED_CONTRAST, // Set Contrast v = 0xCF 0xD9, 0xF1, // Set Precharge = 0xF1 - OLED_SET_COLUMN_ADDRESS_LO, //Set column address for left most pixel + OLED_SET_COLUMN_ADDRESS_LO, //Set column address for left most pixel 0xAF // Display On #elif defined(LCD_ST7565) 0xC8, //SET_COM_REVERSE @@ -78,7 +79,7 @@ const PROGMEM uint8_t Arduboy2Core::lcdBootProgram[] = { 0xA8, 0x7F, //Set MUX ratio 128MUX //0xB2, 0x23, //0xB3, 0xF0, //set devider clock | oscillator frequency - 0x81, 0xCF, //Set contrast + 0x81, OLED_CONTRAST, //Set contrast //0xBC, 0x1F, //set precharge voltage //0x82, 0xFE, //set second Precharge speed 0xB1, 0x21, //reset and 1st precharge phase length phase 2:2 DCLKs, Phase 1: 1 DCLKs @@ -124,7 +125,7 @@ const PROGMEM uint8_t Arduboy2Core::lcdBootProgram[] = { // 0xDA, 0x12, // Set Contrast v = 0xCF - 0x81, 0xCF, + 0x81, OLED_CONTRAST, // Set Precharge = 0xF1 0xD9, 0xF1, @@ -224,11 +225,11 @@ void Arduboy2Core::bootPins() _BV(TX_LED_BIT) | //TX LED off for Arduboy and non Micro based Arduino #endif _BV(CART_BIT) | - #if !(defined(OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX)) + #if !(defined(OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX) || (OLED_SH1106_I2C)) _BV(DC_BIT) | #endif 0) & ~( // Port D INPUTs or LOW outputs - #if !(defined(OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX)) + #if !(defined(OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX) || (OLED_SH1106_I2C)) _BV(CS_BIT) | // oled display enabled _BV(RST_BIT) | // reset active #endif @@ -238,7 +239,7 @@ void Arduboy2Core::bootPins() #if defined(LCD_ST7565) _BV(POWER_LED_BIT) | #endif - #if defined(OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX) + #if defined(OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX) || (OLED_SH1106_I2C) _BV(I2C_SCL) | _BV(I2C_SDA) | #endif @@ -246,7 +247,7 @@ void Arduboy2Core::bootPins() // Port D outputs DDRD = ( - #if !(defined(OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX)) + #if !(defined(OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX) || (OLED_SH1106_I2C)) _BV(DC_BIT) | #endif #if !(defined(AB_ALTERNATE_WIRING) && (CART_CS_SDA)) @@ -262,7 +263,7 @@ void Arduboy2Core::bootPins() _BV(CART_BIT) | _BV(TX_LED_BIT) | 0) & ~(// Port D inputs - #if defined(OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX) + #if defined(OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX) || (OLED_SH1106_I2C) _BV(I2C_SCL) | // SDA and SCL as inputs without pullups _BV(I2C_SDA) | // (both externally pulled up) #endif @@ -349,7 +350,7 @@ void Arduboy2Core::bootOLED() displayWrite(pgm_read_byte(lcdBootProgram + i - 8)); } displayDisable(); -#elif defined(OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX) +#elif defined(OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX) || (OLED_SH1106_I2C) i2c_start(SSD1306_I2C_CMD); for (uint8_t i = 0; i < sizeof(lcdBootProgram); i++) i2c_sendByte(pgm_read_byte(lcdBootProgram + i)); @@ -418,7 +419,7 @@ void Arduboy2Core::SPItransfer(uint8_t data) while (!(SPSR & _BV(SPIF))) { } // wait } -#if defined(OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX) +#if defined(OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX) || (OLED_SH1106_I2C) void Arduboy2Core::i2c_start(uint8_t mode) { I2C_SDA_LOW(); // disable posible internal pullup, ensure SDA low on enabling output @@ -467,7 +468,7 @@ void Arduboy2Core::safeMode() { if (buttonsState() == UP_BUTTON) { - digitalWriteRGB(RED_LED, RGB_ON); + setRGBledRedOn(); #ifndef ARDUBOY_CORE // for Arduboy core timer 0 should remain enabled // prevent the bootloader magic number from being overwritten by timer 0 @@ -529,13 +530,13 @@ void Arduboy2Core::displayOff() displayWrite(0x20); displayWrite(0x00); displayDisable(); -#elif defined(OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX) +#elif defined(OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX) || (OLED_SH1106_I2C) i2c_start(SSD1306_I2C_CMD); i2c_sendByte(0xAE); // display off i2c_sendByte(0x8D); // charge pump: i2c_sendByte(0x10); // disable i2c_stop(); -#else +#else LCDCommandMode(); SPItransfer(0xAE); // display off SPItransfer(0x8D); // charge pump: @@ -554,7 +555,7 @@ void Arduboy2Core::displayOn() void Arduboy2Core::paint8Pixels(uint8_t pixels) { -#if defined(OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX) +#if defined(OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX) || (OLED_SH1106_I2C) i2c_start(SSD1306_I2C_DATA); i2c_sendByte(pixels); i2c_stop(); @@ -587,6 +588,19 @@ void Arduboy2Core::paintScreen(const uint8_t *image) for (int i = 0; i < (HEIGHT * WIDTH) / 8; i++) i2c_sendByte(pgm_read_byte(image+i)); i2c_stop(); +#elif defined (OLED_SH1106_I2C) + for (int page = 0; page < HEIGHT/8; page++) + { + i2c_start(SSD1306_I2C_CMD); + i2c_sendByte(OLED_SET_PAGE_ADDRESS + page); // set page + i2c_sendByte(OLED_SET_COLUMN_ADDRESS_HI); // only reset hi nibble to zero + i2c_stop(); + const uint8_t *line = image + page*WIDTH; + i2c_start(SSD1306_I2C_DATA); + for (int i = 0; i < WIDTH; i++) + i2c_sendByte(pgm_read_byte(line+i)); + i2c_stop(); + } #elif defined(OLED_SH1106) || defined(LCD_ST7565) for (uint8_t i = 0; i < HEIGHT / 8; i++) { @@ -807,7 +821,28 @@ void Arduboy2Core::paintScreen(uint8_t image[], bool clear) ); #endif i2c_stop(); - +#elif defined (OLED_SH1106_I2C) + for (int page = 0; page < HEIGHT/8; page++) + { + i2c_start(SSD1306_I2C_CMD); + i2c_sendByte(OLED_SET_PAGE_ADDRESS + page); // set page + i2c_sendByte(OLED_SET_COLUMN_ADDRESS_HI); + i2c_stop(); + i2c_start(SSD1306_I2C_DATA); + if (clear) + { + for (int i = 0; i < WIDTH; i++) + { + i2c_sendByte(*image); + *(image++) = 0; + } + } else + { + for (int i = 0; i < WIDTH; i++) + i2c_sendByte(*(image++)); + } + i2c_stop(); + } #elif defined(OLED_SH1106) || defined(LCD_ST7565) //Assembly optimized page mode display code with clear support. //Each byte transfer takes 18 cycles @@ -1025,7 +1060,19 @@ void Arduboy2Core::blank() for (int i = 0; i < (HEIGHT * WIDTH) / 8; i++) i2c_sendByte(0); i2c_stop(); -#else +#elif defined (OLED_SH1106_I2C) + for (int page = 0; page < HEIGHT/8; page++) + { + i2c_start(SSD1306_I2C_CMD); + i2c_sendByte(OLED_SET_PAGE_ADDRESS + page); // set page + i2c_sendByte(OLED_SET_COLUMN_ADDRESS_HI); // only reset hi nibble to zero + i2c_stop(); + i2c_start(SSD1306_I2C_DATA); + for (int i = 0; i < WIDTH; i++) + i2c_sendByte(0); + i2c_stop(); + } +#else #if defined (OLED_SH1106) for (int i = 0; i < (HEIGHT * 132) / 8; i++) #elif defined(OLED_96X96) || defined(OLED_128X96) || defined(OLED_128X128)|| defined(OLED_128X64_ON_96X96) || defined(OLED_128X64_ON_128X96) || defined(OLED_128X64_ON_128X128)|| defined(OLED_128X96_ON_128X128) || defined(OLED_96X96_ON_128X128) || defined(OLED_64X128_ON_128X128) @@ -1039,7 +1086,7 @@ void Arduboy2Core::blank() void Arduboy2Core::sendLCDCommand(uint8_t command) { -#if defined(OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX) +#if defined(OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX) || (OLED_SH1106_I2C) i2c_start(SSD1306_I2C_CMD); i2c_sendByte(command); i2c_stop(); @@ -1109,6 +1156,60 @@ void Arduboy2Core::flipHorizontal(bool flipped) /* RGB LED */ +void Arduboy2Core::setRGBledRedOn() +{ + #ifndef LCD_ST7565 + bitClear(RED_LED_PORT, RED_LED_BIT); // Red on + #else + bitSet(RED_LED_PORT, RED_LED_BIT); // Red on + #endif +} + +void Arduboy2Core::setRGBledRedOff() +{ + #ifndef LCD_ST7565 + bitSet(RED_LED_PORT, RED_LED_BIT); // Red off + #else + bitClear(RED_LED_PORT, RED_LED_BIT); // Red off + #endif +} + +void Arduboy2Core::setRGBledGreenOn() +{ + #ifndef LCD_ST7565 + bitClear(GREEN_LED_PORT, GREEN_LED_BIT); // Green on + #else + bitSet(GREEN_LED_PORT, GREEN_LED_BIT); // Green on + #endif +} + +void Arduboy2Core::setRGBledGreenOff() +{ + #ifndef LCD_ST7565 + bitSet(GREEN_LED_PORT, GREEN_LED_BIT); // Green off + #else + bitClear(GREEN_LED_PORT, GREEN_LED_BIT); // Green off + #endif +} + +void Arduboy2Core::setRGBledBlueOn() +{ + #ifndef LCD_ST7565 + bitClear(BLUE_LED_PORT, BLUE_LED_BIT); // Blue on + #else + bitSet(BLUE_LED_PORT, BLUE_LED_BIT); // Blue on + #endif +} + +void Arduboy2Core::setRGBledBlueOff() +{ + #ifndef LCD_ST7565 + bitSet(BLUE_LED_PORT, BLUE_LED_BIT); // Blue off + #else + bitClear(BLUE_LED_PORT, BLUE_LED_BIT); // Blue off + #endif +} + void Arduboy2Core::setRGBled(uint8_t red, uint8_t green, uint8_t blue) { #ifdef LCD_ST7565 @@ -1120,93 +1221,35 @@ void Arduboy2Core::setRGBled(uint8_t red, uint8_t green, uint8_t blue) } #endif #ifdef ARDUBOY_10 // RGB, all the pretty colors - uint8_t pwmstate = TCCR0A; + // 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. #ifndef AB_ALTERNATE_WIRING - pwmstate &= ~_BV(COM0A1); //default to digital pin for min and max values - #else - pwmstate &= ~_BV(COM0B1); + TCCR0A = _BV(COM0A1) | _BV(WGM01) | _BV(WGM00); + #ifndef LCD_ST7565 + OCR0A = 255 - green; + #else + OCR0A = green; + #endif + #else + TCCR0A = _BV(COM0B1) | _BV(WGM01) | _BV(WGM00); + #ifndef LCD_ST7565 + OCR0B = 255 - green; + #else + OCR0B = green; + #endif + #endif + // 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); + #ifndef LCD_ST7565 + OCR1AL = blue; + OCR1BL = red; + #else + OCR1AL = 255 - blue; + OCR1BL = 255 - red; #endif - if (green == 0) - #if defined(LCD_ST7565) - bitClear(GREEN_LED_PORT, GREEN_LED_BIT); - #else - bitSet(GREEN_LED_PORT, GREEN_LED_BIT); - #endif - else if (green == 255) - #if defined(LCD_ST7565) - bitSet(GREEN_LED_PORT, GREEN_LED_BIT); - #else - bitClear(GREEN_LED_PORT, GREEN_LED_BIT); - #endif - else - { - #ifndef AB_ALTERNATE_WIRING - pwmstate |= _BV(COM0A1); //configure pin as pwm pin - #if defined(LCD_ST7565) - OCR0A = green; //set pwm duty - #else - OCR0A = 255 - green; //set pwm duty - #endif - #else - pwmstate |= _BV(COM0B1); - OCR0B = 255 - green; - #endif - } - TCCR0A = pwmstate; - pwmstate = TCCR1A & ~(_BV(COM1B1) | _BV(COM1A1)); //default to digital pins for min and max values - if (red == 0) - { - #if defined(LCD_ST7565) - bitClear(RED_LED_PORT, RED_LED_BIT); - #else - bitSet(RED_LED_PORT, RED_LED_BIT); - #endif - } - else if (red == 255) - { - #if defined(LCD_ST7565) - bitSet(RED_LED_PORT, RED_LED_BIT); - #else - bitClear(RED_LED_PORT, RED_LED_BIT); - #endif - } - else - { - pwmstate |= _BV(COM1B1); //configure pin as pwm pin - OCR1BH = 0; - #if defined(LCD_ST7565) - OCR1BL = red; //set pwm duty - #else - OCR1BL = 255 - red; //set pwm duty - #endif - } - if (blue == 0) - { - #if defined(LCD_ST7565) - bitClear(BLUE_LED_PORT, BLUE_LED_BIT); - #else - bitSet(BLUE_LED_PORT, BLUE_LED_BIT); - #endif - } - else if (blue == 255) - { - #if defined(LCD_ST7565) - bitSet(BLUE_LED_PORT, BLUE_LED_BIT); - #else - bitClear(BLUE_LED_PORT, BLUE_LED_BIT); - #endif - } - else - { - pwmstate |= _BV(COM1A1); //configure pin as pwm pin - OCR1AH = 0; - #if defined(LCD_ST7565) - OCR1AL = blue; //set pwm duty - #else - OCR1AL = 255 - blue; //set pwm duty - #endif - } - TCCR1A = pwmstate; #elif defined(AB_DEVKIT) // only blue on DevKit, which is not PWM capable (void)red; // parameter unused @@ -1324,7 +1367,11 @@ uint8_t Arduboy2Core::buttonsState() // up, right, left, down buttons = ((~PINF) & (_BV(UP_BUTTON_BIT) | _BV(RIGHT_BUTTON_BIT) | - _BV(LEFT_BUTTON_BIT) | _BV(DOWN_BUTTON_BIT))); + _BV(LEFT_BUTTON_BIT) | _BV(DOWN_BUTTON_BIT) | + #ifdef SUPPORT_XY_BUTTONS + _BV(X_BUTTON_BIT) | _BV(Y_BUTTON_BIT) | + #endif + 0)); // A if (bitRead(A_BUTTON_PORTIN, A_BUTTON_BIT) == 0) { buttons |= A_BUTTON; } // B @@ -1421,6 +1468,7 @@ void Arduboy2NoUSB::mainNoUSB() // This would normally be done in the USB code that uses the TX and RX LEDs //TX_RX_LED_INIT; // configured by bootpins + #ifndef ARDUBOY_CORE // (Arduboy core supports UP + DOWN to enter bootloader) // Set the DOWN button pin for INPUT_PULLUP bitSet(DOWN_BUTTON_PORT, DOWN_BUTTON_BIT); bitClear(DOWN_BUTTON_DDR, DOWN_BUTTON_BIT); @@ -1432,7 +1480,7 @@ void Arduboy2NoUSB::mainNoUSB() if (bitRead(DOWN_BUTTON_PORTIN, DOWN_BUTTON_BIT) == 0) { Arduboy2Core::exitToBootloader(); } - + #endif // The remainder is a copy of the Arduino main() function with the // USB code and other unneeded code commented out. // init() was called above. diff --git a/board-package-source/libraries/Arduboy2/src/Arduboy2Core.h b/board-package-source/libraries/Arduboy2/src/Arduboy2Core.h index 217662a..370d5df 100644 --- a/board-package-source/libraries/Arduboy2/src/Arduboy2Core.h +++ b/board-package-source/libraries/Arduboy2/src/Arduboy2Core.h @@ -11,7 +11,6 @@ #include #include -extern volatile unsigned char bootloader_timer; // main hardware compile flags @@ -78,7 +77,7 @@ extern volatile unsigned char bootloader_timer; #define SPI_SCK_PORT PORTB #define SPI_SCK_BIT PORTB1 -#if defined (OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX) +#if defined (OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX) || (OLED_SH1106_I2C) #define I2C_PORT PORTD #define I2C_DDR DDRD #define I2C_PIN PIND @@ -147,6 +146,10 @@ extern volatile unsigned char bootloader_timer; #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 */ +#ifdef SUPPORT_XY_BUTTONS + #define X_BUTTON _BV(1) + #define Y_BUTTON _BV(0) +#endif #define PIN_LEFT_BUTTON A2 #define LEFT_BUTTON_PORT PORTF @@ -184,6 +187,20 @@ extern volatile unsigned char bootloader_timer; #define B_BUTTON_DDR DDRB #define B_BUTTON_BIT PORTB4 +#ifdef SUPPORT_XY_BUTTONS + #define PIN_X_BUTTON A4 + #define X_BUTTON_PORT PORTF + #define X_BUTTON_PORTIN PINF + #define X_BUTTON_DDR DDRF + #define X_BUTTON_BIT PORTF1 + + #define PIN_Y_BUTTON A5 + #define Y_BUTTON_PORT PORTF + #define Y_BUTTON_PORTIN PINF + #define Y_BUTTON_DDR DDRF + #define Y_BUTTON_BIT PORTF0 +#endif + #define PIN_SPEAKER_1 5 /**< The pin number of the first lead of the speaker */ #define SPEAKER_1_PORT PORTC @@ -330,12 +347,13 @@ extern volatile unsigned char bootloader_timer; #define OLED_HORIZ_NORMAL 0xA1 // normal segment re-map #define OLED_SET_PAGE_ADDRESS 0xB0 -#ifdef OLED_SH1106 +#if defined(OLED_SH1106) || defined(OLED_SH1106_I2C) #define OLED_SET_COLUMN_ADDRESS_LO 0x02 //SH1106 only: 1st pixel starts on column 2 #else #define OLED_SET_COLUMN_ADDRESS_LO 0x00 #endif #define OLED_SET_COLUMN_ADDRESS_HI 0x10 + // ----- #if defined (OLED_96X96) || (OLED_96X96_ON_128X128) #define WIDTH 96 @@ -445,7 +463,6 @@ class Arduboy2Core : public Arduboy2NoUSB friend class Arduboy2Ex; public: - Arduboy2Core(); /** \brief * Idle the CPU to save power. @@ -473,7 +490,7 @@ class Arduboy2Core : public Arduboy2NoUSB * * \see LCDCommandMode() SPItransfer() */ - void static inline LCDDataMode() __attribute__((always_inline)) + static void inline LCDDataMode() __attribute__((always_inline)) { #if defined(GU12864_800B) bitClear(DC_PORT, DC_BIT); @@ -503,7 +520,7 @@ class Arduboy2Core : public Arduboy2NoUSB * * \see LCDDataMode() sendLCDCommand() SPItransfer() */ - void static inline LCDCommandMode() __attribute__((always_inline)) + static void inline LCDCommandMode() __attribute__((always_inline)) { #ifdef GU12864_800B bitSet(DC_PORT, DC_BIT); @@ -522,7 +539,7 @@ class Arduboy2Core : public Arduboy2NoUSB * or as data to be placed on the screen, depending on the command/data * mode. * - * \see LCDDataMode() LCDCommandMode() sendLCDCommand() + * \see LCDDataMode() LCDCommandMode() sendLCDCommand() SPItransferAndRead() */ static void SPItransfer(uint8_t data); @@ -548,17 +565,17 @@ class Arduboy2Core : public Arduboy2NoUSB */ static uint8_t SPItransferAndRead(uint8_t data); -#if defined (OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX) - void static i2c_start(uint8_t mode); +#if defined (OLED_SSD1306_I2C) || (OLED_SSD1306_I2CX) || (OLED_SH1106_I2C) + static void i2c_start(uint8_t mode); - void static inline i2c_stop() __attribute__((always_inline)) + static void inline i2c_stop() __attribute__((always_inline)) { // SDA and SCL both are already low, from writing ACK bit no need to change state I2C_SDA_AS_INPUT(); // switch to input so SDA is pulled up externally first for stop condition I2C_SCL_AS_INPUT(); // pull up SCL externally } - void static i2c_sendByte(uint8_t byte); + static void i2c_sendByte(uint8_t byte); #endif //#endif @@ -794,6 +811,13 @@ class Arduboy2Core : public Arduboy2NoUSB */ static void sendLCDCommand(uint8_t command); + static void setRGBledRedOn(); + static void setRGBledRedOff(); + static void setRGBledGreenOn(); + static void setRGBledGreenOff(); + static void setRGBledBlueOn(); + static void setRGBledBlueOff(); + /** \brief * Set the light output of the RGB LED. * @@ -932,14 +956,21 @@ class Arduboy2Core : public Arduboy2NoUSB * \details * This function initializes the display, buttons, etc. * - * This function is called by begin() so isn't normally called within a + * This function is called by `begin()` so isn't normally called within a * sketch. However, in order to free up some code space, by eliminating * some of the start up features, it can be called in place of begin(). - * The functions that begin() would call after boot() can then be called - * to add back in some of the start up features, if desired. - * See the README file or documentation on the main page for more details. + * 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 Arduboy2Base::begin() + * 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(); @@ -953,8 +984,8 @@ class Arduboy2Core : public Arduboy2NoUSB * 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 - * potentially could cause the problem. + * 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 @@ -995,11 +1026,11 @@ class Arduboy2Core : public Arduboy2NoUSB * of Arduino `delay()` will save a few bytes of code. */ #ifndef ARDUBOY_CORE - void static delayShort(uint16_t ms) __attribute__ ((noinline)); + static void delayShort(uint16_t ms) __attribute__ ((noinline)); #else - void static delayShort(uint16_t ms); + static void delayShort(uint16_t ms); #endif - void static delayByte(uint8_t ms) __attribute__ ((noinline)); + static void delayByte(uint8_t ms) __attribute__ ((noinline)); /** \brief * Exit the sketch and start the bootloader @@ -1029,9 +1060,9 @@ class Arduboy2Core : public Arduboy2NoUSB static const PROGMEM uint8_t lcdBootProgram[]; #if defined(GU12864_800B) - void static displayWrite(uint8_t d); - void static displayEnable(); - void static displayDisable(); + static void displayWrite(uint8_t d); + static void displayEnable(); + static void displayDisable(); #endif }; diff --git a/board-package-source/libraries/Arduboy2/src/Arduboy2Data.cpp b/board-package-source/libraries/Arduboy2/src/Arduboy2Data.cpp index c264eab..ec13aff 100644 --- a/board-package-source/libraries/Arduboy2/src/Arduboy2Data.cpp +++ b/board-package-source/libraries/Arduboy2/src/Arduboy2Data.cpp @@ -9,7 +9,7 @@ // arduboy_logo.png // drawBitmap() format -// 88x16 +// 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, @@ -33,7 +33,7 @@ const PROGMEM uint8_t Arduboy2Base::arduboy_logo[] = { // arduboy_logo.png // drawCompressed() format -// 88x16 +// 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, @@ -55,7 +55,7 @@ const PROGMEM uint8_t Arduboy2Base::arduboy_logo_compressed[] = { // arduboy_logo.png // Sprites::drawSelfMasked() format -// 88x16 +// 88x16 px (178 bytes) const PROGMEM uint8_t Arduboy2Base::arduboy_logo_sprite[] = { 88, 16, 0xF0, 0xF8, 0x9C, 0x8E, 0x87, 0x83, 0x87, 0x8E, 0x9C, 0xF8, diff --git a/board-package-source/libraries/Arduboy2/src/ab_logo.c b/board-package-source/libraries/Arduboy2/src/ab_logo.c deleted file mode 100644 index e3f6022..0000000 --- a/board-package-source/libraries/Arduboy2/src/ab_logo.c +++ /dev/null @@ -1,83 +0,0 @@ -/** - * @file ab_logo.c - * \brief - * The ARDUBOY logo bitmap. - */ - -#include - -#ifndef ARDUBOY_LOGO_CREATED -#define ARDUBOY_LOGO_CREATED - -// arduboy_logo.png -// drawBitmap() format -// 88x16 -const uint8_t arduboy_logo[] PROGMEM = { -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 -const uint8_t arduboy_logo_compressed[] PROGMEM = { -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 -const uint8_t arduboy_logo_sprite[] PROGMEM = { -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 -}; - -#endif diff --git a/board-package-source/libraries/Arduboy2/src/glcdfont.c b/board-package-source/libraries/Arduboy2/src/glcdfont.c deleted file mode 100644 index 2164571..0000000 --- a/board-package-source/libraries/Arduboy2/src/glcdfont.c +++ /dev/null @@ -1,274 +0,0 @@ -/** - * @file glcdfont.c - * \brief - * The font definitions used to display text characters. - */ - -#include -#include - -#ifndef FONT5X7_H -#define FONT5X7_H - -// standard ascii 5x7 font -static const 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 diff --git a/board-package-source/libraries/ArduboyFX/src/ArduboyFX.cpp b/board-package-source/libraries/ArduboyFX/src/ArduboyFX.cpp index 2233a68..a1a755f 100644 --- a/board-package-source/libraries/ArduboyFX/src/ArduboyFX.cpp +++ b/board-package-source/libraries/ArduboyFX/src/ArduboyFX.cpp @@ -669,7 +669,7 @@ void FX::readDataArray(uint24_t address, uint8_t index, uint8_t offset, uint8_t } -uint16_t FX::readIndexedUInt8(uint24_t address, uint8_t index) +uint8_t FX::readIndexedUInt8(uint24_t address, uint8_t index) { seekDataArray(address, index, 0, sizeof(uint8_t)); return readEnd();