Library to control a Graphics TFT connected to 4-wire SPI - revised for the Raio RA8875 Display Controller.

Dependents:   FRDM_RA8875_mPaint RA8875_Demo RA8875_KeyPadDemo SignalGenerator ... more

Fork of SPI_TFT by Peter Drescher

See Components - RA8875 Based Display

Enhanced touch-screen support - where it previous supported both the Resistive Touch and Capacitive Touch based on the FT5206 Touch Controller, now it also has support for the GSL1680 Touch Controller.

Offline Help Manual (Windows chm)

/media/uploads/WiredHome/ra8875.zip.bin (download, rename to .zip and unzip)

Files at this revision

API Documentation at this revision

Comitter:
WiredHome
Date:
Sat Mar 28 15:01:38 2020 +0000
Parent:
197:853d08e2fb53
Child:
199:fb06805f447f
Commit message:
BREAKING Changes - ; This update alters several APIs, renames some, and generally simplifies. It also has great improvement for Portrait mode orientation.

Changed in this revision

DisplayDefs.h Show annotated file Show diff for this revision Revisions of this file
Fonts/BPG_Arial08x08.h Show annotated file Show diff for this revision Revisions of this file
Fonts/BPG_Arial10x10.h Show annotated file Show diff for this revision Revisions of this file
Fonts/FontMods.h Show annotated file Show diff for this revision Revisions of this file
GraphicsDisplay.cpp Show annotated file Show diff for this revision Revisions of this file
GraphicsDisplay.h Show annotated file Show diff for this revision Revisions of this file
GraphicsDisplayGIF.cpp Show annotated file Show diff for this revision Revisions of this file
GraphicsDisplayJPEG.cpp Show annotated file Show diff for this revision Revisions of this file
RA8875.cpp Show annotated file Show diff for this revision Revisions of this file
RA8875.h Show annotated file Show diff for this revision Revisions of this file
RA8875_Regs.h Show annotated file Show diff for this revision Revisions of this file
RA8875_Touch.cpp Show annotated file Show diff for this revision Revisions of this file
RA8875_Touch_FT5206.h Show annotated file Show diff for this revision Revisions of this file
TextDisplay.cpp Show annotated file Show diff for this revision Revisions of this file
TextDisplay.h Show annotated file Show diff for this revision Revisions of this file
--- a/DisplayDefs.h	Tue Feb 11 21:51:42 2020 +0000
+++ b/DisplayDefs.h	Sat Mar 28 15:01:38 2020 +0000
@@ -52,6 +52,18 @@
     no_cal,                 ///< no calibration matrix is available
 } TouchCode_t;
 
+/// display orientation argument for @ref RA8875::SetGraphicsOrientation(), @ref RA8875::GetGraphicsOrientation()
+/// with landscape mode as the normal (0 degree) orientation.
+typedef enum
+{
+    normal,         ///< normal (landscape) orientation
+    rotate_0 = normal,  ///< alternate to 'normal'
+    rotate_90,      ///< rotated clockwise 90 degree
+    rotate_180,     ///< rotated (clockwise) 180 degree
+    rotate_270,     ///< rotated clockwise 270 degree
+    invalid,        ///< an invalid angle was detected
+} orientation_t;
+
 /// Data type that manages locations, which is typically an x or y pixel location,
 /// which can range from -N to +N (even as the screen is always defined in the
 /// range of 0 to +n). See also @ref textloc_t.
--- a/Fonts/BPG_Arial08x08.h	Tue Feb 11 21:51:42 2020 +0000
+++ b/Fonts/BPG_Arial08x08.h	Sat Mar 28 15:01:38 2020 +0000
@@ -1,39 +1,37 @@
-//                                                                               
-//    This script modifies a font file which was generated with a tool by        
-//    MikroElektronika - GLD Font Creator.                                       
-//                                                                               
-//    That tool creates the font data set for an embedded system from a Windows  
-//    True Type font. The user is encouraged to ensure that the font used is     
-//    properly licenses, or drawn from a source that does not have a license     
-//    restriction.                                                               
-//                                                                               
+//                                                                              
+//    This script modifies a font file which was generated with a tool by       
+//    MikroElektronika - GLD Font Creator.                                      
+//                                                                              
+//    That tool creates the font data set for an embedded system from a Windows 
+//    True Type font. The user is encouraged to ensure that the font used is    
+//    properly licenses, or drawn from a source that does not have a license    
+//    restriction.                                                              
+//                                                                              
 //    This script will read and then modify the file for a few specific purposes:
-//      * <space>   character is redefined to set the width to 1/4 the height.   
+//      * <space>   character is redefined to set the width to 1/4 the height.  
 //      * '0' - '9' characters are redefined to set the width equal to width('0')
-//                  or to the user override value.                               
-//                                                                               
-//    And just because it can, it then improves upon the documentation in the    
-//    resulting data structure.                                                  
-//                                                                               
-//    This script was created by Smartware Computing, and is provided 'as is'    
-//    with no warranty or suitability of fitness for any purpose. Anyone may use 
-//    or modify it subject to the agreement that:                                
-//      * The Smartware copyright statement remains intact.                      
-//      * Modifications for derivative use are clearly stated in this header.    
-//                                                                               
-//    Modifications from the original:                                           
-//      * none.                                                                  
-//                                                                               
+//                  or to the user override value.                              
+//                                                                              
+//    And just because it can, it then improves upon the documentation in the   
+//    resulting data structure.                                                 
+//                                                                              
+//    This script was created by Smartware Computing, and is provided 'as is'   
+//    with no warranty or suitability of fitness for any purpose. Anyone may use
+//    or modify it subject to the agreement that:                               
+//      * The Smartware copyright statement remains intact.                     
+//      * Modifications for derivative use are clearly stated in this header.   
+//                                                                              
+//    Modifications from the original:                                          
+//      * none.                                                                 
+//                                                                              
 // Script Activation:
 //   ParseMikroeFont BPG_Arial08x08.h New_BPG_Arial08x08.h
-
 //Font Generated by MikroElektronika GLCD Font Creator 1.2.0.0
-//MikroElektrnika 2011 
-//http://www.mikroe.com 
+//MikroElektrnika 2011
+//http://www.mikroe.com
 
 //GLCD FontName : BPG_Arial8x8
 //GLCD FontSize : 8 x 8
-
 const unsigned char BPG_Arial08x08[] = {
     // Font Info
     0x00,                   // Unknown #1
@@ -43,102 +41,102 @@
     0x08,                   // FontHeight
     0x00,                   // Unknown #3
     // Directory of Chars  [Width] [Offset-L] [Offset-M] [Offset-H]
-    0x02,0x88,0x01,0x00,    // 0x20 ' ' 
-    0x02,0x90,0x01,0x00,    // 0x21 '!' 
-    0x04,0x98,0x01,0x00,    // 0x22 '"' 
-    0x06,0xA0,0x01,0x00,    // 0x23 '#' 
-    0x06,0xA8,0x01,0x00,    // 0x24 '$' 
-    0x07,0xB0,0x01,0x00,    // 0x25 '%' 
-    0x06,0xB8,0x01,0x00,    // 0x26 '&' 
-    0x02,0xC0,0x01,0x00,    // 0x27 ''' 
-    0x03,0xC8,0x01,0x00,    // 0x28 '(' 
-    0x03,0xD0,0x01,0x00,    // 0x29 ')' 
-    0x06,0xD8,0x01,0x00,    // 0x2A '*' 
-    0x06,0xE0,0x01,0x00,    // 0x2B '+' 
-    0x03,0xE8,0x01,0x00,    // 0x2C ',' 
-    0x04,0xF0,0x01,0x00,    // 0x2D '-' 
-    0x02,0xF8,0x01,0x00,    // 0x2E '.' 
-    0x04,0x00,0x02,0x00,    // 0x2F '/' 
-    0x06,0x08,0x02,0x00,    // 0x30 '0' 
-    0x06,0x10,0x02,0x00,    // 0x31 '1' 
-    0x06,0x18,0x02,0x00,    // 0x32 '2' 
-    0x06,0x20,0x02,0x00,    // 0x33 '3' 
-    0x06,0x28,0x02,0x00,    // 0x34 '4' 
-    0x06,0x30,0x02,0x00,    // 0x35 '5' 
-    0x06,0x38,0x02,0x00,    // 0x36 '6' 
-    0x06,0x40,0x02,0x00,    // 0x37 '7' 
-    0x06,0x48,0x02,0x00,    // 0x38 '8' 
-    0x06,0x50,0x02,0x00,    // 0x39 '9' 
-    0x02,0x58,0x02,0x00,    // 0x3A ':' 
-    0x03,0x60,0x02,0x00,    // 0x3B ';' 
-    0x06,0x68,0x02,0x00,    // 0x3C '<' 
-    0x06,0x70,0x02,0x00,    // 0x3D '=' 
-    0x06,0x78,0x02,0x00,    // 0x3E '>' 
-    0x06,0x80,0x02,0x00,    // 0x3F '?' 
-    0x07,0x88,0x02,0x00,    // 0x40 '@' 
-    0x06,0x90,0x02,0x00,    // 0x41 'A' 
-    0x06,0x98,0x02,0x00,    // 0x42 'B' 
-    0x06,0xA0,0x02,0x00,    // 0x43 'C' 
-    0x06,0xA8,0x02,0x00,    // 0x44 'D' 
-    0x06,0xB0,0x02,0x00,    // 0x45 'E' 
-    0x06,0xB8,0x02,0x00,    // 0x46 'F' 
-    0x06,0xC0,0x02,0x00,    // 0x47 'G' 
-    0x06,0xC8,0x02,0x00,    // 0x48 'H' 
-    0x02,0xD0,0x02,0x00,    // 0x49 'I' 
-    0x05,0xD8,0x02,0x00,    // 0x4A 'J' 
-    0x06,0xE0,0x02,0x00,    // 0x4B 'K' 
-    0x06,0xE8,0x02,0x00,    // 0x4C 'L' 
-    0x06,0xF0,0x02,0x00,    // 0x4D 'M' 
-    0x06,0xF8,0x02,0x00,    // 0x4E 'N' 
-    0x06,0x00,0x03,0x00,    // 0x4F 'O' 
-    0x06,0x08,0x03,0x00,    // 0x50 'P' 
-    0x06,0x10,0x03,0x00,    // 0x51 'Q' 
-    0x06,0x18,0x03,0x00,    // 0x52 'R' 
-    0x06,0x20,0x03,0x00,    // 0x53 'S' 
-    0x06,0x28,0x03,0x00,    // 0x54 'T' 
-    0x06,0x30,0x03,0x00,    // 0x55 'U' 
-    0x06,0x38,0x03,0x00,    // 0x56 'V' 
-    0x05,0x40,0x03,0x00,    // 0x57 'W' 
-    0x06,0x48,0x03,0x00,    // 0x58 'X' 
-    0x06,0x50,0x03,0x00,    // 0x59 'Y' 
-    0x06,0x58,0x03,0x00,    // 0x5A 'Z' 
-    0x03,0x60,0x03,0x00,    // 0x5B '[' 
-    0x04,0x68,0x03,0x00,    // 0x5C '\\' 
-    0x03,0x70,0x03,0x00,    // 0x5D ']' 
-    0x05,0x78,0x03,0x00,    // 0x5E '^' 
-    0x06,0x80,0x03,0x00,    // 0x5F '_' 
-    0x03,0x88,0x03,0x00,    // 0x60 '`' 
-    0x05,0x90,0x03,0x00,    // 0x61 'a' 
-    0x05,0x98,0x03,0x00,    // 0x62 'b' 
-    0x06,0xA0,0x03,0x00,    // 0x63 'c' 
-    0x06,0xA8,0x03,0x00,    // 0x64 'd' 
-    0x06,0xB0,0x03,0x00,    // 0x65 'e' 
-    0x04,0xB8,0x03,0x00,    // 0x66 'f' 
-    0x06,0xC0,0x03,0x00,    // 0x67 'g' 
-    0x05,0xC8,0x03,0x00,    // 0x68 'h' 
-    0x02,0xD0,0x03,0x00,    // 0x69 'i' 
-    0x03,0xD8,0x03,0x00,    // 0x6A 'j' 
-    0x05,0xE0,0x03,0x00,    // 0x6B 'k' 
-    0x02,0xE8,0x03,0x00,    // 0x6C 'l' 
-    0x06,0xF0,0x03,0x00,    // 0x6D 'm' 
-    0x06,0xF8,0x03,0x00,    // 0x6E 'n' 
-    0x06,0x00,0x04,0x00,    // 0x6F 'o' 
-    0x06,0x08,0x04,0x00,    // 0x70 'p' 
-    0x06,0x10,0x04,0x00,    // 0x71 'q' 
-    0x04,0x18,0x04,0x00,    // 0x72 'r' 
-    0x06,0x20,0x04,0x00,    // 0x73 's' 
-    0x06,0x28,0x04,0x00,    // 0x74 't' 
-    0x05,0x30,0x04,0x00,    // 0x75 'u' 
-    0x06,0x38,0x04,0x00,    // 0x76 'v' 
-    0x08,0x40,0x04,0x00,    // 0x77 'w' 
-    0x06,0x48,0x04,0x00,    // 0x78 'x' 
-    0x05,0x50,0x04,0x00,    // 0x79 'y' 
-    0x05,0x58,0x04,0x00,    // 0x7A 'z' 
-    0x04,0x60,0x04,0x00,    // 0x7B '{' 
-    0x02,0x68,0x04,0x00,    // 0x7C '|' 
-    0x04,0x70,0x04,0x00,    // 0x7D '}' 
-    0x07,0x78,0x04,0x00,    // 0x7E '~' 
-    0x04,0x80,0x04,0x00,    // 0x7F '<non-printable>' 
+    0x02,0x88,0x01,0x00,    // 0x20 ' '
+    0x02,0x90,0x01,0x00,    // 0x21 '!'
+    0x04,0x98,0x01,0x00,    // 0x22 '"'
+    0x06,0xA0,0x01,0x00,    // 0x23 '#'
+    0x06,0xA8,0x01,0x00,    // 0x24 '$'
+    0x07,0xB0,0x01,0x00,    // 0x25 '%'
+    0x06,0xB8,0x01,0x00,    // 0x26 '&'
+    0x02,0xC0,0x01,0x00,    // 0x27 '''
+    0x03,0xC8,0x01,0x00,    // 0x28 '('
+    0x03,0xD0,0x01,0x00,    // 0x29 ')'
+    0x06,0xD8,0x01,0x00,    // 0x2A '*'
+    0x06,0xE0,0x01,0x00,    // 0x2B '+'
+    0x03,0xE8,0x01,0x00,    // 0x2C ','
+    0x04,0xF0,0x01,0x00,    // 0x2D '-'
+    0x02,0xF8,0x01,0x00,    // 0x2E '.'
+    0x04,0x00,0x02,0x00,    // 0x2F '/'
+    0x06,0x08,0x02,0x00,    // 0x30 '0'
+    0x06,0x10,0x02,0x00,    // 0x31 '1'
+    0x06,0x18,0x02,0x00,    // 0x32 '2'
+    0x06,0x20,0x02,0x00,    // 0x33 '3'
+    0x06,0x28,0x02,0x00,    // 0x34 '4'
+    0x06,0x30,0x02,0x00,    // 0x35 '5'
+    0x06,0x38,0x02,0x00,    // 0x36 '6'
+    0x06,0x40,0x02,0x00,    // 0x37 '7'
+    0x06,0x48,0x02,0x00,    // 0x38 '8'
+    0x06,0x50,0x02,0x00,    // 0x39 '9'
+    0x02,0x58,0x02,0x00,    // 0x3A ':'
+    0x03,0x60,0x02,0x00,    // 0x3B ';'
+    0x06,0x68,0x02,0x00,    // 0x3C '<'
+    0x06,0x70,0x02,0x00,    // 0x3D '='
+    0x06,0x78,0x02,0x00,    // 0x3E '>'
+    0x06,0x80,0x02,0x00,    // 0x3F '?'
+    0x07,0x88,0x02,0x00,    // 0x40 '@'
+    0x06,0x90,0x02,0x00,    // 0x41 'A'
+    0x06,0x98,0x02,0x00,    // 0x42 'B'
+    0x06,0xA0,0x02,0x00,    // 0x43 'C'
+    0x06,0xA8,0x02,0x00,    // 0x44 'D'
+    0x06,0xB0,0x02,0x00,    // 0x45 'E'
+    0x06,0xB8,0x02,0x00,    // 0x46 'F'
+    0x06,0xC0,0x02,0x00,    // 0x47 'G'
+    0x06,0xC8,0x02,0x00,    // 0x48 'H'
+    0x02,0xD0,0x02,0x00,    // 0x49 'I'
+    0x05,0xD8,0x02,0x00,    // 0x4A 'J'
+    0x06,0xE0,0x02,0x00,    // 0x4B 'K'
+    0x06,0xE8,0x02,0x00,    // 0x4C 'L'
+    0x06,0xF0,0x02,0x00,    // 0x4D 'M'
+    0x06,0xF8,0x02,0x00,    // 0x4E 'N'
+    0x06,0x00,0x03,0x00,    // 0x4F 'O'
+    0x06,0x08,0x03,0x00,    // 0x50 'P'
+    0x06,0x10,0x03,0x00,    // 0x51 'Q'
+    0x06,0x18,0x03,0x00,    // 0x52 'R'
+    0x06,0x20,0x03,0x00,    // 0x53 'S'
+    0x06,0x28,0x03,0x00,    // 0x54 'T'
+    0x06,0x30,0x03,0x00,    // 0x55 'U'
+    0x06,0x38,0x03,0x00,    // 0x56 'V'
+    0x05,0x40,0x03,0x00,    // 0x57 'W'
+    0x06,0x48,0x03,0x00,    // 0x58 'X'
+    0x06,0x50,0x03,0x00,    // 0x59 'Y'
+    0x06,0x58,0x03,0x00,    // 0x5A 'Z'
+    0x03,0x60,0x03,0x00,    // 0x5B '['
+    0x04,0x68,0x03,0x00,    // 0x5C '\\'
+    0x03,0x70,0x03,0x00,    // 0x5D ']'
+    0x05,0x78,0x03,0x00,    // 0x5E '^'
+    0x06,0x80,0x03,0x00,    // 0x5F '_'
+    0x03,0x88,0x03,0x00,    // 0x60 '`'
+    0x05,0x90,0x03,0x00,    // 0x61 'a'
+    0x05,0x98,0x03,0x00,    // 0x62 'b'
+    0x06,0xA0,0x03,0x00,    // 0x63 'c'
+    0x06,0xA8,0x03,0x00,    // 0x64 'd'
+    0x06,0xB0,0x03,0x00,    // 0x65 'e'
+    0x04,0xB8,0x03,0x00,    // 0x66 'f'
+    0x06,0xC0,0x03,0x00,    // 0x67 'g'
+    0x05,0xC8,0x03,0x00,    // 0x68 'h'
+    0x02,0xD0,0x03,0x00,    // 0x69 'i'
+    0x03,0xD8,0x03,0x00,    // 0x6A 'j'
+    0x05,0xE0,0x03,0x00,    // 0x6B 'k'
+    0x02,0xE8,0x03,0x00,    // 0x6C 'l'
+    0x06,0xF0,0x03,0x00,    // 0x6D 'm'
+    0x06,0xF8,0x03,0x00,    // 0x6E 'n'
+    0x06,0x00,0x04,0x00,    // 0x6F 'o'
+    0x06,0x08,0x04,0x00,    // 0x70 'p'
+    0x06,0x10,0x04,0x00,    // 0x71 'q'
+    0x04,0x18,0x04,0x00,    // 0x72 'r'
+    0x06,0x20,0x04,0x00,    // 0x73 's'
+    0x06,0x28,0x04,0x00,    // 0x74 't'
+    0x05,0x30,0x04,0x00,    // 0x75 'u'
+    0x06,0x38,0x04,0x00,    // 0x76 'v'
+    0x08,0x40,0x04,0x00,    // 0x77 'w'
+    0x06,0x48,0x04,0x00,    // 0x78 'x'
+    0x05,0x50,0x04,0x00,    // 0x79 'y'
+    0x05,0x58,0x04,0x00,    // 0x7A 'z'
+    0x04,0x60,0x04,0x00,    // 0x7B '{'
+    0x02,0x68,0x04,0x00,    // 0x7C '|'
+    0x04,0x70,0x04,0x00,    // 0x7D '}'
+    0x07,0x78,0x04,0x00,    // 0x7E '~'
+    0x04,0x80,0x04,0x00,    // 0x7F '<non-printable>'
     // Chars Bitstream
     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  // 0x20 ' '
     0x02,0x02,0x02,0x02,0x02,0x00,0x02,0x00,  // 0x21 '!'
--- a/Fonts/BPG_Arial10x10.h	Tue Feb 11 21:51:42 2020 +0000
+++ b/Fonts/BPG_Arial10x10.h	Sat Mar 28 15:01:38 2020 +0000
@@ -1,39 +1,37 @@
-//                                                                               
-//    This script modifies a font file which was generated with a tool by        
-//    MikroElektronika - GLD Font Creator.                                       
-//                                                                               
-//    That tool creates the font data set for an embedded system from a Windows  
-//    True Type font. The user is encouraged to ensure that the font used is     
-//    properly licenses, or drawn from a source that does not have a license     
-//    restriction.                                                               
-//                                                                               
+//                                                                              
+//    This script modifies a font file which was generated with a tool by       
+//    MikroElektronika - GLD Font Creator.                                      
+//                                                                              
+//    That tool creates the font data set for an embedded system from a Windows 
+//    True Type font. The user is encouraged to ensure that the font used is    
+//    properly licenses, or drawn from a source that does not have a license    
+//    restriction.                                                              
+//                                                                              
 //    This script will read and then modify the file for a few specific purposes:
-//      * <space>   character is redefined to set the width to 1/4 the height.   
+//      * <space>   character is redefined to set the width to 1/4 the height.  
 //      * '0' - '9' characters are redefined to set the width equal to width('0')
-//                  or to the user override value.                               
-//                                                                               
-//    And just because it can, it then improves upon the documentation in the    
-//    resulting data structure.                                                  
-//                                                                               
-//    This script was created by Smartware Computing, and is provided 'as is'    
-//    with no warranty or suitability of fitness for any purpose. Anyone may use 
-//    or modify it subject to the agreement that:                                
-//      * The Smartware copyright statement remains intact.                      
-//      * Modifications for derivative use are clearly stated in this header.    
-//                                                                               
-//    Modifications from the original:                                           
-//      * none.                                                                  
-//                                                                               
+//                  or to the user override value.                              
+//                                                                              
+//    And just because it can, it then improves upon the documentation in the   
+//    resulting data structure.                                                 
+//                                                                              
+//    This script was created by Smartware Computing, and is provided 'as is'   
+//    with no warranty or suitability of fitness for any purpose. Anyone may use
+//    or modify it subject to the agreement that:                               
+//      * The Smartware copyright statement remains intact.                     
+//      * Modifications for derivative use are clearly stated in this header.   
+//                                                                              
+//    Modifications from the original:                                          
+//      * none.                                                                 
+//                                                                              
 // Script Activation:
 //   ParseMikroeFont BPG_Arial10x10.h New_BPG_Arial10x10.h
-
 //Font Generated by MikroElektronika GLCD Font Creator 1.2.0.0
-//MikroElektrnika 2011 
-//http://www.mikroe.com 
+//MikroElektrnika 2011
+//http://www.mikroe.com
 
 //GLCD FontName : BPG_Arial10x10
 //GLCD FontSize : 10 x 10
-
 const unsigned char BPG_Arial10x10[] = {
     // Font Info
     0x00,                   // Unknown #1
@@ -43,102 +41,102 @@
     0x0A,                   // FontHeight
     0x00,                   // Unknown #3
     // Directory of Chars  [Width] [Offset-L] [Offset-M] [Offset-H]
-    0x02,0x88,0x01,0x00,    // 0x20 ' ' 
-    0x02,0x92,0x01,0x00,    // 0x21 '!' 
-    0x03,0x9C,0x01,0x00,    // 0x22 '"' 
-    0x06,0xA6,0x01,0x00,    // 0x23 '#' 
-    0x06,0xB0,0x01,0x00,    // 0x24 '$' 
-    0x09,0xBA,0x01,0x00,    // 0x25 '%' 
-    0x07,0xCE,0x01,0x00,    // 0x26 '&' 
-    0x01,0xD8,0x01,0x00,    // 0x27 ''' 
-    0x03,0xE2,0x01,0x00,    // 0x28 '(' 
-    0x03,0xEC,0x01,0x00,    // 0x29 ')' 
-    0x06,0xF6,0x01,0x00,    // 0x2A '*' 
-    0x06,0x00,0x02,0x00,    // 0x2B '+' 
-    0x02,0x0A,0x02,0x00,    // 0x2C ',' 
-    0x03,0x14,0x02,0x00,    // 0x2D '-' 
-    0x02,0x1E,0x02,0x00,    // 0x2E '.' 
-    0x03,0x28,0x02,0x00,    // 0x2F '/' 
-    0x07,0x32,0x02,0x00,    // 0x30 '0' 
-    0x07,0x3C,0x02,0x00,    // 0x31 '1' 
-    0x07,0x46,0x02,0x00,    // 0x32 '2' 
-    0x07,0x50,0x02,0x00,    // 0x33 '3' 
-    0x07,0x5A,0x02,0x00,    // 0x34 '4' 
-    0x07,0x64,0x02,0x00,    // 0x35 '5' 
-    0x07,0x6E,0x02,0x00,    // 0x36 '6' 
-    0x07,0x78,0x02,0x00,    // 0x37 '7' 
-    0x07,0x82,0x02,0x00,    // 0x38 '8' 
-    0x07,0x8C,0x02,0x00,    // 0x39 '9' 
-    0x02,0x96,0x02,0x00,    // 0x3A ':' 
-    0x02,0xA0,0x02,0x00,    // 0x3B ';' 
-    0x06,0xAA,0x02,0x00,    // 0x3C '<' 
-    0x06,0xB4,0x02,0x00,    // 0x3D '=' 
-    0x06,0xBE,0x02,0x00,    // 0x3E '>' 
-    0x06,0xC8,0x02,0x00,    // 0x3F '?' 
-    0x09,0xD2,0x02,0x00,    // 0x40 '@' 
-    0x07,0xE6,0x02,0x00,    // 0x41 'A' 
-    0x07,0xF0,0x02,0x00,    // 0x42 'B' 
-    0x07,0xFA,0x02,0x00,    // 0x43 'C' 
-    0x07,0x04,0x03,0x00,    // 0x44 'D' 
-    0x06,0x0E,0x03,0x00,    // 0x45 'E' 
-    0x06,0x18,0x03,0x00,    // 0x46 'F' 
-    0x07,0x22,0x03,0x00,    // 0x47 'G' 
-    0x07,0x2C,0x03,0x00,    // 0x48 'H' 
-    0x02,0x36,0x03,0x00,    // 0x49 'I' 
-    0x06,0x40,0x03,0x00,    // 0x4A 'J' 
-    0x07,0x4A,0x03,0x00,    // 0x4B 'K' 
-    0x06,0x54,0x03,0x00,    // 0x4C 'L' 
-    0x08,0x5E,0x03,0x00,    // 0x4D 'M' 
-    0x07,0x68,0x03,0x00,    // 0x4E 'N' 
-    0x07,0x72,0x03,0x00,    // 0x4F 'O' 
-    0x07,0x7C,0x03,0x00,    // 0x50 'P' 
-    0x07,0x86,0x03,0x00,    // 0x51 'Q' 
-    0x07,0x90,0x03,0x00,    // 0x52 'R' 
-    0x07,0x9A,0x03,0x00,    // 0x53 'S' 
-    0x06,0xA4,0x03,0x00,    // 0x54 'T' 
-    0x07,0xAE,0x03,0x00,    // 0x55 'U' 
-    0x08,0xB8,0x03,0x00,    // 0x56 'V' 
-    0x0A,0xC2,0x03,0x00,    // 0x57 'W' 
-    0x07,0xD6,0x03,0x00,    // 0x58 'X' 
-    0x08,0xE0,0x03,0x00,    // 0x59 'Y' 
-    0x06,0xEA,0x03,0x00,    // 0x5A 'Z' 
-    0x03,0xF4,0x03,0x00,    // 0x5B '[' 
-    0x04,0xFE,0x03,0x00,    // 0x5C '\\' 
-    0x03,0x08,0x04,0x00,    // 0x5D ']' 
-    0x05,0x12,0x04,0x00,    // 0x5E '^' 
-    0x06,0x1C,0x04,0x00,    // 0x5F '_' 
-    0x02,0x26,0x04,0x00,    // 0x60 '`' 
-    0x05,0x30,0x04,0x00,    // 0x61 'a' 
-    0x05,0x3A,0x04,0x00,    // 0x62 'b' 
-    0x06,0x44,0x04,0x00,    // 0x63 'c' 
-    0x06,0x4E,0x04,0x00,    // 0x64 'd' 
-    0x06,0x58,0x04,0x00,    // 0x65 'e' 
-    0x04,0x62,0x04,0x00,    // 0x66 'f' 
-    0x06,0x6C,0x04,0x00,    // 0x67 'g' 
-    0x05,0x76,0x04,0x00,    // 0x68 'h' 
-    0x02,0x80,0x04,0x00,    // 0x69 'i' 
-    0x03,0x8A,0x04,0x00,    // 0x6A 'j' 
-    0x05,0x94,0x04,0x00,    // 0x6B 'k' 
-    0x02,0x9E,0x04,0x00,    // 0x6C 'l' 
-    0x08,0xA8,0x04,0x00,    // 0x6D 'm' 
-    0x05,0xB2,0x04,0x00,    // 0x6E 'n' 
-    0x06,0xBC,0x04,0x00,    // 0x6F 'o' 
-    0x06,0xC6,0x04,0x00,    // 0x70 'p' 
-    0x06,0xD0,0x04,0x00,    // 0x71 'q' 
-    0x04,0xDA,0x04,0x00,    // 0x72 'r' 
-    0x06,0xE4,0x04,0x00,    // 0x73 's' 
-    0x04,0xEE,0x04,0x00,    // 0x74 't' 
-    0x05,0xF8,0x04,0x00,    // 0x75 'u' 
-    0x06,0x02,0x05,0x00,    // 0x76 'v' 
-    0x08,0x0C,0x05,0x00,    // 0x77 'w' 
-    0x06,0x16,0x05,0x00,    // 0x78 'x' 
-    0x06,0x20,0x05,0x00,    // 0x79 'y' 
-    0x05,0x2A,0x05,0x00,    // 0x7A 'z' 
-    0x04,0x34,0x05,0x00,    // 0x7B '{' 
-    0x02,0x3E,0x05,0x00,    // 0x7C '|' 
-    0x04,0x48,0x05,0x00,    // 0x7D '}' 
-    0x07,0x52,0x05,0x00,    // 0x7E '~' 
-    0x04,0x5C,0x05,0x00,    // 0x7F '<non-printable>' 
+    0x02,0x88,0x01,0x00,    // 0x20 ' '
+    0x02,0x92,0x01,0x00,    // 0x21 '!'
+    0x03,0x9C,0x01,0x00,    // 0x22 '"'
+    0x06,0xA6,0x01,0x00,    // 0x23 '#'
+    0x06,0xB0,0x01,0x00,    // 0x24 '$'
+    0x09,0xBA,0x01,0x00,    // 0x25 '%'
+    0x07,0xCE,0x01,0x00,    // 0x26 '&'
+    0x01,0xD8,0x01,0x00,    // 0x27 '''
+    0x03,0xE2,0x01,0x00,    // 0x28 '('
+    0x03,0xEC,0x01,0x00,    // 0x29 ')'
+    0x06,0xF6,0x01,0x00,    // 0x2A '*'
+    0x06,0x00,0x02,0x00,    // 0x2B '+'
+    0x02,0x0A,0x02,0x00,    // 0x2C ','
+    0x03,0x14,0x02,0x00,    // 0x2D '-'
+    0x02,0x1E,0x02,0x00,    // 0x2E '.'
+    0x03,0x28,0x02,0x00,    // 0x2F '/'
+    0x07,0x32,0x02,0x00,    // 0x30 '0'
+    0x07,0x3C,0x02,0x00,    // 0x31 '1'
+    0x07,0x46,0x02,0x00,    // 0x32 '2'
+    0x07,0x50,0x02,0x00,    // 0x33 '3'
+    0x07,0x5A,0x02,0x00,    // 0x34 '4'
+    0x07,0x64,0x02,0x00,    // 0x35 '5'
+    0x07,0x6E,0x02,0x00,    // 0x36 '6'
+    0x07,0x78,0x02,0x00,    // 0x37 '7'
+    0x07,0x82,0x02,0x00,    // 0x38 '8'
+    0x07,0x8C,0x02,0x00,    // 0x39 '9'
+    0x02,0x96,0x02,0x00,    // 0x3A ':'
+    0x02,0xA0,0x02,0x00,    // 0x3B ';'
+    0x06,0xAA,0x02,0x00,    // 0x3C '<'
+    0x06,0xB4,0x02,0x00,    // 0x3D '='
+    0x06,0xBE,0x02,0x00,    // 0x3E '>'
+    0x06,0xC8,0x02,0x00,    // 0x3F '?'
+    0x09,0xD2,0x02,0x00,    // 0x40 '@'
+    0x07,0xE6,0x02,0x00,    // 0x41 'A'
+    0x07,0xF0,0x02,0x00,    // 0x42 'B'
+    0x07,0xFA,0x02,0x00,    // 0x43 'C'
+    0x07,0x04,0x03,0x00,    // 0x44 'D'
+    0x06,0x0E,0x03,0x00,    // 0x45 'E'
+    0x06,0x18,0x03,0x00,    // 0x46 'F'
+    0x07,0x22,0x03,0x00,    // 0x47 'G'
+    0x07,0x2C,0x03,0x00,    // 0x48 'H'
+    0x02,0x36,0x03,0x00,    // 0x49 'I'
+    0x06,0x40,0x03,0x00,    // 0x4A 'J'
+    0x07,0x4A,0x03,0x00,    // 0x4B 'K'
+    0x06,0x54,0x03,0x00,    // 0x4C 'L'
+    0x08,0x5E,0x03,0x00,    // 0x4D 'M'
+    0x07,0x68,0x03,0x00,    // 0x4E 'N'
+    0x07,0x72,0x03,0x00,    // 0x4F 'O'
+    0x07,0x7C,0x03,0x00,    // 0x50 'P'
+    0x07,0x86,0x03,0x00,    // 0x51 'Q'
+    0x07,0x90,0x03,0x00,    // 0x52 'R'
+    0x07,0x9A,0x03,0x00,    // 0x53 'S'
+    0x06,0xA4,0x03,0x00,    // 0x54 'T'
+    0x07,0xAE,0x03,0x00,    // 0x55 'U'
+    0x08,0xB8,0x03,0x00,    // 0x56 'V'
+    0x0A,0xC2,0x03,0x00,    // 0x57 'W'
+    0x07,0xD6,0x03,0x00,    // 0x58 'X'
+    0x08,0xE0,0x03,0x00,    // 0x59 'Y'
+    0x06,0xEA,0x03,0x00,    // 0x5A 'Z'
+    0x03,0xF4,0x03,0x00,    // 0x5B '['
+    0x04,0xFE,0x03,0x00,    // 0x5C '\\'
+    0x03,0x08,0x04,0x00,    // 0x5D ']'
+    0x05,0x12,0x04,0x00,    // 0x5E '^'
+    0x06,0x1C,0x04,0x00,    // 0x5F '_'
+    0x02,0x26,0x04,0x00,    // 0x60 '`'
+    0x05,0x30,0x04,0x00,    // 0x61 'a'
+    0x05,0x3A,0x04,0x00,    // 0x62 'b'
+    0x06,0x44,0x04,0x00,    // 0x63 'c'
+    0x06,0x4E,0x04,0x00,    // 0x64 'd'
+    0x06,0x58,0x04,0x00,    // 0x65 'e'
+    0x04,0x62,0x04,0x00,    // 0x66 'f'
+    0x06,0x6C,0x04,0x00,    // 0x67 'g'
+    0x05,0x76,0x04,0x00,    // 0x68 'h'
+    0x02,0x80,0x04,0x00,    // 0x69 'i'
+    0x03,0x8A,0x04,0x00,    // 0x6A 'j'
+    0x05,0x94,0x04,0x00,    // 0x6B 'k'
+    0x02,0x9E,0x04,0x00,    // 0x6C 'l'
+    0x08,0xA8,0x04,0x00,    // 0x6D 'm'
+    0x05,0xB2,0x04,0x00,    // 0x6E 'n'
+    0x06,0xBC,0x04,0x00,    // 0x6F 'o'
+    0x06,0xC6,0x04,0x00,    // 0x70 'p'
+    0x06,0xD0,0x04,0x00,    // 0x71 'q'
+    0x04,0xDA,0x04,0x00,    // 0x72 'r'
+    0x06,0xE4,0x04,0x00,    // 0x73 's'
+    0x04,0xEE,0x04,0x00,    // 0x74 't'
+    0x05,0xF8,0x04,0x00,    // 0x75 'u'
+    0x06,0x02,0x05,0x00,    // 0x76 'v'
+    0x08,0x0C,0x05,0x00,    // 0x77 'w'
+    0x06,0x16,0x05,0x00,    // 0x78 'x'
+    0x06,0x20,0x05,0x00,    // 0x79 'y'
+    0x05,0x2A,0x05,0x00,    // 0x7A 'z'
+    0x04,0x34,0x05,0x00,    // 0x7B '{'
+    0x02,0x3E,0x05,0x00,    // 0x7C '|'
+    0x04,0x48,0x05,0x00,    // 0x7D '}'
+    0x07,0x52,0x05,0x00,    // 0x7E '~'
+    0x04,0x5C,0x05,0x00,    // 0x7F '<non-printable>'
     // Chars Bitstream
     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  // 0x20 ' '
     0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x02,0x00,0x00,  // 0x21 '!'
--- a/Fonts/FontMods.h	Tue Feb 11 21:51:42 2020 +0000
+++ b/Fonts/FontMods.h	Sat Mar 28 15:01:38 2020 +0000
@@ -9,10 +9,11 @@
 #
 # Parse and Modify Mikroe Font File and make a few strategic changes
 #
-# @copyright Copyright &copy; 2012-2020 by Smartware Computing, all rights reserved.
+# Copyright (c) 2019 by Smartware Computing, all rights reserved.
 #
 use strict;
-use warnings; 
+use warnings;
+
 use POSIX;
 
 my @HelpInfo = (
@@ -149,10 +150,12 @@
     for (my $i=0; $i<($BytesWide*$fontHeight); $i++) {
         $charData{$char}{data}[$i] = 0x00;
     }
-    
+   
+
     #
     # * '0' - '9' characters are redefined to set the width equal to width('0')
-    #             or to the user override value.                               
+    #             or to the user override value.                              
+
     #
     if ($DigitWidth > 0) {
         $charWidth = $DigitWidth;   # User override option
@@ -273,7 +276,8 @@
     printf("    %s,              // LastChar\n", HexStream($lastChar,2));
     printf("    %s,                   // FontHeight\n", HexStream($fontHeight,1));
     printf("    0x%02X,                   // Unknown #3\n", $unk_2);
-    
+   
+
     printf("    // Directory of Chars  [Width] [Offset-L] [Offset-M] [Offset-H]\n") if ($Details);
     my $offsetToChar = 8 + 4 * ($lastChar - $firstChar + 1);
     for (my $char = $firstChar; $char <= $lastChar; $char++) {
@@ -296,7 +300,8 @@
         $asc = "\\\\" if ($char == 0x5C);
         my $string = GetSomeHexBytes($char, 0, 8 * $charByteCount);
         printf("    %s%s  // 0x%02X '%s'\n",
-            $string, 
+            $string,
+
             ($char != $lastChar) ? "," : "",
             $char, $asc
         );
@@ -329,13 +334,15 @@
     my ($char) = shift;
     my $h = $fontHeight;
     my $w = $charData{$char}{width};
-    
+   
+
     PrintChar($char,$w,$h,@{$charData{$char}{data}});
 }
 
 sub PrintChar {
     my ($char,$w,$h,@datablock) = @_;
-    
+   
+
     printf("//     +%s+    \n// ", '-' x $w);
     my $row = 0;
     my $boolStream = 0;
@@ -368,7 +375,8 @@
     my ($char, $offSet, $w) = @_;
     my @out;
     my $x = 0;
-    
+   
+
     $w = floor(($w+7)/8);
     while ($w--) {
         my $c = 0;
@@ -382,7 +390,8 @@
     my ($char, $offSet, $w) = @_;
     my $string = "";
     my $x = 0;
-    
+   
+
     $w = floor(($w+7)/8);
     while ($w--) {
         $string .= sprintf("%02X ", $charData{$char}{data}[$offSet + $x++]);
--- a/GraphicsDisplay.cpp	Tue Feb 11 21:51:42 2020 +0000
+++ b/GraphicsDisplay.cpp	Sat Mar 28 15:01:38 2020 +0000
@@ -110,6 +110,69 @@
 //{
 //}
 
+#if 0
+rect_t GraphicsDisplay::GetWindow() {
+    return windowrect;
+}
+
+rect_t GraphicsDisplay::SetWindow(rect_t r)
+{
+    return SetWindow(r.p1.x, r.p1.y, r.p2.x, r.p2.y);
+}
+
+rect_t GraphicsDisplay::SetWindow(loc_t x1, loc_t y1, loc_t x2, loc_t y2)
+{
+    rect_t oldWin = windowrect;
+    dim_t tempWidth, tempHeight;
+    INFO("SetWindow(%d,%d)-(%d,%d)", x1, y1, x2, y2);
+    // Correct the initial values (0,-1) - (0,-1)
+    if (x2 == (loc_t)-1) x2 = width() - 1;
+    if (y2 == (loc_t)-1) y2 = height() - 1;
+    // Sanity check the parameters.
+    if (x1 < 0 || y1 < 0 || x2 < 0 || y2 < 0
+        || x1 >= width() || y1 >= height()
+        || x2 >= width() || y2 >= height()) {
+        rect_t nullRect = { 0,0,0,0 };
+        return nullRect;
+    }
+    switch (screen_orientation) {
+    case rotate_0:
+    case rotate_180:
+        windowrect.p1.x = x1;
+        windowrect.p1.y = y1;
+        windowrect.p2.x = x2;
+        windowrect.p2.y = y2;
+        tempWidth = max(virt_screenwidth, virt_screenheight);
+        tempHeight = min(virt_screenwidth, virt_screenheight);
+        virt_screenwidth = tempWidth;
+        virt_screenheight = tempHeight;
+        //GraphicsDisplay::SetWindow(x1, y1, x2, y2);
+        WriteCommandW(RA8875_HSAW0, x1);
+        WriteCommandW(RA8875_VSAW0, y1);
+        WriteCommandW(RA8875_HEAW0, x2);
+        WriteCommandW(RA8875_VEAW0, y2);
+        break;
+    case rotate_90:
+    case rotate_270:
+        windowrect.p1.x = y1;
+        windowrect.p1.y = x1;
+        windowrect.p2.x = y2;
+        windowrect.p2.y = x2;
+        tempWidth = min(virt_screenwidth, virt_screenheight);
+        tempHeight = max(virt_screenwidth, virt_screenheight);
+        virt_screenwidth = tempWidth;
+        virt_screenheight = tempHeight;
+        //GraphicsDisplay::SetWindow(x1, y1, x2, y2);
+        WriteCommandW(RA8875_HSAW0, y1);
+        WriteCommandW(RA8875_VSAW0, x1);
+        WriteCommandW(RA8875_HEAW0, y2);
+        WriteCommandW(RA8875_VEAW0, x2);
+        break;
+    }
+    return oldWin;
+}
+#endif
+
 RetCode_t GraphicsDisplay::SelectUserFont(const unsigned char * _font)
 {
     font = _font;     // trusting them, but it might be good to put some checks in here...
@@ -121,44 +184,17 @@
     return fontblit(x, y, c);
 }
 
-RetCode_t GraphicsDisplay::window(rect_t r)
-{
-    return window(r.p1.x, r.p1.y, r.p2.x + 1 - r.p1.x, r.p2.y + 1 - r.p1.y);
-}
-
-RetCode_t GraphicsDisplay::window(loc_t x, loc_t y, dim_t _width, dim_t _height)
-{
-    if (_width == (dim_t)-1)
-        _width = width() - x;
-    if (_height == (dim_t)-1)
-        _height = height() - y;
-
-    // Save the window metrics
-    windowrect.p1.x = x;
-    windowrect.p1.y = y;
-    windowrect.p2.x = x + _width - 1;
-    windowrect.p2.y = y + _height - 1;
-    // current pixel location
-    _x = x;
-    _y = y;
-    return noerror;
-}
-
-RetCode_t GraphicsDisplay::WindowMax(void)
-{
-    return window(0,0, width(),height());
-}
-
 RetCode_t GraphicsDisplay::_putp(color_t color)
 {
+    rect_t win = GetWindow();
     pixel(_x, _y, color);
     // update pixel location based on window settings
     _x++;
-    if(_x > windowrect.p2.x) {
-        _x = windowrect.p1.x;
+    if(_x > win.p2.x) {
+        _x = win.p1.x;
         _y++;
-        if(_y > windowrect.p2.y) {
-            _y = windowrect.p1.y;
+        if(_y > win.p2.y) {
+            _y = win.p1.y;
         }
     }
     return noerror;
@@ -171,29 +207,30 @@
 
 RetCode_t GraphicsDisplay::cls(uint16_t layers)
 {
-    int restore = GetDrawingLayer();
+    uint16_t oldLayer = 0;
     if (layers & 1) {
-        SelectDrawingLayer(0);
+        oldLayer = SelectDrawingLayer(0);
         fill(0, 0, width(), height(), _background);
     }
     if (layers & 2) {
-        SelectDrawingLayer(1);
+        oldLayer = SelectDrawingLayer(1);
         fill(0, 0, width(), height(), _background);
     }
-    SelectDrawingLayer(restore);
+    SelectDrawingLayer(oldLayer);
     return noerror;
 }
 
+
 RetCode_t GraphicsDisplay::blit(loc_t x, loc_t y, dim_t w, dim_t h, const int * color)
 {
-    rect_t restore = windowrect;
-    window(x, y, w, h);
+    rect_t restore = SetWindow(x, y, x + w, y + h);
     _StartGraphicsStream();
     for (int i=0; i<w*h; i++) {
         _putp(color[i]);
     }
     _EndGraphicsStream();
-    return window(restore);
+    SetWindow(restore);
+    return noerror;
 }
 
 // 8 byte "info" section
@@ -221,7 +258,7 @@
     dim_t charHeight = font[6];
     const unsigned char * charRecord;   // width, data, data, data, ...
 
-    INFO("first:%d, last:%d, c:%d", firstChar, lastChar, c);
+    INFO("first:%d, last:%d, c:%02X '%c'", firstChar, lastChar, c, (c >= ' ' && c <= '~') ? c : '-');
     if (c < firstChar || c > lastChar)
         return NULL;       // advance zero pixels since it was unprintable...
 
@@ -244,7 +281,7 @@
     dim_t charWidth, charHeight;        // metrics for the raw char in the font table
     charRecord = getCharMetrics(c, &charWidth, &charHeight);
     if (charRecord) {
-        INFO("hgt:%d, wdt:%d", charHeight, charWidth);
+        INFO("wdt:%d, hgt:%d", charWidth, charHeight);
         booleanStream(x,y,charWidth, charHeight, charRecord);
         return charWidth * fontScaleX;
     } else {
@@ -268,7 +305,8 @@
     return c;
 }
 
-// RGB16 little endian 
+// RGB16 little endian
+
 //      GGGB BBBB RRRR RGGG
 // swap
 //      RRRR RGGG GGGB BBBB
@@ -305,9 +343,9 @@
 
     // Now, Read the bitmap info header
     fread(&BMP_Info, 1, sizeof(BMP_Info), Image);
-    HexDump("BMP_Info", (uint8_t *)&BMP_Info, sizeof(BMP_Info));
+    //HexDump("BMP_Info", (uint8_t *)&BMP_Info, sizeof(BMP_Info));
     BPP_t = BMP_Info.biBitCount;
-    INFO("biBitCount %04X", BPP_t);
+    //INFO("biBitCount %04X", BPP_t);
     if (BPP_t != 1 && BPP_t != 4 && BPP_t != 8 && BPP_t != 16 && BPP_t != 24) { // Support 4, 8, 16, 24-bits per pixel
         fclose(Image);
         return(not_supported_format);
@@ -318,12 +356,12 @@
     }
     PixelHeight = BMP_Info.biHeight;
     PixelWidth = BMP_Info.biWidth;
-    INFO("(%d,%d) (%d,%d) (%d,%d)", x,y, PixelWidth,PixelHeight, width(), height());
+    //INFO("(%d x,%d h) (%d w,%d h) (%d w,%d h)", x,y, PixelWidth,PixelHeight, width(), height());
     if (infoOnly) {
         infoOnly->p1.x = x;
         infoOnly->p1.y = y;
-        infoOnly->p2.x = x+PixelWidth;
-        infoOnly->p2.y = y+PixelHeight;
+        infoOnly->p2.x = x+PixelWidth-1;
+        infoOnly->p2.y = y+PixelHeight-1;
         return (noerror);
     }
 
@@ -344,11 +382,11 @@
             return(not_enough_ram);
         }
         fread(colorPalette, 1, paletteSize, Image);
-        HexDump("Color Palette", (uint8_t *)colorPalette, paletteSize);
+        //HexDump("Color Palette", (uint8_t *)colorPalette, paletteSize);
     }
 
     int lineBufSize = ((BPP_t * PixelWidth + 7)/8);
-    INFO("BPP_t %d, PixelWidth %d, lineBufSize %d", BPP_t, PixelWidth, lineBufSize);
+    //INFO("BPP_t %d, PixelWidth %d, lineBufSize %d", BPP_t, PixelWidth, lineBufSize);
     lineBuffer = (uint8_t *)swMalloc(lineBufSize);
     if (lineBuffer == NULL) {
         swFree(colorPalette);
@@ -369,14 +407,13 @@
         padd = 4 - padd;
 
     // Define window for top to bottom and left to right so writing auto-wraps
-    rect_t restore = windowrect;
-    window(x,y, PixelWidth,PixelHeight);
+    rect_t restore = SetWindow(x,y, x+PixelWidth-1,y+PixelHeight-1);
 //    SetGraphicsCursor(x, y);
 //    _StartGraphicsStream();
 
     //start_data = BMP_Info.bfOffBits;
     //HexDump("Raw Data", (uint8_t *)&start_data, 32);
-    INFO("(%d,%d) (%d,%d), [%d,%d]", x,y, PixelWidth,PixelHeight, lineBufSize, padd);
+    //INFO("(%d,%d) (%d,%d), [%d,%d]", x,y, PixelWidth,PixelHeight, lineBufSize, padd);
     for (j = PixelHeight - 1; j >= 0; j--) {                //Lines bottom up
         offset = fileOffset + j * (lineBufSize + padd);     // start of line
         fseek(Image, offset, SEEK_SET);
@@ -408,7 +445,7 @@
         pixelStream(pixelBuffer, PixelWidth, x, y++);
     }
 //    _EndGraphicsStream();
-    window(restore);
+    SetWindow(restore);
     swFree(pixelBuffer);      // don't leak memory
     swFree(lineBuffer);
     if (colorPalette)
@@ -416,31 +453,43 @@
     return (noerror);
 }
 
-rect_t GraphicsDisplay::GetImageRect(loc_t x, loc_t y, const char *Filename)
+rect_t GraphicsDisplay::GetImageRect(loc_t x, loc_t y, const char* Filename)
 {
-    rect_t r = { 0, 0, 0, 0};
+    rect_t r = { 0, 0, 0, 0 };
+
+    RenderImageFile(x, y, Filename, &r);
+    return r;
+}
 
-    RenderImageFile(x,y,Filename, &r);
+rect_t GraphicsDisplay::GetImageRect(point_t pt, const char* Filename)
+{
+    rect_t r = { 0, 0, 0, 0 };
+
+    RenderImageFile(pt, Filename, &r);
     return r;
 }
 
+RetCode_t GraphicsDisplay::RenderImageFile(point_t pt, const char* FileName, rect_t* getDim) {
+    return RenderImageFile(pt.x, pt.y, FileName, getDim);
+}
+
 RetCode_t GraphicsDisplay::RenderImageFile(loc_t x, loc_t y, const char * FileName, rect_t * getDim) {
     if (mystrnicmp(FileName + strlen(FileName) - 4, ".bmp", 4) == 0) {
         return RenderBitmapFile(x, y, FileName, getDim);
     } else if (mystrnicmp(FileName + strlen(FileName) - 4, ".jpg", 4) == 0) {
         if (getDim)
-            return not_supported_format;
+            return bad_parameter;
         return RenderJpegFile(x, y, FileName);
     } else if (mystrnicmp(FileName + strlen(FileName) - 4, ".ico", 4) == 0) {
         if (getDim)
-            return not_supported_format;
+            return bad_parameter;
         return RenderIconFile(x, y, FileName);
     } else if (mystrnicmp(FileName + strlen(FileName) - 4, ".gif", 4) == 0) {
         if (getDim)
-            return not_supported_format;
+            return bad_parameter;
         return RenderGIFFile(x, y, FileName);
     } else {
-        return not_supported_format;
+        return bad_parameter;
     }
 }
 
@@ -456,12 +505,12 @@
 
     fread(&BMP_Header, 1, sizeof(BMP_Header), Image);      // get the BMP Header
     INFO("bfType %04X, Header size: %d", BMP_Header.bfType, sizeof(BITMAPFILEHEADER));
-    HexDump("BMP_Header", (uint8_t *)&BMP_Header, sizeof(BMP_Header));
+    //HexDump("BMP_Header", (uint8_t *)&BMP_Header, sizeof(BMP_Header));
     if (BMP_Header.bfType != BF_TYPE) {
         fclose(Image);
         return(not_bmp_format);
     }
-    INFO("bfOffits %04X", BMP_Header.bfOffBits);
+    //INFO("bfOffits %04lX", BMP_Header.bfOffBits);
     RetCode_t rt = _RenderBitmap(x, y, BMP_Header.bfOffBits, Image, getDim);
     if (rt != noerror) {
         return rt;
--- a/GraphicsDisplay.h	Tue Feb 11 21:51:42 2020 +0000
+++ b/GraphicsDisplay.h	Sat Mar 28 15:01:38 2020 +0000
@@ -27,6 +27,7 @@
 #include "TextDisplay.h"
 #include "GraphicsDisplayJPEG.h"
 #include "GraphicsDisplayGIF.h"
+#include "DisplayDefs.h"
 
 /// The GraphicsDisplay class
 ///
@@ -140,6 +141,69 @@
     ///
     virtual RetCode_t SetGraphicsCursorRead(loc_t x, loc_t y) = 0;
 
+
+    /// Set the window, constraining where items are written to the screen.
+    ///
+    /// After setting the window, text and graphics are constrained to this
+    /// window. Text will wrap from the right edge back to the left and down
+    /// one row and from the bottom to the top. Graphics drawing will be clipped
+    /// at the edge of the window.
+    ///
+    /// @note If the initial text write is outside the window, it will be shown
+    /// where the cursor position it. Once the write hits the right edge of
+    /// the defined window, it will then wrap back to the left edge. Once it
+    /// hits the bottom, it wraps to the top of the window. For this reason,
+    /// it is common to set the text cursor to the window.
+    ///
+    /// @code
+    ///     rect_t r = {10,10, 90,90};
+    ///     r = lcd.SetWindow(r);
+    ///     lcd.SetTextCursor(r.p1.x, r.p1.y);
+    ///     lcd.puts("012345678901234567890123456789012345678901234567890");
+    ///     lcd.SetWindow(r); restore to previous window setting
+    /// @endcode
+    ///
+    /// @param[in] r is the rect_t used to set the window.
+    /// @returns the previous window definition.
+    ///
+    virtual rect_t SetWindow(rect_t r) = 0;
+
+    /// Set the window, constraining where items are written to the screen.
+    ///
+    /// After setting the window, text and graphics are constrained to this
+    /// window. Text will wrap from the right edge back to the left and down
+    /// one row and from the bottom to the top. Graphics drawing will be clipped
+    /// at the edge of the window.
+    ///
+    /// @note if no parameters are provided, it restores the window to full screen.
+    ///
+    /// @note If the initial text write is outside the window, it will be shown
+    /// where the cursor positions it. Once the write hits the right edge of
+    /// the defined window, it will then wrap back to the left edge. Once it
+    /// hits the bottom, it wraps to the top of the window. For this reason,
+    /// it is common to set the text cursor to the window.
+    ///
+    /// @code
+    ///     lcd.SetWindow(10,10, 80,80);
+    ///     lcd.SetTextCursor(10,10);
+    ///     lcd.puts("012345678901234567890123456789012345678901234567890");
+    ///     lcd.SetWindow(); restore to full screen
+    /// @endcode
+    ///
+    /// @param[in] x1 is the left edge in pixels.
+    /// @param[in] y1 is the top edge in pixels.
+    /// @param[in] x2 is the right edge in pixels.
+    /// @param[in] y2 is the bottom edge in pixels.
+    /// @returns the previous window definition.
+    ///
+    virtual rect_t SetWindow(loc_t x1 = 0, loc_t y1 = 0, loc_t x2 = (loc_t)-1, loc_t y2 = (loc_t)-1) = 0;
+
+    /// Get the current window setting, which constrains what is written to the screen.
+    ///
+    /// @returns the current window definition.
+    ///
+    virtual rect_t GetWindow() = 0;
+
     /// Draw a filled rectangle in the specified color
     ///
     /// @note As a side effect, this changes the current
@@ -181,12 +245,9 @@
     ///
     /// @param[in] layer is 0 or 1 to select the layer for subsequent
     ///     commands.
-    /// @param[out] prevLayer is an optional pointer to where the previous layer
-    ///     will be written, making it a little easer to restore layers.
-    ///     Writes 0 or 1 when the pointer is not NULL.
-    /// @returns @ref RetCode_t value.
+    /// @returns The previous drawing layer.
     ///
-    virtual RetCode_t SelectDrawingLayer(uint16_t layer, uint16_t * prevLayer = NULL) = 0;
+    virtual uint16_t SelectDrawingLayer(uint16_t layer) = 0;
 
 
     /// Get the currently active drawing layer.
@@ -196,7 +257,7 @@
     ///
     /// @code
     ///     uint16_t prevLayer;
-    ///     lcd.SelectDrawingLayer(x, &prevLayer);
+    ///     prevLayer = lcd.SelectDrawingLayer(x);
     ///     lcd.circle(400,25, 25, BrightRed);
     ///     lcd.SelectDrawingLayer(prevLayer);
     /// @endcode
@@ -204,7 +265,7 @@
     /// @attention The user manual refers to Layer 1 and Layer 2, however the
     ///     actual register values are value 0 and 1. This API as well as
     ///     others that reference the layers use the values 0 and 1 for
-    ///     cleaner iteration in the code.
+    ///     cleaner integration in the code.
     ///
     /// @returns the current drawing layer; 0 or 1.
     ///
@@ -229,48 +290,6 @@
     ///
     virtual RetCode_t WriteData(unsigned char data) = 0;
 
-    /// Set the window, which controls where items are written to the screen.
-    ///
-    /// When something hits the window width, it wraps back to the left side
-    /// and down a row.
-    ///
-    /// @note If the initial write is outside the window, it will
-    ///     be captured into the window when it crosses a boundary. It may
-    ///     be appropriate to SetGraphicsCursor() to a point in the window.
-    ///
-    /// @param[in] r is the rect_t rect to define the window.
-    /// @returns success/failure code. @see RetCode_t.
-    ///
-    virtual RetCode_t window(rect_t r);
-
-    /// Set the window, which controls where items are written to the screen.
-    ///
-    /// When something hits the window width, it wraps back to the left side
-    /// and down a row.
-    ///
-    /// @note If the initial write is outside the window, it will
-    ///     be captured into the window when it crosses a boundary. It may
-    ///     be appropriate to SetGraphicsCursor() to a point in the window.
-    ///
-    /// @note if no parameters are provided, it restores the window to full screen.
-    ///
-    /// @param[in] x is the left edge in pixels.
-    /// @param[in] y is the top edge in pixels.
-    /// @param[in] w is the window width in pixels.
-    /// @param[in] h is the window height in pixels.
-    /// @returns success/failure code. @see RetCode_t.
-    ///
-    virtual RetCode_t window(loc_t x = 0, loc_t y = 0, dim_t w = (dim_t)-1, dim_t h = (dim_t)-1);
-
-    /// method to set the window region to the full screen.
-    ///
-    /// This restores the 'window' to the full screen, so that
-    /// other operations (@see cls) would clear the whole screen.
-    ///
-    /// @returns success/failure code. @see RetCode_t.
-    ///
-    virtual RetCode_t WindowMax(void);
-
     /// Clear the screen.
     ///
     /// The behavior is to clear the whole screen.
@@ -416,7 +435,7 @@
     ///     specified file cannot be found, or where this method is not yet
     ///     supported, all elements of the returned rect_r will be zero.
     ///
-    rect_t GetImageRect(point_t pt, const char* Filename);
+    rect_t GetImageRect(point_t pt, const char* FileName);
 
 
     /// This method attempts to render a specified graphics image file at
@@ -465,10 +484,11 @@
     /// @param[in] y is the vertical pixel coordinate of the top-left corner.
     /// @param[in] FileName refers to the fully qualified path and file on
     ///     a mounted file system.
-    /// @param[in] getDim when not NULL the image is not drawn. Instead, the
+    /// @param[in] getDim when not NULL caused the image to not be drawn. Instead,
     ///             getDim is filled in as the rectangle that would be drawn
     ///             relative to the provided x,y origin. This basically
-    ///             provides a GetImageRect on a specified file.
+    ///             provides a GetImageRect on a specified file. @see GetImageRect
+    ///             is the recommended and more obvious API.
     /// @returns success or error code.
     ///
     RetCode_t RenderImageFile(loc_t x, loc_t y, const char * FileName, rect_t * getDim = NULL);
--- a/GraphicsDisplayGIF.cpp	Tue Feb 11 21:51:42 2020 +0000
+++ b/GraphicsDisplayGIF.cpp	Sat Mar 28 15:01:38 2020 +0000
@@ -486,15 +486,14 @@
                             INFO("");
                         }
                         #else
-                        rect_t restore = windowrect;
-                        window(ScreenX + gif_image_descriptor.image_left_position,
+                        rect_t restore = SetWindow(ScreenX + gif_image_descriptor.image_left_position,
                             ScreenY + gif_image_descriptor.image_top_position,
-                            gif_image_descriptor.image_width,
-                            gif_image_descriptor.image_height);
+                            ScreenX + gif_image_descriptor.image_left_position + gif_image_descriptor.image_width,
+                            ScreenY + gif_image_descriptor.image_top_position + gif_image_descriptor.image_height);
                         pixelStream(cbmp, screen_descriptor.width * screen_descriptor.height,
                             ScreenX + gif_image_descriptor.image_left_position,
                             ScreenY + gif_image_descriptor.image_top_position);
-                        window(restore);
+                        SetWindow(restore);
                         #endif
                         // end write
                         free(cbmp);
--- a/GraphicsDisplayJPEG.cpp	Tue Feb 11 21:51:42 2020 +0000
+++ b/GraphicsDisplayJPEG.cpp	Sat Mar 28 15:01:38 2020 +0000
@@ -854,10 +854,10 @@
     } while (--pCount);
     #endif
     //
-    window(x0+img_x, y0+img_y, w, y1 - y0 + 2);
+    rect_t oldWin = SetWindow(x0+img_x, y0+img_y, x0 + img_x + w, y0 + img_y + y1 - y0 + 2);
     uint16_t *src = (uint16_t *)bitmap;     // pointer to RGB565 format
     pixelStream(src, pixelCount, x0+img_x, y0+img_y);
-    window();
+    SetWindow(oldWin);
 #else
     for (int y= y0; y <= y1; y++) {
         SetGraphicsCursor(x0+img_x, y+img_y);
--- a/RA8875.cpp	Tue Feb 11 21:51:42 2020 +0000
+++ b/RA8875.cpp	Sat Mar 28 15:01:38 2020 +0000
@@ -297,7 +297,7 @@
     touchState = no_touch;
     numberOfTouchPoints = 0;
     gesture = 0;
-    panelTouched = 0;
+    panelTouched = false;
     touchSample = 0;
     memset(&tpMatrix, 0, sizeof(tpMatrix_t));
     pKeyMap = NULL;
@@ -305,10 +305,9 @@
     spiwritefreq = 1000000;
     spireadfreq = 1000000;
     screenbpp = 16;
-    screenwidth = 0;
-    screenheight = 0;
+    virt_screenwidth = 0;
+    virt_screenheight = 0;
     memset(&windowrect, 0, sizeof(rect_t));
-    portraitmode = false;
     font = NULL;
     extFontHeight = 0;
     extFontWidth = 0;
@@ -331,10 +330,11 @@
     frequency(RA8875_DEFAULT_SPI_FREQ);         // data rate
     Reset();
     // Set PLL based on display size from buy-display.com sample code
+    // RAIO Reference display values noted: 800w: 0x0B, 480w: 0x0A
     if (width == 800) {
-        WriteCommand(RA8875_PLLC1, 0x0C);               // PLLC1 - Phase Lock Loop registers
+        WriteCommand(RA8875_PLLC1, 0x0C);               // PLLC1 - Phase Lock Loop registers [RAIO 0B]
     } else {
-        WriteCommand(RA8875_PLLC1, 0x0B);               // PLLC1 - Phase Lock Loop registers
+        WriteCommand(RA8875_PLLC1, 0x0B);               // PLLC1 - Phase Lock Loop registers [RAIO 0A]
     }
     wait_us(1000);
     WriteCommand(RA8875_PLLC2, 0x02);
@@ -354,28 +354,28 @@
         wait_us(1000);
 
         // Horizontal Settings
-        screenwidth = width;
+        virt_screenwidth = width;
         WriteCommand(RA8875_HDWR, width/8 - 1);            //HDWR//Horizontal Display Width Setting Bit[6:0]
-        WriteCommand(RA8875_HNDFTR, 0x00);                   //HNDFCR//Horizontal Non-Display Period fine tune Bit[3:0]
-        WriteCommand(RA8875_HNDR, 0x03);                   //HNDR//Horizontal Non-Display Period Bit[4:0]
-        WriteCommand(RA8875_HSTR, 0x03);                   //HSTR//HSYNC Start Position[4:0]
-        WriteCommand(RA8875_HPWR, 0x0B);                   //HPWR//HSYNC Polarity ,The period width of HSYNC.
+        WriteCommand(RA8875_HNDFTR, 0x00);                 //HNDFCR//Horizontal Non-Display Period fine tune Bit[3:0]
+        WriteCommand(RA8875_HNDR, 0x03);                   //HNDR//Horizontal Non-Display Period Bit[4:0] [RAIO 0x01]
+        WriteCommand(RA8875_HSTR, 0x03);                   //HSTR//HSYNC Start Position[4:0] [RAIO 0x00]
+        WriteCommand(RA8875_HPWR, 0x0B);                   //HPWR//HSYNC Polarity ,The period width of HSYNC. [RAIO 0x05]
 
         // Vertical Settings
-        screenheight = height;
+        virt_screenheight = height;
         WriteCommand(RA8875_VDHR0, (height-1)&0xFF);        //VDHR0 //Vertical Display Height Bit [7:0]
         WriteCommand(RA8875_VDHR1, (height-1)>>8);          //VDHR1 //Vertical Display Height Bit [8]
-        WriteCommand(RA8875_VNDR0, 0x20);                   //VNDR0 //Vertical Non-Display Period Bit [7:0]
+        WriteCommand(RA8875_VNDR0, 0x20);                   //VNDR0 //Vertical Non-Display Period Bit [7:0] [RAIO 0x02]
         WriteCommand(RA8875_VNDR1, 0x00);                   //VNDR1 //Vertical Non-Display Period Bit [8]
-        WriteCommand(RA8875_VSTR0, 0x16);                   //VSTR0 //VSYNC Start Position[7:0]
+        WriteCommand(RA8875_VSTR0, 0x16);                   //VSTR0 //VSYNC Start Position[7:0] [RAIO 0x07]
         WriteCommand(RA8875_VSTR1, 0x00);                   //VSTR1 //VSYNC Start Position[8]
-        WriteCommand(RA8875_VPWR, 0x01);                   //VPWR  //VSYNC Polarity ,VSYNC Pulse Width[6:0]
+        WriteCommand(RA8875_VPWR, 0x01);                   //VPWR  //VSYNC Polarity ,VSYNC Pulse Width[6:0] [RAIO 0x09]
     } else {
         WriteCommand(RA8875_PCSR, 0x82);               // PDAT on PCLK falling edge, PCLK = 4 x System Clock
         wait_us(1000);
 
         // Horizontal Settings
-        screenwidth = width;
+        virt_screenwidth = width;
         WriteCommand(RA8875_HDWR, width/8 - 1);            //HDWR//Horizontal Display Width Setting Bit[6:0]
         WriteCommand(RA8875_HNDFTR, 0x02);                   //HNDFCR//Horizontal Non-Display Period fine tune Bit[3:0]
         WriteCommand(RA8875_HNDR, 0x03);                   //HNDR//Horizontal Non-Display Period Bit[4:0]
@@ -383,7 +383,7 @@
         WriteCommand(RA8875_HPWR, 0x03);                   //HPWR//HSYNC Polarity ,The period width of HSYNC.
 
         // Vertical Settings
-        screenheight = height;
+        virt_screenheight = height;
         WriteCommand(RA8875_VDHR0, (height-1)&0xFF);        //VDHR0 //Vertical Display Height Bit [7:0]
         WriteCommand(RA8875_VDHR1, (height-1)>>8);          //VDHR1 //Vertical Display Height Bit [8]
         WriteCommand(RA8875_VNDR0, 0x0F);                   //VNDR0 //Vertical Non-Display Period Bit [7:0]
@@ -393,8 +393,6 @@
         WriteCommand(RA8875_VPWR, 0x01);                   //VPWR  //VSYNC Polarity ,VSYNC Pulse Width[6:0]
     }
 
-    portraitmode = false;
-
     if (width >= 800 && height >= 480 && color_bpp > 8) {
         WriteCommand(RA8875_DPCR, 0x00);               // DPCR - 1-layer mode when the resolution is too high
     } else {
@@ -402,7 +400,7 @@
     }
 
     // Set display image to Blue on Black as default
-    window(0,0, width, height);             // Initialize to full screen
+    SetWindow(0,0, width-1, height-1);             // Initialize to full screen
     SetTextCursorControl();
     foreground(Blue);
     background(Black);
@@ -431,7 +429,7 @@
 {
     RetCode_t ret;
 
-    #if 0
+    #if 1
     if (res != (PinName)NC) {
         res = 0;                            // Active low - assert reset
         wait_us(2000);                         // must be > 1024 clock periods. (@25 MHz, this is 40.96 usec)
@@ -462,20 +460,19 @@
 }
 
 
-RetCode_t RA8875::SelectDrawingLayer(uint16_t layer, uint16_t * prevLayer)
+uint16_t RA8875::SelectDrawingLayer(uint16_t layer)
 {
+    uint16_t prevLayer;
     unsigned char mwcr1 = ReadCommand(0x41); // retain all but the currently selected layer
-
-    if (prevLayer)
-        *prevLayer = mwcr1 & 1;
-
+    prevLayer = (mwcr1 & 1);
     mwcr1 &= ~0x01; // remove the current layer
-    if (screenwidth >= 800 && screenheight >= 480 && screenbpp > 8) {
+    if (virt_screenwidth >= 800 && virt_screenheight >= 480 && screenbpp > 8) {
         layer = 0;
     } else if (layer > 1) {
         layer = 0;
     }
-    return WriteCommand(RA8875_MWCR1, mwcr1 | layer);
+    WriteCommand(RA8875_MWCR1, mwcr1 | layer);
+    return prevLayer;
 }
 
 
@@ -485,16 +482,14 @@
 }
 
 
-RetCode_t RA8875::SetLayerMode(LayerMode_T mode)
+RA8875::LayerMode_T RA8875::SetLayerMode(LayerMode_T mode)
 {
-    unsigned char ltpr0 = ReadCommand(0x52) & ~0x7; // retain all but the display layer mode
-
+    unsigned char ltpr0 = ReadCommand(0x52); // retain all but the display layer mode
+    LayerMode_T oldLayer = (LayerMode_T)(ltpr0 & 0x07);
     if (mode <= (LayerMode_T)6) {
-        WriteCommand(RA8875_LTPR0, ltpr0 | (mode & 0x7));
-        return noerror;
-    } else {
-        return bad_parameter;
+        WriteCommand(RA8875_LTPR0, (ltpr0 & ~0x07) | (mode & 0x07));
     }
+    return oldLayer;
 }
 
 
@@ -509,9 +504,11 @@
 }
 
 
-RetCode_t RA8875::SetBackgroundTransparencyColor(color_t color)
+color_t RA8875::SetBackgroundTransparencyColor(color_t color)
 {
-    return _writeColorTrio(0x67, color);
+    color_t oldColor = _readColorTrio(0x67);
+    _writeColorTrio(0x67, color);
+    return oldColor;
 }
 
 
@@ -690,36 +687,41 @@
 
 rect_t RA8875::AlignRectInRect(rect_t toAlign, rect_t inRect, valign_t v, halign_t h) {
     rect_t newRect; dim_t width; dim_t height;
-    width = toAlign.p2.x - toAlign.p1.x;
-    height = toAlign.p2.y - toAlign.p1.y;
+    width = toAlign.p2.x - toAlign.p1.x + 1;
+    height = toAlign.p2.y - toAlign.p1.y + 1;
+    INFO("Align(%d,%d)-(%d,%d) in (%d,%d)-(%d,%d) v:%d, h:%d",
+        toAlign.p1.x,toAlign.p1.y,toAlign.p2.x,toAlign.p2.y,
+        inRect.p1.x,inRect.p1.y,inRect.p2.x,inRect.p2.y,
+        v,h
+        );
     switch (h) {
         case left:
         default:
             newRect.p1.x = inRect.p1.x;
-            newRect.p2.x = newRect.p1.x + width;
+            newRect.p2.x = newRect.p1.x + width - 1;
             break;
         case center:
             newRect.p1.x = (inRect.p1.x + inRect.p2.x + 1) / 2 - width / 2;
-            newRect.p2.x = newRect.p1.x + width;
+            newRect.p2.x = newRect.p1.x + width - 1;
             break;
         case right:
-            newRect.p1.x = inRect.p2.x - width;
-            newRect.p2.x = newRect.p1.x + width;
+            newRect.p1.x = inRect.p2.x - width - 1;
+            newRect.p2.x = newRect.p1.x + width - 1;
             break;
     }
     switch (v) {
         case top:
         default:
             newRect.p1.y = inRect.p1.y;
-            newRect.p2.y = newRect.p1.y + height;
+            newRect.p2.y = newRect.p1.y + height - 1;
             break;
         case middle:
             newRect.p1.y = (inRect.p1.y + inRect.p2.y + 1) / 2 - height / 2;
-            newRect.p2.y = newRect.p1.y + height;
+            newRect.p2.y = newRect.p1.y + height - 1;
             break;
         case bottom:
-            newRect.p1.y = inRect.p2.y - height;
-            newRect.p2.y = newRect.p1.y + height;
+            newRect.p1.y = inRect.p2.y - height - 1;
+            newRect.p2.y = newRect.p1.y + height - 1;
             break;
     }
     return newRect;
@@ -1001,7 +1003,7 @@
 dim_t RA8875::fontwidth(void)
 {
     if (font == NULL)
-        return (((ReadCommand(0x22) >> 2) & 0x3) + 1) * 8;
+        return (((ReadCommand(RA8875_FNCR1) >> 2) & 0x3) + 1) * 8;
     else
         return extFontWidth;
 }
@@ -1010,13 +1012,13 @@
 dim_t RA8875::fontheight(void)
 {
     if (font == NULL)
-        return (((ReadCommand(0x22) >> 0) & 0x3) + 1) * 16;
+        return (((ReadCommand(RA8875_FNCR1) >> 0) & 0x3) + 1) * 16;
     else
         return extFontHeight;
 }
 
 
-RetCode_t RA8875::locate(textloc_t column, textloc_t row)
+point_t RA8875::locate(textloc_t column, textloc_t row)
 {
     return SetTextCursor(column * fontwidth(), row * fontheight());
 }
@@ -1024,31 +1026,25 @@
 
 int RA8875::columns(void)
 {
-    return screenwidth / fontwidth();
+    return virt_screenwidth / fontwidth();
 }
 
 
 int RA8875::rows(void)
 {
-    return screenheight / fontheight();
+    return virt_screenheight / fontheight();
 }
 
 
 dim_t RA8875::width(void)
 {
-    if (portraitmode)
-        return screenheight;
-    else
-        return screenwidth;
+    return virt_screenwidth;
 }
 
 
 dim_t RA8875::height(void)
 {
-    if (portraitmode)
-        return screenwidth;
-    else
-        return screenheight;
+    return virt_screenheight;
 }
 
 
@@ -1063,53 +1059,76 @@
     return prevWrap;
 }
 
-RetCode_t RA8875::SetTextCursor(point_t p)
+point_t RA8875::SetTextCursor(point_t p)
 {
     return SetTextCursor(p.x, p.y);
 }
 
-RetCode_t RA8875::SetTextCursor(loc_t x, loc_t y)
+point_t RA8875::SetTextCursor(loc_t x, loc_t y)
 {
-    INFO("SetTextCursor(%d, %d)", x, y);
+    point_t oldCursor = GetTextCursor();
     cursor_x = x;     // set these values for non-internal fonts
     cursor_y = y;
-    WriteCommandW(RA8875_FCURXL, x);
-    WriteCommandW(RA8875_FCURYL, y);
-    return noerror;
+    switch (screen_orientation) {
+    default:
+    case rotate_0:
+    case rotate_180:
+        WriteCommandW(RA8875_FCURXL, x);
+        WriteCommandW(RA8875_FCURYL, y);
+        break;
+    case rotate_90:
+    case rotate_270:
+        WriteCommandW(RA8875_FCURXL, y);
+        WriteCommandW(RA8875_FCURYL, x);
+        break;
+    }
+    return oldCursor;
 }
 
 point_t RA8875::GetTextCursor(void)
 {
-    point_t p;
-
-    p.x = GetTextCursor_X();
-    p.y = GetTextCursor_Y();
+    point_t p, tempPt;
+
+    if (font == NULL) {
+        p.x = ReadCommand(RA8875_FCURXL) | (ReadCommand(RA8875_FCURXH) << 8);
+        p.y = ReadCommand(RA8875_FCURYL) | (ReadCommand(RA8875_FCURYH) << 8);
+        switch (screen_orientation) {
+        case rotate_0:
+        case rotate_180:
+            // Nothing
+            break;
+        case rotate_90:
+        case rotate_270:
+            tempPt.x = p.y;
+            tempPt.y = p.x;
+            p = tempPt;
+            break;
+        default:
+            p.x = 0;
+            p.y = 0;
+            break;
+        }
+    } else {
+        p.x = cursor_x;
+        p.y = cursor_y;
+    }
+    //INFO("GetCursor hw: (%d,%d)", p.x, p.y);
     return p;
 }
 
 loc_t RA8875::GetTextCursor_Y(void)
 {
-    loc_t y;
-
-    if (font == NULL)
-        y = ReadCommand(0x2C) | (ReadCommand(0x2D) << 8);
-    else
-        y = cursor_y;
-    INFO("GetTextCursor_Y = %d", y);
-    return y;
+    point_t p = GetTextCursor();
+    INFO("GetTextCursor_Y = %d", p.y);
+    return p.y;
 }
 
 
 loc_t RA8875::GetTextCursor_X(void)
 {
-    loc_t x;
-
-    if (font == NULL)
-        x = ReadCommand(0x2A) | (ReadCommand(0x2B) << 8);
-    else
-        x = cursor_x;
-    INFO("GetTextCursor_X = %d", x);
-    return x;
+    point_t p = GetTextCursor();
+    INFO("GetTextCursor_X = %d", p.x);
+    return p.x;
 }
 
 
@@ -1161,72 +1180,87 @@
     }
 }
 
-RA8875::orientation_t RA8875::GetOrientation()
+orientation_t RA8875::GetGraphicsOrientation()
 {
-    #if 1
     return screen_orientation;
-    #else
-    uint8_t dpcrVal = ReadCommand(RA8875_DPCR);
-
-    dpcrVal &= 0x0C;       // keep the scan direction bits
-    switch (dpcrVal) {
-        default:
-        case 0x00:
-            return rotate_0;
-        case 0x08:
-            return rotate_90;
-        case 0x0C:
-            return rotate_180;
-        case 0x04:
-            return rotate_270;
-    }
-    #endif
 }
 
-RetCode_t RA8875::SetOrientation(RA8875::orientation_t angle)
+orientation_t RA8875::SetGraphicsOrientation(orientation_t angle)
 {
-    uint8_t fncr1Val = ReadCommand(RA8875_FNCR1);
     uint8_t dpcrVal = ReadCommand(RA8875_DPCR);
     uint8_t mwcr0 = ReadCommand(RA8875_MWCR0);
-    
-    fncr1Val &= ~0x10;      // remove the old direction bit
+    uint8_t mrcd = ReadCommand(RA8875_MRCD);
+    dim_t tempWidth, tempHeight;
+    orientation_t oldAngle = screen_orientation;
+
     dpcrVal &= ~0x0C;       // remove the old scan direction bits
     mwcr0 &= 0xE3;          // remove the old direction bits
+    mrcd &= 0xFC;           // remove the old direction bits
     switch (angle) {
-        case RA8875::normal:
-            //fncr1Val |= 0x10;
+        case normal:
             //dpcrVal |= 0x00;
-            portraitmode = false;
+            tempWidth = max(virt_screenwidth, virt_screenheight);
+            tempHeight = min(virt_screenwidth, virt_screenheight);
             break;
-        case RA8875::rotate_90:
-            fncr1Val |= 0x10;
+        case rotate_90:
             dpcrVal |= 0x08;
-            mwcr0 |= 0x00;
-            portraitmode = true;
+            mwcr0 |= 0x08;
+            mrcd |= 0x02;
+            tempWidth = min(virt_screenwidth, virt_screenheight);
+            tempHeight = max(virt_screenwidth, virt_screenheight);
             break;
-        case RA8875::rotate_180:
-            //fncr1Val |= 0x00;
+        case rotate_180:
             dpcrVal |= 0x0C;
             //mwcr0 |= 0x00;
-            portraitmode = false;
+            //mrcd |= 0x00;
+            tempWidth = max(virt_screenwidth, virt_screenheight);
+            tempHeight = min(virt_screenwidth, virt_screenheight);
             break;
-        case RA8875::rotate_270:
-            fncr1Val |= 0x10;
+        case rotate_270:
             dpcrVal |= 0x04;
-            mwcr0 |= 0x00;
-            portraitmode = true;
+            mwcr0 |= 0x08;
+            mrcd |= 0x02;
+            tempWidth = min(virt_screenwidth, virt_screenheight);
+            tempHeight = max(virt_screenwidth, virt_screenheight);
             break;
         default:
-            return bad_parameter;
+            return invalid;
     }
     screen_orientation = angle;
-    INFO("Orientation: %d, %s", angle * 90, portraitmode ? "portrait" : "landscape");
+    virt_screenwidth = tempWidth;
+    virt_screenheight = tempHeight;
+    WriteCommand(RA8875_MRCD, mrcd);
     WriteCommand(RA8875_MWCR0, mwcr0);
+    WriteCommand(RA8875_DPCR, dpcrVal);
+    return oldAngle;
+}
+
+orientation_t RA8875::SetTextFontOrientation(orientation_t angle)
+{
+    uint8_t fncr1Val = ReadCommand(RA8875_FNCR1);
+    orientation_t oldAngle = text_orientation;
+
+    fncr1Val &= ~0x10;      // remove the old direction bit
+    switch (angle) {
+    case normal:
+        //fncr1Val |= 0x10;
+        break;
+    case rotate_90:
+        fncr1Val |= 0x10;
+        break;
+    case rotate_180:
+        //fncr1Val |= 0x00;
+        break;
+    case rotate_270:
+        fncr1Val |= 0x10;
+        break;
+    default:
+        return invalid;
+    }
     WriteCommand(RA8875_FNCR1, fncr1Val);
-    return WriteCommand(RA8875_DPCR, dpcrVal);
+    return oldAngle;
 }
 
-
 RetCode_t RA8875::SetTextFontControl(fill_t fillit,
                                      RA8875::HorizontalScale hScale,
                                      RA8875::VerticalScale vScale,
@@ -1234,7 +1268,7 @@
 {
     if (hScale >= 1 && hScale <= 4 &&
             vScale >= 1 && vScale <= 4) {
-        uint8_t fncr1Val = ReadCommand(0x22);
+        uint8_t fncr1Val = ReadCommand(RA8875_FNCR1);
 
         fncr1Val &= 0x10;      // remove all except the font rotation bit
         if (alignment == align_full)
@@ -1252,7 +1286,7 @@
 fill_t RA8875::SetTextFontFill(fill_t fillit)
 {
     fill_t prevFill = FILL;
-    uint8_t fncr1Val = ReadCommand(0x22);
+    uint8_t fncr1Val = ReadCommand(RA8875_FNCR1);
 
     if (fncr1Val & 0x40)
         prevFill = NOFILL;
@@ -1265,14 +1299,14 @@
 
 RetCode_t RA8875::SetTextFontSize(RA8875::HorizontalScale hScale, RA8875::VerticalScale vScale)
 {
-    unsigned char reg = ReadCommand(0x22);
+    unsigned char reg = ReadCommand(RA8875_FNCR1);
 
     if (vScale == -1)
         vScale = hScale;
     if (hScale >= 1 && hScale <= 4 && vScale >= 1 && vScale <= 4) {
-        fontScaleX = hScale;    // save for use with a Soft Font
+        fontScaleX = hScale;            // save for use with a Soft Font
         fontScaleY = vScale;
-        reg &= 0xF0;    // keep the high nibble as is.
+        reg &= 0xF0;                    // keep the high nibble as is.
         reg |= ((hScale - 1) << 2);
         reg |= ((vScale - 1) << 0);
         WriteCommand(RA8875_FNCR1, reg);
@@ -1284,7 +1318,7 @@
 
 RetCode_t RA8875::GetTextFontSize(RA8875::HorizontalScale * hScale, RA8875::VerticalScale * vScale)
 {
-    unsigned char reg = ReadCommand(0x22);
+    unsigned char reg = ReadCommand(RA8875_FNCR1);
 
     if (hScale)
         *hScale = 1 + ((reg >> 2) & 0x03);
@@ -1297,9 +1331,9 @@
 {
     if (font == NULL) {
         if (charOnly)
-            return fontwidth();     // *fontScaleX;  // fontScale is picked up from fontwidth()
+            return fontwidth();
         else
-            return fontwidth() * strlen(text);// *fontScaleX;
+            return fontwidth() * strlen(text);
     } else {
         dim_t width = 0;
 
@@ -1341,13 +1375,7 @@
             cursor_y += extFontHeight;
         } else {
             dim_t charWidth, charHeight;
-            const uint8_t * charRecord;
-
-            charRecord = getCharMetrics(c, &charWidth, &charHeight);
-            //int advance = charwidth(c);
-            INFO("(%d,%d) - (%d,%d):(%d,%d), charWidth: %d '%c", cursor_x, cursor_y,
-                windowrect.p1.x, windowrect.p1.y, windowrect.p2.x, windowrect.p2.y,
-                charWidth, c);
+            const uint8_t * charRecord = getCharMetrics(c, &charWidth, &charHeight);
             if (charRecord) {
                 //cursor_x += advance;
                 if (cursor_x + charWidth >= windowrect.p2.x) {
@@ -1369,22 +1397,19 @@
 int RA8875::_internal_putc(int c)
 {
     if (c) {
-        unsigned char mwcr0;
-
-        mwcr0 = ReadCommand(RA8875_MWCR0);
+        unsigned char mwcr0 = ReadCommand(RA8875_MWCR0);
         if ((mwcr0 & 0x80) == 0x00)
             WriteCommand(RA8875_MWCR0, 0x80 | mwcr0);    // Put in Text mode if not already
-        if (c == '\r') {
-            loc_t x;
-            x = ReadCommand(0x30) | (ReadCommand(0x31) << 8);   // Left edge of active window
-            WriteCommandW(RA8875_FCURXL, x);
-        } else if (c == '\n') {
-            loc_t y;
-            y = ReadCommand(0x2C) | (ReadCommand(0x2D) << 8);   // current y location
-            y += fontheight();
-            if (y >= height())               // @TODO after bottom of active window, then scroll window?
-                y = 0;
-            WriteCommandW(RA8875_FCURYL, y);
+        if (c == '\r' || c == '\n') {
+            point_t cur = GetTextCursor();
+            if (c == '\r') {
+                cur.x = windowrect.p1.x;
+            } else if (c == '\n') {
+                cur.y += fontheight();
+                if (cur.y >= windowrect.p2.y)               // @TODO after bottom of active window, then scroll window?
+                    cur.y = windowrect.p1.y;
+            }
+            SetTextCursor(cur);
         } else {
             WriteCommand(RA8875_MRWC);                 // RA8875 Internal Fonts
             _select(true);
@@ -1403,9 +1428,9 @@
 
     mwcr0 = ReadCommand(RA8875_MWCR0) & ~0x80;
     mwcr0 |= 0x00;
-    INFO("mwcr0 %02X", mwcr0);
-    WriteCommand(RA8875_MWCR0, mwcr0);    // Graphics write mode
-    WriteCommand(RA8875_MRWC);         // Prepare for streaming data
+    //INFO("_StartGraphicsStream mwcr0: %02X", mwcr0);
+    WriteCommand(RA8875_MWCR0, mwcr0);      // Graphics write mode
+    WriteCommand(RA8875_MRWC);              // Prepare for streaming data
     return noerror;
 }
 
@@ -1438,14 +1463,12 @@
 
 void RA8875::puts(const char * string)
 {
+    INFO("puts len(%d), (%s)", strlen(string), string);
     if (font == NULL) {
-        unsigned char mwcr0;
-
-        mwcr0 = ReadCommand(RA8875_MWCR0);
+        unsigned char mwcr0 = ReadCommand(RA8875_MWCR0);
         if ((mwcr0 & 0x80) == 0x00)
             WriteCommand(RA8875_MWCR0, 0x80 | mwcr0);    // Put in Text mode if not already
     }
-    point_t cursor = GetTextCursor();
     while (string && *string) {           // @TODO calling individual _putc is slower... optimizations?
         if (wordwrap) {
             const char * p = string;
@@ -1453,9 +1476,10 @@
             dim_t txtPos;
             bool newLineNeeded = false;
 
-            cursor = GetTextCursor();
+            point_t cursor = GetTextCursor();
+            //INFO("cursor (%d,%d)", cursor.x, cursor.y);
             txtPos = cursor.x;
-            INFO("(%d,%d) string: '%s'\r\n", cursor.x, cursor.y, string);
+            INFO("(%d,%d) string: '%s'", cursor.x, cursor.y, string);
             // find what fits in the window
             do {
                 if (*p == ' ')
@@ -1468,23 +1492,39 @@
                     break;
                 }
                 dim_t cWidth = GetTextWidth(p, true);
+                INFO("txtPos: %d, cWidth: %d, p2.x: %d", txtPos, cWidth, windowrect.p2.x);
                 if (txtPos + cWidth < windowrect.p2.x) {
                     txtPos += cWidth;
                 } else {
                     newLineNeeded = true;
                     break;
                 }
-                INFO("+ %c width %d, ttl Width %d\r\n", *p, cWidth, txtPos);
+                INFO("+ %c width %d, ttl Width %d < %d", *p, cWidth, txtPos, windowrect.p2.x);
                 p++;
             } while (*p);
-            INFO(" do { } while();\r\n");
+            INFO("p: len(%d), (%s)", strlen(p), p);
             if (*p != ' ' && pSpace) {
                 p = pSpace;
+                INFO("p: len(%d), (%s)", strlen(p), p);
             }
-            INFO("txtPos: %d < windowrect.p2.x: %d\r\n", txtPos, windowrect.p2.x);
+            char dbgBuf[256];
+            strncpy(dbgBuf, string, (p - string));
+            dbgBuf[p - string] = '\0';
+            INFO("chunk: %d < w.p2.x: %d - '%s'", txtPos, windowrect.p2.x, dbgBuf);
             if (txtPos < windowrect.p2.x) {
                 while (*string && string <= p) {
-                    _putc(*string++);
+                    INFO("*string %02X", *string);
+                    if (*string == '\r') {
+                        cursor = GetTextCursor();
+                        SetTextCursor(windowrect.p1.x, cursor.y);
+                    } else if (*string == '\n') {
+                        cursor = GetTextCursor();
+                        SetTextCursor(cursor.x, cursor.y + fontheight());
+                    } else {
+                        INFO("cursor (%d,%d) - %c", cursor.x, cursor.y, *string);
+                        _putc(*string);
+                    }
+                    string++;
                 }
             }
             while (*string == ' ')
@@ -1501,13 +1541,27 @@
             _putc(*string++);
         }
     }
+    //point_t cursor = GetTextCursor();
+    //INFO("cursor (%d,%d)", cursor.x, cursor.y);
 }
 
 
 RetCode_t RA8875::SetGraphicsCursor(loc_t x, loc_t y)
 {
-    WriteCommandW(RA8875_CURH0, x);
-    WriteCommandW(RA8875_CURV0, y);
+    switch (screen_orientation) {
+    case rotate_0:
+    case rotate_180:
+        WriteCommandW(RA8875_CURH0, x);
+        WriteCommandW(RA8875_CURV0, y);
+        break;
+    case rotate_90:
+    case rotate_270:
+        WriteCommandW(RA8875_CURH0, y);
+        WriteCommandW(RA8875_CURV0, x);
+        break;
+    case invalid:
+        return bad_parameter;
+    }
     return noerror;
 }
 
@@ -1520,50 +1574,108 @@
 {
     point_t p;
 
-    p.x = ReadCommandW(0x46);
-    p.y = ReadCommandW(0x48);
+    switch (screen_orientation) {
+    case rotate_0:
+    case rotate_180:
+        p.x = ReadCommandW(RA8875_CURH0);
+        p.y = ReadCommandW(RA8875_CURV0);
+        break;
+    case rotate_90:
+    case rotate_270:
+        p.y = ReadCommandW(RA8875_CURH0);
+        p.x = ReadCommandW(RA8875_CURV0);
+        break;
+    case invalid:
+        p.x = p.y = 0;
+        break;
+    }
     return p;
 }
 
 RetCode_t RA8875::SetGraphicsCursorRead(loc_t x, loc_t y)
 {
-    WriteCommandW(RA8875_RCURH0, x);
-    WriteCommandW(RA8875_RCURV0, y);
+    switch (screen_orientation) {
+    case rotate_0:
+    case rotate_180:
+        WriteCommandW(RA8875_RCURH0, x);
+        WriteCommandW(RA8875_RCURV0, y);
+        break;
+    case rotate_90:
+    case rotate_270:
+        WriteCommandW(RA8875_RCURH0, y);
+        WriteCommandW(RA8875_RCURV0, x);
+        break;
+    case invalid:
+        return bad_parameter;
+    }
     return noerror;
 }
 
-RetCode_t RA8875::window(rect_t r)
+
+rect_t RA8875::GetWindow() {
+    return windowrect;
+}
+
+rect_t RA8875::SetWindow(rect_t r)
 {
-    return window(r.p1.x, r.p1.y, r.p2.x + 1 - r.p1.x, r.p2.y + 1 - r.p1.y);
+    return SetWindow(r.p1.x, r.p1.y, r.p2.x, r.p2.y);
 }
 
-RetCode_t RA8875::window(loc_t x, loc_t y, dim_t width, dim_t height)
+rect_t RA8875::SetWindow(loc_t x1, loc_t y1, loc_t x2, loc_t y2)
 {
-    INFO("window(%d,%d,%d,%d)", x, y, width, height);
-    if (width == (dim_t)-1)
-        width = screenwidth - x;
-    if (height == (dim_t)-1)
-        height = screenheight - y;
-    windowrect.p1.x = x;
-    windowrect.p1.y = y;
-    windowrect.p2.x = x + width - 1;
-    windowrect.p2.y = y + height - 1;
-    GraphicsDisplay::window(x,y, width,height);
-    WriteCommandW(RA8875_HSAW0, x);
-    WriteCommandW(RA8875_VSAW0, y);
-    WriteCommandW(RA8875_HEAW0, (x+width-1));
-    WriteCommandW(RA8875_VEAW0, (y+height-1));
-    //SetTextCursor(x,y);
-    //SetGraphicsCursor(x,y);
-    return noerror;
+    const rect_t nullRect = { 0,0,0,0 };    // in case it is invalid
+    rect_t oldWin = windowrect;
+    dim_t tempWidth, tempHeight;
+    //INFO("SetWindow(%d,%d)-(%d,%d)", x1,y1, x2,y2);
+    // Correct the initial values (0,-1) - (0,-1)
+    if (x2 == (loc_t)-1) x2 = virt_screenwidth - 1;
+    if (y2 == (loc_t)-1) y2 = virt_screenheight - 1;
+    // Sanity check the parameters.
+    if (x1 < 0 || y1 < 0 || x2 < 0 || y2 < 0
+        || x1 >= virt_screenwidth || y1 >= virt_screenheight 
+        || x2 >= virt_screenwidth || y2 >= virt_screenheight) {
+        return nullRect;
+    }
+    windowrect.p1.x = x1;
+    windowrect.p1.y = y1;
+    windowrect.p2.x = x2;
+    windowrect.p2.y = y2;
+    switch (screen_orientation) {
+    case rotate_0:
+    case rotate_180:
+        tempWidth = max(virt_screenwidth, virt_screenheight);
+        tempHeight = min(virt_screenwidth, virt_screenheight);
+        virt_screenwidth = tempWidth;
+        virt_screenheight = tempHeight;
+        //GraphicsDisplay::SetWindow(x1, y1, x2, y2);
+        WriteCommandW(RA8875_HSAW0, x1);
+        WriteCommandW(RA8875_VSAW0, y1);
+        WriteCommandW(RA8875_HEAW0, x2);
+        WriteCommandW(RA8875_VEAW0, y2);
+        break;
+    case rotate_90:
+    case rotate_270:
+        tempWidth = min(virt_screenwidth, virt_screenheight);
+        tempHeight = max(virt_screenwidth, virt_screenheight);
+        virt_screenwidth = tempWidth;
+        virt_screenheight = tempHeight;
+        //GraphicsDisplay::SetWindow(x1, y1, x2, y2);
+        WriteCommandW(RA8875_HSAW0, y1);
+        WriteCommandW(RA8875_VSAW0, x1);
+        WriteCommandW(RA8875_HEAW0, y2);
+        WriteCommandW(RA8875_VEAW0, x2);
+        break;
+    case invalid:
+        break;
+    }
+    return oldWin;
 }
 
-
 RetCode_t RA8875::cls(uint16_t layers)
 {
-    RetCode_t ret;
-
-    INFO("cls()");
+    RetCode_t ret = noerror;
+
+    INFO("cls(%d)", layers);
     PERFORMANCE_RESET;
     if (layers == 0) {
         ret = clsw(FULLWINDOW);
@@ -1581,7 +1693,7 @@
         }
         SelectDrawingLayer(prevLayer);
     }
-    ret = SetTextCursor(0,0);
+    SetTextCursor(0,0);
     //ret = locate(0,0);
     REGISTERPERFORMANCE(PRF_CLS);
     return ret;
@@ -1593,7 +1705,8 @@
     INFO("clsw(%d)", region);
     PERFORMANCE_RESET;
     WriteCommand(RA8875_MCLR, (region == ACTIVEWINDOW) ? 0xC0 : 0x80);
-    if (!_WaitWhileReg(0x8E, 0x80)) {
+    if (!_WaitWhileReg(RA8875_MCLR, 0x80)) {
+        WriteCommand(RA8875_MCLR, 0x00);    // Abort clearing on request
         REGISTERPERFORMANCE(PRF_CLS);
         return external_abort;
     }
@@ -1666,8 +1779,7 @@
 {
     PERFORMANCE_RESET;
     const uint8_t * rowStream = boolStream;
-    rect_t restore = windowrect;
-    window(x, y, w * fontScaleX, h * fontScaleY);       // Scale from font scale factors
+    rect_t restore = SetWindow(x, y, x + w * fontScaleX - 1, y + h * fontScaleY - 1);
     SetGraphicsCursor(x, y);
     _StartGraphicsStream();
     _select(true);
@@ -1702,7 +1814,7 @@
     }
     _select(false);
     _EndGraphicsStream();
-    window(restore);
+    SetWindow(restore);
     REGISTERPERFORMANCE(PRF_BOOLSTREAM);
     return(noerror);
 }
@@ -1788,12 +1900,39 @@
 {
     PERFORMANCE_RESET;
     if (x1 == x2 && y1 == y2) {
-        pixel(x1, y1);
+        switch (screen_orientation) {
+        case invalid:
+            return bad_parameter;
+            //break;
+        case rotate_0:
+        case rotate_180:
+            pixel(x1, y1);
+            break;
+        case rotate_90:
+        case rotate_270:
+            pixel(y1, x1);
+            break;
+        }
     } else {
-        WriteCommandW(RA8875_DLHSR0, x1);
-        WriteCommandW(RA8875_DLVSR0, y1);
-        WriteCommandW(RA8875_DLHER0, x2);
-        WriteCommandW(RA8875_DLVER0, y2);
+        switch (screen_orientation) {
+        case invalid:
+            return bad_parameter;
+            //break;
+        case rotate_0:
+        case rotate_180:
+            WriteCommandW(RA8875_DLHSR0, x1);
+            WriteCommandW(RA8875_DLVSR0, y1);
+            WriteCommandW(RA8875_DLHER0, x2);
+            WriteCommandW(RA8875_DLVER0, y2);
+            break;
+        case rotate_90:
+        case rotate_270:
+            WriteCommandW(RA8875_DLHSR0, y1);
+            WriteCommandW(RA8875_DLVSR0, x1);
+            WriteCommandW(RA8875_DLHER0, y2);
+            WriteCommandW(RA8875_DLVER0, x2);
+            break;
+        }
         unsigned char drawCmd = 0x00;       // Line
         WriteCommand(RA8875_DCR, drawCmd);
         WriteCommand(RA8875_DCR, 0x80 + drawCmd); // Start drawing.
@@ -1809,7 +1948,7 @@
 
 RetCode_t RA8875::ThickLine(point_t p1, point_t p2, dim_t thickness, color_t color)
 {
-    INFO("ThickLine()");
+    //INFO("ThickLine()");
     if (thickness == 1) {
         line(p1,p2, color);
     } else {
@@ -1831,7 +1970,6 @@
             // some diagonal, drawn rather slowly with filled circles
             // @todo draw the end-points with circles, then draw the diagonal
             //      with 2 triangles.
-            #if 1  // New Faster method
             //Round-caps
             if (roundCap) {
                 fillcircle(p1, thickness / 2, color);
@@ -1867,23 +2005,6 @@
             pTri[3].y = p2.y - dy;
             filltriangle(pTri[0],pTri[1],pTri[3], color);
             filltriangle(pTri[0],pTri[2],pTri[3], color);
-            #else // old slower method
-            // Draw with a lot of overlapping circles
-            int dx = abs(p2.x-p1.x), sx = p1.x<p2.x ? 1 : -1;
-            int dy = abs(p2.y-p1.y), sy = p1.y<p2.y ? 1 : -1;
-            int err = (dx>dy ? dx : -dy)/2, e2;
-
-            for (;;) {
-                fillcircle(p1.x, p1.y, thickness/2, color);
-                if (p1.x==p2.x && p1.y==p2.y)
-                    break;
-                e2 = err;
-                if (e2 >-dx)
-                    { err -= dy; p1.x += sx; }
-                if (e2 < dy)
-                    { err += dx; p1.y += sy; }
-            }
-            #endif
         }
     }
     return noerror;
@@ -1930,8 +2051,8 @@
     RetCode_t ret = noerror;
     PERFORMANCE_RESET;
     // check for bad_parameter
-    if (x1 < 0 || x1 >= screenwidth || x2 < 0 || x2 >= screenwidth
-    || y1 < 0 || y1 >= screenheight || y2 < 0 || y2 >= screenheight) {
+    if (x1 < 0 || x1 >= virt_screenwidth || x2 < 0 || x2 >= virt_screenwidth
+    || y1 < 0 || y1 >= virt_screenheight || y2 < 0 || y2 >= virt_screenheight) {
         ret = bad_parameter;
     } else {
         if (x1 == x2 && y1 == y2) {
@@ -1941,10 +2062,27 @@
         } else if (y1 == y2) {
             line(x1, y1, x2, y2);
         } else {
-            WriteCommandW(RA8875_DLHSR0, x1);
-            WriteCommandW(RA8875_DLVSR0, y1);
-            WriteCommandW(RA8875_DLHER0, x2);
-            WriteCommandW(RA8875_DLVER0, y2);
+            switch (screen_orientation) {
+            case rotate_0:
+            case rotate_180:
+                WriteCommandW(RA8875_DLHSR0, x1);
+                WriteCommandW(RA8875_DLVSR0, y1);
+                WriteCommandW(RA8875_DLHER0, x2);
+                WriteCommandW(RA8875_DLVER0, y2);
+                break;
+            case rotate_90:
+            case rotate_270:
+                WriteCommandW(RA8875_DLHSR0, y1);
+                WriteCommandW(RA8875_DLVSR0, x1);
+                WriteCommandW(RA8875_DLHER0, y2);
+                WriteCommandW(RA8875_DLVER0, x2);
+                break;
+            case invalid:
+                REGISTERPERFORMANCE(PRF_DRAWRECTANGLE);
+                ret = bad_parameter;
+                return ret;
+                //break;
+            }
             unsigned char drawCmd = 0x10;   // Rectangle
             if (fillit == FILL)
                 drawCmd |= 0x20;
@@ -1997,8 +2135,8 @@
 
     INFO("roundrect()");
     PERFORMANCE_RESET;
-    if (x1 < 0 || x1 >= screenwidth || x2 < 0 || x2 >= screenwidth
-    || y1 < 0 || y1 >= screenheight || y2 < 0 || y2 >= screenheight) {
+    if (x1 < 0 || x1 >= virt_screenwidth || x2 < 0 || x2 >= virt_screenwidth
+    || y1 < 0 || y1 >= virt_screenheight || y2 < 0 || y2 >= virt_screenheight) {
         ret = bad_parameter;
     } else if (x1 > x2 || y1 > y2 || (radius1 > (x2-x1)/2) || (radius2 > (y2-y1)/2) ) {
         ret = bad_parameter;
@@ -2009,12 +2147,30 @@
     } else if (y1 == y2) {
         line(x1, y1, x2, y2);
     } else {
-        WriteCommandW(RA8875_DLHSR0, x1);
-        WriteCommandW(RA8875_DLVSR0, y1);
-        WriteCommandW(RA8875_DLHER0, x2);
-        WriteCommandW(RA8875_DLVER0, y2);
-        WriteCommandW(RA8875_ELLA0, radius1);
-        WriteCommandW(RA8875_ELLB0, radius2);
+        switch (screen_orientation) {
+        case rotate_0:
+        case rotate_180:
+            WriteCommandW(RA8875_DLHSR0, x1);
+            WriteCommandW(RA8875_DLVSR0, y1);
+            WriteCommandW(RA8875_DLHER0, x2);
+            WriteCommandW(RA8875_DLVER0, y2);
+            WriteCommandW(RA8875_ELLA0, radius1);
+            WriteCommandW(RA8875_ELLB0, radius2);
+            break;
+        case rotate_90:
+        case rotate_270:
+            WriteCommandW(RA8875_DLHSR0, y1);
+            WriteCommandW(RA8875_DLVSR0, x1);
+            WriteCommandW(RA8875_DLHER0, y2);
+            WriteCommandW(RA8875_DLVER0, x2);
+            WriteCommandW(RA8875_ELLA0, radius2);
+            WriteCommandW(RA8875_ELLB0, radius1);
+            break;
+        case invalid:
+            REGISTERPERFORMANCE(PRF_DRAWROUNDEDRECTANGLE);
+            return bad_parameter;
+            //break;
+        }
         // Should not need this...
         WriteCommandW(RA8875_DEHR0, 0);
         WriteCommandW(RA8875_DEVR0, 0);
@@ -2051,8 +2207,8 @@
 {
     RetCode_t ret;
 
-    if (x1 < 0 || x1 >= screenwidth || x2 < 0 || x2 >= screenwidth || x3 < 0 || x3 >= screenwidth
-    || y1 < 0 || y1 >= screenheight || y2 < 0 || y2 >= screenheight || y3 < 0 || y3 >= screenheight)
+    if (x1 < 0 || x1 >= virt_screenwidth || x2 < 0 || x2 >= virt_screenwidth || x3 < 0 || x3 >= virt_screenwidth
+    || y1 < 0 || y1 >= virt_screenheight || y2 < 0 || y2 >= virt_screenheight || y3 < 0 || y3 >= virt_screenheight)
         ret = bad_parameter;
     foreground(color);
     ret = triangle(x1,y1,x2,y2,x3,y3,fillit);
@@ -2081,12 +2237,30 @@
     if (x1 == x2 && y1 == y2 && x1 == x3 && y1 == y3) {
         pixel(x1, y1);
     } else {
-        WriteCommandW(RA8875_DLHSR0, x1);
-        WriteCommandW(RA8875_DLVSR0, y1);
-        WriteCommandW(RA8875_DLHER0, x2);
-        WriteCommandW(RA8875_DLVER0, y2);
-        WriteCommandW(RA8875_DTPH0, x3);
-        WriteCommandW(RA8875_DTPV0, y3);
+        switch (screen_orientation) {
+        case rotate_0:
+        case rotate_180:
+            WriteCommandW(RA8875_DLHSR0, x1);
+            WriteCommandW(RA8875_DLVSR0, y1);
+            WriteCommandW(RA8875_DLHER0, x2);
+            WriteCommandW(RA8875_DLVER0, y2);
+            WriteCommandW(RA8875_DTPH0, x3);
+            WriteCommandW(RA8875_DTPV0, y3);
+            break;
+        case rotate_90:
+        case rotate_270:
+            WriteCommandW(RA8875_DLHSR0, y1);
+            WriteCommandW(RA8875_DLVSR0, x1);
+            WriteCommandW(RA8875_DLHER0, y2);
+            WriteCommandW(RA8875_DLVER0, x2);
+            WriteCommandW(RA8875_DTPH0, y3);
+            WriteCommandW(RA8875_DTPV0, x3);
+            break;
+        case invalid:
+            REGISTERPERFORMANCE(PRF_DRAWTRIANGLE);
+            return bad_parameter;
+            //break;
+        }
         unsigned char drawCmd = 0x01;       // Triangle
         if (fillit == FILL)
             drawCmd |= 0x20;
@@ -2139,41 +2313,34 @@
     return circle(x,y,radius,fillit);
 }
 
-
 RetCode_t RA8875::circle(loc_t x, loc_t y, dim_t radius, fill_t fillit)
 {
     RetCode_t ret = noerror;
 
     INFO("circle");
     PERFORMANCE_RESET;
-    #if 0
-    loc_t t;
-    SetTextCursor(0,10);
-    printf("Circle(%3d,%3d) => ", x,y);
-    switch (screen_orientation) {
-        default:
-        case rotate_0:
-            break;
-        case rotate_90:
-            t = x;
-            x = y;
-            y = t;
-            break;
-        case rotate_180:
-            break;
-        case rotate_270:
-            break;
-    }
-    printf("  => (%3d,%3d)\r\n", x,y);
-    #endif
     if ((x - radius) < 0 || (x + radius) > width()
     || (y - radius) < 0 || (y + radius) > height()) {
         ret = bad_parameter;
     } else if (radius == 1) {
         pixel(x,y);
     } else {
-        WriteCommandW(RA8875_DCHR0, x);
-        WriteCommandW(RA8875_DCVR0, y);
+        switch (screen_orientation) {
+        case rotate_0:
+        case rotate_180:
+            WriteCommandW(RA8875_DCHR0, x);
+            WriteCommandW(RA8875_DCVR0, y);
+            break;
+        case rotate_90:
+        case rotate_270:
+            WriteCommandW(RA8875_DCHR0, y);
+            WriteCommandW(RA8875_DCVR0, x);
+            break;
+        case invalid:
+            REGISTERPERFORMANCE(PRF_DRAWCIRCLE);
+            return bad_parameter;
+            //break;
+        }
         WriteCommand(RA8875_DCRR, radius & 0xFF);
         unsigned char drawCmd = 0x00;       // Circle
         if (fillit == FILL)
@@ -2210,14 +2377,28 @@
 
     INFO("ellipse");
     PERFORMANCE_RESET;
-    if ((x - radius1) < 0 || (x + radius1) > screenwidth
-    || (y - radius2) < 0 || (y + radius2) > screenheight) {
+    if ((x - radius1) < 0 || (x + radius1) > virt_screenwidth
+    || (y - radius2) < 0 || (y + radius2) > virt_screenheight) {
         ret = bad_parameter;
     } else if (radius1 == 1 && radius2 == 1) {
         pixel(x, y);
     } else {
-        WriteCommandW(RA8875_DEHR0, x);
-        WriteCommandW(RA8875_DEVR0, y);
+        switch (screen_orientation) {
+        case rotate_0:
+        case rotate_180:
+            WriteCommandW(RA8875_DEHR0, x);
+            WriteCommandW(RA8875_DEVR0, y);
+            break;
+        case rotate_90:
+        case rotate_270:
+            WriteCommandW(RA8875_DEHR0, y);
+            WriteCommandW(RA8875_DEVR0, x);
+            break;
+        case invalid:
+            REGISTERPERFORMANCE(PRF_DRAWELLIPSE);
+            return bad_parameter;
+            //break;
+        }
         WriteCommandW(RA8875_ELLA0, radius1);
         WriteCommandW(RA8875_ELLB0, radius2);
         unsigned char drawCmd = 0x00;   // Ellipse
@@ -2363,45 +2544,52 @@
         extFontWidth = totalWidth / (lastChar - firstChar);
         INFO("Font Metrics: Avg W: %2d, H: %2d, First:%d, Last:%d", extFontWidth, extFontHeight, firstChar, lastChar);
     }
-    SetTextCursor(GetTextCursor_X(), GetTextCursor_Y());  // soft-font cursor -> hw cursor
+    SetTextCursor(GetTextCursor());  // soft-font cursor -> hw cursor
     font = _font;
     return GraphicsDisplay::SelectUserFont(_font);
 }
 
-RetCode_t RA8875::background(color_t color)
+color_t RA8875::background(color_t color)
 {
+    color_t oldColor = GetBackColor();
     GraphicsDisplay::background(color);
-    return _writeColorTrio(0x60, color);
+    _writeColorTrio(0x60, color);
+    return oldColor;
 }
 
 
-RetCode_t RA8875::background(unsigned char r, unsigned char g, unsigned char b)
+color_t RA8875::background(unsigned char r, unsigned char g, unsigned char b)
 {
-    background(RGB(r,g,b));
-    return noerror;
+    return background(RGB(r,g,b));
 }
 
-
-RetCode_t RA8875::foreground(color_t color)
+color_t RA8875::GetBackColor(void)
 {
-    GraphicsDisplay::foreground(color);
-    return _writeColorTrio(0x63, color);
+    return _readColorTrio(0x60);
 }
 
 
-RetCode_t RA8875::foreground(unsigned char r, unsigned char g, unsigned char b)
+color_t RA8875::foreground(color_t color)
 {
-    foreground(RGB(r,g,b));
-    return noerror;
+    color_t oldColor = GetForeColor();
+    GraphicsDisplay::foreground(color);
+    _writeColorTrio(0x63, color);
+    return oldColor;
 }
 
 
+color_t RA8875::foreground(unsigned char r, unsigned char g, unsigned char b)
+{
+    return foreground(RGB(r,g,b));
+}
+
 color_t RA8875::GetForeColor(void)
 {
     return _readColorTrio(0x63);
 }
 
 
+
 color_t RA8875::DOSColor(int i)
 {
     const color_t colors[16] = {
@@ -2517,10 +2705,10 @@
     color_t * pixelBuffer2 = NULL;
 
     INFO("(%d,%d)-(%d,%d)x%d", x,y,w,h,bitsPerPixel);
-    if (x >= 0 && x < screenwidth
-            && y >= 0 && y < screenheight
-            && w > 0 && x + w <= screenwidth
-            && h > 0 && y + h <= screenheight) {
+    if (x >= 0 && x < virt_screenwidth
+            && y >= 0 && y < virt_screenheight
+            && w > 0 && x + w <= virt_screenwidth
+            && h > 0 && y + h <= virt_screenheight) {
         BMP_Header.bfType = BF_TYPE;
         BMP_Header.bfReserved1 = 0;
         BMP_Header.bfReserved2 = 0;
@@ -2532,14 +2720,14 @@
             case 8:
             default:
                 BMP_Header.bfOffBits = sizeof(BMP_Header) + sizeof(BMP_Info) + sizeof(WebColorPalette);
-                INFO("Initial Offset to Bitstream %X", BMP_Header.bfOffBits);
+                INFO("Initial Offset to Bitstream %lX", BMP_Header.bfOffBits);
                 //if (BMP_Header.bfOffBits & 0x03) {
                 //    BMP_Header.bfOffBits += (4 - (BMP_Header.bfOffBits & 0x03));
                 //}
                 BMP_Header.bfSize = (h * RoundUp(w * 1,4)) + BMP_Header.bfOffBits;
                 break;
         }
-        INFO("Offset to Bitstream %X", BMP_Header.bfOffBits);
+        INFO("Offset to Bitstream %lX", BMP_Header.bfOffBits);
 
         // Bytes in the line buffer
         int lineBufSize = RoundUp(((bitsPerPixel == 24) ? 3 : 1) * w, 4);
@@ -2601,15 +2789,15 @@
         privateCallback(OPEN, (uint8_t *)&BMP_Header.bfSize, 4);
 
         // Be optimistic - don't check for errors.
-        HexDump("BMP_Header", (uint8_t *)&BMP_Header, sizeof(BMP_Header));
+        //HexDump("BMP_Header", (uint8_t *)&BMP_Header, sizeof(BMP_Header));
         //fwrite(&BMP_Header, sizeof(char), sizeof(BMP_Header), Image);
         privateCallback(WRITE, (uint8_t *)&BMP_Header, sizeof(BMP_Header));
 
-        HexDump("BMP_Info", (uint8_t *)&BMP_Info, sizeof(BMP_Info));
+        //HexDump("BMP_Info", (uint8_t *)&BMP_Info, sizeof(BMP_Info));
         //fwrite(&BMP_Info, sizeof(char), sizeof(BMP_Info), Image);
         privateCallback(WRITE, (uint8_t *)&BMP_Info, sizeof(BMP_Info));
         if (bitsPerPixel != 24) {
-            HexDump("Palette", (uint8_t *)&WebColorPalette, sizeof(WebColorPalette));
+            //HexDump("Palette", (uint8_t *)&WebColorPalette, sizeof(WebColorPalette));
             //fwrite(&WebColorPalette, sizeof(char), sizeof(WebColorPalette), Image);
             privateCallback(WRITE, (uint8_t *)&WebColorPalette, sizeof(WebColorPalette));
             if (0 && sizeof(WebColorPalette) % 4) {
@@ -2620,7 +2808,6 @@
         }
         //color_t transparency = GetBackgroundTransparencyColor();
         LayerMode_T ltpr0 = GetLayerMode();
-
         uint16_t prevLayer = GetDrawingLayer();
         // If only one of the layers is visible, select that layer
         switch(ltpr0) {
@@ -2640,10 +2827,10 @@
             if (idle_callback && h >= 1) {
                 (*idle_callback)(progress, (h - 1 - j) * 100 / (h - 1));
             }
-
             if (ltpr0 >= 2)             // Need to combine the layers...
                 SelectDrawingLayer(0);  // so read layer 0 first
             // Read one line of pixels to a local buffer
+            INFO("x,y %d,%d", x, y + j);
             if (getPixelStream(pixelBuffer, w, x,y+j) != noerror) {
                 ERR("getPixelStream error, and no recovery handler...");
             }
@@ -2698,9 +2885,9 @@
                         break;
                 }
             }
-            //if (j == h - 1) {
-            //    HexDump("Line", lineBuffer, lineBufSize);
-            //}
+            if (j == h - 1) {
+                HexDump("Line", lineBuffer, lineBufSize);
+            }
             // Write to disk
             privateCallback(WRITE, (uint8_t *)lineBuffer, lineBufSize);
         }
@@ -2730,11 +2917,11 @@
     color_t * pixelBuffer = NULL;
     color_t * pixelBuffer2 = NULL;
 
-    INFO("(%d,%d)-(%d,%d)x%d %s", x,y,w,h,bitsPerPixel,Name_BMP);
-    if (x >= 0 && x < screenwidth
-            && y >= 0 && y < screenheight
-            && w > 0 && x + w <= screenwidth
-            && h > 0 && y + h <= screenheight) {
+    //INFO("(%d,%d)-(%d,%d)x%d %s", x,y,w,h,bitsPerPixel,Name_BMP);
+    if (x >= 0 && x < virt_screenwidth
+            && y >= 0 && y < virt_screenheight
+            && w > 0 && x + w <= virt_screenwidth
+            && h > 0 && y + h <= virt_screenheight) {
         BMP_Header.bfType = BF_TYPE;
         BMP_Header.bfReserved1 = 0;
         BMP_Header.bfReserved2 = 0;
@@ -2746,18 +2933,18 @@
             case 8:
             default:
                 BMP_Header.bfOffBits = sizeof(BMP_Header) + sizeof(BMP_Info) + sizeof(WebColorPalette);
-                INFO("Initial Offset to Bitstream %X", BMP_Header.bfOffBits);
+                //INFO("Initial Offset to Bitstream %lX", BMP_Header.bfOffBits);
                 //if (BMP_Header.bfOffBits & 0x03) {
                 //    BMP_Header.bfOffBits += (4 - (BMP_Header.bfOffBits & 0x03));
                 //}
                 BMP_Header.bfSize = (h * RoundUp(w * 1,4)) + BMP_Header.bfOffBits;
                 break;
         }
-        INFO("Offset to Bitstream %X", BMP_Header.bfOffBits);
+        //INFO("Offset to Bitstream %lX", BMP_Header.bfOffBits);
 
         // Bytes in the line buffer
         int lineBufSize = RoundUp(((bitsPerPixel == 24) ? 3 : 1) * w, 4);
-        INFO("LineBufSize: %d", lineBufSize);
+        //INFO("LineBufSize: %d", lineBufSize);
 
         BMP_Info.biSize = sizeof(BMP_Info);
         BMP_Info.biWidth = w;
@@ -2824,14 +3011,14 @@
         }
 
         // Be optimistic - don't check for errors.
-        HexDump("BMP_Header", (uint8_t *)&BMP_Header, sizeof(BMP_Header));
+        //HexDump("BMP_Header", (uint8_t *)&BMP_Header, sizeof(BMP_Header));
         fwrite(&BMP_Header, sizeof(char), sizeof(BMP_Header), Image);
 
-        HexDump("BMP_Info", (uint8_t *)&BMP_Info, sizeof(BMP_Info));
+        //HexDump("BMP_Info", (uint8_t *)&BMP_Info, sizeof(BMP_Info));
         fwrite(&BMP_Info, sizeof(char), sizeof(BMP_Info), Image);
 
         if (bitsPerPixel != 24) {
-            HexDump("Palette", (uint8_t *)&WebColorPalette, sizeof(WebColorPalette));
+            //HexDump("Palette", (uint8_t *)&WebColorPalette, sizeof(WebColorPalette));
             fwrite(&WebColorPalette, sizeof(char), sizeof(WebColorPalette), Image);
             if (0 && sizeof(WebColorPalette) % 4) {
                 const uint8_t padd[] = { 0, 0, 0 };
@@ -2864,6 +3051,7 @@
 
             if (ltpr0 >= 2)             // Need to combine the layers...
                 SelectDrawingLayer(0);  // so read layer 0 first
+
             // Read one line of pixels to a local buffer
             if (getPixelStream(pixelBuffer, w, x,y+j) != noerror) {
                 ERR("getPixelStream error, and no recovery handler...");
@@ -2874,7 +3062,7 @@
                     ERR("getPixelStream error, and no recovery handler...");
                 }
             }
-            INFO("Line: %3d", j);
+            //INFO("Line: %3d", j);
             //HexDump("Raster", (uint8_t *)pixelBuffer, w * sizeof(color_t));
             // Convert the local buffer to RGBQUAD format
             int lb = 0;
@@ -2934,7 +3122,7 @@
         if (pixelBuffer)
             swFree(pixelBuffer);
         swFree(lineBuffer);
-        INFO("Image closed");
+        //INFO("Image closed");
         return noerror;
     } else {
         return bad_parameter;
--- a/RA8875.h	Tue Feb 11 21:51:42 2020 +0000
+++ b/RA8875.h	Sat Mar 28 15:01:38 2020 +0000
@@ -2,22 +2,27 @@
 /// @mainpage RA8875 Display Controller Driver library
 ///
 /// The RA8875 Display controller is a powerful interface for low cost displays. It
-/// can support displays up to 800 x 480 pixels x 16-bit color.
+/// can support displays up to 800 x 480 pixels x 16-bit color and has an integrated
+/// 2D graphics engine which significantly unburdens the hosting cpu. The 2D engine
+/// handles many drawing primitives; such as line, rectangle, triangle, circles, and
+/// each either filled or unfilled. Further, it supports fonts - both internal and
+/// with specific formats of external font roms.
 ///
 /// @image html Example_Program.png "Image of an Example Program"
 ///
+/// In more detail:
+///
 /// Aside from 800 x 480 pixel displays, another common implementation is
 /// 480 x 272 x 16 with two layers. The two layers can be exchanged, or blended
-/// in various ways (transparency, OR, AND, and more). It includes graphics
-/// acceleration capabilities for drawing primitives, such as line, rectangle,
-/// circles, and more.
+/// in various ways (transparency, OR, AND, and more). 
 ///
 /// It is not a display for video-speed animations, and maybe could hold its own
-/// as a slow picture frame, at least when using the SPI ports. How the performance
-/// differs using I2C, 8-bit parallel or 16-bit parallel has not been evaluated.
-/// Certainly the parallel interface option would be expected to be a lot faster.
+/// as a slow picture frame, at least when using the SPI interface. How the 
+/// performance differs using I2C, 8-bit parallel or 16-bit parallel has not 
+/// been evaluated. Certainly the parallel interface option would be expected to be 
+/// a lot faster.
 ///
-/// What it is good at is performing as a basic display for appliance or simple
+/// What it is good at is performing as a basic display for appliances or simple
 /// home automation, and because of the built-in capability to draw lines, circles,
 /// ellipses, rectangles, rounded rectangles, and triangles, it does a lot of the
 /// work that your host micro would otherwise be doing, and in many cases it does
@@ -29,26 +34,46 @@
 /// Without the hardware acceleration built into the RA8875, the host would have to
 /// compute every point, set the graphics cursor to that point, and fill in that
 /// point with the target color. A diagonal line of some length might take 100
-/// interactions instead of just a few. Other drawing primitives are similarly easy.
+/// transactions instead of just a few. Other drawing primitives are similarly easy.
 ///
 /// It has some built-in fonts, which can be enhanced with optional font-chips, and
-/// with the provided software font engine, and a few instructions, you can convert
-/// most any True Type Font into the data structures suitable for this display.
+/// with the software font engine that is part of this library. Instructions are provided
+/// to convert most any True Type Font into the data structures suitable for this display.
+/// The user of this library is expected to respect the copyright of those fonts (there 
+/// are open-source fonts that can be found on the web).
 ///
 /// To round out the features, this library offers the ability to render Bitmap (BMP),
-/// Icon (ICO), Join Photographic Experts Group (JPG), and Graphics Interchange Format
+/// Icon (ICO), Joint Photographic Experts Group (JPG), and Graphics Interchange Format
 /// (GIF) images. These are implemented primarily in software, taking advantage of the
-/// hardware acceleration where it can.
+/// hardware acceleration where it can. There are some limitations, based on available
+/// memory.
 ///
 /// When you are satisfied with what appears on screen, there is a PrintScreen method
-/// to pull that image back out and write it to a file system as a BitMap image.
+/// to pull that image back out of the display RAM and write it to a file system as a 
+/// BitMap image.
+///
+///
+/// The RA8875 has an integrated PWM, commonly used for backlight brightness, keypad scanning
+/// (for a 4 x 5 matrix) and an integrated resistive touch-panel support. Support for capacitive
+/// touch screens is also integrated in this library, in a manner that makes the resistive and
+/// capacitive interfaces nearly API identical. The capacitive touch support was crafted to
+/// interface with either the FT5206 or the GSL1680 controller chips (two popular controllers
+/// commonly integrated with the RA8875).
 ///
-/// The controller additionally supports backlight control (via PWM), keypad scanning
-/// (for a 4 x 5 matrix) and resistive touch-panel support. Support for capacitive
-/// touch screens is also integrated, in a manner that makes the resistive and
-/// capacitive interfaces nearly API identical. The capacitive touch support is for
-/// either the FT5206 or the GSL1680 controller chips.
-///
+/// Recent Changes:
+/// * @ref RA8875::SelectDrawingLayer() returns the previously selected layer, making restore quicker.
+/// * @ref RA8875::SetGraphicsOrientation() has been improved to support 0 deg (typical landscape),
+///             90 deg, 180 deg, and 270 deg, and this includes bitmap and soft-font presentation, 
+///             as well as touch support and to return the previous angle.
+/// * @ref RA8875::SetBackgroundTransparencyColor() returns the previous color value, making 
+///             restore quicker.
+/// * @ref RA8875::SetWindow() accepts a rect_t, or an (x1,y1, x2,y2) point-pair, rather than a
+///             point-pair and a width,height. This makes it much more consisten with all other APIs.
+/// * @ref RA8875::SetLayerMode() returns the previous layer mode.
+/// * @ref RA8875::SetTextCursor() returns the previous cursor.
+/// * @ref RA8875::background() returns the previous color.
+/// * @ref RA8875::foreground() returns the previous color.
+
 /// Here's a few hints to get started:
 /// * @ref Display_Config
 /// * @ref Touch_Panel
@@ -58,22 +83,21 @@
 /// * @ref External_Resources
 /// * @ref Future_Plans
 ///
+/// @todo Integrate the touch as a runtime linkable feature, which can then eliminate
+///     the huge memory footprint for the GSL1680 firmware when it is not needed.
 /// @todo Move the global enums into the class (e.g. NOFILL becomes RA8875::NOFILL) to
 ///     avoid namespace clashes.
-/// @todo Integrate the touch as a runtime linkable feature, which can then eliminate
-///     the huge memory footprint for the GSL1680 firmware when it is not needed.
-/// @todo Integrate installed font-rom.
+/// @todo Integrate access to an installed font-rom.
 /// @todo Figure out how to "init()" in the constructor. I ran into some issues if
 ///     the display was instantiated before main(), and the code would not run,
 ///     thus the exposure and activation of the init() function. If the constructor
 ///     was within main(), then it seemed to work as expected.
-/// @todo Add Scroll support for text.
-/// @todo Add Hardware reset signal - but testing to date indicates it is not needed.
-/// @todo Add high level objects - x-y graph, meter, others... but these will
-///     probably be best served in another class, since they may not
-///     be needed for many uses.
+/// @todo Add Scroll support for text in a window.
+/// @todo Add Hardware reset signal - testing to date indicates it is not needed.
 /// @todo Add APIs for the 2nd RA8875 PWM channel. If the frequency can be independently
-///     controlled, it could be used as a simple beeper.
+///     controlled, it could be used as a simple sound channel (beeper).
+/// @todo Find out if 4-wire SPI can leverage 16-bit mode, and if so, how does the 
+///     performance change?
 ///
 /// @note As the author of this library, let me state that I am not affiliated with
 ///     Raio (silicon provider of the RA8875), or with BuyDisplay.com (where a lot
@@ -81,8 +105,8 @@
 ///     of the technology of the RA8875 chip.
 ///
 /// @copyright Copyright &copy; 2012-2020 by Smartware Computing, all rights reserved.
-///     This library is predominantly, that of Smartware Computing, however some
-///     portions are compiled from the work of others. Where the contribution of
+///     This library is predominantly that of Smartware Computing, however some
+///     portions integrate the work of others. Where the contribution of
 ///     others was listed as copyright, that copyright is maintained, even as a
 ///     derivative work may have been created for better integration in this library.
 ///     See @ref Copyright_References.
@@ -135,8 +159,6 @@
 /// * 1 Layer - when the color depth is 16 bits per pixel
 /// * 2 Layers - when the color depth is 8 bits per pixel and the resolution is 480 x 272.
 ///
-///
-///
 /// @page Touch_Panel Touch Panel
 ///
 /// There is support for various touch panel interfaces.
@@ -316,25 +338,17 @@
 ///
 /// - Change the return values for several functions. Most functions return @ref RA8875::RetCode_t,
 ///     but would benefit from returning a data type related to that function. For example,
-///     @ref RA8875::SelectDrawingLayer() could return the current drawing layer even as a new
+///     @ref RA8875::SelectDrawingLayer() should return the current drawing layer even as a new
 ///     layer is defined. This can facilitate switching back and forth between configurations.
-///     Examples:
-///     - @ref RA8875::SelectDrawingLayer()
+///
+///     Review the API for these (and other) functions for this change:
 ///     - @ref RA8875::SelectUserFont()
-///     - @ref RA8875::SetBackgroundTransparencyColor()
-///     - @ref RA8875::SetLayerMode()
 ///     - @ref RA8875::SetLayerTransparency()
-///     - @ref RA8875::SetOrientation()
-///     - @ref RA8875::SetTextCursor()
 ///     - @ref RA8875::SetTextCursorControl()
 ///     - @ref RA8875::SetTextFont()
 ///     - @ref RA8875::SetTextFontControl()
 ///     - @ref RA8875::SetTextFontSize()
-///     - @ref RA8875::background()
-///     - @ref RA8875::foreground()
 ///     - @ref RA8875::Backlight()
-///     - @ref RA8875::window()
-///     - @ref RA8875::WindowMax()
 ///
 /// - Change the title-case of the functions to be consistent. Because this was adapted
 ///     from parts of several different libraries, it isn't very consistently titled.
@@ -380,6 +394,15 @@
 #define MBED_ENCODE_VERSION(major, minor, patch) ((major)*10000 + (minor)*100 + (patch))
 #endif
 
+#if defined(__GNUC__) || defined(__clang__)
+#define DEPRECATED(msg) __attribute__((deprecated(msg)))
+#elif defined(_MSC_VER)
+#define DEPRECATED __declspec(deprecated)
+#else
+#pragma message("WARNING: You need to implement DEPRECATED for this compiler")
+#define DEPRECATED
+#endif
+
 // Define this to enable code that monitors the performance of various
 // graphics commands.
 //#define PERF_METRICS
@@ -391,8 +414,9 @@
 /// @page PredefinedColors Predefined Colors
 ///
 /// Keep in mind that the color scheme shown here is unlikely to precisely match
-/// that on the actual display. The perceived color is additional affected by
-/// other attributes, such as the backlight brightness.
+/// that on the actual display. The perceived color is additionally affected by
+/// other attributes, such as the polarizer, backlight brightness, liquid crystal
+/// fluid properties, viewing angle, and more...
 ///
 /// These are the predefined colors that are typically used where any @ref color_t
 /// variable is applied.
@@ -418,22 +442,28 @@
 /// <td bgcolor='#00FFFF'>&nbsp;</td><td>@ref BrightCyan</td>
 /// </tr>
 /// <tr>
+/// <td bgcolor='#FF0000'>&nbsp;</td><td>@ref BrightRed</td>
 /// <td bgcolor='#FF5555'>&nbsp;</td><td>@ref Orange</td>
 /// <td bgcolor='#FF55FF'>&nbsp;</td><td>@ref Pink</td>
 /// <td bgcolor='#BBBB00'>&nbsp;</td><td>@ref Yellow</td>
-/// <td bgcolor='#FFFFFF'>&nbsp;</td><td>@ref White</td>
 /// </tr>
 /// <tr>
+/// <td bgcolor='#FFFF00'>&nbsp;</td><td>@ref BrightYellow</td>
+/// <td bgcolor='#FFFFFF'>&nbsp;</td><td>@ref White</td>
 /// <td bgcolor='#00003F'>&nbsp;</td><td>@ref DarkBlue </td>
 /// <td bgcolor='#003F00'>&nbsp;</td><td>@ref DarkGreen</td>
-/// <td bgcolor='#003F3F'>&nbsp;</td><td>@ref DarkCyan </td>
-/// <td bgcolor='#3F0000'>&nbsp;</td><td>@ref DarkRed  </td>
 /// </tr>
 /// <tr>
+/// <td bgcolor='#003F3F'>&nbsp;</td><td>@ref DarkCyan </td>
+/// <td bgcolor='#3F0000'>&nbsp;</td><td>@ref DarkRed  </td>
 /// <td bgcolor='#3F003F'>&nbsp;</td><td>@ref DarkMagenta</td>
 /// <td bgcolor='#3F3F00'>&nbsp;</td><td>@ref DarkBrown  </td>
+/// </tr>
+/// <tr>
 /// <td bgcolor='#3F3F3F'>&nbsp;</td><td>@ref DarkGray   </td>
 /// <td bgcolor='#FFFFFF'>&nbsp;</td><td>&nbsp;</td>
+/// <td bgcolor='#FFFFFF'>&nbsp;</td><td>&nbsp;</td>
+/// <td bgcolor='#FFFFFF'>&nbsp;</td><td>&nbsp;</td>
 /// </tr>
 /// </table>
 /// </blockquote>
@@ -550,17 +580,6 @@
         ISO8859_4       ///< ISO8859-4 font
     } font_t;
 
-    /// display orientation argument for @ref SetOrientation()
-    /// with landscape mode as the normal (0 degree) orientation.
-    typedef enum
-    {
-        normal,         ///< normal (landscape) orientation
-        rotate_0 = normal,  ///< alternate to 'normal'
-        rotate_90,      ///< rotated clockwise 90 degree
-        rotate_180,     ///< rotated (clockwise) 180 degree
-        rotate_270,     ///< rotated clockwise 270 degree
-    } orientation_t;
-
     /// alignment control argument for @ref SetTextFontControl()
     typedef enum
     {
@@ -816,10 +835,10 @@
     ///
     /// Typical of the displays that are readily purchased, you will find 480x272 and 800x480 resolutions.
     ///
-    /// @param[in] width in pixels to configure the display for. This parameter is optional
-    ///             and the default is 480.
-    /// @param[in] height in pixels to configure the display for. This parameter is optional
-    ///             and the default is 272.
+    /// @param[in] width in pixels in landscape orientation to configure the display for. 
+    ///             This parameter is optional and the default is 480.
+    /// @param[in] height in pixels in landscape orientation to configure the display for. 
+    ///             This parameter is optional and the default is 272.
     /// @param[in] color_bpp can be either 8 or 16, but must be consistent
     ///             with the width and height parameters. This parameter is optional
     ///             and the default is 16.
@@ -880,12 +899,9 @@
     ///
     /// @param[in] layer is 0 or 1 to select the layer for subsequent
     ///     commands.
-    /// @param[out] prevLayer is an optiona pointer to where the previous layer
-    ///     will be written, making it a little easer to restore layers.
-    ///     Writes 0 or 1 when the pointer is not NULL.
-    /// @returns @ref RetCode_t value.
-    ///
-    virtual RetCode_t SelectDrawingLayer(uint16_t layer, uint16_t * prevLayer = NULL);
+    /// @returns previous drawing layer.
+    ///
+    virtual uint16_t SelectDrawingLayer(uint16_t layer);
 
 
     /// Get the currently active drawing layer.
@@ -928,9 +944,9 @@
     /// @endcode
     ///
     /// @param[in] mode sets the mode in the Layer Transparency Register.
-    /// @returns @ref RetCode_t value.
-    ///
-    RetCode_t SetLayerMode(LayerMode_T mode);
+    /// @returns @ref LayerMode_T as the previous layer value.
+    ///
+    LayerMode_T SetLayerMode(LayerMode_T mode);
 
 
     /// Get the Layer presentation mode.
@@ -971,9 +987,9 @@
     ///
     /// @param[in] color is optional and expressed in 16-bit format. If not
     ///     supplied, a default of Black is used.
-    /// @returns @ref RetCode_t value.
-    ///
-    RetCode_t SetBackgroundTransparencyColor(color_t color = RGB(0,0,0));
+    /// @returns @ref color_t as the previous color value.
+    ///
+    color_t SetBackgroundTransparencyColor(color_t color = RGB(0,0,0));
 
 
     /// Get the background color value used for transparency.
@@ -1258,7 +1274,7 @@
     ///
     ///     // Only if the touch panel is enabled, AND is configured as the resistive
     ///     // panel will the prior command be useful.
-    ///     lcd.init(LCD_W,LCD_H,LCD_C,40, false, true);
+    ///     lcd.init(LCD_PHYS_W,LCD_PHYS_H,LCD_C,40, false, true);
     ///
     /// @endcode
     ///
@@ -1706,9 +1722,9 @@
     ///
     /// @param[in] column is the horizontal position in character positions
     /// @param[in] row is the vertical position in character positions
-    /// @returns @ref RetCode_t value.
-    ///
-    virtual RetCode_t locate(textloc_t column, textloc_t row);
+    /// @returns @ref point_t value that was the last location.
+    ///
+    virtual point_t locate(textloc_t column, textloc_t row);
 
     /// Enable word-wrap in _puts()
     ///
@@ -1732,9 +1748,9 @@
     ///
     /// @param[in] x is the horizontal position in pixels (from the left edge)
     /// @param[in] y is the vertical position in pixels (from the top edge)
-    /// @returns @ref RetCode_t value.
-    ///
-    RetCode_t SetTextCursor(loc_t x, loc_t y);
+    /// @returns @ref point_t value with the prior cursor position.
+    ///
+    point_t SetTextCursor(loc_t x, loc_t y);
 
 
     /// Prepare the controller to write text to the screen by positioning
@@ -1747,9 +1763,9 @@
     /// @endcode
     ///
     /// @param[in] p is the x:y point in pixels from the top-left.
-    /// @returns @ref RetCode_t value.
-    ///
-    RetCode_t SetTextCursor(point_t p);
+    /// @returns @ref point_t value with the prior cursor position.
+    ///
+    point_t SetTextCursor(point_t p);
 
 
     /// Get the current cursor position in pixels.
@@ -1814,9 +1830,9 @@
 
     /// @returns the basic display orientationas an @ref orientation_t value.
     ///
-    orientation_t GetOrientation();
-
-    /// Sets the display orientation.
+    orientation_t GetGraphicsOrientation();
+
+    /// Sets the basic graphics orientation.
     ///
     /// @note This command does not let you "merge" text onto an existing
     ///       image, since it reuses the memory for the new orientation.
@@ -1832,22 +1848,22 @@
     ///
     /// @code
     ///     lcd.cls();
-    ///     lcd.SetOrientation(RA8875::normal);
+    ///     lcd.SetGraphicsOrientation(RA8875::normal);
     ///     lcd.puts(30,30, "Normal Landscape");
     ///     wait_us(2500000);
     ///
     ///     lcd.cls();
-    ///     lcd.SetOrientation(RA8875::rotate_90);
+    ///     lcd.SetGraphicsOrientation(RA8875::rotate_90);
     ///     lcd.puts(30,30, "Rotated 90 Text\r\n");
     ///     wait_us(2500000);
     ///
     ///     lcd.cls();
-    ///     lcd.SetOrientation(RA8875::rotate_180);
+    ///     lcd.SetGraphicsOrientation(RA8875::rotate_180);
     ///     lcd.puts(30,30, "Rotated 180 Text\r\n");
     ///     wait_us(2500000);
     ///
     ///     lcd.cls();
-    ///     lcd.SetOrientation(RA8875::rotate_270);
+    ///     lcd.SetGraphicsOrientation(RA8875::rotate_270);
     ///     lcd.puts(30,30, "Rotated 270 Text\r\n");
     ///     wait_us(2500000);
     /// @endcode
@@ -1859,7 +1875,50 @@
     ///         - rotate_270 (clockwise)
     /// @returns @ref RetCode_t value.
     ///
-    RetCode_t SetOrientation(orientation_t angle = normal);
+    orientation_t SetGraphicsOrientation(orientation_t angle = normal);
+
+    /// Sets the text orientation - Normal or 90 degree.
+    ///
+    /// @attention This command is experimental.
+    ///
+    /// @note This command does not let you "merge" text onto an existing
+    ///       image, since it reuses the memory for the new orientation.
+    ///       Therefore, it is recommended that you issue a cls() prior
+    ///       to sending text to the screen, or you end with a blended
+    ///       image that is probably not as intended.
+    ///
+    /// @note This command only operates on the RA8875 internal fonts.
+    ///
+    /// @code
+    ///     lcd.cls();
+    ///     lcd.SetTextFontOrientation(RA8875::normal);
+    ///     lcd.puts(30,30, "Normal Landscape");
+    ///     wait_us(2500000);
+    ///
+    ///     lcd.cls();
+    ///     lcd.SetTextFontOrientation(RA8875::rotate_90);
+    ///     lcd.puts(30,30, "Rotated 90 Text\r\n");
+    ///     wait_us(2500000);
+    ///
+    ///     lcd.cls();
+    ///     lcd.SetTextFontOrientation(RA8875::rotate_180);
+    ///     lcd.puts(30,30, "Rotated 180 Text\r\n");
+    ///     wait_us(2500000);
+    ///
+    ///     lcd.cls();
+    ///     lcd.SetTextFontOrientation(RA8875::rotate_270);
+    ///     lcd.puts(30,30, "Rotated 270 Text\r\n");
+    ///     wait_us(2500000);
+    /// @endcode
+    ///
+    /// @param[in] angle defaults to normal, but can be rotated
+    ///         - normal | rotate_0
+    ///         - rotate_90 (sets the 90 degree display bit)
+    ///         - rotate_180
+    ///         - rotate_270 (sets the 90 degree display bit)
+    /// @returns @ref RetCode_t value.
+    ///
+    orientation_t SetTextFontOrientation(orientation_t angle);
 
 
     /// Control the font behavior.
@@ -2070,17 +2129,16 @@
     ///
     /// @code
     ///     rect_t r = {10,10, 90,90};
-    ///     lcd.window(r);
+    ///     r = lcd.SetWindow(r);
     ///     lcd.SetTextCursor(r.p1.x, r.p1.y);
     ///     lcd.puts("012345678901234567890123456789012345678901234567890");
-    ///     lcd.window(); restore to full screen
+    ///     lcd.SetWindow(r); restore to previous window setting
     /// @endcode
     ///
     /// @param[in] r is the rect_t used to set the window.
-    /// @returns @ref RetCode_t value.
-    ///
-    virtual RetCode_t window(rect_t r);
-
+    /// @returns the previous window definition.
+    ///
+    rect_t SetWindow(rect_t r);
 
     /// Set the window, constraining where items are written to the screen.
     ///
@@ -2092,25 +2150,31 @@
     /// @note if no parameters are provided, it restores the window to full screen.
     ///
     /// @note If the initial text write is outside the window, it will be shown
-    /// where the cursor position it. Once the write hits the right edge of
+    /// where the cursor positions it. Once the write hits the right edge of
     /// the defined window, it will then wrap back to the left edge. Once it
     /// hits the bottom, it wraps to the top of the window. For this reason,
     /// it is common to set the text cursor to the window.
     ///
     /// @code
-    ///     lcd.window(10,10, 80,80);
+    ///     lcd.SetWindow(10,10, 80,80);
     ///     lcd.SetTextCursor(10,10);
     ///     lcd.puts("012345678901234567890123456789012345678901234567890");
-    ///     lcd.window(); restore to full screen
+    ///     lcd.SetWindow(); restore to full screen
     /// @endcode
     ///
-    /// @param[in] x is the left edge in pixels.
-    /// @param[in] y is the top edge in pixels.
-    /// @param[in] width is the window width in pixels.
-    /// @param[in] height is the window height in pixels.
-    /// @returns @ref RetCode_t value.
-    ///
-    virtual RetCode_t window(loc_t x = 0, loc_t y = 0, dim_t width = (dim_t)-1, dim_t height = (dim_t)-1);
+    /// @param[in] x1 is the left edge in pixels.
+    /// @param[in] y1 is the top edge in pixels.
+    /// @param[in] x2 is the right edge in pixels.
+    /// @param[in] y2 is the bottom edge in pixels.
+    /// @returns the previous window definition.
+    ///
+    virtual rect_t SetWindow(loc_t x1 = 0, loc_t y1 = 0, loc_t x2 = (loc_t)-1, loc_t y2 = (loc_t)-1);
+
+    /// Get the current window setting, which constrains what is written to the screen.
+    ///
+    /// @returns the current window definition.
+    ///
+    virtual rect_t GetWindow();
 
 
     /// Clear either the specified layer, or the active layer.
@@ -2138,10 +2202,10 @@
     ///
     /// The default behavior is to clear the whole screen. With the optional
     /// parameter, the action can be restricted to the active window, which
-    /// can be set with the See @ref window method.
+    /// can be set with the See @ref SetWindow method.
     ///
     /// @code
-    ///     lcd.window(20,20, 40,10);
+    ///     lcd.SetWindow(20,20, 40,10);
     ///     lcd.clsw();
     /// @endcode
     ///
@@ -2155,9 +2219,9 @@
     /// Set the background color.
     ///
     /// @param[in] color is expressed in 16-bit format.
-    /// @returns @ref RetCode_t value.
-    ///
-    virtual RetCode_t background(color_t color);
+    /// @returns @ref color_t value as the previous background color.
+    ///
+    virtual color_t background(color_t color);
 
 
     /// Set the background color.
@@ -2165,17 +2229,17 @@
     /// @param[in] r is the red element of the color.
     /// @param[in] g is the green element of the color.
     /// @param[in] b is the blue element of the color.
-    /// @returns @ref RetCode_t value.
-    ///
-    virtual RetCode_t background(unsigned char r, unsigned char g, unsigned char b);
+    /// @returns @ref color_t value as the previous background color.
+    ///
+    virtual color_t background(unsigned char r, unsigned char g, unsigned char b);
 
 
     /// Set the foreground color.
     ///
     /// @param[in] color is expressed in 16-bit format.
-    /// @returns @ref RetCode_t value.
-    ///
-    virtual RetCode_t foreground(color_t color);
+    /// @returns @ref color_t value as the previous background color.
+    ///
+    virtual color_t foreground(color_t color);
 
 
     /// Set the foreground color.
@@ -2183,9 +2247,9 @@
     /// @param[in] r is the red element of the color.
     /// @param[in] g is the green element of the color.
     /// @param[in] b is the blue element of the color.
-    /// @returns @ref RetCode_t value.
-    ///
-    virtual RetCode_t foreground(unsigned char r, unsigned char g, unsigned char b);
+    /// @returns @ref color_t value as the previous background color.
+    ///
+    virtual color_t foreground(unsigned char r, unsigned char g, unsigned char b);
 
 
     /// Get the current foreground color value.
@@ -2195,6 +2259,13 @@
     color_t GetForeColor(void);
 
 
+    /// Get the current background color value.
+    ///
+    /// @returns the current background color as @ref color_t.
+    ///
+    color_t GetBackColor(void);
+
+
     /// Draw a pixel in the specified color.
     ///
     /// @note Unlike many other operations, this does not
@@ -2825,9 +2896,9 @@
     ///    if (r == noerror) {
     ///        fh = fopen("/local/tpcal.cfg", "wb");
     ///        if (fh) {
-    ///            fwrite(&matrix, sizeof(tpMatrix_t), 1, fh);
-    ///            fclose(fh);
-    ///            printf("  tp cal written.\r\n");
+    ///             fwrite(&matrix, sizeof(tpMatrix_t), 1, fh);
+    ///             fclose(fh);
+    ///             printf("  tp cal written.\r\n");
     ///             lcd.cls();
     ///         } else {
     ///             printf("  couldn't open tpcal file.\r\n");
@@ -2867,7 +2938,7 @@
     ///
     ///     pc.baud(460800);    //I like a snappy terminal, so crank it up!
     ///     pc.printf("\r\nRA8875 BTE Move Test - Build " __DATE__ " " __TIME__ "\r\n");
-    ///     lcd.init(LCD_W,LCD_H,LCD_C, BL_NORM);
+    ///     lcd.init(LCD_PHYS_W,LCD_PHYS_H,LCD_C, BL_NORM);
     ///     lcd.TouchPanelInit();
     ///     #ifndef CAP_TOUCH
     ///     InitTS();   // Calibration for resistive touch panel
@@ -2882,9 +2953,9 @@
     ///             TouchCode_t t = lcd.TouchCode();
     ///
     ///             if (t == touch) {
-    ///                 src = ComputeTopLeftOfRect(xy, RECT_W/2, RECT_H/2, LCD_W, LCD_H);
+    ///                 src = ComputeTopLeftOfRect(xy, RECT_W/2, RECT_H/2, LCD_PHYS_W, LCD_PHYS_H);
     ///             } else if (t == release) {
-    ///                 dst = ComputeTopLeftOfRect(xy, RECT_W/2, RECT_H/2, LCD_W, LCD_H);
+    ///                 dst = ComputeTopLeftOfRect(xy, RECT_W/2, RECT_H/2, LCD_PHYS_W, LCD_PHYS_H);
     ///                 r = lcd.BlockMove(0,0,dst, 0,0,src, RECT_W,RECT_H, 0x2, 0xC);
     ///             }
     ///         }
@@ -3214,7 +3285,7 @@
     ///     ...
     ///     lcd.AttachIdleHandler(myIdle_handler);
     ///     ...
-    ///     RetCode_t r = lcd.PrintScreen(0,0,LCD_W,LCD_H,"/local/print.bmp");
+    ///     RetCode_t r = lcd.PrintScreen(0,0,LCD_PHYS_W,LCD_PHYS_H,"/local/print.bmp");
     ///     if (r ...)
     /// @endcode
     ///
@@ -3274,6 +3345,7 @@
     uint8_t GSL1680_ReadRegU8(uint8_t reg, uint8_t * buf, int count);
     RetCode_t FT5206_Init();
     RetCode_t GSL1680_Init();
+    void ReadResistive();       ///< Analyze the resistive touch
 
     void TouchPanelISR(void);
     uint16_t numberOfTouchPoints;
@@ -3295,23 +3367,11 @@
     InterruptIn * m_irq;
     I2C * m_i2c;
     int m_addr;                 /// I2C Address of the Cap Touch Controller
-    //uint8_t data[2];            /// Transfer data for the I2C interface
 
     bool panelTouched;
 
     ////////////////// Start of Resistive Touch Panel parameters
 
-#if 0
-    /// Resistive Touch Panel register name definitions
-    #define TPCR0   0x70
-    #define TPCR1   0x71
-    #define TPXH    0x72
-    #define TPYH    0x73
-    #define TPXYL   0x74
-    #define INTC1   0xF0
-    #define INTC2   0xF1
-#endif
-
     /// Specify the default settings for the Touch Panel, where different from the chip defaults
     #define TP_MODE_DEFAULT             TP_MODE_AUTO
     #define TP_DEBOUNCE_DEFAULT         TP_DEBOUNCE_ON
@@ -3487,10 +3547,11 @@
 
     // display metrics to avoid lengthy spi read queries
     uint8_t screenbpp;              ///< configured bits per pixel
-    dim_t screenwidth;              ///< configured screen width
-    dim_t screenheight;             ///< configured screen height
-    rect_t windowrect;              ///< window commands are held here for speed of access
-    bool portraitmode;              ///< set true when in portrait mode (w,h are reversed)
+    dim_t virt_screenwidth;         ///< configured screen width cached here for speed of access
+    dim_t virt_screenheight;        ///< configured screen height cached here for speed of access
+    rect_t windowrect;              ///< window rect cached here for speed of access
+    orientation_t screen_orientation;   ///< configured graphic orientation cached here for speed of access
+    orientation_t text_orientation; ///< configured text orientation cached here for speed of access
     bool wordwrap;                  ///< set true when wordwrap is in effect for _puts()
     const unsigned char * font;     ///< reference to an external font somewhere in memory
     uint8_t extFontHeight;          ///< computed from the font table when the user sets the font
@@ -3543,7 +3604,6 @@
     RetCode_t (FPointerDummy::*method_callback)(filecmd_t cmd, uint8_t * buffer, uint16_t size);
     RetCode_t (* idle_callback)(IdleReason_T reason, uint16_t param);
 
-    orientation_t screen_orientation;
     point_t TranslateOrientation(point_t rawPoint);
 };
 
--- a/RA8875_Regs.h	Tue Feb 11 21:51:42 2020 +0000
+++ b/RA8875_Regs.h	Sat Mar 28 15:01:38 2020 +0000
@@ -118,6 +118,7 @@
 
 #define RA8875_DPCR                   0x20
 #define RA8875_FNCR0                  0x21
+
 #define RA8875_FNCR1                  0x22
 #define RA8875_CGSR                   0x23
 #define RA8875_HOFS0                  0x24
--- a/RA8875_Touch.cpp	Tue Feb 11 21:51:42 2020 +0000
+++ b/RA8875_Touch.cpp	Sat Mar 28 15:01:38 2020 +0000
@@ -87,7 +87,6 @@
 {
     if (useTouchPanel == TP_GSL1680) {
         INFO("TouchPanelInit: TP_GSL1680");
-        /// @todo Added support for TP_GSL1680
     } else if (useTouchPanel == TP_FT5206) {
         INFO("TouchPanelInit: TP_FT5206");
         TouchPanelInit();
@@ -241,99 +240,17 @@
  *
  *     Function: TouchPanelReadable()
  *
- *  Description: Given a valid set of calibration factors and a point
- *                value reported by the touch screen, this function
- *                calculates and returns the true (or closest to true)
- *                display point below the spot where the touch screen
- *                was touched.
- *
- *
- *
- *  Argument(s): displayPtr (output) - Pointer to the calculated
- *                                      (true) display point.
- *               screenPtr (input) - Pointer to the reported touch
- *                                    screen point.
- *               matrixPtr (input) - Pointer to calibration factors
- *                                    matrix previously calculated
- *                                    from a call to
- *                                    setCalibrationMatrix()
- *
- *
- *  The function simply solves for Xd and Yd by implementing the
- *   computations required by the translation matrix.
- *
- *                                              /-     -\
- *              /-    -\     /-            -\   |       |
- *              |      |     |              |   |   Xs  |
- *              |  Xd  |     | A    B    C  |   |       |
- *              |      |  =  |              | * |   Ys  |
- *              |  Yd  |     | D    E    F  |   |       |
- *              |      |     |              |   |   1   |
- *              \-    -/     \-            -/   |       |
- *                                              \-     -/
- *
- *  It must be kept brief to avoid consuming CPU cycles.
- *
- *       Return: OK - the display point was correctly calculated
- *                     and its value is in the output argument.
- *               NOT_OK - an error was detected and the function
- *                         failed to return a valid point.
- *
- *                 NOTE!    NOTE!    NOTE!
- *
- *  setCalibrationMatrix() and getDisplayPoint() will do fine
- *  for you as they are, provided that your digitizer
- *  resolution does not exceed 10 bits (1024 values).  Higher
- *  resolutions may cause the integer operations to overflow
- *  and return incorrect values.  If you wish to use these
- *  functions with digitizer resolutions of 12 bits (4096
- *  values) you will either have to a) use 64-bit signed
- *  integer variables and math, or b) judiciously modify the
- *  operations to scale results by a factor of 2 or even 4.
- *
  */
 TouchCode_t RA8875::TouchPanelReadable(point_t * TouchPoint)
 {
     TouchCode_t ts = no_touch;
 
     if (useTouchPanel == TP_FT5206) {
-        INFO("TP_FT5206");
+        //INFO("TP_FT5206");
     } else if (useTouchPanel == TP_GSL1680) {
-        INFO("TP_GSL1680");
+        //INFO("TP_GSL1680");
     } else if (useTouchPanel == TP_RES) {
-        int a2dX = 0;
-        int a2dY = 0;
-
-        touchInfo[0].touchID = 0;
-        ts = TouchPanelA2DFiltered(&a2dX, &a2dY);
-        #ifdef DEBUG
-        static TouchCode_t tsLast;
-        if (tsLast != ts)
-            INFO("ts: %d", ts);
-        tsLast = ts;
-        #endif
-        if (ts != no_touch) {
-            panelTouched = true;
-            numberOfTouchPoints = 1;
-
-            if (tpMatrix.Divider != 0) {
-                /* Operation order is important since we are doing integer */
-                /*  math. Make sure you add all terms together before      */
-                /*  dividing, so that the remainder is not rounded off     */
-                /*  prematurely.                                           */
-                touchInfo[0].coordinates.x = ( (tpMatrix.An * a2dX) +
-                                  (tpMatrix.Bn * a2dY) + tpMatrix.Cn
-                                ) / tpMatrix.Divider ;
-                touchInfo[0].coordinates.y = ( (tpMatrix.Dn * a2dX) +
-                                  (tpMatrix.En * a2dY) + tpMatrix.Fn
-                                ) / tpMatrix.Divider ;
-            } else {
-                ts = no_cal;
-            }
-        } else {
-            numberOfTouchPoints = 0;
-        }
-        touchInfo[0].touchCode = ts;
+        ReadResistive();
     }
     // For Resistive touch, panelTouched is computed above.
     // For Cap Sense, panelTouched is set in another process
@@ -399,27 +316,22 @@
 {
     point_t newPoint = rawPoint;
 
-    #if 1
     switch (screen_orientation) {
         default:
         case rotate_0:
+        case rotate_180:
             newPoint = rawPoint;
             break;
         case rotate_90:
             newPoint.x = rawPoint.y;
-            newPoint.y = height() - rawPoint.x;
-            break;
-        case rotate_180:
-            newPoint.x = width() - rawPoint.x;
-            newPoint.y = height() - rawPoint.y;
+            newPoint.y = rawPoint.x;
             break;
         case rotate_270:
-            newPoint.x = height() - rawPoint.y;
+            newPoint.x = width() - rawPoint.y;
             newPoint.y = rawPoint.x;
             break;
     }
     //INFO("Translate(%3d x %3d) => (%3d x %3d)", rawPoint.x, rawPoint.y, newPoint.x, newPoint.y);
-    #endif
     return newPoint;
 }
 
@@ -475,6 +387,86 @@
     }
 }
 
+
+//  Description: Given a valid set of calibration factors and a point
+//                value reported by the touch screen, this function
+//                calculates and returns the true (or closest to true)
+//                display point below the spot where the touch screen
+//                was touched.
+//
+//  Argument(s): displayPtr (output) - Pointer to the calculated
+//                                      (true) display point.
+//               screenPtr (input) - Pointer to the reported touch
+//                                    screen point.
+//               matrixPtr (input) - Pointer to calibration factors
+//                                    matrix previously calculated
+//                                    from a call to
+//                                    setCalibrationMatrix()
+//
+//  The function simply solves for Xd and Yd by implementing the
+//   computations required by the translation matrix.
+//
+//                                              /-     -\   //
+//              /-    -\     /-            -\   |       |   //
+//              |      |     |              |   |   Xs  |   //
+//              |  Xd  |     | A    B    C  |   |       |   //
+//              |      |  =  |              | * |   Ys  |   //
+//              |  Yd  |     | D    E    F  |   |       |   //
+//              |      |     |              |   |   1   |   //
+//              \-    -/     \-            -/   |       |   //
+//                                              \-     -/   //
+//
+//  It must be kept brief to avoid consuming CPU cycles.
+//
+//       Return: OK - the display point was correctly calculated
+//                     and its value is in the output argument.
+//               NOT_OK - an error was detected and the function
+//                         failed to return a valid point.
+//
+//                 NOTE!    NOTE!    NOTE!
+//
+//  setCalibrationMatrix() and getDisplayPoint() will do fine
+//  for you as they are, provided that your digitizer
+//  resolution does not exceed 10 bits (1024 values).  Higher
+//  resolutions may cause the integer operations to overflow
+//  and return incorrect values.  If you wish to use these
+//  functions with digitizer resolutions of 12 bits (4096
+//  values) you will either have to a) use 64-bit signed
+//  integer variables and math, or b) judiciously modify the
+//  operations to scale results by a factor of 2 or even 4.
+//
+void RA8875::ReadResistive() {
+    TouchCode_t ts = no_touch;
+    int a2dX = 0;
+    int a2dY = 0;
+
+    touchInfo[0].touchID = 0;
+    ts = TouchPanelA2DFiltered(&a2dX, &a2dY);
+    if (ts != no_touch) {
+        panelTouched = true;
+        numberOfTouchPoints = 1;
+
+        if (tpMatrix.Divider != 0) {
+            /* Operation order is important since we are doing integer */
+            /*  math. Make sure you add all terms together before      */
+            /*  dividing, so that the remainder is not rounded off     */
+            /*  prematurely.                                           */
+            touchInfo[0].coordinates.x = ((tpMatrix.An * a2dX) +
+                (tpMatrix.Bn * a2dY) + tpMatrix.Cn
+                ) / tpMatrix.Divider;
+            touchInfo[0].coordinates.y = ((tpMatrix.Dn * a2dX) +
+                (tpMatrix.En * a2dY) + tpMatrix.Fn
+                ) / tpMatrix.Divider;
+        } else {
+            ts = no_cal;
+        }
+    } else {
+        numberOfTouchPoints = 0;
+    }
+    touchInfo[0].touchCode = ts;
+}
+
+
 TouchCode_t RA8875::TouchPanelA2DRaw(int *x, int *y)
 {
     INFO("A2Raw");
@@ -852,13 +844,16 @@
 void RA8875::TouchPanelISR(void)
 {
     if (useTouchPanel == TP_FT5206) {
-        if (FT5206_TouchPositions())
+        if (FT5206_TouchPositions()) {
             panelTouched = true;
+            timeSinceTouch.reset();
+        }
     } else if (useTouchPanel == TP_GSL1680) {
-        if (GSL1680_TouchPositions())
+        if (GSL1680_TouchPositions()) {
             panelTouched = true;
+            timeSinceTouch.reset();
+        }
     }
 }
 
-
 // #### end of touch panel code additions
--- a/RA8875_Touch_FT5206.h	Tue Feb 11 21:51:42 2020 +0000
+++ b/RA8875_Touch_FT5206.h	Sat Mar 28 15:01:38 2020 +0000
@@ -1,6 +1,7 @@
 /// FT5206 Touch Controller definitions
 ///
-/// 
+///
+
 
 #ifndef RA8875_TOUCH_FT5206_H
 #define RA8875_TOUCH_FT5206_H
--- a/TextDisplay.cpp	Tue Feb 11 21:51:42 2020 +0000
+++ b/TextDisplay.cpp	Sat Mar 28 15:01:38 2020 +0000
@@ -9,9 +9,9 @@
 // INFO("Stuff to show %d", var); // new-line is automatically appended
 //
 #if (defined(DEBUG) && !defined(TARGET_LPC11U24))
-#define INFO(x, ...) std::printf("[INF %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
-#define WARN(x, ...) std::printf("[WRN %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
-#define ERR(x, ...)  std::printf("[ERR %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
+#define INFO(x, ...) std::printf("[INF %s %3d] " x "\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
+#define WARN(x, ...) std::printf("[WRN %s %3d] " x "\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
+#define ERR(x, ...)  std::printf("[ERR %s %3d] " x "\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
 #else
 #define INFO(x, ...)
 #define WARN(x, ...)
@@ -72,12 +72,15 @@
     return noerror;
 }
 
-RetCode_t TextDisplay::locate(textloc_t column, textloc_t row)
+point_t TextDisplay::locate(textloc_t column, textloc_t row)
 {
+    point_t oldPt;
+
+    oldPt.x = _column; oldPt.y = _row;
     INFO("locate(%d,%d)", column, row);
     _column = column;
     _row = row;
-    return noerror;
+    return oldPt;
 }
 
 int TextDisplay::_getc()
@@ -85,18 +88,20 @@
     return -1;
 }
 
-RetCode_t TextDisplay::foreground(uint16_t color)
+color_t TextDisplay::foreground(uint16_t color)
 {
+    color_t oldColor = _foreground;
     //INFO("foreground(%4X)", color);
     _foreground = color;
-    return noerror;
+    return oldColor;
 }
 
-RetCode_t TextDisplay::background(uint16_t color)
+color_t TextDisplay::background(uint16_t color)
 {
+    color_t oldColor = _background;
     //INFO("background(%4X)", color);
     _background = color;
-    return noerror;
+    return oldColor;
 }
 
 bool TextDisplay::claim(FILE *stream)
--- a/TextDisplay.h	Tue Feb 11 21:51:42 2020 +0000
+++ b/TextDisplay.h	Sat Mar 28 15:01:38 2020 +0000
@@ -31,7 +31,8 @@
     // functions needing implementation in derived implementation class
     /// Create a TextDisplay interface
     ///
-    /// @param name The name used in the path to access the display through 
+    /// @param name The name used in the path to access the display through
+
     ///     the stdio stream.
     ///
     TextDisplay(const char *name = NULL);
@@ -57,7 +58,8 @@
     ///
     /// @note this method may be overridden in a derived class.
     ///
-    /// @returns number of text rows for the display for the currently 
+    /// @returns number of text rows for the display for the currently
+
     ///     active font.
     ///
     virtual int rows() = 0;
@@ -86,12 +88,14 @@
     ///
     /// @note this method may be overridden in a derived class.
     ///
-    /// @param[in] layers is ignored, but supports maintaining the same 
+    /// @param[in] layers is ignored, but supports maintaining the same
+
     ///     API for the graphics layer.
     /// @returns @ref RetCode_t value.
     ///
     virtual RetCode_t cls(uint16_t layers = 0) = 0;
-    
+   
+
     /// locate the cursor at a character position.
     ///
     /// Based on the currently active font, locate the cursor on screen.
@@ -100,27 +104,28 @@
     ///
     /// @param[in] column is the horizontal offset from the left side.
     /// @param[in] row is the vertical offset from the top.
-    /// @returns @ref RetCode_t value.
+    /// @returns @ref point_t value that was the last location.
     ///
-    virtual RetCode_t locate(textloc_t column, textloc_t row) = 0;
-    
+    virtual point_t locate(textloc_t column, textloc_t row) = 0;
+   
+
     /// set the foreground color
     ///
     /// @note this method may be overridden in a derived class.
     ///
     /// @param[in] color is color to use for foreground drawing.
-    /// @returns @ref RetCode_t value.
+    /// @returns @ref color_t value that was the previous color.
     ///
-    virtual RetCode_t foreground(color_t color) = 0;
+    virtual color_t foreground(color_t color) = 0;
 
     /// set the background color
     ///
     /// @note this method may be overridden in a derived class.
     ///
     /// @param[in] color is color to use for background drawing.
-    /// @returns @ref RetCode_t value.
+    /// @returns @ref color_t value that was the previous color.
     ///
-    virtual RetCode_t background(color_t color) = 0;
+    virtual color_t background(color_t color) = 0;
     // putc (from Stream)
     // printf (from Stream)
 
@@ -131,9 +136,11 @@
     /// @returns the character that was sent.
     ///
     virtual int _putc(int value);
-    
+   
+
     /// a method to get a character from the stdin
-    /// 
+    ///
+
     /// @returns the fetched character.
     ///
     virtual int _getc();