Production Test Program (PTP) for the LPC4088 Experiment Base Board
Dependencies: EALib I2S LM75B SDFileSystem mbed
TestDisplay.cpp
- Committer:
- embeddedartists
- Date:
- 2014-10-01
- Revision:
- 9:eb6086159020
- Parent:
- 7:48375cb50f3a
File content as of revision 9:eb6086159020:
/*
* 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,att;
for (att = 1; att <= 5;att++) {
if (_touch.info(&vh,&vl,&r,&ty)) {
printf("Touch info: v%d.%d, %d-bit resolution, type 0x%x\n", vh, vl, r, ty);
break;
} else {
printf("Attempt %d to get touch controller info failed...\n", att);
wait(1);
}
}
if (att > 5) {
printf("Failed to read touch controller info even after %d attempts\n", att);
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;
}