namespace PIC_Simulator.PIC { class PICTimer { private PICProgramm programm; public PICTimer(PICProgramm p) { programm = p; } private bool prev_RA4 = false; public void TimerBerechnen(uint cycles) { bool tmr_mode = programm.GetRegisterOhneBank(PICProgramm.ADDR_OPTION, PICProgramm.OPTION_BIT_T0CS); bool edge_mode = programm.GetRegisterOhneBank(PICProgramm.ADDR_OPTION, PICProgramm.OPTION_BIT_T0SE); if (!tmr_mode) { bool curr_A4 = programm.GetRegisterOhneBank(PICProgramm.ADDR_PORT_A, 4); if (edge_mode) { if (prev_RA4 && !curr_A4) { TimerHochzaehlen(cycles); } } else { if (!prev_RA4 && curr_A4) { TimerHochzaehlen(cycles); } } } else { TimerHochzaehlen(cycles); } prev_RA4 = programm.GetRegisterOhneBank(PICProgramm.ADDR_PORT_A, 4); } private uint prescale_cntr = 0; // Zähler für timer private void TimerHochzaehlen(uint cycles) { uint current = programm.GetRegisterOhneBank(PICProgramm.ADDR_TMR0); uint scale = BerechneVorskalierung(); prescale_cntr += cycles; while (prescale_cntr >= scale) { prescale_cntr -= scale; uint Result = current + 1; if (Result > 0xFF) { //TODO Interrupt PIT_TIMER } Result %= 0x100; uint tmp_psc = prescale_cntr; programm.SetRegisterOhneBank(PICProgramm.ADDR_TMR0, Result); prescale_cntr = tmp_psc; } } private uint BerechneVorskalierung() { bool prescale_mode = programm.GetRegisterOhneBank(PICProgramm.ADDR_OPTION, PICProgramm.OPTION_BIT_PSA); uint scale = 0; scale += programm.GetRegisterOhneBank(PICProgramm.ADDR_OPTION, PICProgramm.OPTION_BIT_PS2) ? 1U : 0U; scale *= 2; scale += programm.GetRegisterOhneBank(PICProgramm.ADDR_OPTION, PICProgramm.OPTION_BIT_PS1) ? 1U : 0U; scale *= 2; scale += programm.GetRegisterOhneBank(PICProgramm.ADDR_OPTION, PICProgramm.OPTION_BIT_PS0) ? 1U : 0U; return prescale_mode ? 1 : (PICProgramm.SHL(2, scale)); } } }