summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/hp_taco.h
blob: 1695b7ce706e4cd9bb43bbac15fc719b9748741a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
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__ */