@@ -60,7 +60,7 @@ void common_hal_digitalio_digitalinout_deinit(digitalio_digitalinout_obj_t* self
6060void common_hal_digitalio_digitalinout_switch_to_input (
6161 digitalio_digitalinout_obj_t * self , digitalio_pull_t pull ) {
6262 self -> output = false;
63-
63+ // This also sets direction to input.
6464 common_hal_digitalio_digitalinout_set_pull (self , pull );
6565}
6666
@@ -69,13 +69,13 @@ void common_hal_digitalio_digitalinout_switch_to_output(
6969 digitalio_drive_mode_t drive_mode ) {
7070 const uint8_t pin = self -> pin -> pin ;
7171 gpio_set_pin_pull_mode (pin , GPIO_PULL_OFF );
72- gpio_set_pin_direction (pin , GPIO_DIRECTION_OUT );
73-
7472 // Turn on "strong" pin driving (more current available). See DRVSTR doc in datasheet.
7573 hri_port_set_PINCFG_DRVSTR_bit (PORT , (enum gpio_port )GPIO_PORT (pin ), GPIO_PIN (pin ));
7674
7775 self -> output = true;
7876 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.
7979 common_hal_digitalio_digitalinout_set_value (self , value );
8080}
8181
@@ -86,16 +86,22 @@ digitalio_direction_t common_hal_digitalio_digitalinout_get_direction(
8686
8787void common_hal_digitalio_digitalinout_set_value (
8888 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 );
8992 if (value ) {
9093 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 );
9298 } 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 );
95101 }
96102 } 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 );
99105 }
100106}
101107
@@ -105,10 +111,10 @@ bool common_hal_digitalio_digitalinout_get_value(
105111 if (!self -> output ) {
106112 return gpio_get_pin_level (pin );
107113 } 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 ) {
109115 return true;
110116 } 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 ));
112118 }
113119 }
114120}
@@ -119,7 +125,7 @@ void common_hal_digitalio_digitalinout_set_drive_mode(
119125 bool value = common_hal_digitalio_digitalinout_get_value (self );
120126 self -> open_drain = drive_mode == DRIVE_MODE_OPEN_DRAIN ;
121127 // 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.
123129 if (value ) {
124130 common_hal_digitalio_digitalinout_set_value (self , value );
125131 }
@@ -148,7 +154,9 @@ void common_hal_digitalio_digitalinout_set_pull(
148154 default :
149155 break ;
150156 }
157+ // Set pull first to avoid glitches.
151158 gpio_set_pin_pull_mode (self -> pin -> pin , asf_pull );
159+ gpio_set_pin_direction (self -> pin -> pin , GPIO_DIRECTION_IN );
152160}
153161
154162digitalio_pull_t common_hal_digitalio_digitalinout_get_pull (
@@ -158,9 +166,9 @@ digitalio_pull_t common_hal_digitalio_digitalinout_get_pull(
158166 mp_raise_AttributeError ("Cannot get pull while in output mode" );
159167 return PULL_NONE ;
160168 } 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 ) {
162170 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 ) {
164172 return PULL_UP ;
165173 } else {
166174 return PULL_DOWN ;
0 commit comments