From d62ff92a2002896bc19a4b400f2aa2a0b6297deb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20Schw=C3=B6rer?= Date: Tue, 16 May 2017 09:35:47 +0200 Subject: [PATCH] Timer (~) --- PIC_Simulator/Form1.cs | 62 +++++++++------ PIC_Simulator/PIC/PICProgramm.cs | 109 +++++++++++++++++++++++++-- PIC_Simulator/PIC/RS232Verbindung.cs | 12 ++- 3 files changed, 152 insertions(+), 31 deletions(-) diff --git a/PIC_Simulator/Form1.cs b/PIC_Simulator/Form1.cs index 6ef1002..7f30004 100644 --- a/PIC_Simulator/Form1.cs +++ b/PIC_Simulator/Form1.cs @@ -33,6 +33,7 @@ namespace PIC_Simulator lvSpecial.Items.Add(new ListViewItem(new[] { "W", "0x00" })); lvSpecial.Items.Add(new ListViewItem(new[] { "PC", "0x00" })); lvSpecial.Items.Add(new ListViewItem(new[] { "Status", "0b00000000" })); + lvSpecial.Items.Add(new ListViewItem(new[] { "Option", "0b00000000" })); lvSpecial.Items.Add(new ListViewItem(new[] { "Time", "0ms" })); lvSpecial.Items.Add(new ListViewItem(new[] { "RA (Backing)", "0b00000000" })); lvSpecial.Items.Add(new ListViewItem(new[] { "RB (Backing)", "0b00000000" })); @@ -196,12 +197,13 @@ namespace PIC_Simulator lvSpecial.Items[0].SubItems[1].Text = string.Format("0x{0:X2}", programm.Register_W); lvSpecial.Items[1].SubItems[1].Text = string.Format("{0,4}", programm.PCCounter); lvSpecial.Items[2].SubItems[1].Text = string.Format("0b{0}", Convert.ToString(programm.GetRegisterOhneBank(PICProgramm.ADDR_STATUS), 2).PadLeft(8, '0')); - lvSpecial.Items[3].SubItems[1].Text = string.Format("{0}ms", programm.Stepcount * int.Parse(insertTime.Text)); - lvSpecial.Items[4].SubItems[1].Text = "0b" + Convert.ToString(programm.Register[PICProgramm.ADDR_PORT_A], 2).PadLeft(8, '0'); - lvSpecial.Items[5].SubItems[1].Text = "0b" + Convert.ToString(programm.Register[PICProgramm.ADDR_PORT_B], 2).PadLeft(8, '0'); - lvSpecial.Items[6].SubItems[1].Text = programm.GetRegisterOhneBank(PICProgramm.ADDR_STATUS, PICProgramm.STATUS_BIT_C) ? "1" : "0"; - lvSpecial.Items[7].SubItems[1].Text = programm.GetRegisterOhneBank(PICProgramm.ADDR_STATUS, PICProgramm.STATUS_BIT_DC) ? "1" : "0"; - lvSpecial.Items[8].SubItems[1].Text = programm.GetRegisterOhneBank(PICProgramm.ADDR_STATUS, PICProgramm.STATUS_BIT_Z) ? "1" : "0"; + lvSpecial.Items[3].SubItems[1].Text = string.Format("0b{0}", Convert.ToString(programm.GetRegisterOhneBank(PICProgramm.ADDR_OPTION), 2).PadLeft(8, '0')); + lvSpecial.Items[4].SubItems[1].Text = string.Format("{0}ms", programm.Stepcount * int.Parse(insertTime.Text)); + lvSpecial.Items[5].SubItems[1].Text = "0b" + Convert.ToString(programm.Register[PICProgramm.ADDR_PORT_A], 2).PadLeft(8, '0'); + lvSpecial.Items[6].SubItems[1].Text = "0b" + Convert.ToString(programm.Register[PICProgramm.ADDR_PORT_B], 2).PadLeft(8, '0'); + lvSpecial.Items[7].SubItems[1].Text = programm.GetRegisterOhneBank(PICProgramm.ADDR_STATUS, PICProgramm.STATUS_BIT_C) ? "1" : "0"; + lvSpecial.Items[8].SubItems[1].Text = programm.GetRegisterOhneBank(PICProgramm.ADDR_STATUS, PICProgramm.STATUS_BIT_DC) ? "1" : "0"; + lvSpecial.Items[9].SubItems[1].Text = programm.GetRegisterOhneBank(PICProgramm.ADDR_STATUS, PICProgramm.STATUS_BIT_Z) ? "1" : "0"; lbStack.Items.Clear(); foreach (var u in programm.Stack) lbStack.Items.Add(u.ToString()); @@ -322,56 +324,64 @@ namespace PIC_Simulator private void btn_RA_7_Click(object sender, EventArgs e) { if (programm == null) return; - programm.SetRegisterOhneBank(PICProgramm.ADDR_PORT_A, 7, !programm.GetRegisterOhneBank(PICProgramm.ADDR_PORT_A, 7)); + if (!programm.GetRegisterOhneBank(PICProgramm.ADDR_TRIS_A, 7)) return; + programm.Register[PICProgramm.ADDR_PORT_A] = PICProgramm.SetBit(programm.Register[PICProgramm.ADDR_PORT_A], 7, !PICProgramm.GetBit(programm.Register[PICProgramm.ADDR_PORT_A], 7)); OberflaecheAktualisieren(); } private void btn_RA_6_Click(object sender, EventArgs e) { if (programm == null) return; - programm.SetRegisterOhneBank(PICProgramm.ADDR_PORT_A, 6, !programm.GetRegisterOhneBank(PICProgramm.ADDR_PORT_A, 6)); + if (!programm.GetRegisterOhneBank(PICProgramm.ADDR_TRIS_A, 6)) return; + programm.Register[PICProgramm.ADDR_PORT_A] = PICProgramm.SetBit(programm.Register[PICProgramm.ADDR_PORT_A], 6, !PICProgramm.GetBit(programm.Register[PICProgramm.ADDR_PORT_A], 6)); OberflaecheAktualisieren(); } private void btn_RA_5_Click(object sender, EventArgs e) { if (programm == null) return; - programm.SetRegisterOhneBank(PICProgramm.ADDR_PORT_A, 5, !programm.GetRegisterOhneBank(PICProgramm.ADDR_PORT_A, 5)); + if (!programm.GetRegisterOhneBank(PICProgramm.ADDR_TRIS_A, 5)) return; + programm.Register[PICProgramm.ADDR_PORT_A] = PICProgramm.SetBit(programm.Register[PICProgramm.ADDR_PORT_A], 5, !PICProgramm.GetBit(programm.Register[PICProgramm.ADDR_PORT_A], 5)); OberflaecheAktualisieren(); } private void btn_RA_4_Click(object sender, EventArgs e) { if (programm == null) return; - programm.SetRegisterOhneBank(PICProgramm.ADDR_PORT_A, 4, !programm.GetRegisterOhneBank(PICProgramm.ADDR_PORT_A, 4)); + if (!programm.GetRegisterOhneBank(PICProgramm.ADDR_TRIS_A, 4)) return; + programm.Register[PICProgramm.ADDR_PORT_A] = PICProgramm.SetBit(programm.Register[PICProgramm.ADDR_PORT_A], 4, !PICProgramm.GetBit(programm.Register[PICProgramm.ADDR_PORT_A], 4)); OberflaecheAktualisieren(); } private void btn_RA_3_Click(object sender, EventArgs e) { if (programm == null) return; - programm.SetRegisterOhneBank(PICProgramm.ADDR_PORT_A, 3, !programm.GetRegisterOhneBank(PICProgramm.ADDR_PORT_A, 3)); + if (!programm.GetRegisterOhneBank(PICProgramm.ADDR_TRIS_A, 3)) return; + programm.Register[PICProgramm.ADDR_PORT_A] = PICProgramm.SetBit(programm.Register[PICProgramm.ADDR_PORT_A], 3, !PICProgramm.GetBit(programm.Register[PICProgramm.ADDR_PORT_A], 3)); OberflaecheAktualisieren(); } private void btn_RA_2_Click(object sender, EventArgs e) { if (programm == null) return; - programm.SetRegisterOhneBank(PICProgramm.ADDR_PORT_A, 2, !programm.GetRegisterOhneBank(PICProgramm.ADDR_PORT_A, 2)); + if (!programm.GetRegisterOhneBank(PICProgramm.ADDR_TRIS_A, 2)) return; + programm.Register[PICProgramm.ADDR_PORT_A] = PICProgramm.SetBit(programm.Register[PICProgramm.ADDR_PORT_A], 2, !PICProgramm.GetBit(programm.Register[PICProgramm.ADDR_PORT_A], 2)); OberflaecheAktualisieren(); } private void btn_RA_1_Click(object sender, EventArgs e) { if (programm == null) return; - programm.SetRegisterOhneBank(PICProgramm.ADDR_PORT_A, 1, !programm.GetRegisterOhneBank(PICProgramm.ADDR_PORT_A, 1)); + if (!programm.GetRegisterOhneBank(PICProgramm.ADDR_TRIS_A, 1)) return; + programm.Register[PICProgramm.ADDR_PORT_A] = PICProgramm.SetBit(programm.Register[PICProgramm.ADDR_PORT_A], 1, !PICProgramm.GetBit(programm.Register[PICProgramm.ADDR_PORT_A], 1)); OberflaecheAktualisieren(); } private void btn_RA_0_Click(object sender, EventArgs e) { if (programm == null) return; - programm.SetRegisterOhneBank(PICProgramm.ADDR_PORT_A, 0, !programm.GetRegisterOhneBank(PICProgramm.ADDR_PORT_A, 0)); + if (!programm.GetRegisterOhneBank(PICProgramm.ADDR_TRIS_A, 0)) return; + programm.Register[PICProgramm.ADDR_PORT_A] = PICProgramm.SetBit(programm.Register[PICProgramm.ADDR_PORT_A], 0, !PICProgramm.GetBit(programm.Register[PICProgramm.ADDR_PORT_A], 0)); OberflaecheAktualisieren(); } @@ -434,56 +444,64 @@ namespace PIC_Simulator private void btn_RB_7_Click(object sender, EventArgs e) { if (programm == null) return; - programm.SetRegisterOhneBank(PICProgramm.ADDR_PORT_B, 7, !programm.GetRegisterOhneBank(PICProgramm.ADDR_PORT_B, 7)); + if (!programm.GetRegisterOhneBank(PICProgramm.ADDR_TRIS_B, 7)) return; + programm.Register[PICProgramm.ADDR_PORT_B] = PICProgramm.SetBit(programm.Register[PICProgramm.ADDR_PORT_B], 7, !PICProgramm.GetBit(programm.Register[PICProgramm.ADDR_PORT_B], 7)); OberflaecheAktualisieren(); } private void btn_RB_6_Click(object sender, EventArgs e) { if (programm == null) return; - programm.SetRegisterOhneBank(PICProgramm.ADDR_PORT_B, 6, !programm.GetRegisterOhneBank(PICProgramm.ADDR_PORT_B, 6)); + if (!programm.GetRegisterOhneBank(PICProgramm.ADDR_TRIS_B, 6)) return; + programm.Register[PICProgramm.ADDR_PORT_B] = PICProgramm.SetBit(programm.Register[PICProgramm.ADDR_PORT_B], 6, !PICProgramm.GetBit(programm.Register[PICProgramm.ADDR_PORT_B], 6)); OberflaecheAktualisieren(); } private void btn_RB_5_Click(object sender, EventArgs e) { if (programm == null) return; - programm.SetRegisterOhneBank(PICProgramm.ADDR_PORT_B, 5, !programm.GetRegisterOhneBank(PICProgramm.ADDR_PORT_B, 5)); + if (!programm.GetRegisterOhneBank(PICProgramm.ADDR_TRIS_B, 5)) return; + programm.Register[PICProgramm.ADDR_PORT_B] = PICProgramm.SetBit(programm.Register[PICProgramm.ADDR_PORT_B], 5, !PICProgramm.GetBit(programm.Register[PICProgramm.ADDR_PORT_B], 5)); OberflaecheAktualisieren(); } private void btn_RB_4_Click(object sender, EventArgs e) { if (programm == null) return; - programm.SetRegisterOhneBank(PICProgramm.ADDR_PORT_B, 4, !programm.GetRegisterOhneBank(PICProgramm.ADDR_PORT_B, 4)); + if (!programm.GetRegisterOhneBank(PICProgramm.ADDR_TRIS_B, 4)) return; + programm.Register[PICProgramm.ADDR_PORT_B] = PICProgramm.SetBit(programm.Register[PICProgramm.ADDR_PORT_B], 4, !PICProgramm.GetBit(programm.Register[PICProgramm.ADDR_PORT_B], 4)); OberflaecheAktualisieren(); } private void btn_RB_3_Click(object sender, EventArgs e) { if (programm == null) return; - programm.SetRegisterOhneBank(PICProgramm.ADDR_PORT_B, 3, !programm.GetRegisterOhneBank(PICProgramm.ADDR_PORT_B, 3)); + if (!programm.GetRegisterOhneBank(PICProgramm.ADDR_TRIS_B, 3)) return; + programm.Register[PICProgramm.ADDR_PORT_B] = PICProgramm.SetBit(programm.Register[PICProgramm.ADDR_PORT_B], 3, !PICProgramm.GetBit(programm.Register[PICProgramm.ADDR_PORT_B], 3)); OberflaecheAktualisieren(); } private void btn_RB_2_Click(object sender, EventArgs e) { if (programm == null) return; - programm.SetRegisterOhneBank(PICProgramm.ADDR_PORT_B, 2, !programm.GetRegisterOhneBank(PICProgramm.ADDR_PORT_B, 2)); + if (!programm.GetRegisterOhneBank(PICProgramm.ADDR_TRIS_B, 2)) return; + programm.Register[PICProgramm.ADDR_PORT_B] = PICProgramm.SetBit(programm.Register[PICProgramm.ADDR_PORT_B], 2, !PICProgramm.GetBit(programm.Register[PICProgramm.ADDR_PORT_B], 2)); OberflaecheAktualisieren(); } private void btn_RB_1_Click(object sender, EventArgs e) { if (programm == null) return; - programm.SetRegisterOhneBank(PICProgramm.ADDR_PORT_B, 1, !programm.GetRegisterOhneBank(PICProgramm.ADDR_PORT_B, 1)); + if (!programm.GetRegisterOhneBank(PICProgramm.ADDR_TRIS_B, 1)) return; + programm.Register[PICProgramm.ADDR_PORT_B] = PICProgramm.SetBit(programm.Register[PICProgramm.ADDR_PORT_B], 1, !PICProgramm.GetBit(programm.Register[PICProgramm.ADDR_PORT_B], 1)); OberflaecheAktualisieren(); } private void btn_RB_0_Click(object sender, EventArgs e) { if (programm == null) return; - programm.SetRegisterOhneBank(PICProgramm.ADDR_PORT_B, 0, !programm.GetRegisterOhneBank(PICProgramm.ADDR_PORT_B, 0)); + if (!programm.GetRegisterOhneBank(PICProgramm.ADDR_TRIS_B, 0)) return; + programm.Register[PICProgramm.ADDR_PORT_B] = PICProgramm.SetBit(programm.Register[PICProgramm.ADDR_PORT_B], 0, !PICProgramm.GetBit(programm.Register[PICProgramm.ADDR_PORT_B], 0)); OberflaecheAktualisieren(); } diff --git a/PIC_Simulator/PIC/PICProgramm.cs b/PIC_Simulator/PIC/PICProgramm.cs index 9559a77..33d9ea4 100644 --- a/PIC_Simulator/PIC/PICProgramm.cs +++ b/PIC_Simulator/PIC/PICProgramm.cs @@ -239,6 +239,8 @@ namespace PIC_Simulator.PIC if (IsSleeping) return false; + uint cycleCount = 1; + if (aktueller_befehl.befehl == ADDWF) { // Add the contents of the W register with @@ -673,6 +675,7 @@ namespace PIC_Simulator.PIC // GOTO is a two cycle instruction. PCCounter = befehle.FindIndex(b => b.labelnummer == aktueller_befehl.parameter_k) - 1; + cycleCount = 2; } else if (aktueller_befehl.befehl == IORLW) { @@ -714,6 +717,7 @@ namespace PIC_Simulator.PIC // instruction. Register_W = (byte)aktueller_befehl.parameter_k; PCCounter = (int) Stack.Pop(); + cycleCount = 2; } else if (aktueller_befehl.befehl == RETURN) { @@ -722,6 +726,7 @@ namespace PIC_Simulator.PIC // is loaded into the program counter.This // is a two cycle instruction. PCCounter = (int)Stack.Pop(); + cycleCount = 2; } else if (aktueller_befehl.befehl == SLEEP) { @@ -790,9 +795,103 @@ namespace PIC_Simulator.PIC PCCounter++; Stepcount++; + TimerBerechnen(cycleCount); + return PCCounter >= befehle.Count; } + private bool prev_RA4 = false; + private void TimerBerechnen(uint cycles) + { + bool tmr_mode = GetRegisterOhneBank(ADDR_OPTION, OPTION_BIT_T0CS); + bool edge_mode = GetRegisterOhneBank(ADDR_OPTION, OPTION_BIT_T0SE); + + if (!tmr_mode) + { + bool curr_A4 = GetRegisterOhneBank(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 = GetRegisterOhneBank(ADDR_PORT_A, 4); + } + + private uint prescale_cntr = 0; // Zähler für timer + + private void TimerHochzaehlen(uint cycles) + { + uint current = GetRegisterOhneBank(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; + SetRegisterOhneBank(ADDR_TMR0, Result); + prescale_cntr = tmp_psc; + } + } + + private uint BerechneVorskalierung() + { + bool prescale_mode = GetRegisterOhneBank(ADDR_OPTION, OPTION_BIT_PSA); + + uint scale = 0; + scale += GetRegisterOhneBank(ADDR_OPTION, OPTION_BIT_PS2) ? 1U : 0U; + scale *= 2; + scale += GetRegisterOhneBank(ADDR_OPTION, OPTION_BIT_PS1) ? 1U : 0U; + scale *= 2; + scale += GetRegisterOhneBank(ADDR_OPTION, OPTION_BIT_PS0) ? 1U : 0U; + + return prescale_mode ? 1 : (SHL(2, scale)); + } + + private uint UIntPower(uint x, uint power) + { + if (power == 0) + return 1; + if (power == 1) + return x; + // ---------------------- + int n = 15; + while ((power <<= 1) >= 0) + n--; + + uint tmp = x; + while (--n > 0) + tmp = tmp * tmp * + (((power <<= 1) < 0) ? x : 1); + return tmp; + } + public void SetRegisterOhneBank(uint index, uint wert) { // register die nur einmal auf bank1 + 2 existieren @@ -866,9 +965,6 @@ namespace PIC_Simulator.PIC return Register[Register[ADDR_FSR]]; } - if (index == ADDR_PORT_A) return Latch_RA; - if (index == ADDR_PORT_A) return Latch_RB; - return Register[index]; } @@ -901,7 +997,6 @@ namespace PIC_Simulator.PIC SetRegisterOhneBank(index, SetBit(GetRegisterOhneBank(index), bit, wert)); } - private void SetRegister(uint index, uint bit, bool wert) { SetRegister(index, SetBit(GetRegister(index), bit, wert)); @@ -928,7 +1023,7 @@ namespace PIC_Simulator.PIC return (xa + xb) > 0x0F; } - public static bool GetBit(uint val, uint pos) + public static bool GetBit(byte val, uint pos) { return (val & SHL(1, pos)) != 0; } @@ -943,9 +1038,9 @@ namespace PIC_Simulator.PIC return (uint)((val) >> ((int)steps)); } - public static uint SetBit(uint val, uint pos, bool bit) + public static byte SetBit(byte val, uint pos, bool bit) { - return bit ? (val | SHL(1, pos)) : (val & ~SHL(1, pos)); + return (byte)(bit ? (val | SHL(1, pos)) : (val & ~SHL(1, pos))); } } diff --git a/PIC_Simulator/PIC/RS232Verbindung.cs b/PIC_Simulator/PIC/RS232Verbindung.cs index 73674c1..02fc258 100644 --- a/PIC_Simulator/PIC/RS232Verbindung.cs +++ b/PIC_Simulator/PIC/RS232Verbindung.cs @@ -135,8 +135,16 @@ namespace PIC_Simulator.PIC } else { - Programm.SetRegisterOhneBank(PICProgramm.ADDR_PORT_A, v.Item1); - Programm.SetRegisterOhneBank(PICProgramm.ADDR_PORT_B, v.Item2); + for (uint i = 0; i < 8; i++) + { + // Nur 'i' bits übernehmen + + if (Programm.GetRegisterOhneBank(PICProgramm.ADDR_TRIS_A, i)) + Programm.Register[PICProgramm.ADDR_PORT_A] = PICProgramm.SetBit(Programm.Register[PICProgramm.ADDR_PORT_A], i, !PICProgramm.GetBit((byte)v.Item1, i)); + if (Programm.GetRegisterOhneBank(PICProgramm.ADDR_TRIS_B, i)) + Programm.Register[PICProgramm.ADDR_PORT_B] = PICProgramm.SetBit(Programm.Register[PICProgramm.ADDR_PORT_B], i, !PICProgramm.GetBit((byte)v.Item1, i)); + } + Fenster.OberflaecheAktualisieren(); } }