~ubuntu-branches/ubuntu/precise/mame/precise-proposed

« back to all changes in this revision

Viewing changes to src/emu/machine/i2cmemdev.c

  • Committer: Bazaar Package Importer
  • Author(s): Cesare Falco
  • Date: 2010-08-01 23:18:31 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20100801231831-9dj2qbsynutixsoe
Tags: 0.139-0ubuntu1
* New upstream release (LP: #612070)
* debian/contrib/manpages: removed, accepted upstream
* debian/patches/:
  - deprecated_gtk_macros: removed, fixed upstream
  - missing_newline.patch: removed, fixed upstream
  - typos.patch: removed, fixed upstream
* debian/rules: new variables SYMLEVEL and DUMPSYM
* mame-tools: ldplayer removed, possibly for good (FTBFS upstream)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
   I2C Memory
3
 
 
4
 
Generic ram/rom/eeprom/flash on an i2c bus. Supports specifying the slave address,
5
 
the data size & the page size for writing.
6
 
 
7
 
inputs:
8
 
 e0,e1,e2  lower 3 bits of the slave address
9
 
 sda       serial data
10
 
 scl       serial clock
11
 
 wc        write protect
12
 
 
13
 
outputs:
14
 
 sda       serial data
15
 
 
16
 
The memory address is only 8 bits, devices larger than this have multiple slave addresses.
17
 
The top five address bits are set at manufacture time, two values are standard.
18
 
Up to 4096 bytes can be addressed.
19
 
 
20
 
*/
21
 
 
22
 
#include "emu.h"
23
 
#include "machine/i2cmemdev.h"
24
 
 
25
 
#define VERBOSE_LEVEL ( 0 )
26
 
 
27
 
INLINE void ATTR_PRINTF(3,4) verboselog( running_machine *machine, int n_level, const char *s_fmt, ... )
28
 
{
29
 
        if( VERBOSE_LEVEL >= n_level )
30
 
        {
31
 
                va_list v;
32
 
                char buf[ 32768 ];
33
 
                va_start( v, s_fmt );
34
 
                vsprintf( buf, s_fmt, v );
35
 
                va_end( v );
36
 
                logerror( "%s: %s", cpuexec_describe_context(machine), buf );
37
 
        }
38
 
}
39
 
 
40
 
#define STATE_IDLE ( 0 )
41
 
#define STATE_DEVSEL ( 1 )
42
 
#define STATE_BYTEADDR ( 2 )
43
 
#define STATE_DATAIN ( 3 )
44
 
#define STATE_DATAOUT ( 4 )
45
 
 
46
 
#define DEVSEL_RW ( 1 )
47
 
#define DEVSEL_ADDRESS ( 0xfe )
48
 
 
49
 
typedef struct _i2cmem_state i2cmem_state;
50
 
struct _i2cmem_state
51
 
{
52
 
        int slave_address;
53
 
        int scl;
54
 
        int sdaw;
55
 
        int e0;
56
 
        int e1;
57
 
        int e2;
58
 
        int wc;
59
 
        int sdar;
60
 
        int state;
61
 
        int bits;
62
 
        int shift;
63
 
        int devsel;
64
 
        int byteaddr;
65
 
        unsigned char *data;
66
 
        int data_size;
67
 
        unsigned char *page;
68
 
        int page_offset;
69
 
        int page_size;
70
 
        int readmode;
71
 
};
72
 
 
73
 
/*-------------------------------------------------
74
 
    get_safe_token - makes sure that the passed
75
 
    in device is, in fact, an I2C memory
76
 
-------------------------------------------------*/
77
 
 
78
 
INLINE i2cmem_state *get_safe_token( running_device *device )
79
 
{
80
 
        assert( device != NULL );
81
 
        assert( device->token != NULL );
82
 
        assert( device->type == I2CMEM );
83
 
 
84
 
        return (i2cmem_state *)device->token;
85
 
}
86
 
 
87
 
static int select_device( i2cmem_state *c )
88
 
{
89
 
        int device = ( c->slave_address & 0xf0 ) | ( c->e2 << 3 ) | ( c->e1 << 2 ) | ( c->e0 << 1 );
90
 
        int mask = DEVSEL_ADDRESS & ~( ( c->data_size - 1 ) >> 7 );
91
 
 
92
 
        if( ( c->devsel & mask ) == ( device & mask ) )
93
 
        {
94
 
                return 1;
95
 
        }
96
 
 
97
 
        return 0;
98
 
}
99
 
 
100
 
static int data_offset( i2cmem_state *c )
101
 
{
102
 
        return ( ( ( c->devsel << 7 ) & 0xff00 ) | ( c->byteaddr & 0xff ) ) & ( c->data_size - 1 );
103
 
}
104
 
 
105
 
void i2cmemdev_write( running_device *device, int line, int data )
106
 
{
107
 
        i2cmem_state *c = get_safe_token( device );
108
 
 
109
 
        switch( line )
110
 
        {
111
 
        case I2CMEM_E0:
112
 
                if( c->e0 != data )
113
 
                {
114
 
                        c->e0 = data;
115
 
                        verboselog( device->machine, 2, "i2cmem_write( I2CMEM_E0, %d )\n", c->e0 );
116
 
                }
117
 
                break;
118
 
 
119
 
        case I2CMEM_E1:
120
 
                if( c->e1 != data )
121
 
                {
122
 
                        c->e1 = data;
123
 
                        verboselog( device->machine, 2, "i2cmem_write( I2CMEM_E1, %d )\n", c->e1 );
124
 
                }
125
 
                break;
126
 
 
127
 
        case I2CMEM_E2:
128
 
                if( c->e2 != data )
129
 
                {
130
 
                        c->e2 = data;
131
 
                        verboselog( device->machine, 2, "i2cmem_write( I2CMEM_E2, %d )\n", c->e2 );
132
 
                }
133
 
                break;
134
 
 
135
 
        case I2CMEM_SDA:
136
 
                if( c->sdaw != data )
137
 
                {
138
 
                        c->sdaw = data;
139
 
                        verboselog( device->machine, 2, "i2cmem_write( I2CMEM_SDA, %d )\n", c->sdaw );
140
 
 
141
 
                        if( c->scl )
142
 
                        {
143
 
                                if( c->sdaw )
144
 
                                {
145
 
                                        verboselog( device->machine, 1, "i2cmem stop\n");
146
 
                                        c->state = STATE_IDLE;
147
 
                                        c->byteaddr = 0;
148
 
                                }
149
 
                                else
150
 
                                {
151
 
                                        verboselog( device->machine, 2, "i2cmem start\n");
152
 
                                        c->state = STATE_DEVSEL;
153
 
                                        c->bits = 0;
154
 
                                }
155
 
 
156
 
                                c->sdar = 1;
157
 
                        }
158
 
                }
159
 
                break;
160
 
 
161
 
        case I2CMEM_SCL:
162
 
                if( c->scl != data )
163
 
                {
164
 
                        c->scl = data;
165
 
                        verboselog( device->machine, 2, "i2cmem_write( I2CMEM_SCL, %d )\n", c->scl );
166
 
 
167
 
                        switch( c->state )
168
 
                        {
169
 
                        case STATE_DEVSEL:
170
 
                        case STATE_BYTEADDR:
171
 
                        case STATE_DATAIN:
172
 
                                if( c->bits < 8 )
173
 
                                {
174
 
                                        if( c->scl )
175
 
                                        {
176
 
                                                c->shift = ( ( c->shift << 1 ) | c->sdaw ) & 0xff;
177
 
                                                c->bits++;
178
 
                                        }
179
 
                                }
180
 
                                else
181
 
                                {
182
 
                                        if( c->scl )
183
 
                                        {
184
 
                                                switch( c->state )
185
 
                                                {
186
 
                                                case STATE_DEVSEL:
187
 
                                                        c->devsel = c->shift;
188
 
 
189
 
                                                        if( !select_device( c ) )
190
 
                                                        {
191
 
                                                                verboselog( device->machine, 1, "i2cmem devsel %02x: not this device\n", c->devsel );
192
 
                                                                c->state = STATE_IDLE;
193
 
                                                        }
194
 
                                                        else if( ( c->devsel & DEVSEL_RW ) == 0 )
195
 
                                                        {
196
 
                                                                verboselog( device->machine, 1, "i2cmem devsel %02x: write\n", c->devsel );
197
 
                                                                c->state = STATE_BYTEADDR;
198
 
                                                        }
199
 
                                                        else
200
 
                                                        {
201
 
                                                                verboselog( device->machine, 1, "i2cmem devsel %02x: read\n", c->devsel );
202
 
                                                                c->state = STATE_DATAOUT;
203
 
                                                        }
204
 
                                                        break;
205
 
 
206
 
                                                case STATE_BYTEADDR:
207
 
                                                        c->byteaddr = c->shift;
208
 
                                                        c->page_offset = 0;
209
 
 
210
 
                                                        verboselog( device->machine, 1, "i2cmem byteaddr %02x\n", c->byteaddr );
211
 
 
212
 
                                                        c->state = STATE_DATAIN;
213
 
                                                        break;
214
 
 
215
 
                                                case STATE_DATAIN:
216
 
                                                        if( c->wc )
217
 
                                                        {
218
 
                                                                verboselog( device->machine, 0, "i2cmem write not enabled\n");
219
 
                                                                c->state = STATE_IDLE;
220
 
                                                        }
221
 
                                                        else if( c->page_size > 0 )
222
 
                                                        {
223
 
                                                                c->page[ c->page_offset ] = c->shift;
224
 
                                                                verboselog( device->machine, 1, "i2cmem page[ %04x ] <- %02x\n", c->page_offset, c->page[ c->page_offset ] );
225
 
 
226
 
                                                                c->page_offset++;
227
 
                                                                if( c->page_offset == c->page_size )
228
 
                                                                {
229
 
                                                                        int offset = data_offset( c ) & ~( c->page_size - 1 );
230
 
 
231
 
                                                                        memcpy( &c->data[ offset ], c->page, c->page_size );
232
 
                                                                        verboselog( device->machine, 1, "i2cmem data[ %04x to %04x ] = page\n", offset, offset + c->page_size - 1 );
233
 
 
234
 
                                                                        c->page_offset = 0;
235
 
                                                                }
236
 
                                                        }
237
 
                                                        else
238
 
                                                        {
239
 
                                                                int offset = data_offset( c );
240
 
 
241
 
                                                                c->data[ offset ] = c->shift;
242
 
                                                                verboselog( device->machine, 1, "i2cmem data[ %04x ] <- %02x\n", offset, c->data[ offset ] );
243
 
 
244
 
                                                                c->byteaddr++;
245
 
                                                        }
246
 
                                                        break;
247
 
                                                }
248
 
 
249
 
                                                c->bits++;
250
 
                                        }
251
 
                                        else
252
 
                                        {
253
 
                                                if( c->bits == 8 )
254
 
                                                {
255
 
                                                        c->sdar = 0;
256
 
                                                }
257
 
                                                else
258
 
                                                {
259
 
                                                        c->bits = 0;
260
 
                                                        c->sdar = 1;
261
 
                                                }
262
 
                                        }
263
 
                                }
264
 
                                break;
265
 
 
266
 
                        case STATE_DATAOUT:
267
 
                                if( c->bits < 8 )
268
 
                                {
269
 
                                        if( c->scl )
270
 
                                        {
271
 
                                                if( c->bits == 0 )
272
 
                                                {
273
 
                                                        int offset = data_offset( c );
274
 
 
275
 
                                                        c->shift = c->data[ offset ];
276
 
                                                        verboselog( device->machine, 1, "i2cmem data[ %04x ] -> %02x\n", offset, c->data[ offset ] );
277
 
                                                        c->byteaddr++;
278
 
                                                }
279
 
 
280
 
                                                c->sdar = ( c->shift >> 7 ) & 1;
281
 
 
282
 
                                                c->shift = ( c->shift << 1 ) & 0xff;
283
 
                                                c->bits++;
284
 
                                        }
285
 
                                }
286
 
                                else
287
 
                                {
288
 
                                        if( c->scl )
289
 
                                        {
290
 
                                                if( c->sdaw )
291
 
                                                {
292
 
                                                        verboselog( device->machine, 1, "i2cmem sleep\n");
293
 
                                                        c->state = STATE_IDLE;
294
 
                                                }
295
 
 
296
 
                                                c->bits++;
297
 
                                        }
298
 
                                        else
299
 
                                        {
300
 
                                                if( c->bits == 8 )
301
 
                                                {
302
 
                                                        c->sdar = 1;
303
 
                                                }
304
 
                                                else
305
 
                                                {
306
 
                                                        c->bits = 0;
307
 
                                                }
308
 
                                        }
309
 
                                }
310
 
                                break;
311
 
                        }
312
 
                }
313
 
                break;
314
 
 
315
 
        case I2CMEM_WC:
316
 
                if( c->wc != data )
317
 
                {
318
 
                        c->wc = data;
319
 
                        verboselog( device->machine, 2, "i2cmem_write( I2CMEM_WC, %d )\n", c->wc );
320
 
                }
321
 
                break;
322
 
 
323
 
        default:
324
 
                verboselog( device->machine, 0, "i2cmem_write( %d, %d ) invalid line\n", line, data );
325
 
                break;
326
 
        }
327
 
}
328
 
 
329
 
int i2cmemdev_read( running_device *device, int line )
330
 
{
331
 
        i2cmem_state *c = get_safe_token( device );
332
 
 
333
 
        switch( line )
334
 
        {
335
 
        case I2CMEM_SDA:
336
 
                if (c->readmode == 0)
337
 
                {
338
 
                        verboselog( device->machine, 2, "i2cmem_read( I2CMEM_SDA ) %d\n", c->sdar & c->sdaw );
339
 
                        return c->sdar & c->sdaw;
340
 
                }
341
 
                else
342
 
                {
343
 
                        verboselog( device->machine, 2, "i2cmem_read( I2CMEM_SDA ) %d\n", c->sdar );
344
 
                        return c->sdar;
345
 
                }
346
 
 
347
 
        default:
348
 
                verboselog( device->machine, 0, "i2cmem_read( %d ) invalid line\n", line );
349
 
                break;
350
 
        }
351
 
 
352
 
        return 0;
353
 
}
354
 
 
355
 
void i2cmemdev_set_read_mode( running_device *device, int mode )
356
 
{
357
 
        i2cmem_state *c = get_safe_token( device );
358
 
 
359
 
        c->readmode = mode;
360
 
}
361
 
 
362
 
/*-------------------------------------------------
363
 
    device start callback
364
 
-------------------------------------------------*/
365
 
 
366
 
static DEVICE_START( i2cmem )
367
 
{
368
 
        i2cmem_state *c = get_safe_token( device );
369
 
        const i2cmem_config *config;
370
 
        unsigned char *page = NULL;
371
 
 
372
 
        /* validate some basic stuff */
373
 
        assert( device != NULL );
374
 
        assert( device->baseconfig().inline_config != NULL );
375
 
        assert( device->machine != NULL );
376
 
        assert( device->machine->config != NULL );
377
 
 
378
 
        config = (const i2cmem_config *)device->baseconfig().inline_config;
379
 
 
380
 
        c->scl = 0;
381
 
        c->sdaw = 0;
382
 
        c->e0 = 0;
383
 
        c->e1 = 0;
384
 
        c->e2 = 0;
385
 
        c->wc = 0;
386
 
        c->sdar = 1;
387
 
        c->state = STATE_IDLE;
388
 
        c->bits = 0;
389
 
        c->shift = 0;
390
 
        c->devsel = 0;
391
 
        c->byteaddr = 0;
392
 
        c->readmode = 0;
393
 
 
394
 
        if( config != NULL )
395
 
        {
396
 
                c->data = auto_alloc_array( device->machine, UINT8, config->data_size );
397
 
                memcpy(c->data, config->data, config->data_size);
398
 
 
399
 
                if( config->page_size > 0 )
400
 
                        page = auto_alloc_array( device->machine, UINT8, config->page_size );
401
 
 
402
 
                c->slave_address = config->slave_address;
403
 
                c->data_size = config->data_size;
404
 
                c->page_size = config->page_size;
405
 
                c->page = page;
406
 
        }
407
 
 
408
 
        state_save_register_device_item( device, 0, c->scl );
409
 
        state_save_register_device_item( device, 0, c->sdaw );
410
 
        state_save_register_device_item( device, 0, c->e0 );
411
 
        state_save_register_device_item( device, 0, c->e1 );
412
 
        state_save_register_device_item( device, 0, c->e2 );
413
 
        state_save_register_device_item( device, 0, c->wc );
414
 
        state_save_register_device_item( device, 0, c->sdar );
415
 
        state_save_register_device_item( device, 0, c->state );
416
 
        state_save_register_device_item( device, 0, c->bits );
417
 
        state_save_register_device_item( device, 0, c->shift );
418
 
        state_save_register_device_item( device, 0, c->devsel );
419
 
        state_save_register_device_item( device, 0, c->byteaddr );
420
 
        state_save_register_device_item_pointer( device, 0, c->data, c->data_size );
421
 
        state_save_register_device_item( device, 0, c->readmode );
422
 
}
423
 
 
424
 
/*-------------------------------------------------
425
 
    device reset callback
426
 
-------------------------------------------------*/
427
 
 
428
 
static DEVICE_RESET( i2cmem )
429
 
{
430
 
}
431
 
 
432
 
static DEVICE_NVRAM( i2cmem )
433
 
{
434
 
        const i2cmem_config *config = (const i2cmem_config *)device->baseconfig().inline_config;
435
 
        i2cmem_state *c = get_safe_token( device );
436
 
 
437
 
        if( read_or_write )
438
 
        {
439
 
                mame_fwrite( file, c->data, c->data_size );
440
 
        }
441
 
        else if( file )
442
 
        {
443
 
                mame_fread( file, c->data, c->data_size );
444
 
        }
445
 
        else
446
 
        {
447
 
                if( config->data != NULL )
448
 
                        memcpy( c->data, config->data, config->data_size );
449
 
        }
450
 
}
451
 
 
452
 
/*-------------------------------------------------
453
 
    device get info callback
454
 
-------------------------------------------------*/
455
 
 
456
 
DEVICE_GET_INFO( i2cmem )
457
 
{
458
 
        switch ( state )
459
 
        {
460
 
                /* --- the following bits of info are returned as 64-bit signed integers --- */
461
 
                case DEVINFO_INT_TOKEN_BYTES:                   info->i = sizeof( i2cmem_state ); break;
462
 
                case DEVINFO_INT_INLINE_CONFIG_BYTES:   info->i = sizeof( i2cmem_config ); break;
463
 
                case DEVINFO_INT_CLASS:                                 info->i = DEVICE_CLASS_PERIPHERAL; break;
464
 
 
465
 
                /* --- the following bits of info are returned as pointers to data or functions --- */
466
 
                case DEVINFO_FCT_START:                                 info->start = DEVICE_START_NAME( i2cmem ); break;
467
 
                case DEVINFO_FCT_STOP:                                  /* nothing */ break;
468
 
                case DEVINFO_FCT_RESET:                                 info->reset = DEVICE_RESET_NAME( i2cmem ); break;
469
 
                case DEVINFO_FCT_NVRAM:                                 info->nvram = DEVICE_NVRAM_NAME( i2cmem ); break;
470
 
 
471
 
                /* --- the following bits of info are returned as NULL-terminated strings --- */
472
 
                case DEVINFO_STR_NAME:                                  strcpy( info->s, "I2CMEM" ); break;
473
 
                case DEVINFO_STR_FAMILY:                                strcpy( info->s, "EEPROM" ); break;
474
 
                case DEVINFO_STR_VERSION:                               strcpy( info->s, "1.0" ); break;
475
 
                case DEVINFO_STR_SOURCE_FILE:                   strcpy( info->s, __FILE__ ); break;
476
 
                case DEVINFO_STR_CREDITS:                               strcpy( info->s, "Copyright Nicola Salmoria and the MAME Team" ); break;
477
 
        }
478
 
}