summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/hp_dc100_tape.h
blob: 3792be1acb8d402cbdfc1e46458a442eff0a7d6b (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
179
// 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 "imagedev/magtape.h"

#include "formats/hti_tape.h"

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

	// device_image_interface implementation
	virtual std::pair<std::error_condition, std::string> call_load() override;
	virtual std::pair<std::error_condition, std::string> call_create(int format_type, util::option_resolution *format_options) override;
	virtual void call_unload() override;
	virtual std::string call_display() override;
	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_image_format(hti_format_t::image_format_t fmt);
	void set_go_threshold(double threshold);
	void set_name(const std::string& name);

	// 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_t implementation
	virtual void device_start() override;
	virtual void device_reset() override;

	TIMER_CALLBACK_MEMBER(bit_timer_tick);
	TIMER_CALLBACK_MEMBER(tacho_timer_tick);
	TIMER_CALLBACK_MEMBER(hole_timer_tick);
	TIMER_CALLBACK_MEMBER(motion_timer_tick);

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;
	std::string m_unit_name;

	// 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();
	std::pair<std::error_condition, std::string> 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