updatate source with Arduboy FX library to v1.0.5
This commit is contained in:
parent
c26e9dd8a6
commit
29dd60bb1c
Binary file not shown.
After Width: | Height: | Size: 413 B |
Binary file not shown.
After Width: | Height: | Size: 260 B |
|
@ -0,0 +1,142 @@
|
||||||
|
/* *****************************************************************************
|
||||||
|
* FX drawDrame example v1.00 by Mr.Blinky Jan 2023 licenced under CC0
|
||||||
|
* *****************************************************************************
|
||||||
|
*
|
||||||
|
* This is a example that shows how you can draw animations from the FX external
|
||||||
|
* flash memory using the drawframes function
|
||||||
|
*
|
||||||
|
* Before this example sketch is uploaded and run on the Arduboy FX, make sure
|
||||||
|
* the fxdata used by this sketch has been build and uploaded to the Arduboy FX.
|
||||||
|
*
|
||||||
|
* If the Arduboy FX Arduino plugin has been installed you can simply choose the
|
||||||
|
* 'Build and upload Arduboy FX data' from the Arduino IDE Tools menu.
|
||||||
|
*
|
||||||
|
* Alternatively the fxdata.txt script file can be build using the fxdata-build.py
|
||||||
|
* Python script. using the command:
|
||||||
|
*
|
||||||
|
* fxdata-upload.py fxdata.txt
|
||||||
|
|
||||||
|
The created fxdata.bin file can be uploaded to your Arduboy by using the
|
||||||
|
*uploader-gui.py Python script using the command:
|
||||||
|
|
||||||
|
* fxdata-upload.py fxdata.bin
|
||||||
|
*
|
||||||
|
* On some OS you may need to type python3 infront of the script name and supply
|
||||||
|
* the full path to the script and fxdata files.
|
||||||
|
*
|
||||||
|
******************************************************************************
|
||||||
|
*
|
||||||
|
* There are 3 functions to make drawing animations of multiple bitmap images
|
||||||
|
* easier:
|
||||||
|
*
|
||||||
|
* - uint24_t FX::drawFrame(uint24_t address)
|
||||||
|
* - FX::setFrame(uint24_t frame, uint8_t repeat);
|
||||||
|
* - uint8_t FX::drawFrame();
|
||||||
|
*
|
||||||
|
* FX::drawFrame(uint24_t address)
|
||||||
|
* -------------------------------
|
||||||
|
* drawFrame is a bit like FX::drawBitmap but instead of passing the parameters
|
||||||
|
* along with the function directly, they are stored in FX memory at the given
|
||||||
|
* address. In addition to that parameters of multiple bitmaps can be stored at
|
||||||
|
* the address to draw multiple bitmaps by this function.
|
||||||
|
|
||||||
|
* the list of bitmap parameters is called a frame. The parameters are the same
|
||||||
|
* as used with FX::drawBitmap except the mode parameter. An extra flag value
|
||||||
|
* can be added to mark the end of a frame or to mark the frame as the last in
|
||||||
|
* the list of frames.
|
||||||
|
*
|
||||||
|
* this functions return the address of the next frame unless the frame is
|
||||||
|
* flagged as a last frame. In that case the function returns 0
|
||||||
|
*
|
||||||
|
* using this function has no effect on using the other frame functions.
|
||||||
|
*
|
||||||
|
* FX::setFrame(uint24_t address, uint8_t repeat)
|
||||||
|
* --------------------------------------------
|
||||||
|
* setFrame sets the current frame address and repeat value for the drawFrame
|
||||||
|
* function below.
|
||||||
|
*
|
||||||
|
* - address is the address of a frame list in FX memory.
|
||||||
|
* - repeat is number of times each frame should be repeated.
|
||||||
|
* Each frame is drawn repeat + 1 times.
|
||||||
|
*
|
||||||
|
* uint8_t FX::drawFrame()
|
||||||
|
* ------------------------
|
||||||
|
*
|
||||||
|
* drawFrame without parameters draws the current frame in the frame list set
|
||||||
|
* by the setFrame function above. When the last frame of the framelist is
|
||||||
|
* drawn and is also the last repeated frame, the current frame pointer is
|
||||||
|
* reset to start of the frame list. This effectively loops the frame list.
|
||||||
|
* the function also returns 0 in that case. This can be usedto detect the
|
||||||
|
* end of the animation.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include <Arduboy2.h> // required to build for Arduboy
|
||||||
|
#include <ArduboyFX.h> // 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
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
||||||
|
}
|
Binary file not shown.
|
@ -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;
|
|
@ -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
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
name=ArduboyFX
|
name=ArduboyFX
|
||||||
version=1.0.4
|
version=1.0.5
|
||||||
author=Mr.Blinky
|
author=Mr.Blinky
|
||||||
maintainer=mstr.blinky@gmail.com
|
maintainer=mstr.blinky@gmail.com
|
||||||
sentence=The Arduboy FX library.
|
sentence=The Arduboy FX library.
|
||||||
|
|
|
@ -6,6 +6,8 @@ uint16_t FX::programSavePage; // program read and write data location in flash m
|
||||||
Font FX::font;
|
Font FX::font;
|
||||||
Cursor FX::cursor = {0,0,0,WIDTH};
|
Cursor FX::cursor = {0,0,0,WIDTH};
|
||||||
|
|
||||||
|
FrameControl FX::frameControl;
|
||||||
|
|
||||||
|
|
||||||
uint8_t FX::writeByte(uint8_t data)
|
uint8_t FX::writeByte(uint8_t data)
|
||||||
{
|
{
|
||||||
|
@ -124,10 +126,27 @@ void FX::writeEnable()
|
||||||
void FX::seekCommand(uint8_t command, uint24_t address)
|
void FX::seekCommand(uint8_t command, uint24_t address)
|
||||||
{
|
{
|
||||||
enable();
|
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(command);
|
||||||
writeByte(address >> 16);
|
writeByte(address >> 16);
|
||||||
writeByte(address >> 8);
|
writeByte(address >> 8);
|
||||||
writeByte(address);
|
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"
|
" mul %[index], %[size] \n"
|
||||||
" brne .+2 \n" //treat size 0 as size 256
|
" brne .+2 \n" //treat size 0 as size 256
|
||||||
" mov r1, %[index] \n"
|
" mov r1, %[index] \n"
|
||||||
" clr r24 \n" //use as alternative zero reg
|
" clr r21 \n" //use as alternative zero reg
|
||||||
" add r0, %[offset] \n"
|
" add r0, %[offset] \n"
|
||||||
" adc r1, r24 \n"
|
" adc r1, r21 \n"
|
||||||
" add %A[address], r0 \n"
|
" add %A[address], r0 \n"
|
||||||
" adc %B[address], r1 \n"
|
" adc %B[address], r1 \n"
|
||||||
" adc %C[address], r24 \n"
|
" adc %C[address], r21 \n"
|
||||||
" clr r1 \n"
|
" clr r1 \n"
|
||||||
: [address] "+r" (address)
|
: [address] "+&r" (address)
|
||||||
: [index] "r" (index),
|
: [index] "r" (index),
|
||||||
[offset] "r" (offset),
|
[offset] "r" (offset),
|
||||||
[size] "r" (elementSize)
|
[size] "r" (elementSize)
|
||||||
: "r24"
|
: "r21"
|
||||||
);
|
);
|
||||||
#else
|
#else
|
||||||
address += size ? index * size + offset : index * 256 + offset;
|
address += size ? index * size + offset : index * 256 + offset;
|
||||||
#endif
|
#endif
|
||||||
seekData(address);
|
seekData(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,9 +231,6 @@ uint8_t FX::readPendingUInt8()
|
||||||
|
|
||||||
uint8_t FX::readPendingLastUInt8()
|
uint8_t FX::readPendingLastUInt8()
|
||||||
{
|
{
|
||||||
#ifdef ARDUINO_ARCH_AVR
|
|
||||||
asm volatile("ArduboyFX_cpp_readPendingLastUInt8:\n"); // create label for calls in FX::readPendingUInt16
|
|
||||||
#endif
|
|
||||||
return readEnd();
|
return readEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,7 +243,7 @@ uint16_t FX::readPendingUInt16()
|
||||||
( "ArduboyFX_cpp_readPendingUInt16: \n"
|
( "ArduboyFX_cpp_readPendingUInt16: \n"
|
||||||
"call ArduboyFX_cpp_readPendingUInt8 \n"
|
"call ArduboyFX_cpp_readPendingUInt8 \n"
|
||||||
"mov %B[val], r24 \n"
|
"mov %B[val], r24 \n"
|
||||||
"call ArduboyFX_cpp_readPendingUInt8 \n"
|
"jmp ArduboyFX_cpp_readPendingUInt8 \n"
|
||||||
: [val] "=&r" (result)
|
: [val] "=&r" (result)
|
||||||
: "" (readPendingUInt8)
|
: "" (readPendingUInt8)
|
||||||
:
|
:
|
||||||
|
@ -245,17 +261,17 @@ uint16_t FX::readPendingLastUInt16()
|
||||||
uint16_t result asm("r24"); // we want result to be assigned to r24,r25
|
uint16_t result asm("r24"); // we want result to be assigned to r24,r25
|
||||||
asm volatile
|
asm volatile
|
||||||
( "ArduboyFX_cpp_readPendingLastUInt16: \n"
|
( "ArduboyFX_cpp_readPendingLastUInt16: \n"
|
||||||
"call ArduboyFX_cpp_readPendingUInt8 \n"
|
"call %x1 \n"
|
||||||
"mov %B[val], r24 \n"
|
"mov %B[val], r24 \n"
|
||||||
"call ArduboyFX_cpp_readPendingLastUInt8 \n"
|
"jmp %x2 \n"
|
||||||
: [val] "=&r" (result)
|
: [val] "=&r" (result)
|
||||||
: "" (readPendingUInt8),
|
: "" (readPendingUInt8),
|
||||||
"" (readPendingLastUInt8)
|
"" (readEnd)
|
||||||
:
|
:
|
||||||
);
|
);
|
||||||
return result;
|
return result;
|
||||||
#else //C++ implementation for non AVR platforms
|
#else //C++ implementation for non AVR platforms
|
||||||
return ((uint16_t)readPendingUint8() << 8) | (uint16_t)readPendingLastUInt8();
|
return ((uint16_t)readPendingUint8() << 8) | (uint16_t)readEnd();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,19 +305,19 @@ uint24_t FX::readPendingLastUInt24()
|
||||||
uint24_t result asm("r24"); // we want result to be assigned to r24,r25,r26
|
uint24_t result asm("r24"); // we want result to be assigned to r24,r25,r26
|
||||||
asm volatile
|
asm volatile
|
||||||
(
|
(
|
||||||
"call ArduboyFX_cpp_readPendingUInt16 \n"
|
"call %x1 \n"
|
||||||
"mov %B[val], r24 \n"
|
"mov %B[val], r24 \n"
|
||||||
"call ArduboyFX_cpp_readPendingLastUInt8 \n"
|
"call %x2 \n"
|
||||||
"mov %A[val], r24 \n"
|
"mov %A[val], r24 \n"
|
||||||
"mov %C[val], r25 \n"
|
"mov %C[val], r25 \n"
|
||||||
: [val] "=&r" (result)
|
: [val] "=&r" (result)
|
||||||
: "" (readPendingUInt16),
|
: "" (readPendingUInt16),
|
||||||
"" (readPendingLastUInt8)
|
"" (readEnd)
|
||||||
:
|
:
|
||||||
);
|
);
|
||||||
return result;
|
return result;
|
||||||
#else //C++ implementation for non AVR platforms
|
#else //C++ implementation for non AVR platforms
|
||||||
return ((uint24_t)readPendingUInt16() << 8) | readPendingLastUInt8();
|
return ((uint24_t)readPendingUInt16() << 8) | readEnd();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -678,6 +694,167 @@ void FX::drawBitmap(int16_t x, int16_t y, uint24_t address, uint8_t frame, uint8
|
||||||
#endif
|
#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)
|
void FX::readDataArray(uint24_t address, uint8_t index, uint8_t offset, uint8_t elementSize, uint8_t* buffer, size_t length)
|
||||||
{
|
{
|
||||||
|
|
|
@ -38,6 +38,8 @@ constexpr uint8_t dbfBlack = 2; // bitmap will be blackened
|
||||||
constexpr uint8_t dbfReverseBlack = 3; // reverses bitmap data
|
constexpr uint8_t dbfReverseBlack = 3; // reverses bitmap data
|
||||||
constexpr uint8_t dbfMasked = 4; // bitmap contains mask data
|
constexpr uint8_t dbfMasked = 4; // bitmap contains mask data
|
||||||
constexpr uint8_t dbfExtraRow = 7; // ignored (internal use)
|
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
|
// 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
|
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
|
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
|
// drawn and which pixels remain unchanged on display
|
||||||
// (same as sprites drawPlusMask)
|
// (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)
|
// Note above modes may be combined like (dbmMasked | dbmReverse)
|
||||||
|
|
||||||
|
@ -132,6 +136,24 @@ struct Cursor
|
||||||
int16_t wrap;
|
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
|
class FX
|
||||||
{
|
{
|
||||||
public:
|
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 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
|
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 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);
|
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 eraseSaveBlock(uint16_t page);
|
||||||
|
|
||||||
static void writeSavePage(uint16_t page, uint8_t* buffer);
|
static void writeSavePage(uint16_t page, uint8_t* buffer);
|
||||||
|
|
||||||
static void waitWhileBusy(); // wait for outstanding erase or write to finish
|
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 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 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);
|
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 uint16_t programSavePage; // program read and write data area in flash memory
|
||||||
static Font font;
|
static Font font;
|
||||||
static Cursor cursor;
|
static Cursor cursor;
|
||||||
|
|
||||||
|
static FrameControl frameControl;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue