mos652x.h
/*
* This file is part of libsidplayfp, a SID player engine.
*
* Copyright 2011-2021 Leandro Nini <drfiemost@users.sourceforge.net>
* Copyright 2009-2014 VICE Project
* Copyright 2007-2010 Antti Lankila
* Copyright 2000 Simon White
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef MOS652X_H
#define MOS652X_H
#include <memory>
#include <stdint.h>
#include "interrupt.h"
#include "timer.h"
#include "tod.h"
#include "SerialPort.h"
#include "EventScheduler.h"
#include "sidcxx11.h"
class EventContext;
namespace libsidplayfp
{
class MOS652X;
class TimerA final : public Timer
{
private:
void underFlow() override;
void serialPort() override;
public:
TimerA(EventScheduler &scheduler, MOS652X &parent) :
Timer("CIA Timer A", scheduler, parent) {}
};
class TimerB final : public Timer
{
private:
void underFlow() override;
public:
TimerB(EventScheduler &scheduler, MOS652X &parent) :
Timer("CIA Timer B", scheduler, parent) {}
void cascade()
{
// we pretend that we are CPU doing a write to ctrl register
syncWithCpu();
state |= CIAT_STEP;
wakeUpAfterSyncWithCpu();
}
bool started() const { return (state & CIAT_CR_START) != 0; }
};
class InterruptSource8521 final : public InterruptSource
{
protected:
void triggerInterrupt() override
{
idr |= INTERRUPT_REQUEST;
idrTemp |= INTERRUPT_REQUEST;
if (ack0())
scheduleIrq();
}
public:
InterruptSource8521(EventScheduler &scheduler, MOS652X &parent) :
InterruptSource(scheduler, parent)
{}
void trigger(uint8_t interruptMask) override;
};
class InterruptSource6526 final : public InterruptSource
{
protected:
void triggerInterrupt() override { idr |= INTERRUPT_REQUEST; }
public:
InterruptSource6526(EventScheduler &scheduler, MOS652X &parent) :
InterruptSource(scheduler, parent)
{}
void trigger(uint8_t interruptMask) override;
uint8_t clear() override;
};
class MOS652X
{
friend class InterruptSource;
friend class SerialPort;
friend class TimerA;
friend class TimerB;
friend class Tod;
public:
typedef enum
{
MOS6526 = 0
,MOS8521
,MOS6526W4485
} model_t;
private:
static const char *credit;
protected:
EventScheduler &eventScheduler;
uint8_t &pra, &prb, &ddra, &ddrb;
uint8_t regs[0x10];
TimerA timerA;
TimerB timerB;
std::unique_ptr<InterruptSource> interruptSource;
Tod tod;
SerialPort serialPort;
EventCallback<MOS652X> bTickEvent;
private:
void todInterrupt();
void spInterrupt();
void bTick();
void underflowA();
void underflowB();
void handleSerialPort();
protected:
MOS652X(EventScheduler &scheduler);
virtual void interrupt(bool state) = 0;
virtual void portA() {}
virtual void portB() {}
uint8_t adjustDataPort(uint8_t data);
uint8_t read(uint_least8_t addr);
void write(uint_least8_t addr, uint8_t data);
public:
void setModel(model_t model);
virtual void reset();
static const char *credits();
void setDayOfTimeRate(unsigned int clock) { tod.setPeriod(clock); }
};
}
#endif // MOS6526_H
libsidplayfp::EventCallback
Definition: EventCallback.h:36
libsidplayfp::EventScheduler
Definition: EventScheduler.h:62
libsidplayfp::InterruptSource6526
Definition: mos652x.h:134
libsidplayfp::InterruptSource6526::trigger
void trigger(uint8_t interruptMask) override
Definition: mos652x.cpp:85
libsidplayfp::InterruptSource6526::clear
uint8_t clear() override
Definition: mos652x.cpp:103
libsidplayfp::InterruptSource8521
Definition: mos652x.h:111
libsidplayfp::InterruptSource8521::trigger
void trigger(uint8_t interruptMask) override
Definition: mos652x.cpp:75
libsidplayfp::InterruptSource
Definition: interrupt.h:44
libsidplayfp::InterruptSource::idr
uint8_t idr
Interrupt data register.
Definition: interrupt.h:73
libsidplayfp::InterruptSource::InterruptSource
InterruptSource(EventScheduler &scheduler, MOS652X &parent)
Definition: interrupt.h:126
libsidplayfp::InterruptSource::INTERRUPT_REQUEST
@ INTERRUPT_REQUEST
control bit
Definition: interrupt.h:54
libsidplayfp::InterruptSource::ack0
bool ack0() const
Definition: interrupt.h:105
libsidplayfp::MOS652X
Definition: mos652x.h:154
libsidplayfp::MOS652X::timerA
TimerA timerA
Timers A and B.
Definition: mos652x.h:186
libsidplayfp::MOS652X::write
void write(uint_least8_t addr, uint8_t data)
Definition: mos652x.cpp:220
libsidplayfp::MOS652X::regs
uint8_t regs[0x10]
These are all CIA registers.
Definition: mos652x.h:182
libsidplayfp::MOS652X::adjustDataPort
uint8_t adjustDataPort(uint8_t data)
Definition: mos652x.cpp:164
libsidplayfp::MOS652X::eventScheduler
EventScheduler & eventScheduler
Event context.
Definition: mos652x.h:174
libsidplayfp::MOS652X::MOS652X
MOS652X(EventScheduler &scheduler)
Definition: mos652x.cpp:121
libsidplayfp::MOS652X::pra
uint8_t & pra
Ports.
Definition: mos652x.h:178
libsidplayfp::MOS652X::tod
Tod tod
TOD.
Definition: mos652x.h:194
libsidplayfp::MOS652X::model_t
model_t
Definition: mos652x.h:163
libsidplayfp::MOS652X::MOS6526W4485
@ MOS6526W4485
A batch of old CIA model with unique serial port behavior.
Definition: mos652x.h:166
libsidplayfp::MOS652X::MOS6526
@ MOS6526
Old CIA model, interrupts are delayed by 1 clock.
Definition: mos652x.h:164
libsidplayfp::MOS652X::MOS8521
@ MOS8521
New CIA model.
Definition: mos652x.h:165
libsidplayfp::MOS652X::credits
static const char * credits()
Definition: mos652x.cpp:111
libsidplayfp::MOS652X::setModel
void setModel(model_t model)
Definition: mos652x.cpp:321
libsidplayfp::MOS652X::reset
virtual void reset()
Definition: mos652x.cpp:145
libsidplayfp::MOS652X::bTickEvent
EventCallback< MOS652X > bTickEvent
Events.
Definition: mos652x.h:201
libsidplayfp::MOS652X::read
uint8_t read(uint_least8_t addr)
Definition: mos652x.cpp:181
libsidplayfp::MOS652X::interruptSource
std::unique_ptr< InterruptSource > interruptSource
Interrupt Source.
Definition: mos652x.h:191
libsidplayfp::MOS652X::serialPort
SerialPort serialPort
Serial Data Registers.
Definition: mos652x.h:197
libsidplayfp::MOS652X::setDayOfTimeRate
void setDayOfTimeRate(unsigned int clock)
Definition: mos652x.h:309
libsidplayfp::MOS652X::interrupt
virtual void interrupt(bool state)=0
libsidplayfp::SerialPort
Definition: SerialPort.h:37
libsidplayfp::TimerA
Definition: mos652x.h:53
libsidplayfp::TimerA::TimerA
TimerA(EventScheduler &scheduler, MOS652X &parent)
Definition: mos652x.h:66
libsidplayfp::TimerB
Definition: mos652x.h:77
libsidplayfp::TimerB::TimerB
TimerB(EventScheduler &scheduler, MOS652X &parent)
Definition: mos652x.h:85
libsidplayfp::TimerB::cascade
void cascade()
Definition: mos652x.h:91
libsidplayfp::TimerB::started
bool started() const
Definition: mos652x.h:104
libsidplayfp::Timer
Definition: timer.h:43
libsidplayfp::Timer::wakeUpAfterSyncWithCpu
void wakeUpAfterSyncWithCpu()
Definition: timer.cpp:60
libsidplayfp::Timer::syncWithCpu
void syncWithCpu()
Definition: timer.cpp:37
libsidplayfp::Timer::state
int_least32_t state
CRA/CRB control register / state.
Definition: timer.h:95
libsidplayfp::Timer::parent
MOS652X & parent
Pointer to the MOS6526 which this Timer belongs to.
Definition: timer.h:92
libsidplayfp::Tod
Definition: tod.h:40
libsidplayfp::Tod::setPeriod
void setPeriod(event_clock_t clock)
Definition: tod.h:118