Hexley Ball / RA8875_fork

Fork of RA8875 by David Smart

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 specific display from buydisplay.com,
00004 /// which is 480 x 272. It has other attributes (like display controller
00005 /// managed backlight brightness. So, there are expectations and some
00006 /// defined constants based on that specific display. Some initial work
00007 /// was done to support other display resolutions (e.g. 800 x 480), but
00008 /// this has not been tested.
00009 ///
00010 #include "RA8875.h"
00011 
00012 //#define DEBUG "RAIO"
00013 // ...
00014 // INFO("Stuff to show %d", var); // new-line is automatically appended
00015 //
00016 #if (defined(DEBUG) && !defined(TARGET_LPC11U24))
00017 #define INFO(x, ...) std::printf("[INF %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
00018 #define WARN(x, ...) std::printf("[WRN %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
00019 #define ERR(x, ...)  std::printf("[ERR %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
00020 #else
00021 #define INFO(x, ...)
00022 #define WARN(x, ...)
00023 #define ERR(x, ...)
00024 #endif
00025 
00026 
00027 #define RA8875_DISPLAY_WIDTH  480
00028 #define RA8875_DISPLAY_HEIGHT 272
00029 #define RA8875_COLORDEPTH_BPP 16    /* Not an API */
00030 
00031 #ifdef PERF_METRICS
00032 #define PERFORMANCE_RESET performance.reset()
00033 #define REGISTERPERFORMANCE(a) RegisterPerformance(a)
00034 static const char *metricsName[] = 
00035 {
00036     "Cls", "Pixel", "Pixel Stream", 
00037     "Read Pixel", "Read Pixel Stream",
00038     "Line", 
00039     "Rectangle", "Rounded Rectangle", "Triangle", "Circle", "Ellipse"
00040 };
00041 #else
00042 #define PERFORMANCE_RESET
00043 #define REGISTERPERFORMANCE(a)
00044 #endif
00045 
00046 // When it is going to poll a register for completion, how many 
00047 // uSec should it wait between each polling activity.
00048 #define POLLWAITuSec 10
00049 
00050 
00051 RA8875::RA8875(PinName mosi, PinName miso, PinName sclk, PinName csel, PinName reset, const char *name)
00052     : spi(mosi, miso, sclk)
00053     , cs(csel)
00054     , res(reset)
00055     , GraphicsDisplay(name)
00056 {
00057     font = NULL;                        // no external font, use internal.
00058     select(false);                      // deselect the display
00059     frequency(RA8875_DEFAULT_SPI_FREQ); // data rate
00060     Reset();
00061     Power(true);
00062     Backlight_u8(255);
00063 #ifdef PERF_METRICS
00064     performance.start();
00065     ClearPerformance();
00066 #endif
00067 }
00068 
00069 
00070 //RA8875::~RA8875()
00071 //{
00072 //}
00073 
00074 
00075 RetCode_t RA8875::SelectLayer(uint16_t layer)
00076 {
00077     unsigned char mwcr1 = ReadCommand(0x41) & ~0x01; // retain all but the currently selected layer
00078 
00079     if (width() >= 800 && height() >= 480 && color_bpp() == 8) {
00080         return bad_parameter;
00081     } else if (layer > 1) {
00082         return bad_parameter;
00083     } else { // layer == 0 ro 1
00084         WriteCommand(0x41, mwcr1 | layer);
00085     }
00086     return noerror;
00087 }
00088 
00089 
00090 RetCode_t RA8875::SetLayerMode(uint8_t mode)
00091 {
00092     WriteCommand(0x52, mode);
00093     return noerror;
00094 }
00095 
00096 
00097 RetCode_t RA8875::SetLayerTransparency(uint8_t layer1, uint8_t layer2)
00098 {
00099     if (layer1 > 8)
00100         layer1 = 8;
00101     if (layer2 > 8)
00102         layer2 = 8;
00103     WriteCommand(0x53, ((layer2 & 0xF) << 4) | (layer1 & 0xF));
00104     return noerror;
00105 }
00106 
00107 
00108 #ifdef PERF_METRICS
00109 void RA8875::ClearPerformance()
00110 {
00111     for (int i=0; i<METRICCOUNT; i++)
00112         metrics[i] = 0;
00113 }
00114 
00115 
00116 void RA8875::RegisterPerformance(method_e method)
00117 {
00118     unsigned long elapsed = performance.read_us();
00119     
00120     if (method < METRICCOUNT && elapsed > metrics[method])
00121         metrics[method] = elapsed;
00122 }
00123 
00124 
00125 void RA8875::ReportPerformance(Serial & pc)
00126 {
00127     pc.printf("\r\nPerformance Metrics\r\n");
00128     for (int i=0; i<METRICCOUNT; i++) {
00129         pc.printf("%10d uS %s\r\n", metrics[i], metricsName[i]);
00130     }    
00131 }
00132 #endif
00133 
00134 
00135 RetCode_t RA8875::WriteCommandW(uint8_t command, uint16_t data)
00136 {
00137     #if 1
00138     WriteCommand(command, data & 0xFF);
00139     WriteCommand(command+1, data >> 8);
00140     #else
00141     // This should be a little faster, but doesn't work...
00142     INFO("WriteCommandW(%02X, %04X)", command, data);
00143     select(true);
00144     spiwrite(0x80);
00145     spiwrite(command);
00146     //spiwrite(0x00);     // dummy
00147     spiwrite(data & 0xFF);
00148     spiwrite(data >> 8);
00149     select(false);
00150     #endif
00151     return noerror;
00152 }
00153 
00154 
00155 RetCode_t RA8875::WriteCommand(unsigned char command, unsigned int data)
00156 {
00157     select(true);
00158     spiwrite(0x80);         // cmd: write command
00159     spiwrite(command);
00160     if (data <= 0xFF) {   // only if in the valid range
00161         spiwrite(0x00);
00162         spiwrite(data);
00163     }
00164     select(false);
00165     return noerror;
00166 }
00167 
00168 
00169 RetCode_t RA8875::WriteDataW(uint16_t data)
00170 {
00171     select(true);
00172     spiwrite(0x00);         // cmd: write data
00173     spiwrite(data & 0xFF);
00174     spiwrite(data >> 8);
00175     select(false);
00176     return noerror;
00177 }
00178 
00179 
00180 RetCode_t RA8875::WriteData(unsigned char data)
00181 {
00182     select(true);
00183     spiwrite(0x00);
00184     spiwrite(data);
00185     select(false);
00186     return noerror;
00187 }
00188 
00189 
00190 unsigned char RA8875::ReadCommand(unsigned char command)
00191 {
00192     WriteCommand(command);
00193     return ReadData();
00194 }
00195 
00196 
00197 unsigned char RA8875::ReadData(void)
00198 {
00199     unsigned char data;
00200     
00201     select(true);
00202     spiwrite(0x40);
00203     data = spiread();
00204     select(false);
00205     return data;
00206 }
00207 
00208 
00209 uint16_t RA8875::ReadDataW(void)
00210 {
00211     uint16_t data;
00212     
00213     select(true);
00214     spiwrite(0x40);
00215     data  = spiread();
00216     data |= (spiread() << 8);
00217     select(false);
00218     return data;
00219 }
00220 
00221 
00222 unsigned char RA8875::ReadStatus(void)
00223 {
00224     unsigned char data;
00225     
00226     select(true);
00227     spiwrite(0xC0);
00228     data = spiread();
00229     select(false);
00230     return data;
00231 }
00232 
00233 
00234 dim_t RA8875::fontwidth(void)
00235 {
00236     if (font == NULL)
00237         return (((ReadCommand(0x22) >> 2) & 0x3) + 1) * 16;
00238     else
00239         return font[1];
00240 }
00241 
00242 
00243 dim_t RA8875::fontheight(void)
00244 {
00245     if (font == NULL)
00246         return (((ReadCommand(0x22) >> 0) & 0x3) + 1) * 16;
00247     else
00248         return font[2];
00249 }
00250 
00251 
00252 RetCode_t RA8875::locate(textloc_t column, textloc_t row)
00253 {
00254     return SetTextCursor(column * fontwidth(), row * fontheight());
00255 }
00256 
00257 
00258 int RA8875::columns(void)
00259 {
00260     return width() / fontwidth();
00261 }
00262 
00263 
00264 int RA8875::rows(void)
00265 {
00266     return height() / fontheight();
00267 }
00268 
00269 
00270 dim_t RA8875::width(void)
00271 {
00272     return (ReadCommand(0x14) + 1) * 8;
00273 }
00274 
00275 
00276 dim_t RA8875::height(void)
00277 {
00278     return (ReadCommand(0x19) | (ReadCommand(0x1A) << 8)) + 1;
00279 }
00280 
00281 
00282 dim_t RA8875::color_bpp(void)
00283 {
00284     if ((ReadCommand(0x10) & 0x0C) == 0x04)
00285         return 16;
00286     else
00287         return 8;
00288 }
00289 
00290 
00291 RetCode_t RA8875::SetTextCursor(loc_t x, loc_t y)
00292 {
00293     cursor_x = x; cursor_y = y;     // for non-internal fonts
00294     WriteCommandW(0x2A, x);
00295     WriteCommandW(0x2C, y);
00296     return noerror;
00297 }
00298 
00299 
00300 loc_t RA8875::GetTextCursor_Y(void)
00301 {
00302     if (font == NULL)
00303         return ReadCommand(0x2C) | (ReadCommand(0x2D) << 8);
00304     else
00305         return cursor_y;
00306 }
00307 
00308 
00309 loc_t RA8875::GetTextCursor_X(void)
00310 {
00311     if (font == NULL)
00312         return ReadCommand(0x2A) | (ReadCommand(0x2B) << 8);
00313     else
00314         return cursor_x;
00315 }
00316 
00317 
00318 RetCode_t RA8875::SetTextCursorControl(cursor_t cursor, bool blink)
00319 {
00320     unsigned char mwcr0 = ReadCommand(0x40) & 0x0F; // retain direction, auto-increase
00321     unsigned char mwcr1 = ReadCommand(0x41) & 0x01; // retain currently selected layer
00322     unsigned char horz = 0;
00323     unsigned char vert = 0;
00324     
00325     mwcr0 |= 0x80;                  // text mode
00326     if (cursor != NOCURSOR)
00327         mwcr0 |= 0x40;              // visible
00328     if (blink)
00329         mwcr0 |= 0x20;              // blink
00330     WriteCommand(0x40, mwcr0);      // configure the cursor
00331     WriteCommand(0x41, mwcr1);      // close the graphics cursor
00332     WriteCommand(0x44, 0x1f);       // The cursor flashing cycle
00333     switch (cursor) {
00334         case IBEAM:
00335             horz = 0x01;
00336             vert = 0x1F;
00337             break;
00338         case UNDER:
00339             horz = 0x07;
00340             vert = 0x01;
00341             break;
00342         case BLOCK:
00343             horz = 0x07;
00344             vert = 0x1F;
00345             break;
00346         case NOCURSOR:
00347         default:
00348             break;
00349     }
00350     WriteCommand(0x4e, horz);       // The cursor size horz
00351     WriteCommand(0x4f, vert);       // The cursor size vert
00352     return noerror;
00353 }
00354 
00355 
00356 RetCode_t RA8875::SetTextFont(RA8875::font_t font)
00357 {
00358     if (/*font >= RA8875::ISO8859_1 && */ font <= RA8875::ISO8859_4) {
00359         WriteCommand(0x21, (unsigned int)(font));
00360         return noerror;
00361     } else {
00362         return bad_parameter;
00363     }
00364 }
00365 
00366 
00367 RetCode_t RA8875::SetTextFontControl(fill_t fillit,
00368     RA8875::font_angle_t angle, 
00369     RA8875::HorizontalScale hScale, 
00370     RA8875::VerticalScale vScale, 
00371     RA8875::alignment_t alignment)
00372 {
00373     if (hScale >= 1 && hScale <= 4 && 
00374     vScale >= 1 && vScale <= 4) {
00375         unsigned char x = 0;
00376         
00377         if (alignment == align_full)
00378             x |= 0x80;
00379         if (fillit == NOFILL)
00380             x |= 0x40;
00381         if (angle == rotated)
00382             x |= 0x10;
00383         x |= ((hScale - 1) << 2);
00384         x |= ((vScale - 1) << 0);
00385         WriteCommand(0x22, x);
00386         return noerror;
00387     } else {
00388         return bad_parameter;
00389     }
00390 }
00391 
00392 
00393 RetCode_t RA8875::SetTextFontSize(RA8875::HorizontalScale hScale, RA8875::VerticalScale vScale)
00394 {
00395     unsigned char reg = ReadCommand(0x22);
00396     
00397     if (vScale == -1)
00398         vScale = hScale;
00399     if (hScale >= 1 && hScale <= 4 && vScale >= 1 && vScale <= 4) {
00400         reg &= 0xF0;    // keep the high nibble as is.
00401         reg |= ((hScale - 1) << 2);
00402         reg |= ((vScale - 1) << 0);
00403         WriteCommand(0x22, reg);
00404         return noerror;
00405     } else {
00406         return bad_parameter;
00407     }
00408 }
00409 
00410 
00411 int RA8875::_putc(int c)
00412 {
00413     if (font == NULL) {
00414         return _internal_putc(c);
00415     } else {
00416         return _external_putc(c);
00417     }
00418 }
00419 
00420 
00421 int RA8875::_external_putc(int c)
00422 {
00423     if (c) {
00424         if (c == '\r') {
00425             cursor_x = 0;
00426         } else if (c == '\n') {
00427             cursor_y += font[2];
00428         } else {
00429             int advance = character(cursor_x, cursor_y, c);     // advance tells us how many pixels we advanced
00430             //INFO("x,y,advance %d,%d,%d", cursor_x, cursor_y, advance);
00431             if (advance) {
00432                 cursor_x += advance;
00433                 if (cursor_x >= width()) {
00434                     cursor_x = 0;
00435                     cursor_y += font[2];
00436                     if (cursor_y >= height()) {
00437                         cursor_y = 0;               // @todo Should it scroll?
00438                     }
00439                 }
00440             }
00441         }
00442     }
00443     return c;
00444 }
00445 
00446 
00447 int RA8875::_internal_putc(int c)
00448 {
00449     if (c) {
00450         unsigned char mwcr0;
00451         
00452         mwcr0 = ReadCommand(0x40);
00453         if ((mwcr0 & 0x80) == 0x00) {
00454             WriteCommand(0x40, 0x80 | mwcr0);    // Put in Text mode if not already
00455         }
00456         if (c == '\r') {
00457             loc_t x;
00458             x = ReadCommand(0x30) | (ReadCommand(0x31) << 8);   // Left edge of active window
00459             WriteCommandW(0x2A, x);
00460         } else if (c == '\n') {
00461             loc_t y;
00462             y = ReadCommand(0x2C) | (ReadCommand(0x2D) << 8);   // current y location
00463             y += fontheight();
00464             if (y >= height())               // @TODO after bottom of active window, then scroll window? #### hb changed test to include = to fix dropped line in vertical wrap.
00465                 y = 0;
00466             WriteCommandW(0x2C, y);
00467         } else {
00468             WriteCommand(0x02);                 // RA8875 Internal Fonts
00469             select(true);
00470             WriteData(c);
00471             while (ReadStatus() & 0x80)
00472                 wait_us(POLLWAITuSec);          // Chk_Busy();
00473             select(false);
00474         }
00475     }
00476     return c;
00477 }
00478 
00479 
00480 RetCode_t RA8875::_StartGraphicsStream(void)
00481 {
00482     WriteCommand(0x40,0x00);    // Graphics write mode
00483     WriteCommand(0x02);         // Prepare for streaming data
00484     return noerror;
00485 }
00486 
00487 
00488 RetCode_t RA8875::_EndGraphicsStream(void)
00489 {
00490     return noerror;
00491 }
00492 
00493 
00494 RetCode_t RA8875::putp(color_t pixel)
00495 {
00496     WriteDataW((pixel>>8) | (pixel<<8));
00497     return noerror;   
00498 }
00499 
00500 
00501 void RA8875::puts(loc_t x, loc_t y, const char * string)
00502 {
00503     SetTextCursor(x,y);
00504     puts(string);
00505 }
00506 
00507 
00508 void RA8875::puts(const char * string)
00509 {
00510     unsigned char mwcr0 = ReadCommand(0x40);
00511     
00512     if (font == NULL) {
00513         if ((mwcr0 & 0x80) == 0x00)
00514             WriteCommand(0x40,0x80);    // Put in Text mode if not already
00515     } else {
00516         _StartGraphicsStream();
00517     }
00518     if (*string != '\0') {
00519         #if 1
00520         while (*string) {           // @TODO calling individual _putc is slower... optimizations?
00521             _putc(*string++);
00522         }
00523         #else
00524         WriteCommand(0x02);
00525         select(true);
00526         while (*string != '\0') {
00527             WriteData(*string);
00528             ++string;
00529             while (ReadStatus() & 0x80)
00530                 wait_us(POLLWAITuSec);            // Chk_Busy();
00531         }
00532         select(false);
00533         #endif
00534     }
00535     if (font)
00536         _EndGraphicsStream();
00537 }
00538 
00539 
00540 RetCode_t RA8875::SetGraphicsCursor(loc_t x, loc_t y)
00541 {
00542     WriteCommandW(0x46, x);
00543     WriteCommandW(0x48, y);
00544     return noerror;
00545 }
00546 
00547 
00548 RetCode_t RA8875::SetGraphicsCursorRead(loc_t x, loc_t y)
00549 {
00550     //WriteCommand(0x40, 0);  // Graphics mode
00551     //WriteCommand(0x45, 0);  // left->right, top->bottom
00552     WriteCommandW(0x4A, x);
00553     WriteCommandW(0x4C, y);
00554     return noerror;
00555 }
00556 
00557 
00558 RetCode_t RA8875::window(loc_t x, loc_t y, dim_t width, dim_t height)
00559 {
00560     GraphicsDisplay::window(x,y, width,height);
00561     WriteCommandW(0x30, x);
00562     WriteCommandW(0x32, y);
00563     WriteCommandW(0x34, (x+width-1));
00564     WriteCommandW(0x36, (y+height-1));
00565     SetGraphicsCursor(x,y);
00566     return noerror;
00567 }
00568 
00569 
00570 RetCode_t RA8875::cls(void)
00571 {
00572     PERFORMANCE_RESET;
00573     clsw(FULLWINDOW);
00574     SetTextCursor(0,0);
00575     REGISTERPERFORMANCE(PRF_CLS);
00576     return noerror;
00577 }
00578 
00579 
00580 RetCode_t RA8875::clsw(RA8875::Region_t region)
00581 {
00582     PERFORMANCE_RESET;
00583     WriteCommand(0x8E, (region == ACTIVEWINDOW) ? 0xC0 : 0x80);
00584     while (ReadCommand(0x8E) & 0x80)
00585         wait_us(POLLWAITuSec);
00586     REGISTERPERFORMANCE(PRF_CLS);
00587     return noerror;
00588 }
00589 
00590 
00591 RetCode_t RA8875::pixel(loc_t x, loc_t y, color_t color)
00592 {
00593     #if 1
00594     return pixelStream(&color, 1, x,y);
00595     #else
00596     foreground(color);
00597     return pixel(x,y);
00598     #endif
00599 }
00600 
00601 
00602 RetCode_t RA8875::pixel(loc_t x, loc_t y)
00603 {
00604     RetCode_t ret;
00605     
00606     PERFORMANCE_RESET;
00607     color_t color = GetForeColor();
00608     WriteCommand(0x40,0x00);    // Graphics write mode
00609     SetGraphicsCursor(x, y);
00610     WriteCommand(0x02);
00611     WriteDataW(color);
00612     ret = noerror;
00613     REGISTERPERFORMANCE(PRF_DRAWPIXEL);
00614     return ret;
00615 }
00616 
00617 
00618 RetCode_t RA8875::pixelStream(color_t * p, uint32_t count, loc_t x, loc_t y)
00619 {
00620     PERFORMANCE_RESET;
00621     WriteCommand(0x40,0x00);    // Graphics write mode
00622     SetGraphicsCursor(x, y);
00623     WriteCommand(0x02);
00624     select(true);
00625     spiwrite(0x00);         // Cmd: write data
00626     while (count--) {
00627         spiwrite(*p >> 8);
00628         spiwrite(*p & 0xFF);
00629         p++;
00630     }
00631     select(false);
00632     REGISTERPERFORMANCE(PRF_PIXELSTREAM);
00633     return(noerror);
00634 }
00635 
00636 
00637 color_t RA8875::getPixel(loc_t x, loc_t y)
00638 {
00639     color_t pixel;
00640     
00641     PERFORMANCE_RESET;
00642     //WriteCommand(0x45,0x00);    // read left->right, top->bottom
00643     WriteCommand(0x40,0x00);    // Graphics write mode
00644     SetGraphicsCursorRead(x, y);
00645     WriteCommand(0x02);
00646     select(true);
00647     spiwrite(0x40);         // Cmd: read data
00648     spiwrite(0x00);         // dummy read
00649     pixel  = spiread();
00650     pixel |= (spiread() << 8);
00651     select(false);
00652     REGISTERPERFORMANCE(PRF_READPIXEL);
00653     return pixel;
00654 }
00655 
00656 
00657 RetCode_t RA8875::getPixelStream(color_t * p, uint32_t count, loc_t x, loc_t y)
00658 {
00659     color_t pixel;
00660     
00661     PERFORMANCE_RESET;
00662     //WriteCommand(0x45,0x00);    // read left->right, top->bottom
00663     WriteCommand(0x40,0x00);    // Graphics write mode
00664     SetGraphicsCursorRead(x, y);
00665     WriteCommand(0x02);
00666     select(true);
00667     spiwrite(0x40);         // Cmd: read data
00668     spiwrite(0x00);         // dummy read
00669     while (count--) {
00670         pixel  = spiread();
00671         pixel |= (spiread() << 8);
00672         *p++ = pixel;
00673     }
00674     select(false);
00675     REGISTERPERFORMANCE(PRF_READPIXELSTREAM);
00676     return noerror;
00677 }
00678 
00679 
00680 RetCode_t RA8875::line(loc_t x1, loc_t y1, loc_t x2, loc_t y2, color_t color)
00681 {
00682     foreground(color);
00683     return line(x1,y1,x2,y2);
00684 }
00685 
00686 
00687 RetCode_t RA8875::line(loc_t x1, loc_t y1, loc_t x2, loc_t y2)
00688 {
00689     PERFORMANCE_RESET;
00690     WriteCommandW(0x91, x1);
00691     WriteCommandW(0x93, y1);
00692     WriteCommandW(0x95, x2);
00693     WriteCommandW(0x97, y2);
00694     unsigned char drawCmd = 0x00;       // Line
00695     WriteCommand(0x90, drawCmd);
00696     WriteCommand(0x90, 0x80 + drawCmd); // Start drawing.
00697     while (ReadCommand(0x90) & 0x80)    // await completion.
00698         wait_us(POLLWAITuSec);
00699     REGISTERPERFORMANCE(PRF_DRAWLINE);
00700     return noerror;
00701 }
00702 
00703 
00704 RetCode_t RA8875::fillrect(loc_t x1, loc_t y1, loc_t x2, loc_t y2, 
00705     color_t color, fill_t fillit)
00706 {
00707     return rect(x1,y1,x2,y2,color,fillit);
00708 }
00709 
00710 
00711 RetCode_t RA8875::rect(loc_t x1, loc_t y1, loc_t x2, loc_t y2, 
00712     color_t color, fill_t fillit)
00713 {
00714     foreground(color);
00715     return rect(x1,y1,x2,y2,fillit);
00716 }
00717 
00718 
00719 RetCode_t RA8875::rect(loc_t x1, loc_t y1, loc_t x2, loc_t y2, 
00720     fill_t fillit)
00721 {
00722     PERFORMANCE_RESET;
00723     if (x1 == x2 && y1 == y2) {
00724         pixel(x1, y1);
00725     } else if (x1 == x2) {
00726         line(x1, y1, x2, y2);
00727     } else if (y1 == y2) {
00728         line(x1, y1, x2, y2);
00729     } else {
00730         WriteCommandW(0x91, x1);
00731         WriteCommandW(0x93, y1);
00732         WriteCommandW(0x95, x2);
00733         WriteCommandW(0x97, y2);
00734         unsigned char drawCmd = 0x10;   // Rectangle
00735         if (fillit == FILL)
00736             drawCmd |= 0x20;
00737         WriteCommand(0x90, drawCmd);
00738         WriteCommand(0x90, 0x80 + drawCmd); // Start drawing.
00739         while (ReadCommand(0x90) & 0x80)    // await completion.
00740             wait_us(POLLWAITuSec);
00741     }
00742     REGISTERPERFORMANCE(PRF_DRAWRECTANGLE);
00743     return noerror;
00744 }
00745 
00746 
00747 RetCode_t RA8875::fillroundrect(loc_t x1, loc_t y1, loc_t x2, loc_t y2, 
00748     dim_t radius1, dim_t radius2, color_t color, fill_t fillit)
00749 {
00750     foreground(color);
00751     return roundrect(x1,y1,x2,y2,radius1,radius2,fillit);
00752 }
00753 
00754 
00755 RetCode_t RA8875::roundrect(loc_t x1, loc_t y1, loc_t x2, loc_t y2, 
00756     dim_t radius1, dim_t radius2, color_t color, fill_t fillit)
00757 {
00758     foreground(color);
00759     return roundrect(x1,y1,x2,y2,radius1,radius2,fillit);
00760 }
00761 
00762 
00763 RetCode_t RA8875::roundrect(loc_t x1, loc_t y1, loc_t x2, loc_t y2, 
00764     dim_t radius1, dim_t radius2, fill_t fillit)
00765 {
00766     RetCode_t ret = noerror;
00767     
00768     PERFORMANCE_RESET;
00769     if (x1 > x2 || y1 > y2 || (radius1 > (x2-x1)/2) || (radius2 > (y2-y1)/2) ) {
00770         ret = bad_parameter;
00771     } else if (x1 == x2 && y1 == y2) {
00772         pixel(x1, y1);
00773     } else if (x1 == x2) {
00774         line(x1, y1, x2, y2);
00775     } else if (y1 == y2) {
00776         line(x1, y1, x2, y2);
00777     } else {
00778         WriteCommandW(0x91, x1);
00779         WriteCommandW(0x93, y1);
00780         WriteCommandW(0x95, x2);
00781         WriteCommandW(0x97, y2);
00782         WriteCommandW(0xA1, radius1);
00783         WriteCommandW(0xA3, radius2);
00784         // Should not need this...
00785         WriteCommandW(0xA5, 0);
00786         WriteCommandW(0xA7, 0);
00787         unsigned char drawCmd = 0x20;       // Rounded Rectangle
00788         if (fillit == FILL)
00789             drawCmd |= 0x40;
00790         WriteCommand(0xA0, drawCmd);
00791         WriteCommand(0xA0, 0x80 + drawCmd); // Start drawing.
00792         while (ReadCommand(0xA0) & 0x80) {   // await completion.
00793             wait_us(POLLWAITuSec);
00794         }
00795     }
00796     REGISTERPERFORMANCE(PRF_DRAWROUNDEDRECTANGLE);
00797     return ret;
00798 }
00799 
00800 
00801 RetCode_t RA8875::triangle(loc_t x1, loc_t y1, loc_t x2, loc_t y2, 
00802     loc_t x3, loc_t y3, color_t color, fill_t fillit)
00803 {
00804     RetCode_t ret;
00805     
00806     foreground(color);
00807     ret = triangle(x1,y1,x2,y2,x3,y3,fillit);
00808     return ret;
00809 }
00810 
00811 
00812 RetCode_t RA8875::filltriangle(loc_t x1, loc_t y1, loc_t x2, loc_t y2, 
00813     loc_t x3, loc_t y3, color_t color, fill_t fillit)
00814 {
00815     RetCode_t ret;
00816 
00817     foreground(color);
00818     ret = triangle(x1,y1,x2,y2,x3,y3,fillit);
00819     return ret;
00820 }
00821 
00822 
00823 RetCode_t RA8875::triangle(loc_t x1, loc_t y1 ,loc_t x2, loc_t y2, 
00824     loc_t x3, loc_t y3, fill_t fillit)
00825 {
00826     RetCode_t ret = noerror;
00827     
00828     PERFORMANCE_RESET;
00829     if (x1 == x2 && y1 == y2 && x1 == x3 && y1 == y3) {
00830         pixel(x1, y1);
00831     } else {
00832         WriteCommandW(0x91, x1);
00833         WriteCommandW(0x93, y1);
00834         WriteCommandW(0x95, x2);
00835         WriteCommandW(0x97, y2);
00836         WriteCommandW(0xA9, x3);
00837         WriteCommandW(0xAB, y3);
00838         unsigned char drawCmd = 0x01;       // Triangle
00839         if (fillit == FILL)
00840             drawCmd |= 0x20;
00841         WriteCommand(0x90, drawCmd);
00842         WriteCommand(0x90, 0x80 + drawCmd); // Start drawing.
00843         while (ReadCommand(0x90) & 0x80)    // await completion.
00844             wait_us(POLLWAITuSec);
00845     }
00846     REGISTERPERFORMANCE(PRF_DRAWTRIANGLE);
00847     return ret;
00848 }
00849 
00850 RetCode_t RA8875::circle(loc_t x, loc_t y, dim_t radius, 
00851     color_t color, fill_t fillit)
00852 {
00853     foreground(color);
00854     return circle(x,y,radius,fillit);
00855 }
00856 
00857 
00858 RetCode_t RA8875::fillcircle(loc_t x, loc_t y, dim_t radius, 
00859     color_t color, fill_t fillit)
00860 {
00861     foreground(color);
00862     return circle(x,y,radius,fillit);
00863 }
00864 
00865 
00866 RetCode_t RA8875::circle(loc_t x, loc_t y, dim_t radius, fill_t fillit)
00867 {
00868     RetCode_t ret = noerror;
00869     
00870     PERFORMANCE_RESET;
00871     if (radius <= 0) {
00872         ret = bad_parameter;
00873     } else if (radius == 1) {
00874         pixel(x,y);
00875     } else {
00876         WriteCommandW(0x99, x);
00877         WriteCommandW(0x9B, y);
00878         WriteCommand(0x9d, radius & 0xFF);
00879         unsigned char drawCmd = 0x00;       // Circle
00880         if (fillit == FILL)
00881             drawCmd |= 0x20;
00882         WriteCommand(0x90, drawCmd);
00883         WriteCommand(0x90, 0x40 + drawCmd); // Start drawing.
00884         while (ReadCommand(0x90) & 0x40)    // await completion.
00885             wait_us(POLLWAITuSec);
00886     }
00887     REGISTERPERFORMANCE(PRF_DRAWCIRCLE);
00888     return ret;
00889 }
00890 
00891 
00892 RetCode_t RA8875::ellipse(loc_t x, loc_t y, dim_t radius1, dim_t radius2, color_t color, fill_t fillit)
00893 {
00894     foreground(color);
00895     return ellipse(x,y,radius1,radius2,fillit);
00896 }
00897 
00898 
00899 RetCode_t RA8875::fillellipse(loc_t x, loc_t y, dim_t radius1, dim_t radius2, color_t color, fill_t fillit)
00900 {
00901     foreground(color);
00902     return ellipse(x,y,radius1,radius2,fillit);
00903 }
00904 
00905         
00906 RetCode_t RA8875::ellipse(loc_t x, loc_t y, dim_t radius1, dim_t radius2, fill_t fillit)
00907 {
00908     RetCode_t ret = noerror;
00909     
00910     PERFORMANCE_RESET;
00911     if (radius1 <= 0 || radius2 <= 0) {
00912         ;   // do nothing
00913     } else if (radius1 == 1 && radius2 == 1) {
00914         pixel(x, y);
00915     } else {
00916         WriteCommandW(0xA5, x);
00917         WriteCommandW(0xA7, y);
00918         WriteCommandW(0xA1, radius1);
00919         WriteCommandW(0xA3, radius2);
00920         unsigned char drawCmd = 0x00;   // Ellipse
00921         if (fillit == FILL)
00922             drawCmd |= 0x40;
00923         WriteCommand(0xA0, drawCmd);
00924         WriteCommand(0xA0, 0x80 + drawCmd); // Start drawing.
00925         while (ReadCommand(0xA0) & 0x80)    // await completion.
00926             wait_us(POLLWAITuSec);
00927     }
00928     REGISTERPERFORMANCE(PRF_DRAWELLIPSE);
00929     return ret;
00930 }
00931 
00932 
00933 RetCode_t RA8875::frequency(unsigned long Hz)
00934 {
00935     spi.frequency(Hz);
00936     //       __   ___
00937     // Clock   ___A     Rising edge latched
00938     //       ___ ____
00939     // Data  ___X____
00940     spi.format(8, 3);           // 8 bits and clock to data phase 0
00941     return noerror;
00942 }
00943 
00944 
00945 RetCode_t RA8875::Power(bool on)
00946 {
00947     WriteCommand(0x01, (on) ? 0x80 : 0x00);
00948     return noerror;
00949 }
00950 
00951 
00952 RetCode_t RA8875::Reset(void)
00953 {
00954     WriteCommand(0x01, 0x01);   // Apply Display Off, Reset
00955     wait_ms(2);                     // no idea if I need to wait, or how long
00956     WriteCommand(0x01, 0x00);   // Display off, Remove reset
00957     wait_ms(2);                     // no idea if I need to wait, or how long    
00958     init(RA8875_DISPLAY_WIDTH, RA8875_DISPLAY_HEIGHT, RA8875_COLORDEPTH_BPP);
00959     return noerror;
00960 }
00961 
00962 
00963 RetCode_t RA8875::Backlight_u8(unsigned char brightness)
00964 {
00965     static bool is_enabled = false;
00966     if (brightness == 0) {
00967         WriteCommand(0x8a); // Disable the PWM
00968         WriteData(0x00);
00969         is_enabled = false;
00970     } else if (!is_enabled) {
00971         WriteCommand(0x8a); // Enable the PWM
00972         WriteData(0x80);
00973         WriteCommand(0x8a); // Not sure why this is needed, but following the pattern
00974         WriteData(0x81);    // open PWM (SYS_CLK / 2 as best I can tell)
00975         is_enabled = true;
00976     }
00977     WriteCommand(0x8b, brightness);  // Brightness parameter 0xff-0x00
00978     return noerror;
00979 }
00980 
00981 
00982 RetCode_t RA8875::Backlight(float brightness)
00983 {
00984     unsigned char b;
00985     
00986     if (brightness >= 1.0)
00987         b = 255;
00988     else if (brightness <= 0.0)
00989         b = 0;
00990     else
00991         b = (unsigned char)(brightness * 255);
00992     return Backlight_u8(b);
00993 }
00994 
00995 
00996 RetCode_t RA8875::set_font(const unsigned char * _font)
00997 {
00998     if (font && ! _font) {
00999         SetTextCursor(cursor_x, cursor_y);  // soft-font cursor -> hw cursor
01000     }
01001     font = _font;
01002     GraphicsDisplay::set_font(_font);
01003     return noerror;     // trusting them, but it might be good to put some checks in here...
01004 }
01005 
01006 
01007 RetCode_t RA8875::background(color_t color)
01008 {
01009     GraphicsDisplay::background(color);
01010     WriteCommand(0x60, (color>>11));                  // BGCR0
01011     WriteCommand(0x61, (unsigned char)(color>>5));    // BGCR0
01012     WriteCommand(0x62, (unsigned char)(color));       // BGCR0
01013     return noerror;
01014 }
01015 
01016 
01017 RetCode_t RA8875::background(unsigned char r, unsigned char g, unsigned char b)
01018 {
01019     background(RGB(r,g,b));
01020 //    WriteCommand(0x60, r);
01021 //    WriteCommand(0x61, g);
01022 //    WriteCommand(0x62, b);
01023     return noerror;
01024 }
01025 
01026 
01027 RetCode_t RA8875::foreground(color_t color)
01028 {
01029     GraphicsDisplay::foreground(color);
01030     WriteCommand(0x63, (unsigned char)(color>>11));
01031     WriteCommand(0x64, (unsigned char)(color>>5));
01032     WriteCommand(0x65, (unsigned char)(color));
01033     return noerror;
01034 }
01035 
01036 
01037 RetCode_t RA8875::foreground(unsigned char r, unsigned char g, unsigned char b)
01038 {
01039     foreground(RGB(r,g,b));
01040 //    WriteCommand(0x63, r);
01041 //    WriteCommand(0x64, g);
01042 //    WriteCommand(0x65, b);
01043     return noerror;
01044 }
01045 
01046 
01047 color_t RA8875::GetForeColor(void)
01048 {
01049     color_t color;
01050     
01051     color  = (ReadCommand(0x63) & 0x1F) << 11;
01052     color |= (ReadCommand(0x64) & 0x3F) << 5;
01053     color |= (ReadCommand(0x65) & 0x1F);
01054     return color;
01055 }
01056 
01057 
01058 color_t RA8875::DOSColor(int i)
01059     {
01060     const color_t colors[16] = 
01061         {
01062         Black,    Blue,       Green,       Cyan,
01063         Red,      Magenta,    Brown,       Gray,
01064         Charcoal, BrightBlue, BrightGreen, BrightCyan,
01065         Orange,   Pink,       Yellow,      White
01066         };
01067     if (i < 16)
01068         return colors[i];
01069     else
01070         return 0;
01071     }
01072 
01073 
01074 const char * RA8875::DOSColorNames(int i) 
01075     {
01076     const char * names[16] = 
01077         {
01078         "Black",    "Blue",       "Green",       "Cyan",
01079         "Red",      "Magenta",    "Brown",       "Gray",
01080         "Charcoal", "BrightBlue", "BrightGreen", "BrightCyan",
01081         "Orange",   "Pink",       "Yellow",      "White"
01082         };
01083     if (i < 16)
01084         return names[i];
01085     else
01086         return NULL;
01087     }
01088 
01089 
01090 ///////////////////////////////////////////////////////////////
01091 // Private functions
01092 
01093 unsigned char RA8875::spiwrite(unsigned char data)
01094 {
01095     unsigned char retval;
01096     
01097     retval = spi.write(data);
01098     return retval;
01099 }
01100 
01101 
01102 unsigned char RA8875::spiread(void)
01103 {
01104     unsigned char retval;
01105     unsigned char data = 0;
01106     
01107     retval = spi.write(data);
01108     return retval;
01109 }
01110 
01111 
01112 RetCode_t RA8875::select(bool chipsel)
01113 {
01114     cs = (chipsel == true) ? 0 : 1;
01115     return noerror;
01116 }
01117 
01118 
01119 RetCode_t RA8875::init(int width, int height, int color_bpp)
01120 {
01121     Backlight_u8(0);
01122     WriteCommand(0x88, 0x0a);                   // PLLC1 - Phase Lock Loop registers
01123     wait_ms(1);
01124     WriteCommand(0x89, 0x02);
01125     wait_ms(1);
01126     
01127     // System Config Register (SYSR)
01128     if (color_bpp == 16) {
01129         WriteCommand(0x10, 0x0C);               // 16-bpp (65K colors) color depth, 8-bit interface
01130     } else { // color_bpp == 8
01131         WriteCommand(0x10, 0x00);               // 8-bpp (256 colors)
01132     }
01133     // Pixel Clock Setting Register (PCSR)
01134     WriteCommand(0x04, 0x82);                   // PDAT on PCLK falling edge, PCLK = 4 x System Clock
01135     wait_ms(1);
01136 
01137     // Horizontal Settings
01138     WriteCommand(0x14, width/8 - 1);            //HDWR//Horizontal Display Width Setting Bit[6:0]
01139     WriteCommand(0x15, 0x02);                   //HNDFCR//Horizontal Non-Display Period fine tune Bit[3:0]
01140     WriteCommand(0x16, 0x03);                   //HNDR//Horizontal Non-Display Period Bit[4:0]
01141     WriteCommand(0x17, 0x01);                   //HSTR//HSYNC Start Position[4:0]
01142     WriteCommand(0x18, 0x03);                   //HPWR//HSYNC Polarity ,The period width of HSYNC.
01143 
01144     // Vertical Settings
01145     WriteCommand(0x19, (height-1)&0xFF);        //VDHR0 //Vertical Display Height Bit [7:0]
01146     WriteCommand(0x1a, (height-1)>>8);          //VDHR1 //Vertical Display Height Bit [8]
01147     WriteCommand(0x1b, 0x0F);                   //VNDR0 //Vertical Non-Display Period Bit [7:0]
01148     WriteCommand(0x1c, 0x00);                   //VNDR1 //Vertical Non-Display Period Bit [8]
01149     WriteCommand(0x1d, 0x0e);                   //VSTR0 //VSYNC Start Position[7:0]
01150     WriteCommand(0x1e, 0x06);                   //VSTR1 //VSYNC Start Position[8]
01151     WriteCommand(0x1f, 0x01);                   //VPWR //VSYNC Polarity ,VSYNC Pulse Width[6:0]
01152 
01153     if (width >= 800 && height >= 480 && color_bpp > 8) {
01154         WriteCommand(0x20, 0x00);               // DPCR - 1-layer mode when the resolution is too high
01155     } else {
01156         WriteCommand(0x20, 0x80);               // DPCR - 2-layer mode
01157     }
01158     
01159     // Clear ram image
01160     window(0,0, width, height);             // Initialize to full screen
01161     SetTextCursorControl();
01162     foreground(Blue);
01163     background(Black);
01164     cls();
01165     return noerror;
01166 }
01167 
01168 #ifdef TESTENABLE
01169 
01170 #include "Arial12x12.h"
01171 #include "Small_6.h"
01172 
01173 //      ______________  ______________  ______________  _______________
01174 //     /_____   _____/ /  ___________/ /  ___________/ /_____   ______/
01175 //          /  /      /  /            /  /                  /  /
01176 //         /  /      /  /___         /  /__________        /  /
01177 //        /  /      /  ____/        /__________   /       /  /
01178 //       /  /      /  /                       /  /       /  /
01179 //      /  /      /  /__________  ___________/  /       /  /
01180 //     /__/      /_____________/ /_____________/       /__/
01181 //
01182 //    Everything from here down is test code.
01183 bool SuppressSlowStuff = false;
01184 
01185 
01186 void TextCursorTest(RA8875 & display, Serial & pc)
01187 {
01188     const char * iCursor = "The I-Beam cursor should be visible for this text.\r\n";
01189     const char * uCursor = "The Underscore cursor should be visible for this text.\r\n";
01190     const char * bCursor = "The Block cursor should be visible for this text.\r\n";
01191     const char * bbCursor = "The Blinking Block cursor should be visible for this text.\r\n";
01192     const char * p;
01193     int delay = 100;
01194     
01195     if (!SuppressSlowStuff)
01196         pc.printf("Text Cursor Test\r\n");
01197     else 
01198         delay = 0;
01199     display.background(Black);
01200     display.foreground(Blue);
01201     display.cls();
01202     display.Backlight_u8(255);
01203     display.puts(0,0, "Text Cursor Test.");
01204     
01205     // visible, non-blinking
01206     display.SetTextCursor(0,20);
01207     display.SetTextCursorControl(IBEAM, false);
01208     p = iCursor;
01209     while (*p) {
01210         display._putc(*p++);
01211         wait_ms(delay);
01212     }
01213 
01214     display.SetTextCursorControl(UNDER, false);
01215     p = uCursor;
01216     while (*p) {
01217         display._putc(*p++);
01218         wait_ms(delay);
01219     }
01220     
01221     display.SetTextCursorControl(BLOCK, false);
01222     p = bCursor;
01223     while (*p) {
01224         display._putc(*p++);
01225         wait_ms(delay);
01226     }
01227 
01228     display.SetTextCursorControl(BLOCK, true);
01229     p = bbCursor;
01230     while (*p) {
01231         display._putc(*p++);
01232         wait_ms(delay);
01233     }
01234     wait_ms(delay * 20);
01235     display.SetTextCursorControl(NOCURSOR, false);
01236 }
01237 
01238 
01239 void BacklightTest(RA8875 & display, Serial & pc, float ramptime)
01240 {
01241     char buf[60];
01242     unsigned int w = (ramptime * 1000)/ 256;
01243     int delay = 200;
01244 
01245     if (!SuppressSlowStuff)
01246         pc.printf("Backlight Test - ramp over %f sec.\r\n", ramptime);
01247     else {
01248         delay = 0;
01249         w = 0;
01250     }
01251     display.Backlight_u8(0);
01252     display.background(White);
01253     display.foreground(Blue);
01254     display.cls();
01255     wait_ms(delay);
01256     display.puts(0,0, "RA8875 Backlight Test - Ramp up.");
01257     for (int i=0; i <= 255; i++) {
01258         sprintf(buf, "%3d, %4d", i, w);
01259         display.puts(100,100,buf);
01260         display.Backlight_u8(i);
01261         wait_ms(w);
01262     }
01263 }
01264 
01265 
01266 void BacklightTest2(RA8875 & display, Serial & pc)
01267 {
01268     int delay = 20;
01269 
01270     if (!SuppressSlowStuff)
01271         pc.printf("Backlight Test 2\r\n");
01272     else
01273         delay = 0;
01274 
01275     // Dim it out at the end of the tests.
01276     display.foreground(Blue);
01277     display.puts(0,0, "Ramp Backlight down.");
01278     // Ramp it off
01279     for (int i=255; i != 0; i--) {
01280         display.Backlight_u8(i);
01281         wait_ms(delay);
01282     }
01283     display.Backlight_u8(0);
01284 }
01285 
01286 
01287 void ExternalFontTest(RA8875 & display, Serial & pc)
01288 {
01289     if (!SuppressSlowStuff)
01290         pc.printf("External Font Test\r\n");
01291     display.background(Black);
01292     display.foreground(Blue);
01293     display.cls();
01294     display.Backlight(1);
01295     display.puts(0,0, "External Font Test.");
01296 
01297     display.set_font(Small_6);
01298     display.puts(0,30, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\r\n");    
01299 
01300     display.set_font(Arial12x12);
01301     display.puts("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\r\n");
01302     display.set_font();     // restore to internal
01303     
01304     display.puts("Normal font again.");
01305     //display.window(0,0, display.width(), display.height());
01306 }
01307 
01308 
01309 void DOSColorTest(RA8875 & display, Serial & pc)
01310 {
01311     if (!SuppressSlowStuff)
01312         pc.printf("DOS Color Test\r\n");
01313     display.background(Black);
01314     display.foreground(Blue);
01315     display.cls();
01316     display.puts(0,0, "DOS Colors - Fore");
01317     display.puts(280,0, "Back");
01318     display.background(Gray);
01319     for (int i=0; i<16; i++) {
01320         display.foreground(display.DOSColor(i));
01321         display.puts(160, i*16, display.DOSColorNames(i));
01322         display.background(Black);
01323     }
01324     display.foreground(White);
01325     for (int i=0; i<16; i++) {
01326         display.background(display.DOSColor(i));
01327         display.puts(360, i*16, display.DOSColorNames(i));
01328         display.foreground(White);
01329     }
01330 }
01331 
01332 
01333 void WebColorTest(RA8875 & display, Serial & pc)
01334 {
01335     if (!SuppressSlowStuff)
01336         pc.printf("Web Color Test\r\n");
01337     display.background(Black);
01338     display.foreground(Blue);
01339     display.window(0,0, display.width(), display.height());
01340     display.cls();
01341     display.puts(0,0, "Web Color Test\r\n");
01342     display.SetTextFontSize(1,2);
01343     for (int i=0; i<sizeof(WebColors)/sizeof(WebColors[0]); i++) {
01344         display.background(WebColors[i]);
01345         display.puts(" ");
01346         if (i % 36 == 35)
01347             display.puts("\r\n");
01348     }
01349     display.SetTextFontSize(1,1);
01350 }
01351 
01352 
01353 void PixelTest(RA8875 & display, Serial & pc)
01354 {
01355     int i, c, x, y;
01356 
01357     if (!SuppressSlowStuff)
01358         pc.printf("Pixel Test\r\n");
01359     display.background(Black);
01360     display.foreground(Blue);
01361     display.cls();
01362     display.puts(0,0, "Pixel Test");
01363     for (i=0; i<1000; i++) {
01364         x = rand() % 480;
01365         y = 16 + rand() % (272-16);
01366         c = rand() % 16;
01367         //pc.printf("  (%d,%d) - %d\r\n", x,y,r1);
01368         display.pixel(x,y, display.DOSColor(c));
01369     }
01370 }
01371 
01372 
01373 void LineTest(RA8875 & display, Serial & pc)
01374 {
01375     int i, x, y, x2, y2;
01376 
01377     if (!SuppressSlowStuff)
01378         pc.printf("Line Test\r\n");
01379     display.background(Black);
01380     display.foreground(Blue);
01381     display.cls();
01382     display.puts(0,0, "Line Test");
01383     for (i=0; i<16; i++) {
01384         // Lines
01385         x = rand() % 480;
01386         y = rand() % 272;
01387         x2 = rand() % 480;
01388         y2 = rand() % 272;
01389         display.line(x,y, x2,y2, display.DOSColor(i));
01390     }
01391 }
01392 
01393 
01394 void RectangleTest(RA8875 & display, Serial & pc)
01395 {
01396     int i, x1,y1, x2,y2;
01397 
01398     if (!SuppressSlowStuff)
01399         pc.printf("Rectangle Test\r\n");
01400     display.background(Black);
01401     display.foreground(Blue);
01402     display.cls();
01403     display.puts(0,0, "Rectangle Test");
01404     for (i=0; i<16; i++) {
01405         x1 = rand() % 240;
01406         y1 = 50 + rand() % 200;
01407         x2 = rand() % 240;
01408         y2 = 50 + rand() % 200;
01409         display.rect(x1,y1, x2,y2, display.DOSColor(i));
01410 
01411         x1 = 240 + rand() % 240;
01412         y1 = 50 + rand() % 200;
01413         x2 = 240 + rand() % 240;
01414         y2 = 50 + rand() % 200;
01415         display.rect(x1,y1, x2,y2, FILL);
01416     }
01417 }
01418 
01419 
01420 void LayerTest(RA8875 & display, Serial & pc)
01421 {
01422     loc_t i, x1,y1, x2,y2, r1,r2;
01423 
01424     if (!SuppressSlowStuff)
01425         pc.printf("Layer Test\r\n");
01426 
01427     display.SelectLayer(0);
01428     display.background(Black);
01429     display.foreground(Blue);
01430     display.cls();
01431     display.puts(0,0, "Layer 0");
01432     for (i=0; i<16; i++) {
01433         x1 = rand() % 240;
01434         y1 = 50 + rand() % 200;
01435         x2 = x1 + rand() % 100;
01436         y2 = y1 + rand() % 100;
01437         r1 = rand() % (x2 - x1)/2;
01438         r2 = rand() % (y2 - y1)/2;
01439         display.roundrect(x1,y1, x2,y2, r1,r2, display.DOSColor(i));
01440         if (!SuppressSlowStuff)
01441             wait_ms(20);
01442     }
01443     if (!SuppressSlowStuff)
01444         wait_ms(1000);
01445 
01446     display.SelectLayer(1);
01447     display.background(Black);
01448     display.foreground(Yellow);
01449     display.cls();
01450     display.puts(240,0, "Layer 1");
01451     for (i=0; i<16; i++) {
01452         x1 = 300 + rand() % 100;
01453         y1 = 70 + rand() % 200;
01454         r1 = rand() % min(y1 - 20, 100);
01455         display.circle(x1,y1,r1, display.DOSColor(i));
01456         if (!SuppressSlowStuff)
01457             wait_ms(20);
01458     }
01459     display.SetLayerMode(1);        // Show it after the build-up
01460     if (!SuppressSlowStuff)
01461         wait_ms(2000);
01462 
01463     display.SelectLayer(0);
01464     display.SetLayerMode(0);        // Show Layer 0 again
01465     if (!SuppressSlowStuff)
01466         wait_ms(1000);
01467     display.SetLayerMode(3);        // Transparent mode
01468     if (!SuppressSlowStuff)
01469         wait_ms(1000);
01470     for (i=0; i<=8; i++) {
01471         display.SetLayerTransparency(i, 8-i);
01472         if (!SuppressSlowStuff)
01473             wait_ms(200);
01474     }
01475     
01476     // Restore before we exit
01477     display.SetLayerTransparency(0, 0);
01478     display.SetLayerMode(0);        // Restore to layer 0
01479 }
01480 
01481 
01482 void RoundRectTest(RA8875 & display, Serial & pc)
01483 {
01484     loc_t i, x1,y1, x2,y2, r1,r2;
01485 
01486     if (!SuppressSlowStuff)
01487         pc.printf("Round Rectangle Test\r\n");
01488     display.background(Black);
01489     display.foreground(Blue);
01490     display.cls();
01491     display.puts(0,0, "Rounded Rectangle Test");
01492     
01493     for (i=0; i<16; i++) {
01494         x1 = rand() % 240;
01495         y1 = 50 + rand() % 200;
01496         x2 = x1 + rand() % 100;
01497         y2 = y1 + rand() % 100;
01498         r1 = rand() % (x2 - x1)/2;
01499         r2 = rand() % (y2 - y1)/2;
01500         display.roundrect(x1,y1, x2,y2, 5,8, display.DOSColor(i));
01501 
01502         x1 = 240 + rand() % 240;
01503         y1 = 50 + rand() % 200;
01504         x2 = x1 + rand() % 100;
01505         y2 = y1 + rand() % 100;
01506         r1 = rand() % (x2 - x1)/2;
01507         r2 = rand() % (y2 - y1)/2;
01508         display.roundrect(x1,y1, x2,y2, r1,r2, FILL);
01509     }
01510 }
01511 
01512 
01513 void TriangleTest(RA8875 & display, Serial & pc)
01514 {
01515     int i, x1, y1, x2, y2, x3, y3;
01516 
01517     if (!SuppressSlowStuff)
01518         pc.printf("Triangle Test\r\n");
01519     display.background(Black);
01520     display.foreground(Blue);
01521     display.cls();
01522     display.puts(0,0, "Triangle Test");
01523 
01524     x1 = 150;
01525     y1 = 2;
01526     x2 = 190;
01527     y2 = 7;
01528     x3 = 170;
01529     y3 = 16;
01530     display.triangle(x1,y1, x2,y2, x3,y3);
01531 
01532     x1 = 200;
01533     y1 = 2;
01534     x2 = 240;
01535     y2 = 7;
01536     x3 = 220;
01537     y3 = 16;
01538     display.filltriangle(x1,y1, x2,y2, x3,y3, BrightRed);
01539 
01540     x1 = 300;
01541     y1 = 2;
01542     x2 = 340;
01543     y2 = 7;
01544     x3 = 320;
01545     y3 = 16;
01546     display.triangle(x1,y1, x2,y2, x3,y3, NOFILL);
01547 
01548     x1 = 400;
01549     y1 = 2;
01550     x2 = 440;
01551     y2 = 7;
01552     x3 = 420;
01553     y3 = 16;
01554     display.triangle(x1,y1, x2,y2, x3,y3, Blue);
01555 
01556     for (i=0; i<16; i++) {
01557         x1 = rand() % 240;
01558         y1 = 50 + rand() % 200;
01559         x2 = rand() % 240;
01560         y2 = 50 + rand() % 200;
01561         x3 = rand() % 240;
01562         y3 = 50 + rand() % 200;
01563         display.triangle(x1,y1, x2,y2, x3,y3, display.DOSColor(i));
01564         x1 = 240 + rand() % 240;
01565         y1 = 50 + rand() % 200;
01566         x2 = 240 + rand() % 240;
01567         y2 = 50 + rand() % 200;
01568         x3 = 240 + rand() % 240;
01569         y3 = 50 + rand() % 200;
01570         display.triangle(x1,y1, x2,y2, x3,y3, FILL);
01571     }
01572 }
01573 
01574 
01575 void CircleTest(RA8875 & display, Serial & pc)
01576 {
01577     int i, x, y, r1;
01578 
01579     if (!SuppressSlowStuff)
01580         pc.printf("Circle Test\r\n");
01581     display.background(Black);
01582     display.foreground(Blue);
01583     display.cls();
01584     display.puts(0,0, "Circle Test");
01585     for (i=0; i<16; i++) {
01586         x = 100 + rand() % 100;
01587         y = 70 + rand() % 200;
01588         r1 = rand() % min(y - 20, 100);
01589         //pc.printf("  (%d,%d) - %d\r\n", x,y,r1);
01590         display.circle(x,y,r1, display.DOSColor(i));
01591 
01592         x = 300 + rand() % 100;
01593         y = 70 + rand() % 200;
01594         r1 = rand() % min(y - 20, 100);
01595         //pc.printf("  (%d,%d) - %d FILL\r\n", x,y,r1);
01596         display.circle(x,y,r1, display.DOSColor(i), FILL);
01597     }
01598 }
01599 
01600 
01601 void EllipseTest(RA8875 & display, Serial & pc)
01602 {
01603     int i,x,y,r1,r2;
01604 
01605     if (!SuppressSlowStuff)
01606         pc.printf("Ellipse Test\r\n");
01607     display.background(Black);
01608     display.foreground(Blue);
01609     display.cls();
01610     display.puts(0,0, "Ellipse Test");
01611     for (i=0; i<16; i++) {
01612         x = 100 + rand() % 100;
01613         y = 70 + rand() % 200;
01614         r1 = rand() % min(y - 20, 100);
01615         r2 = rand() % min(y - 20, 100);
01616         display.ellipse(x,y,r1,r2, display.DOSColor(i));
01617 
01618         x = 300 + rand() % 100;
01619         y = 70 + rand() % 200;
01620         r1 = rand() % min(y - 20, 100);
01621         r2 = rand() % min(y - 20, 100);
01622         display.ellipse(x,y,r1,r2, FILL);
01623     }
01624 }
01625 
01626 
01627 void TestGraphicsBitmap(RA8875 & display, Serial & pc)
01628 {
01629     LocalFileSystem local("local");
01630     if (!SuppressSlowStuff)
01631         pc.printf("Bitmap File Load\r\n");    
01632     display.background(Black);
01633     display.foreground(Blue);
01634     display.cls();
01635     display.puts(0,0, "Graphics Test, loading /local/TestPat.bmp");
01636     wait(3);
01637 
01638     int r = display.RenderBitmapFile(0,0, "/local/TestPat.bmp");
01639 }
01640 
01641 
01642 void SpeedTest(RA8875 & display, Serial & pc)
01643 {
01644     Timer t;
01645     SuppressSlowStuff = true;
01646     pc.printf("\r\nSpeedTest disables delays, runs tests, reports overall time.\r\n");
01647     t.start();
01648     // do stuff fast
01649     TextCursorTest(display, pc);
01650     BacklightTest(display, pc, 0);
01651     BacklightTest2(display, pc);
01652     ExternalFontTest(display, pc);
01653     DOSColorTest(display, pc);
01654     WebColorTest(display, pc);
01655     PixelTest(display, pc);
01656     LineTest(display, pc);
01657     RectangleTest(display, pc);
01658     RoundRectTest(display, pc);
01659     TriangleTest(display, pc);
01660     CircleTest(display, pc);
01661     EllipseTest(display, pc);
01662     LayerTest(display, pc);
01663     //TestGraphicsBitmap(display, pc);
01664     pc.printf("SpeedTest completed in %d msec\r\n", t.read_ms());
01665     #ifdef PERF_METRICS
01666     display.ReportPerformance(pc);
01667     #endif
01668     SuppressSlowStuff = false;
01669 }
01670 
01671 
01672 void PrintScreen(RA8875 & display, Serial & pc)
01673 {
01674     LocalFileSystem local("local");
01675     if (!SuppressSlowStuff)
01676         pc.printf("PrintScreen\r\n");    
01677     display.PrintScreen( 0,0, 480,272, "/local/Capture.bmp");
01678 }
01679 
01680 
01681 void RunTestSet(RA8875 & lcd, Serial & pc)
01682 {
01683     int q = 0;
01684     int automode = 0;
01685     const unsigned char modelist[] = "BDWtGLlFROTPCEb";   // auto-test in this order.
01686 
01687     while(1) {
01688         pc.printf("\r\n"
01689                   "B - Backlight up      b - backlight dim\r\n"
01690                   "D - DOS Colors        W - Web Colors\r\n"
01691                   "t - text cursor       G - Graphics Bitmap\r\n"
01692                   "L - Lines             F - external Font\r\n"
01693                   "R - Rectangles        O - rOund rectangles\r\n"
01694                   "T - Triangles         P - Pixels  \r\n"
01695                   "C - Circles           E - Ellipses\r\n"
01696                   "A - Auto Test mode    S - Speed Test\r\n"
01697                   "p - print screen      r - reset  \r\n"
01698                   "l - layer test             \r\n"
01699                   #ifdef DEBUG
01700                   "0 - clear performance 1 - report performance\r\n"
01701                   #endif
01702                   "> ");
01703         if (automode == -1 || pc.readable()) {
01704             automode = -1;
01705             q = pc.getc();
01706             while (pc.readable())
01707                 pc.getc();
01708         } else if (automode >= 0) {
01709             q = modelist[automode];
01710         }
01711         switch(q) {
01712             #ifdef DEBUG
01713             case '0':
01714                 lcd.ClearPerformance();
01715                 break;
01716             case '1':
01717                 lcd.ReportPerformance(pc);
01718                 break;
01719             #endif
01720             case 'A':
01721                 automode = 0;
01722                 break;
01723             case 'B':
01724                 BacklightTest(lcd, pc, 2);
01725                 break;
01726             case 'b':
01727                 BacklightTest2(lcd, pc);
01728                 break;
01729             case 'D':
01730                 DOSColorTest(lcd, pc);
01731                 break;
01732             case 'W':
01733                 WebColorTest(lcd, pc);
01734                 break;
01735             case 't':
01736                 TextCursorTest(lcd, pc);
01737                 break;
01738             case 'F':
01739                 ExternalFontTest(lcd, pc);
01740                 break;
01741             case 'L':
01742                 LineTest(lcd, pc);
01743                 break;
01744             case 'l':
01745                 LayerTest(lcd, pc);
01746                 break;
01747             case 'R':
01748                 RectangleTest(lcd, pc);
01749                 break;
01750             case 'O':
01751                 RoundRectTest(lcd, pc);
01752                 break;
01753             case 'p':
01754                 PrintScreen(lcd, pc);
01755                 break;
01756             case 'S':
01757                 SpeedTest(lcd, pc);
01758                 break;
01759             case 'T':
01760                 TriangleTest(lcd, pc);
01761                 break;
01762             case 'P':
01763                 PixelTest(lcd, pc);
01764                 break;
01765             case 'G':
01766                 TestGraphicsBitmap(lcd, pc);
01767                 break;
01768             case 'C':
01769                 CircleTest(lcd, pc);
01770                 break;
01771             case 'E':
01772                 EllipseTest(lcd, pc);
01773                 break;
01774             case 'r':
01775                 pc.printf("Resetting ...\r\n");
01776                 wait_ms(20);
01777                 mbed_reset();
01778                 break;
01779             default:
01780                 printf("huh?\n");
01781                 break;
01782         }
01783         if (automode >= 0) {
01784             automode++;
01785             if (automode >= sizeof(modelist))
01786                 automode = 0;
01787             wait_ms(2000);
01788         }
01789         wait_ms(200);
01790     }
01791 }
01792 
01793 #endif // TESTENABLE