Forked.

Fork of mbed-dev by mbed official

Revision:
172:7d866c31b3c5
diff -r 89b338f31ef1 -r 7d866c31b3c5 targets/TARGET_TOSHIBA/TARGET_TMPM066/pwmout_api.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/TARGET_TOSHIBA/TARGET_TMPM066/pwmout_api.c	Thu Aug 31 17:27:04 2017 +0100
@@ -0,0 +1,243 @@
+/* mbed Microcontroller Library
+ * (C)Copyright TOSHIBA ELECTRONIC DEVICES & STORAGE CORPORATION 2017 All rights reserved
+ *
+ * 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.
+ */
+#include "pwmout_api.h"
+#include "PeripheralNames.h"
+#include "pinmap.h"
+#include "tmpm066_tmrb.h"
+
+#define CLOCK_FREQUENCY         SystemCoreClock // input source clock
+#define MAX_COUNTER_16B         0xFFFF
+#define DEFAULT_CLOCK_DIVISION  32
+#define DEFAULT_PERIOD          0.02f // 20ms
+
+static const PinMap PinMap_PWM[] = {
+    {PD1, PWM_0, PIN_DATA(1, 1)},
+    {PD2, PWM_1, PIN_DATA(1, 1)},
+    {PD3, PWM_2, PIN_DATA(1, 1)},
+    {PF4, PWM_3, PIN_DATA(1, 1)},
+    {PF5, PWM_4, PIN_DATA(1, 1)},
+    {PJ0, PWM_5, PIN_DATA(1, 1)},
+    {PJ1, PWM_6, PIN_DATA(1, 1)},
+    {NC,  NC,    0}
+};
+
+static const uint32_t prescale_tbl[] = {
+    2, 8, 32, 64, 128, 256, 512
+};
+
+void pwmout_init(pwmout_t *obj, PinName pin)
+{
+    uint16_t counter = 0;
+    TMRB_FFOutputTypeDef FFStruct;
+    TMRB_InitTypeDef m_tmrb;
+
+    // Determine the pwm channel
+    PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM);
+    //Assert input is valid
+    MBED_ASSERT(pwm != (PWMName)NC);
+
+    // Enable clock supply to TB0
+    CG_SetFcPeriphA(CG_FC_PERIPH_TMRB0_3, ENABLE);
+    CG_SetFcPeriphA(CG_FC_PERIPH_TMRB4_6, ENABLE);
+
+    switch (pwm) {
+        case PWM_0:
+            obj->channel = TSB_TB0;
+            break;
+        case PWM_1:
+            obj->channel = TSB_TB1;
+            break;
+        case PWM_2:
+            obj->channel = TSB_TB2;
+            break;
+        case PWM_3:
+            obj->channel = TSB_TB3;
+            break;
+        case PWM_4:
+            obj->channel = TSB_TB4;
+            break;
+        case PWM_5:
+            obj->channel = TSB_TB5;
+            CG_SetFcPeriphA(CG_FC_PERIPH_PORTJ, ENABLE);
+            break;
+        case PWM_6:
+            obj->channel = TSB_TB6;
+            CG_SetFcPeriphA(CG_FC_PERIPH_PORTJ, ENABLE);
+            break;
+        default:
+            obj->channel = NULL;
+            return;
+    }
+    // Set pin function as PWM
+    pinmap_pinout(pin, PinMap_PWM);
+    obj->pin = pin;
+    obj->period = DEFAULT_PERIOD;
+    // Enable channel
+    TMRB_Enable(obj->channel);
+    // Stops and clear count operation
+    TMRB_SetRunState(obj->channel, TMRB_STOP);
+    // Disables double buffering
+    TMRB_SetDoubleBuf(obj->channel, DISABLE);
+    // Set default period = 20ms, duty cycle = 0
+    obj->divisor = DEFAULT_CLOCK_DIVISION;
+    counter = (uint16_t)((DEFAULT_PERIOD * CLOCK_FREQUENCY) / obj->divisor);
+
+    // Init timer variable for using PPG mode
+    m_tmrb.Mode = TMRB_INTERVAL_TIMER;
+    m_tmrb.ClkDiv = TMRB_CLK_DIV_32;
+    m_tmrb.UpCntCtrl = TMRB_AUTO_CLEAR;     // clear UC when matching value
+    m_tmrb.TrailingTiming = counter;        // period = 20ms
+    m_tmrb.LeadingTiming = counter;         // duty cycle = 0%
+
+    // Init timer function
+    TMRB_Init(obj->channel, &m_tmrb);
+    obj->trailing_timing = counter;
+    obj->leading_timing = counter;
+
+    // Enable double buffering
+    TMRB_SetDoubleBuf(obj->channel, ENABLE);
+
+    // Setting to TBxFF0 reverse trigger
+    FFStruct.FlipflopCtrl = TMRB_FLIPFLOP_CLEAR;
+    FFStruct.FlipflopReverseTrg = TMRB_FLIPFLOP_MATCH_TRAILINGTIMING | TMRB_FLIPFLOP_MATCH_LEADINGTIMING;
+    TMRB_SetFlipFlop(obj->channel, &FFStruct);
+
+    // Start count operation
+    TMRB_SetRunState(obj->channel, TMRB_RUN);
+}
+
+void pwmout_free(pwmout_t *obj)
+{
+    // Stops and clear count operation
+    TMRB_SetRunState(obj->channel, TMRB_STOP);
+    pwmout_write(obj,0);
+    obj->pin = NC;
+    obj->channel = NULL;
+    obj->trailing_timing = 0;
+    obj->leading_timing = 0;
+    obj->divisor = 0;
+}
+
+void pwmout_write(pwmout_t *obj, float value)
+{
+    TMRB_FFOutputTypeDef FFStruct;
+
+    // Stop timer for setting clock again
+    TMRB_SetRunState(obj->channel, TMRB_STOP);
+    // values outside this range will be saturated to 0.0f or 1.0f
+    // Disable flip-flop reverse trigger when leading_timing and trailing_timing are duplicated
+    if (value <= 0.0f) {
+        value = 0;
+        FFStruct.FlipflopCtrl = TMRB_FLIPFLOP_CLEAR;
+        FFStruct.FlipflopReverseTrg = TMRB_DISABLE_FLIPFLOP;
+        TMRB_SetFlipFlop(obj->channel, &FFStruct);
+    } else if (value >= 1.0f) {
+        value = 1;
+        FFStruct.FlipflopCtrl = TMRB_FLIPFLOP_SET;
+        FFStruct.FlipflopReverseTrg = TMRB_DISABLE_FLIPFLOP;
+        TMRB_SetFlipFlop(obj->channel, &FFStruct);
+    } else {
+        FFStruct.FlipflopCtrl = TMRB_FLIPFLOP_CLEAR;
+        FFStruct.FlipflopReverseTrg = TMRB_FLIPFLOP_MATCH_TRAILINGTIMING | TMRB_FLIPFLOP_MATCH_LEADINGTIMING;
+        TMRB_SetFlipFlop(obj->channel, &FFStruct);
+    }
+
+    // Store the new leading_timing value
+    obj->leading_timing = obj->trailing_timing - (uint16_t)(obj->trailing_timing * value);
+
+    // Setting TBxRG0 register
+    TMRB_ChangeLeadingTiming(obj->channel, obj->leading_timing);
+    TMRB_SetRunState(obj->channel, TMRB_RUN);
+}
+
+float pwmout_read(pwmout_t *obj)
+{
+    float duty_cycle = (float)(obj->trailing_timing - obj->leading_timing) / obj->trailing_timing;
+    return duty_cycle;
+}
+
+void pwmout_period(pwmout_t *obj, float seconds)
+{
+    pwmout_period_us(obj, (int)(seconds * 1000000.0f));
+}
+
+void pwmout_period_ms(pwmout_t *obj, int ms)
+{
+    pwmout_period_us(obj, ms * 1000);
+}
+
+// Set the PWM period, keeping the duty cycle the same.
+void pwmout_period_us(pwmout_t *obj, int us)
+{
+    float seconds = 0;
+    int cycles = 0;
+    uint32_t clkdiv = 0;
+    float duty_cycle = 0;
+    TMRB_InitTypeDef m_tmrb;
+    seconds = (float)((us) / 1000000.0f);
+    obj->period = seconds;
+
+    MBED_ASSERT(obj->channel != NULL);
+
+    // Select highest timer resolution
+    for (int i = 0; i < 7; ++i) {
+        cycles = (int)((CLOCK_FREQUENCY / prescale_tbl[i]) * seconds);
+        if (cycles <= MAX_COUNTER_16B) {
+            clkdiv = i + 1; // range 1:7
+            break;
+        }
+    }
+    // Stop timer for setting clock again
+    TMRB_SetRunState(obj->channel, TMRB_STOP);
+    // Restore the duty-cycle
+    duty_cycle = (float)(obj->trailing_timing - obj->leading_timing) / obj->trailing_timing;
+    obj->trailing_timing = cycles;
+    obj->leading_timing = (cycles - (uint16_t)(cycles * duty_cycle));
+
+    // Change the source clock division and period
+    m_tmrb.Mode = TMRB_INTERVAL_TIMER;
+    m_tmrb.ClkDiv = clkdiv;
+    m_tmrb.UpCntCtrl = TMRB_AUTO_CLEAR;
+    m_tmrb.TrailingTiming = obj->trailing_timing;
+    m_tmrb.LeadingTiming = obj->leading_timing;
+
+    //Init timer function
+    TMRB_Init(obj->channel, &m_tmrb);
+    //Start timer function
+    TMRB_SetRunState(obj->channel, TMRB_RUN);
+}
+
+void pwmout_pulsewidth(pwmout_t *obj, float seconds)
+{
+    pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
+}
+
+void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
+{
+    pwmout_pulsewidth_us(obj, ms * 1000);
+}
+
+void pwmout_pulsewidth_us(pwmout_t *obj, int us)
+{
+    float seconds = 0;
+    float value = 0;
+
+    MBED_ASSERT(obj->channel != NULL);
+
+    seconds = (float)(us / 1000000.0f);
+    value = (((seconds / obj->period) * 100.0f) / 100.0f);
+    pwmout_write(obj, value);
+}