From 73b6d39404afefa0ec26c9c0f701cfdb20bd977d Mon Sep 17 00:00:00 2001 From: fulivi Date: Mon, 22 Nov 2021 14:00:36 +0100 Subject: hp_taco: added support for writing hp9825-format tapes (#8860) --- src/devices/machine/hp_taco.cpp | 74 +++++++++++++++++++++++++---------------- src/devices/machine/hp_taco.h | 1 + 2 files changed, 47 insertions(+), 28 deletions(-) diff --git a/src/devices/machine/hp_taco.cpp b/src/devices/machine/hp_taco.cpp index 5be1a1ebc9a..fc95c72e454 100644 --- a/src/devices/machine/hp_taco.cpp +++ b/src/devices/machine/hp_taco.cpp @@ -28,8 +28,8 @@ // according to flow charts in [1] // - Handling of error conditions, R/W bits, tachometer ticks and gaps according to [1] // What's not in: -// - Commands that are not used at all by the software I analyzed, especially those that -// write tapes in HP9825 format. They could be added easily, though. +// - Commands that are not used at all by the software I analyzed. They could be added easily, +// though. // - Accurate execution times of commands // - Handling of FLG signal: the emulated chip always reports itself as ready for writing. // - Read threshold is ignored. Real tapes could be read with either a low or high threshold. @@ -243,7 +243,7 @@ enum cmd_t : uint8_t { CMD_ERASE = 0b000100, // Erase tape CMD_WR_REVERSAL = 0b000101, // Write flux reversal (*) CMD_WR = 0b000110, // Write - CMD_WR_9825 = 0b000111, // Write 9825 (*) + CMD_WR_9825 = 0b000111, // Write 9825 CMD_STOP = 0b001000, // Stop CMD_STOP_INT = 0b001001, // Stop & interrupt CMD_SET_TRACK = 0b001100, // Set track @@ -262,10 +262,10 @@ enum cmd_t : uint8_t { CMD_WR_GAP_N_TACH = 0b101100, // Write gap of N tach CMD_INT_N_GAP = 0b110000, // Interrupt on N gap CMD_WR_SYNC = 0b110010, // Write synchronous - CMD_WR_SYNC_9825 = 0b110011, // Write synchronous 9825 (*) + CMD_WR_SYNC_9825 = 0b110011, // Write synchronous 9825 CMD_INT_N_TACH_22 = 0b110100, // Interrupt on N tach after 22 ips CMD_WR_CSUM = 0b110110, // Write checksum - CMD_WR_CSUM_9825 = 0b110111, // Write checksum 9825 (*) + CMD_WR_CSUM_9825 = 0b110111, // Write checksum 9825 CMD_INT_STOP_N_TACH = 0b111000, // Interrupt and stop on N tach CMD_INT_STOP_N_TACH1= 0b111001, // Interrupt and stop on N tach (int when stopped) CMD_RD_6UPD = 0b111010, // Read 6% update @@ -479,35 +479,34 @@ WRITE_LINE_MEMBER(hp_taco_device::rd_bit_w) // Synchronized LOG_RW("RD synced!\n"); m_cmd_state = CMD_PH2; - m_bit_idx = BIT(m_cmd_reg , CMD_ST_G0) ? 16 : 15; + m_bit_idx = BIT(m_cmd_reg , CMD_ST_G0) ? 17 : 15; m_working_reg = 0; } } else if (m_cmd_state == CMD_PH2) { - if (m_bit_idx == 16) { + if (m_bit_idx == 17) { + // 9825 format: skip first 17th bit after preamble + m_bit_idx = 15; + break; + } else if (m_bit_idx != 16 && state) { // Skip 17th bit when reading in 9825 format - m_bit_idx--; - } else { - if (state) { - BIT_SET(m_working_reg , m_bit_idx); - } - if (m_bit_idx) { - m_bit_idx--; - } else { - m_data_reg = m_working_reg; - m_bit_idx = BIT(m_cmd_reg , CMD_ST_G0) ? 16 : 15; - m_working_reg = 0; - if (!BIT(m_cmd_reg , CMD_ST_G2)) { - update_checksum(m_data_reg); - } - LOG_RW("RD word %04x csum=%04x\n" , m_data_reg , m_checksum_reg); - irq_w(true); + BIT_SET(m_working_reg , m_bit_idx); + } + if (adv_bit_idx()) { + m_data_reg = m_working_reg; + m_working_reg = 0; + if (!BIT(m_cmd_reg , CMD_ST_G2)) { + update_checksum(m_data_reg); } + LOG_RW("RD word %04x csum=%04x\n" , m_data_reg , m_checksum_reg); + irq_w(true); } } break; case CMD_WR_SYNC: + case CMD_WR_SYNC_9825: case CMD_WR_CSUM: + case CMD_WR_CSUM_9825: if (m_cmd_state == CMD_PH1) { LOG_RW("WR synced\n"); m_cmd_state = CMD_PH2; @@ -526,13 +525,16 @@ READ_LINE_MEMBER(hp_taco_device::wr_bit_r) { bool bit = false; if (is_cmd_wr(m_cmd_reg) && m_cmd_state == CMD_PH2) { - bit = BIT(m_working_reg , m_bit_idx); - if (m_bit_idx) { - m_bit_idx--; + if (m_bit_idx == 16) { + // HP9825 format: 17th bit + bit = true; } else { - m_bit_idx = 15; + bit = BIT(m_working_reg , m_bit_idx); + } + if (adv_bit_idx()) { m_working_reg = m_data_reg; - if (get_cmd(m_cmd_reg) != CMD_WR_CSUM) { + // Bit 0 selects HP9825 mode: it is to be ignored here + if ((get_cmd(m_cmd_reg) & ~BIT_MASK(0)) != CMD_WR_CSUM) { update_checksum(m_data_reg); } LOG_RW("WR word %04x csum=%04x\n" , m_working_reg , m_checksum_reg); @@ -810,6 +812,16 @@ void hp_taco_device::start_wr() m_evd_timer->reset(); } +bool hp_taco_device::adv_bit_idx() +{ + if (m_bit_idx) { + m_bit_idx--; + } else { + m_bit_idx = BIT(m_cmd_reg , CMD_ST_G0) ? 16 : 15; + } + return m_bit_idx == 15; +} + void hp_taco_device::update_checksum(uint16_t data) { // Update checksum with data @@ -846,6 +858,7 @@ void hp_taco_device::cmd_fsm() break; case CMD_WR: + case CMD_WR_9825: if (m_cmd_state == CMD_PH0 && is_at_slow_speed()) { m_cmd_state = CMD_PH2; m_bit_idx = 15; @@ -887,7 +900,9 @@ void hp_taco_device::cmd_fsm() break; case CMD_WR_SYNC: + case CMD_WR_SYNC_9825: case CMD_WR_CSUM: + case CMD_WR_CSUM_9825: if (m_cmd_state == CMD_PH0 && is_at_slow_speed()) { m_cmd_state = CMD_PH1; start_rd(); @@ -1003,8 +1018,11 @@ void hp_taco_device::start_cmd_exec(uint16_t new_cmd_reg) break; case CMD_WR: + case CMD_WR_9825: case CMD_WR_SYNC: + case CMD_WR_SYNC_9825: case CMD_WR_CSUM: + case CMD_WR_CSUM_9825: // 1. Wait for tape to reach 22 ips // 2. Wait for data to begin (not for CMD_WR) // 3. Write words on tape diff --git a/src/devices/machine/hp_taco.h b/src/devices/machine/hp_taco.h index 243b79e98ba..88ab82f2579 100644 --- a/src/devices/machine/hp_taco.h +++ b/src/devices/machine/hp_taco.h @@ -110,6 +110,7 @@ private: bool is_at_slow_speed() const; void start_rd(); void start_wr(); + bool adv_bit_idx(); void update_checksum(uint16_t data); void cmd_fsm(); static uint8_t get_cmd(uint16_t cmd_reg); -- cgit v1.2.3