1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-19 23:32:28 +00:00
CLK/Machines/Atari/ST/DMAController.hpp
Thomas Harte 05bcd73f82 Attempts to pull drive ownership into DiskController.
For the sake of being more intelligent as to drive clocking, hopefully. And, eventually, to support multiple drive selection.
2020-02-11 21:59:13 -05:00

117 lines
2.9 KiB
C++

//
// 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>
#include <vector>
#include "../../../ClockReceiver/ClockReceiver.hpp"
#include "../../../ClockReceiver/ClockingHintSource.hpp"
#include "../../../Components/1770/1770.hpp"
#include "../../../Activity/Source.hpp"
namespace Atari {
namespace ST {
class DMAController: public WD::WD1770::Delegate, public ClockingHint::Source, public ClockingHint::Observer {
public:
DMAController();
uint16_t read(int address);
void write(int address, uint16_t value);
void run_for(HalfCycles duration);
bool get_interrupt_line();
bool get_bus_request_line();
/*!
Indicates that the DMA controller has been granted bus access to the block of memory at @c ram, which
is of size @c size.
@returns The number of words read or written.
*/
int bus_grant(uint16_t *ram, size_t size);
void set_floppy_drive_selection(bool drive1, bool drive2, bool side2);
void set_floppy_disk(std::shared_ptr<Storage::Disk::Disk> disk, size_t drive);
struct Delegate {
virtual void dma_controller_did_change_output(DMAController *) = 0;
};
void set_delegate(Delegate *delegate);
void set_activity_observer(Activity::Observer *observer);
// ClockingHint::Source.
ClockingHint::Preference preferred_clocking() final;
private:
HalfCycles running_time_;
struct WD1772: public WD::WD1770 {
WD1772(): WD::WD1770(WD::WD1770::P1772) {
emplace_drives(2, 8000000, 300, 2);
set_is_double_density(true); // TODO: is this selectable on the ST?
}
void set_motor_on(bool motor_on) final {
for_all_drives([motor_on] (Storage::Disk::Drive &drive, size_t) {
drive.set_motor_on(motor_on);
});
}
void set_floppy_drive_selection(bool drive1, bool drive2, bool side2) {
set_drive(
(drive1 ? 1 : 0) |
(drive2 ? 2 : 0)
);
for_all_drives([side2] (Storage::Disk::Drive &drive, size_t) {
drive.set_head(side2);
});
}
void set_activity_observer(Activity::Observer *observer) {
get_drive(0).set_activity_observer(observer, "Internal", true);
get_drive(1).set_activity_observer(observer, "External", true);
}
void set_disk(std::shared_ptr<Storage::Disk::Disk> disk, size_t drive) {
get_drive(drive).set_disk(disk);
}
} fdc_;
void wd1770_did_change_output(WD::WD1770 *) final;
uint16_t control_ = 0;
Delegate *delegate_ = nullptr;
bool interrupt_line_ = false;
bool bus_request_line_ = false;
void set_component_prefers_clocking(ClockingHint::Source *, ClockingHint::Preference) final;
// MARK: - DMA State.
struct Buffer {
uint8_t contents[16];
bool is_full = false;
} buffer_[2];
int active_buffer_ = 0;
int bytes_received_ = 0;
bool error_ = false;
int address_ = 0;
int byte_count_ = 0;
};
}
}
#endif /* DMAController_hpp */