155 lines
4.8 KiB
C++
155 lines
4.8 KiB
C++
#include "pch.h"
|
|
#include "XYParserApi.h"
|
|
|
|
#include "XYEegParser8.h"
|
|
#include "XYEegParser64.h"
|
|
|
|
#include <algorithm>
|
|
#include <new>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
namespace {
|
|
|
|
struct ParserContext {
|
|
std::uint8_t channel_count = 0;
|
|
XYEegParser8 parser8;
|
|
XYEegParser64 parser64;
|
|
std::string last_error;
|
|
};
|
|
|
|
void FillSummary(const XYEegFrame8& frame, XYParserFrameSummary& summary)
|
|
{
|
|
summary.frame_index = frame.index;
|
|
summary.channel_count = frame.channel_count;
|
|
summary.battery = frame.battery;
|
|
summary.sample_count = static_cast<std::uint8_t>(frame.samples.size());
|
|
for (std::size_t sample_index = 0; sample_index < XYPARSER_SAMPLES_PER_FRAME; ++sample_index) {
|
|
summary.trigger_types[sample_index] = frame.samples[sample_index].trigger_type;
|
|
summary.trigger_indices[sample_index] = frame.samples[sample_index].trigger_index;
|
|
for (std::size_t channel_index = 0; channel_index < XYPARSER_MAX_CHANNELS; ++channel_index) {
|
|
summary.channel_values_uv[sample_index][channel_index] =
|
|
channel_index < frame.channel_count
|
|
? frame.samples[sample_index].channel_values_uv[channel_index]
|
|
: 0.0;
|
|
}
|
|
}
|
|
}
|
|
|
|
void FillSummary(const XYEegFrame64& frame, XYParserFrameSummary& summary)
|
|
{
|
|
summary.frame_index = frame.index;
|
|
summary.channel_count = frame.channel_count;
|
|
summary.battery = frame.battery;
|
|
summary.sample_count = static_cast<std::uint8_t>(frame.samples.size());
|
|
for (std::size_t sample_index = 0; sample_index < XYPARSER_SAMPLES_PER_FRAME; ++sample_index) {
|
|
summary.trigger_types[sample_index] = frame.samples[sample_index].trigger_type;
|
|
summary.trigger_indices[sample_index] = frame.samples[sample_index].trigger_index;
|
|
for (std::size_t channel_index = 0; channel_index < XYPARSER_MAX_CHANNELS; ++channel_index) {
|
|
summary.channel_values_uv[sample_index][channel_index] =
|
|
channel_index < frame.channel_count
|
|
? frame.samples[sample_index].channel_values_uv[channel_index]
|
|
: 0.0;
|
|
}
|
|
}
|
|
}
|
|
|
|
} // namespace
|
|
|
|
extern "C" {
|
|
|
|
XYParserHandle XYParser_CreateParser(std::uint8_t channel_count)
|
|
{
|
|
if (channel_count != 8 && channel_count != 64) {
|
|
return nullptr;
|
|
}
|
|
|
|
ParserContext* context = new (std::nothrow) ParserContext();
|
|
if (context == nullptr) {
|
|
return nullptr;
|
|
}
|
|
|
|
context->channel_count = channel_count;
|
|
return context;
|
|
}
|
|
|
|
void XYParser_DestroyParser(XYParserHandle handle)
|
|
{
|
|
ParserContext* context = static_cast<ParserContext*>(handle);
|
|
delete context;
|
|
}
|
|
|
|
void XYParser_SetAdcParams(XYParserHandle handle, double vref, double gain)
|
|
{
|
|
ParserContext* context = static_cast<ParserContext*>(handle);
|
|
if (context == nullptr) {
|
|
return;
|
|
}
|
|
|
|
if (context->channel_count == 8) {
|
|
context->parser8.SetAdcParams(vref, gain);
|
|
} else {
|
|
context->parser64.SetAdcParams(vref, gain);
|
|
}
|
|
}
|
|
|
|
void XYParser_SetBypassChecksum(XYParserHandle handle, int bypass)
|
|
{
|
|
ParserContext* context = static_cast<ParserContext*>(handle);
|
|
if (context == nullptr) {
|
|
return;
|
|
}
|
|
|
|
const bool enabled = bypass != 0;
|
|
if (context->channel_count == 8) {
|
|
context->parser8.SetBypassChecksum(enabled);
|
|
} else {
|
|
context->parser64.SetBypassChecksum(enabled);
|
|
}
|
|
}
|
|
|
|
int XYParser_Feed(XYParserHandle handle,
|
|
const std::uint8_t* data,
|
|
std::size_t size,
|
|
XYParserFrameSummary* out_summaries,
|
|
int max_summaries)
|
|
{
|
|
ParserContext* context = static_cast<ParserContext*>(handle);
|
|
if (context == nullptr || data == nullptr || size == 0) {
|
|
return 0;
|
|
}
|
|
|
|
if (max_summaries < 0) {
|
|
max_summaries = 0;
|
|
}
|
|
|
|
if (context->channel_count == 8) {
|
|
const std::vector<XYEegFrame8> frames = context->parser8.Feed(data, size);
|
|
context->last_error = context->parser8.LastError();
|
|
const int write_count = std::min<int>(static_cast<int>(frames.size()), max_summaries);
|
|
for (int i = 0; i < write_count; ++i) {
|
|
FillSummary(frames[static_cast<std::size_t>(i)], out_summaries[i]);
|
|
}
|
|
return write_count;
|
|
}
|
|
|
|
const std::vector<XYEegFrame64> frames = context->parser64.Feed(data, size);
|
|
context->last_error = context->parser64.LastError();
|
|
const int write_count = std::min<int>(static_cast<int>(frames.size()), max_summaries);
|
|
for (int i = 0; i < write_count; ++i) {
|
|
FillSummary(frames[static_cast<std::size_t>(i)], out_summaries[i]);
|
|
}
|
|
return write_count;
|
|
}
|
|
|
|
const char* XYParser_GetLastError(XYParserHandle handle)
|
|
{
|
|
ParserContext* context = static_cast<ParserContext*>(handle);
|
|
if (context == nullptr) {
|
|
return "invalid parser handle";
|
|
}
|
|
return context->last_error.c_str();
|
|
}
|
|
|
|
}
|