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
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
//! GCONF - Global configuration register (0x00)
use super::{Address, ReadableRegister, Register, WritableRegister};
/// Global configuration register.
///
/// Controls general driver settings including analog current scaling,
/// internal/external sense resistors, chopper mode selection, and more.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Gconf(u32);
impl Gconf {
/// Create a new GCONF with default value.
///
/// Default: 0x00000040 (pdn_disable=1 for UART operation)
pub fn new() -> Self {
Self(0x00000040)
}
/// I_scale_analog: Use voltage supplied to VREF as current reference.
///
/// - `true`: Use external VREF voltage
/// - `false`: Use internal reference derived from 5VOUT
pub fn i_scale_analog(&self) -> bool {
self.0 & (1 << 0) != 0
}
/// Set I_scale_analog.
pub fn set_i_scale_analog(&mut self, value: bool) -> &mut Self {
if value {
self.0 |= 1 << 0;
} else {
self.0 &= !(1 << 0);
}
self
}
/// Internal Rsense: Use internal sense resistors.
///
/// - `true`: Use internal sense resistors
/// - `false`: Use external sense resistors on BRA/BRB pins
pub fn internal_rsense(&self) -> bool {
self.0 & (1 << 1) != 0
}
/// Set internal_rsense.
pub fn set_internal_rsense(&mut self, value: bool) -> &mut Self {
if value {
self.0 |= 1 << 1;
} else {
self.0 &= !(1 << 1);
}
self
}
/// Enable SpreadCycle mode.
///
/// - `true`: SpreadCycle mode enabled
/// - `false`: StealthChop PWM mode enabled (if configured)
pub fn en_spreadcycle(&self) -> bool {
self.0 & (1 << 2) != 0
}
/// Set en_spreadcycle.
pub fn set_en_spreadcycle(&mut self, value: bool) -> &mut Self {
if value {
self.0 |= 1 << 2;
} else {
self.0 &= !(1 << 2);
}
self
}
/// Shaft: Inverse motor direction.
///
/// - `true`: Inverse direction
/// - `false`: Normal direction
pub fn shaft(&self) -> bool {
self.0 & (1 << 3) != 0
}
/// Set shaft (motor direction).
pub fn set_shaft(&mut self, value: bool) -> &mut Self {
if value {
self.0 |= 1 << 3;
} else {
self.0 &= !(1 << 3);
}
self
}
/// Index output shows OTPW (overtemperature prewarning).
///
/// - `true`: INDEX outputs OTPW
/// - `false`: INDEX outputs first microstep position
pub fn index_otpw(&self) -> bool {
self.0 & (1 << 4) != 0
}
/// Set index_otpw.
pub fn set_index_otpw(&mut self, value: bool) -> &mut Self {
if value {
self.0 |= 1 << 4;
} else {
self.0 &= !(1 << 4);
}
self
}
/// Index output shows step pulses.
///
/// - `true`: INDEX shows step pulses (toggles on each step)
/// - `false`: INDEX as selected by index_otpw
pub fn index_step(&self) -> bool {
self.0 & (1 << 5) != 0
}
/// Set index_step.
pub fn set_index_step(&mut self, value: bool) -> &mut Self {
if value {
self.0 |= 1 << 5;
} else {
self.0 &= !(1 << 5);
}
self
}
/// PDN_UART disable.
///
/// **Must be set to `true` when using UART interface.**
///
/// - `true`: PDN_UART input disabled, UART interface enabled
/// - `false`: PDN_UART controls standstill current reduction
pub fn pdn_disable(&self) -> bool {
self.0 & (1 << 6) != 0
}
/// Set pdn_disable.
pub fn set_pdn_disable(&mut self, value: bool) -> &mut Self {
if value {
self.0 |= 1 << 6;
} else {
self.0 &= !(1 << 6);
}
self
}
/// Microstep resolution selected by MRES register.
///
/// - `true`: MRES bits in CHOPCONF select resolution
/// - `false`: MS1/MS2 pins select resolution
pub fn mstep_reg_select(&self) -> bool {
self.0 & (1 << 7) != 0
}
/// Set mstep_reg_select.
pub fn set_mstep_reg_select(&mut self, value: bool) -> &mut Self {
if value {
self.0 |= 1 << 7;
} else {
self.0 &= !(1 << 7);
}
self
}
/// Multistep filter enable.
///
/// - `true`: Step pulse optimization enabled for >750Hz
/// - `false`: Disabled
pub fn multistep_filt(&self) -> bool {
self.0 & (1 << 8) != 0
}
/// Set multistep_filt.
pub fn set_multistep_filt(&mut self, value: bool) -> &mut Self {
if value {
self.0 |= 1 << 8;
} else {
self.0 &= !(1 << 8);
}
self
}
/// Test mode (do not use).
///
/// **Must be set to `false` for normal operation.**
pub fn test_mode(&self) -> bool {
self.0 & (1 << 9) != 0
}
/// Set test_mode.
pub fn set_test_mode(&mut self, value: bool) -> &mut Self {
if value {
self.0 |= 1 << 9;
} else {
self.0 &= !(1 << 9);
}
self
}
/// DIAG0 output shows stall (StallGuard).
///
/// When enabled, DIAG0 (active low) indicates a stall condition.
/// Used for sensorless homing.
///
/// Note: This is an alias that combines the DIAG functionality.
/// The TMC2209 uses the DIAG pin for multiple purposes.
pub fn diag0_stall(&self) -> bool {
// In TMC2209, stall is indicated via DIAG when configured
// This is controlled by enabling the proper mode
self.0 & (1 << 4) == 0 && self.0 & (1 << 5) == 0
}
/// Enable DIAG0 output for stall indication.
///
/// This configures the DIAG pin to output stall detection
/// for sensorless homing applications.
pub fn set_diag0_stall(&mut self, value: bool) -> &mut Self {
if value {
// Clear index_otpw and index_step to enable stall output
self.0 &= !(1 << 4);
self.0 &= !(1 << 5);
}
self
}
/// Get the raw register value.
pub fn raw(&self) -> u32 {
self.0
}
/// Create from raw value.
pub fn from_raw(value: u32) -> Self {
Self(value)
}
}
impl Register for Gconf {
const ADDRESS: Address = Address::Gconf;
}
impl ReadableRegister for Gconf {}
impl WritableRegister for Gconf {}
impl From<u32> for Gconf {
fn from(value: u32) -> Self {
Self(value)
}
}
impl From<Gconf> for u32 {
fn from(reg: Gconf) -> u32 {
reg.0
}
}