diff options
author | Marti Bolivar <mbolivar@leaflabs.com> | 2011-05-05 17:18:25 -0400 |
---|---|---|
committer | Marti Bolivar <mbolivar@leaflabs.com> | 2011-05-06 19:30:49 -0400 |
commit | b1f6476ba450121af95c9f8e74adfbc6ece03ef4 (patch) | |
tree | 45697b1f8a326a8e6e4c48b3881ef383a339c138 /source | |
parent | ba2883d21a4a1f8598bf6eaae667a6bb4d86943d (diff) | |
download | librambutan-b1f6476ba450121af95c9f8e74adfbc6ece03ef4.tar.gz librambutan-b1f6476ba450121af95c9f8e74adfbc6ece03ef4.zip |
Putting updated HardwareTimer back into the build.
HardwareTimer was removed from the build when the timer refactor was
done; this redoes it in terms of the new timer.h interface. A variety
of conflicting or badly designed bits were deprecated or removed.
I'm still not satisfied with this interface, as it's going to make
life difficult moving forward to high-density chips, where the
addition of basic timers means that the capture/compare methods won't
apply in some cases. However, we need to get 0.0.10 out the door, so
it'll have to do for now.
The docs are up to date, and contain a warning that the Wirish API
isn't stable and a recommendation to use libmaple proper.
Diffstat (limited to 'source')
-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 ------------------ |