You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

451 lines
16 KiB

12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
11 months ago
12 months ago
12 months ago
12 months ago
  1. #include "tmc51x0.hpp"
  2. #include "reg/TMC5130_Constants.h"
  3. #include "reg/TMC5130_Fields.h"
  4. #include "reg/TMC5130_Register.h"
  5. //
  6. using namespace iflytop;
  7. #if 0
  8. // Register access permissions:
  9. // 0x00: none (reserved)
  10. // 0x01: read
  11. // 0x02: write
  12. // 0x03: read/write
  13. // 0x13: read/write, separate functions/values for reading or writing
  14. // 0x21: read, flag register (read to clear)
  15. // 0x42: write, has hardware presets on reset
  16. static const uint8_t tmc5130_defaultRegisterAccess[TMC5130_REGISTER_COUNT] = {
  17. // 0 1 2 3 4 5 6 7 8 9 A B C D E F
  18. 0x03, 0x21, 0x01, 0x02, 0x13, 0x02, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, // 0x00 - 0x0F
  19. 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, // 0x10 - 0x1F
  20. 0x03, 0x03, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, ____, 0x02, 0x02, 0x02, 0x03, ____, ____, // 0x20 - 0x2F
  21. ____, ____, ____, 0x02, 0x03, 0x21, 0x01, ____, 0x03, 0x03, 0x02, 0x21, 0x01, ____, ____, ____, // 0x30 - 0x3F
  22. ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, // 0x40 - 0x4F
  23. ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, // 0x50 - 0x5F
  24. 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x01, 0x01, 0x03, 0x02, 0x02, 0x01, // 0x60 - 0x6F
  25. 0x42, 0x01, 0x02, 0x01, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____ // 0x70 - 0x7F
  26. };
  27. #endif
  28. /***********************************************************************************************************************
  29. * ? *
  30. ***********************************************************************************************************************/
  31. #define FIELD_SET(data, mask, shift, value) (data = (((data) & (~(mask))) | (((value) << (shift)) & (mask))))
  32. #define FIELD_GET(data, mask, shift) (((data) & (mask)) >> (shift))
  33. #define BYTE(value, n) (((value) >> ((n) << 3)) & 0xFF)
  34. #define NIBBLE(value, n) (((value) >> ((n) << 2)) & 0x0F)
  35. #define SHORT(value, n) (((value) >> ((n) << 4)) & 0xFFFF)
  36. #define WORD(value, n) (((value) >> ((n) << 5)) & 0xFFFFFFFF)
  37. #define TMC51x0_ADDRESS(x) ((x) & (TMC5130_ADDRESS_MASK))
  38. #define TAG "TMC51X0"
  39. void TMC51X0::initialize(int mid, TMC51X0Cfg cfg) {
  40. m_mid = mid;
  41. m_cfg = cfg;
  42. m_hspi = cfg.hspi;
  43. ZLOGI(TAG, "SPI:%p CSPin:%s,enPIn:%s", cfg.hspi, pinname(cfg.csnpin), pinname(cfg.ennpin));
  44. m_mutex.init();
  45. m_csnpin.initAsOutput(m_cfg.csnpin, kxs_gpio_nopull, false, true);
  46. m_ennpin.initAsOutput(m_cfg.ennpin, kxs_gpio_nopull, false, true);
  47. enable(false);
  48. stop();
  49. writeInt(TMC5130_PWMCONF, 0x000500C8);
  50. writeInt(TMC5130_CHOPCONF, 0x000100c3);
  51. writeInt(TMC5130_IHOLD_IRUN, 0x00051A00);
  52. writeInt(TMC5130_PWMCONF, 0x000401c8);
  53. writeInt(TMC5130_XTARGET, 0);
  54. writeInt(TMC5130_XACTUAL, 0x00000000);
  55. writeInt(TMC5130_VACTUAL, 0x00000000);
  56. writeInt(TMC5130_TZEROWAIT, 0);
  57. setVstart(100);
  58. setA1(30);
  59. setAmax(50);
  60. setV1(500);
  61. setDmax(50);
  62. setD1(30);
  63. setVstop(100);
  64. setTzerowait(100);
  65. setIHOLD_IRUN(0, 30, 100);
  66. enable(false);
  67. }
  68. /*******************************************************************************
  69. * *
  70. *******************************************************************************/
  71. void TMC51X0::readWriteArray(uint8_t *data, size_t length) {
  72. portENTER_CRITICAL();
  73. m_csnpin.write(false);
  74. HAL_SPI_TransmitReceive(m_hspi, data, data, length, 100);
  75. m_csnpin.write(true);
  76. portEXIT_CRITICAL();
  77. }
  78. void TMC51X0::writeDatagram(uint8_t address, uint8_t x1, uint8_t x2, uint8_t x3, uint8_t x4) {
  79. uint8_t data[5] = {static_cast<uint8_t>(address | static_cast<uint8_t>(TMC5130_WRITE_BIT)), x1, x2, x3, x4};
  80. readWriteArray(&data[0], 5);
  81. }
  82. void TMC51X0::writeInt(uint8_t address, int32_t value) { //
  83. writeDatagram(address, BYTE(value, 3), BYTE(value, 2), BYTE(value, 1), BYTE(value, 0));
  84. }
  85. void TMC51X0::writeField(uint8_t add, uint32_t mask, uint32_t shift, uint32_t value) {
  86. uint32_t regval = readUInt(add);
  87. regval = (regval & ~mask) | ((value << shift) & mask);
  88. writeInt(add, regval);
  89. }
  90. int32_t TMC51X0::readInt(uint8_t address) {
  91. /**
  92. * @WARNING:
  93. * ?
  94. */
  95. address = TMC51x0_ADDRESS(address);
  96. uint8_t data[5] = {0, 0, 0, 0, 0};
  97. data[0] = address;
  98. readWriteArray(&data[0], 5);
  99. data[0] = address;
  100. readWriteArray(&data[0], 5);
  101. return ((uint32_t)data[1] << 24) | ((uint32_t)data[2] << 16) | (data[3] << 8) | data[4];
  102. }
  103. uint32_t TMC51X0::readUInt(uint8_t address) {
  104. int32_t val = readInt(address);
  105. uint32_t ret;
  106. memcpy(&ret, &val, sizeof(uint32_t));
  107. return ret;
  108. }
  109. /***********************************************************************************************************************
  110. * BASIC *
  111. ***********************************************************************************************************************/
  112. bool TMC51X0::ping() {
  113. zlock_guard lkg(m_mutex);
  114. uint32_t regval = readUInt(TMC5130_IOIN);
  115. uint32_t chipId = FIELD_GET(regval, TMC5130_VERSION_MASK, TMC5130_VERSION_SHIFT);
  116. return chipId != 0;
  117. }
  118. void TMC51X0::enable(bool enable) {
  119. zlock_guard lkg(m_mutex);
  120. m_ennpin.write(!enable);
  121. }
  122. int32_t TMC51X0::to_motor_acc(int32_t acc) { //
  123. int32_t val = acc / 60.0 * m_onecirclepulse; // 65535
  124. if (val > 65535) val = 65535;
  125. return val;
  126. }
  127. int32_t TMC51X0::to_motor_vel(int32_t vel) { //
  128. int32_t val = vel / 60.0 * m_onecirclepulse;
  129. if (val > 8388095 /*2^23-512*/) {
  130. val = 8388095;
  131. }
  132. return val;
  133. } // rpm
  134. int32_t TMC51X0::to_motor_pos(int32_t pos) { //
  135. int32_t val = pos * 1.0 / m_scale * m_scale_deceleration * m_onecirclepulse + 0.5;
  136. return val;
  137. } //
  138. int32_t TMC51X0::to_user_pos(int32_t pos) { //
  139. int32_t val = pos / m_onecirclepulse * m_scale / m_scale_deceleration + 0.5;
  140. // ZLOGI("TMC5130", "to_user_pos %d,%d", pos, val);
  141. return val;
  142. } //
  143. int32_t TMC51X0::to_user_vel(int32_t vel) { //
  144. int32_t val = vel * 60.0 / m_onecirclepulse;
  145. return val;
  146. }
  147. /***********************************************************************************************************************
  148. * CTRL *
  149. ***********************************************************************************************************************/
  150. void TMC51X0::stop() {
  151. zlock_guard lkg(m_mutex);
  152. int mode = readInt(TMC5130_RAMPMODE);
  153. if (mode == TMC5130_MODE_POSITION) {
  154. // writeInt(TMC5130_RAMPMODE, TMC5130_MODE_POSITION);
  155. writeInt(TMC5130_VMAX, to_motor_vel(300));
  156. writeInt(TMC5130_XTARGET, readInt(TMC5130_XACTUAL));
  157. } else {
  158. rotate(0);
  159. }
  160. // rotate(0);
  161. }
  162. void TMC51X0::rotate(int32_t velocity) {
  163. zlock_guard lkg(m_mutex);
  164. velocity = to_motor_vel(velocity);
  165. writeInt(TMC5130_VMAX, abs(velocity));
  166. writeInt(TMC5130_RAMPMODE, (velocity >= 0) ? TMC5130_MODE_VELPOS : TMC5130_MODE_VELNEG);
  167. }
  168. void TMC51X0::moveTo(int32_t position, uint32_t velocityMax) {
  169. zlock_guard lkg(m_mutex);
  170. position = to_motor_pos(position);
  171. velocityMax = to_motor_vel(velocityMax);
  172. writeInt(TMC5130_RAMPMODE, TMC5130_MODE_POSITION);
  173. writeInt(TMC5130_VMAX, velocityMax);
  174. writeInt(TMC5130_XTARGET, position);
  175. }
  176. void TMC51X0::moveToEnd(int32_t direction, uint32_t velocityMax) {
  177. zlock_guard lkg(m_mutex);
  178. if (direction >= 0) {
  179. writeInt(TMC5130_RAMPMODE, TMC5130_MODE_POSITION);
  180. writeInt(TMC5130_VMAX, to_motor_vel(velocityMax));
  181. writeInt(TMC5130_XTARGET, INT32_MAX / 1.5 - 1000);
  182. } else {
  183. writeInt(TMC5130_RAMPMODE, TMC5130_MODE_POSITION);
  184. writeInt(TMC5130_VMAX, to_motor_vel(velocityMax));
  185. writeInt(TMC5130_XTARGET, INT32_MIN / 1.5 + 1000);
  186. }
  187. }
  188. void TMC51X0::moveBy(int32_t relativePosition, uint32_t velocityMax) { // determine actual position and add numbers of ticks to move
  189. zlock_guard lkg(m_mutex);
  190. // m_mid
  191. // ZLOGI(TAG, "m[%d] moveBy %d,%d", m_mid, relativePosition, velocityMax);
  192. int32_t pos = getXACTUAL();
  193. int32_t target = pos + relativePosition;
  194. moveTo(target, velocityMax);
  195. }
  196. /***********************************************************************************************************************
  197. * GET STATE *
  198. ***********************************************************************************************************************/
  199. int32_t TMC51X0::getXACTUAL() {
  200. zlock_guard lkg(m_mutex);
  201. return to_user_pos(readInt(TMC5130_XACTUAL));
  202. }
  203. int32_t TMC51X0::getXactualRAW() {
  204. zlock_guard lkg(m_mutex);
  205. return readInt(TMC5130_XACTUAL);
  206. }
  207. int32_t TMC51X0::getVACTUAL() {
  208. zlock_guard lkg(m_mutex);
  209. return to_user_pos(readInt(TMC5130_VACTUAL));
  210. }
  211. int32_t TMC51X0::getEncVal() {
  212. zlock_guard lkg(m_mutex);
  213. int32_t enc_val = to_user_pos(readInt(TMC5130_XENC));
  214. if (m_enc_resolution < 0) {
  215. enc_val = -enc_val;
  216. }
  217. return enc_val;
  218. }
  219. TMC5130RampStat TMC51X0::getRampStat() {
  220. zlock_guard lkg(m_mutex);
  221. int32_t val = readInt(TMC5130_RAMPSTAT);
  222. return TMC5130RampStat(val);
  223. }
  224. bool TMC51X0::isReachTarget(TMC5130RampStat *state) {
  225. zlock_guard lkg(m_mutex);
  226. int mode = readInt(TMC5130_RAMPMODE);
  227. if (mode == TMC5130_MODE_POSITION) {
  228. return state->isSetted(TMC5130RampStat::ktmc5130_rs_posreached);
  229. } else {
  230. return state->isSetted(TMC5130RampStat::ktmc5130_rs_vzero) && state->isSetted(TMC5130RampStat::ktmc5130_rs_velreached);
  231. }
  232. }
  233. bool TMC51X0::isTMC5130() {
  234. zlock_guard lkg(m_mutex);
  235. uint32_t regval = readUInt(TMC5130_IOIN);
  236. uint32_t chipId = FIELD_GET(regval, TMC5130_VERSION_MASK, TMC5130_VERSION_SHIFT);
  237. return chipId == kTMC5130;
  238. }
  239. TMC5130DevStatusReg_t TMC51X0::getDevStatus() { // R
  240. zlock_guard lkg(m_mutex);
  241. static_assert(sizeof(TMC5130DevStatusReg_t) == 4);
  242. uint32_t value = readInt(TMC5130_DRVSTATUS);
  243. TMC5130DevStatusReg_t val;
  244. memcpy(&val, &value, sizeof(TMC5130DevStatusReg_t));
  245. return val;
  246. }
  247. TMC5130GState_t TMC51X0::getGState() { // R+C
  248. zlock_guard lkg(m_mutex);
  249. static_assert(sizeof(TMC5130GState_t) == 4);
  250. uint32_t value = readInt(TMC5130_GSTAT);
  251. TMC5130GState_t val;
  252. memcpy(&val, &value, sizeof(TMC5130GState_t));
  253. return val;
  254. }
  255. int32_t TMC51X0::readICVersion() {
  256. zlock_guard lkg(m_mutex);
  257. uint32_t regval = readUInt(TMC5130_IOIN);
  258. uint32_t chipId = FIELD_GET(regval, TMC5130_VERSION_MASK, TMC5130_VERSION_SHIFT);
  259. return chipId;
  260. }
  261. /***********************************************************************************************************************
  262. * set state *
  263. ***********************************************************************************************************************/
  264. void TMC51X0::setXACTUAL(int32_t value) {
  265. zlock_guard lkg(m_mutex);
  266. writeInt(TMC5130_XACTUAL, to_motor_pos(value));
  267. }
  268. void TMC51X0::setMotorShaft(bool reverse) {
  269. zlock_guard lkg(m_mutex);
  270. uint32_t regval = readUInt(TMC5130_GCONF);
  271. FIELD_SET(regval, TMC5130_SHAFT_MASK, TMC5130_SHAFT_SHIFT, reverse ? 1 : 0);
  272. writeInt(TMC5130_GCONF, regval);
  273. // uint32_t readbak = readUInt(TMC5130_GCONF);
  274. // ZLOGI(TAG, "%x,%x", regval, readbak);
  275. }
  276. void TMC51X0::setIHOLD_IRUN(uint8_t ihold, uint8_t irun, uint16_t iholddelay) {
  277. zlock_guard lkg(m_mutex);
  278. writeInt(TMC5130_IHOLD_IRUN, (iholddelay << TMC5130_IHOLDDELAY_SHIFT) | (irun << TMC5130_IRUN_SHIFT) | (ihold << TMC5130_IHOLD_SHIFT));
  279. }
  280. void TMC51X0::setGlobalScale(uint8_t globalscale) {
  281. #define TMC5160_GLOBAL_SCALER 0x0B
  282. #define TMC5160_GLOBAL_SCALER_MASK 0xFF
  283. #define TMC5160_GLOBAL_SCALER_SHIFT 0
  284. zlock_guard lkg(m_mutex);
  285. if (isTMC5130()) {
  286. return;
  287. }
  288. if (globalscale == 0) {
  289. globalscale = 0;
  290. } else if (globalscale <= 31 && globalscale >= 1) {
  291. globalscale = 32;
  292. } else {
  293. globalscale = globalscale;
  294. }
  295. writeInt(TMC5160_GLOBAL_SCALER, (readInt(TMC5160_GLOBAL_SCALER) & ~TMC5160_GLOBAL_SCALER_MASK) | (globalscale << TMC5160_GLOBAL_SCALER_SHIFT));
  296. }
  297. void TMC51X0::setScale(int32_t scale) {
  298. zlock_guard lkg(m_mutex);
  299. m_scale = scale;
  300. }
  301. void TMC51X0::setScaleDenominator(int32_t scale) {
  302. zlock_guard lkg(m_mutex);
  303. m_scale_deceleration = scale;
  304. }
  305. void TMC51X0::setVstart(int32_t val) {
  306. zlock_guard lkg(m_mutex);
  307. writeInt(TMC5130_VSTART, to_motor_vel(val));
  308. }
  309. void TMC51X0::setA1(int32_t val) {
  310. zlock_guard lkg(m_mutex);
  311. writeInt(TMC5130_A1, to_motor_acc(val));
  312. }
  313. void TMC51X0::setAmax(int32_t val) {
  314. zlock_guard lkg(m_mutex);
  315. writeInt(TMC5130_AMAX, to_motor_acc(val));
  316. }
  317. void TMC51X0::setV1(int32_t val) {
  318. zlock_guard lkg(m_mutex);
  319. writeInt(TMC5130_V1, to_motor_vel(val));
  320. }
  321. void TMC51X0::setDmax(int32_t val) {
  322. zlock_guard lkg(m_mutex);
  323. writeInt(TMC5130_DMAX, to_motor_acc(val));
  324. }
  325. void TMC51X0::setD1(int32_t val) {
  326. zlock_guard lkg(m_mutex);
  327. writeInt(TMC5130_D1, to_motor_acc(val));
  328. }
  329. void TMC51X0::setVstop(int32_t val) {
  330. zlock_guard lkg(m_mutex);
  331. writeInt(TMC5130_VSTOP, to_motor_vel(val));
  332. }
  333. void TMC51X0::setTzerowait(int32_t val) {
  334. zlock_guard lkg(m_mutex);
  335. writeInt(TMC5130_TZEROWAIT, val);
  336. }
  337. bool TMC51X0::setEncResolution(int32_t enc_resolution) {
  338. zlock_guard lkg(m_mutex);
  339. /**
  340. * @brief
  341. *
  342. */
  343. int32_t enc_resolution_tmp = enc_resolution * 4;
  344. int16_t enc_const_integral = 0;
  345. int16_t enc_const_fractional = 0;
  346. switch (abs(enc_resolution_tmp)) {
  347. case 1000:
  348. enc_const_integral = 51;
  349. enc_const_fractional = 0.2 * 10000;
  350. break;
  351. case 1024:
  352. enc_const_integral = 50;
  353. enc_const_fractional = 0 * 10000;
  354. break;
  355. case 4000:
  356. enc_const_integral = 12;
  357. enc_const_fractional = 0.8 * 10000;
  358. break;
  359. case 4096:
  360. enc_const_integral = 12;
  361. enc_const_fractional = 0.5 * 10000;
  362. break;
  363. case 16384:
  364. enc_const_integral = 3;
  365. enc_const_fractional = 0.125 * 10000;
  366. break;
  367. case 0:
  368. m_enc_resolution = 0;
  369. return true;
  370. default:
  371. return false;
  372. break;
  373. }
  374. m_enc_resolution = enc_resolution;
  375. uint32_t setval = 0;
  376. uint8_t *psetval = (uint8_t *)&setval;
  377. memcpy(psetval + 2, &enc_const_integral, 2);
  378. memcpy(psetval, &enc_const_fractional, 2);
  379. writeInt(TMC5130_ENCMODE, 0x1 << 10);
  380. writeInt(TMC5130_ENC_CONST, setval);
  381. return true;
  382. }
  383. void TMC51X0::setEncVal(int32_t enc_val) {
  384. zlock_guard lkg(m_mutex);
  385. int32_t enc_set_val = to_motor_pos(enc_val);
  386. if (m_enc_resolution < 0) {
  387. enc_set_val = -enc_set_val;
  388. }
  389. writeInt(TMC5130_XENC, enc_set_val);
  390. }
  391. /***********************************************************************************************************************
  392. * reg operation *
  393. ***********************************************************************************************************************/
  394. void TMC51X0::writeIntExt(uint8_t address, int32_t value) {
  395. zlock_guard lkg(m_mutex);
  396. writeInt(address, value);
  397. }
  398. int32_t TMC51X0::readIntExt(uint8_t address) {
  399. zlock_guard lkg(m_mutex);
  400. return readInt(address);
  401. }