@@ -60,7 +60,7 @@ void common_hal_digitalio_digitalinout_deinit(digitalio_digitalinout_obj_t* self
60
60
void common_hal_digitalio_digitalinout_switch_to_input (
61
61
digitalio_digitalinout_obj_t * self , digitalio_pull_t pull ) {
62
62
self -> output = false;
63
-
63
+ // This also sets direction to input.
64
64
common_hal_digitalio_digitalinout_set_pull (self , pull );
65
65
}
66
66
@@ -69,13 +69,13 @@ void common_hal_digitalio_digitalinout_switch_to_output(
69
69
digitalio_drive_mode_t drive_mode ) {
70
70
const uint8_t pin = self -> pin -> pin ;
71
71
gpio_set_pin_pull_mode (pin , GPIO_PULL_OFF );
72
- gpio_set_pin_direction (pin , GPIO_DIRECTION_OUT );
73
-
74
72
// Turn on "strong" pin driving (more current available). See DRVSTR doc in datasheet.
75
73
hri_port_set_PINCFG_DRVSTR_bit (PORT , (enum gpio_port )GPIO_PORT (pin ), GPIO_PIN (pin ));
76
74
77
75
self -> output = true;
78
76
self -> open_drain = drive_mode == DRIVE_MODE_OPEN_DRAIN ;
77
+
78
+ // Direction is set in set_value. We don't need to do it here.
79
79
common_hal_digitalio_digitalinout_set_value (self , value );
80
80
}
81
81
@@ -86,16 +86,22 @@ digitalio_direction_t common_hal_digitalio_digitalinout_get_direction(
86
86
87
87
void common_hal_digitalio_digitalinout_set_value (
88
88
digitalio_digitalinout_obj_t * self , bool value ) {
89
+ const uint8_t pin = self -> pin -> pin ;
90
+ const uint8_t port = GPIO_PORT (pin );
91
+ const uint32_t pin_mask = 1U << GPIO_PIN (pin );
89
92
if (value ) {
90
93
if (self -> open_drain ) {
91
- gpio_set_pin_direction (self -> pin -> pin , GPIO_DIRECTION_IN );
94
+ // Assertion: pull is off, so the pin is floating in this case.
95
+ // We do open-drain high output (no sinking of current)
96
+ // by changing the direction to input with no pulls.
97
+ hri_port_clear_DIR_DIR_bf (PORT , port , pin_mask );
92
98
} else {
93
- gpio_set_pin_level ( self -> pin -> pin , true );
94
- gpio_set_pin_direction ( self -> pin -> pin , GPIO_DIRECTION_OUT );
99
+ hri_port_set_DIR_DIR_bf ( PORT , port , pin_mask );
100
+ hri_port_set_OUT_OUT_bf ( PORT , port , pin_mask );
95
101
}
96
102
} else {
97
- gpio_set_pin_level ( self -> pin -> pin , false );
98
- gpio_set_pin_direction ( self -> pin -> pin , GPIO_DIRECTION_OUT );
103
+ hri_port_set_DIR_DIR_bf ( PORT , port , pin_mask );
104
+ hri_port_clear_OUT_OUT_bf ( PORT , port , pin_mask );
99
105
}
100
106
}
101
107
@@ -105,10 +111,10 @@ bool common_hal_digitalio_digitalinout_get_value(
105
111
if (!self -> output ) {
106
112
return gpio_get_pin_level (pin );
107
113
} else {
108
- if (self -> open_drain && hri_port_get_DIR_reg (PORT , ( enum gpio_port ) GPIO_PORT (pin ), 1U << GPIO_PIN (pin )) == 0 ) {
114
+ if (self -> open_drain && hri_port_get_DIR_reg (PORT , GPIO_PORT (pin ), 1U << GPIO_PIN (pin )) == 0 ) {
109
115
return true;
110
116
} else {
111
- return hri_port_get_OUT_reg (PORT , ( enum gpio_port ) GPIO_PORT (pin ), 1U << GPIO_PIN (pin ));
117
+ return hri_port_get_OUT_reg (PORT , GPIO_PORT (pin ), 1U << GPIO_PIN (pin ));
112
118
}
113
119
}
114
120
}
@@ -119,7 +125,7 @@ void common_hal_digitalio_digitalinout_set_drive_mode(
119
125
bool value = common_hal_digitalio_digitalinout_get_value (self );
120
126
self -> open_drain = drive_mode == DRIVE_MODE_OPEN_DRAIN ;
121
127
// True is implemented differently between modes so reset the value to make
122
- // sure its correct for the new mode.
128
+ // sure it's correct for the new mode.
123
129
if (value ) {
124
130
common_hal_digitalio_digitalinout_set_value (self , value );
125
131
}
@@ -148,7 +154,9 @@ void common_hal_digitalio_digitalinout_set_pull(
148
154
default :
149
155
break ;
150
156
}
157
+ // Set pull first to avoid glitches.
151
158
gpio_set_pin_pull_mode (self -> pin -> pin , asf_pull );
159
+ gpio_set_pin_direction (self -> pin -> pin , GPIO_DIRECTION_IN );
152
160
}
153
161
154
162
digitalio_pull_t common_hal_digitalio_digitalinout_get_pull (
@@ -158,9 +166,9 @@ digitalio_pull_t common_hal_digitalio_digitalinout_get_pull(
158
166
mp_raise_AttributeError ("Cannot get pull while in output mode" );
159
167
return PULL_NONE ;
160
168
} else {
161
- if (hri_port_get_PINCFG_PULLEN_bit (PORT , ( enum gpio_port ) GPIO_PORT (pin ), GPIO_PIN (pin )) == 0 ) {
169
+ if (hri_port_get_PINCFG_PULLEN_bit (PORT , GPIO_PORT (pin ), GPIO_PIN (pin )) == 0 ) {
162
170
return PULL_NONE ;
163
- } if (hri_port_get_OUT_reg (PORT , ( enum gpio_port ) GPIO_PORT (pin ), 1U << GPIO_PIN (pin )) > 0 ) {
171
+ } if (hri_port_get_OUT_reg (PORT , GPIO_PORT (pin ), 1U << GPIO_PIN (pin )) > 0 ) {
164
172
return PULL_UP ;
165
173
} else {
166
174
return PULL_DOWN ;
0 commit comments