1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-02-18 16:30:29 +00:00

Made a very basic attempt to emulate tape output.

This commit is contained in:
Thomas Harte 2016-01-24 18:20:55 -05:00
parent 1819e7b9cc
commit 96c946b8af
2 changed files with 98 additions and 52 deletions

View File

@ -117,12 +117,12 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin
if(isReadOperation(operation)) if(isReadOperation(operation))
{ {
*value = _tape.get_data_register(); *value = _tape.get_data_register();
_tape.clear_interrupts(Interrupt::TransmitDataEmpty); _tape.clear_interrupts(Interrupt::ReceiveDataFull);
} }
else else
{ {
_tape.set_data_register(*value); _tape.set_data_register(*value);
_tape.clear_interrupts(Interrupt::ReceiveDataFull); _tape.clear_interrupts(Interrupt::TransmitDataEmpty);
} }
break; break;
case 0x5: case 0x5:
@ -606,7 +606,7 @@ void Speaker::set_is_enabled(bool is_enabled)
Tape Tape
*/ */
Tape::Tape() : _is_running(false), _data_register(0), _delegate(nullptr) {} Tape::Tape() : _is_running(false), _data_register(0), _delegate(nullptr), _output_bits_remaining(0), _last_posted_interrupt_status(0), _interrupt_status(0) {}
void Tape::set_tape(std::shared_ptr<Storage::Tape> tape) void Tape::set_tape(std::shared_ptr<Storage::Tape> tape)
{ {
@ -627,23 +627,23 @@ inline void Tape::get_next_tape_pulse()
inline void Tape::push_tape_bit(uint16_t bit) inline void Tape::push_tape_bit(uint16_t bit)
{ {
_data_register = (uint16_t)((_data_register >> 1) | (bit << 10)); _data_register = (uint16_t)((_data_register >> 1) | (bit << 10));
uint8_t old_interrupt_status = _interrupt_status;
if(_bits_since_start) if(_bits_since_start)
{ {
_bits_since_start--; _bits_since_start--;
if(_bits_since_start == 7) if(_bits_since_start == 7)
{ {
_interrupt_status &= ~Interrupt::TransmitDataEmpty; _interrupt_status &= ~Interrupt::ReceiveDataFull;
} }
} }
else evaluate_interrupts();
{ }
inline void Tape::evaluate_interrupts()
{
if((_data_register&0x3) == 0x1) if((_data_register&0x3) == 0x1)
{ {
_interrupt_status |= Interrupt::TransmitDataEmpty; _interrupt_status |= Interrupt::ReceiveDataFull;
_bits_since_start = 9; _bits_since_start = 9;
} }
@ -651,9 +651,12 @@ inline void Tape::push_tape_bit(uint16_t bit)
_interrupt_status |= Interrupt::HighToneDetect; _interrupt_status |= Interrupt::HighToneDetect;
else else
_interrupt_status &= ~Interrupt::HighToneDetect; _interrupt_status &= ~Interrupt::HighToneDetect;
}
if(old_interrupt_status != _interrupt_status && _delegate) _delegate->tape_did_change_interrupt_status(this); if(_last_posted_interrupt_status != _interrupt_status)
{
_last_posted_interrupt_status = _interrupt_status;
if(_delegate) _delegate->tape_did_change_interrupt_status(this);
}
} }
inline void Tape::clear_interrupts(uint8_t interrupts) inline void Tape::clear_interrupts(uint8_t interrupts)
@ -665,9 +668,29 @@ inline void Tape::clear_interrupts(uint8_t interrupts)
} }
} }
inline void Tape::set_is_in_input_mode(bool is_in_input_mode)
{
_is_in_input_mode = is_in_input_mode;
}
inline void Tape::set_counter(uint8_t value)
{
_pulse_stepper = std::shared_ptr<SignalProcessing::Stepper>(new SignalProcessing::Stepper(1200, 2000000));
}
inline void Tape::set_data_register(uint8_t value)
{
_data_register = (uint16_t)((value << 2) | 1);
_output_bits_remaining = 9;
}
inline void Tape::run_for_cycles(unsigned int number_of_cycles) inline void Tape::run_for_cycles(unsigned int number_of_cycles)
{ {
if(_is_running && _is_enabled && _tape != nullptr) if(_is_enabled)
{
if(_is_in_input_mode)
{
if(_is_running && _tape != nullptr)
{ {
while(number_of_cycles--) while(number_of_cycles--)
{ {
@ -704,4 +727,25 @@ inline void Tape::run_for_cycles(unsigned int number_of_cycles)
} }
} }
} }
}
else
{
while(number_of_cycles--)
{
if(_pulse_stepper->step())
{
_output_bits_remaining--;
if(!_output_bits_remaining)
{
_output_bits_remaining = 9;
_interrupt_status |= Interrupt::TransmitDataEmpty;
}
evaluate_interrupts();
_data_register = (_data_register >> 1) | 0x200;
}
}
}
}
} }

View File

@ -33,8 +33,8 @@ enum ROMSlot: uint8_t {
enum Interrupt: uint8_t { enum Interrupt: uint8_t {
DisplayEnd = 0x04, DisplayEnd = 0x04,
RealTimeClock = 0x08, RealTimeClock = 0x08,
TransmitDataEmpty = 0x10, ReceiveDataFull = 0x10,
ReceiveDataFull = 0x20, TransmitDataEmpty = 0x20,
HighToneDetect = 0x40 HighToneDetect = 0x40
}; };
@ -64,8 +64,8 @@ class Tape {
void set_tape(std::shared_ptr<Storage::Tape> tape); void set_tape(std::shared_ptr<Storage::Tape> tape);
inline uint8_t get_data_register() { return (uint8_t)(_data_register >> 2); } inline uint8_t get_data_register() { return (uint8_t)(_data_register >> 2); }
inline void set_data_register(uint8_t value) {} inline void set_data_register(uint8_t value);
inline void set_counter(uint8_t value) {} inline void set_counter(uint8_t value);
inline uint8_t get_interrupt_status() { return _interrupt_status; } inline uint8_t get_interrupt_status() { return _interrupt_status; }
inline void clear_interrupts(uint8_t interrupts); inline void clear_interrupts(uint8_t interrupts);
@ -80,7 +80,7 @@ class Tape {
inline void set_is_running(bool is_running) { _is_running = is_running; } inline void set_is_running(bool is_running) { _is_running = is_running; }
inline void set_is_enabled(bool is_enabled) { _is_enabled = is_enabled; } inline void set_is_enabled(bool is_enabled) { _is_enabled = is_enabled; }
inline void set_is_in_input_mode(bool is_in_input_mode) {} inline void set_is_in_input_mode(bool is_in_input_mode);
private: private:
inline void push_tape_bit(uint16_t bit); inline void push_tape_bit(uint16_t bit);
@ -94,11 +94,13 @@ class Tape {
bool _is_running; bool _is_running;
bool _is_enabled; bool _is_enabled;
bool _is_in_input_mode;
int _bits_since_start; inline void evaluate_interrupts();
int _bits_since_start, _output_bits_remaining;
uint16_t _data_register; uint16_t _data_register;
uint8_t _interrupt_status; uint8_t _interrupt_status, _last_posted_interrupt_status;
Delegate *_delegate; Delegate *_delegate;
enum { enum {