1 /*
2 * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: CC0-1.0
5 */
6
7 #include <freertos/FreeRTOS.h>
8 #include <freertos/task.h>
9 #include <string.h>
10 #include "hal/gpio_types.h"
11 #include "driver/gpio.h"
12 #include "esp_check.h"
13 #include "step_motor_driver_io_a4988.h"
14
15 static const char *TAG = "A4988_IO";
16
17 #define A4988_RESPONSE_DELAY_MS 10
18
a4988_init(step_motor_driver_io_t * handle)19 static esp_err_t a4988_init(step_motor_driver_io_t *handle)
20 {
21 step_motor_driver_io_a4988_t *a4988_motor = __containerof(handle, step_motor_driver_io_a4988_t, base);
22 gpio_config_t io_conf;
23 io_conf.intr_type = GPIO_INTR_DISABLE;
24 io_conf.mode = GPIO_MODE_OUTPUT;
25 //bit mask of the pins that you want to set,e.g.GPIO18/19
26 io_conf.pin_bit_mask = BIT64(a4988_motor->conf.direction_pin) |
27 BIT64(a4988_motor->conf.sleep_pin) |
28 BIT64(a4988_motor->conf.reset_pin) |
29 BIT64(a4988_motor->conf.ms3_pin) |
30 BIT64(a4988_motor->conf.ms2_pin) |
31 BIT64(a4988_motor->conf.ms1_pin) |
32 BIT64(a4988_motor->conf.enable_pin);
33 io_conf.pull_down_en = 0;
34 io_conf.pull_up_en = 0;
35 ESP_ERROR_CHECK(gpio_config(&io_conf));
36
37 ESP_ERROR_CHECK(gpio_set_level(a4988_motor->conf.direction_pin, 0));
38 ESP_ERROR_CHECK(gpio_set_level(a4988_motor->conf.sleep_pin, 0)); // default sleep
39 ESP_ERROR_CHECK(gpio_set_level(a4988_motor->conf.reset_pin, 0)); // keep reset
40 ESP_ERROR_CHECK(gpio_set_level(a4988_motor->conf.ms3_pin, 0)); // 1/1 phase
41 ESP_ERROR_CHECK(gpio_set_level(a4988_motor->conf.ms2_pin, 0));
42 ESP_ERROR_CHECK(gpio_set_level(a4988_motor->conf.ms1_pin, 0));
43 ESP_ERROR_CHECK(gpio_set_level(a4988_motor->conf.enable_pin, 1)); // disable by default
44 vTaskDelay(pdMS_TO_TICKS(A4988_RESPONSE_DELAY_MS));
45 ESP_ERROR_CHECK(gpio_set_level(a4988_motor->conf.reset_pin, 1));
46 ESP_ERROR_CHECK(gpio_set_level(a4988_motor->conf.sleep_pin, 1));
47 ESP_ERROR_CHECK(gpio_set_level(a4988_motor->conf.enable_pin, 0));
48 vTaskDelay(pdMS_TO_TICKS(A4988_RESPONSE_DELAY_MS));
49 return ESP_OK;
50 }
51
a4988_set_direction(step_motor_driver_io_t * handle,step_direction direction)52 static esp_err_t a4988_set_direction(step_motor_driver_io_t *handle, step_direction direction)
53 {
54 step_motor_driver_io_a4988_t *a4988_motor = __containerof(handle, step_motor_driver_io_a4988_t, base);
55 ESP_ERROR_CHECK(gpio_set_level(a4988_motor->conf.direction_pin, direction));
56 return ESP_OK;
57 }
58
a4988_enable_sleep(step_motor_driver_io_t * handle,bool enabled)59 static esp_err_t a4988_enable_sleep(step_motor_driver_io_t *handle, bool enabled)
60 {
61 step_motor_driver_io_a4988_t *a4988_motor = __containerof(handle, step_motor_driver_io_a4988_t, base);
62 ESP_ERROR_CHECK(gpio_set_level(a4988_motor->conf.sleep_pin, enabled));
63 return ESP_OK;
64 }
65
a4988_enable_output(step_motor_driver_io_t * handle,bool enabled)66 static esp_err_t a4988_enable_output(step_motor_driver_io_t *handle, bool enabled)
67 {
68 step_motor_driver_io_a4988_t *a4988_motor = __containerof(handle, step_motor_driver_io_a4988_t, base);
69 ESP_ERROR_CHECK(gpio_set_level(a4988_motor->conf.enable_pin, enabled));
70 return ESP_OK;
71 }
72
a4988_set_microstep(step_motor_driver_io_t * handle,uint16_t microstep)73 static esp_err_t a4988_set_microstep(step_motor_driver_io_t *handle, uint16_t microstep)
74 {
75 step_motor_driver_io_a4988_t *a4988_motor = __containerof(handle, step_motor_driver_io_a4988_t, base);
76 switch (microstep) {
77 case 1:
78 ESP_ERROR_CHECK(gpio_set_level(a4988_motor->conf.ms3_pin, 0));
79 ESP_ERROR_CHECK(gpio_set_level(a4988_motor->conf.ms2_pin, 0));
80 ESP_ERROR_CHECK(gpio_set_level(a4988_motor->conf.ms1_pin, 0));
81 break;
82 case 2:
83 ESP_ERROR_CHECK(gpio_set_level(a4988_motor->conf.ms3_pin, 0));
84 ESP_ERROR_CHECK(gpio_set_level(a4988_motor->conf.ms2_pin, 0));
85 ESP_ERROR_CHECK(gpio_set_level(a4988_motor->conf.ms1_pin, 1));
86 break;
87 case 4:
88 ESP_ERROR_CHECK(gpio_set_level(a4988_motor->conf.ms3_pin, 0));
89 ESP_ERROR_CHECK(gpio_set_level(a4988_motor->conf.ms2_pin, 1));
90 ESP_ERROR_CHECK(gpio_set_level(a4988_motor->conf.ms1_pin, 0));
91 break;
92 case 8:
93 ESP_ERROR_CHECK(gpio_set_level(a4988_motor->conf.ms3_pin, 0));
94 ESP_ERROR_CHECK(gpio_set_level(a4988_motor->conf.ms2_pin, 1));
95 ESP_ERROR_CHECK(gpio_set_level(a4988_motor->conf.ms1_pin, 1));
96 break;
97 case 16:
98 ESP_ERROR_CHECK(gpio_set_level(a4988_motor->conf.ms3_pin, 1));
99 ESP_ERROR_CHECK(gpio_set_level(a4988_motor->conf.ms2_pin, 1));
100 ESP_ERROR_CHECK(gpio_set_level(a4988_motor->conf.ms1_pin, 1));
101 break;
102 default:
103 return ESP_ERR_NOT_SUPPORTED;
104 }
105 return ESP_OK;
106 }
107
a4988_reset(step_motor_driver_io_t * handle)108 static esp_err_t a4988_reset(step_motor_driver_io_t *handle)
109 {
110 step_motor_driver_io_a4988_t *a4988_motor = __containerof(handle, step_motor_driver_io_a4988_t, base);
111 ESP_ERROR_CHECK(gpio_set_level(a4988_motor->conf.reset_pin, 0));
112 vTaskDelay(pdMS_TO_TICKS(A4988_RESPONSE_DELAY_MS));
113 ESP_ERROR_CHECK(gpio_set_level(a4988_motor->conf.reset_pin, 1));
114 return ESP_OK;
115 }
116
a4988_deinit(step_motor_driver_io_t * handle)117 static esp_err_t a4988_deinit(step_motor_driver_io_t *handle)
118 {
119 step_motor_driver_io_a4988_t *a4988_motor = __containerof(handle, step_motor_driver_io_a4988_t, base);
120 gpio_config_t io_conf;
121 io_conf.intr_type = GPIO_INTR_DISABLE;
122 io_conf.mode = GPIO_MODE_INPUT;
123 io_conf.pin_bit_mask = BIT64(a4988_motor->conf.direction_pin) |
124 BIT64(a4988_motor->conf.sleep_pin) |
125 BIT64(a4988_motor->conf.reset_pin) |
126 BIT64(a4988_motor->conf.ms3_pin) |
127 BIT64(a4988_motor->conf.ms2_pin) |
128 BIT64(a4988_motor->conf.ms1_pin) |
129 BIT64(a4988_motor->conf.enable_pin);
130 io_conf.pull_down_en = 0;
131 io_conf.pull_up_en = 0;
132 ESP_ERROR_CHECK(gpio_config(&io_conf));
133 return ESP_OK;
134 }
135
step_motor_new_a4988_io_driver(const step_motor_io_a4988_conf_t * conf,step_motor_driver_io_handle_t * handle)136 esp_err_t step_motor_new_a4988_io_driver(const step_motor_io_a4988_conf_t *conf, step_motor_driver_io_handle_t *handle)
137 {
138 esp_err_t ret = ESP_OK;
139 step_motor_driver_io_a4988_t *a4988 = NULL;
140 ESP_GOTO_ON_FALSE(conf, ESP_ERR_INVALID_ARG, err, TAG, "configuration can't be null");
141 ESP_GOTO_ON_FALSE(handle, ESP_ERR_INVALID_ARG, err, TAG, "can't assign handle to null");
142
143 a4988 = calloc(1, sizeof(step_motor_driver_io_a4988_t));
144 ESP_GOTO_ON_FALSE(a4988, ESP_ERR_NO_MEM, err, TAG, "allocate context memory failed");
145 memcpy(&a4988->conf, conf, sizeof(step_motor_io_a4988_conf_t));
146
147 a4988->base.init = a4988_init;
148 a4988->base.deinit = a4988_deinit;
149 a4988->base.set_direction = a4988_set_direction;
150 a4988->base.set_microstep = a4988_set_microstep;
151 a4988->base.enable_sleep = a4988_enable_sleep;
152 a4988->base.enable_output = a4988_enable_output;
153 a4988->base.trigger_reset = a4988_reset;
154 a4988->base.step_triggered_edge = 1;
155 a4988->base.pulse_high_period_us = 1;
156 a4988->base.pulse_low_period_us = 1;
157
158 *handle = &(a4988->base);
159 return ESP_OK;
160
161 err:
162 if (a4988) {
163 free(a4988);
164 }
165 return ret;
166 }
167
step_motor_delete_a4988_io_driver(step_motor_driver_io_handle_t handle)168 esp_err_t step_motor_delete_a4988_io_driver(step_motor_driver_io_handle_t handle)
169 {
170 ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_STATE, TAG, "empty handle");
171 step_motor_driver_io_a4988_t *a4988 = __containerof(handle, step_motor_driver_io_a4988_t, base);
172 free(a4988);
173 return ESP_OK;
174 }
175