4
Generic ram/rom/eeprom/flash on an i2c bus. Supports specifying the slave address,
5
the data size & the page size for writing.
8
e0,e1,e2 lower 3 bits of the slave address
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.
23
#include "machine/i2cmemdev.h"
25
#define VERBOSE_LEVEL ( 0 )
27
INLINE void ATTR_PRINTF(3,4) verboselog( running_machine *machine, int n_level, const char *s_fmt, ... )
29
if( VERBOSE_LEVEL >= n_level )
34
vsprintf( buf, s_fmt, v );
36
logerror( "%s: %s", cpuexec_describe_context(machine), buf );
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 )
46
#define DEVSEL_RW ( 1 )
47
#define DEVSEL_ADDRESS ( 0xfe )
49
typedef struct _i2cmem_state i2cmem_state;
73
/*-------------------------------------------------
74
get_safe_token - makes sure that the passed
75
in device is, in fact, an I2C memory
76
-------------------------------------------------*/
78
INLINE i2cmem_state *get_safe_token( running_device *device )
80
assert( device != NULL );
81
assert( device->token != NULL );
82
assert( device->type == I2CMEM );
84
return (i2cmem_state *)device->token;
87
static int select_device( i2cmem_state *c )
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 );
92
if( ( c->devsel & mask ) == ( device & mask ) )
100
static int data_offset( i2cmem_state *c )
102
return ( ( ( c->devsel << 7 ) & 0xff00 ) | ( c->byteaddr & 0xff ) ) & ( c->data_size - 1 );
105
void i2cmemdev_write( running_device *device, int line, int data )
107
i2cmem_state *c = get_safe_token( device );
115
verboselog( device->machine, 2, "i2cmem_write( I2CMEM_E0, %d )\n", c->e0 );
123
verboselog( device->machine, 2, "i2cmem_write( I2CMEM_E1, %d )\n", c->e1 );
131
verboselog( device->machine, 2, "i2cmem_write( I2CMEM_E2, %d )\n", c->e2 );
136
if( c->sdaw != data )
139
verboselog( device->machine, 2, "i2cmem_write( I2CMEM_SDA, %d )\n", c->sdaw );
145
verboselog( device->machine, 1, "i2cmem stop\n");
146
c->state = STATE_IDLE;
151
verboselog( device->machine, 2, "i2cmem start\n");
152
c->state = STATE_DEVSEL;
165
verboselog( device->machine, 2, "i2cmem_write( I2CMEM_SCL, %d )\n", c->scl );
176
c->shift = ( ( c->shift << 1 ) | c->sdaw ) & 0xff;
187
c->devsel = c->shift;
189
if( !select_device( c ) )
191
verboselog( device->machine, 1, "i2cmem devsel %02x: not this device\n", c->devsel );
192
c->state = STATE_IDLE;
194
else if( ( c->devsel & DEVSEL_RW ) == 0 )
196
verboselog( device->machine, 1, "i2cmem devsel %02x: write\n", c->devsel );
197
c->state = STATE_BYTEADDR;
201
verboselog( device->machine, 1, "i2cmem devsel %02x: read\n", c->devsel );
202
c->state = STATE_DATAOUT;
207
c->byteaddr = c->shift;
210
verboselog( device->machine, 1, "i2cmem byteaddr %02x\n", c->byteaddr );
212
c->state = STATE_DATAIN;
218
verboselog( device->machine, 0, "i2cmem write not enabled\n");
219
c->state = STATE_IDLE;
221
else if( c->page_size > 0 )
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 ] );
227
if( c->page_offset == c->page_size )
229
int offset = data_offset( c ) & ~( c->page_size - 1 );
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 );
239
int offset = data_offset( c );
241
c->data[ offset ] = c->shift;
242
verboselog( device->machine, 1, "i2cmem data[ %04x ] <- %02x\n", offset, c->data[ offset ] );
273
int offset = data_offset( c );
275
c->shift = c->data[ offset ];
276
verboselog( device->machine, 1, "i2cmem data[ %04x ] -> %02x\n", offset, c->data[ offset ] );
280
c->sdar = ( c->shift >> 7 ) & 1;
282
c->shift = ( c->shift << 1 ) & 0xff;
292
verboselog( device->machine, 1, "i2cmem sleep\n");
293
c->state = STATE_IDLE;
319
verboselog( device->machine, 2, "i2cmem_write( I2CMEM_WC, %d )\n", c->wc );
324
verboselog( device->machine, 0, "i2cmem_write( %d, %d ) invalid line\n", line, data );
329
int i2cmemdev_read( running_device *device, int line )
331
i2cmem_state *c = get_safe_token( device );
336
if (c->readmode == 0)
338
verboselog( device->machine, 2, "i2cmem_read( I2CMEM_SDA ) %d\n", c->sdar & c->sdaw );
339
return c->sdar & c->sdaw;
343
verboselog( device->machine, 2, "i2cmem_read( I2CMEM_SDA ) %d\n", c->sdar );
348
verboselog( device->machine, 0, "i2cmem_read( %d ) invalid line\n", line );
355
void i2cmemdev_set_read_mode( running_device *device, int mode )
357
i2cmem_state *c = get_safe_token( device );
362
/*-------------------------------------------------
363
device start callback
364
-------------------------------------------------*/
366
static DEVICE_START( i2cmem )
368
i2cmem_state *c = get_safe_token( device );
369
const i2cmem_config *config;
370
unsigned char *page = NULL;
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 );
378
config = (const i2cmem_config *)device->baseconfig().inline_config;
387
c->state = STATE_IDLE;
396
c->data = auto_alloc_array( device->machine, UINT8, config->data_size );
397
memcpy(c->data, config->data, config->data_size);
399
if( config->page_size > 0 )
400
page = auto_alloc_array( device->machine, UINT8, config->page_size );
402
c->slave_address = config->slave_address;
403
c->data_size = config->data_size;
404
c->page_size = config->page_size;
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 );
424
/*-------------------------------------------------
425
device reset callback
426
-------------------------------------------------*/
428
static DEVICE_RESET( i2cmem )
432
static DEVICE_NVRAM( i2cmem )
434
const i2cmem_config *config = (const i2cmem_config *)device->baseconfig().inline_config;
435
i2cmem_state *c = get_safe_token( device );
439
mame_fwrite( file, c->data, c->data_size );
443
mame_fread( file, c->data, c->data_size );
447
if( config->data != NULL )
448
memcpy( c->data, config->data, config->data_size );
452
/*-------------------------------------------------
453
device get info callback
454
-------------------------------------------------*/
456
DEVICE_GET_INFO( i2cmem )
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;
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;
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;