USB_Laptop_Keyboard_Controller/Example_Touchpads/Azoteq_TP.ino
2021-10-21 16:23:05 -07:00

130 lines
6.1 KiB
C++

/* Copyright 2021 Frank Adams
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.
*/
// This software controls an Azoteq touchpad Part No: TPS65-201A-S over I2C and sends the results
// over USB using the Teensyduino mouse.move function. The mouse.set_buttons function is used
// to send a left button push and release based on a finger tap on the touchpad.
//
#include <Wire.h>
#define rdy 10 // touchpad ready signal monitored by Teensy, active high
#define rst_n 12 // touchpad reset driven by Teensy, active low
#define tp_address 0x74 // Azoteq touchpad i2c address
char gesture0; // holds gesture events 0
char gesture1; // holds gesture events 1
char sys_info0; // holds system info 0
char sys_info1; // holds system info 1
char finger_count; // number of fingers
char xrel_high; // holds the relative x high 8 bits
char xrel_low; // holds the relative x low 8 bits
char yrel_high; // holds the relative y high 8 bits
char yrel_low; // holds the relative y low 8 bits
char xabs_high; // holds the absolute x high 8 bits
char xabs_low; // holds the absolute x low 8 bits
char yabs_high; // holds the absolute y high 8 bits
char yabs_low; // holds the absolute y low 8 bits
char tch_strength_high; // holds the touch strength high 8 bits
char tch_strength_low; // holds the touch strength low 8 bits
char tch_area; // holds the touch area/size
boolean left_button = 0; // Active high, on/off variable for left button
boolean old_left_button = 0; // Active high, on/off variable for left button status from the previous polling cycle
boolean button_change = 0; // Active high, shows when a touchpad left button has changed since the last polling cycle
//
// ********************Common Functions**********************************************
//
// Function to set a pin to high impedance (acts like open drain output)
void go_z(int pin)
{
pinMode(pin, INPUT);
digitalWrite(pin, HIGH);
}
//
// Function to send a pin to a logic low
void go_0(int pin)
{
pinMode(pin, OUTPUT);
digitalWrite(pin, LOW);
}
//
// Function to send a pin to a logic high
void go_1(int pin)
{
pinMode(pin, OUTPUT);
digitalWrite(pin, HIGH);
}
//
void setup() {
go_z(rdy); // set rdy pin as an input without a pullup
// reset the TP
go_0(rst_n); // drive reset low (active) to TP
delay (1000); // wait a second
go_1(rst_n); // drive reset high (inactive) to TP
Wire.begin(); //Initiate the Wire library and join the I2C bus as a master
}
void loop() {
if (digitalRead(rdy)) { // check rdy signal to see if TP has data
Wire.beginTransmission(tp_address); //
Wire.write(0x00); // high btye address of first register to read
Wire.write(0x0d); // low byte address of first register to read
Wire.endTransmission(false); // no stop bit (makes a repeated start)
Wire.requestFrom(tp_address,16); // read 16 bytes starting at 0x000d
if (Wire.endTransmission(true) == 0) { // send stop bit and check if TP "acked"
gesture0 = Wire.read(); // read the gesture 0 byte from register 0x000d
gesture1 = Wire.read(); // read the gesture 1 byte from register 0x000e
sys_info0 = Wire.read(); // read the system info 0 byte from register 0x000f
sys_info1 = Wire.read(); // read the system info 1 byte from register 0x0010
finger_count = Wire.read(); // read the finger count byte from register 0x0011
xrel_high = Wire.read(); // read the high relative X byte from register 0x0012
xrel_low = Wire.read(); // read the low relative X byte from register 0x0013
yrel_high = Wire.read(); // read the high relative Y byte from register 0x0014
yrel_low = Wire.read(); // read the low relative Y byte from register 0x0015
xabs_high = Wire.read(); // read the high absolute X byte from register 0x0016
xabs_low = Wire.read(); // read the low absolute X byte from register 0x0017
yabs_high = Wire.read(); // read the high absolute Y byte from register 0x0018
yabs_low = Wire.read(); // read the low absolute Y byte from register 0x0019
tch_strength_high = Wire.read(); // read the high touch strength byte from register 0x001a
tch_strength_low = Wire.read(); // read the low touch strength byte from register 0x001b
tch_area = Wire.read(); // read the touch area/size byte from register 0x001c
//
// send the x and y data back via usb if either one is non-zero
if ((xrel_low != 0x00) || (yrel_low != 0x00)) {
Mouse.move(xrel_low,yrel_low);
xrel_low = 0; // zero out the registers (just in case)
yrel_low = 0;
}
if ((gesture0 & 0x01) == 0x01) { // test bit 0
left_button = 1;
}
else {
left_button = 0;
}
// Determine if the left touchpad button has changed since last polling cycle using xor
button_change = left_button ^ old_left_button;
// Don't send button status if there's no change since last time.
if (button_change) {
Mouse.set_buttons(left_button, 0, 0); // send left button value and 0 for middle and right button
}
old_left_button = left_button; // remember button status for next polling cycle
}
else {
// put future no-acknoledge error handler here
}
// Send the End Communication Window Command per para 8.7 of Azoteq data sheet
Wire.beginTransmission(tp_address); //
Wire.write(0xee); // high btye of address pointer
Wire.write(0xee); // low byte of address pointer
Wire.write(0x00); // data value doesn't matter
Wire.endTransmission(true); // send stop bit
//
delay (30); // overall loop rate in milliseconds
}
}