t_stat pclk_show_freq (FILE *st, UNIT *uptr, int32 val, CONST void *desc) { static const char *freqs[] = {"100K Hz", "10K Hz", "Line Freq", "External (10Hz)"}; fprintf (st, "%s", freqs[CSR_GETRATE (pclk_csr)]); return SCPE_OK; }
t_stat pclk_svc (UNIT *uptr) { int32 rv; pclk_tick (); /* tick clock */ if ((pclk_csr & CSR_GO) == 0) /* done? */ return SCPE_OK; rv = CSR_GETRATE (pclk_csr); /* get rate */ sim_activate (&pclk_unit, sim_rtcn_calb (rate[rv], TMR_PCLK)); return SCPE_OK; }
static void pclk_set_ctr (uint32 val) { if ((pclk_csr & CSR_GO) == 0) /* stopped? */ pclk_ctr = val; /* save */ else { uint32 delay = DMASK & ((pclk_csr & CSR_UPDN) ? (DMASK + 1 - val) : val); int32 rv; rv = CSR_GETRATE (pclk_csr); /* get rate */ sim_activate_after (&pclk_unit, xtim[rv] * delay); /* schedule interrupt */ } }
t_stat pclk_wr (int32 data, int32 PA, int32 access) { int32 old_csr = pclk_csr; int32 rv; switch ((PA >> 1) & 03) { case 00: /* CSR */ pclk_csr = data & PCLKCSR_WRMASK; /* clear and write */ CLR_INT (PCLK); /* clr intr */ rv = CSR_GETRATE (pclk_csr); /* new rate */ if ((pclk_csr & CSR_GO) == 0) { /* stopped? */ pclk_ctr = pclk_get_ctr (); /* save current value */ sim_cancel (&pclk_unit); /* cancel */ if (data & CSR_FIX) { /* fix? tick */ pclk_ctr = DMASK & (pclk_ctr + (pclk_csr & CSR_UPDN)? 1 : -1); if (pclk_ctr == 0) pclk_svc (&pclk_unit); } } else if (((old_csr & CSR_GO) == 0) || /* run 0 -> 1? */ (rv != CSR_GETRATE (old_csr))) { /* rate change? */ sim_cancel (&pclk_unit); /* cancel */ pclk_set_ctr (pclk_csb); /* start clock */ } break; case 01: /* buffer */ pclk_csb = data; /* store ctr */ pclk_set_ctr (data); pclk_csr = pclk_csr & ~(CSR_ERR | CSR_DONE); /* clr err, done */ CLR_INT (PCLK); /* clr intr */ break; case 02: /* counter */ break; /* read only */ } return SCPE_OK; }
t_stat pclk_wr (int32 data, int32 PA, int32 access) { int32 old_csr = pclk_csr; int32 rv; switch ((PA >> 1) & 03) { case 00: /* CSR */ pclk_csr = data & PCLKCSR_WRMASK; /* clear and write */ CLR_INT (PCLK); /* clr intr */ rv = CSR_GETRATE (pclk_csr); /* new rate */ pclk_unit.wait = xtim[rv]; /* new delay */ if ((pclk_csr & CSR_GO) == 0) { /* stopped? */ sim_cancel (&pclk_unit); /* cancel */ if (data & CSR_FIX) /* fix? tick */ pclk_tick (); } else if (((old_csr & CSR_GO) == 0) || /* run 0 -> 1? */ (rv != CSR_GETRATE (old_csr))) { /* rate change? */ sim_cancel (&pclk_unit); /* cancel */ sim_activate (&pclk_unit, /* start clock */ sim_rtcn_init (pclk_unit.wait, TMR_PCLK)); } break; case 01: /* buffer */ pclk_csb = pclk_ctr = data; /* store ctr */ pclk_csr = pclk_csr & ~(CSR_ERR | CSR_DONE); /* clr err, done */ CLR_INT (PCLK); /* clr intr */ break; case 02: /* counter */ break; /* read only */ } return SCPE_OK; }
static uint32 pclk_get_ctr (void) { uint32 val; int32 rv; if (!sim_is_active (&pclk_unit)) return pclk_ctr; rv = CSR_GETRATE (pclk_csr); /* get rate */ val = (uint32)((sim_activate_time (&pclk_unit) / sim_timer_inst_per_sec ()) * (1000000 / xtim[rv])); val &= DMASK; if (pclk_csr & CSR_UPDN) val = DMASK + 1 - val; return val; }
t_stat pclk_svc (UNIT *uptr) { int32 rv; rv = CSR_GETRATE (pclk_csr); /* get rate */ if (pclk_csr & CSR_DONE) /* done already set? */ pclk_csr = pclk_csr | CSR_ERR; /* set error */ else pclk_csr = pclk_csr | CSR_DONE; /* else set done */ if (pclk_csr & CSR_IE) /* if IE, set int */ SET_INT (PCLK); if (pclk_csr & CSR_MODE) /* if rpt, reload */ pclk_set_ctr (pclk_csb); else { pclk_csb = 0; /* else clr ctr */ pclk_csr = pclk_csr & ~CSR_GO; /* and clr go */ } return SCPE_OK; }