This repository has been archived by the owner on Aug 27, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 199
/
dda.h
199 lines (159 loc) · 6.87 KB
/
dda.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
#ifndef _DDA_H
#define _DDA_H
#include <stdint.h>
#include "config_wrapper.h"
#ifdef ACCELERATION_REPRAP
#ifdef ACCELERATION_RAMPING
#error Cant use ACCELERATION_REPRAP and ACCELERATION_RAMPING together.
#endif
#endif
// The distance of any move and a single axis should never go above this limit.
// Check move_duration and c_limit calculations in dda.c
#define MAX_DELTA_UM ((int32_t)(UINT32_MAX / 2400L))
// Enum to denote an axis
enum axis_e { X = 0, Y, Z, E, AXIS_COUNT };
/**
\typedef axes_uint32_t
\brief n-dimensional vector used to describe uint32_t axis information.
Stored value can be anything unsigned. Units should be specified when declared.
*/
typedef uint32_t axes_uint32_t[AXIS_COUNT];
/**
\typedef axes_int32_t
\brief n-dimensional vector used to describe int32_t axis information.
Stored value can be anything unsigned. Units should be specified when declared.
*/
typedef int32_t axes_int32_t[AXIS_COUNT];
/**
\struct TARGET
\brief target is simply a point in space/time
X, Y, Z and E are in micrometers unless explcitely stated. F is in mm/min.
*/
typedef struct {
axes_int32_t axis;
uint32_t F;
uint16_t e_multiplier;
uint16_t f_multiplier;
uint8_t e_relative :1; ///< bool: e axis relative? Overrides all_relative
} TARGET;
/**
\struct MOVE_STATE
\brief this struct is made for tracking the current state of the movement
Parts of this struct are initialised only once per reboot, so make sure dda_step() leaves them with a value compatible to begin a new movement at the end of the movement. Other parts are filled in by dda_start().
*/
typedef struct {
// bresenham counters
axes_int32_t counter; ///< counter for total_steps vs each axis
#ifdef ACCELERATION_TEMPORAL
axes_uint32_t time; ///< time of the last step on each axis
uint32_t last_time; ///< time of the last step of any axis
#endif
axes_uint32_t steps; ///< number of steps on each axis
/// Endstop handling.
uint8_t endstop_stop; ///< Stop due to endstop trigger
uint8_t debounce_count_x, debounce_count_y, debounce_count_z;
} MOVE_STATE;
/**
\struct DDA
\brief this is a digital differential analyser data struct
This struct holds all the details of an individual multi-axis move, including pre-calculated acceleration data.
This struct is filled in by dda_create(), called from enqueue(), called mostly from gcode_process() and from a few other places too (eg \file homing.c)
*/
typedef struct {
/// this is where we should finish
TARGET endpoint;
union {
struct {
// status fields
uint8_t nullmove :1; ///< bool: no axes move, maybe we wait for temperatures or change speed
volatile uint8_t live :1; ///< bool: this DDA is running and still has steps to do
uint8_t done :1; ///< bool: this DDA is done.
#ifdef ACCELERATION_REPRAP
uint8_t accel :1; ///< bool: speed changes during this move, run accel code
#endif
// directions
// As we have muldiv() now, overflows became much less an issue and
// it's likely time to get rid of these flags and use int instead of
// uint for distance/speed calculations. --Traumflug 2014-07-04
uint8_t x_direction :1; ///< direction flag for X axis
uint8_t y_direction :1; ///< direction flag for Y axis
uint8_t z_direction :1; ///< direction flag for Z axis
uint8_t e_direction :1; ///< direction flag for E axis
};
uint16_t allflags; ///< used for clearing all flags
};
// distances
axes_uint32_t delta; ///< number of steps on each axis
// uint8_t fast_axis; (see below)
uint32_t total_steps; ///< steps of the "fast" axis
uint32_t fast_um; ///< movement length of this fast axis
uint32_t c; ///< time until next step, 24.8 fixed point
#ifdef ACCELERATION_REPRAP
uint32_t end_c; ///< time between 2nd last step and last step
int32_t n; ///< precalculated step time offset variable
#endif
#ifdef ACCELERATION_RAMPING
/// precalculated step time offset variable
int32_t n;
/// number of steps accelerating
uint32_t rampup_steps;
/// number of last step before decelerating
uint32_t rampdown_steps;
/// 24.8 fixed point timer value, maximum speed
uint32_t c_min;
#ifdef LOOKAHEAD
// With the look-ahead functionality, it is possible to retain physical
// movement between G1 moves. These variables keep track of the entry and
// exit speeds between moves.
uint32_t distance;
uint32_t crossF;
// These two are based on the "fast" axis, the axis with the most steps.
uint32_t start_steps; ///< would be required to reach start feedrate
uint32_t end_steps; ///< would be required to stop from end feedrate
#endif
// Number the moves to be able to test at the end of lookahead if the moves
// are the same. Note: we do not need a lot of granularity here: more than
// MOVEBUFFER_SIZE is already enough.
uint8_t id;
#endif
#ifdef ACCELERATION_TEMPORAL
axes_uint32_t step_interval; ///< time between steps on each axis
uint8_t axis_to_step; ///< axis to be stepped on the next interrupt
#endif
/// Small variables. Many CPUs can access 32-bit variables at word or double
/// word boundaries only and fill smaller variables in between with gaps,
/// so keep small variables grouped together to reduce the amount of these
/// gaps. See e.g. NXP application note AN10963, page 10f.
uint8_t fast_axis; ///< number of the fast axis
/// Endstop homing
uint8_t endstop_check; ///< Do we need to check endstops? 0x1=Check X, 0x2=Check Y, 0x4=Check Z
uint8_t endstop_stop_cond; ///< Endstop condition on which to stop motion: 0=Stop on detrigger, 1=Stop on trigger
} DDA;
/*
variables
*/
/// startpoint holds the endpoint of the most recently created DDA, so we know where the next one created starts. could also be called last_endpoint
extern TARGET startpoint;
/// the same as above, counted in motor steps
extern TARGET startpoint_steps;
/// current_position holds the machine's current position. this is only updated when we step, or when G92 (set home) is received.
extern TARGET current_position;
/*
methods
*/
int8_t get_direction(DDA *dda, enum axis_e n);
// initialize dda structures
void dda_init(void);
// distribute a new startpoint
void dda_new_startpoint(void);
// create a DDA
void dda_create(DDA *dda, const TARGET *target);
// start a created DDA (called from timer interrupt)
void dda_start(DDA *dda);
// DDA takes one step (called from timer interrupt)
void dda_step(DDA *dda);
// regular movement maintenance
void dda_clock(void);
// update current_position
void update_current_position(void);
#endif /* _DDA_H */