From 29dd60bb1c497a7a2ab5ecda36baae1eb9f94ae3 Mon Sep 17 00:00:00 2001 From: "Mr.Blinky" Date: Sat, 7 Jan 2023 02:07:49 +0100 Subject: [PATCH] updatate source with Arduboy FX library to v1.0.5 --- .../drawframes/assets/arduboy-logo.png | Bin 0 -> 413 bytes .../examples/drawframes/assets/fx-logo.png | Bin 0 -> 260 bytes .../examples/drawframes/drawframes.ino | 142 +++++++++++ .../drawframes/fxdata/ArduboyLogo_Frame.txt | 83 +++++++ .../examples/drawframes/fxdata/fxdata.bin | Bin 0 -> 674 bytes .../examples/drawframes/fxdata/fxdata.h | 21 ++ .../examples/drawframes/fxdata/fxdata.txt | 95 ++++++++ .../libraries/ArduboyFX/library.properties | 2 +- .../libraries/ArduboyFX/src/ArduboyFX.cpp | 225 ++++++++++++++++-- .../libraries/ArduboyFX/src/ArduboyFX.h | 42 +++- 10 files changed, 579 insertions(+), 31 deletions(-) create mode 100644 board-package-source/libraries/ArduboyFX/examples/drawframes/assets/arduboy-logo.png create mode 100644 board-package-source/libraries/ArduboyFX/examples/drawframes/assets/fx-logo.png create mode 100644 board-package-source/libraries/ArduboyFX/examples/drawframes/drawframes.ino create mode 100644 board-package-source/libraries/ArduboyFX/examples/drawframes/fxdata/ArduboyLogo_Frame.txt create mode 100644 board-package-source/libraries/ArduboyFX/examples/drawframes/fxdata/fxdata.bin create mode 100644 board-package-source/libraries/ArduboyFX/examples/drawframes/fxdata/fxdata.h create mode 100644 board-package-source/libraries/ArduboyFX/examples/drawframes/fxdata/fxdata.txt diff --git a/board-package-source/libraries/ArduboyFX/examples/drawframes/assets/arduboy-logo.png b/board-package-source/libraries/ArduboyFX/examples/drawframes/assets/arduboy-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..bba8288d913ebae2d5a95de32567f502e124cef6 GIT binary patch literal 413 zcmV;O0b>4%P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGqB>(^xB>_oNB=7(L0WwKMK~z{r-IWUx zgCGnMn5n~8pKgPwre=cK8;XF8x(R8&MnO{-|&hgYH z(WIsucnF%#qw!Fihu2@CDdF5;HplNo zjk!nHV<9DId2;I)T5H=zn6pm_9*qYpj}~jG?K&bxn6HSZ3oUYfc<=U-dpg$BS_|sY zmvh`+a@zPutabEyDtVK0IfisFCVD!#KMU{O&R}iSFrrgD@EWj|-VK1>_&d?m!SYz( z5IE5ajND|6AxFfDn=8z&t!aZ(u{Z=zcUT%NwsIb!YX^Hb8Rw#h<)>*ZX5~TRVQ@NF zVo4%%_?pQTh4(Z{{212E%EO43=S@3 // required to build for Arduboy +#include // required to access the FX external flash +#include "fxdata/fxdata.h" // this file contains all references to FX data + +Arduboy2 arduboy; + +enum class State : uint8_t { + init, + logo, + wait, + main, +}; + +State state; +uint8_t timer; + +void setup() { + arduboy.boot(); // boot is used instead of begin as we don't want the Arduboy startup logo + arduboy.display(CLEAR_BUFFER); // another way to clear the display + arduboy.systemButtons(); // also do system buttons as it's normally used by begin + //arduboy.setFrameRate(60); // Only needed for frameRates other than 60 + FX::begin(FX_DATA_PAGE); // initialise FX chip + state = State::init; +} + +void loop() { + if (!arduboy.nextFrame()) return; // Do nothing until it's time for the next display frame + arduboy.pollButtons(); // required here for arduboy.justPressed() below + + switch (state) { + + //initialise animation using setFrame + case State::init: + { + FX::setFrame(ArduboyLogo_Frame, 0); // set frame list for drawFrame() and 0 repeats + state = State::logo; // changing the 0 into an higher value will + } // slow down the animation + break; + + // do logo animation + case State::logo: + { // draw a frame from the frame list and test if it was the last frame + if(!FX::drawFrame()) { // without this test the animation would loop continiously + state = State::wait; // it was the last frame go for wait state + timer = 60; // wait for 60 frames + } + } + break; + + //wait and display a single frame + case State::wait: + { + FX::drawFrame(ArduboyLogo_LastFrame); + if (--timer == 0) state = State::main; + } + break; + + case State::main: + { + // No special code here so the screen will turn black after the wait period + + // pressing A or B button will restart the animation + if (arduboy.justPressed(A_BUTTON | B_BUTTON)) state = State::init; + } + break; + } + + FX::display(CLEAR_BUFFER); // Using CLEAR_BUFFER will clear the display buffer after it is displayed +} diff --git a/board-package-source/libraries/ArduboyFX/examples/drawframes/fxdata/ArduboyLogo_Frame.txt b/board-package-source/libraries/ArduboyFX/examples/drawframes/fxdata/ArduboyLogo_Frame.txt new file mode 100644 index 0000000..5d6f3dd --- /dev/null +++ b/board-package-source/libraries/ArduboyFX/examples/drawframes/fxdata/ArduboyLogo_Frame.txt @@ -0,0 +1,83 @@ + ArduboyLogo_Frame[] = { + + int16_t 20, -15, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, -14, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, -13, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, -12, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, -11, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, -10, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, -9, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, -8, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, -7, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, -6, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, -5, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, -4, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, -3, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, -2, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, -1, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, 0, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, 1, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, 2, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, 3, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, 4, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, 5, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, 6, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, 7, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, 8, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, 9, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, 10, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, 11, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, 12, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, 13, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, 14, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, 15, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, 16, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, 17, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, 18, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, 19, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, 20, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, 21, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, 22, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, 23, int24_t ArduboyLogo, int8_t 0, dbmNormal_end + + int16_t 20, 24, int24_t ArduboyLogo, int8_t 0, dbmNormal_last + + } diff --git a/board-package-source/libraries/ArduboyFX/examples/drawframes/fxdata/fxdata.bin b/board-package-source/libraries/ArduboyFX/examples/drawframes/fxdata/fxdata.bin new file mode 100644 index 0000000000000000000000000000000000000000..e8120758423b052bd99d96f9af0d66adb084bfeb GIT binary patch literal 674 zcmZ9}%}&BV5C`z7MHaOdRQxy)_7yyGFx1EJ0ek>X!hxhD9Jmo5fXDFQ!9%&|&1Yyr z;?Y!5th(;F)8@~CnWXvcw6nXJ(iJtbd^VkoC(~J;5n1*nRA};z1v8Z)usoJ{dL4F% zaucd`PZX!gXq2RJ#O#$J4a|XyR=2;H6UCfJq`gQJ>8O{k7ctKz7X5B(!`@Dkg?DKa0na$#jWL= VV^mInQ{YT6qJRnzT?_8$_8+S#qf7t* literal 0 HcmV?d00001 diff --git a/board-package-source/libraries/ArduboyFX/examples/drawframes/fxdata/fxdata.h b/board-package-source/libraries/ArduboyFX/examples/drawframes/fxdata/fxdata.h new file mode 100644 index 0000000..2b6f7fb --- /dev/null +++ b/board-package-source/libraries/ArduboyFX/examples/drawframes/fxdata/fxdata.h @@ -0,0 +1,21 @@ +#pragma once + +/**** FX data header generated by fxdata-build.py tool version 1.12 ****/ + +using uint24_t = __uint24; + +// Initialize FX hardware using FX::begin(FX_DATA_PAGE); in the setup() function. + +constexpr uint16_t FX_DATA_PAGE = 0xfffd; +constexpr uint24_t FX_DATA_BYTES = 674; + +constexpr uint24_t ArduboyLogo = 0x000000; +constexpr uint16_t ArduboyLogoWidth = 88; +constexpr uint16_t ArduboyLogoHeight = 16; + +constexpr uint24_t FXLogo = 0x0000B4; +constexpr uint16_t FXLogoWidth = 28; +constexpr uint16_t FXLogoHeight = 16; + +constexpr uint24_t ArduboyLogo_Frame = 0x000128; +constexpr uint24_t ArduboyLogo_LastFrame = 0x000290; diff --git a/board-package-source/libraries/ArduboyFX/examples/drawframes/fxdata/fxdata.txt b/board-package-source/libraries/ArduboyFX/examples/drawframes/fxdata/fxdata.txt new file mode 100644 index 0000000..cfcebef --- /dev/null +++ b/board-package-source/libraries/ArduboyFX/examples/drawframes/fxdata/fxdata.txt @@ -0,0 +1,95 @@ +/******************************************************************************* + FX Data resource file. +******************************************************************************** + + Run this file through the fx-data.py Python script (drag and drop) to create + a c-style header file that can be included with your project. + + a .bin file will also be created containing the actual resource data. This .bin + file can be uploaded to the FX flash chip using the Arduino plugin or using the + fxdata-upload.py or uploader-gui.py (Use Upload Development data button). + + Note fxdata.txt file maybe split up into multiple parts and can be included + using the include directive. + + Data types: + + int8_t, uint8_t values will be stored as 8-bit bytes (unsigned char) + + int16_t, uint16_t values will be stored as 16-bit (half)words (int) + + int24_t,uint24_t values will be stored as 24-bit address that points to + a FX data resource + + int32_t,uint32_t values will be stored as 32-bit long words + + image_t a filename with a relative path to a .bmp or .png image file + raw_t a filename with a relative path to a raw file + + to create a constant to point to a FX resource, a similar format as in C(++): + is used. + + image_t FXlogo = "fx-logo.png"; + image_t arduboyLogo = "FXSprite.png"; + + when data of the same format is used the data type may be ommited. The semicolon + may also be ommited in all cases. + + image_t FXlogo = "FX-logo.png" + FxSprite = "FXSprite.png" + + or even: + + image_t FXlogo = "FX-logo.png", FxSprite = "FXSprite.png" + + When specifying multiple data make sure they are seperated by at least a space + (comma is optional). A data array can be simplified. For examle: + + uint8_t tilemap[] = { + 0, 1, 2, 3, 4, 5, 6 + }; + + can also be written simply as: + + uint8_t tilemap = 0 1 2 3 4 5 6 + + data can be commented out using // for a single line or + using /* */ for a block comment + + Symbols + + For the drawFrames functions there are some predefined bitmap mode symbols: + + dbmNormal + dbmOverwrite + dbmWhite + dbmReverse + dbmBlack + dbmInvert + dbmMasked + + to mark the end of a frame _end is appended to the above symbols like + + dbmNormal_end + + to mark the end of the last frame in a frames list append _last to the above + symbols like + + dbmNormal_last + +******************************************************************************** + drawFrame example : +*******************************************************************************/ + +// Arduboy FX logo image: + +image_t ArduboyLogo = "../assets/arduboy-logo.png" +image_t FXLogo = "../assets/fx-logo.png" + +include "ArduboyLogo_Frame.txt" + + ArduboyLogo_LastFrame[] = { // create a reference to last frame + + int16_t 12, 24, int24_t ArduboyLogo, int8_t 0, dbmNormal + int16_t 100, 24, int24_t FXLogo, int8_t 0, dbmMasked_last + } \ No newline at end of file diff --git a/board-package-source/libraries/ArduboyFX/library.properties b/board-package-source/libraries/ArduboyFX/library.properties index 3912467..abf0a9a 100644 --- a/board-package-source/libraries/ArduboyFX/library.properties +++ b/board-package-source/libraries/ArduboyFX/library.properties @@ -1,5 +1,5 @@ name=ArduboyFX -version=1.0.4 +version=1.0.5 author=Mr.Blinky maintainer=mstr.blinky@gmail.com sentence=The Arduboy FX library. diff --git a/board-package-source/libraries/ArduboyFX/src/ArduboyFX.cpp b/board-package-source/libraries/ArduboyFX/src/ArduboyFX.cpp index fbd9a9e..fc6eee1 100644 --- a/board-package-source/libraries/ArduboyFX/src/ArduboyFX.cpp +++ b/board-package-source/libraries/ArduboyFX/src/ArduboyFX.cpp @@ -6,6 +6,8 @@ uint16_t FX::programSavePage; // program read and write data location in flash m Font FX::font; Cursor FX::cursor = {0,0,0,WIDTH}; +FrameControl FX::frameControl; + uint8_t FX::writeByte(uint8_t data) { @@ -124,10 +126,27 @@ void FX::writeEnable() void FX::seekCommand(uint8_t command, uint24_t address) { enable(); + #ifdef ARDUINO_ARCH_AVR + register uint8_t cmd asm("r24") = command; //assembly optimizer for AVR platform ~saves 12 bytes + asm volatile( + "call %x2 \n" + "mov r24, %C[addr] \n" + "call %x2 \n" + "mov r24, %B[addr] \n" + "call %x2 \n" + "mov r24, %A[addr] \n" + "call %x2 \n" + : [cmd] "+&r" (cmd) + : [addr] "r" (address), + [write] "i" (writeByte) + : + ); + #else writeByte(command); writeByte(address >> 16); writeByte(address >> 8); writeByte(address); + #endif } @@ -158,22 +177,22 @@ void FX::seekDataArray(uint24_t address, uint8_t index, uint8_t offset, uint8_t " mul %[index], %[size] \n" " brne .+2 \n" //treat size 0 as size 256 " mov r1, %[index] \n" - " clr r24 \n" //use as alternative zero reg + " clr r21 \n" //use as alternative zero reg " add r0, %[offset] \n" - " adc r1, r24 \n" + " adc r1, r21 \n" " add %A[address], r0 \n" " adc %B[address], r1 \n" - " adc %C[address], r24 \n" + " adc %C[address], r21 \n" " clr r1 \n" - : [address] "+r" (address) + : [address] "+&r" (address) : [index] "r" (index), [offset] "r" (offset), [size] "r" (elementSize) - : "r24" + : "r21" ); - #else - address += size ? index * size + offset : index * 256 + offset; - #endif + #else + address += size ? index * size + offset : index * 256 + offset; + #endif seekData(address); } @@ -212,9 +231,6 @@ uint8_t FX::readPendingUInt8() uint8_t FX::readPendingLastUInt8() { - #ifdef ARDUINO_ARCH_AVR - asm volatile("ArduboyFX_cpp_readPendingLastUInt8:\n"); // create label for calls in FX::readPendingUInt16 - #endif return readEnd(); } @@ -227,7 +243,7 @@ uint16_t FX::readPendingUInt16() ( "ArduboyFX_cpp_readPendingUInt16: \n" "call ArduboyFX_cpp_readPendingUInt8 \n" "mov %B[val], r24 \n" - "call ArduboyFX_cpp_readPendingUInt8 \n" + "jmp ArduboyFX_cpp_readPendingUInt8 \n" : [val] "=&r" (result) : "" (readPendingUInt8) : @@ -245,17 +261,17 @@ uint16_t FX::readPendingLastUInt16() uint16_t result asm("r24"); // we want result to be assigned to r24,r25 asm volatile ( "ArduboyFX_cpp_readPendingLastUInt16: \n" - "call ArduboyFX_cpp_readPendingUInt8 \n" - "mov %B[val], r24 \n" - "call ArduboyFX_cpp_readPendingLastUInt8 \n" + "call %x1 \n" + "mov %B[val], r24 \n" + "jmp %x2 \n" : [val] "=&r" (result) : "" (readPendingUInt8), - "" (readPendingLastUInt8) + "" (readEnd) : ); return result; #else //C++ implementation for non AVR platforms - return ((uint16_t)readPendingUint8() << 8) | (uint16_t)readPendingLastUInt8(); + return ((uint16_t)readPendingUint8() << 8) | (uint16_t)readEnd(); #endif } @@ -289,19 +305,19 @@ uint24_t FX::readPendingLastUInt24() uint24_t result asm("r24"); // we want result to be assigned to r24,r25,r26 asm volatile ( - "call ArduboyFX_cpp_readPendingUInt16 \n" - "mov %B[val], r24 \n" - "call ArduboyFX_cpp_readPendingLastUInt8 \n" - "mov %A[val], r24 \n" - "mov %C[val], r25 \n" + "call %x1 \n" + "mov %B[val], r24 \n" + "call %x2 \n" + "mov %A[val], r24 \n" + "mov %C[val], r25 \n" : [val] "=&r" (result) : "" (readPendingUInt16), - "" (readPendingLastUInt8) + "" (readEnd) : ); return result; #else //C++ implementation for non AVR platforms - return ((uint24_t)readPendingUInt16() << 8) | readPendingLastUInt8(); + return ((uint24_t)readPendingUInt16() << 8) | readEnd(); #endif } @@ -678,6 +694,167 @@ void FX::drawBitmap(int16_t x, int16_t y, uint24_t address, uint8_t frame, uint8 #endif } +void FX::setFrame(uint24_t frame, uint8_t repeat) //~22 bytes +{ + #ifdef ARDUINO_ARCH_AVR + FrameControl* ctrl = &frameControl; + asm volatile( + "ldi r30, lo8(%[ctrl]) \n" + "ldi r31, hi8(%[ctrl]) \n" + "st z, %A[frame] \n" // start + "std z+1, %B[frame] \n" + "std z+2, %C[frame] \n" + "std z+3, %A[frame] \n" // current + "std z+4, %B[frame] \n" + "std z+5, %C[frame] \n" + "std z+6, %A[repeat] \n" // repeat + "std z+7, %A[repeat] \n" // count + : + : [ctrl] "" (ctrl), + [frame] "r" (frame), + [repeat] "r" (repeat) + : //"r30", "r31" + ); + #else + frameControl.start = frame; + frameControl.current = frame; + frameControl.repeat = repeat; + frameControl.count = repeat; + #endif +} + +uint8_t FX::drawFrame() // ~66 bytes +{ + uint24_t frame = drawFrame(frameControl.current); + uint8_t moreFrames; + #ifdef ARDUINO_ARCH_AVR + FrameControl* ctrl = &frameControl; + asm volatile( + "ldi r30, lo8(%[ctrl]) \n" + "ldi r31, hi8(%[ctrl]) \n" + "ldd r0, z+7 \n" // frameControl.count + "mov %[more], r0 \n" // moreFrames = (frame != 0) | frameControl.count; + "or %[more], %A[frame] \n" + "or %[more], %B[frame] \n" + "or %[more], %C[frame] \n" + "tst r0 \n" + "breq 1f \n" // skip frameControl.count == 0 + " \n" + "dec r0 \n" + "std z+7, r0 \n" // frameControl.count-- + "rjmp 3f \n" // return + "1: \n" + "ldd r0, z+6 \n" // frameControl.count = frameControl.repeat + "std z+7, r0 \n" + "tst %[more] \n" // + "brne 2f \n" // if if moreFrames skip + " \n" + "ld %A[frame], z \n" // frame = frameControl.start + "ldd %B[frame], z+1 \n" + "ldd %C[frame], z+2 \n" + "2: \n" + "std z+3, %A[frame] \n" // frameControl.current = frame + "std z+4, %B[frame] \n" + "std z+5, %C[frame] \n" + "3: \n" + : [more] "=&r" (moreFrames) + : [ctrl] "" (ctrl), + [frame] "r" (frame) + : "r0", "r30", "r31" + ); + #else + moreFrames = (frame != 0) | frameControl.count; + if (frameControl.count > 0) + { + frameControl.count--; + } + else + { + frameControl.count = frameControl.repeat; + if (!moreFrames) frame = frameControl.start; + frameControl.current = frame; + } + #endif + return moreFrames; +} + +uint24_t FX::drawFrame(uint24_t address) //~94 bytes +{ + FrameData f; + #ifdef ARDUINO_ARCH_AVR + asm volatile ( + "push r6 \n" + "push r7 \n" + "push r8 \n" + "push r14 \n" + "push r16 \n" + "0: \n" + "movw r6, %A[addr] \n" //save address for calls + "mov r8, %C[addr] \n" + "call %x6 \n" + "call %x1 \n" + "movw r30, r24 \n" //temporary save x + "call %x1 \n" + "movw r26, r24 \n" //temporary save y + "call %x2 \n" + "mov r20, r24 \n" // bmp address + "movw r18, r22 \n" + "call %x3 \n" + "movw r16, r24 \n" // frame + "call %x4 \n" + "mov r14, r24 \n" // mode + "movw r24, r30 \n" // x + "movw r22, r26 \n" // y + "call %x5 \n" // drawbitmap + "movw %A[addr], r6 \n" // restore address + "mov %C[addr], r8 \n" + "subi %A[addr], -%[size] \n" + "sbci %B[addr], 0xFF \n" + "sbci %C[addr], 0xFF \n" + " \n" + "sbrc r14, 6 \n" // test next frame + "rjmp 1f \n" // skip end of this frame + " \n" + "sbrs r14, 7 \n" // test last frame + "rjmp 0b \n" // loop not last frame + " \n" + "clr %A[addr] \n" + "clr %B[addr] \n" + "clr %C[addr] \n" + "1: \n" + "pop r16 \n" + "pop r14 \n" + "pop r8 \n" + "pop r7 \n" + "pop r6 \n" + + : [addr] "+&r" (address) + : "" (readPendingUInt16), + "" (readPendingUInt24), + "" (readPendingUInt8), + "" (readEnd), + "" (drawBitmap), + "" (seekData), + [size] "" (sizeof(f)) + : "r18","r19", "r20", "r21", "r25", "r26", "r27", "r30", "r31" + ); + return address; + #else + seekData(address); + address += sizeof(f); + for(;;) + { + f.x = readPendingUInt16(); + f.y = readPendingUInt16(); + f.bmp = readPendingUInt24(); + f.frame = readPendingUInt8(); + f.mode = readEnd(); + drawBitmap(f.x, f.y, f.bmp, f.frame, f.mode); + if (f.mode & dbmEndFrame) return address; + if (f.mode & dbmLastFrame) return 0; + } + #endif +} void FX::readDataArray(uint24_t address, uint8_t index, uint8_t offset, uint8_t elementSize, uint8_t* buffer, size_t length) { diff --git a/board-package-source/libraries/ArduboyFX/src/ArduboyFX.h b/board-package-source/libraries/ArduboyFX/src/ArduboyFX.h index f6fef45..1209929 100644 --- a/board-package-source/libraries/ArduboyFX/src/ArduboyFX.h +++ b/board-package-source/libraries/ArduboyFX/src/ArduboyFX.h @@ -38,6 +38,8 @@ constexpr uint8_t dbfBlack = 2; // bitmap will be blackened constexpr uint8_t dbfReverseBlack = 3; // reverses bitmap data constexpr uint8_t dbfMasked = 4; // bitmap contains mask data constexpr uint8_t dbfExtraRow = 7; // ignored (internal use) +constexpr uint8_t dbfEndFrame = 6; // last bitmap image of a frame +constexpr uint8_t dbfLastFrame = 7; // last bitmap image of the last frame // drawBitmap modes with same behaviour as Arduboy library drawBitmap modes constexpr uint8_t dbmBlack = _BV(dbfReverseBlack) | // white pixels in bitmap will be drawn as black pixels on display @@ -62,6 +64,8 @@ constexpr uint8_t dbmReverse = _BV(dbfReverseBlack); // White pixels in bitma constexpr uint8_t dbmMasked = _BV(dbfMasked); // The bitmap contains a mask that will determine which pixels are // drawn and which pixels remain unchanged on display // (same as sprites drawPlusMask) +constexpr uint8_t dbmEndFrame = _BV(dbfEndFrame); // last bitmap of a frame but more frames +constexpr uint8_t dbmLastFrame = _BV(dbfLastFrame); // last bitmap of a frame and at end of frames // Note above modes may be combined like (dbmMasked | dbmReverse) @@ -132,6 +136,24 @@ struct Cursor int16_t wrap; }; +struct FrameControl +{ + uint24_t start; + uint24_t current; + uint8_t repeat; + uint8_t count; +}; + +struct FrameData +{ + int16_t x; + int16_t y; + uint24_t bmp; + uint8_t frame; + uint8_t mode; +}; + + class FX { public: @@ -227,11 +249,11 @@ class FX static uint8_t readPendingUInt8() __attribute__ ((noinline)); //read a prefetched byte from the current flash location - static uint8_t readPendingLastUInt8() __attribute__ ((noinline)); //read a prefetched byte from the current flash location + static uint8_t readPendingLastUInt8() __attribute__ ((noinline)); //depreciated use readEnd() instead (see below) - static uint16_t readPendingUInt16() __attribute__ ((noinline)); //read a partly prefetched 16-bit word from the current flash location + static uint16_t readPendingUInt16() __attribute__ ((noinline)) __attribute__ ((naked)); //read a partly prefetched 16-bit word from the current flash location - static uint16_t readPendingLastUInt16() __attribute__ ((noinline)); //read a partly prefetched 16-bit word from the current flash location + static uint16_t readPendingLastUInt16() __attribute__ ((noinline)) __attribute__ ((naked)); //read a partly prefetched 16-bit word from the current flash location static uint24_t readPendingUInt24() ; //read a partly prefetched 24-bit word from the current flash location @@ -243,9 +265,9 @@ class FX static void readBytes(uint8_t* buffer, size_t length);// read a number of bytes from the current flash location - static void readBytesEnd(uint8_t* buffer, size_t length); // read a number of bytes from the current flash location and end the read command + static void readBytesEnd(uint8_t* buffer, size_t length); // read a number of bytes from the current flash location and ends the read command - static uint8_t readEnd(); //read last pending byte and end read command + static uint8_t readEnd() __attribute__ ((noinline)); //read the last prefetched byte from the current flash location and ends the read command static void readDataBytes(uint24_t address, uint8_t* buffer, size_t length); @@ -254,11 +276,17 @@ class FX static void eraseSaveBlock(uint16_t page); static void writeSavePage(uint16_t page, uint8_t* buffer); - + static void waitWhileBusy(); // wait for outstanding erase or write to finish static void drawBitmap(int16_t x, int16_t y, uint24_t address, uint8_t frame, uint8_t mode) __attribute__((noinline)); + static void setFrame(uint24_t frame, uint8_t repeat)__attribute__ ((noinline)); + + static uint8_t drawFrame(); + + static uint24_t drawFrame(uint24_t address) __attribute__((noinline)); // draw a list of bitmap images located at address + static void readDataArray(uint24_t address, uint8_t index, uint8_t offset, uint8_t elementSize, uint8_t* buffer, size_t length); static uint8_t readIndexedUInt8(uint24_t address, uint8_t index); @@ -431,5 +459,7 @@ class FX static uint16_t programSavePage; // program read and write data area in flash memory static Font font; static Cursor cursor; + + static FrameControl frameControl; }; #endif