]> Git Repo - qemu.git/blame - hw/misc/max111x.c
migration: Move the VMStateDescription typedef to typedefs.h
[qemu.git] / hw / misc / max111x.c
CommitLineData
c824cacd
AZ
1/*
2 * Maxim MAX1110/1111 ADC chip emulation.
3 *
4 * Copyright (c) 2006 Openedhand Ltd.
5 * Written by Andrzej Zaborowski <[email protected]>
6 *
7 * This code is licensed under the GNU GPLv2.
6b620ca3
PB
8 *
9 * Contributions after 2012-01-13 are licensed under the terms of the
10 * GNU GPL, version 2 or (at your option) any later version.
c824cacd
AZ
11 */
12
0d1c9782 13#include "qemu/osdep.h"
64552b6b 14#include "hw/irq.h"
8fd06719 15#include "hw/ssi/ssi.h"
0b8fa32f 16#include "qemu/module.h"
c824cacd 17
a984a69e 18typedef struct {
7c77b654
PC
19 SSISlave parent_obj;
20
c824cacd
AZ
21 qemu_irq interrupt;
22 uint8_t tb1, rb2, rb3;
23 int cycle;
24
54d970d1 25 uint8_t input[8];
c824cacd 26 int inputs, com;
a984a69e 27} MAX111xState;
c824cacd 28
5ef4a1c3
PC
29#define TYPE_MAX_111X "max111x"
30
7c77b654
PC
31#define MAX_111X(obj) \
32 OBJECT_CHECK(MAX111xState, (obj), TYPE_MAX_111X)
33
5ef4a1c3
PC
34#define TYPE_MAX_1110 "max1110"
35#define TYPE_MAX_1111 "max1111"
36
c824cacd
AZ
37/* Control-byte bitfields */
38#define CB_PD0 (1 << 0)
39#define CB_PD1 (1 << 1)
40#define CB_SGL (1 << 2)
41#define CB_UNI (1 << 3)
42#define CB_SEL0 (1 << 4)
43#define CB_SEL1 (1 << 5)
44#define CB_SEL2 (1 << 6)
45#define CB_START (1 << 7)
46
47#define CHANNEL_NUM(v, b0, b1, b2) \
7d37435b
PB
48 ((((v) >> (2 + (b0))) & 4) | \
49 (((v) >> (3 + (b1))) & 2) | \
50 (((v) >> (4 + (b2))) & 1))
c824cacd 51
a984a69e 52static uint32_t max111x_read(MAX111xState *s)
c824cacd 53{
c824cacd
AZ
54 if (!s->tb1)
55 return 0;
56
57 switch (s->cycle ++) {
58 case 1:
59 return s->rb2;
60 case 2:
61 return s->rb3;
62 }
63
64 return 0;
65}
66
67/* Interpret a control-byte */
a984a69e 68static void max111x_write(MAX111xState *s, uint32_t value)
c824cacd 69{
c824cacd
AZ
70 int measure, chan;
71
72 /* Ignore the value if START bit is zero */
73 if (!(value & CB_START))
74 return;
75
76 s->cycle = 0;
77
78 if (!(value & CB_PD1)) {
79 s->tb1 = 0;
80 return;
81 }
82
83 s->tb1 = value;
84
85 if (s->inputs == 8)
86 chan = CHANNEL_NUM(value, 1, 0, 2);
87 else
88 chan = CHANNEL_NUM(value & ~CB_SEL0, 0, 1, 2);
89
90 if (value & CB_SGL)
91 measure = s->input[chan] - s->com;
92 else
93 measure = s->input[chan] - s->input[chan ^ 1];
94
95 if (!(value & CB_UNI))
96 measure ^= 0x80;
97
98 s->rb2 = (measure >> 2) & 0x3f;
99 s->rb3 = (measure << 6) & 0xc0;
100
a984a69e
PB
101 /* FIXME: When should the IRQ be lowered? */
102 qemu_irq_raise(s->interrupt);
103}
104
105static uint32_t max111x_transfer(SSISlave *dev, uint32_t value)
106{
7c77b654 107 MAX111xState *s = MAX_111X(dev);
a984a69e
PB
108 max111x_write(s, value);
109 return max111x_read(s);
c824cacd
AZ
110}
111
38cb3aa9
JQ
112static const VMStateDescription vmstate_max111x = {
113 .name = "max111x",
66530953
PC
114 .version_id = 1,
115 .minimum_version_id = 1,
8f1e884b 116 .fields = (VMStateField[]) {
7c77b654 117 VMSTATE_SSI_SLAVE(parent_obj, MAX111xState),
38cb3aa9
JQ
118 VMSTATE_UINT8(tb1, MAX111xState),
119 VMSTATE_UINT8(rb2, MAX111xState),
120 VMSTATE_UINT8(rb3, MAX111xState),
d2164ad3 121 VMSTATE_INT32_EQUAL(inputs, MAX111xState, NULL),
38cb3aa9
JQ
122 VMSTATE_INT32(com, MAX111xState),
123 VMSTATE_ARRAY_INT32_UNSAFE(input, MAX111xState, inputs,
124 vmstate_info_uint8, uint8_t),
125 VMSTATE_END_OF_LIST()
126 }
127};
aa941b94 128
1a7d9ee6 129static int max111x_init(SSISlave *d, int inputs)
c824cacd 130{
1a7d9ee6 131 DeviceState *dev = DEVICE(d);
7c77b654 132 MAX111xState *s = MAX_111X(dev);
c824cacd 133
1a7d9ee6 134 qdev_init_gpio_out(dev, &s->interrupt, 1);
c824cacd 135
a984a69e 136 s->inputs = inputs;
c824cacd
AZ
137 /* TODO: add a user interface for setting these */
138 s->input[0] = 0xf0;
139 s->input[1] = 0xe0;
140 s->input[2] = 0xd0;
141 s->input[3] = 0xc0;
142 s->input[4] = 0xb0;
143 s->input[5] = 0xa0;
144 s->input[6] = 0x90;
145 s->input[7] = 0x80;
146 s->com = 0;
aa941b94 147
1a7d9ee6 148 vmstate_register(dev, -1, &vmstate_max111x, s);
81a322d4 149 return 0;
c824cacd
AZ
150}
151
7673bb4c 152static void max1110_realize(SSISlave *dev, Error **errp)
c824cacd 153{
7673bb4c 154 max111x_init(dev, 8);
c824cacd
AZ
155}
156
7673bb4c 157static void max1111_realize(SSISlave *dev, Error **errp)
c824cacd 158{
7673bb4c 159 max111x_init(dev, 4);
c824cacd
AZ
160}
161
a984a69e 162void max111x_set_input(DeviceState *dev, int line, uint8_t value)
c824cacd 163{
7c77b654 164 MAX111xState *s = MAX_111X(dev);
a984a69e 165 assert(line >= 0 && line < s->inputs);
c824cacd
AZ
166 s->input[line] = value;
167}
a984a69e 168
5ef4a1c3 169static void max111x_class_init(ObjectClass *klass, void *data)
cd6c4cf2
AL
170{
171 SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
172
cd6c4cf2
AL
173 k->transfer = max111x_transfer;
174}
175
5ef4a1c3
PC
176static const TypeInfo max111x_info = {
177 .name = TYPE_MAX_111X,
39bffca2
AL
178 .parent = TYPE_SSI_SLAVE,
179 .instance_size = sizeof(MAX111xState),
5ef4a1c3
PC
180 .class_init = max111x_class_init,
181 .abstract = true,
182};
183
184static void max1110_class_init(ObjectClass *klass, void *data)
185{
186 SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
187
7673bb4c 188 k->realize = max1110_realize;
5ef4a1c3
PC
189}
190
191static const TypeInfo max1110_info = {
192 .name = TYPE_MAX_1110,
193 .parent = TYPE_MAX_111X,
39bffca2 194 .class_init = max1110_class_init,
a984a69e
PB
195};
196
cd6c4cf2
AL
197static void max1111_class_init(ObjectClass *klass, void *data)
198{
199 SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
200
7673bb4c 201 k->realize = max1111_realize;
cd6c4cf2
AL
202}
203
8c43a6f0 204static const TypeInfo max1111_info = {
5ef4a1c3
PC
205 .name = TYPE_MAX_1111,
206 .parent = TYPE_MAX_111X,
39bffca2 207 .class_init = max1111_class_init,
a984a69e
PB
208};
209
83f7d43a 210static void max111x_register_types(void)
a984a69e 211{
5ef4a1c3 212 type_register_static(&max111x_info);
39bffca2
AL
213 type_register_static(&max1110_info);
214 type_register_static(&max1111_info);
a984a69e
PB
215}
216
83f7d43a 217type_init(max111x_register_types)
This page took 0.983747 seconds and 4 git commands to generate.