-
Notifications
You must be signed in to change notification settings - Fork 0
/
isdv4.c
202 lines (152 loc) · 3.88 KB
/
isdv4.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/*************************************************************
WaxWasp ISDV4 Interface Code
File: isdv4.c
Author: Jakob
Some parts shamelessly stolen from waxbee :P
Licensed under GPL v2.
You should have received a copy of the license with this code.
*************************************************************/
#include "isdv4.h"
#define WACOM_PKGLEN_TPC 9
#define WACOM_PKGLEN_TPCCTL 11
#ifndef F_CPU
#endif
#define F_12MHz
//#define F_16MHz
#ifdef F_12MHz
#ifndef F_CPU
#define F_CPU 12000000UL
#endif
#define UBRR0H_val 0x00
#define UBRR0L_val 0x26
#endif
#ifdef F_16MHz
#ifndef F_CPU
#define F_CPU 16000000UL
#endif
#define UBRR0H_val 0x00
#define UBRR0L_val 0x51
#endif
#include <stdint.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#include "penevent.h"
#define true 1
#define false 0
#define halted 0
#define query_packet 1
#define packet 2
#define BITV(bit, val) (val << bit)
unsigned char state = 0; //0=halted, 1=query_packet, 2=packet
unsigned char datalen = 0;
unsigned char buffer[11];
struct {
unsigned in_proximity:1;
unsigned eraser_mode:1;
} tool;
struct penEvent penevent;
void uart_putch(unsigned char c){
while(!(UCSR0A & (1<<UDRE0))){} //wait till buffer is empty
UDR0 = c; //write char to buffer
}
void uart_puts(char *s){
while(*s){
uart_putch(*s);
s++;
}
}
void resetToolState(){
tool.in_proximity = 0;
tool.eraser_mode = 0;
}
void start_packets(){
datalen = 0;
uart_puts("\r\r1\r"); // send a few \r to make sure we are in sync
state = packet;
}
void gotSerialByte(unsigned char data){
if(state == 0) return;
else{ //packet
if(data & 0x80){
datalen = 0;
}else if(datalen == 0){
return; // wait for the first valid byte
}
if(datalen < WACOM_PKGLEN_TPC){
buffer[datalen] = data;
datalen++;
}
if(datalen == WACOM_PKGLEN_TPC){
// event consumed
datalen = 0;
penevent.proximity = (buffer[0] & 0x20)?1:0;
penevent.x = (((uint16_t)(buffer[6] & 0x60)) >> 5) |
(((uint16_t) buffer[2] ) << 2) |
(((uint16_t) buffer[1] ) << 9);
penevent.y = (((uint16_t)(buffer[6] & 0x18)) >> 3) |
(((uint16_t) buffer[4] ) << 2) |
(((uint16_t) buffer[3] ) << 9);
//pressure
penevent.pressure = (((uint16_t)(buffer[6] & 0x07)) << 7) | buffer[5];
//not sure if this bit is looked at anyways
penevent.touch = penevent.pressure > 10;
penevent.button0 = buffer[0] & 0x02;
penevent.button1 = buffer[0] & 0x04;
//check which device has been reported
unsigned char curEvent_eraser = (buffer[0] & 4)? 1:0;
//detect tool state
if(!tool.in_proximity)
{
if(penevent.proximity)
{
//entering proximity
tool.in_proximity = true;
if(curEvent_eraser)
tool.eraser_mode = true;
else
tool.eraser_mode = false;
}
}
else if(!penevent.proximity)
resetToolState();
penevent.eraser = tool.eraser_mode;
if(tool.eraser_mode)
{
// no buttons with eraser
penevent.button0 = 0;
penevent.button1 = 0;
}
penevent.is_mouse = 0;
// TODO: understand the extra logic from the linux driver (wcmISDV4.c)
/* check on previous proximity */
/* we might have been fooled by tip and second
* sideswitch when it came into prox */
// no tilt data?
penevent.tilt_x = 0;
penevent.tilt_y = 0;
penevent.rotation_z = 0;
input_pen_event(penevent);
}
}
}
void init_isdv4(){
UBRR0H = UBRR0H_val;
UBRR0L = UBRR0L_val; //19200 Baud at 12MHz
UCSR0A = 0;
UCSR0B = BITV(RXCIE0, 1) |
BITV(TXCIE0, 0) |
BITV(UDRIE0, 0) |
BITV(RXEN0, 1) |
BITV(TXEN0, 1) |
BITV(UCSZ02, 0); //8 bits
UCSR0C = BITV(UMSEL00, 0) | // Async USART
BITV(UMSEL01, 0) | // Async USART
BITV(UPM00, 0) | // No parity
BITV(UPM01, 0) | // No parity
BITV(USBS0, 0) | //1 stop bit
BITV(UCSZ01, 1) | //8 bits
BITV(UCSZ00, 1); //8 bits
resetToolState();
sei();
start_packets();
}