summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/machine/ds2401.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/machine/ds2401.c')
-rw-r--r--src/emu/machine/ds2401.c272
1 files changed, 272 insertions, 0 deletions
diff --git a/src/emu/machine/ds2401.c b/src/emu/machine/ds2401.c
new file mode 100644
index 00000000000..baa987a7e19
--- /dev/null
+++ b/src/emu/machine/ds2401.c
@@ -0,0 +1,272 @@
+/*
+ * DS2401
+ *
+ * Dallas Semiconductor
+ * Silicon Serial Number
+ *
+ */
+
+#include <stdarg.h>
+#include "driver.h"
+#include "state.h"
+#include "machine/ds2401.h"
+
+#define VERBOSE_LEVEL ( 0 )
+
+INLINE void verboselog( int n_level, const char *s_fmt, ... )
+{
+ if( VERBOSE_LEVEL >= n_level )
+ {
+ va_list v;
+ char buf[ 32768 ];
+ va_start( v, s_fmt );
+ vsprintf( buf, s_fmt, v );
+ va_end( v );
+ if( cpu_getactivecpu() != -1 )
+ {
+ logerror( "%08x: %s", activecpu_get_pc(), buf );
+ }
+ else
+ {
+ logerror( "(timer) : %s", buf );
+ }
+ }
+}
+
+struct ds2401_chip
+{
+ int state;
+ int bit;
+ int byte;
+ int shift;
+ int rx;
+ int tx;
+ UINT8 *data;
+ emu_timer *timer;
+ emu_timer *reset_timer;
+ attotime t_samp;
+ attotime t_rdv;
+ attotime t_rstl;
+ attotime t_pdh;
+ attotime t_pdl;
+};
+
+#define SIZE_DATA ( 8 )
+
+#define STATE_IDLE ( 0 )
+#define STATE_RESET ( 1 )
+#define STATE_RESET1 ( 2 )
+#define STATE_RESET2 ( 3 )
+#define STATE_COMMAND ( 4 )
+#define STATE_READROM ( 5 )
+
+#define COMMAND_READROM ( 0x33 )
+
+static struct ds2401_chip ds2401[ DS2401_MAXCHIP ];
+
+static TIMER_CALLBACK( ds2401_reset )
+{
+ int which = param;
+ struct ds2401_chip *c = &ds2401[ which ];
+
+ verboselog( 1, "ds2401_reset(%d)\n", which );
+
+ c->state = STATE_RESET;
+ timer_adjust( c->timer, attotime_never, which, attotime_never );
+}
+
+static TIMER_CALLBACK( ds2401_tick )
+{
+ int which = param;
+ struct ds2401_chip *c = &ds2401[ which ];
+
+ switch( c->state )
+ {
+ case STATE_RESET1:
+ verboselog( 2, "ds2401_tick(%d) state_reset1 %d\n", which, c->rx );
+ c->tx = 0;
+ c->state = STATE_RESET2;
+ timer_adjust( c->timer, c->t_pdl, which, attotime_never );
+ break;
+ case STATE_RESET2:
+ verboselog( 2, "ds2401_tick(%d) state_reset2 %d\n", which, c->rx );
+ c->tx = 1;
+ c->bit = 0;
+ c->shift = 0;
+ c->state = STATE_COMMAND;
+ break;
+ case STATE_COMMAND:
+ verboselog( 2, "ds2401_tick(%d) state_command %d\n", which, c->rx );
+ c->shift >>= 1;
+ if( c->rx != 0 )
+ {
+ c->shift |= 0x80;
+ }
+ c->bit++;
+ if( c->bit == 8 )
+ {
+ switch( c->shift )
+ {
+ case COMMAND_READROM:
+ verboselog( 1, "ds2401_tick(%d) readrom\n", which );
+ c->bit = 0;
+ c->byte = 0;
+ c->state = STATE_READROM;
+ break;
+ default:
+ verboselog( 0, "ds2401_tick(%d) command not handled %02x\n", which, c->shift );
+ c->state = STATE_IDLE;
+ break;
+ }
+ }
+ break;
+ case STATE_READROM:
+ c->tx = 1;
+ if( c->byte == 8 )
+ {
+ verboselog( 1, "ds2401_tick(%d) readrom finished\n", which );
+ c->state = STATE_IDLE;
+ }
+ else
+ {
+ verboselog( 2, "ds2401_tick(%d) readrom window closed\n", which );
+ }
+ break;
+ default:
+ verboselog( 0, "ds2401_tick(%d) state not handled: %d\n", which, c->state );
+ break;
+ }
+}
+
+void ds2401_init( int which, UINT8 *data )
+{
+ struct ds2401_chip *c = &ds2401[ which ];
+
+ if( data == NULL )
+ {
+ data = auto_malloc( SIZE_DATA );
+ }
+
+ c->state = STATE_IDLE;
+ c->bit = 0;
+ c->byte = 0;
+ c->shift = 0;
+ c->rx = 1;
+ c->tx = 1;
+ c->data = data;
+ c->t_samp = ATTOTIME_IN_USEC( 15 );
+ c->t_rdv = ATTOTIME_IN_USEC( 15 );
+ c->t_rstl = ATTOTIME_IN_USEC( 480 );
+ c->t_pdh = ATTOTIME_IN_USEC( 15 );
+ c->t_pdl = ATTOTIME_IN_USEC( 60 );
+
+ state_save_register_item( "ds2401", which, c->state );
+ state_save_register_item( "ds2401", which, c->bit );
+ state_save_register_item( "ds2401", which, c->byte );
+ state_save_register_item( "ds2401", which, c->shift );
+ state_save_register_item( "ds2401", which, c->rx );
+ state_save_register_item( "ds2401", which, c->tx );
+ state_save_register_item_pointer( "ds2401", which, data, SIZE_DATA );
+
+ c->timer = timer_alloc( ds2401_tick );
+ c->reset_timer = timer_alloc( ds2401_reset );
+}
+
+void ds2401_write( int which, int data )
+{
+ struct ds2401_chip *c = &ds2401[ which ];
+
+ verboselog( 1, "ds2401_write( %d, %d )\n", which, data );
+
+ if( data == 0 && c->rx != 0 )
+ {
+ switch( c->state )
+ {
+ case STATE_IDLE:
+ break;
+ case STATE_COMMAND:
+ verboselog( 2, "ds2401_write(%d) state_command\n", which );
+ timer_adjust( c->timer, c->t_samp, which, attotime_never );
+ break;
+ case STATE_READROM:
+ if( c->bit == 0 )
+ {
+ c->shift = c->data[ 7 - c->byte ];
+ verboselog( 1, "ds2401_write(%d) <- data %02x\n", which, c->shift );
+ }
+ c->tx = c->shift & 1;
+ c->shift >>= 1;
+ c->bit++;
+ if( c->bit == 8 )
+ {
+ c->bit = 0;
+ c->byte++;
+ }
+ verboselog( 2, "ds2401_write(%d) state_readrom %d\n", which, c->tx );
+ timer_adjust( c->timer, c->t_rdv, which, attotime_never );
+ break;
+ default:
+ verboselog( 0, "ds2401_write(%d) state not handled: %d\n", which, c->state );
+ break;
+ }
+ timer_adjust( c->reset_timer, c->t_rstl, which, attotime_never );
+ }
+ else if( data == 1 && c->rx == 0 )
+ {
+ switch( c->state )
+ {
+ case STATE_RESET:
+ c->state = STATE_RESET1;
+ timer_adjust( c->timer, c->t_pdh, which, attotime_never );
+ break;
+ }
+ timer_adjust( c->reset_timer, attotime_never, which, attotime_never );
+ }
+ c->rx = data;
+}
+
+int ds2401_read( int which )
+{
+ struct ds2401_chip *c = &ds2401[ which ];
+
+ verboselog( 2, "ds2401_read( %d ) %d\n", which, c->tx & c->rx );
+ return c->tx & c->rx;
+}
+
+/*
+
+app74.pdf
+
+Under normal circumstances an ibutton will sample the line 30us after the falling edge of the start condition.
+The internal time base of ibutton may deviate from its nominal value. The allowed tollerance band ranges from 15us to 60us.
+This means that the actual slave sampling may occur anywhere from 15 and 60us after the start condition, which is a ratio of 1 to 4.
+During this time frame the voltage on the data line must stay below Vilmax or above Vihmin.
+
+In the 1-Wire system, the logical values 1 and 0 are represented by certain voltages in special waveforms.
+The waveforms needed to write commands or data to ibuttons are called write-1 and write-0 time slots.
+The duration of a low pulse to write a 1 must be shorter than 15us.
+To write a 0, the duration of the low pulse must be at least 60us to cope with worst-case conditions.
+
+The duration of the active part of a time slot can be extended beyond 60us.
+The maximum extension is limited by the fact that a low pulse of a duration of at least eight active time slots ( 480us ) is defined as a Reset Pulse.
+Allowing the same worst-case tolerance ratio, a low pulse of 120us might be sufficient for a reset.
+This limits the extension of the active part of a time slot to a maximum of 120us to prevent misinterpretation with reset.
+
+Commands and data are sent to ibuttons by combining write-0 and write-1 time slots.
+To read data, the master has to generate read-data time slots to define the start condition of each bit.
+The read-data time slots looks essentially the same as a write-1 time slot from the masters point of view.
+Starting at the high-to-low transition, the ibuttons sends 1 bit of its addressed contents.
+If the data bit is a 1, the ibutton leaves the pulse unchanged.
+If the data bit is a 0, the ibutton will pull the data line low for 15us.
+In this time frame data is valid for reading by the master.
+The duration of the low pulse sent by the master should be a minimum of 1us with a maximum value as short as possible to maximize the master sampling window.
+
+The Reset Pulse provides a clear starting condition that supersedes any time slot synchronisation.
+It is defined as single low pulse of minimum duration of eight time slots or 480us followed by a Reset-high time tRSTH of another 480us.
+After a Reset Pulse has been sent, the ibutton will wait for the time tPDH and then generate a Pulse-Presence Pulse of duration tPDL.
+No other communication on the 1-Wire bus is allowed during tRSTH.
+
+There are 1,000 microseconds in a millisecond, and 1,000 milliseconds in a second.
+Thus, there are 1,000,000 microseconds in a second. Why is it "usec"?
+The "u" is supposed to look like the Greek letter Mu that we use for "micro". .
+*/