Graphical demo for the LPC4088 Experiment Base Board with one of the Display Expansion Kits. This demo shows a number of dots projected on a rotating sphere.
Revision 0:79b286950b60, committed 2014-10-03
- Comitter:
- embeddedartists
- Date:
- Fri Oct 03 13:15:25 2014 +0000
- Commit message:
- First version
Changed in this revision
diff -r 000000000000 -r 79b286950b60 AR1021I2C.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/AR1021I2C.cpp Fri Oct 03 13:15:25 2014 +0000 @@ -0,0 +1,560 @@ +/* + * 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 "mbed_debug.h" + +#include "AR1021I2C.h" + +/****************************************************************************** + * Defines and typedefs + *****************************************************************************/ + +#define AR1021_REG_TOUCH_THRESHOLD (0x02) +#define AR1021_REG_SENS_FILTER (0x03) +#define AR1021_REG_SAMPLING_FAST (0x04) +#define AR1021_REG_SAMPLING_SLOW (0x05) +#define AR1021_REG_ACC_FILTER_FAST (0x06) +#define AR1021_REG_ACC_FILTER_SLOW (0x07) +#define AR1021_REG_SPEED_THRESHOLD (0x08) +#define AR1021_REG_SLEEP_DELAY (0x0A) +#define AR1021_REG_PEN_UP_DELAY (0x0B) +#define AR1021_REG_TOUCH_MODE (0x0C) +#define AR1021_REG_TOUCH_OPTIONS (0x0D) +#define AR1021_REG_CALIB_INSETS (0x0E) +#define AR1021_REG_PEN_STATE_REPORT_DELAY (0x0F) +#define AR1021_REG_TOUCH_REPORT_DELAY (0x11) + + +#define AR1021_CMD_GET_VERSION (0x10) +#define AR1021_CMD_ENABLE_TOUCH (0x12) +#define AR1021_CMD_DISABLE_TOUCH (0x13) +#define AR1021_CMD_CALIBRATE_MODE (0x14) +#define AR1021_CMD_REGISTER_READ (0x20) +#define AR1021_CMD_REGISTER_WRITE (0x21) +#define AR1021_CMD_REGISTER_START_ADDR_REQUEST (0x22) +#define AR1021_CMD_REGISTER_WRITE_TO_EEPROM (0x23) +#define AR1021_CMD_EEPROM_READ (0x28) +#define AR1021_CMD_EEPROM_WRITE (0x29) +#define AR1021_CMD_EEPROM_WRITE_TO_REGISTERS (0x2B) + +#define AR1021_RESP_STAT_OK (0x00) +#define AR1021_RESP_STAT_CMD_UNREC (0x01) +#define AR1021_RESP_STAT_HDR_UNREC (0x03) +#define AR1021_RESP_STAT_TIMEOUT (0x04) +#define AR1021_RESP_STAT_CANCEL_CALIB (0xFC) + + +#define AR1021_ERR_NO_HDR (-1000) +#define AR1021_ERR_INV_LEN (-1001) +#define AR1021_ERR_INV_RESP (-1002) +#define AR1021_ERR_INV_RESPLEN (-1003) +#define AR1021_ERR_TIMEOUT (-1004) + +// bit 7 is always 1 and bit 0 defines pen up or down +#define AR1021_PEN_MASK (0x81) + +#define AR1021_NUM_CALIB_POINTS (4) + +#define AR1021_ADDR (0x4D << 1) + +#define AR1021_TIMEOUT 1000 //how many ms to wait for responce +#define AR1021_RETRY 5 //how many times to retry sending command + +#define AR1021_MIN(__a, __b) (((__a)<(__b))?(__a):(__b)) + + +AR1021I2C::AR1021I2C(PinName sda, PinName scl, PinName siq) : +_i2c(sda, scl), _siq(siq), _siqIrq(siq) +{ + _i2c.frequency(200000); + + // default calibration inset is 25 -> (25/2 = 12.5%) + _inset = 25; + + // make sure _calibPoint has an invalid value to begin with + // correct value is set in calibrateStart() + _calibPoint = AR1021_NUM_CALIB_POINTS+1; + + _x = 0; + _y = 0; + _pen = 0; + + _initialized = false; +} + + +bool AR1021I2C::read(touchCoordinate_t &coord) { + + if (!_initialized) return false; + + coord.x = _x * _width/4095; + coord.y = _y * _height/4095; + coord.z = _pen; + + return true; +} + + +bool AR1021I2C::init(uint16_t width, uint16_t height) { + int result = 0; + bool ok = false; + int attempts = 0; + + _width = width; + _height = height; + + while (1) { + + do { + // disable touch + result = cmd(AR1021_CMD_DISABLE_TOUCH, NULL, 0, NULL, 0); + if (result != 0) { + debug("disable touch failed (%d)\n", result); + break; + } + + char regOffset = 0; + int regOffLen = 1; + result = cmd(AR1021_CMD_REGISTER_START_ADDR_REQUEST, NULL, 0, + ®Offset, ®OffLen); + if (result != 0) { + debug("register offset request failed (%d)\n", result); + break; + } + + // enable calibrated coordinates + // high, low address, len, value + char toptions[4] = {0x00, AR1021_REG_TOUCH_OPTIONS+regOffset, 0x01, 0x01}; + result = cmd(AR1021_CMD_REGISTER_WRITE, toptions, 4, NULL, 0); + if (result != 0) { + debug("register write request failed (%d)\n", result); + break; + } + + // save registers to eeprom + result = cmd(AR1021_CMD_REGISTER_WRITE_TO_EEPROM, NULL, 0, NULL, 0); + if (result != 0) { + debug("register write to eeprom failed (%d)\n", result); + break; + } + + // enable touch + result = cmd(AR1021_CMD_ENABLE_TOUCH, NULL, 0, NULL, 0); + if (result != 0) { + debug("enable touch failed (%d)\n", result); + break; + } + + _siqIrq.rise(this, &AR1021I2C::readTouchIrq); + + _initialized = true; + ok = true; + + } while(0); + + if (ok) break; + + // try to run the initialize sequence at most 2 times + if(++attempts >= 2) break; + } + + + return ok; +} + +bool AR1021I2C::calibrateStart() { + bool ok = false; + int result = 0; + int attempts = 0; + + if (!_initialized) return false; + + _siqIrq.rise(NULL); + + while(1) { + + do { + // disable touch + result = cmd(AR1021_CMD_DISABLE_TOUCH, NULL, 0, NULL, 0); + if (result != 0) { + debug("disable touch failed (%d)\n", result); + break; + } + + char regOffset = 0; + int regOffLen = 1; + result = cmd(AR1021_CMD_REGISTER_START_ADDR_REQUEST, NULL, 0, + ®Offset, ®OffLen); + if (result != 0) { + debug("register offset request failed (%d)\n", result); + break; + } + + // set insets + // enable calibrated coordinates + // high, low address, len, value + char insets[4] = {0x00, AR1021_REG_CALIB_INSETS+regOffset, 0x01, _inset}; + result = cmd(AR1021_CMD_REGISTER_WRITE, insets, 4, NULL, 0); + if (result != 0) { + debug("register write request failed (%d)\n", result); + break; + } + + // calibration mode + char calibType = 4; + result = cmd(AR1021_CMD_CALIBRATE_MODE, &calibType, 1, NULL, 0, false); + if (result != 0) { + debug("calibration mode failed (%d)\n", result); + break; + } + + _calibPoint = 0; + ok = true; + + } while(0); + + if (ok) break; + + // try to run the calibrate mode sequence at most 2 times + if (++attempts >= 2) break; + } + + return ok; +} + +bool AR1021I2C::getNextCalibratePoint(uint16_t* x, uint16_t* y) { + + if (!_initialized) return false; + if (x == NULL || y == NULL) return false; + + int xInset = (_width * _inset / 100) / 2; + int yInset = (_height * _inset / 100) / 2; + + switch(_calibPoint) { + case 0: + *x = xInset; + *y = yInset; + break; + case 1: + *x = _width - xInset; + *y = yInset; + break; + case 2: + *x = _width - xInset; + *y = _height - yInset; + break; + case 3: + *x = xInset; + *y = _height - yInset; + break; + default: + return false; + } + + return true; +} + +bool AR1021I2C::waitForCalibratePoint(bool* morePoints, uint32_t timeout) { + int result = 0; + bool ret = false; + + if (!_initialized) return false; + + do { + if (morePoints == NULL || _calibPoint >= AR1021_NUM_CALIB_POINTS) { + break; + } + + // wait for response + result = waitForCalibResponse(timeout); + if (result != 0) { + debug("wait for calibration response failed (%d)\n", result); + break; + } + + _calibPoint++; + *morePoints = (_calibPoint < AR1021_NUM_CALIB_POINTS); + + + // no more points -> enable touch + if (!(*morePoints)) { + + // wait for calibration data to be written to eeprom + // before enabling touch + result = waitForCalibResponse(timeout); + if (result != 0) { + debug("wait for calibration response failed (%d)\n", result); + break; + } + + + // clear chip-select since calibration is done; +// _cs = 1; + + result = cmd(AR1021_CMD_ENABLE_TOUCH, NULL, 0, NULL, 0); + if (result != 0) { + debug("enable touch failed (%d)\n", result); + break; + } + + _siqIrq.rise(this, &AR1021I2C::readTouchIrq); + } + + ret = true; + + } while (0); + + + + if (!ret) { + // make sure to set chip-select off in case of an error +// _cs = 1; + // calibration must restart if an error occurred + _calibPoint = AR1021_NUM_CALIB_POINTS+1; + } + + + + return ret; +} + +int AR1021I2C::cmd(char cmd, char* data, int len, char* respBuf, int* respLen, + bool setCsOff) { + + int ret = 0; + int readLen = (respLen == NULL) ? 0 : *respLen; + for (int attempt = 1; attempt <= AR1021_RETRY; attempt++) { + if (attempt > 1) { + wait_ms(50); + } + + // command request + // --------------- + // 0x00 0x55 len cmd data + // 0x00 = protocol command byte + // 0x55 = header + // len = data length + cmd (1) + // data = data to send + + _i2c.start(); + _i2c.write(AR1021_ADDR); //send write address + _i2c.write(0x00); + _i2c.write(0x55); //header + _i2c.write(len+1); //message length + _i2c.write(cmd); + for (int i = 0; i < len; i++) { + _i2c.write(data[i]); + } + wait_us(60); + _i2c.stop(); + + // wait for response (siq goes high when response is available) + Timer t; + t.start(); + while(_siq.read() != 1 && t.read_ms() < AR1021_TIMEOUT); + + if (t.read_ms() < AR1021_TIMEOUT) { + + // command response + // --------------- + // 0x55 len status cmd data + // 0x55 = header + // len = number of bytes following the len byte (i.e. including the status&cmd) + // status = status + // cmd = command ID + // data = data to receive + _i2c.start(); + _i2c.write(AR1021_ADDR + 1); //send read address + char header = _i2c.read(1); //header should always be 0x55 + if (header != 0x55) { + ret = AR1021_ERR_NO_HDR; + continue; + } + char length = _i2c.read(1); //data length + if (length < 2) { + ret = AR1021_ERR_INV_LEN; //must have at least status and command bytes + continue; + } + length -= 2; + if (length > readLen) { + ret = AR1021_ERR_INV_LEN; //supplied buffer is not enough + continue; + } + + char status = _i2c.read(1); //command status + char usedCmd; + if (readLen <= 0) { + usedCmd = _i2c.read(0); //no data => read command byte + NACK + } else { + usedCmd = _i2c.read(1); //which command + + //we need to send a NACK on the last read. + int i; + for (i = 0; i < (length-1); i++) { + respBuf[i] = _i2c.read(1); + } + respBuf[i] = _i2c.read(0); //last returned data byte + NACK + } + _i2c.stop(); + + + if (status != AR1021_RESP_STAT_OK) { + ret = -status; + continue; + } + if (usedCmd != cmd) { + ret = AR1021_ERR_INV_RESP; + continue; + } + + // success + ret = 0; + break; + + } else { + ret = AR1021_ERR_TIMEOUT; + continue; + } + } + + return ret; +} + +int AR1021I2C::waitForCalibResponse(uint32_t timeout) { + Timer t; + int ret = 0; + + t.start(); + + // wait for siq + while (_siq.read() != 1 && + (timeout == 0 || (uint32_t)t.read_ms() < (int)timeout)); + + + do { + + if (timeout > 0 && (uint32_t)t.read_ms() >= timeout) { + ret = AR1021_ERR_TIMEOUT; + break; + } + + // command response + // --------------- + // 0x55 len status cmd data + // 0x55 = header + // len = number of bytes following the len byte (should be 2) + // status = status + // cmd = command ID + _i2c.start(); + _i2c.write(AR1021_ADDR + 1); //send read address + char header = _i2c.read(1); //header should always be 0x55 + char length = _i2c.read(1); //data length + + if (header != 0x55) { + ret = AR1021_ERR_NO_HDR; + break; + } + if (length < 2) { + ret = AR1021_ERR_INV_LEN; + break; + } + char status = _i2c.read(1); //status + char cmd = _i2c.read(0); //command, should be NACK'ed + _i2c.stop(); + if (status != AR1021_RESP_STAT_OK) { + ret = -status; + break; + } + if (cmd != AR1021_CMD_CALIBRATE_MODE) { + ret = AR1021_ERR_INV_RESP; + break; + } + + // success + ret = 0; + + } while (0); + + return ret; +} + + +void AR1021I2C::readTouchIrq() { + while(_siq.read() == 1) { + + // touch coordinates are sent in a 5-byte data packet + _i2c.start(); + _i2c.write(AR1021_ADDR + 1); //send read address + int pen = _i2c.read(1); + int xlo = _i2c.read(1); + int xhi = _i2c.read(1); + int ylo = _i2c.read(1); + int yhi = _i2c.read(0); + _i2c.stop(); + + // pen down + if ((pen&AR1021_PEN_MASK) == (1<<7|1<<0)) { + _pen = 1; + } + // pen up + else if ((pen&AR1021_PEN_MASK) == (1<<7)){ + _pen = 0; + } + // invalid value + else { + continue; + } + + _x = ((xhi<<7)|xlo); + _y = ((yhi<<7)|ylo); + } +} + +bool AR1021I2C::info(int* verHigh, int* verLow, int* resBits, int* type) +{ + char buff[3] = {0,0,0}; + int read = 3; + int res = cmd(AR1021_CMD_GET_VERSION, NULL, 0, buff, &read); + if (res == 0) { + *verHigh = buff[0]; + *verLow = buff[1]; + switch(buff[2] & 3) { + case 0: + *resBits = 8; + break; + case 1: + *resBits = 10; + break; + case 2: + *resBits = 12; + break; + case 3: + *resBits = 12; + break; + default: + res = 25; + printf("Invalid resolution %d\n", buff[2]&3); + break; + } + *type = buff[2]>>2; + } + return (res == 0); +}
diff -r 000000000000 -r 79b286950b60 AR1021I2C.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/AR1021I2C.h Fri Oct 03 13:15:25 2014 +0000 @@ -0,0 +1,77 @@ +/* + * 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. + */ + +#ifndef AR1021I2C_H +#define AR1021I2C_H + +#include "TouchPanel.h" + +/** + * Microchip Touch Screen Controller (AR1021). + * + * Please note that this touch panel has an on-board storage for + * calibration data. Once a successful calibration has been performed + * it is not needed to do additional calibrations since the stored + * calibration data will be used. + */ +class AR1021I2C : public TouchPanel { +public: + + + /** + * Constructor + * + * @param mosi I2C SDA pin + * @param miso I2C SCL pin + * @param siq interrupt pin + */ + AR1021I2C(PinName sda, PinName scl, PinName siq); + + bool info(int* verHigh, int* verLow, int* resBits, int* type); + + virtual bool init(uint16_t width, uint16_t height); + virtual bool read(touchCoordinate_t &coord); + virtual bool calibrateStart(); + virtual bool getNextCalibratePoint(uint16_t* x, uint16_t* y); + virtual bool waitForCalibratePoint(bool* morePoints, uint32_t timeout); + +private: + + + I2C _i2c; + DigitalIn _siq; + InterruptIn _siqIrq; + bool _initialized; + + + int32_t _x; + int32_t _y; + int32_t _pen; + + uint16_t _width; + uint16_t _height; + uint8_t _inset; + + int _calibPoint; + + + int cmd(char cmd, char* data, int len, char* respBuf, int* respLen, bool setCsOff=true); + int waitForCalibResponse(uint32_t timeout); + void readTouchIrq(); +}; + +#endif +
diff -r 000000000000 -r 79b286950b60 EALib.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/EALib.lib Fri Oct 03 13:15:25 2014 +0000 @@ -0,0 +1,1 @@ +https://mbed.org/users/embeddedartists/code/EALib/#b3a179cc3d88
diff -r 000000000000 -r 79b286950b60 EaLcdBoardGPIO.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/EaLcdBoardGPIO.cpp Fri Oct 03 13:15:25 2014 +0000 @@ -0,0 +1,96 @@ +/* + * 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 "EaLcdBoardGPIO.h" + +/****************************************************************************** + * Defines and typedefs + *****************************************************************************/ + + +EaLcdBoardGPIO::EaLcdBoardGPIO(PinName sda, PinName scl) + : EaLcdBoard(sda, scl), /*pinWP(P4_15),*/ pin3v3(P2_0), pin5v(P2_21), pinDE(P2_11), pinContrast(P2_1) +{ + pinContrast.period_ms(10); + setWriteProtect(true); + set3V3Signal(false); + set5VSignal(false); + setDisplayEnableSignal(false); + setBacklightContrast(0); +} + + +void EaLcdBoardGPIO::setWriteProtect(bool enable) +{ + // Not Applicable +} + +void EaLcdBoardGPIO::set3V3Signal(bool enabled) { //P2.0 L=3.3V on + if (enabled) { + pin3v3 = 0; + } else { + pin3v3 = 1; + } +} + +void EaLcdBoardGPIO::set5VSignal(bool enabled) { //P2.21 H=5V on + if (enabled) { + pin5v = 1; + } else { + pin5v = 0; + } +} + +void EaLcdBoardGPIO::setDisplayEnableSignal(bool enabled) { //P2.11 H=enabled + LPC_IOCON->P2_11 &= ~7; /* GPIO2[11] @ P2.11 */ + if (enabled) { + pinDE = 1; + } else { + pinDE = 0; + } +} + +void EaLcdBoardGPIO::setBacklightContrast(uint32_t value) { //P2.1, set to 4.30 for now +#if 0 + LPC_IOCON->P2_1 &= ~7; /* GPIO2[1] @ P2.1 */ + if (value > 50) { + pinContrast = 1; + } else { + pinContrast = 0; + } +#else + uint32_t tmp = LPC_IOCON->P2_1; + tmp &= ~7; + tmp |= 1; + LPC_IOCON->P2_1 = tmp; /* PWM2[1] @ P2.1 */ + float f = value; + pinContrast = f/100.0f; +#endif + +// if (value > 100) return; + +// pca9532_setBlink0Duty(100-value); +// pca9532_setBlink0Period(0); +// pca9532_setBlink0Leds(LCDB_CTRL_BL_C); +} + + +
diff -r 000000000000 -r 79b286950b60 EaLcdBoardGPIO.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/EaLcdBoardGPIO.h Fri Oct 03 13:15:25 2014 +0000 @@ -0,0 +1,50 @@ +/* + * 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. + */ + +#ifndef EALCDBOARDGPIO_H +#define EALCDBOARDGPIO_H + +#include "EaLcdBoard.h" + +/** An interface to Embedded Artists LCD Boards + * + */ +class EaLcdBoardGPIO : public EaLcdBoard { +public: + + EaLcdBoardGPIO(PinName sda, PinName scl); + + void setBC(uint32_t val) { setBacklightContrast(val); }; + +protected: + virtual void setWriteProtect(bool enable); + virtual void set3V3Signal(bool enabled); + virtual void set5VSignal(bool enabled); + virtual void setDisplayEnableSignal(bool enabled); + virtual void setBacklightContrast(uint32_t value); + +private: + //DigitalOut pinWP; + DigitalOut pin3v3; + DigitalOut pin5v; + DigitalOut pinDE; + //DigitalOut pinContrast; + PwmOut pinContrast; +}; + +#endif + +
diff -r 000000000000 -r 79b286950b60 GlobeDemo.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GlobeDemo.cpp Fri Oct 03 13:15:25 2014 +0000 @@ -0,0 +1,396 @@ +/****************************************************************************** + * Includes + *****************************************************************************/ + +#include "mbed.h" + +#include "LcdController.h" +#include "EaLcdBoard.h" +#include "GlobeDemo.h" + +#include <math.h> + +//#include "wchar.h" + +/****************************************************************************** + * Typedefs and defines + *****************************************************************************/ + +#define NUM_OF_DOTS 50 + +/****************************************************************************** + * Local variables + *****************************************************************************/ + + +/****************************************************************************** + * External variables + *****************************************************************************/ + +/****************************************************************************** + * Local functions + *****************************************************************************/ + +// Vertex structure +typedef struct +{ +#ifdef USE_FLOAT + float x, y, z; +#else + long x, y, z; +#endif +}tVertex; + +// Transformed vertices +tVertex *gRVtx; + +#ifdef USE_FLOAT +// Original vertices +static tVertex *gVtx; +#else +static const tVertex gVtx[NUM_OF_DOTS] = { +{-21585, 17597, -17265}, +{28493, -7790, 14183}, +{13031, 27845, 11338}, +{10822, 29162, -10304}, +{19517, -25865, -4876}, +{1283, 30949, -10687}, +{-23097, 12297, 19723}, +{-17162, 1188, 27888}, +{-29007, -1547, 15163}, +{-8182, -31729, -197}, +{11599, -28575, -11073}, +{25963, 12182, 15850}, +{106, 10547, -31023}, +{-24312, 3053, -21755}, +{9966, -18803, -24916}, +{17598, -6037, -26973}, +{23321, 17149, -15353}, +{-3265, 8867, -31376}, +{-23639, 13701, 18087}, +{-2433, -22123, -24049}, +{21284, -11349, -22179}, +{-21407, 24683, -2486}, +{-32011, -4336, 5495}, +{-20191, 22605, 12450}, +{14752, -23540, 17376}, +{-8961, -17292, -26351}, +{-18078, 13561, -23727}, +{10730, -23639, 19994}, +{-18718, 17555, 20376}, +{13626, -22837, 19144}, +{-24695, -19036, -10073}, +{11935, 22275, 20859}, +{-2182, -28801, -15474}, +{21428, -21867, -11678}, +{-19601, 21558, -14991}, +{24512, 10876, -18830}, +{12385, 27881, 11956}, +{26982, 15618, -10088}, +{-16954, 19591, 20061}, +{-6027, 22699, -22850}, +{5453, 28825, -14598}, +{-20155, -16252, -20083}, +{-15962, 11757, -26089}, +{-29175, -11289, -9750}, +{-15370, 604, -28933}, +{26009, 19868, -1575}, +{24722, -17277, -12806}, +{-4527, 25836, -19639}, +{-22224, 10442, 21697}, +{-10388, 24393, -19255}}; +#endif + +unsigned short GlobeDemo::isqrt(unsigned long a) const { + unsigned long temp; + long e; + unsigned long x = 0; + if((a & 0xffff0000) != 0) + x = 444 + a / 26743; + else if((a & 0xff00) != 0) + x = 21 + a / 200; + else + x = 1 + a / 12; + do{ + temp = a / x; + e = (x - temp) / 2; + x = (x + temp) / 2; + } + while(e != 0); + return (unsigned short)x; +} + +short GlobeDemo::_sin(short y) const { + static short s1 = 0x6487; + static short s3 = 0x2951; + static short s5 = 0x4f6; + long z, prod, sum; + + z = ((long)y * y) >> 12; + prod = (z * s5) >> 16; + sum = s3 - prod; + prod = (z * sum) >> 16; + sum = s1 - prod; + + // for better accuracy, round here + return (short)((y * sum) >> 13); + } + +short GlobeDemo::_cos(short y) const { + static short c0 = 0x7fff; + static short c2 = 0x4eea; + static short c4 = 0x0fc4; + long z, prod, sum; + z = ((long)y * y) >> 12; + prod = (z * c4) >> 16; + sum = c2 - prod; + + // for better accuracy, round here + prod = (z * sum) >> 15; + return (short)(c0 - prod); +} + +short GlobeDemo::isine(short x) const { + unsigned short n = (((unsigned short)x + 0x2000) >> 14) & 0x3; + x -= n * 0x4000; + switch(n){ + case 0: + return _sin(x); + case 1: + return _cos(x); + case 2: + return - _sin(x); + case 3: + return - _cos(x); + } + return 0; + } + + +short GlobeDemo::icosine(short x) const { + return isine(x + 0x4000); + } + +void GlobeDemo::initialize() +{ +// gVtx = (tVertex*)malloc(sizeof(tVertex) * NUM_OF_DOTS); + gRVtx = (tVertex*)malloc(sizeof(tVertex) * NUM_OF_DOTS); + +#ifdef USE_FLOAT + int i; + for (i = 0; i < NUM_OF_DOTS; i++) + { + gVtx[i].x = (rand() % 32768) - 16384.0f; + gVtx[i].y = (rand() % 32768) - 16384.0f; + gVtx[i].z = (rand() % 32768) - 16384.0f; + float len = (float)sqrt(gVtx[i].x * gVtx[i].x + + gVtx[i].y * gVtx[i].y + + gVtx[i].z * gVtx[i].z); + if (len != 0) + { + gVtx[i].x /= len; + gVtx[i].y /= len; + gVtx[i].z /= len; + } + } +#endif +} + +#ifdef USE_FLOAT +void GlobeDemo::rotate_z(float angle) +{ + float ca = (float)cos(angle); + float sa = (float)sin(angle); + int i; + for (i = 0; i < NUM_OF_DOTS; i++) + { + float x = gRVtx[i].x * ca - gRVtx[i].y * sa; + float y = gRVtx[i].x * sa + gRVtx[i].y * ca; + gRVtx[i].x = x; + gRVtx[i].y = y; + } +} + +void GlobeDemo::rotate_y(float angle) +{ + float ca = (float)cos(angle); + float sa = (float)sin(angle); + int i + for (i = 0; i < NUM_OF_DOTS; i++) + { + float z = gRVtx[i].z * ca - gRVtx[i].x * sa; + float x = gRVtx[i].z * sa + gRVtx[i].x * ca; + gRVtx[i].z = z; + gRVtx[i].x = x; + } +} +#else +void GlobeDemo::rotate_z(uint32_t angle) +{ + uint32_t i; + long x,y,ca,sa; + + ca = icosine(angle); + sa = isine(angle); + for (i = 0; i < NUM_OF_DOTS; i++) + { + x = (gRVtx[i].x * ca - gRVtx[i].y * sa) / 0x7fff; + y = (gRVtx[i].x * sa + gRVtx[i].y * ca) / 0x7fff; + gRVtx[i].x = x; + gRVtx[i].y = y; + } +} + +void GlobeDemo::rotate_y(uint32_t angle) +{ + uint32_t i; + long x,z,ca,sa; + + ca = icosine(angle); + sa = isine(angle); + for (i = 0; i < NUM_OF_DOTS; i++) + { + z = (gRVtx[i].z * ca - gRVtx[i].x * sa) / 0x7fff; + x = (gRVtx[i].z * sa + gRVtx[i].x * ca) / 0x7fff; + gRVtx[i].z = z; + gRVtx[i].x = x; + } +} +#endif + +#if 0 +void GlobeDemo::rotate_x(float angle) +{ + float ca = (float)cos(angle); + float sa = (float)sin(angle); + int i; + for (i = 0; i < NUM_OF_DOTS; i++) + { + float y = gRVtx[i].y * ca - gRVtx[i].z * sa; + float z = gRVtx[i].y * sa + gRVtx[i].z * ca; + gRVtx[i].y = y; + gRVtx[i].z = z; + } +} +#endif + +void GlobeDemo::render(uint32_t idx) +{ + uint32_t i; +#ifdef USE_FLOAT + float rotz; + float roty; +#else + uint32_t rotz; + uint32_t roty; +#endif + + static uint8_t cnt=0; + + if (cnt == 0) + { + cnt = 1; + pFrmBuf = pFrmBuf1; + } + else if (cnt == 1) + { + cnt = 2; + pFrmBuf = pFrmBuf2; + } + else + { + cnt = 0; + pFrmBuf = pFrmBuf3; + } + + graphics.setFrameBuffer(pFrmBuf); + + // rendering here + memset((void*)(pFrmBuf), BACKGROUND_COLOR, this->windowX * this->windowY * 2); + +// lcd_fillcircle(myLcdHnd, WIDTH / 2, HEIGHT / 2, HEIGHT / 4, LARGE_CIRCLE_COLOR); + graphics.put_circle(this->windowX / 2, this->windowY / 2, LARGE_CIRCLE_COLOR, this->windowY / 4, 1); + + memcpy(gRVtx, gVtx, sizeof(tVertex) * NUM_OF_DOTS); + +#ifdef USE_FLOAT + rotz = idx /*tick*/ * 0.0005f; + roty = idx /*tick*/ * 0.0020f; +#else + rotz = idx /*tick*/ * 50*5; + roty = idx /*tick*/ * 200*5; +#endif + rotate_y(roty); + rotate_z(rotz); + + for (i = 0; i < NUM_OF_DOTS; i++) + { + uint16_t c = SMALL_CIRCLE_FRONT_COLOR; + + if (gRVtx[i].z < 0) + c = SMALL_CIRCLE_BACK_COLOR; +#if 0 + lcd_point(myLcdHnd, + (int)((gRVtx[i].x * (HEIGHT / 4)) / 0x7fff + WIDTH / 2), + (int)((gRVtx[i].y * (HEIGHT / 4)) / 0x7fff + HEIGHT / 2), + c); +#else +// lcd_fillcircle(myLcdHnd, +// (int)((gRVtx[i].x * (HEIGHT / 4)) / 0x7fff + WIDTH / 2), +// (int)((gRVtx[i].y * (HEIGHT / 4)) / 0x7fff + HEIGHT / 2), +// 2, +// c); + graphics.put_circle((int)((gRVtx[i].x * (this->windowY / 4)) / 0x7fff + this->windowX / 2), (int)((gRVtx[i].y * (this->windowY / 4)) / 0x7fff + this->windowY / 2), c, 2, 1); + +#endif + } +#ifdef USE_FLOAT + lcd_fillcircle(myLcdHnd, + (int)((WIDTH / 3) * cos(rotz) + WIDTH / 2), + (int)((WIDTH / 3) * sin(rotz) + HEIGHT / 2), + 6, + SMALL_CIRCLE_FRONT_COLOR); +#else +// lcd_fillcircle(myLcdHnd, +// (int)(((HEIGHT / 3) * icosine(rotz))/0x7fff + WIDTH / 2), +// (int)(((HEIGHT / 3) * isine(rotz)) /0x7fff + HEIGHT / 2), +// 7, +// SMALL_CIRCLE_FRONT_COLOR); + graphics.put_circle((int)(((this->windowY / 3) * icosine(rotz))/0x7fff + this->windowX / 2), (int)(((this->windowY / 3) * isine(rotz)) /0x7fff + this->windowY / 2), SMALL_CIRCLE_FRONT_COLOR, 7, 1); +#endif +} + + +/****************************************************************************** + * Public functions + *****************************************************************************/ +GlobeDemo::GlobeDemo(uint8_t *pFrameBuf, uint16_t dispWidth, uint16_t dispHeight) + : graphics((uint16_t *)pFrameBuf, dispWidth, dispHeight) { + + this->windowX = dispWidth; + this->windowY = dispHeight; + this->pFrmBuf = (uint16_t *)pFrameBuf; + this->pFrmBuf1 = (uint16_t *)pFrameBuf; + this->pFrmBuf2 = (uint16_t *)((uint32_t)pFrameBuf + dispWidth*dispHeight*2); + this->pFrmBuf3 = (uint16_t *)((uint32_t)pFrameBuf + dispWidth*dispHeight*4); + + initialize(); +} + +void GlobeDemo::run(EaLcdBoardGPIO& lcdBoard, uint32_t loops, uint32_t delayMs) { + + printf("GlobeDemo, %d loops, %dms delay\n", loops, delayMs); + + for(int32_t n=0;n<loops;n++) { + + //render globe + render(n); + + //update framebuffer + lcdBoard.setFrameBuffer((uint32_t)this->pFrmBuf); + + wait_ms(delayMs); + } + free(gRVtx); +} +
diff -r 000000000000 -r 79b286950b60 GlobeDemo.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GlobeDemo.h Fri Oct 03 13:15:25 2014 +0000 @@ -0,0 +1,64 @@ + +#ifndef GLOBEDEMO_H +#define GLOBEDEMO_H + +#include "Graphics.h" +#include "GFXFb.h" +#include "EaLcdBoardGPIO.h" + +class GlobeDemo { +public: + + /** Set the address of the frame buffer to use. + * + * It is the content of the frame buffer that is shown on the + * display. All the drawing on the frame buffer can be done + * 'offline' and whenever it should be shown this function + * can be called with the address of the offline frame buffer. + * + * @param pFrameBuf Pointer to the frame buffer, which must be + * 3 times as big as the frame size (for tripple + * buffering). + * dispWidth The width of the display (in pixels). + * dispHeight The height of the display (in pixels). + * loops Number of loops in the demo code. + * delayMs Delay in milliseconds between schreen updates. + * + * @returns + * none + */ + GlobeDemo(uint8_t *pFrameBuf, uint16_t dispWidth, uint16_t dispHeight); + + void run(EaLcdBoardGPIO& lcdBoard, uint32_t loops, uint32_t delayMs); + +private: + enum Constants { + BACKGROUND_COLOR = BLACK, + LARGE_CIRCLE_COLOR = 0x39e7, //DARK_GRAY + SMALL_CIRCLE_FRONT_COLOR = WHITE, + SMALL_CIRCLE_BACK_COLOR = 0x7bef, //LIGHT_GRAY + }; + + int32_t windowX; + int32_t windowY; + uint16_t *pFrmBuf; + uint16_t *pFrmBuf1; + uint16_t *pFrmBuf2; + uint16_t *pFrmBuf3; + + Graphics graphics; + + unsigned short isqrt(unsigned long a) const; + short _sin(short y) const; + short _cos(short y) const; + short isine(short x) const; + short icosine(short x) const; + void rotate_z(uint32_t angle); + void rotate_y(uint32_t angle); + void initialize(); + void render(uint32_t idx); + +}; + +#endif /* GLOBEDEMO_H */ +
diff -r 000000000000 -r 79b286950b60 Graphics.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Graphics.cpp Fri Oct 03 13:15:25 2014 +0000 @@ -0,0 +1,241 @@ + +#include "mbed.h" +#include "Graphics.h" + + +Graphics::Graphics(uint16_t *pFrmBuf, uint16_t dispWidth, uint16_t dispHeight) +{ + this->windowX = dispWidth; + this->windowY = dispHeight; + this->pFrmBuf = pFrmBuf; +} + +void Graphics::setFrameBuffer( uint16_t *pFrmBuf ) +{ + this->pFrmBuf = pFrmBuf; +} + +int32_t Graphics::abs(int32_t v1) const +{ + if (v1 > 0) + return v1; + + return -v1; +} + +/*********************************************************************** + * + * Function: swim_put_line_raw + * + * Purpose: Draw a line on the physical display + * + * Processing: + * See function. + * + * Parameters: + * win : Window identifier + * x1 : Physical X position of X line start + * y1 : Physical Y position of Y line start + * x2 : Physical X position of X line end + * y2 : Physical Y position of Y line end + * + * Outputs: None + * + * Returns: Nothing + * + * Notes: None + * + **********************************************************************/ +void Graphics::put_line(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int16_t color) +{ + int32_t e2, sx, sy, dx, dy, err; + + /* calculate delta_x and delta_y */ + dx = abs(x2 - x1); + dy = abs(y2 - y1); + + /* set the direction for the step for both x and y, and + initialize the error */ + if (x1 < x2) + sx = 1; + else + sx = -1; + + if (y1 < y2) + sy = 1; + else + sy = -1; + + err = dx - dy; + + while (1) + { + if ((x1 >= 0) && (x1 < this->windowX) && + (y1 >= 0) && (y1 < this->windowY)) + this->pFrmBuf[x1 + (this->windowX*y1)] = color; + + if ((x1 == x2) && (y1 == y2)) + return; + + e2 = 2 * err; + if (e2 > -dy) + { + err -= dy; + x1 += sx; + } + if (e2 < dx) + { + err += dx; + y1 += sy; + } + } +} + +/*********************************************************************** + * + * Function: plot4points + * + * Purpose: + * + * Processing: + * See function. + * + * Parameters: + * win : Window identifier + * cx : + * cy : + * x : + * y : + * Filled : + * + * Outputs: None + * + * Returns: Nothing + * + * Notes: None + * + **********************************************************************/ +void Graphics::plot4points( int32_t cx, int32_t cy, int32_t x, int32_t y, int16_t color, int32_t Filled ) + { + int16_t x0, x1, y0, y1; + + y0 = cy + y; + y1 = cy - y; + if( Filled ) + { + for( x0=cx - x; x0<=cx + x; x0++ ) + { + if ((x0>=0) && (x0<this->windowX) && (y0>=0) && (y0<this->windowY)) + this->pFrmBuf[x0 + (this->windowX*y0)] = color; + if ((x0>=0) && (x0<this->windowX) && (y1>=0) && (y1<this->windowY)) + this->pFrmBuf[x0 + (this->windowX*y1)] = color; + } + } + else + { + x0 = cx + x; + x1 = cx - x; + if ((x0>=0) && (x0<this->windowX) && (y0>=0) && (y0<this->windowY)) + this->pFrmBuf[x0 + (this->windowX*y0)] = color; + if ((x != 0) && + (x1>=0) && (x1<this->windowX) && (y0>=0) && (y0<this->windowY)) + this->pFrmBuf[x1 + (this->windowX*y0)] = color; + if ((y != 0) && + (x0>=0) && (x0<this->windowX) && (y1>=0) && (y1<this->windowY)) + this->pFrmBuf[x0 + (this->windowX*y1)] = color; + if ((x != 0 && y != 0) && + (x1>=0) && (x1<this->windowX) && (y1>=0) && (y1<this->windowY)) + this->pFrmBuf[x1 + (this->windowX*y1)] = color; + } + } + +/*********************************************************************** + * + * Function: plot8points + * + * Purpose: + * + * Processing: + * See function. + * + * Parameters: + * win : Window identifier + * cx : + * cy : + * x : + * y : + * Filled : + * + * Outputs: None + * + * Returns: Nothing + * + * Notes: None + * + **********************************************************************/ +void Graphics::plot8points( int32_t cx, int32_t cy, int32_t x, int32_t y, int16_t color, int32_t Filled ) + { + plot4points( cx, cy, x, y, color, Filled ); + if (x != y) + plot4points( cx, cy, y, x, color, Filled ); + } + +/*********************************************************************** + * + * Function: swim_put_circle + * + * Purpose: + * + * Processing: + * See function. + * + * Parameters: + * win : Window identifier + * cx : + * cy : + * radius : + * Filled : + * + * Outputs: None + * + * Returns: Nothing + * + * Notes: None + * + **********************************************************************/ +void Graphics::put_circle( int32_t cx, int32_t cy, int16_t color, int32_t radius, int32_t Filled ) + { + int32_t Error = -radius; + int16_t x = radius; + int16_t y = 0; + + while( x >= y ) + { + plot8points( cx, cy, x, y, color, Filled ); + + Error += y; + ++y; + Error += y; + + if( Error >= 0 ) + { + --x; + Error -= x; + Error -= x; + } + } + } + +void Graphics::put_dot( int32_t cx, int32_t cy, int16_t color ) +{ + int size = 1; + for (int y1 = cy - size; y1 <= (cy + size); y1++) { + for (int x1 = cx - size; x1 <= (cx + size); x1++) { + if ((x1 >= 0) && (x1 < this->windowX) && (y1 >= 0) && (y1 < this->windowY)) { + this->pFrmBuf[x1 + (this->windowX*y1)] = color; + } + } + } +} + +
diff -r 000000000000 -r 79b286950b60 Graphics.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Graphics.h Fri Oct 03 13:15:25 2014 +0000 @@ -0,0 +1,29 @@ + +#ifndef GRAPHICS_H +#define GRAPHICS_H + +class Graphics { +public: + + Graphics(uint16_t *pFrmBuf, uint16_t dispWidth, uint16_t dispHeight); + + void setFrameBuffer( uint16_t *pFrmBuf ); + void put_line(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int16_t color); + void put_circle( int32_t cx, int32_t cy, int16_t color, int32_t radius, int32_t Filled ); + void put_dot( int32_t cx, int32_t cy, int16_t color ); + +protected: + uint16_t windowX; + uint16_t windowY; + uint16_t *pFrmBuf; + + int32_t abs(int32_t v1) const; + + virtual void plot4points( int32_t cx, int32_t cy, int32_t x, int32_t y, int16_t color, int32_t Filled ); + void plot8points( int32_t cx, int32_t cy, int32_t x, int32_t y, int16_t color, int32_t Filled ); + +}; + +#endif + +
diff -r 000000000000 -r 79b286950b60 TestDisplay.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TestDisplay.cpp Fri Oct 03 13:15:25 2014 +0000 @@ -0,0 +1,216 @@ +/* + * 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" + +#include "GlobeDemo.h" + +/****************************************************************************** + * Defines and typedefs + *****************************************************************************/ + +#define LCD_CONFIGURATION_43 \ + 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_43 (char*)"v1,cd0,c50,cc0,c30,d100,c31,d100,cd1,d10,o,c51,cc100" + +#define LCD_CONFIGURATION_50 \ + 46, /* horizontalBackPorch */ \ + 20, /* horizontalFrontPorch */ \ + 2, /* hsync */ \ + 800, /* width */ \ + 23, /* verticalBackPorch */ \ + 10, /* verticalFrontPorch */ \ + 3, /* vsync */ \ + 480, /* height */ \ + false, /* invertOutputEnable */ \ + false, /* invertPanelClock */ \ + true, /* invertHsync */ \ + true, /* invertVsync */ \ + 1, /* acBias */ \ + LcdController::Bpp_16_565, /* bpp */ \ + 30000000, /* optimalClock */ \ + LcdController::Tft, /* panelType */ \ + false /* dualPanel */ + +#define LCD_INIT_STRING_50 (char*)"v1,cc0,c31,d50,o,d200,c51,cc100" + +#define MY_ABS(__a) (((__a) < 0) ? -(__a) : (__a)) + +/****************************************************************************** + * 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 + +*/ + +TestDisplay::TestDisplay(WhichDisplay which) : + _initStr(NULL), + _lcdCfg(NULL), + _lcdBoard(P0_27, P0_28), + _touch(P0_27, P0_28, P2_25) { + + switch (which) { + case TFT_5: + _lcdCfg = new LcdController::Config(LCD_CONFIGURATION_50); + _initStr = LCD_INIT_STRING_50; + break; + case TFT_4_3: + _lcdCfg = new LcdController::Config(LCD_CONFIGURATION_43); + _initStr = LCD_INIT_STRING_43; + break; + default: + mbed_die(); + } + + if (sdram_init() == 1) { + printf("Failed to initialize SDRAM\n"); + _framebuffer = 0; + } else { + _framebuffer = (uint32_t) malloc(_lcdCfg->width * _lcdCfg->height * 2 * 3); // 2 is for 16 bit color, 3 is the number of buffers + if (_framebuffer != 0) { + memset((uint8_t*)_framebuffer, 0, _lcdCfg->width * _lcdCfg->height * 2 * 3); + } + } +} + +TestDisplay::~TestDisplay() { + if (_framebuffer != 0) { + free((void*)_framebuffer); + _framebuffer = 0; + } +} + +bool TestDisplay::runTest() { + do { + if (_framebuffer == 0) { + printf("Failed to allocate memory for framebuffer\n"); + break; + } + + EaLcdBoard::Result result = _lcdBoard.open(_lcdCfg, _initStr); + 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; + } + + GlobeDemo globeDemo((uint8_t *)_framebuffer, _lcdCfg->width, _lcdCfg->height); + while (1) { + globeDemo.run(_lcdBoard, 400, 30); + } + } while(0); + + return false; +} + +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 5999 seconds + Timer t; + t.start(); + TouchPanel::touchCoordinate_t tc; + while(t.read() < 6000) { + 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; +}
diff -r 000000000000 -r 79b286950b60 TestDisplay.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TestDisplay.h Fri Oct 03 13:15:25 2014 +0000 @@ -0,0 +1,63 @@ +/* + * 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. + */ + +#ifndef TESTDISPLAY_H +#define TESTDISPLAY_H + +#include "AR1021I2C.h" +#include "Graphics.h" +#include "LcdController.h" +#include "EaLcdBoardGPIO.h" + +/** + * Test the display connected with a FPC cable to the LPC4088 Experiment Base Board + * as well as the AR1021 touch sensor on the board. + */ +class TestDisplay { +public: + enum WhichDisplay { + TFT_5, // 5" display + TFT_4_3, // 4.3" display + }; + + /** + * Create an interface to the display + */ + TestDisplay(WhichDisplay which); + ~TestDisplay(); + + /** + * Test the display + * + * @return true if the test was successful; otherwise false + */ + bool runTest(); + +private: + + void calibrate_drawMarker(Graphics &g, uint16_t x, uint16_t y, bool erase); + bool calibrate_display(); + + char* _initStr; + LcdController::Config* _lcdCfg; + EaLcdBoardGPIO _lcdBoard; + AR1021I2C _touch; + + uint32_t _framebuffer; +}; + +#endif +
diff -r 000000000000 -r 79b286950b60 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Fri Oct 03 13:15:25 2014 +0000 @@ -0,0 +1,46 @@ +/****************************************************************************** + * Includes + *****************************************************************************/ +#include "mbed.h" + +#include "TestDisplay.h" + +/****************************************************************************** + * Typedefs and defines + *****************************************************************************/ + + +/****************************************************************************** + * Local variables + *****************************************************************************/ + +DigitalOut myled(LED1); + +/****************************************************************************** + * Local functions + *****************************************************************************/ + +/* + * Test program for the 4.3" and 5" displays. This test is supposed to run + * on a LPC4088QSB board on an LPC4088 Experiment Base Board. + */ + + +int main() { + printf("\n" + "---\n" + "Display Demo Program for 4.3 and 5 inch display on the LPC4088 Experiment Base Board\n" + "Build Date: " __DATE__ " at " __TIME__ "\n" + "\n"); + + //TestDisplay display(TestDisplay::TFT_4_3); + TestDisplay display(TestDisplay::TFT_5); + display.runTest(); + + while(1) { + myled = 1; + wait(0.2); + myled = 0; + wait(0.2); + } +}
diff -r 000000000000 -r 79b286950b60 mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Fri Oct 03 13:15:25 2014 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/552587b429a1 \ No newline at end of file