Previous 15994 Revisions Next

r8474 Monday 12th July, 2010 at 06:32:54 UTC by Miodrag Milanović
whoops forgot to remove this
[src/emu]emu.mak
[src/emu/machine]i2cmemdev.c i2cmemdev.h

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

Previous 15994 Revisions Next


© 1998-2018 The MESS Team