symbian-qemu-0.9.1-12/qemu-symbian-svp/hw/max111x.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     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 "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 struct max111x_s *max111x_init(qemu_irq cb)
       
   125 {
       
   126     struct max111x_s *s;
       
   127     s = (struct max111x_s *)
       
   128             qemu_mallocz(sizeof(struct max111x_s));
       
   129     memset(s, 0, sizeof(struct max111x_s));
       
   130 
       
   131     s->interrupt = cb;
       
   132 
       
   133     /* TODO: add a user interface for setting these */
       
   134     s->input[0] = 0xf0;
       
   135     s->input[1] = 0xe0;
       
   136     s->input[2] = 0xd0;
       
   137     s->input[3] = 0xc0;
       
   138     s->input[4] = 0xb0;
       
   139     s->input[5] = 0xa0;
       
   140     s->input[6] = 0x90;
       
   141     s->input[7] = 0x80;
       
   142     s->com = 0;
       
   143 
       
   144     register_savevm("max111x", -1, 0, max111x_save, max111x_load, s);
       
   145 
       
   146     return s;
       
   147 }
       
   148 
       
   149 struct max111x_s *max1110_init(qemu_irq cb)
       
   150 {
       
   151     struct max111x_s *s = max111x_init(cb);
       
   152     s->inputs = 8;
       
   153     return s;
       
   154 }
       
   155 
       
   156 struct max111x_s *max1111_init(qemu_irq cb)
       
   157 {
       
   158     struct max111x_s *s = max111x_init(cb);
       
   159     s->inputs = 4;
       
   160     return s;
       
   161 }
       
   162 
       
   163 void max111x_set_input(struct max111x_s *s, int line, uint8_t value)
       
   164 {
       
   165     if (line >= s->inputs) {
       
   166         printf("%s: There's no input %i\n", __FUNCTION__, line);
       
   167         return;
       
   168     }
       
   169 
       
   170     s->input[line] = value;
       
   171 }