Production Test Program (PTP) for the LPC4088 Experiment Base Board

Dependencies:   EALib I2S LM75B SDFileSystem mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers TestDisplay.cpp Source File

TestDisplay.cpp

00001 /*
00002  *  Copyright 2013 Embedded Artists AB
00003  *
00004  *  Licensed under the Apache License, Version 2.0 (the "License");
00005  *  you may not use this file except in compliance with the License.
00006  *  You may obtain a copy of the License at
00007  *
00008  *    http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  *  Unless required by applicable law or agreed to in writing, software
00011  *  distributed under the License is distributed on an "AS IS" BASIS,
00012  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  *  See the License for the specific language governing permissions and
00014  *  limitations under the License.
00015  */
00016 
00017 /******************************************************************************
00018  * Includes
00019  *****************************************************************************/
00020 
00021 #include "mbed.h"
00022 #include "TestDisplay.h"
00023 #include "sdram.h"
00024 
00025 
00026 /******************************************************************************
00027  * Defines and typedefs
00028  *****************************************************************************/
00029 
00030 #define LCD_CONFIGURATION \
00031         40,                         /* horizontalBackPorch */ \
00032         5,                          /* horizontalFrontPorch */ \
00033         2,                          /* hsync */ \
00034         480,                        /* width */ \
00035         8,                          /* verticalBackPorch */ \
00036         8,                          /* verticalFrontPorch */ \
00037         2,                          /* vsync */ \
00038         272,                        /* height */ \
00039         false,                      /* invertOutputEnable */ \
00040         false,                      /* invertPanelClock */ \
00041         true,                       /* invertHsync */ \
00042         true,                       /* invertVsync */ \
00043         1,                          /* acBias */ \
00044         LcdController::Bpp_16_565,  /* bpp */ \
00045         9000000,                    /* optimalClock */ \
00046         LcdController::Tft,         /* panelType */ \
00047         false                       /* dualPanel */
00048 
00049 #define LCD_INIT_STRING  (char*)"v1,cd0,c50,cc0,c30,d100,c31,d100,cd1,d10,o,c51,cc100"
00050 
00051 /******************************************************************************
00052  * Public Functions
00053  *****************************************************************************/
00054 
00055 /*
00056    Prerequisites:
00057  
00058    - A display must be connected to the LPC4088 Experiment Base Board
00059      with the FPC connector
00060 
00061    - The touch controller uses the I2C bus so for this test to work 
00062      jumpers JP8 and JP9 on the LPC4088 Experiment Base Board must 
00063      both be in positions 1-2
00064 
00065 */
00066 
00067 /* 
00068    Test Description:
00069 
00070    - The SDRAM is initialized and a framebuffer is allocated
00071    - Display is initialized and a color bar (red-green-blue) is shown
00072    - The user have 10 seconds to test display contrast by turning the
00073      right trimpot on the board
00074    - The touch calibration is started and the user must press each of
00075      the four crosshairs that appear.
00076    - After calibration the display can be drawn upon for 5 seconds.
00077    
00078    Any failed part test will abort the sequence
00079 */
00080 
00081 TestDisplay::TestDisplay() : 
00082     _lcdCfg(LCD_CONFIGURATION),
00083     _lcdBoard(P0_27, P0_28),
00084     _touch(P0_27, P0_28, P2_25) {
00085         
00086     if (sdram_init() == 1) {
00087         printf("Failed to initialize SDRAM\n");
00088         _framebuffer = 0;
00089     } else {
00090         _framebuffer = (uint32_t) malloc(_lcdCfg.width * _lcdCfg.height * 2);
00091     }
00092     _displayWorking = false;
00093 }
00094 
00095 TestDisplay::~TestDisplay() {
00096     if (_framebuffer != 0) {
00097         free((void*)_framebuffer);
00098         _framebuffer = 0;
00099     }
00100 }
00101 
00102 void TestDisplay::showStatus(bool success) {
00103     if (_displayWorking) {
00104         if (success) {
00105             // Green cannot be memsetted so it will have to be the
00106             // more manual way
00107             uint16_t* p = (uint16_t*)_framebuffer;
00108             for (int x = _lcdCfg.width; x > 0; x--) {
00109                 for (int y = _lcdCfg.height; y > 0; y--) {
00110                     *p++ = 0x07e0;
00111                 }
00112             }
00113         } else {
00114             // Red is possible to set directly as 0xe0e0 in RGB565 have
00115             // only significant RED bits set.
00116             memset((uint8_t*)_framebuffer, 0xe0, _lcdCfg.width * _lcdCfg.height * 2); // RED
00117         }
00118     }    
00119 }
00120 
00121 bool TestDisplay::runTest() {
00122     bool testPassed = false;
00123     do {
00124         if (_framebuffer == 0) {
00125             printf("Failed to allocate memory for framebuffer\n");
00126             break;
00127         }
00128         
00129         // Prepare framebuffer
00130         drawBars();
00131 
00132         EaLcdBoard::Result result = _lcdBoard.open(&_lcdCfg, LCD_INIT_STRING);
00133         if (result != EaLcdBoard::Ok) {
00134             printf("Failed to open display, error %d\n", result);
00135             break;
00136         }
00137 
00138         result = _lcdBoard.setFrameBuffer(_framebuffer);
00139         if (result != EaLcdBoard::Ok) {
00140             printf("Failed to set framebuffer, error %d\n", result);
00141             break;
00142         }
00143             
00144         printf("Initialized. Control contrast with right trimpot (8 seconds)\n");
00145         AnalogIn trimpot(p15);
00146         Timer t;
00147         t.start();
00148         int delays = 0;
00149         float last = -0.999;
00150         while (t.read() < 8) {
00151             float f = trimpot.read();
00152             if (f != last) {
00153                 last = f;
00154                 _lcdBoard.setBC(100*f); // contrast is in 0..100 and analog value is 0.000..1.000
00155             }
00156             wait(0.1);
00157             
00158             // Countdown
00159             if (delays%10 == 0) {
00160                 printf("%ds\n", (80-delays)/10);
00161             }
00162             delays++;
00163         }
00164         
00165         int vh,vl,r,ty,att;
00166         for (att = 1; att <= 5;att++) {
00167             if (_touch.info(&vh,&vl,&r,&ty)) {
00168                 printf("Touch info: v%d.%d, %d-bit resolution, type 0x%x\n", vh, vl, r, ty);
00169                 break;
00170             } else {
00171                 printf("Attempt %d to get touch controller info failed...\n", att);
00172                 wait(1);
00173             }
00174         }
00175         if (att > 5) {
00176             printf("Failed to read touch controller info even after %d attempts\n", att);
00177             break;
00178         }
00179 
00180         printf("Calibrate display\n");
00181         testPassed = calibrate_display();
00182     } while(0);
00183     
00184     _displayWorking = testPassed;
00185     return testPassed;
00186 }
00187 
00188 void TestDisplay::drawBars() {
00189     uint16_t* p = (uint16_t*)_framebuffer;
00190     int third = _lcdCfg.width/3;
00191     for (int y = 0; y < _lcdCfg.height; y++) {
00192         int x;
00193         for (x = 0; x < third; x++) {
00194             *p = 0xf800;
00195             p++;
00196         }
00197         for (; x < 2*third; x++) {
00198             *p = 0x07e0;
00199             p++;
00200         }
00201         for (; x < _lcdCfg.width; x++) {
00202             *p = 0x001f;
00203             p++;
00204         }
00205     }
00206 }
00207 
00208 void TestDisplay::calibrate_drawMarker(Graphics &g, uint16_t x, uint16_t y, bool erase) {
00209     uint16_t color = (erase ? 0x0000 : 0xffff);
00210     g.put_line(x-15, y, x+15, y, color);
00211     g.put_line(x, y-15, x, y+15, color);
00212     g.put_circle(x, y, color, 10, false);
00213 }
00214 
00215 bool TestDisplay::calibrate_display() {
00216     bool morePoints = true;
00217     uint16_t x, y;
00218     int point = 0;
00219     Graphics g((uint16_t*)_framebuffer, _lcdCfg.width, _lcdCfg.height);
00220     
00221     do {
00222         if (!_touch.init(_lcdCfg.width, _lcdCfg.height)) {
00223             printf("Failed to initialize touch controller\n");
00224             break;
00225         }
00226         if (!_touch.calibrateStart()) {
00227             printf("Failed to start calibration\n");
00228             break;
00229         }  
00230         while (morePoints) {
00231             if (point++ > 0) {
00232                 // erase old location
00233                 calibrate_drawMarker(g, x, y, true);
00234             }
00235             if (!_touch.getNextCalibratePoint(&x, &y)) {
00236                 printf("Failed to get calibration point\n");
00237                 break;
00238             }
00239             calibrate_drawMarker(g, x, y, false);
00240             if (!_touch.waitForCalibratePoint(&morePoints, 0)) {
00241                 printf("Failed to get user click\n");
00242                 break;
00243             }
00244         }
00245         if (morePoints) {
00246             // aborted calibration due to error(s)
00247             break;
00248         }
00249 
00250         // erase old location
00251         calibrate_drawMarker(g, x, y, true);
00252 
00253         // allow user to draw for 5 seconds
00254         Timer t;
00255         t.start();
00256         TouchPanel::touchCoordinate_t tc;
00257         while(t.read() < 6) {
00258             if (_touch.read(tc)) {
00259                 //printf("TC: x,y,z = {%5d, %5d, %5d}\n", tc.x, tc.y, tc.z);
00260                 if (tc.z) {
00261                     g.put_dot(tc.x, tc.y, 0xffff);
00262                 }
00263             }
00264         }
00265     } while(0);
00266     
00267     return !morePoints;
00268 }
00269 
00270 
00271