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