nimphea/per/tim

Source   Edit  

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
Source   Edit  
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