Fantasy 8Bit system (F8), is a fantasy 8bit console and a set of libraries for creating fantasy 8bit consoles.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

737 lines
19KB

  1. const expect = require('chai').expect;
  2. const MOSCIA = require('../src/MOS/CIA.js');
  3. describe("MOSCIA Tests...", function(){
  4. //var cia = new MOSCIA();
  5. it("R/W Pin", function(){
  6. let cia = new MOSCIA();
  7. // The RW pin is default low, so writting should be enabled.
  8. cia.RS = 0x02;
  9. expect(cia.DATA).to.be.equal(0x00);
  10. cia.DATA = 0xFF;
  11. expect(cia.DATA).to.be.equal(0xFF);
  12. // Set RW high to disable writting!
  13. cia.RW = 1;
  14. cia.DATA = 0x00;
  15. expect(cia.DATA).to.be.equal(0xFF);
  16. // Set it low once more
  17. cia.RW = 0;
  18. cia.DATA = 0x00;
  19. expect(cia.DATA).to.be.equal(0x00);
  20. });
  21. it("Interrupts (via FLAG)", function(){
  22. let cia = new MOSCIA();
  23. cia.FLAG = 1;
  24. cia.RS = 0x0D;
  25. let IC = cia.DATA;
  26. expect(IC & 0x10).to.be.equal(0x10);
  27. expect(IC & 0x80).to.be.equal(0x80);
  28. expect(cia.DATA).to.be.equal(0x00);
  29. // Setting data changes the interrupt mask. This should mask the
  30. // FLAG interrupt.
  31. cia.DATA = 0x90;
  32. cia.FLAG = 1;
  33. IC = cia.DATA;
  34. expect(IC).to.be.equal(0x00);
  35. });
  36. it("PD*/DD* Masking", function(){
  37. let cia = new MOSCIA();
  38. let pdaVal = 0x3C;
  39. let pdbVal = 0xC3;
  40. cia.onRead("PDA", (name, dda) => {
  41. if (dda < 255)
  42. cia.setPDA(pdaVal);
  43. });
  44. cia.onRead("PDB", (name, ddb) => {
  45. if (ddb < 255)
  46. cia.setPDB(pdbVal);
  47. });
  48. cia.RS = 0x02;
  49. cia.DATA = 0x00;
  50. cia.RS = 0x00;
  51. expect(cia.DATA).to.be.equal(pdaVal);
  52. cia.RS = 0x03;
  53. cia.DATA = 0x00;
  54. cia.RS = 0x01;
  55. expect(cia.DATA).to.be.equal(pdbVal);
  56. cia.RS = 0x02;
  57. cia.DATA = pdbVal;
  58. cia.RS = 0x00;
  59. cia.DATA = pdbVal;
  60. expect(cia.DATA).to.be.equal(0xFF);
  61. cia.RS = 0x03;
  62. cia.DATA = pdaVal;
  63. cia.RS = 0x01;
  64. cia.DATA = pdaVal;
  65. expect(cia.DATA).to.be.equal(0xFF);
  66. });
  67. it("Serial IO", function(){
  68. let cia = new MOSCIA();
  69. let Input = (i) => {
  70. cia.SP = i;
  71. cia.CNT = 1;
  72. cia.phi2 = 1;
  73. };
  74. var outval = 0;
  75. let Output = () => {
  76. cia.CNT = 1;
  77. cia.phi2 = 1;
  78. outval = (outval << 1) | cia.SP;
  79. }
  80. cia.RS = 0x0C;
  81. Input(1);
  82. expect(cia.DATA).to.be.equal(1);
  83. Input(1);
  84. expect(cia.DATA).to.be.equal(3);
  85. Input(0);
  86. expect(cia.DATA).to.be.equal(6);
  87. Input(0);
  88. Input(1);
  89. Input(1);
  90. Input(0);
  91. Input(1);
  92. expect(cia.DATA).to.be.equal(0xCD);
  93. cia.RS = 0x0D;
  94. let IC = cia.DATA;
  95. expect(IC & 0x08).to.be.equal(0x08);
  96. expect(IC & 0x80).to.be.equal(0x80);
  97. // Reading from RS = 0x0D should clear the interrupt values. Checking this
  98. expect(cia.DATA).to.be.equal(0);
  99. cia.RS = 0x0E;
  100. cia.DATA = 0x40; // Enable serial output.
  101. Output();
  102. expect(outval).to.be.equal(1);
  103. Output();
  104. expect(outval).to.be.equal(3);
  105. Output();
  106. expect(outval).to.be.equal(6);
  107. Output();
  108. Output();
  109. Output();
  110. Output();
  111. Output();
  112. expect(outval).to.be.equal(0xCD);
  113. cia.RS = 0x0C;
  114. expect(cia.DATA).to.be.equal(0);
  115. cia.RS = 0x0D;
  116. expect((cia.DATA & 0x08) >> 3).to.be.equal(1);
  117. expect(cia.DATA).to.be.equal(0);
  118. });
  119. it("TOD 60hz", function(){
  120. // NOTE: The TOD clock doesn't actually enforce the frequency.
  121. // The TOD 'pin' is expected to be attached to a clock pulsing at the
  122. // designated frequency.
  123. // As such, this test will run MUCH MUCH faster than the 1.1 seconds
  124. // actually being checked (because I'm not using a clock here).
  125. let cia = new MOSCIA();
  126. let tick60 = () => {
  127. for (let i=0; i < 6; i++)
  128. cia.TOD = 1;
  129. };
  130. // NOTE: The CIA defaults to 60hz TOD clock. Nothing needs to be set.
  131. // Check that seconds is at 0 (we'll test this again later)
  132. cia.RS = 0x09;
  133. expect(cia.DATA).to.be.equal(0);
  134. // Switch to 10ths of a second and go!
  135. cia.RS = 0x08;
  136. expect(cia.DATA).to.be.equal(0);
  137. tick60();
  138. expect(cia.DATA).to.be.equal(0x01);
  139. tick60();
  140. expect(cia.DATA).to.be.equal(0x02);
  141. tick60();
  142. expect(cia.DATA).to.be.equal(0x03);
  143. for (let i=0; i < 8; i++)
  144. tick60();
  145. // Should have looped back around a little at this point!
  146. expect(cia.DATA).to.be.equal(0x01);
  147. // Check seconds again. This should have gone up once!
  148. cia.RS = 0x09;
  149. expect(cia.DATA).to.be.equal(0x01);
  150. });
  151. it("TOD 50hz", function(){
  152. // NOTE: The TOD clock doesn't actually enforce the frequency.
  153. // The TOD 'pin' is expected to be attached to a clock pulsing at the
  154. // designated frequency.
  155. // As such, this test will run MUCH MUCH faster than the 1.1 seconds
  156. // actually being checked (because I'm not using a clock here).
  157. let cia = new MOSCIA();
  158. let tick50 = () => {
  159. for (let i=0; i < 5; i++)
  160. cia.TOD = 1;
  161. };
  162. // enabling 50 hz mode.
  163. cia.RS = 0x0E;
  164. cia.DATA = cia.DATA | 0x80;
  165. // Check that seconds is at 0 (we'll test this again later)
  166. cia.RS = 0x09;
  167. expect(cia.DATA).to.be.equal(0);
  168. // Switch to 10ths of a second and go!
  169. cia.RS = 0x08;
  170. expect(cia.DATA).to.be.equal(0);
  171. tick50();
  172. expect(cia.DATA).to.be.equal(0x01);
  173. tick50();
  174. expect(cia.DATA).to.be.equal(0x02);
  175. tick50();
  176. expect(cia.DATA).to.be.equal(0x03);
  177. for (let i=0; i < 8; i++)
  178. tick50();
  179. // Should have looped back around a little at this point!
  180. expect(cia.DATA).to.be.equal(0x01);
  181. // Check seconds again. This should have gone up once!
  182. cia.RS = 0x09;
  183. expect(cia.DATA).to.be.equal(0x01);
  184. });
  185. it("TOD Latching", function(){
  186. let cia = new MOSCIA();
  187. let tick = (cycles) => {
  188. let ccount = cycles * 6;
  189. for (let i=0; i < ccount; i++)
  190. cia.TOD = 1;
  191. };
  192. cia.setTOD(0x03, 0x59, 0x58, 0x00);
  193. // Copying current clock values for later reference.
  194. let TOD = [0,0,0,0];
  195. cia.RS = 0x08;
  196. TOD[0] = cia.DATA;
  197. cia.RS = 0x09;
  198. TOD[1] = cia.DATA;
  199. cia.RS = 0x0A;
  200. TOD[2] = cia.DATA;
  201. cia.RS = 0x0B;
  202. TOD[3] = cia.DATA; // This should latch the timer!!
  203. tick(11); // Simulate 1.1 second time passing.
  204. // TOD Latch shouldn't be released until next read from RS=0x08, so...
  205. expect(cia.DATA).to.be.equal(TOD[3]);
  206. cia.RS = 0x0A;
  207. expect(cia.DATA).to.be.equal(TOD[2]);
  208. cia.RS = 0x09;
  209. expect(cia.DATA).to.be.equal(TOD[1]);
  210. cia.RS = 0x08;
  211. expect(cia.DATA).to.be.equal(TOD[0]); // Should release the TOD latch
  212. // With latch released, we should be able to read the new time...
  213. expect(cia.DATA).to.be.equal(0x01);
  214. cia.RS = 0x09;
  215. expect(cia.DATA).to.be.equal(0x59);
  216. });
  217. it("TOD Time Rollover with AM/PM change", function(){
  218. let cia = new MOSCIA();
  219. let tick = () => {
  220. for (let i=0; i < 6; i++)
  221. cia.TOD = 1;
  222. };
  223. cia.setTOD(0x11, 0x59, 0x59, 0x09);
  224. tick();
  225. cia.RS = 0x0B;
  226. expect(cia.DATA).to.be.equal(0x80);
  227. cia.RS = 0x0A;
  228. expect(cia.DATA).to.be.equal(0x00);
  229. cia.RS = 0x09;
  230. expect(cia.DATA).to.be.equal(0x00);
  231. cia.RS = 0x08;
  232. expect(cia.DATA).to.be.equal(0x00);
  233. cia.setTOD(0x91, 0x59, 0x59, 0x09);
  234. tick();
  235. cia.RS = 0x0B;
  236. expect(cia.DATA).to.be.equal(0x00);
  237. cia.RS = 0x0A;
  238. expect(cia.DATA).to.be.equal(0x00);
  239. cia.RS = 0x09;
  240. expect(cia.DATA).to.be.equal(0x00);
  241. cia.RS = 0x08;
  242. expect(cia.DATA).to.be.equal(0x00);
  243. });
  244. it("TOD Write Time and Cycle Stop on Write", function(){
  245. let cia = new MOSCIA();
  246. let tick = (cycles) => {
  247. let ccount = cycles * 6;
  248. for (let i=0; i < ccount; i++)
  249. cia.TOD = 1;
  250. };
  251. cia.RS = 0x0B;
  252. cia.DATA = 0x11;
  253. cia.RS = 0x0A;
  254. cia.DATA = 0x30;
  255. cia.RS = 0x09;
  256. cia.DATA = 0x20;
  257. // The lock on the timer isn't released until a write to RS=0x08
  258. // so running a few ticks should NOT change the current values!
  259. tick(10);
  260. cia.RS = 0x0B;
  261. expect(cia.DATA).to.be.equal(0x11);
  262. cia.RS = 0x0A;
  263. expect(cia.DATA).to.be.equal(0x30);
  264. cia.RS = 0x09;
  265. expect(cia.DATA).to.be.equal(0x20);
  266. cia.RS = 0x08;
  267. expect(cia.DATA).to.be.equal(0x00);
  268. // Write to RS=0x08 and cycle again!
  269. cia.DATA = 0x08; // <= 8/10ths a second.
  270. tick(8);
  271. expect(cia.DATA).to.be.equal(0x06);
  272. cia.RS = 0x09;
  273. expect(cia.DATA).to.be.equal(0x21);
  274. // Check if writing is prevented unless Hours (0x0B) is written to first
  275. cia.DATA = 0x44;
  276. expect(cia.DATA).to.be.equal(0x21);
  277. cia.RS = 0x08;
  278. cia.DATA = 0x04;
  279. expect(cia.DATA).to.be.equal(0x06);
  280. });
  281. it("TOD Alarm Set and Trigger", function(){
  282. let cia = new MOSCIA();
  283. let tick = (cycles) => {
  284. let ccount = cycles * 6;
  285. for (let i=0; i < ccount; i++)
  286. cia.TOD = 1;
  287. };
  288. // Setting alarm values.
  289. cia.RS = 0x0F;
  290. cia.DATA = cia.DATA | 0x80;
  291. cia.RS = 0x0B;
  292. cia.DATA = 0x01;
  293. cia.RS = 0x0A;
  294. cia.DATA = 0x01;
  295. cia.RS = 0x09;
  296. cia.DATA = 0x01;
  297. cia.RS = 0x08;
  298. cia.DATA = 0x04;
  299. // Testing that all TOD values remain unchanged.
  300. expect(cia.DATA).to.be.equal(0x00);
  301. cia.RS = 0x09;
  302. expect(cia.DATA).to.be.equal(0x00);
  303. cia.RS = 0x0A;
  304. expect(cia.DATA).to.be.equal(0x00);
  305. cia.RS = 0x0B;
  306. expect(cia.DATA).to.be.equal(0x00);
  307. // Forcing TOD to be 4/10ths a second from triggering the alarm.
  308. cia.setTOD(0x01, 0x01, 0x01, 0x00);
  309. tick(4);
  310. cia.RS = 0x0D;
  311. // Hold the value as the IC clears after a read.
  312. let IC = cia.DATA;
  313. expect(IC & 0x04).to.be.equal(0x04);
  314. expect(IC & 0x80).to.be.equal(0x80);
  315. });
  316. it("Timer A, phi2 Triggered, Interrupt Verification", function(){
  317. let cia = new MOSCIA();
  318. let tick = (cycles) => {
  319. for (let i=0; i < cycles; i++)
  320. cia.phi2 = 1;
  321. };
  322. cia.RS = 0x04;
  323. cia.DATA = 0xFF;
  324. cia.RS = 0x05;
  325. cia.DATA = 0x01;
  326. cia.RS = 0x0E;
  327. // Force latch load into Timer A and activate Timer A
  328. cia.DATA = cia.DATA | 0x11;
  329. cia.RS = 0x04;
  330. expect(cia.DATA).to.be.equal(0xFF);
  331. tick(1);
  332. expect(cia.DATA).to.be.equal(0xFE);
  333. tick(1);
  334. expect(cia.DATA).to.be.equal(0xFD);
  335. tick(0x0200 - 3);
  336. expect(cia.DATA).to.be.equal(0x00);
  337. cia.RS = 0x05;
  338. expect(cia.DATA).to.be.equal(0x00);
  339. tick(1);
  340. expect(cia.DATA).to.be.equal(0x01);
  341. cia.RS = 0x04;
  342. expect(cia.DATA).to.be.equal(0xFF);
  343. cia.RS = 0x0D;
  344. let IC = cia.DATA;
  345. expect(IC & 0x01).to.be.equal(0x01);
  346. expect(IC & 0x80).to.be.equal(0x80);
  347. });
  348. it("Timer A, CNT Triggered, Underflow report to Port B", function(){
  349. let cia = new MOSCIA();
  350. let tick = (cycles, cnt) => {
  351. cnt = (cnt === true);
  352. for (let i=0; i < cycles; i++){
  353. if (cnt)
  354. cia.CNT = 1;
  355. cia.phi2 = 1;
  356. if (cnt)
  357. cia.CNT = 0;
  358. }
  359. };
  360. cia.RS = 0x04;
  361. cia.DATA = 0x08;
  362. cia.RS = 0x05;
  363. cia.DATA = 0x00;
  364. cia.RS = 0x0E;
  365. // Force latch load into Timer A,
  366. // enable underflow reporting on Port B bit 6,
  367. // set Timer A to trigger on CNT,
  368. // and activate Timer A
  369. cia.DATA = 0x33;
  370. cia.RS = 0x04;
  371. // First, test a few ticks where CNT is not high.
  372. expect(cia.DATA).to.be.equal(0x08); // Validate inital timer value.
  373. tick(1);
  374. tick(1);
  375. tick(1);
  376. tick(1);
  377. expect(cia.DATA).to.be.equal(0x08);
  378. // Now verify CNT triggers!
  379. tick(1, true);
  380. expect(cia.DATA).to.be.equal(0x07);
  381. tick(1, true);
  382. expect(cia.DATA).to.be.equal(0x06);
  383. tick(1, true);
  384. tick(1, true);
  385. tick(1, true);
  386. tick(1, true);
  387. tick(1, true);
  388. tick(1, true);
  389. expect(cia.DATA).to.be.equal(0x00);
  390. tick(1, true);
  391. // Double check that timer has reset to latch value...
  392. expect(cia.DATA).to.be.equal(0x08);
  393. // Verify Interrupt (again... but it doesn't hurt!)
  394. cia.RS = 0x0D;
  395. let IC = cia.DATA;
  396. expect(IC & 0x01).to.be.equal(0x01);
  397. expect(IC & 0x80).to.be.equal(0x80);
  398. // Checking Port B bit 6 which should only go high for 1 cycle!
  399. cia.RS = 0x01;
  400. expect(cia.DATA & 0x40).to.be.equal(0x40);
  401. tick(1, true);
  402. expect(cia.DATA & 0x40).to.be.equal(0x00);
  403. // Check Port B bit 6 toggling...
  404. // -------------------------------------------
  405. // Force latch load into Timer A,
  406. // enable underflow reporting on Port B bit 6,
  407. // setup Port B bit 6 to invert,
  408. // set Timer A to trigger on CNT,
  409. // and activate Timer A
  410. cia.RS = 0x0E;
  411. cia.DATA = 0x37;
  412. for (let i=0; i < 9; i++)
  413. tick(1, true);
  414. cia.RS = 0x04;
  415. expect(cia.DATA).to.be.equal(0x08);
  416. cia.RS = 0x01;
  417. expect(cia.DATA & 0x40).to.be.equal(0x40);
  418. tick(1, true);
  419. expect(cia.DATA & 0x40).to.be.equal(0x40);
  420. cia.RS = 0x04;
  421. expect(cia.DATA).to.be.equal(0x07);
  422. for (let i=0; i < 8; i++)
  423. tick(1, true);
  424. expect(cia.DATA).to.be.equal(0x08);
  425. cia.RS = 0x01;
  426. expect(cia.DATA & 0x40).to.be.equal(0x00);
  427. });
  428. it("Timer B, phi2 Triggered, Interrupt Verification", function(){
  429. let cia = new MOSCIA();
  430. let tick = (cycles) => {
  431. for (let i=0; i < cycles; i++)
  432. cia.phi2 = 1;
  433. };
  434. cia.RS = 0x06;
  435. cia.DATA = 0xFF;
  436. cia.RS = 0x07;
  437. cia.DATA = 0x01;
  438. cia.RS = 0x0F;
  439. // Force latch load into Timer B and activate Timer B
  440. cia.DATA = cia.DATA | 0x11;
  441. cia.RS = 0x06;
  442. expect(cia.DATA).to.be.equal(0xFF);
  443. tick(1);
  444. expect(cia.DATA).to.be.equal(0xFE);
  445. tick(1);
  446. expect(cia.DATA).to.be.equal(0xFD);
  447. tick(0x0200 - 3);
  448. expect(cia.DATA).to.be.equal(0x00);
  449. cia.RS = 0x07;
  450. expect(cia.DATA).to.be.equal(0x00);
  451. tick(1);
  452. expect(cia.DATA).to.be.equal(0x01);
  453. cia.RS = 0x06;
  454. expect(cia.DATA).to.be.equal(0xFF);
  455. cia.RS = 0x0D;
  456. let IC = cia.DATA;
  457. expect(IC & 0x02).to.be.equal(0x02);
  458. expect(IC & 0x80).to.be.equal(0x80);
  459. });
  460. it("Timer B, CNT Triggered, Underflow report to Port B", function(){
  461. let cia = new MOSCIA();
  462. let tick = (cycles, cnt) => {
  463. cnt = (cnt === true);
  464. for (let i=0; i < cycles; i++){
  465. if (cnt)
  466. cia.CNT = 1;
  467. cia.phi2 = 1;
  468. if (cnt)
  469. cia.CNT = 0;
  470. }
  471. };
  472. cia.RS = 0x06;
  473. cia.DATA = 0x08;
  474. cia.RS = 0x07;
  475. cia.DATA = 0x00;
  476. cia.RS = 0x0F;
  477. // Force latch load into Timer B,
  478. // enable underflow reporting on Port B bit 7,
  479. // set Timer B to trigger on CNT,
  480. // and activate Timer B
  481. cia.DATA = 0x33;
  482. cia.RS = 0x06;
  483. // First, test a few ticks where CNT is not high.
  484. expect(cia.DATA).to.be.equal(0x08); // Validate inital timer value.
  485. tick(1);
  486. tick(1);
  487. tick(1);
  488. tick(1);
  489. expect(cia.DATA).to.be.equal(0x08);
  490. // Now verify CNT triggers!
  491. tick(1, true);
  492. expect(cia.DATA).to.be.equal(0x07);
  493. tick(1, true);
  494. expect(cia.DATA).to.be.equal(0x06);
  495. tick(1, true);
  496. tick(1, true);
  497. tick(1, true);
  498. tick(1, true);
  499. tick(1, true);
  500. tick(1, true);
  501. expect(cia.DATA).to.be.equal(0x00);
  502. tick(1, true);
  503. // Double check that timer has reset to latch value...
  504. expect(cia.DATA).to.be.equal(0x08);
  505. // Verify Interrupt (again... but it doesn't hurt!)
  506. cia.RS = 0x0D;
  507. let IC = cia.DATA;
  508. expect(IC & 0x02).to.be.equal(0x02);
  509. expect(IC & 0x80).to.be.equal(0x80);
  510. // Checking Port B bit 7 which should only go high for 1 cycle!
  511. cia.RS = 0x01;
  512. expect(cia.DATA & 0x80).to.be.equal(0x80);
  513. tick(1, true);
  514. expect(cia.DATA & 0x80).to.be.equal(0x00);
  515. // Check Port B bit 7 toggling...
  516. // -------------------------------------------
  517. // Force latch load into Timer B,
  518. // enable underflow reporting on Port B bit 7,
  519. // setup Port B bit 7 to invert,
  520. // set Timer B to trigger on CNT,
  521. // and activate Timer B
  522. cia.RS = 0x0F;
  523. cia.DATA = 0x37;
  524. for (let i=0; i < 9; i++)
  525. tick(1, true);
  526. cia.RS = 0x06;
  527. expect(cia.DATA).to.be.equal(0x08);
  528. cia.RS = 0x01;
  529. expect(cia.DATA & 0x80).to.be.equal(0x80);
  530. tick(1, true);
  531. expect(cia.DATA & 0x80).to.be.equal(0x80);
  532. cia.RS = 0x06;
  533. expect(cia.DATA).to.be.equal(0x07);
  534. for (let i=0; i < 8; i++)
  535. tick(1, true);
  536. expect(cia.DATA).to.be.equal(0x08);
  537. cia.RS = 0x01;
  538. expect(cia.DATA & 0x80).to.be.equal(0x00);
  539. });
  540. it("Timer B tick on Timer A Underflow (phi2 Triggered)", function(){
  541. let cia = new MOSCIA();
  542. let tick = (cycle) => {
  543. for (let i=0; i < cycle; i++)
  544. cia.phi2 = 1;
  545. };
  546. // Setting up Timer A
  547. cia.RS = 0x04;
  548. cia.DATA = 0x02;
  549. cia.RS = 0x0E;
  550. cia.DATA = 0x11;
  551. // Setting up Timer B
  552. cia.RS = 0x06;
  553. cia.DATA = 0x01;
  554. cia.RS = 0x0F;
  555. cia.DATA = 0x51;
  556. cia.RS = 0x06;
  557. // Verify Timer B Low Byte Value
  558. expect(cia.DATA).to.be.equal(0x01);
  559. tick(1);
  560. // Timer B should not have changed.
  561. expect(cia.DATA).to.be.equal(0x01);
  562. // Timer A should have ticked down by 1.
  563. cia.RS = 0x04;
  564. expect(cia.DATA).to.be.equal(0x01);
  565. tick(1); tick(1);
  566. // Timer A should have underflowed and Timer B ticked down by 1
  567. expect(cia.DATA).to.be.equal(0x02);
  568. cia.RS = 0x06;
  569. expect(cia.DATA).to.be.equal(0x00);
  570. // Check that Timer A triggered interrupt... but Timer B did not!
  571. cia.RS = 0x0D;
  572. let IC = cia.DATA;
  573. expect(IC & 0x01).to.be.equal(0x01);
  574. expect(IC & 0x02).to.be.equal(0x00);
  575. tick(3); // Run through Timer A once more.
  576. // Check that both Timer A & B triggered interrupt!
  577. IC = cia.DATA;
  578. expect(IC & 0x01).to.be.equal(0x01);
  579. expect(IC & 0x02).to.be.equal(0x02);
  580. // Both timers should have latched back to their starting values.
  581. cia.RS = 0x04;
  582. expect(cia.DATA).to.be.equal(0x02);
  583. cia.RS = 0x06;
  584. expect(cia.DATA).to.be.equal(0x01);
  585. });
  586. it("Timer B ticks on Timer A Underflow (CNT Triggered for B only)", function(){
  587. let cia = new MOSCIA();
  588. let tick = (cycle) => {
  589. for (let i=0; i < cycle; i++)
  590. cia.phi2 = 1;
  591. };
  592. // Setup Timer A (trigger on phi2 only)
  593. cia.RS = 0x04;
  594. cia.DATA = 0x02;
  595. cia.RS = 0x0E;
  596. cia.DATA = 0x11;
  597. // Setup Timer B (trigger on A underflow and CNT high)
  598. cia.RS = 0x06;
  599. cia.DATA = 0x01;
  600. cia.RS = 0x0F;
  601. cia.DATA = 0x71;
  602. // Keep CNT low, check that underflowing A *does NOT* tick B.
  603. cia.CNT = 0; // <-- Just to be sure.
  604. tick(2);
  605. // Just make sure we're ticking A
  606. cia.RS = 0x04;
  607. expect(cia.DATA).to.be.equal(0x00);
  608. tick(1);
  609. expect(cia.DATA).to.be.equal(0x02);
  610. // Make sure B did not tick!
  611. cia.RS = 0x06;
  612. expect(cia.DATA).to.be.equal(0x01);
  613. // Clear interrupt flags
  614. cia.RS = 0x0D;
  615. let IC = cia.DATA;
  616. // NOW tick with CNT high!
  617. cia.CNT = 1;
  618. tick(3);
  619. // Checking A rolled over
  620. cia.RS = 0x04;
  621. expect(cia.DATA).to.be.equal(0x02);
  622. // Now checking B ticked...
  623. cia.RS = 0x06;
  624. expect(cia.DATA).to.be.equal(0x00);
  625. // Double check CNT is high
  626. expect(cia.CNT).to.be.equal(1);
  627. // One more A cycle to check B rolls over!
  628. tick(3);
  629. expect(cia.DATA).to.be.equal(0x01);
  630. cia.RS = 0x04;
  631. expect(cia.DATA).to.be.equal(0x02);
  632. });
  633. });