|
|
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. ! 8: */ ! 9: ! 10: #include "hw.h" ! 11: #include "i2c.h" ! 12: ! 13: struct max111x_s { ! 14: qemu_irq interrupt; ! 15: uint8_t tb1, rb2, rb3; ! 16: int cycle; ! 17: ! 18: int input[8]; ! 19: int inputs, com; ! 20: }; ! 21: ! 22: /* Control-byte bitfields */ ! 23: #define CB_PD0 (1 << 0) ! 24: #define CB_PD1 (1 << 1) ! 25: #define CB_SGL (1 << 2) ! 26: #define CB_UNI (1 << 3) ! 27: #define CB_SEL0 (1 << 4) ! 28: #define CB_SEL1 (1 << 5) ! 29: #define CB_SEL2 (1 << 6) ! 30: #define CB_START (1 << 7) ! 31: ! 32: #define CHANNEL_NUM(v, b0, b1, b2) \ ! 33: ((((v) >> (2 + (b0))) & 4) | \ ! 34: (((v) >> (3 + (b1))) & 2) | \ ! 35: (((v) >> (4 + (b2))) & 1)) ! 36: ! 37: uint32_t max111x_read(void *opaque) ! 38: { ! 39: struct max111x_s *s = (struct max111x_s *) opaque; ! 40: ! 41: if (!s->tb1) ! 42: return 0; ! 43: ! 44: switch (s->cycle ++) { ! 45: case 1: ! 46: return s->rb2; ! 47: case 2: ! 48: return s->rb3; ! 49: } ! 50: ! 51: return 0; ! 52: } ! 53: ! 54: /* Interpret a control-byte */ ! 55: void max111x_write(void *opaque, uint32_t value) ! 56: { ! 57: struct max111x_s *s = (struct max111x_s *) opaque; ! 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: ! 89: if (s->interrupt) ! 90: qemu_irq_raise(s->interrupt); ! 91: } ! 92: ! 93: static void max111x_save(QEMUFile *f, void *opaque) ! 94: { ! 95: struct max111x_s *s = (struct max111x_s *) opaque; ! 96: int i; ! 97: ! 98: qemu_put_8s(f, &s->tb1); ! 99: qemu_put_8s(f, &s->rb2); ! 100: qemu_put_8s(f, &s->rb3); ! 101: qemu_put_be32(f, s->inputs); ! 102: qemu_put_be32(f, s->com); ! 103: for (i = 0; i < s->inputs; i ++) ! 104: qemu_put_byte(f, s->input[i]); ! 105: } ! 106: ! 107: static int max111x_load(QEMUFile *f, void *opaque, int version_id) ! 108: { ! 109: struct max111x_s *s = (struct max111x_s *) opaque; ! 110: int i; ! 111: ! 112: qemu_get_8s(f, &s->tb1); ! 113: qemu_get_8s(f, &s->rb2); ! 114: qemu_get_8s(f, &s->rb3); ! 115: if (s->inputs != qemu_get_be32(f)) ! 116: return -EINVAL; ! 117: s->com = qemu_get_be32(f); ! 118: for (i = 0; i < s->inputs; i ++) ! 119: s->input[i] = qemu_get_byte(f); ! 120: ! 121: return 0; ! 122: } ! 123: ! 124: static int max111x_iid = 0; ! 125: ! 126: static struct max111x_s *max111x_init(qemu_irq cb) ! 127: { ! 128: struct max111x_s *s; ! 129: s = (struct max111x_s *) ! 130: qemu_mallocz(sizeof(struct max111x_s)); ! 131: memset(s, 0, sizeof(struct max111x_s)); ! 132: ! 133: s->interrupt = cb; ! 134: ! 135: /* TODO: add a user interface for setting these */ ! 136: s->input[0] = 0xf0; ! 137: s->input[1] = 0xe0; ! 138: s->input[2] = 0xd0; ! 139: s->input[3] = 0xc0; ! 140: s->input[4] = 0xb0; ! 141: s->input[5] = 0xa0; ! 142: s->input[6] = 0x90; ! 143: s->input[7] = 0x80; ! 144: s->com = 0; ! 145: ! 146: register_savevm("max111x", max111x_iid ++, 0, ! 147: max111x_save, max111x_load, s); ! 148: ! 149: return s; ! 150: } ! 151: ! 152: struct max111x_s *max1110_init(qemu_irq cb) ! 153: { ! 154: struct max111x_s *s = max111x_init(cb); ! 155: s->inputs = 8; ! 156: return s; ! 157: } ! 158: ! 159: struct max111x_s *max1111_init(qemu_irq cb) ! 160: { ! 161: struct max111x_s *s = max111x_init(cb); ! 162: s->inputs = 4; ! 163: return s; ! 164: } ! 165: ! 166: void max111x_set_input(struct max111x_s *s, int line, uint8_t value) ! 167: { ! 168: if (line >= s->inputs) { ! 169: printf("%s: There's no input %i\n", __FUNCTION__, line); ! 170: return; ! 171: } ! 172: ! 173: s->input[line] = value; ! 174: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.