mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-25 16:31:42 +00:00
Started turning the 1540 into an actual disk drive.
This commit is contained in:
parent
6532b3a8c8
commit
89a1881fef
@ -7,11 +7,14 @@
|
||||
//
|
||||
|
||||
#include "C1540.hpp"
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include "../../../Storage/Disk/Encodings/CommodoreGCR.hpp"
|
||||
|
||||
using namespace Commodore::C1540;
|
||||
|
||||
Machine::Machine()
|
||||
Machine::Machine() :
|
||||
_shift_register(0),
|
||||
Storage::DiskDrive(1000000, 300)
|
||||
{
|
||||
// create a serial port and a VIA to run it
|
||||
_serialPortVIA.reset(new SerialPortVIA);
|
||||
@ -24,6 +27,9 @@ Machine::Machine()
|
||||
// set this instance as the delegate to receive interrupt requests from both VIAs
|
||||
_serialPortVIA->set_delegate(this);
|
||||
_driveVIA.set_delegate(this);
|
||||
|
||||
// set a bit rate
|
||||
set_expected_bit_length(Storage::Encodings::CommodoreGCR::length_of_a_bit_in_time_zone(3));
|
||||
}
|
||||
|
||||
void Machine::set_serial_bus(std::shared_ptr<::Commodore::Serial::Bus> serial_bus)
|
||||
@ -91,9 +97,10 @@ void Machine::set_rom(const uint8_t *rom)
|
||||
memcpy(_rom, rom, sizeof(_rom));
|
||||
}
|
||||
|
||||
void Machine::set_disk(std::shared_ptr<Storage::Disk> disk)
|
||||
void Machine::run_for_cycles(int number_of_cycles)
|
||||
{
|
||||
_disk = disk;
|
||||
CPU6502::Processor<Machine>::run_for_cycles(number_of_cycles);
|
||||
Storage::DiskDrive::run_for_cycles(number_of_cycles);
|
||||
}
|
||||
|
||||
#pragma mark - 6522 delegate
|
||||
@ -103,3 +110,13 @@ void Machine::mos6522_did_change_interrupt_status(void *mos6522)
|
||||
// both VIAs are connected to the IRQ line
|
||||
set_irq_line(_serialPortVIA->get_interrupt_line() || _driveVIA.get_interrupt_line());
|
||||
}
|
||||
|
||||
#pragma mark - Disk drive
|
||||
|
||||
void Machine::process_input_bit(int value, unsigned int cycles_since_index_hole)
|
||||
{
|
||||
_shift_register = (_shift_register >> 1) | (value << 10);
|
||||
}
|
||||
|
||||
// the 1540 does not recognise index holes
|
||||
void Machine::process_index_hole() {}
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "../SerialBus.hpp"
|
||||
|
||||
#include "../../../Storage/Disk/Disk.hpp"
|
||||
#include "../../../Storage/Disk/DiskDrive.hpp"
|
||||
|
||||
namespace Commodore {
|
||||
namespace C1540 {
|
||||
@ -161,7 +162,8 @@ class SerialPort : public ::Commodore::Serial::Port {
|
||||
*/
|
||||
class Machine:
|
||||
public CPU6502::Processor<Machine>,
|
||||
public MOS::MOS6522IRQDelegate::Delegate {
|
||||
public MOS::MOS6522IRQDelegate::Delegate,
|
||||
public Storage::DiskDrive {
|
||||
|
||||
public:
|
||||
Machine();
|
||||
@ -179,7 +181,9 @@ class Machine:
|
||||
/*!
|
||||
Sets the disk from which this 1540 is reading data.
|
||||
*/
|
||||
void set_disk(std::shared_ptr<Storage::Disk> disk);
|
||||
// void set_disk(std::shared_ptr<Storage::Disk> disk);
|
||||
|
||||
void run_for_cycles(int number_of_cycles);
|
||||
|
||||
// to satisfy CPU6502::Processor
|
||||
unsigned int perform_bus_operation(CPU6502::BusOperation operation, uint16_t address, uint8_t *value);
|
||||
@ -196,6 +200,10 @@ class Machine:
|
||||
DriveVIA _driveVIA;
|
||||
|
||||
std::shared_ptr<Storage::Disk> _disk;
|
||||
|
||||
int _shift_register;
|
||||
virtual void process_input_bit(int value, unsigned int cycles_since_index_hole);
|
||||
virtual void process_index_hole();
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -316,6 +316,7 @@
|
||||
4BB299F91B587D8400A49093 /* tyan in Resources */ = {isa = PBXBuildFile; fileRef = 4BB298ED1B587D8400A49093 /* tyan */; };
|
||||
4BB697C71D4B558F00248BDF /* Factors.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BB697C51D4B558F00248BDF /* Factors.cpp */; };
|
||||
4BB697CB1D4B6D3E00248BDF /* TimedEventLoop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BB697C91D4B6D3E00248BDF /* TimedEventLoop.cpp */; };
|
||||
4BB697CE1D4BA44400248BDF /* CommodoreGCR.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BB697CC1D4BA44400248BDF /* CommodoreGCR.cpp */; };
|
||||
4BB73EA21B587A5100552FC2 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BB73EA11B587A5100552FC2 /* AppDelegate.swift */; };
|
||||
4BB73EA71B587A5100552FC2 /* Atari2600Document.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4BB73EA51B587A5100552FC2 /* Atari2600Document.xib */; };
|
||||
4BB73EA91B587A5100552FC2 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4BB73EA81B587A5100552FC2 /* Assets.xcassets */; };
|
||||
@ -706,6 +707,8 @@
|
||||
4BB697C61D4B558F00248BDF /* Factors.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Factors.hpp; path = ../../NumberTheory/Factors.hpp; sourceTree = "<group>"; };
|
||||
4BB697C91D4B6D3E00248BDF /* TimedEventLoop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TimedEventLoop.cpp; sourceTree = "<group>"; };
|
||||
4BB697CA1D4B6D3E00248BDF /* TimedEventLoop.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TimedEventLoop.hpp; sourceTree = "<group>"; };
|
||||
4BB697CC1D4BA44400248BDF /* CommodoreGCR.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommodoreGCR.cpp; path = Encodings/CommodoreGCR.cpp; sourceTree = "<group>"; };
|
||||
4BB697CD1D4BA44400248BDF /* CommodoreGCR.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = CommodoreGCR.hpp; path = Encodings/CommodoreGCR.hpp; sourceTree = "<group>"; };
|
||||
4BB73E9E1B587A5100552FC2 /* Clock Signal.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Clock Signal.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
4BB73EA11B587A5100552FC2 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
4BB73EA61B587A5100552FC2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/Atari2600Document.xib; sourceTree = "<group>"; };
|
||||
@ -1005,15 +1008,16 @@
|
||||
4BAB62AA1D3272D200DF5BA0 /* Disk */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4BAB62B21D327F7E00DF5BA0 /* Formats */,
|
||||
4BAB62AB1D3272D200DF5BA0 /* Disk.cpp */,
|
||||
4BAB62AC1D3272D200DF5BA0 /* Disk.hpp */,
|
||||
4BAB62B61D3302CA00DF5BA0 /* PCMTrack.cpp */,
|
||||
4BAB62B71D3302CA00DF5BA0 /* PCMTrack.hpp */,
|
||||
4B0BE4261D3481E700D5256B /* DigitalPhaseLockedLoop.cpp */,
|
||||
4B0BE4271D3481E700D5256B /* DigitalPhaseLockedLoop.hpp */,
|
||||
4BAB62AB1D3272D200DF5BA0 /* Disk.cpp */,
|
||||
4B6C73BB1D387AE500AFCFCA /* DiskDrive.cpp */,
|
||||
4BAB62B61D3302CA00DF5BA0 /* PCMTrack.cpp */,
|
||||
4B0BE4271D3481E700D5256B /* DigitalPhaseLockedLoop.hpp */,
|
||||
4BAB62AC1D3272D200DF5BA0 /* Disk.hpp */,
|
||||
4B6C73BC1D387AE500AFCFCA /* DiskDrive.hpp */,
|
||||
4BAB62B71D3302CA00DF5BA0 /* PCMTrack.hpp */,
|
||||
4BB697CF1D4BA44900248BDF /* Encodings */,
|
||||
4BAB62B21D327F7E00DF5BA0 /* Formats */,
|
||||
);
|
||||
path = Disk;
|
||||
sourceTree = "<group>";
|
||||
@ -1308,6 +1312,15 @@
|
||||
name = NumberTheory;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4BB697CF1D4BA44900248BDF /* Encodings */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4BB697CC1D4BA44400248BDF /* CommodoreGCR.cpp */,
|
||||
4BB697CD1D4BA44400248BDF /* CommodoreGCR.hpp */,
|
||||
);
|
||||
name = Encodings;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4BB73E951B587A5100552FC2 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -1892,6 +1905,7 @@
|
||||
files = (
|
||||
4BAB62AD1D3272D200DF5BA0 /* Disk.cpp in Sources */,
|
||||
4BC9DF4F1D04691600F44158 /* 6560.cpp in Sources */,
|
||||
4BB697CE1D4BA44400248BDF /* CommodoreGCR.cpp in Sources */,
|
||||
4BBF99151C8FBA6F0075DAFB /* CRTOpenGL.cpp in Sources */,
|
||||
4B0CCC451C62D0B3001CAC5F /* CRT.cpp in Sources */,
|
||||
4BB697C71D4B558F00248BDF /* Factors.cpp in Sources */,
|
||||
|
@ -57,7 +57,7 @@ void DiskDrive::set_track()
|
||||
get_next_event();
|
||||
}
|
||||
|
||||
void DiskDrive::run_for_cycles(unsigned int number_of_cycles)
|
||||
void DiskDrive::run_for_cycles(int number_of_cycles)
|
||||
{
|
||||
if(has_disk())
|
||||
{
|
||||
|
@ -24,7 +24,7 @@ class DiskDrive: public DigitalPhaseLockedLoop::Delegate, public TimedEventLoop
|
||||
void set_disk(std::shared_ptr<Disk> disk);
|
||||
bool has_disk();
|
||||
|
||||
void run_for_cycles(unsigned int number_of_cycles);
|
||||
void run_for_cycles(int number_of_cycles);
|
||||
|
||||
bool get_is_track_zero();
|
||||
void step(int direction);
|
||||
|
20
Storage/Disk/Encodings/CommodoreGCR.cpp
Normal file
20
Storage/Disk/Encodings/CommodoreGCR.cpp
Normal file
@ -0,0 +1,20 @@
|
||||
//
|
||||
// CommodoreGCR.cpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 29/07/2016.
|
||||
// Copyright © 2016 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#include "CommodoreGCR.hpp"
|
||||
|
||||
using namespace Storage;
|
||||
|
||||
Time Storage::Encodings::CommodoreGCR::length_of_a_bit_in_time_zone(unsigned int time_zone)
|
||||
{
|
||||
Time duration;
|
||||
// the speed zone divides a 4Mhz clock by 13, 14, 15 or 16, with higher-numbered zones being faster (i.e. each bit taking less time)
|
||||
duration.length = 16 - time_zone;
|
||||
duration.clock_rate = 4000000;
|
||||
return duration;
|
||||
}
|
22
Storage/Disk/Encodings/CommodoreGCR.hpp
Normal file
22
Storage/Disk/Encodings/CommodoreGCR.hpp
Normal file
@ -0,0 +1,22 @@
|
||||
//
|
||||
// CommodoreGCR.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 29/07/2016.
|
||||
// Copyright © 2016 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef CommodoreGCR_hpp
|
||||
#define CommodoreGCR_hpp
|
||||
|
||||
#include "../../Storage.hpp"
|
||||
|
||||
namespace Storage {
|
||||
namespace Encodings {
|
||||
namespace CommodoreGCR {
|
||||
Time length_of_a_bit_in_time_zone(unsigned int time_zone);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CommodoreGCR_hpp */
|
@ -10,6 +10,7 @@
|
||||
|
||||
#include <vector>
|
||||
#include "../PCMTrack.hpp"
|
||||
#include "../Encodings/CommodoreGCR.hpp"
|
||||
|
||||
using namespace Storage;
|
||||
|
||||
@ -117,14 +118,14 @@ std::shared_ptr<Track> G64::get_track_at_position(unsigned int position)
|
||||
unsigned int start_byte_in_current_speed = 0;
|
||||
for(unsigned int byte = 0; byte < track_length; byte ++)
|
||||
{
|
||||
unsigned int byte_speed = speed_zone_contents[byte >> 2] >> (6 - (byte&3)*2);
|
||||
unsigned int byte_speed = speed_zone_contents[byte >> 2] >> (6 - (byte&3)*2);
|
||||
if(byte_speed != current_speed || byte == (track_length-1))
|
||||
{
|
||||
unsigned int number_of_bytes = byte - start_byte_in_current_speed;
|
||||
|
||||
PCMSegment segment;
|
||||
segment.number_of_bits = number_of_bytes * 8;
|
||||
segment.length_of_a_bit = length_of_a_bit_in_time_zone(current_speed);
|
||||
segment.length_of_a_bit = Encodings::CommodoreGCR::length_of_a_bit_in_time_zone(current_speed);
|
||||
segment.data.reset(new uint8_t[number_of_bytes]);
|
||||
memcpy(segment.data.get(), &track_contents.get()[start_byte_in_current_speed], number_of_bytes);
|
||||
segments.push_back(std::move(segment));
|
||||
@ -140,7 +141,7 @@ std::shared_ptr<Track> G64::get_track_at_position(unsigned int position)
|
||||
{
|
||||
PCMSegment segment;
|
||||
segment.number_of_bits = track_length * 8;
|
||||
segment.length_of_a_bit = length_of_a_bit_in_time_zone((unsigned int)speed_zone_offset);
|
||||
segment.length_of_a_bit = Encodings::CommodoreGCR::length_of_a_bit_in_time_zone((unsigned int)speed_zone_offset);
|
||||
segment.data = std::move(track_contents);
|
||||
|
||||
resulting_track.reset(new PCMTrack(std::move(segment)));
|
||||
@ -151,12 +152,3 @@ std::shared_ptr<Track> G64::get_track_at_position(unsigned int position)
|
||||
|
||||
return resulting_track;
|
||||
}
|
||||
|
||||
Time G64::length_of_a_bit_in_time_zone(unsigned int time_zone)
|
||||
{
|
||||
Time duration;
|
||||
// the speed zone divides a 4Mhz clock by 13, 14, 15 or 16, with higher-numbered zones being faster (i.e. each bit taking less time)
|
||||
duration.length = 16 - time_zone;
|
||||
duration.clock_rate = 4000000;
|
||||
return duration;
|
||||
}
|
||||
|
@ -31,8 +31,6 @@ class G64: public Disk {
|
||||
|
||||
uint8_t _number_of_tracks;
|
||||
uint16_t _maximum_track_size;
|
||||
|
||||
Time length_of_a_bit_in_time_zone(unsigned int time_zone);
|
||||
};
|
||||
|
||||
};
|
||||
|
@ -47,7 +47,7 @@ void TapePlayer::get_next_pulse()
|
||||
set_next_event_time_interval(_current_pulse.length);
|
||||
}
|
||||
|
||||
void TapePlayer::run_for_cycles(unsigned int number_of_cycles)
|
||||
void TapePlayer::run_for_cycles(int number_of_cycles)
|
||||
{
|
||||
if(has_tape())
|
||||
{
|
||||
|
@ -54,7 +54,7 @@ class TapePlayer: public TimedEventLoop {
|
||||
void set_tape(std::shared_ptr<Storage::Tape> tape);
|
||||
bool has_tape();
|
||||
|
||||
void run_for_cycles(unsigned int number_of_cycles);
|
||||
void run_for_cycles(int number_of_cycles);
|
||||
void run_for_input_pulse();
|
||||
|
||||
protected:
|
||||
|
@ -14,9 +14,9 @@ using namespace Storage;
|
||||
TimedEventLoop::TimedEventLoop(unsigned int input_clock_rate) :
|
||||
_input_clock_rate(input_clock_rate) {}
|
||||
|
||||
void TimedEventLoop::run_for_cycles(unsigned int number_of_cycles)
|
||||
void TimedEventLoop::run_for_cycles(int number_of_cycles)
|
||||
{
|
||||
_time_into_interval += (unsigned int)_stepper->step(number_of_cycles);
|
||||
_time_into_interval += (unsigned int)_stepper->step((uint64_t)number_of_cycles);
|
||||
while(_time_into_interval >= _event_interval.length)
|
||||
{
|
||||
process_next_event();
|
||||
|
@ -19,7 +19,7 @@ namespace Storage {
|
||||
class TimedEventLoop {
|
||||
public:
|
||||
TimedEventLoop(unsigned int input_clock_rate);
|
||||
void run_for_cycles(unsigned int number_of_cycles);
|
||||
void run_for_cycles(int number_of_cycles);
|
||||
|
||||
protected:
|
||||
void reset_timer();
|
||||
|
Loading…
Reference in New Issue
Block a user