max111x.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  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. #include "ssi.h"
  10. typedef struct {
  11. SSISlave ssidev;
  12. qemu_irq interrupt;
  13. uint8_t tb1, rb2, rb3;
  14. int cycle;
  15. uint8_t input[8];
  16. int inputs, com;
  17. } MAX111xState;
  18. /* Control-byte bitfields */
  19. #define CB_PD0 (1 << 0)
  20. #define CB_PD1 (1 << 1)
  21. #define CB_SGL (1 << 2)
  22. #define CB_UNI (1 << 3)
  23. #define CB_SEL0 (1 << 4)
  24. #define CB_SEL1 (1 << 5)
  25. #define CB_SEL2 (1 << 6)
  26. #define CB_START (1 << 7)
  27. #define CHANNEL_NUM(v, b0, b1, b2) \
  28. ((((v) >> (2 + (b0))) & 4) | \
  29. (((v) >> (3 + (b1))) & 2) | \
  30. (((v) >> (4 + (b2))) & 1))
  31. static uint32_t max111x_read(MAX111xState *s)
  32. {
  33. if (!s->tb1)
  34. return 0;
  35. switch (s->cycle ++) {
  36. case 1:
  37. return s->rb2;
  38. case 2:
  39. return s->rb3;
  40. }
  41. return 0;
  42. }
  43. /* Interpret a control-byte */
  44. static void max111x_write(MAX111xState *s, uint32_t value)
  45. {
  46. int measure, chan;
  47. /* Ignore the value if START bit is zero */
  48. if (!(value & CB_START))
  49. return;
  50. s->cycle = 0;
  51. if (!(value & CB_PD1)) {
  52. s->tb1 = 0;
  53. return;
  54. }
  55. s->tb1 = value;
  56. if (s->inputs == 8)
  57. chan = CHANNEL_NUM(value, 1, 0, 2);
  58. else
  59. chan = CHANNEL_NUM(value & ~CB_SEL0, 0, 1, 2);
  60. if (value & CB_SGL)
  61. measure = s->input[chan] - s->com;
  62. else
  63. measure = s->input[chan] - s->input[chan ^ 1];
  64. if (!(value & CB_UNI))
  65. measure ^= 0x80;
  66. s->rb2 = (measure >> 2) & 0x3f;
  67. s->rb3 = (measure << 6) & 0xc0;
  68. /* FIXME: When should the IRQ be lowered? */
  69. qemu_irq_raise(s->interrupt);
  70. }
  71. static uint32_t max111x_transfer(SSISlave *dev, uint32_t value)
  72. {
  73. MAX111xState *s = FROM_SSI_SLAVE(MAX111xState, dev);
  74. max111x_write(s, value);
  75. return max111x_read(s);
  76. }
  77. static const VMStateDescription vmstate_max111x = {
  78. .name = "max111x",
  79. .version_id = 0,
  80. .minimum_version_id = 0,
  81. .minimum_version_id_old = 0,
  82. .fields = (VMStateField[]) {
  83. VMSTATE_UINT8(tb1, MAX111xState),
  84. VMSTATE_UINT8(rb2, MAX111xState),
  85. VMSTATE_UINT8(rb3, MAX111xState),
  86. VMSTATE_INT32_EQUAL(inputs, MAX111xState),
  87. VMSTATE_INT32(com, MAX111xState),
  88. VMSTATE_ARRAY_INT32_UNSAFE(input, MAX111xState, inputs,
  89. vmstate_info_uint8, uint8_t),
  90. VMSTATE_END_OF_LIST()
  91. }
  92. };
  93. static int max111x_init(SSISlave *dev, int inputs)
  94. {
  95. MAX111xState *s = FROM_SSI_SLAVE(MAX111xState, dev);
  96. qdev_init_gpio_out(&dev->qdev, &s->interrupt, 1);
  97. s->inputs = inputs;
  98. /* TODO: add a user interface for setting these */
  99. s->input[0] = 0xf0;
  100. s->input[1] = 0xe0;
  101. s->input[2] = 0xd0;
  102. s->input[3] = 0xc0;
  103. s->input[4] = 0xb0;
  104. s->input[5] = 0xa0;
  105. s->input[6] = 0x90;
  106. s->input[7] = 0x80;
  107. s->com = 0;
  108. vmstate_register(&dev->qdev, -1, &vmstate_max111x, s);
  109. return 0;
  110. }
  111. static int max1110_init(SSISlave *dev)
  112. {
  113. return max111x_init(dev, 8);
  114. }
  115. static int max1111_init(SSISlave *dev)
  116. {
  117. return max111x_init(dev, 4);
  118. }
  119. void max111x_set_input(DeviceState *dev, int line, uint8_t value)
  120. {
  121. MAX111xState *s = FROM_SSI_SLAVE(MAX111xState, SSI_SLAVE_FROM_QDEV(dev));
  122. assert(line >= 0 && line < s->inputs);
  123. s->input[line] = value;
  124. }
  125. static SSISlaveInfo max1110_info = {
  126. .qdev.name = "max1110",
  127. .qdev.size = sizeof(MAX111xState),
  128. .init = max1110_init,
  129. .transfer = max111x_transfer
  130. };
  131. static SSISlaveInfo max1111_info = {
  132. .qdev.name = "max1111",
  133. .qdev.size = sizeof(MAX111xState),
  134. .init = max1111_init,
  135. .transfer = max111x_transfer
  136. };
  137. static void max111x_register_devices(void)
  138. {
  139. ssi_register_slave(&max1110_info);
  140. ssi_register_slave(&max1111_info);
  141. }
  142. device_init(max111x_register_devices)