libsidplayfp 1.0.3
|
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