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.
195 lines
6.6 KiB
195 lines
6.6 KiB
/* |
|
* SPDX-FileCopyrightText: Copyright (c) 2024 Fabian Blatz <fabianblatz@gmail.com> |
|
* SPDX-License-Identifier: Apache-2.0 |
|
*/ |
|
|
|
#include "../step_dir/step_dir_stepper_common.h" |
|
|
|
#include <zephyr/logging/log.h> |
|
LOG_MODULE_REGISTER(tmc22xx, CONFIG_STEPPER_LOG_LEVEL); |
|
|
|
#define MSX_PIN_COUNT 2 |
|
#define MSX_PIN_STATE_COUNT 4 |
|
|
|
struct tmc22xx_config { |
|
struct step_dir_stepper_common_config common; |
|
const struct gpio_dt_spec enable_pin; |
|
const struct gpio_dt_spec *msx_pins; |
|
enum stepper_micro_step_resolution *msx_resolutions; |
|
}; |
|
|
|
struct tmc22xx_data { |
|
struct step_dir_stepper_common_data common; |
|
enum stepper_micro_step_resolution resolution; |
|
}; |
|
|
|
STEP_DIR_STEPPER_STRUCT_CHECK(struct tmc22xx_config, struct tmc22xx_data); |
|
|
|
static int tmc22xx_stepper_enable(const struct device *dev, const bool enable) |
|
{ |
|
const struct tmc22xx_config *config = dev->config; |
|
|
|
LOG_DBG("Stepper motor controller %s %s", dev->name, enable ? "enabled" : "disabled"); |
|
if (enable) { |
|
return gpio_pin_set_dt(&config->enable_pin, 1); |
|
} else { |
|
return gpio_pin_set_dt(&config->enable_pin, 0); |
|
} |
|
} |
|
|
|
static int tmc22xx_stepper_set_micro_step_res(const struct device *dev, |
|
enum stepper_micro_step_resolution micro_step_res) |
|
{ |
|
struct tmc22xx_data *data = dev->data; |
|
const struct tmc22xx_config *config = dev->config; |
|
int ret; |
|
|
|
if (!config->msx_pins) { |
|
LOG_ERR("Microstep resolution pins are not configured"); |
|
return -ENODEV; |
|
} |
|
|
|
for (uint8_t i = 0; i < MSX_PIN_STATE_COUNT; i++) { |
|
if (micro_step_res != config->msx_resolutions[i]) { |
|
continue; |
|
} |
|
|
|
ret = gpio_pin_set_dt(&config->msx_pins[0], i & 0x01); |
|
if (ret < 0) { |
|
LOG_ERR("Failed to set MS1 pin: %d", ret); |
|
return ret; |
|
} |
|
|
|
ret = gpio_pin_set_dt(&config->msx_pins[1], (i & 0x02) >> 1); |
|
if (ret < 0) { |
|
LOG_ERR("Failed to set MS2 pin: %d", ret); |
|
return ret; |
|
} |
|
|
|
data->resolution = micro_step_res; |
|
return 0; |
|
} |
|
|
|
LOG_ERR("Unsupported microstep resolution: %d", micro_step_res); |
|
return -EINVAL; |
|
} |
|
|
|
static int tmc22xx_stepper_get_micro_step_res(const struct device *dev, |
|
enum stepper_micro_step_resolution *micro_step_res) |
|
{ |
|
struct tmc22xx_data *data = dev->data; |
|
|
|
*micro_step_res = data->resolution; |
|
return 0; |
|
} |
|
|
|
static int tmc22xx_stepper_configure_msx_pins(const struct device *dev) |
|
{ |
|
const struct tmc22xx_config *config = dev->config; |
|
int ret; |
|
|
|
for (uint8_t i = 0; i < MSX_PIN_COUNT; i++) { |
|
if (!gpio_is_ready_dt(&config->msx_pins[i])) { |
|
LOG_ERR("MSX pin %u are not ready", i); |
|
return -ENODEV; |
|
} |
|
|
|
ret = gpio_pin_configure_dt(&config->msx_pins[i], GPIO_OUTPUT); |
|
if (ret < 0) { |
|
LOG_ERR("Failed to configure msx pin %u", i); |
|
return ret; |
|
} |
|
} |
|
return 0; |
|
} |
|
|
|
static int tmc22xx_stepper_init(const struct device *dev) |
|
{ |
|
const struct tmc22xx_config *config = dev->config; |
|
struct tmc22xx_data *data = dev->data; |
|
int ret; |
|
|
|
if (!gpio_is_ready_dt(&config->enable_pin)) { |
|
LOG_ERR("GPIO pins are not ready"); |
|
return -ENODEV; |
|
} |
|
|
|
ret = gpio_pin_configure_dt(&config->enable_pin, GPIO_OUTPUT); |
|
if (ret < 0) { |
|
LOG_ERR("Failed to configure enable pin: %d", ret); |
|
return ret; |
|
} |
|
|
|
if (config->msx_pins) { |
|
ret = tmc22xx_stepper_configure_msx_pins(dev); |
|
if (ret < 0) { |
|
LOG_ERR("Failed to configure MSX pins: %d", ret); |
|
return ret; |
|
} |
|
|
|
ret = tmc22xx_stepper_set_micro_step_res(dev, data->resolution); |
|
if (ret < 0) { |
|
LOG_ERR("Failed to set microstep resolution: %d", ret); |
|
return ret; |
|
} |
|
} |
|
|
|
ret = step_dir_stepper_common_init(dev); |
|
if (ret < 0) { |
|
LOG_ERR("Failed to init step dir common stepper: %d", ret); |
|
return ret; |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
static DEVICE_API(stepper, tmc22xx_stepper_api) = { |
|
.enable = tmc22xx_stepper_enable, |
|
.move_by = step_dir_stepper_common_move_by, |
|
.is_moving = step_dir_stepper_common_is_moving, |
|
.set_reference_position = step_dir_stepper_common_set_reference_position, |
|
.get_actual_position = step_dir_stepper_common_get_actual_position, |
|
.move_to = step_dir_stepper_common_move_to, |
|
.set_max_velocity = step_dir_stepper_common_set_max_velocity, |
|
.run = step_dir_stepper_common_run, |
|
.set_event_callback = step_dir_stepper_common_set_event_callback, |
|
.set_micro_step_res = tmc22xx_stepper_set_micro_step_res, |
|
.get_micro_step_res = tmc22xx_stepper_get_micro_step_res, |
|
}; |
|
|
|
#define TMC22XX_STEPPER_DEFINE(inst, msx_table) \ |
|
IF_ENABLED(DT_INST_NODE_HAS_PROP(inst, msx_gpios), ( \ |
|
static const struct gpio_dt_spec tmc22xx_stepper_msx_pins_##inst[] = { \ |
|
DT_INST_FOREACH_PROP_ELEM_SEP( \ |
|
inst, msx_gpios, GPIO_DT_SPEC_GET_BY_IDX, (,) \ |
|
), \ |
|
}; \ |
|
BUILD_ASSERT( \ |
|
ARRAY_SIZE(tmc22xx_stepper_msx_pins_##inst) == MSX_PIN_COUNT, \ |
|
"Two microstep config pins needed"); \ |
|
)) \ |
|
\ |
|
static const struct tmc22xx_config tmc22xx_config_##inst = { \ |
|
.common = STEP_DIR_STEPPER_DT_INST_COMMON_CONFIG_INIT(inst), \ |
|
.enable_pin = GPIO_DT_SPEC_INST_GET(inst, en_gpios), \ |
|
.msx_resolutions = msx_table, \ |
|
IF_ENABLED(DT_INST_NODE_HAS_PROP(inst, msx_gpios), \ |
|
(.msx_pins = tmc22xx_stepper_msx_pins_##inst)) \ |
|
}; \ |
|
static struct tmc22xx_data tmc22xx_data_##inst = { \ |
|
.common = STEP_DIR_STEPPER_DT_INST_COMMON_DATA_INIT(inst), \ |
|
.resolution = DT_INST_PROP(inst, micro_step_res), \ |
|
}; \ |
|
DEVICE_DT_INST_DEFINE(inst, tmc22xx_stepper_init, NULL, &tmc22xx_data_##inst, \ |
|
&tmc22xx_config_##inst, POST_KERNEL, CONFIG_STEPPER_INIT_PRIORITY, \ |
|
&tmc22xx_stepper_api); |
|
|
|
#define DT_DRV_COMPAT adi_tmc2209 |
|
static enum stepper_micro_step_resolution tmc2209_msx_resolutions[MSX_PIN_STATE_COUNT] = { |
|
STEPPER_MICRO_STEP_8, |
|
STEPPER_MICRO_STEP_32, |
|
STEPPER_MICRO_STEP_64, |
|
STEPPER_MICRO_STEP_16, |
|
}; |
|
DT_INST_FOREACH_STATUS_OKAY_VARGS(TMC22XX_STEPPER_DEFINE, tmc2209_msx_resolutions) |
|
#undef DT_DRV_COMPAT
|
|
|