2019-10-27 01:33:57 +00:00
|
|
|
//
|
|
|
|
// DMAController.hpp
|
|
|
|
// Clock Signal
|
|
|
|
//
|
|
|
|
// Created by Thomas Harte on 26/10/2019.
|
|
|
|
// Copyright © 2019 Thomas Harte. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
#ifndef DMAController_hpp
|
|
|
|
#define DMAController_hpp
|
|
|
|
|
|
|
|
#include <cstdint>
|
2019-10-27 02:39:11 +00:00
|
|
|
#include <vector>
|
|
|
|
|
2019-10-27 01:33:57 +00:00
|
|
|
#include "../../ClockReceiver/ClockReceiver.hpp"
|
2019-10-31 02:59:32 +00:00
|
|
|
#include "../../ClockReceiver/ClockingHintSource.hpp"
|
2019-10-27 01:33:57 +00:00
|
|
|
#include "../../Components/1770/1770.hpp"
|
|
|
|
|
|
|
|
namespace Atari {
|
|
|
|
namespace ST {
|
|
|
|
|
2019-10-31 02:59:32 +00:00
|
|
|
class DMAController: public WD::WD1770::Delegate, public ClockingHint::Source, public ClockingHint::Observer {
|
2019-10-27 01:33:57 +00:00
|
|
|
public:
|
|
|
|
DMAController();
|
|
|
|
|
|
|
|
uint16_t read(int address);
|
|
|
|
void write(int address, uint16_t value);
|
|
|
|
void run_for(HalfCycles duration);
|
|
|
|
|
2019-10-29 01:13:21 +00:00
|
|
|
bool get_interrupt_line();
|
|
|
|
|
2019-11-03 03:04:08 +00:00
|
|
|
void set_floppy_drive_selection(bool drive1, bool drive2, bool side2);
|
2019-11-03 03:26:42 +00:00
|
|
|
void set_floppy_disk(std::shared_ptr<Storage::Disk::Disk> disk, size_t drive);
|
2019-11-03 03:04:08 +00:00
|
|
|
|
2019-10-29 01:13:21 +00:00
|
|
|
struct InterruptDelegate {
|
|
|
|
virtual void dma_controller_did_change_interrupt_status(DMAController *) = 0;
|
|
|
|
};
|
|
|
|
void set_interrupt_delegate(InterruptDelegate *delegate);
|
|
|
|
|
2019-10-31 02:59:32 +00:00
|
|
|
// ClockingHint::Source.
|
|
|
|
ClockingHint::Preference preferred_clocking() final;
|
|
|
|
|
2019-10-27 01:33:57 +00:00
|
|
|
private:
|
|
|
|
HalfCycles running_time_;
|
2019-10-27 02:39:11 +00:00
|
|
|
struct WD1772: public WD::WD1770 {
|
|
|
|
WD1772(): WD::WD1770(WD::WD1770::P1772) {
|
|
|
|
drives_.emplace_back(new Storage::Disk::Drive(8000000, 300, 2));
|
|
|
|
drives_.emplace_back(new Storage::Disk::Drive(8000000, 300, 2));
|
|
|
|
set_drive(drives_[0]);
|
2019-11-03 03:26:42 +00:00
|
|
|
set_is_double_density(true); // TODO: is this selectable on the ST?
|
2019-10-27 02:39:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void set_motor_on(bool motor_on) final {
|
|
|
|
drives_[0]->set_motor_on(motor_on);
|
|
|
|
drives_[1]->set_motor_on(motor_on);
|
|
|
|
}
|
|
|
|
|
2019-11-03 03:04:08 +00:00
|
|
|
void set_floppy_drive_selection(bool drive1, bool drive2, bool side2) {
|
|
|
|
// TODO: handle no drives and/or both drives selected.
|
|
|
|
if(drive1) {
|
|
|
|
set_drive(drives_[0]);
|
|
|
|
} else {
|
|
|
|
set_drive(drives_[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
drives_[0]->set_head(side2);
|
|
|
|
drives_[1]->set_head(side2);
|
|
|
|
}
|
|
|
|
|
2019-10-27 02:39:11 +00:00
|
|
|
std::vector<std::shared_ptr<Storage::Disk::Drive>> drives_;
|
|
|
|
} fdc_;
|
2019-10-27 01:33:57 +00:00
|
|
|
|
2019-10-29 01:13:21 +00:00
|
|
|
void wd1770_did_change_output(WD::WD1770 *) final;
|
|
|
|
|
2019-10-27 01:33:57 +00:00
|
|
|
uint16_t control_ = 0;
|
2019-10-29 01:13:21 +00:00
|
|
|
|
|
|
|
InterruptDelegate *interrupt_delegate_ = nullptr;
|
|
|
|
bool interrupt_line_ = false;
|
2019-10-31 02:59:32 +00:00
|
|
|
|
|
|
|
void set_component_prefers_clocking(ClockingHint::Source *, ClockingHint::Preference) final;
|
2019-11-03 22:24:36 +00:00
|
|
|
|
|
|
|
// MARK: - DMA State.
|
|
|
|
uint8_t buffer_[2][16];
|
|
|
|
int active_buffer_ = 0;
|
|
|
|
int bytes_received_ = 0;
|
|
|
|
bool error_ = false;
|
|
|
|
int address_ = 0;
|
|
|
|
int byte_count_ = 0;
|
2019-10-27 01:33:57 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* DMAController_hpp */
|