#include "C64SerialAnalyzer.h" #include "C64SerialAnalyzerSettings.h" #include C64SerialAnalyzer::C64SerialAnalyzer() : Analyzer2(), mSettings(new C64SerialAnalyzerSettings()), mSimulationInitilized(false) { SetAnalyzerSettings(mSettings.get()); } C64SerialAnalyzer::~C64SerialAnalyzer() { KillThread(); } void C64SerialAnalyzer::SetupResults() { mResults.reset(new C64SerialAnalyzerResults(this, mSettings.get())); SetAnalyzerResults(mResults.get()); mResults->AddChannelBubblesWillAppearOn(mSettings->mDataChannel); } U64 C64SerialAnalyzer::AdvanceTo(U64 sample) { mData->AdvanceToAbsPosition(sample); mClock->AdvanceToAbsPosition(sample); //mAttention->AdvanceToAbsPosition(sample); return sample; } bool C64SerialAnalyzer::ReceiveByte() { // Advance until both clock and data lines are asserted. while (mData->GetBitState() == BIT_LOW || mClock->GetBitState() == BIT_LOW) { AdvanceTo(std::min(mData->GetSampleOfNextEdge(), mClock->GetSampleOfNextEdge())); } bool eoi = mData->GetSampleOfNextEdge() < mClock->GetSampleOfNextEdge(); if (eoi) { // An EOI happened, go back to idle after finishing. mResults->AddMarker(mClock->GetSampleNumber(), AnalyzerResults::X, mSettings->mClockChannel); } mResults->AddMarker(mClock->GetSampleNumber(), AnalyzerResults::Start, mSettings->mDataChannel); U64 start_sample = AdvanceTo(mClock->GetSampleOfNextEdge()); // Receive a byte U8 byte = 0; for (int i = 0; i < 8; i++) { AdvanceTo(mClock->GetSampleOfNextEdge()); mResults->AddMarker(mClock->GetSampleNumber(), AnalyzerResults::Dot, mSettings->mDataChannel); mResults->AddMarker(mClock->GetSampleNumber(), AnalyzerResults::UpArrow, mSettings->mClockChannel); byte |= mData->GetBitState() << i; AdvanceTo(mClock->GetSampleOfNextEdge()); mResults->AddMarker(mClock->GetSampleNumber(), AnalyzerResults::DownArrow, mSettings->mClockChannel); } // We have a byte to save Frame frame; frame.mData1 = byte; frame.mType = static_cast(mState); frame.mStartingSampleInclusive = start_sample; frame.mEndingSampleInclusive = mData->GetSampleNumber(); mResults->AddFrame(frame); mResults->CommitResults(); ReportProgress(frame.mEndingSampleInclusive); // Wait until data is high and back down. if (mData->GetBitState() == BIT_LOW) { AdvanceTo(mData->GetSampleOfNextEdge()); } AdvanceTo(mData->GetSampleOfNextEdge()); mResults->AddMarker(mClock->GetSampleNumber(), AnalyzerResults::Stop, mSettings->mDataChannel); return eoi; } enum class FrameType { Attention, Talking, }; void C64SerialAnalyzer::Update() { mResults->AddMarker(mClock->GetSampleNumber(), AnalyzerResults::Dot, mSettings->mAttentionChannel); if (mState == State::Idle) { // Advance until both clock and data lines are asserted. while (mData->GetBitState() == BIT_HIGH || mClock->GetBitState() == BIT_HIGH) { AdvanceTo(std::min(mData->GetSampleOfNextEdge(), mClock->GetSampleOfNextEdge())); } // Check if attention was asserted. BitState old_attention = mAttention->GetBitState(); mAttention->AdvanceToAbsPosition(mClock->GetSampleOfNextEdge()); BitState new_attention = mAttention->GetBitState(); if (new_attention == BIT_LOW) { mState = State::Attention; } else if (old_attention == BIT_LOW) { // If attention was low but is now high, check if talking continues. if (mData->GetSampleOfNextEdge() > mClock->GetSampleOfNextEdge()) { mState = State::Talking; } else { AdvanceTo(mAttention->GetSampleNumber()); } } else { mState = State::Talking; } } else if (mState == State::Attention) { ReceiveByte(); mState = State::Idle; } else if (mState == State::Talking) { bool eoi = ReceiveByte(); if (eoi) { mState = State::Idle; } } else if (mState == State::TurnAround) { } } void C64SerialAnalyzer::WorkerThread() { mSampleRateHz = GetSampleRate(); mAttention = GetAnalyzerChannelData(mSettings->mAttentionChannel); mData = GetAnalyzerChannelData(mSettings->mDataChannel); mClock = GetAnalyzerChannelData(mSettings->mClockChannel); mState = State::Idle; while (true) { Update(); CheckIfThreadShouldExit(); } } bool C64SerialAnalyzer::NeedsRerun() { return false; } U32 C64SerialAnalyzer::GenerateSimulationData( U64 minimum_sample_index, U32 device_sample_rate, SimulationChannelDescriptor **simulation_channels) { if (mSimulationInitilized == false) { mSimulationDataGenerator.Initialize(GetSimulationSampleRate(), mSettings.get()); mSimulationInitilized = true; } return mSimulationDataGenerator.GenerateSimulationData( minimum_sample_index, device_sample_rate, simulation_channels); } U32 C64SerialAnalyzer::GetMinimumSampleRateHz() { // return mSettings->mBitRate * 4; return 4000000; } const char *C64SerialAnalyzer::GetAnalyzerName() const { return "C64 Serial"; } const char *GetAnalyzerName() { return "C64 Serial"; } Analyzer *CreateAnalyzer() { return new C64SerialAnalyzer(); } void DestroyAnalyzer(Analyzer *analyzer) { delete analyzer; }