summaryrefslogblamecommitdiffstatshomepage
path: root/src/devices/machine/hp_dc100_tape.h
blob: 3792be1acb8d402cbdfc1e46458a442eff0a7d6b (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15














                                                                      

                             

                             
                                                          




                                                                                                              
                                                

                                                                                                                                            

                                                    
                                                                      









                                                                                        
                                                                
                                                
                                               

























































                                                                                                              
                                  

                                             




                                                 














                                              
                                
































                                                                                                                       
                                                                                   


















                                                                                                                                        
// 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