// Schrittweise Ausführung des Programms public bool Step(int frequenz) { if (PCCounter >= befehle.Count) { return(true); } PICBefehl aktueller_befehl = befehle[PCCounter]; if (TaktgeberAktiviert) { TaktgeberZahler += frequenz; if (TaktgeberZahler >= TaktgeberFrequenz) { if (TaktgeberAdresse == ADDR_PORT_A) { var wert = SetBit(GetRegisterOhneBank(TaktgeberAdresse), TaktgeberBitnummer, !GetRegisterOhneBank(TaktgeberAdresse, TaktgeberBitnummer)); var ta = Register[ADDR_TRIS_A]; if (GetBit(ta, TaktgeberBitnummer)) { Latch_RA = (byte)(wert & 0xFF); Register[ADDR_PORT_A] = wert; } } else if (TaktgeberAdresse == ADDR_PORT_B) { var wert = SetBit(GetRegisterOhneBank(TaktgeberAdresse), TaktgeberBitnummer, !GetRegisterOhneBank(TaktgeberAdresse, TaktgeberBitnummer)); var tb = Register[ADDR_TRIS_B]; if (GetBit(tb, TaktgeberBitnummer)) { Latch_RB = (byte)(wert & 0xFF); Register[ADDR_PORT_B] = wert; } } else { SetRegisterOhneBank(TaktgeberAdresse, TaktgeberBitnummer, !GetRegisterOhneBank(TaktgeberAdresse, TaktgeberBitnummer)); } TaktgeberZahler = 0; } } if (IsSleeping) { WatchDog.Aktualisieren(1); return(false); } uint cycleCount = 1; if (aktueller_befehl.befehl == ADDWF) { // Add the contents of the W register with // register 'f'.If 'd' is 0 the result is stored // in the W register.If 'd' is 1 the result is // stored back in register 'f'. byte a = GetRegister(aktueller_befehl.parameter_f); byte b = Register_W; uint Result = (uint)(a + b); bool dc = AdditionDigitCarry(a, b); SetRegisterOhneBank(ADDR_STATUS, STATUS_BIT_Z, (Result % 0x100) == 0); SetRegisterOhneBank(ADDR_STATUS, STATUS_BIT_DC, dc); SetRegisterOhneBank(ADDR_STATUS, STATUS_BIT_C, Result > 0xFF); Result %= 0x100; if (aktueller_befehl.parameter_d != 0) { SetRegister(aktueller_befehl.parameter_f, (byte)Result); } else { Register_W = (byte)Result; } } else if (aktueller_befehl.befehl == ANDWF) { // AND the W register with register 'f'.If 'd' // is 0 the result is stored in the W regis - // ter.If 'd' is 1 the result is stored back in // register 'f' byte Result = (byte)(Register_W & GetRegister(aktueller_befehl.parameter_f)); SetRegisterOhneBank(ADDR_STATUS, STATUS_BIT_Z, Result == 0); if (aktueller_befehl.parameter_d != 0) { SetRegister(aktueller_befehl.parameter_f, Result); } else { Register_W = Result; } } else if (aktueller_befehl.befehl == CLRF) { // The contents of register 'f' are cleared // and the Z bit is set. SetRegister(aktueller_befehl.parameter_f, 0x00); SetRegisterOhneBank(ADDR_STATUS, STATUS_BIT_Z, true); } else if (aktueller_befehl.befehl == CLRW) { // W register is cleared.Zero bit (Z) is // set. Register_W = 0; SetRegisterOhneBank(ADDR_STATUS, STATUS_BIT_Z, true); } else if (aktueller_befehl.befehl == COMF) { // The contents of register 'f' are comple- // mented.If 'd' is 0 the result is stored in // W.If 'd' is 1 the result is stored back in // register 'f'. byte Result = (byte)~GetRegister(aktueller_befehl.parameter_f); SetRegisterOhneBank(ADDR_STATUS, STATUS_BIT_Z, Result == 0); if (aktueller_befehl.parameter_d != 0) { SetRegister(aktueller_befehl.parameter_f, Result); } else { Register_W = Result; } } else if (aktueller_befehl.befehl == DECF) { // Decrement register 'f'.If 'd' is 0 the // result is stored in the W register.If 'd' is // 1 the result is stored back in register 'f'. uint Result = GetRegister(aktueller_befehl.parameter_f); if (Result == 0) { Result = 0xFF; } else { Result -= 1; } SetRegisterOhneBank(ADDR_STATUS, STATUS_BIT_Z, Result == 0); if (aktueller_befehl.parameter_d != 0) { SetRegister(aktueller_befehl.parameter_f, Result); } else { Register_W = (byte)Result; } } else if (aktueller_befehl.befehl == DECFSZ) { // The contents of register 'f' are decre- // mented.If 'd' is 0 the result is placed in the // W register.If 'd' is 1 the result is placed // back in register 'f'. // If the result is 1, the next instruction, is // executed.If the result is 0, then a NOP is // executed instead making it a 2T CY instruc - // tion. bool Cond = GetRegister(aktueller_befehl.parameter_f) == 1; uint Result = GetRegister(aktueller_befehl.parameter_f); if (Result == 0) { Result = 0xFF; } else { Result -= 1; } if (aktueller_befehl.parameter_d != 0) { SetRegister(aktueller_befehl.parameter_f, Result); } else { Register_W = (byte)Result; } if (Cond) { PCCounter++; // skip next cycleCount = 2; } } else if (aktueller_befehl.befehl == INCF) { // The contents of register 'f' are incre- // mented.If 'd' is 0 the result is placed in // the W register.If 'd' is 1 the result is // placed back in register 'f'. uint Result = GetRegister(aktueller_befehl.parameter_f); Result += 1; Result %= 0x100; SetRegisterOhneBank(ADDR_STATUS, STATUS_BIT_Z, Result == 0); if (aktueller_befehl.parameter_d != 0) { SetRegister(aktueller_befehl.parameter_f, Result); } else { Register_W = (byte)Result; } } else if (aktueller_befehl.befehl == INCFSZ) { // The contents of register 'f' are incre- // mented.If 'd' is 0 the result is placed in // the W register.If 'd' is 1 the result is // placed back in register 'f'. // If the result is 1, the next instruction is // executed.If the result is 0, a NOP is exe - // cuted instead making it a 2T CY instruc - // tion bool Cond = GetRegister(aktueller_befehl.parameter_f) == 0xFF; uint Result = GetRegister(aktueller_befehl.parameter_f); Result += 1; Result %= 0x100; if (aktueller_befehl.parameter_d != 0) { SetRegister(aktueller_befehl.parameter_f, Result); } else { Register_W = (byte)Result; } if (Cond) { PCCounter++; // skip next cycleCount = 2; } } else if (aktueller_befehl.befehl == IORWF) { // Inclusive OR the W register with regis - // ter 'f'.If 'd' is 0 the result is placed in the // W register.If 'd' is 1 the result is placed // back in register 'f'. byte Result = (byte)(Register_W | GetRegister(aktueller_befehl.parameter_f)); SetRegisterOhneBank(ADDR_STATUS, STATUS_BIT_Z, Result == 0); if (aktueller_befehl.parameter_d != 0) { SetRegister(aktueller_befehl.parameter_f, Result); } else { Register_W = Result; } } else if (aktueller_befehl.befehl == MOVF) { // The contents of register f is moved to a // destination dependant upon the status // of d. If d = 0, destination is W register. If // d = 1, the destination is file register f // itself.d = 1 is useful to test a file regis- // ter since status flag Z is affected. uint Result = GetRegister(aktueller_befehl.parameter_f); SetRegisterOhneBank(ADDR_STATUS, STATUS_BIT_Z, Result == 0); if (aktueller_befehl.parameter_d != 0) { SetRegister(aktueller_befehl.parameter_f, Result); } else { Register_W = (byte)Result; } } else if (aktueller_befehl.befehl == MOVWF) { // Move data from W register to register // 'f' SetRegister(aktueller_befehl.parameter_f, Register_W); } else if (aktueller_befehl.befehl == NOP) { //No operation. } else if (aktueller_befehl.befehl == RLF) { // The contents of register 'f' are rotated // one bit to the left through the Carry // Flag.If 'd' is 0 the result is placed in the // W register.If 'd' is 1 the result is stored // back in register 'f'. uint Result = GetRegister(aktueller_befehl.parameter_f); uint Carry_Old = GetRegisterOhneBank(ADDR_STATUS, STATUS_BIT_C) ? 1u : 0u; uint Carry_New = (Result & 0x80) >> 7; Result = Result << 1; Result &= 0xFF; Result |= Carry_Old; SetRegisterOhneBank(ADDR_STATUS, STATUS_BIT_C, Carry_New != 0); if (aktueller_befehl.parameter_d != 0) { SetRegister(aktueller_befehl.parameter_f, Result); } else { Register_W = (byte)Result; } } else if (aktueller_befehl.befehl == RRF) { // The contents of register 'f' are rotated // one bit to the right through the Carry // Flag.If 'd' is 0 the result is placed in the // W register.If 'd' is 1 the result is placed // back in register 'f'. uint Result = GetRegister(aktueller_befehl.parameter_f); uint Carry_Old = GetRegisterOhneBank(ADDR_STATUS, STATUS_BIT_C) ? 0x80u : 0x00u; uint Carry_New = Result & 0x01; Result = Result >> 1; Result &= 0xFF; Result |= Carry_Old; SetRegisterOhneBank(ADDR_STATUS, STATUS_BIT_C, Carry_New != 0); if (aktueller_befehl.parameter_d != 0) { SetRegister(aktueller_befehl.parameter_f, Result); } else { Register_W = (byte)Result; } } else if (aktueller_befehl.befehl == SUBWF) { // Subtract(2’s complement method) W reg- // ister from register 'f'.If 'd' is 0 the result is // stored in the W register.If 'd' is 1 the // result is stored back in register 'f'. uint a = GetRegister(aktueller_befehl.parameter_f); uint b = Register_W; bool carry = (a + ((~b) & 0xFF)) > 0xFF; bool dc = SubtractionDigitCarry((byte)a, (byte)b); if (a < b) { a += 0x100; } uint Result = a - b; SetRegisterOhneBank(ADDR_STATUS, STATUS_BIT_Z, (Result % 0x100) == 0); SetRegisterOhneBank(ADDR_STATUS, STATUS_BIT_DC, dc); SetRegisterOhneBank(ADDR_STATUS, STATUS_BIT_C, carry); Result %= 0x100; if (aktueller_befehl.parameter_d != 0) { SetRegister(aktueller_befehl.parameter_f, Result); } else { Register_W = (byte)Result; } } else if (aktueller_befehl.befehl == SWAPF) { // The upper and lower nibbles of register // 'f' are exchanged. If 'd' is 0 the result is // placed in W register. If 'd' is 1 the result // is placed in register 'f'. uint Result = GetRegister(aktueller_befehl.parameter_f); uint Low = Result & 0x0F; uint High = Result & 0xF0; Result = (Low << 4) | (High >> 4); if (aktueller_befehl.parameter_d != 0) { SetRegister(aktueller_befehl.parameter_f, Result); } else { Register_W = (byte)Result; } } else if (aktueller_befehl.befehl == XORWF) { // Exclusive OR the contents of the W // register with register 'f'.If 'd' is 0 the // result is stored in the W register.If 'd' is // 1 the result is stored back in register 'f'. byte Result = (byte)(Register_W ^ GetRegister(aktueller_befehl.parameter_f)); SetRegisterOhneBank(ADDR_STATUS, STATUS_BIT_Z, Result == 0); if (aktueller_befehl.parameter_d != 0) { SetRegister(aktueller_befehl.parameter_f, Result); } else { Register_W = Result; } } else if (aktueller_befehl.befehl == BCF) { // Bit 'b' in register 'f' is cleared SetRegister(aktueller_befehl.parameter_f, aktueller_befehl.parameter_b, false); } else if (aktueller_befehl.befehl == BSF) { // Bit 'b' in register 'f' is set. SetRegister(aktueller_befehl.parameter_f, aktueller_befehl.parameter_b, true); } else if (aktueller_befehl.befehl == BTFSC) { // If bit 'b' in register 'f' is '1' then the next // instruction is executed. // If bit 'b', in register 'f', is '0' then the next // instruction is discarded, and a NOP is // executed instead, making this a 2T CY // instruction if (!GetBit(GetRegister(aktueller_befehl.parameter_f), aktueller_befehl.parameter_b)) { PCCounter++; cycleCount = 2; } } else if (aktueller_befehl.befehl == BTFSS) { // If bit 'b' in register 'f' is '0' then the next // instruction is executed. // If bit 'b' is '1', then the next instruction is // discarded and a NOP is executed // instead, making this a 2T CY instruction. if (GetBit(GetRegister(aktueller_befehl.parameter_f), aktueller_befehl.parameter_b)) { PCCounter++; cycleCount = 2; } } else if (aktueller_befehl.befehl == ADDLW) { // The contents of the W register are // added to the eight bit literal 'k' and the // result is placed in the W register uint a = Register_W; uint b = aktueller_befehl.parameter_k; uint Result = a + b; bool dc = AdditionDigitCarry((byte)a, (byte)b); SetRegisterOhneBank(ADDR_STATUS, STATUS_BIT_Z, (Result % 0x100) == 0); SetRegisterOhneBank(ADDR_STATUS, STATUS_BIT_DC, dc); SetRegisterOhneBank(ADDR_STATUS, STATUS_BIT_C, Result > 0xFF); Result %= 0x100; Register_W = (byte)Result; } else if (aktueller_befehl.befehl == ANDLW) { // The contents of W register are // AND’ed with the eight bit literal 'k'.The // result is placed in the W register uint Result = Register_W & aktueller_befehl.parameter_k; SetRegisterOhneBank(ADDR_STATUS, STATUS_BIT_Z, Result == 0); Register_W = (byte)Result; } else if (aktueller_befehl.befehl == CALL) { // Call Subroutine. First, return address // (PC + 1) is pushed onto the stack. The // eleven bit immediate address is loaded // into PC bits<10:0 >.The upper bits of // the PC are loaded from PCLATH.CALL // is a two cycle instruction. Stack.Push((uint)PCCounter); PCCounter = (int)(aktueller_befehl.parameter_k - 1); cycleCount = 2; } else if (aktueller_befehl.befehl == CLRWDT) { // CLRWDT instruction resets the Watch - // dog Timer.It also resets the prescaler // of the WDT. Status bits TO and PD are // set. WatchDog.Reset(); if (GetRegisterOhneBank(ADDR_OPTION, OPTION_BIT_PSA)) { SetRegisterOhneBank(ADDR_OPTION, OPTION_BIT_PS0, false); SetRegisterOhneBank(ADDR_OPTION, OPTION_BIT_PS1, false); SetRegisterOhneBank(ADDR_OPTION, OPTION_BIT_PS2, false); } SetRegisterOhneBank(ADDR_STATUS, STATUS_BIT_TO, true); SetRegisterOhneBank(ADDR_STATUS, STATUS_BIT_PD, true); } else if (aktueller_befehl.befehl == GOTO) { // GOTO is an unconditional branch.The // eleven bit immediate value is loaded // into PC bits<10:0>.The upper bits of // PC are loaded from PCLATH<4:3>. // 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) { // The contents of the W register is // OR’ed with the eight bit literal 'k'.The // result is placed in the W register uint Result = Register_W | aktueller_befehl.parameter_k; SetRegisterOhneBank(ADDR_STATUS, STATUS_BIT_Z, Result == 0); Register_W = (byte)Result; } else if (aktueller_befehl.befehl == MOVLW) { // The eight bit literal 'k' is loaded into W // register.The don’t cares will assemble // as 0’s. Register_W = (byte)aktueller_befehl.parameter_k; } else if (aktueller_befehl.befehl == RETFIE) { // Return from Interrupt.Stack is POPed // and Top of Stack(TOS) is loaded in the // PC.Interrupts are enabled by setting // Global Interrupt Enable bit, GIE // (INTCON < 7 >).This is a two cycle // instruction. PCCounter = (int)Stack.Pop(); SetRegisterOhneBank(ADDR_INTCON, INTCON_BIT_GIE, true); cycleCount = 2; } else if (aktueller_befehl.befehl == RETLW) { // The W register is loaded with the eight // bit literal 'k'.The program counter is // loaded from the top of the stack(the // return address). This is a two cycle // instruction. Register_W = (byte)aktueller_befehl.parameter_k; PCCounter = (int)Stack.Pop(); cycleCount = 2; } else if (aktueller_befehl.befehl == RETURN) { // Return from subroutine. The stack is // POPed and the top of the stack(TOS) // is loaded into the program counter.This // is a two cycle instruction. PCCounter = (int)Stack.Pop(); cycleCount = 2; } else if (aktueller_befehl.befehl == SLEEP) { // The power-down status bit, PD is // cleared.Time -out status bit, TO is // set.Watchdog Timer and its prescaler // are cleared. // The processor is put into SLEEP // mode with the oscillator stopped. See // Section 14.8 for more details. if (GetRegisterOhneBank(ADDR_OPTION, OPTION_BIT_PSA)) { SetRegisterOhneBank(ADDR_OPTION, OPTION_BIT_PS0, false); SetRegisterOhneBank(ADDR_OPTION, OPTION_BIT_PS1, false); SetRegisterOhneBank(ADDR_OPTION, OPTION_BIT_PS2, false); } SetRegisterOhneBank(ADDR_STATUS, STATUS_BIT_TO, true); SetRegisterOhneBank(ADDR_STATUS, STATUS_BIT_PD, false); IsSleeping = true; } else if (aktueller_befehl.befehl == SUBLW) { // The W register is subtracted (2’s comple- // ment method) from the eight bit literal 'k'. // The result is placed in the W register. uint a = aktueller_befehl.parameter_k; uint b = Register_W; bool carry; bool dc = SubtractionDigitCarry((byte)a, (byte)b); if (carry = a < b) { a += 0x100; } uint Result = a - b; SetRegisterOhneBank(ADDR_STATUS, STATUS_BIT_Z, (Result % 0x100) == 0); SetRegisterOhneBank(ADDR_STATUS, STATUS_BIT_DC, dc); SetRegisterOhneBank(ADDR_STATUS, STATUS_BIT_C, !carry); Result %= 0x100; Register_W = (byte)Result; } else if (aktueller_befehl.befehl == XORLW) { // The contents of the W register are // XOR’ed with the eight bit literal 'k'. // The result is placed in the W regis - // ter. uint Result = Register_W ^ aktueller_befehl.parameter_k; SetRegisterOhneBank(ADDR_STATUS, STATUS_BIT_Z, Result == 0); Register_W = (byte)Result;; } PCCounter++; Stepcount++; Zaehler.TimerBerechnen(cycleCount); WatchDog.Aktualisieren(cycleCount); if (Merker_RB0 != Register[ADDR_PORT_B]) { Interrupt_RB(Merker_RB0, Register[ADDR_PORT_B]); Merker_RB0 = Register[ADDR_PORT_B]; } return(PCCounter >= befehle.Count); }
// Befehlserkunng anhand bitweisem Vergleich private PICBefehl FindeBefehl(string zeile, int zeilennummer) { foreach (var cmd in ALL_COMMANDS) { string bin = hex2binary(zeile.Substring(5, 4)); uint p_d = 0; uint p_f = 0; uint p_x = 0; uint p_k = 0; uint p_b = 0; bool ok = true; for (int i = 0; i < 14; i++) //Jeder befehl wird durchgegangen und über AND wird geschaut ob der Befehl und der Code identisch sind { if (cmd[i] == '0' && bin[i] == '0') { continue; } if (cmd[i] == '1' && bin[i] == '1') { continue; } if (cmd[i] == 'd' && bin[i] == '0') { p_d <<= 1; p_d |= 0; continue; } if (cmd[i] == 'd' && bin[i] == '1') { p_d <<= 1; p_d |= 1; continue; } if (cmd[i] == 'f' && bin[i] == '0') { p_f <<= 1; p_f |= 0; continue; } if (cmd[i] == 'f' && bin[i] == '1') { p_f <<= 1; p_f |= 1; continue; } if (cmd[i] == 'x' && bin[i] == '0') { p_x <<= 1; p_x |= 0; continue; } if (cmd[i] == 'x' && bin[i] == '1') { p_x <<= 1; p_x |= 1; continue; } if (cmd[i] == 'k' && bin[i] == '0') { p_k <<= 1; p_k |= 0; continue; } if (cmd[i] == 'k' && bin[i] == '1') { p_k <<= 1; p_k |= 1; continue; } if (cmd[i] == 'b' && bin[i] == '0') { p_b <<= 1; p_b |= 0; continue; } if (cmd[i] == 'b' && bin[i] == '1') { p_b <<= 1; p_b |= 1; continue; } if (cmd[i] == '0' && bin[i] == '1') { ok = false; break; } if (cmd[i] == '1' && bin[i] == '0') { ok = false; break; } throw new Exception("Falscher wert in cmd"); } if (ok) { PICBefehl b = new PICBefehl(); b.befehl = cmd; b.parameter_d = p_d; b.parameter_f = p_f; b.parameter_k = p_k; b.parameter_x = p_x; b.parameter_b = p_b; b.zeilennummer = zeilennummer; b.labelnummer = Convert.ToInt32(zeile.Substring(0, 4), 16); return(b); } } throw new Exception("konnte befehl nicht finden: " + zeile); }