1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-01 22:41:32 +00:00

Formalised clock-rate multiplication within disk drives, discovered that the stepper didn't have ideal behaviour for my timed event loop and hence nailed down the semantics a ilttle more.

(obiter: the 1540 now appears to discern the correct sequence of bits. Framing is off in my test printfs but that's neither here nor there).
This commit is contained in:
Thomas Harte 2016-07-31 13:32:30 -04:00
parent 6ee784a893
commit 2332f72875
7 changed files with 59 additions and 14 deletions

View File

@ -14,7 +14,7 @@ using namespace Commodore::C1540;
Machine::Machine() :
_shift_register(0),
Storage::DiskDrive(1000000, 300)
Storage::DiskDrive(1000000, 16, 300)
{
// create a serial port and a VIA to run it
_serialPortVIA.reset(new SerialPortVIA);
@ -115,7 +115,7 @@ void Machine::mos6522_did_change_interrupt_status(void *mos6522)
void Machine::process_input_bit(int value, unsigned int cycles_since_index_hole)
{
_shift_register = (_shift_register >> 1) | (value << 10);
_shift_register = (_shift_register << 1) | value;
static int bitCount = 0;
bitCount++;

View File

@ -1008,7 +1008,7 @@ inline void Tape::run_for_cycles(unsigned int number_of_cycles)
{
if(_is_running)
{
TapePlayer::run_for_cycles(number_of_cycles);
TapePlayer::run_for_cycles((int)number_of_cycles);
}
}
else

View File

@ -19,6 +19,9 @@ namespace SignalProcessing {
clock to sample something with another.
Uses a Bresenham-like error term internally for full-integral storage with no drift.
Pegs the beginning of both clocks to the time at which the stepper is created. So e.g. a stepper
that converts from an input clock of 1200 to an output clock of 2 will first fire on cycle 600.
*/
class Stepper
{
@ -33,7 +36,7 @@ class Stepper
of steps that should be taken at the @c output_rate.
*/
Stepper(uint64_t output_rate, uint64_t input_rate) :
accumulated_error_(0),
accumulated_error_(-((int64_t)input_rate << 1)),
input_rate_(input_rate),
output_rate_(output_rate),
whole_step_(output_rate / input_rate),

View File

@ -10,17 +10,19 @@
using namespace Storage;
DiskDrive::DiskDrive(unsigned int clock_rate, unsigned int revolutions_per_minute) :
_clock_rate(clock_rate * 16),
DiskDrive::DiskDrive(unsigned int clock_rate, unsigned int clock_rate_multiplier, unsigned int revolutions_per_minute) :
_clock_rate(clock_rate * clock_rate_multiplier),
_clock_rate_multiplier(clock_rate_multiplier),
_revolutions_per_minute(revolutions_per_minute),
_head_position(0),
TimedEventLoop(clock_rate * 16)
TimedEventLoop(clock_rate * clock_rate_multiplier)
{}
void DiskDrive::set_expected_bit_length(Time bit_length)
{
_bit_length = bit_length;
printf("expected bit length: %0.4f\n", bit_length.get_float() * 1000.0);
// this conversion doesn't need to be exact because there's a lot of variation to be taken
// account of in rotation speed, air turbulence, etc, so a direct conversion will do
@ -54,6 +56,28 @@ void DiskDrive::step(int direction)
void DiskDrive::set_track()
{
_track = _disk->get_track_at_position((unsigned int)_head_position);
// printf("***");
// int calibration = -1;
// int bit = 0, shift = 0;
// while(1)
// {
// Track::Event event = _track->get_next_event();
// if(event.type == Track::Event::IndexHole) break;
// if(calibration < 0) calibration = event.length.length;
//
// int number_of_bits = event.length.length / calibration;
// while(number_of_bits > 1)
// {
// shift = (shift << 1)&0xff;
// number_of_bits--;
// bit++; if(bit == 8) { printf("%02x.", shift); bit = 0; }
// }
// shift = ((shift << 1) | 0x01)&0xff;
// bit++; if(bit == 8) { printf("%02x.", shift); bit = 0; }
// }
// printf("***\n");
reset_timer();
get_next_event();
}
@ -62,11 +86,13 @@ void DiskDrive::run_for_cycles(int number_of_cycles)
{
if(has_disk())
{
_cycles_since_index_hole += (unsigned int)number_of_cycles;
number_of_cycles *= 16;
_pll->run_for_cycles(number_of_cycles);
TimedEventLoop::run_for_cycles(number_of_cycles);
number_of_cycles *= _clock_rate_multiplier;
while(number_of_cycles--)
{
_cycles_since_index_hole ++;
_pll->run_for_cycles(1);
TimedEventLoop::run_for_cycles(1);
}
}
}
@ -90,6 +116,7 @@ void DiskDrive::get_next_event()
event_interval.clock_rate *= _revolutions_per_minute;
event_interval.simplify();
set_next_event_time_interval(event_interval);
// printf("bit length: %0.4f\n", event_interval.get_float() * 1000.0);
}
void DiskDrive::process_next_event()

View File

@ -17,7 +17,7 @@ namespace Storage {
class DiskDrive: public DigitalPhaseLockedLoop::Delegate, public TimedEventLoop {
public:
DiskDrive(unsigned int clock_rate, unsigned int revolutions_per_minute);
DiskDrive(unsigned int clock_rate, unsigned int clock_rate_multiplier, unsigned int revolutions_per_minute);
void set_expected_bit_length(Time bit_length);
@ -43,6 +43,7 @@ class DiskDrive: public DigitalPhaseLockedLoop::Delegate, public TimedEventLoop
private:
Time _bit_length;
unsigned int _clock_rate;
unsigned int _clock_rate_multiplier;
unsigned int _revolutions_per_minute;
std::shared_ptr<DigitalPhaseLockedLoop> _pll;

View File

@ -32,6 +32,8 @@ PCMTrack::Event PCMTrack::get_next_event()
while(_segment_pointer < _segments.size())
{
unsigned int clock_multiplier = _track_clock_rate / _segments[_segment_pointer].length_of_a_bit.clock_rate;
unsigned int bit_length = clock_multiplier * _segments[_segment_pointer].length_of_a_bit.length;
const uint8_t *segment_data = _segments[_segment_pointer].data.get();
while(_bit_pointer < _segments[_segment_pointer].number_of_bits)
{
@ -39,7 +41,7 @@ PCMTrack::Event PCMTrack::get_next_event()
// TODO: should I account for the converse bit ordering? Or can I assume MSB first?
int bit = segment_data[_bit_pointer >> 3] & (0x80 >> (_bit_pointer&7));
_bit_pointer++;
_next_event.length.length += clock_multiplier * _segments[_segment_pointer].length_of_a_bit.length;
_next_event.length.length += bit_length;
if(bit) return _next_event;
}
@ -74,5 +76,12 @@ void PCMTrack::fix_length()
_next_event.length.clock_rate += _segments[c].length_of_a_bit.length * _segments[c].number_of_bits * multiplier;
}
uint8_t *data = _segments[0].data.get();
for(int c = 0; c < _segments[0].number_of_bits >> 3; c++)
{
printf("%02x.", data[c]);
}
printf("===\n");
_segment_pointer = _bit_pointer = 0;
}

View File

@ -22,6 +22,11 @@ struct Time {
length /= common_divisor;
clock_rate /= common_divisor;
}
inline float get_float()
{
return (float)length / (float)clock_rate;
}
};
}