touch screen handler for the microchip AR1020
ar1020.cpp
- Committer:
- hlipka
- Date:
- 2011-02-24
- Revision:
- 6:a6971458d612
- Parent:
- 5:a5eba88e8c3e
File content as of revision 6:a6971458d612:
/* * 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(PinName mosi, PinName miso, PinName clk, PinName enable, PinName siq, PinName power) { _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(siq); _siq=new DigitalIn(siq); _x=-1; _y=-1; _pen=0; _oldPen=false; _led=new DigitalOut(LED1); _power=new DigitalOut(power); _power->write(0); } AR1020::~AR1020() { delete _enable; delete _irq; } void AR1020::init() { bool ok=false; while (!ok) { printf("power on AR1020\n"); _power->write(0); wait_ms(400); _power->write(1); wait_ms(200); int r=cmd(0x13,NULL,0); printf("disable touch=%i\n",r); if (0!=r) continue; int regStart=cmd(0x22,NULL,0); printf("reg offset=%i\n",regStart); if (regStart<0) continue; char cid2[4]={0x00,0x0d+regStart,0x01,0x01}; r=cmd(0x21,cid2,4); printf("set mode=1 => %i\n",r); if (0!=r) continue; r=cmd(0x23,NULL,0 ); printf("save regs => %i\n",r); if (0!=r) continue; r=cmd(0x12,NULL,0); printf("enable touch=%i\n",r); if (0!=r) continue; ok=true; } _irq->rise(this, &AR1020::read); } int AR1020::x() { return _x; } int AR1020::y() { return _y; } int AR1020::pen() { return _pen; } void AR1020::read() { while (1==_siq->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); if (1==_siq->read()) wait_ms(5); } } int AR1020::cmd(char cmd,char* data, int len, bool doEnable) { if (doEnable) { _enable->write(1); wait_us(1000); _enable->write(0); } wait_us(100); 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==_siq->read()) break; if (t.read_ms()>1000) { printf("timeout\n"); break; } } char rhead=readByte(); wait_us(100); if (rhead!=0x55) { if (doEnable) _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); if (doEnable) _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) { if (doEnable) _enable->write(1); return -3000; } char rd=readByte(); wait_us(100); if (doEnable) _enable->write(1); if (r==0) return rd; return -r; } else { if (doEnable) _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); wait_us(100); _enable->write(0); wait_us(10); char cid3[1]={0x04}; r=cmd(0x14,cid3,1,false); printf("start calibration=%i\n",r); if (r<0) return; printf("start OK, press upper left\n"); led1=1; int resp=readCalibResponse(); printf("status=%i\n",resp); printf("press upper right\n"); led2=1; resp=readCalibResponse(); printf("status=%i\n",resp); printf("press lower right\n"); led3=1; resp=readCalibResponse(); printf("status=%i\n",resp); printf("press lower left\n"); led4=1; resp=readCalibResponse(); printf("status=%i\n",resp); printf("exit calibration mode\n"); led1=0; led2=0; led3=0; led4=0; _enable->write(1); wait_ms(1000); r=cmd(0x23,NULL,0); printf("save registers=%i\n",r); r=cmd(0x12,NULL,0); printf("enable touch=%i\n",r); _irq->rise(this, &AR1020::read); } int AR1020::readCalibResponse() { while (true) { while (true) { wait_us(10); if (1==_siq->read()) break; } int r=readByte(); if (r!=0x55) { // printf("1=0x%x\n",r); wait_ms(100); continue; } wait_us(100); r=readByte(); if (r!=0x02) { printf("2=0x%x\n",r); continue; } wait_us(100); r=readByte(); if (r!=0x00) { printf("3=0x%x\n",r); continue; } wait_us(100); int rc=readByte(); 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"); }