2016-07-05 17:28:27 +00:00
|
|
|
//
|
|
|
|
// Commodore1540.hpp
|
|
|
|
// Clock Signal
|
|
|
|
//
|
|
|
|
// Created by Thomas Harte on 05/07/2016.
|
|
|
|
// Copyright © 2016 Thomas Harte. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
#ifndef Commodore1540_hpp
|
|
|
|
#define Commodore1540_hpp
|
|
|
|
|
2016-07-05 20:39:18 +00:00
|
|
|
#include "../../../Processors/6502/CPU6502.hpp"
|
|
|
|
#include "../../../Components/6522/6522.hpp"
|
2016-07-05 21:27:02 +00:00
|
|
|
#include "../SerialBus.hpp"
|
2016-07-05 20:39:18 +00:00
|
|
|
|
|
|
|
namespace Commodore {
|
|
|
|
namespace C1540 {
|
|
|
|
|
2016-07-05 21:27:02 +00:00
|
|
|
class SerialPortVIA: public MOS::MOS6522<SerialPortVIA>, public MOS::MOS6522IRQDelegate {
|
|
|
|
public:
|
|
|
|
using MOS6522IRQDelegate::set_interrupt_status;
|
2016-07-05 23:12:43 +00:00
|
|
|
|
2016-07-07 02:17:32 +00:00
|
|
|
SerialPortVIA() : _portB(0x9f) {}
|
2016-07-05 23:12:43 +00:00
|
|
|
|
|
|
|
uint8_t get_port_input(Port port) {
|
|
|
|
if(port) {
|
|
|
|
return _portB;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0xff;
|
|
|
|
}
|
|
|
|
|
|
|
|
void set_port_output(Port port, uint8_t value, uint8_t mask) {
|
|
|
|
if(port) {
|
|
|
|
std::shared_ptr<::Commodore::Serial::Port> serialPort = _serialPort.lock();
|
|
|
|
if(serialPort) {
|
|
|
|
serialPort->set_output(::Commodore::Serial::Line::Attention, !(value&0x10));
|
|
|
|
serialPort->set_output(::Commodore::Serial::Line::Clock, !(value&0x08));
|
|
|
|
serialPort->set_output(::Commodore::Serial::Line::Data, !(value&0x02));
|
|
|
|
}
|
2016-07-06 11:46:21 +00:00
|
|
|
// printf("1540 serial port VIA port B: %02x\n", value);
|
2016-07-05 23:12:43 +00:00
|
|
|
}
|
2016-07-06 11:46:21 +00:00
|
|
|
// else
|
|
|
|
// printf("1540 serial port VIA port A: %02x\n", value);
|
2016-07-05 23:12:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void set_serial_line_state(::Commodore::Serial::Line line, bool value) {
|
2016-07-06 11:46:21 +00:00
|
|
|
// printf("1540 Serial port line %d: %s\n", line, value ? "on" : "off");
|
2016-07-05 23:12:43 +00:00
|
|
|
switch(line) {
|
|
|
|
default: break;
|
2016-07-07 02:17:32 +00:00
|
|
|
case ::Commodore::Serial::Line::Data: _portB = (_portB & ~0x01) | (value ? 0x00 : 0x01); break;
|
|
|
|
case ::Commodore::Serial::Line::Clock: _portB = (_portB & ~0x04) | (value ? 0x00 : 0x04); break;
|
2016-07-05 23:19:46 +00:00
|
|
|
case ::Commodore::Serial::Line::Attention:
|
|
|
|
_portB = (_portB & ~0x80) | (value ? 0 : 0x80);
|
2016-07-07 00:22:46 +00:00
|
|
|
set_control_line_input(Port::A, Line::One, !value); // truth here is active low; the 6522 takes true to be high
|
2016-07-05 23:19:46 +00:00
|
|
|
break;
|
2016-07-05 23:12:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void set_serial_port(std::shared_ptr<::Commodore::Serial::Port> serialPort) {
|
|
|
|
_serialPort = serialPort;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
uint8_t _portB;
|
|
|
|
std::weak_ptr<::Commodore::Serial::Port> _serialPort;
|
2016-07-05 21:27:02 +00:00
|
|
|
};
|
|
|
|
|
2016-07-07 00:22:46 +00:00
|
|
|
class DriveVIA: public MOS::MOS6522<DriveVIA>, public MOS::MOS6522IRQDelegate {
|
2016-07-06 02:22:09 +00:00
|
|
|
public:
|
|
|
|
using MOS6522IRQDelegate::set_interrupt_status;
|
2016-07-07 02:17:32 +00:00
|
|
|
|
|
|
|
uint8_t get_port_input(Port port) {
|
|
|
|
return 0xff;
|
|
|
|
}
|
2016-07-06 02:22:09 +00:00
|
|
|
};
|
|
|
|
|
2016-07-05 21:27:02 +00:00
|
|
|
class SerialPort : public ::Commodore::Serial::Port {
|
|
|
|
public:
|
|
|
|
void set_input(::Commodore::Serial::Line line, bool value) {
|
2016-07-05 23:12:43 +00:00
|
|
|
std::shared_ptr<SerialPortVIA> serialPortVIA = _serialPortVIA.lock();
|
|
|
|
if(serialPortVIA) serialPortVIA->set_serial_line_state(line, value);
|
2016-07-05 21:27:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void set_serial_port_via(std::shared_ptr<SerialPortVIA> serialPortVIA) {
|
|
|
|
_serialPortVIA = serialPortVIA;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
std::weak_ptr<SerialPortVIA> _serialPortVIA;
|
|
|
|
};
|
|
|
|
|
2016-07-05 20:39:18 +00:00
|
|
|
class Machine:
|
2016-07-05 23:12:43 +00:00
|
|
|
public CPU6502::Processor<Machine>,
|
|
|
|
public MOS::MOS6522IRQDelegate::Delegate {
|
2016-07-05 20:39:18 +00:00
|
|
|
|
|
|
|
public:
|
2016-07-05 21:27:02 +00:00
|
|
|
Machine();
|
2016-07-05 20:39:18 +00:00
|
|
|
unsigned int perform_bus_operation(CPU6502::BusOperation operation, uint16_t address, uint8_t *value);
|
|
|
|
|
2016-07-05 20:54:25 +00:00
|
|
|
void set_rom(const uint8_t *rom);
|
2016-07-05 21:27:02 +00:00
|
|
|
void set_serial_bus(std::shared_ptr<::Commodore::Serial::Bus> serial_bus);
|
2016-07-05 20:39:18 +00:00
|
|
|
|
2016-07-05 23:12:43 +00:00
|
|
|
// to satisfy MOS::MOS6522::Delegate
|
|
|
|
virtual void mos6522_did_change_interrupt_status(void *mos6522);
|
|
|
|
|
2016-07-05 20:39:18 +00:00
|
|
|
private:
|
|
|
|
uint8_t _ram[0x800];
|
|
|
|
uint8_t _rom[0x4000];
|
2016-07-05 21:27:02 +00:00
|
|
|
|
|
|
|
std::shared_ptr<SerialPortVIA> _serialPortVIA;
|
|
|
|
std::shared_ptr<SerialPort> _serialPort;
|
2016-07-06 02:22:09 +00:00
|
|
|
DriveVIA _driveVIA;
|
2016-07-05 20:39:18 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
2016-07-05 17:28:27 +00:00
|
|
|
|
|
|
|
#endif /* Commodore1540_hpp */
|