@@ -87,15 +87,16 @@ void CRaylaseCoordinateTransform::applyTransform(double& dX, double& dY)
8787}
8888
8989
90- CRaylaseCardList::CRaylaseCardList (PRaylaseSDK pSDK, rlHandle cardHandle, double dMaxLaserPowerInWatts, PRaylaseCoordinateTransform pCoordinateTransform, const std::map<std::string, ePartSuppressionMode>& partSuppressions, PNLightDriverImpl pNLightBoardImpl)
90+ CRaylaseCardList::CRaylaseCardList (PRaylaseSDK pSDK, rlHandle cardHandle, double dMaxLaserPowerInWatts, PRaylaseCoordinateTransform pCoordinateTransform, const std::map<std::string, ePartSuppressionMode>& partSuppressions, PNLightDriverImpl pNLightBoardImpl, PRaylaseCardIOCycleMapping pIOCycleMapping )
9191 : m_pSDK(pSDK),
9292 m_ListHandle(0 ),
9393 m_CardHandle(cardHandle),
9494 m_dMaxLaserPowerInWatts_Mode0(dMaxLaserPowerInWatts),
9595 m_nListIDOnCard (RAYLASE_LISTONCARDNOTSET ),
9696 m_pCoordinateTransform (pCoordinateTransform),
9797 m_PartSuppressions (partSuppressions),
98- m_pNLightBoardImpl (pNLightBoardImpl)
98+ m_pNLightBoardImpl (pNLightBoardImpl),
99+ m_pIOCycleMapping (pIOCycleMapping)
99100
100101{
101102 if (pSDK.get () == nullptr )
@@ -165,6 +166,16 @@ void CRaylaseCardList::addLayerToList(LibMCEnv::PToolpathLayer pLayer, uint32_t
165166
166167 double dUnits = pLayer->GetUnits ();
167168
169+ // Check if pre/post cycle attributes are present
170+ uint32_t nPreCycleAttributeID = 0 ;
171+ if (pLayer->HasCustomSegmentAttribute (" http://schemas.raylase.com/iocontrol/2026/01" , " precycleid" ))
172+ nPreCycleAttributeID = pLayer->FindCustomSegmentAttributeID (" http://schemas.raylase.com/iocontrol/2026/01" , " precycleid" );
173+
174+ uint32_t nPostCycleAttributeID = 0 ;
175+ if (pLayer->HasCustomSegmentAttribute (" http://schemas.raylase.com/iocontrol/2026/01" , " postcycleid" ))
176+ nPostCycleAttributeID = pLayer->FindCustomSegmentAttributeID (" http://schemas.raylase.com/iocontrol/2026/01" , " postcycleid" );
177+
178+
168179 m_pSDK->checkError (m_pSDK->rlListAppendLaserOff (m_ListHandle), " rlListAppendLaserOff" );
169180
170181 uint32_t nSegmentCount = pLayer->GetSegmentCount ();
@@ -196,6 +207,16 @@ void CRaylaseCardList::addLayerToList(LibMCEnv::PToolpathLayer pLayer, uint32_t
196207 bDrawSegment = false ;
197208 }
198209
210+
211+ // Check for pre/postcycles to execute.
212+ int64_t nPreCycleID = 0 ;
213+ if (nPreCycleAttributeID != 0 )
214+ nPreCycleID = pLayer->GetSegmentIntegerAttribute (nSegmentIndex, nPreCycleAttributeID);
215+
216+ int64_t nPostCycleID = 0 ;
217+ if (nPostCycleAttributeID != 0 )
218+ nPostCycleID = pLayer->GetSegmentIntegerAttribute (nSegmentIndex, nPostCycleAttributeID);
219+
199220 // Check if part is not to be ignored
200221 std::string sSegmentPartUUID = pLayer->GetSegmentPartUUID (nSegmentIndex);
201222 ePartSuppressionMode suppressionMode = getPartSuppressionMode (sSegmentPartUUID );
@@ -230,6 +251,17 @@ void CRaylaseCardList::addLayerToList(LibMCEnv::PToolpathLayer pLayer, uint32_t
230251 }
231252
232253 }
254+
255+
256+ // Execute pre-cycle if specified
257+ if (nPreCycleID != 0 ) {
258+ if (m_pIOCycleMapping.get () == nullptr )
259+ throw ELibMCDriver_RaylaseInterfaceException (LIBMCDRIVER_RAYLASE_ERROR_IOCYCLENOTFOUND , " Pre-cycle ID " + std::to_string (nPreCycleID) + " specified but no IO cycle mapping available" );
260+ if (!m_pIOCycleMapping->ioCycleExists ((uint32_t )nPreCycleID))
261+ throw ELibMCDriver_RaylaseInterfaceException (LIBMCDRIVER_RAYLASE_ERROR_IOCYCLENOTFOUND , " Pre-cycle ID " + std::to_string (nPreCycleID) + " not found" );
262+ auto pPreCycle = m_pIOCycleMapping->getIOCycle ((uint32_t )nPreCycleID);
263+ executeIOCycle (pPreCycle);
264+ }
233265
234266
235267 double dJumpSpeedInMeterPerSecond = dJumpSpeedInMMPerSecond * 0.001 ;
@@ -345,6 +377,16 @@ void CRaylaseCardList::addLayerToList(LibMCEnv::PToolpathLayer pLayer, uint32_t
345377
346378 }
347379
380+ // Execute post-cycle if specified
381+ if (nPostCycleID != 0 ) {
382+ if (m_pIOCycleMapping.get () == nullptr )
383+ throw ELibMCDriver_RaylaseInterfaceException (LIBMCDRIVER_RAYLASE_ERROR_IOCYCLENOTFOUND , " Post-cycle ID " + std::to_string (nPostCycleID) + " specified but no IO cycle mapping available" );
384+ if (!m_pIOCycleMapping->ioCycleExists ((uint32_t )nPostCycleID))
385+ throw ELibMCDriver_RaylaseInterfaceException (LIBMCDRIVER_RAYLASE_ERROR_IOCYCLENOTFOUND , " Post-cycle ID " + std::to_string (nPostCycleID) + " not found" );
386+ auto pPostCycle = m_pIOCycleMapping->getIOCycle ((uint32_t )nPostCycleID);
387+ executeIOCycle (pPostCycle);
388+ }
389+
348390 }
349391
350392 }
@@ -430,3 +472,67 @@ LibMCDriver_Raylase::ePartSuppressionMode CRaylaseCardList::getPartSuppressionMo
430472}
431473
432474
475+ void CRaylaseCardList::executeIOCycle (PRaylaseIOCycleImpl pIOCycle)
476+ {
477+ if (pIOCycle.get () == nullptr )
478+ return ;
479+
480+ const auto & entries = pIOCycle->getEntries ();
481+ for (const auto & entry : entries) {
482+ switch (entry.m_EntryType ) {
483+ case eIOCycleEntryType::SignalOut:
484+ {
485+ // Convert LibMCDriver_Raylase::eIOPort to eRLIOPort
486+ eRLIOPort rlPort = eRLIOPort::ioPortA;
487+ switch (entry.m_IOPort ) {
488+ case eIOPort::PortA: rlPort = eRLIOPort::ioPortA; break ;
489+ case eIOPort::PortB: rlPort = eRLIOPort::ioPortB; break ;
490+ case eIOPort::PortC: rlPort = eRLIOPort::ioPortC; break ;
491+ case eIOPort::PortD: rlPort = eRLIOPort::ioPortD; break ;
492+ case eIOPort::PortE: rlPort = eRLIOPort::ioPortE; break ;
493+ default :
494+ throw ELibMCDriver_RaylaseInterfaceException (LIBMCDRIVER_RAYLASE_ERROR_INVALIDIOPORT );
495+ }
496+
497+ // Set the pin high using the pin mask
498+ uint32_t nPinMask = (1u << entry.m_nIOPin );
499+ m_pSDK->checkError (m_pSDK->rlListAppendGpioValue (m_ListHandle, rlPort, eRLPinAction::paSet, nPinMask), " rlListAppendGpioValue" );
500+ break ;
501+ }
502+
503+ case eIOCycleEntryType::WaitForSignal:
504+ {
505+ // Convert LibMCDriver_Raylase::eIOPort to eRLIOPort
506+ eRLIOPort rlPort = eRLIOPort::ioPortA;
507+ switch (entry.m_IOPort ) {
508+ case eIOPort::PortA: rlPort = eRLIOPort::ioPortA; break ;
509+ case eIOPort::PortB: rlPort = eRLIOPort::ioPortB; break ;
510+ case eIOPort::PortC: rlPort = eRLIOPort::ioPortC; break ;
511+ case eIOPort::PortD: rlPort = eRLIOPort::ioPortD; break ;
512+ case eIOPort::PortE: rlPort = eRLIOPort::ioPortE; break ;
513+ default :
514+ throw ELibMCDriver_RaylaseInterfaceException (LIBMCDRIVER_RAYLASE_ERROR_INVALIDIOPORT );
515+ }
516+
517+ // Wait for input signal on the specified pin
518+ uint32_t nPinMask = (1u << entry.m_nIOPin );
519+ int32_t nTimeoutInMicroseconds = (int32_t )entry.m_nTimeoutOrDelayInMicroseconds ;
520+ m_pSDK->checkError (m_pSDK->rlListAppendWaitForInput (m_ListHandle, nPinMask, rlPort, true , false , nPinMask, nTimeoutInMicroseconds), " rlListAppendWaitForInput" );
521+ break ;
522+ }
523+
524+ case eIOCycleEntryType::Delay:
525+ {
526+ // Delay is specified in microseconds, SDK expects seconds
527+ double dDelayInSeconds = (double )entry.m_nTimeoutOrDelayInMicroseconds / 1000000.0 ;
528+ m_pSDK->checkError (m_pSDK->rlListAppendSleep (m_ListHandle, dDelayInSeconds), " rlListAppendSleep" );
529+ break ;
530+ }
531+
532+ default :
533+ break ;
534+ }
535+ }
536+ }
537+
538+
0 commit comments