summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/machine/hp9825_tape.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/machine/hp9825_tape.cpp')
-rw-r--r--src/mame/machine/hp9825_tape.cpp719
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;
-}
-