Skip to content

analogWrite: set the pin as an output for the 0 and 255 endpoints - #653

Open
ws-asahi wants to merge 2 commits into
SpenceKonde:masterfrom
ws-asahi:fix/analogwrite-endpoint-output
Open

analogWrite: set the pin as an output for the 0 and 255 endpoints#653
ws-asahi wants to merge 2 commits into
SpenceKonde:masterfrom
ws-asahi:fix/analogwrite-endpoint-output

Conversation

@ws-asahi

Copy link
Copy Markdown

The val==0 / val==255 branch returned without setting the pin direction.
The classic AVR core calls pinMode(pin, OUTPUT) in analogWrite.
(the API docs promise analog output pins need no pinMode call)

So on a pin not already an output:

analogWrite(pin, 0)   -> Hi-Z instead of driven low
analogWrite(pin, 255) -> pull-up only instead of driven high

Only these two values are affected (the normal PWM path ends in _setOutput()).

Additional Information:
megaTinyCore's analogWrite has the same pattern.

The classic Arduino AVR core calls pinMode(pin, OUTPUT) before its
val==0 / val==255 branch, and documents that this is deliberate: the
analog output pins are not supposed to need a pinMode() call. This core
returned from the endpoint branch without ever touching PORTx.DIR, so on
a pin that had not already been made an output:

  analogWrite(pin, 0)   left the pin Hi-Z instead of driving it low
  analogWrite(pin, 255) enabled the pull-up instead of driving it high

The normal PWM path ends in _setOutput(), so only these two values were
affected - which is precisely where a sketch is most likely to omit
pinMode(): fades that start at 0, and on/off control written as
analogWrite(pin, 0) / analogWrite(pin, 255).

Found on the Wazamono Tachi (AVR64DU32) while checking Pro Micro
compatibility: with the pin left Hi-Z, a jumpered neighbour pin read an
arbitrary floating level for analogWrite(pin, 0) and a weak pull-up
level for 255.

digitalWrite() runs first (it writes OUT and turns off any PWM), then
the direction is set, so the pin never briefly drives a stale level.
digitalWrite()'s classic-AVR emulation leaves PULLUPEN set in the 255
case; that is harmless and matches classic AVR, where the pull-up is
disconnected while the pin is an output (DS40002548B 18.3.2.3 and
equivalents). Applies to every part this core supports.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant