summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/mc6843.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/mc6843.cpp')
-rw-r--r--src/devices/machine/mc6843.cpp1493
1 files changed, 800 insertions, 693 deletions
diff --git a/src/devices/machine/mc6843.cpp b/src/devices/machine/mc6843.cpp
index 74945094b40..caf637c2eb3 100644
--- a/src/devices/machine/mc6843.cpp
+++ b/src/devices/machine/mc6843.cpp
@@ -1,835 +1,942 @@
// license:BSD-3-Clause
-// copyright-holders:Antoine Mine
-/**********************************************************************
-
- Copyright (C) Antoine Mine' 2007
-
- Motorola 6843 Floppy Disk Controller emulation.
-
-**********************************************************************/
-
-/*
- Main MC 6843 features are:
- - single density floppies
- - IBM 3740 compatible
- - DMA-able
- - high-level commands (including multi-sector read/write)
-
- CLONES: HD 46503S seems to be a clone of MC 6843
-
- BUGS
- The driver was designed with Thomson computer emulation in mind
- (CD 90-015 5"1/4 floppy controller) and works in this context.
- It might work in other contexts but has currently shortcomings:
- - DMA is not emulated
- - Free-Format Read is not emulated
- - Free-Format Write only supports track formatting, in a specific
- format (FWF=1, Thomson-like sector formats)
- - very rough timing: basically, there is a fixed delay between
- a command request (CMR write) and its response (first byte
- available, seek complete, etc.); there is no delay between
- read / write
- */
+// copyright-holders:Olivier Galibert
+// Not implemented for lack of test cases: FFR
#include "emu.h"
#include "mc6843.h"
-//#define VERBOSE 1
-#include "logmacro.h"
-
-
-/******************* parameters ******************/
-
-/* macro-command numbers */
-#define CMD_STZ 0x2 /* seek track zero */
-#define CMD_SEK 0x3 /* seek */
-#define CMD_SSR 0x4 /* single sector read */
-#define CMD_SSW 0x5 /* single sector write */
-#define CMD_RCR 0x6 /* read CRC */
-#define CMD_SWD 0x7 /* single sector write with delete data mark */
-#define CMD_MSW 0xd /* multiple sector write */
-#define CMD_MSR 0xc /* multiple sector read */
-#define CMD_FFW 0xb /* free format write */
-#define CMD_FFR 0xa /* free format read */
-
-/* coarse delays */
-#define DELAY_SEEK attotime::from_usec( 100 ) /* track seek time */
-#define DELAY_ADDR attotime::from_usec( 100 ) /* search-address time */
-#define DELAY_CRC attotime::from_usec( 64 ) /* read crc time */
-
-
-
-static const char *const mc6843_cmd[16] =
-{
- "---", "---", "STZ", "SEK", "SSR", "SSW", "RCR", "SWD",
- "---", "---", "FFR", "FFW", "MSR", "MSW", "---", "---",
-};
-
-
-
-
DEFINE_DEVICE_TYPE(MC6843, mc6843_device, "mc6843", "Motorola MC6843 FDC")
mc6843_device::mc6843_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, MC6843, tag, owner, clock),
- m_floppy(*this, {finder_base::DUMMY_TAG, finder_base::DUMMY_TAG, finder_base::DUMMY_TAG, finder_base::DUMMY_TAG}),
- m_write_irq(*this),
- m_CTAR(0),
- m_CMR(0),
- m_ISR(0),
- m_SUR(0),
- m_STRA(0),
- m_STRB(0),
- m_SAR(0),
- m_GCR(0),
- m_CCR(0),
- m_LTAR(0),
- m_drive(0),
- m_side(0),
- m_data_size(0),
- m_data_idx(0),
- m_data_id(0),
- m_index_pulse(0),
- m_crc_wait(0),
- m_timer_cont(nullptr)
-{
- for (auto & elem : m_data)
- {
- elem = 0;
- }
+ m_irq(*this),
+ m_force_ready(false)
+{
}
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
void mc6843_device::device_start()
{
- m_write_irq.resolve_safe();
-
- m_timer_cont = timer_alloc(TIMER_CONT);
-
- save_item(NAME(m_CTAR));
- save_item(NAME(m_CMR));
- save_item(NAME(m_ISR));
- save_item(NAME(m_SUR));
- save_item(NAME(m_STRA));
- save_item(NAME(m_STRB));
- save_item(NAME(m_SAR));
- save_item(NAME(m_GCR));
- save_item(NAME(m_CCR));
- save_item(NAME(m_LTAR));
- save_item(NAME(m_drive));
- save_item(NAME(m_side));
- save_item(NAME(m_data));
- save_item(NAME(m_data_size));
- save_item(NAME(m_data_idx));
- save_item(NAME(m_data_id));
- save_item(NAME(m_crc_wait));
-}
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
+ m_irq.resolve_safe();
+ m_timer = timer_alloc(0);
+ m_floppy = nullptr;
+
+ m_dir = 0x00;
+ m_dor = 0x00;
+ m_ctar = 0x00;
+ m_sur = 0x00;
+ m_cmr = 0x00;
+ m_gcr = 0x00;
+ m_ccr = 0x00;
+ m_ltar = 0x00;
+
+ save_item(NAME(m_dir));
+ save_item(NAME(m_dor));
+ save_item(NAME(m_ctar));
+ save_item(NAME(m_cmr));
+ save_item(NAME(m_isr));
+ save_item(NAME(m_sur));
+ save_item(NAME(m_stra));
+ save_item(NAME(m_sar));
+ save_item(NAME(m_strb));
+ save_item(NAME(m_gcr));
+ save_item(NAME(m_ccr));
+ save_item(NAME(m_ltar));
+ save_item(NAME(m_state));
+ save_item(NAME(m_step_count));
+ save_item(NAME(m_head_loaded));
+ save_item(NAME(m_dir_loaded));
+ save_item(NAME(m_dor_loaded));
+ save_item(NAME(m_dor_needed));
+ save_item(NAME(m_idam_turns));
+}
void mc6843_device::device_reset()
{
- LOG (( "mc6843 reset\n" ));
+ m_state = S_IDLE;
+ m_cur_live.state = L_IDLE;
+ m_cur_live.tm = attotime::never;
- /* setup/reset floppy drive */
- for (auto &img : m_floppy)
- {
- if (img.found())
- {
- img->floppy_mon_w(CLEAR_LINE);
- img->floppy_drive_set_ready_state(FLOPPY_DRIVE_READY, 0 );
- img->floppy_drive_set_rpm( 300. );
- }
- }
+ m_step_count = 0;
+ m_head_loaded = false;
- /* reset registers */
- m_CMR &= 0xf0; /* zero only command */
- m_ISR = 0;
- m_STRA &= 0x5c;
- m_SAR = 0;
- m_STRB &= 0x20;
- status_update( );
-
- m_data_size = 0;
- m_data_idx = 0;
- m_crc_wait = 0;
- m_timer_cont->adjust( attotime::never );
-}
-
-/************************** floppy interface ****************************/
+ m_dir_loaded = false;
+ m_dor_loaded = false;
+ m_dor_needed = false;
+ m_idam_turns = 0;
+ m_cmr &= 0xf0;
+ m_isr = 0x00;
+ m_stra = 0x00;
+ m_sar = 0x00;
+ m_strb = 0x00;
+}
-legacy_floppy_image_device* mc6843_device::floppy_image( )
+void mc6843_device::map(address_map &map)
{
- assert(m_floppy[m_drive].found());
- return m_floppy[m_drive].target();
+ map(0, 0).rw(FUNC(mc6843_device::dir_r), FUNC(mc6843_device::dor_w));
+ map(1, 1).rw(FUNC(mc6843_device::ctar_r), FUNC(mc6843_device::ctar_w));
+ map(2, 2).rw(FUNC(mc6843_device::isr_r), FUNC(mc6843_device::cmr_w));
+ map(3, 3).rw(FUNC(mc6843_device::stra_r), FUNC(mc6843_device::sur_w));
+ map(4, 4).rw(FUNC(mc6843_device::strb_r), FUNC(mc6843_device::sar_w));
+ map(5, 5).w (FUNC(mc6843_device::gcr_w));
+ map(6, 6).w (FUNC(mc6843_device::ccr_w));
+ map(7, 7).w (FUNC(mc6843_device::ltar_w));
}
-
-void mc6843_device::set_drive( int drive )
+void mc6843_device::set_floppy(floppy_image_device *floppy)
{
- m_drive = drive;
-}
+ if(m_floppy == floppy)
+ return;
+ int prev_ready = m_floppy ? m_floppy->ready_r() : 1;
+ if(m_floppy) {
+ m_floppy->setup_index_pulse_cb(floppy_image_device::index_pulse_cb());
+ m_floppy->setup_ready_cb(floppy_image_device::ready_cb());
+ }
-void mc6843_device::set_side( int side )
-{
- m_side = side;
-}
+ m_floppy = floppy;
+ logerror("floppy %s\n", m_floppy ? m_floppy->tag() : "-");
+ int next_ready = m_floppy ? m_floppy->ready_r() : 1;
-/* called after ISR or STRB has changed */
-void mc6843_device::status_update( )
-{
- int irq = 0;
+ if(m_floppy) {
+ m_floppy->setup_index_pulse_cb(floppy_image_device::index_pulse_cb(&mc6843_device::index_callback, this));
+ m_floppy->setup_ready_cb(floppy_image_device::ready_cb(&mc6843_device::ready_callback, this));
+ }
- /* ISR3 */
- if ( (m_CMR & 0x40) || ! m_STRB )
- m_ISR &= ~8;
- else
- m_ISR |= 8;
+ if(prev_ready != next_ready)
+ ready_callback(m_floppy, next_ready);
+}
- /* interrupts */
- if ( m_ISR & 4 )
- irq = 1; /* unmaskable */
- if ( ! (m_CMR & 0x80) )
- {
- /* maskable */
- if ( m_ISR & ~4 )
- irq = 1;
+u8 mc6843_device::dir_r()
+{
+ if(!machine().side_effects_disabled()) {
+ m_dir_loaded = false;
+ logerror("dir_r %02x\n", m_dir);
}
-
- m_write_irq( irq );
- LOG( "status_update: irq=%i (CMR=%02X, ISR=%02X)\n", irq, m_CMR, m_ISR );
+ return m_dir;
}
+void mc6843_device::dor_w(u8 data)
+{
+ m_dor = data;
+ m_dor_loaded = true;
+ logerror("dor_w %02x\n", m_dor);
+}
-void mc6843_device::set_index_pulse( int index_pulse )
+u8 mc6843_device::ctar_r()
{
- m_index_pulse = index_pulse;
+ if(!machine().side_effects_disabled())
+ logerror("ctar_r %02x\n", m_ctar);
+ return m_ctar;
}
+void mc6843_device::ctar_w(u8 data)
+{
+ m_ctar = data;
+ logerror("ctar_w %02x\n", m_ctar);
+}
-/* called at end of command */
-void mc6843_device::cmd_end( )
+void mc6843_device::isr_raise(u8 flag)
{
- int cmd = m_CMR & 0x0f;
+ m_isr |= flag;
+}
- if ( ( cmd == CMD_STZ ) || ( cmd == CMD_SEK ) )
- {
- m_ISR |= 0x02; /* set Settling Time Complete */
- }
- else
- {
- m_ISR |= 0x01; /* set Macro Command Complete */
+u8 mc6843_device::isr_r()
+{
+ u8 res = m_isr;
+ if(!machine().side_effects_disabled()) {
+ logerror("isr_r %02x\n", m_isr);
+ m_isr &= 0x8;
}
- m_STRA &= ~0x80; /* clear Busy */
- m_CMR &= 0xf0; /* clear command */
- status_update( );
+ return res;
}
-
-
-/* Seek Track Zero bottom half */
-void mc6843_device::finish_STZ( )
+void mc6843_device::cmr_w(u8 data)
{
- legacy_floppy_image_device* img = floppy_image( );
- int i;
-
- /* seek to track zero */
- for ( i=0; i<83; i++ )
- {
- if (img->floppy_tk00_r() == CLEAR_LINE)
- break;
- img->floppy_drive_seek( -1 );
+ static const char *cmds[0x10] = {
+ "nop", "?1",
+ "stz", "sek", "ssr", "ssw", "rcr", "swd",
+ "?8", "?9",
+ "ffr", "ffw", "msr", "msw",
+ "?e", "?f"
+ };
+
+ if(m_stra & SA_BUSY) {
+ if((data & 0xf) == 0 && (m_cmr & 0xf) == C_FFW) {
+ m_stra &= ~SA_BUSY;
+ live_abort();
+ m_state = S_IDLE;
+ } else {
+ logerror("cmr_w %02x - dropped busy\n", data);
+ return;
+ }
}
- LOG( "%f mc6843_finish_STZ: actual=%i\n", machine().time().as_double(), img->floppy_drive_get_current_track() );
-
- /* update state */
- m_CTAR = 0;
- m_GCR = 0;
- m_SAR = 0;
- m_STRB |= img->floppy_tk00_r() << 4;
-
- cmd_end( );
+ m_cmr = data;
+ logerror("cmr_w %02x - isr=%s isr3=%s %s fwf=%d %s\n", m_cmr,
+ m_cmr & 0x80 ? "off" : "on",
+ m_cmr & 0x40 ? "off" : "on",
+ m_cmr & 0x20 ? "dma" : "pio",
+ m_cmr & 0x10 ? 1 : 0,
+ cmds[m_cmr & 0xf]);
+ command_start();
}
-
-
-/* Seek bottom half */
-void mc6843_device::finish_SEK( )
+u8 mc6843_device::stra_r()
{
- legacy_floppy_image_device* img = floppy_image( );
+ u8 res = m_stra;
+ if(m_floppy) {
+ if(m_floppy->idx_r())
+ res |= SA_IDX;
+ if(m_floppy->wpt_r())
+ res |= SA_WPT;
+ if(!m_floppy->trk00_r())
+ res |= SA_TRK0;
+ }
+ if(is_ready())
+ res |= SA_RDY;
- /* seek to track */
- // TODO: not sure how CTAR bit 7 is handled here, but this is the safest approach for now
- img->floppy_drive_seek( m_GCR - (m_CTAR & 0x7F) );
+ switch(m_cmr & 0xf) {
+ case C_SSR: case C_MSR: case C_FFR:
+ if(m_dir_loaded)
+ res |= SA_DTR;
+ break;
+ case C_SSW: case C_SWD: case C_MSW: case C_FFW:
+ if(!m_dor_loaded && m_dor_needed)
+ res |= SA_DTR;
+ break;
+ }
- LOG( "%f mc6843_finish_SEK: from %i to %i (actual=%i)\n", machine().time().as_double(), (m_CTAR & 0x7F), m_GCR, img->floppy_drive_get_current_track() );
+ if(!machine().side_effects_disabled()) {
+ static int prev = -1;
+ if(prev != res) {
+ logerror("stra_r %02x -%s%s%s%s%s%s%s%s\n", res,
+ res & SA_BUSY ? " busy" : "",
+ res & SA_IDX ? " idx" : "",
+ res & SA_TNEQ ? " tneq" : "",
+ res & SA_WPT ? " wpt" : "",
+ res & SA_TRK0 ? " trk0" : "",
+ res & SA_RDY ? " rdy" : "",
+ res & SA_DDM ? " ddm" : "",
+ res & SA_DTR ? " dtr" : "");
+ prev = res;
+ }
+ }
+ return res;
+}
- /* update state */
- m_CTAR = m_GCR;
- m_SAR = 0;
- cmd_end( );
+void mc6843_device::sur_w(u8 data)
+{
+ m_sur = data;
+ logerror("sur_w %02x\n", m_sur);
}
+u8 mc6843_device::strb_r()
+{
+ if(!machine().side_effects_disabled()) {
+ logerror("strb_r %02x -%s%s%s%s%s%s%s%s\n", m_strb,
+ m_strb & SB_HERR ? " herr" : "",
+ m_strb & SB_WERR ? " werr" : "",
+ m_strb & SB_FI ? " fi" : "",
+ m_strb & SB_SERR ? " serr" : "",
+ m_strb & SB_SAERR ? " saerr" : "",
+ m_strb & SB_DMERR ? " dmerr" : "",
+ m_strb & SB_CRC ? " crc" : "",
+ m_strb & SB_DTERR ? " dterr" : "");
+ }
+ return m_strb;
+}
+void mc6843_device::sar_w(u8 data)
+{
+ m_sar = data & 0x1f;
+ logerror("sar_w %02x\n", m_sar);
+}
-/* preamble to all sector read / write commands, returns 1 if found */
-int mc6843_device::address_search( chrn_id* id )
+void mc6843_device::gcr_w(u8 data)
{
- legacy_floppy_image_device* img = floppy_image( );
- int r = 0;
+ m_gcr = data & 0x7f;
+ logerror("gcr_w %02x\n", m_gcr);
+}
- while ( 1 )
- {
- if ( ( ! img->floppy_drive_get_next_id( m_side, id ) ) || ( id->flags & ID_FLAG_CRC_ERROR_IN_ID_FIELD ) || ( id->N != 0 ) )
- {
- /* read address error */
- LOG( "%f mc6843_address_search: get_next_id failed\n", machine().time().as_double() );
- m_STRB |= 0x0a; /* set CRC error & Sector Address Undetected */
- cmd_end( );
- return 0;
- }
+void mc6843_device::ccr_w(u8 data)
+{
+ m_ccr = data & 3;
+ logerror("ccr_w %02x\n", m_ccr);
+}
- if ( id->C != m_LTAR )
- {
- /* track mismatch */
- LOG( "%f mc6843_address_search: track mismatch: logical=%i real=%i\n", machine().time().as_double(), m_LTAR, id->C );
- m_data[0] = id->C; /* make the track number available to the CPU */
- m_STRA |= 0x20; /* set Track Not Equal */
- cmd_end( );
- return 0;
- }
+void mc6843_device::ltar_w(u8 data)
+{
+ m_ltar = data & 0x7f;
+ logerror("ltar_w %02x\n", m_ltar);
+}
- if ( id->R == m_SAR )
- {
- /* found! */
- LOG( "%f mc6843_address_search: sector %i found on track %i\n", machine().time().as_double(), id->R, id->C );
- if ( ! (m_CMR & 0x20) )
- {
- m_ISR |= 0x04; /* if no DMA, set Status Sense */
+void mc6843_device::index_callback(floppy_image_device *floppy, int state)
+{
+ if(state) {
+ live_sync();
+ logerror("idam %d\n", m_idam_turns);
+ if(m_idam_turns) {
+ m_idam_turns --;
+ if(!m_idam_turns) {
+ live_abort();
+ m_state = S_IDAM_NOT_FOUND;
}
- return 1;
}
+ run(false, false, true);
+ }
+}
- if ( img->floppy_drive_get_flag_state( FLOPPY_DRIVE_INDEX ) )
- {
- r++;
- if ( r >= 4 )
- {
- /* time-out after 3 full revolutions */
- LOG( "%f mc6843_address_search: no sector %i found after 3 revolutions\n", machine().time().as_double(), m_SAR );
- m_STRB |= 0x08; /* set Sector Address Undetected */
- cmd_end( );
- return 0;
- }
- }
+void mc6843_device::ready_callback(floppy_image_device *floppy, int state)
+{
+ if(state) {
+ live_sync();
+ run(false, true, false);
}
+}
- //return 0; /* unreachable */
+void mc6843_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ live_sync();
+ run(true, false, false);
}
+void mc6843_device::command_start()
+{
+ assert(m_state == S_IDLE);
+ switch(m_cmr & 0xf) {
+
+ case C_STZ:
+ logerror("Seek to track 0\n");
+ if(m_floppy)
+ m_floppy->dir_w(1);
+ m_stra |= SA_BUSY;
+ m_step_count = 82;
+ m_state = S_STZ_STEP;
+ break;
+ case C_SEK:
+ logerror("Seek from track %d to %d\n", m_ctar, m_gcr);
+ if(m_gcr > m_ctar) {
+ if(m_floppy)
+ m_floppy->dir_w(0);
+ m_step_count = m_gcr - m_ctar;
+ } else {
+ if(m_floppy)
+ m_floppy->dir_w(1);
+ m_step_count = m_ctar - m_gcr;
+ }
+ m_stra |= SA_BUSY;
+ if(!m_step_count) {
+ m_state = S_SEEK_HEAD_SETTLING;
+ delay(4096 * (m_sur & 15));
+ } else
+ m_state = S_SEEK_STEP;
+ break;
-/* preamble specific to read commands (adds extra checks) */
-int mc6843_device::address_search_read( chrn_id* id )
-{
- if ( ! address_search( id ) )
- return 0;
+ case C_SSR: case C_RCR: case C_SSW: case C_SWD: case C_MSR: case C_MSW:
+ m_stra |= SA_BUSY;
+ m_stra &= ~(SA_DDM|SA_TNEQ);
+ m_state = S_SRW_WAIT_READY;
+ break;
- if ( id->flags & ID_FLAG_CRC_ERROR_IN_DATA_FIELD )
- {
- LOG( "%f mc6843_address_search_read: data CRC error\n", machine().time().as_double() );
- m_STRB |= 0x06; /* set CRC error & Data Mark Undetected */
- cmd_end( );
- return 0;
- }
+ case C_FFW:
+ m_stra |= SA_BUSY;
+ m_state = S_FFW_WAIT_READY;
+ m_dor_needed = true;
+ break;
+
+ case 0x0:
+ case 0x1:
+ case 0x8:
+ case 0x9:
+ case 0xe:
+ case 0xf:
+ break;
- if ( id->flags & ID_FLAG_DELETED_DATA )
- {
- LOG( "%f mc6843_address_search_read: deleted data\n", machine().time().as_double() );
- m_STRA |= 0x02; /* set Delete Data Mark Detected */
+ default:
+ fatalerror("Unsupported command\n");
}
- return 1;
+ run(false, false, false);
}
+void mc6843_device::delay(int cycles)
+{
+ // A delay of zero freezes the fdc, it's expected
+ if(cycles) {
+ m_timer->adjust(attotime::from_ticks(cycles, clock()));
+ }
+}
+bool mc6843_device::is_ready() const
+{
+ return m_force_ready || (m_floppy && !m_floppy->ready_r());
+}
-/* Read CRC bottom half */
-void mc6843_device::finish_RCR( )
+void mc6843_device::run(bool timeout, bool ready, bool index)
{
- chrn_id id;
- if ( ! address_search_read( &id ) )
- return;
- cmd_end( );
-}
+ for(;;) {
+ if(m_cur_live.state != L_IDLE) {
+ live_run();
+ if(m_cur_live.state != L_IDLE)
+ return;
+ }
+ switch(m_state) {
+ case S_IDLE:
+ return;
+ case S_STZ_STEP:
+ if(m_floppy && !m_floppy->trk00_r()) {
+ m_floppy->stp_w(0);
+ m_floppy->stp_w(1);
+ }
+ m_step_count --;
+ m_state = S_STZ_STEP_WAIT;
+ delay(1024 * (m_sur >> 4));
+ return;
+
+ case S_STZ_STEP_WAIT:
+ if(!timeout)
+ return;
+ if(m_step_count)
+ m_state = S_STZ_STEP;
+ else {
+ m_ctar = m_gcr = 0;
+ m_state = S_STZ_HEAD_SETTLING;
+ delay(4096 * (m_sur & 15));
+ return;
+ }
+ break;
-/* Single / Multiple Sector Read bottom half */
-void mc6843_device::cont_SR( )
-{
- chrn_id id;
- legacy_floppy_image_device* img = floppy_image( );
+ case S_STZ_HEAD_SETTLING:
+ if(!timeout)
+ return;
+ m_head_loaded = true;
+ m_stra &= ~SA_BUSY;
+ m_state = S_IDLE;
+ isr_raise(I_SCE);
+ return;
+
+ case S_SEEK_STEP:
+ if(m_floppy) {
+ m_floppy->stp_w(0);
+ m_floppy->stp_w(1);
+ }
+ m_step_count --;
+ m_state = S_SEEK_STEP_WAIT;
+ delay(1024 * (m_sur >> 4));
+ return;
+
+ case S_SEEK_STEP_WAIT:
+ if(!timeout)
+ return;
+ if(m_step_count)
+ m_state = S_SEEK_STEP;
+ else {
+ m_ctar = m_gcr;
+ m_state = S_SEEK_HEAD_SETTLING;
+ delay(4096 * (m_sur & 15));
+ return;
+ }
+ break;
- /* sector seek */
- if ( ! address_search_read( &id ) )
- return;
+ case S_SEEK_HEAD_SETTLING:
+ if(!timeout)
+ return;
+ m_head_loaded = true;
+ m_stra &= ~SA_BUSY;
+ m_state = S_IDLE;
+ isr_raise(I_SCE);
+ return;
+
+ case S_SRW_WAIT_READY:
+ if(!is_ready())
+ return;
+ if(!m_head_loaded) {
+ m_state = S_SRW_HEAD_SETTLING;
+ delay(4096 * (m_sur & 15));
+ return;
+ } else
+ m_state = S_SRW_START;
+ break;
+
+ case S_SRW_HEAD_SETTLING:
+ if(timeout) {
+ m_head_loaded = true;
+ m_state = S_SRW_START;
+ }
+ break;
- /* sector read */
- img->floppy_drive_read_sector_data( m_side, id.data_id, m_data, 128 );
- m_data_idx = 0;
- m_data_size = 128;
- m_STRA |= 0x01; /* set Data Transfer Request */
- status_update( );
+ case S_SRW_START:
+ m_idam_turns = 3;
+ live_start(L_IDAM_SEARCH);
+ return;
+
+ case S_FFW_WAIT_READY:
+ if(!is_ready())
+ return;
+ if(!m_head_loaded) {
+ m_state = S_FFW_HEAD_SETTLING;
+ delay(4096 * (m_sur & 15));
+ return;
+ } else
+ m_state = S_FFW_START;
+ break;
+
+ case S_FFW_HEAD_SETTLING:
+ if(timeout) {
+ m_head_loaded = true;
+ m_state = S_FFW_START;
+ }
+ break;
+
+ case S_FFW_START:
+ live_start(L_FFW_BYTE);
+ return;
+
+ case S_IDAM_BAD_TRACK:
+ m_dir = m_cur_live.data_reg;
+ m_stra |= SA_TNEQ;
+ m_stra &= ~SA_BUSY;
+ m_state = S_IDLE;
+ isr_raise(I_RWCE);
+ return;
+
+ case S_IDAM_BAD_CRC:
+ m_strb |= SB_CRC | SB_SAERR;
+ m_stra &= ~SA_BUSY;
+ m_state = S_IDLE;
+ isr_raise(I_RWCE | I_STRB);
+ return;
+
+ case S_IDAM_FOUND:
+ if(m_cmr & 0x20)
+ isr_raise(I_SSR);
+ if((m_cmr & 0xf) == C_SSR || (m_cmr & 0xf) == C_MSR || (m_cmr & 0xf) == C_RCR)
+ live_start(L_DAM_SEARCH);
+
+ else {
+ m_dor_needed = true;
+ live_start(L_DAM_WAIT);
+ }
+ return;
+
+ case S_IDAM_NOT_FOUND:
+ m_stra &= ~SA_BUSY;
+ m_strb |= SB_SAERR;
+ m_state = S_IDLE;
+ isr_raise(I_RWCE | I_STRB);
+ logerror("not found\n");
+ return;
+
+ case S_DAM_NOT_FOUND:
+ m_strb |= SB_DMERR;
+ m_stra &= ~SA_BUSY;
+ m_state = S_IDLE;
+ isr_raise(I_RWCE | I_STRB);
+ return;
+
+ case S_DAM_BAD_CRC:
+ m_strb |= SB_CRC;
+ m_stra &= ~SA_BUSY;
+ m_state = S_IDLE;
+ isr_raise(I_RWCE | I_STRB);
+ return;
+
+ case S_DAM_DONE:
+ m_dor_needed = false;
+ if((m_cmr & 0xf) == C_MSR || (m_cmr & 0xf) == C_MSW) {
+ m_sar = (m_sar + 1) & 0x1f;
+ m_gcr = (m_gcr - 1) & 0x7f;
+ if(m_gcr != 0x7f) {
+ m_state = S_SRW_START;
+ break;
+ }
+ }
+ m_stra &= ~SA_BUSY;
+ m_state = S_IDLE;
+ isr_raise(I_RWCE);
+ return;
+ }
+ }
}
-void mc6843_device::finish_SR( )
+void mc6843_device::live_start(int state, bool start_writing)
{
- m_crc_wait = 0;
- cmd_end( );
+ m_cur_live.tm = machine().time();
+ m_cur_live.state = state;
+ m_cur_live.next_state = -1;
+ m_cur_live.shift_reg = 0;
+ m_cur_live.crc = 0xffff;
+ m_cur_live.bit_counter = 0;
+ m_cur_live.data_separator_phase = false;
+ m_cur_live.data_reg = 0;
+
+ m_cur_live.pll.reset(m_cur_live.tm);
+ m_cur_live.pll.set_clock(attotime::from_ticks(2, clock()));
+ if(start_writing)
+ m_cur_live.pll.start_writing(machine().time());
+
+ m_checkpoint_live = m_cur_live;
+
+ live_run();
}
-/* Single / Multiple Sector Write bottom half */
-void mc6843_device::cont_SW( )
+void mc6843_device::checkpoint()
{
- chrn_id id;
-
- /* sector seek */
- if ( ! address_search( &id ) )
- return;
-
- /* setup sector write buffer */
- m_data_idx = 0;
- m_data_size = 128;
- m_STRA |= 0x01; /* set Data Transfer Request */
- m_data_id = id.data_id; /* for subsequent write sector command */
- status_update( );
+ m_cur_live.pll.commit(m_floppy, m_cur_live.tm);
+ m_checkpoint_live = m_cur_live;
}
+void mc6843_device::rollback()
+{
+ m_cur_live = m_checkpoint_live;
+}
+void mc6843_device::live_delay(int state)
+{
+ m_cur_live.next_state = state;
+ m_timer->adjust(m_cur_live.tm - machine().time());
+}
-/* bottom halves, called to continue / finish a command after some delay */
-void mc6843_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+void mc6843_device::live_sync()
{
- switch (id)
- {
- case TIMER_CONT:
- {
- int cmd = m_CMR & 0x0f;
-
- LOG( "%f mc6843_cont: timer called for cmd=%s(%i)\n", machine().time().as_double(), mc6843_cmd[cmd], cmd );
-
- m_timer_cont->adjust( attotime::never );
-
- switch ( cmd )
- {
- case CMD_STZ: finish_STZ( ); break;
- case CMD_SEK: finish_SEK( ); break;
- case CMD_SSR:
- case CMD_MSR:
- if ( m_crc_wait )
- finish_SR( );
- else
- cont_SR( );
- break;
- case CMD_SSW: cont_SW( ); break;
- case CMD_RCR: finish_RCR( ); break;
- case CMD_SWD: cont_SW( ); break;
- case CMD_MSW: cont_SW( ); break;
- }
+ if(m_cur_live.state != L_IDLE && !m_cur_live.tm.is_never()) {
+ if(m_cur_live.tm > machine().time()) {
+ if(0)
+ logerror("%s: Rolling back and replaying (%s)\n", machine().time().to_string(), m_cur_live.tm.to_string());
+ rollback();
+ live_run(machine().time());
+ m_cur_live.pll.commit(m_floppy, m_cur_live.tm);
+ } else {
+ if(0)
+ logerror("%s: Committing (%s)\n", machine().time().to_string(), m_cur_live.tm.to_string());
+ m_cur_live.pll.commit(m_floppy, m_cur_live.tm);
+ if(m_cur_live.next_state != -1) {
+ m_cur_live.state = m_cur_live.next_state;
+ m_cur_live.next_state = -1;
}
- break;
-
- default:
- break;
+ if(m_cur_live.state == L_IDLE) {
+ m_cur_live.pll.stop_writing(m_floppy, m_cur_live.tm);
+ m_cur_live.tm = attotime::never;
+ }
+ }
+ m_cur_live.next_state = -1;
+ checkpoint();
}
}
+void mc6843_device::live_abort()
+{
+ if(!m_cur_live.tm.is_never() && m_cur_live.tm > machine().time()) {
+ rollback();
+ live_run(machine().time());
+ }
+ m_cur_live.pll.stop_writing(m_floppy, m_cur_live.tm);
+ m_cur_live.tm = attotime::never;
+ m_cur_live.state = L_IDLE;
+ m_cur_live.next_state = -1;
+}
-/************************** CPU interface ****************************/
-
-
+bool mc6843_device::read_one_bit(const attotime &limit)
+{
+ int bit = m_cur_live.pll.get_next_bit(m_cur_live.tm, m_floppy, limit);
+ if(bit < 0)
+ return true;
+ m_cur_live.shift_reg = (m_cur_live.shift_reg << 1) | bit;
+ m_cur_live.bit_counter++;
+ if(m_cur_live.data_separator_phase) {
+ m_cur_live.data_reg = (m_cur_live.data_reg << 1) | bit;
+ if((m_cur_live.crc ^ (bit ? 0x8000 : 0x0000)) & 0x8000)
+ m_cur_live.crc = (m_cur_live.crc << 1) ^ 0x1021;
+ else
+ m_cur_live.crc = m_cur_live.crc << 1;
+ }
+ m_cur_live.data_separator_phase = !m_cur_live.data_separator_phase;
+ return false;
+}
-uint8_t mc6843_device::read(offs_t offset)
+bool mc6843_device::write_one_bit(const attotime &limit)
{
- uint8_t data = 0;
+ bool bit = m_cur_live.shift_reg & 0x8000;
+ if(m_cur_live.pll.write_next_bit(bit, m_cur_live.tm, m_floppy, limit))
+ return true;
+ if(m_cur_live.bit_counter & 1) {
+ if((m_cur_live.crc ^ (bit ? 0x8000 : 0x0000)) & 0x8000)
+ m_cur_live.crc = (m_cur_live.crc << 1) ^ 0x1021;
+ else
+ m_cur_live.crc = m_cur_live.crc << 1;
+ }
+ m_cur_live.shift_reg = m_cur_live.shift_reg << 1;
+ m_cur_live.bit_counter--;
+ return false;
+}
- switch ( offset ) {
- case 0: /* Data Input Register (DIR) */
- {
- int cmd = m_CMR & 0x0f;
+void mc6843_device::live_run(attotime limit)
+{
+ if(m_cur_live.state == L_IDLE || m_cur_live.next_state != -1)
+ return;
- if (machine().side_effects_disabled())
- {
- data = m_data[0];
- break;
+ if(limit == attotime::never) {
+ if(m_floppy)
+ limit = m_floppy->time_next_index();
+ if(limit == attotime::never) {
+ // Happens when there's no disk or if the wd is not
+ // connected to a drive, hence no index pulse. Force a
+ // sync from time to time in that case, so that the main
+ // cpu timeout isn't too painful. Avoids looping into
+ // infinity looking for data too.
+
+ limit = machine().time() + attotime::from_msec(1);
+ m_timer->adjust(attotime::from_msec(1));
}
+ }
- LOG( "%f %s mc6843_r: data input cmd=%s(%i), pos=%i/%i, GCR=%i, ",
- machine().time().as_double(), machine().describe_context(),
- mc6843_cmd[cmd], cmd, m_data_idx,
- m_data_size, m_GCR );
-
- if ( cmd == CMD_SSR || cmd == CMD_MSR )
- {
- /* sector read */
- assert( m_data_size > 0 );
- assert( m_data_idx < m_data_size );
- assert( m_data_idx < sizeof(m_data) );
- data = m_data[ m_data_idx ];
- m_data_idx++;
-
- if ( m_data_idx >= m_data_size )
- {
- /* end of sector read */
-
- m_STRA &= ~0x01; /* clear Data Transfer Request */
-
- if ( cmd == CMD_MSR )
- {
- /* schedule next sector in multiple sector read */
- m_GCR--;
- m_SAR++;
- if ( m_GCR == 0xff )
- {
- m_crc_wait = 1;
- m_timer_cont->adjust( DELAY_CRC );
- }
- else if ( m_SAR > 26 )
-
- {
- m_STRB |= 0x08; /* set Sector Address Undetected */
- m_crc_wait = 1;
- m_timer_cont->adjust( DELAY_CRC );
- }
- else
- {
- m_timer_cont->adjust( DELAY_ADDR );
- }
- }
- else
- {
- m_crc_wait = 1;
- m_timer_cont->adjust( DELAY_CRC );
- }
+ for(;;) {
+ switch(m_cur_live.state) {
+ case L_IDAM_SEARCH:
+ if(read_one_bit(limit))
+ return;
+
+ if(0)
+ logerror("%s: shift = %04x data=%02x c=%d\n", m_cur_live.tm.to_string(), m_cur_live.shift_reg,
+ (m_cur_live.shift_reg & 0x4000 ? 0x80 : 0x00) |
+ (m_cur_live.shift_reg & 0x1000 ? 0x40 : 0x00) |
+ (m_cur_live.shift_reg & 0x0400 ? 0x20 : 0x00) |
+ (m_cur_live.shift_reg & 0x0100 ? 0x10 : 0x00) |
+ (m_cur_live.shift_reg & 0x0040 ? 0x08 : 0x00) |
+ (m_cur_live.shift_reg & 0x0010 ? 0x04 : 0x00) |
+ (m_cur_live.shift_reg & 0x0004 ? 0x02 : 0x00) |
+ (m_cur_live.shift_reg & 0x0001 ? 0x01 : 0x00),
+ m_cur_live.bit_counter);
+
+ if(m_cur_live.shift_reg == 0xf57e) {
+ m_cur_live.crc = 0xef21;
+ m_cur_live.data_separator_phase = false;
+ m_cur_live.bit_counter = 0;
+ m_cur_live.state = L_IDAM_CHECK_TRACK;
}
- }
- else if ( cmd == 0 )
- {
- data = m_data[0];
- }
- else
- {
- /* XXX TODO: other read modes */
- data = m_data[0];
- logerror( "%s mc6843 read in unsupported command mode %i\n", machine().describe_context(), cmd );
- }
-
- LOG( "data=%02X\n", data );
+ break;
- break;
- }
+ case L_IDAM_CHECK_TRACK:
+ if(read_one_bit(limit))
+ return;
- case 1: /* Current-Track Address Register (CTAR) */
- data = m_CTAR;
- if (machine().side_effects_disabled())
- break;
- LOG( "%f %s mc6843_r: read CTAR %i (actual=%i)\n",
- machine().time().as_double(), machine().describe_context(), data,
- floppy_image()->floppy_drive_get_current_track());
- break;
+ if(m_cur_live.bit_counter == 16) {
+ logerror("%s IDAM track %d\n", m_cur_live.tm.to_string(), m_cur_live.data_reg);
+ if(m_cur_live.data_reg != m_ltar) {
+ m_state = S_IDAM_BAD_TRACK;
+ live_delay(L_IDLE);
+ return;
- case 2: /* Interrupt Status Register (ISR) */
- data = m_ISR;
- if (machine().side_effects_disabled())
+ } else
+ m_cur_live.state = L_IDAM_CHECK_SECTOR;
+ }
break;
- LOG( "%f %s mc6843_r: read ISR %02X: cmd=%scomplete settle=%scomplete sense-rq=%i STRB=%i\n",
- machine().time().as_double(), machine().describe_context(), data,
- (data & 1) ? "" : "not-" , (data & 2) ? "" : "not-",
- (data >> 2) & 1, (data >> 3) & 1 );
-
- /* reset */
- m_ISR &= 8; /* keep STRB */
- status_update( );
- break;
- case 3: /* Status Register A (STRA) */
- {
- /* update */
- legacy_floppy_image_device* img = floppy_image( );
- int flag = img->floppy_drive_get_flag_state( FLOPPY_DRIVE_READY);
- data = m_STRA & 0xa3;
- if ( flag & FLOPPY_DRIVE_READY )
- data |= 0x04;
+ case L_IDAM_CHECK_SECTOR:
+ if(read_one_bit(limit))
+ return;
- data |= !img->floppy_tk00_r() << 3;
- data |= !img->floppy_wpt_r() << 4;
+ if(m_cur_live.bit_counter == 48) {
+ logerror("%s IDAM sector %d\n", m_cur_live.tm.to_string(), m_cur_live.data_reg);
+ if(m_cur_live.data_reg != m_sar)
+ m_cur_live.state = L_IDAM_SEARCH;
+ else
+ m_cur_live.state = L_IDAM_CHECK_CRC;
+ }
+ break;
- if ( m_index_pulse )
- data |= 0x40;
+ case L_IDAM_CHECK_CRC:
+ if(read_one_bit(limit))
+ return;
- if (machine().side_effects_disabled())
+ if(m_cur_live.bit_counter == 96) {
+ logerror("IDAM crc remainder %04x\n", m_cur_live.crc);
+ if(m_cur_live.crc)
+ m_state = S_IDAM_BAD_CRC;
+ else
+ m_state = S_IDAM_FOUND;
+ live_delay(L_IDLE);
+ return;
+ }
break;
- m_STRA = data;
- LOG( "%f %s mc6843_r: read STRA %02X: data-rq=%i del-dta=%i ready=%i t0=%i wp=%i trk-dif=%i idx=%i busy=%i\n",
- machine().time().as_double(), machine().describe_context(), data,
- data & 1, (data >> 1) & 1, (data >> 2) & 1, (data >> 3) & 1,
- (data >> 4) & 1, (data >> 5) & 1, (data >> 6) & 1, (data >> 7) & 1 );
- break;
- }
-
- case 4: /* Status Register B (STRB) */
- data = m_STRB;
- if (machine().side_effects_disabled())
+ case L_DAM_SEARCH:
+ if(read_one_bit(limit))
+ return;
+
+ if(m_cur_live.shift_reg == 0xf56a || m_cur_live.shift_reg == 0xf56f) {
+ m_cur_live.data_separator_phase = false;
+ m_cur_live.bit_counter = 0;
+ logerror("DAM mark %02x\n", m_cur_live.data_reg);
+ if(m_cur_live.shift_reg == 0xf56f) {
+ logerror("DAM found\n");
+ m_cur_live.crc = 0xbf84;
+ m_cur_live.state = L_DAM_READ;
+ } else {
+ logerror("DDAM found\n");
+ m_cur_live.crc = 0x8fe7;
+ live_delay(L_DAM_DELETED);
+ return;
+ }
+ }
break;
- LOG( "%f %s mc6843_r: read STRB %02X: data-err=%i CRC-err=%i dta--mrk-err=%i sect-mrk-err=%i seek-err=%i fi=%i wr-err=%i hard-err=%i\n",
- machine().time().as_double(), machine().describe_context(), data,
- data & 1, (data >> 1) & 1, (data >> 2) & 1, (data >> 3) & 1,
- (data >> 4) & 1, (data >> 5) & 1, (data >> 6) & 1, (data >> 7) & 1 );
-
- /* (partial) reset */
- m_STRB &= ~0xfb;
- status_update( );
- break;
- case 7: /* Logical-Track Address Register (LTAR) */
- data = m_LTAR;
- if (machine().side_effects_disabled())
+ case L_DAM_DELETED:
+ m_stra |= SA_DDM;
+ m_cur_live.state = L_DAM_READ;
break;
- LOG( "%f %s mc6843_r: read LTAR %i (actual=%i)\n",
- machine().time().as_double(), machine().describe_context(), data,
- floppy_image()->floppy_drive_get_current_track());
- break;
- default:
- logerror( "%s mc6843 invalid read offset %i\n", machine().describe_context(), offset );
- }
+ case L_DAM_READ:
+ if(read_one_bit(limit))
+ return;
- return data;
-}
-
-void mc6843_device::write(offs_t offset, uint8_t data)
-{
- switch ( offset ) {
- case 0: /* Data Output Register (DOR) */
- {
- int cmd = m_CMR & 0x0f;
- int FWF = (m_CMR >> 4) & 1;
-
- LOG( "%f %s mc6843_w: data output cmd=%s(%i), pos=%i/%i, GCR=%i, data=%02X\n",
- machine().time().as_double(), machine().describe_context(),
- mc6843_cmd[cmd], cmd, m_data_idx,
- m_data_size, m_GCR, data );
-
- if ( cmd == CMD_SSW || cmd == CMD_MSW || cmd == CMD_SWD )
- {
- /* sector write */
- assert( m_data_size > 0 );
- assert( m_data_idx < m_data_size );
- assert( m_data_idx < sizeof(m_data) );
- m_data[ m_data_idx ] = data;
- m_data_idx++;
- if ( m_data_idx >= m_data_size )
- {
- /* end of sector write */
- legacy_floppy_image_device* img = floppy_image( );
-
- LOG( "%f %s mc6843_w: write sector %i\n", machine().time().as_double(), machine().describe_context(), m_data_id );
-
- img->floppy_drive_write_sector_data(
- m_side, m_data_id,
- m_data, m_data_size,
- (cmd == CMD_SWD) ? ID_FLAG_DELETED_DATA : 0 );
-
- m_STRA &= ~0x01; /* clear Data Transfer Request */
-
- if ( cmd == CMD_MSW )
- {
- m_GCR--;
- m_SAR++;
- if ( m_GCR == 0xff )
- {
- cmd_end( );
- }
- else if ( m_SAR > 26 )
-
- {
- m_STRB |= 0x08; /* set Sector Address Undetected */
- cmd_end( );
- }
- else
- {
- m_timer_cont->adjust( DELAY_ADDR );
- }
- }
- else
- {
- cmd_end( );
- }
+ if(!(m_cur_live.bit_counter & 0xf)) {
+ live_delay(L_DAM_READ_BYTE);
+ return;
}
- }
- else if ( (cmd == CMD_FFW) && FWF )
- {
- /* assume we are formatting */
- uint8_t nibble;
- nibble =
- (data & 0x01) |
- ((data & 0x04) >> 1 )|
- ((data & 0x10) >> 2 )|
- ((data & 0x40) >> 3 );
-
- assert( m_data_idx < sizeof(m_data) );
-
- m_data[m_data_idx / 2] =
- (m_data[m_data_idx / 2] << 4) | nibble;
-
- if ( (m_data_idx == 0) && (m_data[0] == 0xfe ) )
- {
- /* address mark detected */
- m_data_idx = 2;
- }
- else if ( m_data_idx == 9 )
- {
- /* address id field complete */
- if ( (m_data[2] == 0) && (m_data[4] == 0) )
- {
- /* valid address id field */
- legacy_floppy_image_device* img = floppy_image( );
- uint8_t track = m_data[1];
- uint8_t sector = m_data[3];
- uint8_t filler = 0xe5; /* standard Thomson filler */
- LOG( "%f %s mc6843_w: address id detected track=%i sector=%i\n", machine().time().as_double(), machine().describe_context(), track, sector);
- img->floppy_drive_format_sector( m_side, sector, track, 0, sector, 0, filler );
- m_data_idx = 0;
+ break;
+
+ case L_DAM_READ_BYTE: {
+ int byte = m_cur_live.bit_counter >> 4;
+ logerror("byte %02x = %02x crc %04x\n", byte, m_cur_live.data_reg, m_cur_live.crc);
+ if(byte <= 128) {
+ if((m_cmr & 0xf) != C_RCR) {
+ if(m_dir_loaded)
+ m_strb |= SB_DTERR;
+ m_dir_loaded = true;
}
+ m_dir = m_cur_live.data_reg;
+ } else if(byte == 130) {
+ if(m_cur_live.crc)
+ m_state = S_DAM_BAD_CRC;
else
- {
- /* abort */
- m_data_idx = 0;
- }
- }
- else if ( m_data_idx > 0 )
- {
- /* accumulate address id field */
- m_data_idx++;
+ m_state = S_DAM_DONE;
+ m_cur_live.state = L_IDLE;
+ return;
}
- }
- else if ( cmd == 0 )
- {
- /* nothing */
- }
- else
- {
- /* XXX TODO: other write modes */
- logerror( "%s mc6843 write %02X in unsupported command mode %i (FWF=%i)\n", machine().describe_context(), data, cmd, FWF );
- }
- break;
- }
-
- case 1: /* Current-Track Address Register (CTAR) */
- m_CTAR = data;
- LOG( "%f %s mc6843_w: set CTAR to %i %02X (actual=%i) \n",
- machine().time().as_double(), machine().describe_context(), m_CTAR, data,
- floppy_image()->floppy_drive_get_current_track());
- break;
-
- case 2: /* Command Register (CMR) */
- {
- int cmd = data & 15;
-
- LOG( "%f %s mc6843_w: set CMR to $%02X: cmd=%s(%i) FWF=%i DMA=%i ISR3-intr=%i fun-intr=%i\n",
- machine().time().as_double(), machine().describe_context(),
- data, mc6843_cmd[cmd], cmd, (data >> 4) & 1, (data >> 5) & 1,
- (data >> 6) & 1, (data >> 7) & 1 );
-
- /* sanitize state */
- m_STRA &= ~0x81; /* clear Busy & Data Transfer Request */
- m_data_idx = 0;
- m_data_size = 0;
-
- /* commands are initiated by updating some flags and scheduling
- a bottom-half (mc6843_cont) after some delay */
-
- switch (cmd)
- {
- case CMD_SSW:
- case CMD_SSR:
- case CMD_SWD:
- case CMD_RCR:
- case CMD_MSR:
- case CMD_MSW:
- m_STRA |= 0x80; /* set Busy */
- m_STRA &= ~0x22; /* clear Track Not Equal & Delete Data Mark Detected */
- m_STRB &= ~0x04; /* clear Data Mark Undetected */
- m_timer_cont->adjust( DELAY_ADDR );
- break;
- case CMD_STZ:
- case CMD_SEK:
- m_STRA |= 0x80; /* set Busy */
- m_timer_cont->adjust( DELAY_SEEK );
- break;
- case CMD_FFW:
- case CMD_FFR:
- m_data_idx = 0;
- m_STRA |= 0x01; /* set Data Transfer Request */
+ m_cur_live.state = L_DAM_READ;
break;
}
- m_CMR = data;
- status_update( );
- break;
- }
-
- case 3: /* Set-Up Register (SUR) */
- m_SUR = data;
+ case L_DAM_WAIT:
+ if(read_one_bit(limit))
+ return;
- /* assume CLK freq = 1MHz (IBM 3740 compatibility) */
- LOG( "%f %s mc6843_w: set SUR to $%02X: head settling time=%fms, track-to-track seek time=%f\n",
- machine().time().as_double(), machine().describe_context(),
- data, 4.096 * (data & 15), 1.024 * ((data >> 4) & 15) );
- break;
+ if(m_cur_live.bit_counter == 11*16) {
+ m_cur_live.bit_counter = (6+1+128+2)*16;
+ live_delay(L_DAM_WRITE_BYTE);
+ return;
+ }
+ break;
- case 4: /* Sector Address Register (SAR) */
- m_SAR = data & 0x1f;
- LOG( "%f %s mc6843_w: set SAR to %i (%02X)\n", machine().time().as_double(), machine().describe_context(), m_SAR, data );
- break;
+ case L_DAM_WRITE:
+ if(write_one_bit(limit))
+ return;
+ if(!(m_cur_live.bit_counter & 0xf)) {
+ live_delay(L_DAM_WRITE_BYTE);
+ return;
+ }
+ break;
- case 5: /* General Count Register (GCR) */
- m_GCR = data & 0x7f;
- LOG( "%f %s mc6843_w: set GCR to %i (%02X)\n", machine().time().as_double(), machine().describe_context(), m_GCR, data );
- break;
+ case L_DAM_WRITE_BYTE: {
+ int byte = (6+1+128+2) - (m_cur_live.bit_counter >> 4);
+ if(!byte) {
+ m_cur_live.pll.start_writing(m_cur_live.tm);
+ m_cur_live.shift_reg = 0xaaaa;
- case 6: /* CRC Control Register (CCR) */
- m_CCR = data & 3;
- LOG( "%f %s mc6843_w: set CCR to %02X: CRC=%s shift=%i\n",
- machine().time().as_double(), machine().describe_context(), data,
- (data & 1) ? "enabled" : "disabled", (data >> 1) & 1 );
- break;
+ } else if(byte <= 5) {
+ m_cur_live.shift_reg = 0xaaaa;
- case 7: /* Logical-Track Address Register (LTAR) */
- m_LTAR = data & 0x7f;
- LOG( "%f %s mc6843_w: set LTAR to %i %02X (actual=%i)\n",
- machine().time().as_double(), machine().describe_context(), m_LTAR, data,
- floppy_image()->floppy_drive_get_current_track());
- break;
+ } else if(byte <= 6) {
+ m_cur_live.crc = 0xffff;
+ if((m_cmr & 0xf) == C_SWD)
+ m_cur_live.shift_reg = 0xf56a;
+ else
+ m_cur_live.shift_reg = 0xf56f;
+
+ } else if(byte <= 134) {
+ if(!m_dor_loaded)
+ m_strb |= SB_DTERR;
+ m_dor_loaded = false;
+ if(byte == 128)
+ m_dor_needed = false;
+ m_cur_live.shift_reg = 0xaaaa |
+ (m_dor & 0x80 ? 1<<14 : 0) |
+ (m_dor & 0x40 ? 1<<12 : 0) |
+ (m_dor & 0x20 ? 1<<10 : 0) |
+ (m_dor & 0x10 ? 1<< 8 : 0) |
+ (m_dor & 0x08 ? 1<< 6 : 0) |
+ (m_dor & 0x04 ? 1<< 4 : 0) |
+ (m_dor & 0x02 ? 1<< 2 : 0) |
+ (m_dor & 0x01 ? 1 : 0);
+
+ } else if(byte <= 136) {
+ m_cur_live.shift_reg = 0xaaaa |
+ (m_cur_live.crc & 0x8000 ? 1<<14 : 0) |
+ (m_cur_live.crc & 0x4000 ? 1<<12 : 0) |
+ (m_cur_live.crc & 0x2000 ? 1<<10 : 0) |
+ (m_cur_live.crc & 0x1000 ? 1<< 8 : 0) |
+ (m_cur_live.crc & 0x0800 ? 1<< 6 : 0) |
+ (m_cur_live.crc & 0x0400 ? 1<< 4 : 0) |
+ (m_cur_live.crc & 0x0200 ? 1<< 2 : 0) |
+ (m_cur_live.crc & 0x0100 ? 1 : 0);
+
+ } else if(byte <= 137) {
+ m_cur_live.shift_reg = 0xffff;
+
+ } else {
+ m_state = S_DAM_DONE;
+ m_cur_live.state = L_IDLE;
+ m_cur_live.pll.stop_writing(m_floppy, m_cur_live.tm);
+ return;
+ }
+ m_cur_live.state = L_DAM_WRITE;
+ break;
+ }
+
+ case L_FFW_BYTE:
+ if(!m_dor_loaded)
+ m_strb |= SB_DTERR;
+ m_dor_loaded = false;
+ logerror("write %02x\n", m_dor);
+ if(m_cmr & 0x10) {
+ m_cur_live.shift_reg = m_dor << 8;
+ m_cur_live.bit_counter = 8;
+
+ } else {
+ m_cur_live.shift_reg = 0xaaaa |
+ (m_dor & 0x80 ? 1<<14 : 0) |
+ (m_dor & 0x40 ? 1<<12 : 0) |
+ (m_dor & 0x20 ? 1<<10 : 0) |
+ (m_dor & 0x10 ? 1<< 8 : 0) |
+ (m_dor & 0x08 ? 1<< 6 : 0) |
+ (m_dor & 0x04 ? 1<< 4 : 0) |
+ (m_dor & 0x02 ? 1<< 2 : 0) |
+ (m_dor & 0x01 ? 1 : 0);
+ m_cur_live.bit_counter = 16;
+ }
+ m_cur_live.state = L_FFW_WRITE;
+ break;
- default:
- logerror( "%s mc6843 invalid write offset %i (data=$%02X)\n", machine().describe_context(), offset, data );
+ case L_FFW_WRITE:
+ if(write_one_bit(limit))
+ return;
+ if(m_cur_live.bit_counter == 0) {
+ live_delay(L_FFW_BYTE);
+ return;
+ }
+ break;
+ }
}
}