mirror of
https://github.com/holub/mame
synced 2025-06-30 07:58:56 +03:00
hp9845: Introduced no-data timeouts throughout TACO device
This commit is contained in:
parent
13d8279e49
commit
ae64748f91
@ -131,9 +131,9 @@
|
|||||||
// validate my solutions by running the original firmware in MAME, though (no real hw at hand).
|
// validate my solutions by running the original firmware in MAME, though (no real hw at hand).
|
||||||
//
|
//
|
||||||
// TODOs/issues:
|
// TODOs/issues:
|
||||||
// * It seems like all commands expecting to read data off the tape have a kind of timeout. More
|
// * Commands 00 & 10 seem to do the same things. My bet is that they differ in some subtle way that
|
||||||
// investigation is needed.
|
// is not stimulated by all the tape software I used for R.E. Maybe it's just the length of the
|
||||||
// * Emulation of CMD_NOT_INDTA is not entirely ok, SIF utilities fail when using this command.
|
// no-data timeout they have.
|
||||||
// * Find more info on TACO chips (does anyone with a working 9845 or access to internal HP docs want to
|
// * Find more info on TACO chips (does anyone with a working 9845 or access to internal HP docs want to
|
||||||
// help me here, please?)
|
// help me here, please?)
|
||||||
//
|
//
|
||||||
@ -144,7 +144,7 @@
|
|||||||
// Debugging
|
// Debugging
|
||||||
#define VERBOSE 1
|
#define VERBOSE 1
|
||||||
#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
|
#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
|
||||||
#define VERBOSE_0 0
|
#define VERBOSE_0 1
|
||||||
#define LOG_0(x) do { if (VERBOSE_0) logerror x; } while (0)
|
#define LOG_0(x) do { if (VERBOSE_0) logerror x; } while (0)
|
||||||
|
|
||||||
// Macros to clear/set single bits
|
// Macros to clear/set single bits
|
||||||
@ -155,7 +155,8 @@
|
|||||||
// Timers
|
// Timers
|
||||||
enum {
|
enum {
|
||||||
TAPE_TMR_ID,
|
TAPE_TMR_ID,
|
||||||
HOLE_TMR_ID
|
HOLE_TMR_ID,
|
||||||
|
TIMEOUT_TMR_ID
|
||||||
};
|
};
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
@ -182,7 +183,8 @@ enum {
|
|||||||
#define SHORT_GAP_LENGTH ((tape_pos_t)(0.066 * ONE_INCH_POS)) // Minimum length of short gaps: 0.066" ([1], pg 8-10)
|
#define SHORT_GAP_LENGTH ((tape_pos_t)(0.066 * ONE_INCH_POS)) // Minimum length of short gaps: 0.066" ([1], pg 8-10)
|
||||||
#define LONG_GAP_LENGTH ((tape_pos_t)(1.5 * ONE_INCH_POS)) // Minimum length of long gaps: 1.5" ([1], pg 8-10)
|
#define LONG_GAP_LENGTH ((tape_pos_t)(1.5 * ONE_INCH_POS)) // Minimum length of long gaps: 1.5" ([1], pg 8-10)
|
||||||
#define NULL_TAPE_POS ((tape_pos_t)-1) // Special value for invalid/unknown tape position
|
#define NULL_TAPE_POS ((tape_pos_t)-1) // Special value for invalid/unknown tape position
|
||||||
#define NO_DATA_GAP (17 * ONE_BIT_LEN) // Minimum gap size to detect end of data: length of longest word (0xffff)
|
#define PREAMBLE_TIMEOUT ((tape_pos_t)(2.6 * ONE_INCH_POS)) // Min. length of gap making preamble search time out (totally made up)
|
||||||
|
#define DATA_TIMEOUT ((tape_pos_t)(0.066 * ONE_INCH_POS)) // Min. length of gap that will cause data reading to time out (totally made up)
|
||||||
#define FILE_MAGIC 0x4f434154 // Magic value at start of image file: "TACO"
|
#define FILE_MAGIC 0x4f434154 // Magic value at start of image file: "TACO"
|
||||||
|
|
||||||
// Parts of command register
|
// Parts of command register
|
||||||
@ -203,7 +205,7 @@ enum {
|
|||||||
|
|
||||||
// Commands
|
// Commands
|
||||||
enum {
|
enum {
|
||||||
CMD_INDTA_INGAP, // 00: scan for data first then for gap
|
CMD_INDTA_INGAP, // 00: scan for data first then for gap (see also cmd 10)
|
||||||
CMD_UNK_01, // 01: unknown
|
CMD_UNK_01, // 01: unknown
|
||||||
CMD_FINAL_GAP, // 02: write final gap
|
CMD_FINAL_GAP, // 02: write final gap
|
||||||
CMD_INIT_WRITE, // 03: write words for tape formatting
|
CMD_INIT_WRITE, // 03: write words for tape formatting
|
||||||
@ -219,7 +221,7 @@ enum {
|
|||||||
CMD_UNK_0d, // 0d: unknown
|
CMD_UNK_0d, // 0d: unknown
|
||||||
CMD_CLEAR, // 0e: clear errors/unlatch status bits
|
CMD_CLEAR, // 0e: clear errors/unlatch status bits
|
||||||
CMD_UNK_0f, // 0f: unknown
|
CMD_UNK_0f, // 0f: unknown
|
||||||
CMD_NOT_INDTA, // 10: scan for end of data
|
CMD_NOT_INDTA, // 10: scan for end of data (at the moment it's the same as cmd 00)
|
||||||
CMD_UNK_11, // 11: unknown
|
CMD_UNK_11, // 11: unknown
|
||||||
CMD_UNK_12, // 12: unknown
|
CMD_UNK_12, // 12: unknown
|
||||||
CMD_UNK_13, // 13: unknown
|
CMD_UNK_13, // 13: unknown
|
||||||
@ -422,6 +424,7 @@ void hp_taco_device::device_start()
|
|||||||
|
|
||||||
m_tape_timer = timer_alloc(TAPE_TMR_ID);
|
m_tape_timer = timer_alloc(TAPE_TMR_ID);
|
||||||
m_hole_timer = timer_alloc(HOLE_TMR_ID);
|
m_hole_timer = timer_alloc(HOLE_TMR_ID);
|
||||||
|
m_timeout_timer = timer_alloc(TIMEOUT_TMR_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
// device_stop
|
// device_stop
|
||||||
@ -467,12 +470,6 @@ void hp_taco_device::device_timer(emu_timer &timer, device_timer_id id, int para
|
|||||||
m_rw_pos = m_tape_pos;
|
m_rw_pos = m_tape_pos;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_SCAN_RECORDS:
|
|
||||||
// Cmds 18 is terminated at first hole
|
|
||||||
terminate_cmd_now();
|
|
||||||
// No reloading of hole timer
|
|
||||||
return;
|
|
||||||
|
|
||||||
case CMD_MOVE_INGAP:
|
case CMD_MOVE_INGAP:
|
||||||
m_hole_timer->adjust(time_to_next_hole());
|
m_hole_timer->adjust(time_to_next_hole());
|
||||||
// No IRQ at holes
|
// No IRQ at holes
|
||||||
@ -485,10 +482,20 @@ void hp_taco_device::device_timer(emu_timer &timer, device_timer_id id, int para
|
|||||||
freeze_tach_reg(true);
|
freeze_tach_reg(true);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case CMD_INDTA_INGAP:
|
||||||
|
case CMD_INGAP_MOVE:
|
||||||
|
case CMD_NOT_INDTA:
|
||||||
|
case CMD_SCAN_RECORDS:
|
||||||
|
// Commands are terminated at first hole (and failure is reported)
|
||||||
|
terminate_cmd_now();
|
||||||
|
set_error(true);
|
||||||
|
return;
|
||||||
|
|
||||||
case CMD_START_READ:
|
case CMD_START_READ:
|
||||||
case CMD_END_READ:
|
case CMD_END_READ:
|
||||||
set_error(true);
|
// Commands report failure at first hole
|
||||||
break;
|
set_error(true);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Other cmds: default processing (update tape pos, set IRQ, schedule timer for next hole)
|
// Other cmds: default processing (update tape pos, set IRQ, schedule timer for next hole)
|
||||||
@ -500,6 +507,23 @@ void hp_taco_device::device_timer(emu_timer &timer, device_timer_id id, int para
|
|||||||
m_hole_timer->adjust(time_to_next_hole());
|
m_hole_timer->adjust(time_to_next_hole());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TIMEOUT_TMR_ID:
|
||||||
|
LOG_0(("T/O tmr @%g cmd %02x st %d\n" , machine().time().as_double() , CMD_CODE(m_cmd_reg) , m_cmd_state));
|
||||||
|
switch (CMD_CODE(m_cmd_reg)) {
|
||||||
|
case CMD_START_READ:
|
||||||
|
if (m_cmd_state == CMD_PH1) {
|
||||||
|
irq_w(true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Most commands are terminated with failure on data T/O
|
||||||
|
terminate_cmd_now();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
set_error(true);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -684,7 +708,7 @@ hp_taco_device::tape_pos_t hp_taco_device::next_hole(void) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// No more holes: will hit end of tape
|
// No more holes: will hit end of tape
|
||||||
return TAPE_LENGTH;
|
return NULL_TAPE_POS;
|
||||||
} else {
|
} else {
|
||||||
for (int i = (sizeof(tape_holes) / sizeof(tape_holes[ 0 ])) - 1; i >= 0; i--) {
|
for (int i = (sizeof(tape_holes) / sizeof(tape_holes[ 0 ])) - 1; i >= 0; i--) {
|
||||||
if (tape_holes[ i ] < m_tape_pos) {
|
if (tape_holes[ i ] < m_tape_pos) {
|
||||||
@ -693,7 +717,7 @@ hp_taco_device::tape_pos_t hp_taco_device::next_hole(void) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// No more holes: will hit start of tape
|
// No more holes: will hit start of tape
|
||||||
return 0;
|
return NULL_TAPE_POS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -749,13 +773,15 @@ bool hp_taco_device::start_tape_cmd(UINT16 cmd_reg , UINT16 must_be_1 , UINT16 m
|
|||||||
BIT_CLR(m_status_reg, STATUS_GAP_BIT);
|
BIT_CLR(m_status_reg, STATUS_GAP_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!not_moving && !prev_tape_braking && prev_tape_fwd != m_tape_fwd) {
|
if (!not_moving && prev_tape_fwd != m_tape_fwd) {
|
||||||
// Tape direction inverted, stop tape before executing command
|
// Tape direction inverted, stop tape before executing command
|
||||||
m_tape_fwd = prev_tape_fwd;
|
m_tape_fwd = prev_tape_fwd;
|
||||||
m_tape_fast = prev_tape_fast;
|
m_tape_fast = prev_tape_fast;
|
||||||
m_cmd_state = CMD_INVERTING;
|
m_cmd_state = CMD_INVERTING;
|
||||||
LOG_0(("Direction reversed! fwd = %d fast = %d\n" , m_tape_fwd , m_tape_fast));
|
LOG_0(("Direction reversed! fwd = %d fast = %d\n" , m_tape_fwd , m_tape_fast));
|
||||||
m_tape_timer->adjust(time_to_stopping_pos());
|
if (!prev_tape_braking) {
|
||||||
|
m_tape_timer->adjust(time_to_stopping_pos());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// No change in direction, immediate execution
|
// No change in direction, immediate execution
|
||||||
m_cmd_state = CMD_PH0;
|
m_cmd_state = CMD_PH0;
|
||||||
@ -763,7 +789,7 @@ bool hp_taco_device::start_tape_cmd(UINT16 cmd_reg , UINT16 must_be_1 , UINT16 m
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_hole_timer->reset();
|
m_hole_timer->reset();
|
||||||
|
m_timeout_timer->reset();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1146,7 +1172,13 @@ void hp_taco_device::set_tape_present(bool present)
|
|||||||
|
|
||||||
attotime hp_taco_device::time_to_next_hole(void) const
|
attotime hp_taco_device::time_to_next_hole(void) const
|
||||||
{
|
{
|
||||||
return time_to_target(next_hole());
|
tape_pos_t pos = next_hole();
|
||||||
|
|
||||||
|
if (pos == NULL_TAPE_POS) {
|
||||||
|
return attotime::never;
|
||||||
|
} else {
|
||||||
|
return time_to_target(pos);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
attotime hp_taco_device::time_to_tach_pulses(void) const
|
attotime hp_taco_device::time_to_tach_pulses(void) const
|
||||||
@ -1159,6 +1191,13 @@ void hp_taco_device::terminate_cmd_now(void)
|
|||||||
m_cmd_state = CMD_END;
|
m_cmd_state = CMD_END;
|
||||||
m_tape_timer->adjust(attotime::zero);
|
m_tape_timer->adjust(attotime::zero);
|
||||||
m_hole_timer->reset();
|
m_hole_timer->reset();
|
||||||
|
m_timeout_timer->reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void hp_taco_device::set_data_timeout(bool long_timeout)
|
||||||
|
{
|
||||||
|
attotime timeout = time_to_distance(long_timeout ? PREAMBLE_TIMEOUT : DATA_TIMEOUT);
|
||||||
|
m_timeout_timer->adjust(timeout , 0 , timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void hp_taco_device::cmd_fsm(void)
|
void hp_taco_device::cmd_fsm(void)
|
||||||
@ -1167,6 +1206,7 @@ void hp_taco_device::cmd_fsm(void)
|
|||||||
// Command ended
|
// Command ended
|
||||||
m_cmd_state = CMD_IDLE;
|
m_cmd_state = CMD_IDLE;
|
||||||
m_hole_timer->reset();
|
m_hole_timer->reset();
|
||||||
|
m_timeout_timer->reset();
|
||||||
irq_w(true);
|
irq_w(true);
|
||||||
if (AUTO_STOP(m_cmd_reg)) {
|
if (AUTO_STOP(m_cmd_reg)) {
|
||||||
// Automatic stop after command execution
|
// Automatic stop after command execution
|
||||||
@ -1195,23 +1235,6 @@ void hp_taco_device::cmd_fsm(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (CMD_CODE(m_cmd_reg)) {
|
switch (CMD_CODE(m_cmd_reg)) {
|
||||||
case CMD_INDTA_INGAP:
|
|
||||||
if (m_cmd_state == CMD_PH0) {
|
|
||||||
// PH0
|
|
||||||
if (next_data(m_rd_it , m_tape_pos , true)) {
|
|
||||||
cmd_duration = time_to_target(farthest_end(m_rd_it));
|
|
||||||
}
|
|
||||||
m_cmd_state = CMD_PH1;
|
|
||||||
} else {
|
|
||||||
// PH1
|
|
||||||
tape_pos_t target = m_tape_pos;
|
|
||||||
if (next_n_gap(target, 1, min_gap_size())) {
|
|
||||||
cmd_duration = time_to_target(target);
|
|
||||||
}
|
|
||||||
m_cmd_state = CMD_END;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CMD_FINAL_GAP:
|
case CMD_FINAL_GAP:
|
||||||
if (m_cmd_state == CMD_PH0) {
|
if (m_cmd_state == CMD_PH0) {
|
||||||
// PH0
|
// PH0
|
||||||
@ -1232,6 +1255,8 @@ void hp_taco_device::cmd_fsm(void)
|
|||||||
// Search for preamble first
|
// Search for preamble first
|
||||||
m_rd_it_valid = next_data(m_rd_it , m_tape_pos , false);
|
m_rd_it_valid = next_data(m_rd_it , m_tape_pos , false);
|
||||||
cmd_duration = time_to_rd_next_word(m_rw_pos);
|
cmd_duration = time_to_rd_next_word(m_rw_pos);
|
||||||
|
// Set T/O for preamble search
|
||||||
|
set_data_timeout(true);
|
||||||
m_cmd_state = CMD_PH1;
|
m_cmd_state = CMD_PH1;
|
||||||
break;
|
break;
|
||||||
} else if (m_cmd_state == CMD_PH1) {
|
} else if (m_cmd_state == CMD_PH1) {
|
||||||
@ -1241,12 +1266,15 @@ void hp_taco_device::cmd_fsm(void)
|
|||||||
m_cmd_state = CMD_PH2;
|
m_cmd_state = CMD_PH2;
|
||||||
// m_rw_pos already at correct position
|
// m_rw_pos already at correct position
|
||||||
cmd_duration = fetch_next_wr_word();
|
cmd_duration = fetch_next_wr_word();
|
||||||
|
m_timeout_timer->reset();
|
||||||
irq_w(true);
|
irq_w(true);
|
||||||
} else {
|
} else {
|
||||||
adv_res_t res = adv_it(m_rd_it);
|
adv_res_t res = adv_it(m_rd_it);
|
||||||
if (res != ADV_NO_MORE_DATA) {
|
if (res != ADV_NO_MORE_DATA) {
|
||||||
cmd_duration = time_to_rd_next_word(m_rw_pos);
|
cmd_duration = time_to_rd_next_word(m_rw_pos);
|
||||||
}
|
}
|
||||||
|
// Set T/O for arrival of data words
|
||||||
|
set_data_timeout(false);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1310,20 +1338,25 @@ void hp_taco_device::cmd_fsm(void)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CMD_INDTA_INGAP:
|
||||||
case CMD_NOT_INDTA:
|
case CMD_NOT_INDTA:
|
||||||
if (m_cmd_state == CMD_PH0) {
|
if (m_cmd_state == CMD_PH0) {
|
||||||
// PH0
|
// PH0
|
||||||
if (next_data(m_rd_it , m_tape_pos , true)) {
|
if (next_data(m_rd_it , m_tape_pos , true)) {
|
||||||
cmd_duration = time_to_target(farthest_end(m_rd_it));
|
cmd_duration = time_to_target(farthest_end(m_rd_it));
|
||||||
}
|
}
|
||||||
|
// Set T/O for data
|
||||||
|
set_data_timeout(true);
|
||||||
m_cmd_state = CMD_PH1;
|
m_cmd_state = CMD_PH1;
|
||||||
} else {
|
} else {
|
||||||
// PH1
|
// PH1
|
||||||
tape_pos_t target = m_tape_pos;
|
tape_pos_t target = m_tape_pos;
|
||||||
if (next_n_gap(target, 1, NO_DATA_GAP)) {
|
if (next_n_gap(target, 1, min_gap_size())) {
|
||||||
LOG_0(("End of data @%d\n" , target));
|
LOG_0(("End of data @%d\n" , target));
|
||||||
cmd_duration = time_to_target(target);
|
cmd_duration = time_to_target(target);
|
||||||
}
|
}
|
||||||
|
// Got data, stop T/O
|
||||||
|
m_timeout_timer->reset();
|
||||||
m_cmd_state = CMD_END;
|
m_cmd_state = CMD_END;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1344,16 +1377,20 @@ void hp_taco_device::cmd_fsm(void)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_SCAN_RECORDS:
|
case CMD_SCAN_RECORDS:
|
||||||
|
// It's probably more correct to implement this to alternate between next data and next gap by using different
|
||||||
|
// FSM states. It times out sooner if the record being searched for doesn't exist on tape. With the current
|
||||||
|
// implementation it has to wait until a hole is reached at either end of the tape.
|
||||||
if (m_cmd_state == CMD_PH0) {
|
if (m_cmd_state == CMD_PH0) {
|
||||||
// PH0
|
// PH0
|
||||||
if (next_data(m_rd_it , m_tape_pos , true)) {
|
if (next_data(m_rd_it , m_tape_pos , true)) {
|
||||||
cmd_duration = time_to_target(farthest_end(m_rd_it));
|
cmd_duration = time_to_target(farthest_end(m_rd_it));
|
||||||
}
|
}
|
||||||
|
// Set T/O for data
|
||||||
|
set_data_timeout(true);
|
||||||
m_cmd_state = CMD_PH1;
|
m_cmd_state = CMD_PH1;
|
||||||
} else {
|
} else {
|
||||||
// PH1
|
// PH1
|
||||||
tape_pos_t target = m_tape_pos;
|
tape_pos_t target = m_tape_pos;
|
||||||
// b8 seems to select size of gaps
|
|
||||||
// Tach. register is incremented at each gap. Command ends when this register goes positive (b15 = 0).
|
// Tach. register is incremented at each gap. Command ends when this register goes positive (b15 = 0).
|
||||||
unsigned n_gaps;
|
unsigned n_gaps;
|
||||||
if (BIT(m_tach_reg , 15)) {
|
if (BIT(m_tach_reg , 15)) {
|
||||||
@ -1367,6 +1404,7 @@ void hp_taco_device::cmd_fsm(void)
|
|||||||
LOG_0(("%u gaps @%d\n" , n_gaps, target));
|
LOG_0(("%u gaps @%d\n" , n_gaps, target));
|
||||||
cmd_duration = time_to_target(target);
|
cmd_duration = time_to_target(target);
|
||||||
}
|
}
|
||||||
|
m_timeout_timer->reset();
|
||||||
m_cmd_state = CMD_END;
|
m_cmd_state = CMD_END;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1382,6 +1420,8 @@ void hp_taco_device::cmd_fsm(void)
|
|||||||
if (next_data(m_rd_it , m_tape_pos , true)) {
|
if (next_data(m_rd_it , m_tape_pos , true)) {
|
||||||
cmd_duration = time_to_target(farthest_end(m_rd_it));
|
cmd_duration = time_to_target(farthest_end(m_rd_it));
|
||||||
}
|
}
|
||||||
|
// Set T/O for data
|
||||||
|
set_data_timeout(true);
|
||||||
m_cmd_state = CMD_END;
|
m_cmd_state = CMD_END;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1417,23 +1457,18 @@ void hp_taco_device::cmd_fsm(void)
|
|||||||
if (!m_rd_it_valid) {
|
if (!m_rd_it_valid) {
|
||||||
// Search for preamble first
|
// Search for preamble first
|
||||||
m_rd_it_valid = next_data(m_rd_it , m_tape_pos , false);
|
m_rd_it_valid = next_data(m_rd_it , m_tape_pos , false);
|
||||||
|
// Set T/O for preamble search
|
||||||
|
set_data_timeout(true);
|
||||||
|
|
||||||
m_cmd_state = CMD_PH1;
|
m_cmd_state = CMD_PH1;
|
||||||
} else {
|
} else {
|
||||||
// Resume reading from last position, skip preamble search
|
// Resume reading from last position, skip preamble search
|
||||||
m_cmd_state = CMD_PH2;
|
m_cmd_state = CMD_PH2;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd_duration = time_to_rd_next_word(m_rw_pos);
|
|
||||||
} else {
|
} else {
|
||||||
// Just to be sure..
|
// Just to be sure..
|
||||||
m_tape_pos = m_rw_pos;
|
m_tape_pos = m_rw_pos;
|
||||||
|
|
||||||
if (m_cmd_state == CMD_PH3) {
|
|
||||||
// PH3: delayed setting of error condition
|
|
||||||
set_error(true);
|
|
||||||
m_cmd_state = CMD_PH2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_cmd_state == CMD_PH1) {
|
if (m_cmd_state == CMD_PH1) {
|
||||||
// PH1
|
// PH1
|
||||||
// Any word with at least a 0 will do as preamble.
|
// Any word with at least a 0 will do as preamble.
|
||||||
@ -1445,6 +1480,9 @@ void hp_taco_device::cmd_fsm(void)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// PH2
|
// PH2
|
||||||
|
if (m_irq) {
|
||||||
|
LOG(("Data reg overflow!\n"));
|
||||||
|
}
|
||||||
irq_w(true);
|
irq_w(true);
|
||||||
m_data_reg = m_rd_it->second;
|
m_data_reg = m_rd_it->second;
|
||||||
if (m_clear_checksum_reg) {
|
if (m_clear_checksum_reg) {
|
||||||
@ -1454,24 +1492,15 @@ void hp_taco_device::cmd_fsm(void)
|
|||||||
m_checksum_reg += m_data_reg;
|
m_checksum_reg += m_data_reg;
|
||||||
LOG_0(("RD %04x\n" , m_data_reg));
|
LOG_0(("RD %04x\n" , m_data_reg));
|
||||||
}
|
}
|
||||||
|
// Set T/O for arrival of data words
|
||||||
|
set_data_timeout(false);
|
||||||
adv_res_t res = adv_it(m_rd_it);
|
adv_res_t res = adv_it(m_rd_it);
|
||||||
LOG_0(("adv_it %d\n" , res));
|
LOG_0(("adv_it %d\n" , res));
|
||||||
if (res == ADV_NO_MORE_DATA) {
|
if (res == ADV_NO_MORE_DATA) {
|
||||||
m_rd_it_valid = false;
|
m_rd_it_valid = false;
|
||||||
} else {
|
|
||||||
cmd_duration = time_to_rd_next_word(m_rw_pos);
|
|
||||||
if (res == ADV_DISCONT_DATA) {
|
|
||||||
// Wild guess: TACO sets error flag when it stumbles on a gap between words
|
|
||||||
if (m_cmd_state == CMD_PH2 && abs(m_tape_pos - m_rw_pos) > ((tape_pos_t)(0.25 * ONE_INCH_POS))) {
|
|
||||||
m_cmd_state = CMD_PH3;
|
|
||||||
} else {
|
|
||||||
// Hit a gap, restart preamble search
|
|
||||||
// TODO: is this ok?
|
|
||||||
m_cmd_state = CMD_PH1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
cmd_duration = time_to_rd_next_word(m_rw_pos);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_DELTA_MOVE_IRG:
|
case CMD_DELTA_MOVE_IRG:
|
||||||
@ -1485,6 +1514,7 @@ void hp_taco_device::cmd_fsm(void)
|
|||||||
if (m_cmd_state == CMD_PH0) {
|
if (m_cmd_state == CMD_PH0) {
|
||||||
// PH0
|
// PH0
|
||||||
cmd_duration = time_to_rd_next_word(m_rw_pos);
|
cmd_duration = time_to_rd_next_word(m_rw_pos);
|
||||||
|
set_data_timeout(false);
|
||||||
m_cmd_state = CMD_PH1;
|
m_cmd_state = CMD_PH1;
|
||||||
} else {
|
} else {
|
||||||
// PH1
|
// PH1
|
||||||
@ -1545,7 +1575,8 @@ void hp_taco_device::start_cmd_exec(UINT16 new_cmd_reg)
|
|||||||
m_cmd_reg = new_cmd_reg;
|
m_cmd_reg = new_cmd_reg;
|
||||||
freeze_tach_reg(false);
|
freeze_tach_reg(false);
|
||||||
m_hole_timer->reset();
|
m_hole_timer->reset();
|
||||||
if (m_cmd_state == CMD_INVERTING || m_cmd_state == CMD_STOPPING) {
|
m_timeout_timer->reset();
|
||||||
|
if (is_braking()) {
|
||||||
// Already braking
|
// Already braking
|
||||||
// m_tape_timer already set
|
// m_tape_timer already set
|
||||||
} else if (m_start_time.is_never()) {
|
} else if (m_start_time.is_never()) {
|
||||||
@ -1585,8 +1616,8 @@ void hp_taco_device::start_cmd_exec(UINT16 new_cmd_reg)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case CMD_NOT_INDTA:
|
case CMD_NOT_INDTA:
|
||||||
// Errors: CART OUT,FAST SPEED
|
// Errors: CART OUT
|
||||||
started = start_tape_cmd(new_cmd_reg , 0 , SPEED_FAST_MASK);
|
started = start_tape_cmd(new_cmd_reg , 0 , 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_WRITE_IRG:
|
case CMD_WRITE_IRG:
|
||||||
@ -1629,8 +1660,7 @@ void hp_taco_device::start_cmd_exec(UINT16 new_cmd_reg)
|
|||||||
|
|
||||||
case CMD_END_READ:
|
case CMD_END_READ:
|
||||||
// This command only makes sense after CMD_START_READ
|
// This command only makes sense after CMD_START_READ
|
||||||
if (CMD_CODE(m_cmd_reg) == CMD_START_READ &&
|
if (CMD_CODE(m_cmd_reg) == CMD_START_READ) {
|
||||||
(m_cmd_state == CMD_PH2 || m_cmd_state == CMD_PH3)) {
|
|
||||||
started = start_tape_cmd(new_cmd_reg , 0 , SPEED_FAST_MASK);
|
started = start_tape_cmd(new_cmd_reg , 0 , SPEED_FAST_MASK);
|
||||||
LOG_0(("END_READ %d\n" , m_rd_it_valid));
|
LOG_0(("END_READ %d\n" , m_rd_it_valid));
|
||||||
}
|
}
|
||||||
@ -1647,6 +1677,7 @@ void hp_taco_device::start_cmd_exec(UINT16 new_cmd_reg)
|
|||||||
m_cmd_state = CMD_IDLE;
|
m_cmd_state = CMD_IDLE;
|
||||||
m_tape_timer->reset();
|
m_tape_timer->reset();
|
||||||
m_hole_timer->reset();
|
m_hole_timer->reset();
|
||||||
|
m_timeout_timer->reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,7 +103,6 @@ private:
|
|||||||
CMD_PH0,
|
CMD_PH0,
|
||||||
CMD_PH1,
|
CMD_PH1,
|
||||||
CMD_PH2,
|
CMD_PH2,
|
||||||
CMD_PH3,
|
|
||||||
CMD_END,
|
CMD_END,
|
||||||
CMD_STOPPING
|
CMD_STOPPING
|
||||||
} cmd_state_t;
|
} cmd_state_t;
|
||||||
@ -118,6 +117,7 @@ private:
|
|||||||
// Timers
|
// Timers
|
||||||
emu_timer *m_tape_timer;
|
emu_timer *m_tape_timer;
|
||||||
emu_timer *m_hole_timer;
|
emu_timer *m_hole_timer;
|
||||||
|
emu_timer *m_timeout_timer;
|
||||||
|
|
||||||
// Content of tape tracks
|
// Content of tape tracks
|
||||||
tape_track_t m_tracks[ 2 ];
|
tape_track_t m_tracks[ 2 ];
|
||||||
@ -180,6 +180,7 @@ private:
|
|||||||
attotime time_to_next_hole(void) const;
|
attotime time_to_next_hole(void) const;
|
||||||
attotime time_to_tach_pulses(void) const;
|
attotime time_to_tach_pulses(void) const;
|
||||||
void terminate_cmd_now(void);
|
void terminate_cmd_now(void);
|
||||||
|
void set_data_timeout(bool long_timeout);
|
||||||
void cmd_fsm(void);
|
void cmd_fsm(void);
|
||||||
void start_cmd_exec(UINT16 new_cmd_reg);
|
void start_cmd_exec(UINT16 new_cmd_reg);
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user