Hi Patrick, to describe the ADR engine in short:
It calculates the link budget when receiving the uplink based on the SNR and the min. SNR required for the used spreading-factor. When that link budget is calculated, it subtracts the installation-margin from it. That value divided by 3 defines the number of steps.
Given the number of steps is positive, it means it can increase the data-rate (decrease the spreading-factor) by that number of steps until it reaches the max. DR.
When there are steps left, then it will use these to decrease the TXPower. E.g. for EU this is:
Currently when the number of steps is negative, it will increase the TXPower if possible. It will never decrease-the data-rate! See also: https://github.com/brocaar/loraserver/blob/master/internal/adr/adr.go#L174.
Please note that a device should ACK when the requested TXPower is not implemented (LoRaWAN 1.0.2 spec):