touch screen handler for the microchip AR1020
Diff: ar1020.cpp
- Revision:
- 0:cf4dd04052e3
- Child:
- 1:264ad2a00fd9
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ar1020.cpp Mon Feb 21 22:29:40 2011 +0000 @@ -0,0 +1,401 @@ +/* +* mbed AR1020 library +* Copyright (c) 2010 Hendrik Lipka +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ + +#include "ar1020.h" +#include "wait_api.h" + +AR1020::AR1020(SPI *spi, PinName enable, PinName sqi, bool swapX, bool swapY, bool swapXY) +{ + _spi=spi; + _enable=new DigitalOut(enable); + _enable->write(1); + _irq=new InterruptIn(sqi); + _x=-1; + _y=-1; + _pen=0; + _oldPen=false; + _led=new DigitalOut(LED1); +} + +AR1020::AR1020(PinName mosi, PinName miso, PinName clk, PinName enable, PinName sqi, bool swapX, bool swapY, bool swapXY) +{ + _mosi=new DigitalOut(mosi); + _miso=new DigitalIn(miso); + _clk=new DigitalOut(clk); + _clk->write(0); + + _enable=new DigitalOut(enable); + _enable->write(1); + _irq=new InterruptIn(sqi); + _sqi=new DigitalIn(sqi); + _x=-1; + _y=-1; + _pen=0; + _oldPen=false; + _led=new DigitalOut(LED1); +} + +AR1020::~AR1020() +{ + delete _enable; + delete _irq; +} + +void AR1020::init() +{ + int r=cmd(0x13,NULL,0); + printf("disable touch=%i\n",r); + + int regStart=cmd(0x22,NULL,0); + printf("reg offset=%i\n",regStart); + + if (regStart<0) + return; + + char cid2[4]={0x00,0x0d+regStart,0x01,0x01}; + r=cmd(0x21,cid2,4); + printf("set mode=1 => %i\n",r); + + + r=cmd(0x12,NULL,0); + printf("enable touch=%i\n",r); + _irq->rise(this, &AR1020::read); +} + +int AR1020::x() +{ + return _x; +} + +int AR1020::y() +{ + return _y; +} + +int AR1020::pen() +{ + return _pen; +} + + +void AR1020::read() +{ + _led->write(1); + _enable->write(0); + wait_us(60); + + int pen=readByte(); + wait_us(60); + + int xlo=readByte(); + wait_us(60); + + int xhi=readByte(); + wait_us(60); + + int ylo=readByte(); + wait_us(60); + + int yhi=readByte(); + _enable->write(1); + +// printf("0x%x|0x%x|0x%x|0x%x|0x%x\n", pen,xlo,xhi,ylo,yhi); + if (0x4d==pen || 0==pen || 255==pen) + { + // ignore invalid stuff, do nothing... + } + else if (0x81!=pen&0x81) // pen set? + { + _pen=0; + int x=xlo+(xhi<<7); + int y=ylo+(yhi<<7); + if (0!=x&&0!=y) + { + _x=x; + _y=y; + } + } + else + { + _pen=1; + int x=xlo+(xhi<<7); + int y=ylo+(yhi<<7); + if (0!=x&&0!=y) + { + _x=x; + _y=y; + } + } + _event.x=_x; + _event.y=_y; + _event.pen=_pen; + if (_pen==1 && _oldPen==false) + { // pen down + _callbackPD.call((uint32_t)&_event); + } + else if (_pen==1 && _oldPen==true) + { // pen moved + _callbackPM.call((uint32_t)&_event); + } + else if (_pen==0 && _oldPen==true) + { // pen up + _callbackPU.call((uint32_t)&_event); + } + else + { + // happens on the first touch (the first report is send with pen=0). + } + _oldPen=(_pen==1); + _led->write(0); +} + +int AR1020::cmd(char cmd,char* data, int len) +{ + _enable->write(1); + wait_us(100); + _enable->write(0); + + wait_us(10); + + writeByte(0x55); + wait_us(100); + + writeByte(len+1); + wait_us(100); + + writeByte(cmd); + wait_us(100); + + for (int i=0;i<len;i++) + { + writeByte(data[i]); + wait_us(100); + } + Timer t; + t.start(); + while (true) + { + wait_us(100); + if (1==_sqi->read()) + break; + if (t.read_ms()>1) + break; + } + char rhead=readByte(); + wait_us(100); + if (rhead!=0x55) + { + _enable->write(1); + printf("rh=0x%x\n",rhead); + return -1000; + } + char rlen=readByte(); + wait_us(100); + if (rlen==2) + { + char r=readByte(); + wait_us(100); + char rc=readByte(); + wait_us(100); + _enable->write(1); + if (rc!=cmd) + return -2000; + return -r; + } + else if (rlen==3) + { + char r=readByte(); + wait_us(100); + char rc=readByte(); + wait_us(100); + if (rc!=cmd) + { + _enable->write(1); + return -3000; + } + char rd=readByte(); + wait_us(100); + _enable->write(1); + if (r==0) + return rd; + return -r; + } + else + { + _enable->write(1); + return -4000; + } +} +void AR1020::calibrate() +{ + _irq->rise(NULL); + + DigitalOut led1(LED1); + DigitalOut led2(LED2); + DigitalOut led3(LED3); + DigitalOut led4(LED4); + led1=0;led2=0;led3=1;led4=1; + + int r=cmd(0x13,NULL,0); + printf("disable touch=%i\n",r); + wait_ms(100); + if (r<0) + return; + led4=0; + + int regStart=cmd(0x22,NULL,0); + printf("reg offset=%i\n",regStart); + + char cid[3]={0x00,0x0d+regStart,0x01}; + int mode=cmd(0x20,cid,3); + printf("mode=%i\n",mode); + + if (regStart<0) + return; + printf("start calibrate\n"); + led3=0; + char cid2[4]={0x00,0x0e+regStart,0x01,0x19}; + r=cmd(0x21,cid2,4); + printf("set inset=%i\n",r); + if (r<0) + return; + + _enable->write(1); + _enable->write(0); + wait_us(10); + writeByte(0x55); + wait_us(100); + writeByte(0x02); + wait_us(100); + writeByte(0x14); + wait_us(100); + writeByte(0x04); + + wait_ms(10); + + int resp=readCalibResponse(); + printf("status=%i\n",resp); + printf("start OK, press upper left"); + led1=1; + resp=readCalibResponse(); + printf("status=%i\n",resp); + printf("press upper right"); + led2=1; + resp=readCalibResponse(); + printf("status=%i\n",resp); + printf("press lower right"); + led3=1; + resp=readCalibResponse(); + printf("status=%i\n",resp); + printf("press lower left"); + led4=1; + resp=readCalibResponse(); + printf("status=%i\n",resp); + + _enable->write(1); + + r=cmd(0x12,NULL,0); + printf("enable touch=%i\n",r); + + _irq->rise(this, &AR1020::read); + +} + +int AR1020::readCalibResponse() +{ + while (true) + { + int r=readByte(); + if (r!=0x55) + { + printf("1=0x%x\n",r); + wait_ms(100); + continue; + } + + r=readByte(); + wait_us(100); + if (r!=0x02) + { + printf("2=0x%x\n",r); + continue; + } + + r=readByte(); + wait_us(100); + if (r!=0x00) + { + printf("3=0x%x\n",r); + continue; + } + int rc=readByte(); + wait_us(100); + if (rc!=0x14) + { + printf("4=0x%x\n",r); + continue; + } + + return r; + } +} + +int AR1020::readByte() +{ + _clk->write(0); + wait_us(10); + int r=0; + for (int i=0;i<8;i++) + { + r=r<<1; + _clk->write(1); + wait_us(10); + _clk->write(0); + wait_us(10); + int bit=_miso->read(); + r+=bit; + } +// printf("<-%i\n",r); + return r; +} + +void AR1020::writeByte(char byte) +{ + _clk->write(0); + wait_us(10); +// printf("->0x%x\n",byte); + for (int i=0;i<8;i++) + { + int bit=byte>127; +// printf("%i",bit); + _clk->write(1); + wait_us(10); + _mosi->write(bit); + wait_us(10); + _clk->write(0); + wait_us(10); + byte=(char)(byte<<1); + + } +// printf("\n"); +} \ No newline at end of file