|
|
1.1 root 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.
1.1.1.7 ! root 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.
1.1 root 11: */
12:
1.1.1.3 root 13: #include "ssi.h"
1.1 root 14:
1.1.1.3 root 15: typedef struct {
16: SSISlave ssidev;
1.1 root 17: qemu_irq interrupt;
18: uint8_t tb1, rb2, rb3;
19: int cycle;
20:
1.1.1.6 root 21: uint8_t input[8];
1.1 root 22: int inputs, com;
1.1.1.3 root 23: } MAX111xState;
1.1 root 24:
25: /* Control-byte bitfields */
26: #define CB_PD0 (1 << 0)
27: #define CB_PD1 (1 << 1)
28: #define CB_SGL (1 << 2)
29: #define CB_UNI (1 << 3)
30: #define CB_SEL0 (1 << 4)
31: #define CB_SEL1 (1 << 5)
32: #define CB_SEL2 (1 << 6)
33: #define CB_START (1 << 7)
34:
35: #define CHANNEL_NUM(v, b0, b1, b2) \
36: ((((v) >> (2 + (b0))) & 4) | \
37: (((v) >> (3 + (b1))) & 2) | \
38: (((v) >> (4 + (b2))) & 1))
39:
1.1.1.3 root 40: static uint32_t max111x_read(MAX111xState *s)
1.1 root 41: {
42: if (!s->tb1)
43: return 0;
44:
45: switch (s->cycle ++) {
46: case 1:
47: return s->rb2;
48: case 2:
49: return s->rb3;
50: }
51:
52: return 0;
53: }
54:
55: /* Interpret a control-byte */
1.1.1.3 root 56: static void max111x_write(MAX111xState *s, uint32_t value)
1.1 root 57: {
58: int measure, chan;
59:
60: /* Ignore the value if START bit is zero */
61: if (!(value & CB_START))
62: return;
63:
64: s->cycle = 0;
65:
66: if (!(value & CB_PD1)) {
67: s->tb1 = 0;
68: return;
69: }
70:
71: s->tb1 = value;
72:
73: if (s->inputs == 8)
74: chan = CHANNEL_NUM(value, 1, 0, 2);
75: else
76: chan = CHANNEL_NUM(value & ~CB_SEL0, 0, 1, 2);
77:
78: if (value & CB_SGL)
79: measure = s->input[chan] - s->com;
80: else
81: measure = s->input[chan] - s->input[chan ^ 1];
82:
83: if (!(value & CB_UNI))
84: measure ^= 0x80;
85:
86: s->rb2 = (measure >> 2) & 0x3f;
87: s->rb3 = (measure << 6) & 0xc0;
88:
1.1.1.3 root 89: /* FIXME: When should the IRQ be lowered? */
90: qemu_irq_raise(s->interrupt);
91: }
92:
93: static uint32_t max111x_transfer(SSISlave *dev, uint32_t value)
94: {
95: MAX111xState *s = FROM_SSI_SLAVE(MAX111xState, dev);
96: max111x_write(s, value);
97: return max111x_read(s);
1.1 root 98: }
99:
1.1.1.6 root 100: static const VMStateDescription vmstate_max111x = {
101: .name = "max111x",
102: .version_id = 0,
103: .minimum_version_id = 0,
104: .minimum_version_id_old = 0,
105: .fields = (VMStateField[]) {
106: VMSTATE_UINT8(tb1, MAX111xState),
107: VMSTATE_UINT8(rb2, MAX111xState),
108: VMSTATE_UINT8(rb3, MAX111xState),
109: VMSTATE_INT32_EQUAL(inputs, MAX111xState),
110: VMSTATE_INT32(com, MAX111xState),
111: VMSTATE_ARRAY_INT32_UNSAFE(input, MAX111xState, inputs,
112: vmstate_info_uint8, uint8_t),
113: VMSTATE_END_OF_LIST()
114: }
115: };
1.1 root 116:
1.1.1.4 root 117: static int max111x_init(SSISlave *dev, int inputs)
1.1 root 118: {
1.1.1.3 root 119: MAX111xState *s = FROM_SSI_SLAVE(MAX111xState, dev);
1.1 root 120:
1.1.1.3 root 121: qdev_init_gpio_out(&dev->qdev, &s->interrupt, 1);
1.1 root 122:
1.1.1.3 root 123: s->inputs = inputs;
1.1 root 124: /* TODO: add a user interface for setting these */
125: s->input[0] = 0xf0;
126: s->input[1] = 0xe0;
127: s->input[2] = 0xd0;
128: s->input[3] = 0xc0;
129: s->input[4] = 0xb0;
130: s->input[5] = 0xa0;
131: s->input[6] = 0x90;
132: s->input[7] = 0x80;
133: s->com = 0;
134:
1.1.1.6 root 135: vmstate_register(&dev->qdev, -1, &vmstate_max111x, s);
1.1.1.4 root 136: return 0;
1.1 root 137: }
138:
1.1.1.4 root 139: static int max1110_init(SSISlave *dev)
1.1 root 140: {
1.1.1.4 root 141: return max111x_init(dev, 8);
1.1 root 142: }
143:
1.1.1.4 root 144: static int max1111_init(SSISlave *dev)
1.1 root 145: {
1.1.1.4 root 146: return max111x_init(dev, 4);
1.1 root 147: }
148:
1.1.1.3 root 149: void max111x_set_input(DeviceState *dev, int line, uint8_t value)
1.1 root 150: {
1.1.1.3 root 151: MAX111xState *s = FROM_SSI_SLAVE(MAX111xState, SSI_SLAVE_FROM_QDEV(dev));
152: assert(line >= 0 && line < s->inputs);
1.1 root 153: s->input[line] = value;
154: }
1.1.1.3 root 155:
1.1.1.7 ! root 156: static void max1110_class_init(ObjectClass *klass, void *data)
! 157: {
! 158: SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
! 159:
! 160: k->init = max1110_init;
! 161: k->transfer = max111x_transfer;
! 162: }
! 163:
! 164: static TypeInfo max1110_info = {
! 165: .name = "max1110",
! 166: .parent = TYPE_SSI_SLAVE,
! 167: .instance_size = sizeof(MAX111xState),
! 168: .class_init = max1110_class_init,
1.1.1.3 root 169: };
170:
1.1.1.7 ! root 171: static void max1111_class_init(ObjectClass *klass, void *data)
! 172: {
! 173: SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
! 174:
! 175: k->init = max1111_init;
! 176: k->transfer = max111x_transfer;
! 177: }
! 178:
! 179: static TypeInfo max1111_info = {
! 180: .name = "max1111",
! 181: .parent = TYPE_SSI_SLAVE,
! 182: .instance_size = sizeof(MAX111xState),
! 183: .class_init = max1111_class_init,
1.1.1.3 root 184: };
185:
1.1.1.7 ! root 186: static void max111x_register_types(void)
1.1.1.3 root 187: {
1.1.1.7 ! root 188: type_register_static(&max1110_info);
! 189: type_register_static(&max1111_info);
1.1.1.3 root 190: }
191:
1.1.1.7 ! root 192: type_init(max111x_register_types)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.