Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
RA8875.cpp
00001 // RA8875 Display Controller Library. 00002 // 00003 // This is being created for a Raio RA8875-based display from buydisplay.com, 00004 // which is either 480 x 272 or 800 x 480, using a 4-wire SPI interface. 00005 // Support is provided for both a keypad and a resistive touch-screen. 00006 // 00007 // See the RA8875.h file for full details. 00008 // 00009 // 20161106: Updated the initialization to set the various registers based on 00010 // the BuyDisplay.com example code. This altered several registers 00011 // for the 800x480 display driver. 00012 // 00013 #include "RA8875.h" 00014 00015 //#include "Utility.h" // private memory manager 00016 #ifndef UTILITY_H 00017 #define swMalloc malloc // use the standard 00018 #define swFree free 00019 #endif 00020 00021 //#define DEBUG "RAIO" 00022 // ... 00023 // INFO("Stuff to show %d", var); // new-line is automatically appended 00024 // 00025 #if (defined(DEBUG) && !defined(TARGET_LPC11U24)) 00026 #define INFO(x, ...) std::printf("[INF %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); 00027 #define WARN(x, ...) std::printf("[WRN %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); 00028 #define ERR(x, ...) std::printf("[ERR %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); 00029 static void HexDump(const char * title, const uint8_t * p, int count) 00030 { 00031 int i; 00032 char buf[100] = "0000: "; 00033 00034 if (*title) 00035 INFO("%s", title); 00036 for (i=0; i<count; ) { 00037 sprintf(buf + strlen(buf), "%02X ", *(p+i)); 00038 if ((++i & 0x0F) == 0x00) { 00039 INFO("%s", buf); 00040 if (i < count) 00041 sprintf(buf, "%04X: ", i); 00042 else 00043 buf[0] = '\0'; 00044 } 00045 } 00046 if (strlen(buf)) 00047 INFO("%s", buf); 00048 } 00049 #else 00050 #define INFO(x, ...) 00051 #define WARN(x, ...) 00052 #define ERR(x, ...) 00053 #define HexDump(a, b, c) 00054 #endif 00055 00056 // Defaults. Users can override this with the init() method. 00057 #define RA8875_DISPLAY_WIDTH 480 00058 #define RA8875_DISPLAY_HEIGHT 272 00059 #define RA8875_COLORDEPTH_BPP 16 /* Not an API */ 00060 00061 #ifdef PERF_METRICS 00062 #define PERFORMANCE_RESET performance.reset() 00063 #define REGISTERPERFORMANCE(a) RegisterPerformance(a) 00064 #define COUNTIDLETIME(a) CountIdleTime(a) 00065 static const char *metricsName[] = { 00066 "Cls", "Pixel", "Pixel Stream", "Boolean Stream", 00067 "Read Pixel", "Read Pixel Stream", 00068 "Line", 00069 "Rectangle", "Rounded Rectangle", 00070 "Triangle", "Circle", "Ellipse" 00071 }; 00072 uint16_t commandsUsed[256]; // track which commands are used with simple counter of number of hits. 00073 #else 00074 #define PERFORMANCE_RESET 00075 #define REGISTERPERFORMANCE(a) 00076 #define COUNTIDLETIME(a) 00077 #endif 00078 00079 // When it is going to poll a register for completion, how many 00080 // uSec should it wait between each polling activity. 00081 #define POLLWAITuSec 10 00082 00083 // Private RawKeyMap for the Keyboard interface 00084 static const uint8_t DefaultKeyMap[22] = { 00085 0, 00086 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 00087 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 00088 255 00089 }; 00090 00091 static const char * ErrMessages[] = { 00092 "noerror", ///< no errors, command completed successfully 00093 "bad parameter", ///< one or more parameters are invalid 00094 "file not found", ///< specified file could not be found 00095 "not bmp format", ///< file is not a .bmp file 00096 "not ico format", ///< file is not a .ico file 00097 "not supported format", ///< file format is not yet supported 00098 "image too big", ///< image is too large for the screen 00099 "not enough ram", ///< could not allocate ram for scanline 00100 "touch cal. timeout", ///< calibration could not complete in time 00101 "external abort", ///< during an idle callback, the user code initiated an abort 00102 }; 00103 00104 typedef struct { 00105 uint8_t b; 00106 uint8_t g; 00107 uint8_t r; 00108 uint8_t a; 00109 } rgbTrio_t; 00110 00111 /// This is defined as a "Web-Safe" color palette of 216 colors. 00112 /// 00113 /// It is defined so it can be emitted into a BMP file as the color palette, and it is then used 00114 /// for downscaling from higher resolution color depth to an 8-bit format. 00115 /// 00116 static const rgbTrio_t WebColorPalette[] = { 00117 {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x33,0xFF}, {0x00,0x00,0x66,0xFF}, {0x00,0x00,0x99,0xFF}, {0x00,0x00,0xCC,0xFF}, {0x00,0x00,0xFF,0xFF}, 00118 {0x00,0x33,0x00,0xFF}, {0x00,0x33,0x33,0xFF}, {0x00,0x33,0x66,0xFF}, {0x00,0x33,0x99,0xFF}, {0x00,0x33,0xCC,0xFF}, {0x00,0x33,0xFF,0xFF}, 00119 {0x00,0x66,0x00,0xFF}, {0x00,0x66,0x33,0xFF}, {0x00,0x66,0x66,0xFF}, {0x00,0x66,0x99,0xFF}, {0x00,0x66,0xCC,0xFF}, {0x00,0x66,0xFF,0xFF}, 00120 {0x00,0x99,0x00,0xFF}, {0x00,0x99,0x33,0xFF}, {0x00,0x99,0x66,0xFF}, {0x00,0x99,0x99,0xFF}, {0x00,0x99,0xCC,0xFF}, {0x00,0x99,0xFF,0xFF}, 00121 {0x00,0xCC,0x00,0xFF}, {0x00,0xCC,0x33,0xFF}, {0x00,0xCC,0x66,0xFF}, {0x00,0xCC,0x99,0xFF}, {0x00,0xCC,0xCC,0xFF}, {0x00,0xCC,0xFF,0xFF}, 00122 {0x00,0xFF,0x00,0xFF}, {0x00,0xFF,0x33,0xFF}, {0x00,0xFF,0x66,0xFF}, {0x00,0xFF,0x99,0xFF}, {0x00,0xFF,0xCC,0xFF}, {0x00,0xFF,0xFF,0xFF}, 00123 {0x33,0x00,0x00,0xFF}, {0x33,0x00,0x33,0xFF}, {0x33,0x00,0x66,0xFF}, {0x33,0x00,0x99,0xFF}, {0x33,0x00,0xCC,0xFF}, {0x33,0x00,0xFF,0xFF}, 00124 {0x33,0x33,0x00,0xFF}, {0x33,0x33,0x33,0xFF}, {0x33,0x33,0x66,0xFF}, {0x33,0x33,0x99,0xFF}, {0x33,0x33,0xCC,0xFF}, {0x33,0x33,0xFF,0xFF}, 00125 {0x33,0x66,0x00,0xFF}, {0x33,0x66,0x33,0xFF}, {0x33,0x66,0x66,0xFF}, {0x33,0x66,0x99,0xFF}, {0x33,0x66,0xCC,0xFF}, {0x33,0x66,0xFF,0xFF}, 00126 {0x33,0x99,0x00,0xFF}, {0x33,0x99,0x33,0xFF}, {0x33,0x99,0x66,0xFF}, {0x33,0x99,0x99,0xFF}, {0x33,0x99,0xCC,0xFF}, {0x33,0x99,0xFF,0xFF}, 00127 {0x33,0xCC,0x00,0xFF}, {0x33,0xCC,0x33,0xFF}, {0x33,0xCC,0x66,0xFF}, {0x33,0xCC,0x99,0xFF}, {0x33,0xCC,0xCC,0xFF}, {0x33,0xCC,0xFF,0xFF}, 00128 {0x33,0xFF,0x00,0xFF}, {0x33,0xFF,0x33,0xFF}, {0x33,0xFF,0x66,0xFF}, {0x33,0xFF,0x99,0xFF}, {0x33,0xFF,0xCC,0xFF}, {0x33,0xFF,0xFF,0xFF}, 00129 {0x66,0x00,0x00,0xFF}, {0x66,0x00,0x33,0xFF}, {0x66,0x00,0x66,0xFF}, {0x66,0x00,0x99,0xFF}, {0x66,0x00,0xCC,0xFF}, {0x66,0x00,0xFF,0xFF}, 00130 {0x66,0x33,0x00,0xFF}, {0x66,0x33,0x33,0xFF}, {0x66,0x33,0x66,0xFF}, {0x66,0x33,0x99,0xFF}, {0x66,0x33,0xCC,0xFF}, {0x66,0x33,0xFF,0xFF}, 00131 {0x66,0x66,0x00,0xFF}, {0x66,0x66,0x33,0xFF}, {0x66,0x66,0x66,0xFF}, {0x66,0x66,0x99,0xFF}, {0x66,0x66,0xCC,0xFF}, {0x66,0x66,0xFF,0xFF}, 00132 {0x66,0x99,0x00,0xFF}, {0x66,0x99,0x33,0xFF}, {0x66,0x99,0x66,0xFF}, {0x66,0x99,0x99,0xFF}, {0x66,0x99,0xCC,0xFF}, {0x66,0x99,0xFF,0xFF}, 00133 {0x66,0xCC,0x00,0xFF}, {0x66,0xCC,0x33,0xFF}, {0x66,0xCC,0x66,0xFF}, {0x66,0xCC,0x99,0xFF}, {0x66,0xCC,0xCC,0xFF}, {0x66,0xCC,0xFF,0xFF}, 00134 {0x66,0xFF,0x00,0xFF}, {0x66,0xFF,0x33,0xFF}, {0x66,0xFF,0x66,0xFF}, {0x66,0xFF,0x99,0xFF}, {0x66,0xFF,0xCC,0xFF}, {0x66,0xFF,0xFF,0xFF}, 00135 {0x99,0x00,0x00,0xFF}, {0x99,0x00,0x33,0xFF}, {0x99,0x00,0x66,0xFF}, {0x99,0x00,0x99,0xFF}, {0x99,0x00,0xCC,0xFF}, {0x99,0x00,0xFF,0xFF}, 00136 {0x99,0x33,0x00,0xFF}, {0x99,0x33,0x33,0xFF}, {0x99,0x33,0x66,0xFF}, {0x99,0x33,0x99,0xFF}, {0x99,0x33,0xCC,0xFF}, {0x99,0x33,0xFF,0xFF}, 00137 {0x99,0x66,0x00,0xFF}, {0x99,0x66,0x33,0xFF}, {0x99,0x66,0x66,0xFF}, {0x99,0x66,0x99,0xFF}, {0x99,0x66,0xCC,0xFF}, {0x99,0x66,0xFF,0xFF}, 00138 {0x99,0x99,0x00,0xFF}, {0x99,0x99,0x33,0xFF}, {0x99,0x99,0x66,0xFF}, {0x99,0x99,0x99,0xFF}, {0x99,0x99,0xCC,0xFF}, {0x99,0x99,0xFF,0xFF}, 00139 {0x99,0xCC,0x00,0xFF}, {0x99,0xCC,0x33,0xFF}, {0x99,0xCC,0x66,0xFF}, {0x99,0xCC,0x99,0xFF}, {0x99,0xCC,0xCC,0xFF}, {0x99,0xCC,0xFF,0xFF}, 00140 {0x99,0xFF,0x00,0xFF}, {0x99,0xFF,0x33,0xFF}, {0x99,0xFF,0x66,0xFF}, {0x99,0xFF,0x99,0xFF}, {0x99,0xFF,0xCC,0xFF}, {0x99,0xFF,0xFF,0xFF}, 00141 {0xCC,0x00,0x00,0xFF}, {0xCC,0x00,0x33,0xFF}, {0xCC,0x00,0x66,0xFF}, {0xCC,0x00,0x99,0xFF}, {0xCC,0x00,0xCC,0xFF}, {0xCC,0x00,0xFF,0xFF}, 00142 {0xCC,0x33,0x00,0xFF}, {0xCC,0x33,0x33,0xFF}, {0xCC,0x33,0x66,0xFF}, {0xCC,0x33,0x99,0xFF}, {0xCC,0x33,0xCC,0xFF}, {0xCC,0x33,0xFF,0xFF}, 00143 {0xCC,0x66,0x00,0xFF}, {0xCC,0x66,0x33,0xFF}, {0xCC,0x66,0x66,0xFF}, {0xCC,0x66,0x99,0xFF}, {0xCC,0x66,0xCC,0xFF}, {0xCC,0x66,0xFF,0xFF}, 00144 {0xCC,0x99,0x00,0xFF}, {0xCC,0x99,0x33,0xFF}, {0xCC,0x99,0x66,0xFF}, {0xCC,0x99,0x99,0xFF}, {0xCC,0x99,0xCC,0xFF}, {0xCC,0x99,0xFF,0xFF}, 00145 {0xCC,0xCC,0x00,0xFF}, {0xCC,0xCC,0x33,0xFF}, {0xCC,0xCC,0x66,0xFF}, {0xCC,0xCC,0x99,0xFF}, {0xCC,0xCC,0xCC,0xFF}, {0xCC,0xCC,0xFF,0xFF}, 00146 {0xCC,0xFF,0x00,0xFF}, {0xCC,0xFF,0x33,0xFF}, {0xCC,0xFF,0x66,0xFF}, {0xCC,0xFF,0x99,0xFF}, {0xCC,0xFF,0xCC,0xFF}, {0xCC,0xFF,0xFF,0xFF}, 00147 {0xFF,0x00,0x00,0xFF}, {0xFF,0x00,0x33,0xFF}, {0xFF,0x00,0x66,0xFF}, {0xFF,0x00,0x99,0xFF}, {0xFF,0x00,0xCC,0xFF}, {0xFF,0x00,0xFF,0xFF}, 00148 {0xFF,0x33,0x00,0xFF}, {0xFF,0x33,0x33,0xFF}, {0xFF,0x33,0x66,0xFF}, {0xFF,0x33,0x99,0xFF}, {0xFF,0x33,0xCC,0xFF}, {0xFF,0x33,0xFF,0xFF}, 00149 {0xFF,0x66,0x00,0xFF}, {0xFF,0x66,0x33,0xFF}, {0xFF,0x66,0x66,0xFF}, {0xFF,0x66,0x99,0xFF}, {0xFF,0x66,0xCC,0xFF}, {0xFF,0x66,0xFF,0xFF}, 00150 {0xFF,0x99,0x00,0xFF}, {0xFF,0x99,0x33,0xFF}, {0xFF,0x99,0x66,0xFF}, {0xFF,0x99,0x99,0xFF}, {0xFF,0x99,0xCC,0xFF}, {0xFF,0x99,0xFF,0xFF}, 00151 {0xFF,0xCC,0x00,0xFF}, {0xFF,0xCC,0x33,0xFF}, {0xFF,0xCC,0x66,0xFF}, {0xFF,0xCC,0x99,0xFF}, {0xFF,0xCC,0xCC,0xFF}, {0xFF,0xCC,0xFF,0xFF}, 00152 {0xFF,0xFF,0x00,0xFF}, {0xFF,0xFF,0x33,0xFF}, {0xFF,0xFF,0x66,0xFF}, {0xFF,0xFF,0x99,0xFF}, {0xFF,0xFF,0xCC,0xFF}, {0xFF,0xFF,0xFF,0xFF}, 00153 00154 {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, 00155 {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, 00156 {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, 00157 {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, 00158 {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, 00159 {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, 00160 {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, 00161 }; 00162 00163 #define sqr(a) ((a) * (a)) 00164 00165 /// Find the nearest color match in the lookup table. 00166 /// 00167 /// The typical process is to find the difference between a given color and each entry in 00168 /// the table. The difference is defined as: 00169 /// diff = sqrt(sqr(r - table[i].r) + sqr(g - table[i].g) + sqr(b - table[i].b)) 00170 /// The square root function is very CPU intensive, especially w/o a floating point unit, 00171 /// so that step is omitted to speed it up a bit. 00172 /// 00173 static int FindNearestWebColor(uint8_t r, uint8_t g, uint8_t b) { 00174 int bestNdx = 0; 00175 float bestDiff = (sqr(r - WebColorPalette[0].r) + sqr(g - WebColorPalette[0].g) + sqr(b - WebColorPalette[0].b)); 00176 for (int i=1; i<216; i++) { 00177 float thisDiff = (sqr(r - WebColorPalette[i].r) + sqr(g - WebColorPalette[i].g) + sqr(b - WebColorPalette[i].b)); 00178 if (thisDiff < bestDiff) { 00179 bestDiff = thisDiff; 00180 bestNdx = i; 00181 } 00182 } 00183 return bestNdx; 00184 } 00185 00186 // Non-Touch, or Resistive Touch when later initialized that way 00187 // 00188 RA8875::RA8875(PinName mosi, PinName miso, PinName sclk, PinName csel, PinName reset, 00189 const char *name) 00190 : GraphicsDisplay(name) 00191 , spi(mosi, miso, sclk) 00192 , cs(csel) 00193 , res(reset) 00194 { 00195 INFO("RA8875"); 00196 touchInfo = (touchInfo_T *)malloc(RESISTIVE_TOUCH_POINTS * sizeof(touchInfo_T)); 00197 if (touchInfo) 00198 useTouchPanel = TP_RES; 00199 else 00200 useTouchPanel = TP_NONE; // unfortnately a silent failure, but unlikely 00201 tpFQFN = NULL; 00202 tpCalMessage = NULL; 00203 m_irq = NULL; 00204 m_i2c = NULL; 00205 m_wake = NULL; 00206 c_callback = NULL; 00207 obj_callback = NULL; 00208 method_callback = NULL; 00209 idle_callback = NULL; 00210 fontScaleX = fontScaleY = 1; 00211 } 00212 00213 // Touch, based on FT5206 Controller Chip 00214 // 00215 RA8875::RA8875(PinName mosi, PinName miso, PinName sclk, PinName csel, PinName reset, 00216 PinName sda, PinName scl, PinName irq, const char * name) 00217 : GraphicsDisplay(name) 00218 , spi(mosi, miso, sclk) 00219 , cs(csel) 00220 , res(reset) 00221 { 00222 INFO("RA8875"); 00223 tpFQFN = NULL; 00224 tpCalMessage = NULL; 00225 m_irq = new InterruptIn(irq); 00226 m_i2c = new I2C(sda, scl); 00227 INFO("m_i2c = %p", m_i2c); 00228 00229 // Cap touch panel config 00230 touchInfo = (touchInfo_T *)malloc(FT5206_TOUCH_POINTS * sizeof(touchInfo_T)); 00231 if (touchInfo) 00232 useTouchPanel = TP_FT5206; 00233 else 00234 useTouchPanel = TP_NONE; // unfortnately a silent failure, but unlikely 00235 m_addr = (FT5206_I2C_ADDRESS << 1); 00236 m_i2c->frequency(FT5206_I2C_FREQUENCY); 00237 m_wake = NULL; // not used for FT5206 00238 00239 c_callback = NULL; 00240 obj_callback = NULL; 00241 method_callback = NULL; 00242 idle_callback = NULL; 00243 fontScaleX = fontScaleY = 1; 00244 00245 // Interrupt 00246 m_irq->mode(PullUp); 00247 #if MBED_VERSION >= MBED_ENCODE_VERSION(5,8,0) 00248 eventThread.start(callback(&queue, &EventQueue::dispatch_forever)); 00249 m_irq->fall(queue.event(callback(this, &RA8875::TouchPanelISR))); 00250 #elif (MBED_MAJOR_VERSION >= 5) || (MBED_LIBRARY_VERSION > 128) // Is this the right version? 00251 m_irq->fall(callback(this, &RA8875::TouchPanelISR)); 00252 #else 00253 m_irq->fall(this, &RA8875::TouchPanelISR); 00254 #endif 00255 m_irq->enable_irq(); 00256 TouchPanelInit(); 00257 INFO("RA8875 end."); 00258 } 00259 00260 00261 // Touch, based on GSL1680 Controller Chip 00262 // 00263 RA8875::RA8875(PinName mosi, PinName miso, PinName sclk, PinName csel, PinName reset, 00264 PinName sda, PinName scl, PinName wake, PinName irq, const char * name) 00265 : GraphicsDisplay(name) 00266 , spi(mosi, miso, sclk) 00267 , cs(csel) 00268 , res(reset) 00269 { 00270 INFO("RA8875"); 00271 tpFQFN = NULL; 00272 tpCalMessage = NULL; 00273 m_irq = new InterruptIn(irq); 00274 m_i2c = new I2C(sda, scl); 00275 00276 // Cap touch panel config 00277 touchInfo = (touchInfo_T *)malloc(FT5206_TOUCH_POINTS * sizeof(touchInfo_T)); 00278 if (touchInfo) 00279 useTouchPanel = TP_GSL1680; 00280 else 00281 useTouchPanel = TP_NONE; // unfortnately a silent failure, but unlikely 00282 m_addr = (GSL1680_I2C_ADDRESS << 1); 00283 m_i2c->frequency(GSL1680_I2C_FREQUENCY); 00284 m_wake = new DigitalOut(wake); 00285 00286 c_callback = NULL; 00287 obj_callback = NULL; 00288 method_callback = NULL; 00289 idle_callback = NULL; 00290 fontScaleX = fontScaleY = 1; 00291 00292 // Interrupt 00293 m_irq->mode(PullUp); 00294 m_irq->enable_irq(); 00295 #if MBED_VERSION >= MBED_ENCODE_VERSION(5,8,0) 00296 eventThread.start(callback(&queue, &EventQueue::dispatch_forever)); 00297 m_irq->fall(queue.event(callback(this, &RA8875::TouchPanelISR))); 00298 #elif (MBED_MAJOR_VERSION >= 5) || (MBED_LIBRARY_VERSION > 128) // Is this the right version? 00299 m_irq->fall(callback(this, &RA8875::TouchPanelISR)); 00300 #else 00301 m_irq->fall(this, &RA8875::TouchPanelISR); 00302 #endif 00303 TouchPanelInit(); 00304 } 00305 00306 00307 00308 //RA8875::~RA8875() 00309 //{ 00310 //} 00311 00312 00313 RetCode_t RA8875::init(int width, int height, int color_bpp, uint8_t poweron, bool keypadon, bool touchscreenon) 00314 { 00315 INFO("RA8875::init()"); 00316 font = NULL; // no external font, use internal. 00317 pKeyMap = DefaultKeyMap; // set default key map 00318 _select(false); // deselect the display 00319 frequency(RA8875_DEFAULT_SPI_FREQ); // data rate 00320 Reset(); 00321 // Set PLL based on display size from buy-display.com sample code 00322 if (width == 800) { 00323 WriteCommand(RA8875_PLLC1, 0x0C); // PLLC1 - Phase Lock Loop registers 00324 } else { 00325 WriteCommand(RA8875_PLLC1, 0x0B); // PLLC1 - Phase Lock Loop registers 00326 } 00327 wait_ms(1); 00328 WriteCommand(RA8875_PLLC2, 0x02); 00329 wait_ms(1); 00330 00331 // System Config Register (SYSR) 00332 screenbpp = color_bpp; 00333 if (color_bpp == 16) { 00334 WriteCommand(RA8875_SYSR, 0x0C); // 16-bpp (65K colors) color depth, 8-bit interface 00335 } else { // color_bpp == 8 00336 WriteCommand(RA8875_SYSR, 0x00); // 8-bpp (256 colors) 00337 } 00338 00339 // Set Pixel Clock Setting Register (PCSR) based on display size from buy-display.com sample code 00340 if (width == 800) { 00341 WriteCommand(RA8875_PCSR, 0x81); // PDAT on PCLK falling edge, PCLK = 4 x System Clock 00342 wait_ms(1); 00343 00344 // Horizontal Settings 00345 screenwidth = width; 00346 WriteCommand(RA8875_HDWR, width/8 - 1); //HDWR//Horizontal Display Width Setting Bit[6:0] 00347 WriteCommand(RA8875_HNDFTR, 0x00); //HNDFCR//Horizontal Non-Display Period fine tune Bit[3:0] 00348 WriteCommand(RA8875_HNDR, 0x03); //HNDR//Horizontal Non-Display Period Bit[4:0] 00349 WriteCommand(RA8875_HSTR, 0x03); //HSTR//HSYNC Start Position[4:0] 00350 WriteCommand(RA8875_HPWR, 0x0B); //HPWR//HSYNC Polarity ,The period width of HSYNC. 00351 00352 // Vertical Settings 00353 screenheight = height; 00354 WriteCommand(RA8875_VDHR0, (height-1)&0xFF); //VDHR0 //Vertical Display Height Bit [7:0] 00355 WriteCommand(RA8875_VDHR1, (height-1)>>8); //VDHR1 //Vertical Display Height Bit [8] 00356 WriteCommand(RA8875_VNDR0, 0x20); //VNDR0 //Vertical Non-Display Period Bit [7:0] 00357 WriteCommand(RA8875_VNDR1, 0x00); //VNDR1 //Vertical Non-Display Period Bit [8] 00358 WriteCommand(RA8875_VSTR0, 0x16); //VSTR0 //VSYNC Start Position[7:0] 00359 WriteCommand(RA8875_VSTR1, 0x00); //VSTR1 //VSYNC Start Position[8] 00360 WriteCommand(RA8875_VPWR, 0x01); //VPWR //VSYNC Polarity ,VSYNC Pulse Width[6:0] 00361 } else { 00362 WriteCommand(RA8875_PCSR, 0x82); // PDAT on PCLK falling edge, PCLK = 4 x System Clock 00363 wait_ms(1); 00364 00365 // Horizontal Settings 00366 screenwidth = width; 00367 WriteCommand(RA8875_HDWR, width/8 - 1); //HDWR//Horizontal Display Width Setting Bit[6:0] 00368 WriteCommand(RA8875_HNDFTR, 0x02); //HNDFCR//Horizontal Non-Display Period fine tune Bit[3:0] 00369 WriteCommand(RA8875_HNDR, 0x03); //HNDR//Horizontal Non-Display Period Bit[4:0] 00370 WriteCommand(RA8875_HSTR, 0x01); //HSTR//HSYNC Start Position[4:0] 00371 WriteCommand(RA8875_HPWR, 0x03); //HPWR//HSYNC Polarity ,The period width of HSYNC. 00372 00373 // Vertical Settings 00374 screenheight = height; 00375 WriteCommand(RA8875_VDHR0, (height-1)&0xFF); //VDHR0 //Vertical Display Height Bit [7:0] 00376 WriteCommand(RA8875_VDHR1, (height-1)>>8); //VDHR1 //Vertical Display Height Bit [8] 00377 WriteCommand(RA8875_VNDR0, 0x0F); //VNDR0 //Vertical Non-Display Period Bit [7:0] 00378 WriteCommand(RA8875_VNDR1, 0x00); //VNDR1 //Vertical Non-Display Period Bit [8] 00379 WriteCommand(RA8875_VSTR0, 0x0e); //VSTR0 //VSYNC Start Position[7:0] 00380 WriteCommand(RA8875_VSTR1, 0x06); //VSTR1 //VSYNC Start Position[8] 00381 WriteCommand(RA8875_VPWR, 0x01); //VPWR //VSYNC Polarity ,VSYNC Pulse Width[6:0] 00382 } 00383 00384 portraitmode = false; 00385 00386 if (width >= 800 && height >= 480 && color_bpp > 8) { 00387 WriteCommand(RA8875_DPCR, 0x00); // DPCR - 1-layer mode when the resolution is too high 00388 } else { 00389 WriteCommand(RA8875_DPCR, 0x80); // DPCR - 2-layer mode 00390 } 00391 00392 // Set display image to Blue on Black as default 00393 window(0,0, width, height); // Initialize to full screen 00394 SetTextCursorControl(); 00395 foreground(Blue); 00396 background(Black); 00397 cls(3); 00398 00399 Power(poweron); 00400 Backlight_u8(poweron); 00401 if (keypadon) 00402 KeypadInit(); 00403 if (touchscreenon) { 00404 if (useTouchPanel == TP_NONE) 00405 useTouchPanel = TP_RES; 00406 if (useTouchPanel == TP_RES) 00407 TouchPanelInit(); // only init again if resistive (due to HW reset applied above). 00408 } 00409 #ifdef PERF_METRICS 00410 performance.start(); 00411 ClearPerformance(); 00412 #endif 00413 INFO("RA8875::init() end"); 00414 return noerror; 00415 } 00416 00417 00418 RetCode_t RA8875::Reset(void) 00419 { 00420 RetCode_t ret; 00421 00422 #if 0 00423 if (res != (PinName)NC) { 00424 res = 0; // Active low - assert reset 00425 wait_ms(2); // must be > 1024 clock periods. (@25 MHz, this is 40.96 usec) 00426 res = 1; // de-assert reset 00427 } 00428 #endif 00429 ret = WriteCommand(RA8875_PWRR, 0x01); // Apply Display Off, Reset 00430 wait_ms(2); // no idea if I need to wait, or how long 00431 if (ret == noerror) { 00432 ret = WriteCommand(RA8875_PWRR, 0x00); // Display off, Remove reset 00433 wait_ms(2); // no idea if I need to wait, or how long 00434 } 00435 return ret; 00436 } 00437 00438 00439 const char * RA8875::GetErrorMessage(RetCode_t code) 00440 { 00441 if (code >= LastErrCode) 00442 code = bad_parameter; 00443 return ErrMessages[code]; 00444 } 00445 00446 00447 uint16_t RA8875::GetDrawingLayer(void) 00448 { 00449 return (ReadCommand(0x41) & 0x01); 00450 } 00451 00452 00453 RetCode_t RA8875::SelectDrawingLayer(uint16_t layer, uint16_t * prevLayer) 00454 { 00455 unsigned char mwcr1 = ReadCommand(0x41); // retain all but the currently selected layer 00456 00457 if (prevLayer) 00458 *prevLayer = mwcr1 & 1; 00459 00460 mwcr1 &= ~0x01; // remove the current layer 00461 if (screenwidth >= 800 && screenheight >= 480 && screenbpp > 8) { 00462 layer = 0; 00463 } else if (layer > 1) { 00464 layer = 0; 00465 } 00466 return WriteCommand(RA8875_MWCR1, mwcr1 | layer); 00467 } 00468 00469 00470 RA8875::LayerMode_T RA8875::GetLayerMode(void) 00471 { 00472 return (LayerMode_T)(ReadCommand(0x52) & 0x7); 00473 } 00474 00475 00476 RetCode_t RA8875::SetLayerMode(LayerMode_T mode) 00477 { 00478 unsigned char ltpr0 = ReadCommand(0x52) & ~0x7; // retain all but the display layer mode 00479 00480 if (mode <= (LayerMode_T)6) { 00481 WriteCommand(RA8875_LTPR0, ltpr0 | (mode & 0x7)); 00482 return noerror; 00483 } else { 00484 return bad_parameter; 00485 } 00486 } 00487 00488 00489 RetCode_t RA8875::SetLayerTransparency(uint8_t layer1, uint8_t layer2) 00490 { 00491 if (layer1 > 8) 00492 layer1 = 8; 00493 if (layer2 > 8) 00494 layer2 = 8; 00495 WriteCommand(RA8875_LTPR1, ((layer2 & 0xF) << 4) | (layer1 & 0xF)); 00496 return noerror; 00497 } 00498 00499 00500 RetCode_t RA8875::SetBackgroundTransparencyColor(color_t color) 00501 { 00502 return _writeColorTrio(0x67, color); 00503 } 00504 00505 00506 color_t RA8875::GetBackgroundTransparencyColor(void) 00507 { 00508 RGBQUAD q; 00509 00510 q.rgbRed = ReadCommand(0x67); 00511 q.rgbGreen = ReadCommand(0x68); 00512 q.rgbBlue = ReadCommand(0x69); 00513 return RGBQuadToRGB16(&q, 0); 00514 } 00515 00516 00517 RetCode_t RA8875::KeypadInit(bool scanEnable, bool longDetect, uint8_t sampleTime, uint8_t scanFrequency, 00518 uint8_t longTimeAdjustment, bool interruptEnable, bool wakeupEnable) 00519 { 00520 uint8_t value = 0; 00521 00522 if (sampleTime > 3 || scanFrequency > 7 || longTimeAdjustment > 3) 00523 return bad_parameter; 00524 value |= (scanEnable) ? 0x80 : 0x00; 00525 value |= (longDetect) ? 0x40 : 0x00; 00526 value |= (sampleTime & 0x03) << 4; 00527 value |= (scanFrequency & 0x07); 00528 WriteCommand(RA8875_KSCR1, value); // KSCR1 - Enable Key Scan (and ignore possibility of an error) 00529 00530 value = 0; 00531 value |= (wakeupEnable) ? 0x80 : 0x00; 00532 value |= (longTimeAdjustment & 0x03) << 2; 00533 WriteCommand(RA8875_KSCR2, value); // KSCR2 - (and ignore possibility of an error) 00534 00535 value = ReadCommand(0xF0); // (and ignore possibility of an error) 00536 value &= ~0x10; 00537 value |= (interruptEnable) ? 0x10 : 0x00; 00538 return WriteCommand(RA8875_INTC1, value); // INT 00539 } 00540 00541 00542 RetCode_t RA8875::SetKeyMap(const uint8_t * CodeList) 00543 { 00544 pKeyMap = CodeList; 00545 return noerror; 00546 } 00547 00548 00549 bool RA8875::readable(void) 00550 { 00551 return (ReadCommand(0xF1) & 0x10); // check KS status - true if kbhit 00552 } 00553 00554 00555 uint8_t RA8875::getc(void) 00556 { 00557 //#define GETC_DEV // for development 00558 #ifdef GETC_DEV 00559 uint8_t keyCode1, keyCode2; 00560 #endif 00561 uint8_t keyCode3; 00562 static uint8_t count = 0; 00563 uint8_t col, row; 00564 uint8_t key; 00565 00566 while (!readable()) { 00567 wait_us(POLLWAITuSec); 00568 // COUNTIDLETIME(POLLWAITuSec); // As it is voluntary to call the getc and pend. Don't tally it. 00569 if (idle_callback) { 00570 if (external_abort == (*idle_callback)(getc_wait, 0)) { 00571 return 0; 00572 } 00573 } 00574 } 00575 // read the key press number 00576 uint8_t keyNumReg = ReadCommand(0xC1) & 0x03; 00577 count++; 00578 switch (keyNumReg) { 00579 case 0x01: // one key 00580 keyCode3 = ReadCommand(0xC2); 00581 #ifdef GETC_DEV 00582 keyCode2 = 0; 00583 keyCode1 = 0; 00584 #endif 00585 break; 00586 case 0x02: // two keys 00587 keyCode3 = ReadCommand(0xC3); 00588 #ifdef GETC_DEV 00589 keyCode2 = ReadCommand(0xC2); 00590 keyCode1 = 0; 00591 #endif 00592 break; 00593 case 0x03: // three keys 00594 keyCode3 = ReadCommand(0xC4); 00595 #ifdef GETC_DEV 00596 keyCode2 = ReadCommand(0xC3); 00597 keyCode1 = ReadCommand(0xC2); 00598 #endif 00599 break; 00600 default: // no keys (key released) 00601 keyCode3 = 0xFF; 00602 #ifdef GETC_DEV 00603 keyCode2 = 0; 00604 keyCode1 = 0; 00605 #endif 00606 break; 00607 } 00608 if (keyCode3 == 0xFF) 00609 key = pKeyMap[0]; // Key value 0 00610 else { 00611 row = (keyCode3 >> 4) & 0x03; 00612 col = (keyCode3 & 7); 00613 key = row * 5 + col + 1; // Keys value 1 - 20 00614 if (key > 21) { 00615 key = 21; 00616 } 00617 key = pKeyMap[key]; 00618 key |= (keyCode3 & 0x80); // combine the key held flag 00619 } 00620 #if GETC_DEV // for Development only 00621 SetTextCursor(0, 20); 00622 printf(" Reg: %02x\r\n", keyNumReg); 00623 printf(" key1: %02x\r\n", keyCode1); 00624 printf(" key2: %02x\r\n", keyCode2); 00625 printf(" key3: %02x\r\n", keyCode3); 00626 printf(" count: %02X\r\n", count); 00627 printf(" key: %02X\r\n", key); 00628 #endif 00629 WriteCommand(RA8875_INTC2, 0x10); // Clear KS status 00630 return key; 00631 } 00632 00633 00634 #ifdef PERF_METRICS 00635 void RA8875::ClearPerformance() 00636 { 00637 int i; 00638 00639 for (i=0; i<METRICCOUNT; i++) 00640 metrics[i] = 0; 00641 idletime_usec = 0; 00642 for (i=0; i<256; i++) 00643 commandsUsed[i] = 0; 00644 } 00645 00646 00647 void RA8875::RegisterPerformance(method_e method) 00648 { 00649 unsigned long elapsed = performance.read_us(); 00650 00651 if (method < METRICCOUNT && elapsed > metrics[method]) 00652 metrics[method] = elapsed; 00653 } 00654 00655 00656 void RA8875::CountIdleTime(uint32_t t) 00657 { 00658 idletime_usec += t; 00659 } 00660 00661 00662 void RA8875::ReportPerformance(Serial & pc) 00663 { 00664 int i; 00665 00666 pc.printf("\r\nPerformance Metrics\r\n"); 00667 for (i=0; i<METRICCOUNT; i++) { 00668 pc.printf("%10d uS %s\r\n", metrics[i], metricsName[i]); 00669 } 00670 pc.printf("%10d uS Idle time polling display for ready.\r\n", idletime_usec); 00671 for (i=0; i<256; i++) { 00672 if (commandsUsed[i]) 00673 pc.printf("Command %02X used %5d times.\r\n", i, commandsUsed[i]); 00674 } 00675 } 00676 #endif 00677 00678 00679 bool RA8875::Intersect(rect_t rect, point_t p) 00680 { 00681 if (p.x >= min(rect.p1.x, rect.p2.x) && p.x <= max(rect.p1.x, rect.p2.x) 00682 && p.y >= min(rect.p1.y, rect.p2.y) && p.y <= max(rect.p1.y, rect.p2.y)) 00683 return true; 00684 else 00685 return false; 00686 } 00687 00688 00689 bool RA8875::Intersect(rect_t rect1, rect_t rect2) 00690 { 00691 #if 1 00692 // If one rectangle is on left side of other 00693 if (max(rect1.p1.x,rect1.p2.x) < min(rect2.p1.x,rect2.p2.x) 00694 || min(rect1.p1.x, rect1.p2.x) > max(rect2.p1.x, rect2.p2.x)) 00695 return false; 00696 // If one rectangle is above other 00697 if (max(rect1.p1.y, rect1.p2.y) < min(rect2.p1.y, rect2.p2.y) 00698 || min(rect1.p1.y, rect1.p2.y) > max(rect2.p1.y, rect2.p2.y)) 00699 return false; 00700 return true; // all that's left is they overlap 00701 #else 00702 point_t bl, tr; 00703 bl.x = rect2.p1.x; 00704 bl.y = rect2.p2.y; 00705 tr.x = rect2.p2.x; 00706 tr.y = rect2.p1.y; 00707 if (Intersect(rect1, rect2.p1) || Intersect(rect1, rect2.p2) 00708 || Intersect(rect1, bl) || Intersect(rect1, tr)) 00709 return true; 00710 else 00711 return false; 00712 #endif 00713 } 00714 00715 00716 bool RA8875::Intersect(rect_t * pRect1, const rect_t * pRect2) 00717 { 00718 if (Intersect(*pRect1, *pRect2)) { 00719 rect_t iSect; 00720 00721 iSect.p1.x = max(min(pRect1->p1.x,pRect1->p2.x),min(pRect2->p1.x,pRect2->p2.x)); 00722 iSect.p1.y = max(min(pRect1->p1.y,pRect1->p2.y),min(pRect2->p1.y,pRect2->p2.y)); 00723 iSect.p2.x = min(max(pRect1->p1.x,pRect1->p2.x),max(pRect2->p1.x,pRect2->p2.x)); 00724 iSect.p2.y = min(max(pRect1->p1.y,pRect1->p2.y),max(pRect2->p1.y,pRect2->p2.y)); 00725 *pRect1 = iSect; 00726 return true; 00727 } else { 00728 return false; 00729 } 00730 } 00731 00732 00733 RetCode_t RA8875::WriteCommandW(uint8_t command, uint16_t data) 00734 { 00735 WriteCommand(command, data & 0xFF); 00736 WriteCommand(command+1, data >> 8); 00737 return noerror; 00738 } 00739 00740 00741 RetCode_t RA8875::WriteCommand(unsigned char command, unsigned int data) 00742 { 00743 #ifdef PERF_METRICS 00744 if (commandsUsed[command] < 65535) 00745 commandsUsed[command]++; 00746 #endif 00747 _select(true); 00748 _spiwrite(0x80); // RS:1 (Cmd/Status), RW:0 (Write) 00749 _spiwrite(command); 00750 if (data <= 0xFF) { // only if in the valid range 00751 _spiwrite(0x00); 00752 _spiwrite(data); 00753 } 00754 _select(false); 00755 return noerror; 00756 } 00757 00758 00759 RetCode_t RA8875::WriteDataW(uint16_t data) 00760 { 00761 _select(true); 00762 _spiwrite(0x00); // RS:0 (Data), RW:0 (Write) 00763 _spiwrite(data & 0xFF); 00764 _spiwrite(data >> 8); 00765 _select(false); 00766 return noerror; 00767 } 00768 00769 00770 RetCode_t RA8875::WriteData(unsigned char data) 00771 { 00772 _select(true); 00773 _spiwrite(0x00); // RS:0 (Data), RW:0 (Write) 00774 _spiwrite(data); 00775 _select(false); 00776 return noerror; 00777 } 00778 00779 00780 unsigned char RA8875::ReadCommand(unsigned char command) 00781 { 00782 WriteCommand(command); 00783 return ReadData(); 00784 } 00785 00786 uint16_t RA8875::ReadCommandW(unsigned char command) 00787 { 00788 WriteCommand(command); 00789 return ReadDataW(); 00790 } 00791 00792 unsigned char RA8875::ReadData(void) 00793 { 00794 unsigned char data; 00795 00796 _select(true); 00797 _spiwrite(0x40); // RS:0 (Data), RW:1 (Read) 00798 data = _spiread(); 00799 _select(false); 00800 return data; 00801 } 00802 00803 00804 uint16_t RA8875::ReadDataW(void) 00805 { 00806 uint16_t data; 00807 00808 _select(true); 00809 _spiwrite(0x40); // RS:0 (Data), RW:1 (Read) 00810 data = _spiread(); 00811 data |= (_spiread() << 8); 00812 _select(false); 00813 return data; 00814 } 00815 00816 00817 unsigned char RA8875::ReadStatus(void) 00818 { 00819 unsigned char data; 00820 00821 _select(true); 00822 _spiwrite(0xC0); // RS:1 (Cmd/Status), RW:1 (Read) (Read STSR) 00823 data = _spiread(); 00824 _select(false); 00825 return data; 00826 } 00827 00828 00829 /// @todo add a timeout and return false, but how long 00830 /// to wait since some operations can be very long. 00831 bool RA8875::_WaitWhileBusy(uint8_t mask) 00832 { 00833 int i = 20000/POLLWAITuSec; // 20 msec max 00834 00835 while (i-- && ReadStatus() & mask) { 00836 wait_us(POLLWAITuSec); 00837 COUNTIDLETIME(POLLWAITuSec); 00838 if (idle_callback) { 00839 if (external_abort == (*idle_callback)(status_wait, 0)) { 00840 return false; 00841 } 00842 } 00843 } 00844 if (i) 00845 return true; 00846 else 00847 return false; 00848 } 00849 00850 00851 /// @todo add a timeout and return false, but how long 00852 /// to wait since some operations can be very long. 00853 bool RA8875::_WaitWhileReg(uint8_t reg, uint8_t mask) 00854 { 00855 int i = 20000/POLLWAITuSec; // 20 msec max 00856 00857 while (i-- && ReadCommand(reg) & mask) { 00858 wait_us(POLLWAITuSec); 00859 COUNTIDLETIME(POLLWAITuSec); 00860 if (idle_callback) { 00861 if (external_abort == (*idle_callback)(command_wait, 0)) { 00862 return false; 00863 } 00864 } 00865 } 00866 if (i) 00867 return true; 00868 else 00869 return false; 00870 } 00871 00872 // RRRR RGGG GGGB BBBB 00873 // 4321 0543 2104 3210 00874 // RRRG GGBB 00875 // 2102 1010 00876 uint8_t RA8875::_cvt16to8(color_t c16) 00877 { 00878 return ((c16 >> 8) & 0xE0) 00879 | ((c16 >> 6) & 0x1C) 00880 | ((c16 >> 3) & 0x03); 00881 } 00882 00883 // RRRG GGBB 00884 // 2102 1010 00885 // RRRR RGGG GGGB BBBB 00886 // 2101 0543 2104 3210 00887 color_t RA8875::_cvt8to16(uint8_t c8) 00888 { 00889 color_t c16; 00890 color_t temp = (color_t)c8; 00891 00892 c16 = ((temp & 0xE0) << 8) 00893 | ((temp & 0xC0) << 5) 00894 | ((temp & 0x1C) << 6) 00895 | ((temp & 0x1C) << 3) 00896 | ((temp & 0x03) << 3) 00897 | ((temp & 0x03) << 1) 00898 | ((temp & 0x03) >> 1); 00899 c16 = (c16 << 8) | (c16 >> 8); 00900 return c16; 00901 } 00902 00903 RetCode_t RA8875::_writeColorTrio(uint8_t regAddr, color_t color) 00904 { 00905 RetCode_t rt = noerror; 00906 00907 if (screenbpp == 16) { 00908 WriteCommand(regAddr+0, (color>>11)); // BGCR0 00909 WriteCommand(regAddr+1, (unsigned char)(color>>5)); // BGCR1 00910 rt = WriteCommand(regAddr+2, (unsigned char)(color)); // BGCR2 00911 } else { 00912 uint8_t r, g, b; 00913 00914 // RRRR RGGG GGGB BBBB RGB 00915 // RRR GGG B B 00916 r = (uint8_t)((color) >> 13); 00917 g = (uint8_t)((color) >> 8); 00918 b = (uint8_t)((color) >> 3); 00919 WriteCommand(regAddr+0, r); // BGCR0 00920 WriteCommand(regAddr+1, g); // BGCR1 00921 rt = WriteCommand(regAddr+2, b); // BGCR2 00922 } 00923 return rt; 00924 } 00925 00926 color_t RA8875::_readColorTrio(uint8_t regAddr) 00927 { 00928 color_t color; 00929 uint8_t r, g, b; 00930 00931 r = ReadCommand(regAddr+0); 00932 g = ReadCommand(regAddr+1); 00933 b = ReadCommand(regAddr+2); 00934 if (screenbpp == 16) { 00935 // 000R RRRR 00GG GGGG 000B BBBB 00936 // RRRR RGGG GGGB BBBB 00937 color = (r & 0x1F) << 11; 00938 color |= (g & 0x3F) << 5; 00939 color |= (b & 0x1F); 00940 } else { 00941 // RRRG GGBB 00942 // RRRR RGGG GGGB BBBB 00943 color = (r & 0x07) << 13; 00944 color |= (g & 0x07) << 8; 00945 color |= (b & 0x03) << 3; 00946 } 00947 return color; 00948 } 00949 00950 00951 dim_t RA8875::fontwidth(void) 00952 { 00953 if (font == NULL) 00954 return (((ReadCommand(0x22) >> 2) & 0x3) + 1) * 8; 00955 else 00956 return extFontWidth; 00957 } 00958 00959 00960 dim_t RA8875::fontheight(void) 00961 { 00962 if (font == NULL) 00963 return (((ReadCommand(0x22) >> 0) & 0x3) + 1) * 16; 00964 else 00965 return extFontHeight; 00966 } 00967 00968 00969 RetCode_t RA8875::locate(textloc_t column, textloc_t row) 00970 { 00971 return SetTextCursor(column * fontwidth(), row * fontheight()); 00972 } 00973 00974 00975 int RA8875::columns(void) 00976 { 00977 return screenwidth / fontwidth(); 00978 } 00979 00980 00981 int RA8875::rows(void) 00982 { 00983 return screenheight / fontheight(); 00984 } 00985 00986 00987 dim_t RA8875::width(void) 00988 { 00989 if (portraitmode) 00990 return screenheight; 00991 else 00992 return screenwidth; 00993 } 00994 00995 00996 dim_t RA8875::height(void) 00997 { 00998 if (portraitmode) 00999 return screenwidth; 01000 else 01001 return screenheight; 01002 } 01003 01004 01005 dim_t RA8875::color_bpp(void) 01006 { 01007 return screenbpp; 01008 } 01009 01010 RetCode_t RA8875::SetTextCursor(point_t p) 01011 { 01012 return SetTextCursor(p.x, p.y); 01013 } 01014 01015 RetCode_t RA8875::SetTextCursor(loc_t x, loc_t y) 01016 { 01017 INFO("SetTextCursor(%d, %d)", x, y); 01018 cursor_x = x; // set these values for non-internal fonts 01019 cursor_y = y; 01020 WriteCommandW(RA8875_FCURXL, x); 01021 WriteCommandW(RA8875_FCURYL, y); 01022 return noerror; 01023 } 01024 01025 point_t RA8875::GetTextCursor(void) 01026 { 01027 point_t p; 01028 01029 p.x = GetTextCursor_X(); 01030 p.y = GetTextCursor_Y(); 01031 return p; 01032 } 01033 01034 loc_t RA8875::GetTextCursor_Y(void) 01035 { 01036 loc_t y; 01037 01038 if (font == NULL) 01039 y = ReadCommand(0x2C) | (ReadCommand(0x2D) << 8); 01040 else 01041 y = cursor_y; 01042 INFO("GetTextCursor_Y = %d", y); 01043 return y; 01044 } 01045 01046 01047 loc_t RA8875::GetTextCursor_X(void) 01048 { 01049 loc_t x; 01050 01051 if (font == NULL) 01052 x = ReadCommand(0x2A) | (ReadCommand(0x2B) << 8); 01053 else 01054 x = cursor_x; 01055 INFO("GetTextCursor_X = %d", x); 01056 return x; 01057 } 01058 01059 01060 RetCode_t RA8875::SetTextCursorControl(cursor_t cursor, bool blink) 01061 { 01062 unsigned char mwcr0 = ReadCommand(0x40) & 0x0F; // retain direction, auto-increase 01063 unsigned char mwcr1 = ReadCommand(0x41) & 0x01; // retain currently selected layer 01064 unsigned char horz = 0; 01065 unsigned char vert = 0; 01066 01067 mwcr0 |= 0x80; // text mode 01068 if (cursor != NOCURSOR) 01069 mwcr0 |= 0x40; // visible 01070 if (blink) 01071 mwcr0 |= 0x20; // blink 01072 WriteCommand(RA8875_MWCR0, mwcr0); // configure the cursor 01073 WriteCommand(RA8875_MWCR1, mwcr1); // close the graphics cursor 01074 WriteCommand(RA8875_BTCR, 0x1f); // The cursor flashing cycle 01075 switch (cursor) { 01076 case IBEAM: 01077 horz = 0x01; 01078 vert = 0x1F; 01079 break; 01080 case UNDER: 01081 horz = 0x07; 01082 vert = 0x01; 01083 break; 01084 case BLOCK: 01085 horz = 0x07; 01086 vert = 0x1F; 01087 break; 01088 case NOCURSOR: 01089 default: 01090 break; 01091 } 01092 WriteCommand(RA8875_CURHS, horz); // The cursor size horz 01093 WriteCommand(RA8875_CURVS, vert); // The cursor size vert 01094 return noerror; 01095 } 01096 01097 01098 RetCode_t RA8875::SetTextFont(RA8875::font_t font) 01099 { 01100 if (/*font >= RA8875::ISO8859_1 && */ font <= RA8875::ISO8859_4) { 01101 WriteCommand(RA8875_FNCR0, (unsigned int)(font)); 01102 return noerror; 01103 } else { 01104 return bad_parameter; 01105 } 01106 } 01107 01108 01109 RetCode_t RA8875::SetOrientation(RA8875::orientation_t angle) 01110 { 01111 uint8_t fncr1Val = ReadCommand(0x22); 01112 uint8_t dpcrVal = ReadCommand(0x20); 01113 01114 fncr1Val &= ~0x10; // remove the old direction bit 01115 dpcrVal &= ~0x0C; // remove the old scan direction bits 01116 switch (angle) { 01117 case RA8875::normal: 01118 //fncr1Val |= 0x10; 01119 //dpcrVal |= 0x00; 01120 portraitmode = false; 01121 break; 01122 case RA8875::rotate_90: 01123 fncr1Val |= 0x10; 01124 dpcrVal |= 0x08; 01125 portraitmode = true; 01126 break; 01127 case RA8875::rotate_180: 01128 //fncr1Val |= 0x00; 01129 dpcrVal |= 0x0C; 01130 portraitmode = false; 01131 break; 01132 case RA8875::rotate_270: 01133 fncr1Val |= 0x10; 01134 dpcrVal |= 0x04; 01135 portraitmode = true; 01136 break; 01137 default: 01138 return bad_parameter; 01139 } 01140 INFO("Orientation: %d, %d", angle, portraitmode); 01141 WriteCommand(RA8875_FNCR1, fncr1Val); 01142 return WriteCommand(RA8875_DPCR, dpcrVal); 01143 } 01144 01145 01146 RetCode_t RA8875::SetTextFontControl(fill_t fillit, 01147 RA8875::HorizontalScale hScale, 01148 RA8875::VerticalScale vScale, 01149 RA8875::alignment_t alignment) 01150 { 01151 if (hScale >= 1 && hScale <= 4 && 01152 vScale >= 1 && vScale <= 4) { 01153 uint8_t fncr1Val = ReadCommand(0x22); 01154 01155 fncr1Val &= ~0x10; // do not disturb the rotate flag 01156 if (alignment == align_full) 01157 fncr1Val |= 0x80; 01158 if (fillit == NOFILL) 01159 fncr1Val |= 0x40; 01160 fncr1Val |= ((hScale - 1) << 2); 01161 fncr1Val |= ((vScale - 1) << 0); 01162 return WriteCommand(RA8875_FNCR1, fncr1Val); 01163 } else { 01164 return bad_parameter; 01165 } 01166 } 01167 01168 01169 RetCode_t RA8875::SetTextFontSize(RA8875::HorizontalScale hScale, RA8875::VerticalScale vScale) 01170 { 01171 unsigned char reg = ReadCommand(0x22); 01172 01173 if (vScale == -1) 01174 vScale = hScale; 01175 if (hScale >= 1 && hScale <= 4 && vScale >= 1 && vScale <= 4) { 01176 fontScaleX = hScale; // save for use with a Soft Font 01177 fontScaleY = vScale; 01178 reg &= 0xF0; // keep the high nibble as is. 01179 reg |= ((hScale - 1) << 2); 01180 reg |= ((vScale - 1) << 0); 01181 WriteCommand(RA8875_FNCR1, reg); 01182 return noerror; 01183 } else { 01184 return bad_parameter; 01185 } 01186 } 01187 01188 RetCode_t RA8875::GetTextFontSize(RA8875::HorizontalScale * hScale, RA8875::VerticalScale * vScale) 01189 { 01190 unsigned char reg = ReadCommand(0x22); 01191 01192 if (hScale) 01193 *hScale = 1 + (reg >> 2) & 0x03; 01194 if (vScale) 01195 *vScale = 1 + reg & 0x03; 01196 return noerror; 01197 } 01198 01199 int RA8875::_putc(int c) 01200 { 01201 if (font == NULL) { 01202 return _internal_putc(c); 01203 } else { 01204 return _external_putc(c); 01205 } 01206 } 01207 01208 01209 01210 // Questions to ponder - 01211 // - if we choose to wrap to the next line, because the character won't fit on the current line, 01212 // should it erase the space to the width of the screen (in case there is leftover junk there)? 01213 // - it currently wraps from the bottom of the screen back to the top. I have pondered what 01214 // it might take to scroll the screen - but haven't thought hard enough about it. 01215 // 01216 int RA8875::_external_putc(int c) 01217 { 01218 if (c) { 01219 if (c == '\r') { 01220 cursor_x = windowrect.p1.x; 01221 } else if (c == '\n') { 01222 cursor_y += extFontHeight; 01223 } else { 01224 dim_t charWidth, charHeight; 01225 const uint8_t * charRecord; 01226 01227 charRecord = getCharMetrics(c, &charWidth, &charHeight); 01228 //int advance = charwidth(c); 01229 INFO("(%d,%d) - (%d,%d):(%d,%d), charWidth: %d '%c", cursor_x, cursor_y, 01230 windowrect.p1.x, windowrect.p1.y, windowrect.p2.x, windowrect.p2.y, 01231 charWidth, c); 01232 if (charRecord) { 01233 //cursor_x += advance; 01234 if (cursor_x + charWidth >= windowrect.p2.x) { 01235 cursor_x = windowrect.p1.x; 01236 cursor_y += charHeight; 01237 } 01238 if (cursor_y + charHeight >= windowrect.p2.y) { 01239 cursor_y = windowrect.p1.y; // @todo Should it scroll? 01240 } 01241 (void)character(cursor_x, cursor_y, c); 01242 cursor_x += charWidth * fontScaleX; 01243 } 01244 } 01245 } 01246 return c; 01247 } 01248 01249 01250 int RA8875::_internal_putc(int c) 01251 { 01252 if (c) { 01253 unsigned char mwcr0; 01254 01255 mwcr0 = ReadCommand(0x40); 01256 if ((mwcr0 & 0x80) == 0x00) { 01257 WriteCommand(RA8875_MWCR0, 0x80 | mwcr0); // Put in Text mode if not already 01258 } 01259 if (c == '\r') { 01260 loc_t x; 01261 x = ReadCommand(0x30) | (ReadCommand(0x31) << 8); // Left edge of active window 01262 WriteCommandW(RA8875_FCURXL, x); 01263 } else if (c == '\n') { 01264 loc_t y; 01265 y = ReadCommand(0x2C) | (ReadCommand(0x2D) << 8); // current y location 01266 y += fontheight(); 01267 if (y >= height()) // @TODO after bottom of active window, then scroll window? 01268 y = 0; 01269 WriteCommandW(RA8875_FCURYL, y); 01270 } else { 01271 WriteCommand(RA8875_MRWC); // RA8875 Internal Fonts 01272 _select(true); 01273 WriteData(c); 01274 _WaitWhileBusy(0x80); 01275 _select(false); 01276 } 01277 } 01278 return c; 01279 } 01280 01281 01282 RetCode_t RA8875::_StartGraphicsStream(void) 01283 { 01284 WriteCommand(RA8875_MWCR0,0x00); // Graphics write mode 01285 WriteCommand(RA8875_MRWC); // Prepare for streaming data 01286 return noerror; 01287 } 01288 01289 01290 RetCode_t RA8875::_EndGraphicsStream(void) 01291 { 01292 return noerror; 01293 } 01294 01295 01296 RetCode_t RA8875::_putp(color_t pixel) 01297 { 01298 WriteDataW((pixel>>8) | (pixel<<8)); 01299 return noerror; 01300 } 01301 01302 01303 void RA8875::puts(loc_t x, loc_t y, const char * string) 01304 { 01305 SetTextCursor(x,y); 01306 puts(string); 01307 } 01308 01309 01310 void RA8875::puts(const char * string) 01311 { 01312 if (font == NULL) { 01313 WriteCommand(RA8875_MWCR0,0x80); // Put in Text mode if internal font 01314 } 01315 if (*string != '\0') { 01316 while (*string) { // @TODO calling individual _putc is slower... optimizations? 01317 _putc(*string++); 01318 } 01319 } 01320 } 01321 01322 01323 RetCode_t RA8875::SetGraphicsCursor(loc_t x, loc_t y) 01324 { 01325 WriteCommandW(RA8875_CURH0, x); 01326 WriteCommandW(RA8875_CURV0, y); 01327 return noerror; 01328 } 01329 01330 RetCode_t RA8875::SetGraphicsCursor(point_t p) 01331 { 01332 return SetGraphicsCursor(p.x, p.y); 01333 } 01334 01335 point_t RA8875::GetGraphicsCursor(void) 01336 { 01337 point_t p; 01338 01339 p.x = ReadCommandW(0x46); 01340 p.y = ReadCommandW(0x48); 01341 return p; 01342 } 01343 01344 RetCode_t RA8875::SetGraphicsCursorRead(loc_t x, loc_t y) 01345 { 01346 WriteCommandW(RA8875_RCURH0, x); 01347 WriteCommandW(RA8875_RCURV0, y); 01348 return noerror; 01349 } 01350 01351 RetCode_t RA8875::window(rect_t r) 01352 { 01353 return window(r.p1.x, r.p1.y, r.p2.x + 1 - r.p1.x, r.p2.y + 1 - r.p1.y); 01354 } 01355 01356 RetCode_t RA8875::window(loc_t x, loc_t y, dim_t width, dim_t height) 01357 { 01358 INFO("window(%d,%d,%d,%d)", x, y, width, height); 01359 if (width == (dim_t)-1) 01360 width = screenwidth - x; 01361 if (height == (dim_t)-1) 01362 height = screenheight - y; 01363 windowrect.p1.x = x; 01364 windowrect.p1.y = y; 01365 windowrect.p2.x = x + width - 1; 01366 windowrect.p2.y = y + height - 1; 01367 GraphicsDisplay::window(x,y, width,height); 01368 WriteCommandW(RA8875_HSAW0, x); 01369 WriteCommandW(RA8875_VSAW0, y); 01370 WriteCommandW(RA8875_HEAW0, (x+width-1)); 01371 WriteCommandW(RA8875_VEAW0, (y+height-1)); 01372 //SetTextCursor(x,y); 01373 //SetGraphicsCursor(x,y); 01374 return noerror; 01375 } 01376 01377 01378 RetCode_t RA8875::cls(uint16_t layers) 01379 { 01380 RetCode_t ret; 01381 01382 INFO("cls()"); 01383 PERFORMANCE_RESET; 01384 if (layers == 0) { 01385 ret = clsw(FULLWINDOW); 01386 } else if (layers > 3) { 01387 ret = bad_parameter; 01388 } else { 01389 uint16_t prevLayer = GetDrawingLayer(); 01390 if (layers & 1) { 01391 SelectDrawingLayer(0); 01392 clsw(FULLWINDOW); 01393 } 01394 if (layers & 2) { 01395 SelectDrawingLayer(1); 01396 clsw(FULLWINDOW); 01397 } 01398 SelectDrawingLayer(prevLayer); 01399 } 01400 ret = SetTextCursor(0,0); 01401 //ret = locate(0,0); 01402 REGISTERPERFORMANCE(PRF_CLS); 01403 return ret; 01404 } 01405 01406 01407 RetCode_t RA8875::clsw(RA8875::Region_t region) 01408 { 01409 INFO("clsw()"); 01410 PERFORMANCE_RESET; 01411 WriteCommand(RA8875_MCLR, (region == ACTIVEWINDOW) ? 0xC0 : 0x80); 01412 if (!_WaitWhileReg(0x8E, 0x80)) { 01413 REGISTERPERFORMANCE(PRF_CLS); 01414 return external_abort; 01415 } 01416 REGISTERPERFORMANCE(PRF_CLS); 01417 return noerror; 01418 } 01419 01420 01421 RetCode_t RA8875::pixel(point_t p, color_t color) 01422 { 01423 return pixel(p.x, p.y, color); 01424 } 01425 01426 RetCode_t RA8875::pixel(point_t p) 01427 { 01428 return pixel(p.x, p.y); 01429 } 01430 01431 RetCode_t RA8875::pixel(loc_t x, loc_t y, color_t color) 01432 { 01433 RetCode_t ret; 01434 01435 PERFORMANCE_RESET; 01436 ret = pixelStream(&color, 1, x,y); 01437 REGISTERPERFORMANCE(PRF_DRAWPIXEL); 01438 return ret; 01439 } 01440 01441 01442 RetCode_t RA8875::pixel(loc_t x, loc_t y) 01443 { 01444 RetCode_t ret; 01445 01446 PERFORMANCE_RESET; 01447 color_t color = GetForeColor(); 01448 ret = pixelStream(&color, 1, x, y); 01449 REGISTERPERFORMANCE(PRF_DRAWPIXEL); 01450 return ret; 01451 } 01452 01453 01454 RetCode_t RA8875::pixelStream(color_t * p, uint32_t count, loc_t x, loc_t y) 01455 { 01456 PERFORMANCE_RESET; 01457 SetGraphicsCursor(x, y); 01458 _StartGraphicsStream(); 01459 _select(true); 01460 _spiwrite(0x00); // Cmd: write data 01461 while (count--) { 01462 if (screenbpp == 16) { 01463 _spiwrite(*p >> 8); 01464 _spiwrite(*p & 0xFF); 01465 } else { 01466 _spiwrite(_cvt16to8(*p)); 01467 } 01468 p++; 01469 } 01470 _select(false); 01471 _EndGraphicsStream(); 01472 REGISTERPERFORMANCE(PRF_PIXELSTREAM); 01473 return(noerror); 01474 } 01475 01476 // With a font scale X = 1, a pixel stream is "abcdefg..." 01477 // With a font scale X = 2, a pixel stream is "aabbccddeeffgg..." 01478 // With a font scale Y = 2, a pixel stream is "abcdefg..." 01479 // "abcdefg..." 01480 // 01481 RetCode_t RA8875::booleanStream(loc_t x, loc_t y, dim_t w, dim_t h, const uint8_t * boolStream) 01482 { 01483 PERFORMANCE_RESET; 01484 const uint8_t * rowStream; 01485 rect_t restore = windowrect; 01486 window(x, y, w * fontScaleX, h * fontScaleY); // Scale from font scale factors 01487 SetGraphicsCursor(x, y); 01488 _StartGraphicsStream(); 01489 _select(true); 01490 _spiwrite(0x00); // Cmd: write data 01491 while (h--) { 01492 for (int dy=0; dy<fontScaleY; dy++) { // Vertical Font Scale Factor 01493 uint8_t pixels = w; 01494 uint8_t bitmask = 0x01; 01495 rowStream = boolStream; 01496 while (pixels) { 01497 uint8_t byte = *rowStream; 01498 //INFO("byte, mask: %02X, %02X", byte, bitmask); 01499 color_t c = (byte & bitmask) ? _foreground : _background; 01500 01501 for (int dx=0; dx<fontScaleX; dx++) { // Horizontal Font Scale Factor 01502 if (screenbpp == 16) { 01503 _spiwrite(c >> 8); 01504 _spiwrite(c & 0xFF); 01505 } else { 01506 _spiwrite(_cvt16to8(c)); 01507 } 01508 } 01509 bitmask <<= 1; 01510 if (pixels > 1 && bitmask == 0) { 01511 bitmask = 0x01; 01512 rowStream++; 01513 } 01514 pixels--; 01515 } 01516 } 01517 boolStream += (rowStream - boolStream + 1); 01518 } 01519 _select(false); 01520 _EndGraphicsStream(); 01521 window(restore); 01522 REGISTERPERFORMANCE(PRF_BOOLSTREAM); 01523 return(noerror); 01524 } 01525 01526 color_t RA8875::getPixel(loc_t x, loc_t y) 01527 { 01528 color_t pixel; 01529 01530 PERFORMANCE_RESET; 01531 WriteCommand(RA8875_MWCR0,0x00); // Graphics write mode 01532 SetGraphicsCursorRead(x, y); 01533 WriteCommand(RA8875_MRWC); 01534 _select(true); 01535 _spiwrite(0x40); // Cmd: read data 01536 _spiwrite(0x00); // dummy read 01537 if (screenbpp == 16) { 01538 pixel = _spiread(); 01539 pixel |= (_spiread() << 8); 01540 } else { 01541 pixel = _cvt8to16(_spiread()); 01542 } 01543 _select(false); 01544 REGISTERPERFORMANCE(PRF_READPIXEL); 01545 return pixel; 01546 } 01547 01548 01549 RetCode_t RA8875::getPixelStream(color_t * p, uint32_t count, loc_t x, loc_t y) 01550 { 01551 color_t pixel; 01552 RetCode_t ret = noerror; 01553 01554 PERFORMANCE_RESET; 01555 ret = WriteCommand(RA8875_MWCR0,0x00); // Graphics write mode 01556 ret = SetGraphicsCursorRead(x, y); 01557 ret = WriteCommand(RA8875_MRWC); 01558 _select(true); 01559 _spiwrite(0x40); // Cmd: read data 01560 _spiwrite(0x00); // dummy read 01561 if (screenbpp == 16) 01562 _spiwrite(0x00); // dummy read is only necessary when in 16-bit mode 01563 while (count--) { 01564 if (screenbpp == 16) { 01565 pixel = _spiread(); 01566 pixel |= (_spiread() << 8); 01567 } else { 01568 pixel = _cvt8to16(_spiread()); 01569 } 01570 *p++ = pixel; 01571 } 01572 _select(false); 01573 REGISTERPERFORMANCE(PRF_READPIXELSTREAM); 01574 return ret; 01575 } 01576 01577 01578 RetCode_t RA8875::line(point_t p1, point_t p2) 01579 { 01580 return line(p1.x, p1.y, p2.x, p2.y); 01581 } 01582 01583 01584 RetCode_t RA8875::line(point_t p1, point_t p2, color_t color) 01585 { 01586 return line(p1.x, p1.y, p2.x, p2.y, color); 01587 } 01588 01589 01590 RetCode_t RA8875::line(loc_t x1, loc_t y1, loc_t x2, loc_t y2, color_t color) 01591 { 01592 foreground(color); 01593 return line(x1,y1,x2,y2); 01594 } 01595 01596 01597 RetCode_t RA8875::line(loc_t x1, loc_t y1, loc_t x2, loc_t y2) 01598 { 01599 PERFORMANCE_RESET; 01600 if (x1 == x2 && y1 == y2) { 01601 pixel(x1, y1); 01602 } else { 01603 WriteCommandW(RA8875_DLHSR0, x1); 01604 WriteCommandW(RA8875_DLVSR0, y1); 01605 WriteCommandW(RA8875_DLHER0, x2); 01606 WriteCommandW(RA8875_DLVER0, y2); 01607 unsigned char drawCmd = 0x00; // Line 01608 WriteCommand(RA8875_DCR, drawCmd); 01609 WriteCommand(RA8875_DCR, 0x80 + drawCmd); // Start drawing. 01610 if (!_WaitWhileReg(0x90, 0x80)) { 01611 REGISTERPERFORMANCE(PRF_DRAWLINE); 01612 return external_abort; 01613 } 01614 } 01615 REGISTERPERFORMANCE(PRF_DRAWLINE); 01616 return noerror; 01617 } 01618 01619 01620 RetCode_t RA8875::ThickLine(point_t p1, point_t p2, dim_t thickness, color_t color) 01621 { 01622 INFO("ThickLine()"); 01623 if (thickness == 1) { 01624 line(p1,p2, color); 01625 } else { 01626 if (p1.x == p2.x) { 01627 // vertical 01628 fillcircle(p1, thickness/2, color); 01629 fillcircle(p2, thickness/2, color); 01630 fillrect(p1.x-thickness/2,p1.y, p2.x+thickness/2,p2.y, color); 01631 } else if (p1.y == p2.y) { 01632 // horizontal 01633 fillcircle(p1, thickness/2, color); 01634 fillcircle(p2, thickness/2, color); 01635 fillrect(p1.x,p1.y-thickness/2, p2.x,p2.y+thickness/2, color); 01636 } else { 01637 // some diagonal, drawn rather slowly with filled circles 01638 // @todo draw the end-points with circles, then draw the diagonal 01639 // with 2 triangles. 01640 #if 1 // New Faster method 01641 //Round-caps 01642 fillcircle(p1, thickness/2, color); 01643 fillcircle(p2, thickness/2, color); 01644 // Compute the perpendicular points to draw the triangles 01645 // + fillTriangle: p1a,p1b,p2a 01646 // / + p1a p1a,p2a,p2b 01647 // + +p1+ . . . . . 01648 // p1b + / . angle 01649 // + . 01650 // . 01651 // 01652 // . + 01653 // / + p2a 01654 // + +p2+ 01655 // p2b + / 01656 // + 01657 point_t pTri[4]; 01658 float slope = (p2.y - p1.y) / (p2.x - p1.x); 01659 slope = -1/slope; 01660 //centerline 01661 //line(p1,p2,color); 01662 float dx = (thickness/2 / sqrt(thickness/2 + (slope * slope))); 01663 float dy = slope * dx; 01664 pTri[0].x = p1.x + dx; 01665 pTri[0].y = p1.y + dy; 01666 pTri[1].x = p1.x - dx; 01667 pTri[1].y = p1.y - dy; 01668 pTri[2].x = p2.x + dx; 01669 pTri[2].y = p2.y + dy; 01670 pTri[3].x = p2.x - dx; 01671 pTri[3].y = p2.y - dy; 01672 filltriangle(pTri[0],pTri[1],pTri[3], color); 01673 filltriangle(pTri[0],pTri[2],pTri[3], color); 01674 #else // old slower method 01675 // Draw with a lot of overlapping circles 01676 int dx = abs(p2.x-p1.x), sx = p1.x<p2.x ? 1 : -1; 01677 int dy = abs(p2.y-p1.y), sy = p1.y<p2.y ? 1 : -1; 01678 int err = (dx>dy ? dx : -dy)/2, e2; 01679 01680 for (;;) { 01681 fillcircle(p1.x, p1.y, thickness/2, color); 01682 if (p1.x==p2.x && p1.y==p2.y) 01683 break; 01684 e2 = err; 01685 if (e2 >-dx) 01686 { err -= dy; p1.x += sx; } 01687 if (e2 < dy) 01688 { err += dx; p1.y += sy; } 01689 } 01690 #endif 01691 } 01692 } 01693 return noerror; 01694 } 01695 01696 01697 // 01698 // Rectangle functions all mostly helpers to the basic rectangle function 01699 // 01700 01701 RetCode_t RA8875::fillrect(rect_t r, color_t color, fill_t fillit) 01702 { 01703 return rect(r.p1.x, r.p1.y, r.p2.x, r.p2.y, color, fillit); 01704 } 01705 01706 RetCode_t RA8875::fillrect(loc_t x1, loc_t y1, loc_t x2, loc_t y2, 01707 color_t color, fill_t fillit) 01708 { 01709 return rect(x1,y1,x2,y2,color,fillit); 01710 } 01711 01712 RetCode_t RA8875::rect(rect_t r, color_t color, fill_t fillit) 01713 { 01714 return rect(r.p1.x, r.p1.y, r.p2.x, r.p2.y, color, fillit); 01715 } 01716 01717 RetCode_t RA8875::rect(loc_t x1, loc_t y1, loc_t x2, loc_t y2, 01718 color_t color, fill_t fillit) 01719 { 01720 foreground(color); 01721 return rect(x1,y1,x2,y2,fillit); 01722 } 01723 01724 RetCode_t RA8875::rect(loc_t x1, loc_t y1, loc_t x2, loc_t y2, 01725 fill_t fillit) 01726 { 01727 RetCode_t ret = noerror; 01728 PERFORMANCE_RESET; 01729 // check for bad_parameter 01730 if (x1 < 0 || x1 >= screenwidth || x2 < 0 || x2 >= screenwidth 01731 || y1 < 0 || y1 >= screenheight || y2 < 0 || y2 >= screenheight) { 01732 ret = bad_parameter; 01733 } else { 01734 if (x1 == x2 && y1 == y2) { 01735 pixel(x1, y1); 01736 } else if (x1 == x2) { 01737 line(x1, y1, x2, y2); 01738 } else if (y1 == y2) { 01739 line(x1, y1, x2, y2); 01740 } else { 01741 WriteCommandW(RA8875_DLHSR0, x1); 01742 WriteCommandW(RA8875_DLVSR0, y1); 01743 WriteCommandW(RA8875_DLHER0, x2); 01744 WriteCommandW(RA8875_DLVER0, y2); 01745 unsigned char drawCmd = 0x10; // Rectangle 01746 if (fillit == FILL) 01747 drawCmd |= 0x20; 01748 WriteCommand(RA8875_DCR, drawCmd); 01749 ret = WriteCommand(RA8875_DCR, 0x80 + drawCmd); // Start drawing. 01750 if (!_WaitWhileReg(0x90, 0x80)) { 01751 REGISTERPERFORMANCE(PRF_DRAWRECTANGLE); 01752 return external_abort; 01753 } 01754 } 01755 } 01756 REGISTERPERFORMANCE(PRF_DRAWRECTANGLE); 01757 return ret; 01758 } 01759 01760 01761 // 01762 // rounded rectangle functions are mostly helpers to the base round rect 01763 // 01764 01765 RetCode_t RA8875::fillroundrect(rect_t r, dim_t radius1, dim_t radius2, color_t color, fill_t fillit) 01766 { 01767 return roundrect(r.p1.x, r.p1.y, r.p2.x, r.p2.y, radius1, radius2, color, fillit); 01768 } 01769 01770 RetCode_t RA8875::fillroundrect(loc_t x1, loc_t y1, loc_t x2, loc_t y2, 01771 dim_t radius1, dim_t radius2, color_t color, fill_t fillit) 01772 { 01773 foreground(color); 01774 return roundrect(x1,y1,x2,y2,radius1,radius2,fillit); 01775 } 01776 01777 RetCode_t RA8875::roundrect(rect_t r, dim_t radius1, dim_t radius2, color_t color, fill_t fillit) 01778 { 01779 return roundrect(r.p1.x, r.p1.y, r.p2.x, r.p2.y, radius1, radius2, color, fillit); 01780 } 01781 01782 RetCode_t RA8875::roundrect(loc_t x1, loc_t y1, loc_t x2, loc_t y2, 01783 dim_t radius1, dim_t radius2, color_t color, fill_t fillit) 01784 { 01785 foreground(color); 01786 return roundrect(x1,y1,x2,y2,radius1,radius2,fillit); 01787 } 01788 01789 01790 RetCode_t RA8875::roundrect(loc_t x1, loc_t y1, loc_t x2, loc_t y2, 01791 dim_t radius1, dim_t radius2, fill_t fillit) 01792 { 01793 RetCode_t ret = noerror; 01794 01795 INFO("roundrect()"); 01796 PERFORMANCE_RESET; 01797 if (x1 < 0 || x1 >= screenwidth || x2 < 0 || x2 >= screenwidth 01798 || y1 < 0 || y1 >= screenheight || y2 < 0 || y2 >= screenheight) { 01799 ret = bad_parameter; 01800 } else if (x1 > x2 || y1 > y2 || (radius1 > (x2-x1)/2) || (radius2 > (y2-y1)/2) ) { 01801 ret = bad_parameter; 01802 } else if (x1 == x2 && y1 == y2) { 01803 pixel(x1, y1); 01804 } else if (x1 == x2) { 01805 line(x1, y1, x2, y2); 01806 } else if (y1 == y2) { 01807 line(x1, y1, x2, y2); 01808 } else { 01809 WriteCommandW(RA8875_DLHSR0, x1); 01810 WriteCommandW(RA8875_DLVSR0, y1); 01811 WriteCommandW(RA8875_DLHER0, x2); 01812 WriteCommandW(RA8875_DLVER0, y2); 01813 WriteCommandW(RA8875_ELLA0, radius1); 01814 WriteCommandW(RA8875_ELLB0, radius2); 01815 // Should not need this... 01816 WriteCommandW(RA8875_DEHR0, 0); 01817 WriteCommandW(RA8875_DEVR0, 0); 01818 unsigned char drawCmd = 0x20; // Rounded Rectangle 01819 if (fillit == FILL) 01820 drawCmd |= 0x40; 01821 WriteCommand(RA8875_ELLIPSE, drawCmd); 01822 WriteCommand(RA8875_ELLIPSE, 0x80 + drawCmd); // Start drawing. 01823 if (!_WaitWhileReg(0xA0, 0x80)) { 01824 REGISTERPERFORMANCE(PRF_DRAWROUNDEDRECTANGLE); 01825 return external_abort; 01826 } 01827 } 01828 REGISTERPERFORMANCE(PRF_DRAWROUNDEDRECTANGLE); 01829 return ret; 01830 } 01831 01832 01833 // 01834 // triangle functions 01835 // 01836 RetCode_t RA8875::filltriangle(point_t p1, point_t p2, point_t p3, color_t color, fill_t fillit) 01837 { 01838 return filltriangle(p1.x,p1.y, p2.x,p2.y, p3.x,p3.y, color, fillit); 01839 } 01840 01841 RetCode_t RA8875::triangle(point_t p1, point_t p2, point_t p3, color_t color, fill_t fillit) 01842 { 01843 return triangle(p1.x,p1.y, p2.x,p2.y, p3.x,p3.y, color, fillit); 01844 } 01845 01846 RetCode_t RA8875::triangle(loc_t x1, loc_t y1, loc_t x2, loc_t y2, 01847 loc_t x3, loc_t y3, color_t color, fill_t fillit) 01848 { 01849 RetCode_t ret; 01850 01851 if (x1 < 0 || x1 >= screenwidth || x2 < 0 || x2 >= screenwidth || x3 < 0 || x3 >= screenwidth 01852 || y1 < 0 || y1 >= screenheight || y2 < 0 || y2 >= screenheight || y3 < 0 || y3 >= screenheight) 01853 ret = bad_parameter; 01854 foreground(color); 01855 ret = triangle(x1,y1,x2,y2,x3,y3,fillit); 01856 return ret; 01857 } 01858 01859 01860 RetCode_t RA8875::filltriangle(loc_t x1, loc_t y1, loc_t x2, loc_t y2, 01861 loc_t x3, loc_t y3, color_t color, fill_t fillit) 01862 { 01863 RetCode_t ret; 01864 01865 foreground(color); 01866 ret = triangle(x1,y1,x2,y2,x3,y3,fillit); 01867 return ret; 01868 } 01869 01870 01871 RetCode_t RA8875::triangle(loc_t x1, loc_t y1 ,loc_t x2, loc_t y2, 01872 loc_t x3, loc_t y3, fill_t fillit) 01873 { 01874 RetCode_t ret = noerror; 01875 01876 INFO("triangle"); 01877 PERFORMANCE_RESET; 01878 if (x1 == x2 && y1 == y2 && x1 == x3 && y1 == y3) { 01879 pixel(x1, y1); 01880 } else { 01881 WriteCommandW(RA8875_DLHSR0, x1); 01882 WriteCommandW(RA8875_DLVSR0, y1); 01883 WriteCommandW(RA8875_DLHER0, x2); 01884 WriteCommandW(RA8875_DLVER0, y2); 01885 WriteCommandW(RA8875_DTPH0, x3); 01886 WriteCommandW(RA8875_DTPV0, y3); 01887 unsigned char drawCmd = 0x01; // Triangle 01888 if (fillit == FILL) 01889 drawCmd |= 0x20; 01890 WriteCommand(RA8875_DCR, drawCmd); 01891 WriteCommand(RA8875_DCR, 0x80 + drawCmd); // Start drawing. 01892 if (!_WaitWhileReg(0x90, 0x80)) { 01893 REGISTERPERFORMANCE(PRF_DRAWTRIANGLE); 01894 return external_abort; 01895 } 01896 } 01897 REGISTERPERFORMANCE(PRF_DRAWTRIANGLE); 01898 return ret; 01899 } 01900 01901 01902 RetCode_t RA8875::circle(point_t p, dim_t radius, 01903 color_t color, fill_t fillit) 01904 { 01905 foreground(color); 01906 return circle(p.x,p.y,radius,fillit); 01907 } 01908 01909 01910 RetCode_t RA8875::fillcircle(point_t p, dim_t radius, 01911 color_t color, fill_t fillit) 01912 { 01913 foreground(color); 01914 return circle(p.x,p.y,radius,fillit); 01915 } 01916 01917 01918 RetCode_t RA8875::circle(point_t p, dim_t radius, fill_t fillit) 01919 { 01920 return circle(p.x,p.y,radius,fillit); 01921 } 01922 01923 01924 RetCode_t RA8875::circle(loc_t x, loc_t y, dim_t radius, 01925 color_t color, fill_t fillit) 01926 { 01927 foreground(color); 01928 return circle(x,y,radius,fillit); 01929 } 01930 01931 01932 RetCode_t RA8875::fillcircle(loc_t x, loc_t y, dim_t radius, 01933 color_t color, fill_t fillit) 01934 { 01935 foreground(color); 01936 return circle(x,y,radius,fillit); 01937 } 01938 01939 01940 RetCode_t RA8875::circle(loc_t x, loc_t y, dim_t radius, fill_t fillit) 01941 { 01942 RetCode_t ret = noerror; 01943 01944 INFO("circle"); 01945 PERFORMANCE_RESET; 01946 if (radius <= 0 || (x - radius) < 0 || (x + radius) > screenwidth 01947 || (y - radius) < 0 || (y + radius) > screenheight) { 01948 ret = bad_parameter; 01949 } else if (radius == 1) { 01950 pixel(x,y); 01951 } else { 01952 WriteCommandW(RA8875_DCHR0, x); 01953 WriteCommandW(RA8875_DCVR0, y); 01954 WriteCommand(RA8875_DCRR, radius & 0xFF); 01955 unsigned char drawCmd = 0x00; // Circle 01956 if (fillit == FILL) 01957 drawCmd |= 0x20; 01958 WriteCommand(RA8875_DCR, drawCmd); 01959 WriteCommand(RA8875_DCR, 0x40 + drawCmd); // Start drawing. 01960 if (!_WaitWhileReg(0x90, 0x40)) { 01961 REGISTERPERFORMANCE(PRF_DRAWCIRCLE); 01962 return external_abort; 01963 } 01964 } 01965 REGISTERPERFORMANCE(PRF_DRAWCIRCLE); 01966 return ret; 01967 } 01968 01969 01970 RetCode_t RA8875::ellipse(loc_t x, loc_t y, dim_t radius1, dim_t radius2, color_t color, fill_t fillit) 01971 { 01972 foreground(color); 01973 return ellipse(x,y,radius1,radius2,fillit); 01974 } 01975 01976 01977 RetCode_t RA8875::fillellipse(loc_t x, loc_t y, dim_t radius1, dim_t radius2, color_t color, fill_t fillit) 01978 { 01979 foreground(color); 01980 return ellipse(x,y,radius1,radius2,fillit); 01981 } 01982 01983 01984 RetCode_t RA8875::ellipse(loc_t x, loc_t y, dim_t radius1, dim_t radius2, fill_t fillit) 01985 { 01986 RetCode_t ret = noerror; 01987 01988 INFO("ellipse"); 01989 PERFORMANCE_RESET; 01990 if (radius1 <= 0 || radius2 <= 0 || (x - radius1) < 0 || (x + radius1) > screenwidth 01991 || (y - radius2) < 0 || (y + radius2) > screenheight) { 01992 ret = bad_parameter; 01993 } else if (radius1 == 1 && radius2 == 1) { 01994 pixel(x, y); 01995 } else { 01996 WriteCommandW(RA8875_DEHR0, x); 01997 WriteCommandW(RA8875_DEVR0, y); 01998 WriteCommandW(RA8875_ELLA0, radius1); 01999 WriteCommandW(RA8875_ELLB0, radius2); 02000 unsigned char drawCmd = 0x00; // Ellipse 02001 if (fillit == FILL) 02002 drawCmd |= 0x40; 02003 WriteCommand(RA8875_ELLIPSE, drawCmd); 02004 WriteCommand(RA8875_ELLIPSE, 0x80 + drawCmd); // Start drawing. 02005 if (!_WaitWhileReg(0xA0, 0x80)) { 02006 REGISTERPERFORMANCE(PRF_DRAWELLIPSE); 02007 return external_abort; 02008 } 02009 } 02010 REGISTERPERFORMANCE(PRF_DRAWELLIPSE); 02011 return ret; 02012 } 02013 02014 02015 RetCode_t RA8875::frequency(unsigned long Hz, unsigned long Hz2) 02016 { 02017 spiwritefreq = Hz; 02018 if (Hz2 != 0) 02019 spireadfreq = Hz2; 02020 else 02021 spireadfreq = Hz/2; 02022 _setWriteSpeed(true); 02023 // __ ___ 02024 // Clock ___A Rising edge latched 02025 // ___ ____ 02026 // Data ___X____ 02027 spi.format(8, 3); // 8 bits and clock to data phase 0 02028 return noerror; 02029 } 02030 02031 void RA8875::_setWriteSpeed(bool writeSpeed) 02032 { 02033 if (writeSpeed) { 02034 spi.frequency(spiwritefreq); 02035 spiWriteSpeed = true; 02036 } else { 02037 spi.frequency(spireadfreq); 02038 spiWriteSpeed = false; 02039 } 02040 } 02041 02042 02043 02044 RetCode_t RA8875::BlockMove(uint8_t dstLayer, uint8_t dstDataSelect, point_t dstPoint, 02045 uint8_t srcLayer, uint8_t srcDataSelect, point_t srcPoint, 02046 dim_t bte_width, dim_t bte_height, 02047 uint8_t bte_op_code, uint8_t bte_rop_code) 02048 { 02049 uint8_t cmd; 02050 02051 PERFORMANCE_RESET; 02052 ///@todo range check and error return rather than to secretly fix 02053 srcPoint.x &= 0x3FF; // prevent high bits from doing unexpected things 02054 srcPoint.y &= 0x1FF; 02055 dstPoint.x &= 0x3FF; 02056 dstPoint.y &= 0x1FF; 02057 WriteCommandW(RA8875_HSBE0, srcPoint.x); 02058 WriteCommandW(RA8875_VSBE0, ((dim_t)(srcLayer & 1) << 15) | srcPoint.y); 02059 WriteCommandW(RA8875_HDBE0, dstPoint.x); 02060 WriteCommandW(RA8875_VDBE0, ((dim_t)(dstLayer & 1) << 15) | dstPoint.y); 02061 WriteCommandW(RA8875_BEWR0, bte_width); 02062 WriteCommandW(RA8875_BEHR0, bte_height); 02063 WriteCommand(RA8875_BECR1, ((bte_rop_code & 0x0F) << 4) | (bte_op_code & 0x0F)); 02064 cmd = ((srcDataSelect & 1) << 6) | ((dstDataSelect & 1) << 5); 02065 WriteCommand(RA8875_BECR0, 0x80 | cmd); // enable the BTE 02066 if (!_WaitWhileBusy(0x40)) { 02067 REGISTERPERFORMANCE(PRF_BLOCKMOVE); 02068 return external_abort; 02069 } 02070 REGISTERPERFORMANCE(PRF_BLOCKMOVE); 02071 return noerror; 02072 } 02073 02074 02075 RetCode_t RA8875::Power(bool on) 02076 { 02077 WriteCommand(RA8875_PWRR, (on) ? 0x80 : 0x00); 02078 return noerror; 02079 } 02080 02081 02082 RetCode_t RA8875::Backlight_u8(uint8_t brightness) 02083 { 02084 static bool is_enabled = false; 02085 02086 if (brightness == 0) { 02087 WriteCommand(RA8875_P1CR); // Disable the PWM 02088 WriteData(0x00); 02089 is_enabled = false; 02090 } else if (!is_enabled) { 02091 WriteCommand(RA8875_P1CR); // Enable the PWM 02092 WriteData(0x80); 02093 WriteCommand(RA8875_P1CR); // Not sure why this is needed, but following the pattern 02094 WriteData(0x81); // open PWM (SYS_CLK / 2 as best I can tell) 02095 is_enabled = true; 02096 } 02097 WriteCommand(RA8875_P1DCR, brightness); // Brightness parameter 0xff-0x00 02098 return noerror; 02099 } 02100 02101 uint8_t RA8875::GetBacklight_u8(void) 02102 { 02103 return ReadCommand(0x8b); 02104 } 02105 02106 RetCode_t RA8875::Backlight(float brightness) 02107 { 02108 unsigned char b; 02109 02110 if (brightness >= 1.0) 02111 b = 255; 02112 else if (brightness <= 0.0) 02113 b = 0; 02114 else 02115 b = (unsigned char)(brightness * 255); 02116 return Backlight_u8(b); 02117 } 02118 02119 float RA8875::GetBacklight(void) 02120 { 02121 return (float)(GetBacklight_u8())/255; 02122 } 02123 02124 RetCode_t RA8875::SelectUserFont(const uint8_t * _font) 02125 { 02126 INFO("SelectUserFont(%p)", _font); 02127 if (_font) { 02128 HexDump("Font Memory", _font, 16); 02129 extFontHeight = _font[6]; 02130 uint32_t totalWidth = 0; 02131 uint16_t firstChar = _font[3] * 256 + _font[2]; 02132 uint16_t lastChar = _font[5] * 256 + _font[4]; 02133 uint16_t i; 02134 02135 for (i=firstChar; i<=lastChar; i++) { 02136 // 8 bytes of preamble to the first level lookup table 02137 uint16_t offsetToCharLookup = 8 + 4 * (i - firstChar); // 4-bytes: width(pixels), 16-bit offset from table start, 0 02138 totalWidth += _font[offsetToCharLookup]; 02139 } 02140 extFontWidth = totalWidth / (lastChar - firstChar); 02141 INFO("Font Metrics: Avg W: %2d, H: %2d, First:%d, Last:%d", extFontWidth, extFontHeight, firstChar, lastChar); 02142 } 02143 SetTextCursor(GetTextCursor_X(), GetTextCursor_Y()); // soft-font cursor -> hw cursor 02144 font = _font; 02145 return GraphicsDisplay::SelectUserFont(_font); 02146 } 02147 02148 RetCode_t RA8875::background(color_t color) 02149 { 02150 GraphicsDisplay::background(color); 02151 return _writeColorTrio(0x60, color); 02152 } 02153 02154 02155 RetCode_t RA8875::background(unsigned char r, unsigned char g, unsigned char b) 02156 { 02157 background(RGB(r,g,b)); 02158 return noerror; 02159 } 02160 02161 02162 RetCode_t RA8875::foreground(color_t color) 02163 { 02164 GraphicsDisplay::foreground(color); 02165 return _writeColorTrio(0x63, color); 02166 } 02167 02168 02169 RetCode_t RA8875::foreground(unsigned char r, unsigned char g, unsigned char b) 02170 { 02171 foreground(RGB(r,g,b)); 02172 return noerror; 02173 } 02174 02175 02176 color_t RA8875::GetForeColor(void) 02177 { 02178 return _readColorTrio(0x63); 02179 } 02180 02181 02182 color_t RA8875::DOSColor(int i) 02183 { 02184 const color_t colors[16] = { 02185 Black, Blue, Green, Cyan, 02186 Red, Magenta, Brown, Gray, 02187 Charcoal, BrightBlue, BrightGreen, BrightCyan, 02188 Orange, Pink, Yellow, White 02189 }; 02190 if (i >= 0 && i < 16) 02191 return colors[i]; 02192 else 02193 return 0; 02194 } 02195 02196 02197 const char * RA8875::DOSColorNames(int i) 02198 { 02199 const char * names[16] = { 02200 "Black", "Blue", "Green", "Cyan", 02201 "Red", "Magenta", "Brown", "Gray", 02202 "Charcoal", "BrightBlue", "BrightGreen", "BrightCyan", 02203 "Orange", "Pink", "Yellow", "White" 02204 }; 02205 if (i >= 0 && i < 16) 02206 return names[i]; 02207 else 02208 return NULL; 02209 } 02210 02211 02212 /////////////////////////////////////////////////////////////// 02213 // Private functions 02214 02215 unsigned char RA8875::_spiwrite(unsigned char data) 02216 { 02217 unsigned char retval; 02218 02219 if (!spiWriteSpeed) 02220 _setWriteSpeed(true); 02221 retval = spi.write(data); 02222 return retval; 02223 } 02224 02225 02226 unsigned char RA8875::_spiread(void) 02227 { 02228 unsigned char retval; 02229 unsigned char data = 0; 02230 02231 if (spiWriteSpeed) 02232 _setWriteSpeed(false); 02233 retval = spi.write(data); 02234 return retval; 02235 } 02236 02237 02238 RetCode_t RA8875::_select(bool chipsel) 02239 { 02240 cs = (chipsel == true) ? 0 : 1; 02241 return noerror; 02242 } 02243 02244 02245 RetCode_t RA8875::PrintScreen(uint16_t layer, loc_t x, loc_t y, dim_t w, dim_t h, const char *Name_BMP) 02246 { 02247 (void)layer; 02248 02249 // AttachPrintHandler(this, RA8875::_printCallback); 02250 // return PrintScreen(x,y,w,h); 02251 return PrintScreen(x, y, w, h, Name_BMP); 02252 } 02253 02254 RetCode_t RA8875::_printCallback(RA8875::filecmd_t cmd, uint8_t * buffer, uint16_t size) 02255 { 02256 HexDump("CB", buffer, size); 02257 switch(cmd) { 02258 case RA8875::OPEN: 02259 //pc.printf("About to write %lu bytes\r\n", *(uint32_t *)buffer); 02260 _printFH = fopen("file.bmp", "w+b"); 02261 if (_printFH == 0) 02262 return file_not_found; 02263 break; 02264 case RA8875::WRITE: 02265 //pc.printf(" Write %4u bytes\r\n", size); 02266 fwrite(buffer, 1, size, _printFH); 02267 break; 02268 case RA8875::CLOSE: 02269 //pc.printf(" close\r\n"); 02270 fclose(_printFH); 02271 _printFH = 0; 02272 break; 02273 default: 02274 //pc.printf("Unexpected callback %d\r\n", cmd); 02275 return file_not_found; 02276 //break; 02277 } 02278 return noerror; 02279 } 02280 02281 int RA8875::RoundUp(int value, int roundTo) 02282 { 02283 if (roundTo == 0) 02284 return 0; 02285 return ((value + roundTo - 1) / roundTo) * roundTo; 02286 } 02287 02288 RetCode_t RA8875::PrintScreen(loc_t x, loc_t y, dim_t w, dim_t h, uint8_t bitsPerPixel) 02289 { 02290 BITMAPFILEHEADER BMP_Header; 02291 BITMAPINFOHEADER BMP_Info; 02292 uint8_t * lineBuffer = NULL; 02293 color_t * pixelBuffer = NULL; 02294 color_t * pixelBuffer2 = NULL; 02295 02296 INFO("(%d,%d)-(%d,%d)x%d", x,y,w,h,bitsPerPixel); 02297 if (x >= 0 && x < screenwidth 02298 && y >= 0 && y < screenheight 02299 && w > 0 && x + w <= screenwidth 02300 && h > 0 && y + h <= screenheight) { 02301 BMP_Header.bfType = BF_TYPE; 02302 BMP_Header.bfReserved1 = 0; 02303 BMP_Header.bfReserved2 = 0; 02304 switch (bitsPerPixel) { 02305 case 24: 02306 BMP_Header.bfOffBits = sizeof(BMP_Header) + sizeof(BMP_Info); 02307 BMP_Header.bfSize = (h * RoundUp(w * sizeof(RGBQUAD),4)) + BMP_Header.bfOffBits; 02308 break; 02309 case 8: 02310 default: 02311 BMP_Header.bfOffBits = sizeof(BMP_Header) + sizeof(BMP_Info) + sizeof(WebColorPalette); 02312 INFO("Initial Offset to Bitstream %X", BMP_Header.bfOffBits); 02313 //if (BMP_Header.bfOffBits & 0x03) { 02314 // BMP_Header.bfOffBits += (4 - (BMP_Header.bfOffBits & 0x03)); 02315 //} 02316 BMP_Header.bfSize = (h * RoundUp(w * 1,4)) + BMP_Header.bfOffBits; 02317 break; 02318 } 02319 INFO("Offset to Bitstream %X", BMP_Header.bfOffBits); 02320 02321 // Bytes in the line buffer 02322 int lineBufSize = RoundUp(((bitsPerPixel == 24) ? 3 : 1) * w, 4); 02323 INFO("LineBufSize: %d", lineBufSize); 02324 02325 BMP_Info.biSize = sizeof(BMP_Info); 02326 BMP_Info.biWidth = w; 02327 BMP_Info.biHeight = h; 02328 BMP_Info.biPlanes = 1; 02329 BMP_Info.biBitCount = bitsPerPixel; 02330 BMP_Info.biCompression = BI_RGB; 02331 BMP_Info.biSizeImage = lineBufSize * h; 02332 BMP_Info.biXPelsPerMeter = 0; 02333 BMP_Info.biYPelsPerMeter = 0; 02334 // for 24-bit, there is no palette, so these are zero 02335 // for 8-bit, there can be up to 256 RGB values in the palette 02336 02337 BMP_Info.biClrUsed = (bitsPerPixel == 24) ? 0 : sizeof(WebColorPalette)/sizeof(WebColorPalette[0]); // for 8b/pixel 02338 BMP_Info.biClrImportant = BMP_Info.biClrUsed; 02339 02340 // Allocate the memory we need to proceed 02341 lineBuffer = (uint8_t *)swMalloc(lineBufSize); 02342 if (lineBuffer == NULL) { 02343 ERR("Not enough RAM for PrintScreen lineBuffer"); 02344 return(not_enough_ram); 02345 } 02346 memset(lineBuffer, 0, lineBufSize); // zero-Fill 02347 02348 #define DOUBLEBUF /* one larger buffer instead of two */ 02349 02350 #ifdef DOUBLEBUF 02351 // In the "#else", pixelBuffer2 malloc returns a value, 02352 // but is actually causing a failure later. 02353 // This test helps determine if it is truly out of memory, 02354 // or if malloc is broken. 02355 pixelBuffer = (color_t *)swMalloc(2 * w * sizeof(color_t)); 02356 pixelBuffer2 = pixelBuffer + (w * sizeof(color_t)); 02357 #else 02358 pixelBuffer = (color_t *)swMalloc(w * sizeof(color_t)); 02359 pixelBuffer2 = (color_t *)swMalloc(w * sizeof(color_t)); 02360 #endif 02361 if (pixelBuffer == NULL || pixelBuffer2 == NULL) { 02362 ERR("Not enough RAM for pixelBuffer"); 02363 #ifndef DOUBLEBUF 02364 if (pixelBuffer2) 02365 swFree(pixelBuffer2); 02366 #endif 02367 if (pixelBuffer) 02368 swFree(pixelBuffer); 02369 swFree(lineBuffer); 02370 return(not_enough_ram); 02371 } 02372 02373 // Get the file primed... 02374 /// @todo check return value for possibility of a fatal error 02375 privateCallback(OPEN, (uint8_t *)&BMP_Header.bfSize, 4); 02376 02377 // Be optimistic - don't check for errors. 02378 HexDump("BMP_Header", (uint8_t *)&BMP_Header, sizeof(BMP_Header)); 02379 //fwrite(&BMP_Header, sizeof(char), sizeof(BMP_Header), Image); 02380 privateCallback(WRITE, (uint8_t *)&BMP_Header, sizeof(BMP_Header)); 02381 02382 HexDump("BMP_Info", (uint8_t *)&BMP_Info, sizeof(BMP_Info)); 02383 //fwrite(&BMP_Info, sizeof(char), sizeof(BMP_Info), Image); 02384 privateCallback(WRITE, (uint8_t *)&BMP_Info, sizeof(BMP_Info)); 02385 if (bitsPerPixel != 24) { 02386 HexDump("Palette", (uint8_t *)&WebColorPalette, sizeof(WebColorPalette)); 02387 //fwrite(&WebColorPalette, sizeof(char), sizeof(WebColorPalette), Image); 02388 privateCallback(WRITE, (uint8_t *)&WebColorPalette, sizeof(WebColorPalette)); 02389 if (0 && sizeof(WebColorPalette) % 4) { 02390 const uint8_t padd[] = { 0, 0, 0 }; 02391 //fwrite(&padd, sizeof(char), (sizeof(BMP_Header) + sizeof(BMP_Info) + sizeof(WebColorPalette)) % 4, Image); 02392 privateCallback(WRITE, (uint8_t *)&padd, (sizeof(BMP_Header) + sizeof(BMP_Info) + sizeof(WebColorPalette)) % 4); 02393 } 02394 } 02395 //color_t transparency = GetBackgroundTransparencyColor(); 02396 LayerMode_T ltpr0 = GetLayerMode(); 02397 02398 uint16_t prevLayer = GetDrawingLayer(); 02399 // If only one of the layers is visible, select that layer 02400 switch(ltpr0) { 02401 case ShowLayer0: 02402 SelectDrawingLayer(0); 02403 break; 02404 case ShowLayer1: 02405 SelectDrawingLayer(1); 02406 break; 02407 default: 02408 break; 02409 } 02410 02411 // Read the display from the last line toward the top 02412 // so we can write the file in one pass. 02413 for (int j = h - 1; j >= 0; j--) { 02414 if (idle_callback) { 02415 (*idle_callback)(progress, (h - 1 - j) * 100 / (h - 1)); 02416 } 02417 02418 if (ltpr0 >= 2) // Need to combine the layers... 02419 SelectDrawingLayer(0); // so read layer 0 first 02420 // Read one line of pixels to a local buffer 02421 if (getPixelStream(pixelBuffer, w, x,y+j) != noerror) { 02422 ERR("getPixelStream error, and no recovery handler..."); 02423 } 02424 if (ltpr0 >= 2) { // Need to combine the layers... 02425 SelectDrawingLayer(1); // so read layer 1 next 02426 if (getPixelStream(pixelBuffer2, w, x,y+j) != noerror) { 02427 ERR("getPixelStream error, and no recovery handler..."); 02428 } 02429 } 02430 INFO("Line: %3d", j); 02431 //HexDump("Raster", (uint8_t *)pixelBuffer, w * sizeof(color_t)); 02432 // Convert the local buffer to RGBQUAD format 02433 int lb = 0; 02434 for (int i=0; i<w; i++) { 02435 color_t tColor = pixelBuffer[x+i]; 02436 tColor = (tColor >> 8) | (tColor << 8); // Byte Swap 02437 RGBQUAD q0 = RGB16ToRGBQuad(tColor); // Scale to 24-bits 02438 tColor = pixelBuffer2[x+i]; 02439 tColor = (tColor >> 8) | (tColor << 8); // Byte Swap 02440 RGBQUAD q1 = RGB16ToRGBQuad(tColor); // Scale to 24-bits 02441 switch (ltpr0) { 02442 case 0: 02443 case 1: 02444 case 2: // lighten-overlay (@TODO Not supported yet) 02445 case 6: // Floating Windows (@TODO not sure how to support) 02446 default: // Reserved... 02447 //lineBuffer[lb++] = q0.rgbBlue; 02448 //lineBuffer[lb++] = q0.rgbGreen; 02449 //lineBuffer[lb++] = q0.rgbRed; 02450 break; 02451 case 3: // transparent mode (@TODO Read the background color register for transparent) 02452 case 4: // boolean or 02453 q0.rgbBlue = q0.rgbBlue | q1.rgbBlue; 02454 q0.rgbGreen = q0.rgbGreen | q1.rgbGreen; 02455 q0.rgbRed = q0.rgbRed | q1.rgbRed; 02456 break; 02457 case 5: // boolean AND 02458 q0.rgbBlue = q0.rgbBlue & q1.rgbBlue; 02459 q0.rgbGreen = q0.rgbGreen & q1.rgbGreen; 02460 q0.rgbRed = q0.rgbRed & q1.rgbRed; 02461 break; 02462 } 02463 switch (bitsPerPixel) { 02464 case 24: 02465 lineBuffer[lb++] = q0.rgbBlue; 02466 lineBuffer[lb++] = q0.rgbGreen; 02467 lineBuffer[lb++] = q0.rgbRed; 02468 break; 02469 case 8: 02470 default: 02471 lineBuffer[lb++] = FindNearestWebColor(q0.rgbRed,q0.rgbGreen,q0.rgbBlue); 02472 break; 02473 } 02474 } 02475 //if (j == h - 1) { 02476 // HexDump("Line", lineBuffer, lineBufSize); 02477 //} 02478 // Write to disk 02479 privateCallback(WRITE, (uint8_t *)lineBuffer, lineBufSize); 02480 } 02481 SelectDrawingLayer(prevLayer); 02482 privateCallback(CLOSE, NULL, 0); 02483 #ifndef DOUBLEBUF 02484 if (pixelBuffer2) 02485 swFree(pixelBuffer2); 02486 #endif 02487 if (pixelBuffer) 02488 swFree(pixelBuffer); 02489 swFree(lineBuffer); 02490 INFO("Image closed"); 02491 return noerror; 02492 } else { 02493 return bad_parameter; 02494 } 02495 } 02496 02497 02498 02499 RetCode_t RA8875::PrintScreen(loc_t x, loc_t y, dim_t w, dim_t h, const char *Name_BMP, uint8_t bitsPerPixel) 02500 { 02501 BITMAPFILEHEADER BMP_Header; 02502 BITMAPINFOHEADER BMP_Info; 02503 uint8_t * lineBuffer = NULL; 02504 color_t * pixelBuffer = NULL; 02505 color_t * pixelBuffer2 = NULL; 02506 02507 INFO("(%d,%d)-(%d,%d)x%d %s", x,y,w,h,bitsPerPixel,Name_BMP); 02508 if (x >= 0 && x < screenwidth 02509 && y >= 0 && y < screenheight 02510 && w > 0 && x + w <= screenwidth 02511 && h > 0 && y + h <= screenheight) { 02512 BMP_Header.bfType = BF_TYPE; 02513 BMP_Header.bfReserved1 = 0; 02514 BMP_Header.bfReserved2 = 0; 02515 switch (bitsPerPixel) { 02516 case 24: 02517 BMP_Header.bfOffBits = sizeof(BMP_Header) + sizeof(BMP_Info); 02518 BMP_Header.bfSize = (h * RoundUp(w * sizeof(RGBQUAD),4)) + BMP_Header.bfOffBits; 02519 break; 02520 case 8: 02521 default: 02522 BMP_Header.bfOffBits = sizeof(BMP_Header) + sizeof(BMP_Info) + sizeof(WebColorPalette); 02523 INFO("Initial Offset to Bitstream %X", BMP_Header.bfOffBits); 02524 //if (BMP_Header.bfOffBits & 0x03) { 02525 // BMP_Header.bfOffBits += (4 - (BMP_Header.bfOffBits & 0x03)); 02526 //} 02527 BMP_Header.bfSize = (h * RoundUp(w * 1,4)) + BMP_Header.bfOffBits; 02528 break; 02529 } 02530 INFO("Offset to Bitstream %X", BMP_Header.bfOffBits); 02531 02532 // Bytes in the line buffer 02533 int lineBufSize = RoundUp(((bitsPerPixel == 24) ? 3 : 1) * w, 4); 02534 INFO("LineBufSize: %d", lineBufSize); 02535 02536 BMP_Info.biSize = sizeof(BMP_Info); 02537 BMP_Info.biWidth = w; 02538 BMP_Info.biHeight = h; 02539 BMP_Info.biPlanes = 1; 02540 BMP_Info.biBitCount = bitsPerPixel; 02541 BMP_Info.biCompression = BI_RGB; 02542 BMP_Info.biSizeImage = lineBufSize * h; 02543 BMP_Info.biXPelsPerMeter = 0; 02544 BMP_Info.biYPelsPerMeter = 0; 02545 // for 24-bit, there is no palette, so these are zero 02546 // for 8-bit, there can be up to 256 RGB values in the palette 02547 02548 BMP_Info.biClrUsed = (bitsPerPixel == 24) ? 0 : sizeof(WebColorPalette)/sizeof(WebColorPalette[0]); // for 8b/pixel 02549 BMP_Info.biClrImportant = BMP_Info.biClrUsed; 02550 02551 // Allocate the memory we need to proceed 02552 lineBuffer = (uint8_t *)swMalloc(lineBufSize); 02553 if (lineBuffer == NULL) { 02554 ERR("Not enough RAM for PrintScreen lineBuffer"); 02555 return(not_enough_ram); 02556 } 02557 memset(lineBuffer, 0, lineBufSize); // zero-Fill 02558 02559 #define DOUBLEBUF /* one larger buffer instead of two */ 02560 02561 #ifdef DOUBLEBUF 02562 // In the "#else", pixelBuffer2 malloc returns a value, 02563 // but is actually causing a failure later. 02564 // This test helps determine if it is truly out of memory, 02565 // or if malloc is broken. 02566 pixelBuffer = (color_t *)swMalloc(2 * w * sizeof(color_t)); 02567 pixelBuffer2 = pixelBuffer + (w * sizeof(color_t)); 02568 #else 02569 pixelBuffer = (color_t *)swMalloc(w * sizeof(color_t)); 02570 pixelBuffer2 = (color_t *)swMalloc(w * sizeof(color_t)); 02571 #endif 02572 if (pixelBuffer == NULL || pixelBuffer2 == NULL) { 02573 ERR("Not enough RAM for pixelBuffer"); 02574 #ifndef DOUBLEBUF 02575 if (pixelBuffer2) 02576 swFree(pixelBuffer2); 02577 #endif 02578 if (pixelBuffer) 02579 swFree(pixelBuffer); 02580 swFree(lineBuffer); 02581 return(not_enough_ram); 02582 } 02583 02584 FILE *Image = fopen(Name_BMP, "wb"); 02585 if (!Image) { 02586 ERR("Can't open file for write"); 02587 #ifndef DOUBLEBUF 02588 if (pixelBuffer2) 02589 swFree(pixelBuffer2); 02590 #endif 02591 if (pixelBuffer) 02592 swFree(pixelBuffer); 02593 swFree(lineBuffer); 02594 return(file_not_found); 02595 } 02596 02597 // Be optimistic - don't check for errors. 02598 HexDump("BMP_Header", (uint8_t *)&BMP_Header, sizeof(BMP_Header)); 02599 fwrite(&BMP_Header, sizeof(char), sizeof(BMP_Header), Image); 02600 02601 HexDump("BMP_Info", (uint8_t *)&BMP_Info, sizeof(BMP_Info)); 02602 fwrite(&BMP_Info, sizeof(char), sizeof(BMP_Info), Image); 02603 02604 if (bitsPerPixel != 24) { 02605 HexDump("Palette", (uint8_t *)&WebColorPalette, sizeof(WebColorPalette)); 02606 fwrite(&WebColorPalette, sizeof(char), sizeof(WebColorPalette), Image); 02607 if (0 && sizeof(WebColorPalette) % 4) { 02608 const uint8_t padd[] = { 0, 0, 0 }; 02609 fwrite(&padd, sizeof(char), 02610 (sizeof(BMP_Header) + sizeof(BMP_Info) + sizeof(WebColorPalette)) % 4, Image); 02611 } 02612 } 02613 //color_t transparency = GetBackgroundTransparencyColor(); 02614 LayerMode_T ltpr0 = GetLayerMode(); 02615 02616 uint16_t prevLayer = GetDrawingLayer(); 02617 // If only one of the layers is visible, select that layer 02618 switch(ltpr0) { 02619 case ShowLayer0: 02620 SelectDrawingLayer(0); 02621 break; 02622 case ShowLayer1: 02623 SelectDrawingLayer(1); 02624 break; 02625 default: 02626 break; 02627 } 02628 02629 // Read the display from the last line toward the top 02630 // so we can write the file in one pass. 02631 for (int j = h - 1; j >= 0; j--) { 02632 if (idle_callback) { 02633 (*idle_callback)(progress, (h - 1 - j) * 100 / (h - 1)); 02634 } 02635 02636 if (ltpr0 >= 2) // Need to combine the layers... 02637 SelectDrawingLayer(0); // so read layer 0 first 02638 // Read one line of pixels to a local buffer 02639 if (getPixelStream(pixelBuffer, w, x,y+j) != noerror) { 02640 ERR("getPixelStream error, and no recovery handler..."); 02641 } 02642 if (ltpr0 >= 2) { // Need to combine the layers... 02643 SelectDrawingLayer(1); // so read layer 1 next 02644 if (getPixelStream(pixelBuffer2, w, x,y+j) != noerror) { 02645 ERR("getPixelStream error, and no recovery handler..."); 02646 } 02647 } 02648 INFO("Line: %3d", j); 02649 //HexDump("Raster", (uint8_t *)pixelBuffer, w * sizeof(color_t)); 02650 // Convert the local buffer to RGBQUAD format 02651 int lb = 0; 02652 for (int i=0; i<w; i++) { 02653 color_t tColor = pixelBuffer[x+i]; 02654 tColor = (tColor >> 8) | (tColor << 8); // Byte Swap 02655 RGBQUAD q0 = RGB16ToRGBQuad(tColor); // Scale to 24-bits 02656 tColor = pixelBuffer2[x+i]; 02657 tColor = (tColor >> 8) | (tColor << 8); // Byte Swap 02658 RGBQUAD q1 = RGB16ToRGBQuad(tColor); // Scale to 24-bits 02659 switch (ltpr0) { 02660 case 0: 02661 case 1: 02662 case 2: // lighten-overlay (@TODO Not supported yet) 02663 case 6: // Floating Windows (@TODO not sure how to support) 02664 default: // Reserved... 02665 //lineBuffer[lb++] = q0.rgbBlue; 02666 //lineBuffer[lb++] = q0.rgbGreen; 02667 //lineBuffer[lb++] = q0.rgbRed; 02668 break; 02669 case 3: // transparent mode (@TODO Read the background color register for transparent) 02670 case 4: // boolean or 02671 q0.rgbBlue = q0.rgbBlue | q1.rgbBlue; 02672 q0.rgbGreen = q0.rgbGreen | q1.rgbGreen; 02673 q0.rgbRed = q0.rgbRed | q1.rgbRed; 02674 break; 02675 case 5: // boolean AND 02676 q0.rgbBlue = q0.rgbBlue & q1.rgbBlue; 02677 q0.rgbGreen = q0.rgbGreen & q1.rgbGreen; 02678 q0.rgbRed = q0.rgbRed & q1.rgbRed; 02679 break; 02680 } 02681 switch (bitsPerPixel) { 02682 case 24: 02683 lineBuffer[lb++] = q0.rgbBlue; 02684 lineBuffer[lb++] = q0.rgbGreen; 02685 lineBuffer[lb++] = q0.rgbRed; 02686 break; 02687 case 8: 02688 default: 02689 lineBuffer[lb++] = FindNearestWebColor(q0.rgbRed,q0.rgbGreen,q0.rgbBlue); 02690 break; 02691 } 02692 } 02693 //if (j == h - 1) { 02694 // HexDump("Line", lineBuffer, lineBufSize); 02695 //} 02696 // Write to disk 02697 fwrite(lineBuffer, sizeof(char), lineBufSize, Image); 02698 } 02699 SelectDrawingLayer(prevLayer); 02700 fclose(Image); 02701 #ifndef DOUBLEBUF 02702 if (pixelBuffer2) 02703 swFree(pixelBuffer2); 02704 #endif 02705 if (pixelBuffer) 02706 swFree(pixelBuffer); 02707 swFree(lineBuffer); 02708 INFO("Image closed"); 02709 return noerror; 02710 } else { 02711 return bad_parameter; 02712 } 02713 } 02714 02715 02716 // ########################################################################## 02717 // ########################################################################## 02718 // ########################################################################## 02719 02720 #ifdef TESTENABLE 02721 02722 #include "BPG_Arial08x08.h" 02723 #include "BPG_Arial20x20.h" 02724 02725 // ______________ ______________ ______________ _______________ 02726 // /_____ _____/ / ___________/ / ___________/ /_____ ______/ 02727 // / / / / / / / / 02728 // / / / /___ / /__________ / / 02729 // / / / ____/ /__________ / / / 02730 // / / / / / / / / 02731 // / / / /__________ ___________/ / / / 02732 // /__/ /_____________/ /_____________/ /__/ 02733 // 02734 // Everything from here down is test code. 02735 // 02736 bool SuppressSlowStuff = false; 02737 02738 void TextWrapTest(RA8875 & display, Serial & pc) 02739 { 02740 if (!SuppressSlowStuff) 02741 pc.printf("Text Wrap Test\r\n"); 02742 display.background(Black); 02743 display.foreground(Blue); 02744 display.cls(); 02745 display.Backlight_u8(255); 02746 display.puts("Text Wrap Test.\r\n"); 02747 for (int i=1; i<60; i++) { 02748 display.printf("L%2d\n", i % 17); 02749 if (!SuppressSlowStuff) 02750 wait_ms(100); 02751 } 02752 if (!SuppressSlowStuff) 02753 wait_ms(3000); 02754 } 02755 02756 02757 void ShowKey(RA8875 & display, int key) 02758 { 02759 loc_t col, row; 02760 dim_t r1 = 25; 02761 color_t color = (key & 0x80) ? Red : Green; 02762 02763 key &= 0x7F; // remove the long-press flag 02764 row = (key - 1) / 5; 02765 col = (key - 1) % 5; 02766 if (col > 5) col = 5; 02767 if (row > 4) row = 4; 02768 display.circle(450 - + (2 * r1) * col, 200 - (2 * r1) * row, r1-2, color, FILL); 02769 } 02770 02771 void HideKey(RA8875 & display, int key) 02772 { 02773 loc_t col, row; 02774 dim_t r1 = 25; 02775 02776 row = (key - 1) / 5; 02777 col = (key - 1) % 5; 02778 if (col > 5) col = 5; 02779 if (row > 4) row = 4; 02780 display.background(Black); 02781 display.circle(450 - (2 * r1) * col, 200 - (2 * r1) * row, r1-2, Black, FILL); 02782 display.circle(450 - (2 * r1) * col, 200 - (2 * r1) * row, r1-2, Blue); 02783 } 02784 02785 void KeyPadTest(RA8875 & display, Serial & pc) 02786 { 02787 const uint8_t myMap[22] = { 02788 0, 02789 'a', 'b', 'c', 'd', 'e', 02790 'f', 'g', 'h', 'i', 'j', 02791 'k', 'l', 'm', 'n', 'o', 02792 'p', 'q', 'r', 's', 't', 02793 'x' 02794 }; 02795 02796 display.background(Black); 02797 display.foreground(Blue); 02798 display.cls(); 02799 display.Backlight_u8(255); 02800 display.puts("KeyPad Test. Touch the keypad..."); 02801 pc.printf("\r\n" 02802 "Raw KeyPad Test. Keypad returns the key-number.\r\n" 02803 "Press [most] any PC keyboard key to advance to next test.\r\n"); 02804 RetCode_t ret = display.KeypadInit(true, true, 3, 7, 3); 02805 if (ret != noerror) 02806 pc.printf("returncode from KeypadInit is %d\r\n", ret); 02807 int lastKey = 0; 02808 while (!pc.readable()) { 02809 if (display.readable()) { 02810 int key = display.getc(); 02811 if (key) { 02812 if (((key & 0x7F) != lastKey) && (lastKey != 0)) 02813 HideKey(display, lastKey); 02814 ShowKey(display, key); 02815 lastKey = key & 0x7F; 02816 } else { 02817 // erase the last one 02818 if (lastKey) 02819 HideKey(display, lastKey); 02820 } 02821 } 02822 } 02823 (void)pc.getc(); 02824 pc.printf("\r\n" 02825 "Map KeyPad Test. Keypad returns the remapped key 'a' - 't'.\r\n" 02826 "Press [most] any PC keyboard key to advance to exit test.\r\n"); 02827 display.SetKeyMap(myMap); 02828 while (!pc.readable()) { 02829 if (display.readable()) { 02830 int key = display.getc(); 02831 bool longPress = key & 0x80; 02832 display.SetTextCursor(0, 120); 02833 display.printf("Long Press: %d\r\n", longPress); 02834 display.printf(" Remapped: %c %02X\r\n", (key) ? key & 0x7F : ' ', key); 02835 } 02836 } 02837 (void)pc.getc(); 02838 display.SetKeyMap(); 02839 pc.printf("\r\n"); 02840 } 02841 02842 void TextCursorTest(RA8875 & display, Serial & pc) 02843 { 02844 const char * iCursor = "The I-Beam cursor should be visible for this text.\r\n"; 02845 const char * uCursor = "The Underscore cursor should be visible for this text.\r\n"; 02846 const char * bCursor = "The Block cursor should be visible for this text.\r\n"; 02847 const char * bbCursor = "The Blinking Block cursor should be visible for this text.\r\n"; 02848 const char * p; 02849 int delay = 60; 02850 02851 if (!SuppressSlowStuff) 02852 pc.printf("Text Cursor Test\r\n"); 02853 else 02854 delay = 0; 02855 display.background(Black); 02856 display.foreground(Blue); 02857 display.cls(); 02858 display.Backlight_u8(255); 02859 display.puts("Text Cursor Test."); 02860 02861 // visible, non-blinking 02862 display.SetTextCursor(0,20); 02863 display.SetTextCursorControl(RA8875::IBEAM, false); 02864 p = iCursor; 02865 while (*p) { 02866 display._putc(*p++); 02867 wait_ms(delay); 02868 } 02869 02870 display.SetTextCursorControl(RA8875::UNDER, false); 02871 p = uCursor; 02872 while (*p) { 02873 display._putc(*p++); 02874 wait_ms(delay); 02875 } 02876 02877 display.SetTextCursorControl(RA8875::BLOCK, false); 02878 p = bCursor; 02879 while (*p) { 02880 display._putc(*p++); 02881 wait_ms(delay); 02882 } 02883 02884 display.SetTextCursorControl(RA8875::BLOCK, true); 02885 p = bbCursor; 02886 while (*p) { 02887 display._putc(*p++); 02888 wait_ms(delay); 02889 } 02890 wait_ms(delay * 20); 02891 display.SetTextCursorControl(RA8875::NOCURSOR, false); 02892 } 02893 02894 02895 void BacklightTest(RA8875 & display, Serial & pc, float ramptime) 02896 { 02897 char buf[60]; 02898 unsigned int w = (ramptime * 1000)/ 256; 02899 int delay = 200; 02900 02901 if (!SuppressSlowStuff) 02902 pc.printf("Backlight Test - ramp over %f sec.\r\n", ramptime); 02903 else { 02904 delay = 0; 02905 w = 0; 02906 } 02907 display.Backlight_u8(0); 02908 display.background(White); 02909 display.foreground(Blue); 02910 display.cls(); 02911 display.puts("RA8875 Backlight Test - Ramp up."); 02912 wait_ms(delay); 02913 for (int i=0; i <= 255; i++) { 02914 snprintf(buf, sizeof(buf), "%3d, %4d", i, w); 02915 display.puts(100,100,buf); 02916 display.Backlight_u8(i); 02917 wait_ms(w); 02918 } 02919 } 02920 02921 02922 void BacklightTest2(RA8875 & display, Serial & pc) 02923 { 02924 int delay = 20; 02925 02926 if (!SuppressSlowStuff) 02927 pc.printf("Backlight Test 2\r\n"); 02928 else 02929 delay = 0; 02930 02931 // Dim it out at the end of the tests. 02932 display.foreground(Blue); 02933 display.puts(0,0, "Ramp Backlight down."); 02934 // Ramp it off 02935 for (int i=255; i != 0; i--) { 02936 display.Backlight_u8(i); 02937 wait_ms(delay); 02938 } 02939 display.Backlight_u8(0); 02940 } 02941 02942 02943 void ExternalFontTest(RA8875 & display, Serial & pc) 02944 { 02945 if (!SuppressSlowStuff) 02946 pc.printf("External Font Test\r\n"); 02947 display.background(Black); 02948 display.foreground(Blue); 02949 display.cls(); 02950 display.puts("External Font Test."); 02951 display.Backlight(1); 02952 02953 display.SelectUserFont(BPG_Arial08x08); 02954 display.puts(0,30, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\r\n"); 02955 02956 display.SelectUserFont(BPG_Arial20x20); 02957 display.puts("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\r\n"); 02958 02959 display.SelectUserFont(); 02960 02961 display.puts("Normal font again."); 02962 //display.window(0,0, display.width(), display.height()); 02963 } 02964 02965 02966 void DOSColorTest(RA8875 & display, Serial & pc) 02967 { 02968 if (!SuppressSlowStuff) 02969 pc.printf("DOS Color Test\r\n"); 02970 display.background(Black); 02971 display.foreground(Blue); 02972 display.cls(); 02973 display.puts("DOS Colors - Fore"); 02974 display.puts(280,0, "Back"); 02975 display.background(Gray); 02976 for (int i=0; i<16; i++) { 02977 display.foreground(display.DOSColor(i)); 02978 display.puts(160, i*16, display.DOSColorNames(i)); 02979 display.background(Black); 02980 } 02981 display.foreground(White); 02982 for (int i=0; i<16; i++) { 02983 display.background(display.DOSColor(i)); 02984 display.puts(360, i*16, display.DOSColorNames(i)); 02985 display.foreground(White); 02986 } 02987 } 02988 02989 02990 void WebColorTest(RA8875 & display, Serial & pc) 02991 { 02992 if (!SuppressSlowStuff) 02993 pc.printf("Web Color Test\r\n"); 02994 display.background(Black); 02995 display.foreground(Blue); 02996 display.window(0,0, display.width(), display.height()); 02997 display.cls(); 02998 display.SetTextFontSize(1,1); 02999 display.puts(200,0, "Web Color Test"); 03000 display.SetTextCursor(0,0); 03001 display.puts(" "); 03002 for (int i=0; i<16; i++) 03003 display.printf("%X", i&0xF); 03004 display.puts("\r\n0 "); 03005 for (int i=0; i<sizeof(WebColors)/sizeof(WebColors[0]); i++) { 03006 display.background(WebColors[i]); 03007 display.puts(" "); 03008 if (i % 16 == 15 && i < 255) { 03009 display.printf("\r\n%X ", ((i+1)/16)); 03010 } 03011 } 03012 display.SetTextFontSize(1,1); 03013 } 03014 03015 03016 void PixelTest(RA8875 & display, Serial & pc) 03017 { 03018 int i, c, x, y; 03019 03020 if (!SuppressSlowStuff) 03021 pc.printf("Pixel Test\r\n"); 03022 display.background(Black); 03023 display.foreground(Blue); 03024 display.cls(); 03025 display.puts("Pixel Test"); 03026 for (i=0; i<1000; i++) { 03027 x = rand() % 480; 03028 y = 16 + rand() % (272-16); 03029 c = rand() % 16; 03030 //pc.printf(" (%d,%d) - %d\r\n", x,y,r1); 03031 display.pixel(x,y, display.DOSColor(c)); 03032 } 03033 } 03034 03035 03036 void LineTest(RA8875 & display, Serial & pc) 03037 { 03038 int i, x, y, x2, y2; 03039 03040 if (!SuppressSlowStuff) 03041 pc.printf("Line Test\r\n"); 03042 display.background(Black); 03043 display.foreground(Blue); 03044 display.cls(); 03045 display.puts("Line Test"); 03046 for (i=0; i<16; i++) { 03047 // Lines 03048 x = rand() % 480; 03049 y = rand() % 272; 03050 x2 = rand() % 480; 03051 y2 = rand() % 272; 03052 display.line(x,y, x2,y2, display.DOSColor(i)); 03053 } 03054 display.foreground(BrightRed); 03055 display.foreground(BrightGreen); 03056 display.foreground(BrightBlue); 03057 display.line(55,50, 79,74, BrightRed); 03058 display.line(57,50, 81,74, BrightGreen); 03059 display.line(59,50, 83,74, BrightBlue); 03060 // horz 03061 display.line(30,40, 32,40, BrightRed); 03062 display.line(30,42, 32,42, BrightGreen); 03063 display.line(30,44, 32,44, BrightBlue); 03064 // vert 03065 display.line(20,40, 20,42, BrightRed); 03066 display.line(22,40, 22,42, BrightGreen); 03067 display.line(24,40, 24,42, BrightBlue); 03068 // compare point to line-point 03069 display.pixel(20,50, BrightRed); 03070 display.pixel(22,50, BrightGreen); 03071 display.pixel(24,50, BrightBlue); 03072 display.line(20,52, 20,52, BrightRed); 03073 display.line(22,52, 22,52, BrightGreen); 03074 display.line(24,52, 24,52, BrightBlue); 03075 03076 // point 03077 display.line(50,50, 50,50, Red); 03078 display.line(52,52, 52,52, Green); 03079 display.line(54,54, 54,54, Blue); 03080 display.line(60,60, 60,60, BrightRed); 03081 display.line(62,62, 62,62, BrightGreen); 03082 display.line(64,64, 64,64, BrightBlue); 03083 display.line(70,70, 70,70, DarkRed); 03084 display.line(72,72, 72,72, DarkGreen); 03085 display.line(74,74, 74,74, DarkBlue); 03086 } 03087 03088 03089 void RectangleTest(RA8875 & display, Serial & pc) 03090 { 03091 int i, x1,y1, x2,y2; 03092 03093 if (!SuppressSlowStuff) 03094 pc.printf("Rectangle Test\r\n"); 03095 display.background(Black); 03096 display.foreground(Blue); 03097 display.cls(); 03098 display.puts("Rectangle Test"); 03099 for (i=0; i<16; i++) { 03100 x1 = rand() % 240; 03101 y1 = 50 + rand() % 200; 03102 x2 = rand() % 240; 03103 y2 = 50 + rand() % 200; 03104 display.rect(x1,y1, x2,y2, display.DOSColor(i)); 03105 03106 x1 = 240 + rand() % 240; 03107 y1 = 50 + rand() % 200; 03108 x2 = 240 + rand() % 240; 03109 y2 = 50 + rand() % 200; 03110 display.rect(x1,y1, x2,y2, FILL); 03111 } 03112 } 03113 03114 03115 void LayerTest(RA8875 & display, Serial & pc) 03116 { 03117 loc_t i, x1,y1, x2,y2, r1,r2; 03118 03119 if (!SuppressSlowStuff) 03120 pc.printf("Layer Test\r\n"); 03121 03122 display.SelectDrawingLayer(0); 03123 display.background(Black); 03124 display.foreground(Blue); 03125 display.cls(); 03126 display.puts("Layer 0"); 03127 for (i=0; i<16; i++) { 03128 x1 = rand() % 240; 03129 y1 = 50 + rand() % 200; 03130 x2 = x1 + rand() % 100; 03131 y2 = y1 + rand() % 100; 03132 r1 = rand() % (x2 - x1)/2; 03133 r2 = rand() % (y2 - y1)/2; 03134 display.roundrect(x1,y1, x2,y2, r1,r2, display.DOSColor(i)); 03135 if (!SuppressSlowStuff) 03136 wait_ms(20); 03137 } 03138 if (!SuppressSlowStuff) 03139 wait_ms(1000); 03140 03141 display.SelectDrawingLayer(1); 03142 display.background(Black); 03143 display.foreground(Yellow); 03144 display.cls(); 03145 display.puts(240,0, "Layer 1"); 03146 for (i=0; i<16; i++) { 03147 x1 = 300 + rand() % 100; 03148 y1 = 70 + rand() % 200; 03149 r1 = rand() % min(y1 - 20, 100); 03150 display.circle(x1,y1,r1, display.DOSColor(i)); 03151 if (!SuppressSlowStuff) 03152 wait_ms(20); 03153 } 03154 display.SetLayerMode(RA8875::ShowLayer1); // Show it after the build-up 03155 if (!SuppressSlowStuff) 03156 wait_ms(2000); 03157 03158 display.SelectDrawingLayer(0); 03159 display.SetLayerMode(RA8875::ShowLayer0); // Show Layer 0 again 03160 if (!SuppressSlowStuff) 03161 wait_ms(1000); 03162 display.SetLayerMode(RA8875::TransparentMode); // Transparent mode 03163 if (!SuppressSlowStuff) 03164 wait_ms(1000); 03165 for (i=0; i<=8; i++) { 03166 display.SetLayerTransparency(i, 8-i); 03167 if (!SuppressSlowStuff) 03168 wait_ms(200); 03169 } 03170 03171 // Restore before we exit 03172 display.SetLayerTransparency(0, 0); 03173 display.SetLayerMode(RA8875::ShowLayer0); // Restore to layer 0 03174 } 03175 03176 03177 void RoundRectTest(RA8875 & display, Serial & pc) 03178 { 03179 loc_t i, x1,y1, x2,y2, r1,r2; 03180 03181 if (!SuppressSlowStuff) 03182 pc.printf("Round Rectangle Test\r\n"); 03183 display.background(Black); 03184 display.foreground(Blue); 03185 display.cls(); 03186 display.puts("Rounded Rectangle Test"); 03187 03188 for (i=0; i<16; i++) { 03189 x1 = rand() % 240; 03190 y1 = 50 + rand() % 200; 03191 x2 = x1 + rand() % 100; 03192 y2 = y1 + rand() % 100; 03193 r1 = rand() % (x2 - x1)/2; 03194 r2 = rand() % (y2 - y1)/2; 03195 display.roundrect(x1,y1, x2,y2, 5,8, display.DOSColor(i)); 03196 03197 x1 = 240 + rand() % 240; 03198 y1 = 50 + rand() % 200; 03199 x2 = x1 + rand() % 100; 03200 y2 = y1 + rand() % 100; 03201 r1 = rand() % (x2 - x1)/2; 03202 r2 = rand() % (y2 - y1)/2; 03203 display.roundrect(x1,y1, x2,y2, r1,r2, FILL); 03204 } 03205 } 03206 03207 03208 void TriangleTest(RA8875 & display, Serial & pc) 03209 { 03210 int i, x1, y1, x2, y2, x3, y3; 03211 03212 if (!SuppressSlowStuff) 03213 pc.printf("Triangle Test\r\n"); 03214 display.background(Black); 03215 display.foreground(Blue); 03216 display.cls(); 03217 display.puts(0,0, "Triangle Test"); 03218 03219 x1 = 150; 03220 y1 = 2; 03221 x2 = 190; 03222 y2 = 7; 03223 x3 = 170; 03224 y3 = 16; 03225 display.triangle(x1,y1, x2,y2, x3,y3); 03226 03227 x1 = 200; 03228 y1 = 2; 03229 x2 = 240; 03230 y2 = 7; 03231 x3 = 220; 03232 y3 = 16; 03233 display.filltriangle(x1,y1, x2,y2, x3,y3, BrightRed); 03234 03235 x1 = 300; 03236 y1 = 2; 03237 x2 = 340; 03238 y2 = 7; 03239 x3 = 320; 03240 y3 = 16; 03241 display.triangle(x1,y1, x2,y2, x3,y3, NOFILL); 03242 03243 x1 = 400; 03244 y1 = 2; 03245 x2 = 440; 03246 y2 = 7; 03247 x3 = 420; 03248 y3 = 16; 03249 display.triangle(x1,y1, x2,y2, x3,y3, Blue); 03250 03251 for (i=0; i<16; i++) { 03252 x1 = rand() % 240; 03253 y1 = 50 + rand() % 200; 03254 x2 = rand() % 240; 03255 y2 = 50 + rand() % 200; 03256 x3 = rand() % 240; 03257 y3 = 50 + rand() % 200; 03258 display.triangle(x1,y1, x2,y2, x3,y3, display.DOSColor(i)); 03259 x1 = 240 + rand() % 240; 03260 y1 = 50 + rand() % 200; 03261 x2 = 240 + rand() % 240; 03262 y2 = 50 + rand() % 200; 03263 x3 = 240 + rand() % 240; 03264 y3 = 50 + rand() % 200; 03265 display.triangle(x1,y1, x2,y2, x3,y3, FILL); 03266 } 03267 } 03268 03269 03270 void CircleTest(RA8875 & display, Serial & pc) 03271 { 03272 int i, x, y, r1; 03273 03274 if (!SuppressSlowStuff) 03275 pc.printf("Circle Test\r\n"); 03276 display.background(Black); 03277 display.foreground(Blue); 03278 display.cls(); 03279 display.puts("Circle Test"); 03280 for (i=0; i<16; i++) { 03281 x = 100 + rand() % 100; 03282 y = 70 + rand() % 200; 03283 r1 = rand() % min(y - 20, 100); 03284 //pc.printf(" (%d,%d) - %d\r\n", x,y,r1); 03285 display.circle(x,y,r1, display.DOSColor(i)); 03286 03287 x = 300 + rand() % 100; 03288 y = 70 + rand() % 200; 03289 r1 = rand() % min(y - 20, 100); 03290 //pc.printf(" (%d,%d) - %d FILL\r\n", x,y,r1); 03291 display.circle(x,y,r1, display.DOSColor(i), FILL); 03292 } 03293 } 03294 03295 03296 void EllipseTest(RA8875 & display, Serial & pc) 03297 { 03298 int i,x,y,r1,r2; 03299 03300 if (!SuppressSlowStuff) 03301 pc.printf("Ellipse Test\r\n"); 03302 display.background(Black); 03303 display.foreground(Blue); 03304 display.cls(); 03305 display.puts("Ellipse Test"); 03306 for (i=0; i<16; i++) { 03307 x = 100 + rand() % 100; 03308 y = 70 + rand() % 200; 03309 r1 = rand() % min(y - 20, 100); 03310 r2 = rand() % min(y - 20, 100); 03311 display.ellipse(x,y,r1,r2, display.DOSColor(i)); 03312 03313 x = 300 + rand() % 100; 03314 y = 70 + rand() % 200; 03315 r1 = rand() % min(y - 20, 100); 03316 r2 = rand() % min(y - 20, 100); 03317 display.ellipse(x,y,r1,r2, FILL); 03318 } 03319 } 03320 03321 03322 void TestGraphicsBitmap(RA8875 & display, Serial & pc) 03323 { 03324 LocalFileSystem local("local"); 03325 if (!SuppressSlowStuff) 03326 pc.printf("Bitmap File Load\r\n"); 03327 display.background(Black); 03328 display.foreground(Blue); 03329 display.cls(); 03330 display.puts("Graphics Test, loading /local/TestPat.bmp"); 03331 wait(3); 03332 03333 int r = display.RenderBitmapFile(0,0, "/local/TestPat.bmp"); 03334 if (!SuppressSlowStuff) 03335 pc.printf(" returned %d\r\n", r); 03336 } 03337 03338 03339 void TouchPanelTest(RA8875 & display, Serial & pc) 03340 { 03341 Timer t; 03342 int x, y; 03343 tpMatrix_t calmatrix; 03344 03345 display.background(Black); 03346 display.foreground(Blue); 03347 display.cls(); 03348 display.puts("Touch Panel Test\r\n"); 03349 pc.printf("Touch Panel Test\r\n"); 03350 display.TouchPanelInit(); 03351 pc.printf(" TP: c - calibrate, r - restore, t - test\r\n"); 03352 int c = pc.getc(); 03353 if (c == 'c') { 03354 point_t pTest[3] = 03355 { { 50, 50 }, {450, 150}, {225,250} }; 03356 point_t pSample[3]; 03357 for (int i=0; i<3; i++) { 03358 display.foreground(Blue); 03359 display.printf(" (%3d,%3d) => ", pTest[i].x, pTest[i].y); 03360 display.line(pTest[i].x-10, pTest[i].y, pTest[i].x+10, pTest[i].y, White); 03361 display.line(pTest[i].x, pTest[i].y-10, pTest[i].x, pTest[i].y+10, White); 03362 while (!display.TouchPanelA2DFiltered(&x, &y)) 03363 wait_ms(20); 03364 pSample[i].x = x; 03365 pSample[i].y = y; 03366 display.line(pTest[i].x-10, pTest[i].y, pTest[i].x+10, pTest[i].y, Black); 03367 display.line(pTest[i].x, pTest[i].y-10, pTest[i].x, pTest[i].y+10, Black); 03368 display.foreground(Blue); 03369 display.printf(" (%4d,%4d)\r\n", x,y); 03370 while (display.TouchPanelA2DFiltered(&x, &y)) 03371 wait_ms(20); 03372 wait(2); 03373 } 03374 display.TouchPanelComputeCalibration(pTest, pSample, &calmatrix); 03375 display.printf(" Writing calibration to tpcal.cfg\r\n"); 03376 FILE * fh = fopen("/local/tpcal.cfg", "wb"); 03377 if (fh) { 03378 fwrite(&calmatrix, sizeof(calmatrix), 1, fh); 03379 fclose(fh); 03380 } 03381 display.printf(" Calibration is complete."); 03382 } else if (c == 'r') { 03383 display.printf(" Reading calibration from tpcal.cfg\r\n"); 03384 FILE * fh = fopen("/local/tpcal.cfg", "rb"); 03385 if (fh) { 03386 fread(&calmatrix, sizeof(calmatrix), 1, fh); 03387 fclose(fh); 03388 } 03389 display.printf(" Calibration is complete."); 03390 display.TouchPanelSetMatrix(&calmatrix); 03391 } 03392 t.start(); 03393 do { 03394 point_t point = {0, 0}; 03395 if (display.TouchPanelReadable(&point)) { 03396 display.pixel(point.x, point.y, Red); 03397 } 03398 } while (t.read_ms() < 30000); 03399 pc.printf(">"); 03400 } 03401 03402 03403 void SpeedTest(RA8875 & display, Serial & pc) 03404 { 03405 Timer t; 03406 SuppressSlowStuff = true; 03407 pc.printf("\r\nSpeedTest disables delays, runs tests, reports overall time.\r\n"); 03408 t.start(); 03409 // do stuff fast 03410 TextCursorTest(display, pc); 03411 TextWrapTest(display, pc); 03412 BacklightTest(display, pc, 0); 03413 BacklightTest2(display, pc); 03414 ExternalFontTest(display, pc); 03415 DOSColorTest(display, pc); 03416 WebColorTest(display, pc); 03417 PixelTest(display, pc); 03418 LineTest(display, pc); 03419 RectangleTest(display, pc); 03420 RoundRectTest(display, pc); 03421 TriangleTest(display, pc); 03422 CircleTest(display, pc); 03423 EllipseTest(display, pc); 03424 LayerTest(display, pc); 03425 //TestGraphicsBitmap(display, pc); 03426 pc.printf("SpeedTest completed in %d msec\r\n", t.read_ms()); 03427 #ifdef PERF_METRICS 03428 display.ReportPerformance(pc); 03429 #endif 03430 SuppressSlowStuff = false; 03431 } 03432 03433 03434 void PrintScreen(RA8875 & display, Serial & pc) 03435 { 03436 if (!SuppressSlowStuff) 03437 pc.printf("PrintScreen\r\n"); 03438 display.PrintScreen( 0,0, 480,272, "/local/Capture.bmp"); 03439 } 03440 03441 03442 void RunTestSet(RA8875 & lcd, Serial & pc) 03443 { 03444 int q = 0; 03445 int automode = 0; 03446 const unsigned char modelist[] = "BDWtGLlFROTPCEbw"; // auto-test in this order. 03447 03448 while(1) { 03449 pc.printf("\r\n" 03450 "B - Backlight up b - backlight dim\r\n" 03451 "D - DOS Colors W - Web Colors\r\n" 03452 "t - text cursor G - Graphics Bitmap\r\n" 03453 "L - Lines F - external Font\r\n" 03454 "R - Rectangles O - rOund rectangles\r\n" 03455 "T - Triangles P - Pixels \r\n" 03456 "C - Circles E - Ellipses\r\n" 03457 "A - Auto Test mode S - Speed Test\r\n" 03458 "K - Keypad Test s - touch screen test\r\n" 03459 "p - print screen r - reset \r\n" 03460 "l - layer test w - wrapping text \r\n" 03461 #ifdef PERF_METRICS 03462 "0 - clear performance 1 - report performance\r\n" 03463 #endif 03464 "> "); 03465 if (automode == -1 || pc.readable()) { 03466 automode = -1; 03467 q = pc.getc(); 03468 while (pc.readable()) 03469 pc.getc(); 03470 } else if (automode >= 0) { 03471 q = modelist[automode]; 03472 } 03473 switch(q) { 03474 #ifdef PERF_METRICS 03475 case '0': 03476 lcd.ClearPerformance(); 03477 break; 03478 case '1': 03479 lcd.ReportPerformance(pc); 03480 break; 03481 #endif 03482 case 'A': 03483 automode = 0; 03484 break; 03485 case 'B': 03486 BacklightTest(lcd, pc, 2); 03487 break; 03488 case 'b': 03489 BacklightTest2(lcd, pc); 03490 break; 03491 case 'D': 03492 DOSColorTest(lcd, pc); 03493 break; 03494 case 'K': 03495 KeyPadTest(lcd, pc); 03496 break; 03497 case 'W': 03498 WebColorTest(lcd, pc); 03499 break; 03500 case 't': 03501 TextCursorTest(lcd, pc); 03502 break; 03503 case 'w': 03504 TextWrapTest(lcd, pc); 03505 break; 03506 case 'F': 03507 ExternalFontTest(lcd, pc); 03508 break; 03509 case 'L': 03510 LineTest(lcd, pc); 03511 break; 03512 case 'l': 03513 LayerTest(lcd, pc); 03514 break; 03515 case 'R': 03516 RectangleTest(lcd, pc); 03517 break; 03518 case 'O': 03519 RoundRectTest(lcd, pc); 03520 break; 03521 case 'p': 03522 PrintScreen(lcd, pc); 03523 break; 03524 case 'S': 03525 SpeedTest(lcd, pc); 03526 break; 03527 case 's': 03528 TouchPanelTest(lcd, pc); 03529 break; 03530 case 'T': 03531 TriangleTest(lcd, pc); 03532 break; 03533 case 'P': 03534 PixelTest(lcd, pc); 03535 break; 03536 case 'G': 03537 TestGraphicsBitmap(lcd, pc); 03538 break; 03539 case 'C': 03540 CircleTest(lcd, pc); 03541 break; 03542 case 'E': 03543 EllipseTest(lcd, pc); 03544 break; 03545 case 'r': 03546 pc.printf("Resetting ...\r\n"); 03547 wait_ms(20); 03548 mbed_reset(); 03549 break; 03550 case ' ': 03551 break; 03552 default: 03553 printf("huh?\n"); 03554 break; 03555 } 03556 if (automode >= 0) { 03557 automode++; 03558 if (automode >= sizeof(modelist)) 03559 automode = 0; 03560 wait_ms(2000); 03561 } 03562 wait_ms(200); 03563 } 03564 } 03565 03566 #endif // TESTENABLE
Generated on Mon Jul 18 2022 18:51:06 by
1.7.2