prusa3d / Prusa-Firmware-Buddy

Firmware for the Original Prusa MINI, Original Prusa MK4 and the Original Prusa XL 3D printers by Prusa Research.
Other
1.08k stars 212 forks source link

[ENHANCEMENT] Enable M42 command for GPIO access #3993

Open Rahix opened 1 month ago

Rahix commented 1 month ago

Printer type - [MINI]

Is your suggested improvement related to an existing problem? Please describe. I'm looking to add status indicator lights (like this) to the printer to help visualize the current status at a glance. For this, I'd like to get access to the GPIOs on the expansion connector from G-code.

Describe the expected functionality There are two free GPIOs on the expansion connector (STM pins PE0 and PB5, mapping to #64 and #21). There is not much missing for them to be accessible via the M42 command. However, the way the firmware works at the moment, trying to issue an M42 command for either pin currently fails with a "blue screen". The error message is always

?HWIO error
pin #21 (0x15)
analog write

This comes from the fact that the M42 implementation tries to digitalWrite() and analogWrite() the pin at the same time:

https://github.com/prusa3d/Prusa-Firmware-Buddy/blob/b46ac81aee5bfaad7a85d352957ffafb60dde51c/lib/Marlin/Marlin/src/gcode/control/M42.cpp#L56-L58

The digitalWrite() actually seems to pass, but the analogWrite() then panics, because the pin is not a known analog output:

https://github.com/prusa3d/Prusa-Firmware-Buddy/blob/b46ac81aee5bfaad7a85d352957ffafb60dde51c/src/common/hwio_buddy_2209_02.cpp#L534-L535

I guess the Marlin code for the M42 implementation assumes that digitalWrite()/analogWrite() fail silently on an undefined pin instead of panicking.

To me it is completely reasonable that digitalWrite()/analogWrite() fail with noise when receiving unknown inputs and it is the caller's responsibility (M42 implementation) to check for pin type and validity. However, it looks to me like there isn't really a way to check for pin type at the moment. For digital pins, there seems to be an isOutputPin() used in digitalWrite(), but that's commented out right now, so I don't know if it is actually working:

https://github.com/prusa3d/Prusa-Firmware-Buddy/blob/b46ac81aee5bfaad7a85d352957ffafb60dde51c/src/common/hwio_buddy_2209_02.cpp#L469-L475

OTOH analogWrite() seems to hard-code known analog pins, so there is no way to check for pin type.


I see multiple possible solutions:

References: #3649, #3711

Fil4ment commented 1 month ago

Following this issue. They closed mine, as you know, because they are implementing i2c, but not on the expansion connector, and no analog.