Timer based PWM output for MAX326XXFTHR platforms

Dependents:   MAX32620FTHR_PwmBlinky

Fork of MAX326XXFTHR_PwmOut by Jesse Marroquin

This library provides PWM output using the MAX32620/MAX32630 32-bit timers.

The mbed PwmOut API implementation uses Pulse Train peripherals.

The tables below contain the available GPIO pins that can be connected to the six 32-bit timers (TMR0-5). Timer 0 is used for the microsecond ticker API and is not available for PWM output. On the MAX32630FTHR platform, timer 5 is used by the BLE API and will not be available for PWM output if the BLE API is used.

MAX32620FTHR 32-Bit Timer PWM Mapping

TimerGPIO Port and Pin
TMR1P0_1, P0_7, P1_5, P3_1, P4_5, P5_3
TMR2P0_2, P1_0, P1_6, P2_4, P3_2, P4_0, P4_6, P5_4
TMR3P0_3, P1_1, P1_7, P2_5, P3_3, P4_7, P5_5
TMR4P0_4, P1_2, P2_6, P3_4, P5_0, P5_6
TMR5P0_5, P1_3, P2_7, P3_5, P5_1, P5_7

MAX32630FTHR 32-Bit Timer PWM Mapping

TimerGPIO Port and Pin
TMR1P3_1, P5_3
TMR2P2_4, P3_2, P4_0, P5_4
TMR3P2_5, P3_3, P5_5
TMR4P2_6, P3_4, P5_0, P5_6
TMR5P3_5, P5_1

Note GPIO P2_4, P2_5 and P2_6 are connected to onboard LEDs 1, 2 and 3.

Revision:
0:bb005bb0a24c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MAX326XXFTHR_PwmOut.h	Mon Apr 23 18:24:11 2018 +0000
@@ -0,0 +1,325 @@
+/* Original files PwmOut.h and pwmout_api.h contained the following copyright */
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2013 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ /* Original files PwmOut.h and pwmout_api.h combined and modified:
+    23 April 2018 Maxim Integrated Products, Inc.
+ */
+  
+#ifndef _MAX326XXFTHR_PWMOUT_H_
+#define _MAX326XXFTHR_PWMOUT_H_
+
+#include "mbed.h"
+#include "PinNames.h"
+#include "platform/mbed_critical.h"
+#include "platform/mbed_power_mgmt.h"
+#include "tmr_regs.h"
+
+/**
+ * @brief Timer based PWM output for the MAX326XXFTHR platform
+ *
+ * @details This library provides PWM output using the MAX326XX 32-bit timers.
+ * The mbed PwmOut API implementation uses the MAX326XX Pulse Train peripherals.
+ * The table below contains the available GPIO pins that can be connected to the
+ * six 32-bit timers (TMR0-5).  Timer 0 is used for the microsecond ticker API
+ * and is not available for PWM output.  On the MAX32630FTHR platform, 
+ * timer 5 is used by the BLE API and will not be available for PWM output if 
+ * the BLE API is used.
+ *
+ * MAX32620FTHR 32-Bit Timer PWM Mapping
+ *
+ * Timer | GPIO Port and Pin                                                <br>
+ * TMR1  | P0_1, P0_7, P1_5,       P3_1,       P4_5, P5_3                   <br>
+ * TMR2  | P0_2, P1_0, P1_6, P2_4, P3_2, P4_0, P4_6, P5_4                   <br>
+ * TMR3  | P0_3  P1_1  P1_7, P2_5, P3_3,       P4_7, P5_5                   <br>
+ * TMR4  | P0_4  P1_2        P2_6, P3_4,       P5_0, P5_6                   <br>
+ * TMR5  | P0_5  P1_3        P2_7, P3_5,       P5_1, P5_7                   <br>
+ * 
+ * MAX32630FTHR 32-Bit Timer PWM Mapping
+ *
+ * Timer | GPIO Port and Pin                                                <br>
+ * TMR1  |       P3_1,              P5_3                                    <br>
+ * TMR2  | P2_4, P3_2,  P4_0,       P5_4                                    <br>
+ * TMR3  | P2_5, P3_3,              P5_5                                    <br>
+ * TMR4  | P2_6, P3_4,        P5_0, P5_6                                    <br>
+ * TMR5  |       P3_5,        P5_1                                          <br>
+ *
+ * Note that for MAX32620FTHR and MAX32630FTHR GPIOs P2_4, P2_5 and P2_6 are 
+ * connected to onboard LEDs 1, 2 and 3.
+ *
+ * @code
+ * #include "mbed.h"
+ * #include "MAX326XXFTHR_PwmOut.h"
+ * 
+ * MAX326XXFTHR_PwmOut led[] = {
+ *     MAX326XXFTHR_PwmOut(LED1),
+ *     MAX326XXFTHR_PwmOut(LED2),
+ *     MAX326XXFTHR_PwmOut(LED3)
+ * };
+ * 
+ * int main()
+ * {
+ *     float dc;
+ *     unsigned int idx = 0;
+ * 
+ *     while (1) {
+ *         for (dc = 0.0f; dc <= 1.0f; dc += 0.01f) {
+ *             led[idx % 3].write(dc);
+ *             led[(idx + 1) % 3].write(1.0f - dc);
+ *             wait_ms(20);
+ *         }
+ *         idx++;
+ *     }
+ * }
+ * @endcode
+ */
+
+class MAX326XXFTHR_PwmOut
+{
+public:
+    
+    /** Create a PwmOut connected to the specified pin
+     *
+     *  @param pin PwmOut pin to connect to
+     */
+    MAX326XXFTHR_PwmOut(PinName pin) : _deep_sleep_locked(false) {
+        core_util_critical_section_enter();
+        pwmout_init(pin);
+        core_util_critical_section_exit();
+    }
+
+    ~MAX326XXFTHR_PwmOut() {
+        core_util_critical_section_enter();
+        unlock_deep_sleep();
+        core_util_critical_section_exit();
+    }
+
+    /** Set the ouput duty-cycle, specified as a percentage (float)
+     *
+     *  @param value A floating-point value representing the output duty-cycle,
+     *    specified as a percentage. The value should lie between
+     *    0.0f (representing on 0%) and 1.0f (representing on 100%).
+     *    Values outside this range will be saturated to 0.0f or 1.0f.
+     */
+    void write(float value) {
+        core_util_critical_section_enter();
+        lock_deep_sleep();
+        pwmout_write(value);
+        core_util_critical_section_exit();
+    }
+
+    /** Return the current output duty-cycle setting, measured as a percentage (float)
+     *
+     *  @returns
+     *    A floating-point value representing the current duty-cycle being output on the pin,
+     *    measured as a percentage. The returned value will lie between
+     *    0.0f (representing on 0%) and 1.0f (representing on 100%).
+     *
+     *  @note
+     *  This value may not match exactly the value set by a previous write().
+     */
+    float read() {
+        core_util_critical_section_enter();
+        float val = pwmout_read();
+        core_util_critical_section_exit();
+        return val;
+    }
+
+    /** Set the PWM period, specified in seconds (float), keeping the duty cycle the same.
+     *
+     *  @param seconds Change the period of a PWM signal in seconds (float) without modifying the duty cycle
+     *  @note
+     *   The resolution is currently in microseconds; periods smaller than this
+     *   will be set to zero.
+     */
+    void period(float seconds) {
+        core_util_critical_section_enter();
+        pwmout_period(seconds);
+        core_util_critical_section_exit();
+    }
+
+    /** Set the PWM period, specified in milli-seconds (int), keeping the duty cycle the same.
+     *  @param ms Change the period of a PWM signal in milli-seconds without modifying the duty cycle
+     */
+    void period_ms(int ms) {
+        core_util_critical_section_enter();
+        pwmout_period_ms(ms);
+        core_util_critical_section_exit();
+    }
+
+    /** Set the PWM period, specified in micro-seconds (int), keeping the duty cycle the same.
+     *  @param us Change the period of a PWM signal in micro-seconds without modifying the duty cycle
+     */
+    void period_us(int us) {
+        core_util_critical_section_enter();
+        pwmout_period_us(us);
+        core_util_critical_section_exit();
+    }
+
+    /** Set the PWM pulsewidth, specified in seconds (float), keeping the period the same.
+     *  @param seconds Change the pulse width of a PWM signal specified in seconds (float)
+     */
+    void pulsewidth(float seconds) {
+        core_util_critical_section_enter();
+        pwmout_pulsewidth(seconds);
+        core_util_critical_section_exit();
+    }
+
+    /** Set the PWM pulsewidth, specified in milli-seconds (int), keeping the period the same.
+     *  @param ms Change the pulse width of a PWM signal specified in milli-seconds
+     */
+    void pulsewidth_ms(int ms) {
+        core_util_critical_section_enter();
+        pwmout_pulsewidth_ms(ms);
+        core_util_critical_section_exit();
+    }
+
+    /** Set the PWM pulsewidth, specified in micro-seconds (int), keeping the period the same.
+     *  @param us Change the pulse width of a PWM signal specified in micro-seconds
+     */
+    void pulsewidth_us(int us) {
+        core_util_critical_section_enter();
+        pwmout_pulsewidth_us(us);
+        core_util_critical_section_exit();
+    }
+
+    /** A operator shorthand for write()
+     *  \sa PwmOut::write()
+     */
+    MAX326XXFTHR_PwmOut& operator= (float value) {
+        // Underlying call is thread safe
+        write(value);
+        return *this;
+    }
+
+    /** A operator shorthand for write()
+     * \sa PwmOut::write()
+     */
+    MAX326XXFTHR_PwmOut& operator= (PwmOut& rhs) {
+        // Underlying call is thread safe
+        write(rhs.read());
+        return *this;
+    }
+
+    /** An operator shorthand for read()
+     * \sa PwmOut::read()
+     */
+    operator float() {
+        // Underlying call is thread safe
+        return read();
+    }
+
+protected:
+    /** Lock deep sleep only if it is not yet locked */
+    void lock_deep_sleep() {
+        if (_deep_sleep_locked == false) {
+            sleep_manager_lock_deep_sleep();
+            _deep_sleep_locked = true;
+        }
+    }
+
+    /** Unlock deep sleep in case it is locked */
+    void unlock_deep_sleep() {
+        if (_deep_sleep_locked == true) {
+            sleep_manager_unlock_deep_sleep();
+            _deep_sleep_locked = false;
+        }
+    }
+
+    bool _deep_sleep_locked;
+
+private:
+    /** Initialize the pwm out peripheral and configure the pin
+     *
+     * @param obj The pwmout object to initialize
+     * @param pin The pwmout pin to initialize
+     */
+    void pwmout_init(PinName pin);
+
+    /** Deinitialize the pwmout object
+     *
+     * @param obj The pwmout object
+     */
+    void pwmout_free();
+
+    /** Set the output duty-cycle in range <0.0f, 1.0f>
+     *
+     * Value 0.0f represents 0 percentage, 1.0f represents 100 percent.
+     * @param obj     The pwmout object
+     * @param percent The floating-point percentage number
+     */
+    void pwmout_write(float percent);
+
+    /** Read the current float-point output duty-cycle
+     *
+     * @param obj The pwmout object
+     * @return A floating-point output duty-cycle
+     */
+    float pwmout_read();
+
+    /** Set the PWM period specified in seconds, keeping the duty cycle the same
+     *
+     * Periods smaller than microseconds (the lowest resolution) are set to zero.
+     * @param obj     The pwmout object
+     * @param seconds The floating-point seconds period
+     */
+    void pwmout_period(float seconds);
+
+    /** Set the PWM period specified in miliseconds, keeping the duty cycle the same
+     *
+     * @param obj The pwmout object
+     * @param ms  The milisecond period
+     */
+    void pwmout_period_ms(int ms);
+
+    /** Set the PWM period specified in microseconds, keeping the duty cycle the same
+     *
+     * @param obj The pwmout object
+     * @param us  The microsecond period
+     */
+    void pwmout_period_us(int us);
+
+    /** Set the PWM pulsewidth specified in seconds, keeping the period the same.
+     *
+     * @param obj     The pwmout object
+     * @param seconds The floating-point pulsewidth in seconds
+     */
+    void pwmout_pulsewidth(float seconds);
+
+    /** Set the PWM pulsewidth specified in miliseconds, keeping the period the same.
+     *
+     * @param obj The pwmout object
+     * @param ms  The floating-point pulsewidth in miliseconds
+     */
+    void pwmout_pulsewidth_ms(int ms);
+
+    /** Set the PWM pulsewidth specified in microseconds, keeping the period the same.
+     *
+     * @param obj The pwmout object
+     * @param us  The floating-point pulsewidth in microseconds
+     */
+    void pwmout_pulsewidth_us(int us);
+
+
+    PinName pin;
+    mxc_tmr_regs_t *tmr;
+    int tmr_idx;
+    int pwm_period;
+    int pulse_width;
+    int last_pulse_width;
+    void pwmout_update(void);
+};
+
+#endif