49 lines
1.9 KiB
Python
49 lines
1.9 KiB
Python
import decimal
|
|
from typing import Union
|
|
|
|
|
|
def get_interrupt_timeout_seconds(control_register_value, clock_frequency):
|
|
# Robot passes values as strings, so convert them.
|
|
control_register_value = int(control_register_value.strip(), 0)
|
|
interrupt_interval_power = control_register_value & 0b1110000 # bits 7:4
|
|
|
|
# Interrupt interval starts at 2^6 when value is 0.
|
|
power_offset = 6
|
|
|
|
return get_timeout_seconds(interrupt_interval_power, power_offset, clock_frequency)
|
|
|
|
|
|
def get_reset_timeout_seconds(control_register_value, clock_frequency):
|
|
# Robot passes values as strings, so convert them.
|
|
control_register_value = int(control_register_value.strip(), 0)
|
|
reset_interval_power = control_register_value & 0b11100000000 # bits 10:8
|
|
|
|
# Reset interval starts at 2^7 when value is 0.
|
|
power_offset = 7
|
|
|
|
return get_timeout_seconds(reset_interval_power, power_offset, clock_frequency)
|
|
|
|
|
|
def get_timeout_seconds(interval_power, power_offset, clock_frequency):
|
|
# Robot passes values as strings, so convert them.
|
|
clock_frequency = int(clock_frequency.strip(), 0)
|
|
|
|
interval_cycles = pow(2, interval_power + power_offset)
|
|
seconds_per_cycle = 1 / clock_frequency
|
|
timeout_seconds = interval_cycles * seconds_per_cycle
|
|
|
|
# Round the number so we wait for slightly longer than necessary,
|
|
# otherwise we risk waiting too little due to precision loss.
|
|
return round_to_n_significant_digits(timeout_seconds, 3)
|
|
|
|
|
|
def round_to_n_significant_digits(value: Union[str, float], digits: int):
|
|
with decimal.localcontext() as context:
|
|
# Adjust precision to match the number of significant digits we want.
|
|
context.prec = digits
|
|
# Always round up, since we don't want to accidentally wait for too little time.
|
|
context.rounding = decimal.ROUND_UP
|
|
|
|
rounded_number = decimal.Decimal(value).normalize(context)
|
|
return format(rounded_number, "f")
|