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