Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 
 
 
 

462 Zeilen
15 KiB

  1. #include "plsr_path.h"
  2. #include <string.h>
  3. /* 等待寄存器类型编码(PLSR_VALUE_SOURCE)与软元件类型(PLSR_DEVICE_TYPE)
  4. * 相差 1:D=1→D、HD=2→HD、FD=3→FD、X=4→X、M=5→M、HM=6→HM。 */
  5. static uint8_t PlsrPathDeviceFromSource(uint8_t sourceCode)
  6. {
  7. return (uint8_t)(sourceCode - 1U);
  8. }
  9. static uint8_t PlsrPathReadDword(const PLSR_DATA_SOURCE *source,
  10. PLSR_DEVICE_TYPE device,
  11. uint32_t address,
  12. int32_t *value)
  13. {
  14. uint16_t lowWord;
  15. uint16_t highWord;
  16. if ((source->readWord == NULL)
  17. || (source->readWord(source->context,
  18. device,
  19. address,
  20. &lowWord) == 0U)
  21. || (source->readWord(source->context,
  22. device,
  23. address + 1U,
  24. &highWord) == 0U))
  25. {
  26. return 0U;
  27. }
  28. *value = (int32_t)(((uint32_t)highWord << 16U) | (uint32_t)lowWord);
  29. return 1U;
  30. }
  31. static uint8_t PlsrPathReadBit(const PLSR_DATA_SOURCE *source,
  32. PLSR_DEVICE_TYPE device,
  33. uint32_t address,
  34. uint8_t *value)
  35. {
  36. if ((source->readBit == NULL)
  37. || (source->readBit(source->context, device, address, value) == 0U))
  38. {
  39. return 0U;
  40. }
  41. return 1U;
  42. }
  43. /* 求值当前段的跳转目标。
  44. * 返回:0=顺序下一段,1~segmentCount=指定段。
  45. * 动态来源在跳转发生时重新读取;非法值置 error。 */
  46. static int32_t PlsrPathResolveJumpTarget(const PLSR_JOB_SNAPSHOT *job,
  47. uint16_t segment,
  48. uint8_t *error)
  49. {
  50. const PLSR_SEGMENT_SNAPSHOT *segmentSnapshot =
  51. &job->segments[segment - 1U];
  52. int32_t target;
  53. *error = 0U;
  54. if (segmentSnapshot->jumpSource == PLSR_VALUE_CONSTANT)
  55. {
  56. target = segmentSnapshot->jumpValueOrAddress;
  57. }
  58. else
  59. {
  60. if (PlsrPathReadDword(&job->source,
  61. (PLSR_DEVICE_TYPE)PlsrPathDeviceFromSource(
  62. segmentSnapshot->jumpSource),
  63. (uint32_t)segmentSnapshot->jumpValueOrAddress,
  64. &target) == 0U)
  65. {
  66. *error = 1U;
  67. return 0;
  68. }
  69. }
  70. if ((target < 0) || (target > (int32_t)job->segmentCount))
  71. {
  72. *error = 1U;
  73. return 0;
  74. }
  75. return target;
  76. }
  77. /* 段是否零脉冲:相对模式脉冲数为 0,或绝对模式目标等于进入段时的位置。 */
  78. static uint8_t PlsrPathSegmentIsZeroPulse(const PLSR_JOB_SNAPSHOT *job,
  79. uint16_t segment,
  80. int64_t logicalPosition)
  81. {
  82. const PLSR_SEGMENT_SNAPSHOT *segmentSnapshot =
  83. &job->segments[segment - 1U];
  84. int64_t targetPosition;
  85. if ((segmentSnapshot->flags & PLSR_SEGMENT_FLAG_ZERO_PULSE) != 0U)
  86. {
  87. return 1U;
  88. }
  89. if ((job->positioningMode == 1U)
  90. && (PlsrPositionAbsoluteUnitsToPulses(
  91. &job->equivalent,
  92. segmentSnapshot->pulseOrTarget,
  93. &targetPosition) == PLSR_RESULT_OK)
  94. && (targetPosition == logicalPosition))
  95. {
  96. return 1U;
  97. }
  98. return 0U;
  99. }
  100. /* 进入新段时的初始化:求值 ACT 时间、EXT/等待信号地址与当前电平。 */
  101. static void PlsrPathEnterSegment(PLSR_PATH_CONTEXT *context,
  102. const PLSR_JOB_SNAPSHOT *job)
  103. {
  104. const PLSR_SEGMENT_SNAPSHOT *segmentSnapshot =
  105. &job->segments[context->currentSegment - 1U];
  106. int32_t actValue;
  107. context->segmentEnded = 0U;
  108. context->extActive = 0U;
  109. context->actActive = 0U;
  110. context->waitCondition = (uint8_t)segmentSnapshot->waitCondition;
  111. switch (context->waitCondition)
  112. {
  113. case PLSR_WAIT_ACT_TIME:
  114. context->actActive = 1U;
  115. if (segmentSnapshot->waitSource == PLSR_VALUE_CONSTANT)
  116. {
  117. actValue = segmentSnapshot->waitValueOrAddress;
  118. }
  119. else
  120. {
  121. actValue = 0;
  122. (void)PlsrPathReadDword(&job->source,
  123. (PLSR_DEVICE_TYPE)
  124. PlsrPathDeviceFromSource(
  125. segmentSnapshot->waitSource),
  126. (uint32_t)
  127. segmentSnapshot->waitValueOrAddress,
  128. &actValue);
  129. }
  130. context->waitRemainingMs =
  131. (actValue > 0) ? (uint32_t)actValue : 0U;
  132. break;
  133. case PLSR_WAIT_SIGNAL:
  134. case PLSR_WAIT_EXT:
  135. case PLSR_WAIT_EXT_OR_COMPLETE:
  136. context->waitSignalDevice =
  137. PlsrPathDeviceFromSource(segmentSnapshot->waitSource);
  138. context->waitSignalAddress =
  139. (uint32_t)segmentSnapshot->waitValueOrAddress;
  140. if (context->waitCondition != PLSR_WAIT_SIGNAL)
  141. {
  142. /* EXT:记录段开始时的电平,已有的有效电平不算新边沿。 */
  143. uint8_t level = 0U;
  144. (void)PlsrPathReadBit(&job->source,
  145. (PLSR_DEVICE_TYPE)
  146. context->waitSignalDevice,
  147. context->waitSignalAddress,
  148. &level);
  149. context->lastExtLevel = level;
  150. context->extActive = 1U;
  151. }
  152. break;
  153. default:
  154. break;
  155. }
  156. }
  157. /* EXT 边沿检测:电平 0→1 才算新边沿。 */
  158. static uint8_t PlsrPathPollExt(PLSR_PATH_CONTEXT *context,
  159. const PLSR_JOB_SNAPSHOT *job)
  160. {
  161. uint8_t level = 0U;
  162. uint8_t triggered = 0U;
  163. if (PlsrPathReadBit(&job->source,
  164. (PLSR_DEVICE_TYPE)context->waitSignalDevice,
  165. context->waitSignalAddress,
  166. &level) != 0U)
  167. {
  168. if ((level != 0U) && (context->lastExtLevel == 0U))
  169. {
  170. triggered = 1U;
  171. }
  172. context->lastExtLevel = level;
  173. }
  174. return triggered;
  175. }
  176. /* 推进跳转链:零脉冲段连续跳转(预算内),直到有脉冲段、结束或预算耗尽。 */
  177. static PLSR_PATH_ACTION PlsrPathAdvance(PLSR_PATH_CONTEXT *context,
  178. const PLSR_JOB_SNAPSHOT *job,
  179. int64_t logicalPosition)
  180. {
  181. uint8_t error;
  182. int32_t target;
  183. uint16_t next;
  184. while (context->zeroJumpBudget > 0U)
  185. {
  186. target = PlsrPathResolveJumpTarget(job,
  187. context->currentSegment,
  188. &error);
  189. if (error != 0U)
  190. {
  191. context->jobEnded = 1U;
  192. context->phase = PLSR_PATH_ENDED;
  193. return PLSR_PATH_ACTION_ERROR;
  194. }
  195. if (target == 0)
  196. {
  197. if (context->currentSegment >= job->segmentCount)
  198. {
  199. context->jobEnded = 1U;
  200. context->phase = PLSR_PATH_ENDED;
  201. return PLSR_PATH_ACTION_JOB_COMPLETE;
  202. }
  203. next = (uint16_t)(context->currentSegment + 1U);
  204. }
  205. else
  206. {
  207. next = (uint16_t)target;
  208. }
  209. if (PlsrPathSegmentIsZeroPulse(job, next, logicalPosition) != 0U)
  210. {
  211. context->zeroJumpBudget--;
  212. context->currentSegment = next;
  213. context->nextSegment = next;
  214. PlsrPathEnterSegment(context, job);
  215. continue;
  216. }
  217. context->currentSegment = next;
  218. context->nextSegment = next;
  219. context->phase = PLSR_PATH_SEGMENT_RUNNING;
  220. PlsrPathEnterSegment(context, job);
  221. return PLSR_PATH_ACTION_NEXT_SEGMENT;
  222. }
  223. context->jumpChainPending = 1U;
  224. return PLSR_PATH_ACTION_YIELD;
  225. }
  226. void PlsrPathBegin(PLSR_PATH_CONTEXT *context,
  227. const PLSR_JOB_SNAPSHOT *job,
  228. int64_t logicalPosition)
  229. {
  230. (void)memset(context, 0, sizeof(*context));
  231. context->currentSegment = job->startSegment;
  232. context->nextSegment = context->currentSegment;
  233. context->zeroJumpBudget = PLSR_PATH_ZERO_JUMP_BUDGET;
  234. context->phase = PLSR_PATH_SEGMENT_RUNNING;
  235. PlsrPathEnterSegment(context, job);
  236. if (PlsrPathSegmentIsZeroPulse(job,
  237. context->currentSegment,
  238. logicalPosition) != 0U)
  239. {
  240. /* 起点段就是零脉冲:直接走跳转链。 */
  241. (void)PlsrPathAdvance(context, job, logicalPosition);
  242. }
  243. }
  244. PLSR_PATH_ACTION PlsrPathOnSegmentDone(PLSR_PATH_CONTEXT *context,
  245. const PLSR_JOB_SNAPSHOT *job,
  246. int64_t logicalPosition)
  247. {
  248. const PLSR_SEGMENT_SNAPSHOT *segmentSnapshot;
  249. int32_t waitValue;
  250. uint8_t level;
  251. if ((context->jobEnded != 0U) || (context->phase == PLSR_PATH_ENDED))
  252. {
  253. return PLSR_PATH_ACTION_NONE;
  254. }
  255. context->segmentEnded = 1U;
  256. context->zeroJumpBudget = PLSR_PATH_ZERO_JUMP_BUDGET;
  257. context->jumpChainPending = 0U;
  258. segmentSnapshot = &job->segments[context->currentSegment - 1U];
  259. switch (context->waitCondition)
  260. {
  261. case PLSR_WAIT_PULSE_COMPLETE:
  262. case PLSR_WAIT_EXT_OR_COMPLETE:
  263. return PlsrPathAdvance(context, job, logicalPosition);
  264. case PLSR_WAIT_TIME:
  265. /* 等待时间在段完成时求值一次。 */
  266. if (segmentSnapshot->waitSource == PLSR_VALUE_CONSTANT)
  267. {
  268. waitValue = segmentSnapshot->waitValueOrAddress;
  269. }
  270. else
  271. {
  272. waitValue = 0;
  273. (void)PlsrPathReadDword(
  274. &job->source,
  275. (PLSR_DEVICE_TYPE)PlsrPathDeviceFromSource(
  276. segmentSnapshot->waitSource),
  277. (uint32_t)segmentSnapshot->waitValueOrAddress,
  278. &waitValue);
  279. }
  280. context->waitRemainingMs =
  281. (waitValue > 0) ? (uint32_t)waitValue : 0U;
  282. if (context->waitRemainingMs == 0U)
  283. {
  284. return PlsrPathAdvance(context, job, logicalPosition);
  285. }
  286. context->phase = PLSR_PATH_WAIT_TIME;
  287. return PLSR_PATH_ACTION_ENTER_WAIT;
  288. case PLSR_WAIT_SIGNAL:
  289. /* 信号地址已在进入段时求值;先立即检查一次,已有效则直接跳。 */
  290. if (PlsrPathReadBit(&job->source,
  291. (PLSR_DEVICE_TYPE)context->waitSignalDevice,
  292. context->waitSignalAddress,
  293. &level) != 0U)
  294. {
  295. if (level != 0U)
  296. {
  297. return PlsrPathAdvance(context, job, logicalPosition);
  298. }
  299. }
  300. context->phase = PLSR_PATH_WAIT_SIGNAL;
  301. return PLSR_PATH_ACTION_ENTER_WAIT;
  302. case PLSR_WAIT_ACT_TIME:
  303. if (context->waitRemainingMs == 0U)
  304. {
  305. return PlsrPathAdvance(context, job, logicalPosition);
  306. }
  307. /* 段已完成但 ACT 未到:停在 ACT_PENDING(core 处于 WAIT)。 */
  308. context->phase = PLSR_PATH_ACT_PENDING;
  309. return PLSR_PATH_ACTION_ENTER_WAIT;
  310. case PLSR_WAIT_EXT:
  311. /* 段已完成但 EXT 未触发:继续等新边沿。 */
  312. context->phase = PLSR_PATH_WAIT_SIGNAL;
  313. return PLSR_PATH_ACTION_ENTER_WAIT;
  314. default:
  315. return PlsrPathAdvance(context, job, logicalPosition);
  316. }
  317. }
  318. PLSR_PATH_ACTION PlsrPathTick(PLSR_PATH_CONTEXT *context,
  319. const PLSR_JOB_SNAPSHOT *job,
  320. int64_t logicalPosition)
  321. {
  322. uint8_t level;
  323. if ((context->jobEnded != 0U) || (context->phase == PLSR_PATH_ENDED))
  324. {
  325. return PLSR_PATH_ACTION_NONE;
  326. }
  327. if (context->jumpChainPending != 0U)
  328. {
  329. /* 上轮预算耗尽让出:本轮重置预算继续跳转链。 */
  330. context->zeroJumpBudget = PLSR_PATH_ZERO_JUMP_BUDGET;
  331. context->jumpChainPending = 0U;
  332. return PlsrPathAdvance(context, job, logicalPosition);
  333. }
  334. switch (context->phase)
  335. {
  336. case PLSR_PATH_SEGMENT_RUNNING:
  337. if ((context->actActive != 0U)
  338. && (context->waitRemainingMs > 0U))
  339. {
  340. context->waitRemainingMs--;
  341. if (context->waitRemainingMs == 0U)
  342. {
  343. /* ACT 到时:截断当前段,立即跳转。 */
  344. return PlsrPathAdvance(context, job, logicalPosition);
  345. }
  346. }
  347. if ((context->extActive != 0U)
  348. && (PlsrPathPollExt(context, job) != 0U))
  349. {
  350. return PlsrPathAdvance(context, job, logicalPosition);
  351. }
  352. break;
  353. case PLSR_PATH_WAIT_TIME:
  354. if (context->waitRemainingMs > 0U)
  355. {
  356. context->waitRemainingMs--;
  357. }
  358. if (context->waitRemainingMs == 0U)
  359. {
  360. return PlsrPathAdvance(context, job, logicalPosition);
  361. }
  362. break;
  363. case PLSR_PATH_WAIT_SIGNAL:
  364. if (context->waitCondition == PLSR_WAIT_SIGNAL)
  365. {
  366. /* H02:电平有效即触发。 */
  367. if (PlsrPathReadBit(&job->source,
  368. (PLSR_DEVICE_TYPE)
  369. context->waitSignalDevice,
  370. context->waitSignalAddress,
  371. &level) != 0U)
  372. {
  373. if (level != 0U)
  374. {
  375. return PlsrPathAdvance(context, job, logicalPosition);
  376. }
  377. }
  378. }
  379. else
  380. {
  381. /* H04 段完成后的 EXT 等待:新边沿触发。 */
  382. if (PlsrPathPollExt(context, job) != 0U)
  383. {
  384. return PlsrPathAdvance(context, job, logicalPosition);
  385. }
  386. }
  387. break;
  388. case PLSR_PATH_ACT_PENDING:
  389. if (context->waitRemainingMs > 0U)
  390. {
  391. context->waitRemainingMs--;
  392. }
  393. if (context->waitRemainingMs == 0U)
  394. {
  395. return PlsrPathAdvance(context, job, logicalPosition);
  396. }
  397. break;
  398. default:
  399. break;
  400. }
  401. return PLSR_PATH_ACTION_NONE;
  402. }
  403. uint16_t PlsrPathGetCurrentSegment(const PLSR_PATH_CONTEXT *context)
  404. {
  405. if (context == NULL)
  406. {
  407. return 0U;
  408. }
  409. return context->currentSegment;
  410. }
  411. void PlsrPathTerminate(PLSR_PATH_CONTEXT *context)
  412. {
  413. if (context == NULL)
  414. {
  415. return;
  416. }
  417. context->phase = PLSR_PATH_ENDED;
  418. context->jobEnded = 1U;
  419. context->jumpChainPending = 0U;
  420. context->zeroJumpBudget = 0U;
  421. }