예제 #1
0
        public void OnFrameCompletedWorksWithLowPulseAfterTheFirsttact()
        {
            // --- Arrange
            var spectrum     = new SpectrumBeepTestMachine();
            var beeperDevice = new BeeperDevice();

            beeperDevice.OnAttachedToVm(spectrum);

            // --- Act
            spectrum.SetCurrentFrameTact(100);
            beeperDevice.ProcessEarBitValue(false, false);
            spectrum.SetCurrentFrameTact(spectrum.FrameTacts);
            beeperDevice.OnFrameCompleted();

            // --- Assert
            beeperDevice.FrameCount.ShouldBe(0);
            beeperDevice.Pulses.Count.ShouldBe(2);
            beeperDevice.LastEarBit.ShouldBeFalse();
            beeperDevice.LastPulseTact.ShouldBe(100);
            var pulse1 = beeperDevice.Pulses[0];

            pulse1.EarBit.ShouldBeTrue();
            pulse1.Lenght.ShouldBe(100);
            var pulse2 = beeperDevice.Pulses[1];

            pulse2.EarBit.ShouldBeFalse();
            pulse2.Lenght.ShouldBe(spectrum.FrameTacts - 100);
        }
        public void OnNewFrameCreatesOverflowSample(int overflow, int[] tacts, float?sample)
        {
            // --- Arrange
            var spectrum     = new SpectrumBeepTestMachine();
            var beeperDevice = new BeeperDevice();

            beeperDevice.OnAttachedToVm(spectrum);
            var initialBit = false;

            // --- Act
            foreach (var tact in tacts)
            {
                spectrum.SetCurrentCpuTact(tact);
                beeperDevice.ProcessEarBitValue(false, initialBit);
                initialBit = !initialBit;
            }
            spectrum.SetCurrentCpuTact(69888 + overflow);
            beeperDevice.OnFrameCompleted();
            var overflowBefore = beeperDevice.Overflow;

            beeperDevice.OnNewFrame();

            // --- Assert
            beeperDevice.SamplesIndex.ShouldBe(sample == null ? 0 : 1);
            overflowBefore.ShouldBe(overflow);
            beeperDevice.Overflow.ShouldBe(0);
            if (sample.HasValue)
            {
                beeperDevice.AudioSamples[0].ShouldBe(sample.Value);
            }
        }
        public void OnFrameCompletedWorksWithMultiplePulsesAndOverflow(int[] tacts, float[] samples)
        {
            // --- Arrange
            var spectrum     = new SpectrumBeepTestMachine();
            var beeperDevice = new BeeperDevice();

            beeperDevice.OnAttachedToVm(spectrum);
            var initialBit = false;

            // --- Act
            foreach (var tact in tacts)
            {
                spectrum.SetCurrentCpuTact(tact);
                beeperDevice.ProcessEarBitValue(false, initialBit);
                initialBit = !initialBit;
            }
            spectrum.SetCurrentCpuTact(69888 + 11);
            beeperDevice.OnFrameCompleted();

            // --- Assert
            beeperDevice.LastEarBit.ShouldBe(!initialBit);
            beeperDevice.FrameCount.ShouldBe(0);
            beeperDevice.Overflow.ShouldBe(11);
            beeperDevice.LastSampleTact.ShouldBe(beeperDevice.HostVm.AudioConfiguration.TactsPerSample * 699);
            for (var i = 0; i < samples.Length; i++)
            {
                samples[i].ShouldBe(beeperDevice.AudioSamples[i]);
            }
            var remainingSample = beeperDevice.LastEarBit ? 1.0f : 0.0f;

            for (var i = samples.Length; i < 699; i++)
            {
                beeperDevice.AudioSamples[i].ShouldBe(remainingSample);
            }
        }
        public void DeviceIsInitializedProperly()
        {
            // --- Arrange
            var spectrum     = new SpectrumBeepTestMachine();
            var beeperDevice = new BeeperDevice();

            // --- Act
            beeperDevice.OnAttachedToVm(spectrum);

            // --- Assert
            beeperDevice.LastEarBit.ShouldBeTrue();
            beeperDevice.FrameCount.ShouldBe(0);
            beeperDevice.LastSampleTact.ShouldBe(0);
            beeperDevice.AudioSamples.Length.ShouldBe(699);
        }
예제 #5
0
        public void DeviceIsInitializedProperty()
        {
            // --- Arrange
            var spectrum = new SpectrumBeepTestMachine();

            // --- Act
            var beeperDevice = new BeeperDevice();

            beeperDevice.OnAttachedToVm(spectrum);

            // --- Assert
            beeperDevice.Pulses.Count.ShouldBe(0);
            beeperDevice.LastEarBit.ShouldBeTrue();
            beeperDevice.LastPulseTact.ShouldBe(0);
            beeperDevice.FrameCount.ShouldBe(0);
        }
예제 #6
0
        public void ProcessEarBitWorksForTheFirstHighPulse()
        {
            // --- Arrange
            var spectrum     = new SpectrumBeepTestMachine();
            var beeperDevice = new BeeperDevice();

            beeperDevice.OnAttachedToVm(spectrum);

            // --- Act
            beeperDevice.ProcessEarBitValue(false, true);

            // --- Assert
            beeperDevice.Pulses.Count.ShouldBe(0);
            beeperDevice.LastEarBit.ShouldBeTrue();
            beeperDevice.LastPulseTact.ShouldBe(0);
        }
        public void SampleLengthIsCalculatedProperly(int frames, int[] lenghts)
        {
            // --- Arrange
            var spectrum     = new SpectrumBeepTestMachine();
            var beeperDevice = new BeeperDevice();

            beeperDevice.OnAttachedToVm(spectrum);

            // --- Act/Assert
            for (var i = 1; i <= frames; i++)
            {
                spectrum.SetCurrentCpuTact(69888 * i);
                beeperDevice.OnFrameCompleted();
                beeperDevice.AudioSamples.Length.ShouldBe(lenghts[i - 1]);
                beeperDevice.OnNewFrame();
            }
        }
예제 #8
0
        public void OnNewFrameInitsNextFrame()
        {
            // --- Arrange
            var spectrum     = new SpectrumBeepTestMachine();
            var beeperDevice = new BeeperDevice();

            beeperDevice.OnAttachedToVm(spectrum);

            // --- Act
            beeperDevice.OnNewFrame();

            // --- Assert
            beeperDevice.FrameCount.ShouldBe(1);
            beeperDevice.Pulses.Count.ShouldBe(0);
            beeperDevice.LastEarBit.ShouldBeTrue();
            beeperDevice.LastPulseTact.ShouldBe(0);
        }
예제 #9
0
        public void ProcessEarBitWorksWithLowPulseAtTact0()
        {
            // --- Arrange
            var spectrum     = new SpectrumBeepTestMachine();
            var beeperDevice = new BeeperDevice();

            beeperDevice.OnAttachedToVm(spectrum);

            // --- Act
            spectrum.SetCurrentFrameTact(0);
            beeperDevice.ProcessEarBitValue(false, false);

            // --- Assert
            beeperDevice.Pulses.Count.ShouldBe(0);
            beeperDevice.LastEarBit.ShouldBeFalse();
            beeperDevice.LastPulseTact.ShouldBe(0);
        }
예제 #10
0
        public void OnFrameCompletedWorksWithHighPulse()
        {
            // --- Arrange
            var spectrum     = new SpectrumBeepTestMachine();
            var beeperDevice = new BeeperDevice();

            beeperDevice.OnAttachedToVm(spectrum);

            // --- Act
            beeperDevice.ProcessEarBitValue(false, true);
            beeperDevice.OnFrameCompleted();

            // --- Assert
            beeperDevice.FrameCount.ShouldBe(0);
            beeperDevice.Pulses.Count.ShouldBe(1);
            beeperDevice.LastEarBit.ShouldBeTrue();
            beeperDevice.LastPulseTact.ShouldBe(0);
        }
        public void FirstPulseIsProcessedProperly(bool pulse, int tact, float[] samples)
        {
            // --- Arrange
            var spectrum     = new SpectrumBeepTestMachine();
            var beeperDevice = new BeeperDevice();

            beeperDevice.OnAttachedToVm(spectrum);

            // --- Act
            spectrum.SetCurrentCpuTact(tact);
            beeperDevice.ProcessEarBitValue(false, pulse);

            // --- Assert
            beeperDevice.LastSampleTact.ShouldBe(beeperDevice.HostVm.AudioConfiguration.TactsPerSample * samples.Length);
            for (var i = 0; i < samples.Length; i++)
            {
                samples[i].ShouldBe(beeperDevice.AudioSamples[i]);
            }
        }
예제 #12
0
        public void ProcessEarBitWorksForTheFirstLowPulse()
        {
            // --- Arrange
            var spectrum     = new SpectrumBeepTestMachine();
            var beeperDevice = new BeeperDevice();

            beeperDevice.OnAttachedToVm(spectrum);

            // --- Act
            spectrum.SetCurrentFrameTact(100);
            beeperDevice.ProcessEarBitValue(false, false);

            // --- Assert
            beeperDevice.Pulses.Count.ShouldBe(1);
            beeperDevice.LastEarBit.ShouldBeFalse();
            beeperDevice.LastPulseTact.ShouldBe(100);
            var pulse = beeperDevice.Pulses[0];

            pulse.EarBit.ShouldBeTrue();
            pulse.Lenght.ShouldBe(100);
        }
예제 #13
0
        public void OnNewFrameKeepsLastEarBitValue()
        {
            // --- Arrange
            var spectrum     = new SpectrumBeepTestMachine();
            var beeperDevice = new BeeperDevice();

            beeperDevice.OnAttachedToVm(spectrum);

            // --- Act
            spectrum.SetCurrentFrameTact(100);
            beeperDevice.ProcessEarBitValue(false, false);
            spectrum.SetCurrentFrameTact(spectrum.FrameTacts);
            beeperDevice.OnFrameCompleted();
            beeperDevice.OnNewFrame();

            // --- Assert
            beeperDevice.FrameCount.ShouldBe(1);
            beeperDevice.Pulses.Count.ShouldBe(0);
            beeperDevice.LastEarBit.ShouldBeFalse();
            beeperDevice.LastPulseTact.ShouldBe(0);
        }
        public void OnFrameCompletedWorksWithNoPulseEndOverflow()
        {
            // --- Arrange
            var spectrum     = new SpectrumBeepTestMachine();
            var beeperDevice = new BeeperDevice();

            beeperDevice.OnAttachedToVm(spectrum);

            // --- Act
            spectrum.SetCurrentCpuTact(69888 + 11);
            beeperDevice.OnFrameCompleted();

            // --- Assert
            beeperDevice.LastEarBit.ShouldBeTrue();
            beeperDevice.FrameCount.ShouldBe(0);
            beeperDevice.Overflow.ShouldBe(11);
            beeperDevice.AudioSamples.Length.ShouldBe(699);

            foreach (var sample in beeperDevice.AudioSamples)
            {
                sample.ShouldBe(1.0f);
            }
        }
예제 #15
0
        public void ProcessEarBitWorksForFourPulses()
        {
            // --- Arrange
            var spectrum     = new SpectrumBeepTestMachine();
            var beeperDevice = new BeeperDevice();

            beeperDevice.OnAttachedToVm(spectrum);

            // --- Act
            spectrum.SetCurrentFrameTact(100);
            beeperDevice.ProcessEarBitValue(false, false);
            spectrum.SetCurrentFrameTact(140);
            beeperDevice.ProcessEarBitValue(false, true);
            spectrum.SetCurrentFrameTact(160);
            beeperDevice.ProcessEarBitValue(false, true);
            spectrum.SetCurrentFrameTact(190);
            beeperDevice.ProcessEarBitValue(false, false);


            // --- Assert
            beeperDevice.Pulses.Count.ShouldBe(3);
            beeperDevice.LastEarBit.ShouldBeFalse();
            beeperDevice.LastPulseTact.ShouldBe(190);
            var pulse1 = beeperDevice.Pulses[0];

            pulse1.EarBit.ShouldBeTrue();
            pulse1.Lenght.ShouldBe(100);
            var pulse2 = beeperDevice.Pulses[1];

            pulse2.EarBit.ShouldBeFalse();
            pulse2.Lenght.ShouldBe(40);
            var pulse3 = beeperDevice.Pulses[2];

            pulse3.EarBit.ShouldBeTrue();
            pulse3.Lenght.ShouldBe(50);
        }
        public void MultiplePulsesAreProcessedProperly(int[] tacts, float[] samples)
        {
            // --- Arrange
            var spectrum     = new SpectrumBeepTestMachine();
            var beeperDevice = new BeeperDevice();

            beeperDevice.OnAttachedToVm(spectrum);
            var initialBit = false;

            // --- Act
            foreach (var tact in tacts)
            {
                spectrum.SetCurrentCpuTact(tact);
                beeperDevice.ProcessEarBitValue(false, initialBit);
                initialBit = !initialBit;
            }

            // --- Assert
            beeperDevice.LastSampleTact.ShouldBe(beeperDevice.HostVm.AudioConfiguration.TactsPerSample * samples.Length);
            for (var i = 0; i < samples.Length; i++)
            {
                samples[i].ShouldBe(beeperDevice.AudioSamples[i]);
            }
        }
예제 #17
0
        /// <summary>Initializes a new instance of the <see cref="T:System.Object" /> class.</summary>
        public Spectrum48(
            IRomProvider romProvider,
            IClockProvider clockProvider,
            IKeyboardProvider keyboardProvider,
            IScreenFrameProvider pixelRenderer,
            IEarBitFrameProvider earBitFrameProvider   = null,
            ITapeContentProvider loadContentProvider   = null,
            ISaveToTapeProvider tapeSaveToTapeProvider = null)
        {
            // --- Init the CPU
            MemoryDevice  = new Spectrum48MemoryDevice();
            PortDevice    = new Spectrum48PortDevice();
            Cpu           = new Z80Cpu(MemoryDevice, PortDevice);
            OsInitialized = false;

            // --- Setup the clock
            Clock = clockProvider;

            // --- Set up Spectrum devices
            BorderDevice    = new BorderDevice();
            ScreenDevice    = new Spectrum48ScreenDevice(pixelRenderer);
            BeeperDevice    = new BeeperDevice(earBitFrameProvider);
            KeyboardDevice  = new KeyboardDevice(keyboardProvider);
            InterruptDevice = new InterruptDevice(InterruptTact);
            TapeDevice      = new TapeDevice(loadContentProvider, tapeSaveToTapeProvider);

            // --- Carry out frame calculations

            ResetUlaTact();
            _frameTacts             = ScreenDevice.ScreenConfiguration.UlaFrameTactCount;
            PhysicalFrameClockCount = Clock.GetFrequency() / (double)ClockFrequeny * _frameTacts;
            FrameCount      = 0;
            Overflow        = 0;
            _frameCompleted = true;

            // --- Collect Spectrum devices
            _spectrumDevices.Add(MemoryDevice);
            _spectrumDevices.Add(PortDevice);
            _spectrumDevices.Add(BorderDevice);
            _spectrumDevices.Add(ScreenDevice);
            _spectrumDevices.Add(BeeperDevice);
            _spectrumDevices.Add(KeyboardDevice);
            _spectrumDevices.Add(InterruptDevice);
            _spectrumDevices.Add(TapeDevice);

            // --- Now, prepare devices to find each other
            foreach (var device in _spectrumDevices)
            {
                device.OnAttachedToVm(this);
            }

            // --- Prepare bound devices
            _frameBoundDevices = _spectrumDevices
                                 .OfType <IFrameBoundDevice>()
                                 .ToList();
            _cpuBoundDevices = _spectrumDevices
                               .OfType <ICpuOperationBoundDevice>()
                               .ToList();

            DebugInfoProvider = new SpectrumDebugInfoProvider();

            // --- Init the ROM
            InitRom(romProvider, "ZXSpectrum48");
        }