<commit_before>// X6_1000.cpp
//
// Provides interface to BBN's custom firmware for the II X6-1000 card
//
// Original authors: <NAME>, <NAME> and <NAME>
//
// Copyright 2013-2015 Raytheon BBN Technologies

#include <algorithm>  // std::max
#include <chrono>     // std::chrono::seconds etc.
#include <thread>     // std::this_thread
#include <bitset>

#include "X6_1000.h"
#include "X6_errno.h"
#include "helpers.h"
#include "constants.h"

#include <IppMemoryUtils_Mb.h>  // for Init::UsePerformanceMemoryFunctions
#include <BufferDatagrams_Mb.h> // for ShortDG

using namespace Innovative;

// constructor
X6_1000::X6_1000() :
    isOpen_{false},
    isRunning_{false},
    needToInit_{true},
    activeInputChannels_{true, true},
    activeOutputChannels_{false, false, false, false},
    refSource_{INTERNAL_REFERENCE}
    {

    timer_.Interval(1000);

    // Use IPP performance memory functions.
    Init::UsePerformanceMemoryFunctions();
}

X6_1000::~X6_1000() {
	if (isOpen_) close();
}

void X6_1000::open(int deviceID) {
    /* Connects to the II module with the given device ID returns MODULE_ERROR
     * if the device cannot be found
     */

    if (isOpen_) return;

    deviceID_ = deviceID;

    //  Configure Trigger Manager Event Handlers
    trigger_.OnDisableTrigger.SetEvent(this, &X6_1000::HandleDisableTrigger);
    trigger_.OnExternalTrigger.SetEvent(this, &X6_1000::HandleExternalTrigger);
    trigger_.OnSoftwareTrigger.SetEvent(this, &X6_1000::HandleSoftwareTrigger);
    trigger_.DelayedTrigger(true); // trigger delayed after start

    //  Configure Module Event Handlers
    module_.OnBeforeStreamStart.SetEvent(this, &X6_1000::HandleBeforeStreamStart);
    module_.OnBeforeStreamStart.Synchronize();
    module_.OnAfterStreamStart.SetEvent(this, &X6_1000::HandleAfterStreamStart);
    module_.OnAfterStreamStart.Synchronize();
    module_.OnAfterStreamStop.SetEvent(this, &X6_1000::HandleAfterStreamStop);
    module_.OnAfterStreamStop.Synchronize();

    // Stream Event Handlers
    stream_.DirectDataMode(false);
    stream_.OnVeloDataAvailable.SetEvent(this, &X6_1000::HandleDataAvailable);

    stream_.RxLoadBalancing(false);
    stream_.TxLoadBalancing(false);

    timer_.OnElapsed.SetEvent(this, &X6_1000::HandleTimer);
    timer_.OnElapsed.Thunk();

    // Insure BM size is a multiple of four MB
    const int RxBmSize = std::max(BusmasterSize/4, 1) * 4;
    const int TxBmSize = std::max(BusmasterSize/4, 1) * 4;
    module_.IncomingBusMasterSize(RxBmSize * Meg);
    module_.OutgoingBusMasterSize(TxBmSize * Meg);

    module_.Target(deviceID);

    try {
        module_.Open();
        FILE_LOG(logINFO) << "Opened Device " << deviceID;
        FILE_LOG(logINFO) << "Bus master size: Input => " << RxBmSize << " MB" << " Output => " << TxBmSize << " MB";
    }
    catch(...) {
        FILE_LOG(logINFO) << "Module Device Open Failure!";
        throw X6_MODULE_ERROR;
    }

    module_.Reset();
    FILE_LOG(logINFO) << "X6 module opened and reset successfully...";

    needToInit_ = true;

    isOpen_ = true;

    log_card_info();

    //  Connect Stream
    stream_.ConnectTo(&module_);
    FILE_LOG(logINFO) << "Stream Connected...";

    prefillPacketCount_ = stream_.PrefillPacketCount();
    FILE_LOG(logDEBUG) << "Stream prefill packet count: " << prefillPacketCount_;

    //Set some default clocking so get_pll_frequency and *_nco_frequency work
    //Use internal reference and 1GS ADC/DAC
    FILE_LOG(logDEBUG) << "Setting default clocking to internal 10MHz reference.";
    module_.Clock().Reference(IX6ClockIo::rsInternal);
    module_.Clock().ReferenceFrequency(10e6);
    module_.Clock().Source(IX6ClockIo::csInternal);
    module_.Clock().Frequency(1e9);
  }

void X6_1000::init() {
    //Initialize/preconfigure the stream for the current channel configuration

    set_active_channels();

    //For now hard-code in some clocking and routing
    module_.Clock().ExternalClkSelect(IX6ClockIo::cslFrontPanel);
    module_.Clock().Source(IX6ClockIo::csInternal);

    //Switch between internal and external reference
    module_.Clock().ReferenceFrequency(10e6); //assume 10MHz for now
    module_.Clock().Reference((refSource_ == EXTERNAL_REFERENCE) ? IX6ClockIo::rsExternal : IX6ClockIo::rsInternal);

    //Run the ADC and DAC at full rate for now
    module_.Clock().Adc().Frequency(1000 * 1e6);
    module_.Clock().Dac().Frequency(1000 * 1e6);
    // Readback Frequency
    double adc_freq_actual = module_.Clock().Adc().FrequencyActual();
    double dac_freq_actual = module_.Clock().Dac().FrequencyActual();
    double adc_freq = module_.Clock().Adc().Frequency();
    double dac_freq = module_.Clock().Dac().Frequency();

    FILE_LOG(logDEBUG) << "Desired PLL Frequencies: [ADC] " << adc_freq << " [DAC] " << dac_freq;
    FILE_LOG(logDEBUG) << "Actual PLL Frequencies: [ADC] " << adc_freq_actual << " [DAC] " << dac_freq_actual;

    FILE_LOG(logDEBUG) << "AFE reg. 0x98 (DAC calibration): " << hexn<8> << read_wishbone_register(0x0800, 0x98);
    FILE_LOG(logDEBUG) << "Preconfiguring stream...";
    stream_.Preconfigure();
    FILE_LOG(logDEBUG) << "AFE reg. 0x98 (DAC calibration): " << hexn<8> << read_wishbone_register(0x0800, 0x98);

    needToInit_ = false;
}

void X6_1000::close() {
    stream_.Disconnect();
    module_.Close();

    isOpen_ = false;
    FILE_LOG(logINFO) << "Closed connection to device " << deviceID_;
}

uint16_t X6_1000::get_firmware_version(X6_MODULE_FIRMWARE_VERSION mod) {
    uint32_t regVal;
    switch (mod) {
        case BBN_PG:
            //Read from PG regs
            regVal = read_wishbone_register(BASE_PG[0], WB_PG_MODULE_FIRMWARE_VERSION);<commit_msg>Maximum sample rate for the DACs is 500MS in two channel mode<commit_after>// X6_1000.cpp
//
// Provides interface to BBN's custom firmware for the II X6-1000 card
//
// Original authors: <NAME>, <NAME> and <NAME>
//
// Copyright 2013-2015 Raytheon BBN Technologies

#include <algorithm>  // std::max
#include <chrono>     // std::chrono::seconds etc.
#include <thread>     // std::this_thread
#include <bitset>

#include "X6_1000.h"
#include "X6_errno.h"
#include "helpers.h"
#include "constants.h"

#include <IppMemoryUtils_Mb.h>  // for Init::UsePerformanceMemoryFunctions
#include <BufferDatagrams_Mb.h> // for ShortDG

using namespace Innovative;

// constructor
X6_1000::X6_1000() :
    isOpen_{false},
    isRunning_{false},
    needToInit_{true},
    activeInputChannels_{true, true},
    activeOutputChannels_{false, false, false, false},
    refSource_{INTERNAL_REFERENCE}
    {

    timer_.Interval(1000);

    // Use IPP performance memory functions.
    Init::UsePerformanceMemoryFunctions();
}

X6_1000::~X6_1000() {
	if (isOpen_) close();
}

void X6_1000::open(int deviceID) {
    /* Connects to the II module with the given device ID returns MODULE_ERROR
     * if the device cannot be found
     */

    if (isOpen_) return;

    deviceID_ = deviceID;

    //  Configure Trigger Manager Event Handlers
    trigger_.OnDisableTrigger.SetEvent(this, &X6_1000::HandleDisableTrigger);
    trigger_.OnExternalTrigger.SetEvent(this, &X6_1000::HandleExternalTrigger);
    trigger_.OnSoftwareTrigger.SetEvent(this, &X6_1000::HandleSoftwareTrigger);
    trigger_.DelayedTrigger(true); // trigger delayed after start

    //  Configure Module Event Handlers
    module_.OnBeforeStreamStart.SetEvent(this, &X6_1000::HandleBeforeStreamStart);
    module_.OnBeforeStreamStart.Synchronize();
    module_.OnAfterStreamStart.SetEvent(this, &X6_1000::HandleAfterStreamStart);
    module_.OnAfterStreamStart.Synchronize();
    module_.OnAfterStreamStop.SetEvent(this, &X6_1000::HandleAfterStreamStop);
    module_.OnAfterStreamStop.Synchronize();

    // Stream Event Handlers
    stream_.DirectDataMode(false);
    stream_.OnVeloDataAvailable.SetEvent(this, &X6_1000::HandleDataAvailable);

    stream_.RxLoadBalancing(false);
    stream_.TxLoadBalancing(false);

    timer_.OnElapsed.SetEvent(this, &X6_1000::HandleTimer);
    timer_.OnElapsed.Thunk();

    // Insure BM size is a multiple of four MB
    const int RxBmSize = std::max(BusmasterSize/4, 1) * 4;
    const int TxBmSize = std::max(BusmasterSize/4, 1) * 4;
    module_.IncomingBusMasterSize(RxBmSize * Meg);
    module_.OutgoingBusMasterSize(TxBmSize * Meg);

    module_.Target(deviceID);

    try {
        module_.Open();
        FILE_LOG(logINFO) << "Opened Device " << deviceID;
        FILE_LOG(logINFO) << "Bus master size: Input => " << RxBmSize << " MB" << " Output => " << TxBmSize << " MB";
    }
    catch(...) {
        FILE_LOG(logINFO) << "Module Device Open Failure!";
        throw X6_MODULE_ERROR;
    }

    module_.Reset();
    FILE_LOG(logINFO) << "X6 module opened and reset successfully...";

    needToInit_ = true;

    isOpen_ = true;

    log_card_info();

    //  Connect Stream
    stream_.ConnectTo(&module_);
    FILE_LOG(logINFO) << "Stream Connected...";

    prefillPacketCount_ = stream_.PrefillPacketCount();
    FILE_LOG(logDEBUG) << "Stream prefill packet count: " << prefillPacketCount_;

    //Set some default clocking so get_pll_frequency and *_nco_frequency work
    //Use internal reference and 1GS ADC/DAC
    FILE_LOG(logDEBUG) << "Setting default clocking to internal 10MHz reference.";
    module_.Clock().Reference(IX6ClockIo::rsInternal);
    module_.Clock().ReferenceFrequency(10e6);
    module_.Clock().Source(IX6ClockIo::csInternal);
    module_.Clock().Frequency(1e9);
  }

void X6_1000::init() {
    //Initialize/preconfigure the stream for the current channel configuration

    set_active_channels();

    //For now hard-code in some clocking and routing
    module_.Clock().ExternalClkSelect(IX6ClockIo::cslFrontPanel);
    module_.Clock().Source(IX6ClockIo::csInternal);

    //Switch between internal and external reference
    module_.Clock().ReferenceFrequency(10e6); //assume 10MHz for now
    module_.Clock().Reference((refSource_ == EXTERNAL_REFERENCE) ? IX6ClockIo::rsExternal : IX6ClockIo::rsInternal);

    //Run the ADC and DAC at full rate for now
    module_.Clock().Adc().Frequency(1000 * 1e6);
    //Full rate in one channel mode is 1GS but two channels at 500MS/s
    if (activeOutputChannels_[1] || activeOutputChannels_[3]) {
        module_.Clock().Dac().Frequency(500 * 1e6);
    }
    else {
        module_.Clock().Dac().Frequency(1000 * 1e6);
    }

    // Readback Frequency
    double adc_freq_actual = module_.Clock().Adc().FrequencyActual();
    double dac_freq_actual = module_.Clock().Dac().FrequencyActual();
    double adc_freq = module_.Clock().Adc().Frequency();
    double dac_freq = module_.Clock().Dac().Frequency();

    FILE_LOG(logDEBUG) << "Desired PLL Frequencies: [ADC] " << adc_freq << " [DAC] " << dac_freq;
    FILE_LOG(logDEBUG) << "Actual PLL Frequencies: [ADC] " << adc_freq_actual << " [DAC] " << dac_freq_actual;

    FILE_LOG(logDEBUG) << "AFE reg. 0x98 (DAC calibration): " << hexn<8> << read_wishbone_register(0x0800, 0x98);
    FILE_LOG(logDEBUG) << "Preconfiguring stream...";
    stream_.Preconfigure();
    FILE_LOG(logDEBUG) << "AFE reg. 0x98 (DAC calibration): " << hexn<8> << read_wishbone_register(0x0800, 0x98);

    needToInit_ = false;
}

void X6_1000::close() {
    stream_.Disconnect();
    module_.Close();

    isOpen_ = false;
    FILE_LOG(logINFO) << "Closed connection to device " << deviceID_;
}

uint16_t X6_1000::get_firmware_version(X6_MODULE_FIRMWARE_VERSION mod) {
    uint32_t regVal;
    switch (mod) {
        case BBN_PG:
            //Read from PG regs
            regVal = read_wishbone_register(BASE_PG[0], WB_PG_MODULE_FIRMWARE_VERSION);
{'fraction_non_alphanumeric': 0.12890456931417263, 'fraction_numerical': 0.0316668100851906, 'mean_word_length': 3.9287531806615776, 'pattern_counts': {'":': 0, '<': 149, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3175946', 'n_tokens_mistral': 4031, 'n_tokens_neox': 3694, 'n_words': 791}