brw1

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers RA8875.cpp Source File

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