Exemplo n.º 1
0
        public void ExecutePhase()
        {
            var shiftIn = false;

            // TODO: use this or delete
            ////var shiftOut = false;

            // Process delayed interrupts
            _ifr |= _interruptNextClock;
            _interruptNextClock = 0;

            // Process 'pulse' and 'handshake' outputs on PB7, CA2 and CB2
            if (_resetCa2NextClock)
            {
                Ca2 = true;
                _resetCa2NextClock = false;
            }
            else if (_handshakeCa2NextClock)
            {
                Ca2 = false;
                _resetCa2NextClock     = _pcrCa2Control == PCR_CONTROL_PULSE_OUTPUT;
                _handshakeCa2NextClock = false;
            }

            if (_resetCb2NextClock)
            {
                Cb2 = true;
                _resetCb2NextClock = false;
            }
            else if (_handshakeCb2NextClock)
            {
                Cb2 = false;
                _resetCb2NextClock     = _pcrCb2Control == PCR_CONTROL_PULSE_OUTPUT;
                _handshakeCb2NextClock = false;
            }

            if (_resetPb7NextClock)
            {
                _prb &= 0x7F;
                _resetPb7NextClock = false;
            }
            else if (_setPb7NextClock)
            {
                _prb            |= 0x80;
                _setPb7NextClock = false;
            }

            // Count timers
            if (_t1Delayed > 0)
            {
                _t1Delayed--;
            }
            else
            {
                _t1C--;
                if (_t1C == 0)
                {
                    switch (_acrT1Control)
                    {
                    case ACR_T1_CONTROL_CONTINUOUS_INTERRUPTS_AND_OUTPUT_ON_PB7:
                        _prb ^= 0x80;
                        break;

                    case ACR_T1_CONTROL_INTERRUPT_ON_LOAD_AND_PULSE_PB7:
                        _prb |= 0x80;
                        break;
                    }
                }
                else if (_t1C < 0)
                {
                    if (_t1CLoaded)
                    {
                        _interruptNextClock |= 0x40;
                        _t1CLoaded           = false;
                    }

                    switch (_acrT1Control)
                    {
                    case ACR_T1_CONTROL_CONTINUOUS_INTERRUPTS:
                    case ACR_T1_CONTROL_CONTINUOUS_INTERRUPTS_AND_OUTPUT_ON_PB7:
                        _t1C       = _t1L;
                        _t1CLoaded = true;
                        break;
                    }

                    _t1C &= 0xFFFF;
                }
            }

            if (_t2Delayed > 0)
            {
                _t2Delayed--;
            }
            else
            {
                switch (_acrT2Control)
                {
                case ACR_T2_CONTROL_TIMED:
                    _t2C--;
                    if (_t2C < 0)
                    {
                        if (_t2CLoaded)
                        {
                            _interruptNextClock |= 0x20;
                            _t2CLoaded           = false;
                        }
                        _t2C = _t2L;
                    }
                    break;

                case ACR_T2_CONTROL_COUNT_ON_PB6:
                    _pb6L = _pb6;
                    _pb6  = (_port.ReadExternalPrb() & 0x40) != 0;
                    if (!_pb6 && _pb6L)
                    {
                        _t2C--;
                        if (_t2C == 0)
                        {
                            _ifr |= 0x20;
                        }
                        _t2C &= 0xFFFF;
                    }
                    break;
                }
            }

            // Process CA2
            switch (_pcrCa2Control)
            {
            case PCR_CONTROL_INPUT_NEGATIVE_ACTIVE_EDGE:
            case PCR_CONTROL_INDEPENDENT_INTERRUPT_INPUT_NEGATIVE_EDGE:
                if (_ca2L && !Ca2)
                {
                    _ifr |= 0x01;
                }
                break;

            case PCR_CONTROL_INPUT_POSITIVE_ACTIVE_EDGE:
            case PCR_CONTROL_INDEPENDENT_INTERRUPT_INPUT_POSITIVE_EDGE:
                if (!_ca2L && Ca2)
                {
                    _ifr |= 0x01;
                }
                break;

            case PCR_CONTROL_HANDSHAKE_OUTPUT:
                if (_ca1L && !Ca1)
                {
                    Ca2   = true;
                    _ifr |= 0x01;
                }
                break;

            case PCR_CONTROL_PULSE_OUTPUT:
                break;

            case PCR_CONTROL_LOW_OUTPUT:
                Ca2 = false;
                break;

            case PCR_CONTROL_HIGH_OUTPUT:
                Ca2 = true;
                break;
            }

            // Process CB2
            switch (_pcrCb2Control)
            {
            case PCR_CONTROL_INPUT_NEGATIVE_ACTIVE_EDGE:
            case PCR_CONTROL_INDEPENDENT_INTERRUPT_INPUT_NEGATIVE_EDGE:
                if (_cb2L && !Cb2)
                {
                    _ifr |= 0x08;
                }
                break;

            case PCR_CONTROL_INPUT_POSITIVE_ACTIVE_EDGE:
            case PCR_CONTROL_INDEPENDENT_INTERRUPT_INPUT_POSITIVE_EDGE:
                if (!_cb2L && Cb2)
                {
                    _ifr |= 0x08;
                }
                break;

            case PCR_CONTROL_HANDSHAKE_OUTPUT:
                if (_cb1L && !Cb1)
                {
                    Cb2   = true;
                    _ifr |= 0x08;
                }
                break;

            case PCR_CONTROL_PULSE_OUTPUT:
                break;

            case PCR_CONTROL_LOW_OUTPUT:
                Cb2 = false;
                break;

            case PCR_CONTROL_HIGH_OUTPUT:
                Cb2 = true;
                break;
            }

            // interrupt generation

            if (_acrSrControl == ACR_SR_CONTROL_DISABLED)
            {
                _ifr    &= 0xFB;
                _srCount = 0;
            }

            /*
             *      As long as the CA1 interrupt flag is set, the data on the peripheral pins can change
             *      without affecting the data in the latches. This input latching can be used with any of the CA2
             *      input or output modes.
             *      It is important to note that on the PA port, the processor always reads the data on the
             *      peripheral pins (as reflected in the latches). For output pins, the processor still reads the
             *      latches. This may or may not reflect the data currently in the ORA. Proper system operation
             *      requires careful planning on the part of the system designer if input latching is combined
             *      with output pins on the peripheral ports.
             */

            if ((_pcrCa1IntControl == PCR_INT_CONTROL_POSITIVE_EDGE && Ca1 && !_ca1L) ||
                (_pcrCa1IntControl == PCR_INT_CONTROL_NEGATIVE_EDGE && !Ca1 && _ca1L))
            {
                if (_acrPaLatchEnable && (_ifr & 0x02) == 0)
                {
                    _paLatch = _port.ReadExternalPra();
                }
                _ifr |= 0x02;
            }

            /*
             * Input latching on the PB port is controlled in the same manner as that described for the PA port.
             * However, with the peripheral B port the input latch will store either the voltage on the pin or the contents
             * of the Output Register (ORB) depending on whether the pin is programmed to act as an input or an
             * output. As with the PA port, the processor always reads the input latches.
             */

            if ((_pcrCb1IntControl == PCR_INT_CONTROL_POSITIVE_EDGE && Cb1 && !_cb1L) ||
                (_pcrCb1IntControl == PCR_INT_CONTROL_NEGATIVE_EDGE && !Cb1 && _cb1L))
            {
                if (_acrPbLatchEnable && (_ifr & 0x10) == 0)
                {
                    _pbLatch = _port.ReadPrb(_prb, _ddrb);
                }
                if (_acrSrControl == ACR_SR_CONTROL_DISABLED)
                {
                    shiftIn = true;
                }
                _ifr |= 0x10;
            }

            if (shiftIn)
            {
                _sr <<= 1;
                _sr  |= Cb2 ? 1 : 0;
            }

            if ((_ifr & _ier & 0x7F) != 0)
            {
                _ifr |= 0x80;
            }
            else
            {
                _ifr &= 0x7F;
            }

            _ca1L = Ca1;
            _ca2L = Ca2;
            _cb1L = Cb1;
            _cb2L = Cb2;
        }
Exemplo n.º 2
0
        public void ExecutePhase()
        {
            // Process delayed interrupts
            _ifr |= _interruptNextClock;
            _interruptNextClock = 0;

            // Process 'pulse' and 'handshake' outputs on CA2 and CB2

            if (_resetCa2NextClock)
            {
                Ca2 = true;
                _resetCa2NextClock = false;
            }
            else if (_handshakeCa2NextClock)
            {
                Ca2 = false;
                _resetCa2NextClock     = _pcrCa2Control == PCR_CONTROL_PULSE_OUTPUT;
                _handshakeCa2NextClock = false;
            }

            if (_resetCb2NextClock)
            {
                Cb2 = true;
                _resetCb2NextClock = false;
            }
            else if (_handshakeCb2NextClock)
            {
                Cb2 = false;
                _resetCb2NextClock     = _pcrCb2Control == PCR_CONTROL_PULSE_OUTPUT;
                _handshakeCb2NextClock = false;
            }

            // Count timers

            if (_t1Delayed > 0)
            {
                _t1Delayed--;
            }
            else
            {
                _t1C--;
                if (_t1C < 0)
                {
                    if (_t1CLoaded)
                    {
                        _interruptNextClock |= 0x40;
                        _t1CLoaded           = false;
                    }
                    switch (_acrT1Control)
                    {
                    case ACR_T1_CONTROL_CONTINUOUS_INTERRUPTS:
                        _t1C       = _t1L;
                        _t1CLoaded = true;
                        break;

                    case ACR_T1_CONTROL_CONTINUOUS_INTERRUPTS_AND_OUTPUT_ON_PB7:
                        _t1C       = _t1L;
                        _prb      ^= 0x80;
                        _t1CLoaded = true;
                        break;
                    }
                    _t1C &= 0xFFFF;
                }
            }

            if (_t2Delayed > 0)
            {
                _t2Delayed--;
            }
            else
            {
                switch (_acrT2Control)
                {
                case ACR_T2_CONTROL_TIMED:
                    _t2C--;
                    if (_t2C < 0)
                    {
                        if (_t2CLoaded)
                        {
                            _interruptNextClock |= 0x20;
                            _t2CLoaded           = false;
                        }
                        _t2C = _t2L;
                    }
                    break;

                case ACR_T2_CONTROL_COUNT_ON_PB6:
                    _pb6L = _pb6;
                    _pb6  = (_port.ReadExternalPrb() & 0x40) != 0;
                    if (!_pb6 && _pb6L)
                    {
                        _t2C--;
                        if (_t2C < 0)
                        {
                            _ifr |= 0x20;
                            _t2C  = 0xFFFF;
                        }
                    }
                    break;
                }
            }

            // Process CA2

            switch (_pcrCa2Control)
            {
            case PCR_CONTROL_INPUT_NEGATIVE_ACTIVE_EDGE:
            case PCR_CONTROL_INDEPENDENT_INTERRUPT_INPUT_NEGATIVE_EDGE:
                if (_ca2L && !Ca2)
                {
                    _ifr |= 0x01;
                }
                break;

            case PCR_CONTROL_INPUT_POSITIVE_ACTIVE_EDGE:
            case PCR_CONTROL_INDEPENDENT_INTERRUPT_INPUT_POSITIVE_EDGE:
                if (!_ca2L && Ca2)
                {
                    _ifr |= 0x01;
                }
                break;

            case PCR_CONTROL_HANDSHAKE_OUTPUT:
                if (_ca1L && !Ca1)
                {
                    Ca2   = true;
                    _ifr |= 0x01;
                }
                break;

            case PCR_CONTROL_PULSE_OUTPUT:
                break;

            case PCR_CONTROL_LOW_OUTPUT:
                Ca2 = false;
                break;

            case PCR_CONTROL_HIGH_OUTPUT:
                Ca2 = true;
                break;
            }

            // Process CB2

            switch (_pcrCb2Control)
            {
            case PCR_CONTROL_INPUT_NEGATIVE_ACTIVE_EDGE:
            case PCR_CONTROL_INDEPENDENT_INTERRUPT_INPUT_NEGATIVE_EDGE:
                if (_cb2L && !Cb2)
                {
                    _ifr |= 0x08;
                }
                break;

            case PCR_CONTROL_INPUT_POSITIVE_ACTIVE_EDGE:
            case PCR_CONTROL_INDEPENDENT_INTERRUPT_INPUT_POSITIVE_EDGE:
                if (!_cb2L && Cb2)
                {
                    _ifr |= 0x08;
                }
                break;

            case PCR_CONTROL_HANDSHAKE_OUTPUT:
                if (_cb1L && !Cb1)
                {
                    Cb2   = true;
                    _ifr |= 0x08;
                }
                break;

            case PCR_CONTROL_PULSE_OUTPUT:
                break;

            case PCR_CONTROL_LOW_OUTPUT:
                Cb2 = false;
                break;

            case PCR_CONTROL_HIGH_OUTPUT:
                Cb2 = true;
                break;
            }

            // interrupt generation

            if ((_pcrCb1IntControl == PCR_INT_CONTROL_POSITIVE_EDGE && Cb1 && !_cb1L) ||
                (_pcrCb1IntControl == PCR_INT_CONTROL_NEGATIVE_EDGE && !Cb1 && _cb1L))
            {
                _ifr |= 0x10;
                if (_acrPbLatchEnable)
                {
                    _pbLatch = _port.ReadExternalPrb();
                }
            }

            if ((_pcrCa1IntControl == PCR_INT_CONTROL_POSITIVE_EDGE && Ca1 && !_ca1L) ||
                (_pcrCa1IntControl == PCR_INT_CONTROL_NEGATIVE_EDGE && !Ca1 && _ca1L))
            {
                _ifr |= 0x02;
                if (_acrPaLatchEnable)
                {
                    _paLatch = _port.ReadExternalPra();
                }
            }

            switch (_acrSrControl)
            {
            case ACR_SR_CONTROL_DISABLED:
                _ifr &= 0xFB;
                break;

            default:
                break;
            }

            if ((_ifr & _ier & 0x7F) != 0)
            {
                _ifr |= 0x80;
            }
            else
            {
                _ifr &= 0x7F;
            }

            _ca1L = Ca1;
            _ca2L = Ca2;
            _cb1L = Cb1;
            _cb2L = Cb2;
        }