mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

targets/TARGET_TOSHIBA/TARGET_TMPM4G9/pwmout_api.c

Committer:
AnnaBridge
Date:
2019-02-20
Revision:
189:f392fc9709a3
Parent:
188:bcfe06ba3d64

File content as of revision 189:f392fc9709a3:

/* mbed Microcontroller Library
 * (C)Copyright TOSHIBA ELECTRONIC DEVICES & STORAGE CORPORATION 2018 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"

#define GPIO_CLK_OFFSET                 2
// Because Timer operating frequency is 2.5 MhZ
#define CALCULATE_RGC1_VAL              2.5

static const PinMap PinMap_PWM[] = {
    {PA5, PWM_0,  PIN_DATA(5, 1)},
    {PB2, PWM_1,  PIN_DATA(5, 1)},
    {PB4, PWM_2,  PIN_DATA(5, 1)},
    {PD2, PWM_3,  PIN_DATA(5, 1)},
    {PD4, PWM_4,  PIN_DATA(5, 1)},
    {PE1, PWM_5,  PIN_DATA(5, 1)},
    {PE6, PWM_6,  PIN_DATA(5, 1)},
    {PC2, PWM_7,  PIN_DATA(5, 1)},
    {PL6, PWM_8,  PIN_DATA(3, 1)},
    {PC4, PWM_9,  PIN_DATA(5, 1)},
    {PM2, PWM_10, PIN_DATA(3, 1)},
    {PU0, PWM_11, PIN_DATA(3, 1)},
    {PU6, PWM_12, PIN_DATA(3, 1)},
    {NC,  NC,     0}
};

void pwmout_init(pwmout_t *obj, PinName pin)
{
    // Determine the pwm channel
    PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM);

    // Assert input is valid
    MBED_ASSERT(pwm != (PWMName)NC);

    switch (pwm) {
        case PWM_0:
            obj->p_t32a.p_instance   = TSB_T32A1;
            // Clock enable of T32A ch01
            TSB_CG_FSYSMENA_IPMENA07 = TXZ_ENABLE;
            break;
        case PWM_1:
            obj->p_t32a.p_instance   = TSB_T32A2;
            // Clock enable of T32A ch02
            TSB_CG_FSYSMENA_IPMENA08 = TXZ_ENABLE;
            break;
        case PWM_2:
            obj->p_t32a.p_instance   = TSB_T32A3;
            // Clock enable of T32A ch03
            TSB_CG_FSYSMENA_IPMENA09 = TXZ_ENABLE;
            break;
        case PWM_3:
            obj->p_t32a.p_instance   = TSB_T32A4;
            // Clock enable of T32A ch04
            TSB_CG_FSYSMENA_IPMENA10 = TXZ_ENABLE;
            break;
        case PWM_4:
            obj->p_t32a.p_instance   = TSB_T32A5;
            // Clock enable of T32A ch05
            TSB_CG_FSYSMENA_IPMENA11 = TXZ_ENABLE;
            break;
        case PWM_5:
            obj->p_t32a.p_instance   = TSB_T32A6;
            // Clock enable of T32A ch06
            TSB_CG_FSYSMENA_IPMENA12 = TXZ_ENABLE;
            break;
        case PWM_6:
            obj->p_t32a.p_instance   = TSB_T32A7;
            // Clock enable of T32A ch07
            TSB_CG_FSYSMENA_IPMENA13 = TXZ_ENABLE;
            break;
        case PWM_7:
            obj->p_t32a.p_instance   = TSB_T32A8;
            // Clock enable of T32A ch08
            TSB_CG_FSYSMENA_IPMENA14 = TXZ_ENABLE;
            break;
        case PWM_8:
            obj->p_t32a.p_instance   = TSB_T32A9;
            // Clock enable of T32A ch09
            TSB_CG_FSYSMENA_IPMENA15 = TXZ_ENABLE;
            break;
        case PWM_9:
            obj->p_t32a.p_instance   = TSB_T32A10;
            // Clock enable of T32A ch10
            TSB_CG_FSYSMENA_IPMENA16 = TXZ_ENABLE;
            break;
        case PWM_10:
            obj->p_t32a.p_instance   = TSB_T32A11;
            // Clock enable of T32A ch11
            TSB_CG_FSYSMENA_IPMENA17 = TXZ_ENABLE;
            break;
        case PWM_11:
            obj->p_t32a.p_instance   = TSB_T32A12;
            // Clock enable of T32A ch12
            TSB_CG_FSYSMENA_IPMENA18 = TXZ_ENABLE;
            break;
        case PWM_12:
            obj->p_t32a.p_instance   = TSB_T32A13;
            // Clock enable of T32A ch13
            TSB_CG_FSYSMENA_IPMENA19 = TXZ_ENABLE;
            break;
        default:
            obj->p_t32a.p_instance = NULL;
            break;
    }

    if (obj->p_t32a.p_instance == NULL) {
        return;
    }

    // Enable clock for GPIO port.
    TSB_CG->FSYSMENB |= (TXZ_ENABLE << ((PIN_PORT(pin)) + GPIO_CLK_OFFSET));

    // Set pin function as PWM
    pinmap_pinout(pin, PinMap_PWM);

    // Default to 20ms, 0% duty cycle
    pwmout_period_ms(obj, 20);
}

void pwmout_free(pwmout_t *obj)
{
    // Stop PWM
    obj->p_t32a.p_instance->RUNC    = (T32A_RUN_ENABLE | T32A_COUNT_STOP);
    obj->trailing_timing = TXZ_DISABLE;
    obj->leading_timing = TXZ_DISABLE;
    obj->p_t32a.p_instance = NULL;
}

void pwmout_write(pwmout_t *obj, float value)
{
    // Stop PWM
    obj->p_t32a.p_instance->RUNC = (T32A_RUN_ENABLE | T32A_COUNT_STOP);

    if (value <= 0.0f) {
        value = TXZ_DISABLE;
    } else if (value >= 1.0f) {
        value = TXZ_ENABLE;
    }

    // Store the new leading_timing value
    obj->leading_timing = obj->trailing_timing - (obj->trailing_timing * value);

    // Setting T32A_RGA0 register
    obj->p_t32a.p_instance->RGC0 = obj->leading_timing;

    // Start PWM
    obj->p_t32a.p_instance->RUNC = (T32A_RUN_ENABLE | T32A_COUNT_START);
}

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)
{
    uint32_t prscl   = 0;
    float duty_cycle = 0;
    float seconds    = (float)((us) / 1000000.0f);

    obj->period = seconds;
    // Restore the duty-cycle
    duty_cycle  = ((float)(obj->trailing_timing - obj->leading_timing) / obj->trailing_timing);
    prscl       = T32A_PRSCLx_32;

    obj->trailing_timing = (us * CALCULATE_RGC1_VAL);
    obj->leading_timing  = ((obj->trailing_timing)- (obj->trailing_timing * duty_cycle));

    obj->p_t32a.p_instance->MOD     =  T32A_MODE_32;
    obj->p_t32a.p_instance->RUNC    = (T32A_RUN_DISABLE | T32A_COUNT_STOP);
    obj->p_t32a.p_instance->CRC     = (prscl | T32A_RELOAD_TREGx);
    obj->p_t32a.p_instance->IMC     = (T32A_IMUFx_MASK_REQ | T32A_IMOFx_MASK_REQ |
                                       T32A_IMx1_MASK_REQ  | T32A_IMx0_MASK_REQ);
    obj->p_t32a.p_instance->RGC0    = obj->leading_timing;
    obj->p_t32a.p_instance->RGC1    = obj->trailing_timing;
    obj->p_t32a.p_instance->OUTCRC0 = T32A_OCR_DISABLE;
    obj->p_t32a.p_instance->OUTCRC1 = (T32A_OCRCMPx1_CLR | T32A_OCRCMPx0_SET);
    obj->p_t32a.p_instance->RUNC    = (T32A_RUN_ENABLE   | T32A_COUNT_START);
}

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;

    seconds = (float)(us / 1000000.0f);
    value   = (((seconds / obj->period) * 100.0f) / 100.0f);
    pwmout_write(obj, value);
}