No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 
 
 
 

1537 líneas
55 KiB

  1. #include "plsr_job.h"
  2. #include "plc_device.h"
  3. #include "plsr_address_map.h"
  4. #include <limits.h>
  5. #include <string.h>
  6. #define PLSR_S0_HEADER_WORDS (10UL)
  7. #define PLSR_S0_SEGMENT_WORDS (10UL)
  8. #define PLSR_S1_WORDS (4UL)
  9. #define PLSR_SFD_AXIS_STRIDE (130U)
  10. #define PLSR_SFD_SET_OFFSET (50U)
  11. #define PLSR_S2_SET_WORDS (20U)
  12. #define PLSR_HSD_SET_BASE (460U)
  13. #define PLSR_TIMER_168MHZ (168000000UL)
  14. #define PLSR_TIMER_84MHZ (84000000UL)
  15. static void PlsrSetDetail(PLSR_PARSE_DETAIL *detail,
  16. PLSR_RESULT result,
  17. PLSR_PARSE_BLOCK block,
  18. uint32_t address,
  19. int32_t value,
  20. uint16_t segment)
  21. {
  22. if (detail != NULL)
  23. {
  24. detail->result = result;
  25. detail->block = block;
  26. detail->address = address;
  27. detail->value = value;
  28. detail->segment = segment;
  29. }
  30. }
  31. static uint8_t PlsrIsWordDevice(PLSR_DEVICE_TYPE device)
  32. {
  33. return ((device == PLSR_DEVICE_D) || (device == PLSR_DEVICE_HD)
  34. || (device == PLSR_DEVICE_FD))
  35. ? 1U
  36. : 0U;
  37. }
  38. static uint8_t PlsrSourceIsUsable(const PLSR_DATA_SOURCE *source)
  39. {
  40. return ((source != NULL) && (source->validateWords != NULL)
  41. && (source->readWord != NULL))
  42. ? 1U
  43. : 0U;
  44. }
  45. static PLSR_RESULT PlsrValidateRange(const PLSR_DATA_SOURCE *source,
  46. PLSR_DATA_REF reference,
  47. uint32_t wordCount,
  48. PLSR_PARSE_BLOCK block,
  49. PLSR_PARSE_DETAIL *detail)
  50. {
  51. uint64_t endAddress;
  52. if ((PlsrIsWordDevice(reference.device) == 0U) || (wordCount == 0UL))
  53. {
  54. PlsrSetDetail(detail,
  55. PLSR_RESULT_DATA_ACCESS,
  56. block,
  57. reference.address,
  58. (int32_t)reference.device,
  59. 0U);
  60. return PLSR_RESULT_DATA_ACCESS;
  61. }
  62. endAddress = (uint64_t)reference.address + (uint64_t)wordCount - 1ULL;
  63. if (endAddress > UINT32_MAX)
  64. {
  65. PlsrSetDetail(detail,
  66. PLSR_RESULT_ADDRESS_OVERFLOW,
  67. block,
  68. reference.address,
  69. (int32_t)wordCount,
  70. 0U);
  71. return PLSR_RESULT_ADDRESS_OVERFLOW;
  72. }
  73. if (source->validateWords(source->context,
  74. reference.device,
  75. reference.address,
  76. wordCount)
  77. == 0U)
  78. {
  79. PlsrSetDetail(detail,
  80. PLSR_RESULT_DATA_ACCESS,
  81. block,
  82. reference.address,
  83. (int32_t)wordCount,
  84. 0U);
  85. return PLSR_RESULT_DATA_ACCESS;
  86. }
  87. return PLSR_RESULT_OK;
  88. }
  89. static PLSR_RESULT PlsrReadWord(const PLSR_DATA_SOURCE *source,
  90. PLSR_DEVICE_TYPE device,
  91. uint32_t address,
  92. uint16_t *value,
  93. PLSR_PARSE_BLOCK block,
  94. uint16_t segment,
  95. PLSR_PARSE_DETAIL *detail)
  96. {
  97. if ((value == NULL)
  98. || (source->readWord(source->context, device, address, value) == 0U))
  99. {
  100. PlsrSetDetail(detail,
  101. PLSR_RESULT_DATA_ACCESS,
  102. block,
  103. address,
  104. 0,
  105. segment);
  106. return PLSR_RESULT_DATA_ACCESS;
  107. }
  108. return PLSR_RESULT_OK;
  109. }
  110. static PLSR_RESULT PlsrReadInt32(const PLSR_DATA_SOURCE *source,
  111. PLSR_DEVICE_TYPE device,
  112. uint32_t address,
  113. int32_t *value,
  114. PLSR_PARSE_BLOCK block,
  115. uint16_t segment,
  116. PLSR_PARSE_DETAIL *detail)
  117. {
  118. uint16_t lowWord;
  119. uint16_t highWord;
  120. PLSR_RESULT result;
  121. if (address == UINT32_MAX)
  122. {
  123. PlsrSetDetail(detail,
  124. PLSR_RESULT_ADDRESS_OVERFLOW,
  125. block,
  126. address,
  127. 2,
  128. segment);
  129. return PLSR_RESULT_ADDRESS_OVERFLOW;
  130. }
  131. if (source->readDword != NULL)
  132. {
  133. if (source->readDword(source->context,
  134. device,
  135. address,
  136. value) == 0U)
  137. {
  138. PlsrSetDetail(detail,
  139. PLSR_RESULT_DATA_ACCESS,
  140. block,
  141. address,
  142. 0,
  143. segment);
  144. return PLSR_RESULT_DATA_ACCESS;
  145. }
  146. return PLSR_RESULT_OK;
  147. }
  148. result = PlsrReadWord(source,
  149. device,
  150. address,
  151. &lowWord,
  152. block,
  153. segment,
  154. detail);
  155. if (result != PLSR_RESULT_OK)
  156. {
  157. return result;
  158. }
  159. result = PlsrReadWord(source,
  160. device,
  161. address + 1UL,
  162. &highWord,
  163. block,
  164. segment,
  165. detail);
  166. if (result != PLSR_RESULT_OK)
  167. {
  168. return result;
  169. }
  170. *value = (int32_t)(((uint32_t)highWord << 16U) | (uint32_t)lowWord);
  171. return PLSR_RESULT_OK;
  172. }
  173. static uint8_t PlsrBlocksOverlap(PLSR_DATA_REF first,
  174. uint32_t firstWords,
  175. PLSR_DATA_REF second,
  176. uint32_t secondWords)
  177. {
  178. uint64_t firstEnd;
  179. uint64_t secondEnd;
  180. if (first.device != second.device)
  181. {
  182. return 0U;
  183. }
  184. firstEnd = (uint64_t)first.address + (uint64_t)firstWords - 1ULL;
  185. secondEnd = (uint64_t)second.address + (uint64_t)secondWords - 1ULL;
  186. return (((uint64_t)first.address <= secondEnd)
  187. && ((uint64_t)second.address <= firstEnd))
  188. ? 1U
  189. : 0U;
  190. }
  191. static PLSR_RESULT PlsrReadFixedWord(uint8_t useHsd,
  192. uint16_t address,
  193. uint16_t *value,
  194. PLSR_PARSE_DETAIL *detail)
  195. {
  196. PLC_DEVICE_RESULT deviceResult;
  197. deviceResult = (useHsd != 0U) ? PlcDeviceReadHsd(address, value)
  198. : PlcDeviceReadSfd(address, value);
  199. if (deviceResult != PLC_DEVICE_OK)
  200. {
  201. PlsrSetDetail(detail,
  202. PLSR_RESULT_INVALID_S2,
  203. PLSR_PARSE_BLOCK_S2,
  204. address,
  205. 0,
  206. 0U);
  207. return PLSR_RESULT_INVALID_S2;
  208. }
  209. return PLSR_RESULT_OK;
  210. }
  211. static PLSR_RESULT PlsrReadFixedDword(uint8_t useHsd,
  212. uint16_t address,
  213. uint32_t *value,
  214. PLSR_PARSE_DETAIL *detail)
  215. {
  216. uint16_t lowWord;
  217. uint16_t highWord;
  218. PLSR_RESULT result;
  219. result = PlsrReadFixedWord(useHsd, address, &lowWord, detail);
  220. if (result != PLSR_RESULT_OK)
  221. {
  222. return result;
  223. }
  224. result = PlsrReadFixedWord(useHsd,
  225. (uint16_t)(address + 1U),
  226. &highWord,
  227. detail);
  228. if (result != PLSR_RESULT_OK)
  229. {
  230. return result;
  231. }
  232. *value = ((uint32_t)highWord << 16U) | (uint32_t)lowWord;
  233. return PLSR_RESULT_OK;
  234. }
  235. PLSR_RESULT PlsrCalculateTimerDivider(uint32_t timerClockHz,
  236. uint32_t frequencyHz,
  237. uint16_t *psc,
  238. uint16_t *arr)
  239. {
  240. uint64_t minimumDivider;
  241. uint64_t periodTicks;
  242. if ((timerClockHz == 0UL) || (frequencyHz == 0UL) || (psc == NULL)
  243. || (arr == NULL))
  244. {
  245. return PLSR_RESULT_INVALID_ARGUMENT;
  246. }
  247. minimumDivider = ((uint64_t)timerClockHz
  248. + ((uint64_t)frequencyHz * 65536ULL) - 1ULL)
  249. / ((uint64_t)frequencyHz * 65536ULL);
  250. if (minimumDivider == 0ULL)
  251. {
  252. minimumDivider = 1ULL;
  253. }
  254. if (minimumDivider > 65536ULL)
  255. {
  256. return PLSR_RESULT_DIVIDER_UNREPRESENTABLE;
  257. }
  258. periodTicks = ((uint64_t)timerClockHz
  259. + ((uint64_t)frequencyHz * minimumDivider) / 2ULL)
  260. / ((uint64_t)frequencyHz * minimumDivider);
  261. if ((periodTicks < 2ULL) || (periodTicks > 65536ULL))
  262. {
  263. return PLSR_RESULT_DIVIDER_UNREPRESENTABLE;
  264. }
  265. *psc = (uint16_t)(minimumDivider - 1ULL);
  266. *arr = (uint16_t)(periodTicks - 1ULL);
  267. return PLSR_RESULT_OK;
  268. }
  269. static PLSR_RESULT PlsrValidateFrequencyDivider(
  270. const PLSR_JOB_SNAPSHOT *snapshot,
  271. uint32_t frequency,
  272. PLSR_PARSE_DETAIL *detail,
  273. uint16_t segment)
  274. {
  275. uint16_t psc;
  276. uint16_t arr;
  277. PLSR_RESULT result;
  278. result = PlsrCalculateTimerDivider(snapshot->timerClockHz,
  279. frequency,
  280. &psc,
  281. &arr);
  282. if ((result == PLSR_RESULT_OK)
  283. && (snapshot->pairedTimerClockHz != 0UL))
  284. {
  285. result = PlsrCalculateTimerDivider(snapshot->pairedTimerClockHz,
  286. frequency,
  287. &psc,
  288. &arr);
  289. }
  290. if (result != PLSR_RESULT_OK)
  291. {
  292. PlsrSetDetail(detail,
  293. PLSR_RESULT_DIVIDER_UNREPRESENTABLE,
  294. PLSR_PARSE_BLOCK_S0,
  295. snapshot->s0.address
  296. + (uint32_t)segment * PLSR_S0_SEGMENT_WORDS,
  297. (int32_t)frequency,
  298. segment);
  299. return PLSR_RESULT_DIVIDER_UNREPRESENTABLE;
  300. }
  301. return PLSR_RESULT_OK;
  302. }
  303. static PLSR_RESULT PlsrResolveOperand(const PLSR_CALL *call,
  304. const PLSR_VALUE_OPERAND *operand,
  305. int32_t *value,
  306. PLSR_PARSE_DETAIL *detail)
  307. {
  308. PLSR_RESULT result;
  309. if (operand->type == PLSR_OPERAND_CONSTANT)
  310. {
  311. *value = operand->constant;
  312. return PLSR_RESULT_OK;
  313. }
  314. if ((operand->type != PLSR_OPERAND_DATA)
  315. || (PlsrIsWordDevice(operand->data.device) == 0U))
  316. {
  317. PlsrSetDetail(detail,
  318. PLSR_RESULT_INVALID_S2,
  319. PLSR_PARSE_BLOCK_S2,
  320. operand->data.address,
  321. (int32_t)operand->type,
  322. 0U);
  323. return PLSR_RESULT_INVALID_S2;
  324. }
  325. result = PlsrValidateRange(&call->source,
  326. operand->data,
  327. 2UL,
  328. PLSR_PARSE_BLOCK_S2,
  329. detail);
  330. if (result != PLSR_RESULT_OK)
  331. {
  332. return result;
  333. }
  334. return PlsrReadInt32(&call->source,
  335. operand->data.device,
  336. operand->data.address,
  337. value,
  338. PLSR_PARSE_BLOCK_S2,
  339. 0U,
  340. detail);
  341. }
  342. static PLSR_RESULT PlsrLoadS2(const PLSR_CALL *call,
  343. PLSR_JOB_SNAPSHOT *snapshot,
  344. PLSR_PARSE_DETAIL *detail)
  345. {
  346. uint16_t commonBase;
  347. uint16_t setBase;
  348. uint16_t word;
  349. uint16_t commonFlags;
  350. uint16_t switchLogic;
  351. uint16_t limitPoints;
  352. uint32_t rawLimit;
  353. int32_t selectedSet;
  354. uint8_t useHsd;
  355. PLSR_RESULT result;
  356. result = PlsrResolveOperand(call, &call->s2, &selectedSet, detail);
  357. if (result != PLSR_RESULT_OK)
  358. {
  359. return result;
  360. }
  361. if ((selectedSet < 0) || (selectedSet > 4))
  362. {
  363. PlsrSetDetail(detail,
  364. PLSR_RESULT_INVALID_S2,
  365. PLSR_PARSE_BLOCK_S2,
  366. call->s2.data.address,
  367. selectedSet,
  368. 0U);
  369. return PLSR_RESULT_INVALID_S2;
  370. }
  371. snapshot->s2Set = (uint8_t)selectedSet;
  372. commonBase = (uint16_t)(PLSR_SFD_CONFIG_START
  373. + (uint16_t)call->dAxis
  374. * PLSR_SFD_AXIS_STRIDE);
  375. if (snapshot->s2Set == 0U)
  376. {
  377. useHsd = 1U;
  378. setBase = (uint16_t)(PLSR_HSD_SET_BASE
  379. + (uint16_t)call->dAxis * PLSR_S2_SET_WORDS);
  380. }
  381. else
  382. {
  383. useHsd = 0U;
  384. setBase = (uint16_t)(commonBase + PLSR_SFD_SET_OFFSET
  385. + (uint16_t)(snapshot->s2Set - 1U)
  386. * PLSR_S2_SET_WORDS);
  387. }
  388. result = PlsrReadFixedDword(useHsd,
  389. setBase,
  390. &snapshot->s2.defaultSpeed,
  391. detail);
  392. if (result != PLSR_RESULT_OK) return result;
  393. result = PlsrReadFixedWord(useHsd,
  394. (uint16_t)(setBase + 2U),
  395. &snapshot->s2.accelerationMs,
  396. detail);
  397. if (result != PLSR_RESULT_OK) return result;
  398. result = PlsrReadFixedWord(useHsd,
  399. (uint16_t)(setBase + 3U),
  400. &snapshot->s2.decelerationMs,
  401. detail);
  402. if (result != PLSR_RESULT_OK) return result;
  403. result = PlsrReadFixedWord(useHsd,
  404. (uint16_t)(setBase + 4U),
  405. &snapshot->s2.gapAccelerationMs,
  406. detail);
  407. if (result != PLSR_RESULT_OK) return result;
  408. result = PlsrReadFixedWord(useHsd,
  409. (uint16_t)(setBase + 5U),
  410. &word,
  411. detail);
  412. if (result != PLSR_RESULT_OK) return result;
  413. snapshot->s2.curveMode = (uint8_t)(word & 0x03U);
  414. result = PlsrReadFixedDword(useHsd,
  415. (uint16_t)(setBase + 6U),
  416. &snapshot->s2.maximumSpeed,
  417. detail);
  418. if (result != PLSR_RESULT_OK) return result;
  419. result = PlsrReadFixedDword(useHsd,
  420. (uint16_t)(setBase + 8U),
  421. &snapshot->s2.startSpeed,
  422. detail);
  423. if (result != PLSR_RESULT_OK) return result;
  424. result = PlsrReadFixedDword(useHsd,
  425. (uint16_t)(setBase + 10U),
  426. &snapshot->s2.stopSpeed,
  427. detail);
  428. if (result != PLSR_RESULT_OK) return result;
  429. result = PlsrReadFixedWord(useHsd,
  430. (uint16_t)(setBase + 12U),
  431. &word,
  432. detail);
  433. if (result != PLSR_RESULT_OK) return result;
  434. if ((word < 1U) || (word > 100U))
  435. {
  436. PlsrSetDetail(detail,
  437. PLSR_RESULT_INVALID_S2,
  438. PLSR_PARSE_BLOCK_S2,
  439. (uint16_t)(setBase + 12U),
  440. word,
  441. 0U);
  442. return PLSR_RESULT_INVALID_S2;
  443. }
  444. snapshot->s2.follow = (uint8_t)word;
  445. result = PlsrReadFixedWord(useHsd,
  446. (uint16_t)(setBase + 13U),
  447. &word,
  448. detail);
  449. if (result != PLSR_RESULT_OK) return result;
  450. if (word > 100U)
  451. {
  452. PlsrSetDetail(detail,
  453. PLSR_RESULT_INVALID_S2,
  454. PLSR_PARSE_BLOCK_S2,
  455. (uint16_t)(setBase + 13U),
  456. word,
  457. 0U);
  458. return PLSR_RESULT_INVALID_S2;
  459. }
  460. snapshot->s2.feedforwardPercent = (uint8_t)word;
  461. result = PlsrReadFixedWord(useHsd,
  462. (uint16_t)(setBase + 14U),
  463. &word,
  464. detail);
  465. if (result != PLSR_RESULT_OK) return result;
  466. snapshot->s2.refreshCode = (uint8_t)(word & 0x03U);
  467. result = PlsrReadFixedDword(useHsd,
  468. (uint16_t)(setBase + 16U),
  469. &snapshot->s2.zrnHighSpeed,
  470. detail);
  471. if (result != PLSR_RESULT_OK) return result;
  472. result = PlsrReadFixedDword(useHsd,
  473. (uint16_t)(setBase + 18U),
  474. &snapshot->s2.zrnCrawlSpeed,
  475. detail);
  476. if (result != PLSR_RESULT_OK) return result;
  477. result = PlsrReadFixedWord(0U, commonBase, &word, detail);
  478. if (result != PLSR_RESULT_OK) return result;
  479. commonFlags = word;
  480. snapshot->directionNegativeLogic =
  481. ((commonFlags & (1U << 1U)) != 0U) ? 1U : 0U;
  482. snapshot->limits.softLimitEnabled =
  483. ((commonFlags & (1U << 2U)) != 0U) ? 1U : 0U;
  484. snapshot->equivalent.unitCode =
  485. (uint8_t)((commonFlags >> 8U) & 0x07U);
  486. result = PlsrReadFixedWord(0U,
  487. (uint16_t)(commonBase + 8U),
  488. &snapshot->positiveBacklashPulses,
  489. detail);
  490. if (result != PLSR_RESULT_OK) return result;
  491. result = PlsrReadFixedWord(0U,
  492. (uint16_t)(commonBase + 9U),
  493. &snapshot->negativeBacklashPulses,
  494. detail);
  495. if (result != PLSR_RESULT_OK) return result;
  496. if (PlsrPositionUnitCodeIsValid(snapshot->equivalent.unitCode) == 0U)
  497. {
  498. PlsrSetDetail(detail,
  499. PLSR_RESULT_INVALID_S2,
  500. PLSR_PARSE_BLOCK_S2,
  501. commonBase,
  502. snapshot->equivalent.unitCode,
  503. 0U);
  504. return PLSR_RESULT_INVALID_S2;
  505. }
  506. result = PlsrReadFixedDword(0U,
  507. (uint16_t)(commonBase + 2U),
  508. &snapshot->equivalent.pulsesPerRevolution,
  509. detail);
  510. if (result != PLSR_RESULT_OK) return result;
  511. result = PlsrReadFixedDword(0U,
  512. (uint16_t)(commonBase + 4U),
  513. &snapshot->equivalent.movementPerRevolution,
  514. detail);
  515. if (result != PLSR_RESULT_OK) return result;
  516. if (PlsrPositionValidateEquivalent(&snapshot->equivalent)
  517. != PLSR_RESULT_OK)
  518. {
  519. uint16_t invalidAddress =
  520. (snapshot->equivalent.pulsesPerRevolution == 0UL)
  521. ? (uint16_t)(commonBase + 2U)
  522. : (uint16_t)(commonBase + 4U);
  523. PlsrSetDetail(detail,
  524. PLSR_RESULT_INVALID_S2,
  525. PLSR_PARSE_BLOCK_S2,
  526. invalidAddress,
  527. 0,
  528. 0U);
  529. return PLSR_RESULT_INVALID_S2;
  530. }
  531. result = PlsrReadFixedWord(0U,
  532. (uint16_t)(commonBase + 12U),
  533. &switchLogic,
  534. detail);
  535. if (result != PLSR_RESULT_OK) return result;
  536. result = PlsrReadFixedWord(0U,
  537. (uint16_t)(commonBase + 15U),
  538. &limitPoints,
  539. detail);
  540. if (result != PLSR_RESULT_OK) return result;
  541. snapshot->limits.positiveInputPoint = (uint8_t)(limitPoints & 0xFFU);
  542. snapshot->limits.negativeInputPoint = (uint8_t)(limitPoints >> 8U);
  543. snapshot->limits.positiveInputActiveLow =
  544. ((switchLogic & (1U << 2U)) != 0U) ? 1U : 0U;
  545. snapshot->limits.negativeInputActiveLow =
  546. ((switchLogic & (1U << 3U)) != 0U) ? 1U : 0U;
  547. if (((snapshot->limits.positiveInputPoint != 0xFFU)
  548. || (snapshot->limits.negativeInputPoint != 0xFFU))
  549. && (call->source.readBit == NULL))
  550. {
  551. PlsrSetDetail(detail,
  552. PLSR_RESULT_DATA_ACCESS,
  553. PLSR_PARSE_BLOCK_S2,
  554. (uint16_t)(commonBase + 15U),
  555. limitPoints,
  556. 0U);
  557. return PLSR_RESULT_DATA_ACCESS;
  558. }
  559. result = PlsrReadFixedDword(0U,
  560. (uint16_t)(commonBase + 30U),
  561. &rawLimit,
  562. detail);
  563. if (result != PLSR_RESULT_OK) return result;
  564. result = PlsrPositionAbsoluteUnitsToPulses(
  565. &snapshot->equivalent,
  566. (int32_t)rawLimit,
  567. &snapshot->limits.positiveSoftLimitPulses);
  568. if (result != PLSR_RESULT_OK)
  569. {
  570. PlsrSetDetail(detail,
  571. PLSR_RESULT_POSITION_OVERFLOW,
  572. PLSR_PARSE_BLOCK_POSITION,
  573. (uint16_t)(commonBase + 30U),
  574. (int32_t)rawLimit,
  575. 0U);
  576. return PLSR_RESULT_POSITION_OVERFLOW;
  577. }
  578. result = PlsrReadFixedDword(0U,
  579. (uint16_t)(commonBase + 32U),
  580. &rawLimit,
  581. detail);
  582. if (result != PLSR_RESULT_OK) return result;
  583. result = PlsrPositionAbsoluteUnitsToPulses(
  584. &snapshot->equivalent,
  585. (int32_t)rawLimit,
  586. &snapshot->limits.negativeSoftLimitPulses);
  587. if (result != PLSR_RESULT_OK)
  588. {
  589. PlsrSetDetail(detail,
  590. PLSR_RESULT_POSITION_OVERFLOW,
  591. PLSR_PARSE_BLOCK_POSITION,
  592. (uint16_t)(commonBase + 32U),
  593. (int32_t)rawLimit,
  594. 0U);
  595. return PLSR_RESULT_POSITION_OVERFLOW;
  596. }
  597. if ((snapshot->limits.softLimitEnabled != 0U)
  598. && (snapshot->limits.positiveSoftLimitPulses
  599. <= snapshot->limits.negativeSoftLimitPulses))
  600. {
  601. PlsrSetDetail(detail,
  602. PLSR_RESULT_INVALID_S2,
  603. PLSR_PARSE_BLOCK_S2,
  604. (uint16_t)(commonBase + 30U),
  605. (int32_t)rawLimit,
  606. 0U);
  607. return PLSR_RESULT_INVALID_S2;
  608. }
  609. if (call->outputModeOverride == PLSR_OUTPUT_MODE_FROM_SFD)
  610. {
  611. snapshot->outputMode = ((commonFlags & (1U << 13U)) != 0U)
  612. ? (uint8_t)PLSR_OUTPUT_AB
  613. : (uint8_t)PLSR_OUTPUT_PULSE_DIR;
  614. }
  615. else if (call->outputModeOverride <= (uint8_t)PLSR_OUTPUT_CW_CCW)
  616. {
  617. snapshot->outputMode = call->outputModeOverride;
  618. }
  619. else
  620. {
  621. PlsrSetDetail(detail,
  622. PLSR_RESULT_INVALID_RESOURCE,
  623. PLSR_PARSE_BLOCK_OUTPUT,
  624. commonBase,
  625. call->outputModeOverride,
  626. 0U);
  627. return PLSR_RESULT_INVALID_RESOURCE;
  628. }
  629. result = PlsrReadFixedWord(0U,
  630. (uint16_t)(commonBase + 6U),
  631. &word,
  632. detail);
  633. if (result != PLSR_RESULT_OK) return result;
  634. if (word > UINT8_MAX)
  635. {
  636. PlsrSetDetail(detail,
  637. PLSR_RESULT_INVALID_RESOURCE,
  638. PLSR_PARSE_BLOCK_OUTPUT,
  639. (uint16_t)(commonBase + 6U),
  640. word,
  641. 0U);
  642. return PLSR_RESULT_INVALID_RESOURCE;
  643. }
  644. snapshot->directionPoint = (uint8_t)word;
  645. result = PlsrReadFixedWord(0U,
  646. (uint16_t)(commonBase + 7U),
  647. &snapshot->s2.directionDelayMs,
  648. detail);
  649. if (result != PLSR_RESULT_OK) return result;
  650. if ((snapshot->s2.maximumSpeed < PLSR_FREQUENCY_MIN_HZ)
  651. || (snapshot->s2.maximumSpeed > PLSR_FREQUENCY_MAX_HZ)
  652. || (snapshot->s2.curveMode > 2U) || (snapshot->s2.follow < 1U)
  653. || (snapshot->s2.follow > 100U)
  654. || (snapshot->s2.feedforwardPercent > 100U)
  655. || ((snapshot->s2.refreshCode != 0U)
  656. && (snapshot->s2.refreshCode != 2U)))
  657. {
  658. PlsrSetDetail(detail,
  659. PLSR_RESULT_INVALID_S2,
  660. PLSR_PARSE_BLOCK_S2,
  661. setBase,
  662. (int32_t)snapshot->s2.maximumSpeed,
  663. 0U);
  664. return PLSR_RESULT_INVALID_S2;
  665. }
  666. if (snapshot->s2.startSpeed > snapshot->s2.maximumSpeed)
  667. {
  668. snapshot->s2.startSpeed = snapshot->s2.maximumSpeed;
  669. snapshot->speedClamped = 1U;
  670. }
  671. if (snapshot->s2.stopSpeed > snapshot->s2.maximumSpeed)
  672. {
  673. snapshot->s2.stopSpeed = snapshot->s2.maximumSpeed;
  674. snapshot->speedClamped = 1U;
  675. }
  676. snapshot->inputDefaultSpeed = snapshot->s2.defaultSpeed;
  677. snapshot->inputMaximumSpeed = snapshot->s2.maximumSpeed;
  678. return PLSR_RESULT_OK;
  679. }
  680. PLSR_RESULT PlsrReadLiveFrequencyRaw(const PLSR_JOB_SNAPSHOT *snapshot,
  681. uint16_t segment,
  682. int32_t *rawFrequency)
  683. {
  684. uint32_t segmentAddress;
  685. if ((snapshot == NULL) || (rawFrequency == NULL)
  686. || (segment < 1U) || (segment > snapshot->segmentCount))
  687. {
  688. return PLSR_RESULT_INVALID_ARGUMENT;
  689. }
  690. segmentAddress = snapshot->s0.address
  691. + (uint32_t)segment * PLSR_S0_SEGMENT_WORDS;
  692. return PlsrReadInt32(&snapshot->source,
  693. snapshot->s0.device,
  694. segmentAddress,
  695. rawFrequency,
  696. PLSR_PARSE_BLOCK_S0,
  697. segment,
  698. NULL);
  699. }
  700. static PLSR_RESULT PlsrValidateVariableReference(
  701. const PLSR_CALL *call,
  702. uint8_t sourceCode,
  703. int32_t addressValue,
  704. uint8_t bitReference,
  705. int32_t *currentValue,
  706. PLSR_PARSE_BLOCK block,
  707. uint16_t segment,
  708. PLSR_PARSE_DETAIL *detail)
  709. {
  710. PLSR_DEVICE_TYPE device;
  711. PLSR_DATA_REF reference;
  712. uint8_t bitValue;
  713. PLSR_RESULT result;
  714. if ((sourceCode == 0U) || (sourceCode > 6U) || (addressValue < 0))
  715. {
  716. PlsrSetDetail(detail,
  717. (block == PLSR_PARSE_BLOCK_S0)
  718. ? PLSR_RESULT_INVALID_WAIT
  719. : PLSR_RESULT_DATA_ACCESS,
  720. block,
  721. (uint32_t)addressValue,
  722. sourceCode,
  723. segment);
  724. return (block == PLSR_PARSE_BLOCK_S0) ? PLSR_RESULT_INVALID_WAIT
  725. : PLSR_RESULT_DATA_ACCESS;
  726. }
  727. device = (PLSR_DEVICE_TYPE)(sourceCode - 1U);
  728. if (bitReference != 0U)
  729. {
  730. if ((device < PLSR_DEVICE_X) || (call->source.readBit == NULL)
  731. || (call->source.readBit(call->source.context,
  732. device,
  733. (uint32_t)addressValue,
  734. &bitValue)
  735. == 0U))
  736. {
  737. PlsrSetDetail(detail,
  738. PLSR_RESULT_INVALID_WAIT,
  739. block,
  740. (uint32_t)addressValue,
  741. sourceCode,
  742. segment);
  743. return PLSR_RESULT_INVALID_WAIT;
  744. }
  745. *currentValue = (int32_t)bitValue;
  746. return PLSR_RESULT_OK;
  747. }
  748. if (PlsrIsWordDevice(device) == 0U)
  749. {
  750. PlsrSetDetail(detail,
  751. PLSR_RESULT_INVALID_WAIT,
  752. block,
  753. (uint32_t)addressValue,
  754. sourceCode,
  755. segment);
  756. return PLSR_RESULT_INVALID_WAIT;
  757. }
  758. reference.device = device;
  759. reference.address = (uint32_t)addressValue;
  760. result = PlsrValidateRange(&call->source,
  761. reference,
  762. 2UL,
  763. block,
  764. detail);
  765. if (result != PLSR_RESULT_OK)
  766. {
  767. return result;
  768. }
  769. return PlsrReadInt32(&call->source,
  770. device,
  771. reference.address,
  772. currentValue,
  773. block,
  774. segment,
  775. detail);
  776. }
  777. static PLSR_RESULT PlsrValidateWait(const PLSR_CALL *call,
  778. PLSR_SEGMENT_SNAPSHOT *segmentData,
  779. uint16_t segment,
  780. PLSR_PARSE_DETAIL *detail)
  781. {
  782. int32_t currentValue;
  783. PLSR_RESULT result;
  784. if ((segmentData->waitCondition > PLSR_WAIT_EXT_OR_COMPLETE)
  785. || (segmentData->waitSource > PLSR_VALUE_HM))
  786. {
  787. goto invalidWait;
  788. }
  789. if (segmentData->waitCondition == PLSR_WAIT_PULSE_COMPLETE)
  790. {
  791. if (segmentData->waitSource != PLSR_VALUE_CONSTANT)
  792. {
  793. goto invalidWait;
  794. }
  795. return PLSR_RESULT_OK;
  796. }
  797. if ((segmentData->waitCondition == PLSR_WAIT_TIME)
  798. || (segmentData->waitCondition == PLSR_WAIT_ACT_TIME))
  799. {
  800. if (segmentData->waitSource == PLSR_VALUE_CONSTANT)
  801. {
  802. currentValue = segmentData->waitValueOrAddress;
  803. }
  804. else
  805. {
  806. if (segmentData->waitSource > PLSR_VALUE_FD)
  807. {
  808. goto invalidWait;
  809. }
  810. result = PlsrValidateVariableReference(call,
  811. segmentData->waitSource,
  812. segmentData->waitValueOrAddress,
  813. 0U,
  814. &currentValue,
  815. PLSR_PARSE_BLOCK_S0,
  816. segment,
  817. detail);
  818. if (result != PLSR_RESULT_OK) return result;
  819. }
  820. if (currentValue < 0) goto invalidWait;
  821. return PLSR_RESULT_OK;
  822. }
  823. if (segmentData->waitCondition == PLSR_WAIT_SIGNAL)
  824. {
  825. if ((segmentData->waitSource < PLSR_VALUE_X)
  826. || (segmentData->waitSource > PLSR_VALUE_HM))
  827. {
  828. goto invalidWait;
  829. }
  830. }
  831. else if ((segmentData->waitCondition == PLSR_WAIT_EXT)
  832. || (segmentData->waitCondition == PLSR_WAIT_EXT_OR_COMPLETE))
  833. {
  834. if (segmentData->waitSource != PLSR_VALUE_X)
  835. {
  836. goto invalidWait;
  837. }
  838. }
  839. result = PlsrValidateVariableReference(call,
  840. segmentData->waitSource,
  841. segmentData->waitValueOrAddress,
  842. 1U,
  843. &currentValue,
  844. PLSR_PARSE_BLOCK_S0,
  845. segment,
  846. detail);
  847. return result;
  848. invalidWait:
  849. PlsrSetDetail(detail,
  850. PLSR_RESULT_INVALID_WAIT,
  851. PLSR_PARSE_BLOCK_S0,
  852. call->s0.address
  853. + (uint32_t)segment * PLSR_S0_SEGMENT_WORDS + 4UL,
  854. ((int32_t)segmentData->waitCondition << 8)
  855. | segmentData->waitSource,
  856. segment);
  857. return PLSR_RESULT_INVALID_WAIT;
  858. }
  859. static PLSR_RESULT PlsrValidateJump(const PLSR_CALL *call,
  860. const PLSR_JOB_SNAPSHOT *snapshot,
  861. PLSR_SEGMENT_SNAPSHOT *segmentData,
  862. uint16_t segment,
  863. int32_t *resolvedJump,
  864. PLSR_PARSE_DETAIL *detail)
  865. {
  866. PLSR_RESULT result;
  867. if (segmentData->jumpSource > PLSR_VALUE_FD)
  868. {
  869. goto invalidJump;
  870. }
  871. if (segmentData->jumpSource == PLSR_VALUE_CONSTANT)
  872. {
  873. *resolvedJump = segmentData->jumpValueOrAddress;
  874. }
  875. else
  876. {
  877. result = PlsrValidateVariableReference(call,
  878. segmentData->jumpSource,
  879. segmentData->jumpValueOrAddress,
  880. 0U,
  881. resolvedJump,
  882. PLSR_PARSE_BLOCK_NONE,
  883. segment,
  884. detail);
  885. if (result != PLSR_RESULT_OK)
  886. {
  887. PlsrSetDetail(detail,
  888. PLSR_RESULT_INVALID_JUMP,
  889. PLSR_PARSE_BLOCK_S0,
  890. (uint32_t)segmentData->jumpValueOrAddress,
  891. segmentData->jumpSource,
  892. segment);
  893. return PLSR_RESULT_INVALID_JUMP;
  894. }
  895. }
  896. if ((*resolvedJump < 0)
  897. || (*resolvedJump > (int32_t)snapshot->segmentCount))
  898. {
  899. goto invalidJump;
  900. }
  901. if (*resolvedJump == (int32_t)segment)
  902. {
  903. segmentData->flags |= PLSR_SEGMENT_FLAG_SELF_LOOP;
  904. }
  905. return PLSR_RESULT_OK;
  906. invalidJump:
  907. PlsrSetDetail(detail,
  908. PLSR_RESULT_INVALID_JUMP,
  909. PLSR_PARSE_BLOCK_S0,
  910. call->s0.address
  911. + (uint32_t)segment * PLSR_S0_SEGMENT_WORDS + 7UL,
  912. *resolvedJump,
  913. segment);
  914. return PLSR_RESULT_INVALID_JUMP;
  915. }
  916. static PLSR_RESULT PlsrCheckConstantPath(PLSR_JOB_SNAPSHOT *snapshot,
  917. PLSR_PARSE_DETAIL *detail)
  918. {
  919. uint8_t visited[PLSR_MAX_SEGMENTS];
  920. uint16_t segment = snapshot->startSegment;
  921. int32_t next;
  922. (void)memset(visited, 0, sizeof(visited));
  923. while ((segment >= 1U) && (segment <= snapshot->segmentCount))
  924. {
  925. if (visited[segment - 1U] != 0U)
  926. {
  927. PlsrSetDetail(detail,
  928. PLSR_RESULT_PATH_CYCLE,
  929. PLSR_PARSE_BLOCK_S0,
  930. snapshot->s0.address
  931. + (uint32_t)segment * PLSR_S0_SEGMENT_WORDS
  932. + 8UL,
  933. segment,
  934. segment);
  935. return PLSR_RESULT_PATH_CYCLE;
  936. }
  937. visited[segment - 1U] = 1U;
  938. if (snapshot->segments[segment - 1U].jumpSource
  939. != PLSR_VALUE_CONSTANT)
  940. {
  941. return PLSR_RESULT_OK;
  942. }
  943. next = snapshot->segments[segment - 1U].jumpValueOrAddress;
  944. if (next == (int32_t)segment)
  945. {
  946. snapshot->hasSelfLoop = 1U;
  947. return PLSR_RESULT_OK;
  948. }
  949. if (next == 0)
  950. {
  951. if (segment == snapshot->segmentCount)
  952. {
  953. return PLSR_RESULT_OK;
  954. }
  955. segment++;
  956. }
  957. else
  958. {
  959. segment = (uint16_t)next;
  960. }
  961. }
  962. return PLSR_RESULT_OK;
  963. }
  964. static PLSR_RESULT PlsrCheckInitialPosition(
  965. PLSR_JOB_SNAPSHOT *snapshot,
  966. const PLSR_PARSE_CONTEXT *context,
  967. PLSR_PARSE_DETAIL *detail)
  968. {
  969. uint8_t visited[PLSR_MAX_SEGMENTS];
  970. int64_t position = context->logicalPosition;
  971. int64_t movement;
  972. int64_t targetPosition;
  973. int64_t remainder = 0;
  974. int32_t next;
  975. uint16_t segment = snapshot->startSegment;
  976. PLSR_RESULT result;
  977. if ((snapshot->positioningMode != 0U) && (context->positionValid == 0U))
  978. {
  979. PlsrSetDetail(detail,
  980. PLSR_RESULT_POSITION_INVALID,
  981. PLSR_PARSE_BLOCK_POSITION,
  982. snapshot->s1.address,
  983. 1,
  984. 0U);
  985. return PLSR_RESULT_POSITION_INVALID;
  986. }
  987. (void)memset(visited, 0, sizeof(visited));
  988. while ((segment >= 1U) && (segment <= snapshot->segmentCount)
  989. && (visited[segment - 1U] == 0U))
  990. {
  991. PLSR_SEGMENT_SNAPSHOT *segmentData = &snapshot->segments[segment - 1U];
  992. visited[segment - 1U] = 1U;
  993. if (snapshot->positioningMode == 0U)
  994. {
  995. result = PlsrPositionUnitsToPulses(&snapshot->equivalent,
  996. segmentData->pulseOrTarget,
  997. remainder,
  998. &movement,
  999. &remainder);
  1000. if (result != PLSR_RESULT_OK)
  1001. {
  1002. PlsrSetDetail(detail,
  1003. PLSR_RESULT_POSITION_OVERFLOW,
  1004. PLSR_PARSE_BLOCK_POSITION,
  1005. snapshot->s0.address
  1006. + (uint32_t)segment
  1007. * PLSR_S0_SEGMENT_WORDS
  1008. + 2UL,
  1009. segmentData->pulseOrTarget,
  1010. segment);
  1011. return PLSR_RESULT_POSITION_OVERFLOW;
  1012. }
  1013. if (((movement > 0) && (position > INT64_MAX - movement))
  1014. || ((movement < 0) && (position < INT64_MIN - movement)))
  1015. {
  1016. PlsrSetDetail(detail,
  1017. PLSR_RESULT_POSITION_OVERFLOW,
  1018. PLSR_PARSE_BLOCK_POSITION,
  1019. snapshot->s0.address
  1020. + (uint32_t)segment
  1021. * PLSR_S0_SEGMENT_WORDS
  1022. + 2UL,
  1023. movement,
  1024. segment);
  1025. return PLSR_RESULT_POSITION_OVERFLOW;
  1026. }
  1027. position += movement;
  1028. }
  1029. else
  1030. {
  1031. result = PlsrPositionAbsoluteUnitsToPulses(
  1032. &snapshot->equivalent,
  1033. segmentData->pulseOrTarget,
  1034. &targetPosition);
  1035. if (result != PLSR_RESULT_OK)
  1036. {
  1037. return PLSR_RESULT_POSITION_OVERFLOW;
  1038. }
  1039. movement = (targetPosition > position)
  1040. ? 1
  1041. : ((targetPosition < position) ? -1 : 0);
  1042. position = targetPosition;
  1043. }
  1044. if ((movement != 0) && (snapshot->initialDirectionPositive == 0U))
  1045. {
  1046. snapshot->initialDirectionPositive = (movement > 0) ? 2U : 1U;
  1047. }
  1048. if (segmentData->jumpSource != PLSR_VALUE_CONSTANT)
  1049. {
  1050. break;
  1051. }
  1052. next = segmentData->jumpValueOrAddress;
  1053. if (next == (int32_t)segment)
  1054. {
  1055. break;
  1056. }
  1057. if (next == 0)
  1058. {
  1059. if (segment == snapshot->segmentCount) break;
  1060. segment++;
  1061. }
  1062. else
  1063. {
  1064. segment = (uint16_t)next;
  1065. }
  1066. }
  1067. snapshot->initialDirectionPositive =
  1068. (snapshot->initialDirectionPositive == 2U) ? 1U : 0U;
  1069. return PLSR_RESULT_OK;
  1070. }
  1071. static PLSR_RESULT PlsrConvertSnapshotSpeeds(
  1072. PLSR_JOB_SNAPSHOT *snapshot,
  1073. PLSR_PARSE_DETAIL *detail)
  1074. {
  1075. uint16_t segment;
  1076. PLSR_RESULT result;
  1077. result = PlsrPositionSpeedToPulseFrequency(&snapshot->equivalent,
  1078. snapshot->s2.defaultSpeed,
  1079. &snapshot->s2.defaultSpeed);
  1080. if (result != PLSR_RESULT_OK) return result;
  1081. result = PlsrPositionSpeedToPulseFrequency(&snapshot->equivalent,
  1082. snapshot->s2.maximumSpeed,
  1083. &snapshot->s2.maximumSpeed);
  1084. if (result != PLSR_RESULT_OK) return result;
  1085. result = PlsrPositionSpeedToPulseFrequency(&snapshot->equivalent,
  1086. snapshot->s2.startSpeed,
  1087. &snapshot->s2.startSpeed);
  1088. if (result != PLSR_RESULT_OK) return result;
  1089. result = PlsrPositionSpeedToPulseFrequency(&snapshot->equivalent,
  1090. snapshot->s2.stopSpeed,
  1091. &snapshot->s2.stopSpeed);
  1092. if (result != PLSR_RESULT_OK) return result;
  1093. result = PlsrPositionSpeedToPulseFrequency(&snapshot->equivalent,
  1094. snapshot->s2.zrnHighSpeed,
  1095. &snapshot->s2.zrnHighSpeed);
  1096. if (result != PLSR_RESULT_OK) return result;
  1097. result = PlsrPositionSpeedToPulseFrequency(&snapshot->equivalent,
  1098. snapshot->s2.zrnCrawlSpeed,
  1099. &snapshot->s2.zrnCrawlSpeed);
  1100. if (result != PLSR_RESULT_OK) return result;
  1101. if ((snapshot->s2.maximumSpeed < PLSR_FREQUENCY_MIN_HZ)
  1102. || (snapshot->s2.maximumSpeed > PLSR_FREQUENCY_MAX_HZ))
  1103. {
  1104. PlsrSetDetail(detail,
  1105. PLSR_RESULT_INVALID_FREQUENCY,
  1106. PLSR_PARSE_BLOCK_S2,
  1107. 0UL,
  1108. (int32_t)snapshot->s2.maximumSpeed,
  1109. 0U);
  1110. return PLSR_RESULT_INVALID_FREQUENCY;
  1111. }
  1112. for (segment = 1U; segment <= snapshot->segmentCount; segment++)
  1113. {
  1114. PLSR_SEGMENT_SNAPSHOT *segmentData =
  1115. &snapshot->segments[segment - 1U];
  1116. if (segmentData->targetFrequency == 0UL)
  1117. {
  1118. continue;
  1119. }
  1120. result = PlsrPositionSpeedToPulseFrequency(
  1121. &snapshot->equivalent,
  1122. segmentData->targetFrequency,
  1123. &segmentData->targetFrequency);
  1124. if ((result != PLSR_RESULT_OK)
  1125. || (segmentData->targetFrequency < PLSR_FREQUENCY_MIN_HZ)
  1126. || (segmentData->targetFrequency > PLSR_FREQUENCY_MAX_HZ))
  1127. {
  1128. PlsrSetDetail(detail,
  1129. PLSR_RESULT_INVALID_FREQUENCY,
  1130. PLSR_PARSE_BLOCK_S0,
  1131. snapshot->s0.address
  1132. + (uint32_t)segment * PLSR_S0_SEGMENT_WORDS,
  1133. (int32_t)segmentData->targetFrequency,
  1134. segment);
  1135. return PLSR_RESULT_INVALID_FREQUENCY;
  1136. }
  1137. result = PlsrValidateFrequencyDivider(snapshot,
  1138. segmentData->targetFrequency,
  1139. detail,
  1140. segment);
  1141. if (result != PLSR_RESULT_OK) return result;
  1142. }
  1143. return PLSR_RESULT_OK;
  1144. }
  1145. PLSR_RESULT PlsrBuildJobSnapshot(const PLSR_CALL *call,
  1146. const PLSR_PARSE_CONTEXT *context,
  1147. PLSR_JOB_SNAPSHOT *snapshot,
  1148. PLSR_PARSE_DETAIL *detail)
  1149. {
  1150. uint64_t s0Words64;
  1151. uint32_t s0Words;
  1152. uint32_t segmentBase;
  1153. int32_t intValue;
  1154. int32_t resolvedJump;
  1155. uint16_t word;
  1156. uint16_t segment;
  1157. uint8_t index;
  1158. PLSR_RESULT result;
  1159. if ((call == NULL) || (context == NULL) || (snapshot == NULL)
  1160. || (PlsrSourceIsUsable(&call->source) == 0U))
  1161. {
  1162. return PLSR_RESULT_INVALID_ARGUMENT;
  1163. }
  1164. if (call->dAxis >= PLSR_AXIS_COUNT)
  1165. {
  1166. return PLSR_RESULT_INVALID_AXIS;
  1167. }
  1168. (void)memset(snapshot, 0, sizeof(*snapshot));
  1169. if (detail != NULL) (void)memset(detail, 0, sizeof(*detail));
  1170. snapshot->source = call->source;
  1171. snapshot->s0 = call->s0;
  1172. snapshot->s1 = call->s1;
  1173. snapshot->dAxis = call->dAxis;
  1174. snapshot->timerClockHz = ((call->dAxis == 0U) || (call->dAxis == 2U))
  1175. ? PLSR_TIMER_168MHZ
  1176. : PLSR_TIMER_84MHZ;
  1177. result = PlsrValidateRange(&call->source,
  1178. call->s0,
  1179. PLSR_S0_HEADER_WORDS,
  1180. PLSR_PARSE_BLOCK_S0,
  1181. detail);
  1182. if (result != PLSR_RESULT_OK) return result;
  1183. result = PlsrReadInt32(&call->source,
  1184. call->s0.device,
  1185. call->s0.address,
  1186. &intValue,
  1187. PLSR_PARSE_BLOCK_S0,
  1188. 0U,
  1189. detail);
  1190. if ((result != PLSR_RESULT_OK) || (intValue < 1)
  1191. || (intValue > (int32_t)PLSR_MAX_SEGMENTS))
  1192. {
  1193. if (result == PLSR_RESULT_OK)
  1194. {
  1195. PlsrSetDetail(detail,
  1196. PLSR_RESULT_SEGMENT_OVERFLOW,
  1197. PLSR_PARSE_BLOCK_S0,
  1198. call->s0.address,
  1199. intValue,
  1200. 0U);
  1201. result = PLSR_RESULT_SEGMENT_OVERFLOW;
  1202. }
  1203. return result;
  1204. }
  1205. snapshot->segmentCount = (uint16_t)intValue;
  1206. s0Words64 = (uint64_t)snapshot->segmentCount * PLSR_S0_SEGMENT_WORDS
  1207. + PLSR_S0_HEADER_WORDS;
  1208. if (s0Words64 > UINT32_MAX)
  1209. {
  1210. return PLSR_RESULT_ADDRESS_OVERFLOW;
  1211. }
  1212. s0Words = (uint32_t)s0Words64;
  1213. result = PlsrValidateRange(&call->source,
  1214. call->s0,
  1215. s0Words,
  1216. PLSR_PARSE_BLOCK_S0,
  1217. detail);
  1218. if (result != PLSR_RESULT_OK) return result;
  1219. result = PlsrValidateRange(&call->source,
  1220. call->s1,
  1221. PLSR_S1_WORDS,
  1222. PLSR_PARSE_BLOCK_S1,
  1223. detail);
  1224. if (result != PLSR_RESULT_OK) return result;
  1225. if (PlsrBlocksOverlap(call->s0, s0Words, call->s1, PLSR_S1_WORDS) != 0U)
  1226. {
  1227. PlsrSetDetail(detail,
  1228. PLSR_RESULT_BLOCK_OVERLAP,
  1229. PLSR_PARSE_BLOCK_S1,
  1230. call->s1.address,
  1231. (int32_t)s0Words,
  1232. 0U);
  1233. return PLSR_RESULT_BLOCK_OVERLAP;
  1234. }
  1235. for (index = 2U; index < 10U; index++)
  1236. {
  1237. result = PlsrReadWord(&call->source,
  1238. call->s0.device,
  1239. call->s0.address + index,
  1240. &word,
  1241. PLSR_PARSE_BLOCK_S0,
  1242. 0U,
  1243. detail);
  1244. if (result != PLSR_RESULT_OK) return result;
  1245. if (word != 0U)
  1246. {
  1247. PlsrSetDetail(detail,
  1248. PLSR_RESULT_RESERVED_NOT_ZERO,
  1249. PLSR_PARSE_BLOCK_S0,
  1250. call->s0.address + index,
  1251. word,
  1252. 0U);
  1253. return PLSR_RESULT_RESERVED_NOT_ZERO;
  1254. }
  1255. }
  1256. result = PlsrReadInt32(&call->source,
  1257. call->s1.device,
  1258. call->s1.address,
  1259. &intValue,
  1260. PLSR_PARSE_BLOCK_S1,
  1261. 0U,
  1262. detail);
  1263. if (result != PLSR_RESULT_OK) return result;
  1264. if ((intValue < 0) || (intValue > 1))
  1265. {
  1266. PlsrSetDetail(detail,
  1267. PLSR_RESULT_INVALID_POSITION_MODE,
  1268. PLSR_PARSE_BLOCK_S1,
  1269. call->s1.address,
  1270. intValue,
  1271. 0U);
  1272. return PLSR_RESULT_INVALID_POSITION_MODE;
  1273. }
  1274. snapshot->positioningMode = (uint8_t)intValue;
  1275. result = PlsrReadInt32(&call->source,
  1276. call->s1.device,
  1277. call->s1.address + 2UL,
  1278. &intValue,
  1279. PLSR_PARSE_BLOCK_S1,
  1280. 0U,
  1281. detail);
  1282. if (result != PLSR_RESULT_OK) return result;
  1283. if ((intValue < 0) || (intValue > snapshot->segmentCount))
  1284. {
  1285. PlsrSetDetail(detail,
  1286. PLSR_RESULT_INVALID_ARGUMENT,
  1287. PLSR_PARSE_BLOCK_S1,
  1288. call->s1.address + 2UL,
  1289. intValue,
  1290. 0U);
  1291. return PLSR_RESULT_INVALID_ARGUMENT;
  1292. }
  1293. snapshot->startSegment = (intValue <= 1) ? 1U : (uint16_t)intValue;
  1294. result = PlsrLoadS2(call, snapshot, detail);
  1295. if (result != PLSR_RESULT_OK) return result;
  1296. if ((snapshot->outputMode == PLSR_OUTPUT_AB)
  1297. || (snapshot->outputMode == PLSR_OUTPUT_CW_CCW))
  1298. {
  1299. if ((call->dAxis != 0U) && (call->dAxis != 2U))
  1300. {
  1301. PlsrSetDetail(detail,
  1302. PLSR_RESULT_INVALID_RESOURCE,
  1303. PLSR_PARSE_BLOCK_OUTPUT,
  1304. call->dAxis,
  1305. snapshot->outputMode,
  1306. 0U);
  1307. return PLSR_RESULT_INVALID_RESOURCE;
  1308. }
  1309. snapshot->pairedTimerClockHz = PLSR_TIMER_84MHZ;
  1310. }
  1311. for (segment = 1U; segment <= snapshot->segmentCount; segment++)
  1312. {
  1313. PLSR_SEGMENT_SNAPSHOT *segmentData = &snapshot->segments[segment - 1U];
  1314. segmentBase = call->s0.address
  1315. + (uint32_t)segment * PLSR_S0_SEGMENT_WORDS;
  1316. result = PlsrReadInt32(&call->source,
  1317. call->s0.device,
  1318. segmentBase,
  1319. &intValue,
  1320. PLSR_PARSE_BLOCK_S0,
  1321. segment,
  1322. detail);
  1323. if (result != PLSR_RESULT_OK) return result;
  1324. if (intValue < 0)
  1325. {
  1326. PlsrSetDetail(detail,
  1327. PLSR_RESULT_INVALID_FREQUENCY,
  1328. PLSR_PARSE_BLOCK_S0,
  1329. segmentBase,
  1330. intValue,
  1331. segment);
  1332. return PLSR_RESULT_INVALID_FREQUENCY;
  1333. }
  1334. segmentData->targetFrequency = (uint32_t)intValue;
  1335. result = PlsrReadInt32(&call->source,
  1336. call->s0.device,
  1337. segmentBase + 2UL,
  1338. &segmentData->pulseOrTarget,
  1339. PLSR_PARSE_BLOCK_S0,
  1340. segment,
  1341. detail);
  1342. if (result != PLSR_RESULT_OK) return result;
  1343. result = PlsrReadWord(&call->source,
  1344. call->s0.device,
  1345. segmentBase + 4UL,
  1346. &word,
  1347. PLSR_PARSE_BLOCK_S0,
  1348. segment,
  1349. detail);
  1350. if (result != PLSR_RESULT_OK) return result;
  1351. segmentData->waitSource = (uint8_t)(word & 0xFFU);
  1352. segmentData->waitCondition = (uint8_t)(word >> 8U);
  1353. result = PlsrReadInt32(&call->source,
  1354. call->s0.device,
  1355. segmentBase + 5UL,
  1356. &segmentData->waitValueOrAddress,
  1357. PLSR_PARSE_BLOCK_S0,
  1358. segment,
  1359. detail);
  1360. if (result != PLSR_RESULT_OK) return result;
  1361. result = PlsrReadWord(&call->source,
  1362. call->s0.device,
  1363. segmentBase + 7UL,
  1364. &word,
  1365. PLSR_PARSE_BLOCK_S0,
  1366. segment,
  1367. detail);
  1368. if (result != PLSR_RESULT_OK) return result;
  1369. if ((word & 0xFF00U) != 0U)
  1370. {
  1371. PlsrSetDetail(detail,
  1372. PLSR_RESULT_RESERVED_NOT_ZERO,
  1373. PLSR_PARSE_BLOCK_S0,
  1374. segmentBase + 7UL,
  1375. word,
  1376. segment);
  1377. return PLSR_RESULT_RESERVED_NOT_ZERO;
  1378. }
  1379. segmentData->jumpSource = (uint8_t)(word & 0xFFU);
  1380. result = PlsrReadInt32(&call->source,
  1381. call->s0.device,
  1382. segmentBase + 8UL,
  1383. &segmentData->jumpValueOrAddress,
  1384. PLSR_PARSE_BLOCK_S0,
  1385. segment,
  1386. detail);
  1387. if (result != PLSR_RESULT_OK) return result;
  1388. if ((snapshot->positioningMode == 0U)
  1389. && (segmentData->pulseOrTarget == 0))
  1390. {
  1391. segmentData->flags |= PLSR_SEGMENT_FLAG_ZERO_PULSE;
  1392. segmentData->targetFrequency = 0UL;
  1393. }
  1394. else if (segmentData->targetFrequency == 0UL)
  1395. {
  1396. if (snapshot->s2.defaultSpeed == 0UL)
  1397. {
  1398. PlsrSetDetail(detail,
  1399. PLSR_RESULT_INVALID_FREQUENCY,
  1400. PLSR_PARSE_BLOCK_S2,
  1401. 0UL,
  1402. 0,
  1403. segment);
  1404. return PLSR_RESULT_INVALID_FREQUENCY;
  1405. }
  1406. segmentData->targetFrequency = snapshot->s2.defaultSpeed;
  1407. segmentData->flags |= PLSR_SEGMENT_FLAG_DEFAULT_SPEED;
  1408. }
  1409. if (segmentData->targetFrequency > snapshot->s2.maximumSpeed)
  1410. {
  1411. segmentData->targetFrequency = snapshot->s2.maximumSpeed;
  1412. segmentData->flags |= PLSR_SEGMENT_FLAG_SPEED_CLAMPED;
  1413. snapshot->speedClamped = 1U;
  1414. }
  1415. result = PlsrValidateWait(call, segmentData, segment, detail);
  1416. if (result != PLSR_RESULT_OK) return result;
  1417. result = PlsrValidateJump(call,
  1418. snapshot,
  1419. segmentData,
  1420. segment,
  1421. &resolvedJump,
  1422. detail);
  1423. if (result != PLSR_RESULT_OK) return result;
  1424. }
  1425. result = PlsrConvertSnapshotSpeeds(snapshot, detail);
  1426. if (result != PLSR_RESULT_OK) return result;
  1427. result = PlsrCheckConstantPath(snapshot, detail);
  1428. if (result != PLSR_RESULT_OK) return result;
  1429. result = PlsrCheckInitialPosition(snapshot, context, detail);
  1430. if (result != PLSR_RESULT_OK) return result;
  1431. if (detail != NULL) detail->result = PLSR_RESULT_OK;
  1432. return PLSR_RESULT_OK;
  1433. }
  1434. PLSR_RESULT PlsrResolveLiveFrequency(const PLSR_JOB_SNAPSHOT *snapshot,
  1435. uint16_t segment,
  1436. uint32_t *frequency,
  1437. uint8_t *clamped)
  1438. {
  1439. int32_t rawFrequency;
  1440. PLSR_RESULT result;
  1441. if ((snapshot == NULL) || (frequency == NULL) || (clamped == NULL)
  1442. || (segment < 1U) || (segment > snapshot->segmentCount))
  1443. {
  1444. return PLSR_RESULT_INVALID_ARGUMENT;
  1445. }
  1446. if ((snapshot->segments[segment - 1U].flags
  1447. & PLSR_SEGMENT_FLAG_ZERO_PULSE)
  1448. != 0U)
  1449. {
  1450. *frequency = 0UL;
  1451. *clamped = 0U;
  1452. return PLSR_RESULT_OK;
  1453. }
  1454. result = PlsrReadLiveFrequencyRaw(snapshot, segment, &rawFrequency);
  1455. if (result != PLSR_RESULT_OK) return result;
  1456. if (rawFrequency < 0) return PLSR_RESULT_INVALID_FREQUENCY;
  1457. *frequency = (rawFrequency == 0) ? snapshot->inputDefaultSpeed
  1458. : (uint32_t)rawFrequency;
  1459. *clamped = 0U;
  1460. if (*frequency > snapshot->inputMaximumSpeed)
  1461. {
  1462. *frequency = snapshot->inputMaximumSpeed;
  1463. *clamped = 1U;
  1464. }
  1465. if (*frequency == 0UL) return PLSR_RESULT_INVALID_FREQUENCY;
  1466. result = PlsrPositionSpeedToPulseFrequency(&snapshot->equivalent,
  1467. *frequency,
  1468. frequency);
  1469. if ((result != PLSR_RESULT_OK) || (*frequency == 0UL)
  1470. || (*frequency > PLSR_FREQUENCY_MAX_HZ))
  1471. {
  1472. return PLSR_RESULT_INVALID_FREQUENCY;
  1473. }
  1474. return PlsrValidateFrequencyDivider(snapshot, *frequency, NULL, segment);
  1475. }