Longan Nano
Longan Nano Demo
longan_nano_screen.hpp
Go to the documentation of this file.
1 /**********************************************************************************
2 BSD 3-Clause License
3 
4 Copyright (c) 2020, Orso Eric
5 All rights reserved.
6 
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9 
10 1. Redistributions of source code must retain the above copyright notice, this
11  list of conditions and the following disclaimer.
12 
13 2. Redistributions in binary form must reproduce the above copyright notice,
14  this list of conditions and the following disclaimer in the documentation
15  and/or other materials provided with the distribution.
16 
17 3. Neither the name of the copyright holder nor the names of its
18  contributors may be used to endorse or promote products derived from
19  this software without specific prior written permission.
20 
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 **********************************************************************************/
32 
33 /**********************************************************************************
34 ** ENVIROMENT VARIABILE
35 **********************************************************************************/
36 
37 #ifndef SCREEN_HPP_
38  #define SCREEN_HPP_
39 
40 /**********************************************************************************
41 ** GLOBAL INCLUDES
42 **********************************************************************************/
43 
44 //Display driver. Physical interface and microcontroller peripherals.
45 #include "ST7735S_W160_H80_C16.hpp"
46 //Number -> string
47 #include "embedded_string.hpp"
48 
49 /**********************************************************************************
50 ** DEBUG
51 **********************************************************************************/
52 /*
53 #ifndef DEBUG_H_
54  #include <stdio.h>
55  #define ENABLE_DEBUG
56  #include "debug.h"
57 #endif
58 */
59 //If DEBUG is not needed, blank out the implementations
60 #ifndef DEBUG_H_
61  #define DEBUG_VARS_PROTOTYPES()
62  #define DEBUG_VARS()
63  #define DSHOW( ... )
64  #define DSTART( ... )
65  #define DSTOP()
66  #define DTAB( ... )
67  #define DPRINT( ... )
68  #define DPRINT_NOTAB( ... )
69  #define DENTER( ... )
70  #define DRETURN( ... )
71  #define DENTER_ARG( ... )
72  #define DRETURN_ARG( ... )
73 
74  #define show_frame_sprite( ... )
75  #define show_pixels( ... )
76 #endif
77 
78 /**********************************************************************************
79 ** DEFINES
80 **********************************************************************************/
81 
82 /**********************************************************************************
83 ** MACROS
84 **********************************************************************************/
85 
86 /**********************************************************************************
87 ** NAMESPACE
88 **********************************************************************************/
89 
91 namespace Longan_nano
92 {
93 
94 /**********************************************************************************
95 ** TYPEDEFS
96 **********************************************************************************/
97 
98 //Font size 10 has 8x20 sprites on screen
99 //Font size 16 has 5x20 sprites on screen
100 #define FONT_HEIGHT 10
101 
102 /**********************************************************************************
103 ** PROTOTYPE: STRUCTURES
104 **********************************************************************************/
105 
106 /**********************************************************************************
107 ** PROTOTYPE: GLOBAL VARIABILES
108 **********************************************************************************/
109 
110 /**********************************************************************************
111 ** PROTOTYPE: CLASS
112 **********************************************************************************/
113 
114 /**********************************************************************************
115 ** DESCRIPTION
116 ***********************************************************************************
117 ** SPRITE
118 ** Logically devide screen in blocks width*height
119 **
120 ** NULL COLOR vs. NULL SPRITE
121 ** I need at least one combination that forces a sprite not to be updated (transparent)
122 **
123 ** GLOBAL BACKGROUND/FOREGROUND
124 ** SCREEN
125 ** WIDTH
126 ** 0,0 ---X--> 159,0
127 ** |
128 ** Y
129 ** |
130 ** v
131 ** 0,79 159,79
132 **
133 ** Use the following build flags in platformio.ini
134 ** build_flags = -fno-exceptions
135 **********************************************************************************/
136 
137 /*********************************************************************************/
139 /*********************************************************************************/
216 /*********************************************************************************/
217 
219 {
220  //Visible to all
221  public:
222  /*********************************************************************************************************************************************************
223  **********************************************************************************************************************************************************
224  ** PUBLIC ENUM
225  **********************************************************************************************************************************************************
226  *********************************************************************************************************************************************************/
227 
229  typedef enum _Config
230  {
231  PEDANTIC_CHECKS = true, //Pedantic check meant for debug
232  //Screen Logical Configuration. The screen is divided in sprites, shrinking the frame buffer
233  SPRITE_WIDTH = 8, //Width of a sprite
234  SPRITE_HEIGHT = FONT_HEIGHT, //Height of a sprite
235  SPRITE_PIXEL_COUNT = SPRITE_HEIGHT *SPRITE_WIDTH, //Number of pixels in a sprite
236  SPRITE_SCAN_LIMIT = 5, //Scan at most # idle sprites before releasing control from update() anyway
237  //Special sprite codes
238  NUM_SPECIAL_SPRITES = 5, //Number of special sprites
239  SPRITE_TRANSPARENT = 0, //Transparent sprite. Never updated. Ignore update flag.
240  SPRITE_BLACK = 1, //Always mapped to a full black sprite, invariant to palette index and content
241  SPRITE_WHITE = 2, //Always mapped to a full white sprite, invariant to palette index and content
242  SPRITE_BACKGROUND = 3, //Sprite with the background color
243  SPRITE_FOREGROUND = 4, //Sprite with the foreground color
244  //ASCII Sprite Table Definitions
245  ASCII_START = ' ', //First ASCII character defined in the sprite table
246  ASCII_STOP = '~', //Last ASCII character defined in the sprite table
247  //Colors are discretized in a palette
248  PALETTE_SIZE = 16, //Size of the palette
249  PALETTE_SIZE_BIT = 4, //Number of bit required to describe a color in the palette
250  //Size of the frame buffer. Display phisical size comes from the Physical Display class
251  FRAME_BUFFER_WIDTH = Longan_nano::Display::Config::WIDTH /SPRITE_WIDTH,
252  FRAME_BUFFER_HEIGHT = Longan_nano::Display::Config::HEIGHT /SPRITE_HEIGHT,
254  SPRITE_SIZE = 128, //Number of sprites in the sprite table
255  SPRITE_SIZE_BIT = 7 //Size of the sprite table
257 
259  typedef enum _Color
260  {
277  } Color;
278 
280  typedef enum _Format_format
281  {
282  NUM, //Extended number
283  ENG, //Engineering format with four significant digits and SI suffix
285 
287  typedef enum _Format_align
288  {
292 
294  typedef enum _Error
295  {
296  //Screen class working as intended
297  OK,
298  //Pending counter either underflow or overflow. Means an algorithmic error occurred in the screen class
302  //Handle error of error. errorception!
305  } Error;
306  /*
307  //Possible rules for conditional formatting of numbers
308  typedef enum _Rule_condition
309  {
310  NEVER,
311  ALWAYS,
312  EQUAL,
313  GREATER,
314  GREATER_EQUAL,
315  SMALLER,
316  SMALLER_EQUAL,
317  } Rule_condition;
318  */
319  /*********************************************************************************************************************************************************
320  **********************************************************************************************************************************************************
321  ** PUBLIC STRUCT
322  **********************************************************************************************************************************************************
323  *********************************************************************************************************************************************************/
324  /*
325  //Define a conditional formatting rule
326  typedef struct _Rule
327  {
328  Rule_condition condition;
329  int number;
330  Color background;
331  Color foreground;
332  typedef struct _Rule next_rule;
333  } Rule;
334  */
335  /*********************************************************************************************************************************************************
336  **********************************************************************************************************************************************************
337  ** CONSTRUCTORS
338  **********************************************************************************************************************************************************
339  *********************************************************************************************************************************************************/
340 
341  //Empty constructor
342  Screen( void );
343 
344  /*********************************************************************************************************************************************************
345  **********************************************************************************************************************************************************
346  ** DESTRUCTORS
347  **********************************************************************************************************************************************************
348  *********************************************************************************************************************************************************/
349 
350  //Empty Destructor
351  ~Screen( void );
352 
353  /*********************************************************************************************************************************************************
354  **********************************************************************************************************************************************************
355  ** PUBLIC INIT
356  **********************************************************************************************************************************************************
357  *********************************************************************************************************************************************************/
358 
359  //call the initializations for the driver
360  bool init( void );
361  //Reset the colors to default
362  bool reset_colors( void );
363 
364  /*********************************************************************************************************************************************************
365  **********************************************************************************************************************************************************
366  ** PUBLIC SETTER
367  **********************************************************************************************************************************************************
368  *********************************************************************************************************************************************************/
369 
370  //Set the background and foreground color of a sprite in a given position without changing the content
371  int set_color( int origin_h, int origin_w, Color background, Color foreground );
372  //Set the default background and foreground color. Change all sprites that use those colors to the new ones
373  int set_default_colors( Color new_background, Color new_foreground );
374  //Change a color in the palette to another RGB color
375  int set_palette_color( Color palette_index, uint8_t r, uint8_t g, uint8_t b );
376  //Set the display format of the print number method
377  bool set_format( int number_size, Format_align align, Format_format format );
378  //Set the display format of the print number method. Include default exponent for ENG number
379  bool set_format( int number_size, Format_align align, Format_format format, int exp );
380 
381  /*********************************************************************************************************************************************************
382  **********************************************************************************************************************************************************
383  ** PUBLIC GETTER
384  **********************************************************************************************************************************************************
385  *********************************************************************************************************************************************************/
386 
387  //Get the number of sprites that are pending for update
388  int get_pending( void );
389  //Get current error of the screen class
390  Error get_error( void );
391 
392  /*********************************************************************************************************************************************************
393  **********************************************************************************************************************************************************
394  ** PUBLIC METHODS
395  **********************************************************************************************************************************************************
396  *********************************************************************************************************************************************************/
397 
398  //Expose color conversion method
399  using Display::color;
400  //Core method. FSM that synchronize the frame buffer with the display using the driver
401  bool update( void );
402  //Swap source color for dest color for each sprite
403  int change_color( Color source, Color dest );
404  //Clear the screen to solid black, even if there is no black in the palette
405  int clear( void );
406  //Clear the screen with given colors from the palette. Return number of sprites updated
407  int clear( Color color_tmp );
408  //Print a character on screen with given palette colors. Return number of sprites updated.
409  int print( int origin_h, int origin_w, char c, Color background, Color foreground );
410  //Print character with just foreground color. use default colors for background
411  int print( int origin_h, int origin_w, char c, Color foreground );
412  //Print character. Use default colors
413  int print( int origin_h, int origin_w, char c );
414  //Print a string with given colors from the palette. Return number of sprites updated
415  int print( int origin_h, int origin_w, const char *str, Color background, Color foreground );
416  //Print string with just foreground color. use default colors for background
417  int print( int origin_h, int origin_w, const char *str, Color foreground );
418  //Print string. Use default colors
419  int print( int origin_h, int origin_w, const char *str );
420  //Print number with given colors. Number format configuration is handled by set_format. Return number of sprites updated
421  int print( int origin_h, int origin_w, int num, Color background, Color foreground );
422  //Print number with just foreground color. Number format configuration is handled by set_format.
423  int print( int origin_h, int origin_w, int num, Color foreground );
424  //Print number. Use default colors. Number format configuration is handled by set_format.
425  int print( int origin_h, int origin_w, int num );
426  //Draw a solid color sprite on the screen
427  int paint( int origin_h, int origin_w, Color color );
428  //Show the current error code on the screen. green foreground for ok. red foreground for error
429  int print_err( int origin_h, int origin_w );
430 
431  //Visible only inside the class
432  private:
433  /*********************************************************************************************************************************************************
434  **********************************************************************************************************************************************************
435  ** PRIVATE ENUM
436  **********************************************************************************************************************************************************
437  *********************************************************************************************************************************************************/
438 
440  typedef enum _Fsm_state
441  {
442  SCAN_SPRITE, //Search for a sprite
443  SEND_SPRITE, //Ask the Display driver to send sprites to the physical display
445 
446  /*********************************************************************************************************************************************************
447  **********************************************************************************************************************************************************
448  ** PRIVATE STRUCT
449  **********************************************************************************************************************************************************
450  *********************************************************************************************************************************************************/
451 
453  typedef struct _Frame_buffer_sprite
454  {
455  //true: this sprite was changed since last scan | false: this sprite does not need updating
456  uint8_t f_update : 1;
457  //sprite index inside the sprite table. A number are special sprite. Not all sprites are mapped
458  uint8_t sprite_index : Screen::Config::SPRITE_SIZE_BIT;
459  //foreground palette color index
460  uint8_t foreground_color : Screen::Config::PALETTE_SIZE_BIT;
461  //background palette color index
462  uint8_t background_color : Screen::Config::PALETTE_SIZE_BIT;
464 
466  typedef struct _Fsm_status
467  {
468  //width and height scan indexes
469  uint16_t scan_w, scan_h;
470  //Index withing the sprite sending sequence. Number of steps is defined inside the driver
471  uint8_t cnt;
472  //Status of the scan
475 
477  typedef struct _Format_number
478  {
479  //Number of characters allowed for the number. 0 means no limit
480  int size;
481  //Number alignment
483  //Number format
485  //Base Exponent for the engineering number notation
486  int8_t eng_exp;
488 
489  /*********************************************************************************************************************************************************
490  **********************************************************************************************************************************************************
491  ** PRIVATE INIT
492  **********************************************************************************************************************************************************
493  *********************************************************************************************************************************************************/
494 
495  //Initialize class vars
496  bool init_class_vars( void );
497  //Initialize the sprite frame buffer
498  bool init_frame_buffer( void );
499  //Initialize the default colors
500  bool init_default_colors( void );
501  //Initialize the default color palette
502  bool init_palette( void );
503  //Initialize Screen FSM
504  bool init_fsm( void );
505 
506  /*********************************************************************************************************************************************************
507  **********************************************************************************************************************************************************
508  ** PRIVATE TESTERS
509  **********************************************************************************************************************************************************
510  *********************************************************************************************************************************************************/
511 
512  //Return true if the character is in the ascii sprite table
513  bool is_valid_char( char c );
514  //return true if the sprite make use of the background palette color
515  bool is_using_background( uint8_t sprite );
516  //return true if the sprite make use of the foreground palette color
517  bool is_using_foreground( uint8_t sprite );
518  //true = sprite_a functionally the same as sprite_b
519  bool is_same_sprite( Frame_buffer_sprite sprite_a, Frame_buffer_sprite sprite_b );
520 
521  /*********************************************************************************************************************************************************
522  **********************************************************************************************************************************************************
523  ** PRIVATE METHODS
524  **********************************************************************************************************************************************************
525  *********************************************************************************************************************************************************/
526 
527  //Register a sprite for draw in the display driver if possible. Sprite can be xomplex color map or solid color
528  int8_t register_sprite( uint16_t index_h, uint16_t index_w );
529  //Update a sprite in the frame buffer and mark it for update if required. Increase workload counter if required.
530  int8_t update_sprite( uint16_t index_h, uint16_t index_w, Frame_buffer_sprite new_sprite );
531  //Report an error in the Screen class
532  void report_error( Error error_code );
533 
534  /*********************************************************************************************************************************************************
535  **********************************************************************************************************************************************************
536  ** PRIVATE DEBUGGERS
537  **********************************************************************************************************************************************************
538  *********************************************************************************************************************************************************/
539 
540  #ifdef ENABLE_DEBUG
541 
542  void show_frame_sprite( Frame_buffer_sprite sprite_tmp )
543  {
544  DPRINT("update: %d | index: %5d | background: %5d | foreground: %5d |\n", sprite_tmp.f_update, sprite_tmp.sprite_index, sprite_tmp.background_color, sprite_tmp.foreground_color );
545  DPRINT("decoded background color: %6x | decoded foreground color: %6x |\n", g_palette[sprite_tmp.background_color], sprite_tmp.foreground_color );
546  return;
547  }
548 
549  void show_pixels( void )
550  {
551  DENTER_ARG("oh: %5d, ow: %5d, sh: %5d, sw: %5d\n", g_sprite.origin_h, g_sprite.origin_w, g_sprite.size_h, g_sprite.size_w);
552 
553  for (int th = 0;th < g_sprite.size_h;th++)
554  {
555  DPRINT("");
556  for (int tw = 0;tw < g_sprite.size_w;tw++)
557  {
558  DPRINT_NOTAB("%6x | ", g_pixel_data[th *g_sprite.size_w +tw]);
559  }
560  DPRINT_NOTAB("\n");
561  }
562 
563  DRETURN();
564  return;
565  }
566 
567  void show_palette( void )
568  {
569  DENTER();
570  for (int t = 0;t < Config::PALETTE_SIZE;t++)
571  {
572  DPRINT("%d -> %6x\n", t, g_palette[t] );
573 
574  }
575 
576  DRETURN();
577  return;
578  }
579 
580  #endif
581 
582  /*********************************************************************************************************************************************************
583  **********************************************************************************************************************************************************
584  ** PRIVATE VARS
585  **********************************************************************************************************************************************************
586  *********************************************************************************************************************************************************/
587 
594  uint16_t g_palette[ Config::PALETTE_SIZE ];
596  Frame_buffer_sprite g_frame_buffer[ Config::FRAME_BUFFER_HEIGHT ][ Config::FRAME_BUFFER_WIDTH ];
598  uint16_t g_pending_cnt;
600  uint16_t g_pixel_data[ Config::SPRITE_PIXEL_COUNT ];
605 
606  //Support for font with height of 10 pixels
607  #if FONT_HEIGHT == 10
608  //Font: Courier New 8 with two rows removed from bot and four rows removed from top
610  static constexpr uint8_t g_ascii_sprites[96*10] =
611  {
612  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //char: 32 ' '
613  0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, //char: 33 '!'
614  0x6C, 0x6C, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //char: 34 '"'
615  0x48, 0x24, 0x7E, 0x24, 0x24, 0x7E, 0x24, 0x12, 0x12, 0x00, //char: 35 '#'
616  0x38, 0x24, 0x04, 0x18, 0x20, 0x24, 0x1C, 0x10, 0x10, 0x00, //char: 36 '$'
617  0x04, 0x0A, 0x04, 0x30, 0x0E, 0x10, 0x28, 0x10, 0x00, 0x00, //char: 37 '%'
618  0x00, 0x70, 0x08, 0x08, 0x18, 0x54, 0x24, 0x78, 0x00, 0x00, //char: 38 '&'
619  0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //char: 39 '''
620  0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, //char: 40 '('
621  0x04, 0x04, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, //char: 41 ')'
622  0x10, 0x7C, 0x10, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, //char: 42 '*'
623  0x00, 0x10, 0x10, 0x10, 0xFE, 0x10, 0x10, 0x10, 0x00, 0x00, //char: 43 '+'
624  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x08, 0x0C, 0x04, //char: 44 ','
625  0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, //char: 45 '-'
626  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, //char: 46 '.'
627  0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x00, //char: 47 '/'
628  0x3C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, //char: 48 '0'
629  0x10, 0x1C, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7C, 0x00, 0x00, //char: 49 '1'
630  0x1C, 0x22, 0x20, 0x10, 0x08, 0x04, 0x22, 0x3E, 0x00, 0x00, //char: 50 '2'
631  0x1C, 0x22, 0x20, 0x18, 0x20, 0x20, 0x22, 0x1C, 0x00, 0x00, //char: 51 '3'
632  0x30, 0x28, 0x24, 0x24, 0x7E, 0x20, 0x20, 0x70, 0x00, 0x00, //char: 52 '4'
633  0x7C, 0x04, 0x04, 0x3C, 0x40, 0x40, 0x42, 0x3C, 0x00, 0x00, //char: 53 '5'
634  0x70, 0x08, 0x04, 0x3C, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, //char: 54 '6'
635  0x7E, 0x42, 0x40, 0x20, 0x20, 0x10, 0x10, 0x10, 0x00, 0x00, //char: 55 '7'
636  0x3C, 0x42, 0x42, 0x3C, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, //char: 56 '8'
637  0x3C, 0x42, 0x42, 0x42, 0x7C, 0x40, 0x20, 0x1E, 0x00, 0x00, //char: 57 '9'
638  0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, //char: 58 ':'
639  0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x0C, 0x04, 0x00, //char: 59 ';'
640  0x00, 0x40, 0x30, 0x08, 0x06, 0x08, 0x30, 0x40, 0x00, 0x00, //char: 60 '<'
641  0x00, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, //char: 61 '='
642  0x00, 0x02, 0x0C, 0x10, 0x60, 0x10, 0x0C, 0x02, 0x00, 0x00, //char: 62 '>'
643  0x38, 0x44, 0x40, 0x40, 0x20, 0x10, 0x00, 0x18, 0x00, 0x00, //char: 63 '?'
644  0x22, 0x22, 0x32, 0x2A, 0x2A, 0x32, 0x02, 0x22, 0x1C, 0x00, //char: 64 '@'
645  0x18, 0x10, 0x28, 0x28, 0x28, 0x38, 0x44, 0xEE, 0x00, 0x00, //char: 65 'A'
646  0x3E, 0x44, 0x44, 0x3C, 0x44, 0x44, 0x44, 0x3E, 0x00, 0x00, //char: 66 'B'
647  0x78, 0x44, 0x02, 0x02, 0x02, 0x02, 0x44, 0x38, 0x00, 0x00, //char: 67 'C'
648  0x1E, 0x24, 0x44, 0x44, 0x44, 0x44, 0x24, 0x1E, 0x00, 0x00, //char: 68 'D'
649  0x7E, 0x44, 0x14, 0x1C, 0x14, 0x04, 0x44, 0x7E, 0x00, 0x00, //char: 69 'E'
650  0x7E, 0x44, 0x14, 0x1C, 0x14, 0x04, 0x04, 0x0E, 0x00, 0x00, //char: 70 'F'
651  0x78, 0x44, 0x02, 0x02, 0xE2, 0x42, 0x44, 0x38, 0x00, 0x00, //char: 71 'G'
652  0xEE, 0x44, 0x44, 0x7C, 0x44, 0x44, 0x44, 0xEE, 0x00, 0x00, //char: 72 'H'
653  0x7C, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7C, 0x00, 0x00, //char: 73 'I'
654  0x78, 0x20, 0x20, 0x20, 0x22, 0x22, 0x22, 0x1C, 0x00, 0x00, //char: 74 'J'
655  0xEE, 0x44, 0x24, 0x14, 0x1C, 0x24, 0x44, 0xCE, 0x00, 0x00, //char: 75 'K'
656  0x0E, 0x04, 0x04, 0x04, 0x04, 0x44, 0x44, 0x7E, 0x00, 0x00, //char: 76 'L'
657  0xEE, 0x6C, 0x6C, 0x54, 0x54, 0x44, 0x44, 0xEE, 0x00, 0x00, //char: 77 'M'
658  0xE7, 0x46, 0x4A, 0x4A, 0x52, 0x52, 0x62, 0x67, 0x00, 0x00, //char: 78 'N'
659  0x38, 0x44, 0x82, 0x82, 0x82, 0x82, 0x44, 0x38, 0x00, 0x00, //char: 79 'O'
660  0x3E, 0x44, 0x44, 0x44, 0x3C, 0x04, 0x04, 0x0E, 0x00, 0x00, //char: 80 'P'
661  0x38, 0x44, 0x82, 0x82, 0x82, 0x82, 0x44, 0x38, 0xF8, 0x00, //char: 81 'Q'
662  0x3E, 0x44, 0x44, 0x44, 0x3C, 0x24, 0x44, 0x8E, 0x00, 0x00, //char: 82 'R'
663  0x5C, 0x62, 0x02, 0x3C, 0x40, 0x40, 0x46, 0x3A, 0x00, 0x00, //char: 83 'S'
664  0xFE, 0x92, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, //char: 84 'T'
665  0xEE, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, //char: 85 'U'
666  0xE7, 0x42, 0x42, 0x24, 0x24, 0x24, 0x18, 0x18, 0x00, 0x00, //char: 86 'V'
667  0xEE, 0x44, 0x44, 0x54, 0x54, 0x54, 0x54, 0x28, 0x00, 0x00, //char: 87 'W'
668  0xEE, 0x44, 0x28, 0x10, 0x10, 0x28, 0x44, 0xEE, 0x00, 0x00, //char: 88 'X'
669  0xEE, 0x44, 0x28, 0x28, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, //char: 89 'Y'
670  0x7C, 0x44, 0x20, 0x10, 0x10, 0x08, 0x44, 0x7C, 0x00, 0x00, //char: 90 'Z'
671  0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, //char: 91 '['
672  0x02, 0x04, 0x04, 0x08, 0x08, 0x08, 0x10, 0x10, 0x10, 0x00, //char: 92 '\'
673  0x0E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0E, //char: 93 ']'
674  0x08, 0x14, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //char: 94 '^'
675  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //char: 95 '_'
676  0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //char: 96 '`'
677  0x00, 0x00, 0x3C, 0x42, 0x7C, 0x42, 0x62, 0xDC, 0x00, 0x00, //char: 97 'a'
678  0x03, 0x02, 0x3A, 0x46, 0x42, 0x42, 0x46, 0x3B, 0x00, 0x00, //char: 98 'b'
679  0x00, 0x00, 0x5C, 0x62, 0x02, 0x02, 0x42, 0x3C, 0x00, 0x00, //char: 99 'c'
680  0x60, 0x40, 0x5C, 0x62, 0x42, 0x42, 0x62, 0xDC, 0x00, 0x00, //char: 100 'd'
681  0x00, 0x00, 0x3C, 0x42, 0x7E, 0x02, 0x02, 0x7C, 0x00, 0x00, //char: 101 'e'
682  0x70, 0x08, 0x7E, 0x08, 0x08, 0x08, 0x08, 0x7E, 0x00, 0x00, //char: 102 'f'
683  0x00, 0x00, 0xDC, 0x62, 0x42, 0x42, 0x62, 0x5C, 0x40, 0x3C, //char: 103 'g'
684  0x06, 0x04, 0x34, 0x4C, 0x44, 0x44, 0x44, 0xEE, 0x00, 0x00, //char: 104 'h'
685  0x10, 0x00, 0x1C, 0x10, 0x10, 0x10, 0x10, 0x7C, 0x00, 0x00, //char: 105 'i'
686  0x10, 0x00, 0x3C, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1E, //char: 106 'j'
687  0x06, 0x04, 0xF4, 0x24, 0x1C, 0x14, 0x24, 0xE6, 0x00, 0x00, //char: 107 'k'
688  0x18, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7C, 0x00, 0x00, //char: 108 'l'
689  0x00, 0x00, 0x4B, 0xB6, 0x92, 0x92, 0x92, 0xB7, 0x00, 0x00, //char: 109 'm'
690  0x00, 0x00, 0x36, 0x4C, 0x44, 0x44, 0x44, 0xEE, 0x00, 0x00, //char: 110 'n'
691  0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, //char: 111 'o'
692  0x00, 0x00, 0x36, 0x4C, 0x44, 0x44, 0x44, 0x3C, 0x04, 0x0E, //char: 112 'p'
693  0x00, 0x00, 0xDC, 0x62, 0x42, 0x42, 0x62, 0x5C, 0x40, 0xE0, //char: 113 'q'
694  0x00, 0x00, 0x76, 0x0C, 0x04, 0x04, 0x04, 0x3E, 0x00, 0x00, //char: 114 'r'
695  0x00, 0x00, 0x7C, 0x42, 0x3C, 0x40, 0x42, 0x3E, 0x00, 0x00, //char: 115 's'
696  0x00, 0x04, 0x3E, 0x04, 0x04, 0x04, 0x44, 0x38, 0x00, 0x00, //char: 116 't'
697  0x00, 0x00, 0x66, 0x44, 0x44, 0x44, 0x64, 0xD8, 0x00, 0x00, //char: 117 'u'
698  0x00, 0x00, 0xE7, 0x42, 0x24, 0x24, 0x18, 0x18, 0x00, 0x00, //char: 118 'v'
699  0x00, 0x00, 0xEE, 0x44, 0x54, 0x54, 0x54, 0x28, 0x00, 0x00, //char: 119 'w'
700  0x00, 0x00, 0x66, 0x24, 0x18, 0x18, 0x24, 0x66, 0x00, 0x00, //char: 120 'x'
701  0x00, 0x00, 0xEE, 0x44, 0x44, 0x28, 0x28, 0x10, 0x10, 0x1C, //char: 121 'y'
702  0x00, 0x00, 0x7C, 0x24, 0x10, 0x08, 0x44, 0x7C, 0x00, 0x00, //char: 122 'z'
703  0x10, 0x08, 0x08, 0x08, 0x04, 0x08, 0x08, 0x08, 0x10, 0x00, //char: 123 '{'
704  0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, //char: 124 '|'
705  0x04, 0x08, 0x08, 0x08, 0x10, 0x08, 0x08, 0x08, 0x04, 0x00, //char: 125 '}'
706  0x00, 0x00, 0x00, 0x4C, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, //char: 126 '~'
707  0xC6, 0xBA, 0xBE, 0xBE, 0xDE, 0xEE, 0xFE, 0xEE, 0xEE, 0x7C, //char: 127 ' '
708  };
709 
710  //Support for font with height of 16 pixels
711  #elif FONT_HEIGHT == 16
712  //Font: NSimSun 11 with one row added on top
714  static constexpr uint8_t g_ascii_sprites[96*16] =
715  {
716  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //char: 32 ' '
717  0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08, 0x08, 0x00, 0x00, //char: 33 '!'
718  0x00, 0x00, 0x28, 0x14, 0x14, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //char: 34 '"'
719  0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x7E, 0x24, 0x24, 0x24, 0x7E, 0x24, 0x24, 0x24, 0x00, 0x00, //char: 35 '#'
720  0x00, 0x00, 0x00, 0x10, 0x3C, 0x52, 0x52, 0x14, 0x18, 0x30, 0x50, 0x52, 0x52, 0x3C, 0x10, 0x10, //char: 36 '$'
721  0x00, 0x00, 0x00, 0x00, 0x22, 0x25, 0x15, 0x15, 0x2D, 0x5A, 0x54, 0x54, 0x52, 0x22, 0x00, 0x00, //char: 37 '%'
722  0x00, 0x00, 0x00, 0x00, 0x0C, 0x12, 0x12, 0x0A, 0x66, 0x25, 0x25, 0x29, 0x91, 0x6E, 0x00, 0x00, //char: 38 '&'
723  0x00, 0x00, 0x06, 0x04, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //char: 39 '''
724  0x00, 0x00, 0x40, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x20, 0x40, 0x00, //char: 40 '('
725  0x00, 0x00, 0x01, 0x02, 0x04, 0x04, 0x08, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x02, 0x01, 0x00, //char: 41 ')'
726  0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x6B, 0x1C, 0x1C, 0x6B, 0x08, 0x08, 0x00, 0x00, 0x00, //char: 42 '*'
727  0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0xFE, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, //char: 43 '+'
728  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x04, 0x04, 0x02, //char: 44 ','
729  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //char: 45 '-'
730  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, //char: 46 '.'
731  0x00, 0x00, 0x40, 0x20, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x00, //char: 47 '/'
732  0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00, 0x00, //char: 48 '0'
733  0x00, 0x00, 0x00, 0x00, 0x08, 0x0E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3E, 0x00, 0x00, //char: 49 '1'
734  0x00, 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x40, 0x20, 0x10, 0x08, 0x04, 0x42, 0x7E, 0x00, 0x00, //char: 50 '2'
735  0x00, 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x20, 0x18, 0x20, 0x40, 0x42, 0x42, 0x3C, 0x00, 0x00, //char: 51 '3'
736  0x00, 0x00, 0x00, 0x00, 0x20, 0x30, 0x30, 0x28, 0x24, 0x22, 0xFE, 0x20, 0x20, 0x78, 0x00, 0x00, //char: 52 '4'
737  0x00, 0x00, 0x00, 0x00, 0x7E, 0x02, 0x02, 0x3E, 0x42, 0x40, 0x40, 0x42, 0x42, 0x3C, 0x00, 0x00, //char: 53 '5'
738  0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x02, 0x3A, 0x46, 0x42, 0x42, 0x42, 0x44, 0x38, 0x00, 0x00, //char: 54 '6'
739  0x00, 0x00, 0x00, 0x00, 0x7E, 0x42, 0x20, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, //char: 55 '7'
740  0x00, 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x3C, 0x24, 0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, //char: 56 '8'
741  0x00, 0x00, 0x00, 0x00, 0x1C, 0x22, 0x42, 0x42, 0x62, 0x5C, 0x40, 0x40, 0x24, 0x18, 0x00, 0x00, //char: 57 '9'
742  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, //char: 58 ':'
743  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, //char: 59 ';'
744  0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, //char: 60 '<'
745  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, //char: 61 '='
746  0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x40, 0x40, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, //char: 62 '>'
747  0x00, 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x20, 0x10, 0x10, 0x00, 0x18, 0x18, 0x00, 0x00, //char: 63 '?'
748  0x00, 0x00, 0x00, 0x00, 0x1C, 0x22, 0x59, 0x55, 0x55, 0x55, 0x55, 0x39, 0x42, 0x3C, 0x00, 0x00, //char: 64 '@'
749  0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x14, 0x14, 0x14, 0x14, 0x3E, 0x22, 0x22, 0x77, 0x00, 0x00, //char: 65 'A'
750  0x00, 0x00, 0x00, 0x00, 0x3F, 0x42, 0x42, 0x22, 0x1E, 0x22, 0x42, 0x42, 0x42, 0x3F, 0x00, 0x00, //char: 66 'B'
751  0x00, 0x00, 0x00, 0x00, 0x7C, 0x42, 0x41, 0x01, 0x01, 0x01, 0x01, 0x41, 0x22, 0x1C, 0x00, 0x00, //char: 67 'C'
752  0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x22, 0x1F, 0x00, 0x00, //char: 68 'D'
753  0x00, 0x00, 0x00, 0x00, 0x3F, 0x42, 0x12, 0x12, 0x1E, 0x12, 0x12, 0x02, 0x42, 0x3F, 0x00, 0x00, //char: 69 'E'
754  0x00, 0x00, 0x00, 0x00, 0x3F, 0x42, 0x12, 0x12, 0x1E, 0x12, 0x12, 0x02, 0x02, 0x07, 0x00, 0x00, //char: 70 'F'
755  0x00, 0x00, 0x00, 0x00, 0x3C, 0x22, 0x21, 0x01, 0x01, 0x01, 0x71, 0x21, 0x22, 0x1C, 0x00, 0x00, //char: 71 'G'
756  0x00, 0x00, 0x00, 0x00, 0x77, 0x22, 0x22, 0x22, 0x3E, 0x22, 0x22, 0x22, 0x22, 0x77, 0x00, 0x00, //char: 72 'H'
757  0x00, 0x00, 0x00, 0x00, 0x3E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3E, 0x00, 0x00, //char: 73 'I'
758  0x00, 0x00, 0x00, 0x00, 0x7C, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x0F, //char: 74 'J'
759  0x00, 0x00, 0x00, 0x00, 0x77, 0x22, 0x12, 0x0A, 0x0E, 0x0A, 0x12, 0x12, 0x22, 0x77, 0x00, 0x00, //char: 75 'K'
760  0x00, 0x00, 0x00, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x42, 0x7F, 0x00, 0x00, //char: 76 'L'
761  0x00, 0x00, 0x00, 0x00, 0x77, 0x36, 0x36, 0x36, 0x36, 0x2A, 0x2A, 0x2A, 0x2A, 0x6B, 0x00, 0x00, //char: 77 'M'
762  0x00, 0x00, 0x00, 0x00, 0x77, 0x26, 0x26, 0x2A, 0x2A, 0x2A, 0x32, 0x32, 0x32, 0x27, 0x00, 0x00, //char: 78 'N'
763  0x00, 0x00, 0x00, 0x00, 0x1C, 0x22, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x22, 0x1C, 0x00, 0x00, //char: 79 'O'
764  0x00, 0x00, 0x00, 0x00, 0x3F, 0x42, 0x42, 0x42, 0x3E, 0x02, 0x02, 0x02, 0x02, 0x07, 0x00, 0x00, //char: 80 'P'
765  0x00, 0x00, 0x00, 0x00, 0x1C, 0x22, 0x41, 0x41, 0x41, 0x41, 0x41, 0x4D, 0x32, 0x1C, 0x60, 0x00, //char: 81 'Q'
766  0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x22, 0x22, 0x1E, 0x0A, 0x12, 0x12, 0x22, 0x67, 0x00, 0x00, //char: 82 'R'
767  0x00, 0x00, 0x00, 0x00, 0x7C, 0x42, 0x42, 0x02, 0x0C, 0x30, 0x40, 0x42, 0x42, 0x3E, 0x00, 0x00, //char: 83 'S'
768  0x00, 0x00, 0x00, 0x00, 0x7F, 0x49, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1C, 0x00, 0x00, //char: 84 'T'
769  0x00, 0x00, 0x00, 0x00, 0x77, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1C, 0x00, 0x00, //char: 85 'U'
770  0x00, 0x00, 0x00, 0x00, 0x77, 0x22, 0x22, 0x22, 0x14, 0x14, 0x14, 0x14, 0x08, 0x08, 0x00, 0x00, //char: 86 'V'
771  0x00, 0x00, 0x00, 0x00, 0x6B, 0x2A, 0x2A, 0x2A, 0x2A, 0x36, 0x14, 0x14, 0x14, 0x14, 0x00, 0x00, //char: 87 'W'
772  0x00, 0x00, 0x00, 0x00, 0x77, 0x22, 0x14, 0x14, 0x08, 0x08, 0x14, 0x14, 0x22, 0x77, 0x00, 0x00, //char: 88 'X'
773  0x00, 0x00, 0x00, 0x00, 0x77, 0x22, 0x22, 0x14, 0x14, 0x08, 0x08, 0x08, 0x08, 0x1C, 0x00, 0x00, //char: 89 'Y'
774  0x00, 0x00, 0x00, 0x00, 0x7C, 0x22, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x44, 0x7E, 0x00, 0x00, //char: 90 'Z'
775  0x00, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, //char: 91 '['
776  0x00, 0x00, 0x00, 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x20, 0x40, //char: 92 '\'
777  0x00, 0x00, 0x1E, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1E, 0x00, //char: 93 ']'
778  0x00, 0x00, 0x18, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //char: 94 '^'
779  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, //char: 95 '_'
780  0x00, 0x06, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //char: 96 '`'
781  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x22, 0x30, 0x2C, 0x22, 0x32, 0x6C, 0x00, 0x00, //char: 97 'a'
782  0x00, 0x00, 0x00, 0x03, 0x02, 0x02, 0x02, 0x3A, 0x46, 0x42, 0x42, 0x42, 0x42, 0x3E, 0x00, 0x00, //char: 98 'b'
783  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x02, 0x02, 0x02, 0x44, 0x38, 0x00, 0x00, //char: 99 'c'
784  0x00, 0x00, 0x00, 0x60, 0x40, 0x40, 0x40, 0x7C, 0x42, 0x42, 0x42, 0x42, 0x62, 0xDC, 0x00, 0x00, //char: 100 'd'
785  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x7E, 0x02, 0x42, 0x3C, 0x00, 0x00, //char: 101 'e'
786  0x00, 0x00, 0x00, 0x30, 0x48, 0x08, 0x08, 0x3E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3E, 0x00, 0x00, //char: 102 'f'
787  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x22, 0x22, 0x1C, 0x02, 0x3C, 0x42, 0x42, 0x3C, //char: 103 'g'
788  0x00, 0x00, 0x00, 0x03, 0x02, 0x02, 0x02, 0x3A, 0x46, 0x42, 0x42, 0x42, 0x42, 0xE7, 0x00, 0x00, //char: 104 'h'
789  0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3E, 0x00, 0x00, //char: 105 'i'
790  0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x38, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x1E, //char: 106 'j'
791  0x00, 0x00, 0x00, 0x03, 0x02, 0x02, 0x02, 0x72, 0x12, 0x0A, 0x16, 0x12, 0x22, 0x77, 0x00, 0x00, //char: 107 'k'
792  0x00, 0x00, 0x00, 0x0E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3E, 0x00, 0x00, //char: 108 'l'
793  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x6B, 0x00, 0x00, //char: 109 'm'
794  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3B, 0x46, 0x42, 0x42, 0x42, 0x42, 0xE7, 0x00, 0x00, //char: 110 'n'
795  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00, 0x00, //char: 111 'o'
796  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3B, 0x46, 0x42, 0x42, 0x42, 0x46, 0x3A, 0x02, 0x07, //char: 112 'p'
797  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5C, 0x62, 0x42, 0x42, 0x42, 0x62, 0x5C, 0x40, 0xE0, //char: 113 'q'
798  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x4C, 0x04, 0x04, 0x04, 0x04, 0x1F, 0x00, 0x00, //char: 114 'r'
799  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x22, 0x02, 0x1C, 0x20, 0x22, 0x1E, 0x00, 0x00, //char: 115 's'
800  0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, 0x08, 0x08, 0x48, 0x30, 0x00, 0x00, //char: 116 't'
801  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x42, 0x42, 0x42, 0x42, 0x62, 0xDC, 0x00, 0x00, //char: 117 'u'
802  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x22, 0x22, 0x14, 0x14, 0x08, 0x08, 0x00, 0x00, //char: 118 'v'
803  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x2A, 0x2A, 0x2A, 0x14, 0x14, 0x14, 0x00, 0x00, //char: 119 'w'
804  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6E, 0x24, 0x18, 0x18, 0x18, 0x24, 0x76, 0x00, 0x00, //char: 120 'x'
805  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE7, 0x42, 0x24, 0x24, 0x18, 0x18, 0x08, 0x08, 0x06, //char: 121 'y'
806  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x22, 0x10, 0x08, 0x08, 0x44, 0x7E, 0x00, 0x00, //char: 122 'z'
807  0x00, 0x00, 0x60, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x60, 0x00, //char: 123 '{'
808  0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, //char: 124 '|'
809  0x00, 0x00, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x04, 0x04, 0x04, 0x04, 0x04, 0x06, 0x00, //char: 125 '}'
810  0x00, 0x04, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //char: 126 '~'
811  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //char: 127 ' '
812  };
813  #else
814  #error "ERR: Font size not supported"
815  #endif
816 }; //End Class: Screen
817 
818  /*********************************************************************************************************************************************************
819  **********************************************************************************************************************************************************
820  ** CONSTRUCTORS
821  **********************************************************************************************************************************************************
822  *********************************************************************************************************************************************************/
823 
824 /***************************************************************************/
827 /***************************************************************************/
830 /***************************************************************************/
831 
833 {
834  DENTER();
835  //----------------------------------------------------------------
836  // VARS
837  //----------------------------------------------------------------
838 
839  //----------------------------------------------------------------
840  // BODY
841  //----------------------------------------------------------------
842 
843  this -> init_class_vars();
844 
845  //----------------------------------------------------------------
846  // RETURN
847  //----------------------------------------------------------------
848  DRETURN();
849  return;
850 } //End constructor: Screen | void
851 
852  /*********************************************************************************************************************************************************
853  **********************************************************************************************************************************************************
854  ** DESTRUCTORS
855  **********************************************************************************************************************************************************
856  *********************************************************************************************************************************************************/
857 
858 /***************************************************************************/
861 /***************************************************************************/
864 /***************************************************************************/
865 
867 {
868  DENTER();
869  //----------------------------------------------------------------
870  // VARS
871  //----------------------------------------------------------------
872 
873  //----------------------------------------------------------------
874  // BODY
875  //----------------------------------------------------------------
876 
877  //----------------------------------------------------------------
878  // RETURN
879  //----------------------------------------------------------------
880  DRETURN();
881  return;
882 } //End Destructor: ~Screen | void |
883 
884  /*********************************************************************************************************************************************************
885  **********************************************************************************************************************************************************
886  ** PUBLIC INIT
887  **********************************************************************************************************************************************************
888  *********************************************************************************************************************************************************/
889 
890 /***************************************************************************/
893 /***************************************************************************/
897 /***************************************************************************/
898 
899 bool Screen::init( void )
900 {
901  DENTER();
902  //----------------------------------------------------------------
903  // VARS
904  //----------------------------------------------------------------
905 
906  //Return flag
907  bool f_ret = false;
908 
909  //----------------------------------------------------------------
910  // BODY
911  //----------------------------------------------------------------
912 
913  //Initialize the display driver. It handles phisical communication with the display and provide methods to write sprites
914  f_ret = this -> Longan_nano::Display::init();
915  //Initialize colors
916  this -> init_default_colors();
917  //Initialize the frame buffer
918  f_ret |= this -> init_frame_buffer();
919  //Initialize default palette
920  f_ret |= this -> init_palette();
921  //Initialize update FSM
922  f_ret |= this -> init_fsm();
923  //Clear the display to black
924  this -> Display::clear();
925 
926  //----------------------------------------------------------------
927  // RETURN
928  //----------------------------------------------------------------
929  DRETURN();
930  return f_ret;
931 } //End public init: init | void
932 
933 /***************************************************************************/
936 /***************************************************************************/
940 /***************************************************************************/
941 
943 {
944  DENTER();
945  //----------------------------------------------------------------
946  // VARS
947  //----------------------------------------------------------------
948 
949  //Return flag
950  bool f_ret = false;
951 
952  //----------------------------------------------------------------
953  // BODY
954  //----------------------------------------------------------------
955 
956  this -> init_default_colors();
957  f_ret |= this -> init_palette();
958  this -> Display::clear();
959 
960  //----------------------------------------------------------------
961  // RETURN
962  //----------------------------------------------------------------
963  DRETURN();
964  return f_ret; //OK
965 } //End public init: reset_colors | void
966 
967  /*********************************************************************************************************************************************************
968  **********************************************************************************************************************************************************
969  ** PUBLIC SETTER
970  **********************************************************************************************************************************************************
971  *********************************************************************************************************************************************************/
972 
973 /***************************************************************************/
976 /***************************************************************************/
984 /***************************************************************************/
985 
986 inline int Screen::set_color( int origin_h, int origin_w, Color background, Color foreground )
987 {
988  DENTER();
989  //----------------------------------------------------------------
990  // CHECK
991  //----------------------------------------------------------------
992 
993  //If: first character is outside the ascii sprite table
994  if ((origin_h < 0) || (origin_h >= Config::FRAME_BUFFER_HEIGHT) || (origin_w < 0) || (origin_w >= Config::FRAME_BUFFER_WIDTH))
995  {
996  DRETURN_ARG("ERR: out of the sprite table %5d %5d\n", origin_h, origin_w);
997  return true; //FAIL
998  }
999  //If: colors are bad
1000  if ((background >= (Color)Config::PALETTE_SIZE) || (foreground >= (Color)Config::PALETTE_SIZE))
1001  {
1002  DRETURN_ARG("ERR: bad default colors | Back: %3d | Fore: %3d |\n", background, foreground );
1003  return true; //FAIL
1004  }
1005 
1006  //----------------------------------------------------------------
1007  // BODY
1008  //----------------------------------------------------------------
1009 
1010  //Has the sprite changed?
1011  bool f_changed = false;
1012  //Fetch sprite
1013  Frame_buffer_sprite sprite_tmp = g_frame_buffer[origin_h][origin_w];
1014  //If: sprite uses color and color has changed
1015  if ((this -> is_using_background(sprite_tmp.sprite_index) == true) && (sprite_tmp.background_color != background))
1016  {
1017  //Update colors
1018  sprite_tmp.background_color = background;
1019  f_changed = true;
1020  }
1021  //If: sprite uses color and color has changed
1022  if ((this -> is_using_foreground(sprite_tmp.sprite_index) == true) && (sprite_tmp.foreground_color != foreground))
1023  {
1024  //Update colors
1025  sprite_tmp.foreground_color = foreground;
1026  f_changed = true;
1027  }
1028  //Number of sprites changed
1029  int ret;
1030  //If the sprite has changed
1031  if (f_changed == true)
1032  {
1033  //Update the frame buffer with the new sprite if needed
1034  ret = this -> update_sprite( origin_h, origin_w, sprite_tmp );
1035  }
1036 
1037  //----------------------------------------------------------------
1038  // RETURN
1039  //----------------------------------------------------------------
1040  DRETURN();
1041  return ret; //OK
1042 } //End public setter: set_color | int | int | Color | Color
1043 
1044 /***************************************************************************/
1047 /***************************************************************************/
1054 /***************************************************************************/
1055 
1056 int Screen::set_default_colors( Color new_background, Color new_foreground )
1057 {
1058  DENTER();
1059  //----------------------------------------------------------------
1060  // CHECK
1061  //----------------------------------------------------------------
1062 
1063  //If: colors are bad
1064  if ((new_background >= (Color)Config::PALETTE_SIZE) || (new_foreground >= (Color)Config::PALETTE_SIZE))
1065  {
1066  DRETURN_ARG("ERR: bad default colors | Back: %3d | Fore: %3d |\n", new_background, new_foreground );
1067  return -1; //FAIL
1068  }
1069 
1070  //----------------------------------------------------------------
1071  // VARS
1072  //----------------------------------------------------------------
1073 
1074  //Temp sprite
1075  Frame_buffer_sprite sprite_tmp;
1076  //Num of updated sprites
1077  int ret;
1078  //Compute branch flags
1079  Color old_background = this -> g_default_background_color;
1080  Color old_foreground = this -> g_default_foreground_color;
1081  bool f_background_change = (this -> g_default_background_color != new_background);
1082  bool f_foreground_change = (this -> g_default_foreground_color != new_foreground);
1083  //Number of sprites changed
1084  int num_changed_sprites = 0;
1085 
1086  //----------------------------------------------------------------
1087  // BODY
1088  //----------------------------------------------------------------
1089 
1090  //If: nothing to do
1091  if ( (f_background_change == false) && (f_foreground_change == false))
1092  {
1093  //Do nothing
1094  }
1095  //If: only background change
1096  if ( (f_background_change == true) && (f_foreground_change == false))
1097  {
1098  //Update defaults
1099  this -> g_default_background_color = new_background;
1100  //For: scan height
1101  for (uint8_t th = 0;th < Config::FRAME_BUFFER_HEIGHT;th++)
1102  {
1103  //For: scan width
1104  for (uint8_t tw = 0;tw < Config::FRAME_BUFFER_WIDTH;tw++)
1105  {
1106  //Fetch sprite
1107  sprite_tmp = this -> g_frame_buffer[ th ][ tw ];
1108  //If: the background is a color to be swapped and the character uses the background
1109  if ( (sprite_tmp.background_color == old_background) && (this -> is_using_background( sprite_tmp.sprite_index )) )
1110  {
1111  //Change the color
1112  sprite_tmp.background_color = new_background;
1113  //Update the sprite
1114  ret = this -> update_sprite( th, tw, sprite_tmp );
1115  //If: failed to update sprite
1116  if ((Config::PEDANTIC_CHECKS == true) && (ret < 0))
1117  {
1118  DRETURN_ARG("ERR: Failed to update sprite\n");
1119  return -1;
1120  }
1121  //If: either zero or one sprite was changed
1122  else
1123  {
1124  //Accumulate number of sprites changed
1125  num_changed_sprites += ret;
1126  }
1127  }
1128  } //End For: scan width
1129  } //For: scan height
1130  } //End If: only background change
1131  //If: only foreground change
1132  else if ( (f_background_change == false) && (f_foreground_change == true))
1133  {
1134  //Update defaults
1135  this -> g_default_foreground_color = new_foreground;
1136  //For: scan height
1137  for (uint8_t th = 0;th < Config::FRAME_BUFFER_HEIGHT;th++)
1138  {
1139  //For: scan width
1140  for (uint8_t tw = 0;tw < Config::FRAME_BUFFER_WIDTH;tw++)
1141  {
1142  //Fetch sprite
1143  sprite_tmp = this -> g_frame_buffer[ th ][ tw ];
1144  //If: the background is a color to be swapped and the character uses the background
1145  if ( (sprite_tmp.foreground_color == old_foreground) && (this -> is_using_foreground( sprite_tmp.sprite_index )) )
1146  {
1147  //Change the color
1148  sprite_tmp.foreground_color = new_foreground;
1149  //Update the sprite
1150  ret = this -> update_sprite( th, tw, sprite_tmp );
1151  //If: failed to update sprite
1152  if ((Config::PEDANTIC_CHECKS == true) && (ret < 0))
1153  {
1154  DRETURN_ARG("ERR: Failed to update sprite\n");
1155  return -1;
1156  }
1157  //If: either zero or one sprite was changed
1158  else
1159  {
1160  //Accumulate number of sprites changed
1161  num_changed_sprites += ret;
1162  }
1163  }
1164  } //End For: scan width
1165  } //For: scan height
1166  } //End If: only foreground change
1167  //If: both colors have changed
1168  else //if ( (f_background_change == true) && (f_foreground_change == true))
1169  {
1170  //Has sprite changed
1171  bool f_changed = false;
1172  //Update defaults
1173  this -> g_default_background_color = new_background;
1174  this -> g_default_foreground_color = new_foreground;
1175  //For: scan height
1176  for (uint8_t th = 0;th < Config::FRAME_BUFFER_HEIGHT;th++)
1177  {
1178  //For: scan width
1179  for (uint8_t tw = 0;tw < Config::FRAME_BUFFER_WIDTH;tw++)
1180  {
1181  //Fetch sprite
1182  sprite_tmp = this -> g_frame_buffer[ th ][ tw ];
1183  //If: the background is a color to be swapped and the character uses the background
1184  if ( (sprite_tmp.background_color == old_background) && (this -> is_using_background( sprite_tmp.sprite_index )) )
1185  {
1186  //Change the color
1187  f_changed = true;
1188  sprite_tmp.background_color = new_background;
1189  }
1190  //If: the background is a color to be swapped and the character uses the background
1191  if ( (sprite_tmp.foreground_color == old_foreground) && (this -> is_using_foreground( sprite_tmp.sprite_index )) )
1192  {
1193  //Change the color
1194  f_changed = true;
1195  sprite_tmp.foreground_color = new_foreground;
1196  }
1197  //If: Sprite has changed
1198  if (f_changed == true)
1199  {
1200  //Mark sprite for update
1201  sprite_tmp.f_update = true;
1202  //Update the sprite
1203  ret = this -> update_sprite( th, tw, sprite_tmp );
1204  //If: failed to update sprite
1205  if ((Config::PEDANTIC_CHECKS == true) && (ret < 0))
1206  {
1207  DRETURN_ARG("ERR: Failed to update sprite\n");
1208  return -1;
1209  }
1210  //If: either zero or one sprite was changed
1211  else
1212  {
1213  //Accumulate number of sprites changed
1214  num_changed_sprites += ret;
1215  }
1216  }
1217  } //End For: scan width
1218  } //For: scan height
1219  } //End If: both colors have changed
1220 
1221  //----------------------------------------------------------------
1222  // RETURN
1223  //----------------------------------------------------------------
1224  DRETURN();
1225  return num_changed_sprites; //Number of sprites changed
1226 } //End public setter: set_default_colors | Color | Color
1227 
1228 /***************************************************************************/
1231 /***************************************************************************/
1241 /***************************************************************************/
1242 
1243 int Screen::set_palette_color( Color palette_index, uint8_t r, uint8_t g, uint8_t b )
1244 {
1245  DENTER_ARG("source: %d |\n", palette_index);
1246  //----------------------------------------------------------------
1247  // CHECK
1248  //----------------------------------------------------------------
1249  //If: bad colors
1250  if ((Config::PEDANTIC_CHECKS == true) && (palette_index >= (Color)Config::PALETTE_SIZE))
1251  {
1252  DRETURN_ARG("ERR: bad palette index | source: %d |\n", palette_index );
1253  return -1;
1254  }
1255 
1256  //----------------------------------------------------------------
1257  // CHANGE PALETTE
1258  //----------------------------------------------------------------
1259 
1260  //Ask the display driver to compute the RGB color to the color supported by the screen
1261  uint16_t new_color = Display::color( r, g, b );
1262  //If: desired color is already in the palette
1263  if (this -> g_palette[ palette_index ] == new_color)
1264  {
1265  DRETURN();
1266  return 0;
1267  }
1268  //Set the color in the palette
1269  this -> g_palette[ palette_index ] = new_color;
1270 
1271  //----------------------------------------------------------------
1272  // MARK CHANGED SPRITES FOR UPDATE
1273  //----------------------------------------------------------------
1274 
1275  //Temp sprite
1276  Frame_buffer_sprite sprite_tmp;
1277  //Num of updated sprites
1278  int ret;
1279  bool f_sprite_changed;
1280  int num_changed_sprites = 0;
1281  //For: scan height
1282  for (uint8_t th = 0;th < Config::FRAME_BUFFER_HEIGHT;th++)
1283  {
1284  //For: scan width
1285  for (uint8_t tw = 0;tw < Config::FRAME_BUFFER_WIDTH;tw++)
1286  {
1287  //Fetch sprite
1288  sprite_tmp = this -> g_frame_buffer[ th ][ tw ];
1289  //Was sprite changed?
1290  f_sprite_changed = false;
1291  //If: the background is a color to be swapped and the character uses the background
1292  if ( (sprite_tmp.background_color == palette_index) && (this -> is_using_background( sprite_tmp.sprite_index )) )
1293  {
1294  f_sprite_changed = true;
1295  }
1296  //If: the foreground is a color to be swapped and the character uses the foreground
1297  if ( (sprite_tmp.foreground_color == palette_index) && (this -> is_using_foreground( sprite_tmp.sprite_index )) )
1298  {
1299  f_sprite_changed = true;
1300  }
1301  //If: sprite was changed
1302  if (f_sprite_changed == true)
1303  {
1304  //Update the sprite
1305  ret = this -> update_sprite( th, tw, sprite_tmp );
1306  //If: failed to update sprite
1307  if ((Config::PEDANTIC_CHECKS == true) && (ret < 0))
1308  {
1309  DRETURN_ARG("ERR: Failed to update sprite\n");
1310  return -1;
1311  }
1312  //If: either zero or one sprite was changed
1313  else
1314  {
1315  //Accumulate number of sprites changed
1316  num_changed_sprites += ret;
1317  }
1318  }
1319  } //End For: scan width
1320  } //For: scan height
1321 
1322  //----------------------------------------------------------------
1323  // RETURN
1324  //----------------------------------------------------------------
1325  DRETURN();
1326  return num_changed_sprites;
1327 } //End public setter: set_palette_color | Color | uint8_t | uint8_t | uint8_t |
1328 
1329 /***************************************************************************/
1332 /***************************************************************************/
1344 /***************************************************************************/
1345 
1346 inline bool Screen::set_format( int number_size, Format_align align, Format_format format )
1347 {
1348  DENTER_ARG("number_size: %d |align: %d | format: %d\n", number_size, (int)align, (int)format );
1349  //----------------------------------------------------------------
1350  // CHECK
1351  //----------------------------------------------------------------
1352  //If: bad number size
1353  if (number_size <= 0)
1354  {
1355  DENTER_ARG("ERR: bad number_size: %d\n", number_size );
1356  return true; //ERR
1357  }
1358 
1359  //----------------------------------------------------------------
1360  // BODY
1361  //----------------------------------------------------------------
1362 
1363  //Configure number format for the next print
1364  this -> g_format_number.size = number_size;
1365  this -> g_format_number.align = align;
1366  this -> g_format_number.format = format;
1367 
1368  //----------------------------------------------------------------
1369  // RETURN
1370  //----------------------------------------------------------------
1371  DRETURN();
1372  return false; //OK
1373 } //End public setter: set_format | int | Format_align | Format_format |
1374 
1375 /***************************************************************************/
1378 /***************************************************************************/
1391 /***************************************************************************/
1392 
1393 inline bool Screen::set_format( int number_size, Format_align align, Format_format format, int exp )
1394 {
1395  DENTER_ARG("number_size: %d |align: %d | format: %d | ENG exponent: %d\n", number_size, (int)align, (int)format, exp );
1396  //----------------------------------------------------------------
1397  // CHECK
1398  //----------------------------------------------------------------
1399  //If: bad number size
1400  if (number_size <= 0)
1401  {
1402  DENTER_ARG("ERR: bad number_size: %d\n", number_size );
1403  return true; //ERR
1404  }
1405  //If: bad exponent
1406  if ((exp < -6) || (exp > 6))
1407  {
1408  DENTER_ARG("ERR: bad ENG exponent: %d\n", exp );
1409  return true; //ERR
1410  }
1411 
1412  //----------------------------------------------------------------
1413  // BODY
1414  //----------------------------------------------------------------
1415 
1416  //Configure number format for the next print
1417  this -> g_format_number.size = number_size;
1418  this -> g_format_number.align = align;
1419  this -> g_format_number.format = format;
1420  //Configure ENG number exponent
1421  this -> g_format_number.eng_exp = exp;
1422 
1423  //----------------------------------------------------------------
1424  // RETURN
1425  //----------------------------------------------------------------
1426  DRETURN();
1427  return false; //OK
1428 } //End public setter: set_format | int | Format_align | Format_format | int |
1429 
1430  /*********************************************************************************************************************************************************
1431  **********************************************************************************************************************************************************
1432  ** PUBLIC GETTERS
1433  **********************************************************************************************************************************************************
1434  *********************************************************************************************************************************************************/
1435 
1436 /***************************************************************************/
1439 /***************************************************************************/
1443 /***************************************************************************/
1444 
1446 {
1447  DENTER(); //Trace Enter
1451  DRETURN_ARG("Pending: %d", this -> g_pending_cnt ); //Trace Return
1452  return this -> g_pending_cnt ; //OK
1453 } //end public getter: get_pending | void |
1454 
1455 /***************************************************************************/
1458 /***************************************************************************/
1462 /***************************************************************************/
1463 
1465 {
1466  DENTER(); //Trace Enter
1470  DRETURN_ARG("ERR%d", (int)this -> g_error_code ); //Trace Return
1471  return this -> g_error_code ; //OK
1472 } //end public getter: get_pending | void |
1473 
1474  /*********************************************************************************************************************************************************
1475  **********************************************************************************************************************************************************
1476  ** PUBLIC METHODS
1477  **********************************************************************************************************************************************************
1478  *********************************************************************************************************************************************************/
1479 
1480 /***************************************************************************/
1483 /***************************************************************************/
1488 /***************************************************************************/
1489 
1490 bool Screen::update( void )
1491 {
1492  DENTER();
1493  //----------------------------------------------------------------
1494  // VARS
1495  //----------------------------------------------------------------
1496 
1497  //Allows the FSM to run
1498  bool f_continue = true;
1499  //Temp FSM status
1500  Fsm_status status;
1501 
1502  //----------------------------------------------------------------
1503  // BODY
1504  //----------------------------------------------------------------
1505 
1506  //Snap status of the FSM
1507  status = this -> g_status;
1508  //While: the Screen FSM is allowed to run
1509  while (f_continue == true)
1510  {
1511  DPRINT("exe: %3d | w: %5d | h: %5d | cnt: %3d\n", status.phase, status.scan_w, status.scan_h, status.cnt );
1512  //If: I'm scanning for the next sprite to be updated
1513  if (status.phase == Fsm_state::SCAN_SPRITE)
1514  {
1515  //Fetch the sprite
1516  Frame_buffer_sprite sprite_tmp = this -> g_frame_buffer[ status.scan_h ][ status.scan_w ];
1517 
1518  //If: there are no sprites to be updated in the frame buffer
1519  if (this -> g_pending_cnt == 0)
1520  {
1521  //I'm done. Don't wasete time scanning
1522  f_continue = false;
1523  }
1524  //If: the sprite indexed is to be updated
1525  else if (sprite_tmp.f_update == true)
1526  {
1527  //This sprite is not to be updated anymore
1528  this -> g_frame_buffer[ status.scan_h ][ status.scan_w ].f_update = false;
1529  //If: pending counter is already zero
1530  if ((Config::PEDANTIC_CHECKS == true) && (this -> g_pending_cnt == 0))
1531  {
1532  //Algorithmic error
1533  this -> report_error( Screen::Error::PENDING_UNDERFLOW );
1534  DRETURN_ARG("ERR: %d\n", (int)this -> get_error() );
1535  return true;
1536  }
1537  //If: pending ccounter is valid
1538  else
1539  {
1540  //A pending sprite has been processed. This is the only code allowed to reduce workload
1541  this -> g_pending_cnt--;
1542  }
1543  DPRINT("REFRESH sprite h: %5d | w: %5d\n", status.scan_h, status.scan_w );
1544  //Compute the pixel data and try to register the sprite for draw inside the display driver
1545  int ret = this -> register_sprite( status.scan_h, status.scan_w );
1546  //If: no sprites were registered but no errors occurred
1547  if (ret == 0)
1548  {
1549  //Maybe a transparent sprite. Keep scanning for sprites
1550  }
1551  //If: sprite has been registered for draw
1552  else if (ret > 0)
1553  {
1554  //Begin execution of the driver FSM that sends pixel data to the screen
1555  status.phase = Fsm_state::SEND_SPRITE;
1556  //Count number of execution steps of the Display FSM
1557  status.cnt = 0;
1558  }
1559  //If: failed to register sprite
1560  else
1561  {
1562  DPRINT("ERR: Failed to register sprite\n");
1563  //Reset the update FSM
1564  this -> init_fsm();
1565  f_continue = false;
1566  }
1567 
1568  //Move on to next sprite
1569  //if: space to advance in width
1570  if (status.scan_w < Config::FRAME_BUFFER_WIDTH -1)
1571  {
1572  //Move cursor right
1573  status.scan_w++;
1574  }
1575  //If: space to advance in height
1576  else if (status.scan_h < Config::FRAME_BUFFER_HEIGHT -1)
1577  {
1578  //Get back left
1579  status.scan_w = 0;
1580  //Move down in height (2° rank of frame buffer vector)
1581  status.scan_h++;
1582  }
1583  //if: scan limit
1584  else
1585  {
1586  //Get back to the top left
1587  status.scan_h = 0;
1588  status.scan_w = 0;
1589  }
1590  } //End If: the sprite indexed is to be updated
1591  //If: I'm allowed to scan for more sprites
1592  else if (status.cnt < Config::SPRITE_SCAN_LIMIT -1)
1593  {
1594  //Move on to next sprite
1595  //if: space to advance in width
1596  if (status.scan_w < Config::FRAME_BUFFER_WIDTH -1)
1597  {
1598  //Move cursor right
1599  status.scan_w++;
1600  }
1601  //If: space to advance in height
1602  else if (status.scan_h < Config::FRAME_BUFFER_HEIGHT -1)
1603  {
1604  //Get back left
1605  status.scan_w = 0;
1606  //Move down in height (2nd rank of frame buffer vector)
1607  status.scan_h++;
1608  }
1609  //if: scan limit
1610  else
1611  {
1612  //Get back to the top left
1613  status.scan_h = 0;
1614  status.scan_w = 0;
1615  }
1616  //I scanned a sprite
1617  status.cnt++;
1618  } //End if: I'm allowed to scan for more sprites
1619  //If: I reached the scan limit
1620  else
1621  {
1622  //Reset the scan sprite counter
1623  status.cnt = 0;
1624  //I'm not allowed to scan more sprite. Release execution of the FSM
1625  f_continue = false;
1626  } //End If: I reached the scan limit
1627  } //End If: I'm scanning for the next sprite to be updated
1628  //If: I'm in the process of sending a sprite
1629  else if (status.phase == Fsm_state::SEND_SPRITE)
1630  {
1631  DPRINT("Execute display FSM: step: %d\n", status.cnt);
1632  //Have the display drivere execute a step in its internal FSM. FSMs are partitioned in logical and physical for future expansion of the screen class.
1633  bool f_ret = this -> Display::update_sprite();
1634  //if: Display driver FSM is busy
1635  if (f_ret == true)
1636  {
1637  //A FSM step was executed
1638  status.cnt++;
1639  //Driver still has work to do. Do not scan for more work.
1640  }
1641  //if: Display driver FSM is IDLE
1642  else
1643  {
1644  DPRINT("Display FSM IDLE\n");
1645  //reset status counter
1646  status.cnt = 0;
1647  //Driver FSM is done. I can scan for more work, if any is available.
1648  status.phase = Fsm_state::SCAN_SPRITE;
1649  }
1650  //
1651  f_continue = false;
1652  } //End If: I'm in the process of sending a sprite
1653  //If: Algorithmic error
1654  else
1655  {
1656  //Reset the update FSM
1657  this -> init_fsm();
1658  f_continue = false;
1659  } //End If: Algorithmic error
1660  } //End While: the Screen FSM is allowed to run
1661  //Write back FSM status
1662  this -> g_status = status;
1663 
1664  //----------------------------------------------------------------
1665  // RETURN
1666  //----------------------------------------------------------------
1667  DRETURN_ARG("exe: %3d | w: %5d | h: %5d | cnt: %3d\n", status.phase, status.scan_w, status.scan_h, status.cnt );
1668  return false; //OK
1669 } //End public method: update | void
1670 
1671 /***************************************************************************/
1674 /***************************************************************************/
1681 /***************************************************************************/
1682 
1683 int Screen::change_color( Color source, Color dest )
1684 {
1685  DENTER_ARG("source: %d | dest: %d |\n", source, dest);
1686  //----------------------------------------------------------------
1687  // CHECK
1688  //----------------------------------------------------------------
1689  //If: bad colors
1690  if ((Config::PEDANTIC_CHECKS == true) && ((source >= (Color)Config::PALETTE_SIZE) || (dest >= (Color)Config::PALETTE_SIZE)) )
1691  {
1692  DRETURN_ARG("ERR: bad colors | source: %d | dest: %d |\n", source, dest );
1693  return -1;
1694  }
1695 
1696  //----------------------------------------------------------------
1697  // BODY
1698  //----------------------------------------------------------------
1699 
1700  //Temp sprite
1701  Frame_buffer_sprite sprite_tmp;
1702  //Num of updated sprites
1703  int ret = 0;
1704  bool f_sprite_changed;
1705  //For: scan height
1706  for (uint8_t th = 0;th < Config::FRAME_BUFFER_HEIGHT;th++)
1707  {
1708  //For: scan width
1709  for (uint8_t tw = 0;tw < Config::FRAME_BUFFER_WIDTH;tw++)
1710  {
1711  //Fetch sprite
1712  sprite_tmp = this -> g_frame_buffer[ th ][ tw ];
1713  //Was sprite changed?
1714  f_sprite_changed = false;
1715  //If: the background is a color to be swapped and the character uses the background
1716  if ( (sprite_tmp.background_color == source) && (this -> is_using_background( sprite_tmp.sprite_index )) )
1717  {
1718  //Swap the color
1719  sprite_tmp.background_color = dest;
1720  f_sprite_changed = true;
1721  }
1722  //If: the foreground is a color to be swapped and the character uses the foreground
1723  if ( (sprite_tmp.foreground_color == source) && (this -> is_using_foreground( sprite_tmp.sprite_index )) )
1724  {
1725  //Swap the color
1726  sprite_tmp.foreground_color = dest;
1727  f_sprite_changed = true;
1728  }
1729  //If: sprite was changed
1730  if (f_sprite_changed == true)
1731  {
1732 
1733  this -> update_sprite( th, tw, sprite_tmp );
1734 
1735  }
1736  } //End For: scan width
1737  } //For: scan height
1738 
1739  //----------------------------------------------------------------
1740  // RETURN
1741  //----------------------------------------------------------------
1742  DENTER_ARG("sprites updated %d |\n", ret);
1743  return ret; //fail
1744 } //End public method: change_color | Color | Color |
1745 
1746 /***************************************************************************/
1749 /***************************************************************************/
1753 /***************************************************************************/
1754 
1755 int Screen::clear( void )
1756 {
1757  DENTER();
1758 
1759  //----------------------------------------------------------------
1760  // VARS
1761  //----------------------------------------------------------------
1762 
1763  //Fast counters
1764  uint8_t th, tw;
1765  //Temp sprite
1766  Frame_buffer_sprite sprite_tmp;
1767  //Number of sprites updated
1768  int num_sprites_updated = 0;
1769  int ret;
1770 
1771  //----------------------------------------------------------------
1772  // BODY
1773  //----------------------------------------------------------------
1774 
1775  //Construct sprite.
1776  //Special sprite with full background color
1777  sprite_tmp.sprite_index = Config::SPRITE_BLACK;
1778  //Set color. I don't care about background color
1779  sprite_tmp.background_color = Color::BLACK;
1780  sprite_tmp.foreground_color = Color::BLACK;
1781  sprite_tmp.f_update = true;
1782  //For: each frame buffer row (height scan)
1783  for (th = 0;th < Screen::Config::FRAME_BUFFER_HEIGHT;th++)
1784  {
1785  //For: each frame buffer col (width scan)
1786  for (tw = 0;tw < Screen::Config::FRAME_BUFFER_WIDTH;tw++)
1787  {
1788  //Update the frame buffer with the new sprite if needed
1789  ret = this -> update_sprite( th, tw, sprite_tmp );
1790  //If: an error occurred
1791  if ((Config::PEDANTIC_CHECKS == true) && (ret < 0))
1792  {
1793  DRETURN_ARG("ERR: Failed to update sprite\n");
1794  return ret;
1795  }
1796  else
1797  {
1798  //Compute number of updated sprites
1799  num_sprites_updated += ret;
1800  }
1801  } //End For: each frame buffer col (width scan)
1802  } //End For: each frame buffer row (height scan)
1803 
1804  //----------------------------------------------------------------
1805  // RETURN
1806  //----------------------------------------------------------------
1807  DRETURN();
1808  return num_sprites_updated;
1809 } //End public method: clear | void |
1810 
1811 /***************************************************************************/
1814 /***************************************************************************/
1819 /***************************************************************************/
1820 
1821 int Screen::clear( Color color_tmp )
1822 {
1823  DENTER_ARG("color: %d\n", (int)color_tmp);
1824  //----------------------------------------------------------------
1825  // CHECK
1826  //----------------------------------------------------------------
1827 
1828  //If: palette index outside the palette
1829  if (color_tmp >= (Color)Screen::Config::PALETTE_SIZE)
1830  {
1831  DRETURN_ARG("ERR: palette index outside the palette\n");
1832  return -1;
1833  }
1834 
1835  //----------------------------------------------------------------
1836  // VARS
1837  //----------------------------------------------------------------
1838 
1839  //Fast counters
1840  uint8_t th, tw;
1841  //Temp sprite
1842  Frame_buffer_sprite sprite_tmp;
1843  //Number of sprites updated
1844  int num_sprites_updated = 0;
1845  //Temp return
1846  int ret;
1847 
1848  //----------------------------------------------------------------
1849  // BODY
1850  //----------------------------------------------------------------
1851 
1852  //Construct sprite.
1853  //Special sprite with full background color
1854  sprite_tmp.sprite_index = Config::SPRITE_BACKGROUND;
1855  //Set color. I don't care about background color
1856  sprite_tmp.background_color = color_tmp;
1857  sprite_tmp.foreground_color = color_tmp;
1858  sprite_tmp.f_update = true;
1859  //For: each frame buffer row (height scan)
1860  for (th = 0;th < Screen::Config::FRAME_BUFFER_HEIGHT;th++)
1861  {
1862  //For: each frame buffer col (width scan)
1863  for (tw = 0;tw < Screen::Config::FRAME_BUFFER_WIDTH;tw++)
1864  {
1865  //Update the frame buffer with the new sprite if needed
1866  ret = this -> update_sprite( th, tw, sprite_tmp );
1867  //If: an error occurred
1868  if ((Config::PEDANTIC_CHECKS == true) && (ret < 0))
1869  {
1870  DRETURN_ARG("ERR: Failed to update sprite\n");
1871  return ret;
1872  }
1873  else
1874  {
1875  //Compute number of updated sprites
1876  num_sprites_updated += ret;
1877  }
1878  } //End For: each frame buffer col (width scan)
1879  } //End For: each frame buffer row (height scan)
1880 
1881  //----------------------------------------------------------------
1882  // RETURN
1883  //----------------------------------------------------------------
1884  DRETURN();
1885  return num_sprites_updated;
1886 } //End public method: clear | Color |
1887 
1888 /***************************************************************************/
1891 /***************************************************************************/
1902 /***************************************************************************/
1903 
1904 int Screen::print( int origin_h, int origin_w, char c, Color background, Color foreground )
1905 {
1906  DENTER_ARG("h: %5d, w: %5d, c: %d %d\n", origin_h, origin_w, (int)background, (int)foreground);
1907  //----------------------------------------------------------------
1908  // CHECK
1909  //----------------------------------------------------------------
1910 
1911  //If: character is outside the ascii sprite table
1912  if ((origin_h < 0) || (origin_h >= Config::FRAME_BUFFER_HEIGHT) || (origin_w < 0) || (origin_w >= Config::FRAME_BUFFER_WIDTH))
1913  {
1914  DRETURN_ARG("ERR: out of the sprite table\n");
1915  return -1; //FAIL
1916  }
1917  //If: colors are bad
1918  if ((background >= (Color)Config::PALETTE_SIZE) || (foreground >= (Color)Config::PALETTE_SIZE))
1919  {
1920  DRETURN_ARG("ERR: bad default colors | Back: %3d | Fore: %3d |\n", background, foreground );
1921  return -1; //FAIL
1922  }
1923  //If: character is not stored inside the ascii sprite table
1924  if (is_valid_char( c ) == false)
1925  {
1926  DRETURN_ARG("ERR: character not on the char table\n");
1927  return -1; //FAIL
1928  }
1929 
1930  //----------------------------------------------------------------
1931  // VARS
1932  //----------------------------------------------------------------
1933 
1934  //Temp sprite
1935  Frame_buffer_sprite sprite_tmp;
1936  //Construct temp sprite
1937  //Sprite index. use its ascii code
1938  sprite_tmp.sprite_index = c;
1939  //Use default background and foreground colors
1940  sprite_tmp.background_color = background;
1941  sprite_tmp.foreground_color = foreground;
1942  //Mark this sprite for update
1943  sprite_tmp.f_update = true;
1944 
1945  //----------------------------------------------------------------
1946  // BODY
1947  //----------------------------------------------------------------
1948 
1949  //Update the frame buffer with the new sprite if needed
1950  int ret = this -> update_sprite( origin_h, origin_w, sprite_tmp );
1951  //@debug
1952  show_frame_sprite(this -> g_frame_buffer[origin_h][origin_w]);
1953 
1954  //----------------------------------------------------------------
1955  // RETURN
1956  //----------------------------------------------------------------
1957  DRETURN();
1958  return ret;
1959 } //End public method: print | int | int | char | Color | Color
1960 
1961 /***************************************************************************/
1964 /***************************************************************************/
1972 /***************************************************************************/
1973 
1974 inline int Screen::print( int origin_h, int origin_w, char c, Color foreground )
1975 {
1976  DENTER();
1977  //----------------------------------------------------------------
1978  // BODY
1979  //----------------------------------------------------------------
1980 
1981  //Call the more generic print char method and return its result
1982  int num_changed_sprites = this -> print( origin_h, origin_w, c, this -> g_default_background_color, foreground );
1983 
1984  //----------------------------------------------------------------
1985  // RETURN
1986  //----------------------------------------------------------------
1987  DRETURN();
1988  return num_changed_sprites;
1989 } //End public method: print | int | int | char | Color
1990 
1991 /***************************************************************************/
1994 /***************************************************************************/
2002 /***************************************************************************/
2003 
2004 inline int Screen::print( int origin_h, int origin_w, char c )
2005 {
2006  DENTER();
2007  //----------------------------------------------------------------
2008  // BODY
2009  //----------------------------------------------------------------
2010 
2011  //Call the more generic print char method and return its result
2012  int num_changed_sprites = this -> print( origin_h, origin_w, c, this -> g_default_background_color, this -> g_default_foreground_color );
2013 
2014  //----------------------------------------------------------------
2015  // RETURN
2016  //----------------------------------------------------------------
2017  DRETURN();
2018  return num_changed_sprites;
2019 } //End public method: print | int | int | char |
2020 
2021 /***************************************************************************/
2024 /***************************************************************************/
2035 /***************************************************************************/
2036 
2037 int Screen::print( int origin_h, int origin_w, const char *str, Color background, Color foreground )
2038 {
2039  DENTER_ARG("h: %5d, w: %5d, c: %p %s\n", origin_h, origin_w, str, str);
2040  //----------------------------------------------------------------
2041  // CHECK
2042  //----------------------------------------------------------------
2043 
2044  //If: first character is outside the ascii sprite table
2045  if ((origin_h < 0) || (origin_h >= Config::FRAME_BUFFER_HEIGHT) || (origin_w < 0) || (origin_w >= Config::FRAME_BUFFER_WIDTH))
2046  {
2047  DRETURN_ARG("ERR: out of the sprite table %5d %5d\n", origin_h, origin_w);
2048  return -1; //FAIL
2049  }
2050  //If: colors are bad
2051  if ((background >= (Color)Config::PALETTE_SIZE) || (foreground >= (Color)Config::PALETTE_SIZE))
2052  {
2053  DRETURN_ARG("ERR: bad default colors | Back: %3d | Fore: %3d |\n", background, foreground );
2054  return -1; //FAIL
2055  }
2056  //If: string is invalid
2057  if (str == nullptr)
2058  {
2059  DRETURN_ARG("ERR: null pointer string\n");
2060  return -1; //FAIL
2061  }
2062 
2063  //----------------------------------------------------------------
2064  // VARS
2065  //----------------------------------------------------------------
2066 
2067  //Temp sprite
2068  Frame_buffer_sprite sprite_tmp;
2069  //Initialize colors
2070  sprite_tmp.f_update = true;
2071  sprite_tmp.background_color = background;
2072  sprite_tmp.foreground_color = foreground;
2073 
2074  //----------------------------------------------------------------
2075  // BODY
2076  //----------------------------------------------------------------
2077 
2078  int num_changed_sprites = 0;
2079  //Fast counters
2080  uint8_t t = 0;
2081  uint8_t tw = origin_w;
2082  int ret;
2083  //While: I'm allowed to print, I didn't exceed the string size, and I didn't exceed the screen position
2084  while ((str[t] != '\0') && (tw < Config::FRAME_BUFFER_WIDTH))
2085  {
2086  //Compute sprite ascii char
2087  sprite_tmp.sprite_index = str[t];
2088  DPRINT("t: %5d | tw: %5d | ", t, tw);
2089  //If this is not a printable ascii character
2090  if (this -> is_valid_char(sprite_tmp.sprite_index) == false)
2091  {
2093  DPRINT_NOTAB("H: %5d | W: %5d | non printable\n", origin_h, tw );
2094  }
2095  else
2096  {
2097  //Update the frame buffer with the new sprite if needed
2098  ret = this -> update_sprite( origin_h, tw, sprite_tmp );
2099  //If: an error occurred
2100  if ((Config::PEDANTIC_CHECKS == true) && (ret < 0))
2101  {
2102  DRETURN_ARG("ERR: Failed to update sprite\n");
2103  return ret;
2104  }
2105  else
2106  {
2107  //Compute number of updated sprites
2108  num_changed_sprites += ret;
2109  show_frame_sprite(this -> g_frame_buffer[origin_h][tw]);
2110  }
2111  }
2112  //Next character
2113  t++;
2114  tw++;
2115  } //End While: I'm allowed to print, I didn't exceed the string size, and I didn't exceed the screen position
2116 
2117  //----------------------------------------------------------------
2118  // RETURN
2119  //----------------------------------------------------------------
2120  DRETURN();
2121  return num_changed_sprites;
2122 } //End public method: print | int | int | const char * | Color | Color |
2123 
2124 /***************************************************************************/
2127 /***************************************************************************/
2137 /***************************************************************************/
2138 
2139 inline int Screen::print( int origin_h, int origin_w, const char *str, Color foreground )
2140 {
2141  DENTER(); //Trace enter
2142  //----------------------------------------------------------------
2143  // BODY
2144  //----------------------------------------------------------------
2145 
2146  //more general print string function
2147  int num_changed_sprites = print( origin_h, origin_w, str, this -> g_default_background_color, foreground );
2148 
2149  //----------------------------------------------------------------
2150  // RETURN
2151  //----------------------------------------------------------------
2152  DRETURN(); //Trace enter
2153  return num_changed_sprites;
2154 } //End public method: print | int | int | const char* | Color |
2155 
2156 /***************************************************************************/
2159 /***************************************************************************/
2168 /***************************************************************************/
2169 
2170 inline int Screen::print( int origin_h, int origin_w, const char *str )
2171 {
2172  DENTER(); //Trace enter
2173  //----------------------------------------------------------------
2174  // BODY
2175  //----------------------------------------------------------------
2176 
2177  //more general print string function
2178  int num_changed_sprites = print( origin_h, origin_w, str, this -> g_default_background_color, this -> g_default_foreground_color );
2179 
2180  //----------------------------------------------------------------
2181  // RETURN
2182  //----------------------------------------------------------------
2183  DRETURN(); //Trace enter
2184  return num_changed_sprites;
2185 } //End public method: print | int | int | char |
2186 
2187 /***************************************************************************/
2190 /***************************************************************************/
2205 /***************************************************************************/
2206 
2207 int Screen::print( int origin_h, int origin_w, int num, Color background, Color foreground )
2208 {
2209  DENTER_ARG("NUM: %d\n", num); //Trace enter
2210 
2211  //----------------------------------------------------------------
2212  // CHECK
2213  //----------------------------------------------------------------
2214  // Quit if the number is fully outside the screen for sure
2215  // Avoid wasting CPU time for the conversion
2216 
2217  //If: colors are bad
2218  if ((background >= (Color)Config::PALETTE_SIZE) || (foreground >= (Color)Config::PALETTE_SIZE))
2219  {
2220  DRETURN_ARG("ERR: bad default colors | Back: %3d | Fore: %3d |\n", background, foreground );
2221  return -1; //FAIL
2222  }
2223  //If: height fully outside screen
2224  if ((origin_h < 0) || (origin_h >= Config::FRAME_BUFFER_HEIGHT))
2225  {
2226  DRETURN_ARG("ERR: Height out of range: %d\n", origin_h);
2227  return -1;
2228  }
2229  //Fetch the format of the number locally
2230  Format_number format_tmp = this -> g_format_number;
2231  //Compute first sprite and last sprite that can be occupied by the number
2232  uint8_t start_w = ((format_tmp.align == Format_align::ADJ_LEFT)?(origin_w):(origin_w -format_tmp.size +1));
2233  uint8_t stop_w = ((format_tmp.align == Format_align::ADJ_LEFT)?(origin_w +format_tmp.size -1):(origin_w));
2234  DPRINT("start_w: %3d | stop_w: %3d\n", start_w, stop_w );
2235  //If: width fully outside screen in right adjust
2236  if ( (stop_w < 0) || (start_w >= Config::FRAME_BUFFER_WIDTH) )
2237  {
2238  DRETURN_ARG("ERR: Width out of range\n");
2239  return -1;
2240  }
2241  //Clip the start and stop position to be inside the screen
2242  start_w = ((start_w < 0)?(0):(start_w));
2243  stop_w = ((stop_w >= Config::FRAME_BUFFER_WIDTH)?(Config::FRAME_BUFFER_WIDTH -1):(stop_w));
2244 
2245  //----------------------------------------------------------------
2246  // NUM -> STRING
2247  //----------------------------------------------------------------
2248  // Execute the conversion
2249 
2250  int num_changed_sprites = 0;
2251  //Prepare a string to hold the number
2252  char str[User::String::Config::STRING_SIZE_S32];
2253  //Temp return
2254  uint8_t num_digit;
2255  //Fast counter
2256  uint8_t t;
2257  //if: number format is extended
2258  if (format_tmp.format == Format_format::NUM)
2259  {
2260  //Try to convert the number into a string
2261  num_digit = User::String::num_to_str( (int32_t)num, User::String::Config::STRING_SIZE_S32, str );
2262  //If: fail
2263  if (num_digit == 0)
2264  {
2265  DRETURN_ARG("ERR: Failed to convert NUM number: %d", num);
2266  return -1;
2267  }
2268  }
2269  //If: number format is enginnering
2270  else //if (format_tmp.format = Format_format::ENG)
2271  {
2272  //Try to convert the number into a string
2273  num_digit = User::String::num_to_eng( (int32_t)num, this -> g_format_number.eng_exp, User::String::Config::STRING_SIZE_S32, str );
2274  //If: fail
2275  if (num_digit == 0)
2276  {
2277  DRETURN_ARG("ERR: Failed to convert ENG number: %d", num);
2278  return -1;
2279  }
2280  }
2281 
2282  //----------------------------------------------------------------
2283  // NUMBER PARTIALLY OUT OF SCREEN
2284  //----------------------------------------------------------------
2285  // Having just a piece of a number on screen is dangerous
2286  // partially blanked digits need to invalidate the full number and show '#'
2287  // Condition for partially out
2288  // START STOP
2289  // LEFT OW<0 OW+NUM-1>=W
2290  // RIGHT OW-NUM+1<0 OW>=W
2291 
2292  int ret;
2293  //Temporary sprite
2294  Frame_buffer_sprite sprite_tmp;
2295  //Build temporary sprite
2296  sprite_tmp.background_color = background;
2297  sprite_tmp.foreground_color = foreground;
2298  sprite_tmp.f_update = true;
2299  //If: number is too big
2300  if (num_digit > format_tmp.size)
2301  {
2302  //Print the invalid number character to show the user the number has no meaning
2303  sprite_tmp.sprite_index = '#';
2304  //For: each number character that can be displayed
2305  for (t = start_w;t <= stop_w;t++)
2306  {
2307  //Update the frame buffer with the new sprite if needed
2308  ret = this -> update_sprite( origin_h, t, sprite_tmp );
2309  //If: an error occurred
2310  if ((Config::PEDANTIC_CHECKS == true) && (ret < 0))
2311  {
2312  DRETURN_ARG("ERR: Failed to update sprite\n");
2313  return ret;
2314  }
2315  else
2316  {
2317  //Compute number of updated sprites
2318  num_changed_sprites += ret;
2319  }
2320  }
2321  DRETURN_ARG("ERR: Width partially out of range | LEFT | start %d | stop %d |\n", start_w, stop_w );
2322  return num_changed_sprites;
2323  }
2324  //If: number partially outside screen in left adjust
2325  else if ( (format_tmp.align == Format_align::ADJ_LEFT) && ((origin_w < 0) || ((origin_w +num_digit -1) >= Config::FRAME_BUFFER_WIDTH)) )
2326  {
2327  //Print the invalid number character to show the user the number has no meaning
2328  sprite_tmp.sprite_index = '#';
2329  //For: each number character that can be displayed
2330  for (t = start_w;t <= stop_w;t++)
2331  {
2332  //Update the frame buffer with the new sprite if needed
2333  ret = this -> update_sprite( origin_h, t, sprite_tmp );
2334  //If: an error occurred
2335  if ((Config::PEDANTIC_CHECKS == true) && (ret < 0))
2336  {
2337  DRETURN_ARG("ERR: Failed to update sprite\n");
2338  return ret;
2339  }
2340  else
2341  {
2342  //Compute number of updated sprites
2343  num_changed_sprites += ret;
2344  }
2345  }
2346  DRETURN_ARG("ERR: Width partially out of range | LEFT | start %d | stop %d |\n", start_w, stop_w );
2347  return num_changed_sprites;
2348  }
2349  //If: number partially outside screen in right adjust
2350  else if ( (format_tmp.align == Format_align::ADJ_RIGHT) && ((origin_w -num_digit +1 < 0) || (origin_w >= Config::FRAME_BUFFER_WIDTH)) )
2351  {
2352  //Print the invalid number character to show the user the number has no meaning
2353  sprite_tmp.sprite_index = '#';
2354  //For: each number character that can be displayed
2355  for (t = start_w;t <= stop_w;t++)
2356  {
2357  //Update the frame buffer with the new sprite if needed
2358  ret = this -> update_sprite( origin_h, t, sprite_tmp );
2359  //If: an error occurred
2360  if ((Config::PEDANTIC_CHECKS == true) && (ret < 0))
2361  {
2362  DRETURN_ARG("ERR: Failed to update sprite\n");
2363  return ret;
2364  }
2365  else
2366  {
2367  //Compute number of updated sprites
2368  num_changed_sprites += ret;
2369  }
2370  }
2371  DRETURN_ARG("ERR: Width partially out of range | RIGHT | start %d | stop %d |\n", start_w, stop_w );
2372  return num_changed_sprites;
2373  }
2374 
2375  //----------------------------------------------------------------
2376  // NUMBER FULLY INSIDE SCREEN
2377  //----------------------------------------------------------------
2378  // Number can be shown fully on screen, with at most spaces left out
2379 
2380  //If: left alignment
2381  if (format_tmp.align == Format_align::ADJ_LEFT)
2382  {
2383  //Print the number
2384  //For: every number digit
2385  for (t = 0;t < num_digit; t++)
2386  {
2387  //Digit -> Sprite
2388  sprite_tmp.sprite_index = str[t];
2389  //Update the frame buffer with the new sprite if needed
2390  ret = this -> update_sprite( origin_h, t, sprite_tmp );
2391  //If: an error occurred
2392  if ((Config::PEDANTIC_CHECKS == true) && (ret < 0))
2393  {
2394  DRETURN_ARG("ERR: Failed to update sprite\n");
2395  return ret;
2396  }
2397  else
2398  {
2399  //Compute number of updated sprites
2400  num_changed_sprites += ret;
2401  }
2402  } //End For: every digit
2403  //Print spaces to clear the previously printed character
2404  //space sprite
2405  sprite_tmp.sprite_index = ' ';
2406  //For: every number digit
2407  for (;t <= stop_w; t++)
2408  {
2409  //Update the frame buffer with the new sprite if needed
2410  ret = this -> update_sprite( origin_h, t, sprite_tmp );
2411  //If: an error occurred
2412  if ((Config::PEDANTIC_CHECKS == true) && (ret < 0))
2413  {
2414  DRETURN_ARG("ERR: Failed to update sprite\n");
2415  return ret;
2416  }
2417  else
2418  {
2419  //Compute number of updated sprites
2420  num_changed_sprites += ret;
2421  }
2422  }
2423  } //End If: left alignment
2424  //If: right alignment
2425  else //if (format_tmp.align == Format_align::ADJ_RIGHT)
2426  {
2427  //Print the correct number of spaces
2428  //space sprite
2429  sprite_tmp.sprite_index = ' ';
2430  //For: every number digit
2431  for (t = start_w;t < stop_w -num_digit +1; t++)
2432  {
2433  //Update the frame buffer with the new sprite if needed
2434  ret = this -> update_sprite( origin_h, t, sprite_tmp );
2435  //If: an error occurred
2436  if ((Config::PEDANTIC_CHECKS == true) && (ret < 0))
2437  {
2438  DRETURN_ARG("ERR: Failed to update sprite\n");
2439  return ret;
2440  }
2441  else
2442  {
2443  //Compute number of updated sprites
2444  num_changed_sprites += ret;
2445  }
2446  }
2447  //Reset start position
2448  start_w = t;
2449  //For: every number digit
2450  for (t = 0;t < num_digit; t++)
2451  {
2452  //Digit -> Sprite
2453  sprite_tmp.sprite_index = str[t];
2454  //Update the frame buffer with the new sprite if needed
2455  ret = this -> update_sprite( origin_h, start_w +t, sprite_tmp );
2456  //If: an error occurred
2457  if ((Config::PEDANTIC_CHECKS == true) && (ret < 0))
2458  {
2459  DRETURN_ARG("ERR: Failed to update sprite\n");
2460  return ret;
2461  }
2462  else
2463  {
2464  //Compute number of updated sprites
2465  num_changed_sprites += ret;
2466  }
2467  } //End For: every digit
2468  } //End If: right alignment
2469 
2470  //----------------------------------------------------------------
2471  // RETURN
2472  //----------------------------------------------------------------
2473  DRETURN();
2474  return num_changed_sprites; //OK
2475 } //End public method: print | int | int | int | Color | Color |
2476 
2477 /***************************************************************************/
2480 /***************************************************************************/
2488 /***************************************************************************/
2489 
2490 inline int Screen::print( int origin_h, int origin_w, int num, Color foreground )
2491 {
2492  DENTER_ARG("Num: %d\n", num );
2493  //----------------------------------------------------------------
2494  // RETURN
2495  //----------------------------------------------------------------
2496  //
2497  int num_changed_sprites = print( origin_h, origin_w, num, this -> g_default_background_color, foreground );
2498  DRETURN_ARG("Success: %d\n", num_changed_sprites );
2499  return num_changed_sprites;
2500 } //End public method: print | int | int | int |
2501 
2502 /***************************************************************************/
2505 /***************************************************************************/
2512 /***************************************************************************/
2513 
2514 inline int Screen::print( int origin_h, int origin_w, int num )
2515 {
2516  DENTER_ARG("Num: %d\n", num );
2517  //----------------------------------------------------------------
2518  // RETURN
2519  //----------------------------------------------------------------
2520  //
2521  int ret = print( origin_h, origin_w, num, this -> g_default_background_color, this -> g_default_foreground_color );
2522  DRETURN_ARG("Success: %d\n", f_ret );
2523  return ret;
2524 } //End public method: print | int | int | int |
2525 
2526 /***************************************************************************/
2529 /***************************************************************************/
2534 /***************************************************************************/
2535 
2536 int Screen::paint( int origin_h, int origin_w, Color color )
2537 {
2538  DENTER_ARG("H: %d, W: %d, color index: %d\n", origin_h, origin_w, (int)color );
2539  //----------------------------------------------------------------
2540  // CHECK
2541  //----------------------------------------------------------------
2542 
2543  //If: colors are bad
2544  if (color >= (Color)Config::PALETTE_SIZE)
2545  {
2546  DRETURN_ARG("ERR: bad default colors | Color: %3d |\n", color );
2547  return -1; //FAIL
2548  }
2549  //If: height fully outside screen
2550  if ((origin_h < 0) || (origin_h >= Config::FRAME_BUFFER_HEIGHT))
2551  {
2552  DRETURN_ARG("ERR: Height out of range: %d\n", origin_h);
2553  return -1;
2554  }
2555  //If: width fully outside screen
2556  if ((origin_w < 0) || (origin_w >= Config::FRAME_BUFFER_WIDTH))
2557  {
2558  DRETURN_ARG("ERR: Height out of range: %d\n", origin_w);
2559  return -1;
2560  }
2561 
2562  //----------------------------------------------------------------
2563  // Construct Sprite
2564  //----------------------------------------------------------------
2565 
2566  //Temporary sprite
2567  Frame_buffer_sprite sprite_tmp;
2568  //Build temporary sprite
2569  sprite_tmp.sprite_index = Config::SPRITE_BACKGROUND;
2570  sprite_tmp.background_color = color;
2571  sprite_tmp.foreground_color = color;
2572  sprite_tmp.f_update = true;
2573 
2574  //----------------------------------------------------------------
2575  // Update Frame Buffer
2576  //----------------------------------------------------------------
2577 
2578  //Update the frame buffer with the new sprite if needed
2579  int ret = this -> update_sprite( origin_h, origin_w, sprite_tmp );
2580 
2581  //----------------------------------------------------------------
2582  // RETURN
2583  //----------------------------------------------------------------
2584  DRETURN();
2585  return ret; //No sprites have been drawn
2586 } //End public method: paint | int | int | Color |
2587 
2588 /***************************************************************************/
2591 /***************************************************************************/
2599 /***************************************************************************/
2600 
2601 int Screen::print_err( int origin_h, int origin_w )
2602 {
2603  DENTER(); //Trace enter
2604  //----------------------------------------------------------------
2605  // BODY
2606  //----------------------------------------------------------------
2607 
2608  //more general print string function
2609  int num_changed_sprites;
2610  //If: OK
2611  if (this -> g_error_code == 0)
2612  {
2613  num_changed_sprites = print( origin_h, origin_w, "OK", Color::GREEN );
2614  }
2615  //If: ERR
2616  else
2617  {
2618  num_changed_sprites = print( origin_h, origin_w, "ERR", Color::RED );
2619  this -> set_format(2, Format_align::ADJ_LEFT, Format_format::NUM );
2620  num_changed_sprites += print( origin_h, origin_w +3, (int)this -> g_error_code, Color::RED );
2621  }
2622 
2623  //----------------------------------------------------------------
2624  // RETURN
2625  //----------------------------------------------------------------
2626  DRETURN(); //Trace enter
2627  return num_changed_sprites;
2628 } //End public method: print_err | int | int |
2629 
2630  /*********************************************************************************************************************************************************
2631  **********************************************************************************************************************************************************
2632  ** PRIVATE INIT
2633  **********************************************************************************************************************************************************
2634  *********************************************************************************************************************************************************/
2635 
2636 /***************************************************************************/
2639 /***************************************************************************/
2643 /***************************************************************************/
2644 
2646 {
2647  //----------------------------------------------------------------
2648  // VARS
2649  //----------------------------------------------------------------
2650 
2651  //----------------------------------------------------------------
2652  // BODY
2653  //----------------------------------------------------------------
2654 
2655  //Initialize error code
2656  this -> g_error_code = Screen::Error::OK;
2657  //Initialize default number format
2658  this -> set_format( Screen::Config::FRAME_BUFFER_WIDTH, Format_align::ADJ_LEFT, Format_format::NUM, 0 );
2659 
2660  //----------------------------------------------------------------
2661  // RETURN
2662  //----------------------------------------------------------------
2663 
2664  return false; //OK
2665 } //End private init: init_class_vars | void |
2666 
2667 /***************************************************************************/
2670 /***************************************************************************/
2674 /***************************************************************************/
2675 
2677 {
2678  DENTER();
2679  //----------------------------------------------------------------
2680  // VARS
2681  //----------------------------------------------------------------
2682 
2683  //Fast counter
2684  uint16_t tw, th;
2685  //Temp sprite
2686  Frame_buffer_sprite sprite_tmp;
2687 
2688  //----------------------------------------------------------------
2689  // BODY
2690  //----------------------------------------------------------------
2691 
2692  //Force update of this sprite
2693  sprite_tmp.f_update = true;
2694  //Initialize sprite code to FULL BACKGROUND sprite
2695  sprite_tmp.sprite_index = Config::SPRITE_BLACK;
2696  //Initialize colors to defaults Color black and white
2697  sprite_tmp.background_color = Screen::Color::BLACK;
2698  sprite_tmp.foreground_color = Screen::Color::WHITE;
2699  show_frame_sprite( sprite_tmp );
2700  //For: each frame buffer row (height scan)
2701  for (th = 0;th < Screen::Config::FRAME_BUFFER_HEIGHT;th++)
2702  {
2703  //For: each frame buffer col (width scan)
2704  for (tw = 0;tw < Screen::Config::FRAME_BUFFER_WIDTH;tw++)
2705  {
2706  //Save default sprite in the frame buffer
2707  this -> g_frame_buffer[th][tw] = sprite_tmp;
2708  } //End For: each frame buffer col (width scan)
2709  } //End For: each frame buffer row (height scan)
2710  //All sprites require update at the initialization
2711  this -> g_pending_cnt = Config::FRAME_BUFFER_SIZE;
2712 
2713  //----------------------------------------------------------------
2714  // RETURN
2715  //----------------------------------------------------------------
2716  DRETURN();
2717  return false; //OK
2718 } //End private init: init_frame_buffer | void
2719 
2720 /***************************************************************************/
2723 /***************************************************************************/
2727 /***************************************************************************/
2728 
2729 inline bool Screen::init_default_colors( void )
2730 {
2731  DENTER();
2732  //----------------------------------------------------------------
2733  // BODY
2734  //----------------------------------------------------------------
2735 
2736  //Initialize default colors
2737  this -> g_default_background_color = Color::BLACK;
2738  this -> g_default_foreground_color = Color::WHITE;
2739 
2740  //----------------------------------------------------------------
2741  // RETURN
2742  //----------------------------------------------------------------
2743  DRETURN();
2744  return false; //OK
2745 } //End private init: init_default_colors | void |
2746 
2747 /***************************************************************************/
2750 /***************************************************************************/
2754 /***************************************************************************/
2755 
2757 {
2758  DENTER();
2759  //----------------------------------------------------------------
2760  // BODY
2761  //----------------------------------------------------------------
2762 
2763  //Use the CGA default palette (https://en.wikipedia.org/wiki/Color_Graphics_Adapter)
2764  this -> g_palette[Screen::Color::BLACK] = Longan_nano::Display::color( 0x00, 0x00, 0x00 );
2765  this -> g_palette[Screen::Color::BLUE] = Longan_nano::Display::color( 0x00, 0x00, 0xAA );
2766  this -> g_palette[Screen::Color::GREEN] = Longan_nano::Display::color( 0x00, 0xAA, 0x00 );
2767  this -> g_palette[Screen::Color::CYAN] = Longan_nano::Display::color( 0x00, 0xAA, 0xAA );
2768  this -> g_palette[Screen::Color::RED] = Longan_nano::Display::color( 0xAA, 0x00, 0x00 );
2769  this -> g_palette[Screen::Color::MAGENTA] = Longan_nano::Display::color( 0xAA, 0x00, 0xAA );
2770  this -> g_palette[Screen::Color::BROWN] = Longan_nano::Display::color( 0xAA, 0x55, 0x00 );
2771  this -> g_palette[Screen::Color::LGRAY] = Longan_nano::Display::color( 0xAA, 0xAA, 0xAA );
2772  this -> g_palette[Screen::Color::DGRAY] = Longan_nano::Display::color( 0x55, 0x55, 0x55 );
2773  this -> g_palette[Screen::Color::LBLUE] = Longan_nano::Display::color( 0x55, 0x55, 0xFF );
2774  this -> g_palette[Screen::Color::LGREEN] = Longan_nano::Display::color( 0x55, 0xFF, 0x55 );
2775  this -> g_palette[Screen::Color::LCYAN] = Longan_nano::Display::color( 0x55, 0xFF, 0xFF );
2776  this -> g_palette[Screen::Color::LRED] = Longan_nano::Display::color( 0xFF, 0x55, 0x55 );
2777  this -> g_palette[Screen::Color::LMAGENTA] = Longan_nano::Display::color( 0xFF, 0x55, 0xFF );
2778  this -> g_palette[Screen::Color::YELLOW] = Longan_nano::Display::color( 0xFF, 0xFF, 0x55 );
2779  this -> g_palette[Screen::Color::WHITE] = Longan_nano::Display::color( 0xFF, 0xFF, 0xFF );
2780  #ifdef DEBUG_ENABLE
2781  {
2782  DPRINT("TEST: %6x\n", Longan_nano::Display::color( 0xFF, 0xFF, 0xFF ));
2783  this -> show_palette();
2784  }
2785  #endif
2786  //----------------------------------------------------------------
2787  // RETURN
2788  //----------------------------------------------------------------
2789  DRETURN();
2790  return false; //OK
2791 } //End private init: init_palette | void
2792 
2793 /***************************************************************************/
2796 /***************************************************************************/
2800 /***************************************************************************/
2801 
2802 bool Screen::init_fsm( void )
2803 {
2804  //----------------------------------------------------------------
2805  // BODY
2806  //----------------------------------------------------------------
2807 
2808  //Start from top left
2809  this -> g_status.scan_h = 0;
2810  this -> g_status.scan_w = 0;
2811  //IDLE state
2812  this -> g_status.cnt = 0;
2813  //Update should scan for the next sprite to be updated
2814  this -> g_status.phase = Fsm_state::SCAN_SPRITE;
2815 
2816  //----------------------------------------------------------------
2817  // RETURN
2818  //----------------------------------------------------------------
2819 
2820  return false; //OK
2821 } //End private init: init_fsm | void |
2822 
2823  /*********************************************************************************************************************************************************
2824  **********************************************************************************************************************************************************
2825  ** PRIVATE SETTER
2826  **********************************************************************************************************************************************************
2827  *********************************************************************************************************************************************************/
2828 
2829 /***************************************************************************/
2832 /***************************************************************************/
2837 /***************************************************************************/
2838 
2839 void Screen::report_error( Error error_code )
2840 {
2841  DENTER_ARG("ERR%d\n", (int)error_code ); //Trace Enter
2845 
2846  if ((Config::PEDANTIC_CHECKS == true) && (error_code >= Screen::Error::NUM_ERROR_CODES))
2847  {
2848  this -> g_error_code = Screen::Error::BAD_ERROR_CODE;
2849  }
2850  else
2851  {
2852  this -> g_error_code = error_code;
2853  }
2854 
2858  DRETURN(); //Trace Return
2859  return;
2860 } //end private setter: report_error | Error |
2861 
2862  /*********************************************************************************************************************************************************
2863  **********************************************************************************************************************************************************
2864  ** PRIVATE TESTERS
2865  **********************************************************************************************************************************************************
2866  *********************************************************************************************************************************************************/
2867 
2868 /***************************************************************************/
2871 /***************************************************************************/
2875 /***************************************************************************/
2876 
2877 inline bool Screen::is_valid_char( char c )
2878 {
2879  //----------------------------------------------------------------
2880  // RETURN
2881  //----------------------------------------------------------------
2882 
2883  return ((c >= Config::ASCII_START) && (c <= Config::ASCII_STOP));
2884 } //End private tester: is_valid_char | char |
2885 
2886 /***************************************************************************/
2889 /***************************************************************************/
2893 /***************************************************************************/
2894 
2895 inline bool Screen::is_using_background( uint8_t sprite )
2896 {
2897  //----------------------------------------------------------------
2898  // BODY
2899  //----------------------------------------------------------------
2900  //If: special sprite
2901  if (sprite < Config::NUM_SPECIAL_SPRITES)
2902  {
2903  //If: special sprite that use the background
2904  if (sprite == Config::SPRITE_BACKGROUND)
2905  {
2906  //Use background
2907  return true;
2908  }
2909  else
2910  {
2911  //Do not use the background
2912  return false;
2913  }
2914  }
2915  //If: sprite is an ascii character
2916  else if (this -> is_valid_char(sprite) == true)
2917  {
2918  //An ascii character use the background
2919  return true;
2920  }
2921 
2922  //----------------------------------------------------------------
2923  // RETURN
2924  //----------------------------------------------------------------
2925 
2926  //Non drawable sprite
2927  return false;
2928 } //End private tester: is_using_background | uint8_t |
2929 
2930 /***************************************************************************/
2933 /***************************************************************************/
2937 /***************************************************************************/
2938 
2939 inline bool Screen::is_using_foreground( uint8_t sprite )
2940 {
2941  //----------------------------------------------------------------
2942  // BODY
2943  //----------------------------------------------------------------
2944  //If: special sprite
2945  if (sprite < Config::NUM_SPECIAL_SPRITES)
2946  {
2947  //If: special sprite that use the color
2948  if (sprite == Config::SPRITE_FOREGROUND)
2949  {
2950  //Using color
2951  return true;
2952  }
2953  else
2954  {
2955  //Not Using color
2956  return false;
2957  }
2958  }
2959  //If: sprite is an ascii character
2960  else if (this -> is_valid_char(sprite) == true)
2961  {
2962  //An ascii character use the color
2963  return true;
2964  }
2965 
2966  //----------------------------------------------------------------
2967  // RETURN
2968  //----------------------------------------------------------------
2969 
2970  //Non drawable sprite
2971  return false;
2972 } //End private tester: is_using_foreground | uint8_t |
2973 
2974 /***************************************************************************/
2977 /***************************************************************************/
2988 /***************************************************************************/
2989 
2991 {
2992  DENTER();
2993  //----------------------------------------------------------------
2994  // VARS
2995  //----------------------------------------------------------------
2996 
2997  bool f_ascii_a = is_valid_char( sprite_a.sprite_index );
2998  bool f_special_a = (sprite_a.sprite_index < Config::NUM_SPECIAL_SPRITES);
2999  bool f_ascii_b = is_valid_char( sprite_b.sprite_index );
3000  bool f_special_b = (sprite_b.sprite_index < Config::NUM_SPECIAL_SPRITES);
3001 
3002  //----------------------------------------------------------------
3003  // BODY
3004  //----------------------------------------------------------------
3005 
3006  //If: both characters are special
3007  if ((f_special_a == true) && (f_special_b == true))
3008  {
3009  //If: sprite indexes are the same
3010  if (sprite_a.sprite_index == sprite_b.sprite_index)
3011  {
3012  //If: fixed color sprites (do not use palette)
3013  if ((sprite_a.sprite_index == Config::SPRITE_BLACK) || (sprite_a.sprite_index == Config::SPRITE_WHITE))
3014  {
3015  DRETURN_ARG("Same fixed solid sprites: %d %d\n", sprite_a.sprite_index, sprite_b.sprite_index );
3016  return true; //Same
3017  }
3018  //If: character that use background only
3019  else if (sprite_a.sprite_index == Config::SPRITE_BACKGROUND)
3020  {
3021  //If: background are the same
3022  if (sprite_a.background_color == sprite_b.background_color)
3023  {
3024  DRETURN_ARG("Same solid background sprites: %d\n", sprite_a.background_color );
3025  return true; //Same
3026  }
3027  //If: background are the different
3028  else
3029  {
3030  DRETURN_ARG("Different solid background sprites: %d %d\n", sprite_a.background_color, sprite_b.background_color );
3031  return false; //Different
3032  }
3033  }
3034  //If: character that use foreground only
3035  else if (sprite_a.sprite_index == Config::SPRITE_FOREGROUND)
3036  {
3037  //If: background are the same
3038  if (sprite_a.foreground_color == sprite_b.foreground_color)
3039  {
3040  DRETURN_ARG("Same solid foreground sprites: %d\n", sprite_a.foreground_color );
3041  return true; //Same
3042  }
3043  //If: background are the different
3044  else
3045  {
3046  DRETURN_ARG("Different solid foreground sprites: %d %d\n", sprite_a.foreground_color, sprite_b.foreground_color );
3047  return false; //Different
3048  }
3049  }
3050  //Default:
3051  else
3052  {
3053  //Any other combination is to be treated as different sprites
3054  DRETURN_ARG("Different sprites: %d %d\n", sprite_a.sprite_index, sprite_b.sprite_index );
3055  return false; //Different
3056  }
3057  } //End If: sprite indexes are the same
3058  //End If: sprite indexes are the different
3059  else
3060  {
3061  //@todo: there are combinations of different indexes that yield the same color
3062  DRETURN_ARG("Different sprites: %d %d\n", sprite_a.sprite_index, sprite_b.sprite_index );
3063  return false; //Different
3064  }
3065  } //End If: both characters are special
3066  //If: both are validascii characters
3067  else if ((f_ascii_a == true) && (f_ascii_b == true))
3068  {
3069  //If: sprites have the same index, the same background and the same foreground
3070  if ((sprite_a.sprite_index == sprite_b.sprite_index) && (sprite_a.background_color == sprite_b.background_color) && (sprite_a.foreground_color == sprite_b.foreground_color))
3071  {
3072  DRETURN_ARG("Same ascii characters: %c %c\n", sprite_a.sprite_index, sprite_b.sprite_index );
3073  return true; //Same ascii
3074  }
3075  //If: any property is different
3076  else
3077  {
3078  DRETURN_ARG("Different ascii characters: %c %c\n", sprite_a.sprite_index, sprite_b.sprite_index );
3079  return false; //Different ascii
3080  }
3081  }
3082  //@todo: graphics sprites (Symbols)
3083  //If: every other combination is an invalid sprite
3084  else
3085  {
3086  //Do nothing
3087  }
3088 
3089  //----------------------------------------------------------------
3090  // RETURN
3091  //----------------------------------------------------------------
3092  DRETURN();
3093  return false; //Sprites are different
3094 } //End private tester: is_same_sprite | Frame_buffer_sprite | Frame_buffer_sprite |
3095 
3096  /*********************************************************************************************************************************************************
3097  **********************************************************************************************************************************************************
3098  ** PRIVATE METHODS
3099  **********************************************************************************************************************************************************
3100  *********************************************************************************************************************************************************/
3101 
3102 /***************************************************************************/
3105 /***************************************************************************/
3112 /***************************************************************************/
3113 
3114 int8_t Screen::register_sprite( uint16_t index_h, uint16_t index_w )
3115 {
3116  DENTER_ARG("index_h : %5d | index_w %5d\n", index_h, index_w);
3117  //----------------------------------------------------------------
3118  // VARS
3119  //----------------------------------------------------------------
3120 
3121  //Temp sprite data
3122  uint16_t foreground_color, background_color;
3123  //Temp color
3124  uint16_t color;
3125  //false = complex color map | true = solid color
3126  bool f_solid_color;
3127 
3128  //----------------------------------------------------------------
3129  // INIT
3130  //----------------------------------------------------------------
3131 
3132  //If: bad parameters
3133  if ((Config::PEDANTIC_CHECKS == true) && ((index_w >= Config::FRAME_BUFFER_WIDTH) || (index_h >= Config::FRAME_BUFFER_HEIGHT)) )
3134  {
3135  DRETURN_ARG("ERR: bad parameters\n");
3136  return -1; //FAIL
3137  }
3138 
3139  //----------------------------------------------------------------
3140  // DECODE SPRITE
3141  //----------------------------------------------------------------
3142 
3143  //Fetch a frame sprite
3144  Frame_buffer_sprite sprite_tmp = g_frame_buffer[index_h][index_w];
3145  show_frame_sprite( sprite_tmp );
3146  //Decode background and foreground colors
3147  background_color = g_palette[ sprite_tmp.background_color ];
3148  foreground_color = g_palette[ sprite_tmp.foreground_color ];
3149  DPRINT("sprite: %d | background color: %6x | foreground_color: %6x |\n", sprite_tmp.sprite_index, background_color, foreground_color );
3150  //Pointer to sprite data
3151  const uint8_t *sprite_ptr = nullptr;
3152 
3153  //If: special sprite
3154  if (sprite_tmp.sprite_index < Config::NUM_SPECIAL_SPRITES)
3155  {
3156  //If: Solid black
3157  if (sprite_tmp.sprite_index == Config::SPRITE_BLACK)
3158  {
3159  f_solid_color = true;
3160  color = Display::color(0x00,0x00,0x00);
3161  }
3162  //If: Solid white
3163  else if (sprite_tmp.sprite_index == Config::SPRITE_WHITE)
3164  {
3165  f_solid_color = true;
3166  color = Display::color(0xFF,0xFF,0xFF);
3167  }
3168  //If: Solid background
3169  else if (sprite_tmp.sprite_index == Config::SPRITE_BACKGROUND)
3170  {
3171  f_solid_color = true;
3172  color = background_color;
3173  }
3174  //If: Solid foreground
3175  else if (sprite_tmp.sprite_index == Config::SPRITE_FOREGROUND)
3176  {
3177  f_solid_color = true;
3178  color = foreground_color;
3179  }
3180  //If: Transparent sprite
3181  else if (sprite_tmp.sprite_index == Config::SPRITE_TRANSPARENT)
3182  {
3183  DRETURN_ARG("Transparent Sprite\n");
3184  return 0;
3185  }
3186  //If: unhandled special sprite
3187  else
3188  {
3189  //Signal the error
3190  this -> report_error( Error::REGISTER_SPRITE_FAIL );
3191  DRETURN_ARG("ERR%d: unhandled special sprit\n", this -> get_error() );
3192  return -1;
3193  }
3194  } //End If: special sprite
3195  //If: Handled Ascii Character in the character table
3196  else if (this -> is_valid_char( sprite_tmp.sprite_index ) == true)
3197  {
3198  //If: background and foreground are different
3199  if (background_color != foreground_color)
3200  {
3201  //Full pixel color map
3202  f_solid_color = false;
3203  //Point to the first byte of the ascii sprite
3204  sprite_ptr = &g_ascii_sprites[ (sprite_tmp.sprite_index -Config::ASCII_START) *Config::SPRITE_HEIGHT ];
3205  }
3206  //If: background and foreground are the same
3207  else //if (background_color == foreground_color)
3208  {
3209  //Draw a solid color sprite. Don't bother with computing a redundant pixel color map
3210  f_solid_color = true;
3211  color = background_color;
3212  }
3213  }
3214  //If: Unhandled sprite
3215  else
3216  {
3217  //Signal the error
3218  this -> report_error( Error::REGISTER_SPRITE_FAIL );
3219  DRETURN_ARG("ERR%d: unhandled special sprit\n", this -> get_error() );
3220  return -1;
3221  }
3222 
3223  //----------------------------------------------------------------
3224  // BUILD PIXEL MAP
3225  //----------------------------------------------------------------
3226 
3227  //Temp return
3228  int ret;
3229  //If: sprite is a complex color map
3230  if (f_solid_color == false)
3231  {
3232  //Fast counter
3233  int tw, th;
3234  //Store a fullbinary width slice (row)
3235  uint32_t sprite_width_slice;
3236  DPRINT("sprite table index: %c %5d | width slice | ", sprite_index, sprite_index-' ' );
3237  //For: Scan height
3238  for (th = 0;th < Config::SPRITE_HEIGHT;th++)
3239  {
3240  //Grab full width slice of data
3241  sprite_width_slice = sprite_ptr[ th ];
3242  DPRINT_NOTAB(" %x |",sprite_width_slice);
3243  //For: Scan width
3244  for (tw = 0;tw < Config::SPRITE_WIDTH;tw++)
3245  {
3246  //Compute color from the binary sprite map | false = background | true = foreground
3247  color = ((sprite_width_slice & 0x01) == 0x00)?(background_color):(foreground_color);
3248  //Shift away the decoded bit
3249  sprite_width_slice = sprite_width_slice >> 1;
3250  //Save pixel
3251  this -> g_pixel_data[((th *Config::SPRITE_WIDTH) +tw)] = color;
3252  } //End For: Scan width
3253  } //End For: Scan height
3254  DPRINT_NOTAB("\n");
3255  //Register the sprite for draw in the Display driver
3256  ret = this -> Display::register_sprite( index_h *Config::SPRITE_HEIGHT, index_w *Config::SPRITE_WIDTH, Config::SPRITE_HEIGHT, Config::SPRITE_WIDTH, g_pixel_data );
3257  //If: failed to register. the register sprite in future can be smaller than the sprite size if trying to register a sprite partially out of screen
3258  if (ret <= 0)
3259  {
3260  //Signal the error
3261  this -> report_error( Error::REGISTER_SPRITE_FAIL );
3262  //Failed to register sprite
3263  ret = -1;
3264  }
3265  //If: success
3266  else
3267  {
3268  //One sprite has been drawn
3269  ret = 1;
3270  }
3271  } //End If: sprite is a complex color map
3272  //If: sprite is a solid color
3273  else //if (f_solid_color == true)
3274  {
3275  //Register the sprite for draw in the Display driver
3276  ret = this -> Display::register_sprite( index_h *Config::SPRITE_HEIGHT, index_w *Config::SPRITE_WIDTH, Config::SPRITE_HEIGHT, Config::SPRITE_WIDTH, color );
3277  //If: failed to register. the register sprite in future can be smaller than the sprite size if trying to register a sprite partially out of screen
3278  if (ret <= 0)
3279  {
3280  //Signal the error
3281  this -> report_error( Error::REGISTER_SPRITE_FAIL );
3282  //Failed to register sprite
3283  ret = -1;
3284  }
3285  //If: success
3286  else
3287  {
3288  //One sprite has been drawn
3289  ret = 1;
3290  }
3291  } //End If: sprite is a solid color
3292 
3293  //DEBUG
3294  show_pixels();
3295 
3296  //----------------------------------------------------------------
3297  // RETURN
3298  //----------------------------------------------------------------
3299  DRETURN();
3300  return ret;
3301 } //End private method: register_sprite | uint16_t | uint16_t |
3302 
3303 /***************************************************************************/
3306 /***************************************************************************/
3312 /***************************************************************************/
3313 
3314 int8_t Screen::update_sprite( uint16_t index_h, uint16_t index_w, Frame_buffer_sprite new_sprite )
3315 {
3316  DENTER_ARG("H: %d | W: %d |\n", index_h, index_w );
3317  //----------------------------------------------------------------
3318  // CHECK
3319  //----------------------------------------------------------------
3320 
3321  //If: invalid coordinates
3322  if ((Config::PEDANTIC_CHECKS == true) && ((index_h >= Config::FRAME_BUFFER_HEIGHT) || (index_w >= Config::FRAME_BUFFER_WIDTH)) )
3323  {
3324  DRETURN_ARG("ERR: bad index H: %d | W: %d |\n", index_h, index_w);
3325  return -1;
3326  }
3327 
3328  //----------------------------------------------------------------
3329  // BODY
3330  //----------------------------------------------------------------
3331 
3332  int8_t num_updated_sprites;
3333  //Fetch sprite
3334  Frame_buffer_sprite old_sprite = this -> g_frame_buffer[index_h][index_w];
3335  //If: the sprites are the same
3336  if (this -> is_same_sprite(old_sprite, new_sprite) == true)
3337  {
3338  //Do nothing
3339  num_updated_sprites = 0;
3340  }
3341  //If: the sprites are not the same
3342  else //if (old_sprite.f_update == true)
3343  {
3344  //If: old sprite was not marked for update
3345  if (old_sprite.f_update == false)
3346  {
3347  //If: the library workload is full
3348  if ((Config::PEDANTIC_CHECKS == true) && (this -> g_pending_cnt >= Config::FRAME_BUFFER_SIZE))
3349  {
3350  this -> report_error( Screen::Error::PENDING_OVERFLOW );
3351  }
3352  //If: the screen class was IDLE before this call
3353  else if (this -> g_pending_cnt == 0)
3354  {
3355  //Set the scan to this sprite so that the seek is quick
3356  this -> g_status.scan_h = index_h;
3357  this -> g_status.scan_w = index_w;
3358  //Increase workload of the Screen class
3359  this -> g_pending_cnt = 1;
3360  }
3361  //If: Screen class is already busy
3362  else
3363  {
3364  //Increase workload of the Screen class
3365  this -> g_pending_cnt++;
3366  }
3367  }
3368 
3369  //Mark for update
3370  new_sprite.f_update = true;
3371  //Update the sprite
3372  this -> g_frame_buffer[index_h][index_w] = new_sprite;
3373  //A sprite was updated
3374  num_updated_sprites = 1;
3375  }
3376 
3377  //----------------------------------------------------------------
3378  // RETURN
3379  //----------------------------------------------------------------
3380  DRETURN();
3381  return num_updated_sprites;
3382 } //End private method: update_sprite | uint16_t | uint16_t | Frame_buffer_sprite |
3383 
3384 /**********************************************************************************
3385 ** NAMESPACE
3386 **********************************************************************************/
3387 
3388 } //End Namespace: Longan_nano
3389 
3390 #else
3391  #warning "Multiple inclusion of hader file"
3392 #endif
Longan_nano::Screen::g_error_code
Error g_error_code
Error code of the library. Default is Error::OK.
Definition: longan_nano_screen.hpp:589
Longan_nano::Display::color
static uint16_t color(uint8_t r, uint8_t g, uint8_t b)
Public Method color | uint8_t | uint8_t | uint8_t |.
Definition: ST7735S_W160_H80_C16.hpp:524
Longan_nano::Screen::LGREEN
@ LGREEN
Definition: longan_nano_screen.hpp:271
Longan_nano::Screen::init_class_vars
bool init_class_vars(void)
private init init_class_vars | void |
Definition: longan_nano_screen.hpp:2645
Longan_nano::Screen::Config
enum Longan_nano::Screen::_Config Config
Configuration parameters for the logical screen.
Longan_nano::Screen::SPRITE_SCAN_LIMIT
@ SPRITE_SCAN_LIMIT
Definition: longan_nano_screen.hpp:240
Longan_nano::Screen::ASCII_STOP
@ ASCII_STOP
Definition: longan_nano_screen.hpp:250
Longan_nano::Screen::_Format_align
_Format_align
Left or Right alignment for a number.
Definition: longan_nano_screen.hpp:288
Longan_nano
Longan_nano::Screen::SPRITE_BACKGROUND
@ SPRITE_BACKGROUND
Definition: longan_nano_screen.hpp:246
Longan_nano::Screen
Longan Nano Screen Class.
Definition: longan_nano_screen.hpp:219
User::String::num_to_str
static uint8_t num_to_str(uint8_t num, uint8_t str_len, char *str)
public static method num_to_str | uint8_t | uint8_t | char * |
Definition: embedded_string.hpp:238
Longan_nano::Screen::is_using_background
bool is_using_background(uint8_t sprite)
private tester is_using_background | uint8_t |
Definition: longan_nano_screen.hpp:2895
Longan_nano::Screen::_Color
_Color
Use the default Color palette. Short hand indexes for user. User can change the palette at will.
Definition: longan_nano_screen.hpp:260
DENTER_ARG
#define DENTER_ARG(...)
Definition: longan_nano_screen.hpp:71
Longan_nano::Screen::_Error
_Error
Enumerate possible error of the Screen class.
Definition: longan_nano_screen.hpp:295
Longan_nano::Display::_Sprite::size_h
uint16_t size_h
Definition: ST7735S_W160_H80_C16.hpp:293
Longan_nano::Screen::is_valid_char
bool is_valid_char(char c)
private tester is_valid_char | char |
Definition: longan_nano_screen.hpp:2877
Longan_nano::Screen::report_error
void report_error(Error error_code)
private setter report_error | Error |
Definition: longan_nano_screen.hpp:2839
Longan_nano::Screen::_Frame_buffer_sprite::background_color
uint8_t background_color
Definition: longan_nano_screen.hpp:466
Longan_nano::Screen::g_pending_cnt
uint16_t g_pending_cnt
Track the number of sprites that require update. At zero the update method quit without scanning and ...
Definition: longan_nano_screen.hpp:598
Longan_nano::Screen::FRAME_BUFFER_HEIGHT
@ FRAME_BUFFER_HEIGHT
Definition: longan_nano_screen.hpp:256
Longan_nano::Screen::_Format_number::format
Format_format format
Definition: longan_nano_screen.hpp:484
Longan_nano::Screen::OK
@ OK
Definition: longan_nano_screen.hpp:297
Longan_nano::Screen::_Format_format
_Format_format
Possible number configurations.
Definition: longan_nano_screen.hpp:281
Longan_nano::Screen::NUM_ERROR_CODES
@ NUM_ERROR_CODES
Definition: longan_nano_screen.hpp:304
DRETURN_ARG
#define DRETURN_ARG(...)
Definition: longan_nano_screen.hpp:72
Longan_nano::Screen::g_pixel_data
uint16_t g_pixel_data[Config::SPRITE_PIXEL_COUNT]
Sprite buffer that stores raw pixel data for a single sprite.
Definition: longan_nano_screen.hpp:600
DRETURN
#define DRETURN(...)
Definition: longan_nano_screen.hpp:70
Longan_nano::Screen::SCAN_SPRITE
@ SCAN_SPRITE
Definition: longan_nano_screen.hpp:446
Longan_nano::Screen::print
int print(int origin_h, int origin_w, char c, Color background, Color foreground)
public method print | int | int | char | Color | Color
Definition: longan_nano_screen.hpp:1904
Longan_nano::Screen::set_color
int set_color(int origin_h, int origin_w, Color background, Color foreground)
public setter set_color | int | int | Color | Color
Definition: longan_nano_screen.hpp:986
Longan_nano::Screen::Format_align
enum Longan_nano::Screen::_Format_align Format_align
Left or Right alignment for a number.
Longan_nano::Screen::update
bool update(void)
public method update | void
Definition: longan_nano_screen.hpp:1490
Longan_nano::Screen::reset_colors
bool reset_colors(void)
public init reset_colors |
Definition: longan_nano_screen.hpp:942
Longan_nano::Display::g_sprite
Sprite g_sprite
Runtime sprite informations.
Definition: ST7735S_W160_H80_C16.hpp:383
Longan_nano::Screen::PALETTE_SIZE
@ PALETTE_SIZE
Definition: longan_nano_screen.hpp:252
User::String::num_to_eng
static uint8_t num_to_eng(uint32_t num, int8_t num_exp, uint8_t str_len, char *str)
public static method num_to_eng | uint32_t | uint8_t | char * |
Definition: embedded_string.hpp:852
Longan_nano::Screen::BAD_ERROR_CODE
@ BAD_ERROR_CODE
Definition: longan_nano_screen.hpp:303
DENTER
#define DENTER(...)
Definition: longan_nano_screen.hpp:69
show_pixels
#define show_pixels(...)
Definition: longan_nano_screen.hpp:75
Longan_nano::Display::clear
int clear(void)
public method clear | void |
Definition: ST7735S_W160_H80_C16.hpp:974
Longan_nano::Display::_Sprite::size_w
uint16_t size_w
Definition: ST7735S_W160_H80_C16.hpp:294
Longan_nano::Screen::Fsm_status
struct Longan_nano::Screen::_Fsm_status Fsm_status
Status of the update FSM.
Longan_nano::Screen::g_frame_buffer
Frame_buffer_sprite g_frame_buffer[Config::FRAME_BUFFER_HEIGHT][Config::FRAME_BUFFER_WIDTH]
Frame Buffer.
Definition: longan_nano_screen.hpp:596
Longan_nano::Screen::init_palette
bool init_palette(void)
private init init_palette | void
Definition: longan_nano_screen.hpp:2756
Longan_nano::Screen::Error
enum Longan_nano::Screen::_Error Error
Enumerate possible error of the Screen class.
Longan_nano::Screen::_Fsm_status::scan_h
uint16_t scan_h
Definition: longan_nano_screen.hpp:469
Longan_nano::Screen::_Frame_buffer_sprite::foreground_color
uint8_t foreground_color
Definition: longan_nano_screen.hpp:464
Longan_nano::Screen::is_using_foreground
bool is_using_foreground(uint8_t sprite)
private tester is_using_foreground | uint8_t |
Definition: longan_nano_screen.hpp:2939
Longan_nano::Screen::DGRAY
@ DGRAY
Definition: longan_nano_screen.hpp:269
Longan_nano::Screen::_Fsm_status::scan_w
uint16_t scan_w
Definition: longan_nano_screen.hpp:469
Longan_nano::Screen::get_error
Error get_error(void)
public getter get_pending | void |
Definition: longan_nano_screen.hpp:1464
Longan_nano::Screen::g_default_background_color
Color g_default_background_color
Default background and foreground colors to be used.
Definition: longan_nano_screen.hpp:591
ST7735S_W160_H80_C16.hpp
Longan_nano::Screen::init_frame_buffer
bool init_frame_buffer(void)
private init init_frame_buffer | void
Definition: longan_nano_screen.hpp:2676
Longan_nano::Screen::paint
int paint(int origin_h, int origin_w, Color color)
public method paint | int | int | Color |
Definition: longan_nano_screen.hpp:2536
Longan_nano::Screen::BLACK
@ BLACK
Definition: longan_nano_screen.hpp:261
Longan_nano::Screen::BROWN
@ BROWN
Definition: longan_nano_screen.hpp:267
Longan_nano::Screen::_Format_number::align
Format_align align
Definition: longan_nano_screen.hpp:482
Longan_nano::Screen::SPRITE_BLACK
@ SPRITE_BLACK
Definition: longan_nano_screen.hpp:244
Longan_nano::Screen::NUM_SPECIAL_SPRITES
@ NUM_SPECIAL_SPRITES
Definition: longan_nano_screen.hpp:242
Longan_nano::Screen::ADJ_RIGHT
@ ADJ_RIGHT
Definition: longan_nano_screen.hpp:290
Longan_nano::Screen::SPRITE_PIXEL_COUNT
@ SPRITE_PIXEL_COUNT
Definition: longan_nano_screen.hpp:239
Longan_nano::Screen::set_format
bool set_format(int number_size, Format_align align, Format_format format)
public setter set_format | int | Format_align | Format_format |
Definition: longan_nano_screen.hpp:1346
Longan_nano::Display::init
bool init(void)
Public init init | void |.
Definition: ST7735S_W160_H80_C16.hpp:462
Longan_nano::Screen::g_palette
uint16_t g_palette[Config::PALETTE_SIZE]
Color Palette. One special code for transparent. Two special indexes store global background and fore...
Definition: longan_nano_screen.hpp:594
FONT_HEIGHT
#define FONT_HEIGHT
Definition: longan_nano_screen.hpp:100
Longan_nano::Screen::register_sprite
int8_t register_sprite(uint16_t index_h, uint16_t index_w)
private method register_sprite | uint16_t | uint16_t |
Definition: longan_nano_screen.hpp:3114
show_frame_sprite
#define show_frame_sprite(...)
Definition: longan_nano_screen.hpp:74
Longan_nano::Screen::ENG
@ ENG
Definition: longan_nano_screen.hpp:283
Longan_nano::Screen::g_status
Fsm_status g_status
Status of the update FSM.
Definition: longan_nano_screen.hpp:602
Longan_nano::Screen::LGRAY
@ LGRAY
Definition: longan_nano_screen.hpp:268
Longan_nano::Screen::is_same_sprite
bool is_same_sprite(Frame_buffer_sprite sprite_a, Frame_buffer_sprite sprite_b)
private tester is_same_sprite | Frame_buffer_sprite | Frame_buffer_sprite |
Definition: longan_nano_screen.hpp:2990
Longan_nano::Screen::Format_format
enum Longan_nano::Screen::_Format_format Format_format
Possible number configurations.
Longan_nano::Screen::YELLOW
@ YELLOW
Definition: longan_nano_screen.hpp:275
Longan_nano::Screen::ASCII_START
@ ASCII_START
Definition: longan_nano_screen.hpp:249
Longan_nano::Screen::GREEN
@ GREEN
Definition: longan_nano_screen.hpp:263
Longan_nano::Screen::SPRITE_WHITE
@ SPRITE_WHITE
Definition: longan_nano_screen.hpp:245
Longan_nano::Screen::LRED
@ LRED
Definition: longan_nano_screen.hpp:273
Longan_nano::Screen::init_default_colors
bool init_default_colors(void)
private init init_default_colors | void |
Definition: longan_nano_screen.hpp:2729
Longan_nano::Screen::print_err
int print_err(int origin_h, int origin_w)
public method print_err | int | int |
Definition: longan_nano_screen.hpp:2601
Longan_nano::Screen::REGISTER_SPRITE_FAIL
@ REGISTER_SPRITE_FAIL
Definition: longan_nano_screen.hpp:301
Longan_nano::Screen::FRAME_BUFFER_SIZE
@ FRAME_BUFFER_SIZE
Definition: longan_nano_screen.hpp:257
Longan_nano::Screen::_Frame_buffer_sprite::f_update
uint8_t f_update
Definition: longan_nano_screen.hpp:460
Longan_nano::Screen::Screen
Screen(void)
empty constructor Screen | void
Definition: longan_nano_screen.hpp:832
Longan_nano::Screen::BLUE
@ BLUE
Definition: longan_nano_screen.hpp:262
Longan_nano::Screen::get_pending
int get_pending(void)
public getter get_pending | void |
Definition: longan_nano_screen.hpp:1445
Longan_nano::Screen::MAGENTA
@ MAGENTA
Definition: longan_nano_screen.hpp:266
Longan_nano::Screen::Frame_buffer_sprite
struct Longan_nano::Screen::_Frame_buffer_sprite Frame_buffer_sprite
Structure that describes a sprite in the sprite frame buffer.
Longan_nano::Screen::set_default_colors
int set_default_colors(Color new_background, Color new_foreground)
public setter set_default_colors | Color | Color
Definition: longan_nano_screen.hpp:1056
Longan_nano::Screen::LBLUE
@ LBLUE
Definition: longan_nano_screen.hpp:270
DPRINT
#define DPRINT(...)
Definition: longan_nano_screen.hpp:67
Longan_nano::Display::_Sprite::origin_w
uint16_t origin_w
Definition: ST7735S_W160_H80_C16.hpp:291
Longan_nano::Display::_Sprite::origin_h
uint16_t origin_h
Definition: ST7735S_W160_H80_C16.hpp:290
Longan_nano::Display::register_sprite
int register_sprite(int origin_h, int origin_w, int size_h, int size_w, uint16_t *sprite_ptr)
public method register_sprite | int | int | int | int | uint16_t * |
Definition: ST7735S_W160_H80_C16.hpp:552
DPRINT_NOTAB
#define DPRINT_NOTAB(...)
Definition: longan_nano_screen.hpp:68
Longan_nano::Screen::_Fsm_state
_Fsm_state
States of the Screen side FSM. Display driver also has its own FSM states
Definition: longan_nano_screen.hpp:441
Longan_nano::Screen::_Frame_buffer_sprite
Structure that describes a sprite in the sprite frame buffer.
Definition: longan_nano_screen.hpp:454
Longan_nano::Screen::ADJ_LEFT
@ ADJ_LEFT
Definition: longan_nano_screen.hpp:289
Longan_nano::Screen::_Fsm_status::cnt
uint8_t cnt
Definition: longan_nano_screen.hpp:471
Longan_nano::Screen::LMAGENTA
@ LMAGENTA
Definition: longan_nano_screen.hpp:274
Longan_nano::Screen::CYAN
@ CYAN
Definition: longan_nano_screen.hpp:264
Longan_nano::Screen::WHITE
@ WHITE
Definition: longan_nano_screen.hpp:276
embedded_string.hpp
Longan_nano::Screen::SPRITE_WIDTH
@ SPRITE_WIDTH
Definition: longan_nano_screen.hpp:237
Longan_nano::Screen::g_ascii_sprites
static constexpr uint8_t g_ascii_sprites[96 *10]
ASCII Sprites. Stored in the flash memory. 95 sprites from space ' ' code 32 to tilda '~' code 126 + ...
Definition: longan_nano_screen.hpp:610
Longan_nano::Screen::init
bool init(void)
public init init | void
Definition: longan_nano_screen.hpp:899
Longan_nano::Screen::SPRITE_SIZE
@ SPRITE_SIZE
Definition: longan_nano_screen.hpp:258
Longan_nano::Screen::_Format_number::eng_exp
int8_t eng_exp
Definition: longan_nano_screen.hpp:486
Longan_nano::Screen::PENDING_UNDERFLOW
@ PENDING_UNDERFLOW
Definition: longan_nano_screen.hpp:300
Longan_nano::Screen::FRAME_BUFFER_WIDTH
@ FRAME_BUFFER_WIDTH
Definition: longan_nano_screen.hpp:255
Longan_nano::Screen::PEDANTIC_CHECKS
@ PEDANTIC_CHECKS
Definition: longan_nano_screen.hpp:235
Longan_nano::Screen::SPRITE_SIZE_BIT
@ SPRITE_SIZE_BIT
Definition: longan_nano_screen.hpp:259
Longan_nano::Screen::_Fsm_status
Status of the update FSM.
Definition: longan_nano_screen.hpp:467
Longan_nano::Screen::~Screen
~Screen(void)
empty destructor ~Screen | void |
Definition: longan_nano_screen.hpp:866
Longan_nano::Screen::clear
int clear(void)
public method clear | void |
Definition: longan_nano_screen.hpp:1755
Longan_nano::Screen::_Fsm_status::phase
Fsm_state phase
Definition: longan_nano_screen.hpp:473
Longan_nano::Screen::g_default_foreground_color
Color g_default_foreground_color
Definition: longan_nano_screen.hpp:592
Longan_nano::Display
Longan Nano Display Driver.
Definition: ST7735S_W160_H80_C16.hpp:124
Longan_nano::Screen::_Config
_Config
Configuration parameters for the logical screen.
Definition: longan_nano_screen.hpp:230
Longan_nano::Screen::SPRITE_FOREGROUND
@ SPRITE_FOREGROUND
Definition: longan_nano_screen.hpp:247
Longan_nano::Screen::SPRITE_TRANSPARENT
@ SPRITE_TRANSPARENT
Definition: longan_nano_screen.hpp:243
Longan_nano::Screen::_Format_number
number format to be printed by the print number method
Definition: longan_nano_screen.hpp:478
Longan_nano::Screen::set_palette_color
int set_palette_color(Color palette_index, uint8_t r, uint8_t g, uint8_t b)
public setter set_palette_color | Color | uint8_t | uint8_t | uint8_t |
Definition: longan_nano_screen.hpp:1243
Longan_nano::Screen::LCYAN
@ LCYAN
Definition: longan_nano_screen.hpp:272
Longan_nano::Screen::change_color
int change_color(Color source, Color dest)
public method change_color | Color | Color |
Definition: longan_nano_screen.hpp:1683
Longan_nano::Screen::_Frame_buffer_sprite::sprite_index
uint8_t sprite_index
Definition: longan_nano_screen.hpp:462
Longan_nano::Screen::g_format_number
Format_number g_format_number
Display format for print numeric values.
Definition: longan_nano_screen.hpp:604
Longan_nano::Screen::Fsm_state
enum Longan_nano::Screen::_Fsm_state Fsm_state
States of the Screen side FSM. Display driver also has its own FSM states
Longan_nano::Screen::_Format_number::size
int size
Definition: longan_nano_screen.hpp:480
Longan_nano::Screen::RED
@ RED
Definition: longan_nano_screen.hpp:265
Longan_nano::Screen::SPRITE_HEIGHT
@ SPRITE_HEIGHT
Definition: longan_nano_screen.hpp:238
Longan_nano::Screen::init_fsm
bool init_fsm(void)
private init init_fsm | void |
Definition: longan_nano_screen.hpp:2802
Longan_nano::Screen::Format_number
struct Longan_nano::Screen::_Format_number Format_number
number format to be printed by the print number method
Longan_nano::Screen::Color
enum Longan_nano::Screen::_Color Color
Use the default Color palette. Short hand indexes for user. User can change the palette at will.
Longan_nano::Screen::SEND_SPRITE
@ SEND_SPRITE
Definition: longan_nano_screen.hpp:447
Longan_nano::Display::update_sprite
bool update_sprite(void)
public method update_sprite | void |
Definition: ST7735S_W160_H80_C16.hpp:632
Longan_nano::Screen::NUM
@ NUM
Definition: longan_nano_screen.hpp:282
Longan_nano::Screen::PENDING_OVERFLOW
@ PENDING_OVERFLOW
Definition: longan_nano_screen.hpp:299
Longan_nano::Screen::PALETTE_SIZE_BIT
@ PALETTE_SIZE_BIT
Definition: longan_nano_screen.hpp:253