123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071 |
- #include "spdlog/spdlog.h"
- #include "spdlog/async.h"
- #include "spdlog/sinks/stdout_color_sinks.h"
- #include "CereConn.h"
- #include "CereConnHelpers.h"
- #include <algorithm>
- #include <cstdio>
- #include <functional>
- namespace cc
- {
- CereConn::CereConn(uint32_t instance, bool withSRE, bool withSBPE)
- : m_msgQ (20)
- , m_conType (CBSDKCONNECTION_DEFAULT)
- , m_instance (instance)
- , m_state (State::Closed)
- , m_keep_going(true)
- , m_with_SRE(withSRE)
- , m_with_SBPE(withSBPE)
- {
- std::fill(std::begin(m_sgroup_changed), std::end(m_sgroup_changed), true);
-
- auto l = spdlog::get("CereConn");
- if (l)
- {
- m_console = l;
- }
- else
- {
- m_console = spdlog::stdout_color_mt<spdlog::async_factory>("CereConn");
- }
- l = spdlog::get("CereConnAcq");
- if (l)
- {
- m_acq = l;
- }
- else
- {
- m_acq = std::make_shared<spdlog::logger>("CereConnAcq", begin(m_console->sinks()), end(m_console->sinks()));
- spdlog::register_logger(m_acq);
- }
- m_pRb = std::make_unique<SampleGroupRingBufferCollection>();
- m_pSRb = std::make_unique<SpikeRingBuffer>();
- m_pCRb = std::make_unique<CommentRingBuffer>();
- m_pDIRb = std::make_unique<DigInEvRingBuffer>();
-
-
- mp_rateRB = std::make_shared<sre::SpikeRateEstimator::rate_ring_buffer_type>();
- mp_sbpRB = std::make_shared<sbpe::SpikeBandPowerEstimator::sbp_ring_buffer_type>();
-
-
- #if defined(CC_LOG_LEVEL_DEBUG)
- spdlog::set_level(spdlog::level::debug);
- #else
- spdlog::set_level(spdlog::level::info);
- #endif
- spikeRateEstimatorSetUp();
- spikeBandPowerEstimatorSetUp();
- m_console->info("Welcome to CereConn!");
- m_sample_groups_enabled.fill(false);
- startThread();
- }
- CereConn::~CereConn()
- {
- spikeRateEstimatorStop();
- spikeBandPowerEstimatorStop();
-
- m_keep_going.store(false);
- sendMessage(Instruction::Close);
- if (m_thread.joinable())
- {
- m_thread.join();
- }
- }
- void CereConn::startThread()
- {
- m_console->debug("Starting NSP Thread from outside {}...", std::hash<std::thread::id>()(std::this_thread::get_id()));
- if (m_thread.joinable())
- {
- m_keep_going.store(false);
- sendMessage(Instruction::Close);
- m_thread.join();
- }
- while (m_msgQ.sizeGuess())
- {
- m_msgQ.popFront();
- }
- m_thread = std::thread(&CereConn::threadFun, this);
- }
- void CereConn::sendMessage(Instruction instruction)
- {
- std::unique_lock<std::mutex> locker(m_msg_lock);
- m_console->info("CereConnMsg thread sending {} ...", static_cast<int>(instruction));
- m_msgQ.write(instruction);
- m_msg_queue_not_empty.notify_one();
- }
- void CereConn::ccOpen()
- {
- sendMessage(Instruction::Open);
- }
- void CereConn::ccRecord()
- {
- sendMessage(Instruction::Record);
- }
- void CereConn::ccIdle()
- {
- sendMessage(Instruction::Idle);
- }
- void CereConn::ccClose()
- {
- sendMessage(Instruction::Close);
- }
- CereConn::ReturnCode CereConn::getSampleGroupData(SampleGroupList &sgl, uint32_t &cbTime)
- {
- if (m_state != State::Recording)
- {
- m_console->warn("CereConn::getSampleGroupData called while not recording.");
- return ReturnCode::NotRecording;
- }
- m_pRb->consume(sgl);
- cbSdkResult res;
- res = cbSdkGetTime(m_instance, &cbTime);
- if (res != 0)
- {
- m_acq->error("cbSdkGetTime returned {}", res);
- return ReturnCode::NoValidTimestamp;
- }
- sgl.timestamp = cbTime;
- return ReturnCode::Success;
- }
- void CereConn::threadFun()
- {
- m_acq->debug("Starting NSP Thread {}...", std::hash<std::thread::id>()(std::this_thread::get_id()));
- CereConn::Instruction my_instruction;
- m_keep_going.store(true);
- while (m_keep_going.load())
- {
- std::unique_lock<std::mutex> locker(m_msg_lock);
- // ensure queue is not empty when we wake up
- m_msg_queue_not_empty.wait(locker, std::bind(std::logical_not<bool>(), std::bind(&folly::ProducerConsumerQueue<Instruction>::isEmpty, &m_msgQ)));
- if (! m_msgQ.read(my_instruction))
- {
- continue;
- }
- m_acq->info("Got message {}", static_cast<int> (my_instruction));
- switch (my_instruction)
- {
- case Instruction::Open:
- if (m_state == State::Closed || m_state == State::Invalid)
- {
- cbOpen();
- }
- break;
- case Instruction::Close:
- if (m_state == State::Idle || m_state == State::Recording)
- {
- cbClose();
- }
- break;
- case Instruction::Record:
- if (m_state == State::Idle)
- {
- cbStartRecording();
- }
- break;
- case Instruction::Idle:
- if (m_state == State::Recording)
- {
- cbStopRecording();
- }
- break;
- case Instruction::Invalid:
- default:
- break;
- }
- }
- }
- void CereConn::cbOpen()
- {
- m_acq->debug("Opening cbSDK ...");
- cbSdkResult res = cbSdkOpen(m_instance, m_conType);
- if (res == 0)
- {
- m_acq->debug("cbSdkOpen returned: {}", res);
- m_state = State::Idle;
- // Hard-coding of sample periods. TODO: make this dynamic by interrogating CereLink
-
- for (unsigned int i = 0; i < constants::NSampleGroups; ++i)
- {
- m_pRb->setSamplePeriodForGroup(i + 1, constants::SampleGroupPeriods[i]);
- }
- res = cbSdkRegisterCallback(m_instance, CBSDKCALLBACK_GROUPINFO, CereConn::cbSdkCallbackGroupInfo, this);
- if (res != 0)
- {
- m_acq->error("cbSdkRegisterCallback CBSDKCALLBACK_GROUPINFO returned {}", res);
- return;
- }
- updateGroupChannelLists();
- }
- else
- {
- m_acq->error("cbSdkOpen returned {}", res);
- m_state = State::Invalid;
- return;
- }
- }
- void CereConn::cbStartRecording()
- {
- cbSdkResult res;
- if (m_with_SRE)
- {
- spikeRateEstimatorStart();
- }
- if (m_with_SBPE)
- {
- spikeBandPowerEstimatorStart();
- }
-
- res = cbSdkRegisterCallback(m_instance, CBSDKCALLBACK_CONTINUOUS, CereConn::cbSdkCallbackContinuous, this);
- if (res != 0)
- {
- m_acq->error("cbSdkRegisterCallback CBSDKCALLBACK_CONTINUOUS returned {}", res);
- return;
- }
- res = cbSdkRegisterCallback(m_instance, CBSDKCALLBACK_SPIKE, CereConn::cbSdkCallbackSpike, this);
- if (res != 0)
- {
- m_acq->error("cbSdkRegisterCallback CBSDKCALLBACK_SPIKE returned {}", res);
- return;
- }
- res = cbSdkRegisterCallback(m_instance, CBSDKCALLBACK_COMMENT, CereConn::cbSdkCallbackComment, this);
- if (res != 0)
- {
- m_acq->error("cbSdkRegisterCallback CBSDKCALLBACK_COMMENT returned {}", res);
- return;
- }
- res = cbSdkRegisterCallback(m_instance, CBSDKCALLBACK_DIGITAL, CereConn::cbSdkCallbackDigInEv, this);
- if (res != 0)
- {
- m_acq->error("cbSdkRegisterCallback CBSDKCALLBACK_DIGITAL returned {}", res);
- return;
- }
- res = cbSdkRegisterCallback(m_instance, CBSDKCALLBACK_SERIAL, CereConn::cbSdkCallbackDigInEv, this);
- if (res != 0)
- {
- m_acq->error("cbSdkRegisterCallback CBSDKCALLBACK_SERIAL returned {}", res);
- return;
- }
- m_acq->info("Registered packet callbacks.");
- m_state = State::Recording;
-
- }
- void CereConn::cbStopRecording()
- {
- cbSdkResult res = cbSdkUnRegisterCallback(m_instance, CBSDKCALLBACK_CONTINUOUS);
- if (res != 0)
- {
- m_acq->error("cbSdkUnRegisterCallback CBSDKCALLBACK_CONTINUOUS returned {}", res);
- return;
- }
- res = cbSdkUnRegisterCallback(m_instance, CBSDKCALLBACK_SPIKE);
- if (res != 0)
- {
- m_acq->error("cbSdkUnRegisterCallback CBSDKCALLBACK_SPIKE returned {}", res);
- return;
- }
- res = cbSdkUnRegisterCallback(m_instance, CBSDKCALLBACK_COMMENT);
- if (res != 0)
- {
- m_acq->error("cbSdkUnRegisterCallback CBSDKCALLBACK_COMMENT returned {}", res);
- return;
- }
- res = cbSdkUnRegisterCallback(m_instance, CBSDKCALLBACK_DIGITAL);
- if (res != 0)
- {
- m_acq->error("cbSdkUnRegisterCallback CBSDKCALLBACK_DIGITAL returned {}", res);
- return;
- }
-
- res = cbSdkUnRegisterCallback(m_instance, CBSDKCALLBACK_SERIAL);
- if (res != 0)
- {
- m_acq->error("cbSdkUnRegisterCallback CBSDKCALLBACK_SERIAL returned {}", res);
- return;
- }
-
- if (m_with_SRE)
- {
- spikeRateEstimatorStop();
- }
- if (m_with_SBPE)
- {
- spikeBandPowerEstimatorStop();
- }
-
- m_acq->info("Unregistered packet callbacks.");
- m_state = State::Idle;
- }
- void CereConn::cbClose()
- {
- m_acq->debug("Closing cbSDK ...");
-
- cbSdkResult res = cbSdkUnRegisterCallback(m_instance, CBSDKCALLBACK_GROUPINFO);
- if (res != 0)
- {
- m_acq->error("cbSdkUnRegisterCallback CBSDKCALLBACK_GROUPINFO returned {}", res);
- }
-
- res = cbSdkClose(m_instance);
- m_state = State::Closed;
- if (res == 0)
- {
- m_acq->debug("cbSdkClose returned: {}", res);
- }
- else
- {
- m_acq->error("cbSdkClose returned {}", res);
- return;
- }
- }
- CereConn::State CereConn::getState() const
- {
- return m_state;
- }
- CereConn::ReturnCode CereConn::sendComment(const std::string comment, const uint32_t rgba, const uint8_t charset)
- {
- cbSdkResult res = cbSdkSetComment(m_instance, rgba, charset, comment.c_str());
- m_acq->info("Sent comment <{}> ({}) with result: {}", comment, rgba, res);
- if (res != 0)
- {
- m_acq->error("cbSdkSetComment returned {} (in sendComment)", res);
- return ReturnCode::Error;
- }
- return ReturnCode::Success;
- }
- CereConn::ReturnCode CereConn::getCommentData(CommentList &clist, uint32_t &cbTime)
- {
- size_t oc;
- return getCommentData(clist, cbTime, oc);
- }
- CereConn::ReturnCode CereConn::getCommentData(CommentList &clist, uint32_t &cbTime, size_t &overflowCount)
- {
- if (m_state != State::Recording)
- {
- m_console->warn("CereConn::getCommentData called while not recording.");
- return ReturnCode::NotRecording;
- }
- m_pCRb->consume(clist, overflowCount);
- cbSdkResult res;
- res = cbSdkGetTime(m_instance, &cbTime);
- if (res != 0)
- {
- m_acq->error("cbSdkGetTime returned {} (in getCommentData)", res);
- return ReturnCode::NoValidTimestamp;
- }
- return ReturnCode::Success;
- }
- CereConn::ReturnCode CereConn::getDigInEvData(DigInEvList &dievlist, uint32_t &cbTime)
- {
- size_t oc;
- return getDigInEvData(dievlist, cbTime, oc);
- }
- CereConn::ReturnCode CereConn::getDigInEvData(DigInEvList &dievlist, uint32_t &cbTime, size_t &overflowCount)
- {
- if (m_state != State::Recording)
- {
- m_console->warn("CereConn::getDigInEvData called while not recording.");
- return ReturnCode::NotRecording;
- }
- m_pDIRb->consume(dievlist, overflowCount);
- cbSdkResult res;
- res = cbSdkGetTime(m_instance, &cbTime);
- if (res != 0)
- {
- m_acq->error("cbSdkGetTime returned {} (in getDigInEvData)", res);
- return ReturnCode::NoValidTimestamp;
- }
- return ReturnCode::Success;
- }
- CereConn::ReturnCode CereConn::getCbTime(uint32_t &cbTime)
- {
- cbSdkResult res;
- if (m_state == State::Invalid || m_state == State::Closed)
- {
- m_console->warn("CereConn::getCbTime called while not recording.");
- return ReturnCode::NotRecording;
- }
- res = cbSdkGetTime(m_instance, &cbTime);
- if (res != 0)
- {
- m_acq->error("cbSdkGetTime returned {}", res);
- return ReturnCode::NoValidTimestamp;
- }
- return ReturnCode::Success;
- }
- void CereConn::setEnabledSampleGroups(const SGroupBoolA &sgroups_enabled)
- {
- std::copy(sgroups_enabled.begin(), sgroups_enabled.end(), m_sample_groups_enabled.begin());
- }
- void CereConn::setSampleGroup(const size_t group, const bool state)
- {
- m_sample_groups_enabled[group - 1] = state;
- }
- bool CereConn::getSampleGroup(const size_t group) const
- {
- return m_sample_groups_enabled[group - 1];
- }
- bool CereConn::setCARChannels(const size_t group, const ChannelNumList_t &carChannelList)
- {
- if (mp_sbpe)
- {
- mp_sbpe->setCARChannels(group, carChannelList);
- }
- return m_pRb->setCARChannels(group, carChannelList);
- }
- bool CereConn::setCARChannels(const size_t group, ChannelNumList_t &&carChannelList)
- {
- if (mp_sbpe)
- {
- mp_sbpe->setCARChannels(group, carChannelList);
- }
- return m_pRb->setCARChannels(group, carChannelList);
- }
- void CereConn::disableCAR(const size_t group)
- {
- if (mp_sbpe)
- {
- mp_sbpe->disableCAR(group);
- }
-
- m_pRb->disableCAR(group);
- }
- void CereConn::printBufferState() const
- {
- std::array<size_t, constants::NSampleGroups> ofc = m_pRb->getOverflowCount();
- for (unsigned int i = 0; i < constants::NSampleGroups; ++i)
- {
- m_acq->info("Sample group {} Buffer overflow counter: {}", i+1, ofc[i]);
- }
- }
- void CereConn::spikeRateEstimatorSetUp()
- {
- using namespace std::literals;
-
- mp_sre = std::make_unique<sre::SpikeRateEstimator>(constants::MaxFEChannels, constants::MaxUnits, 200, 100ms);
- if (mp_sre)
- {
- mp_sre->set_logger(m_console);
- if (mp_rateRB)
- {
- mp_sre->attachSpikeRateRB(mp_rateRB);
- }
- mp_sre->bindCallback([](const sre::SpikeRateEstimator::unit_hist_type& uh){ return r_estimate_with_boxcar_w_cont(uh, 10);});
- mp_sre->bindTimestampCallback([this](){Timestamp_t cbTime = 0; cbSdkGetTime(m_instance, &cbTime); return cbTime;});
- }
- }
- void CereConn::spikeRateEstimatorStart()
- {
- if (mp_sre)
- {
- m_console->debug("Starting SpikeRateEstimator");
- mp_sre->signalStart();
- }
- else
- {
- m_console->warn("CereConn::spikeRateEstimatorStart: spike rate estimator not initialised");
- }
- }
- void CereConn::spikeRateEstimatorStop()
- {
- if (mp_sre)
- {
- m_console->debug("Stopping SpikeRateEstimator");
- mp_sre->signalStop();
- }
- else
- {
- m_console->warn("CereConn::spikeRateEstimatorStop: spike rate estimator not initialised");
- }
- }
- void CereConn::setSpikeRateEstimatorChannelUnitList(const sre::SpikeRateEstimator::ch_un_list_type & ch_un_list)
- {
- if (mp_sre)
- {
- m_console->debug("CereConn::setSpikeRateEstimatorChannelUnitList: change channel unit map");
-
- mp_sre->setChannelUnitList(ch_un_list);
- }
- else
- {
- m_console->warn("CereConn::setSpikeRateEstimatorChannelUnitList: spike rate estimator not initialised");
- }
- }
- void CereConn::fillSpikeRateEstimatorChannelUnitList(const sre::SpikeRateEstimator::size_type n_channels, const sre::SpikeRateEstimator::size_type n_units)
- {
- if (mp_sre)
- {
- m_console->debug("CereConn::fillSpikeRateEstimatorChannelUnitList: change channel unit map");
-
- mp_sre->fillChannelUnitList(n_channels, n_units);
- }
- else
- {
- m_console->warn("CereConn::fillSpikeRateEstimatorChannelUnitList: spike rate estimator not initialised");
- }
- }
- std::pair<sre::SpikeRateEstimator::ch_un_list_type, sre::SpikeRateEstimator::ch_un_map_type> CereConn::getSpikeRateEstimatorChannelUnitMapping() const
- {
- if (mp_sre)
- {
- return mp_sre->getChannelUnitMapping();
- }
- else
- {
- m_console->warn("CereConn::getSpikeRateEstimatorChannelUnitMapping: spike rate estimator not initialised");
- return std::make_pair<sre::SpikeRateEstimator::ch_un_list_type, sre::SpikeRateEstimator::ch_un_map_type>({},{});
- }
- }
- sre::SpikeRateEstimator::ch_un_list_type CereConn::getSpikeRateEstimatorChannelUnitList() const
- {
- if (mp_sre)
- {
- return mp_sre->getChannelUnitList();
- }
- else
- {
- m_console->warn("CereConn::getSpikeRateEstimatorChannelUnitList: spike rate estimator not initialised");
- return sre::SpikeRateEstimator::ch_un_list_type({});
- }
- }
- void CereConn::setSpikeRateEstimatorLoopInterval(const sre::SpikeRateEstimator::rate_interval_type & new_interval)
- {
- if (mp_sre)
- {
- mp_sre->setSpikeRateLoopInterval(new_interval);
- }
- }
- sre::SpikeRateEstimator::rate_interval_type CereConn::getSpikeRateEstimatorLoopInterval() const
- {
- if (mp_sre)
- {
- return mp_sre->getSpikeRateLoopInterval();
- }
- else
- {
- return sre::SpikeRateEstimator::rate_interval_type{0};
- }
- }
- void CereConn::setSpikeRateEstimatorLoopIntervalMS(const unsigned int & new_interval)
- {
- if (mp_sre)
- {
- std::chrono::milliseconds new_interval_ms{new_interval};
- mp_sre->setSpikeRateLoopInterval(std::chrono::duration_cast<sre::SpikeRateEstimator::rate_interval_type>(new_interval_ms));
- }
- }
- unsigned int CereConn::getSpikeRateEstimatorLoopIntervalMS() const
- {
- if (mp_sre)
- {
- return std::chrono::duration_cast<std::chrono::milliseconds>(mp_sre->getSpikeRateLoopInterval()).count();
- }
- else
- {
- return 0;
- }
- }
- void CereConn::bindSpikeRateEstimatorCallback(const sre::SpikeRateEstimator::rate_callback_type& rcb)
- {
- if (mp_sre)
- {
- mp_sre->bindCallback(rcb);
- }
- }
- void CereConn::spikeRateEstimatorId()
- {
- const sre::SpikeRateEstimator::rate_callback_type rcb = [](const sre::SpikeRateEstimator::unit_hist_type& uh){ return r_estimate_id_w_cont(uh);};
- bindSpikeRateEstimatorCallback(rcb);
- }
- void CereConn::spikeRateEstimatorBoxcar(const size_t length)
- {
- const sre::SpikeRateEstimator::rate_callback_type rcb = [length](const sre::SpikeRateEstimator::unit_hist_type& uh){ return r_estimate_with_boxcar_w_cont(uh, length);};
- bindSpikeRateEstimatorCallback(rcb);
- }
- void CereConn::spikeRateEstimatorExp(const double decay_factor, const size_t max_length)
- {
- const sre::SpikeRateEstimator::rate_callback_type rcb = [decay_factor, max_length](const sre::SpikeRateEstimator::unit_hist_type& uh){ return r_estimate_with_exp_decay_w_cont(uh, decay_factor, max_length);};
- bindSpikeRateEstimatorCallback(rcb);
- }
- CereConn::ReturnCode CereConn::getSpikeRateData(sre::SpikeRateEstimator::rate_list_type &srl, uint32_t &cbTime)
- {
- size_t oc;
- return getSpikeRateData(srl, cbTime, oc);
- }
- CereConn::ReturnCode CereConn::getSpikeRateData(sre::SpikeRateEstimator::rate_list_type &srl, uint32_t &cbTime, size_t &overflowCount)
- {
- if (m_state != State::Recording)
- {
- m_console->warn("CereConn::getSpikeRateData called while not recording.");
- return ReturnCode::NotRecording;
- }
- if (!mp_rateRB)
- {
- m_console->warn("CereConn::getSpikeRateData has no spike rate buffer.");
- return ReturnCode::InvalidSpikeRateBuffer;
- }
- if (!mp_sre)
- {
- m_console->warn("CereConn::getSpikeRateData: no Spike Rate Estimator present.");
- return ReturnCode::InvalidSpikeRateEstimator;
- }
- if (mp_sre->ringBufferInvalid())
- {
- m_console->warn("CereConn::getSpikeRateData: spike rate buffer is invalid.");
- return ReturnCode::InvalidSpikeRateBuffer;
- }
- if (mp_rateRB->wasEmpty())
- {
- m_console->debug("spike rate ring buffer estimated empty");
- }
- mp_rateRB->consume(srl, overflowCount);
-
- cbSdkResult res;
- res = cbSdkGetTime(m_instance, &cbTime);
- if (res != 0)
- {
- m_acq->error("cbSdkGetTime returned {}", res);
- return ReturnCode::CbSdkError;
- }
- return ReturnCode::Success;
- }
- void CereConn::spikeBandPowerEstimatorSetUp()
- {
- using namespace std::literals;
-
- mp_sbpe = std::make_unique<sbpe::SpikeBandPowerEstimator>(constants::MaxFEChannels, 50ms);
- if (mp_sbpe)
- {
- mp_sbpe->setLogger(m_console);
- if (mp_sbpRB)
- {
- mp_sbpe->attachSpikeBandPowerRB(mp_sbpRB);
- }
- mp_sbpe->bindTimestampCallback([this](){Timestamp_t cbTime = 0; cbSdkGetTime(m_instance, &cbTime); return cbTime;});
- }
- }
- void CereConn::spikeBandPowerEstimatorStart()
- {
- if (mp_sbpe)
- {
- m_console->debug("Starting SpikeBandPowerEstimator");
- mp_sbpe->reset(m_sgroup_chlist[mp_sbpe->getAcceptedSampleGroup() - 1]);
- mp_sbpe->signalStart();
- }
- else
- {
- m_console->warn("CereConn::spikeBandPowerEstimatorStart: spike band power estimator not initialised");
- }
- }
- void CereConn::spikeBandPowerEstimatorStop()
- {
- if (mp_sbpe)
- {
- m_console->debug("Stopping SpikeBandPowerEstimator");
- mp_sbpe->signalStop();
- }
- else
- {
- m_console->warn("CereConn::spikeBandPowerEstimatorStop: spike band power estimator not initialised");
- }
- }
- void CereConn::setSpikeBandPowerEstimatorChannelList(const sbpe::SpikeBandPowerEstimator::ch_list_type & ch_list)
- {
- if (mp_sbpe)
- {
- m_console->debug("CereConn::setSpikeBandPowerEstimatorChannelList: change channel map");
- mp_sbpe->setChannelList(ch_list);
- }
- else
- {
- m_console->warn("CereConn::setSpikeBandPowerEstimatorChannelList: spike band power estimator not initialised");
- }
- }
- void CereConn::fillSpikeBandPowerEstimatorChannelList(const sbpe::SpikeBandPowerEstimator::size_type n_channels)
- {
- if (mp_sbpe)
- {
- mp_sbpe->fillChannelList(n_channels);
- }
- }
- std::pair<sbpe::SpikeBandPowerEstimator::ch_list_type, sbpe::SpikeBandPowerEstimator::ch_map_type> CereConn::getSpikeBandPowerEstimatorChannelMapping() const
- {
- if (mp_sbpe)
- {
- return mp_sbpe->getChannelMapping();
- }
- else
- {
- m_console->warn("CereConn::getSpikeBandPowerEstimatorChannelMapping: spike band power estimator not initialised");
- return std::make_pair<sbpe::SpikeBandPowerEstimator::ch_list_type, sbpe::SpikeBandPowerEstimator::ch_map_type>({},{});
- }
- }
- sbpe::SpikeBandPowerEstimator::ch_list_type CereConn::getSpikeBandPowerEstimatorChannelList() const
- {
- if (mp_sbpe)
- {
- return mp_sbpe->getChannelList();
- }
- else
- {
- m_console->warn("CereConn::getSpikeBandPowerEstimatorChannelList: spike band power estimator not initialised");
- return sbpe::SpikeBandPowerEstimator::ch_list_type({});
- }
- }
- void CereConn::setSpikeBandPowerEstimatorLoopInterval(const sbpe::SpikeBandPowerEstimator::sbp_interval_type & new_interval)
- {
- if (mp_sbpe)
- {
- mp_sbpe->setLoopInterval(new_interval);
- }
- }
- sbpe::SpikeBandPowerEstimator::sbp_interval_type CereConn::getSpikeBandPowerEstimatorLoopInterval() const
- {
- if (mp_sbpe)
- {
- return mp_sbpe->getLoopInterval();
- }
- else
- {
- return sbpe::SpikeBandPowerEstimator::sbp_interval_type{0};
- }
- }
- void CereConn::setSpikeBandPowerEstimatorLoopIntervalMS(const unsigned int & new_interval)
- {
- if (mp_sre)
- {
- std::chrono::milliseconds new_interval_ms{new_interval};
- mp_sbpe->setLoopInterval(std::chrono::duration_cast<sre::SpikeRateEstimator::rate_interval_type>(new_interval_ms));
- }
- }
- unsigned int CereConn::getSpikeBandPowerEstimatorLoopIntervalMS() const
- {
- if (mp_sbpe)
- {
- return std::chrono::duration_cast<std::chrono::milliseconds>(mp_sbpe->getLoopInterval()).count();
- }
- else
- {
- return 0;
- }
- }
- void CereConn::setSpikeBandPowerEstimatorAcceptedSampleGroup(const size_t group)
- {
- if (mp_sbpe)
- {
- mp_sbpe->setAcceptedSampleGroup(group);
- }
- }
- size_t CereConn::getSpikeBandPowerEstimatorAcceptedSampleGroup() const
- {
- if (mp_sbpe)
- {
- return mp_sbpe->getAcceptedSampleGroup();
- }
- else
- {
- return 0;
- }
- }
- void CereConn::setSpikeBandPowerEstimatorIIRFilterNSamples(const size_t n_samples)
- {
- if (mp_sbpe)
- {
- mp_sbpe->setIIRFilterNSamples(n_samples);
- }
- }
- size_t CereConn::getSpikeBandPowerEstimatorIIRFilterNSamples() const
- {
- if (mp_sbpe)
- {
- return mp_sbpe->getIIRFilterNSamples();
- }
- else
- {
- return 0;
- }
- }
- void CereConn::setSpikeBandPowerEstimatorAvgNBins(const size_t n_bins)
- {
- if (mp_sbpe)
- {
- mp_sbpe->setRMSNBins(n_bins);
- }
- }
- size_t CereConn::getSpikeBandPowerEstimatorAvgNBins() const
- {
- if (mp_sbpe)
- {
- return mp_sbpe->getRMSNBins();
- }
- else
- {
- return 0;
- }
- }
- void CereConn::setSpikeBandPowerEstimatorIIRFilterCoeffs(const sbpe::SpikeBandPowerEstimator::iir_filt_coeff_type &b, const sbpe::SpikeBandPowerEstimator::iir_filt_coeff_type &a)
- {
- if (mp_sbpe)
- {
- mp_sbpe->setIIRFilterCoeffs(b, a);
- }
- }
- std::pair<sbpe::SpikeBandPowerEstimator::iir_filt_coeff_type, sbpe::SpikeBandPowerEstimator::iir_filt_coeff_type> CereConn::getSpikeBandPowerEstimatorIIRFilterCoeffs() const
- {
- if (mp_sbpe)
- {
- return mp_sbpe->getIIRFilterCoeffs();
- }
- else
- {
- return std::make_pair<>(sbpe::SpikeBandPowerEstimator::iir_filt_coeff_type(), sbpe::SpikeBandPowerEstimator::iir_filt_coeff_type());
- }
- }
- CereConn::ReturnCode CereConn::getSpikeBandPowerData(sbpe::SpikeBandPowerEstimator::sbp_list_type &sbpl, uint32_t &cbTime)
- {
- size_t overflowCount;
- return getSpikeBandPowerData(sbpl, cbTime, overflowCount);
- }
- CereConn::ReturnCode CereConn::getSpikeBandPowerData(sbpe::SpikeBandPowerEstimator::sbp_list_type &sbpl, uint32_t &cbTime, size_t &overflowCount)
- {
- if (m_state != State::Recording)
- {
- m_console->warn("CereConn::getSpikeBandPowerData called while not recording.");
- return ReturnCode::NotRecording;
- }
- if (!mp_sbpRB)
- {
- m_console->warn("CereConn::getSpikeBandPowerData has no spike band power buffer.");
- return ReturnCode::InvalidSpikeBandPowerBuffer;
- }
- if (!mp_sbpe)
- {
- m_console->warn("CereConn::getSpikeBandPowerData: no Spike Band Power Estimator present.");
- return ReturnCode::InvalidSpikeBandPowerEstimator;
- }
- if (mp_sbpe->ringBufferInvalid())
- {
- m_console->warn("CereConn::getSpikeBandPowerData: spike band power buffer is invalid.");
- return ReturnCode::InvalidSpikeBandPowerBuffer;
- }
- mp_sbpRB->consume(sbpl, overflowCount);
-
- cbSdkResult res;
- res = cbSdkGetTime(m_instance, &cbTime);
- if (res != 0)
- {
- m_acq->error("cbSdkGetTime returned {}", res);
- return ReturnCode::CbSdkError;
- }
- return ReturnCode::Success;
- }
- void CereConn::cbSdkCallbackContinuous(uint32_t nInstance, const cbSdkPktType type, const void* pPkt)
- {
- cbPKT_GROUP * pPktSgrp = (cbPKT_GROUP *) pPkt;
- const uint32_t group = pPktSgrp->type;
- if (mp_sbpe)
- {
- mp_sbpe->addSamplesFromPacket(pPktSgrp);
- }
- // ignore if group ignored
- if (!m_sample_groups_enabled[group - 1])
- {
- return;
- }
- m_pRb->addSamplesFromPacket(pPktSgrp);
- }
- void CereConn::cbSdkCallbackContinuous(uint32_t nInstance, const cbSdkPktType type, const void* pPkt, void* pCallbackData)
- {
- CereConn *me = reinterpret_cast<CereConn*>(pCallbackData);
- me->cbSdkCallbackContinuous(nInstance, type, pPkt);
- }
- void CereConn::cbSdkCallbackSpike(uint32_t nInstance, const cbSdkPktType type, const void* pPkt)
- {
- const cbPKT_SPK * pSpk = (const cbPKT_SPK *) pPkt;
- SpikeRingBuffer::BufType spk(*pSpk);
- m_pSRb->push(spk);
- if (mp_sre)
- {
- mp_sre->addSpike(pSpk->chid, pSpk->unit);
- }
- m_acq->debug("pkt time: {}, chid: {}, unit: {}", pSpk->time, pSpk->chid, pSpk->unit);
- }
- void CereConn::cbSdkCallbackSpike(uint32_t nInstance, const cbSdkPktType type, const void* pPkt, void* pCallbackData)
- {
- CereConn *me = reinterpret_cast<CereConn*>(pCallbackData);
- me->cbSdkCallbackSpike(nInstance, type, pPkt);
- }
- void CereConn::cbSdkCallbackComment(uint32_t nInstance, const cbSdkPktType type, const void* pPkt)
- {
- const cbPKT_COMMENT * pCmt = (const cbPKT_COMMENT *) pPkt;
- CommentRingBuffer::BufType comment(*pCmt);
- // m_acq->debug("received comment: time: {}, comment: {}, data: {}", comment.timestamp, comment.comment, comment.data);
-
- m_pCRb->push(comment);
- }
- void CereConn::cbSdkCallbackComment(uint32_t nInstance, const cbSdkPktType type, const void* pPkt, void* pCallbackData)
- {
- CereConn *me = reinterpret_cast<CereConn*>(pCallbackData);
- me->cbSdkCallbackComment(nInstance, type, pPkt);
- }
- void CereConn::cbSdkCallbackDigInEv(uint32_t nInstance, const cbSdkPktType type, const void* pPkt)
- {
- const cbPKT_DINP * pDIE = (const cbPKT_DINP *) pPkt;
- DigInEvRingBuffer::BufType digInEv(*pDIE);
- m_pDIRb->push(digInEv);
- }
- void CereConn::cbSdkCallbackDigInEv(uint32_t nInstance, const cbSdkPktType type, const void* pPkt, void* pCallbackData)
- {
- CereConn *me = reinterpret_cast<CereConn*>(pCallbackData);
- me->cbSdkCallbackDigInEv(nInstance, type, pPkt);
- }
- void CereConn::cbSdkCallbackGroupInfo(uint32_t nInstance, const cbSdkPktType type, const void* pPkt)
- {
- const cbPKT_GROUPINFO * pGI = (const cbPKT_GROUPINFO *) pPkt;
-
- updateGroupChannelList(pGI->group);
-
- m_acq->info("Group Info Callback called, group {} changed", pGI->group);
- }
- void CereConn::cbSdkCallbackGroupInfo(uint32_t nInstance, const cbSdkPktType type, const void* pPkt, void* pCallbackData)
- {
- CereConn *me = reinterpret_cast<CereConn*>(pCallbackData);
- me->cbSdkCallbackGroupInfo(nInstance, type, pPkt);
- }
- void CereConn::updateGroupChannelList(const uint32_t group)
- {
- uint32_t length;
- const uint32_t group0 = group - 1;
-
- m_sgroup_changed[group0] = true;
-
- cbSdkGetSampleGroupInfo(m_instance, 1, group, nullptr, nullptr, &length);
- m_sgroup_chlist[group0].resize(length);
- cbSdkGetSampleGroupList(m_instance, 1, group, nullptr, m_sgroup_chlist[group0].data());
-
- m_pRb->reset(group, m_sgroup_chlist[group0]);
- if (mp_sbpe)
- {
- mp_sbpe->reset(group, m_sgroup_chlist[group0]);
- }
- std::ostringstream oss;
- std::for_each(m_sgroup_chlist[group0].cbegin(), m_sgroup_chlist[group0].cend(), [&oss](auto x){oss << x << ", ";} );
- m_acq->debug("Channel ID list for sampling group {}: [{}]", group, oss.str());
- }
- void CereConn::updateGroupChannelLists()
- {
- for (uint32_t i = 1; i <= cc::constants::NSampleGroups; ++i)
- {
- updateGroupChannelList(i);
- }
- }
- } // namespace cc
|