1 /* 2 * Copyright 2024 Fabian Blatz <fabianblatz@gmail.com> 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #ifndef ZEPHYR_DRIVER_STEPPER_STEP_DIR_STEPPER_COMMON_H_ 8 #define ZEPHYR_DRIVER_STEPPER_STEP_DIR_STEPPER_COMMON_H_ 9 10 /** 11 * @brief Stepper Driver APIs 12 * @defgroup step_dir_stepper Stepper Driver APIs 13 * @ingroup io_interfaces 14 * @{ 15 */ 16 17 #include <zephyr/device.h> 18 #include <zephyr/drivers/gpio.h> 19 #include <zephyr/drivers/stepper.h> 20 #include <zephyr/drivers/counter.h> 21 22 #include "step_dir_stepper_timing_source.h" 23 24 /** 25 * @brief Common step direction stepper config. 26 * 27 * This structure **must** be placed first in the driver's config structure. 28 */ 29 struct step_dir_stepper_common_config { 30 const struct gpio_dt_spec step_pin; 31 const struct gpio_dt_spec dir_pin; 32 bool dual_edge; 33 const struct stepper_timing_source_api *timing_source; 34 const struct device *counter; 35 }; 36 37 /** 38 * @brief Initialize common step direction stepper config from devicetree instance. 39 * If the counter property is set, the timing source will be set to the counter timing 40 * source. 41 * 42 * @param node_id The devicetree node identifier. 43 */ 44 #define STEP_DIR_STEPPER_DT_COMMON_CONFIG_INIT(node_id) \ 45 { \ 46 .step_pin = GPIO_DT_SPEC_GET(node_id, step_gpios), \ 47 .dir_pin = GPIO_DT_SPEC_GET(node_id, dir_gpios), \ 48 .dual_edge = DT_PROP_OR(node_id, dual_edge_step, false), \ 49 .counter = DEVICE_DT_GET_OR_NULL(DT_PHANDLE(node_id, counter)), \ 50 .timing_source = COND_CODE_1(DT_NODE_HAS_PROP(node_id, counter), \ 51 (&step_counter_timing_source_api), \ 52 (&step_work_timing_source_api)), \ 53 } 54 55 /** 56 * @brief Initialize common step direction stepper config from devicetree instance. 57 * @param inst Instance. 58 */ 59 #define STEP_DIR_STEPPER_DT_INST_COMMON_CONFIG_INIT(inst) \ 60 STEP_DIR_STEPPER_DT_COMMON_CONFIG_INIT(DT_DRV_INST(inst)) 61 62 /** 63 * @brief Common step direction stepper data. 64 * 65 * This structure **must** be placed first in the driver's data structure. 66 */ 67 struct step_dir_stepper_common_data { 68 const struct device *dev; 69 struct k_spinlock lock; 70 enum stepper_direction direction; 71 enum stepper_run_mode run_mode; 72 int32_t actual_position; 73 uint32_t max_velocity; 74 int32_t step_count; 75 stepper_event_callback_t callback; 76 void *event_cb_user_data; 77 78 struct k_work_delayable stepper_dwork; 79 80 #ifdef CONFIG_STEP_DIR_STEPPER_COUNTER_TIMING 81 struct counter_top_cfg counter_top_cfg; 82 bool counter_running; 83 #endif /* CONFIG_STEP_DIR_STEPPER_COUNTER_TIMING */ 84 85 #ifdef CONFIG_STEPPER_STEP_DIR_GENERATE_ISR_SAFE_EVENTS 86 struct k_work event_callback_work; 87 struct k_msgq event_msgq; 88 uint8_t event_msgq_buffer[CONFIG_STEPPER_STEP_DIR_EVENT_QUEUE_LEN * 89 sizeof(enum stepper_event)]; 90 #endif /* CONFIG_STEPPER_STEP_DIR_GENERATE_ISR_SAFE_EVENTS */ 91 }; 92 93 /** 94 * @brief Initialize common step direction stepper data from devicetree instance. 95 * 96 * @param node_id The devicetree node identifier. 97 */ 98 #define STEP_DIR_STEPPER_DT_COMMON_DATA_INIT(node_id) \ 99 { \ 100 .dev = DEVICE_DT_GET(node_id), \ 101 } 102 103 /** 104 * @brief Initialize common step direction stepper data from devicetree instance. 105 * @param inst Instance. 106 */ 107 #define STEP_DIR_STEPPER_DT_INST_COMMON_DATA_INIT(inst) \ 108 STEP_DIR_STEPPER_DT_COMMON_DATA_INIT(DT_DRV_INST(inst)) 109 110 /** 111 * @brief Validate the offset of the common data structures. 112 * 113 * @param config Name of the config structure. 114 * @param data Name of the data structure. 115 */ 116 #define STEP_DIR_STEPPER_STRUCT_CHECK(config, data) \ 117 BUILD_ASSERT(offsetof(config, common) == 0, \ 118 "struct step_dir_stepper_common_config must be placed first"); \ 119 BUILD_ASSERT(offsetof(data, common) == 0, \ 120 "struct step_dir_stepper_common_data must be placed first"); 121 122 /** 123 * @brief Common function to initialize a step direction stepper device at init time. 124 * 125 * This function must be called at the end of the device init function. 126 * 127 * @param dev Step direction stepper device instance. 128 * 129 * @retval 0 If initialized successfully. 130 * @retval -errno Negative errno in case of failure. 131 */ 132 int step_dir_stepper_common_init(const struct device *dev); 133 134 /** 135 * @brief Move the stepper motor by a given number of micro_steps. 136 * 137 * @param dev Pointer to the device structure. 138 * @param micro_steps Number of micro_steps to move. Can be positive or negative. 139 * @return 0 on success, or a negative error code on failure. 140 */ 141 int step_dir_stepper_common_move_by(const struct device *dev, const int32_t micro_steps); 142 143 /** 144 * @brief Set the maximum velocity in micro_steps per second. 145 * 146 * @param dev Pointer to the device structure. 147 * @param velocity Maximum velocity in micro_steps per second. 148 * @return 0 on success, or a negative error code on failure. 149 */ 150 int step_dir_stepper_common_set_max_velocity(const struct device *dev, const uint32_t velocity); 151 152 /** 153 * @brief Set the reference position of the stepper motor. 154 * 155 * @param dev Pointer to the device structure. 156 * @param value The reference position value to set. 157 * @return 0 on success, or a negative error code on failure. 158 */ 159 int step_dir_stepper_common_set_reference_position(const struct device *dev, const int32_t value); 160 161 /** 162 * @brief Get the actual (reference) position of the stepper motor. 163 * 164 * @param dev Pointer to the device structure. 165 * @param value Pointer to a variable where the position value will be stored. 166 * @return 0 on success, or a negative error code on failure. 167 */ 168 int step_dir_stepper_common_get_actual_position(const struct device *dev, int32_t *value); 169 170 /** 171 * @brief Set the absolute target position of the stepper motor. 172 * 173 * @param dev Pointer to the device structure. 174 * @param value The target position to set. 175 * @return 0 on success, or a negative error code on failure. 176 */ 177 int step_dir_stepper_common_move_to(const struct device *dev, const int32_t value); 178 179 /** 180 * @brief Check if the stepper motor is still moving. 181 * 182 * @param dev Pointer to the device structure. 183 * @param is_moving Pointer to a boolean where the movement status will be stored. 184 * @return 0 on success, or a negative error code on failure. 185 */ 186 int step_dir_stepper_common_is_moving(const struct device *dev, bool *is_moving); 187 188 /** 189 * @brief Run the stepper with a given velocity in a given direction. 190 * 191 * @param dev Pointer to the device structure. 192 * @param direction The direction of movement (positive or negative). 193 * @param velocity The velocity in micro_steps per second. 194 * @return 0 on success, or a negative error code on failure. 195 */ 196 int step_dir_stepper_common_run(const struct device *dev, const enum stepper_direction direction, 197 const uint32_t velocity); 198 199 /** 200 * @brief Set a callback function for stepper motor events. 201 * 202 * This function sets a user-defined callback that will be invoked when a stepper motor event 203 * occurs. 204 * 205 * @param dev Pointer to the device structure. 206 * @param callback The callback function to set. 207 * @param user_data Pointer to user-defined data that will be passed to the callback. 208 * @return 0 on success, or a negative error code on failure. 209 */ 210 int step_dir_stepper_common_set_event_callback(const struct device *dev, 211 stepper_event_callback_t callback, void *user_data); 212 213 /** 214 * @brief Handle a timing signal and update the stepper position. 215 * @param dev Pointer to the device structure. 216 */ 217 void stepper_handle_timing_signal(const struct device *dev); 218 219 /** @} */ 220 221 #endif /* ZEPHYR_DRIVER_STEPPER_STEP_DIR_STEPPER_COMMON_H_ */ 222