helpfor studient
Dependents: STM32_F103-C8T6basecanblink_led
Fork of mbed-dev by
targets/TARGET_TOSHIBA/TARGET_TMPM46B/pwmout_api.c@185:08ed48f1de7f, 2018-04-19 (annotated)
- Committer:
- AnnaBridge
- Date:
- Thu Apr 19 17:12:19 2018 +0100
- Revision:
- 185:08ed48f1de7f
mbed-dev library. Release version 161
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
AnnaBridge | 185:08ed48f1de7f | 1 | /* mbed Microcontroller Library |
AnnaBridge | 185:08ed48f1de7f | 2 | * Copyright (c) 2006-2013 ARM Limited |
AnnaBridge | 185:08ed48f1de7f | 3 | * |
AnnaBridge | 185:08ed48f1de7f | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
AnnaBridge | 185:08ed48f1de7f | 5 | * you may not use this file except in compliance with the License. |
AnnaBridge | 185:08ed48f1de7f | 6 | * You may obtain a copy of the License at |
AnnaBridge | 185:08ed48f1de7f | 7 | * |
AnnaBridge | 185:08ed48f1de7f | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
AnnaBridge | 185:08ed48f1de7f | 9 | * |
AnnaBridge | 185:08ed48f1de7f | 10 | * Unless required by applicable law or agreed to in writing, software |
AnnaBridge | 185:08ed48f1de7f | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
AnnaBridge | 185:08ed48f1de7f | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
AnnaBridge | 185:08ed48f1de7f | 13 | * See the License for the specific language governing permissions and |
AnnaBridge | 185:08ed48f1de7f | 14 | * limitations under the License. |
AnnaBridge | 185:08ed48f1de7f | 15 | */ |
AnnaBridge | 185:08ed48f1de7f | 16 | #include "pwmout_api.h" |
AnnaBridge | 185:08ed48f1de7f | 17 | #include "PeripheralNames.h" |
AnnaBridge | 185:08ed48f1de7f | 18 | #include "pinmap.h" |
AnnaBridge | 185:08ed48f1de7f | 19 | #include "tmpm46b_tmrb.h" |
AnnaBridge | 185:08ed48f1de7f | 20 | |
AnnaBridge | 185:08ed48f1de7f | 21 | #define MAX_COUNTER_16B 0xFFFF |
AnnaBridge | 185:08ed48f1de7f | 22 | |
AnnaBridge | 185:08ed48f1de7f | 23 | static TMRB_InitTypeDef m_tmrb; |
AnnaBridge | 185:08ed48f1de7f | 24 | static TMRB_FFOutputTypeDef FFStruct; |
AnnaBridge | 185:08ed48f1de7f | 25 | |
AnnaBridge | 185:08ed48f1de7f | 26 | static const PinMap PinMap_PWM[] = { |
AnnaBridge | 185:08ed48f1de7f | 27 | {PE4, PWM_0, PIN_DATA(5, 1)}, |
AnnaBridge | 185:08ed48f1de7f | 28 | {PB6, PWM_1, PIN_DATA(4, 1)}, |
AnnaBridge | 185:08ed48f1de7f | 29 | {PH1, PWM_2, PIN_DATA(2, 1)}, |
AnnaBridge | 185:08ed48f1de7f | 30 | {PH0, PWM_3, PIN_DATA(2, 1)}, |
AnnaBridge | 185:08ed48f1de7f | 31 | {PK1, PWM_4, PIN_DATA(4, 1)}, |
AnnaBridge | 185:08ed48f1de7f | 32 | {PA7, PWM_5, PIN_DATA(5, 1)}, |
AnnaBridge | 185:08ed48f1de7f | 33 | {NC, NC, 0} |
AnnaBridge | 185:08ed48f1de7f | 34 | }; |
AnnaBridge | 185:08ed48f1de7f | 35 | |
AnnaBridge | 185:08ed48f1de7f | 36 | static const uint32_t prescale_tbl[] = { |
AnnaBridge | 185:08ed48f1de7f | 37 | 2, 8, 32, 64, 128, 256, 512 |
AnnaBridge | 185:08ed48f1de7f | 38 | }; |
AnnaBridge | 185:08ed48f1de7f | 39 | |
AnnaBridge | 185:08ed48f1de7f | 40 | #define CLOCK_FREQUENCY (48000000) // Input source clock |
AnnaBridge | 185:08ed48f1de7f | 41 | |
AnnaBridge | 185:08ed48f1de7f | 42 | void pwmout_init(pwmout_t *obj, PinName pin) |
AnnaBridge | 185:08ed48f1de7f | 43 | { |
AnnaBridge | 185:08ed48f1de7f | 44 | // Determine the pwm channel |
AnnaBridge | 185:08ed48f1de7f | 45 | PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM); |
AnnaBridge | 185:08ed48f1de7f | 46 | //Assert input is valid |
AnnaBridge | 185:08ed48f1de7f | 47 | MBED_ASSERT(pwm != (PWMName)NC); |
AnnaBridge | 185:08ed48f1de7f | 48 | switch (pwm) { |
AnnaBridge | 185:08ed48f1de7f | 49 | case PWM_0: |
AnnaBridge | 185:08ed48f1de7f | 50 | obj->channel = TSB_TB2; |
AnnaBridge | 185:08ed48f1de7f | 51 | break; |
AnnaBridge | 185:08ed48f1de7f | 52 | case PWM_1: |
AnnaBridge | 185:08ed48f1de7f | 53 | obj->channel = TSB_TB3; |
AnnaBridge | 185:08ed48f1de7f | 54 | break; |
AnnaBridge | 185:08ed48f1de7f | 55 | case PWM_2: |
AnnaBridge | 185:08ed48f1de7f | 56 | obj->channel = TSB_TB4; |
AnnaBridge | 185:08ed48f1de7f | 57 | break; |
AnnaBridge | 185:08ed48f1de7f | 58 | case PWM_3: |
AnnaBridge | 185:08ed48f1de7f | 59 | obj->channel = TSB_TB5; |
AnnaBridge | 185:08ed48f1de7f | 60 | break; |
AnnaBridge | 185:08ed48f1de7f | 61 | case PWM_4: |
AnnaBridge | 185:08ed48f1de7f | 62 | obj->channel = TSB_TB6; |
AnnaBridge | 185:08ed48f1de7f | 63 | break; |
AnnaBridge | 185:08ed48f1de7f | 64 | case PWM_5: |
AnnaBridge | 185:08ed48f1de7f | 65 | obj->channel = TSB_TB7; |
AnnaBridge | 185:08ed48f1de7f | 66 | break; |
AnnaBridge | 185:08ed48f1de7f | 67 | default: |
AnnaBridge | 185:08ed48f1de7f | 68 | obj->channel = NULL; |
AnnaBridge | 185:08ed48f1de7f | 69 | break; |
AnnaBridge | 185:08ed48f1de7f | 70 | } |
AnnaBridge | 185:08ed48f1de7f | 71 | CG_SetFcPeriphA((0x01U << (15U + pwm)), ENABLE); |
AnnaBridge | 185:08ed48f1de7f | 72 | TMRB_SetIdleMode(TSB_TB0, DISABLE); |
AnnaBridge | 185:08ed48f1de7f | 73 | // Set pin function as PWM |
AnnaBridge | 185:08ed48f1de7f | 74 | pinmap_pinout(pin, PinMap_PWM); |
AnnaBridge | 185:08ed48f1de7f | 75 | // Default to 20ms, 0% duty cycle |
AnnaBridge | 185:08ed48f1de7f | 76 | pwmout_period_ms(obj, 20); |
AnnaBridge | 185:08ed48f1de7f | 77 | } |
AnnaBridge | 185:08ed48f1de7f | 78 | |
AnnaBridge | 185:08ed48f1de7f | 79 | void pwmout_free(pwmout_t *obj) |
AnnaBridge | 185:08ed48f1de7f | 80 | { |
AnnaBridge | 185:08ed48f1de7f | 81 | // Stops and clear count operation |
AnnaBridge | 185:08ed48f1de7f | 82 | TMRB_SetRunState(obj->channel, TMRB_STOP); |
AnnaBridge | 185:08ed48f1de7f | 83 | pwmout_write(obj,0); |
AnnaBridge | 185:08ed48f1de7f | 84 | obj->channel = NULL; |
AnnaBridge | 185:08ed48f1de7f | 85 | obj->trailing_timing = 0; |
AnnaBridge | 185:08ed48f1de7f | 86 | obj->leading_timing = 0; |
AnnaBridge | 185:08ed48f1de7f | 87 | obj->divisor = 0; |
AnnaBridge | 185:08ed48f1de7f | 88 | TMRB_SetIdleMode(TSB_TB0, ENABLE); |
AnnaBridge | 185:08ed48f1de7f | 89 | } |
AnnaBridge | 185:08ed48f1de7f | 90 | |
AnnaBridge | 185:08ed48f1de7f | 91 | void pwmout_write(pwmout_t *obj, float value) |
AnnaBridge | 185:08ed48f1de7f | 92 | { |
AnnaBridge | 185:08ed48f1de7f | 93 | // Stop timer for setting clock again |
AnnaBridge | 185:08ed48f1de7f | 94 | TMRB_SetRunState(obj->channel, TMRB_STOP); |
AnnaBridge | 185:08ed48f1de7f | 95 | // values outside this range will be saturated to 0.0f or 1.0f |
AnnaBridge | 185:08ed48f1de7f | 96 | // Disable flip-flop reverse trigger when leading_timing and trailing_timing are duplicated |
AnnaBridge | 185:08ed48f1de7f | 97 | if (value <= 0.0f) { |
AnnaBridge | 185:08ed48f1de7f | 98 | value = 0; |
AnnaBridge | 185:08ed48f1de7f | 99 | FFStruct.FlipflopCtrl = TMRB_FLIPFLOP_CLEAR; |
AnnaBridge | 185:08ed48f1de7f | 100 | FFStruct.FlipflopReverseTrg = TMRB_DISABLE_FLIPFLOP; |
AnnaBridge | 185:08ed48f1de7f | 101 | } else if (value >= 1.0f) { |
AnnaBridge | 185:08ed48f1de7f | 102 | value = 1; |
AnnaBridge | 185:08ed48f1de7f | 103 | FFStruct.FlipflopCtrl = TMRB_FLIPFLOP_SET; |
AnnaBridge | 185:08ed48f1de7f | 104 | FFStruct.FlipflopReverseTrg = TMRB_DISABLE_FLIPFLOP; |
AnnaBridge | 185:08ed48f1de7f | 105 | } else { |
AnnaBridge | 185:08ed48f1de7f | 106 | FFStruct.FlipflopCtrl = TMRB_FLIPFLOP_CLEAR; |
AnnaBridge | 185:08ed48f1de7f | 107 | FFStruct.FlipflopReverseTrg = (TMRB_FLIPFLOP_MATCH_TRAILING | TMRB_FLIPFLOP_MATCH_LEADING); |
AnnaBridge | 185:08ed48f1de7f | 108 | } |
AnnaBridge | 185:08ed48f1de7f | 109 | TMRB_SetFlipFlop(obj->channel, &FFStruct); |
AnnaBridge | 185:08ed48f1de7f | 110 | |
AnnaBridge | 185:08ed48f1de7f | 111 | if (obj->period > 0.7) { |
AnnaBridge | 185:08ed48f1de7f | 112 | value = 1; //TMPM46B duty cycle should be < 700ms, above 700ms fixed 50% duty cycle |
AnnaBridge | 185:08ed48f1de7f | 113 | } |
AnnaBridge | 185:08ed48f1de7f | 114 | // Store the new leading_timing value |
AnnaBridge | 185:08ed48f1de7f | 115 | obj->leading_timing = obj->trailing_timing - (uint16_t)(obj->trailing_timing * value); |
AnnaBridge | 185:08ed48f1de7f | 116 | |
AnnaBridge | 185:08ed48f1de7f | 117 | // Setting TBxRG0 register |
AnnaBridge | 185:08ed48f1de7f | 118 | TMRB_ChangeLeadingTiming(obj->channel, obj->leading_timing); |
AnnaBridge | 185:08ed48f1de7f | 119 | TMRB_SetRunState(obj->channel, TMRB_RUN); |
AnnaBridge | 185:08ed48f1de7f | 120 | } |
AnnaBridge | 185:08ed48f1de7f | 121 | |
AnnaBridge | 185:08ed48f1de7f | 122 | float pwmout_read(pwmout_t *obj) |
AnnaBridge | 185:08ed48f1de7f | 123 | { |
AnnaBridge | 185:08ed48f1de7f | 124 | float duty_cycle = (float)(obj->trailing_timing - obj->leading_timing) / obj->trailing_timing; |
AnnaBridge | 185:08ed48f1de7f | 125 | return duty_cycle; |
AnnaBridge | 185:08ed48f1de7f | 126 | } |
AnnaBridge | 185:08ed48f1de7f | 127 | |
AnnaBridge | 185:08ed48f1de7f | 128 | void pwmout_period(pwmout_t *obj, float seconds) |
AnnaBridge | 185:08ed48f1de7f | 129 | { |
AnnaBridge | 185:08ed48f1de7f | 130 | pwmout_period_us(obj, (int)(seconds * 1000000.0f)); |
AnnaBridge | 185:08ed48f1de7f | 131 | } |
AnnaBridge | 185:08ed48f1de7f | 132 | |
AnnaBridge | 185:08ed48f1de7f | 133 | void pwmout_period_ms(pwmout_t *obj, int ms) |
AnnaBridge | 185:08ed48f1de7f | 134 | { |
AnnaBridge | 185:08ed48f1de7f | 135 | pwmout_period_us(obj, (ms * 1000)); |
AnnaBridge | 185:08ed48f1de7f | 136 | } |
AnnaBridge | 185:08ed48f1de7f | 137 | |
AnnaBridge | 185:08ed48f1de7f | 138 | // Set the PWM period, keeping the duty cycle the same. |
AnnaBridge | 185:08ed48f1de7f | 139 | void pwmout_period_us(pwmout_t *obj, int us) |
AnnaBridge | 185:08ed48f1de7f | 140 | { |
AnnaBridge | 185:08ed48f1de7f | 141 | float seconds = 0; |
AnnaBridge | 185:08ed48f1de7f | 142 | uint32_t cycles = 0; |
AnnaBridge | 185:08ed48f1de7f | 143 | int ClkDiv = 0; |
AnnaBridge | 185:08ed48f1de7f | 144 | int i = 0; |
AnnaBridge | 185:08ed48f1de7f | 145 | float duty_cycle = 0; |
AnnaBridge | 185:08ed48f1de7f | 146 | uint32_t clk_freq = 0; |
AnnaBridge | 185:08ed48f1de7f | 147 | |
AnnaBridge | 185:08ed48f1de7f | 148 | seconds = (float)((us) / 1000000.0f); |
AnnaBridge | 185:08ed48f1de7f | 149 | obj->period = seconds; |
AnnaBridge | 185:08ed48f1de7f | 150 | |
AnnaBridge | 185:08ed48f1de7f | 151 | if (obj->period > 0.7) { |
AnnaBridge | 185:08ed48f1de7f | 152 | clk_freq = (CLOCK_FREQUENCY / 2); |
AnnaBridge | 185:08ed48f1de7f | 153 | } else { |
AnnaBridge | 185:08ed48f1de7f | 154 | clk_freq = CLOCK_FREQUENCY; |
AnnaBridge | 185:08ed48f1de7f | 155 | } |
AnnaBridge | 185:08ed48f1de7f | 156 | // Select highest timer resolution |
AnnaBridge | 185:08ed48f1de7f | 157 | for (i = 0; i < 7; ++i) { |
AnnaBridge | 185:08ed48f1de7f | 158 | cycles = (int)((clk_freq / prescale_tbl[i]) * seconds); |
AnnaBridge | 185:08ed48f1de7f | 159 | if (cycles <= MAX_COUNTER_16B) { |
AnnaBridge | 185:08ed48f1de7f | 160 | ClkDiv = i + 1; // range 1:6 |
AnnaBridge | 185:08ed48f1de7f | 161 | break; |
AnnaBridge | 185:08ed48f1de7f | 162 | } else { |
AnnaBridge | 185:08ed48f1de7f | 163 | cycles = MAX_COUNTER_16B; |
AnnaBridge | 185:08ed48f1de7f | 164 | ClkDiv = 7; |
AnnaBridge | 185:08ed48f1de7f | 165 | } |
AnnaBridge | 185:08ed48f1de7f | 166 | } |
AnnaBridge | 185:08ed48f1de7f | 167 | // Stops and clear count operation |
AnnaBridge | 185:08ed48f1de7f | 168 | TMRB_SetRunState(obj->channel, TMRB_STOP); |
AnnaBridge | 185:08ed48f1de7f | 169 | // Restore the duty-cycle |
AnnaBridge | 185:08ed48f1de7f | 170 | duty_cycle = (float)((obj->trailing_timing - obj->leading_timing) / obj->trailing_timing); |
AnnaBridge | 185:08ed48f1de7f | 171 | obj->trailing_timing = cycles; |
AnnaBridge | 185:08ed48f1de7f | 172 | obj->leading_timing = ((cycles)- (uint16_t)(cycles * duty_cycle)); |
AnnaBridge | 185:08ed48f1de7f | 173 | |
AnnaBridge | 185:08ed48f1de7f | 174 | // Change the source clock division and period |
AnnaBridge | 185:08ed48f1de7f | 175 | m_tmrb.Mode = TMRB_INTERVAL_TIMER; |
AnnaBridge | 185:08ed48f1de7f | 176 | m_tmrb.ClkDiv = ClkDiv; |
AnnaBridge | 185:08ed48f1de7f | 177 | m_tmrb.UpCntCtrl = TMRB_AUTO_CLEAR; |
AnnaBridge | 185:08ed48f1de7f | 178 | m_tmrb.TrailingTiming = obj->trailing_timing; |
AnnaBridge | 185:08ed48f1de7f | 179 | m_tmrb.LeadingTiming = obj->leading_timing; |
AnnaBridge | 185:08ed48f1de7f | 180 | FFStruct.FlipflopCtrl = TMRB_FLIPFLOP_SET; |
AnnaBridge | 185:08ed48f1de7f | 181 | FFStruct.FlipflopReverseTrg = (TMRB_FLIPFLOP_MATCH_TRAILING | TMRB_FLIPFLOP_MATCH_LEADING); |
AnnaBridge | 185:08ed48f1de7f | 182 | // Enable channel |
AnnaBridge | 185:08ed48f1de7f | 183 | TMRB_Enable(obj->channel); |
AnnaBridge | 185:08ed48f1de7f | 184 | // Disable double buffering |
AnnaBridge | 185:08ed48f1de7f | 185 | TMRB_SetDoubleBuf(obj->channel, DISABLE, TMRB_WRITE_REG_SEPARATE); |
AnnaBridge | 185:08ed48f1de7f | 186 | // Init timer function |
AnnaBridge | 185:08ed48f1de7f | 187 | TMRB_Init(obj->channel, &m_tmrb); |
AnnaBridge | 185:08ed48f1de7f | 188 | // Enable double buffering |
AnnaBridge | 185:08ed48f1de7f | 189 | TMRB_SetDoubleBuf(obj->channel, ENABLE, TMRB_WRITE_REG_SEPARATE); |
AnnaBridge | 185:08ed48f1de7f | 190 | TMRB_SetFlipFlop(obj->channel, &FFStruct); |
AnnaBridge | 185:08ed48f1de7f | 191 | // Start timer function |
AnnaBridge | 185:08ed48f1de7f | 192 | TMRB_SetRunState(obj->channel, TMRB_RUN); |
AnnaBridge | 185:08ed48f1de7f | 193 | } |
AnnaBridge | 185:08ed48f1de7f | 194 | |
AnnaBridge | 185:08ed48f1de7f | 195 | void pwmout_pulsewidth(pwmout_t *obj, float seconds) |
AnnaBridge | 185:08ed48f1de7f | 196 | { |
AnnaBridge | 185:08ed48f1de7f | 197 | pwmout_pulsewidth_us(obj, (seconds * 1000000.0f)); |
AnnaBridge | 185:08ed48f1de7f | 198 | } |
AnnaBridge | 185:08ed48f1de7f | 199 | |
AnnaBridge | 185:08ed48f1de7f | 200 | void pwmout_pulsewidth_ms(pwmout_t *obj, int ms) |
AnnaBridge | 185:08ed48f1de7f | 201 | { |
AnnaBridge | 185:08ed48f1de7f | 202 | pwmout_pulsewidth_us(obj, (ms * 1000)); |
AnnaBridge | 185:08ed48f1de7f | 203 | } |
AnnaBridge | 185:08ed48f1de7f | 204 | |
AnnaBridge | 185:08ed48f1de7f | 205 | void pwmout_pulsewidth_us(pwmout_t *obj, int us) |
AnnaBridge | 185:08ed48f1de7f | 206 | { |
AnnaBridge | 185:08ed48f1de7f | 207 | float seconds = 0; |
AnnaBridge | 185:08ed48f1de7f | 208 | float value = 0; |
AnnaBridge | 185:08ed48f1de7f | 209 | |
AnnaBridge | 185:08ed48f1de7f | 210 | seconds = (float)(us / 1000000.0f); |
AnnaBridge | 185:08ed48f1de7f | 211 | value = (((seconds / obj->period) * 100.0f) / 100.0f); |
AnnaBridge | 185:08ed48f1de7f | 212 | pwmout_write(obj, value); |
AnnaBridge | 185:08ed48f1de7f | 213 | } |