Annotation of qemu/hw/ads7846.c, revision 1.1.1.2

1.1       root        1: /*
                      2:  * TI ADS7846 / TSC2046 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 GPL v2.
                      8:  */
                      9: 
                     10: #include "hw.h"
                     11: #include "devices.h"
                     12: #include "console.h"
                     13: 
                     14: struct ads7846_state_s {
                     15:     qemu_irq interrupt;
                     16: 
                     17:     int input[8];
                     18:     int pressure;
                     19:     int noise;
                     20: 
                     21:     int cycle;
                     22:     int output;
                     23: };
                     24: 
                     25: /* Control-byte bitfields */
                     26: #define CB_PD0         (1 << 0)
                     27: #define CB_PD1         (1 << 1)
                     28: #define CB_SER         (1 << 2)
                     29: #define CB_MODE                (1 << 3)
                     30: #define CB_A0          (1 << 4)
                     31: #define CB_A1          (1 << 5)
                     32: #define CB_A2          (1 << 6)
                     33: #define CB_START       (1 << 7)
                     34: 
                     35: #define X_AXIS_DMAX    3470
                     36: #define X_AXIS_MIN     290
                     37: #define Y_AXIS_DMAX    3450
                     38: #define Y_AXIS_MIN     200
                     39: 
                     40: #define ADS_VBAT       2000
                     41: #define ADS_VAUX       2000
                     42: #define ADS_TEMP0      2000
                     43: #define ADS_TEMP1      3000
                     44: #define ADS_XPOS(x, y) (X_AXIS_MIN + ((X_AXIS_DMAX * (x)) >> 15))
                     45: #define ADS_YPOS(x, y) (Y_AXIS_MIN + ((Y_AXIS_DMAX * (y)) >> 15))
                     46: #define ADS_Z1POS(x, y)        600
                     47: #define ADS_Z2POS(x, y)        (600 + 6000 / ADS_XPOS(x, y))
                     48: 
                     49: static void ads7846_int_update(struct ads7846_state_s *s)
                     50: {
                     51:     if (s->interrupt)
                     52:         qemu_set_irq(s->interrupt, s->pressure == 0);
                     53: }
                     54: 
                     55: uint32_t ads7846_read(void *opaque)
                     56: {
                     57:     struct ads7846_state_s *s = (struct ads7846_state_s *) opaque;
                     58: 
                     59:     return s->output;
                     60: }
                     61: 
                     62: void ads7846_write(void *opaque, uint32_t value)
                     63: {
                     64:     struct ads7846_state_s *s = (struct ads7846_state_s *) opaque;
                     65: 
                     66:     switch (s->cycle ++) {
                     67:     case 0:
                     68:         if (!(value & CB_START)) {
                     69:             s->cycle = 0;
                     70:             break;
                     71:         }
                     72: 
                     73:         s->output = s->input[(value >> 4) & 7];
                     74: 
                     75:         /* Imitate the ADC noise, some drivers expect this.  */
                     76:         s->noise = (s->noise + 3) & 7;
                     77:         switch ((value >> 4) & 7) {
                     78:         case 1: s->output += s->noise ^ 2; break;
                     79:         case 3: s->output += s->noise ^ 0; break;
                     80:         case 4: s->output += s->noise ^ 7; break;
                     81:         case 5: s->output += s->noise ^ 5; break;
                     82:         }
                     83: 
                     84:         if (value & CB_MODE)
                     85:             s->output >>= 4;   /* 8 bits instead of 12 */
                     86: 
                     87:         break;
                     88:     case 1:
                     89:         s->cycle = 0;
                     90:         break;
                     91:     }
                     92: }
                     93: 
                     94: static void ads7846_ts_event(void *opaque,
                     95:                 int x, int y, int z, int buttons_state)
                     96: {
                     97:     struct ads7846_state_s *s = opaque;
                     98: 
                     99:     if (buttons_state) {
                    100:         x = 0x7fff - x;
                    101:         s->input[1] = ADS_XPOS(x, y);
                    102:         s->input[3] = ADS_Z1POS(x, y);
                    103:         s->input[4] = ADS_Z2POS(x, y);
                    104:         s->input[5] = ADS_YPOS(x, y);
                    105:     }
                    106: 
                    107:     if (s->pressure == !buttons_state) {
                    108:         s->pressure = !!buttons_state;
                    109: 
                    110:         ads7846_int_update(s);
                    111:     }
                    112: }
                    113: 
                    114: static void ads7846_save(QEMUFile *f, void *opaque)
                    115: {
                    116:     struct ads7846_state_s *s = (struct ads7846_state_s *) opaque;
                    117:     int i;
                    118: 
                    119:     for (i = 0; i < 8; i ++)
                    120:         qemu_put_be32(f, s->input[i]);
                    121:     qemu_put_be32(f, s->noise);
                    122:     qemu_put_be32(f, s->cycle);
                    123:     qemu_put_be32(f, s->output);
                    124: }
                    125: 
                    126: static int ads7846_load(QEMUFile *f, void *opaque, int version_id)
                    127: {
                    128:     struct ads7846_state_s *s = (struct ads7846_state_s *) opaque;
                    129:     int i;
                    130: 
                    131:     for (i = 0; i < 8; i ++)
                    132:         s->input[i] = qemu_get_be32(f);
                    133:     s->noise = qemu_get_be32(f);
                    134:     s->cycle = qemu_get_be32(f);
                    135:     s->output = qemu_get_be32(f);
                    136: 
                    137:     s->pressure = 0;
                    138:     ads7846_int_update(s);
                    139: 
                    140:     return 0;
                    141: }
                    142: 
                    143: struct ads7846_state_s *ads7846_init(qemu_irq penirq)
                    144: {
                    145:     struct ads7846_state_s *s;
                    146:     s = (struct ads7846_state_s *)
                    147:             qemu_mallocz(sizeof(struct ads7846_state_s));
                    148:     memset(s, 0, sizeof(struct ads7846_state_s));
                    149: 
                    150:     s->interrupt = penirq;
                    151: 
                    152:     s->input[0] = ADS_TEMP0;   /* TEMP0 */
                    153:     s->input[2] = ADS_VBAT;    /* VBAT */
                    154:     s->input[6] = ADS_VAUX;    /* VAUX */
                    155:     s->input[7] = ADS_TEMP1;   /* TEMP1 */
                    156: 
                    157:     /* We want absolute coordinates */
                    158:     qemu_add_mouse_event_handler(ads7846_ts_event, s, 1,
                    159:                     "QEMU ADS7846-driven Touchscreen");
                    160: 
                    161:     ads7846_int_update(s);
                    162: 
1.1.1.2 ! root      163:     register_savevm("ads7846", -1, 0, ads7846_save, ads7846_load, s);
1.1       root      164: 
                    165:     return s;
                    166: }

unix.superglobalmegacorp.com