13
#include "qemu/osdep.h"
15
#include "hw/ssi/ssi.h"
16
#include "migration/vmstate.h"
17
#include "qemu/module.h"
18
#include "ui/console.h"
19
#include "qom/object.h"
33
#define TYPE_ADS7846 "ads7846"
34
OBJECT_DECLARE_SIMPLE_TYPE(ADS7846State, ADS7846)
37
#define CB_PD0 (1 << 0)
38
#define CB_PD1 (1 << 1)
39
#define CB_SER (1 << 2)
40
#define CB_MODE (1 << 3)
44
#define CB_START (1 << 7)
46
#define X_AXIS_DMAX 3470
48
#define Y_AXIS_DMAX 3450
55
#define ADS_XPOS(x, y) (X_AXIS_MIN + ((X_AXIS_DMAX * (x)) >> 15))
56
#define ADS_YPOS(x, y) (Y_AXIS_MIN + ((Y_AXIS_DMAX * (y)) >> 15))
57
#define ADS_Z1POS(x, y) 600
58
#define ADS_Z2POS(x, y) (600 + 6000 / ADS_XPOS(x, y))
60
static void ads7846_int_update(ADS7846State *s)
63
qemu_set_irq(s->interrupt, s->pressure == 0);
66
static uint32_t ads7846_transfer(SSIPeripheral *dev, uint32_t value)
68
ADS7846State *s = ADS7846(dev);
70
switch (s->cycle ++) {
72
if (!(value & CB_START)) {
77
s->output = s->input[(value >> 4) & 7];
80
s->noise = (s->noise + 3) & 7;
81
switch ((value >> 4) & 7) {
82
case 1: s->output += s->noise ^ 2; break;
83
case 3: s->output += s->noise ^ 0; break;
84
case 4: s->output += s->noise ^ 7; break;
85
case 5: s->output += s->noise ^ 5; break;
99
static void ads7846_ts_event(void *opaque,
100
int x, int y, int z, int buttons_state)
102
ADS7846State *s = opaque;
106
s->input[1] = ADS_XPOS(x, y);
107
s->input[3] = ADS_Z1POS(x, y);
108
s->input[4] = ADS_Z2POS(x, y);
109
s->input[5] = ADS_YPOS(x, y);
112
if (s->pressure == !buttons_state) {
113
s->pressure = !!buttons_state;
115
ads7846_int_update(s);
119
static int ads7856_post_load(void *opaque, int version_id)
121
ADS7846State *s = opaque;
124
ads7846_int_update(s);
128
static const VMStateDescription vmstate_ads7846 = {
131
.minimum_version_id = 1,
132
.post_load = ads7856_post_load,
133
.fields = (const VMStateField[]) {
134
VMSTATE_SSI_PERIPHERAL(ssidev, ADS7846State),
135
VMSTATE_INT32_ARRAY(input, ADS7846State, 8),
136
VMSTATE_INT32(noise, ADS7846State),
137
VMSTATE_INT32(cycle, ADS7846State),
138
VMSTATE_INT32(output, ADS7846State),
139
VMSTATE_END_OF_LIST()
143
static void ads7846_realize(SSIPeripheral *d, Error **errp)
145
DeviceState *dev = DEVICE(d);
146
ADS7846State *s = ADS7846(d);
148
qdev_init_gpio_out(dev, &s->interrupt, 1);
150
s->input[0] = ADS_TEMP0;
151
s->input[2] = ADS_VBAT;
152
s->input[6] = ADS_VAUX;
153
s->input[7] = ADS_TEMP1;
156
qemu_add_mouse_event_handler(ads7846_ts_event, s, 1,
157
"QEMU ADS7846-driven Touchscreen");
159
ads7846_int_update(s);
161
vmstate_register_any(NULL, &vmstate_ads7846, s);
164
static void ads7846_class_init(ObjectClass *klass, void *data)
166
DeviceClass *dc = DEVICE_CLASS(klass);
167
SSIPeripheralClass *k = SSI_PERIPHERAL_CLASS(klass);
169
k->realize = ads7846_realize;
170
k->transfer = ads7846_transfer;
171
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
174
static const TypeInfo ads7846_info = {
175
.name = TYPE_ADS7846,
176
.parent = TYPE_SSI_PERIPHERAL,
177
.instance_size = sizeof(ADS7846State),
178
.class_init = ads7846_class_init,
181
static void ads7846_register_types(void)
183
type_register_static(&ads7846_info);
186
type_init(ads7846_register_types)