2020-09-15 15:17:03 +00:00
# ifndef ARDUBOYFX_H
# define ARDUBOYFX_H
# include <Arduboy2.h>
# ifdef CART_CS_RX
# define FX_PORT PORTD
# define FX_BIT PORTD2
# else
# define FX_PORT PORTD
# define FX_BIT PORTD1
# endif
2022-03-12 12:29:54 +00:00
// progam data and save data pages(set by PC manager tool)
constexpr uint16_t FX_VECTOR_KEY_VALUE = 0x9518 ; /* RETI instruction used as magic key */
2020-09-15 15:17:03 +00:00
constexpr uint16_t FX_DATA_VECTOR_KEY_POINTER = 0x0014 ; /* reserved interrupt vector 5 area */
constexpr uint16_t FX_DATA_VECTOR_PAGE_POINTER = 0x0016 ;
constexpr uint16_t FX_SAVE_VECTOR_KEY_POINTER = 0x0018 ; /* reserved interrupt vector 6 area */
constexpr uint16_t FX_SAVE_VECTOR_PAGE_POINTER = 0x001A ;
2022-03-12 12:29:54 +00:00
// Serial Flash Commands
constexpr uint8_t SFC_JEDEC_ID = 0x9F ;
2020-09-15 15:17:03 +00:00
constexpr uint8_t SFC_READSTATUS1 = 0x05 ;
constexpr uint8_t SFC_READSTATUS2 = 0x35 ;
constexpr uint8_t SFC_READSTATUS3 = 0x15 ;
constexpr uint8_t SFC_READ = 0x03 ;
constexpr uint8_t SFC_WRITE_ENABLE = 0x06 ;
2022-11-18 16:26:53 +00:00
constexpr uint8_t SFC_WRITE = 0x02 ;
2020-09-15 15:17:03 +00:00
constexpr uint8_t SFC_ERASE = 0x20 ;
constexpr uint8_t SFC_RELEASE_POWERDOWN = 0xAB ;
constexpr uint8_t SFC_POWERDOWN = 0xB9 ;
2022-03-12 12:29:54 +00:00
// drawbitmap bit flags (used by modes below and internally)
2020-09-15 15:17:03 +00:00
constexpr uint8_t dbfWhiteBlack = 0 ; // bitmap is used as mask
constexpr uint8_t dbfInvert = 1 ; // bitmap is exclusive or-ed with display
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)
2023-01-07 01:07:49 +00:00
constexpr uint8_t dbfEndFrame = 6 ; // last bitmap image of a frame
constexpr uint8_t dbfLastFrame = 7 ; // last bitmap image of the last frame
2020-09-15 15:17:03 +00:00
2022-03-12 12:29:54 +00:00
// drawBitmap modes with same behaviour as Arduboy library drawBitmap modes
2020-09-15 15:17:03 +00:00
constexpr uint8_t dbmBlack = _BV ( dbfReverseBlack ) | // white pixels in bitmap will be drawn as black pixels on display
_BV ( dbfBlack ) | // black pixels in bitmap will not change pixels on display
_BV ( dbfWhiteBlack ) ; // (same as sprites drawErase)
2022-03-21 20:21:15 +00:00
2020-09-15 15:17:03 +00:00
constexpr uint8_t dbmWhite = _BV ( dbfWhiteBlack ) ; // white pixels in bitmap will be drawn as white pixels on display
// black pixels in bitmap will not change pixels on display
//(same as sprites drawSelfMasked)
2022-03-21 20:21:15 +00:00
2020-09-15 15:17:03 +00:00
constexpr uint8_t dbmInvert = _BV ( dbfInvert ) ; // when a pixel in bitmap has a different color than on display the
// pixel on display will be drawn as white. In all other cases the
// pixel will be drawn as black
2022-03-21 20:21:15 +00:00
// additional drawBitmap modes
2020-09-15 15:17:03 +00:00
constexpr uint8_t dbmNormal = 0 ; // White pixels in bitmap will be drawn as white pixels on display
constexpr uint8_t dbmOverwrite = 0 ; // Black pixels in bitmap will be drawn as black pixels on display
// (Same as sprites drawOverwrite)
2022-03-21 20:21:15 +00:00
2020-09-15 15:17:03 +00:00
constexpr uint8_t dbmReverse = _BV ( dbfReverseBlack ) ; // White pixels in bitmap will be drawn as black pixels on display
// Black pixels in bitmap will be drawn as white pixels on display
2022-03-21 20:21:15 +00:00
2020-09-15 15:17:03 +00:00
constexpr uint8_t dbmMasked = _BV ( dbfMasked ) ; // The bitmap contains a mask that will determine which pixels are
2022-03-12 12:29:54 +00:00
// drawn and which pixels remain unchanged on display
2020-09-15 15:17:03 +00:00
// (same as sprites drawPlusMask)
2023-01-07 01:07:49 +00:00
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
2022-03-21 20:21:15 +00:00
2020-09-15 15:17:03 +00:00
// Note above modes may be combined like (dbmMasked | dbmReverse)
2022-03-21 20:21:15 +00:00
// drawChar bit flags (used by modes below)
constexpr uint8_t dcfWhiteBlack = 0 ; // character is used as mask
constexpr uint8_t dcfInvert = 1 ; // character is exclusive or-ed with display
constexpr uint8_t dcfBlack = 2 ; // character will be blackened
constexpr uint8_t dcfReverseBlack = 3 ; // reverses character data
constexpr uint8_t dcfMasked = 4 ; // character contains mask data
constexpr uint8_t dcfProportional = 5 ; // use fonts width table to mimic proportional characters
//draw Font character modes
constexpr uint8_t dcmBlack = _BV ( dcfReverseBlack ) | // white pixels in character will be drawn as black pixels on display
_BV ( dcfBlack ) | // black pixels in character will not change pixels on display
_BV ( dcfWhiteBlack ) ; // (same as sprites drawErase)
constexpr uint8_t dcmWhite = _BV ( dcfWhiteBlack ) ; // white pixels in character will be drawn as white pixels on display
// black pixels in character will not change pixels on display
//(same as sprites drawSelfMasked)
constexpr uint8_t dcmInvert = _BV ( dcfInvert ) ; // when a pixel in character has a different color than on display the
// pixel on display will be drawn as white. In all other cases the
// pixel will be drawn as black
// additional drawcharacter modes
constexpr uint8_t dcmNormal = 0 ; // White pixels in character will be drawn as white pixels on display
constexpr uint8_t dcmOverwrite = 0 ; // Black pixels in character will be drawn as black pixels on display
// (Same as sprites drawOverwrite)
constexpr uint8_t dcmReverse = _BV ( dcfReverseBlack ) ; // White pixels in character will be drawn as black pixels on display
// Black pixels in character will be drawn as white pixels on display
constexpr uint8_t dcmMasked = _BV ( dcfMasked ) ; // The character contains a mask that will determine which pixels are
constexpr uint8_t dcmProportional = _BV ( dcfProportional ) ; // draw characters with variable spacing. When this mode is used a
// 256 byte width table must precede the font data
// Note above modes may be combined like (dcmMasked | dcmProportional)
2020-09-15 15:17:03 +00:00
using uint24_t = __uint24 ;
struct JedecID
{
uint8_t manufacturer ;
uint8_t device ;
uint8_t size ;
} ;
struct FXAddress
{
uint16_t page ;
uint8_t offset ;
} ;
2022-03-21 20:21:15 +00:00
struct Font
{
uint24_t address ;
uint8_t mode ;
uint8_t width ;
uint8_t height ;
} ;
struct Cursor
{
int16_t x ;
int16_t y ;
int16_t left ;
int16_t wrap ;
} ;
2023-01-07 01:07:49 +00:00
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 ;
} ;
2020-09-15 15:17:03 +00:00
class FX
{
public :
static inline void enableOLED ( ) __attribute__ ( ( always_inline ) ) // selects OLED display.
{
CS_PORT & = ~ ( 1 < < CS_BIT ) ;
} ;
static inline void disableOLED ( ) __attribute__ ( ( always_inline ) ) // deselects OLED display.
{
CS_PORT | = ( 1 < < CS_BIT ) ;
} ;
2022-03-21 20:21:15 +00:00
2020-09-15 15:17:03 +00:00
static inline void enable ( ) __attribute__ ( ( always_inline ) ) // selects external flash memory and allows new commands
{
FX_PORT & = ~ ( 1 < < FX_BIT ) ;
} ;
static inline void disable ( ) __attribute__ ( ( always_inline ) ) // deselects external flash memory and ends the last command
{
FX_PORT | = ( 1 < < FX_BIT ) ;
} ;
static inline void wait ( ) __attribute__ ( ( always_inline ) ) // wait for a pending flash transfer to complete
{
while ( ( SPSR & _BV ( SPIF ) ) = = 0 ) ;
}
2022-03-21 20:21:15 +00:00
2020-09-15 15:17:03 +00:00
static uint8_t writeByte ( uint8_t data ) ; // write a single byte to flash memory.
2022-03-21 20:21:15 +00:00
2020-09-15 15:17:03 +00:00
static inline void writeByteBeforeWait ( uint8_t data ) __attribute__ ( ( always_inline ) )
{
SPDR = data ;
asm volatile ( " nop \n " ) ;
wait ( ) ;
}
2022-03-21 20:21:15 +00:00
2020-09-15 15:17:03 +00:00
static inline void writeByteAfterWait ( uint8_t data ) __attribute__ ( ( always_inline ) )
{
wait ( ) ;
SPDR = data ;
}
2022-02-23 00:47:00 +00:00
static uint8_t readByte ( ) ; // read a single byte from flash memory
2020-09-15 15:17:03 +00:00
2022-02-10 10:20:01 +00:00
static void displayPrefetch ( uint24_t address , uint8_t * target , uint16_t len , bool clear ) ;
2022-02-23 00:47:00 +00:00
static void display ( ) ; // display screen buffer
2022-03-21 20:21:15 +00:00
2022-02-23 00:47:00 +00:00
static void display ( bool clear ) ; // display screen buffer with clear
2022-03-21 20:21:15 +00:00
2020-09-15 15:17:03 +00:00
static void begin ( ) ; // Initializes flash memory. Use only when program does not require data and save areas in flash memory
static void begin ( uint16_t programDataPage ) ; // Initializes flash memory. Use when program depends on data in flash memory
static void begin ( uint16_t datapage , uint16_t savepage ) ; // Initializes flash memory. Use when program depends on both data and save data in flash memory
static void readJedecID ( JedecID * id ) ;
2022-03-21 20:21:15 +00:00
2020-09-15 15:17:03 +00:00
static bool detect ( ) ; //detect presence of initialized flash memory
2022-03-21 20:21:15 +00:00
2020-09-15 15:17:03 +00:00
static void noFXReboot ( ) ; // flash RGB LED red and wait for DOWN button to exit to bootloader when no initialized external flash memory is present
2022-03-21 20:21:15 +00:00
2020-09-15 15:17:03 +00:00
static void writeCommand ( uint8_t command ) ; // write a single byte flash command
static void wakeUp ( ) ; // Wake up flash memory from power down mode
static void sleep ( ) ; // Put flash memory in power down mode for low power
static void writeEnable ( ) ; // Puts flash memory in write mode, required prior to any write command
static void seekCommand ( uint8_t command , uint24_t address ) ; // Write command and selects flash memory address. Required by any read or write command
static void seekData ( uint24_t address ) ; // selects flashaddress of program data area for reading and starts the first read
2022-03-21 20:21:15 +00:00
2020-09-15 15:17:03 +00:00
static void seekDataArray ( uint24_t address , uint8_t index , uint8_t offset , uint8_t elementSize ) ;
2023-01-28 21:05:54 +00:00
static void seekSave ( uint24_t address ) __attribute__ ( ( noinline ) ) ; // selects flashaddress of program save area for reading and starts the first read
2022-03-21 20:21:15 +00:00
2020-09-15 15:17:03 +00:00
static inline uint8_t readUnsafe ( ) __attribute__ ( ( always_inline ) ) // read flash data without performing any checks and starts the next read.
{
uint8_t result = SPDR ;
SPDR = 0 ;
return result ;
} ;
static inline uint8_t readUnsafeEnd ( ) __attribute__ ( ( always_inline ) )
{
uint8_t result = SPDR ;
disable ( ) ;
return result ;
} ;
2022-03-21 20:21:15 +00:00
2020-09-15 15:17:03 +00:00
static uint8_t readPendingUInt8 ( ) __attribute__ ( ( noinline ) ) ; //read a prefetched byte from the current flash location
2022-03-21 20:21:15 +00:00
2023-01-07 01:07:49 +00:00
static uint8_t readPendingLastUInt8 ( ) __attribute__ ( ( noinline ) ) ; //depreciated use readEnd() instead (see below)
2022-03-21 20:21:15 +00:00
2023-01-07 01:07:49 +00:00
static uint16_t readPendingUInt16 ( ) __attribute__ ( ( noinline ) ) __attribute__ ( ( naked ) ) ; //read a partly prefetched 16-bit word from the current flash location
2020-09-15 15:17:03 +00:00
2023-01-07 01:07:49 +00:00
static uint16_t readPendingLastUInt16 ( ) __attribute__ ( ( noinline ) ) __attribute__ ( ( naked ) ) ; //read a partly prefetched 16-bit word from the current flash location
2022-03-21 20:21:15 +00:00
2020-09-15 15:17:03 +00:00
static uint24_t readPendingUInt24 ( ) ; //read a partly prefetched 24-bit word from the current flash location
2022-03-21 20:21:15 +00:00
2020-09-15 15:17:03 +00:00
static uint24_t readPendingLastUInt24 ( ) ; //read a partly prefetched 24-bit word from the current flash location
2022-03-21 20:21:15 +00:00
2020-09-15 15:17:03 +00:00
static uint32_t readPendingUInt32 ( ) ; //read a partly prefetched a 32-bit word from the current flash location
2022-03-21 20:21:15 +00:00
2020-09-15 15:17:03 +00:00
static uint32_t readPendingLastUInt32 ( ) ; //read a partly prefetched a 32-bit word from the current flash location
2022-03-21 20:21:15 +00:00
2020-09-15 15:17:03 +00:00
static void readBytes ( uint8_t * buffer , size_t length ) ; // read a number of bytes from the current flash location
2022-03-21 20:21:15 +00:00
2023-01-07 01:07:49 +00:00
static void readBytesEnd ( uint8_t * buffer , size_t length ) ; // read a number of bytes from the current flash location and ends the read command
2022-03-21 20:21:15 +00:00
2023-01-07 01:07:49 +00:00
static uint8_t readEnd ( ) __attribute__ ( ( noinline ) ) ; //read the last prefetched byte from the current flash location and ends the read command
2020-09-15 15:17:03 +00:00
static void readDataBytes ( uint24_t address , uint8_t * buffer , size_t length ) ;
static void readSaveBytes ( uint24_t address , uint8_t * buffer , size_t length ) ;
2023-01-28 21:05:54 +00:00
static uint8_t loadGameState ( uint8_t * gameState , size_t size ) __attribute__ ( ( noinline ) ) ; //loads GameState from program exclusive 4K save data block.
static void saveGameState ( uint8_t * gameState , size_t size ) __attribute__ ( ( noinline ) ) ; // Saves GameState in RAM to programes exclusive 4K save data block.
static void eraseSaveBlock ( uint16_t page ) ; // erases 4K flash block
2020-09-15 15:17:03 +00:00
static void writeSavePage ( uint16_t page , uint8_t * buffer ) ;
2023-01-07 01:07:49 +00:00
2022-11-18 16:26:53 +00:00
static void waitWhileBusy ( ) ; // wait for outstanding erase or write to finish
2020-09-15 15:17:03 +00:00
2022-03-21 20:21:15 +00:00
static void drawBitmap ( int16_t x , int16_t y , uint24_t address , uint8_t frame , uint8_t mode ) __attribute__ ( ( noinline ) ) ;
2023-01-07 01:07:49 +00:00
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
2020-09-15 15:17:03 +00:00
static void readDataArray ( uint24_t address , uint8_t index , uint8_t offset , uint8_t elementSize , uint8_t * buffer , size_t length ) ;
2022-03-21 20:21:15 +00:00
2022-02-10 10:18:35 +00:00
static uint8_t readIndexedUInt8 ( uint24_t address , uint8_t index ) ;
2022-03-21 20:21:15 +00:00
2020-09-15 15:17:03 +00:00
static uint16_t readIndexedUInt16 ( uint24_t address , uint8_t index ) ;
2022-03-21 20:21:15 +00:00
2020-09-15 15:17:03 +00:00
static uint24_t readIndexedUInt24 ( uint24_t address , uint8_t index ) ;
2022-03-21 20:21:15 +00:00
2020-09-15 15:17:03 +00:00
static uint32_t readIndexedUInt32 ( uint24_t address , uint8_t index ) ;
2022-03-21 20:21:15 +00:00
/* Draw character functions */
static void setFont ( uint24_t address , uint8_t mode ) ;
static void setFontMode ( uint8_t mode ) ;
static void setCursor ( int16_t x , int16_t y ) ;
static void setCursorX ( int16_t x ) ;
static void setCursorY ( int16_t y ) ;
static void setCursorRange ( int16_t left , int16_t wrap ) ;
static void setCursorLeft ( int16_t x ) ;
static void setCursorWrap ( int16_t y ) ;
static void drawChar ( uint8_t c ) ;
static void drawString ( const uint8_t * buffer ) ;
static void drawString ( const char * str ) ;
static void drawString ( uint24_t address ) ;
//static void drawNumber(int8_t n, int8_t digits = 0); // draw a signed 8-bit number
//
//static void drawNumber(unt8_t n, int8_t digits = 0); // draw a unsigned 8-bit number
//
static void drawNumber ( int16_t n , int8_t digits = 0 ) ; // draw a signed 16-bit number
static void drawNumber ( uint16_t n , int8_t digits = 0 ) ; // draw a unsigned 16-bit number
static void drawNumber ( int32_t n , int8_t digits = 0 ) ; // draw signed 32-bit number with a fixed number of digits
// digits == 0: No leading characters are added, all digits are drawn
// digits > 0: Leading zeros are added if the number has less than 'digit' digits
// digits < 0: Leading spaces are added if the number has less than 'digit' digits
// Note: Only 'digits' number of digits are drawn regardless if the number has more digits
// The sign character is not counted as a digit.
static void drawNumber ( uint32_t n , int8_t digits = 0 ) ; // draw unsigned 32-bit number with a fixed number of digits
// digits == 0: No leading characters are added, all digits are drawn
// digits > 0: Leading zeros are added if the number has less than 'digit' digits
// digits < 0: Leading spaces are added if the number has less than 'digit' digits
// Note: Only 'digits' number of digits are drawn regardless if the number has more digits
/* general optimized functions */
2020-09-15 15:17:03 +00:00
static inline uint16_t multiplyUInt8 ( uint8_t a , uint8_t b ) __attribute__ ( ( always_inline ) )
{
# ifdef ARDUINO_ARCH_AVR
uint16_t result ;
asm volatile (
" mul %[a], %[b] \n "
" movw %A[result], r0 \n "
" clr r1 \n "
: [ result ] " =&r " ( result )
: [ a ] " r " ( a ) ,
[ b ] " r " ( b )
:
) ;
return result ;
# else
2022-03-21 20:21:15 +00:00
return ( a * b ) ;
2020-09-15 15:17:03 +00:00
# endif
}
2022-03-21 20:21:15 +00:00
2020-09-15 15:17:03 +00:00
static inline uint8_t bitShiftLeftUInt8 ( uint8_t bit ) __attribute__ ( ( always_inline ) ) //fast (1 << (bit & 7))
{
# ifdef ARDUINO_ARCH_AVR
uint8_t result ;
asm volatile (
" ldi %[result], 1 \n " // 0 = 000 => 0000 0001
" sbrc %[bit], 1 \n " // 1 = 001 => 0000 0010
" ldi %[result], 4 \n " // 2 = 010 => 0000 0100
" sbrc %[bit], 0 \n " // 3 = 011 => 0000 1000
2022-03-21 20:21:15 +00:00
" lsl %[result] \n "
2020-09-15 15:17:03 +00:00
" sbrc %[bit], 2 \n " // 4 = 100 => 0001 0000
" swap %[result] \n " // 5 = 101 => 0010 0000
: [ result ] " =&d " ( result ) // 6 = 110 => 0100 0000
: [ bit ] " r " ( bit ) // 7 = 111 => 1000 0000
:
) ;
return result ;
# else
return 1 < < ( bit & 7 ) ;
# endif
}
static inline uint8_t bitShiftRightUInt8 ( uint8_t bit ) __attribute__ ( ( always_inline ) ) //fast (0x80 >> (bit & 7))
{
# ifdef ARDUINO_ARCH_AVR
uint8_t result ;
asm volatile (
" ldi %[result], 1 \n " // 0 = 000 => 1000 0000
" sbrs %[bit], 1 \n " // 1 = 001 => 0100 0000
" ldi %[result], 4 \n " // 2 = 010 => 0010 0000
" sbrs %[bit], 0 \n " // 3 = 011 => 0001 0000
2022-03-21 20:21:15 +00:00
" lsl %[result] \n "
2020-09-15 15:17:03 +00:00
" sbrs %[bit], 2 \n " // 4 = 100 => 0000 1000
" swap %[result] \n " // 5 = 101 => 0000 0100
: [ result ] " =&d " ( result ) // 6 = 110 => 0000 0010
: [ bit ] " r " ( bit ) // 7 = 111 => 0000 0001
:
) ;
return result ;
# else
return 0x80 > > ( bit & 7 ) ;
# endif
}
2022-03-21 20:21:15 +00:00
2020-09-15 15:17:03 +00:00
static inline uint8_t bitShiftLeftMaskUInt8 ( uint8_t bit ) __attribute__ ( ( always_inline ) ) //fast (0xFF << (bit & 7) & 0xFF)
{
# ifdef ARDUINO_ARCH_AVR
uint8_t result ;
asm volatile (
" ldi %[result], 1 \n " // 0 = 000 => 1111 1111 = -1
" sbrc %[bit], 1 \n " // 1 = 001 => 1111 1110 = -2
" ldi %[result], 4 \n " // 2 = 010 => 1111 1100 = -4
" sbrc %[bit], 0 \n " // 3 = 011 => 1111 1000 = -8
2022-03-21 20:21:15 +00:00
" lsl %[result] \n "
2020-09-15 15:17:03 +00:00
" sbrc %[bit], 2 \n " // 4 = 100 => 1111 0000 = -16
" swap %[result] \n " // 5 = 101 => 1110 0000 = -32
" neg %[result] \n " // 6 = 110 => 1100 0000 = -64
: [ result ] " =&d " ( result ) // 7 = 111 => 1000 0000 = -128
2022-03-21 20:21:15 +00:00
: [ bit ] " r " ( bit )
2020-09-15 15:17:03 +00:00
:
) ;
return result ;
# else
return ( 0xFF < < ( bit & 7 ) ) & 0xFF ;
# endif
}
2022-03-21 20:21:15 +00:00
2020-09-15 15:17:03 +00:00
static inline uint8_t bitShiftRightMaskUInt8 ( uint8_t bit ) __attribute__ ( ( always_inline ) ) //fast (0xFF >> (bit & 7))
{
# ifdef ARDUINO_ARCH_AVR
uint8_t result ;
asm volatile (
2022-03-21 20:21:15 +00:00
" ldi %[result], 2 \n " // 0 = 000 => 1111 1111 = 0x00 - 1
2020-09-15 15:17:03 +00:00
" sbrs %A[bit], 1 \n " // 1 = 001 => 0111 1111 = 0x80 - 1
" ldi %[result], 8 \n " // 2 = 010 => 0011 1111 = 0x40 - 1
" sbrs %A[bit], 2 \n " // 3 = 011 => 0001 1111 = 0x20 - 1
2022-03-21 20:21:15 +00:00
" swap %[result] \n "
2020-09-15 15:17:03 +00:00
" sbrs %A[bit], 0 \n " // 4 = 100 => 0000 1111 = 0x10 - 1
" lsl %[result] \n " // 5 = 101 => 0000 0111 = 0x08 - 1
" dec %[result] \n " // 6 = 110 => 0000 0011 = 0x04 - 1
: [ result ] " =&d " ( result ) // 7 = 111 => 0000 0001 = 0x02 - 1
: [ bit ] " r " ( bit )
:
) ;
return result ;
# else
return 0xFF > > ( bit & 7 ) ;
# endif
}
2022-03-21 20:21:15 +00:00
2020-09-15 15:17:03 +00:00
static uint16_t programDataPage ; // program read only data area in flash memory
static uint16_t programSavePage ; // program read and write data area in flash memory
2022-03-21 20:21:15 +00:00
static Font font ;
static Cursor cursor ;
2023-01-07 01:07:49 +00:00
static FrameControl frameControl ;
2020-09-15 15:17:03 +00:00
} ;
# endif