diff options
Diffstat (limited to 'src/mame/machine/hp9825_tape.cpp')
-rw-r--r-- | src/mame/machine/hp9825_tape.cpp | 719 |
1 files changed, 120 insertions, 599 deletions
diff --git a/src/mame/machine/hp9825_tape.cpp b/src/mame/machine/hp9825_tape.cpp index f2f12135ef1..dbfbd22929e 100644 --- a/src/mame/machine/hp9825_tape.cpp +++ b/src/mame/machine/hp9825_tape.cpp @@ -16,11 +16,10 @@ #include "logmacro.h" #define LOG_REG_MASK (LOG_GENERAL << 1) #define LOG_REG(...) LOGMASKED(LOG_REG_MASK, __VA_ARGS__) -#define LOG_TMR_MASK (LOG_REG_MASK << 1) -#define LOG_TMR(...) LOGMASKED(LOG_TMR_MASK, __VA_ARGS__) -#define LOG_DBG_MASK (LOG_TMR_MASK << 1) +#define LOG_DBG_MASK (LOG_REG_MASK << 1) #define LOG_DBG(...) LOGMASKED(LOG_DBG_MASK, __VA_ARGS__) #undef VERBOSE +//#define VERBOSE (LOG_GENERAL | LOG_REG_MASK | LOG_DBG_MASK) #define VERBOSE (LOG_GENERAL) // Bit manipulation @@ -44,11 +43,9 @@ namespace { // Constants constexpr double FAST_SPEED = 90.0; // Fast speed: 90 ips constexpr double SLOW_SPEED = 22.0; // Slow speed: 22 ips -constexpr double MIN_RD_SPEED = 22.0; // Minimum speed to read data off the tape constexpr double MOVING_THRESHOLD = 2.0; // Tape is moving (from MVG bit POV) when speed > 2.0 ips constexpr double ACCELERATION = 1200.0; // Acceleration when speed set point is changed: 1200 ips^2 constexpr unsigned TACH_TICKS_PER_INCH = 483; // Tachometer pulses per inch -constexpr double INVERSION_MARGIN = 1e-5; // Margin to ensure speed is away from 0 when motion is inverted (10 µs) constexpr hti_format_t::tape_pos_t TACH_TICK_LENGTH = hti_format_t::ONE_INCH_POS / TACH_TICKS_PER_INCH; // Length of each tach tick // Bits in command register @@ -74,33 +71,36 @@ enum : unsigned { STAT_REG_EOT_BIT = 0 // End of tape (1) }; -// Timers -enum { - BIT_TMR_ID, - TACHO_TMR_ID, - HOLE_TMR_ID, - INV_TMR_ID -}; - // Device type definition DEFINE_DEVICE_TYPE(HP9825_TAPE, hp9825_tape_device, "hp9825_tape", "HP9825 tape sub-system") hp9825_tape_device::hp9825_tape_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig , HP9825_TAPE , tag , owner , clock) - , device_image_interface(mconfig , *this) , m_flg_handler(*this) , m_sts_handler(*this) , m_dmar_handler(*this) , m_led_handler(*this) + , m_tape(*this , "drive") , m_short_gap_timer(*this , "short_tmr") , m_long_gap_timer(*this , "long_tmr") - , m_image() - , m_image_dirty(false) { } void hp9825_tape_device::device_add_mconfig(machine_config &config) { + HP_DC100_TAPE(config , m_tape , 0); + m_tape->set_acceleration(ACCELERATION); + m_tape->set_set_points(SLOW_SPEED , FAST_SPEED); + m_tape->set_tick_size(TACH_TICK_LENGTH); + m_tape->set_bits_per_word(17); + m_tape->set_go_threshold(MOVING_THRESHOLD); + m_tape->cart_out().set(FUNC(hp9825_tape_device::cart_out_w)); + m_tape->hole().set(FUNC(hp9825_tape_device::hole_w)); + m_tape->tacho_tick().set(FUNC(hp9825_tape_device::tacho_tick_w)); + m_tape->motion_event().set(FUNC(hp9825_tape_device::motion_w)); + m_tape->rd_bit().set(FUNC(hp9825_tape_device::rd_bit_w)); + m_tape->wr_bit().set(FUNC(hp9825_tape_device::wr_bit_r)); + TTL74123(config , m_short_gap_timer , 0); m_short_gap_timer->set_connection_type(TTL74123_NOT_GROUNDED_NO_DIODE); m_short_gap_timer->set_resistor_value(RES_K(37.9)); @@ -124,11 +124,6 @@ void hp9825_tape_device::device_start() m_dmar_handler.resolve_safe(); m_led_handler.resolve_safe(); - m_bit_timer = timer_alloc(BIT_TMR_ID); - m_tacho_timer = timer_alloc(TACHO_TMR_ID); - m_hole_timer = timer_alloc(HOLE_TMR_ID); - m_inv_timer = timer_alloc(INV_TMR_ID); - save_item(NAME(m_cmd_reg)); save_item(NAME(m_stat_reg)); save_item(NAME(m_flg)); @@ -140,24 +135,10 @@ void hp9825_tape_device::device_start() save_item(NAME(m_dma_req)); save_item(NAME(m_in_gap)); save_item(NAME(m_no_go)); - save_item(NAME(m_present)); save_item(NAME(m_valid_bits)); save_item(NAME(m_trans_cnt)); save_item(NAME(m_short_gap_out)); save_item(NAME(m_long_gap_out)); - save_item(NAME(m_image_dirty)); - save_item(NAME(m_tape_pos)); - save_item(NAME(m_next_bit_pos)); - save_item(NAME(m_next_tacho_pos)); - save_item(NAME(m_next_hole_pos)); - save_item(NAME(m_speed)); - save_item(NAME(m_start_time)); - save_item(NAME(m_accelerating)); - save_item(NAME(m_rw_stat)); - save_item(NAME(m_rd_it_valid)); - save_item(NAME(m_rw_word)); - save_item(NAME(m_bit_idx)); - save_item(NAME(m_gap_start)); } void hp9825_tape_device::device_reset() @@ -181,13 +162,6 @@ void hp9825_tape_device::clear_state() m_no_go = false; m_valid_bits = false; m_trans_cnt = 0; - m_tape_pos = 80 * hti_format_t::ONE_INCH_POS; - m_speed = 0.0; - m_start_time = attotime::never; - m_accelerating = false; - m_rw_stat = RW_IDLE; - m_rd_it_valid = false; - m_gap_start = hti_format_t::NULL_TAPE_POS; m_short_gap_timer->b_w(0); m_long_gap_timer->a_w(1); @@ -197,152 +171,6 @@ void hp9825_tape_device::clear_state() m_sts_handler(true); m_dmar_handler(false); m_led_handler(false); - - m_bit_timer->reset(); - m_tacho_timer->reset(); - m_hole_timer->reset(); - m_inv_timer->reset(); - - set_tape_present(false); - set_tape_present(is_loaded()); -} - -void hp9825_tape_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) -{ - LOG_TMR("%.6f TMR %d s=%.3f p=%d a=%d\n" , machine().time().as_double() , id , m_speed , m_tape_pos , m_accelerating); - update_speed_pos(); - - switch (id) { - case BIT_TMR_ID: - m_tape_pos = m_next_bit_pos; - if (m_rw_stat == RW_READING) { - // Reading - // Tape pos here is aligned with the beginning of bit cell. It'd be more correct - // to align with end of cell, though. This solution is a lot simpler and - // it's basically harmless. - - // 17th bit is sync (always 1) - bool bit = m_bit_idx == 16 ? true : BIT(m_rd_it->second , 15 - m_bit_idx); - rd_bit(bit); - if (is_moving_fwd()) { - m_bit_idx++; - if (m_bit_idx >= 17) { - m_rd_it_valid = m_image.adv_it(current_track() , true , m_rd_it) != hti_format_t::ADV_NO_MORE_DATA; - load_rd_word(); - } else { - time_to_distance(bit_size(bit), m_next_bit_pos, m_bit_timer); - } - } else { - if (m_bit_idx > 0) { - m_bit_idx--; - time_to_distance(-bit_size(bit), m_next_bit_pos, m_bit_timer); - } else { - m_rd_it_valid = m_image.adv_it(current_track() , false , m_rd_it) != hti_format_t::ADV_NO_MORE_DATA; - load_rd_word(); - } - } - } else if (m_rw_stat == RW_WRITING) { - // Writing - // Tape pos is aligned with beginning of bit cell - bool bit = m_data_in; - if (BIT(m_cmd_reg , CMD_REG_FLG_SEL_BIT)) { - set_flg(true); - } - wr_bit(bit); - time_to_distance(bit_size(bit), m_next_bit_pos, m_bit_timer); - } - break; - - case TACHO_TMR_ID: - m_tape_pos = m_next_tacho_pos; - if (!BIT(m_cmd_reg , CMD_REG_FLG_SEL_BIT)) { - set_flg(true); - } - adjust_tacho_timer(); - break; - - case HOLE_TMR_ID: - m_tape_pos = m_next_hole_pos; - BIT_SET(m_stat_reg , STAT_REG_EOT_BIT); - update_sts(); - adjust_hole_timer(); - break; - - case INV_TMR_ID: - // In itself it does nothing (all work is in update_speed_pos) - break; - - default: - break; - } - LOG_TMR("%.6f TMR %d s=%.3f p=%d a=%d\n" , machine().time().as_double() , id , m_speed , m_tape_pos , m_accelerating); -} - -image_init_result hp9825_tape_device::internal_load(bool is_create) -{ - LOG("load %d\n" , is_create); - - device_reset(); - - io_generic io; - io.file = (device_image_interface *)this; - io.procs = &image_ioprocs; - io.filler = 0; - if (is_create) { - m_image.clear_tape(); - m_image.save_tape(&io); - } else if (!m_image.load_tape(&io)) { - LOG("load failed\n"); - seterror(IMAGE_ERROR_INVALIDIMAGE , "Wrong format"); - set_tape_present(false); - return image_init_result::FAIL; - } - LOG("load OK\n"); - - m_image_dirty = false; - - set_tape_present(true); - return image_init_result::PASS; -} - -image_init_result hp9825_tape_device::call_load() -{ - return internal_load(false); -} - -image_init_result hp9825_tape_device::call_create(int format_type, util::option_resolution *format_options) -{ - return internal_load(true); -} - -void hp9825_tape_device::call_unload() -{ - LOG("call_unload dirty=%d\n" , m_image_dirty); - - device_reset(); - - if (m_image_dirty) { - io_generic io; - io.file = (device_image_interface *)this; - io.procs = &image_ioprocs; - io.filler = 0; - m_image.save_tape(&io); - m_image_dirty = false; - } - - m_image.clear_tape(); - set_tape_present(false); -} - -std::string hp9825_tape_device::call_display() -{ - // TODO: - return std::string(); -} - -const char *hp9825_tape_device::file_extensions() const -{ - return "hti"; } READ16_MEMBER(hp9825_tape_device::tape_r) @@ -398,16 +226,16 @@ WRITE16_MEMBER(hp9825_tape_device::tape_w) case 1: // R5: write command { - double old_set_point = get_speed_set_point(); auto old_cmd_reg = m_cmd_reg; m_cmd_reg = data; - check_for_speed_change(old_set_point); + check_for_speed_change(); // Direction bit is mirrored (inverted) in status register if (BIT(m_cmd_reg , CMD_REG_DIR_BIT)) { BIT_CLR(m_stat_reg , STAT_REG_DIR_BIT); } else { BIT_SET(m_stat_reg , STAT_REG_DIR_BIT); } + m_tape->set_track_no(!BIT(m_cmd_reg , CMD_REG_TRACK_SEL_BIT)); if (BIT(m_cmd_reg , CMD_REG_DMA_EN_BIT)) { // DMA disabled m_search_complete = false; @@ -418,7 +246,7 @@ WRITE16_MEMBER(hp9825_tape_device::tape_w) if ((old_cmd_reg ^ m_cmd_reg) & (BIT_MASK<uint8_t>(CMD_REG_WR_GATE_BIT) | BIT_MASK<uint8_t>(CMD_REG_THRESHOLD_BIT))) { // Something changed in Wr gate or threshold bit, start rd/wr - update_speed_pos(); + m_tape->update_speed_pos(); start_rd_wr(); } } @@ -436,7 +264,7 @@ WRITE16_MEMBER(hp9825_tape_device::tape_w) case 3: // R7: reset status - if (m_present) { + if (!m_tape->cart_out_r()) { BIT_CLR(m_stat_reg , STAT_REG_COUT_BIT); update_sts(); } @@ -485,6 +313,92 @@ void hp9825_tape_device::set_flg(bool state) } } +WRITE_LINE_MEMBER(hp9825_tape_device::cart_out_w) +{ + LOG_DBG("cart_out_w %d\n" , state); + if (state) { + // STAT_REG_COUT_BIT is cleared by a write to R7 + BIT_SET(m_stat_reg, STAT_REG_COUT_BIT); + } + + if (m_tape->wpr_r()) { + BIT_SET(m_stat_reg, STAT_REG_WPR_BIT); + } else { + BIT_CLR(m_stat_reg, STAT_REG_WPR_BIT); + } + + update_sts(); +} + +WRITE_LINE_MEMBER(hp9825_tape_device::hole_w) +{ + if (state) { + LOG_DBG("hole_w\n"); + BIT_SET(m_stat_reg , STAT_REG_EOT_BIT); + update_sts(); + } +} + +WRITE_LINE_MEMBER(hp9825_tape_device::tacho_tick_w) +{ + if (state) { + LOG_DBG("tacho_tick_w\n"); + if (!BIT(m_cmd_reg , CMD_REG_FLG_SEL_BIT)) { + set_flg(true); + } + } +} + +WRITE_LINE_MEMBER(hp9825_tape_device::motion_w) +{ + if (state) { + LOG_DBG("motion_w\n"); + // Update MVG bit + if (m_tape->is_moving()) { + if (!BIT(m_stat_reg , STAT_REG_MVG_BIT)) { + BIT_SET(m_stat_reg , STAT_REG_MVG_BIT); + m_led_handler(true); + } + } else { + if (BIT(m_stat_reg , STAT_REG_MVG_BIT)) { + BIT_CLR(m_stat_reg , STAT_REG_MVG_BIT); + m_led_handler(false); + } + } + start_rd_wr(); + } +} + +WRITE_LINE_MEMBER(hp9825_tape_device::rd_bit_w) +{ + m_short_gap_timer->b_w(1); + m_short_gap_timer->b_w(0); + m_long_gap_timer->b_w(1); + m_long_gap_timer->b_w(0); + m_data_out = m_valid_bits && state; + if (BIT(m_cmd_reg , CMD_REG_FLG_SEL_BIT)) { + set_flg(true); + } + m_trans_cnt++; + LOG_DBG("TC %u IG %d VB %d\n" , m_trans_cnt , m_in_gap , m_valid_bits); + if ((m_trans_cnt & 0x0c) == 0x0c) { + m_valid_bits = true; + } + if (BIT(m_trans_cnt , 2) && m_in_gap) { + m_in_gap = false; + m_long_gap_timer->a_w(m_in_gap); + update_sts(); + } +} + +READ_LINE_MEMBER(hp9825_tape_device::wr_bit_r) +{ + if (BIT(m_cmd_reg , CMD_REG_FLG_SEL_BIT)) { + set_flg(true); + } + return m_data_in; +} + void hp9825_tape_device::update_sts() { // Inputs to STS computation: @@ -494,7 +408,6 @@ void hp9825_tape_device::update_sts() // STAT_REG_COUT_BIT // m_search_complete // m_in_gap - auto prev_set_point = get_speed_set_point(); auto prev_exception = m_exception; m_exception = @@ -503,7 +416,7 @@ void hp9825_tape_device::update_sts() m_search_complete; if (prev_exception != m_exception) { - check_for_speed_change(prev_set_point); + check_for_speed_change(); } m_no_go = m_exception && !BIT(m_cmd_reg , CMD_REG_MOTOR_BIT); @@ -526,23 +439,6 @@ void hp9825_tape_device::update_dmar() m_dmar_handler(m_dma_req && !BIT(m_cmd_reg , CMD_REG_DMA_EN_BIT)); } -void hp9825_tape_device::set_tape_present(bool present) -{ - m_present = present; - if (present) { - if (is_readonly()) { - BIT_SET(m_stat_reg, STAT_REG_WPR_BIT); - } else { - BIT_CLR(m_stat_reg, STAT_REG_WPR_BIT); - } - // STAT_REG_COUT_BIT is cleared by a write to R7 - } else { - BIT_SET(m_stat_reg, STAT_REG_COUT_BIT); - BIT_SET(m_stat_reg, STAT_REG_WPR_BIT); - update_sts(); - } -} - bool hp9825_tape_device::is_moving_fwd() const { return BIT(m_cmd_reg , CMD_REG_DIR_BIT); @@ -553,412 +449,37 @@ bool hp9825_tape_device::is_speed_fast() const return !BIT(m_cmd_reg , CMD_REG_SPEED_BIT); } -bool hp9825_tape_device::is_actual_dir_fwd() const +void hp9825_tape_device::check_for_speed_change() { - // Actual direction can be different from commanded direction in accelerated phases (e.g. when tape - // direction is turned around) - return m_speed == 0.0 ? is_moving_fwd() : m_speed > 0.0; -} + hp_dc100_tape_device::tape_speed_t new_speed; -double hp9825_tape_device::get_speed_set_point() const -{ if (m_exception || BIT(m_cmd_reg , CMD_REG_MOTOR_BIT)) { // Stop - return 0.0; + new_speed = hp_dc100_tape_device::SP_STOP; } else { - double c; - if (is_speed_fast()) { - // HS - c = FAST_SPEED; - } else { - // LS - c = SLOW_SPEED; - } - if (!is_moving_fwd()) { - // Reverse - c = -c; - } - return c; + new_speed = is_speed_fast() ? hp_dc100_tape_device::SP_FAST : + hp_dc100_tape_device::SP_SLOW; } -} - -void hp9825_tape_device::start_tape() -{ - LOG_DBG("Tape started %.6f p=%d\n" , machine().time().as_double() , m_tape_pos); - m_start_time = machine().time(); - m_accelerating = true; - m_speed = 0; -} -void hp9825_tape_device::stop_tape() -{ - LOG_DBG("Tape stops %.6f p=%d\n" , machine().time().as_double() , m_tape_pos); - m_start_time = attotime::never; - m_accelerating = false; - m_speed = 0; - m_tacho_timer->reset(); - m_hole_timer->reset(); - m_inv_timer->reset(); - stop_rd_wr(); -} + bool changed = m_tape->set_speed_setpoint(new_speed , is_moving_fwd()); -void hp9825_tape_device::check_for_speed_change(double prev_set_point) -{ - double set_point = get_speed_set_point(); - if (prev_set_point != set_point) { - update_speed_pos(); - LOG_DBG("Speed SP changed %f->%f %.6f p=%d\n" , prev_set_point , set_point , machine().time().as_double() , m_tape_pos); - // Speed set point changed, accelerate/decelerate - m_accelerating = true; - if (m_start_time.is_never()) { - // Tape starting now - start_tape(); - } + if (changed) { start_rd_wr(true); - adjust_tacho_timer(); - adjust_hole_timer(); - set_inv_timer(); - } -} - -void hp9825_tape_device::update_speed_pos() -{ - if (m_start_time.is_never()) { - // Tape stopped - return; - } - - attotime delta_time{machine().time() - m_start_time}; - if (delta_time.is_zero()) { - return; - } - m_start_time = machine().time(); - double delta_time_double = delta_time.as_double(); - - // Space in const A phase - double space_const_a; - // Time in const V phase - double time_const_v; - // Do R/W start/stop - bool rw_start_stop = false; - - if (m_accelerating) { - double set_point = get_speed_set_point(); - double time_to_const_v = fabs(set_point - m_speed) / ACCELERATION; - double acceleration = set_point > m_speed ? ACCELERATION : -ACCELERATION; - if (delta_time_double < time_to_const_v) { - space_const_a = const_a_space(acceleration , delta_time_double); - auto prev_speed = m_speed; - m_speed += delta_time_double * acceleration; - rw_start_stop = (fabs(prev_speed) >= MIN_RD_SPEED) != (fabs(m_speed) >= MIN_RD_SPEED); - if (prev_speed * m_speed < 0.0) { - // Direction inverted (speed sign flipped) - LOG_DBG("Dir inverted s=%f\n" , m_speed); - adjust_tacho_timer(); - adjust_hole_timer(); - } - set_inv_timer(); - time_const_v = 0.0; - } else { - space_const_a = const_a_space(acceleration , time_to_const_v); - time_const_v = delta_time_double - time_to_const_v; - LOG_DBG("Acceleration ends\n"); - m_accelerating = false; - m_speed = set_point; - m_inv_timer->reset(); - if (m_speed == 0.0) { - // Tape stops - stop_tape(); - } else { - rw_start_stop = true; - } - } - } else { - space_const_a = 0.0; - time_const_v = delta_time_double; - } - - // Update MVG bit - if (fabs(m_speed) >= MOVING_THRESHOLD) { - if (!BIT(m_stat_reg , STAT_REG_MVG_BIT)) { - BIT_SET(m_stat_reg , STAT_REG_MVG_BIT); - m_led_handler(true); - } - } else { - if (BIT(m_stat_reg , STAT_REG_MVG_BIT)) { - BIT_CLR(m_stat_reg , STAT_REG_MVG_BIT); - m_led_handler(false); - } - } - - hti_format_t::tape_pos_t delta_pos = (hti_format_t::tape_pos_t)((space_const_a + m_speed * time_const_v) * hti_format_t::ONE_INCH_POS); - LOG_DBG("dp=%d\n" , delta_pos); - if (!hti_format_t::pos_offset(m_tape_pos , true , delta_pos)) { - LOG("Tape unspooled!\n"); - } - - if (rw_start_stop) { - start_rd_wr(); - } -} - -void hp9825_tape_device::set_inv_timer() -{ - // Set inversion timer to go off at the moment the tape inverts its motion - // (i.e. when m_speed crosses 0) - if (m_speed == 0.0 || (get_speed_set_point() * m_speed) > 0.0) { - LOG_DBG("Inv tmr reset\n"); - // No inversion in sight - m_inv_timer->reset(); - } else { - // INVERSION_MARGIN is added to ensure that m_speed has already cleared the - // 0-crossing when inv timer goes off - LOG_DBG("Inv tmr set %.6f %f\n" , machine().time().as_double() , m_speed); - m_inv_timer->adjust(attotime::from_double(fabs(m_speed) / ACCELERATION + INVERSION_MARGIN)); - } -} - -void hp9825_tape_device::time_to_distance(hti_format_t::tape_pos_t distance , hti_format_t::tape_pos_t& target_pos , emu_timer *target_timer) const -{ - if (m_start_time.is_never()) { - // If tape is stopped we'll never get there.. - target_timer->reset(); - return; - } - - target_pos = m_tape_pos; - if (!hti_format_t::pos_offset(target_pos , true , distance)) { - // Beyond end of tape - target_timer->reset(); - return; - } - - double space = double(distance) / hti_format_t::ONE_INCH_POS; - double set_point = get_speed_set_point(); - double time_const_a; - - if (m_accelerating) { - // Time to reach constant V phase - double time_to_const_v = fabs(set_point - m_speed) / ACCELERATION; - // Signed acceleration - double acceleration = set_point > m_speed ? ACCELERATION : -ACCELERATION; - // Compute time to cover distance with constant acceleration - // It's the smallest non-negative root of this quadratic equation: - // 1/2*acceleration*t^2+m_speed*t=space - double delta = m_speed * m_speed + 2 * acceleration * space; - bool has_root = delta >= 0.0; - double time_in_const_a = 0.0; - if (has_root) { - double time_in_const_a_pos = (sqrt(delta) - m_speed) / acceleration; - double time_in_const_a_neg = -(sqrt(delta) + m_speed) / acceleration; - LOG_DBG("TTD %.6f %.6f\n" , time_in_const_a_pos , time_in_const_a_neg); - if (time_in_const_a_pos >= 0.0) { - if (time_in_const_a_neg >= 0.0) { - // pos + neg + - time_in_const_a = std::min(time_in_const_a_pos , time_in_const_a_neg); - } else { - // pos + neg - - time_in_const_a = time_in_const_a_pos; - } - } else { - if (time_in_const_a_neg >= 0.0) { - // pos - neg + - time_in_const_a = time_in_const_a_neg; - } else { - // pos - neg - - has_root = false; - } - } - } - LOG_DBG("TTD %d %d %.6f %.6f %.6f\n" , distance , has_root , m_speed , time_to_const_v , time_in_const_a); - if (has_root && time_in_const_a <= time_to_const_v) { - // Entirely in the constant A phase - time_const_a = time_in_const_a; - space = 0.0; - } else { - // Partly in const A & partly in const V - double space_in_const_a = const_a_space(acceleration , time_to_const_v); - space -= space_in_const_a; - time_const_a = time_to_const_v; - } - } else { - // Entirely in const V - time_const_a = 0.0; - } - - // Time in constant V - double time_const_v; - if (space != 0.0) { - if (set_point == 0.0) { - target_timer->reset(); - return; - } else { - time_const_v = space / set_point; - if (time_const_v < 0.0) { - target_timer->reset(); - return; - } - } - } else { - time_const_v = 0.0; - } - LOG_DBG("TTD %.6f %.6f\n" , time_const_a , time_const_v); - - target_timer->adjust(attotime::from_double(time_const_a + time_const_v)); -} - -double hp9825_tape_device::const_a_space(double a , double t) const -{ - // Space traveled in time 't' at constant acceleration 'a' starting with 'm_speed' speed - return t * (m_speed + a / 2 * t); -} - -hti_format_t::tape_pos_t hp9825_tape_device::get_next_hole() const -{ - return hti_format_t::next_hole(m_tape_pos , is_actual_dir_fwd()) - m_tape_pos; -} - -void hp9825_tape_device::adjust_tacho_timer() -{ - hti_format_t::tape_pos_t tick = TACH_TICK_LENGTH; - if (!is_actual_dir_fwd()) { - tick = -tick; } - time_to_distance(tick , m_next_tacho_pos , m_tacho_timer); -} - -void hp9825_tape_device::adjust_hole_timer() -{ - time_to_distance(get_next_hole() , m_next_hole_pos , m_hole_timer); -} - -unsigned hp9825_tape_device::current_track() const -{ - return !BIT(m_cmd_reg , CMD_REG_TRACK_SEL_BIT); -} - -constexpr hti_format_t::tape_pos_t hp9825_tape_device::bit_size(bool bit) -{ - return bit ? hti_format_t::ONE_BIT_LEN : hti_format_t::ZERO_BIT_LEN; } void hp9825_tape_device::start_rd_wr(bool recalc) { - if (fabs(m_speed) >= MIN_RD_SPEED && BIT(m_cmd_reg , CMD_REG_WR_GATE_BIT)) { + if (m_tape->is_above_threshold() && BIT(m_cmd_reg , CMD_REG_WR_GATE_BIT)) { // Reading - if (m_rw_stat != RW_READING || recalc) { - stop_rd_wr(); - LOG_DBG("Start RD @%d s=%f t=%u\n" , m_tape_pos , m_speed , current_track()); - m_rd_it_valid = m_image.next_data(current_track() , m_tape_pos , is_actual_dir_fwd() , false , m_rd_it); - m_rw_stat = RW_READING; - load_rd_word(); - } - } else if (!m_accelerating && !BIT(m_cmd_reg , CMD_REG_WR_GATE_BIT) && BIT(m_cmd_reg , CMD_REG_THRESHOLD_BIT)) { + m_tape->set_op(hp_dc100_tape_device::OP_READ , recalc); + } else if (!m_tape->is_accelerating() && !BIT(m_cmd_reg , CMD_REG_WR_GATE_BIT) && BIT(m_cmd_reg , CMD_REG_THRESHOLD_BIT)) { // Data writing - if (m_rw_stat != RW_WRITING) { - stop_rd_wr(); - // Start WR, only LS FWD is allowed - if (m_speed == SLOW_SPEED) { - LOG_DBG("Start WR @%d\n" , m_tape_pos); - // Looking for sync - m_bit_idx = 17; - m_rw_word = 0; - time_to_distance(bit_size(true) , m_next_bit_pos , m_bit_timer); - m_rw_stat = RW_WRITING; - } else { - LOG("Starting WR s=%f ???\n" , m_speed); - } - } + m_tape->set_op(hp_dc100_tape_device::OP_WRITE); } else if (!BIT(m_cmd_reg , CMD_REG_WR_GATE_BIT) && !BIT(m_cmd_reg , CMD_REG_THRESHOLD_BIT)) { // Gap writing - if (m_rw_stat != RW_WRITING_GAP) { - stop_rd_wr(); - LOG_DBG("Start GAP @%d\n" , m_tape_pos); - m_gap_start = m_tape_pos; - m_rw_stat = RW_WRITING_GAP; - } + m_tape->set_op(hp_dc100_tape_device::OP_ERASE); } else { - stop_rd_wr(); - } -} - -void hp9825_tape_device::load_rd_word() -{ - if (m_rd_it_valid) { - if (is_moving_fwd()) { - m_bit_idx = 0; - } else { - m_bit_idx = 16; - } - // This is actually the nearest end (dir is inverted) - m_next_bit_pos = hti_format_t::farthest_end(m_rd_it , !is_actual_dir_fwd()); - LOG_DBG("Valid np=%d\n" , m_next_bit_pos); - time_to_distance(m_next_bit_pos - m_tape_pos , m_next_bit_pos , m_bit_timer); - } else { - LOG_DBG("Invalid\n"); - stop_rd_wr(); - } -} - -void hp9825_tape_device::rd_bit(bool bit) -{ - m_short_gap_timer->b_w(1); - m_short_gap_timer->b_w(0); - m_long_gap_timer->b_w(1); - m_long_gap_timer->b_w(0); - m_data_out = m_valid_bits && bit; - if (BIT(m_cmd_reg , CMD_REG_FLG_SEL_BIT)) { - set_flg(true); - } - m_trans_cnt++; - LOG_DBG("TC %u IG %d VB %d\n" , m_trans_cnt , m_in_gap , m_valid_bits); - if ((m_trans_cnt & 0x0c) == 0x0c) { - m_valid_bits = true; - } - if (BIT(m_trans_cnt , 2) && m_in_gap) { - m_in_gap = false; - m_long_gap_timer->a_w(m_in_gap); - update_sts(); + m_tape->set_op(hp_dc100_tape_device::OP_IDLE); } } - -void hp9825_tape_device::wr_bit(bool bit) -{ - LOG_DBG("WR %d idx=%u\n" , bit , m_bit_idx); - m_rw_word <<= 1; - m_rw_word |= bit; - - // A bit of heuristic here to achieve synchronization (i.e. find word boundary in bit stream) - if (m_bit_idx >= 17 && m_bit_idx < (17 + 16)) { - m_bit_idx++; - } else if (m_bit_idx == (17 + 16) && (m_rw_word & 3) == 3) { - m_bit_idx = 16; - } - if (m_bit_idx < 16) { - m_bit_idx++; - } else if (m_bit_idx == 16) { - // Write word - if (!BIT(m_rw_word , 0)) { - LOG_DBG("Sync lost! w=%05x\n" , m_rw_word & 0x1ffff); - } else { - hti_format_t::tape_word_t w = (hti_format_t::tape_word_t)(m_rw_word >> 1); - hti_format_t::tape_pos_t wr_pos = m_tape_pos - hti_format_t::word_length(w) + hti_format_t::ONE_BIT_LEN; - LOG_DBG("Wr word %04x @%d\n" , w , wr_pos); - m_image.write_word(current_track() , wr_pos , w , wr_pos); - m_image_dirty = true; - m_bit_idx = 0; - } - } -} - -void hp9825_tape_device::stop_rd_wr() -{ - if (m_rw_stat == RW_WRITING_GAP) { - LOG_DBG("Wr gap from %d to %d\n" , m_gap_start , m_tape_pos); - m_image.write_gap(current_track() , m_gap_start , m_tape_pos); - m_image_dirty = true; - } - m_bit_timer->reset(); - m_rw_stat = RW_IDLE; -} - |