summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/hp9845_io/hp9885.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/bus/hp9845_io/hp9885.cpp')
-rw-r--r--src/devices/bus/hp9845_io/hp9885.cpp489
1 files changed, 305 insertions, 184 deletions
diff --git a/src/devices/bus/hp9845_io/hp9885.cpp b/src/devices/bus/hp9845_io/hp9885.cpp
index ed782054504..5e5ad89482a 100644
--- a/src/devices/bus/hp9845_io/hp9885.cpp
+++ b/src/devices/bus/hp9845_io/hp9885.cpp
@@ -56,7 +56,7 @@
| 1 1|Unit#| Track # [0..76] |Sector#[0..29]|
+-----+-----+--------------------+--------------+
- *FORMAT TRACK* (not implemented yet)
+ *FORMAT TRACK*
+-----------------------------------------------+
|15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0|
@@ -116,20 +116,20 @@
=====================
Images can be in two formats: MFI & HPI.
- A pre-formatted image must be used as formatting is not supported.
- It's not possible to format images for two reasons: the format
- command is not implemented yet and no dump of the disk system tape
- cartridge (HP part no. 09885-90035) is available.
- The latter is needed during format operation to create the so-called
- bootstraps on disk, which in turn are needed by 9825 systems.
+ 9825 systems with 98217 mass storage ROM store the code of most disk commands
+ on the disk itself in the so-called bootstrap area. Initializing this area
+ during formatting is not supported at the moment as no dump of the disk system
+ tape cartridge (HP part no. 09885-90035) is available. This tape holds the
+ code to be copied into the bootstrap area.
A pre-formatted image (9825_empty.hpi) is available here:
http://www.hpmuseum.net/software/9825_discs.zip
+ Other combinations of system and mass storage ROM (e.g. 9825 with 98228 ROM)
+ do not use bootstrap area at all.
TODO
====
- + Implement missing commands
- + PRESET
+ + Implement missing command
Acknowledgments
===============
@@ -146,6 +146,7 @@
#include "emu.h"
#include "hp9885.h"
+#include "formats/fs_hp98x5.h"
#include "formats/hpi_dsk.h"
// Debugging
@@ -184,13 +185,6 @@ namespace {
// device type definition
DEFINE_DEVICE_TYPE(HP9885, hp9885_device, "hp9885" , "HP9885 floppy drive")
-// Timers
-enum {
- FSM_TMR_ID,
- HEAD_TMR_ID,
- BIT_BYTE_TMR_ID
-};
-
// Constants
constexpr unsigned MAX_TRACK = 76; // Maximum valid track
constexpr unsigned MAX_SECTOR = 29; // Maximum valid sector
@@ -203,6 +197,7 @@ constexpr uint16_t PASSWORD = 0xae87; // "Password" to enable commands
constexpr unsigned HALF_CELL_US = 1; // Half bit cell duration (µs)
constexpr unsigned STATUS_DELAY_US = 100; // Status delay (µs)
constexpr unsigned MISSED_ID_REVS = 2; // Disk rotations to stop ID search
+constexpr uint16_t FORMAT_DATA = 0xc6c6; // Data written into sectors when formatting
// Bits in status word
constexpr unsigned STS_DISK_CHANGED = 2; // Disk changed
@@ -268,7 +263,9 @@ void hp9885_device::output_w(uint16_t data)
void hp9885_device::ext_control_w(uint8_t data)
{
LOG_HS("EXT CTRL %u\n" , data);
- if (BIT(data , 0) &&
+ if (BIT(data, 1)) {
+ device_reset();
+ } else if (BIT(data , 0) &&
!BIT(m_status , STS_XFER_COMPLETE) &&
(m_op == OP_READ || m_op == OP_WRITE)) {
// CTL0 terminates current data transfer
@@ -279,7 +276,7 @@ void hp9885_device::ext_control_w(uint8_t data)
}
}
-WRITE_LINE_MEMBER(hp9885_device::pctl_w)
+void hp9885_device::pctl_w(int state)
{
m_pctl = state;
if (m_pctl) {
@@ -293,19 +290,25 @@ WRITE_LINE_MEMBER(hp9885_device::pctl_w)
update_busy();
}
-WRITE_LINE_MEMBER(hp9885_device::io_w)
+void hp9885_device::io_w(int state)
{
LOG_HS("I/O = %d\n" , state);
}
-WRITE_LINE_MEMBER(hp9885_device::preset_w)
+void hp9885_device::preset_w(int state)
{
LOG("PRESET = %d\n" , state);
+ if (state) {
+ device_reset();
+ }
}
static void hp9885_floppy_formats(format_registration &fr)
{
fr.add(FLOPPY_HPI_FORMAT);
+ fr.add(fs::HP9825);
+ fr.add(fs::HP9831);
+ fr.add(fs::HP9845);
};
void hp9885_device::device_add_mconfig(machine_config &config)
@@ -333,12 +336,13 @@ void hp9885_device::device_start()
save_item(NAME(m_sector_cnt));
save_item(NAME(m_word_cnt));
save_item(NAME(m_rev_cnt));
+ save_item(NAME(m_format_track));
save_item(NAME(m_am_detector));
save_item(NAME(m_crc));
- m_fsm_timer = timer_alloc(FSM_TMR_ID);
- m_head_timer = timer_alloc(HEAD_TMR_ID);
- m_bit_byte_timer = timer_alloc(BIT_BYTE_TMR_ID);
+ m_fsm_timer = timer_alloc(FUNC(hp9885_device::fsm_tick), this);
+ m_head_timer = timer_alloc(FUNC(hp9885_device::head_tick), this);
+ m_bit_byte_timer = timer_alloc(FUNC(hp9885_device::bit_byte_tick), this);
m_drive = m_drive_connector->get_device();
@@ -348,6 +352,7 @@ void hp9885_device::device_start()
void hp9885_device::device_reset()
{
+ LOG("Reset\n");
eir_w(0);
psts_w(1);
m_dskchg = true;
@@ -356,175 +361,249 @@ void hp9885_device::device_reset()
m_seek_track = 0;
m_seek_sector = 0;
m_fsm_state = FSM_RECALIBRATING;
+ m_head_state = HEAD_UNLOADED;
+ m_head_timer->reset();
+ m_op = OP_NONE;
set_state(FSM_IDLE);
}
-void hp9885_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(hp9885_device::fsm_tick)
{
- LOG_TIMER("Tmr %.06f ID %d FSM %d HD %d\n" , machine().time().as_double() , id , m_fsm_state , m_head_state);
+ LOG_TIMER("FSM Tmr %s %d HD %d\n" , machine().time().as_string(6) , m_fsm_state , m_head_state);
+ do_FSM();
+}
- switch (id) {
- case FSM_TMR_ID:
+TIMER_CALLBACK_MEMBER(hp9885_device::head_tick)
+{
+ LOG_TIMER("HD Tmr %s FSM %d HD %d\n" , machine().time().as_string(6) , m_fsm_state , m_head_state);
+ if (m_head_state == HEAD_SETTLING) {
+ LOG_HEAD("%s Head loaded\n" , machine().time().as_string(6));
+ m_head_state = HEAD_LOADED;
+ // Trigger actions to be done on head loading
do_FSM();
- break;
+ m_head_timer->adjust(attotime::from_msec(HEAD_TO_MS - HD_SETTLE_MS));
+ } else {
+ LOG_HEAD("%s Head unloaded\n" , machine().time().as_string(6));
+ m_head_state = HEAD_UNLOADED;
+ }
+}
- case HEAD_TMR_ID:
- if (m_head_state == HEAD_SETTLING) {
- LOG_HEAD("%.06f Head loaded\n" , machine().time().as_double());
- m_head_state = HEAD_LOADED;
- // Trigger actions to be done on head loading
- do_FSM();
- m_head_timer->adjust(attotime::from_msec(HEAD_TO_MS - HD_SETTLE_MS));
- } else {
- LOG_HEAD("%.06f Head unloaded\n" , machine().time().as_double());
- m_head_state = HEAD_UNLOADED;
- }
- break;
+TIMER_CALLBACK_MEMBER(hp9885_device::bit_byte_tick)
+{
+ LOG_TIMER("BIT Tmr %s FSM %d HD %d\n" , machine().time().as_string(6) , m_fsm_state , m_head_state);
- case BIT_BYTE_TMR_ID:
+ switch (m_fsm_state) {
+ case FSM_WAIT_ID_AM:
+ case FSM_WAIT_DATA_AM:
{
- switch (m_fsm_state) {
- case FSM_WAIT_ID_AM:
- case FSM_WAIT_DATA_AM:
- {
- attotime edge;
- attotime tm;
- edge = m_drive->get_next_transition(m_pll.ctime);
- bool half_bit = m_pll.feed_read_data(tm , edge , attotime::never);
- m_am_detector <<= 1;
- m_am_detector |= half_bit;
- if (m_am_detector == 0x55552a54) {
- // ID AM
- // CDCDCDCDCDCDCDCD
- // 0 0 0 0 1 1 1 0
- // 0 1 1 1 0 0 0 0
- LOG_DISK("Got ID AM\n");
+ attotime edge;
+ attotime tm;
+ edge = m_drive->get_next_transition(m_pll.ctime);
+ bool half_bit = m_pll.feed_read_data(tm , edge , attotime::never);
+ m_am_detector <<= 1;
+ m_am_detector |= half_bit;
+ if (m_am_detector == 0x55552a54) {
+ // ID AM
+ // CDCDCDCDCDCDCDCD
+ // 0 0 0 0 1 1 1 0
+ // 0 1 1 1 0 0 0 0
+ LOG_DISK("Got ID AM\n");
+ preset_crc();
+ m_word_cnt = 2;
+ set_state(FSM_RD_ID);
+ } else if (m_am_detector == 0x55552a44) {
+ // DATA AM
+ // CDCDCDCDCDCDCDCD
+ // 0 0 0 0 1 0 1 0
+ // 0 1 1 1 0 0 0 0
+ LOG_DISK("Got Data AM\n");
+ if (m_fsm_state == FSM_WAIT_DATA_AM) {
+ m_rev_cnt = 0;
+ if (BIT(m_status , STS_XFER_COMPLETE)) {
+ output_status();
+ return;
+ } else {
preset_crc();
- m_word_cnt = 2;
- set_state(FSM_RD_ID);
- } else if (m_am_detector == 0x55552a44) {
- // DATA AM
- // CDCDCDCDCDCDCDCD
- // 0 0 0 0 1 0 1 0
- // 0 1 1 1 0 0 0 0
- LOG_DISK("Got Data AM\n");
- if (m_fsm_state == FSM_WAIT_DATA_AM) {
- m_rev_cnt = 0;
- if (BIT(m_status , STS_XFER_COMPLETE)) {
- output_status();
- return;
- } else {
- preset_crc();
- if (m_op == OP_READ) {
- m_word_cnt = 129;
- set_state(FSM_RD_DATA);
- } else {
- m_word_cnt = 130;
- set_state(FSM_WR_DATA);
- m_pll.start_writing(m_pll.ctime);
- m_had_transition = false;
- wr_word(m_input);
- set_ibf(false);
- }
- }
+ if (m_op == OP_READ) {
+ m_word_cnt = 129;
+ set_state(FSM_RD_DATA);
+ } else {
+ m_word_cnt = 130;
+ set_state(FSM_WR_DATA);
+ m_pll.start_writing(m_pll.ctime);
+ m_had_transition = false;
+ wr_word(m_input);
+ set_ibf(false);
}
}
}
- break;
+ }
+ }
+ break;
- case FSM_RD_ID:
- {
- // This is needed when state is switched to one of the AM waiting states
- m_am_detector = 0;
- auto word = rd_word();
- m_word_cnt--;
- LOG_DISK("W %04x C %u\n" , word , m_word_cnt);
- if (m_word_cnt && word != ((m_seek_sector << 8) | m_track)) {
- set_state(FSM_WAIT_ID_AM);
- } else if (m_word_cnt == 0) {
- if (m_crc) {
- LOG_DISK("Wrong CRC in ID\n");
- set_state(FSM_WAIT_ID_AM);
- } else {
- LOG_DISK("Sector found\n");
- set_state(FSM_WAIT_DATA_AM);
- }
- }
+ case FSM_RD_ID:
+ {
+ // This is needed when state is switched to one of the AM waiting states
+ m_am_detector = 0;
+ auto word = rd_word();
+ m_word_cnt--;
+ LOG_DISK("W %04x C %u\n" , word , m_word_cnt);
+ if (m_word_cnt && word != ((m_seek_sector << 8) | m_track)) {
+ set_state(FSM_WAIT_ID_AM);
+ } else if (m_word_cnt == 0) {
+ if (m_crc) {
+ LOG_DISK("Wrong CRC in ID\n");
+ set_state(FSM_WAIT_ID_AM);
+ } else {
+ LOG_DISK("Sector found\n");
+ set_state(FSM_WAIT_DATA_AM);
}
- break;
+ }
+ }
+ break;
- case FSM_RD_DATA:
- {
- auto word = rd_word();
- m_word_cnt--;
- LOG_DISK("W %04x C %u\n" , word , m_word_cnt);
- if (m_word_cnt >= 1) {
- if (!BIT(m_status , STS_XFER_COMPLETE)) {
- m_output = word;
- m_obf = true;
- update_busy();
- }
- } else if (m_word_cnt == 0) {
- if (m_crc) {
- LOG_DISK("Wrong CRC in data\n");
- }
- // Move to next sector
- adv_sector();
- if (BIT(m_status , STS_XFER_COMPLETE) || m_sector_cnt == 0) {
- BIT_SET(m_status , STS_XFER_COMPLETE);
- output_status();
- } else {
- set_state(FSM_POSITIONING);
- do_FSM();
- }
- return;
- }
+ case FSM_RD_DATA:
+ {
+ auto word = rd_word();
+ m_word_cnt--;
+ LOG_DISK("W %04x C %u\n" , word , m_word_cnt);
+ if (m_word_cnt >= 1) {
+ if (!BIT(m_status , STS_XFER_COMPLETE)) {
+ m_output = word;
+ m_obf = true;
+ update_busy();
}
- break;
+ } else if (m_word_cnt == 0) {
+ if (m_crc) {
+ LOG_DISK("Wrong CRC in data\n");
+ }
+ // Move to next sector
+ adv_sector();
+ if (BIT(m_status , STS_XFER_COMPLETE) || m_sector_cnt == 0) {
+ BIT_SET(m_status , STS_XFER_COMPLETE);
+ output_status();
+ } else {
+ set_state(FSM_POSITIONING);
+ do_FSM();
+ }
+ return;
+ }
+ }
+ break;
- case FSM_WR_DATA:
- {
- m_word_cnt--;
- if (m_word_cnt > 2) {
- if (BIT(m_status , STS_XFER_COMPLETE)) {
- wr_word(0);
- } else {
- wr_word(m_input);
- if (m_word_cnt > 3) {
- set_ibf(false);
- }
- }
- } else if (m_word_cnt == 2) {
- wr_word(m_crc);
- } else if (m_word_cnt == 1) {
- // Post-amble
- wr_word(0);
- } else {
- m_pll.stop_writing(m_drive , m_pll.ctime);
- // Move to next sector
- adv_sector();
- if (BIT(m_status , STS_XFER_COMPLETE) || m_sector_cnt == 0) {
- BIT_SET(m_status , STS_XFER_COMPLETE);
- output_status();
- } else {
- set_ibf(false);
- set_state(FSM_POSITIONING);
- do_FSM();
- }
- return;
+ case FSM_WR_DATA:
+ {
+ m_word_cnt--;
+ if (m_word_cnt > 2) {
+ if (BIT(m_status , STS_XFER_COMPLETE)) {
+ wr_word(0);
+ } else {
+ wr_word(m_input);
+ if (m_word_cnt > 3) {
+ set_ibf(false);
}
}
- break;
-
- default:
- LOG("Invalid FSM state %d\n" , m_fsm_state);
- set_state(FSM_IDLE);
+ } else if (m_word_cnt == 2) {
+ wr_word(m_crc);
+ } else if (m_word_cnt == 1) {
+ // Post-amble
+ wr_word(0);
+ } else {
+ m_pll.stop_writing(m_drive , m_pll.ctime);
+ // Move to next sector
+ adv_sector();
+ if (BIT(m_status , STS_XFER_COMPLETE) || m_sector_cnt == 0) {
+ BIT_SET(m_status , STS_XFER_COMPLETE);
+ output_status();
+ } else {
+ set_ibf(false);
+ set_state(FSM_POSITIONING);
+ do_FSM();
+ }
return;
}
- timer.adjust(m_pll.ctime - machine().time());
}
break;
+
+ case FSM_FORMATTING:
+ {
+ // m_word_cnt when formatting one sector
+ // =================
+ // 168 Sync 0000
+ // 167 Sync 0000
+ // 166 Sync FFFF
+ // 165 Sync FFFF
+ // 164 ID AM 70/0E
+ // 163 Sec/Trk
+ // 162 ID CRC
+ // 161 ID post-amble
+ // 160..153
+ // Gap 1 0000
+ // 152 Sync 0000
+ // 151 Sync 0000
+ // 150 Sync FFFF
+ // 149 Sync FFFF
+ // 148 DATA AM 50/0E
+ // 147..20
+ // Sector C6C6
+ // 19 Data CRC
+ // 18 Data post-amble
+ // 17..1
+ // Gap 2 0000
+ if (m_word_cnt == 164) {
+ wr_byte(0x70, 0x0e);
+ } else if (m_word_cnt == 148) {
+ wr_byte(0x50, 0x0e);
+ } else {
+ uint16_t word = 0;
+ if (m_word_cnt == 163 ||
+ m_word_cnt == 147) {
+ preset_crc();
+ }
+ if (m_word_cnt == 166 ||
+ m_word_cnt == 165 ||
+ m_word_cnt == 150 ||
+ m_word_cnt == 149) {
+ word = 0xffff;
+ } else if (m_word_cnt == 163) {
+ // Get sector # from CPU
+ LOG("Format: sector %u\n" , m_input);
+ word = ((m_input & 0xff) << 8) | (m_format_track & 0xff);
+ if (m_sector_cnt < MAX_SECTOR) {
+ set_ibf(false);
+ }
+ } else if (m_word_cnt == 162 ||
+ m_word_cnt == 19) {
+ word = m_crc;
+ } else if (20 <= m_word_cnt &&
+ m_word_cnt <= 147) {
+ word = FORMAT_DATA;
+ }
+ wr_word(word);
+ }
+ if (--m_word_cnt == 0) {
+ if (++m_sector_cnt > MAX_SECTOR) {
+ LOG("Format: final gap\n");
+ set_state(FSM_FORMAT_END);
+ } else {
+ // Next sector
+ m_word_cnt = 168;
+ }
+ }
+ }
+ break;
+
+ case FSM_FORMAT_END:
+ // Keep writing 0s until index pulse comes
+ wr_word(0);
+ break;
+
+ default:
+ LOG("Invalid FSM state %d\n" , m_fsm_state);
+ set_state(FSM_IDLE);
+ return;
}
+ m_bit_byte_timer->adjust(m_pll.ctime - machine().time());
}
void hp9885_device::floppy_ready_cb(floppy_image_device *floppy , int state)
@@ -538,19 +617,39 @@ void hp9885_device::floppy_ready_cb(floppy_image_device *floppy , int state)
void hp9885_device::floppy_index_cb(floppy_image_device *floppy , int state)
{
- if (state && m_rev_cnt && --m_rev_cnt == 0) {
- // Sector not found
- LOG("Sector not found\n");
- stop_rdwr();
- set_error(ERR_ID_ERROR);
- output_status(true);
+ if (state) {
+ if (m_fsm_state == FSM_WAIT_INDEX) {
+ LOG("Format: got index\n");
+ set_state(FSM_FORMATTING);
+ // See bit_byte_tick function
+ m_word_cnt = 167;
+ m_pll.set_clock(attotime::from_usec(HALF_CELL_US));
+ m_pll.start_writing(machine().time());
+ m_pll.read_reset(machine().time());
+ m_had_transition = false;
+ // Start by writing 1st sync word
+ wr_word(0);
+ m_sector_cnt = 0;
+ m_bit_byte_timer->adjust(m_pll.ctime - machine().time());
+ } else if (m_fsm_state == FSM_FORMAT_END) {
+ LOG("Format: ended\n");
+ m_pll.stop_writing(m_drive , m_pll.ctime);
+ BIT_SET(m_status , STS_XFER_COMPLETE);
+ output_status();
+ } else if (m_rev_cnt && --m_rev_cnt == 0) {
+ // Sector not found
+ LOG("Sector not found\n");
+ stop_rdwr();
+ set_error(ERR_ID_ERROR);
+ output_status(true);
+ }
}
}
void hp9885_device::set_state(int new_state)
{
if (m_fsm_state != new_state) {
- LOG("%.06f FSM %d->%d\n" , machine().time().as_double() , m_fsm_state , new_state);
+ LOG("%s FSM %d->%d\n" , machine().time().as_string(6) , m_fsm_state , new_state);
m_fsm_state = new_state;
if (m_fsm_state == FSM_IDLE) {
m_op = OP_NONE;
@@ -671,8 +770,20 @@ void hp9885_device::new_word()
uint8_t sect_no = m_input & 0x1f;
if (sect_no == 0x1e) {
// Format
- LOG("Format\n");
- // TODO:
+ LOG("Format track %u\n", track_no);
+ init_status(unit_no);
+ if (!BIT(m_status , STS_NOT_RDY) && !BIT(m_status , STS_WRITE_PROTECT)) {
+ m_op = OP_FORMAT;
+ m_format_track = track_no;
+ set_state(FSM_POSITIONING);
+ if (load_head()) {
+ m_fsm_timer->adjust(attotime::zero);
+ }
+ set_ibf(false);
+ } else {
+ encode_error(true);
+ output_status(true);
+ }
} else if (sect_no == 0x1f) {
switch (track_no) {
case 0x7c:
@@ -746,7 +857,7 @@ void hp9885_device::new_word()
break;
default:
- if (m_op != OP_WRITE) {
+ if (m_op != OP_WRITE && m_op != OP_FORMAT) {
LOG("Got data in state %d!\n" , m_fsm_state);
}
}
@@ -783,6 +894,10 @@ void hp9885_device::do_FSM()
// Set seek complete
BIT_SET(m_status , STS_SEEK_COMPLETE);
output_status();
+ } else if (m_op == OP_FORMAT) {
+ // Format
+ LOG("Format: waiting for index\n");
+ set_state(FSM_WAIT_INDEX);
} else {
// Get status
output_status();
@@ -828,13 +943,13 @@ bool hp9885_device::load_head()
switch (m_head_state) {
case HEAD_UNLOADED:
case HEAD_SETTLING:
- LOG_HEAD("%.06f Loading head..\n" , machine().time().as_double());
+ LOG_HEAD("%s Loading head..\n" , machine().time().as_string(6));
m_head_state = HEAD_SETTLING;
m_head_timer->adjust(attotime::from_msec(HD_SETTLE_MS));
return false;
case HEAD_LOADED:
- LOG_HEAD("%.06f Keep head loaded\n" , machine().time().as_double());
+ LOG_HEAD("%s Keep head loaded\n" , machine().time().as_string(6));
m_head_timer->adjust(attotime::from_msec(HEAD_TO_MS));
return true;
@@ -861,7 +976,7 @@ void hp9885_device::one_step(bool outward)
m_track++;
}
}
- LOG_HEAD("%.06f Step to trk %u\n" , machine().time().as_double() , m_track);
+ LOG_HEAD("%s Step to trk %u\n" , machine().time().as_string(6) , m_track);
m_drive->dir_w(outward);
m_drive->stp_w(0);
m_drive->stp_w(1);
@@ -911,11 +1026,11 @@ uint16_t hp9885_device::rd_word()
return word;
}
-void hp9885_device::wr_word(uint16_t word)
+void hp9885_device::wr_byte(uint8_t data, uint8_t clock)
{
- for (unsigned i = 0; i < 16; ++i) {
- bool data_bit = BIT(word , i);
- bool clock_bit = !data_bit && !m_had_transition;
+ for (unsigned i = 0; i < 8; ++i) {
+ bool data_bit = BIT(data , i);
+ bool clock_bit = !data_bit && (BIT(clock, i) || !m_had_transition);
m_had_transition = data_bit || clock_bit;
attotime dummy;
@@ -926,6 +1041,12 @@ void hp9885_device::wr_word(uint16_t word)
m_pll.commit(m_drive , m_pll.ctime);
}
+void hp9885_device::wr_word(uint16_t word)
+{
+ wr_byte(uint8_t(word & 0xff), 0);
+ wr_byte(uint8_t(word >> 8), 0);
+}
+
void hp9885_device::preset_crc()
{
m_crc = ~0;