| } | } | ||||
| function TimerATick(cia){ | |||||
| if (cia.__timerA > 0){ | |||||
| cia.__timerA -= 1; | |||||
| } else { | |||||
| // Check if Timer A is continuous | |||||
| if (BITM.isOn(cia.__CTA, 3) === 0){ | |||||
| cia.__timerA = cia.__timerALatch; | |||||
| } else { | |||||
| // Not continuous, so clear bit 0 (stop timer). | |||||
| cia.__CTA = BITM.clear(cia.__CTA, 0); | |||||
| } | |||||
| // Check to see if timer modifies the PORT B bit 6. | |||||
| // If so, determine if it's a pulse or an toggle. | |||||
| if (BITM.isOn(cia.__CTA, 1)) | |||||
| cia.__PDB = (BITM.isOn(cia.__CTA, 2) === 0) ? BITM.set(cia.__PDB, 6) : BITM.toggle(cia.__PDB, 6); | |||||
| // If timer B is running, and timer B tracks timer A underflows | |||||
| // tick timer B (or, tick it if CNT is positive) | |||||
| if (BITM.isOn(cia.__CTB, 0)){ | |||||
| let cs = (this.__CTB & 0x60) >> 5; | |||||
| if (cs === 2 || (cs === 3 && cia.__CNT === 1)) | |||||
| TimerBTick(cia); | |||||
| } | |||||
| } | |||||
| } | |||||
| function TimerBTick(cia){ | |||||
| if (cia.__timerB > 0){ | |||||
| cia.__timerB -= 1; | |||||
| } else { | |||||
| if (BITM.isOn(cia.__CTB, 3) === 0){ | |||||
| cia.__timerB = cia.__timerBLatch; | |||||
| } else { | |||||
| cia.__CTB = BITM.clear(cia.__CTB, 0); | |||||
| } | |||||
| if (BITM.isOn(cia.__CTB, 1)) | |||||
| cia.__PDB = (BITM.isOn(cia.__CTB, 2) === 0) ? BITM.set(cia.__PDB, 7) : BITM.toggle(cia.__PDB, 7); | |||||
| } | |||||
| } | |||||
| class MOSCIA{ | class MOSCIA{ | ||||
| constructor(){ | constructor(){ | ||||
| this.__regsel = 0; | this.__regsel = 0; | ||||
| this.__CNT = 0; | |||||
| this.__PDA = 0; | this.__PDA = 0; | ||||
| this.__PDB = 0; | this.__PDB = 0; | ||||
| this.__DDA = 0; | this.__DDA = 0; | ||||
| case 0x03: // Data Direction Reg B | case 0x03: // Data Direction Reg B | ||||
| break; | break; | ||||
| case 0x04: // Timer A Low | case 0x04: // Timer A Low | ||||
| break; | |||||
| val = (this.__timerA & 0x00FF); break; | |||||
| case 0x05: // Timer A High | case 0x05: // Timer A High | ||||
| break | |||||
| val = ((this.__timerA & 0xFF00) >> 4); break; | |||||
| case 0x06: // Timer B Low | case 0x06: // Timer B Low | ||||
| break; | |||||
| val = (this.__timerB & 0x00FF); break; | |||||
| case 0x07: // Timer B High | case 0x07: // Timer B High | ||||
| break; | |||||
| val = ((this.__timerB & 0xFF00) >> 4); break; | |||||
| case 0x08: // 10th of Sec Reg | case 0x08: // 10th of Sec Reg | ||||
| this.__TODLatch = 0; | this.__TODLatch = 0; | ||||
| return this.__TOD[0]; break; | |||||
| val = this.__TOD[0]; break; | |||||
| case 0x09: // Seconds Reg | case 0x09: // Seconds Reg | ||||
| return (this.__TODLatch > 0) ? this.__LTOD[1] : this.__TOD[1]; break; | |||||
| val = (this.__TODLatch > 0) ? this.__LTOD[1] : this.__TOD[1]; break; | |||||
| case 0x0A: // Minutes Reg | case 0x0A: // Minutes Reg | ||||
| return (this.__TODLatch > 0) ? this.__LTOD[2] : this.__TOD[2]; break; | |||||
| val = (this.__TODLatch > 0) ? this.__LTOD[2] : this.__TOD[2]; break; | |||||
| case 0x0B: // Hours AM/PM Reg | case 0x0B: // Hours AM/PM Reg | ||||
| TODLatch(this); | TODLatch(this); | ||||
| return this.__LTOD[3]; break; | |||||
| val = this.__LTOD[3]; break; | |||||
| case 0x0C: // Serial Data | case 0x0C: // Serial Data | ||||
| break; | break; | ||||
| case 0x0D: // Interrupt Control | case 0x0D: // Interrupt Control | ||||
| break; | break; | ||||
| case 0x0E: // Control Timer Reg A | case 0x0E: // Control Timer Reg A | ||||
| break; | |||||
| val = this.__CTA; break; | |||||
| case 0x0F: // Control Timer Reg B | case 0x0F: // Control Timer Reg B | ||||
| break; | |||||
| val = this.__CTB; break; | |||||
| } | } | ||||
| return val; | return val; | ||||
| } | } | ||||
| case 0x03: // Data Direction Reg B | case 0x03: // Data Direction Reg B | ||||
| break; | break; | ||||
| case 0x04: // Timer A Low | case 0x04: // Timer A Low | ||||
| this.__timerALatch = (this.__timerALatch & 0xFF00) | (d & 0xFF); | |||||
| break; | break; | ||||
| case 0x05: // Timer A High | case 0x05: // Timer A High | ||||
| this.__timerALatch = (this.__timerALatch & 0x00FF) | ((d & 0xFF) << 4); | |||||
| break | break | ||||
| case 0x06: // Timer B Low | case 0x06: // Timer B Low | ||||
| this.__timerBLatch = (this.__timerBLatch & 0xFF00) | (d & 0xFF); | |||||
| break; | break; | ||||
| case 0x07: // Timer B High | case 0x07: // Timer B High | ||||
| this.__timerBLatch = (this.__timerBLatch & 0x00FF) | ((d & 0xFF) << 4); | |||||
| break; | break; | ||||
| case 0x08: // 10th of Sec Reg | case 0x08: // 10th of Sec Reg | ||||
| TODLatch(this); | TODLatch(this); | ||||
| case 0x0D: // Interrupt Control | case 0x0D: // Interrupt Control | ||||
| break; | break; | ||||
| case 0x0E: // Control Timer Reg A | case 0x0E: // Control Timer Reg A | ||||
| this.__CTA = d & 0xFF; | |||||
| if (BITM.isOn(this.__CTA, 4)) | |||||
| this.__timerA = this.__timerALatch; | |||||
| break; | break; | ||||
| case 0x0F: // Control Timer Reg B | case 0x0F: // Control Timer Reg B | ||||
| this.__CTB = d & 0xFF; | |||||
| if (BITM.isOn(this.__CTB, 4)) | |||||
| this.__timerB = this.__timerBLatch; | |||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| get CNT(){return 0;} | |||||
| set CNT(c){} | |||||
| get CNT(){return this.__CNT;} | |||||
| set CNT(c){ | |||||
| this.__CNT = (c >= 1) ? 1 : 0; | |||||
| if (this.__CNT === 1){ | |||||
| if (BITM.isOn(this.__CTA, 0) && BITM.isOn(this.__CTA, 5)) | |||||
| TimerATick(this); | |||||
| if (BITM.isOn(this.__CTB, 0){ | |||||
| let cs = (this.__CTB & 0x60) >> 5; | |||||
| if (cs === 1) | |||||
| TimerBTick(this); | |||||
| } | |||||
| } | |||||
| } | |||||
| get SP(){return 0;} | get SP(){return 0;} | ||||
| set SP(b){} | set SP(b){} | ||||
| if (b > 0 || this.__TODLatch < 2) | if (b > 0 || this.__TODLatch < 2) | ||||
| TODTick(this); | TODTick(this); | ||||
| } | } | ||||
| get phi2(){return 0;} | |||||
| set phi2(p){ | |||||
| if (p >= 1){ | |||||
| if (BITM.isOn(this.__CTA, 0) && !BITM.isOn(this.__CTA, 5)){ | |||||
| TimerATick(this); | |||||
| } | |||||
| if (BITM.isOn(this.__CTB, 0)){ | |||||
| let cs = (this.__CTB & 0x60) >> 5; | |||||
| if (cs === 0) | |||||
| TimerBTick(this); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | } | ||||