Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 
 
 
 

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