private void OnTimerEvent(object sender, MicroTimerEventArgs e) { if (++_internalCounter < GetDivider()) { return; } _internalCounter = 0; bool equalUpperLimit = _tcntL.NumValue() == upperLimit[0].NumValue() && _tcntH.NumValue() == upperLimit[1].NumValue(); bool equalLowerLimit = _tcntL.NumValue() == 0 && _tcntH.NumValue() == 0; // Инкремент/декремент if (dec) { if (_tcntL.Dec()) { if (_tcntH.Dec()) { // 0000 -> FFFF underflow Console.WriteLine("Shouldn't normally happen! 0000.Dec()"); } } } else { if (equalUpperLimit) { _tcntL.And(new ExtendedBitArray()); _tcntH.And(new ExtendedBitArray()); SetOverflowFlag(true); } else if (_tcntL.Inc()) { if (_tcntH.Inc()) { // FFFF -> 0000 overflow Console.WriteLine("Shouldn't normally happen! FFFF.Inc()"); SetOverflowFlag(true); } } } equalUpperLimit = _tcntL.NumValue() == upperLimit[0].NumValue() && _tcntH.NumValue() == upperLimit[1].NumValue(); equalLowerLimit = _tcntL.NumValue() == 0 && _tcntH.NumValue() == 0; bool equalTcntOcr = _tcntL.NumValue() == _ocrL.NumValue() && _tcntH.NumValue() == _ocrH.NumValue(); byte mode = GetMode(); switch (mode) { case 1: // сброс при совпадении if (equalTcntOcr) { SetComparisonFlag(true); _tcntH = new ExtendedBitArray(); _tcntL = new ExtendedBitArray(); } break; case 2: // быстрый ШИМ break; case 3: // ШИМ с фазовой коррекцией // проверка совпадения с верхним пределом if (equalUpperLimit) { dec = true; } else if (equalLowerLimit) { dec = false; } break; } byte outputMode = GetOutputMode(); switch (outputMode) { case 0: outputPinValue = false; break; case 1: // инверсия при совпадении TCNT == OCR if (equalTcntOcr) { outputPinValue = !outputPinValue; } break; case 2: if (mode < 2) // Без ШИМ { if (equalTcntOcr) // сброс при совпадении { outputPinValue = false; } } if (mode == 2) // Быстрый ШИМ { if (equalTcntOcr) // сброс при совпадении { outputPinValue = false; } else if (equalUpperLimit) // установка на вершине счета { outputPinValue = true; } } if (mode == 3) // ШИМ с ФК { if (equalTcntOcr) { if (dec) { outputPinValue = true; // установка при совпадении во время обратного счета } else { outputPinValue = false; // сброс при совпадении во время прямого счета } } } break; case 3: if (mode < 2) // Без ШИМ { if (equalTcntOcr) // установка при совпадении { outputPinValue = true; } } if (mode == 2) // Быстрый ШИМ { if (equalTcntOcr) // установка при совпадении { outputPinValue = true; } else if (equalUpperLimit) // сброс на вершине счета { outputPinValue = false; } } if (mode == 3) // ШИМ с ФК { if (equalTcntOcr) { if (dec) { outputPinValue = false; // сброс при совпадении во время обратного счета } else { outputPinValue = true; // установка при совпадении во время прямого счета } } } break; } double nowMillis = DateTime.Now.ToUniversalTime().Subtract( new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc) ).TotalMilliseconds; if (nowMillis - _lastUpdateMillis > UPDATE_PERIOD_MILLIS) { _form.Invoke(_updateFormDelegate); _lastUpdateMillis = nowMillis; } }
/// Определяет к какой группе относится команда и запускает специфичный обработчик private void RunCommand() { var highBin = _cr[1].ToBinString(); var highHex = _cr[1].ToHexString(); var lowBin = _cr[0].ToBinString(); var lowHex = _cr[0].ToHexString(); //Регистровые if (highHex[0] == '5' || highHex == "F0" || highHex == "F1") { ProcessRegisterCommand(highHex, lowBin); } //ОЗУ if (highBin.StartsWith("011")) { ProcessRamCommand(highBin, highHex); } //Переходы if (highBin.StartsWith("0100") || highBin.StartsWith("001")) { ProcessJumpCommand(highBin); } //DJRNZ if (highBin.StartsWith("0001")) { _y63(); _y2(); var overflow = _rdb.Dec(); if (_rdb.NumValue() != 0) { Jump(); } _y5(); } //безадресные команды if (highBin.StartsWith("0000")) { ProcessNonAddressCommands(lowHex); } //Битовые команды if (highBin.StartsWith("1000") || highBin.StartsWith("1001")) { ProcessBitCommands(highBin, highHex, lowBin, lowHex); } //Битовые команды с регистрами ввода/вывода if (highBin.StartsWith("1010") || highBin.StartsWith("1011")) { ProcessIOBitCommands(highBin, highHex, lowBin, lowHex); } //Команды ввода/вывода if (highBin.StartsWith("1100")) { ProcessIOCommand(highBin, highHex, lowBin, lowHex); } if (_cr[0].NumValue() == 0 && _cr[1].NumValue() == 0) { _shouldStopRunning = true; } }
private void ProcessRegisterCommand(string highHex, string lowBin) { //MOV if (highHex[1] == 'F') { _y46(); _y2(); _y47(); _y5(); return; } //POP if (highHex[1] == 'D') { _y45(); _y1(); _y34(); _y47(); _y5(); return; } //WR if (highHex[1] == 'A') { if (lowBin[1] != '0' || lowBin[2] != '0' || lowBin[3] != '0') { LoadRegister(lowBin); _y49(); _y4(); ModifyRegister(lowBin); } else { // Прямая адресация _y49(); _y47(); _y5(); } return; } LoadRegister(lowBin); //NOT if (highHex[1] == '0') { _flags.SetPreviousState(_rdb); _y52(); _flags.UpdateFlags(_rdb, "not"); UnloadRegister(lowBin); ModifyRegister(lowBin); return; } //ADD if (highHex[1] == '1') { _flags.SetPreviousState(_acc); _flags.SetArgument(_rdb); bool overflow = _acc.Add(_rdb); _flags.UpdateFlags(_acc, "add", overflow, _rdb); ModifyRegister(lowBin); return; } //SUB if (highHex[1] == '2') { _flags.SetPreviousState(_acc); _flags.SetArgument(_rdb); bool overflow = _acc.Sub(_rdb); _flags.UpdateFlags(_acc, "sub", overflow, _rdb); ModifyRegister(lowBin); return; } //MUL if (highHex[1] == '3') { _flags.SetPreviousState(_acc); _flags.SetArgument(_rdb); _perform_mul(); bool overflow = false; _flags.UpdateFlags(_acc, "mul", overflow); ModifyRegister(lowBin); return; } //DIV if (highHex[1] == '4') { _flags.SetPreviousState(_acc); _flags.SetArgument(_rdb); _acc.Div(_rdb); _flags.UpdateFlags(_acc, "div"); ModifyRegister(lowBin); return; } //AND if (highHex[1] == '5') { _flags.SetPreviousState(_acc); _acc.And(_rdb); _flags.UpdateFlags(_acc, "and"); ModifyRegister(lowBin); return; } //OR if (highHex[1] == '6') { _flags.SetPreviousState(_acc); _acc.Or(_rdb); _flags.UpdateFlags(_acc, "or"); ModifyRegister(lowBin); return; } //XOR if (highHex[1] == '7') { _flags.SetPreviousState(_acc); _acc.Xor(_rdb); _flags.UpdateFlags(_acc, "xor"); ModifyRegister(lowBin); return; } //CMP if (highHex[1] == '8') { var temp = new ExtendedBitArray(_rdb); _flags.SetPreviousState(temp); _flags.SetArgument(_rdb); bool overflow = temp.Sub(_acc); _flags.UpdateFlags(temp, "cmp", overflow, _rdb); UnloadRegister(lowBin); ModifyRegister(lowBin); return; } //RD if (highHex[1] == '9') { _acc = new ExtendedBitArray(_rdb); ModifyRegister(lowBin); return; } //INC if (highHex[1] == 'B') { _flags.SetPreviousState(_rdb); var overflow = _rdb.Inc(); _flags.UpdateFlags(_rdb, "inc", overflow); UnloadRegister(lowBin); ModifyRegister(lowBin); return; } //DEC if (highHex[1] == 'C') { _flags.SetPreviousState(_rdb); var overflow = _rdb.Dec(); _flags.UpdateFlags(_rdb, "dec", overflow); UnloadRegister(lowBin); ModifyRegister(lowBin); return; } //PUSH if (highHex[1] == 'E') { _y35(); _y45(); _y4(); ModifyRegister(lowBin); return; } //ADC if (highHex == "F0") { _flags.SetPreviousState(_acc); _flags.SetArgument(_rdb); var overflow = _acc.Add(_rdb); if (_flags.C) { overflow |= _acc.Inc(); } _flags.UpdateFlags(_acc, "adc", overflow, _rdb); ModifyRegister(lowBin); return; } //SUBB if (highHex == "F1") { _flags.SetPreviousState(_acc); _flags.SetArgument(_rdb); var overflow = _acc.Sub(_rdb); if (_flags.C) { overflow |= _acc.Dec(); } _flags.UpdateFlags(_acc, "subb", overflow, _rdb); ModifyRegister(lowBin); } }
public void DecOverflowExceptionTest() { var extendedBitArray = new ExtendedBitArray("00000000"); Assert.IsTrue(extendedBitArray.Dec()); }