![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
brw1
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 480 x 272 using a 4-wire SPI interface. Support is provided for 00005 /// both a keypad and a resistive touch-screen. 00006 /// 00007 /// This display controller is used in other display resolutions, up to 800x600. 00008 /// While this driver has not been tested with these variants, nothing was done 00009 /// to prevent easily supporting them. 00010 /// 00011 #include "RA8875.h" 00012 00013 //#define DEBUG "RAIO" 00014 // ... 00015 // INFO("Stuff to show %d", var); // new-line is automatically appended 00016 // 00017 #if (defined(DEBUG) && !defined(TARGET_LPC11U24)) 00018 #define INFO(x, ...) std::printf("[INF %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); 00019 #define WARN(x, ...) std::printf("[WRN %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); 00020 #define ERR(x, ...) std::printf("[ERR %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); 00021 static void HexDump(char * title, uint8_t * p, int count) 00022 { 00023 int i; 00024 char buf[100] = "0000: "; 00025 00026 if (*title) 00027 INFO("%s", title); 00028 for (i=0; i<count; ) { 00029 sprintf(buf + strlen(buf), "%02X ", *(p+i)); 00030 if ((++i & 0x0F) == 0x00) { 00031 INFO("%s", buf); 00032 if (i < count) 00033 sprintf(buf, "%04X: ", i); 00034 else 00035 buf[0] = '\0'; 00036 } 00037 } 00038 if (strlen(buf)) 00039 INFO("%s", buf); 00040 } 00041 #else 00042 #define INFO(x, ...) 00043 #define WARN(x, ...) 00044 #define ERR(x, ...) 00045 #define HexDump(a, b, c) 00046 #endif 00047 00048 00049 #define RA8875_DISPLAY_WIDTH 480 00050 #define RA8875_DISPLAY_HEIGHT 272 00051 #define RA8875_COLORDEPTH_BPP 16 /* Not an API */ 00052 00053 #ifdef PERF_METRICS 00054 #define PERFORMANCE_RESET performance.reset() 00055 #define REGISTERPERFORMANCE(a) RegisterPerformance(a) 00056 #define COUNTIDLETIME(a) CountIdleTime(a) 00057 static const char *metricsName[] = { 00058 "Cls", "Pixel", "Pixel Stream", 00059 "Read Pixel", "Read Pixel Stream", 00060 "Line", 00061 "Rectangle", "Rounded Rectangle", 00062 "Triangle", "Circle", "Ellipse" 00063 }; 00064 #else 00065 #define PERFORMANCE_RESET 00066 #define REGISTERPERFORMANCE(a) 00067 #define COUNTIDLETIME(a) 00068 #endif 00069 00070 // When it is going to poll a register for completion, how many 00071 // uSec should it wait between each polling activity. 00072 #define POLLWAITuSec 10 00073 00074 // Private RawKeyMap for the Keyboard interface 00075 static const uint8_t DefaultKeyMap[22] = { 00076 0, 00077 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 00078 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 00079 255 00080 }; 00081 00082 static const char * ErrMessages[] = { 00083 "noerror", ///< no errors, command completed successfully 00084 "bad_parameter", ///< one or more parameters are invalid 00085 "file_not_found", ///< specified file could not be found 00086 "not_bmp_format", ///< file is not a .bmp file 00087 "not_ico_format", ///< file is not a .ico file 00088 "not_supported_format", ///< file format is not yet supported 00089 "image_too_big", ///< image is too large for the screen 00090 "not_enough_ram", ///< could not allocate ram for scanline 00091 }; 00092 00093 RA8875::RA8875(PinName mosi, PinName miso, PinName sclk, PinName csel, PinName reset, const char *name) 00094 : GraphicsDisplay(name) 00095 , spi(mosi, miso, sclk) 00096 , cs(csel) 00097 , res(reset) 00098 { 00099 } 00100 00101 //RA8875::~RA8875() 00102 //{ 00103 //} 00104 00105 RetCode_t RA8875::init(int width, int height, int color_bpp, bool poweron, bool keypadon, bool touchscreenon) 00106 { 00107 font = NULL; // no external font, use internal. 00108 pKeyMap = DefaultKeyMap; // set default key map 00109 _select(false); // deselect the display 00110 frequency(RA8875_DEFAULT_SPI_FREQ); // data rate 00111 Reset(); 00112 WriteCommand(0x88, 0x0B); // PLLC1 - Phase Lock Loop registers 00113 wait_ms(1); 00114 WriteCommand(0x89, 0x02); 00115 wait_ms(1); 00116 00117 // System Config Register (SYSR) 00118 if (color_bpp == 16) { 00119 WriteCommand(0x10, 0x0C); // 16-bpp (65K colors) color depth, 8-bit interface 00120 } else { // color_bpp == 8 00121 WriteCommand(0x10, 0x00); // 8-bpp (256 colors) 00122 } 00123 // Pixel Clock Setting Register (PCSR) 00124 WriteCommand(0x04, 0x82); // PDAT on PCLK falling edge, PCLK = 4 x System Clock 00125 wait_ms(1); 00126 00127 // Horizontal Settings 00128 WriteCommand(0x14, width/8 - 1); //HDWR//Horizontal Display Width Setting Bit[6:0] 00129 WriteCommand(0x15, 0x02); //HNDFCR//Horizontal Non-Display Period fine tune Bit[3:0] 00130 WriteCommand(0x16, 0x03); //HNDR//Horizontal Non-Display Period Bit[4:0] 00131 WriteCommand(0x17, 0x01); //HSTR//HSYNC Start Position[4:0] 00132 WriteCommand(0x18, 0x03); //HPWR//HSYNC Polarity ,The period width of HSYNC. 00133 00134 // Vertical Settings 00135 WriteCommand(0x19, (height-1)&0xFF); //VDHR0 //Vertical Display Height Bit [7:0] 00136 WriteCommand(0x1a, (height-1)>>8); //VDHR1 //Vertical Display Height Bit [8] 00137 WriteCommand(0x1b, 0x0F); //VNDR0 //Vertical Non-Display Period Bit [7:0] 00138 WriteCommand(0x1c, 0x00); //VNDR1 //Vertical Non-Display Period Bit [8] 00139 WriteCommand(0x1d, 0x0e); //VSTR0 //VSYNC Start Position[7:0] 00140 WriteCommand(0x1e, 0x06); //VSTR1 //VSYNC Start Position[8] 00141 WriteCommand(0x1f, 0x01); //VPWR //VSYNC Polarity ,VSYNC Pulse Width[6:0] 00142 00143 if (width >= 800 && height >= 480 && color_bpp > 8) { 00144 WriteCommand(0x20, 0x00); // DPCR - 1-layer mode when the resolution is too high 00145 } else { 00146 WriteCommand(0x20, 0x80); // DPCR - 2-layer mode 00147 } 00148 00149 // Set display image to Blue on Black as default 00150 window(0,0, width, height); // Initialize to full screen 00151 SetTextCursorControl(); 00152 foreground(Blue); 00153 background(Black); 00154 cls(3); 00155 00156 Power(poweron); 00157 if (poweron) 00158 Backlight_u8(255); 00159 if (keypadon) 00160 KeypadInit(); 00161 if (touchscreenon) 00162 TouchPanelInit(); 00163 #ifdef PERF_METRICS 00164 performance.start(); 00165 ClearPerformance(); 00166 #endif 00167 return noerror; 00168 } 00169 00170 00171 RetCode_t RA8875::Reset(void) 00172 { 00173 RetCode_t ret; 00174 00175 ret = WriteCommand(0x01, 0x01); // Apply Display Off, Reset 00176 wait_ms(2); // no idea if I need to wait, or how long 00177 if (ret == noerror) { 00178 ret = WriteCommand(0x01, 0x00); // Display off, Remove reset 00179 wait_ms(2); // no idea if I need to wait, or how long 00180 } 00181 return ret; 00182 } 00183 00184 00185 const char * RA8875::GetErrorMessage(RetCode_t code) 00186 { 00187 if (code >= LastErrCode) 00188 code = bad_parameter; 00189 return ErrMessages[code]; 00190 } 00191 00192 00193 uint16_t RA8875::GetDrawingLayer(void) 00194 { 00195 return (ReadCommand(0x41) & 0x01); 00196 } 00197 00198 00199 RetCode_t RA8875::SelectDrawingLayer(uint16_t layer) 00200 { 00201 unsigned char mwcr1 = ReadCommand(0x41) & ~0x01; // retain all but the currently selected layer 00202 00203 if (width() >= 800 && height() >= 480 && color_bpp() == 8) { 00204 return bad_parameter; 00205 } else if (layer > 1) { 00206 return bad_parameter; 00207 } else { // layer == 0 ro 1 00208 return WriteCommand(0x41, mwcr1 | layer); 00209 } 00210 } 00211 00212 00213 RetCode_t RA8875::SetLayerMode(LayerMode_T mode) 00214 { 00215 unsigned char ltpr0 = ReadCommand(0x52) & ~0x7; // retain all but the display layer mode 00216 if (mode <= (LayerMode_T)6) { 00217 WriteCommand(0x52, ltpr0 | (mode & 0x7)); 00218 return noerror; 00219 } else { 00220 return bad_parameter; 00221 } 00222 } 00223 00224 00225 RetCode_t RA8875::SetLayerTransparency(uint8_t layer1, uint8_t layer2) 00226 { 00227 if (layer1 > 8) 00228 layer1 = 8; 00229 if (layer2 > 8) 00230 layer2 = 8; 00231 WriteCommand(0x53, ((layer2 & 0xF) << 4) | (layer1 & 0xF)); 00232 return noerror; 00233 } 00234 00235 00236 RetCode_t RA8875::SetBackgroundTransparencyColor(color_t color) 00237 { 00238 WriteCommand(0x67, (color >> 11) & 0x1F); 00239 WriteCommand(0x68, (color >> 5) & 0x3F); 00240 WriteCommand(0x69, (color & 0x1F)); 00241 return noerror; 00242 } 00243 00244 00245 color_t RA8875::GetBackgroundTransparencyColor(void) 00246 { 00247 RGBQUAD q; 00248 q.rgbRed = ReadCommand(0x67); 00249 q.rgbGreen = ReadCommand(0x68); 00250 q.rgbBlue = ReadCommand(0x69); 00251 return RGBQuadToRGB16(&q, 0); 00252 } 00253 00254 00255 RetCode_t RA8875::KeypadInit(bool scanEnable, bool longDetect, uint8_t sampleTime, uint8_t scanFrequency, 00256 uint8_t longTimeAdjustment, bool interruptEnable, bool wakeupEnable) 00257 { 00258 uint8_t value = 0; 00259 00260 if (sampleTime > 3 || scanFrequency > 7 || longTimeAdjustment > 3) 00261 return bad_parameter; 00262 value |= (scanEnable) ? 0x80 : 0x00; 00263 value |= (longDetect) ? 0x40 : 0x00; 00264 value |= (sampleTime & 0x03) << 4; 00265 value |= (scanFrequency & 0x07); 00266 WriteCommand(0xC0, value); // KSCR1 - Enable Key Scan (and ignore possibility of an error) 00267 00268 value = 0; 00269 value |= (wakeupEnable) ? 0x80 : 0x00; 00270 value |= (longTimeAdjustment & 0x03) << 2; 00271 WriteCommand(0xC1, value); // KSCR2 - (and ignore possibility of an error) 00272 00273 value = ReadCommand(0xF0); // (and ignore possibility of an error) 00274 value &= ~0x10; 00275 value |= (interruptEnable) ? 0x10 : 0x00; 00276 return WriteCommand(0xF0, value); // INT 00277 } 00278 00279 00280 RetCode_t RA8875::SetKeyMap(const uint8_t * CodeList) 00281 { 00282 pKeyMap = CodeList; 00283 return noerror; 00284 } 00285 00286 00287 bool RA8875::readable(void) 00288 { 00289 return (ReadCommand(0xF1) & 0x10); // check KS status - true if kbhit 00290 } 00291 00292 00293 uint8_t RA8875::getc(void) 00294 { 00295 //#define GETC_DEV // for development 00296 #ifdef GETC_DEV 00297 uint8_t keyCode1, keyCode2; 00298 #endif 00299 uint8_t keyCode3; 00300 static uint8_t count = 0; 00301 uint8_t col, row; 00302 uint8_t key; 00303 00304 while (!readable()) { 00305 wait_us(POLLWAITuSec); 00306 // COUNTIDLETIME(POLLWAITuSec); // As it is voluntary to call the getc and pend. Don't tally it. 00307 } 00308 // read the key press number 00309 uint8_t keyNumReg = ReadCommand(0xC1) & 0x03; 00310 count++; 00311 switch (keyNumReg) { 00312 case 0x01: // one key 00313 keyCode3 = ReadCommand(0xC2); 00314 #ifdef GETC_DEV 00315 keyCode2 = 0; 00316 keyCode1 = 0; 00317 #endif 00318 break; 00319 case 0x02: // two keys 00320 keyCode3 = ReadCommand(0xC3); 00321 #ifdef GETC_DEV 00322 keyCode2 = ReadCommand(0xC2); 00323 keyCode1 = 0; 00324 #endif 00325 break; 00326 case 0x03: // three keys 00327 keyCode3 = ReadCommand(0xC4); 00328 #ifdef GETC_DEV 00329 keyCode2 = ReadCommand(0xC3); 00330 keyCode1 = ReadCommand(0xC2); 00331 #endif 00332 break; 00333 default: // no keys (key released) 00334 keyCode3 = 0xFF; 00335 #ifdef GETC_DEV 00336 keyCode2 = 0; 00337 keyCode1 = 0; 00338 #endif 00339 break; 00340 } 00341 if (keyCode3 == 0xFF) 00342 key = pKeyMap[0]; // Key value 0 00343 else { 00344 row = (keyCode3 >> 4) & 0x03; 00345 col = (keyCode3 & 7); 00346 key = row * 5 + col + 1; // Keys value 1 - 20 00347 if (key > 21) { 00348 key = 21; 00349 } 00350 key = pKeyMap[key]; 00351 key |= (keyCode3 & 0x80); // combine the key held flag 00352 } 00353 #if GETC_DEV // for Development only 00354 SetTextCursor(0, 20); 00355 printf(" Reg: %02x\r\n", keyNumReg); 00356 printf(" key1: %02x\r\n", keyCode1); 00357 printf(" key2: %02x\r\n", keyCode2); 00358 printf(" key3: %02x\r\n", keyCode3); 00359 printf(" count: %02X\r\n", count); 00360 printf(" key: %02X\r\n", key); 00361 #endif 00362 WriteCommand(0xF1, 0x10); // Clear KS status 00363 return key; 00364 } 00365 00366 00367 #ifdef PERF_METRICS 00368 void RA8875::ClearPerformance() 00369 { 00370 for (int i=0; i<METRICCOUNT; i++) 00371 metrics[i] = 0; 00372 idletime_usec = 0; 00373 } 00374 00375 00376 void RA8875::RegisterPerformance(method_e method) 00377 { 00378 unsigned long elapsed = performance.read_us(); 00379 00380 if (method < METRICCOUNT && elapsed > metrics[method]) 00381 metrics[method] = elapsed; 00382 } 00383 00384 00385 void RA8875::CountIdleTime(uint32_t t) 00386 { 00387 idletime_usec += t; 00388 } 00389 00390 00391 void RA8875::ReportPerformance(Serial & pc) 00392 { 00393 pc.printf("\r\nPerformance Metrics\r\n"); 00394 for (int i=0; i<METRICCOUNT; i++) { 00395 pc.printf("%10d uS %s\r\n", metrics[i], metricsName[i]); 00396 } 00397 pc.printf("%10d uS Idle time polling display for ready.\r\n", idletime_usec); 00398 } 00399 #endif 00400 00401 00402 RetCode_t RA8875::WriteCommandW(uint8_t command, uint16_t data) 00403 { 00404 #if 1 00405 WriteCommand(command, data & 0xFF); 00406 WriteCommand(command+1, data >> 8); 00407 #else 00408 // This should be a little faster, but doesn't work... 00409 INFO("WriteCommandW(%02X, %04X)", command, data); 00410 _select(true); 00411 _spiwrite(0x80); 00412 _spiwrite(command); 00413 //_spiwrite(0x00); // dummy 00414 _spiwrite(data & 0xFF); 00415 _spiwrite(data >> 8); 00416 _select(false); 00417 #endif 00418 return noerror; 00419 } 00420 00421 00422 RetCode_t RA8875::WriteCommand(unsigned char command, unsigned int data) 00423 { 00424 _select(true); 00425 _spiwrite(0x80); // cmd: write command 00426 _spiwrite(command); 00427 if (data <= 0xFF) { // only if in the valid range 00428 _spiwrite(0x00); 00429 _spiwrite(data); 00430 } 00431 _select(false); 00432 return noerror; 00433 } 00434 00435 00436 RetCode_t RA8875::WriteDataW(uint16_t data) 00437 { 00438 _select(true); 00439 _spiwrite(0x00); // cmd: write data 00440 _spiwrite(data & 0xFF); 00441 _spiwrite(data >> 8); 00442 _select(false); 00443 return noerror; 00444 } 00445 00446 00447 RetCode_t RA8875::WriteData(unsigned char data) 00448 { 00449 _select(true); 00450 _spiwrite(0x00); 00451 _spiwrite(data); 00452 _select(false); 00453 return noerror; 00454 } 00455 00456 00457 unsigned char RA8875::ReadCommand(unsigned char command) 00458 { 00459 WriteCommand(command); 00460 return ReadData(); 00461 } 00462 00463 00464 unsigned char RA8875::ReadData(void) 00465 { 00466 unsigned char data; 00467 00468 _select(true); 00469 _spiwrite(0x40); 00470 data = _spiread(); 00471 _select(false); 00472 return data; 00473 } 00474 00475 00476 uint16_t RA8875::ReadDataW(void) 00477 { 00478 uint16_t data; 00479 00480 _select(true); 00481 _spiwrite(0x40); 00482 data = _spiread(); 00483 data |= (_spiread() << 8); 00484 _select(false); 00485 return data; 00486 } 00487 00488 00489 unsigned char RA8875::ReadStatus(void) 00490 { 00491 unsigned char data; 00492 00493 _select(true); 00494 _spiwrite(0xC0); // These two bits are for the special "Status Read" [STSR] 00495 data = _spiread(); 00496 _select(false); 00497 return data; 00498 } 00499 00500 00501 /// @todo add a timeout and return false, but how long 00502 /// to wait since some operations can be very long. 00503 bool RA8875::_WaitWhileBusy(uint8_t mask) 00504 { 00505 int i = 20000/POLLWAITuSec; // 20 msec max 00506 00507 while (i-- && ReadStatus() & mask) { 00508 wait_us(POLLWAITuSec); 00509 COUNTIDLETIME(POLLWAITuSec); 00510 } 00511 if (i) 00512 return true; 00513 else 00514 return false; 00515 } 00516 00517 00518 /// @todo add a timeout and return false, but how long 00519 /// to wait since some operations can be very long. 00520 bool RA8875::_WaitWhileReg(uint8_t reg, uint8_t mask) 00521 { 00522 int i = 20000/POLLWAITuSec; // 20 msec max 00523 00524 while (i-- && ReadCommand(reg) & mask) { 00525 wait_us(POLLWAITuSec); 00526 COUNTIDLETIME(POLLWAITuSec); 00527 } 00528 if (i) 00529 return true; 00530 else 00531 return false; 00532 } 00533 00534 00535 dim_t RA8875::fontwidth(void) 00536 { 00537 if (font == NULL) 00538 return (((ReadCommand(0x22) >> 2) & 0x3) + 1) * 8; 00539 else 00540 return font[1]; 00541 } 00542 00543 00544 dim_t RA8875::fontheight(void) 00545 { 00546 if (font == NULL) 00547 return (((ReadCommand(0x22) >> 0) & 0x3) + 1) * 16; 00548 else 00549 return font[2]; 00550 } 00551 00552 00553 RetCode_t RA8875::locate(textloc_t column, textloc_t row) 00554 { 00555 return SetTextCursor(column * fontwidth(), row * fontheight()); 00556 } 00557 00558 00559 int RA8875::columns(void) 00560 { 00561 return width() / fontwidth(); 00562 } 00563 00564 00565 int RA8875::rows(void) 00566 { 00567 return height() / fontheight(); 00568 } 00569 00570 00571 dim_t RA8875::width(void) 00572 { 00573 return (ReadCommand(0x14) + 1) * 8; 00574 } 00575 00576 00577 dim_t RA8875::height(void) 00578 { 00579 return (ReadCommand(0x19) | (ReadCommand(0x1A) << 8)) + 1; 00580 } 00581 00582 00583 dim_t RA8875::color_bpp(void) 00584 { 00585 if ((ReadCommand(0x10) & 0x0C) == 0x04) 00586 return 16; 00587 else 00588 return 8; 00589 } 00590 00591 00592 RetCode_t RA8875::SetTextCursor(loc_t x, loc_t y) 00593 { 00594 cursor_x = x; // set these values for non-internal fonts 00595 cursor_y = y; 00596 WriteCommandW(0x2A, x); 00597 WriteCommandW(0x2C, y); 00598 return noerror; 00599 } 00600 00601 00602 loc_t RA8875::GetTextCursor_Y(void) 00603 { 00604 if (font == NULL) 00605 return ReadCommand(0x2C) | (ReadCommand(0x2D) << 8); 00606 else 00607 return cursor_y; 00608 } 00609 00610 00611 loc_t RA8875::GetTextCursor_X(void) 00612 { 00613 if (font == NULL) 00614 return ReadCommand(0x2A) | (ReadCommand(0x2B) << 8); 00615 else 00616 return cursor_x; 00617 } 00618 00619 00620 RetCode_t RA8875::SetTextCursorControl(cursor_t cursor, bool blink) 00621 { 00622 unsigned char mwcr0 = ReadCommand(0x40) & 0x0F; // retain direction, auto-increase 00623 unsigned char mwcr1 = ReadCommand(0x41) & 0x01; // retain currently selected layer 00624 unsigned char horz = 0; 00625 unsigned char vert = 0; 00626 00627 mwcr0 |= 0x80; // text mode 00628 if (cursor != NOCURSOR) 00629 mwcr0 |= 0x40; // visible 00630 if (blink) 00631 mwcr0 |= 0x20; // blink 00632 WriteCommand(0x40, mwcr0); // configure the cursor 00633 WriteCommand(0x41, mwcr1); // close the graphics cursor 00634 WriteCommand(0x44, 0x1f); // The cursor flashing cycle 00635 switch (cursor) { 00636 case IBEAM: 00637 horz = 0x01; 00638 vert = 0x1F; 00639 break; 00640 case UNDER: 00641 horz = 0x07; 00642 vert = 0x01; 00643 break; 00644 case BLOCK: 00645 horz = 0x07; 00646 vert = 0x1F; 00647 break; 00648 case NOCURSOR: 00649 default: 00650 break; 00651 } 00652 WriteCommand(0x4e, horz); // The cursor size horz 00653 WriteCommand(0x4f, vert); // The cursor size vert 00654 return noerror; 00655 } 00656 00657 00658 RetCode_t RA8875::SetTextFont(RA8875::font_t font) 00659 { 00660 if (/*font >= RA8875::ISO8859_1 && */ font <= RA8875::ISO8859_4) { 00661 WriteCommand(0x21, (unsigned int)(font)); 00662 return noerror; 00663 } else { 00664 return bad_parameter; 00665 } 00666 } 00667 00668 00669 RetCode_t RA8875::SetTextFontControl(fill_t fillit, 00670 RA8875::font_angle_t angle, 00671 RA8875::HorizontalScale hScale, 00672 RA8875::VerticalScale vScale, 00673 RA8875::alignment_t alignment) 00674 { 00675 if (hScale >= 1 && hScale <= 4 && 00676 vScale >= 1 && vScale <= 4) { 00677 unsigned char x = 0; 00678 00679 if (alignment == align_full) 00680 x |= 0x80; 00681 if (fillit == NOFILL) 00682 x |= 0x40; 00683 if (angle == rotated) 00684 x |= 0x10; 00685 x |= ((hScale - 1) << 2); 00686 x |= ((vScale - 1) << 0); 00687 WriteCommand(0x22, x); 00688 return noerror; 00689 } else { 00690 return bad_parameter; 00691 } 00692 } 00693 00694 00695 RetCode_t RA8875::SetTextFontSize(RA8875::HorizontalScale hScale, RA8875::VerticalScale vScale) 00696 { 00697 unsigned char reg = ReadCommand(0x22); 00698 00699 if (vScale == -1) 00700 vScale = hScale; 00701 if (hScale >= 1 && hScale <= 4 && vScale >= 1 && vScale <= 4) { 00702 reg &= 0xF0; // keep the high nibble as is. 00703 reg |= ((hScale - 1) << 2); 00704 reg |= ((vScale - 1) << 0); 00705 WriteCommand(0x22, reg); 00706 return noerror; 00707 } else { 00708 return bad_parameter; 00709 } 00710 } 00711 00712 00713 int RA8875::_putc(int c) 00714 { 00715 if (font == NULL) { 00716 return _internal_putc(c); 00717 } else { 00718 return _external_putc(c); 00719 } 00720 } 00721 00722 00723 int RA8875::_external_putc(int c) 00724 { 00725 if (c) { 00726 if (c == '\r') { 00727 cursor_x = 0; 00728 } else if (c == '\n') { 00729 cursor_y += font[2]; 00730 } else { 00731 int advance = character(cursor_x, cursor_y, c); // advance tells us how many pixels we advanced 00732 //INFO("x,y,advance %d,%d,%d", cursor_x, cursor_y, advance); 00733 if (advance) { 00734 cursor_x += advance; 00735 if (cursor_x >= width()) { 00736 cursor_x = 0; 00737 cursor_y += font[2]; 00738 if (cursor_y >= height()) { 00739 cursor_y = 0; // @todo Should it scroll? 00740 } 00741 } 00742 } 00743 } 00744 } 00745 return c; 00746 } 00747 00748 00749 int RA8875::_internal_putc(int c) 00750 { 00751 if (c) { 00752 unsigned char mwcr0; 00753 00754 mwcr0 = ReadCommand(0x40); 00755 if ((mwcr0 & 0x80) == 0x00) { 00756 WriteCommand(0x40, 0x80 | mwcr0); // Put in Text mode if not already 00757 } 00758 if (c == '\r') { 00759 loc_t x; 00760 x = ReadCommand(0x30) | (ReadCommand(0x31) << 8); // Left edge of active window 00761 WriteCommandW(0x2A, x); 00762 } else if (c == '\n') { 00763 loc_t y; 00764 y = ReadCommand(0x2C) | (ReadCommand(0x2D) << 8); // current y location 00765 y += fontheight(); 00766 if (y >= height()) // @TODO after bottom of active window, then scroll window? 00767 y = 0; 00768 WriteCommandW(0x2C, y); 00769 } else { 00770 WriteCommand(0x02); // RA8875 Internal Fonts 00771 _select(true); 00772 WriteData(c); 00773 _WaitWhileBusy(0x80); 00774 _select(false); 00775 } 00776 } 00777 return c; 00778 } 00779 00780 00781 RetCode_t RA8875::_StartGraphicsStream(void) 00782 { 00783 WriteCommand(0x40,0x00); // Graphics write mode 00784 WriteCommand(0x02); // Prepare for streaming data 00785 return noerror; 00786 } 00787 00788 00789 RetCode_t RA8875::_EndGraphicsStream(void) 00790 { 00791 return noerror; 00792 } 00793 00794 00795 RetCode_t RA8875::_putp(color_t pixel) 00796 { 00797 WriteDataW((pixel>>8) | (pixel<<8)); 00798 return noerror; 00799 } 00800 00801 00802 void RA8875::puts(loc_t x, loc_t y, const char * string) 00803 { 00804 SetTextCursor(x,y); 00805 puts(string); 00806 } 00807 00808 00809 void RA8875::puts(const char * string) 00810 { 00811 unsigned char mwcr0 = ReadCommand(0x40); 00812 00813 if (font == NULL) { 00814 if ((mwcr0 & 0x80) == 0x00) 00815 WriteCommand(0x40,0x80); // Put in Text mode if not already 00816 } else { 00817 _StartGraphicsStream(); 00818 } 00819 if (*string != '\0') { 00820 #if 1 00821 while (*string) { // @TODO calling individual _putc is slower... optimizations? 00822 _putc(*string++); 00823 } 00824 #else 00825 WriteCommand(0x02); 00826 _select(true); 00827 while (*string != '\0') { 00828 WriteData(*string); 00829 ++string; 00830 _WaitWhileBusy(0x80); 00831 } 00832 _select(false); 00833 #endif 00834 } 00835 if (font) 00836 _EndGraphicsStream(); 00837 } 00838 00839 00840 RetCode_t RA8875::SetGraphicsCursor(loc_t x, loc_t y) 00841 { 00842 WriteCommandW(0x46, x); 00843 WriteCommandW(0x48, y); 00844 return noerror; 00845 } 00846 00847 00848 RetCode_t RA8875::SetGraphicsCursorRead(loc_t x, loc_t y) 00849 { 00850 //WriteCommand(0x40, 0); // Graphics mode 00851 //WriteCommand(0x45, 0); // left->right, top->bottom 00852 WriteCommandW(0x4A, x); 00853 WriteCommandW(0x4C, y); 00854 return noerror; 00855 } 00856 00857 00858 RetCode_t RA8875::window(loc_t x, loc_t y, dim_t width, dim_t height) 00859 { 00860 GraphicsDisplay::window(x,y, width,height); 00861 WriteCommandW(0x30, x); 00862 WriteCommandW(0x32, y); 00863 WriteCommandW(0x34, (x+width-1)); 00864 WriteCommandW(0x36, (y+height-1)); 00865 SetGraphicsCursor(x,y); 00866 return noerror; 00867 } 00868 00869 00870 RetCode_t RA8875::cls(uint16_t layers) 00871 { 00872 RetCode_t ret; 00873 00874 PERFORMANCE_RESET; 00875 if (layers == 0) { 00876 ret = clsw(FULLWINDOW); 00877 ret = SetTextCursor(0,0); 00878 } else if (layers > 3) { 00879 ret = bad_parameter; 00880 } else { 00881 uint16_t prevLayer = GetDrawingLayer(); 00882 if (layers & 1) { 00883 SelectDrawingLayer(0); 00884 clsw(FULLWINDOW); 00885 } 00886 if (layers & 2) { 00887 SelectDrawingLayer(1); 00888 clsw(FULLWINDOW); 00889 } 00890 ret = SelectDrawingLayer(prevLayer); 00891 } 00892 REGISTERPERFORMANCE(PRF_CLS); 00893 return ret; 00894 } 00895 00896 00897 RetCode_t RA8875::clsw(RA8875::Region_t region) 00898 { 00899 PERFORMANCE_RESET; 00900 WriteCommand(0x8E, (region == ACTIVEWINDOW) ? 0xC0 : 0x80); 00901 _WaitWhileReg(0x8E, 0x80); 00902 REGISTERPERFORMANCE(PRF_CLS); 00903 return noerror; 00904 } 00905 00906 00907 RetCode_t RA8875::pixel(loc_t x, loc_t y, color_t color) 00908 { 00909 RetCode_t ret; 00910 00911 PERFORMANCE_RESET; 00912 #if 1 00913 ret = pixelStream(&color, 1, x,y); 00914 #else 00915 foreground(color); 00916 ret = pixel(x,y); 00917 #endif 00918 REGISTERPERFORMANCE(PRF_DRAWPIXEL); 00919 return ret; 00920 } 00921 00922 00923 RetCode_t RA8875::pixel(loc_t x, loc_t y) 00924 { 00925 RetCode_t ret; 00926 00927 PERFORMANCE_RESET; 00928 color_t color = GetForeColor(); 00929 #if 1 00930 ret = pixelStream(&color, 1, x, y); 00931 #else 00932 WriteCommand(0x40,0x00); // Graphics write mode 00933 SetGraphicsCursor(x, y); 00934 WriteCommand(0x02); 00935 WriteDataW(color); 00936 ret = noerror; 00937 #endif 00938 REGISTERPERFORMANCE(PRF_DRAWPIXEL); 00939 return ret; 00940 } 00941 00942 00943 RetCode_t RA8875::pixelStream(color_t * p, uint32_t count, loc_t x, loc_t y) 00944 { 00945 PERFORMANCE_RESET; 00946 WriteCommand(0x40,0x00); // Graphics write mode 00947 SetGraphicsCursor(x, y); 00948 WriteCommand(0x02); 00949 _select(true); 00950 _spiwrite(0x00); // Cmd: write data 00951 while (count--) { 00952 _spiwrite(*p >> 8); 00953 _spiwrite(*p & 0xFF); 00954 p++; 00955 } 00956 _select(false); 00957 REGISTERPERFORMANCE(PRF_PIXELSTREAM); 00958 return(noerror); 00959 } 00960 00961 00962 color_t RA8875::getPixel(loc_t x, loc_t y) 00963 { 00964 color_t pixel; 00965 00966 PERFORMANCE_RESET; 00967 //WriteCommand(0x45,0x00); // read left->right, top->bottom 00968 WriteCommand(0x40,0x00); // Graphics write mode 00969 SetGraphicsCursorRead(x, y); 00970 WriteCommand(0x02); 00971 _select(true); 00972 _spiwrite(0x40); // Cmd: read data 00973 _spiwrite(0x00); // dummy read 00974 pixel = _spiread(); 00975 pixel |= (_spiread() << 8); 00976 _select(false); 00977 REGISTERPERFORMANCE(PRF_READPIXEL); 00978 return pixel; 00979 } 00980 00981 00982 RetCode_t RA8875::getPixelStream(color_t * p, uint32_t count, loc_t x, loc_t y) 00983 { 00984 color_t pixel; 00985 00986 PERFORMANCE_RESET; 00987 //WriteCommand(0x45,0x00); // read left->right, top->bottom 00988 WriteCommand(0x40,0x00); // Graphics write mode 00989 SetGraphicsCursorRead(x, y); 00990 WriteCommand(0x02); 00991 _select(true); 00992 _spiwrite(0x40); // Cmd: read data 00993 _spiwrite(0x00); // dummy read 00994 while (count--) { 00995 pixel = _spiread(); 00996 pixel |= (_spiread() << 8); 00997 *p++ = pixel; 00998 } 00999 _select(false); 01000 REGISTERPERFORMANCE(PRF_READPIXELSTREAM); 01001 return noerror; 01002 } 01003 01004 01005 RetCode_t RA8875::line(loc_t x1, loc_t y1, loc_t x2, loc_t y2, color_t color) 01006 { 01007 foreground(color); 01008 return line(x1,y1,x2,y2); 01009 } 01010 01011 01012 RetCode_t RA8875::line(loc_t x1, loc_t y1, loc_t x2, loc_t y2) 01013 { 01014 PERFORMANCE_RESET; 01015 if (x1 == x2 && y1 == y2) { 01016 pixel(x1, y1); 01017 } else { 01018 WriteCommandW(0x91, x1); 01019 WriteCommandW(0x93, y1); 01020 WriteCommandW(0x95, x2); 01021 WriteCommandW(0x97, y2); 01022 unsigned char drawCmd = 0x00; // Line 01023 WriteCommand(0x90, drawCmd); 01024 WriteCommand(0x90, 0x80 + drawCmd); // Start drawing. 01025 _WaitWhileReg(0x90, 0x80); 01026 } 01027 REGISTERPERFORMANCE(PRF_DRAWLINE); 01028 return noerror; 01029 } 01030 01031 RetCode_t RA8875::fillrect(rect_t r, color_t color, fill_t fillit) 01032 { 01033 return rect(r.p1.x, r.p1.y, r.p2.x, r.p2.y, color, fillit); 01034 } 01035 01036 RetCode_t RA8875::fillrect(loc_t x1, loc_t y1, loc_t x2, loc_t y2, 01037 color_t color, fill_t fillit) 01038 { 01039 return rect(x1,y1,x2,y2,color,fillit); 01040 } 01041 01042 RetCode_t RA8875::rect(rect_t r, color_t color, fill_t fillit) 01043 { 01044 return rect(r.p1.x, r.p1.y, r.p2.x, r.p2.y, color, fillit); 01045 } 01046 01047 RetCode_t RA8875::rect(loc_t x1, loc_t y1, loc_t x2, loc_t y2, 01048 color_t color, fill_t fillit) 01049 { 01050 foreground(color); 01051 return rect(x1,y1,x2,y2,fillit); 01052 } 01053 01054 01055 RetCode_t RA8875::rect(loc_t x1, loc_t y1, loc_t x2, loc_t y2, 01056 fill_t fillit) 01057 { 01058 PERFORMANCE_RESET; 01059 if (x1 == x2 && y1 == y2) { 01060 pixel(x1, y1); 01061 } else if (x1 == x2) { 01062 line(x1, y1, x2, y2); 01063 } else if (y1 == y2) { 01064 line(x1, y1, x2, y2); 01065 } else { 01066 WriteCommandW(0x91, x1); 01067 WriteCommandW(0x93, y1); 01068 WriteCommandW(0x95, x2); 01069 WriteCommandW(0x97, y2); 01070 unsigned char drawCmd = 0x10; // Rectangle 01071 if (fillit == FILL) 01072 drawCmd |= 0x20; 01073 WriteCommand(0x90, drawCmd); 01074 WriteCommand(0x90, 0x80 + drawCmd); // Start drawing. 01075 _WaitWhileReg(0x90, 0x80); 01076 } 01077 REGISTERPERFORMANCE(PRF_DRAWRECTANGLE); 01078 return noerror; 01079 } 01080 01081 01082 RetCode_t RA8875::fillroundrect(loc_t x1, loc_t y1, loc_t x2, loc_t y2, 01083 dim_t radius1, dim_t radius2, color_t color, fill_t fillit) 01084 { 01085 foreground(color); 01086 return roundrect(x1,y1,x2,y2,radius1,radius2,fillit); 01087 } 01088 01089 01090 RetCode_t RA8875::roundrect(loc_t x1, loc_t y1, loc_t x2, loc_t y2, 01091 dim_t radius1, dim_t radius2, color_t color, fill_t fillit) 01092 { 01093 foreground(color); 01094 return roundrect(x1,y1,x2,y2,radius1,radius2,fillit); 01095 } 01096 01097 01098 RetCode_t RA8875::roundrect(loc_t x1, loc_t y1, loc_t x2, loc_t y2, 01099 dim_t radius1, dim_t radius2, fill_t fillit) 01100 { 01101 RetCode_t ret = noerror; 01102 01103 PERFORMANCE_RESET; 01104 if (x1 > x2 || y1 > y2 || (radius1 > (x2-x1)/2) || (radius2 > (y2-y1)/2) ) { 01105 ret = bad_parameter; 01106 } else if (x1 == x2 && y1 == y2) { 01107 pixel(x1, y1); 01108 } else if (x1 == x2) { 01109 line(x1, y1, x2, y2); 01110 } else if (y1 == y2) { 01111 line(x1, y1, x2, y2); 01112 } else { 01113 WriteCommandW(0x91, x1); 01114 WriteCommandW(0x93, y1); 01115 WriteCommandW(0x95, x2); 01116 WriteCommandW(0x97, y2); 01117 WriteCommandW(0xA1, radius1); 01118 WriteCommandW(0xA3, radius2); 01119 // Should not need this... 01120 WriteCommandW(0xA5, 0); 01121 WriteCommandW(0xA7, 0); 01122 unsigned char drawCmd = 0x20; // Rounded Rectangle 01123 if (fillit == FILL) 01124 drawCmd |= 0x40; 01125 WriteCommand(0xA0, drawCmd); 01126 WriteCommand(0xA0, 0x80 + drawCmd); // Start drawing. 01127 _WaitWhileReg(0xA0, 0x80); 01128 } 01129 REGISTERPERFORMANCE(PRF_DRAWROUNDEDRECTANGLE); 01130 return ret; 01131 } 01132 01133 01134 RetCode_t RA8875::triangle(loc_t x1, loc_t y1, loc_t x2, loc_t y2, 01135 loc_t x3, loc_t y3, color_t color, fill_t fillit) 01136 { 01137 RetCode_t ret; 01138 01139 foreground(color); 01140 ret = triangle(x1,y1,x2,y2,x3,y3,fillit); 01141 return ret; 01142 } 01143 01144 01145 RetCode_t RA8875::filltriangle(loc_t x1, loc_t y1, loc_t x2, loc_t y2, 01146 loc_t x3, loc_t y3, color_t color, fill_t fillit) 01147 { 01148 RetCode_t ret; 01149 01150 foreground(color); 01151 ret = triangle(x1,y1,x2,y2,x3,y3,fillit); 01152 return ret; 01153 } 01154 01155 01156 RetCode_t RA8875::triangle(loc_t x1, loc_t y1 ,loc_t x2, loc_t y2, 01157 loc_t x3, loc_t y3, fill_t fillit) 01158 { 01159 RetCode_t ret = noerror; 01160 01161 PERFORMANCE_RESET; 01162 if (x1 == x2 && y1 == y2 && x1 == x3 && y1 == y3) { 01163 pixel(x1, y1); 01164 } else { 01165 WriteCommandW(0x91, x1); 01166 WriteCommandW(0x93, y1); 01167 WriteCommandW(0x95, x2); 01168 WriteCommandW(0x97, y2); 01169 WriteCommandW(0xA9, x3); 01170 WriteCommandW(0xAB, y3); 01171 unsigned char drawCmd = 0x01; // Triangle 01172 if (fillit == FILL) 01173 drawCmd |= 0x20; 01174 WriteCommand(0x90, drawCmd); 01175 WriteCommand(0x90, 0x80 + drawCmd); // Start drawing. 01176 _WaitWhileReg(0x90, 0x80); 01177 } 01178 REGISTERPERFORMANCE(PRF_DRAWTRIANGLE); 01179 return ret; 01180 } 01181 01182 RetCode_t RA8875::circle(loc_t x, loc_t y, dim_t radius, 01183 color_t color, fill_t fillit) 01184 { 01185 foreground(color); 01186 return circle(x,y,radius,fillit); 01187 } 01188 01189 01190 RetCode_t RA8875::fillcircle(loc_t x, loc_t y, dim_t radius, 01191 color_t color, fill_t fillit) 01192 { 01193 foreground(color); 01194 return circle(x,y,radius,fillit); 01195 } 01196 01197 01198 RetCode_t RA8875::circle(loc_t x, loc_t y, dim_t radius, fill_t fillit) 01199 { 01200 RetCode_t ret = noerror; 01201 01202 PERFORMANCE_RESET; 01203 if (radius <= 0) { 01204 ret = bad_parameter; 01205 } else if (radius == 1) { 01206 pixel(x,y); 01207 } else { 01208 WriteCommandW(0x99, x); 01209 WriteCommandW(0x9B, y); 01210 WriteCommand(0x9d, radius & 0xFF); 01211 unsigned char drawCmd = 0x00; // Circle 01212 if (fillit == FILL) 01213 drawCmd |= 0x20; 01214 WriteCommand(0x90, drawCmd); 01215 WriteCommand(0x90, 0x40 + drawCmd); // Start drawing. 01216 _WaitWhileReg(0x90, 0x40); 01217 } 01218 REGISTERPERFORMANCE(PRF_DRAWCIRCLE); 01219 return ret; 01220 } 01221 01222 01223 RetCode_t RA8875::ellipse(loc_t x, loc_t y, dim_t radius1, dim_t radius2, color_t color, fill_t fillit) 01224 { 01225 foreground(color); 01226 return ellipse(x,y,radius1,radius2,fillit); 01227 } 01228 01229 01230 RetCode_t RA8875::fillellipse(loc_t x, loc_t y, dim_t radius1, dim_t radius2, color_t color, fill_t fillit) 01231 { 01232 foreground(color); 01233 return ellipse(x,y,radius1,radius2,fillit); 01234 } 01235 01236 01237 RetCode_t RA8875::ellipse(loc_t x, loc_t y, dim_t radius1, dim_t radius2, fill_t fillit) 01238 { 01239 RetCode_t ret = noerror; 01240 01241 PERFORMANCE_RESET; 01242 if (radius1 <= 0 || radius2 <= 0) { 01243 ; // do nothing 01244 } else if (radius1 == 1 && radius2 == 1) { 01245 pixel(x, y); 01246 } else { 01247 WriteCommandW(0xA5, x); 01248 WriteCommandW(0xA7, y); 01249 WriteCommandW(0xA1, radius1); 01250 WriteCommandW(0xA3, radius2); 01251 unsigned char drawCmd = 0x00; // Ellipse 01252 if (fillit == FILL) 01253 drawCmd |= 0x40; 01254 WriteCommand(0xA0, drawCmd); 01255 WriteCommand(0xA0, 0x80 + drawCmd); // Start drawing. 01256 _WaitWhileReg(0xA0, 0x80); 01257 } 01258 REGISTERPERFORMANCE(PRF_DRAWELLIPSE); 01259 return ret; 01260 } 01261 01262 01263 RetCode_t RA8875::frequency(unsigned long Hz, unsigned long Hz2) 01264 { 01265 spiwritefreq = Hz; 01266 if (Hz2 != 0) 01267 spireadfreq = Hz2; 01268 else 01269 spireadfreq = Hz/2; 01270 _setWriteSpeed(true); 01271 // __ ___ 01272 // Clock ___A Rising edge latched 01273 // ___ ____ 01274 // Data ___X____ 01275 spi.format(8, 3); // 8 bits and clock to data phase 0 01276 return noerror; 01277 } 01278 01279 void RA8875::_setWriteSpeed(bool writeSpeed) 01280 { 01281 if (writeSpeed) { 01282 spi.frequency(spiwritefreq); 01283 spiWriteSpeed = true; 01284 } else { 01285 spi.frequency(spireadfreq); 01286 spiWriteSpeed = false; 01287 } 01288 } 01289 01290 RetCode_t RA8875::Power(bool on) 01291 { 01292 WriteCommand(0x01, (on) ? 0x80 : 0x00); 01293 return noerror; 01294 } 01295 01296 01297 RetCode_t RA8875::Backlight_u8(unsigned char brightness) 01298 { 01299 static bool is_enabled = false; 01300 if (brightness == 0) { 01301 WriteCommand(0x8a); // Disable the PWM 01302 WriteData(0x00); 01303 is_enabled = false; 01304 } else if (!is_enabled) { 01305 WriteCommand(0x8a); // Enable the PWM 01306 WriteData(0x80); 01307 WriteCommand(0x8a); // Not sure why this is needed, but following the pattern 01308 WriteData(0x81); // open PWM (SYS_CLK / 2 as best I can tell) 01309 is_enabled = true; 01310 } 01311 WriteCommand(0x8b, brightness); // Brightness parameter 0xff-0x00 01312 return noerror; 01313 } 01314 01315 01316 RetCode_t RA8875::Backlight(float brightness) 01317 { 01318 unsigned char b; 01319 01320 if (brightness >= 1.0) 01321 b = 255; 01322 else if (brightness <= 0.0) 01323 b = 0; 01324 else 01325 b = (unsigned char)(brightness * 255); 01326 return Backlight_u8(b); 01327 } 01328 01329 01330 RetCode_t RA8875::set_font(const unsigned char * _font) 01331 { 01332 if (font && ! _font) { 01333 SetTextCursor(cursor_x, cursor_y); // soft-font cursor -> hw cursor 01334 } 01335 font = _font; 01336 GraphicsDisplay::set_font(_font); 01337 return noerror; // trusting them, but it might be good to put some checks in here... 01338 } 01339 01340 01341 RetCode_t RA8875::background(color_t color) 01342 { 01343 GraphicsDisplay::background(color); 01344 WriteCommand(0x60, (color>>11)); // BGCR0 01345 WriteCommand(0x61, (unsigned char)(color>>5)); // BGCR0 01346 WriteCommand(0x62, (unsigned char)(color)); // BGCR0 01347 return noerror; 01348 } 01349 01350 01351 RetCode_t RA8875::background(unsigned char r, unsigned char g, unsigned char b) 01352 { 01353 background(RGB(r,g,b)); 01354 // WriteCommand(0x60, r); 01355 // WriteCommand(0x61, g); 01356 // WriteCommand(0x62, b); 01357 return noerror; 01358 } 01359 01360 01361 RetCode_t RA8875::foreground(color_t color) 01362 { 01363 GraphicsDisplay::foreground(color); 01364 WriteCommand(0x63, (unsigned char)(color>>11)); 01365 WriteCommand(0x64, (unsigned char)(color>>5)); 01366 WriteCommand(0x65, (unsigned char)(color)); 01367 return noerror; 01368 } 01369 01370 01371 RetCode_t RA8875::foreground(unsigned char r, unsigned char g, unsigned char b) 01372 { 01373 foreground(RGB(r,g,b)); 01374 // WriteCommand(0x63, r); 01375 // WriteCommand(0x64, g); 01376 // WriteCommand(0x65, b); 01377 return noerror; 01378 } 01379 01380 01381 color_t RA8875::GetForeColor(void) 01382 { 01383 color_t color; 01384 01385 color = (ReadCommand(0x63) & 0x1F) << 11; 01386 color |= (ReadCommand(0x64) & 0x3F) << 5; 01387 color |= (ReadCommand(0x65) & 0x1F); 01388 return color; 01389 } 01390 01391 01392 color_t RA8875::DOSColor(int i) 01393 { 01394 const color_t colors[16] = { 01395 Black, Blue, Green, Cyan, 01396 Red, Magenta, Brown, Gray, 01397 Charcoal, BrightBlue, BrightGreen, BrightCyan, 01398 Orange, Pink, Yellow, White 01399 }; 01400 if (i < 16) 01401 return colors[i]; 01402 else 01403 return 0; 01404 } 01405 01406 01407 const char * RA8875::DOSColorNames(int i) 01408 { 01409 const char * names[16] = { 01410 "Black", "Blue", "Green", "Cyan", 01411 "Red", "Magenta", "Brown", "Gray", 01412 "Charcoal", "BrightBlue", "BrightGreen", "BrightCyan", 01413 "Orange", "Pink", "Yellow", "White" 01414 }; 01415 if (i < 16) 01416 return names[i]; 01417 else 01418 return NULL; 01419 } 01420 01421 01422 /////////////////////////////////////////////////////////////// 01423 // Private functions 01424 01425 unsigned char RA8875::_spiwrite(unsigned char data) 01426 { 01427 unsigned char retval; 01428 01429 if (!spiWriteSpeed) 01430 _setWriteSpeed(true); 01431 retval = spi.write(data); 01432 return retval; 01433 } 01434 01435 01436 unsigned char RA8875::_spiread(void) 01437 { 01438 unsigned char retval; 01439 unsigned char data = 0; 01440 01441 if (spiWriteSpeed) 01442 _setWriteSpeed(false); 01443 retval = spi.write(data); 01444 return retval; 01445 } 01446 01447 01448 RetCode_t RA8875::_select(bool chipsel) 01449 { 01450 cs = (chipsel == true) ? 0 : 1; 01451 return noerror; 01452 } 01453 01454 01455 RetCode_t RA8875::PrintScreen(uint16_t layer, loc_t x, loc_t y, dim_t w, dim_t h, const char *Name_BMP) 01456 { 01457 #if 1 01458 (void)layer; 01459 return PrintScreen(x, y, w, h, Name_BMP); 01460 #else 01461 // This is the deprecated interface and with the changes it is no longer implemented correctly. 01462 uint16_t curLayer = GetDrawingLayer(); 01463 RetCode_t ret = SelectDrawingLayer(layer); 01464 if (ret == noerror) { 01465 ret = PrintScreen(x, y, w, h, Name_BMP); 01466 } 01467 SelectDrawingLayer(curLayer); 01468 return ret; 01469 #endif 01470 } 01471 01472 01473 RetCode_t RA8875::PrintScreen(loc_t x, loc_t y, dim_t w, dim_t h, const char *Name_BMP) 01474 { 01475 BITMAPFILEHEADER BMP_Header; 01476 BITMAPINFOHEADER BMP_Info; 01477 01478 INFO("(%d,%d) - (%d,%d) %s", x,y,w,h,Name_BMP); 01479 if (x >= 0 && x < width() 01480 && y >= 0 && y < height() 01481 && w > 0 && x + w <= width() 01482 && h > 0 && y + h <= height()) { 01483 01484 BMP_Header.bfType = BF_TYPE; 01485 BMP_Header.bfSize = (w * h * sizeof(RGBQUAD)) + sizeof(BMP_Header) + sizeof(BMP_Header); 01486 BMP_Header.bfReserved1 = 0; 01487 BMP_Header.bfReserved2 = 0; 01488 BMP_Header.bfOffBits = sizeof(BMP_Header) + sizeof(BMP_Header); 01489 01490 BMP_Info.biSize = sizeof(BMP_Info); 01491 BMP_Info.biWidth = w; 01492 BMP_Info.biHeight = h; 01493 BMP_Info.biPlanes = 1; 01494 BMP_Info.biBitCount = 24; 01495 BMP_Info.biCompression = BI_RGB; 01496 BMP_Info.biSizeImage = 0; 01497 BMP_Info.biXPelsPerMeter = 0; 01498 BMP_Info.biYPelsPerMeter = 0; 01499 BMP_Info.biClrUsed = 0; 01500 BMP_Info.biClrImportant = 0; 01501 01502 INFO("Writing {%s}", Name_BMP); 01503 FILE *Image = fopen(Name_BMP, "wb"); 01504 if (!Image) { 01505 ERR("File not found"); 01506 return(file_not_found); 01507 } 01508 01509 // Be optimistic - don't check for errors. 01510 //HexDump("BMP_Header", (uint8_t *)&BMP_Header, sizeof(BMP_Header)); 01511 fwrite(&BMP_Header, sizeof(char), sizeof(BMP_Header), Image); 01512 //INFO("fwrite returned %d", r); 01513 01514 //HexDump("BMP_Info", (uint8_t *)&BMP_Info, sizeof(BMP_Info)); 01515 fwrite(&BMP_Info, sizeof(char), sizeof(BMP_Info), Image); 01516 //INFO("fwrite returned %d", r); 01517 01518 int lineBufSize = ((24 * w + 7)/8); 01519 uint8_t * lineBuffer = (uint8_t *)malloc(lineBufSize); 01520 if (lineBuffer == NULL) { 01521 fclose(Image); 01522 ERR("Not enough RAM for lineBuffer"); 01523 return(not_enough_ram); 01524 } 01525 color_t * pixelBuffer = (color_t *)malloc(w * sizeof(color_t)); 01526 color_t * pixelBuffer2 = (color_t *)malloc(w * sizeof(color_t)); 01527 color_t transparency = GetBackgroundTransparencyColor(); 01528 unsigned char ltpr0 = ReadCommand(0x52) & 0x7; 01529 01530 if (pixelBuffer == NULL || pixelBuffer2 == NULL) { 01531 fclose(Image); 01532 free(lineBuffer); 01533 ERR("Not enough RAM for pixelBuffer"); 01534 if (pixelBuffer) 01535 free(pixelBuffer); 01536 return(not_enough_ram); 01537 } 01538 01539 uint16_t prevLayer = GetDrawingLayer(); 01540 // If only one of the layers is visible, select that layer 01541 switch(ltpr0) { 01542 case 0: 01543 SelectDrawingLayer(0); 01544 break; 01545 case 1: 01546 SelectDrawingLayer(1); 01547 break; 01548 default: 01549 break; 01550 } 01551 01552 // Read the display from the last line toward the top 01553 // so we can write the file in one pass. 01554 for (int j = h - 1; j >= 0; j--) { 01555 if (ltpr0 >= 2) // Need to combine the layers... 01556 SelectDrawingLayer(0); // so read layer 0 first 01557 // Read one line of pixels to a local buffer 01558 if (getPixelStream(pixelBuffer, w, x,y+j) != noerror) { 01559 ERR("getPixelStream error, and no recovery handler..."); 01560 } 01561 if (ltpr0 >= 2) { // Need to combine the layers... 01562 SelectDrawingLayer(1); // so read layer 0 first 01563 if (getPixelStream(pixelBuffer2, w, x,y+j) != noerror) { 01564 ERR("getPixelStream error, and no recovery handler..."); 01565 } 01566 } 01567 // Convert the local buffer to RGBQUAD format 01568 int lb = 0; 01569 for (int i=0; i<w; i++) { 01570 RGBQUAD q0 = RGB16ToRGBQuad(pixelBuffer[x+i]); // Scale to 24-bits 01571 RGBQUAD q1 = RGB16ToRGBQuad(pixelBuffer2[x+i]); // Scale to 24-bits 01572 switch (ltpr0) { 01573 case 0: 01574 case 1: 01575 case 2: // lighten-overlay (@TODO Not supported yet) 01576 case 6: // Floating Windows (@TODO not sure how to support) 01577 default: // Reserved... 01578 lineBuffer[lb++] = q0.rgbBlue; 01579 lineBuffer[lb++] = q0.rgbGreen; 01580 lineBuffer[lb++] = q0.rgbRed; 01581 break; 01582 case 3: // transparent mode (@TODO Read the background color register for transparent) 01583 case 4: // boolean or 01584 lineBuffer[lb++] = q0.rgbBlue | q1.rgbBlue; 01585 lineBuffer[lb++] = q0.rgbGreen | q1.rgbGreen; 01586 lineBuffer[lb++] = q0.rgbRed | q1.rgbRed; 01587 break; 01588 case 5: // boolean AND 01589 lineBuffer[lb++] = q0.rgbBlue & q1.rgbBlue; 01590 lineBuffer[lb++] = q0.rgbGreen & q1.rgbGreen; 01591 lineBuffer[lb++] = q0.rgbRed & q1.rgbRed; 01592 break; 01593 } 01594 } 01595 if (j == h - 1) 01596 HexDump("Line", lineBuffer, lineBufSize); 01597 // Write to disk 01598 fwrite(lineBuffer, sizeof(char), lb, Image); 01599 } 01600 SelectDrawingLayer(prevLayer); 01601 fclose(Image); 01602 free(pixelBuffer2); // don't leak memory. 01603 free(pixelBuffer); 01604 free(lineBuffer); 01605 INFO("Image closed"); 01606 return noerror; 01607 } else { 01608 return bad_parameter; 01609 } 01610 } 01611 01612 01613 // ########################################################################## 01614 // ########################################################################## 01615 // ########################################################################## 01616 01617 #ifdef TESTENABLE 01618 01619 #include "Arial12x12.h" 01620 #include "Small_6.h" 01621 01622 // ______________ ______________ ______________ _______________ 01623 // /_____ _____/ / ___________/ / ___________/ /_____ ______/ 01624 // / / / / / / / / 01625 // / / / /___ / /__________ / / 01626 // / / / ____/ /__________ / / / 01627 // / / / / / / / / 01628 // / / / /__________ ___________/ / / / 01629 // /__/ /_____________/ /_____________/ /__/ 01630 // 01631 // Everything from here down is test code. 01632 // 01633 bool SuppressSlowStuff = false; 01634 01635 void TextWrapTest(RA8875 & display, Serial & pc) 01636 { 01637 if (!SuppressSlowStuff) 01638 pc.printf("Text Wrap Test\r\n"); 01639 display.background(Black); 01640 display.foreground(Blue); 01641 display.cls(); 01642 display.Backlight_u8(255); 01643 display.puts(0,0, "Text Wrap Test.\r\n"); 01644 for (int i=1; i<60; i++) { 01645 display.printf("L%2d\n", i % 17); 01646 if (!SuppressSlowStuff) 01647 wait_ms(100); 01648 } 01649 if (!SuppressSlowStuff) 01650 wait_ms(3000); 01651 } 01652 01653 01654 void ShowKey(RA8875 & display, int key) 01655 { 01656 loc_t col, row; 01657 dim_t r1 = 25; 01658 color_t color = (key & 0x80) ? Red : Green; 01659 01660 key &= 0x7F; // remove the long-press flag 01661 row = (key - 1) / 5; 01662 col = (key - 1) % 5; 01663 if (col > 5) col = 5; 01664 if (row > 4) row = 4; 01665 display.circle(450 - + (2 * r1) * col, 200 - (2 * r1) * row, r1-2, color, FILL); 01666 } 01667 01668 void HideKey(RA8875 & display, int key) 01669 { 01670 loc_t col, row; 01671 dim_t r1 = 25; 01672 01673 row = (key - 1) / 5; 01674 col = (key - 1) % 5; 01675 if (col > 5) col = 5; 01676 if (row > 4) row = 4; 01677 display.background(Black); 01678 display.circle(450 - (2 * r1) * col, 200 - (2 * r1) * row, r1-2, Black, FILL); 01679 display.circle(450 - (2 * r1) * col, 200 - (2 * r1) * row, r1-2, Blue); 01680 } 01681 01682 void KeyPadTest(RA8875 & display, Serial & pc) 01683 { 01684 const uint8_t myMap[22] = { 01685 0, 01686 'a', 'b', 'c', 'd', 'e', 01687 'f', 'g', 'h', 'i', 'j', 01688 'k', 'l', 'm', 'n', 'o', 01689 'p', 'q', 'r', 's', 't', 01690 'x' 01691 }; 01692 01693 display.background(Black); 01694 display.foreground(Blue); 01695 display.cls(); 01696 display.Backlight_u8(255); 01697 display.puts(0,0, "KeyPad Test. Touch the keypad..."); 01698 pc.printf("\r\n" 01699 "Raw KeyPad Test. Keypad returns the key-number.\r\n" 01700 "Press [most] any PC keyboard key to advance to next test.\r\n"); 01701 RetCode_t ret = display.KeypadInit(true, true, 3, 7, 3); 01702 if (ret != noerror) 01703 pc.printf("returncode from KeypadInit is %d\r\n", ret); 01704 int lastKey = 0; 01705 while (!pc.readable()) { 01706 if (display.readable()) { 01707 int key = display.getc(); 01708 if (key) { 01709 if (((key & 0x7F) != lastKey) && (lastKey != 0)) 01710 HideKey(display, lastKey); 01711 ShowKey(display, key); 01712 lastKey = key & 0x7F; 01713 } else { 01714 // erase the last one 01715 if (lastKey) 01716 HideKey(display, lastKey); 01717 } 01718 } 01719 } 01720 (void)pc.getc(); 01721 pc.printf("\r\n" 01722 "Map KeyPad Test. Keypad returns the remapped key 'a' - 't'.\r\n" 01723 "Press [most] any PC keyboard key to advance to exit test.\r\n"); 01724 display.SetKeyMap(myMap); 01725 while (!pc.readable()) { 01726 if (display.readable()) { 01727 int key = display.getc(); 01728 bool longPress = key & 0x80; 01729 display.SetTextCursor(0, 120); 01730 display.printf("Long Press: %d\r\n", longPress); 01731 display.printf(" Remapped: %c %02X\r\n", (key) ? key & 0x7F : ' ', key); 01732 } 01733 } 01734 (void)pc.getc(); 01735 display.SetKeyMap(); 01736 pc.printf("\r\n"); 01737 } 01738 01739 void TextCursorTest(RA8875 & display, Serial & pc) 01740 { 01741 const char * iCursor = "The I-Beam cursor should be visible for this text.\r\n"; 01742 const char * uCursor = "The Underscore cursor should be visible for this text.\r\n"; 01743 const char * bCursor = "The Block cursor should be visible for this text.\r\n"; 01744 const char * bbCursor = "The Blinking Block cursor should be visible for this text.\r\n"; 01745 const char * p; 01746 int delay = 100; 01747 01748 if (!SuppressSlowStuff) 01749 pc.printf("Text Cursor Test\r\n"); 01750 else 01751 delay = 0; 01752 display.background(Black); 01753 display.foreground(Blue); 01754 display.cls(); 01755 display.Backlight_u8(255); 01756 display.puts(0,0, "Text Cursor Test."); 01757 01758 // visible, non-blinking 01759 display.SetTextCursor(0,20); 01760 display.SetTextCursorControl(RA8875::IBEAM, false); 01761 p = iCursor; 01762 while (*p) { 01763 display._putc(*p++); 01764 wait_ms(delay); 01765 } 01766 01767 display.SetTextCursorControl(RA8875::UNDER, false); 01768 p = uCursor; 01769 while (*p) { 01770 display._putc(*p++); 01771 wait_ms(delay); 01772 } 01773 01774 display.SetTextCursorControl(RA8875::BLOCK, false); 01775 p = bCursor; 01776 while (*p) { 01777 display._putc(*p++); 01778 wait_ms(delay); 01779 } 01780 01781 display.SetTextCursorControl(RA8875::BLOCK, true); 01782 p = bbCursor; 01783 while (*p) { 01784 display._putc(*p++); 01785 wait_ms(delay); 01786 } 01787 wait_ms(delay * 20); 01788 display.SetTextCursorControl(RA8875::NOCURSOR, false); 01789 } 01790 01791 01792 void BacklightTest(RA8875 & display, Serial & pc, float ramptime) 01793 { 01794 char buf[60]; 01795 unsigned int w = (ramptime * 1000)/ 256; 01796 int delay = 200; 01797 01798 if (!SuppressSlowStuff) 01799 pc.printf("Backlight Test - ramp over %f sec.\r\n", ramptime); 01800 else { 01801 delay = 0; 01802 w = 0; 01803 } 01804 display.Backlight_u8(0); 01805 display.background(White); 01806 display.foreground(Blue); 01807 display.cls(); 01808 wait_ms(delay); 01809 display.puts(0,0, "RA8875 Backlight Test - Ramp up."); 01810 for (int i=0; i <= 255; i++) { 01811 sprintf(buf, "%3d, %4d", i, w); 01812 display.puts(100,100,buf); 01813 display.Backlight_u8(i); 01814 wait_ms(w); 01815 } 01816 } 01817 01818 01819 void BacklightTest2(RA8875 & display, Serial & pc) 01820 { 01821 int delay = 20; 01822 01823 if (!SuppressSlowStuff) 01824 pc.printf("Backlight Test 2\r\n"); 01825 else 01826 delay = 0; 01827 01828 // Dim it out at the end of the tests. 01829 display.foreground(Blue); 01830 display.puts(0,0, "Ramp Backlight down."); 01831 // Ramp it off 01832 for (int i=255; i != 0; i--) { 01833 display.Backlight_u8(i); 01834 wait_ms(delay); 01835 } 01836 display.Backlight_u8(0); 01837 } 01838 01839 01840 void ExternalFontTest(RA8875 & display, Serial & pc) 01841 { 01842 if (!SuppressSlowStuff) 01843 pc.printf("External Font Test\r\n"); 01844 display.background(Black); 01845 display.foreground(Blue); 01846 display.cls(); 01847 display.Backlight(1); 01848 display.puts(0,0, "External Font Test."); 01849 01850 display.set_font(Small_6); 01851 display.puts(0,30, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\r\n"); 01852 01853 display.set_font(Arial12x12); 01854 display.puts("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\r\n"); 01855 display.set_font(); // restore to internal 01856 01857 display.puts("Normal font again."); 01858 //display.window(0,0, display.width(), display.height()); 01859 } 01860 01861 01862 void DOSColorTest(RA8875 & display, Serial & pc) 01863 { 01864 if (!SuppressSlowStuff) 01865 pc.printf("DOS Color Test\r\n"); 01866 display.background(Black); 01867 display.foreground(Blue); 01868 display.cls(); 01869 display.puts(0,0, "DOS Colors - Fore"); 01870 display.puts(280,0, "Back"); 01871 display.background(Gray); 01872 for (int i=0; i<16; i++) { 01873 display.foreground(display.DOSColor(i)); 01874 display.puts(160, i*16, display.DOSColorNames(i)); 01875 display.background(Black); 01876 } 01877 display.foreground(White); 01878 for (int i=0; i<16; i++) { 01879 display.background(display.DOSColor(i)); 01880 display.puts(360, i*16, display.DOSColorNames(i)); 01881 display.foreground(White); 01882 } 01883 } 01884 01885 01886 void WebColorTest(RA8875 & display, Serial & pc) 01887 { 01888 if (!SuppressSlowStuff) 01889 pc.printf("Web Color Test\r\n"); 01890 display.background(Black); 01891 display.foreground(Blue); 01892 display.window(0,0, display.width(), display.height()); 01893 display.cls(); 01894 display.SetTextFontSize(1,1); 01895 display.puts(200,0, "Web Color Test"); 01896 display.SetTextCursor(0,0); 01897 display.puts(" "); 01898 for (int i=0; i<16; i++) 01899 display.printf("%X", i&0xF); 01900 display.puts("\r\n0 "); 01901 for (int i=0; i<sizeof(WebColors)/sizeof(WebColors[0]); i++) { 01902 display.background(WebColors[i]); 01903 display.puts(" "); 01904 if (i % 16 == 15 && i < 255) { 01905 display.printf("\r\n%X ", ((i+1)/16)); 01906 } 01907 } 01908 display.SetTextFontSize(1,1); 01909 } 01910 01911 01912 void PixelTest(RA8875 & display, Serial & pc) 01913 { 01914 int i, c, x, y; 01915 01916 if (!SuppressSlowStuff) 01917 pc.printf("Pixel Test\r\n"); 01918 display.background(Black); 01919 display.foreground(Blue); 01920 display.cls(); 01921 display.puts(0,0, "Pixel Test"); 01922 for (i=0; i<1000; i++) { 01923 x = rand() % 480; 01924 y = 16 + rand() % (272-16); 01925 c = rand() % 16; 01926 //pc.printf(" (%d,%d) - %d\r\n", x,y,r1); 01927 display.pixel(x,y, display.DOSColor(c)); 01928 } 01929 } 01930 01931 01932 void LineTest(RA8875 & display, Serial & pc) 01933 { 01934 int i, x, y, x2, y2; 01935 01936 if (!SuppressSlowStuff) 01937 pc.printf("Line Test\r\n"); 01938 display.background(Black); 01939 display.foreground(Blue); 01940 display.cls(); 01941 display.puts(0,0, "Line Test"); 01942 for (i=0; i<16; i++) { 01943 // Lines 01944 x = rand() % 480; 01945 y = rand() % 272; 01946 x2 = rand() % 480; 01947 y2 = rand() % 272; 01948 display.line(x,y, x2,y2, display.DOSColor(i)); 01949 } 01950 display.foreground(BrightRed); 01951 display.foreground(BrightGreen); 01952 display.foreground(BrightBlue); 01953 display.line(55,50, 79,74, BrightRed); 01954 display.line(57,50, 81,74, BrightGreen); 01955 display.line(59,50, 83,74, BrightBlue); 01956 // horz 01957 display.line(30,40, 32,40, BrightRed); 01958 display.line(30,42, 32,42, BrightGreen); 01959 display.line(30,44, 32,44, BrightBlue); 01960 // vert 01961 display.line(20,40, 20,42, BrightRed); 01962 display.line(22,40, 22,42, BrightGreen); 01963 display.line(24,40, 24,42, BrightBlue); 01964 // compare point to line-point 01965 display.pixel(20,50, BrightRed); 01966 display.pixel(22,50, BrightGreen); 01967 display.pixel(24,50, BrightBlue); 01968 display.line(20,52, 20,52, BrightRed); 01969 display.line(22,52, 22,52, BrightGreen); 01970 display.line(24,52, 24,52, BrightBlue); 01971 01972 // point 01973 display.line(50,50, 50,50, Red); 01974 display.line(52,52, 52,52, Green); 01975 display.line(54,54, 54,54, Blue); 01976 display.line(60,60, 60,60, BrightRed); 01977 display.line(62,62, 62,62, BrightGreen); 01978 display.line(64,64, 64,64, BrightBlue); 01979 display.line(70,70, 70,70, DarkRed); 01980 display.line(72,72, 72,72, DarkGreen); 01981 display.line(74,74, 74,74, DarkBlue); 01982 } 01983 01984 01985 void RectangleTest(RA8875 & display, Serial & pc) 01986 { 01987 int i, x1,y1, x2,y2; 01988 01989 if (!SuppressSlowStuff) 01990 pc.printf("Rectangle Test\r\n"); 01991 display.background(Black); 01992 display.foreground(Blue); 01993 display.cls(); 01994 display.puts(0,0, "Rectangle Test"); 01995 for (i=0; i<16; i++) { 01996 x1 = rand() % 240; 01997 y1 = 50 + rand() % 200; 01998 x2 = rand() % 240; 01999 y2 = 50 + rand() % 200; 02000 display.rect(x1,y1, x2,y2, display.DOSColor(i)); 02001 02002 x1 = 240 + rand() % 240; 02003 y1 = 50 + rand() % 200; 02004 x2 = 240 + rand() % 240; 02005 y2 = 50 + rand() % 200; 02006 display.rect(x1,y1, x2,y2, FILL); 02007 } 02008 } 02009 02010 02011 void LayerTest(RA8875 & display, Serial & pc) 02012 { 02013 loc_t i, x1,y1, x2,y2, r1,r2; 02014 02015 if (!SuppressSlowStuff) 02016 pc.printf("Layer Test\r\n"); 02017 02018 display.SelectDrawingLayer(0); 02019 display.background(Black); 02020 display.foreground(Blue); 02021 display.cls(); 02022 display.puts(0,0, "Layer 0"); 02023 for (i=0; i<16; i++) { 02024 x1 = rand() % 240; 02025 y1 = 50 + rand() % 200; 02026 x2 = x1 + rand() % 100; 02027 y2 = y1 + rand() % 100; 02028 r1 = rand() % (x2 - x1)/2; 02029 r2 = rand() % (y2 - y1)/2; 02030 display.roundrect(x1,y1, x2,y2, r1,r2, display.DOSColor(i)); 02031 if (!SuppressSlowStuff) 02032 wait_ms(20); 02033 } 02034 if (!SuppressSlowStuff) 02035 wait_ms(1000); 02036 02037 display.SelectDrawingLayer(1); 02038 display.background(Black); 02039 display.foreground(Yellow); 02040 display.cls(); 02041 display.puts(240,0, "Layer 1"); 02042 for (i=0; i<16; i++) { 02043 x1 = 300 + rand() % 100; 02044 y1 = 70 + rand() % 200; 02045 r1 = rand() % min(y1 - 20, 100); 02046 display.circle(x1,y1,r1, display.DOSColor(i)); 02047 if (!SuppressSlowStuff) 02048 wait_ms(20); 02049 } 02050 display.SetLayerMode(RA8875::ShowLayer1); // Show it after the build-up 02051 if (!SuppressSlowStuff) 02052 wait_ms(2000); 02053 02054 display.SelectDrawingLayer(0); 02055 display.SetLayerMode(RA8875::ShowLayer0); // Show Layer 0 again 02056 if (!SuppressSlowStuff) 02057 wait_ms(1000); 02058 display.SetLayerMode(RA8875::TransparentMode); // Transparent mode 02059 if (!SuppressSlowStuff) 02060 wait_ms(1000); 02061 for (i=0; i<=8; i++) { 02062 display.SetLayerTransparency(i, 8-i); 02063 if (!SuppressSlowStuff) 02064 wait_ms(200); 02065 } 02066 02067 // Restore before we exit 02068 display.SetLayerTransparency(0, 0); 02069 display.SetLayerMode(RA8875::ShowLayer0); // Restore to layer 0 02070 } 02071 02072 02073 void RoundRectTest(RA8875 & display, Serial & pc) 02074 { 02075 loc_t i, x1,y1, x2,y2, r1,r2; 02076 02077 if (!SuppressSlowStuff) 02078 pc.printf("Round Rectangle Test\r\n"); 02079 display.background(Black); 02080 display.foreground(Blue); 02081 display.cls(); 02082 display.puts(0,0, "Rounded Rectangle Test"); 02083 02084 for (i=0; i<16; i++) { 02085 x1 = rand() % 240; 02086 y1 = 50 + rand() % 200; 02087 x2 = x1 + rand() % 100; 02088 y2 = y1 + rand() % 100; 02089 r1 = rand() % (x2 - x1)/2; 02090 r2 = rand() % (y2 - y1)/2; 02091 display.roundrect(x1,y1, x2,y2, 5,8, display.DOSColor(i)); 02092 02093 x1 = 240 + rand() % 240; 02094 y1 = 50 + rand() % 200; 02095 x2 = x1 + rand() % 100; 02096 y2 = y1 + rand() % 100; 02097 r1 = rand() % (x2 - x1)/2; 02098 r2 = rand() % (y2 - y1)/2; 02099 display.roundrect(x1,y1, x2,y2, r1,r2, FILL); 02100 } 02101 } 02102 02103 02104 void TriangleTest(RA8875 & display, Serial & pc) 02105 { 02106 int i, x1, y1, x2, y2, x3, y3; 02107 02108 if (!SuppressSlowStuff) 02109 pc.printf("Triangle Test\r\n"); 02110 display.background(Black); 02111 display.foreground(Blue); 02112 display.cls(); 02113 display.puts(0,0, "Triangle Test"); 02114 02115 x1 = 150; 02116 y1 = 2; 02117 x2 = 190; 02118 y2 = 7; 02119 x3 = 170; 02120 y3 = 16; 02121 display.triangle(x1,y1, x2,y2, x3,y3); 02122 02123 x1 = 200; 02124 y1 = 2; 02125 x2 = 240; 02126 y2 = 7; 02127 x3 = 220; 02128 y3 = 16; 02129 display.filltriangle(x1,y1, x2,y2, x3,y3, BrightRed); 02130 02131 x1 = 300; 02132 y1 = 2; 02133 x2 = 340; 02134 y2 = 7; 02135 x3 = 320; 02136 y3 = 16; 02137 display.triangle(x1,y1, x2,y2, x3,y3, NOFILL); 02138 02139 x1 = 400; 02140 y1 = 2; 02141 x2 = 440; 02142 y2 = 7; 02143 x3 = 420; 02144 y3 = 16; 02145 display.triangle(x1,y1, x2,y2, x3,y3, Blue); 02146 02147 for (i=0; i<16; i++) { 02148 x1 = rand() % 240; 02149 y1 = 50 + rand() % 200; 02150 x2 = rand() % 240; 02151 y2 = 50 + rand() % 200; 02152 x3 = rand() % 240; 02153 y3 = 50 + rand() % 200; 02154 display.triangle(x1,y1, x2,y2, x3,y3, display.DOSColor(i)); 02155 x1 = 240 + rand() % 240; 02156 y1 = 50 + rand() % 200; 02157 x2 = 240 + rand() % 240; 02158 y2 = 50 + rand() % 200; 02159 x3 = 240 + rand() % 240; 02160 y3 = 50 + rand() % 200; 02161 display.triangle(x1,y1, x2,y2, x3,y3, FILL); 02162 } 02163 } 02164 02165 02166 void CircleTest(RA8875 & display, Serial & pc) 02167 { 02168 int i, x, y, r1; 02169 02170 if (!SuppressSlowStuff) 02171 pc.printf("Circle Test\r\n"); 02172 display.background(Black); 02173 display.foreground(Blue); 02174 display.cls(); 02175 display.puts(0,0, "Circle Test"); 02176 for (i=0; i<16; i++) { 02177 x = 100 + rand() % 100; 02178 y = 70 + rand() % 200; 02179 r1 = rand() % min(y - 20, 100); 02180 //pc.printf(" (%d,%d) - %d\r\n", x,y,r1); 02181 display.circle(x,y,r1, display.DOSColor(i)); 02182 02183 x = 300 + rand() % 100; 02184 y = 70 + rand() % 200; 02185 r1 = rand() % min(y - 20, 100); 02186 //pc.printf(" (%d,%d) - %d FILL\r\n", x,y,r1); 02187 display.circle(x,y,r1, display.DOSColor(i), FILL); 02188 } 02189 } 02190 02191 02192 void EllipseTest(RA8875 & display, Serial & pc) 02193 { 02194 int i,x,y,r1,r2; 02195 02196 if (!SuppressSlowStuff) 02197 pc.printf("Ellipse Test\r\n"); 02198 display.background(Black); 02199 display.foreground(Blue); 02200 display.cls(); 02201 display.puts(0,0, "Ellipse Test"); 02202 for (i=0; i<16; i++) { 02203 x = 100 + rand() % 100; 02204 y = 70 + rand() % 200; 02205 r1 = rand() % min(y - 20, 100); 02206 r2 = rand() % min(y - 20, 100); 02207 display.ellipse(x,y,r1,r2, display.DOSColor(i)); 02208 02209 x = 300 + rand() % 100; 02210 y = 70 + rand() % 200; 02211 r1 = rand() % min(y - 20, 100); 02212 r2 = rand() % min(y - 20, 100); 02213 display.ellipse(x,y,r1,r2, FILL); 02214 } 02215 } 02216 02217 02218 void TestGraphicsBitmap(RA8875 & display, Serial & pc) 02219 { 02220 LocalFileSystem local("local"); 02221 if (!SuppressSlowStuff) 02222 pc.printf("Bitmap File Load\r\n"); 02223 display.background(Black); 02224 display.foreground(Blue); 02225 display.cls(); 02226 display.puts(0,0, "Graphics Test, loading /local/TestPat.bmp"); 02227 wait(3); 02228 02229 int r = display.RenderBitmapFile(0,0, "/local/TestPat.bmp"); 02230 if (!SuppressSlowStuff) 02231 pc.printf(" returned %d\r\n", r); 02232 } 02233 02234 02235 void TouchPanelTest(RA8875 & display, Serial & pc) 02236 { 02237 Timer t; 02238 loc_t x, y; 02239 tpMatrix_t calmatrix; 02240 02241 display.background(Black); 02242 display.foreground(Blue); 02243 display.cls(); 02244 display.puts(0,0, "Touch Panel Test\r\n"); 02245 pc.printf("Touch Panel Test\r\n"); 02246 display.TouchPanelInit(); 02247 pc.printf(" TP: c - calibrate, r - restore, t - test\r\n"); 02248 int c = pc.getc(); 02249 if (c == 'c') { 02250 point_t pTest[3] = 02251 { { 50, 50 }, {450, 150}, {225,250} }; 02252 point_t pSample[3]; 02253 for (int i=0; i<3; i++) { 02254 display.foreground(Blue); 02255 display.printf(" (%3d,%3d) => ", pTest[i].x, pTest[i].y); 02256 display.line(pTest[i].x-10, pTest[i].y, pTest[i].x+10, pTest[i].y, White); 02257 display.line(pTest[i].x, pTest[i].y-10, pTest[i].x, pTest[i].y+10, White); 02258 while (!display.TouchPanelA2DFiltered(&x, &y)) 02259 wait_ms(20); 02260 pSample[i].x = x; 02261 pSample[i].y = y; 02262 display.line(pTest[i].x-10, pTest[i].y, pTest[i].x+10, pTest[i].y, Black); 02263 display.line(pTest[i].x, pTest[i].y-10, pTest[i].x, pTest[i].y+10, Black); 02264 display.foreground(Blue); 02265 display.printf(" (%4d,%4d)\r\n", x,y); 02266 while (display.TouchPanelA2DFiltered(&x, &y)) 02267 wait_ms(20); 02268 wait(2); 02269 } 02270 display.TouchPanelComputeCalibration(pTest, pSample, &calmatrix); 02271 display.printf(" Writing calibration to tpcal.cfg\r\n"); 02272 FILE * fh = fopen("/local/tpcal.cfg", "wb"); 02273 if (fh) { 02274 fwrite(&calmatrix, sizeof(calmatrix), 1, fh); 02275 fclose(fh); 02276 } 02277 display.printf(" Calibration is complete."); 02278 } else if (c == 'r') { 02279 display.printf(" Reading calibration from tpcal.cfg\r\n"); 02280 FILE * fh = fopen("/local/tpcal.cfg", "rb"); 02281 if (fh) { 02282 fread(&calmatrix, sizeof(calmatrix), 1, fh); 02283 fclose(fh); 02284 } 02285 display.printf(" Calibration is complete."); 02286 display.TouchPanelSetMatrix(&calmatrix); 02287 } 02288 t.start(); 02289 do { 02290 point_t point = {0, 0}; 02291 if (display.TouchPanelReadable(&point)) { 02292 display.pixel(point.x, point.y, Red); 02293 } 02294 } while (t.read_ms() < 30000); 02295 pc.printf(">"); 02296 } 02297 02298 02299 void SpeedTest(RA8875 & display, Serial & pc) 02300 { 02301 Timer t; 02302 SuppressSlowStuff = true; 02303 pc.printf("\r\nSpeedTest disables delays, runs tests, reports overall time.\r\n"); 02304 t.start(); 02305 // do stuff fast 02306 TextCursorTest(display, pc); 02307 TextWrapTest(display, pc); 02308 BacklightTest(display, pc, 0); 02309 BacklightTest2(display, pc); 02310 ExternalFontTest(display, pc); 02311 DOSColorTest(display, pc); 02312 WebColorTest(display, pc); 02313 PixelTest(display, pc); 02314 LineTest(display, pc); 02315 RectangleTest(display, pc); 02316 RoundRectTest(display, pc); 02317 TriangleTest(display, pc); 02318 CircleTest(display, pc); 02319 EllipseTest(display, pc); 02320 LayerTest(display, pc); 02321 //TestGraphicsBitmap(display, pc); 02322 pc.printf("SpeedTest completed in %d msec\r\n", t.read_ms()); 02323 #ifdef PERF_METRICS 02324 display.ReportPerformance(pc); 02325 #endif 02326 SuppressSlowStuff = false; 02327 } 02328 02329 02330 void PrintScreen(RA8875 & display, Serial & pc) 02331 { 02332 if (!SuppressSlowStuff) 02333 pc.printf("PrintScreen\r\n"); 02334 display.PrintScreen( 0,0, 480,272, "/local/Capture.bmp"); 02335 } 02336 02337 02338 void RunTestSet(RA8875 & lcd, Serial & pc) 02339 { 02340 int q = 0; 02341 int automode = 0; 02342 const unsigned char modelist[] = "BDWtGLlFROTPCEbw"; // auto-test in this order. 02343 02344 while(1) { 02345 pc.printf("\r\n" 02346 "B - Backlight up b - backlight dim\r\n" 02347 "D - DOS Colors W - Web Colors\r\n" 02348 "t - text cursor G - Graphics Bitmap\r\n" 02349 "L - Lines F - external Font\r\n" 02350 "R - Rectangles O - rOund rectangles\r\n" 02351 "T - Triangles P - Pixels \r\n" 02352 "C - Circles E - Ellipses\r\n" 02353 "A - Auto Test mode S - Speed Test\r\n" 02354 "K - Keypad Test s - touch screen test\r\n" 02355 "p - print screen r - reset \r\n" 02356 "l - layer test w - wrapping text \r\n" 02357 #ifdef PERF_METRICS 02358 "0 - clear performance 1 - report performance\r\n" 02359 #endif 02360 "> "); 02361 if (automode == -1 || pc.readable()) { 02362 automode = -1; 02363 q = pc.getc(); 02364 while (pc.readable()) 02365 pc.getc(); 02366 } else if (automode >= 0) { 02367 q = modelist[automode]; 02368 } 02369 switch(q) { 02370 #ifdef PERF_METRICS 02371 case '0': 02372 lcd.ClearPerformance(); 02373 break; 02374 case '1': 02375 lcd.ReportPerformance(pc); 02376 break; 02377 #endif 02378 case 'A': 02379 automode = 0; 02380 break; 02381 case 'B': 02382 BacklightTest(lcd, pc, 2); 02383 break; 02384 case 'b': 02385 BacklightTest2(lcd, pc); 02386 break; 02387 case 'D': 02388 DOSColorTest(lcd, pc); 02389 break; 02390 case 'K': 02391 KeyPadTest(lcd, pc); 02392 break; 02393 case 'W': 02394 WebColorTest(lcd, pc); 02395 break; 02396 case 't': 02397 TextCursorTest(lcd, pc); 02398 break; 02399 case 'w': 02400 TextWrapTest(lcd, pc); 02401 break; 02402 case 'F': 02403 ExternalFontTest(lcd, pc); 02404 break; 02405 case 'L': 02406 LineTest(lcd, pc); 02407 break; 02408 case 'l': 02409 LayerTest(lcd, pc); 02410 break; 02411 case 'R': 02412 RectangleTest(lcd, pc); 02413 break; 02414 case 'O': 02415 RoundRectTest(lcd, pc); 02416 break; 02417 case 'p': 02418 PrintScreen(lcd, pc); 02419 break; 02420 case 'S': 02421 SpeedTest(lcd, pc); 02422 break; 02423 case 's': 02424 TouchPanelTest(lcd, pc); 02425 break; 02426 case 'T': 02427 TriangleTest(lcd, pc); 02428 break; 02429 case 'P': 02430 PixelTest(lcd, pc); 02431 break; 02432 case 'G': 02433 TestGraphicsBitmap(lcd, pc); 02434 break; 02435 case 'C': 02436 CircleTest(lcd, pc); 02437 break; 02438 case 'E': 02439 EllipseTest(lcd, pc); 02440 break; 02441 case 'r': 02442 pc.printf("Resetting ...\r\n"); 02443 wait_ms(20); 02444 mbed_reset(); 02445 break; 02446 case ' ': 02447 break; 02448 default: 02449 printf("huh?\n"); 02450 break; 02451 } 02452 if (automode >= 0) { 02453 automode++; 02454 if (automode >= sizeof(modelist)) 02455 automode = 0; 02456 wait_ms(2000); 02457 } 02458 wait_ms(200); 02459 } 02460 } 02461 02462 #endif // TESTENABLE
Generated on Fri Jul 15 2022 05:44:41 by
![doxygen](doxygen.png)