This repository has been archived on 2026-06-17. You can view files and clone it, but cannot push or open issues or pull requests.
FireWatchTower_2axis/firmware/lib/tmc/ic/TMC2660/TMC2660.c

154 lines
5.3 KiB
C
Executable File

/*******************************************************************************
* Copyright © 2019 TRINAMIC Motion Control GmbH & Co. KG
* (now owned by Analog Devices Inc.),
*
* Copyright © 2024 Analog Devices Inc. All Rights Reserved.
* This software is proprietary to Analog Devices, Inc. and its licensors.
*******************************************************************************/
#include "TMC2660.h"
/**************************************************************** Cache Implementation *************************************************************************/
#if TMC2660_CACHE == 0
static inline bool tmc2660_cache(uint16_t icID, TMC2660CacheOp operation, uint8_t address, uint32_t *value)
{
UNUSED(icID);
UNUSED(address);
UNUSED(operation);
return false;
}
#else
#if TMC2660_ENABLE_TMC_CACHE == 1
int32_t tmc2660_shadowRegister[TMC2660_IC_CACHE_COUNT][TMC2660_REGISTER_COUNT];
/*
* This function is used to cache the value written to the Write-Only registers in the form of shadow array.
* The shadow copy is then used to read these kinds of registers.
*/
bool tmc2660_cache(uint16_t icID, TMC2660CacheOp operation, uint8_t address, uint32_t *value)
{
if (operation == TMC2660_CACHE_READ)
{
// Check if the value should come from cache
// Only supported chips have a cache
if (icID >= TMC2660_IC_CACHE_COUNT)
return false;
// Only non-readable registers care about caching
// Note: This could also be used to cache i.e. RW config registers to reduce bus accesses
if (TMC2660_IS_READABLE(tmc2660_registerAccess[address]))
return false;
// Grab the value from the cache
*value = tmc2660_shadowRegister[icID][address];
return true;
}
else if (operation == TMC2660_CACHE_WRITE || operation == TMC2660_CACHE_FILL_DEFAULT)
{
// Fill the cache
// only supported chips have a cache
if (icID >= TMC2660_IC_CACHE_COUNT)
return false;
// Write to the shadow register
tmc2660_shadowRegister[icID][address] = *value;
return true;
}
return false;
}
#else
// User must implement their own cache
extern bool tmc2660_cache(uint16_t icID, TMC2660CacheOp operation, uint8_t address, uint32_t *value);
#endif
#endif
/************************************************************** Register read / write Implementation ******************************************************************/
void readWrite(uint8_t icID, uint32_t datagram)
{
uint8_t data[3] = {0};
uint32_t reply;
uint8_t rdsel = TMC2660_GET_RDSEL(datagram);
data[0] = 0xFF & (datagram >> 16);
data[1] = 0xFF & (datagram >> 8);
data[2] = 0xFF & (datagram >> 0);
// Send 24 bytes of data and receive reply
tmc2660_readWriteSPI(icID, &data[0], sizeof(data));
reply = (data[0] << 16 | data[1] << 8 | data[2]) >> 4;
// write value to response shadow register
tmc2660_shadowRegister[icID][rdsel] = reply;
// Store the latest response value to extract status bits in tmc2660_getStatusBits()
tmc2660_shadowRegister[icID][TMC2660_RESPONSE_LATEST] = reply;
// write value to response shadow register
if (TMC2660_GET_ADDRESS(datagram) == TMC2660_DRVCONF)
rdsel = TMC2660_GET_RDSEL(datagram);
// write value to shadow register
tmc2660_shadowRegister[icID][TMC2660_GET_ADDRESS(datagram) | TMC2660_WRITE_BIT] = datagram;
}
void readImmediately(uint8_t icID, uint8_t rdsel)
{
// sets desired reply in DRVCONF register, resets it to previous settings whilst reading desired reply
uint32_t value;
// additional reading to keep all replies up to date
value = tmc2660_readRegister(0, TMC2660_DRVCONF); // buffer (value and drvConf) to write back later
value &= ~TMC2660_SET_RDSEL(-1); // clear RDSEL bits
value |= TMC2660_SET_RDSEL(rdsel % 3); // set rdsel
readWrite(icID, value); // write to chip and readout reply
readWrite(icID, value); // write to chip and return desired reply
}
void tmc2660_writeRegister(uint8_t icID, uint8_t address, uint32_t value)
{
// Don't write to read-only registers
if (TMC2660_IS_READONLY_REGISTER(address))
return;
// Extract 20 bits of valid data
value &= 0x0FFFFF;
//Cache the registers with write-only access
tmc2660_cache(icID, TMC2660_CACHE_WRITE, address, &value);
// 0XF7 to mask the write bit
if (!tmc2660_getcontinuousModeEnable(icID))
readWrite(icID, TMC2660_DATAGRAM((address & 0xF7), value));
}
uint32_t tmc2660_readRegister(uint8_t icID, uint8_t address)
{
uint32_t value;
// Read from cache for registers with write-only access
if (tmc2660_cache(icID, TMC2660_CACHE_READ, address, &value))
return value;
if (!tmc2660_getcontinuousModeEnable(icID))
{
// Read the read-only register, refreshing the cache
readImmediately(icID, address);
}
// Return the read-only register from cache
return tmc2660_shadowRegister[icID][address];
}
uint8_t tmc2660_getStatusBits(uint8_t icID)
{
// Grab the status bits from the last request
return tmc2660_shadowRegister[icID][TMC2660_RESPONSE_LATEST] & TMC2660_STATUS_MASK;
}