]>
git.gir.st - tmk_keyboard.git/blob - tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC82X/pwmout_api.c
1 /* mbed Microcontroller Library
2 * Copyright (c) 2006-2013 ARM Limited
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 #include "mbed_assert.h"
17 #include "pwmout_api.h"
20 #include "mbed_error.h"
24 // bit flags for used SCTs
25 static unsigned char sct_used
= 0;
27 static int get_available_sct()
30 for (i
= 0; i
< 4; i
++) {
31 if ((sct_used
& (1 << i
)) == 0)
37 void pwmout_init(pwmout_t
* obj
, PinName pin
)
39 MBED_ASSERT(pin
!= (uint32_t)NC
);
41 int sct_n
= get_available_sct();
43 error("No available SCT");
46 sct_used
|= (1 << sct_n
);
48 obj
->pwm
= (LPC_SCT_Type
*)LPC_SCT
;
51 LPC_SCT_Type
* pwm
= obj
->pwm
;
53 // Enable the SCT clock
54 LPC_SYSCON
->SYSAHBCLKCTRL
|= (1 << 8);
56 // Clear peripheral reset the SCT:
57 LPC_SYSCON
->PRESETCTRL
|= (1 << 8);
62 LPC_SWM
->PINASSIGN
[7] &= ~0xFF000000;
63 LPC_SWM
->PINASSIGN
[7] |= ((pin
>> PIN_SHIFT
) << 24);
67 LPC_SWM
->PINASSIGN
[8] &= ~0x000000FF;
68 LPC_SWM
->PINASSIGN
[8] |= (pin
>> PIN_SHIFT
);
72 LPC_SWM
->PINASSIGN
[8] &= ~0x0000FF00;
73 LPC_SWM
->PINASSIGN
[8] |= ((pin
>> PIN_SHIFT
) << 8);
77 LPC_SWM
->PINASSIGN
[8] &= ~0x00FF0000;
78 LPC_SWM
->PINASSIGN
[8] |= ((pin
>> PIN_SHIFT
) << 16);
84 // Unified 32-bit counter, autolimit
85 pwm
->CONFIG
|= ((0x3 << 17) | 0x01);
87 // halt and clear the counter
88 pwm
->CTRL
|= (1 << 2) | (1 << 3);
90 // System Clock -> us_ticker (1)MHz
91 pwm
->CTRL
&= ~(0x7F << 5);
92 pwm
->CTRL
|= (((SystemCoreClock
/1000000 - 1) & 0x7F) << 5);
94 pwm
->OUT
[sct_n
].SET
= (1 << ((sct_n
* 2) + 0));
95 pwm
->OUT
[sct_n
].CLR
= (1 << ((sct_n
* 2) + 1));
97 pwm
->EVENT
[(sct_n
* 2) + 0].CTRL
= (1 << 12) | ((sct_n
* 2) + 0); // match event
98 pwm
->EVENT
[(sct_n
* 2) + 0].STATE
= 0xFFFFFFFF;
99 pwm
->EVENT
[(sct_n
* 2) + 1].CTRL
= (1 << 12) | ((sct_n
* 2) + 1);
100 pwm
->EVENT
[(sct_n
* 2) + 1].STATE
= 0xFFFFFFFF;
102 // unhalt the counter:
103 // - clearing bit 2 of the CTRL register
104 pwm
->CTRL
&= ~(1 << 2);
106 // default to 20ms: standard for servos, and fine for e.g. brightness control
107 pwmout_period_ms(obj
, 20);
108 pwmout_write (obj
, 0);
111 void pwmout_free(pwmout_t
* obj
)
113 // Disable the SCT clock
114 LPC_SYSCON
->SYSAHBCLKCTRL
&= ~(1 << 8);
115 sct_used
&= ~(1 << obj
->pwm_ch
);
118 void pwmout_write(pwmout_t
* obj
, float value
)
122 } else if (value
> 1.0f
) {
125 uint32_t t_on
= (uint32_t)((float)(obj
->pwm
->MATCHREL
[obj
->pwm_ch
* 2]) * value
);
126 obj
->pwm
->MATCHREL
[(obj
->pwm_ch
* 2) + 1] = t_on
;
129 float pwmout_read(pwmout_t
* obj
)
131 uint32_t t_off
= obj
->pwm
->MATCHREL
[(obj
->pwm_ch
* 2) + 0];
132 uint32_t t_on
= obj
->pwm
->MATCHREL
[(obj
->pwm_ch
* 2) + 1];
133 float v
= (float)t_on
/(float)t_off
;
134 return (v
> 1.0f
) ? (1.0f
) : (v
);
137 void pwmout_period(pwmout_t
* obj
, float seconds
)
139 pwmout_period_us(obj
, seconds
* 1000000.0f
);
142 void pwmout_period_ms(pwmout_t
* obj
, int ms
)
144 pwmout_period_us(obj
, ms
* 1000);
147 // Set the PWM period, keeping the duty cycle the same.
148 void pwmout_period_us(pwmout_t
* obj
, int us
)
150 uint32_t t_off
= obj
->pwm
->MATCHREL
[(obj
->pwm_ch
* 2) + 0];
151 uint32_t t_on
= obj
->pwm
->MATCHREL
[(obj
->pwm_ch
* 2) + 1];
152 float v
= (float)t_on
/(float)t_off
;
153 obj
->pwm
->MATCHREL
[(obj
->pwm_ch
* 2) + 0] = (uint32_t)us
;
154 obj
->pwm
->MATCHREL
[(obj
->pwm_ch
* 2) + 1] = (uint32_t)((float)us
* (float)v
);
157 void pwmout_pulsewidth(pwmout_t
* obj
, float seconds
)
159 pwmout_pulsewidth_us(obj
, seconds
* 1000000.0f
);
162 void pwmout_pulsewidth_ms(pwmout_t
* obj
, int ms
)
164 pwmout_pulsewidth_us(obj
, ms
* 1000);
167 void pwmout_pulsewidth_us(pwmout_t
* obj
, int us
)
169 obj
->pwm
->MATCHREL
[(obj
->pwm_ch
* 2) + 1] = (uint32_t)us
;