mirror of
https://github.com/holub/mame
synced 2025-04-22 16:31:49 +03:00
Merge pull request #628 from fulivi/hp9845_dev
Hp9845: tape driver added [F. Ulivi]
This commit is contained in:
commit
4d8d9095a1
@ -771,6 +771,18 @@ if (MACHINES["HD64610"]~=null) then
|
||||
}
|
||||
end
|
||||
|
||||
---------------------------------------------------
|
||||
--
|
||||
--@src/devices/machine/hp_taco.h,MACHINES["HP_TACO"] = true
|
||||
---------------------------------------------------
|
||||
|
||||
if (MACHINES["HP_TACO"]~=null) then
|
||||
files {
|
||||
MAME_DIR .. "src/devices/machine/hp_taco.cpp",
|
||||
MAME_DIR .. "src/devices/machine/hp_taco.h",
|
||||
}
|
||||
end
|
||||
|
||||
---------------------------------------------------
|
||||
--
|
||||
--@src/devices/machine/i2cmem.h,MACHINES["I2CMEM"] = true
|
||||
|
@ -398,6 +398,7 @@ MACHINES["ER2055"] = true
|
||||
MACHINES["F3853"] = true
|
||||
MACHINES["HD63450"] = true
|
||||
MACHINES["HD64610"] = true
|
||||
MACHINES["HP_TACO"] = true
|
||||
MACHINES["I2CMEM"] = true
|
||||
MACHINES["I80130"] = true
|
||||
MACHINES["I8089"] = true
|
||||
|
@ -673,12 +673,7 @@ UINT16 hp_hybrid_cpu_device::RM(UINT32 addr)
|
||||
return RIO(CURRENT_PA , addr_wo_bsc - HP_REG_R4_ADDR);
|
||||
|
||||
case HP_REG_IV_ADDR:
|
||||
// Correct?
|
||||
if (!BIT(m_flags , HPHYBRID_IRH_SVC_BIT) && !BIT(m_flags , HPHYBRID_IRL_SVC_BIT)) {
|
||||
return m_reg_IV;
|
||||
} else {
|
||||
return m_reg_IV | CURRENT_PA;
|
||||
}
|
||||
return m_reg_IV;
|
||||
|
||||
case HP_REG_PA_ADDR:
|
||||
return CURRENT_PA;
|
||||
@ -1021,7 +1016,7 @@ void hp_hybrid_cpu_device::check_for_interrupts(void)
|
||||
|
||||
// Do a double-indirect JSM IV,I instruction
|
||||
WM(AEC_CASE_C , ++m_reg_R , m_reg_P);
|
||||
m_reg_P = RM(AEC_CASE_I , RM(HP_REG_IV_ADDR));
|
||||
m_reg_P = RM(AEC_CASE_I , m_reg_IV + CURRENT_PA);
|
||||
m_reg_I = fetch();
|
||||
}
|
||||
|
||||
|
1467
src/devices/machine/hp_taco.cpp
Normal file
1467
src/devices/machine/hp_taco.cpp
Normal file
File diff suppressed because it is too large
Load Diff
169
src/devices/machine/hp_taco.h
Normal file
169
src/devices/machine/hp_taco.h
Normal file
@ -0,0 +1,169 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:F. Ulivi
|
||||
/*********************************************************************
|
||||
|
||||
hp_taco.h
|
||||
|
||||
HP TApe COntroller (5006-3012)
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
#ifndef __HP_TACO_H__
|
||||
#define __HP_TACO_H__
|
||||
|
||||
#include <map>
|
||||
|
||||
#define MCFG_TACO_IRQ_HANDLER(_devcb) \
|
||||
devcb = &hp_taco_device::set_irq_handler(*device , DEVCB_##_devcb);
|
||||
|
||||
#define MCFG_TACO_FLG_HANDLER(_devcb) \
|
||||
devcb = &hp_taco_device::set_flg_handler(*device , DEVCB_##_devcb);
|
||||
|
||||
#define MCFG_TACO_STS_HANDLER(_devcb) \
|
||||
devcb = &hp_taco_device::set_sts_handler(*device , DEVCB_##_devcb);
|
||||
|
||||
class hp_taco_device : public device_t ,
|
||||
public device_image_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
hp_taco_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname);
|
||||
hp_taco_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
|
||||
// static configuration helpers
|
||||
template<class _Object> static devcb_base &set_irq_handler(device_t &device, _Object object) { return downcast<hp_taco_device &>(device).m_irq_handler.set_callback(object); }
|
||||
template<class _Object> static devcb_base &set_flg_handler(device_t &device, _Object object) { return downcast<hp_taco_device &>(device).m_flg_handler.set_callback(object); }
|
||||
template<class _Object> static devcb_base &set_sts_handler(device_t &device, _Object object) { return downcast<hp_taco_device &>(device).m_sts_handler.set_callback(object); }
|
||||
|
||||
// Register read/write
|
||||
DECLARE_WRITE16_MEMBER(reg_w);
|
||||
DECLARE_READ16_MEMBER(reg_r);
|
||||
|
||||
// Flag & status read
|
||||
DECLARE_READ_LINE_MEMBER(flg_r);
|
||||
DECLARE_READ_LINE_MEMBER(sts_r);
|
||||
|
||||
// device_image_interface overrides
|
||||
virtual bool call_load() override;
|
||||
virtual bool call_create(int format_type, option_resolution *format_options) override;
|
||||
virtual void call_unload() override;
|
||||
virtual iodevice_t image_type() const override { return IO_MAGTAPE; }
|
||||
virtual bool is_readable() const override { return true; }
|
||||
virtual bool is_writeable() const override { return true; }
|
||||
virtual bool is_creatable() const override { return true; }
|
||||
virtual bool must_be_loaded() const override { return false; }
|
||||
virtual bool is_reset_on_load() const override { return false; }
|
||||
virtual const char *file_extensions() const override;
|
||||
virtual const option_guide *create_option_guide() const override { return nullptr; }
|
||||
|
||||
// Tape position, 1 unit = 1 inch / (968 * 1024)
|
||||
typedef INT32 tape_pos_t;
|
||||
|
||||
// Words stored on tape
|
||||
typedef UINT16 tape_word_t;
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_config_complete() override;
|
||||
virtual void device_start() override;
|
||||
virtual void device_stop() override;
|
||||
virtual void device_reset() override;
|
||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
|
||||
|
||||
private:
|
||||
// Storage of tracks: mapping from a tape position to word stored there
|
||||
typedef std::map<tape_pos_t , tape_word_t> tape_track_t;
|
||||
|
||||
devcb_write_line m_irq_handler;
|
||||
devcb_write_line m_flg_handler;
|
||||
devcb_write_line m_sts_handler;
|
||||
|
||||
// Registers
|
||||
UINT16 m_data_reg;
|
||||
bool m_data_reg_full;
|
||||
UINT16 m_cmd_reg;
|
||||
UINT16 m_status_reg;
|
||||
UINT16 m_tach_reg;
|
||||
UINT16 m_checksum_reg;
|
||||
UINT16 m_timing_reg;
|
||||
|
||||
// State
|
||||
bool m_irq;
|
||||
bool m_flg;
|
||||
bool m_sts;
|
||||
UINT8 m_cmd_state;
|
||||
|
||||
// Tape position & motion
|
||||
tape_pos_t m_tape_pos;
|
||||
attotime m_start_time; // Tape moving if != never
|
||||
bool m_tape_fwd;
|
||||
bool m_tape_fast;
|
||||
|
||||
// Timers
|
||||
emu_timer *m_tape_timer;
|
||||
emu_timer *m_hole_timer;
|
||||
|
||||
// Content of tape tracks
|
||||
tape_track_t m_tracks[ 2 ];
|
||||
bool m_image_dirty;
|
||||
|
||||
// Reading & writing
|
||||
bool m_tape_wr;
|
||||
tape_pos_t m_rw_pos;
|
||||
UINT16 m_next_word;
|
||||
tape_track_t::iterator m_rd_it;
|
||||
bool m_rd_it_valid;
|
||||
|
||||
// Gap detection
|
||||
tape_pos_t m_gap_detect_start;
|
||||
|
||||
typedef enum {
|
||||
ADV_NO_MORE_DATA,
|
||||
ADV_CONT_DATA,
|
||||
ADV_DISCONT_DATA
|
||||
} adv_res_t;
|
||||
|
||||
void clear_state(void);
|
||||
void irq_w(bool state);
|
||||
void set_error(bool state);
|
||||
unsigned speed_to_tick_freq(void) const;
|
||||
bool pos_offset(tape_pos_t& pos , tape_pos_t offset) const;
|
||||
void move_tape_pos(tape_pos_t delta_pos);
|
||||
void update_tape_pos(void);
|
||||
static void ensure_a_lt_b(tape_pos_t& a , tape_pos_t& b);
|
||||
static bool any_hole(tape_pos_t tape_pos_a , tape_pos_t tape_pos_b);
|
||||
tape_pos_t next_hole(void) const;
|
||||
attotime time_to_distance(tape_pos_t distance) const;
|
||||
attotime time_to_target(tape_pos_t target) const;
|
||||
bool start_tape_cmd(UINT16 cmd_reg , UINT16 must_be_1 , UINT16 must_be_0);
|
||||
void start_tape(UINT16 cmd_reg);
|
||||
void stop_tape(void);
|
||||
tape_track_t& current_track(void);
|
||||
static tape_pos_t word_length(tape_word_t w);
|
||||
static tape_pos_t word_end_pos(const tape_track_t::iterator& it);
|
||||
static void adjust_it(tape_track_t& track , tape_track_t::iterator& it , tape_pos_t pos);
|
||||
void write_word(tape_pos_t start , tape_word_t word , tape_pos_t& length);
|
||||
void write_gap(tape_pos_t a , tape_pos_t b);
|
||||
bool just_gap(tape_pos_t a , tape_pos_t b);
|
||||
tape_pos_t farthest_end(const tape_track_t::iterator& it) const;
|
||||
bool next_data(tape_track_t::iterator& it , tape_pos_t pos , bool inclusive);
|
||||
adv_res_t adv_it(tape_track_t::iterator& it);
|
||||
attotime fetch_next_wr_word(void);
|
||||
attotime time_to_rd_next_word(tape_pos_t& word_rd_pos);
|
||||
bool next_n_gap(tape_pos_t& pos , tape_track_t::iterator it , unsigned n_gaps , tape_pos_t min_gap);
|
||||
bool next_n_gap(tape_pos_t& pos , unsigned n_gaps , tape_pos_t min_gap);
|
||||
void clear_tape(void);
|
||||
void dump_sequence(tape_track_t::const_iterator it_start , unsigned n_words);
|
||||
void save_tape(void);
|
||||
bool load_track(tape_track_t& track);
|
||||
bool load_tape(void);
|
||||
void set_tape_present(bool present);
|
||||
attotime time_to_next_hole(void) const;
|
||||
attotime time_to_tach_pulses(void) const;
|
||||
void start_cmd_exec(UINT16 new_cmd_reg);
|
||||
};
|
||||
|
||||
// device type definition
|
||||
extern const device_type HP_TACO;
|
||||
|
||||
#endif /* __HP_TACO_H__ */
|
@ -16,12 +16,12 @@
|
||||
// - LPU & PPU ROMs
|
||||
// - LPU & PPU RAMs
|
||||
// - Text mode screen
|
||||
// - Keyboard (most of keys)
|
||||
// - Keyboard
|
||||
// - T15 tape drive
|
||||
// What's not yet in:
|
||||
// - Beeper
|
||||
// - Rest of keyboard
|
||||
// - Graphic screen
|
||||
// - Tape drive (this needs some heavy RE of the TACO chip)
|
||||
// - Better naming of tape drive image (it's now "magt", should be "t15")
|
||||
// - Better documentation of this file
|
||||
// - Software list to load optional ROMs
|
||||
// What's wrong:
|
||||
@ -33,6 +33,7 @@
|
||||
#include "cpu/z80/z80.h"
|
||||
#include "softlist.h"
|
||||
#include "cpu/hphybrid/hphybrid.h"
|
||||
#include "machine/hp_taco.h"
|
||||
|
||||
#define BIT_MASK(n) (1U << (n))
|
||||
|
||||
@ -77,7 +78,8 @@ public:
|
||||
m_io_key0(*this , "KEY0"),
|
||||
m_io_key1(*this , "KEY1"),
|
||||
m_io_key2(*this , "KEY2"),
|
||||
m_io_key3(*this , "KEY3")
|
||||
m_io_key3(*this , "KEY3"),
|
||||
m_t15(*this , "t15")
|
||||
{ }
|
||||
|
||||
UINT32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||
@ -90,7 +92,7 @@ public:
|
||||
void vblank_w(screen_device &screen, bool state);
|
||||
|
||||
IRQ_CALLBACK_MEMBER(irq_callback);
|
||||
void update_irl(void);
|
||||
void update_irq(void);
|
||||
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(kb_scan);
|
||||
DECLARE_READ16_MEMBER(kb_scancode_r);
|
||||
@ -99,6 +101,10 @@ public:
|
||||
|
||||
DECLARE_WRITE8_MEMBER(pa_w);
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER(t15_irq_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(t15_flg_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(t15_sts_w);
|
||||
|
||||
private:
|
||||
required_device<hp_5061_3001_cpu_device> m_lpu;
|
||||
required_device<hp_5061_3001_cpu_device> m_ppu;
|
||||
@ -107,6 +113,7 @@ private:
|
||||
required_ioport m_io_key1;
|
||||
required_ioport m_io_key2;
|
||||
required_ioport m_io_key3;
|
||||
required_device<hp_taco_device> m_t15;
|
||||
|
||||
void set_video_mar(UINT16 mar);
|
||||
void video_fill_buff(bool buff_idx);
|
||||
@ -136,12 +143,15 @@ private:
|
||||
|
||||
// Interrupt handling
|
||||
UINT8 m_irl_pending;
|
||||
UINT8 m_irh_pending;
|
||||
|
||||
// State of keyboard
|
||||
ioport_value m_kb_state[ 4 ];
|
||||
UINT8 m_kb_scancode;
|
||||
UINT16 m_kb_status;
|
||||
|
||||
// State of PPU I/O
|
||||
UINT8 m_ppu_pa;
|
||||
};
|
||||
|
||||
static INPUT_PORTS_START(hp9845b)
|
||||
@ -322,10 +332,13 @@ void hp9845b_state::machine_reset()
|
||||
m_video_frame = 0;
|
||||
|
||||
m_irl_pending = 0;
|
||||
m_irh_pending = 0;
|
||||
|
||||
memset(&m_kb_state[ 0 ] , 0 , sizeof(m_kb_state));
|
||||
m_kb_scancode = 0x7f;
|
||||
m_kb_status = 0;
|
||||
|
||||
m_ppu_pa = 0;
|
||||
}
|
||||
|
||||
void hp9845b_state::set_video_mar(UINT16 mar)
|
||||
@ -479,13 +492,14 @@ IRQ_CALLBACK_MEMBER(hp9845b_state::irq_callback)
|
||||
if (irqline == HPHYBRID_IRL) {
|
||||
return m_irl_pending;
|
||||
} else {
|
||||
return 0;
|
||||
return m_irh_pending;
|
||||
}
|
||||
}
|
||||
|
||||
void hp9845b_state::update_irl(void)
|
||||
void hp9845b_state::update_irq(void)
|
||||
{
|
||||
m_ppu->set_input_line(HPHYBRID_IRL , m_irl_pending != 0);
|
||||
m_ppu->set_input_line(HPHYBRID_IRH , m_irh_pending != 0);
|
||||
}
|
||||
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(hp9845b_state::kb_scan)
|
||||
@ -546,7 +560,7 @@ TIMER_DEVICE_CALLBACK_MEMBER(hp9845b_state::kb_scan)
|
||||
m_kb_scancode = i;
|
||||
BIT_SET(m_irl_pending , 0);
|
||||
BIT_SET(m_kb_status, 0);
|
||||
update_irl();
|
||||
update_irq();
|
||||
|
||||
// Special case: pressing stop key sets LPU "status" flag
|
||||
if (i == 0x47) {
|
||||
@ -572,24 +586,50 @@ WRITE16_MEMBER(hp9845b_state::kb_irq_clear_w)
|
||||
{
|
||||
BIT_CLR(m_irl_pending , 0);
|
||||
BIT_CLR(m_kb_status, 0);
|
||||
update_irl();
|
||||
update_irq();
|
||||
m_lpu->status_w(0);
|
||||
// TODO: beeper start
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(hp9845b_state::pa_w)
|
||||
{
|
||||
m_ppu_pa = data;
|
||||
|
||||
// TODO: handle sts & flg
|
||||
if (data == 0xf) {
|
||||
// RHS tape drive (T15)
|
||||
m_ppu->status_w(1);
|
||||
m_ppu->flag_w(1);
|
||||
if (data == 15) {
|
||||
// RHS tape drive (T15)
|
||||
m_ppu->status_w(m_t15->sts_r());
|
||||
m_ppu->flag_w(m_t15->flg_r());
|
||||
} else {
|
||||
m_ppu->status_w(0);
|
||||
m_ppu->flag_w(0);
|
||||
}
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(hp9845b_state::t15_irq_w)
|
||||
{
|
||||
if (state) {
|
||||
BIT_SET(m_irh_pending , 7);
|
||||
} else {
|
||||
BIT_CLR(m_irh_pending , 7);
|
||||
}
|
||||
update_irq();
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(hp9845b_state::t15_flg_w)
|
||||
{
|
||||
if (m_ppu_pa == 15) {
|
||||
m_ppu->flag_w(state);
|
||||
}
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(hp9845b_state::t15_sts_w)
|
||||
{
|
||||
if (m_ppu_pa == 15) {
|
||||
m_ppu->status_w(state);
|
||||
}
|
||||
}
|
||||
|
||||
static MACHINE_CONFIG_START( hp9845a, hp9845_state )
|
||||
//MCFG_CPU_ADD("lpu", HP_5061_3010, XTAL_11_4MHz)
|
||||
//MCFG_CPU_ADD("ppu", HP_5061_3011, XTAL_11_4MHz)
|
||||
@ -638,6 +678,9 @@ static ADDRESS_MAP_START(ppu_io_map , AS_IO , 16 , hp9845b_state)
|
||||
// PA = 0, IC = 3
|
||||
// Keyboard status input & keyboard interrupt clear
|
||||
AM_RANGE(HP_MAKE_IOADDR(0 , 3) , HP_MAKE_IOADDR(0 , 3)) AM_READWRITE(kb_status_r , kb_irq_clear_w)
|
||||
// PA = 15, IC = 0..3
|
||||
// Right-hand side tape drive (T15)
|
||||
AM_RANGE(HP_MAKE_IOADDR(15 , 0) , HP_MAKE_IOADDR(15 , 3)) AM_DEVREADWRITE("t15" , hp_taco_device , reg_r , reg_w)
|
||||
ADDRESS_MAP_END
|
||||
|
||||
static MACHINE_CONFIG_START( hp9845b, hp9845b_state )
|
||||
@ -663,6 +706,12 @@ static MACHINE_CONFIG_START( hp9845b, hp9845b_state )
|
||||
// Actual keyboard refresh rate should be KEY_SCAN_OSCILLATOR / 128 (2560 Hz)
|
||||
MCFG_TIMER_DRIVER_ADD_PERIODIC("kb_timer" , hp9845b_state , kb_scan , attotime::from_hz(100))
|
||||
|
||||
// Tape controller
|
||||
MCFG_DEVICE_ADD("t15" , HP_TACO , 4000000)
|
||||
MCFG_TACO_IRQ_HANDLER(WRITELINE(hp9845b_state , t15_irq_w))
|
||||
MCFG_TACO_FLG_HANDLER(WRITELINE(hp9845b_state , t15_flg_w))
|
||||
MCFG_TACO_STS_HANDLER(WRITELINE(hp9845b_state , t15_sts_w))
|
||||
|
||||
MCFG_SOFTWARE_LIST_ADD("optrom_list", "hp9845b_rom")
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user