diff options
-rw-r--r-- | source/lang/api/analogwrite.rst | 24 | ||||
-rw-r--r-- | source/lang/api/hardwaretimer.rst | 579 | ||||
-rw-r--r-- | source/timers.rst | 10 |
3 files changed, 256 insertions, 357 deletions
diff --git a/source/lang/api/analogwrite.rst b/source/lang/api/analogwrite.rst index e789305..dd2192a 100644 --- a/source/lang/api/analogwrite.rst +++ b/source/lang/api/analogwrite.rst @@ -52,7 +52,7 @@ you much more precise control over the duty cycle of your PWM output. If you're porting code from the Arduino and want a quick-and-dirty fix, one solution is to :ref:`map <lang-map>` the argument to -analogWrite into the right range:: +analogWrite() into the right range:: // Arduino code: analogWrite(pin, duty); @@ -71,8 +71,8 @@ that Timer's overflow to 255. Subsequent calls to analogWrite() should work as on the Arduino (with the same loss of precision). Note, however, that that affects the overflow for the **entire timer**, so other code relying on that timer (such as any -:ref:`interrupts <lang-attachinterrupt>` the timer controls) will -likely need to be modified as well. +:ref:`interrupts <lang-hardwaretimer-interrupts>` the timer controls) +will likely need to be modified as well. Difference 2: You must use pinMode() to set up PWM ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -141,23 +141,27 @@ the steps are: 1. Figure out which :ref:`timer <lang-hardwaretimer>` controls PWM output on your pin (\ :ref:`your board's Timer Pin Map - <gpio-pin-maps>` is your friend here). Let's say it's ``Timern``\ - , where ``n`` is some number 1, 2, 3, or 4. + <gpio-pin-maps>` is your friend here). -2. Call ``Timern.setPeriod(2041)``\ . This will set the timer's - period to approximately 2041 microseconds, which is a frequency of - approximately 490 Hz. +2. Let's say it's timer ``n``, where ``n`` is some number. You'll + then need to put "``HardwareTimer timer(n);``" with your variables, + as described in the :ref:`HardwareTimer + <lang-hardwaretimer-getting-started>` reference. + +3. In your :ref:`lang-setup`, put "``timer.setPeriod(2041);``". This + will set the timer's period to approximately 2041 microseconds, + which is a frequency of approximately 490 Hz. Be aware that this will change the period for the **entire timer**\ , and will affect anything else in your program that depends on that timer. The important examples are :ref:`timer interrupts -<lang-hardwaretimer-attachinterrupt>` and :ref:`PWM +<lang-hardwaretimer-interrupts>` and :ref:`PWM <timers-pwm-conflicts>`\ . See Also -------- -- :ref:`Maple PWM tutorial <pwm>` +- :ref:`pwm` .. rubric:: Footnotes diff --git a/source/lang/api/hardwaretimer.rst b/source/lang/api/hardwaretimer.rst index 526beb6..09245f0 100644 --- a/source/lang/api/hardwaretimer.rst +++ b/source/lang/api/hardwaretimer.rst @@ -5,456 +5,341 @@ HardwareTimer ============= -This class defines the public API for interfacing with the STM32's -built-in timer peripherals. More information on these peripherals -(including code examples) is available in the :ref:`timers reference -<timers>`. +This page describes how to control the built-in timers. It does not +describe how the timers work on your board. For more information on +that, the :ref:`timers reference <timers>`. -.. FIXME [0.0.10] Updated HardwareTimer documentation, with deprecation +.. warning:: The timer interface is still taking shape, and is + expected to change significantly between releases. Because of + that, the functionality described in this page shouldn't be + considered stable. -.. warning:: This class has been deprecated. It is not available in - the current build. + If you want a timer API that will be consistent between releases of + the Maple IDE, your best bet for now is to use the low-level + support in :ref:`libmaple-timer`. -Library Documentation ---------------------- +.. contents:: Contents + :local: -HardwareTimer Class Reference -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +.. _lang-hardwaretimer-getting-started: -To interact with a particular timer, call one of the methods -documented below on one of the predefined ``HardwareTimer`` instances. -For example, to set the prescale factor on timer 1 to 5, call -``Timer1.setPrescaleFactor(5)``. +Getting Started +--------------- -.. TODO add tutorial-style examples +You'll first need to define a ``HardwareTimer`` variable, which you'll +use to control the timer. Do this by putting the line +"``HardwareTimer timer(number);``" with your variables, where +``number`` is the timer's number. -.. cpp:class:: HardwareTimer +Here's an example (we'll fill in :ref:`setup() <lang-setup>` and +:ref:`loop() <lang-loop>` later):: - Class for interacting with a timer. There are four predefined - instances available on the Maple: ``Timer1``, ``Timer2``, - ``Timer3``, and ``Timer4``. + // Use timer 1 + HardwareTimer timer(1); -.. _lang-hardwaretimer-attachinterrupt: + void setup() { + // Your setup code + } -.. cpp:function:: void HardwareTimer::attachInterrupt(int channel, voidFuncPtr handler) + void loop() { + // ... + } - Attach an interrupt handler to the given ``channel``. This - interrupt handler will be called when the timer's counter reaches - the given channel :ref:`compare <lang-hardwaretimer-setcompare>` - value. +Configuring the Prescaler and Overflow +-------------------------------------- - ``handler`` should be a function which takes no arguments and has - :ref:`void <lang-void>` value; i.e. it should have signature :: +After defining your ``timer`` variable, you'll probably want to +configure how fast your timer's counter changes (using the prescaler) +and when it gets reset to zero (using the overflow value). You can do +that with the ``setPrescaleFactor()`` and ``setOverflow()`` functions. - void handler(void); - - You can later detach the interrupt using :ref:`detachInterrupt() - <lang-hardwaretimer-detachinterrupt>`. - - .. note:: The function (often called an *interrupt service - routine*, or ISR) should attempt to return as quickly as - possible. :ref:`Blinking the LED <lang-toggleled>`, some - logic, :ref:`PWM <pwm>` updates, and :ref:`Serial - <lang-serial>` writes are fine; writing to - :ref:`SerialUSB <lang-serialusb>` or :ref:`waiting - <lang-waitforbuttonpress>` for user input can take a long - time and prevent other interrupts from firing on time. - - Tip: if you have a :ref:`delay() <lang-delay>` in your - ISR, you're probably doing it wrong. - -.. cpp:function:: void HardwareTimer::attachCompare1Interrupt(voidFuncPtr handler) - - Equivalent to :ref:`attachInterrupt - <lang-hardwaretimer-attachinterrupt>`\ ``(1, handler)``. - -.. cpp:function:: void HardwareTimer::attachCompare2Interrupt(voidFuncPtr handler) - - Equivalent to :ref:`attachInterrupt - <lang-hardwaretimer-attachinterrupt>`\ ``(2, handler)``. - -.. cpp:function:: void HardwareTimer::attachCompare3Interrupt(voidFuncPtr handler) - - Equivalent to :ref:`attachInterrupt - <lang-hardwaretimer-attachinterrupt>`\ ``(3, handler)``. - -.. cpp:function:: void HardwareTimer::attachCompare4Interrupt(voidFuncPtr handler) - - Equivalent to :ref:`attachInterrupt - <lang-hardwaretimer-attachinterrupt>`\ ``(4, handler)``. - -.. _lang-hardwaretimer-setchannelmode: - -.. cpp:function:: void HardwareTimer::setChannelMode(int channel, TimerMode mode) - - Set the given channel of this timer to the given :ref:`mode - <lang-hardwaretimer-modes>`. The parameter ``channel`` is one of - 1, 2, 3, and 4, and corresponds to the compare channel you would - like to set. Refer to your board's :ref:`master pin map - <gpio-pin-maps>` to match up timer channels and pin numbers. - -.. cpp:function:: void HardwareTimer::setChannel1Mode(TimerMode mode) - - Equivalent to :ref:`setChannelMode <lang-hardwaretimer-setchannelmode>`\ - ``(1, mode)``. - -.. cpp:function:: void HardwareTimer::setChannel2Mode(TimerMode mode) - - Equivalent to :ref:`setChannelMode <lang-hardwaretimer-setchannelmode>`\ - ``(2, mode)``. - -.. cpp:function:: void HardwareTimer::setChannel3Mode(TimerMode mode) - - Equivalent to :ref:`setChannelMode <lang-hardwaretimer-setchannelmode>`\ - ``(3, mode)``. - -.. cpp:function:: void HardwareTimer::setChannel4Mode(TimerMode mode) - - Equivalent to :ref:`setChannelMode <lang-hardwaretimer-setchannelmode>`\ - ``(4, mode)``. - -.. _lang-hardwaretimer-getcompare: - -.. cpp:function:: uint16 HardwareTimer::getCompare(int channel) - - Gets the compare value for the given ``channel``, from 1 to 4. See - :ref:`setCompare() <lang-hardwaretimer-setcompare>`. - -.. cpp:function:: uint16 HardwareTimer::getCompare1() - - Equivalent to :ref:`getCompare <lang-hardwaretimer-getcompare>`\ - ``(1, mode)``. - -.. cpp:function:: uint16 HardwareTimer::getCompare2() - - Equivalent to :ref:`getCompare <lang-hardwaretimer-getcompare>`\ - ``(2, mode)``. - -.. cpp:function:: uint16 HardwareTimer::getCompare3() - - Equivalent to :ref:`getCompare <lang-hardwaretimer-getcompare>`\ - ``(3, mode)``. - -.. cpp:function:: uint16 HardwareTimer::getCompare4() +.. _lang-hardwaretimer-setprescalefactor: - Equivalent to :ref:`getCompare <lang-hardwaretimer-getcompare>`\ - ``(4, mode)``. +.. doxygenfunction:: HardwareTimer::setPrescaleFactor + :no-link: -.. _lang-hardwaretimer-setcompare: +.. _lang-hardwaretimer-setoverflow: -.. cpp:function:: void HardwareTimer::setCompare(int channel, uint16 compare) +.. doxygenfunction:: HardwareTimer::setOverflow + :no-link: - Sets the compare value for the given ``channel`` to ``compare``. - If ``compare`` is greater than this timer's overflow value, it will - be truncated to the overflow value. The default compare value is - 65,535 (the largest unsigned 16-bit integer value). +For example:: - When the counter reaches this value the interrupt for this channel - will fire if the given ``channel`` :ref:`mode - <lang-hardwaretimer-setchannelmode>` is ``TIMER_OUTPUTCOMPARE`` and - an interrupt is :ref:`attached - <lang-hardwaretimer-attachinterrupt>`. + // Use timer 1 + HardwareTimer timer(1); - By default, this only changes the relative offsets between events - on a single timer ("phase"); they don't control the frequency with - which they occur. However, a common trick is to increment the - compare value manually in the interrupt handler so that the event - will fire again after the increment period. There can be a - different increment value for each channel, so this trick allows - events to be programmed at 4 different rates on a single - timer. Note that function call overheads mean that the smallest - increment rate is at least a few microseconds. + void setup() { + timer.setPrescaleFactor(5); + timer.setOverflow(255); + } -.. cpp:function:: void HardwareTimer::setCompare1(uint16 compare) + void loop() { + // ... + } - Equivalent to :ref:`setCompare <lang-hardwaretimer-setcompare>`\ - ``(1, compare)``. +You may also find the ``setPeriod()`` function useful: -.. cpp:function:: void HardwareTimer::setCompare2(uint16 compare) +.. _lang-hardwaretimer-setperiod: - Equivalent to :ref:`setCompare <lang-hardwaretimer-setcompare>`\ - ``(2, compare)``. +.. doxygenfunction:: HardwareTimer::setPeriod + :no-link: -.. cpp:function:: void HardwareTimer::setCompare3(uint16 compare) +For example:: - Equivalent to :ref:`setCompare <lang-hardwaretimer-setcompare>`\ - ``(3, compare)``. + // Use timer 1 + HardwareTimer timer(1); -.. cpp:function:: void HardwareTimer::setCompare4(uint16 compare) + void setup() { + // Have the timer repeat every 20 milliseconds + int microseconds_per_millisecond = 1000; + timer.setPeriod(20 * microseconds_per_millisecond); + } - Equivalent to :ref:`setCompare <lang-hardwaretimer-setcompare>`\ - ``(4, compare)``. + void loop() { + // ... + } -.. cpp:function:: uint16 HardwareTimer::getCount() +.. _lang-hardwaretimer-interrupts: - Gets the current timer count. Due to function call overhead, the - return value will be increasingly accurate with smaller prescale - values. Also see :ref:`setCount() <lang-hardwaretimer-setcount>`. +Using Timer Interrupts +---------------------- -.. _lang-hardwaretimer-setcount: +.. TODO [0.2.0] Improve the interrupts section, here or in timers.rst -.. cpp:function:: void HardwareTimer::setCount(uint16 val) +In order to use timer interrupts, we recommend the following sequence: - Set the timer's current count to ``val``. +* Pause the timer. +* Configure the prescaler and overflow. +* Pick a timer channel to handle the interrupt and set the channel's + :ref:`mode <lang-hardwaretimer-timermode>` to ``TIMER_OUTPUT_COMPARE``. +* Set the channel compare value appropriately (this controls what counter value, + from 0 to overflow - 1). If you just want to make the interrupt fire once + every time the timer overflows, and you don't care what the timer count is, + the channel compare value can just be 1. +* Attach an interrupt handler to the channel. +* Refresh the timer. +* Resume the timer. - Note that there is some function call overhead associated with - calling this method, so using it is not a robust way to get - multiple timers to share a count value. +Here are two complete examples. - If ``val`` exceeds the timer's :ref:`overflow value - <lang-hardwaretimer-getoverflow>`, it is truncated to the overflow - value. +**LED blink**: This example blinks the built-in LED without doing +anything in ``loop()``. :: + #define LED_RATE 500000 // in microseconds; should give 0.5Hz toggles -.. _lang-hardwaretimer-detachinterrupt: - -.. cpp:function:: void HardwareTimer::detachInterrupt(int channel) + // We'll use timer 2 + HardwareTimer timer(2); - Remove the interrupt handler attached to the given ``channel``, if - any. The handler will no longer be called by this timer. + void setup() { + // Set up the LED to blink + pinMode(BOARD_LED_PIN, OUTPUT); -.. cpp:function:: void HardwareTimer::detachCompare1Interrupt() + // Pause the timer while we're configuring it + timer.pause(); - Equivalent to :ref:`detachInterrupt - <lang-hardwaretimer-detachinterrupt>`\ ``(1)``. + // Set up period + timer.setPeriod(LED_RATE); // in microseconds -.. cpp:function:: void HardwareTimer::detachCompare2Interrupt() + // Set up an interrupt on channel 1 + timer.setChannel1Mode(TIMER_OUTPUT_COMPARE); + timer.setCompare(TIMER_CH1, 1); // Interrupt 1 count after each update + timer.attachCompare1Interrupt(handler_led); - Equivalent to :ref:`detachInterrupt - <lang-hardwaretimer-detachinterrupt>`\ ``(2)``. + // Refresh the timer's count, prescale, and overflow + timer.refresh(); -.. cpp:function:: void HardwareTimer::detachCompare3Interrupt() + // Start the timer counting + timer.resume(); + } - Equivalent to :ref:`detachInterrupt - <lang-hardwaretimer-detachinterrupt>`\ ``(3)``. + void loop() { + // Nothing! It's all in the handler_led() interrupt: + } -.. cpp:function:: void HardwareTimer::detachCompare4Interrupt() + void handler_led(void) { + toggleLED(); + } - Equivalent to :ref:`detachInterrupt - <lang-hardwaretimer-detachinterrupt>`\ ``(4)``. +**Racing Counters**: This example shows how to use multiple timers at +the same time. :: -.. _lang-hardwaretimer-generateupdate: + int count3 = 0; + int count4 = 0; -.. cpp:function:: void HardwareTimer::generateUpdate() + // We'll use timers 3 and 4 + HardwareTimer timer3(3); + HardwareTimer timer4(4); - Re-initializes the counter (to 0 in upcounting mode, which is the - default), and generates an update of the prescale and overflow - registers. + void setup() { + // Set up the button for input + pinMode(BOARD_BUTTON_PIN, INPUT_PULLUP); -.. _lang-hardwaretimer-getoverflow: + // Set up timers to add 1 to their counts each time + // their interrupts fire. + timer3.setMode(TIMER_CH1, TIMER_OUTPUT_COMPARE); + timer4.setMode(TIMER_CH1, TIMER_OUTPUT_COMPARE); + timer3.pause(); + timer4.pause(); + timer3.setCount(0); + timer4.setCount(0); + timer3.setOverflow(30000); + timer4.setOverflow(30000); + timer3.setCompare(TIMER_CH1, 1000); // somewhere in the middle + timer4.setCompare(TIMER_CH1, 1000); + timer3.attachCompare1Interrupt(handler3); + timer4.attachCompare1Interrupt(handler4); + timer3.refresh(); + timer4.refresh(); + timer3.resume(); + timer4.resume(); + } -.. cpp:function:: uint16 HardwareTimer::getOverflow() + void loop() { + // Display the running counts + SerialUSB.print("Count 3: "); + SerialUSB.print(count3); + SerialUSB.print("\t\tCount 4: "); + SerialUSB.println(count4); + + // While the button is held down, pause timer 4 + for (int i = 0; i < 1000; i++) { + if (digitalRead(BOARD_BUTTON_PIN)) { + timer4.pause(); + } else { + timer4.resume(); + } + delay(1); + } + } - Gets the timer's overflow value. See :ref:`setOverflow() - <lang-hardwaretimer-setoverflow>`. + void handler3(void) { + count3++; + } -.. _lang-hardwaretimer-setoverflow: + void handler4(void) { + count4++; + } -.. cpp:function:: void HardwareTimer::setOverflow(uint16 val) +``HardwareTimer`` Class Reference +--------------------------------- - Sets the timer overflow (or "reload") value to ``val``. +This section gives a full listing of the capabilities of a +``HardwareTimer``. - When the timer's counter reaches this, value it resets to - zero. Its default value is 65535 (the largest unsigned 16-bit - integer); setting the overflow to anything lower will cause - interrupts to be called more frequently (see :ref:`setPeriod() - <lang-hardwaretimer-setperiod>` function for a shortcut). +.. doxygenclass:: HardwareTimer + :members: HardwareTimer, pause, resume, getPrescaleFactor, setPrescaleFactor, getOverflow, setOverflow, getCount, setCount, setPeriod, setMode, getCompare, setCompare, attachInterrupt, detachInterrupt, refresh - After the next :ref:`timer update - <lang-hardwaretimer-generateupdate>`, this number will be the - maximum value for the timer's channel compare values. +.. _lang-hardwaretimer-timermode: -.. _lang-hardwaretimer-pause: +.. doxygenenum:: timer_mode -.. cpp:function:: void HardwareTimer::pause() +Deprecated Functionality +------------------------ - Stop the timer's counter, without affecting its configuration. +The following functionality exists for now, but it has been +deprecated, and will be removed in a future Maple IDE release. You +shouldn't use it in new programs, and you should change any of your +programs which do use them to use the up-to-date features described +above. - The timer will no longer count or fire interrupts after this - function is called, until it is resumed. This function is useful - during timer setup periods, in order to prevent interrupts from - firing before the timer is fully configured. +The ``TimerMode`` type from previous releases has been renamed +``timer_mode``. The mode ``TIMER_OUTPUTCOMPARE`` is still present, +but will be removed in a future release. Use ``TIMER_OUTPUT_COMPARE`` +instead. - Note that there is some function call overhead associated with this - method, so using it in concert with :ref:`resume() - <lang-hardwaretimer-resume>` is not a robust way to align multiple - timers to the same count value. +.. cpp:function:: void HardwareTimer::attachCompare1Interrupt(voidFuncPtr handler) -.. _lang-hardwaretimer-setperiod: + Use ``attachInterrupt(1, handler)`` instead. -.. cpp:function:: uint16 HardwareTimer::setPeriod(uint32 microseconds) +.. cpp:function:: void HardwareTimer::attachCompare2Interrupt(voidFuncPtr handler) - Configure the :ref:`prescaler - <lang-hardwaretimer-getprescalefactor>` and :ref:`overflow - <lang-hardwaretimer-getoverflow>` values to generate a timer reload - with a period as close to the given number of ``microseconds`` as - possible. + Use ``attachInterrupt(2, handler)`` instead. - The return value is the new overflow value, which may be used to - set channel compare values. However, if a clock that fires an - interrupt every given number of microseconds is all that is - desired, and the relative "phases" are unimportant, channel compare - values may all be set to 1. +.. cpp:function:: void HardwareTimer::attachCompare3Interrupt(voidFuncPtr handler) -.. _lang-hardwaretimer-getprescalefactor: + Use ``attachInterrupt(3, handler)`` instead. -.. cpp:function:: uint16 HardwareTimer::getPrescaleFactor() +.. cpp:function:: void HardwareTimer::attachCompare4Interrupt(voidFuncPtr handler) - Returns the timer's prescale factor. See - :ref:`setPrescaleFactor() <lang-hardwaretimer-setprescalefactor>`. + Use ``attachInterrupt(4, handler)`` instead. -.. _lang-hardwaretimer-setprescalefactor: +.. _lang-hardwaretimer-setchannelmode: -.. cpp:function:: void HardwareTimer::setPrescaleFactor(uint16 factor) +.. cpp:function:: void HardwareTimer::setChannelMode(int channel, timer_mode mode) - Set the timer's prescale factor to ``factor``. + Use ``setMode(channel, mode)`` instead. - The prescaler acts as a clock divider to slow down the rate at - which the counter increments. +.. cpp:function:: void HardwareTimer::setChannel1Mode(timer_mode mode) - For example, the system clock rate is 72MHz, so the counter will - reach 65535 in (13.89 nanoseconds) × (65535 counts) = (910.22 - microseconds), or about a thousand times a second. If the - prescaler equals 1098, then the clock rate is effectively 72MHz / - 1098 = 65.56KHz, and the counter will reach 65536 in (15.25 - microseconds) × (65536 counts) = (0.999 seconds), or about once - per second. + Use ``setMode(1, mode)`` instead. - The :ref:`setPeriod() <lang-hardwaretimer-setperiod>` method may - also be used as a convenient alternative. +.. cpp:function:: void HardwareTimer::setChannel2Mode(timer_mode mode) -.. _lang-hardwaretimer-resume: + Use ``setMode(2, mode)`` instead. -.. cpp:function:: void HardwareTimer::resume() +.. cpp:function:: void HardwareTimer::setChannel3Mode(timer_mode mode) - Resume a paused timer, without affecting its configuration. + Use ``setMode(3, mode)`` instead. - The timer will resume counting and firing interrupts as - appropriate. +.. cpp:function:: void HardwareTimer::setChannel4Mode(timer_mode mode) - Note that there is some function call overhead associated with - using this method, so using it in concert with :ref:`pause() - <lang-hardwaretimer-pause>` is not a robust way to align multiple - timers to the same count value. + Use ``setMode(4, mode)`` instead. -.. cpp:function:: timer_dev_num HardwareTimer::getTimerNum() +.. cpp:function:: uint16 HardwareTimer::getCompare1() - Returns the :ref:`timer device number - <lang-hardwaretimer-timer-dev-num>` associated with the timer. For - example, ``Timer1.getTimerNum()`` would return ``TIMER1``. + Use ``getCompare(1, mode)`` instead. - In most cases, you should not need to use this function. If you do - use it, be careful; the constant ``TIMER1`` is *not equal* to the - number 1; similarly, ``TIMER2`` is *not* the number 2, etc. Be - sure to refer to the timer device number by name. +.. cpp:function:: uint16 HardwareTimer::getCompare2() -.. _lang-hardwaretimer-modes: + Use ``getCompare(2, mode)`` instead. -Timer Modes -^^^^^^^^^^^ -.. doxygenenum:: TimerMode +.. cpp:function:: uint16 HardwareTimer::getCompare3() -.. _lang-hardwaretimer-timer-dev-num: + Use ``getCompare(3, mode)`` instead. -Timer Device Numbers -^^^^^^^^^^^^^^^^^^^^ +.. cpp:function:: uint16 HardwareTimer::getCompare4() -These provide a lower-level interface for interacting with timers. -They are mostly useful in context with the :ref:`getTimer() -<lang-hardwaretimer-gettimer>` function. **Be careful** when using -these not to confuse e.g. ``TIMER1`` with the number 1; they are -different. + Use ``getCompare(4, mode)`` instead. -.. doxygenenum:: timer_dev_num +.. cpp:function:: void HardwareTimer::setCompare1(uint16 compare) -.. _lang-hardwaretimer-convenience: + Use ``setCompare(1, compare)`` instead. -.. _lang-hardwaretimer-gettimer: +.. cpp:function:: void HardwareTimer::setCompare2(uint16 compare) -Other Functions -^^^^^^^^^^^^^^^ -.. doxygenfunction:: getTimer + Use ``setCompare(2, compare)`` instead. -Examples -^^^^^^^^ +.. cpp:function:: void HardwareTimer::setCompare3(uint16 compare) -**LED blink**:: + Use ``setCompare(3, compare)`` instead. - #define LED_RATE 500000 // in microseconds; should give 0.5Hz toggles +.. cpp:function:: void HardwareTimer::setCompare4(uint16 compare) - void handler_led(void); + Use ``setCompare(4, compare)`` instead. - void setup() - { - // Set up the LED to blink - pinMode(BOARD_LED_PIN, OUTPUT); +.. cpp:function:: void HardwareTimer::detachCompare1Interrupt() - // Setup Timer - Timer2.setChannel1Mode(TIMER_OUTPUTCOMPARE); - Timer2.setPeriod(LED_RATE); // in microseconds - Timer2.setCompare1(1); // overflow might be small - Timer2.attachCompare1Interrupt(handler_led); - } + Use ``detachInterrupt(1)`` instead. - void loop() { - // Nothing! It's all in the interrupts - } +.. cpp:function:: void HardwareTimer::detachCompare2Interrupt() - void handler_led(void) { - toggleLED(); - } + Use ``detachInterrupt(2)`` instead. -**Racing Counters**:: +.. cpp:function:: void HardwareTimer::detachCompare3Interrupt() - void handler_count1(void); - void handler_count2(void); + Use ``detachInterrupt(3)`` instead. - int count1 = 0; - int count2 = 0; +.. cpp:function:: void HardwareTimer::detachCompare4Interrupt() - void setup() - { - // Set up BUT for input - pinMode(BOARD_BUTTON_PIN, INPUT_PULLUP); + Use ``detachInterrupt(4)`` instead. - // Setup Counting Timers - Timer3.setChannel1Mode(TIMER_OUTPUTCOMPARE); - Timer4.setChannel1Mode(TIMER_OUTPUTCOMPARE); - Timer3.pause(); - Timer4.pause(); - Timer3.setCount(0); - Timer4.setCount(0); - Timer3.setOverflow(30000); - Timer4.setOverflow(30000); - Timer3.setCompare1(1000); // somewhere in the middle - Timer4.setCompare1(1000); - Timer3.attachCompare1Interrupt(handler1); - Timer4.attachCompare1Interrupt(handler2); - Timer3.resume(); - Timer4.resume(); - } +.. cpp:function:: void HardwareTimer::generateUpdate() - void loop() { - // Display the running counts - SerialUSB.print("Count 1: "); - SerialUSB.print(count1); - SerialUSB.print("\t\tCount 2: "); - SerialUSB.println(count2); - - // Run... while BUT is held, pause Count2 - for(int i = 0; i<1000; i++) { - if(digitalRead(BOARD_BUTTON_PIN)) { - Timer4.pause(); - } else { - Timer4.resume(); - } - delay(1); - } - } + Use ``refresh()`` instead. - void handler1(void) { - count1++; - } - void handler2(void) { - count2++; - } +In previous releases, to interact with a particular timers, you would +use one of the predefined ``HardwareTimer`` instances ``Timer1``, +``Timer2``, ``Timer3``, and ``Timer4``. These are still available for +now, but they are also deprecated, and will be removed in a future +release. As detailed in :ref:`lang-hardwaretimer-getting-started`, +you should define your own ``HardwareTimer`` variables. diff --git a/source/timers.rst b/source/timers.rst index cb30081..9163e69 100644 --- a/source/timers.rst +++ b/source/timers.rst @@ -45,6 +45,16 @@ event" interrupt is generated. You can configure the Maple to notify you when this takes place, by registering an interrupt handler, which is a function that will be called when the update event occurs. +By default, different compare values only change the relative offsets +between events on a single timer ("phase"). They don't control the +frequency with which they occur. However, a common trick is to +increment the compare value manually in the interrupt handler so that +the event will fire again after the increment period. There can be a +different increment value for each channel, so this trick allows +events to be programmed at 4 different rates on a single timer. Note +that function call overheads mean that the smallest increment rate is +at least a few microseconds. + Function Reference ------------------ |