Skip to content

Commit 1b60b98

Browse files
authored
LibMCCore (scanlab, libmcenv): Fix microvector delay tick conversion and implement scatterplot channel fill (#68)
### feat(scanlab): convert microvector laser delays using RTC tick resolution - Added `ConvertDelaySecondsToTicks()` to convert delay seconds into RTC ticks (1 tick = 1/64 µs) and clamp to the supported range [0..32767]. - Updated `AddMicrovectorMovement()` to use the new conversion for LaserOnDelay and LaserOffDelay while preserving `-1` as the “no delay” sentinel. ### feat(libmcenv): implement scatterplot channel population from datatable - Implemented `fillScatterplotChannel()` to populate scatterplot channel/column vectors from the datatable rows with scale and offset applied. - Added basic validation and guarded channel/column creation to avoid duplicate entries. Signed-off-by: Yury Rodzikau <y.rodzikau@c1-technologies.com>
1 parent cb0b541 commit 1b60b98

3 files changed

Lines changed: 41 additions & 5 deletions

File tree

Drivers/ScanLab/Implementation/libmcdriver_scanlab_rtccontext.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1114,6 +1114,15 @@ void CRTCContext::AddMarkMovement(const LibMCDriver_ScanLab_double dTargetX, con
11141114
m_nCurrentScanPositionY = intY;
11151115
}
11161116

1117+
int32_t CRTCContext::ConvertDelaySecondsToTicks(double delay)
1118+
{
1119+
// 1 tick = 1/64 us = 1e-6 / 64 s
1120+
// ticks = delay / (1e-6/64) = delay * 64e6
1121+
const int64_t ticks = static_cast<int64_t>(std::llround(delay * 64.0e6));
1122+
1123+
// Clamp to [0 .. 32767]
1124+
return static_cast<int32_t>( (ticks < 0) ? 0 : (ticks > 32767) ? 32767 : ticks );
1125+
}
11171126

11181127
void CRTCContext::AddMicrovectorMovement(const LibMCDriver_ScanLab_uint64 nMicrovectorArrayBufferSize, const LibMCDriver_ScanLab::sMicroVector* pMicrovectorArrayBuffer)
11191128
{
@@ -1131,9 +1140,8 @@ void CRTCContext::AddMicrovectorMovement(const LibMCDriver_ScanLab_uint64 nMicro
11311140

11321141
int32_t intX = (int32_t)dX;
11331142
int32_t intY = (int32_t)dY;
1134-
1135-
int32_t intDelayLaserOn = (pMicroVector->m_LaserOnDelay < 0.0) ? -1 : round(pMicroVector->m_LaserOnDelay * 100000);
1136-
int32_t intDelayLaserOff = (pMicroVector->m_LaserOffDelay < 0.0) ? -1 : round(pMicroVector->m_LaserOffDelay * 100000);
1143+
int32_t intDelayLaserOn = (pMicroVector->m_LaserOnDelay < 0.0) ? -1 : ConvertDelaySecondsToTicks(pMicroVector->m_LaserOnDelay);
1144+
int32_t intDelayLaserOff = (pMicroVector->m_LaserOffDelay < 0.0) ? -1 : ConvertDelaySecondsToTicks(pMicroVector->m_LaserOffDelay);
11371145

11381146
m_pScanLabSDK->n_micro_vector_abs(m_CardNo, intX, intY, intDelayLaserOn, intDelayLaserOff);
11391147

Drivers/ScanLab/Implementation/libmcdriver_scanlab_rtccontext.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,9 @@ class CRTCContext : public virtual IRTCContext, public virtual CBase {
213213
// Calls the SetTriggerX Call that is necessary for the specific OIE board
214214
void callSetTriggerOIE(uint32_t nPeriod);
215215

216+
// Converts a delay in seconds to RTC ticks
217+
int32_t ConvertDelaySecondsToTicks(double delay);
218+
216219
public:
217220

218221
CRTCContext(PRTCContextOwnerData pOwnerData, uint32_t nCardNo, bool bIsNetwork, LibMCEnv::PDriverEnvironment pDriverEnvironment);

Implementation/LibMCEnv/libmcenv_datatable.cpp

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -841,9 +841,34 @@ class CDataTableColumn_Int32 : public CDataTableColumn
841841

842842
void fillScatterplotChannel(AMC::CScatterplot* pScatterplot, const std::string& sChannel, const std::string& sColumn, double dScaleFactor, double dOffset) override
843843
{
844-
throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_NOTIMPLEMENTED);
845-
}
844+
if (pScatterplot == nullptr)
845+
throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDPARAM);
846846

847+
auto& channelEntries = pScatterplot->getChannelEntries();
848+
auto channelIter = channelEntries.find(sChannel);
849+
850+
if (channelIter == channelEntries.end()) {
851+
channelEntries[sChannel][sColumn] = std::vector<double>();
852+
}
853+
else {
854+
auto& columnEntries = channelIter->second;
855+
856+
if (columnEntries.find(sColumn) == columnEntries.end())
857+
columnEntries[sColumn] = std::vector<double>();
858+
else {
859+
std::string sException = "The channel = " + sChannel + " with the column = " + sColumn + " already exists";
860+
throw std::runtime_error(sException.c_str());
861+
}
862+
}
863+
864+
auto& vecColumn = channelEntries[sChannel][sColumn];
865+
866+
vecColumn.resize(m_Rows.size());
867+
868+
for (size_t nIndex = 0; nIndex < m_Rows.size(); nIndex++) {
869+
vecColumn[nIndex] = (double)m_Rows.at(nIndex) * dScaleFactor + dOffset;
870+
}
871+
}
847872
};
848873

849874

0 commit comments

Comments
 (0)