|
|
#if 1
#include "ztmc4361A.hpp"
#ifdef HAL_SPI_MODULE_ENABLED
#include <stdarg.h>
#include "../basic/basic.hpp"
#include "./TMC4361A/TMC4361A.h"
#include "sdk/os/zos.hpp"
using namespace iflytop; #define PRV_FIELD_WRITE(address, mask, shift, value) (writeInt(address, FIELD_SET(readInt(address), mask, shift, value)))
#define PRV_FIELD_READ(address, mask, shift) FIELD_GET(readInt(address), mask, shift)
#define SET_PIN(pin, val) \
if (pin) { \ pin->setState(val); \ }
#if 1
void TMC4361A::readWriteArray(uint8_t *data, size_t length) { m_csgpio->setState(false); // zchip_clock_early_delayus(10);
zchip_clock_early_delayus(10); HAL_SPI_TransmitReceive(m_spi, data, data, length, 1000); m_csgpio->setState(true); } void TMC4361A::writeInt(uint8_t address, int32_t value) { writeDatagram(address, BYTE(value, 3), BYTE(value, 2), BYTE(value, 1), BYTE(value, 0)); } int32_t TMC4361A::readInt(uint8_t address) { CriticalContext cc;
int value; uint8_t data[5];
address = TMC_ADDRESS(address);
if (!TMC_IS_READABLE(m_registerAccessTable[address])) return m_defaultRegisterResetState[address];
data[0] = address; readWriteArray(&data[0], 5);
data[0] = address; readWriteArray(&data[0], 5);
m_status = data[0]; value = ((uint32_t)data[1] << 24) | ((uint32_t)data[2] << 16) | (data[3] << 8) | data[4];
return value; } void TMC4361A::writeDatagram(uint8_t address, uint8_t x1, uint8_t x2, uint8_t x3, uint8_t x4) { CriticalContext cc;
int value; uint8_t data[5] = {static_cast<uint8_t>(address | static_cast<uint8_t>(TMC4361A_WRITE_BIT)), x1, x2, x3, x4};
readWriteArray(&data[0], 5);
m_status = data[0];
value = ((uint32_t)x1 << 24) | ((uint32_t)x2 << 16) | (x3 << 8) | x4;
// Write to the shadow register and mark the register dirty
address = TMC_ADDRESS(address); shadowRegister[address] = value; }
void TMC4361A::readWriteCover(uint8_t *data, size_t length) { CriticalContext cc; // Buffering old values to not interrupt manual covering
int32_t old_high = shadowRegister[TMC4361A_COVER_HIGH_WR]; int32_t old_low = shadowRegister[TMC4361A_COVER_LOW_WR];
// Check if datagram length is valid
if (length == 0 || length > 8) return;
uint8_t bytes[8] = {0}; uint32_t tmp; size_t i;
// Copy data into buffer of maximum cover datagram length (8 bytes)
for (i = 0; i < length; i++) bytes[i] = data[length - i - 1];
// Send the datagram
if (length > 4) writeDatagram(TMC4361A_COVER_HIGH_WR, bytes[7], bytes[6], bytes[5], bytes[4]); writeDatagram(TMC4361A_COVER_LOW_WR, bytes[3], bytes[2], bytes[1], bytes[0]);
zos_delay(10);
// Read the reply
if (length > 4) { tmp = readInt(TMC4361A_COVER_DRV_HIGH_RD); bytes[4] = BYTE(tmp, 0); bytes[5] = BYTE(tmp, 1); bytes[6] = BYTE(tmp, 2); bytes[7] = BYTE(tmp, 3); } tmp = readInt(TMC4361A_COVER_DRV_LOW_RD); bytes[0] = BYTE(tmp, 0); bytes[1] = BYTE(tmp, 1); bytes[2] = BYTE(tmp, 2); bytes[3] = BYTE(tmp, 3);
// Write the reply to the data array
for (i = 0; i < length; i++) { data[length - i - 1] = bytes[i]; }
// Rewriting old values to prevent interrupting manual covering. Imitating unchanged values and state.
writeInt(TMC4361A_COVER_HIGH_WR, old_high); shadowRegister[TMC4361A_COVER_LOW_WR] = old_low; }
TMC4361A::TMC4361A(/* args */) { m_driver_ic_type = IC_TMC2130; m_lastCallPeriodicJobTick = 0; // m_reachtarget = false;
} /**
* @brief * ������TMC-API�е�tmc4361A_reset/restoreʱ����TMC-API�еķ�������ʼ������оƬ�ļĴ��� * ���Ĵ�����ʼ������֮��������������?? * ���ǿ��������������У���оƬ�IJ��ּĴ������г�ʼ��?? * @param state */ void TMC4361A::tmc4361AConfigCallback(ConfigState state) {}
void TMC4361A::writeSubRegister(uint8_t address, uint32_t mask, uint32_t shift, uint32_t value) { //
PRV_FIELD_WRITE(address, mask, shift, value); } void TMC4361A::setAcceleration(float accelerationpps2) { /**
* @brief * TMC4361A_AMAX:������ģʽ������ʹ�õ���Ƶ��ģʽ * * Frequency mode: [pulses per sec2]
* 22 digits and 2 decimal places: 250 mpps^2 ?? AMAX ?? 4 Mpps^2 * Direct mode: [?v per clk cycle] * a[?v per clk_cycle]= AMAX / 2^37 * AMAX [pps2] = AMAX / 237 ?? fCLK^2 */
int32_t acc = (int32_t)accelerationpps2; writeInt(TMC4361A_AMAX, acc << 2); } void TMC4361A::setDeceleration(float accelerationpps2) { /**
* @brief * TMC4361A_DMAX:������ģʽ������ʹ�õ���Ƶ��ģʽ * * Frequency mode: [pulses per sec2] * 22 digits and 2 decimal places: 250 mpps^2 ?? AMAX ?? 4 Mpps^2 * Direct mode: [?v per clk cycle] * a[?v per clk_cycle]= AMAX / 2^37 * AMAX [pps2] = AMAX / 237 ?? fCLK^2 */
int32_t acc = (int32_t)accelerationpps2; writeInt(TMC4361A_DMAX, acc << 2); }
void TMC4361A::initialize(cfg_t *cfg) { m_spi = cfg->spi; m_csgpio = cfg->csgpio; m_resetPin = cfg->resetPin; m_fREEZEPin = cfg->fREEZEPin; m_ennPin = cfg->ennPin; m_driverIC_resetPin = cfg->driverIC_resetPin; m_driverIC_ennPin = cfg->driverIC_ennPin;
m_driver_ic_type = IC_TMC2160; m_registerAccessTable = &tmc4361A_defaultRegisterAccess[0]; m_defaultRegisterResetState = &tmc4361A_defaultRegisterResetState[0];
memset(shadowRegister, 0, sizeof(shadowRegister));
SET_PIN(m_resetPin, true); SET_PIN(m_fREEZEPin, true); SET_PIN(m_ennPin, true);
reset();
driverIC_reset();
setAcceleration(500000); setDeceleration(500000);
enableIC(true); zchip_clock_early_delayus(300 * 1000); zchip_clock_early_delayus(300 * 1000);
driverIC_setIHOLD_IRUN(1, 3, 0); // ע��Ҫ������IHOLD������IRUN,���������ܲ�����
} uint8_t TMC4361A::reset() { // Pulse the low-active hardware reset pin
stop(); SET_PIN(m_resetPin, false); zchip_clock_early_delayus(1000); SET_PIN(m_resetPin, true);
/**
* @brief ����оƬ�����Ĵ�?? * */ for (uint32_t add = 0; add < TMC4361A_REGISTER_COUNT; add++) { if (!TMC_IS_RESETTABLE(m_registerAccessTable[add])) { continue; } writeInt(add, m_defaultRegisterResetState[add]); }
uint8_t driver, dataLength; uint32_t value; // Setup SPI
switch (m_driver_ic_type) { case IC_TMC2130: case IC_TMC2160: driver = 0x0C; dataLength = 0; break; case IC_TMC2660: driver = 0x0B; dataLength = 0; break; default: driver = 0x0F; dataLength = 40; break; } value = 0x44400040 | (dataLength << 13) | (driver << 0); writeInt(TMC4361A_SPIOUT_CONF, value); writeInt(TMC4361A_CURRENT_CONF, 0x00000003); writeInt(TMC4361A_SCALE_VALUES, 0x00000000); return 1; } uint8_t TMC4361A::restore() { return 1; }
int32_t TMC4361A::getXACTUAL() { return readInt(TMC4361A_XACTUAL); } void TMC4361A::setXACTUAL(int32_t value) { writeInt(TMC4361A_XACTUAL, value); } int32_t TMC4361A::getVACTUAL() { return readInt(TMC4361A_VACTUAL); } int32_t TMC4361A::getXTARGET() { return readInt(TMC4361A_X_TARGET); } int32_t TMC4361A::getENC_POS() { return readInt(TMC4361A_ENC_POS); } void TMC4361A::setENC_POS(int32_t value) { writeInt(TMC4361A_ENC_POS, value); } int32_t TMC4361A::getENC_POS_DEV() { return readInt(TMC4361A_ENC_POS_DEV_RD); } void TMC4361A::enableIC(bool enable) { SET_PIN(m_ennPin, !enable); SET_PIN(m_driverIC_ennPin, !enable); }
int32_t tmc4361A_discardVelocityDecimals(int32_t value) { if (abs(value) > 8000000) { value = (value < 0) ? -8000000 : 8000000; } return value << 8; } void TMC4361A::rotate(int32_t velocity) { m_motor_mode = kvelmode; PRV_FIELD_WRITE(TMC4361A_RAMPMODE, TMC4361A_OPERATION_MODE_MASK, TMC4361A_OPERATION_MODE_SHIFT, 0); writeInt(TMC4361A_VMAX, tmc4361A_discardVelocityDecimals(velocity)); } void TMC4361A::stop() { rotate(0); } void TMC4361A::moveTo(int32_t position, uint32_t velocityMax) { m_motor_mode = kposmode; PRV_FIELD_WRITE(TMC4361A_RAMPMODE, TMC4361A_OPERATION_MODE_MASK, TMC4361A_OPERATION_MODE_SHIFT, 1); writeInt(TMC4361A_VMAX, tmc4361A_discardVelocityDecimals(velocityMax)); writeInt(TMC4361A_X_TARGET, position); } void TMC4361A::moveBy(int32_t relativePosition, uint32_t velocityMax) { relativePosition += readInt(TMC4361A_XACTUAL); moveTo(relativePosition, velocityMax); }
int32_t TMC4361A::readICVersion() { int32_t value = readInt(TMC4361A_VERSION_NO_RD); return (value & TMC4361A_VERSION_NO_MASK) >> TMC4361A_VERSION_NO_SHIFT; }
int32_t TMC4361A::readSubICVersion() { return driverIC_readICVersion(); } /*******************************************************************************
* 2160 function end * *******************************************************************************/ uint32_t TMC4361A::readEVENTS() { uint32_t value = readInt(TMC4361A_EVENTS); return value; } uint32_t TMC4361A::haspassedms(uint32_t now, uint32_t last) { if (now >= last) { return now - last; } else { return 0xFFFFFFFF - last + now; } } bool TMC4361A::isReachTarget() { uint32_t value = readInt(TMC4361A_STATUS); if (m_motor_mode == kposmode) { return (value & TMC4361A_TARGET_REACHED_F_MASK) > 0; } else { return (value & TMC4361A_VEL_REACHED_F_MASK) && (readInt(TMC4361A_VMAX) == 0); } } /*******************************************************************************
* DRIVER_IC * *******************************************************************************/ #define DRIVER_ID_FIELD_READ(address, mask, shift) FIELD_GET(driverIC_readInt(address), mask, shift)
#define DRIVER_ID_FIELD_WRITE(address, mask, shift, value) (driverIC_writeInt(address, FIELD_SET(driverIC_readInt(address), mask, shift, value)))
void TMC4361A::driverIC_reset() { SET_PIN(m_driverIC_resetPin, false); zchip_clock_early_delayus(1000); SET_PIN(m_driverIC_resetPin, true); // Reset the dirty bits
int index = 0; while (true) { while ((index < TMC2160_REGISTER_COUNT) && !TMC_IS_RESTORABLE(tmc2160_defaultRegisterAccess[index])) { index++; } if (index >= TMC2160_REGISTER_COUNT) { break; } // printf("Resetting register %d\n", index);
driverIC_writeInt(index, tmc2160_defaultRegisterResetState[index]); index++; }
driverIC_writeInt(TMC2160_PWMCONF, 0xC40C001E); driverIC_writeInt(TMC2160_DRV_CONF, 0x00080400); }
void TMC4361A::driverIC_enableIC(bool enable) { SET_PIN(m_driverIC_ennPin, !enable); } void TMC4361A::driverIC_writeDatagram(uint8_t address, uint8_t x1, uint8_t x2, uint8_t x3, uint8_t x4) { uint8_t data[5] = {static_cast<uint8_t>(address | static_cast<uint8_t>(TMC2160_WRITE_BIT)), x1, x2, x3, x4}; readWriteCover(&data[0], 5); } void TMC4361A::driverIC_writeInt(uint8_t address, int32_t value) { driverIC_writeDatagram(address, BYTE(value, 3), BYTE(value, 2), BYTE(value, 1), BYTE(value, 0)); } int32_t TMC4361A::driverIC_readInt(uint8_t address) { address = TMC_ADDRESS(address); // register not readable -> shadow register copy
if (!TMC_IS_READABLE(tmc2160_defaultRegisterAccess[address])) return 0;
uint8_t data[5];
data[0] = address; readWriteCover(&data[0], 5);
data[0] = address; readWriteCover(&data[0], 5);
return ((uint32_t)data[1] << 24) | ((uint32_t)data[2] << 16) | (data[3] << 8) | data[4]; } void TMC4361A::driverIC_setMotorShaft(bool reverse) { //
int32_t val = reverse ? 1 : 0; DRIVER_ID_FIELD_WRITE(TMC2160_GCONF, TMC2160_SHAFT_MASK, TMC2160_SHAFT_SHIFT, val); }
uint32_t TMC4361A::driverIC_readICVersion() { int32_t value = driverIC_readInt(TMC2160_IOIN___OUTPUT); return (value & TMC2160_VERSION_MASK) >> TMC2160_VERSION_SHIFT; } void TMC4361A::driverIC_setIHOLD_IRUN(uint8_t ihold, uint8_t irun, uint16_t iholddelay) { driverIC_writeInt(TMC2160_IHOLD_IRUN, (iholddelay << TMC2160_IHOLDDELAY_SHIFT) | (irun << TMC2160_IRUN_SHIFT) | (ihold << TMC2160_IHOLD_SHIFT)); }
#endif
#endif
#endif
|