libsidplayfp 1.0.3
mos6526.h
00001 /*
00002  * This file is part of libsidplayfp, a SID player engine.
00003  *
00004  * Copyright 2011-2013 Leandro Nini <drfiemost@users.sourceforge.net>
00005  * Copyright 2007-2010 Antti Lankila
00006  * Copyright 2000 Simon White
00007  *
00008  * This program is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00021  */
00022 
00023 #ifndef MOS6526_H
00024 #define MOS6526_H
00025 
00026 #include <stdint.h>
00027 
00028 #include "timer.h"
00029 #include "sidplayfp/component.h"
00030 
00037 class TimerA : public Timer
00038 {
00039 private:
00043     void underFlow();
00044 
00045     void serialPort();
00046 
00047 public:
00051     TimerA(EventContext *context, MOS6526* parent) :
00052         Timer("CIA Timer A", context, parent) {}
00053 };
00054 
00061 class TimerB : public Timer
00062 {
00063 private:
00064     void underFlow();
00065 
00066 public:
00070     TimerB(EventContext *context, MOS6526* parent) :
00071         Timer("CIA Timer B", context, parent) {}
00072 
00076     void cascade()
00077     {
00078         /* we pretend that we are CPU doing a write to ctrl register */
00079         syncWithCpu();
00080         state |= CIAT_STEP;
00081         wakeUpAfterSyncWithCpu();
00082     }
00083 
00089     bool started() const { return (state & CIAT_CR_START) != 0; }
00090 };
00091 
00098 class MOS6526: public component
00099 {
00100     friend class TimerA;
00101     friend class TimerB;
00102 
00103 private:
00104     static const char *credit;
00105 
00106 protected:
00110     uint8_t regs[0x10];
00111 
00112     // Ports
00113     uint8_t &pra, &prb, &ddra, &ddrb;
00114 
00118     TimerA timerA;
00119     TimerB timerB;
00120 
00121     // Serial Data Registers
00122     uint8_t sdr_out;
00123     bool    sdr_buffered;
00124     int     sdr_count;
00125 
00127     uint8_t icr;
00128 
00130     uint8_t idr;
00131 
00135     EventContext &event_context;
00136 
00137     // TOD
00138     bool    m_todlatched;
00139     bool    m_todstopped;
00140     uint8_t m_todclock[4], m_todalarm[4], m_todlatch[4];
00141     event_clock_t m_todCycles, m_todPeriod;
00142 
00144     bool triggerScheduled;
00145 
00146     // Events
00147     EventCallback<MOS6526> bTickEvent;
00148     EventCallback<MOS6526> todEvent;
00149     EventCallback<MOS6526> triggerEvent;
00150 
00151 protected:
00157     MOS6526(EventContext *context);
00158     ~MOS6526() {}
00159 
00172     void bTick();
00173 
00177     void tod();
00178 
00182     void trigger();
00183 
00187     void underflowA();
00188 
00192     void underflowB();
00193 
00199   void trigger(uint8_t interruptMask);
00200 
00204     void clear();
00205 
00209     void serialPort();
00210 
00217     virtual void interrupt(bool state) = 0;
00218 
00219     virtual void portA() {}
00220     virtual void portB() {}
00221 
00228     uint8_t read(uint_least8_t addr);
00229 
00238     void write(uint_least8_t addr, uint8_t data);
00239 
00240 private:
00241     // TOD implementation taken from Vice
00242     static uint8_t byte2bcd(uint8_t byte) { return (((byte / 10) << 4) + (byte % 10)) & 0xff; }
00243     static uint8_t bcd2byte(uint8_t bcd) { return ((10*((bcd & 0xf0) >> 4)) + (bcd & 0xf)) & 0xff; }
00244 
00245 public:
00249     virtual void reset();
00250 
00256     const char *credits() const { return credit; }
00257 
00263     void setDayOfTimeRate(unsigned int clock);
00264 };
00265 
00266 #endif // MOS6526_H