touch screen handler for the microchip AR1020

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