source: rtems/c/src/lib/libbsp/arm/lpc176x/pwmout/pwmout.c @ d4edbdbc

4.115
Last change on this file since d4edbdbc was d4edbdbc, checked in by Sebastian Huber <sebastian.huber@…>, on Mar 20, 2015 at 1:09:26 PM

Replace www.rtems.com with www.rtems.org

  • Property mode set to 100755
File size: 5.7 KB
Line 
1/**
2 * @file pwmout.c
3 *
4 * @ingroup lpc176x
5 *
6 * @brief PWM-Out controller for the mbed lpc1768 board.
7 */
8
9/*
10 * Copyright (c) 2014 Taller Technologies.
11 *
12 * @author  Diaz Marcos (marcos.diaz@tallertechnologies.com)
13 *
14 * The license and distribution terms for this file may be
15 * found in the file LICENSE in this distribution or at
16 * http://www.rtems.org/license/LICENSE.
17 */
18
19#include <rtems/status-checks.h>
20#include <bsp/pwmout.h>
21#include <bsp/pwmout-defs.h>
22
23/**
24 * @brief The low level device.
25 */
26static lpc176x_pwm_device *const pwm_device = PWM1_BASE_ADDR;
27
28/**
29 * @brief The possible output pins for each PWM output.
30 */
31static const lpc176x_pwm_pin pwm_pins[ PWM_OUTPUT_NUMBER ][ PWM_NUMBER_OF_PINS
32] =
33{
34  { { 50u, LPC176X_PIN_FUNCTION_10 }, { 64u, LPC176X_PIN_FUNCTION_01 } },
35  { { 52u, LPC176X_PIN_FUNCTION_10 }, { 65u, LPC176X_PIN_FUNCTION_01 } },
36  { { 53u, LPC176X_PIN_FUNCTION_10 }, { 66u, LPC176X_PIN_FUNCTION_01 } },
37  { { 55u, LPC176X_PIN_FUNCTION_10 }, { 67u, LPC176X_PIN_FUNCTION_01 } },
38  { { 56u, LPC176X_PIN_FUNCTION_10 }, { 68u, LPC176X_PIN_FUNCTION_01 } },
39  { { 58u, LPC176X_PIN_FUNCTION_10 }, { 69u, LPC176X_PIN_FUNCTION_01 } },
40};
41
42/**
43 * @brief The pointers to the low level match registers for each PWM output.
44 */
45static volatile uint32_t *const pwm_match[ PWM_OUTPUT_NUMBER ] = {
46  &PWM1MR1,
47  &PWM1MR2,
48  &PWM1MR3,
49  &PWM1MR4,
50  &PWM1MR5,
51  &PWM1MR6
52};
53
54/**
55 * @brief Checks if a pin number is valid for the given PWM,
56 *  and sets the corresponding pin function for that pin.
57 *
58 * @param pin_number The pin number to search.
59 * @param pwm In which PWM search for the pin number.
60 * @param pin_function If the pin number is found, here we return
61 *  the pin function for that pin number.
62 * @return True if found, false otherwise.
63 */
64static inline bool is_found_in_this_pwm(
65  const lpc176x_pin_number       pin_number,
66  const lpc176x_pwm_number    pwm,
67  lpc176x_pin_function *const pin_function
68)
69{
70  lpc176x_pwm_pin_number pnumber = PWM_FIRST_PIN;
71  bool                   found = false;
72
73  while (!found && ( pnumber < PWM_NUMBER_OF_PINS ))
74  {
75    if ( pwm_pins[ pwm ][ pnumber ].pin_number == pin_number ) {
76      found = true;
77      *pin_function = pwm_pins[ pwm ][ pnumber ].pin_function;
78    }/*else implies that the pin number was not found. Keep looking.*/
79    ++pnumber;
80  }
81  return found;
82}
83
84/**
85 * @brief Checks if a pin number is valid for any PWM,
86 *  and sets the corresponding pin function for that pin.
87 *
88 * @param pin_number The pin number to search.
89 * @param pwm If is found here we return in which PWM was found.
90 * @param pin_function If the pin number is found the pin function
91 *  for this pin number one will be returned.
92 * @return True if found, false otherwise.
93 */
94static bool is_valid_pin_number(
95  const lpc176x_pin_number       pin_number,
96  lpc176x_pwm_number *const   pwm,
97  lpc176x_pin_function *const pin_function
98)
99{
100  bool               found = false;
101  lpc176x_pwm_number pwm_local = PWMO_1;
102  while(!found && ( pwm_local < PWM_OUTPUT_NUMBER ))
103  {
104    if ( is_found_in_this_pwm( pin_number, pwm_local, pin_function ) ) {
105      *pwm = pwm_local;
106      found = true;
107    } /*else implies that the pin number was not found. Keep looking.*/
108    ++pwm_local;
109  }
110
111  return found;
112}
113
114/**
115 * @brief Sets the period for the given PWM.
116 *
117 * @param pwm The PWM output in which the period will be set.
118 * @param period The period to set.
119 */
120static void set_period(
121  const lpc176x_pwm_number   pwm,
122  const lpc176x_microseconds period
123)
124{
125  pwm_device->TCR = PWM_TCR_RESET;
126  pwm_device->MR0 = period * PWM_PRESCALER_USECOND;
127  pwm_device->LER |= PWM_LER_LATCH_MATCH_0;
128  pwm_device->TCR = PWM_TCR_PWM | PWM_TCR_ENABLE;
129}
130
131/**
132 * @brief Sets the pulsewidth for the given PWM.
133 *
134 * @param pwm The PWM output in which the pulsewidth will be set.
135 * @param pwidth The pulse width to set.
136 */
137static void set_pulsewidth(
138  const lpc176x_pwm_number pwm,
139  lpc176x_microseconds     pwidth
140)
141{
142  pwidth *= PWM_PRESCALER_USECOND;
143
144  if ( pwm_device->MR0 == pwidth ) {
145    ++pwidth;
146  } /* Not the same as the period, do nothing.*/
147
148  *( pwm_match[ pwm ] ) = pwidth;
149  pwm_device->LER |= PWM_LER_LATCH( pwm );
150}
151
152rtems_status_code pwm_init( const lpc176x_pin_number pin_number )
153{
154  rtems_status_code    sc = RTEMS_INVALID_NUMBER;
155  lpc176x_pin_function pin_function;
156  lpc176x_pwm_number   pwm;
157
158  if ( is_valid_pin_number( pin_number, &pwm, &pin_function ) ) {
159    sc = lpc176x_module_enable( LPC176X_MODULE_PWM_1,
160      LPC176X_MODULE_PCLK_DEFAULT );
161    RTEMS_CHECK_SC( sc, "enable pwm module" );
162
163    pwm_device->PR = 0;
164    pwm_device->MCR = PWM_MCR_RESET_ON_MATCH0;
165    pwm_device->PCR |= PWM_PCR_ENABLE_PWM( pwm );
166
167    set_period( pwm, PWM_DEFAULT_PERIOD );
168    set_pulsewidth( pwm, PWM_DEFAULT_PULSEWIDTH );
169
170    lpc176x_pin_select( pin_number, pin_function );
171  } /* else implies that the pin number is not valid.
172     So, a RTEMS_INVALID_NUMBER will be returned.*/
173
174  return sc;
175}
176
177rtems_status_code pwm_period(
178  const lpc176x_pin_number    pin_number,
179  const lpc176x_microseconds period
180)
181{
182  rtems_status_code    sc = RTEMS_INVALID_NUMBER;
183  lpc176x_pin_function pin_function;
184  lpc176x_pwm_number   pwm;
185
186  if ( is_valid_pin_number( pin_number, &pwm, &pin_function ) ) {
187    sc = RTEMS_SUCCESSFUL;
188    set_period( pwm, period );
189  } /* else implies that the pin number is not valid.
190     So, a RTEMS_INVALID_NUMBER will be returned.*/
191
192  return sc;
193}
194
195rtems_status_code pwm_pulsewidth(
196  const lpc176x_pin_number    pin_number,
197  const lpc176x_microseconds pwidth
198)
199{
200  rtems_status_code    sc = RTEMS_INVALID_NUMBER;
201  lpc176x_pin_function pin_function;
202  lpc176x_pwm_number   pwm;
203
204  if ( is_valid_pin_number( pin_number, &pwm, &pin_function ) ) {
205    sc = RTEMS_SUCCESSFUL;
206    set_pulsewidth( pwm, pwidth );
207  } /* Else wrong pin_number return RTEMS_INVALID_NUMBER*/
208
209  return sc;
210}
Note: See TracBrowser for help on using the repository browser.