25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

967 lines
36 KiB

  1. #include "plsr_self_test.h"
  2. #include "plc_device.h"
  3. #include "modbus_data_store.h"
  4. #include "plsr_core.h"
  5. #include "plsr_job.h"
  6. #include "plsr_modbus_data.h"
  7. #include <string.h>
  8. /* 上电自测(验证后可删除):
  9. * - AB 模式使用 Q0(A)/Q1(B),其余用出厂默认参数(K1)
  10. * - 任务:3 段完整 AB 周期(H00 完成,顺序衔接):
  11. * 段1:2000Hz / +1000 周期(A 超前 B)
  12. * 段2:5000Hz / +6000 周期(A 超前 B)
  13. * 段3:1000Hz / -500 周期(B 超前 A,验证反向)
  14. * 数据源为静态数组,仅自测使用(正式 D 设备适配器见 Modbus 阶段)。 */
  15. #define SELF_TEST_WORD_CAPACITY (192U)
  16. #define SELF_TEST_S0_BASE (10U)
  17. #define SELF_TEST_S1_BASE (60U)
  18. #define SELF_TEST_DIR_POINT (4U)
  19. #define SELF_TEST_SFD_AXIS_STRIDE (130U)
  20. #define SELF_TEST_SFD_SET_OFFSET (50U)
  21. #define SELF_TEST_MODBUS_S0_BASE (1000UL)
  22. #define SELF_TEST_MODBUS_S1_BASE (1100UL)
  23. static uint16_t SelfTestWords[3][SELF_TEST_WORD_CAPACITY];
  24. volatile int32_t PlsrSelfTestLiveFrequencyHz;
  25. volatile uint32_t PlsrSelfTestDynamicTick100us;
  26. volatile uint8_t PlsrSelfTestDynamicPhase;
  27. static volatile uint8_t PlsrSelfTestDynamicEnabled;
  28. void PlsrSelfTestControlTick100us(void)
  29. {
  30. if (PlsrSelfTestDynamicEnabled == 0U)
  31. {
  32. return;
  33. }
  34. if (PlsrSelfTestDynamicTick100us != UINT32_MAX)
  35. {
  36. PlsrSelfTestDynamicTick100us++;
  37. }
  38. switch (PlsrSelfTestDynamicTick100us)
  39. {
  40. case 10000UL: /* 1.0s: 1000 -> 4000Hz. */
  41. PlsrSelfTestLiveFrequencyHz = 4000;
  42. PlsrSelfTestDynamicPhase = 1U;
  43. break;
  44. case 15000UL: /* 1.5s: 4000 -> 500Hz. */
  45. PlsrSelfTestLiveFrequencyHz = 500;
  46. PlsrSelfTestDynamicPhase = 2U;
  47. break;
  48. case 20000UL: /* 2.0s: zero selects the 1000Hz S2 default. */
  49. PlsrSelfTestLiveFrequencyHz = 0;
  50. PlsrSelfTestDynamicPhase = 3U;
  51. break;
  52. case 22000UL: /* 2.2s: 8000 is clamped to the 5000Hz maximum. */
  53. PlsrSelfTestLiveFrequencyHz = 8000;
  54. PlsrSelfTestDynamicPhase = 4U;
  55. break;
  56. case 27000UL: /* 2.7s: invalid value must retain the safe target. */
  57. PlsrSelfTestLiveFrequencyHz = -1;
  58. PlsrSelfTestDynamicPhase = 5U;
  59. break;
  60. case 29000UL: /* 2.9s: recover and hold 2000Hz. */
  61. PlsrSelfTestLiveFrequencyHz = 2000;
  62. PlsrSelfTestDynamicPhase = 6U;
  63. PlsrSelfTestDynamicEnabled = 0U;
  64. break;
  65. default:
  66. break;
  67. }
  68. }
  69. static uint8_t SelfTestValidateWords(void *context,
  70. PLSR_DEVICE_TYPE device,
  71. uint32_t firstAddress,
  72. uint32_t wordCount)
  73. {
  74. (void)context;
  75. if ((device > PLSR_DEVICE_FD) || (wordCount == 0UL))
  76. {
  77. return 0U;
  78. }
  79. return (((uint64_t)firstAddress + wordCount)
  80. <= SELF_TEST_WORD_CAPACITY)
  81. ? 1U
  82. : 0U;
  83. }
  84. static uint8_t SelfTestReadWord(void *context,
  85. PLSR_DEVICE_TYPE device,
  86. uint32_t address,
  87. uint16_t *value)
  88. {
  89. (void)context;
  90. if ((device > PLSR_DEVICE_FD) || (value == NULL)
  91. || (address >= SELF_TEST_WORD_CAPACITY))
  92. {
  93. return 0U;
  94. }
  95. *value = SelfTestWords[device][address];
  96. return 1U;
  97. }
  98. static uint8_t SelfTestReadDwordLive(void *context,
  99. PLSR_DEVICE_TYPE device,
  100. uint32_t address,
  101. int32_t *value)
  102. {
  103. uint16_t lowWord;
  104. uint16_t highWord;
  105. if (value == NULL)
  106. {
  107. return 0U;
  108. }
  109. if ((device == PLSR_DEVICE_D)
  110. && (address == SELF_TEST_S0_BASE + 10UL))
  111. {
  112. /* Aligned Cortex-M4 dword load: atomic source for the TIM6 ISR. */
  113. *value = PlsrSelfTestLiveFrequencyHz;
  114. return 1U;
  115. }
  116. if ((SelfTestReadWord(context, device, address, &lowWord) == 0U)
  117. || (SelfTestReadWord(context,
  118. device,
  119. address + 1UL,
  120. &highWord) == 0U))
  121. {
  122. return 0U;
  123. }
  124. *value = (int32_t)(((uint32_t)highWord << 16U) | lowWord);
  125. return 1U;
  126. }
  127. static uint8_t SelfTestReadBit(void *context,
  128. PLSR_DEVICE_TYPE device,
  129. uint32_t address,
  130. uint8_t *value)
  131. {
  132. (void)context;
  133. (void)device;
  134. (void)address;
  135. *value = 0U;
  136. return 1U;
  137. }
  138. static void SelfTestWriteDword(PLSR_DEVICE_TYPE device,
  139. uint32_t address,
  140. uint32_t value)
  141. {
  142. SelfTestWords[device][address] = (uint16_t)(value & 0xFFFFUL);
  143. SelfTestWords[device][address + 1UL] = (uint16_t)(value >> 16U);
  144. }
  145. static void SelfTestWriteSfdDword(uint16_t address, uint32_t value)
  146. {
  147. (void)PlcDeviceWriteSfd(address, (uint16_t)(value & 0xFFFFUL));
  148. (void)PlcDeviceWriteSfd((uint16_t)(address + 1U),
  149. (uint16_t)(value >> 16U));
  150. }
  151. PLSR_RESULT PlsrSelfTestQueue(void)
  152. {
  153. PLSR_CALL call;
  154. (void)memset(SelfTestWords, 0, sizeof(SelfTestWords));
  155. /* 方向端子 Y4(PULSE/DIR 模式必需,接线参数)。 */
  156. (void)PlcDeviceWriteSfd(906U, SELF_TEST_DIR_POINT);
  157. (void)PlcDeviceWriteSfd(912U, 0U);
  158. (void)PlcDeviceWriteSfd(915U, 0xFFFFU);
  159. /* S0:3 段,H00 完成,顺序跳转。 */
  160. SelfTestWriteDword(PLSR_DEVICE_D, SELF_TEST_S0_BASE, 3U);
  161. SelfTestWriteDword(PLSR_DEVICE_D, SELF_TEST_S0_BASE + 10U, 2000UL);
  162. SelfTestWriteDword(PLSR_DEVICE_D, SELF_TEST_S0_BASE + 12U, 1000UL);
  163. SelfTestWriteDword(PLSR_DEVICE_D, SELF_TEST_S0_BASE + 20U, 5000UL);
  164. SelfTestWriteDword(PLSR_DEVICE_D, SELF_TEST_S0_BASE + 22U, 6000UL);
  165. SelfTestWriteDword(PLSR_DEVICE_D, SELF_TEST_S0_BASE + 30U, 1000UL);
  166. SelfTestWriteDword(PLSR_DEVICE_D,
  167. SELF_TEST_S0_BASE + 32U,
  168. (uint32_t)(int32_t)-500);
  169. /* S1:相对模式,起始段 0(=段1)。 */
  170. SelfTestWriteDword(PLSR_DEVICE_D, SELF_TEST_S1_BASE, 0U);
  171. (void)memset(&call, 0, sizeof(call));
  172. call.sequence = 0xA5A5UL;
  173. call.source.context = NULL;
  174. call.source.validateWords = SelfTestValidateWords;
  175. call.source.readWord = SelfTestReadWord;
  176. call.source.readBit = SelfTestReadBit;
  177. call.s0.device = PLSR_DEVICE_D;
  178. call.s0.address = SELF_TEST_S0_BASE;
  179. call.s1.device = PLSR_DEVICE_D;
  180. call.s1.address = SELF_TEST_S1_BASE;
  181. call.s2.type = PLSR_OPERAND_CONSTANT;
  182. call.s2.constant = 1;
  183. call.dAxis = 0U;
  184. call.outputModeOverride = PLSR_OUTPUT_AB;
  185. return PlsrPostCall(&call);
  186. }
  187. PLSR_RESULT PlsrEquivalentSelfTestQueue(void)
  188. {
  189. PLSR_CALL call;
  190. (void)memset(SelfTestWords, 0, sizeof(SelfTestWords));
  191. /* SFD900 Bit10~8=001(1um当量);3脉冲/2单位。 */
  192. (void)PlcDeviceWriteSfd(900U, (1U << 8U));
  193. SelfTestWriteSfdDword(902U, 3UL);
  194. SelfTestWriteSfdDword(904U, 2UL);
  195. (void)PlcDeviceWriteSfd(906U, SELF_TEST_DIR_POINT);
  196. (void)PlcDeviceWriteSfd(907U, 10U);
  197. (void)PlcDeviceWriteSfd(912U, 0U);
  198. (void)PlcDeviceWriteSfd(915U, 0xFFFFU);
  199. /* 当量换算后物理最高速度=90000Hz,不超过硬件100kHz。 */
  200. SelfTestWriteSfdDword(956U, 60000UL);
  201. /* 板端可观察版本:两段各1001工程单位。
  202. * 3脉冲/2单位带余数换算后分别输出1501、1502脉冲,累计3003脉冲;
  203. * 1500Hz附近持续约2s,避免原3脉冲自检在逻辑分析仪启动前已经结束。 */
  204. SelfTestWriteDword(PLSR_DEVICE_D, SELF_TEST_S0_BASE, 2U);
  205. SelfTestWriteDword(PLSR_DEVICE_D, SELF_TEST_S0_BASE + 10U, 1000UL);
  206. SelfTestWriteDword(PLSR_DEVICE_D, SELF_TEST_S0_BASE + 12U, 1001UL);
  207. SelfTestWriteDword(PLSR_DEVICE_D, SELF_TEST_S0_BASE + 20U, 1000UL);
  208. SelfTestWriteDword(PLSR_DEVICE_D, SELF_TEST_S0_BASE + 22U, 1001UL);
  209. SelfTestWriteDword(PLSR_DEVICE_D, SELF_TEST_S1_BASE, 0U);
  210. (void)memset(&call, 0, sizeof(call));
  211. call.sequence = 0xA5A6UL;
  212. call.source.context = NULL;
  213. call.source.validateWords = SelfTestValidateWords;
  214. call.source.readWord = SelfTestReadWord;
  215. call.source.readBit = SelfTestReadBit;
  216. call.s0.device = PLSR_DEVICE_D;
  217. call.s0.address = SELF_TEST_S0_BASE;
  218. call.s1.device = PLSR_DEVICE_D;
  219. call.s1.address = SELF_TEST_S1_BASE;
  220. call.s2.type = PLSR_OPERAND_CONSTANT;
  221. call.s2.constant = 1;
  222. call.dAxis = 0U;
  223. call.outputModeOverride = PLSR_OUTPUT_PULSE_DIR;
  224. return PlsrPostCall(&call);
  225. }
  226. PLSR_RESULT PlsrProtectionSelfTestQueue(void)
  227. {
  228. PLSR_CALL call;
  229. PLSR_COMMAND command;
  230. PLSR_RESULT result;
  231. (void)memset(SelfTestWords, 0, sizeof(SelfTestWords));
  232. /* Pulse unit, soft limits enabled, 1 pulse per position unit. */
  233. (void)PlcDeviceWriteSfd(900U, (1U << 2U));
  234. SelfTestWriteSfdDword(902U, 1UL);
  235. SelfTestWriteSfdDword(904U, 1UL);
  236. (void)PlcDeviceWriteSfd(906U, SELF_TEST_DIR_POINT);
  237. (void)PlcDeviceWriteSfd(907U, 10U);
  238. (void)PlcDeviceWriteSfd(912U, 0U);
  239. (void)PlcDeviceWriteSfd(915U, 0xFFFFU);
  240. SelfTestWriteSfdDword(930U, 500UL);
  241. SelfTestWriteSfdDword(932U, (uint32_t)(int32_t)-500);
  242. /* K1: 1000Hz, 100ms acceleration/deceleration, 1ms refresh. */
  243. SelfTestWriteSfdDword(950U, 1000UL);
  244. (void)PlcDeviceWriteSfd(952U, 100U);
  245. (void)PlcDeviceWriteSfd(953U, 100U);
  246. (void)PlcDeviceWriteSfd(954U, 0U);
  247. (void)PlcDeviceWriteSfd(955U, 0U);
  248. SelfTestWriteSfdDword(956U, 100000UL);
  249. SelfTestWriteSfdDword(958U, 1000UL);
  250. SelfTestWriteSfdDword(960U, 0UL);
  251. (void)PlcDeviceWriteSfd(962U, 50U);
  252. (void)PlcDeviceWriteSfd(963U, 0U);
  253. (void)PlcDeviceWriteSfd(964U, 0U);
  254. SelfTestWriteSfdDword(966U, 2000UL);
  255. SelfTestWriteSfdDword(968U, 200UL);
  256. /* One relative segment requests +10000 pulses; +500 must stop it. */
  257. SelfTestWriteDword(PLSR_DEVICE_D, SELF_TEST_S0_BASE, 1U);
  258. SelfTestWriteDword(PLSR_DEVICE_D,
  259. SELF_TEST_S0_BASE + 10U,
  260. 1000UL);
  261. SelfTestWriteDword(PLSR_DEVICE_D,
  262. SELF_TEST_S0_BASE + 12U,
  263. 10000UL);
  264. SelfTestWriteDword(PLSR_DEVICE_D, SELF_TEST_S1_BASE, 0U);
  265. (void)memset(&command, 0, sizeof(command));
  266. command.sequence = 0xA5A7UL;
  267. command.axis = 0U;
  268. command.opcode = PLSR_CMD_SET_POSITION;
  269. command.argument = 0;
  270. result = PlsrPostCommand(&command);
  271. if (result != PLSR_RESULT_QUEUED)
  272. {
  273. return result;
  274. }
  275. (void)memset(&call, 0, sizeof(call));
  276. call.sequence = 0xA5A8UL;
  277. call.source.context = NULL;
  278. call.source.validateWords = SelfTestValidateWords;
  279. call.source.readWord = SelfTestReadWord;
  280. call.source.readBit = SelfTestReadBit;
  281. call.s0.device = PLSR_DEVICE_D;
  282. call.s0.address = SELF_TEST_S0_BASE;
  283. call.s1.device = PLSR_DEVICE_D;
  284. call.s1.address = SELF_TEST_S1_BASE;
  285. call.s2.type = PLSR_OPERAND_CONSTANT;
  286. call.s2.constant = 1;
  287. call.dAxis = 0U;
  288. call.outputModeOverride = PLSR_OUTPUT_PULSE_DIR;
  289. return PlsrPostCall(&call);
  290. }
  291. PLSR_RESULT PlsrFourAxisSelfTestQueue(void)
  292. {
  293. static const uint16_t s0Base[PLSR_AXIS_COUNT] =
  294. {
  295. 10U, 40U, 70U, 100U
  296. };
  297. static const uint16_t s1Base[PLSR_AXIS_COUNT] =
  298. {
  299. 160U, 164U, 168U, 172U
  300. };
  301. static const uint32_t frequencyHz[PLSR_AXIS_COUNT] =
  302. {
  303. 1000UL, 2000UL, 3000UL, 4000UL
  304. };
  305. static const int32_t pulseCount[PLSR_AXIS_COUNT] =
  306. {
  307. 1000, 2000, 3000, 4000
  308. };
  309. PLSR_CALL call;
  310. PLSR_COMMAND command;
  311. PLSR_RESULT result;
  312. uint16_t commonBase;
  313. uint16_t setBase;
  314. uint8_t axis;
  315. (void)memset(SelfTestWords, 0, sizeof(SelfTestWords));
  316. for (axis = 0U; axis < PLSR_AXIS_COUNT; axis++)
  317. {
  318. commonBase = (uint16_t)(900U
  319. + (uint16_t)axis
  320. * SELF_TEST_SFD_AXIS_STRIDE);
  321. setBase = (uint16_t)(commonBase + SELF_TEST_SFD_SET_OFFSET);
  322. /* Pulse unit, PULSE/DIR, no limit input, Q4..Q7 as DIR. */
  323. (void)PlcDeviceWriteSfd(commonBase, 0U);
  324. SelfTestWriteSfdDword((uint16_t)(commonBase + 2U), 1UL);
  325. SelfTestWriteSfdDword((uint16_t)(commonBase + 4U), 1UL);
  326. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 6U),
  327. (uint16_t)(SELF_TEST_DIR_POINT + axis));
  328. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 7U), 10U);
  329. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 12U), 0U);
  330. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 15U), 0xFFFFU);
  331. /* K1 has no ramp so all four channels keep an exact fixed rate. */
  332. SelfTestWriteSfdDword(setBase, frequencyHz[axis]);
  333. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 2U), 0U);
  334. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 3U), 0U);
  335. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 4U), 0U);
  336. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 5U), 0U);
  337. SelfTestWriteSfdDword((uint16_t)(setBase + 6U), 100000UL);
  338. SelfTestWriteSfdDword((uint16_t)(setBase + 8U),
  339. frequencyHz[axis]);
  340. SelfTestWriteSfdDword((uint16_t)(setBase + 10U), 0UL);
  341. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 12U), 50U);
  342. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 13U), 0U);
  343. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 14U), 0U);
  344. SelfTestWriteSfdDword((uint16_t)(setBase + 16U), 2000UL);
  345. SelfTestWriteSfdDword((uint16_t)(setBase + 18U), 200UL);
  346. SelfTestWriteDword(PLSR_DEVICE_D, s0Base[axis], 1U);
  347. SelfTestWriteDword(PLSR_DEVICE_D,
  348. (uint32_t)s0Base[axis] + 10UL,
  349. frequencyHz[axis]);
  350. SelfTestWriteDword(PLSR_DEVICE_D,
  351. (uint32_t)s0Base[axis] + 12UL,
  352. (uint32_t)pulseCount[axis]);
  353. SelfTestWriteDword(PLSR_DEVICE_D, s1Base[axis], 0U);
  354. /* Make the board-test result independent of a previously restored
  355. * Backup SRAM position. */
  356. (void)memset(&command, 0, sizeof(command));
  357. command.sequence = 0xA500UL + axis;
  358. command.axis = axis;
  359. command.opcode = PLSR_CMD_SET_POSITION;
  360. command.argument = 0;
  361. result = PlsrPostCommand(&command);
  362. if (result != PLSR_RESULT_QUEUED)
  363. {
  364. return result;
  365. }
  366. (void)memset(&call, 0, sizeof(call));
  367. call.sequence = 0xA600UL + axis;
  368. call.source.context = NULL;
  369. call.source.validateWords = SelfTestValidateWords;
  370. call.source.readWord = SelfTestReadWord;
  371. call.source.readBit = SelfTestReadBit;
  372. call.s0.device = PLSR_DEVICE_D;
  373. call.s0.address = s0Base[axis];
  374. call.s1.device = PLSR_DEVICE_D;
  375. call.s1.address = s1Base[axis];
  376. call.s2.type = PLSR_OPERAND_CONSTANT;
  377. call.s2.constant = 1;
  378. call.dAxis = axis;
  379. call.outputModeOverride = PLSR_OUTPUT_PULSE_DIR;
  380. result = PlsrPostCall(&call);
  381. if (result != PLSR_RESULT_QUEUED)
  382. {
  383. return result;
  384. }
  385. }
  386. return PLSR_RESULT_QUEUED;
  387. }
  388. PLSR_RESULT PlsrBacklashSelfTestQueue(void)
  389. {
  390. PLSR_CALL call;
  391. PLSR_COMMAND command;
  392. PLSR_RESULT result;
  393. (void)memset(SelfTestWords, 0, sizeof(SelfTestWords));
  394. /* Pulse unit, Q4 direction, +10/-20 pulse backlash. */
  395. (void)PlcDeviceWriteSfd(900U, 0U);
  396. SelfTestWriteSfdDword(902U, 1UL);
  397. SelfTestWriteSfdDword(904U, 1UL);
  398. (void)PlcDeviceWriteSfd(906U, SELF_TEST_DIR_POINT);
  399. (void)PlcDeviceWriteSfd(907U, 10U);
  400. (void)PlcDeviceWriteSfd(908U, 10U);
  401. (void)PlcDeviceWriteSfd(909U, 20U);
  402. (void)PlcDeviceWriteSfd(912U, 0U);
  403. (void)PlcDeviceWriteSfd(915U, 0xFFFFU);
  404. /* K1 user segments are fixed 1kHz. Backlash blocks use a 20ms
  405. * acceleration/deceleration parameter. */
  406. SelfTestWriteSfdDword(950U, 1000UL);
  407. (void)PlcDeviceWriteSfd(952U, 0U);
  408. (void)PlcDeviceWriteSfd(953U, 0U);
  409. (void)PlcDeviceWriteSfd(954U, 20U);
  410. (void)PlcDeviceWriteSfd(955U, 0U);
  411. SelfTestWriteSfdDword(956U, 100000UL);
  412. SelfTestWriteSfdDword(958U, 1000UL);
  413. SelfTestWriteSfdDword(960U, 0UL);
  414. (void)PlcDeviceWriteSfd(962U, 50U);
  415. (void)PlcDeviceWriteSfd(963U, 0U);
  416. (void)PlcDeviceWriteSfd(964U, 0U);
  417. SelfTestWriteSfdDword(966U, 2000UL);
  418. SelfTestWriteSfdDword(968U, 200UL);
  419. SelfTestWriteDword(PLSR_DEVICE_D, SELF_TEST_S0_BASE, 3U);
  420. SelfTestWriteDword(PLSR_DEVICE_D,
  421. SELF_TEST_S0_BASE + 10U,
  422. 1000UL);
  423. SelfTestWriteDword(PLSR_DEVICE_D,
  424. SELF_TEST_S0_BASE + 12U,
  425. 200UL);
  426. SelfTestWriteDword(PLSR_DEVICE_D,
  427. SELF_TEST_S0_BASE + 20U,
  428. 1000UL);
  429. SelfTestWriteDword(PLSR_DEVICE_D,
  430. SELF_TEST_S0_BASE + 22U,
  431. (uint32_t)(int32_t)-200);
  432. SelfTestWriteDword(PLSR_DEVICE_D,
  433. SELF_TEST_S0_BASE + 30U,
  434. 1000UL);
  435. SelfTestWriteDword(PLSR_DEVICE_D,
  436. SELF_TEST_S0_BASE + 32U,
  437. 100UL);
  438. SelfTestWriteDword(PLSR_DEVICE_D, SELF_TEST_S1_BASE, 0U);
  439. (void)memset(&command, 0, sizeof(command));
  440. command.sequence = 0xA700UL;
  441. command.axis = 0U;
  442. command.opcode = PLSR_CMD_SET_POSITION;
  443. command.argument = 0;
  444. result = PlsrPostCommand(&command);
  445. if (result != PLSR_RESULT_QUEUED)
  446. {
  447. return result;
  448. }
  449. (void)memset(&call, 0, sizeof(call));
  450. call.sequence = 0xA701UL;
  451. call.source.context = NULL;
  452. call.source.validateWords = SelfTestValidateWords;
  453. call.source.readWord = SelfTestReadWord;
  454. call.source.readBit = SelfTestReadBit;
  455. call.s0.device = PLSR_DEVICE_D;
  456. call.s0.address = SELF_TEST_S0_BASE;
  457. call.s1.device = PLSR_DEVICE_D;
  458. call.s1.address = SELF_TEST_S1_BASE;
  459. call.s2.type = PLSR_OPERAND_CONSTANT;
  460. call.s2.constant = 1;
  461. call.dAxis = 0U;
  462. call.outputModeOverride = PLSR_OUTPUT_PULSE_DIR;
  463. return PlsrPostCall(&call);
  464. }
  465. PLSR_RESULT PlsrDirectionLogicSelfTestQueue(void)
  466. {
  467. static const uint16_t s0Base[2] = {10U, 40U};
  468. static const uint16_t s1Base[2] = {160U, 164U};
  469. static const uint8_t directionPoint[2] = {4U, 3U};
  470. PLSR_CALL call;
  471. PLSR_COMMAND command;
  472. PLSR_RESULT result;
  473. uint16_t commonBase;
  474. uint16_t setBase;
  475. uint8_t axis;
  476. (void)memset(SelfTestWords, 0, sizeof(SelfTestWords));
  477. for (axis = 0U; axis < 2U; axis++)
  478. {
  479. commonBase = (uint16_t)(900U
  480. + (uint16_t)axis
  481. * SELF_TEST_SFD_AXIS_STRIDE);
  482. setBase = (uint16_t)(commonBase + SELF_TEST_SFD_SET_OFFSET);
  483. /* Axis 0 uses positive logic; axis 1 uses negative logic. */
  484. (void)PlcDeviceWriteSfd(commonBase,
  485. (axis == 0U) ? 0U : (1U << 1U));
  486. SelfTestWriteSfdDword((uint16_t)(commonBase + 2U), 1UL);
  487. SelfTestWriteSfdDword((uint16_t)(commonBase + 4U), 1UL);
  488. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 6U),
  489. directionPoint[axis]);
  490. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 7U), 10U);
  491. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 8U), 0U);
  492. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 9U), 0U);
  493. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 12U), 0U);
  494. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 15U), 0xFFFFU);
  495. SelfTestWriteSfdDword(setBase, 1000UL);
  496. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 2U), 0U);
  497. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 3U), 0U);
  498. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 4U), 0U);
  499. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 5U), 0U);
  500. SelfTestWriteSfdDword((uint16_t)(setBase + 6U), 100000UL);
  501. SelfTestWriteSfdDword((uint16_t)(setBase + 8U), 1000UL);
  502. SelfTestWriteSfdDword((uint16_t)(setBase + 10U), 0UL);
  503. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 12U), 50U);
  504. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 13U), 0U);
  505. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 14U), 0U);
  506. SelfTestWriteSfdDword((uint16_t)(setBase + 16U), 2000UL);
  507. SelfTestWriteSfdDword((uint16_t)(setBase + 18U), 200UL);
  508. SelfTestWriteDword(PLSR_DEVICE_D, s0Base[axis], 2U);
  509. SelfTestWriteDword(PLSR_DEVICE_D,
  510. (uint32_t)s0Base[axis] + 10UL,
  511. 1000UL);
  512. SelfTestWriteDword(PLSR_DEVICE_D,
  513. (uint32_t)s0Base[axis] + 12UL,
  514. 200UL);
  515. SelfTestWriteDword(PLSR_DEVICE_D,
  516. (uint32_t)s0Base[axis] + 20UL,
  517. 1000UL);
  518. SelfTestWriteDword(PLSR_DEVICE_D,
  519. (uint32_t)s0Base[axis] + 22UL,
  520. (uint32_t)(int32_t)-200);
  521. SelfTestWriteDword(PLSR_DEVICE_D, s1Base[axis], 0U);
  522. (void)memset(&command, 0, sizeof(command));
  523. command.sequence = 0xA800UL + axis;
  524. command.axis = axis;
  525. command.opcode = PLSR_CMD_SET_POSITION;
  526. command.argument = 0;
  527. result = PlsrPostCommand(&command);
  528. if (result != PLSR_RESULT_QUEUED)
  529. {
  530. return result;
  531. }
  532. (void)memset(&call, 0, sizeof(call));
  533. call.sequence = 0xA810UL + axis;
  534. call.source.context = NULL;
  535. call.source.validateWords = SelfTestValidateWords;
  536. call.source.readWord = SelfTestReadWord;
  537. call.source.readBit = SelfTestReadBit;
  538. call.s0.device = PLSR_DEVICE_D;
  539. call.s0.address = s0Base[axis];
  540. call.s1.device = PLSR_DEVICE_D;
  541. call.s1.address = s1Base[axis];
  542. call.s2.type = PLSR_OPERAND_CONSTANT;
  543. call.s2.constant = 1;
  544. call.dAxis = axis;
  545. call.outputModeOverride = PLSR_OUTPUT_PULSE_DIR;
  546. result = PlsrPostCall(&call);
  547. if (result != PLSR_RESULT_QUEUED)
  548. {
  549. return result;
  550. }
  551. }
  552. return PLSR_RESULT_QUEUED;
  553. }
  554. PLSR_RESULT PlsrCwCcwSelfTestQueue(void)
  555. {
  556. const uint16_t commonBase = 900U;
  557. const uint16_t setBase =
  558. (uint16_t)(commonBase + SELF_TEST_SFD_SET_OFFSET);
  559. PLSR_CALL call;
  560. PLSR_COMMAND command;
  561. PLSR_RESULT result;
  562. (void)memset(SelfTestWords, 0, sizeof(SelfTestWords));
  563. (void)PlcDeviceWriteSfd(commonBase, 0U);
  564. SelfTestWriteSfdDword((uint16_t)(commonBase + 2U), 1UL);
  565. SelfTestWriteSfdDword((uint16_t)(commonBase + 4U), 1UL);
  566. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 6U),
  567. SELF_TEST_DIR_POINT);
  568. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 7U), 10U);
  569. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 8U), 0U);
  570. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 9U), 0U);
  571. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 12U), 0U);
  572. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 15U), 0xFFFFU);
  573. SelfTestWriteSfdDword(setBase, 2000UL);
  574. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 2U), 0U);
  575. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 3U), 0U);
  576. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 4U), 0U);
  577. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 5U), 0U);
  578. SelfTestWriteSfdDword((uint16_t)(setBase + 6U), 100000UL);
  579. SelfTestWriteSfdDword((uint16_t)(setBase + 8U), 1000UL);
  580. SelfTestWriteSfdDword((uint16_t)(setBase + 10U), 0UL);
  581. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 12U), 50U);
  582. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 13U), 0U);
  583. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 14U), 0U);
  584. SelfTestWriteSfdDword((uint16_t)(setBase + 16U), 2000UL);
  585. SelfTestWriteSfdDword((uint16_t)(setBase + 18U), 200UL);
  586. SelfTestWriteDword(PLSR_DEVICE_D, SELF_TEST_S0_BASE, 2U);
  587. SelfTestWriteDword(PLSR_DEVICE_D,
  588. SELF_TEST_S0_BASE + 10UL,
  589. 2000UL);
  590. SelfTestWriteDword(PLSR_DEVICE_D,
  591. SELF_TEST_S0_BASE + 12UL,
  592. 300UL);
  593. SelfTestWriteDword(PLSR_DEVICE_D,
  594. SELF_TEST_S0_BASE + 20UL,
  595. 1000UL);
  596. SelfTestWriteDword(PLSR_DEVICE_D,
  597. SELF_TEST_S0_BASE + 22UL,
  598. (uint32_t)(int32_t)-200);
  599. SelfTestWriteDword(PLSR_DEVICE_D, SELF_TEST_S1_BASE, 0U);
  600. (void)memset(&command, 0, sizeof(command));
  601. command.sequence = 0xA900UL;
  602. command.axis = 0U;
  603. command.opcode = PLSR_CMD_SET_POSITION;
  604. result = PlsrPostCommand(&command);
  605. if (result != PLSR_RESULT_QUEUED)
  606. {
  607. return result;
  608. }
  609. (void)memset(&call, 0, sizeof(call));
  610. call.sequence = 0xA901UL;
  611. call.source.context = NULL;
  612. call.source.validateWords = SelfTestValidateWords;
  613. call.source.readWord = SelfTestReadWord;
  614. call.source.readBit = SelfTestReadBit;
  615. call.s0.device = PLSR_DEVICE_D;
  616. call.s0.address = SELF_TEST_S0_BASE;
  617. call.s1.device = PLSR_DEVICE_D;
  618. call.s1.address = SELF_TEST_S1_BASE;
  619. call.s2.type = PLSR_OPERAND_CONSTANT;
  620. call.s2.constant = 1;
  621. call.dAxis = 0U;
  622. call.outputModeOverride = PLSR_OUTPUT_CW_CCW;
  623. return PlsrPostCall(&call);
  624. }
  625. PLSR_RESULT PlsrFastRefreshSelfTestQueue(void)
  626. {
  627. static const uint16_t s0Base[2] = {10U, 40U};
  628. static const uint16_t s1Base[2] = {160U, 164U};
  629. static const uint8_t directionPoint[2] = {4U, 3U};
  630. PLSR_CALL call;
  631. PLSR_COMMAND command;
  632. PLSR_RESULT result;
  633. uint16_t commonBase;
  634. uint16_t setBase;
  635. uint8_t axis;
  636. (void)memset(SelfTestWords, 0, sizeof(SelfTestWords));
  637. for (axis = 0U; axis < 2U; axis++)
  638. {
  639. commonBase = (uint16_t)(900U
  640. + (uint16_t)axis
  641. * SELF_TEST_SFD_AXIS_STRIDE);
  642. setBase = (uint16_t)(commonBase + SELF_TEST_SFD_SET_OFFSET);
  643. (void)PlcDeviceWriteSfd(commonBase, 0U);
  644. SelfTestWriteSfdDword((uint16_t)(commonBase + 2U), 1UL);
  645. SelfTestWriteSfdDword((uint16_t)(commonBase + 4U), 1UL);
  646. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 6U),
  647. directionPoint[axis]);
  648. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 7U), 10U);
  649. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 8U), 0U);
  650. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 9U), 0U);
  651. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 12U), 0U);
  652. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 15U), 0xFFFFU);
  653. SelfTestWriteSfdDword(setBase, 5000UL);
  654. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 2U), 100U);
  655. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 3U), 100U);
  656. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 4U), 0U);
  657. /* Linear curve keeps the 1ms/0.1ms update granularity visible. */
  658. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 5U), 0U);
  659. SelfTestWriteSfdDword((uint16_t)(setBase + 6U), 100000UL);
  660. SelfTestWriteSfdDword((uint16_t)(setBase + 8U), 100UL);
  661. SelfTestWriteSfdDword((uint16_t)(setBase + 10U), 100UL);
  662. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 12U), 50U);
  663. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 13U), 0U);
  664. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 14U),
  665. (axis == 0U) ? 0U : 2U);
  666. SelfTestWriteSfdDword((uint16_t)(setBase + 16U), 2000UL);
  667. SelfTestWriteSfdDword((uint16_t)(setBase + 18U), 200UL);
  668. SelfTestWriteDword(PLSR_DEVICE_D, s0Base[axis], 1U);
  669. SelfTestWriteDword(PLSR_DEVICE_D,
  670. (uint32_t)s0Base[axis] + 10UL,
  671. 5000UL);
  672. SelfTestWriteDword(PLSR_DEVICE_D,
  673. (uint32_t)s0Base[axis] + 12UL,
  674. 2000UL);
  675. SelfTestWriteDword(PLSR_DEVICE_D, s1Base[axis], 0U);
  676. (void)memset(&command, 0, sizeof(command));
  677. command.sequence = 0xAA00UL + axis;
  678. command.axis = axis;
  679. command.opcode = PLSR_CMD_SET_POSITION;
  680. result = PlsrPostCommand(&command);
  681. if (result != PLSR_RESULT_QUEUED)
  682. {
  683. return result;
  684. }
  685. (void)memset(&call, 0, sizeof(call));
  686. call.sequence = 0xAA10UL + axis;
  687. call.source.context = NULL;
  688. call.source.validateWords = SelfTestValidateWords;
  689. call.source.readWord = SelfTestReadWord;
  690. call.source.readBit = SelfTestReadBit;
  691. call.s0.device = PLSR_DEVICE_D;
  692. call.s0.address = s0Base[axis];
  693. call.s1.device = PLSR_DEVICE_D;
  694. call.s1.address = s1Base[axis];
  695. call.s2.type = PLSR_OPERAND_CONSTANT;
  696. call.s2.constant = 1;
  697. call.dAxis = axis;
  698. call.outputModeOverride = PLSR_OUTPUT_PULSE_DIR;
  699. result = PlsrPostCall(&call);
  700. if (result != PLSR_RESULT_QUEUED)
  701. {
  702. return result;
  703. }
  704. }
  705. return PLSR_RESULT_QUEUED;
  706. }
  707. PLSR_RESULT PlsrDynamicFrequencySelfTestQueue(void)
  708. {
  709. const uint16_t commonBase = 900U;
  710. const uint16_t setBase =
  711. (uint16_t)(commonBase + SELF_TEST_SFD_SET_OFFSET);
  712. PLSR_CALL call;
  713. PLSR_COMMAND command;
  714. PLSR_RESULT result;
  715. (void)memset(SelfTestWords, 0, sizeof(SelfTestWords));
  716. PlsrSelfTestLiveFrequencyHz = 1000;
  717. PlsrSelfTestDynamicTick100us = 0UL;
  718. PlsrSelfTestDynamicPhase = 0U;
  719. PlsrSelfTestDynamicEnabled = 1U;
  720. PlsrSetControlTickHook(PlsrSelfTestControlTick100us);
  721. (void)PlcDeviceWriteSfd(commonBase, 0U);
  722. SelfTestWriteSfdDword((uint16_t)(commonBase + 2U), 1UL);
  723. SelfTestWriteSfdDword((uint16_t)(commonBase + 4U), 1UL);
  724. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 6U), 4U);
  725. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 7U), 10U);
  726. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 8U), 0U);
  727. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 9U), 0U);
  728. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 12U), 0U);
  729. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 15U), 0xFFFFU);
  730. /* 1000Hz default, 5000Hz maximum, 10Hz/ms slope, 0.1ms refresh. */
  731. SelfTestWriteSfdDword(setBase, 1000UL);
  732. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 2U), 100U);
  733. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 3U), 100U);
  734. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 4U), 0U);
  735. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 5U), 0U);
  736. SelfTestWriteSfdDword((uint16_t)(setBase + 6U), 5000UL);
  737. SelfTestWriteSfdDword((uint16_t)(setBase + 8U), 1000UL);
  738. SelfTestWriteSfdDword((uint16_t)(setBase + 10U), 0UL);
  739. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 12U), 50U);
  740. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 13U), 0U);
  741. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 14U), 2U);
  742. SelfTestWriteSfdDword((uint16_t)(setBase + 16U), 2000UL);
  743. SelfTestWriteSfdDword((uint16_t)(setBase + 18U), 200UL);
  744. SelfTestWriteDword(PLSR_DEVICE_D, SELF_TEST_S0_BASE, 1U);
  745. SelfTestWriteDword(PLSR_DEVICE_D,
  746. SELF_TEST_S0_BASE + 10UL,
  747. 1000UL);
  748. SelfTestWriteDword(PLSR_DEVICE_D,
  749. SELF_TEST_S0_BASE + 12UL,
  750. 100000UL);
  751. SelfTestWriteDword(PLSR_DEVICE_D, SELF_TEST_S1_BASE, 0U);
  752. (void)memset(&command, 0, sizeof(command));
  753. command.sequence = 0xAB00UL;
  754. command.axis = 0U;
  755. command.opcode = PLSR_CMD_SET_POSITION;
  756. result = PlsrPostCommand(&command);
  757. if (result != PLSR_RESULT_QUEUED)
  758. {
  759. return result;
  760. }
  761. (void)memset(&call, 0, sizeof(call));
  762. call.sequence = 0xAB01UL;
  763. call.source.context = NULL;
  764. call.source.validateWords = SelfTestValidateWords;
  765. call.source.readWord = SelfTestReadWord;
  766. call.source.readDword = SelfTestReadDwordLive;
  767. call.source.readBit = SelfTestReadBit;
  768. call.s0.device = PLSR_DEVICE_D;
  769. call.s0.address = SELF_TEST_S0_BASE;
  770. call.s1.device = PLSR_DEVICE_D;
  771. call.s1.address = SELF_TEST_S1_BASE;
  772. call.s2.type = PLSR_OPERAND_CONSTANT;
  773. call.s2.constant = 1;
  774. call.dAxis = 0U;
  775. call.outputModeOverride = PLSR_OUTPUT_PULSE_DIR;
  776. return PlsrPostCall(&call);
  777. }
  778. PLSR_RESULT PlsrModbusDataSelfTestQueue(void)
  779. {
  780. const uint16_t commonBase = 900U;
  781. const uint16_t setBase =
  782. (uint16_t)(commonBase + SELF_TEST_SFD_SET_OFFSET);
  783. uint16_t s0Words[20] = {0U};
  784. uint16_t s1Words[4] = {0U};
  785. PLSR_CALL call;
  786. PLSR_COMMAND command;
  787. PLSR_RESULT result;
  788. /* P12 uses D1000 as S0 and D1100 as S1. D1010/D1011 is the live
  789. * current-segment frequency written atomically by Modbus function 0x10. */
  790. s0Words[0] = 1U;
  791. s0Words[10] = 1000U;
  792. s0Words[11] = 0U;
  793. s0Words[12] = (uint16_t)(100000UL & 0xFFFFUL);
  794. s0Words[13] = (uint16_t)(100000UL >> 16U);
  795. if ((ModbusDataWriteWords(MODBUS_DATA_DEVICE_D,
  796. SELF_TEST_MODBUS_S0_BASE,
  797. s0Words,
  798. 20UL) == 0U)
  799. || (ModbusDataWriteWords(MODBUS_DATA_DEVICE_D,
  800. SELF_TEST_MODBUS_S1_BASE,
  801. s1Words,
  802. 4UL) == 0U))
  803. {
  804. return PLSR_RESULT_DATA_ACCESS;
  805. }
  806. (void)PlcDeviceWriteSfd(commonBase, 0U);
  807. SelfTestWriteSfdDword((uint16_t)(commonBase + 2U), 1UL);
  808. SelfTestWriteSfdDword((uint16_t)(commonBase + 4U), 1UL);
  809. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 6U), 4U);
  810. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 7U), 10U);
  811. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 8U), 0U);
  812. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 9U), 0U);
  813. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 12U), 0U);
  814. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 15U), 0xFFFFU);
  815. /* Same limits as P11: 1000Hz default, 5000Hz maximum, 10Hz/ms ramp,
  816. * and a 0.1ms live-frequency refresh. */
  817. SelfTestWriteSfdDword(setBase, 1000UL);
  818. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 2U), 100U);
  819. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 3U), 100U);
  820. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 4U), 0U);
  821. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 5U), 0U);
  822. SelfTestWriteSfdDword((uint16_t)(setBase + 6U), 5000UL);
  823. SelfTestWriteSfdDword((uint16_t)(setBase + 8U), 1000UL);
  824. SelfTestWriteSfdDword((uint16_t)(setBase + 10U), 0UL);
  825. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 12U), 50U);
  826. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 13U), 0U);
  827. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 14U), 2U);
  828. SelfTestWriteSfdDword((uint16_t)(setBase + 16U), 2000UL);
  829. SelfTestWriteSfdDword((uint16_t)(setBase + 18U), 200UL);
  830. (void)memset(&command, 0, sizeof(command));
  831. command.sequence = 0xAC00UL;
  832. command.axis = 0U;
  833. command.opcode = PLSR_CMD_SET_POSITION;
  834. result = PlsrPostCommand(&command);
  835. if (result != PLSR_RESULT_QUEUED)
  836. {
  837. return result;
  838. }
  839. (void)memset(&call, 0, sizeof(call));
  840. call.sequence = 0xAC01UL;
  841. PlsrModbusDataSourceInit(&call.source);
  842. call.s0.device = PLSR_DEVICE_D;
  843. call.s0.address = SELF_TEST_MODBUS_S0_BASE;
  844. call.s1.device = PLSR_DEVICE_D;
  845. call.s1.address = SELF_TEST_MODBUS_S1_BASE;
  846. call.s2.type = PLSR_OPERAND_CONSTANT;
  847. call.s2.constant = 1;
  848. call.dAxis = 0U;
  849. call.outputModeOverride = PLSR_OUTPUT_PULSE_DIR;
  850. return PlsrPostCall(&call);
  851. }
  852. PLSR_RESULT PlsrModbusControlSelfTestPrepare(void)
  853. {
  854. const uint16_t commonBase = 900U;
  855. const uint16_t setBase =
  856. (uint16_t)(commonBase + SELF_TEST_SFD_SET_OFFSET);
  857. (void)PlcDeviceWriteSfd(commonBase, 0U);
  858. SelfTestWriteSfdDword((uint16_t)(commonBase + 2U), 1UL);
  859. SelfTestWriteSfdDword((uint16_t)(commonBase + 4U), 1UL);
  860. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 6U), 4U);
  861. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 7U), 10U);
  862. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 8U), 0U);
  863. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 9U), 0U);
  864. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 12U), 0U);
  865. (void)PlcDeviceWriteSfd((uint16_t)(commonBase + 15U), 0xFFFFU);
  866. /* K1: 1000Hz default/start, 5000Hz maximum, 100ms ramps, 1ms refresh. */
  867. SelfTestWriteSfdDword(setBase, 1000UL);
  868. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 2U), 100U);
  869. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 3U), 100U);
  870. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 4U), 0U);
  871. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 5U), 0U);
  872. SelfTestWriteSfdDword((uint16_t)(setBase + 6U), 5000UL);
  873. SelfTestWriteSfdDword((uint16_t)(setBase + 8U), 1000UL);
  874. SelfTestWriteSfdDword((uint16_t)(setBase + 10U), 0UL);
  875. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 12U), 50U);
  876. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 13U), 0U);
  877. (void)PlcDeviceWriteSfd((uint16_t)(setBase + 14U), 0U);
  878. SelfTestWriteSfdDword((uint16_t)(setBase + 16U), 2000UL);
  879. SelfTestWriteSfdDword((uint16_t)(setBase + 18U), 200UL);
  880. return PLSR_RESULT_OK;
  881. }