Hardware Timer (TIM)
Hardware timer peripheral support for Daisy Seed.
Supports general-purpose TIM peripherals:
- TIM2, TIM5 (32-bit counters)
- TIM3, TIM4 (16-bit counters)
Features:
- High-precision timing (up to 200MHz/240MHz)
- Tick-based or time-based measurements (us/ms)
- Configurable period and prescaler
- User callbacks on period elapsed
- Blocking delays (DelayTick, DelayMs, DelayUs)
Note: DaisySeed uses TIM2 internally for timing/delay purposes at maximum frequency.
Usage:
import nimphea/per/tim var timer: TimerHandle var config = TimerConfig() config.periph = TIM_PERIPH_TIM2 config.dir = TIMER_DIR_UP config.period = 0xffffffff # Max for 32-bit config.enable_irq = false discard timer.init(config) discard timer.start() # Get current tick let tick = timer.getTick() # Delay for 1000us timer.delayUs(1000)
Callback Usage:
proc onTimerPeriod(data: pointer) {.cdecl.} = # Called every period echo "Timer elapsed!" config.enable_irq = true discard timer.init(config) timer.setCallback(onTimerPeriod, nil) discard timer.start()
Types
TimerCallback = proc (data: pointer) {.cdecl.}
-
User callback type that fires at the end of each timer period
Note: Requires enable_irq = true in config
Source Edit TimerConfig {.importcpp: "daisy::TimerHandle::Config", header: "per/tim.h", bycopy.} = object periph*: TimerPeripheral ## Hardware peripheral to use dir*: TimerCounterDir ## Counter direction period*: uint32 ## Period in ticks (max: 0xffff for 16-bit, 0xffffffff for 32-bit) enable_irq*: bool ## Enable interrupt for callbacks
- Timer configuration structure Source Edit
TimerCounterDir {.importcpp: "daisy::TimerHandle::Config::CounterDir", header: "per/tim.h".} = enum TIMER_DIR_UP = 0, ## Count up from 0 to period TIMER_DIR_DOWN ## Count down from period to 0
- Counter direction Source Edit
TimerHandle {.importcpp: "daisy::TimerHandle", header: "per/tim.h".} = object
-
Hardware timer handle
Provides access to one of the four general-purpose timers (TIM2-TIM5).
Source Edit TimerPeripheral {.importcpp: "daisy::TimerHandle::Config::Peripheral", header: "per/tim.h".} = enum TIM_PERIPH_TIM2 = 0, ## 32-bit counter (recommended for long periods) TIM_PERIPH_TIM3, ## 16-bit counter TIM_PERIPH_TIM4, ## 16-bit counter TIM_PERIPH_TIM5 ## 32-bit counter
- Hardware timer peripheral selection Source Edit
TimerResult {.importcpp: "daisy::TimerHandle::Result", header: "per/tim.h".} = enum TIMER_OK = 0, ## Operation successful TIMER_ERR ## Operation failed
- Return values for timer functions Source Edit
Procs
proc createTimerConfig(): TimerConfig {.importcpp: "daisy::TimerHandle::Config()", ...raises: [], tags: [], forbids: [].}
-
Create a timer configuration with default values
Defaults:
- periph: TIM_PERIPH_TIM2
- dir: TIMER_DIR_UP
- period: 0xffffffff (max for 32-bit)
- enable_irq: false
proc deInit(this: var TimerHandle): TimerResult {.importcpp: "#.DeInit()", ...raises: [], tags: [], forbids: [].}
-
Deinitialize the timer
Returns: TIMER_OK on success, TIMER_ERR on failure
Source Edit proc delayMs(this: var TimerHandle; del: uint32) {.importcpp: "#.DelayMs(#)", ...raises: [], tags: [], forbids: [].}
-
Blocking delay for specified milliseconds
Parameters:
- del - Number of milliseconds to delay
Example:
timer.delayMs(100) # Wait 100ms
Source Edit proc delayTick(this: var TimerHandle; del: uint32) {. importcpp: "#.DelayTick(#)", ...raises: [], tags: [], forbids: [].}
-
Blocking delay for specified ticks
Parameters:
- del - Number of ticks to delay
Example:
timer.delayTick(1000) # Wait 1000 ticks
Source Edit proc delayUs(this: var TimerHandle; del: uint32) {.importcpp: "#.DelayUs(#)", ...raises: [], tags: [], forbids: [].}
-
Blocking delay for specified microseconds
Parameters:
- del - Number of microseconds to delay
Example:
timer.delayUs(500) # Wait 500us (0.5ms)
Source Edit proc getConfig(this: TimerHandle): TimerConfig {.importcpp: "#.GetConfig()", ...raises: [], tags: [], forbids: [].}
-
Returns the current configuration
Returns: Timer configuration structure
Source Edit proc getFreq(this: var TimerHandle): uint32 {.importcpp: "#.GetFreq()", ...raises: [], tags: [], forbids: [].}
-
Returns the frequency of each tick in Hz
Returns: Tick frequency in Hz
Example:
let freq = timer.getFreq() echo "Timer ticks at ", freq, " Hz" # Typically 200MHz or 240MHz (boost mode)
Source Edit proc getMs(this: var TimerHandle): uint32 {.importcpp: "#.GetMs()", ...raises: [], tags: [], forbids: [].}
-
Returns ticks scaled as milliseconds
Warning: Ensure period can handle max measurement to avoid wrapping!
Returns: Current time in milliseconds
Source Edit proc getTick(this: var TimerHandle): uint32 {.importcpp: "#.GetTick()", ...raises: [], tags: [], forbids: [].}
-
Returns the current counter position
Increments according to CounterDir and wraps at period.
Returns: Current tick count
Example:
let start = timer.getTick() # ... do work ... let elapsed = timer.getTick() - start
Source Edit proc getUs(this: var TimerHandle): uint32 {.importcpp: "#.GetUs()", ...raises: [], tags: [], forbids: [].}
-
Returns ticks scaled as microseconds
Warning: Ensure period can handle max measurement to avoid wrapping!
Returns: Current time in microseconds
Source Edit proc init(this: var TimerHandle; config: TimerConfig): TimerResult {. importcpp: "#.Init(#)", ...raises: [], tags: [], forbids: [].}
-
Initialize the timer according to the configuration
Parameters:
- config - Timer configuration structure
Returns: TIMER_OK on success, TIMER_ERR on failure
Example:
var timer: TimerHandle var config = createTimerConfig() config.periph = TIM_PERIPH_TIM5 config.period = 10000 # Wrap every 10000 ticks if timer.init(config) == TIMER_OK: echo "Timer initialized"
Source Edit proc setCallback(this: var TimerHandle; cb: TimerCallback; data: pointer = nil) {. importcpp: "#.SetCallback(#, #)", ...raises: [], tags: [], forbids: [].}
-
Set callback that fires when timer reaches end of period
Note: Requires enable_irq = true in config
Parameters:
- cb - User callback function
- data - Optional pointer to user data (defaults to nil)
Example:
proc onPeriod(data: pointer) {.cdecl.} = # Called every period hw.setLed(true) timer.setCallback(onPeriod, nil)
Source Edit proc setPeriod(this: var TimerHandle; ticks: uint32): TimerResult {. importcpp: "#.SetPeriod(#)", ...raises: [], tags: [], forbids: [].}
-
Set the period of the timer
This is the number of ticks before it wraps around. Can be changed on-the-fly while timer is running.
Parameters:
- ticks - Period in ticks (max 0xffff for 16-bit, 0xffffffff for 32-bit)
Returns: TIMER_OK on success
Example:
# Set to wrap every second at 200MHz discard timer.setPeriod(200_000_000)
Source Edit proc setPrescaler(this: var TimerHandle; val: uint32): TimerResult {. importcpp: "#.SetPrescaler(#)", ...raises: [], tags: [], forbids: [].}
-
Set the prescaler applied to the TIM peripheral
Adjusts the rate of ticks: APBx_Freq / prescaler per tick Can be changed on-the-fly while timer is running.
Parameters:
- val - Prescaler value (0 to 0xffff)
Returns: TIMER_OK on success
Example:
# Divide by 200 to get 1MHz ticks from 200MHz clock discard timer.setPrescaler(200)
Source Edit proc start(this: var TimerHandle): TimerResult {.importcpp: "#.Start()", ...raises: [], tags: [], forbids: [].}
-
Start the timer peripheral
Returns: TIMER_OK on success
Source Edit proc stop(this: var TimerHandle): TimerResult {.importcpp: "#.Stop()", ...raises: [], tags: [], forbids: [].}
-
Stop the timer peripheral
Returns: TIMER_OK on success
Source Edit