mbed library sources. Supersedes mbed-src.

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

Committer:
AnnaBridge
Date:
Wed Feb 20 22:31:08 2019 +0000
Revision:
189:f392fc9709a3
Parent:
188:bcfe06ba3d64
mbed library release version 165

Who changed what in which revision?

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