Skip to content

Commit 146eb25

Browse files
committed
Merge pull request #201 from toyowata/master
Added PwmOut for LPC1549 target
2 parents 8c6ca15 + 855bafe commit 146eb25

File tree

3 files changed

+175
-1
lines changed

3 files changed

+175
-1
lines changed

libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/device.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040

4141
#define DEVICE_ETHERNET 0
4242

43-
#define DEVICE_PWMOUT 0
43+
#define DEVICE_PWMOUT 1
4444

4545
#define DEVICE_SEMIHOST 0
4646
#define DEVICE_LOCALFILESYSTEM 0

libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/objects.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ struct gpio_irq_s {
2929
uint32_t ch;
3030
};
3131

32+
struct pwmout_s {
33+
LPC_SCT0_Type* pwm;
34+
uint32_t pwm_ch;
35+
};
36+
3237
struct serial_s {
3338
LPC_USART0_Type *uart;
3439
unsigned char index;
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2006-2013 ARM Limited
3+
*
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
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
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.
15+
*/
16+
17+
#include "pwmout_api.h"
18+
#include "cmsis.h"
19+
#include "pinmap.h"
20+
#include "error.h"
21+
22+
static LPC_SCT0_Type *SCTs[4] = {
23+
(LPC_SCT0_Type*)LPC_SCT0,
24+
(LPC_SCT0_Type*)LPC_SCT1,
25+
(LPC_SCT0_Type*)LPC_SCT2,
26+
(LPC_SCT0_Type*)LPC_SCT3,
27+
};
28+
29+
// bit flags for used SCTs
30+
static unsigned char sct_used = 0;
31+
static int get_available_sct(void) {
32+
int i;
33+
// start from 1, since 0 is used by ticker at the moment
34+
for (i=1; i<4; i++) {
35+
if ((sct_used & (1 << i)) == 0)
36+
return i;
37+
}
38+
return -1;
39+
}
40+
41+
void pwmout_init(pwmout_t* obj, PinName pin) {
42+
if (pin == (uint32_t)NC)
43+
error("PwmOut pin mapping failed");
44+
45+
int sct_n = get_available_sct();
46+
if (sct_n == -1) {
47+
error("No available SCT");
48+
}
49+
50+
sct_used |= (1 << sct_n);
51+
obj->pwm = SCTs[sct_n];
52+
obj->pwm_ch = sct_n;
53+
54+
LPC_SCT0_Type* pwm = obj->pwm;
55+
56+
// Enable the SCT clock
57+
LPC_SYSCON->SYSAHBCLKCTRL1 |= (1 << (obj->pwm_ch + 2));
58+
59+
// Clear peripheral reset the SCT:
60+
LPC_SYSCON->PRESETCTRL1 |= (1 << (obj->pwm_ch + 2));
61+
LPC_SYSCON->PRESETCTRL1 &= ~(1 << (obj->pwm_ch + 2));
62+
63+
switch(obj->pwm_ch) {
64+
case 1:
65+
// SCT1_OUT0
66+
LPC_SWM->PINASSIGN[8] &= ~0x000000FF;
67+
LPC_SWM->PINASSIGN[8] |= (pin);
68+
break;
69+
case 2:
70+
// SCT2_OUT0
71+
LPC_SWM->PINASSIGN[8] &= ~0xFF000000;
72+
LPC_SWM->PINASSIGN[8] |= (pin << 24);
73+
break;
74+
case 3:
75+
// SCT3_OUT0
76+
LPC_SWM->PINASSIGN[9] &= ~0x00FF0000;
77+
LPC_SWM->PINASSIGN[9] |= (pin << 16);
78+
break;
79+
default:
80+
break;
81+
}
82+
83+
// Two 16-bit counters, autolimit
84+
pwm->CONFIG &= ~(0x1);
85+
pwm->CONFIG |= (1 << 17);
86+
87+
// halt and clear the counter
88+
pwm->CTRL |= (1 << 2) | (1 << 3);
89+
90+
// System Clock -> us_ticker (1)MHz
91+
pwm->CTRL &= ~(0x7F << 5);
92+
pwm->CTRL |= (((SystemCoreClock/1000000 - 1) & 0x7F) << 5);
93+
94+
// Match reload register
95+
pwm->MATCHREL0 = 20000; // 20ms
96+
pwm->MATCHREL1 = (pwm->MATCHREL0 / 4); // 50% duty
97+
98+
pwm->OUT0_SET = (1 << 0); // event 0
99+
pwm->OUT0_CLR = (1 << 1); // event 1
100+
101+
pwm->EV0_CTRL = (1 << 12);
102+
pwm->EV0_STATE = 0xFFFFFFFF;
103+
pwm->EV1_CTRL = (1 << 12) | (1 << 0);
104+
pwm->EV1_STATE = 0xFFFFFFFF;
105+
106+
// unhalt the counter:
107+
// - clearing bit 2 of the CTRL register
108+
pwm->CTRL &= ~(1 << 2);
109+
110+
// default to 20ms: standard for servos, and fine for e.g. brightness control
111+
pwmout_period_ms(obj, 20);
112+
pwmout_write (obj, 0);
113+
}
114+
115+
void pwmout_free(pwmout_t* obj) {
116+
// Disable the SCT clock
117+
LPC_SYSCON->SYSAHBCLKCTRL1 &= ~(1 << (obj->pwm_ch + 2));
118+
sct_used &= ~(1 << obj->pwm_ch);
119+
}
120+
121+
void pwmout_write(pwmout_t* obj, float value) {
122+
LPC_SCT0_Type* pwm = obj->pwm;
123+
if (value < 0.0f) {
124+
value = 0.0;
125+
} else if (value > 1.0f) {
126+
value = 1.0;
127+
}
128+
uint32_t t_off = pwm->MATCHREL0 - (uint32_t)((float)(pwm->MATCHREL0) * value);
129+
uint32_t t_on = (uint32_t)((float)(pwm->MATCHREL0) * value);
130+
pwm->MATCHREL1 = t_on;
131+
}
132+
133+
float pwmout_read(pwmout_t* obj) {
134+
uint32_t t_off = obj->pwm->MATCHREL0;
135+
uint32_t t_on = obj->pwm->MATCHREL1;
136+
float v = (float)t_on/(float)t_off;
137+
return (v > 1.0f) ? (1.0f) : (v);
138+
}
139+
140+
void pwmout_period(pwmout_t* obj, float seconds) {
141+
pwmout_period_us(obj, seconds * 1000000.0f);
142+
}
143+
144+
void pwmout_period_ms(pwmout_t* obj, int ms) {
145+
pwmout_period_us(obj, ms * 1000);
146+
}
147+
148+
// Set the PWM period, keeping the duty cycle the same.
149+
void pwmout_period_us(pwmout_t* obj, int us) {
150+
LPC_SCT0_Type* pwm = obj->pwm;
151+
uint32_t t_off = pwm->MATCHREL0;
152+
uint32_t t_on = pwm->MATCHREL1;
153+
float v = (float)t_on/(float)t_off;
154+
pwm->MATCHREL0 = (uint64_t)us;
155+
pwm->MATCHREL1 = (uint64_t)((float)us * (float)v);
156+
}
157+
158+
void pwmout_pulsewidth(pwmout_t* obj, float seconds) {
159+
pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
160+
}
161+
162+
void pwmout_pulsewidth_ms(pwmout_t* obj, int ms) {
163+
pwmout_pulsewidth_us(obj, ms * 1000);
164+
}
165+
166+
void pwmout_pulsewidth_us(pwmout_t* obj, int us) {
167+
obj->pwm->MATCHREL1 = (uint64_t)us;
168+
}
169+

0 commit comments

Comments
 (0)