Production Test Program (PTP) for the LPC4088 Experiment Base Board
Dependencies: EALib I2S LM75B SDFileSystem mbed
Diff: TestDisplay.cpp
- Revision:
- 2:2f4b7535ceb3
- Child:
- 7:48375cb50f3a
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TestDisplay.cpp Thu Aug 28 09:36:13 2014 +0000 @@ -0,0 +1,264 @@ +/* + * Copyright 2013 Embedded Artists AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/****************************************************************************** + * Includes + *****************************************************************************/ + +#include "mbed.h" +#include "TestDisplay.h" +#include "sdram.h" + + +/****************************************************************************** + * Defines and typedefs + *****************************************************************************/ + +#define LCD_CONFIGURATION \ + 40, /* horizontalBackPorch */ \ + 5, /* horizontalFrontPorch */ \ + 2, /* hsync */ \ + 480, /* width */ \ + 8, /* verticalBackPorch */ \ + 8, /* verticalFrontPorch */ \ + 2, /* vsync */ \ + 272, /* height */ \ + false, /* invertOutputEnable */ \ + false, /* invertPanelClock */ \ + true, /* invertHsync */ \ + true, /* invertVsync */ \ + 1, /* acBias */ \ + LcdController::Bpp_16_565, /* bpp */ \ + 9000000, /* optimalClock */ \ + LcdController::Tft, /* panelType */ \ + false /* dualPanel */ + +#define LCD_INIT_STRING (char*)"v1,cd0,c50,cc0,c30,d100,c31,d100,cd1,d10,o,c51,cc100" + +/****************************************************************************** + * Public Functions + *****************************************************************************/ + +/* + Prerequisites: + + - A display must be connected to the LPC4088 Experiment Base Board + with the FPC connector + + - The touch controller uses the I2C bus so for this test to work + jumpers JP8 and JP9 on the LPC4088 Experiment Base Board must + both be in positions 1-2 + +*/ + +/* + Test Description: + + - The SDRAM is initialized and a framebuffer is allocated + - Display is initialized and a color bar (red-green-blue) is shown + - The user have 10 seconds to test display contrast by turning the + right trimpot on the board + - The touch calibration is started and the user must press each of + the four crosshairs that appear. + - After calibration the display can be drawn upon for 5 seconds. + + Any failed part test will abort the sequence +*/ + +TestDisplay::TestDisplay() : + _lcdCfg(LCD_CONFIGURATION), + _lcdBoard(P0_27, P0_28), + _touch(P0_27, P0_28, P2_25) { + + if (sdram_init() == 1) { + printf("Failed to initialize SDRAM\n"); + _framebuffer = 0; + } else { + _framebuffer = (uint32_t) malloc(_lcdCfg.width * _lcdCfg.height * 2); + } + _displayWorking = false; +} + +TestDisplay::~TestDisplay() { + if (_framebuffer != 0) { + free((void*)_framebuffer); + _framebuffer = 0; + } +} + +void TestDisplay::showStatus(bool success) { + if (_displayWorking) { + if (success) { + // Green cannot be memsetted so it will have to be the + // more manual way + uint16_t* p = (uint16_t*)_framebuffer; + for (int x = _lcdCfg.width; x > 0; x--) { + for (int y = _lcdCfg.height; y > 0; y--) { + *p++ = 0x07e0; + } + } + } else { + // Red is possible to set directly as 0xe0e0 in RGB565 have + // only significant RED bits set. + memset((uint8_t*)_framebuffer, 0xe0, _lcdCfg.width * _lcdCfg.height * 2); // RED + } + } +} + +bool TestDisplay::runTest() { + bool testPassed = false; + do { + if (_framebuffer == 0) { + printf("Failed to allocate memory for framebuffer\n"); + break; + } + + // Prepare framebuffer + drawBars(); + + EaLcdBoard::Result result = _lcdBoard.open(&_lcdCfg, LCD_INIT_STRING); + if (result != EaLcdBoard::Ok) { + printf("Failed to open display, error %d\n", result); + break; + } + + result = _lcdBoard.setFrameBuffer(_framebuffer); + if (result != EaLcdBoard::Ok) { + printf("Failed to set framebuffer, error %d\n", result); + break; + } + + printf("Initialized. Control contrast with right trimpot (8 seconds)\n"); + AnalogIn trimpot(p15); + Timer t; + t.start(); + int delays = 0; + float last = -0.999; + while (t.read() < 8) { + float f = trimpot.read(); + if (f != last) { + last = f; + _lcdBoard.setBC(100*f); // contrast is in 0..100 and analog value is 0.000..1.000 + } + wait(0.1); + + // Countdown + if (delays%10 == 0) { + printf("%ds\n", (80-delays)/10); + } + delays++; + } + + int vh,vl,r,ty; + if (_touch.info(&vh,&vl,&r,&ty)) { + printf("Touch info: v%d.%d, %d-bit resolution, type 0x%x\n", vh, vl, r, ty); + } else { + printf("Failed to read touch information\n"); + break; + } + + printf("Calibrate display\n"); + testPassed = calibrate_display(); + } while(0); + + _displayWorking = testPassed; + return testPassed; +} + +void TestDisplay::drawBars() { + uint16_t* p = (uint16_t*)_framebuffer; + int third = _lcdCfg.width/3; + for (int y = 0; y < _lcdCfg.height; y++) { + int x; + for (x = 0; x < third; x++) { + *p = 0xf800; + p++; + } + for (; x < 2*third; x++) { + *p = 0x07e0; + p++; + } + for (; x < _lcdCfg.width; x++) { + *p = 0x001f; + p++; + } + } +} + +void TestDisplay::calibrate_drawMarker(Graphics &g, uint16_t x, uint16_t y, bool erase) { + uint16_t color = (erase ? 0x0000 : 0xffff); + g.put_line(x-15, y, x+15, y, color); + g.put_line(x, y-15, x, y+15, color); + g.put_circle(x, y, color, 10, false); +} + +bool TestDisplay::calibrate_display() { + bool morePoints = true; + uint16_t x, y; + int point = 0; + Graphics g((uint16_t*)_framebuffer, _lcdCfg.width, _lcdCfg.height); + + do { + if (!_touch.init(_lcdCfg.width, _lcdCfg.height)) { + printf("Failed to initialize touch controller\n"); + break; + } + if (!_touch.calibrateStart()) { + printf("Failed to start calibration\n"); + break; + } + while (morePoints) { + if (point++ > 0) { + // erase old location + calibrate_drawMarker(g, x, y, true); + } + if (!_touch.getNextCalibratePoint(&x, &y)) { + printf("Failed to get calibration point\n"); + break; + } + calibrate_drawMarker(g, x, y, false); + if (!_touch.waitForCalibratePoint(&morePoints, 0)) { + printf("Failed to get user click\n"); + break; + } + } + if (morePoints) { + // aborted calibration due to error(s) + break; + } + + // erase old location + calibrate_drawMarker(g, x, y, true); + + // allow user to draw for 5 seconds + Timer t; + t.start(); + TouchPanel::touchCoordinate_t tc; + while(t.read() < 6) { + if (_touch.read(tc)) { + //printf("TC: x,y,z = {%5d, %5d, %5d}\n", tc.x, tc.y, tc.z); + if (tc.z) { + g.put_dot(tc.x, tc.y, 0xffff); + } + } + } + } while(0); + + return !morePoints; +} + + +