summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/hp_dc100_tape.h
blob: 167bb953b10b78b796915a4d22a4a58399fe2396 (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
170
171
172
173
174
175
176
177
178
// license:BSD-3-Clause
// copyright-holders:F. Ulivi
/*********************************************************************

    hp_dc100_tape.h

    HP DC100 tape cartridge & drive

*********************************************************************/

#ifndef MAME_MACHINE_HP_DC100_TAPE_H
#define MAME_MACHINE_HP_DC100_TAPE_H

#pragma once

#include "formats/hti_tape.h"

class hp_dc100_tape_device : public device_t,
							 public device_image_interface
{
public:
	// Construction
	hp_dc100_tape_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);

	// device_image_interface overrides
	virtual image_init_result call_load() override;
	virtual image_init_result call_create(int format_type, util::option_resolution *format_options) override;
	virtual void call_unload() override;
	virtual std::string call_display() override;
	virtual iodevice_t image_type() const noexcept override { return IO_MAGTAPE; }
	virtual bool is_readable() const noexcept override { return true; }
	virtual bool is_writeable() const noexcept override { return true; }
	virtual bool is_creatable() const noexcept override { return true; }
	virtual bool must_be_loaded() const noexcept override { return false; }
	virtual bool is_reset_on_load() const noexcept override { return false; }
	virtual const char *file_extensions() const noexcept override;

	// **** Units ****
	// Tape position or distance    1/(968 * 1024) in (see hti_format_t::tape_pos_t)
	// Speed                        in/s
	// Acceleration                 in/s^2

	// Settings
	void set_acceleration(double accel);
	void set_set_points(double slow_sp , double fast_sp);
	void set_tick_size(hti_format_t::tape_pos_t size);
	void set_bits_per_word(unsigned bits);
	void set_go_threshold(double threshold);

	// Commands
	void set_track_no(unsigned track);

	enum tape_speed_t {
		SP_STOP,    // Stop
		SP_SLOW,    // Slow speed
		SP_FAST     // Fast speed
	};
	bool set_speed_setpoint(tape_speed_t speed , bool fwd);

	enum tape_op_t {
		OP_IDLE,    // No R/W
		OP_READ,    // Read from tape
		OP_WRITE,   // Write to tape
		OP_ERASE    // Erase tape
	};
	void set_op(tape_op_t op , bool force = false);

	void update_speed_pos();

	// State access
	hti_format_t::tape_pos_t get_pos() const { return m_tape_pos; }
	hti_format_t::tape_pos_t get_approx_pos() const;
	double get_speed() const { return m_speed; }
	double get_speed_setpoint() const { return m_set_point; }
	unsigned get_track_no() const { return m_track; }
	tape_op_t get_op() const { return m_current_op; }
	bool has_started() const { return !m_start_time.is_never(); }
	bool is_moving() const { return fabs(m_speed) >= m_go_threshold; }
	bool is_accelerating() const { return m_accelerating; }
	bool is_moving_fwd() const { return m_speed == 0.0 ? m_set_point >= 0.0 : m_speed > 0.0; }
	bool cart_out_r() const { return !m_present; }
	bool wpr_r() const { return !m_present || is_readonly(); }
	bool is_above_threshold() const { return fabs(m_speed) >= m_slow_set_point; }
	bool gap_reached(hti_format_t::tape_pos_t min_gap_size);

	void time_to_next_gap(hti_format_t::tape_pos_t min_gap_size , bool new_gap , emu_timer *target_timer);

	// Callbacks
	// Cartridge is out (1)
	auto cart_out() { return m_cart_out_handler.bind(); }
	// On a hole (1)
	auto hole() { return m_hole_handler.bind(); }
	// Tachometer tick (1)
	auto tacho_tick() { return m_tacho_tick_handler.bind(); }
	// Motion event (1)
	// One of the following:
	// 1. "In motion" threshold crossed
	// 2. Slow speed threshold crossed
	// 3. Accelerated phase ended (== set point reached)
	auto motion_event() { return m_motion_handler.bind(); }
	// Read bit
	auto rd_bit() { return m_rd_bit_handler.bind(); }
	// Bit to write
	auto wr_bit() { return m_wr_bit_handler.bind(); }

protected:
	// device-level overrides
	virtual void device_start() override;
	virtual void device_reset() override;
	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;

private:
	devcb_write_line m_cart_out_handler;
	devcb_write_line m_hole_handler;
	devcb_write_line m_tacho_tick_handler;
	devcb_write_line m_motion_handler;
	devcb_write_line m_rd_bit_handler;
	devcb_read_line m_wr_bit_handler;

	// Settings
	double m_acceleration;
	double m_slow_set_point;
	double m_fast_set_point;
	hti_format_t::tape_pos_t m_tick_size;
	double m_go_threshold;

	// State
	hti_format_t::tape_pos_t m_tape_pos;
	tape_speed_t m_tape_speed;
	double m_set_point;
	double m_speed;
	attotime m_start_time;  // Tape moving if != never
	bool m_accelerating;
	unsigned m_track;
	tape_op_t m_current_op;
	bool m_in_set_op;
	bool m_present;
	hti_format_t::track_iterator_t m_rd_it;
	bool m_rd_it_valid;
	hti_format_t::tape_word_t m_rw_word;
	int m_bit_idx;
	hti_format_t::tape_pos_t m_rw_pos;  // Start position of current R/W word or start position of gap when erasing
	hti_format_t::tape_pos_t m_gap_detect_start;

	// Timers
	emu_timer *m_bit_timer;
	emu_timer *m_tacho_timer;
	emu_timer *m_hole_timer;
	emu_timer *m_motion_timer;
	hti_format_t::tape_pos_t m_next_bit_pos;
	hti_format_t::tape_pos_t m_next_tacho_pos;
	hti_format_t::tape_pos_t m_next_hole_pos;

	// Image of tape
	hti_format_t m_image;
	bool m_image_dirty;

	void clear_state();
	image_init_result internal_load(bool is_create);
	void set_tape_present(bool present);
	double compute_set_point(tape_speed_t speed , bool fwd) const;
	void start_tape();
	void stop_tape();
	double const_a_space(double a , double t) const;
	attotime time_to_threshold(double threshold , bool zero_allowed) const;
	void set_motion_timer();
	void time_to_distance(hti_format_t::tape_pos_t distance , hti_format_t::tape_pos_t& target_pos , emu_timer *target_timer) const;
	void adjust_tacho_timer();
	void adjust_hole_timer();
	void stop_op();
	void load_rd_word();
	void store_wr_word();
};

// device type definition
DECLARE_DEVICE_TYPE(HP_DC100_TAPE, hp_dc100_tape_device)

#endif // MAME_MACHINE_HP_DC100_TAPE_H