Skip to content

RFC: defining machine.Timer #2971

@dpgeorge

Description

@dpgeorge

This issue is to discuss the API of the machine.Timer class. There are currently 3 different version of Timer which don't have much in common:

esp8266:

# id must be -1, period is in milliseconds, mode is PERIODIC or ONE_SHOT
Timer(id, *, period, mode, callback) # constructor
Timer.init(*, period, mode, callback) # reinitialise all parameters
Timer.deinit() # stop the timer

cc3200/wipy:

# mode is PERIODIC, ONE_SHOT or PWM
Timer(id, mode, *, width=16) # constructor
Timer.init(mode, *, width=16) # reinitialise
Timer.deinit() # stop

# each timer has one or more channels
# each timer channel is associated with a specific IO pin (eg for PWM)
Timer.channel(*, freq, period, polarity, duty_cycle) # create channel assoc with TImer
TimerChannel.freq([freq]) # get/set
TimerChannel.period([period]) # get/set
TimerChannel.duty_cycle([duty]) # get/set
TimerChannel.irq(...) # get or set up the IRQ callback

stmhal/pyboard (actually pyb.Timer):

# freq is in Hz (can be float <1), prescaler/period are raw values, mode is UP/DOWN/CENTER
Timer(id, *, freq, prescaler, period, mode, div, callback, deadtime) # constructor
Timer.init(*, freq, prescaler, period, mode, div, callback, deadtime) # reinit
Timer.counter([value]) # get/set the raw timer counter
Timer.source_freq() # get source frequency that clocks this timer
Timer.freq([value]) # get/set
Timer.prescaler([value]) # get/set
Timer.period([value]) # get/set
Timer.callback(callable) # get/set callback (pass None to disable)

# each timer has multiple chanels (usually 4)
# pin is the pin to associate with the channel (eg for PWM)
Timer.channel(mode, *, callback, pin, pulse_width, pulse_width_percent, compare, polarity) # create
TimerChannel.pulse_width([value]) # get/set
TimerChannel.pulse_width_percent([value]) # get/set
TimerChannel.capture([value]) # get/set
TimerChannel.compare([value]) # get/set
TimerChannel.callback(callable) # get/set callback

To compare current usage, for a simple periodic timer at 10Hz one would do:

# esp8266
t = Timer(-1)
t.init(period=100, mode=Timer.PERIODIC, callback=lambda t:print(t))

# stmhal/pyboard
Timer(1, freq=10, callback=lambda t:print(t))

For a one-shot after 2 seconds:

# esp8266
t = Timer(-1)
t.init(period=2000, mode=Timer.ONE_SHOT, callback=lambda t:print(t))

# stmhal/pyboard
def cb(t):
    print(t)
    t.deinit() # or t.callback(None)
Timer(1, freq=0.5, callback=cb)

At the very least I'd suggest that all ports have the same interface to create periodic and one-shot timers, as well as the same way to configure the timer irq/callback. Configuration of the irq should follow the samy signature as machine.Pin.irq(); see also #2297.

I also feel that a timer should have start() and stop() methods, so that one can create an initialise a timer at one point in the code, then start it precisely when needed. This requires definining that the first callback happens one period after start() is called.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions