Markdem
Joined: 24 Jun 2005 Posts: 206
|
Microchip AR1021 Touch screen I2C driver |
Posted: Sat Mar 02, 2013 12:38 am |
|
|
Hi all,
Here is a driver for the Microchip AR1021 controller. It will only work in I2C mode and no calibration function has been written. Most of the time the touch screen is glued onto the LCD anyway so I did not waste my time.
If anyone sees anything that can be improved, please yell out.
Driver:
Code: |
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////// Driver for AR1021 ///////////
/////// Usage: ///////////
/////// AR1021_GetPos(int16 xpos, int16 ypos) ///////////
/////// Where xpos and ypos are varibals to store touch data, returns 1 for pen down and 0 for pen up ///////////
/////// Should only be called on AR1021 interupt ///////////
/////// ///////////
/////// AR1021_Send_Command(int cmd) ///////////
/////// Where cmd is the command to send. Note this should only be used on commands that dont need ///////////
/////// to send data. If using GET_VERSION, returned data will be in AR1021_data[4]. ///////////
/////// Will return 0 if successful, 1 if invalid data was recived and 2 if timed out. ///////////
/////// ///////////
/////// AR1021_Read_Register(int reg) ///////////
/////// Where reg is register to read.Actual register data will be in AR1021_data[2]. ///////////
/////// Will return 0 if successful, 1 if invalid data was recived and 2 if timed out. ///////////
/////// ///////////
/////// AR1021_Set_Register(int reg, int data) ///////////
/////// Where reg is register to set and data will be data to send. ///////////
/////// Will return 0 if successful, 1 if invalid data was recived and 2 if timed out. ///////////
/////// ///////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define AR1021_Address 0x9A
#define AR1021_INT_PIN PIN_B1
//AR1021 Commands
#define GET_VERSION 0x10
#define ENABLE_TOUCH 0x12
#define DISABLE_TOUCH 0x13
#define CALIBRATE_MODE 0x14
#define REGISTER_READ 0x20
#define REGISTER_WRITE 0x21
#define REGISTER_START_ADDRESS_REQUEST 0x22
#define REGISTERS_WRITE_TO_EEPROM 0x23
#define EEPROM_READ 0x28
#define EEPROM_WRITE 0x29
#define EEPROM_WRITE_TO_REGISTERS 0x2B
//AR1021 config register offsets
#define TouchThreshold 0x02
#define SensitivityFilter 0x03
#define SamplingFast 0x04
#define SamplingSlow 0x05
#define AccuracyFilterFast 0x06
#define AccuracyFilterSlow 0x07
#define SpeedThreshold 0x08
#define SleepDelay 0x0A
#define PenUpDelay 0x0B
#define TouchMode 0x0C
#define TouchOptions 0x0D
#define CalibrationInset 0x0E
#define PenStateReportDelay 0x0F
#define AR1021_TIMEOUT 100 //how many ms to wait for responce
#define AR1021_RETRY 5 //how many times to retry sending command
int AR1021_data[8];
int1 AR1021_GetPos(int16 &AR1021_xpos, int16 &AR1021_ypos)
{
int x_msb, x_lsb, y_msb, y_lsb, temp;
int1 pen;
i2c_start();
i2c_write(AR1021_Address + 1); //send read address
temp = i2c_read(1);
x_lsb = i2c_read(1);
x_msb = i2c_read(1);
y_lsb = i2c_read(1);
y_msb = i2c_read(0);
i2c_stop();
AR1021_xpos = make16(x_msb, x_lsb);
AR1021_ypos = make16(y_msb, y_lsb);
pen = bit_test(temp, 0); //get pen state bit
//////////////////////DEBUG//////////////////////////
// GLCD_rect(0,20,319,35, YES, BLACK);
// sprintf(lcd_data,"X=%lu Y=%lu PEN=%u",touch_xpos, touch_ypos, pen);
// glcd_text(0,20,lcd_data,GREEN,BLACK);
////////////////////////////////////////////////////////////
return pen;
}
int AR1021_XFER(int send_lenght)
{
int header, length, i;
int16 timeout;
int exit_code, retry_count = 0;
int1 done = 0;
int RX_buffer[8];
while(!done)
{
timeout = 0;
i2c_start();
i2c_write(AR1021_Address); //send write address
i2c_write(0x00);
i2c_write(0x55); //header
i2c_write(send_lenght); //message lenght
for(i=0;i<send_lenght;i++)
{
i2c_write(AR1021_data[i]); //command
}
delay_us(60); //delay from datasheet
i2c_stop();
while(!input(AR1021_INT_PIN)) //wait untill AR1021 pulls interupt pin high
{
delay_us(10);
timeout++;
if(timeout > AR1021_TIMEOUT)
{
break;
}
}
if(timeout < AR1021_TIMEOUT)
{
i2c_start();
i2c_write(AR1021_Address + 1); //send read address
header = i2c_read(1); //always should be 0x55 (header)
length = i2c_read(1); //data length
for(i=0;i<length-1;i++) //we need to send a NACK on the last read.
{
RX_buffer[i] = i2c_read(1); //returned data, read into diffrent buffer incase we need to retry.
}
RX_buffer[i] = i2c_read(0); //last returned data byte
i2c_stop();
if(RX_buffer[0] == 0x00) //check to see if the status byte is 0
{
for(i=0;i<length;i++) //if data is OK, copy into buffer
{
AR1021_data[i] = RX_buffer[i];
}
exit_code = 0; //OK
done = 1;
}
else
{
exit_code = 1; //Invalid return
retry_count++;
delay_ms(50); //delay before retry
}
}
else
{
exit_code = 2; //Timeout
retry_count++;
delay_ms(50); //delay before retry
}
if(retry_count >= AR1021_RETRY) //check to see if we have exceded the retry count
{
done = 1; //do not retry
}
}
return exit_code;
}
int AR1021_Send_Command(int cmd)
{
int ret_data;
AR1021_data[0] = cmd; //set command to send
ret_data = AR1021_XFER(1); //send command
return ret_data;
}
int AR1021_Read_Register(int reg)
{
int reg_address = 0;
int ret_data;
AR1021_Send_Command(DISABLE_TOUCH); //disable touch reporting while we send commands
delay_ms(100); //delay before sending command
AR1021_data[0] = 0x22; //get start address
ret_data = AR1021_XFER(1); //send command
reg_address = AR1021_data[2] + reg; //work out the address of the register we want
AR1021_data[0] = 0x20; //read command
AR1021_data[1] = 0x00; //register high address, allways 0x00
AR1021_data[2] = reg_address; //register low address
AR1021_data[3] = 0x01; //number of register to read, always 1 here
AR1021_XFER(4); //send command
AR1021_Send_Command(ENABLE_TOUCH); //re-enable touch reporting
return ret_data;
}
int AR1021_Set_Register(int reg, int data)
{
int reg_address = 0;
int ret_data;
AR1021_Send_Command(DISABLE_TOUCH); //disable touch reporting while we send commands
AR1021_data[0] = 0x22; //get start address
AR1021_XFER(1); //send command
reg_address = AR1021_data[2] + reg; //work out the address of the register we want
AR1021_data[0] = 0x21; //write command
AR1021_data[1] = 0x00; //register high address, allways 0x00
AR1021_data[2] = reg_address; //register low address
AR1021_data[3] = 0x01; //number of register to write too, always 1 here
AR1021_data[4] = data; //data to set register
reg_address = AR1021_XFER(5); //send command
AR1021_Send_Command(ENABLE_TOUCH); //re-enable touch reporting
return ret_data;
}
|
Example:
Code: |
#include <18F67k22.h>
#fuses HSH, PLLEN, NOWDT, NODEBUG, NOMCLR, PUT
#use delay(clock=64M)
#use i2c(master, I2C2)
char LCD_Data[90];
int ver, reg1, reg2;
int16 xpos, ypos;
int1 pen;
#include "SSD2119.c"
#include "CGraphics.c"
#include "AR1021.c"
void main()
{
GLCD_init();
output_high(LCD_BL_ENABLE);
AR1021_Send_Command(GET_VERSION);
ver = AR1021_data[4];
sprintf(lcd_data,"Version = %u",ver);
glcd_text(0,0,lcd_data,GREEN,BLACK);
AR1021_Read_Register(PenUpDelay);
reg1 = AR1021_data[2];
AR1021_Set_Register(PenUpDelay, 0x49);
AR1021_Read_Register(PenUpDelay);
reg2 = AR1021_data[2];
sprintf(lcd_data,"Reg1=%X Reg2=%X",reg1, reg2);
glcd_text(0,30,lcd_data,GREEN,BLACK);
while(1)
{
if(input_state(AR1021_INT_PIN)) //check to see if the screen has been touched.
{
pen = AR1021_GetPos(xpos, ypos);
GLCD_rect(0,60,319,80, YES, BLACK);
sprintf(lcd_data,"X=%lu Y=%lu PEN=%u",xpos, ypos, pen);
glcd_text(0,60,lcd_data,GREEN,BLACK);
}
delay_ms(100);
}
|
(No idea what happen to the indents)
Thanks
Mark |
|