25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.
 
 
 
 
 
 

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