Graphical demo for the LPC4088 Experiment Base Board with one of the Display Expansion Kits. This program displays how to use the emWin library from Segger.
Dependencies: EALib ewgui mbed
This program requires the emWin library. Instructions and more information.
Revision 0:7f5765fcd048, committed 2015-07-14
- Comitter:
- embeddedartists
- Date:
- Tue Jul 14 11:34:15 2015 +0000
- Commit message:
- First version
Changed in this revision
diff -r 000000000000 -r 7f5765fcd048 AR1021I2C.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/AR1021I2C.cpp Tue Jul 14 11:34:15 2015 +0000 @@ -0,0 +1,562 @@ +/* + * 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 7f5765fcd048 AR1021I2C.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/AR1021I2C.h Tue Jul 14 11:34:15 2015 +0000 @@ -0,0 +1,79 @@ +/* + * 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 7f5765fcd048 EALib.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/EALib.lib Tue Jul 14 11:34:15 2015 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/embeddedartists/code/EALib/#e1e36493f347
diff -r 000000000000 -r 7f5765fcd048 EaLcdBoardGPIO.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/EaLcdBoardGPIO.cpp Tue Jul 14 11:34:15 2015 +0000 @@ -0,0 +1,98 @@ +/* + * 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 7f5765fcd048 EaLcdBoardGPIO.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/EaLcdBoardGPIO.h Tue Jul 14 11:34:15 2015 +0000 @@ -0,0 +1,52 @@ +/* + * 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 7f5765fcd048 EwGuiImpl.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/EwGuiImpl.cpp Tue Jul 14 11:34:15 2015 +0000 @@ -0,0 +1,206 @@ +#include "EwGuiImpl.h" + +#include "LcdController.h" +#include "EaLcdBoardGPIO.h" +#include "sdram.h" +#include "AR1021I2C.h" + + +#define PIXEL_SIZE (2) + +#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" + +EwGuiImpl::EwGuiImpl(WhichDisplay which) { + + EaLcdBoardGPIO lcdBoard(P0_27, P0_28); + EaLcdBoardGPIO::Result result; + LcdController::Config* lcdCfg; + + do { + + switch (which) { + case TFT_5: + lcdCfg = new LcdController::Config(LCD_CONFIGURATION_50); + result = lcdBoard.open(lcdCfg, LCD_INIT_STRING_50); + break; + case TFT_4_3: + lcdCfg = new LcdController::Config(LCD_CONFIGURATION_43); + result = lcdBoard.open(lcdCfg, LCD_INIT_STRING_43); + break; + default: + mbed_die(); + } + + if (result != EaLcdBoard::Ok) { + printf("Failed to open display: %d\n", result); + break; + } + + _width = lcdCfg->width; + _height = lcdCfg->height; + + // allocate buffer, width x height x 2 (2 bytes = 16 bit color data) + _fb = (uint32_t)malloc(_width*_height*PIXEL_SIZE); + if (_fb == 0) { + printf("Failed to allocate frame buffer\n"); + break; + } + + result = lcdBoard.setFrameBuffer(_fb); + if (result != EaLcdBoard::Ok) { + printf("Failed to activate frameBuffer: %d\n", result); + break; + } + + _memSz = 1024*1024*5; + _mem = (uint32_t)malloc(_memSz); + if (_mem == 0) { + printf("Failed to allocate memory block for emwin\n"); + break; + } + + + memset((void*)_fb, 0x0, _width*_height*PIXEL_SIZE); + + // create touch panel + _touch = new AR1021I2C(P0_27, P0_28, P2_25); + + if (!_touch->init(_width, _height)) { + printf("TouchPanel.init failed\n"); + break; + } + + init(); + + } while(0); + + +} + +void* EwGuiImpl::getMemoryBlockAddress() { + return (void*)_mem; +} + +uint32_t EwGuiImpl::getMemoryBlockSize() { + return _memSz; +} + +uint32_t EwGuiImpl::getDisplayWidth() { + return _width; +} + +uint32_t EwGuiImpl::getDisplayHeight() { + return _height; +} + +void* EwGuiImpl::getFrameBufferAddress() { + return (void*)_fb; +} + +void EwGuiImpl::getTouchValues(int32_t* x, int32_t* y, int32_t* z) { + + if (!x || !y || !z) return; + + TouchPanel::touchCoordinate_t coord; + _touch->read(coord); + + *x = coord.x; + *y = coord.y; + *z = coord.z; +} + +void EwGuiImpl::calibrate() { + + uint16_t x = 0; + uint16_t y = 0; + bool hasMorePoints = false; + + EwPainter painter; + painter.saveContext(); + + do { + + printf("Starting calibration\n"); + if (!_touch->calibrateStart()) { + printf("Failed to start calibration\n"); + break; + } + + do { + if (!_touch->getNextCalibratePoint(&x, &y)) { + printf("Failed to get next calibrate point\n"); + break; + } + + printf("calib: x=%d, y=%d\n", x, y); + drawCalibPoint(painter, x, y); + + if (!_touch->waitForCalibratePoint(&hasMorePoints, 0)) { + printf("Failed waiting for calibration point\n"); + break; + } + + } while(hasMorePoints); + + printf("Calibration done\n"); + + + } while (0); + + + painter.clear(); + painter.restoreContext(); +} + +void EwGuiImpl::drawCalibPoint(EwPainter &painter, int32_t x, int32_t y) { + + painter.clear(); + painter.setColor(EW_WHITE); + painter.drawStringHorizCenter("Touch circle to calibrate", + getDisplayWidth()/2, getDisplayHeight()/2); + + painter.fillCircle(x, y, 10); + painter.setColor(EW_BLACK); + painter.fillCircle(x, y, 5); +} +
diff -r 000000000000 -r 7f5765fcd048 EwGuiImpl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/EwGuiImpl.h Tue Jul 14 11:34:15 2015 +0000 @@ -0,0 +1,46 @@ + +#ifndef EWGUIIMPL_H +#define EWGUIIMPL_H + +#include "mbed.h" +#include "EwGui.h" +#include "EwPainter.h" +#include "TouchPanel.h" + +class EwGuiImpl : public EwGui { +public: + + enum WhichDisplay { + TFT_5, // 5" display + TFT_4_3, // 4.3" display + }; + + EwGuiImpl(WhichDisplay which); + + virtual void* getMemoryBlockAddress(); + virtual uint32_t getMemoryBlockSize(); + + virtual uint32_t getDisplayWidth(); + virtual uint32_t getDisplayHeight(); + + virtual void* getFrameBufferAddress(); + + virtual void getTouchValues(int32_t* x, int32_t* y, int32_t* z); + + void calibrate(); + + +private: + + uint32_t _width; + uint32_t _height; + uint32_t _fb; + uint32_t _mem; + uint32_t _memSz; + TouchPanel* _touch; + + void drawCalibPoint(EwPainter &painter, int32_t x, int32_t y); +}; + +#endif +
diff -r 000000000000 -r 7f5765fcd048 Graphics.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Graphics.cpp Tue Jul 14 11:34:15 2015 +0000 @@ -0,0 +1,243 @@ + +#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 7f5765fcd048 Graphics.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Graphics.h Tue Jul 14 11:34:15 2015 +0000 @@ -0,0 +1,31 @@ + +#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 7f5765fcd048 MyWindow.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MyWindow.cpp Tue Jul 14 11:34:15 2015 +0000 @@ -0,0 +1,97 @@ +#include "mbed.h" + +#include "MyWindow.h" +#include "EwPainter.h" + +MyWindow::MyWindow(EwWindow* parent) : + EwWindow(5, 2, 300, 250, parent), + _changeBtn(130, 200, 40, 20, this), + _checkBox(0, 0, 80, 25, this), + _dropDownLst(0, 0, 100, 50, this){ + + _changeBtn.setText("Click"); + _changeBtn.setClickedListener(this, &MyWindow::clickListener); + + _checkBox.setText("CheckBox"); + _checkBox.setChangedListener(this, &MyWindow::checkedListener); + + _dropDownLst.addString("First"); + _dropDownLst.addString("Second"); + _dropDownLst.addString("Third"); + + _clickCnt = 0; + _pressed = false; + _pressX = 0; + _pressY = 0; + + resizeTo(parent->getWidth()-15, parent->getHeight()-35); + _changeBtn.moveTo(getWidth()/2-_changeBtn.getWidth()/2, + getHeight()-_changeBtn.getHeight()-5); + + _checkBox.moveTo(5, 35); + + _dropDownLst.move(getWidth()-_dropDownLst.getWidth()-5, 5); +} + +bool MyWindow::paintEvent() { + char buf[30]; + EwPainter painter; + + painter.setBackgroundColor(EW_LIGHTGRAY); + painter.clear(); + + if (_clickCnt > 0) { + painter.setColor(EW_BLUE); + if (_clickCnt == 1) { + sprintf(buf, "Clicked %d time", _clickCnt); + } + else { + sprintf(buf, "Clicked %d times", _clickCnt); + } + painter.drawStringClearEOL(buf, 5, 5); + } + + if (_pressed) { + painter.setColor(GUI_DARKRED); + sprintf(buf, "Touch at %d,%d", _pressX, _pressY); + painter.drawStringClearEOL(buf, 5, 15); + } + + return true; +} + +bool MyWindow::touchEvent(int x, int y, EwTouchState_t state) { + + if (state == TouchStatePressed) { + _pressed = true; + _pressX = x; + _pressY = y; + } + else { + _pressed = false; + } + + invalidate(); + + return true; +} + +void MyWindow::clickListener(EwWindow* w) { + _clickCnt++; + invalidate(); +} + +void MyWindow::checkedListener(EwWindow* w) { + EwCheckBox* b = (EwCheckBox*)w; + + ewCheckBoxState_t state = b->getState(); + + if (state == CheckBoxStateUnchecked) { + b->setText("Unchecked"); + } + else { + b->setText("Checked"); + } + +} +
diff -r 000000000000 -r 7f5765fcd048 MyWindow.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MyWindow.h Tue Jul 14 11:34:15 2015 +0000 @@ -0,0 +1,37 @@ + +#ifndef MYWINDOW_H +#define MYWINDOW_H + +#include "EwWindow.h" +#include "EwButton.h" +#include "EwCheckBox.h" +#include "EwDropDown.h" + +class MyWindow : public EwWindow { +public: + + MyWindow(EwWindow* parent); + + virtual bool paintEvent(); + virtual bool touchEvent(int x, int y, EwTouchState_t state); + + virtual bool resizedEvent() {printf("MyWindow resized\n"); return true;} + + +private: + + int _clickCnt; + bool _pressed; + int _pressX; + int _pressY; + EwButton _changeBtn; + EwCheckBox _checkBox; + EwDropDown _dropDownLst; + + + void clickListener(EwWindow* w); + void checkedListener(EwWindow* w); +}; + +#endif +
diff -r 000000000000 -r 7f5765fcd048 ewgui.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ewgui.lib Tue Jul 14 11:34:15 2015 +0000 @@ -0,0 +1,1 @@ +https://mbed.org/users/embeddedartists/code/ewgui/#0b16165ada7c
diff -r 000000000000 -r 7f5765fcd048 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Tue Jul 14 11:34:15 2015 +0000 @@ -0,0 +1,92 @@ + +/****************************************************************************** + * Includes + *****************************************************************************/ + +#include "mbed.h" + +#include "sdram.h" + +#include "EwGuiImpl.h" +#include "EwFrameWindow.h" +#include "MyWindow.h" + + +/****************************************************************************** + * Typedefs and defines + *****************************************************************************/ + + +/****************************************************************************** + * Local variables + *****************************************************************************/ + +static EwGuiImpl* gui = NULL; + +/****************************************************************************** + * Local functions + *****************************************************************************/ + +static void pollTouch() { + if (gui == NULL) return; + + gui->execTouch(); +} + +/****************************************************************************** + * Main function + *****************************************************************************/ + +int main (void) { + Ticker ticker; + + // Frame buffer is put in SDRAM + if (sdram_init() == 1) { + printf("Failed to initialize SDRAM\n"); + return 1; + } + + // instantiate and initialize GUI + gui = new EwGuiImpl(EwGuiImpl::TFT_4_3); + //gui = new EwGuiImpl(EwGuiImpl::TFT_5); + if (gui == NULL) { + printf("Failed to instantiate EwGuiImpl\n"); + return 1; + } + + // calibrate touch screen + gui->calibrate(); + + // register a callback that will check for touch events + ticker.attach(&pollTouch, 0.10); + + // showing how to enable skinning + BUTTON_SetDefaultSkin (BUTTON_SKIN_FLEX); + CHECKBOX_SetDefaultSkin (CHECKBOX_SKIN_FLEX); + DROPDOWN_SetDefaultSkin (DROPDOWN_SKIN_FLEX); + FRAMEWIN_SetDefaultSkin (FRAMEWIN_SKIN_FLEX); + + // make sure the desktop has a color so that it is redrawn + EwWindow::setDesktopColor(EW_BLACK); + + // create a frame window + EwFrameWindow frameWin(30, 30, gui->getDisplayWidth()-60, + gui->getDisplayHeight()-60, "Window Title"); + frameWin.setTitleHeight(20); + + // create and associate a custom window with the frame window + MyWindow myWindow(&frameWin); + + // application loop running the UI and checking for touch events + while(1) { + + // In this example touch events are checked by interrupt + // (pollTouch function), but we could also have done it + // in this while loop + //gui.execTouch(); + gui->exec(); + + } + +} +
diff -r 000000000000 -r 7f5765fcd048 mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Tue Jul 14 11:34:15 2015 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/da0ca467f8b5 \ No newline at end of file