Commit c824cacdb1aa8bfd9e057dd64b4b8a16f5727fff

Authored by balrog
1 parent fd5a3b33

Maxim MAX1110/1111 ADC chip.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2755 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 2 changed files with 144 additions and 0 deletions
hw/max111x.c 0 → 100644
  1 +/*
  2 + * Maxim MAX1110/1111 ADC chip emulation.
  3 + *
  4 + * Copyright (c) 2006 Openedhand Ltd.
  5 + * Written by Andrzej Zaborowski <balrog@zabor.org>
  6 + *
  7 + * This code is licensed under the GNU GPLv2.
  8 + */
  9 +
  10 +#include <vl.h>
  11 +
  12 +struct max111x_s {
  13 + qemu_irq interrupt;
  14 + uint8_t tb1, rb2, rb3;
  15 + int cycle;
  16 +
  17 + int input[8];
  18 + int inputs, com;
  19 +};
  20 +
  21 +/* Control-byte bitfields */
  22 +#define CB_PD0 (1 << 0)
  23 +#define CB_PD1 (1 << 1)
  24 +#define CB_SGL (1 << 2)
  25 +#define CB_UNI (1 << 3)
  26 +#define CB_SEL0 (1 << 4)
  27 +#define CB_SEL1 (1 << 5)
  28 +#define CB_SEL2 (1 << 6)
  29 +#define CB_START (1 << 7)
  30 +
  31 +#define CHANNEL_NUM(v, b0, b1, b2) \
  32 + ((((v) >> (2 + (b0))) & 4) | \
  33 + (((v) >> (3 + (b1))) & 2) | \
  34 + (((v) >> (4 + (b2))) & 1))
  35 +
  36 +uint32_t max111x_read(void *opaque)
  37 +{
  38 + struct max111x_s *s = (struct max111x_s *) opaque;
  39 +
  40 + if (!s->tb1)
  41 + return 0;
  42 +
  43 + switch (s->cycle ++) {
  44 + case 1:
  45 + return s->rb2;
  46 + case 2:
  47 + return s->rb3;
  48 + }
  49 +
  50 + return 0;
  51 +}
  52 +
  53 +/* Interpret a control-byte */
  54 +void max111x_write(void *opaque, uint32_t value)
  55 +{
  56 + struct max111x_s *s = (struct max111x_s *) opaque;
  57 + int measure, chan;
  58 +
  59 + /* Ignore the value if START bit is zero */
  60 + if (!(value & CB_START))
  61 + return;
  62 +
  63 + s->cycle = 0;
  64 +
  65 + if (!(value & CB_PD1)) {
  66 + s->tb1 = 0;
  67 + return;
  68 + }
  69 +
  70 + s->tb1 = value;
  71 +
  72 + if (s->inputs == 8)
  73 + chan = CHANNEL_NUM(value, 1, 0, 2);
  74 + else
  75 + chan = CHANNEL_NUM(value & ~CB_SEL0, 0, 1, 2);
  76 +
  77 + if (value & CB_SGL)
  78 + measure = s->input[chan] - s->com;
  79 + else
  80 + measure = s->input[chan] - s->input[chan ^ 1];
  81 +
  82 + if (!(value & CB_UNI))
  83 + measure ^= 0x80;
  84 +
  85 + s->rb2 = (measure >> 2) & 0x3f;
  86 + s->rb3 = (measure << 6) & 0xc0;
  87 +
  88 + if (s->interrupt)
  89 + qemu_irq_raise(s->interrupt);
  90 +}
  91 +
  92 +static struct max111x_s *max111x_init(qemu_irq cb)
  93 +{
  94 + struct max111x_s *s;
  95 + s = (struct max111x_s *)
  96 + qemu_mallocz(sizeof(struct max111x_s));
  97 + memset(s, 0, sizeof(struct max111x_s));
  98 +
  99 + s->interrupt = cb;
  100 +
  101 + /* TODO: add a user interface for setting these */
  102 + s->input[0] = 0xf0;
  103 + s->input[1] = 0xe0;
  104 + s->input[2] = 0xd0;
  105 + s->input[3] = 0xc0;
  106 + s->input[4] = 0xb0;
  107 + s->input[5] = 0xa0;
  108 + s->input[6] = 0x90;
  109 + s->input[7] = 0x80;
  110 + s->com = 0;
  111 + return s;
  112 +}
  113 +
  114 +struct max111x_s *max1110_init(qemu_irq cb)
  115 +{
  116 + struct max111x_s *s = max111x_init(cb);
  117 + s->inputs = 8;
  118 + return s;
  119 +}
  120 +
  121 +struct max111x_s *max1111_init(qemu_irq cb)
  122 +{
  123 + struct max111x_s *s = max111x_init(cb);
  124 + s->inputs = 4;
  125 + return s;
  126 +}
  127 +
  128 +void max111x_set_input(struct max111x_s *s, int line, uint8_t value)
  129 +{
  130 + if (line >= s->inputs) {
  131 + printf("%s: There's no input %i\n", __FUNCTION__, line);
  132 + return;
  133 + }
  134 +
  135 + s->input[line] = value;
  136 +}
... ...
... ... @@ -1506,6 +1506,14 @@ uint32_t ads7846_read(void *opaque);
1506 1506 void ads7846_write(void *opaque, uint32_t value);
1507 1507 struct ads7846_state_s *ads7846_init(qemu_irq penirq);
1508 1508  
  1509 +/* max111x.c */
  1510 +struct max111x_s;
  1511 +uint32_t max111x_read(void *opaque);
  1512 +void max111x_write(void *opaque, uint32_t value);
  1513 +struct max111x_s *max1110_init(qemu_irq cb);
  1514 +struct max111x_s *max1111_init(qemu_irq cb);
  1515 +void max111x_set_input(struct max111x_s *s, int line, uint8_t value);
  1516 +
1509 1517 /* PCMCIA/Cardbus */
1510 1518  
1511 1519 struct pcmcia_socket_s {
... ...