Mouse code for the MacroRat

Dependencies:   ITG3200 QEI

Committer:
sahilmgandhi
Date:
Sun May 14 23:18:57 2017 +0000
Revision:
18:6a4db94011d3
Publishing again

Who changed what in which revision?

UserRevisionLine numberNew contents of line
sahilmgandhi 18:6a4db94011d3 1 /*
sahilmgandhi 18:6a4db94011d3 2 * Copyright (c) 2013 Nordic Semiconductor ASA
sahilmgandhi 18:6a4db94011d3 3 * All rights reserved.
sahilmgandhi 18:6a4db94011d3 4 *
sahilmgandhi 18:6a4db94011d3 5 * Redistribution and use in source and binary forms, with or without modification,
sahilmgandhi 18:6a4db94011d3 6 * are permitted provided that the following conditions are met:
sahilmgandhi 18:6a4db94011d3 7 *
sahilmgandhi 18:6a4db94011d3 8 * 1. Redistributions of source code must retain the above copyright notice, this list
sahilmgandhi 18:6a4db94011d3 9 * of conditions and the following disclaimer.
sahilmgandhi 18:6a4db94011d3 10 *
sahilmgandhi 18:6a4db94011d3 11 * 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
sahilmgandhi 18:6a4db94011d3 12 * integrated circuit in a product or a software update for such product, must reproduce
sahilmgandhi 18:6a4db94011d3 13 * the above copyright notice, this list of conditions and the following disclaimer in
sahilmgandhi 18:6a4db94011d3 14 * the documentation and/or other materials provided with the distribution.
sahilmgandhi 18:6a4db94011d3 15 *
sahilmgandhi 18:6a4db94011d3 16 * 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
sahilmgandhi 18:6a4db94011d3 17 * used to endorse or promote products derived from this software without specific prior
sahilmgandhi 18:6a4db94011d3 18 * written permission.
sahilmgandhi 18:6a4db94011d3 19 *
sahilmgandhi 18:6a4db94011d3 20 * 4. This software, with or without modification, must only be used with a
sahilmgandhi 18:6a4db94011d3 21 * Nordic Semiconductor ASA integrated circuit.
sahilmgandhi 18:6a4db94011d3 22 *
sahilmgandhi 18:6a4db94011d3 23 * 5. Any software provided in binary or object form under this license must not be reverse
sahilmgandhi 18:6a4db94011d3 24 * engineered, decompiled, modified and/or disassembled.
sahilmgandhi 18:6a4db94011d3 25 *
sahilmgandhi 18:6a4db94011d3 26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
sahilmgandhi 18:6a4db94011d3 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
sahilmgandhi 18:6a4db94011d3 28 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
sahilmgandhi 18:6a4db94011d3 29 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
sahilmgandhi 18:6a4db94011d3 30 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
sahilmgandhi 18:6a4db94011d3 31 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
sahilmgandhi 18:6a4db94011d3 32 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
sahilmgandhi 18:6a4db94011d3 33 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
sahilmgandhi 18:6a4db94011d3 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
sahilmgandhi 18:6a4db94011d3 35 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
sahilmgandhi 18:6a4db94011d3 36 *
sahilmgandhi 18:6a4db94011d3 37 */
sahilmgandhi 18:6a4db94011d3 38
sahilmgandhi 18:6a4db94011d3 39 #include "mbed_assert.h"
sahilmgandhi 18:6a4db94011d3 40 #include "mbed_error.h"
sahilmgandhi 18:6a4db94011d3 41 #include "pwmout_api.h"
sahilmgandhi 18:6a4db94011d3 42 #include "cmsis.h"
sahilmgandhi 18:6a4db94011d3 43 #include "pinmap.h"
sahilmgandhi 18:6a4db94011d3 44
sahilmgandhi 18:6a4db94011d3 45 #if DEVICE_PWMOUT
sahilmgandhi 18:6a4db94011d3 46
sahilmgandhi 18:6a4db94011d3 47 #include "app_util_platform.h"
sahilmgandhi 18:6a4db94011d3 48 #include "nrf_drv_pwm.h"
sahilmgandhi 18:6a4db94011d3 49
sahilmgandhi 18:6a4db94011d3 50 #define MAX_PWM_COUNTERTOP (0x7FFF) // 0x7FFF is the max of COUNTERTOP value for the PWM peripherial of the nRF52.
sahilmgandhi 18:6a4db94011d3 51 #define MAX_PWM_PERIOD_US (MAX_PWM_COUNTERTOP * 8) // PWM hw is driven by 16 MHz clock, hence the tick is 1_us/16,
sahilmgandhi 18:6a4db94011d3 52 // and 128 is the max prescaler value.
sahilmgandhi 18:6a4db94011d3 53 #define MAX_PWM_PERIOD_MS ((MAX_PWM_PERIOD_US / 1000) + 1) // approximations advance
sahilmgandhi 18:6a4db94011d3 54 #define MAX_PWM_PERIOD_S ((MAX_PWM_PERIOD_US / 1000000) + 1) // approximations advance
sahilmgandhi 18:6a4db94011d3 55
sahilmgandhi 18:6a4db94011d3 56
sahilmgandhi 18:6a4db94011d3 57 #define PWM_INSTANCE_COUNT (PWM_COUNT) // import from the nrf_drv_config.h file
sahilmgandhi 18:6a4db94011d3 58
sahilmgandhi 18:6a4db94011d3 59 ///> instances of nRF52 PWM driver
sahilmgandhi 18:6a4db94011d3 60 static const nrf_drv_pwm_t m_pwm_driver[PWM_INSTANCE_COUNT] =
sahilmgandhi 18:6a4db94011d3 61 {
sahilmgandhi 18:6a4db94011d3 62 #if PWM0_ENABLED
sahilmgandhi 18:6a4db94011d3 63 NRF_DRV_PWM_INSTANCE(0),
sahilmgandhi 18:6a4db94011d3 64 #endif
sahilmgandhi 18:6a4db94011d3 65 #if PWM1_ENABLED
sahilmgandhi 18:6a4db94011d3 66 NRF_DRV_PWM_INSTANCE(1),
sahilmgandhi 18:6a4db94011d3 67 #endif
sahilmgandhi 18:6a4db94011d3 68 #if PWM2_ENABLED
sahilmgandhi 18:6a4db94011d3 69 NRF_DRV_PWM_INSTANCE(2)
sahilmgandhi 18:6a4db94011d3 70 #endif
sahilmgandhi 18:6a4db94011d3 71 };
sahilmgandhi 18:6a4db94011d3 72
sahilmgandhi 18:6a4db94011d3 73 typedef struct
sahilmgandhi 18:6a4db94011d3 74 {
sahilmgandhi 18:6a4db94011d3 75 uint32_t period_us;
sahilmgandhi 18:6a4db94011d3 76 uint32_t duty_us;
sahilmgandhi 18:6a4db94011d3 77 float duty;
sahilmgandhi 18:6a4db94011d3 78 } pwm_signal_t; /// PWM signal description type
sahilmgandhi 18:6a4db94011d3 79
sahilmgandhi 18:6a4db94011d3 80 typedef struct
sahilmgandhi 18:6a4db94011d3 81 {
sahilmgandhi 18:6a4db94011d3 82 nrf_drv_pwm_t * p_pwm_driver;
sahilmgandhi 18:6a4db94011d3 83 pwm_signal_t signal;
sahilmgandhi 18:6a4db94011d3 84 volatile nrf_pwm_values_common_t seq_values[1];
sahilmgandhi 18:6a4db94011d3 85 } pwm_t; /// internal PWM instance support type
sahilmgandhi 18:6a4db94011d3 86
sahilmgandhi 18:6a4db94011d3 87 static pwm_t m_pwm[PWM_INSTANCE_COUNT] =
sahilmgandhi 18:6a4db94011d3 88 {
sahilmgandhi 18:6a4db94011d3 89 #if PWM0_ENABLED
sahilmgandhi 18:6a4db94011d3 90 {.p_pwm_driver = NULL},
sahilmgandhi 18:6a4db94011d3 91 #endif
sahilmgandhi 18:6a4db94011d3 92 #if PWM1_ENABLED
sahilmgandhi 18:6a4db94011d3 93 {.p_pwm_driver = NULL},
sahilmgandhi 18:6a4db94011d3 94 #endif
sahilmgandhi 18:6a4db94011d3 95 #if PWM2_ENABLED
sahilmgandhi 18:6a4db94011d3 96 {.p_pwm_driver = NULL}
sahilmgandhi 18:6a4db94011d3 97 #endif
sahilmgandhi 18:6a4db94011d3 98 }; /// Array of internal PWM instances.
sahilmgandhi 18:6a4db94011d3 99
sahilmgandhi 18:6a4db94011d3 100 typedef struct
sahilmgandhi 18:6a4db94011d3 101 {
sahilmgandhi 18:6a4db94011d3 102 uint16_t period_hwu; // unit related to pwm_clk
sahilmgandhi 18:6a4db94011d3 103 uint16_t duty_hwu; // unit related to pwm_clk
sahilmgandhi 18:6a4db94011d3 104 nrf_pwm_clk_t pwm_clk;
sahilmgandhi 18:6a4db94011d3 105 } pulsewidth_set_t; /// helper type for timing calculations
sahilmgandhi 18:6a4db94011d3 106
sahilmgandhi 18:6a4db94011d3 107
sahilmgandhi 18:6a4db94011d3 108 static void internal_pwmout_exe(pwmout_t *obj, bool new_period, bool initialization);
sahilmgandhi 18:6a4db94011d3 109
sahilmgandhi 18:6a4db94011d3 110 // extern PWM nIRQ handler implementations
sahilmgandhi 18:6a4db94011d3 111 void PWM0_IRQHandler(void);
sahilmgandhi 18:6a4db94011d3 112 void PWM1_IRQHandler(void);
sahilmgandhi 18:6a4db94011d3 113 void PWM2_IRQHandler(void);
sahilmgandhi 18:6a4db94011d3 114
sahilmgandhi 18:6a4db94011d3 115 static const peripheral_handler_desc_t pwm_handlers[PWM_INSTANCE_COUNT] =
sahilmgandhi 18:6a4db94011d3 116 {
sahilmgandhi 18:6a4db94011d3 117 {
sahilmgandhi 18:6a4db94011d3 118 PWM0_IRQn,
sahilmgandhi 18:6a4db94011d3 119 (uint32_t)PWM0_IRQHandler
sahilmgandhi 18:6a4db94011d3 120 },
sahilmgandhi 18:6a4db94011d3 121 {
sahilmgandhi 18:6a4db94011d3 122 PWM1_IRQn,
sahilmgandhi 18:6a4db94011d3 123 (uint32_t)PWM1_IRQHandler
sahilmgandhi 18:6a4db94011d3 124 },
sahilmgandhi 18:6a4db94011d3 125 {
sahilmgandhi 18:6a4db94011d3 126 PWM2_IRQn,
sahilmgandhi 18:6a4db94011d3 127 (uint32_t)PWM2_IRQHandler
sahilmgandhi 18:6a4db94011d3 128 }
sahilmgandhi 18:6a4db94011d3 129 };
sahilmgandhi 18:6a4db94011d3 130
sahilmgandhi 18:6a4db94011d3 131 void pwmout_init(pwmout_t *obj, PinName pin)
sahilmgandhi 18:6a4db94011d3 132 {
sahilmgandhi 18:6a4db94011d3 133 uint32_t i;
sahilmgandhi 18:6a4db94011d3 134
sahilmgandhi 18:6a4db94011d3 135 for (i = 0; PWM_INSTANCE_COUNT; i++)
sahilmgandhi 18:6a4db94011d3 136 {
sahilmgandhi 18:6a4db94011d3 137 if (m_pwm[i].p_pwm_driver == NULL) // a driver instance not assigned to the obj?
sahilmgandhi 18:6a4db94011d3 138 {
sahilmgandhi 18:6a4db94011d3 139 NVIC_SetVector(pwm_handlers[i].IRQn, pwm_handlers[i].vector);
sahilmgandhi 18:6a4db94011d3 140
sahilmgandhi 18:6a4db94011d3 141 obj->pin = pin;
sahilmgandhi 18:6a4db94011d3 142
sahilmgandhi 18:6a4db94011d3 143 obj->pwm_channel = i;
sahilmgandhi 18:6a4db94011d3 144
sahilmgandhi 18:6a4db94011d3 145 m_pwm[i].p_pwm_driver = (nrf_drv_pwm_t *) &m_pwm_driver[i];
sahilmgandhi 18:6a4db94011d3 146 m_pwm[i].signal.period_us = 200000; // 0.02 s
sahilmgandhi 18:6a4db94011d3 147 m_pwm[i].signal.duty_us = 100000;
sahilmgandhi 18:6a4db94011d3 148 m_pwm[i].signal.duty = 0.5f;
sahilmgandhi 18:6a4db94011d3 149
sahilmgandhi 18:6a4db94011d3 150 obj->pwm_struct = &m_pwm[i];
sahilmgandhi 18:6a4db94011d3 151
sahilmgandhi 18:6a4db94011d3 152 internal_pwmout_exe(obj, true, true);
sahilmgandhi 18:6a4db94011d3 153
sahilmgandhi 18:6a4db94011d3 154 break;
sahilmgandhi 18:6a4db94011d3 155 }
sahilmgandhi 18:6a4db94011d3 156 }
sahilmgandhi 18:6a4db94011d3 157
sahilmgandhi 18:6a4db94011d3 158 MBED_ASSERT(i != PWM_INSTANCE_COUNT); // assert if free instance was not found.
sahilmgandhi 18:6a4db94011d3 159 }
sahilmgandhi 18:6a4db94011d3 160
sahilmgandhi 18:6a4db94011d3 161 void pwmout_free(pwmout_t *obj)
sahilmgandhi 18:6a4db94011d3 162 {
sahilmgandhi 18:6a4db94011d3 163 nrf_drv_pwm_uninit( (nrf_drv_pwm_t*) obj->pwm_struct );
sahilmgandhi 18:6a4db94011d3 164
sahilmgandhi 18:6a4db94011d3 165 m_pwm[obj->pwm_channel].p_pwm_driver = NULL;
sahilmgandhi 18:6a4db94011d3 166 }
sahilmgandhi 18:6a4db94011d3 167
sahilmgandhi 18:6a4db94011d3 168 void pwmout_write(pwmout_t *obj, float percent)
sahilmgandhi 18:6a4db94011d3 169 {
sahilmgandhi 18:6a4db94011d3 170
sahilmgandhi 18:6a4db94011d3 171 if (percent < 0)
sahilmgandhi 18:6a4db94011d3 172 {
sahilmgandhi 18:6a4db94011d3 173 percent = 0;
sahilmgandhi 18:6a4db94011d3 174 }
sahilmgandhi 18:6a4db94011d3 175 else if (percent > 1)
sahilmgandhi 18:6a4db94011d3 176 {
sahilmgandhi 18:6a4db94011d3 177 percent = 1;
sahilmgandhi 18:6a4db94011d3 178 }
sahilmgandhi 18:6a4db94011d3 179
sahilmgandhi 18:6a4db94011d3 180 pwm_signal_t * p_pwm_signal = &(((pwm_t*)obj->pwm_struct)->signal);
sahilmgandhi 18:6a4db94011d3 181
sahilmgandhi 18:6a4db94011d3 182 p_pwm_signal->duty = percent;
sahilmgandhi 18:6a4db94011d3 183
sahilmgandhi 18:6a4db94011d3 184 int us = (((int)p_pwm_signal->period_us) * percent);
sahilmgandhi 18:6a4db94011d3 185
sahilmgandhi 18:6a4db94011d3 186 pwmout_pulsewidth_us(obj, us);
sahilmgandhi 18:6a4db94011d3 187 }
sahilmgandhi 18:6a4db94011d3 188
sahilmgandhi 18:6a4db94011d3 189 float pwmout_read(pwmout_t *obj)
sahilmgandhi 18:6a4db94011d3 190 {
sahilmgandhi 18:6a4db94011d3 191 pwm_signal_t * p_pwm_signal = &(((pwm_t*)obj->pwm_struct)->signal);
sahilmgandhi 18:6a4db94011d3 192
sahilmgandhi 18:6a4db94011d3 193 return (float)p_pwm_signal->duty_us / (float)p_pwm_signal->period_us;
sahilmgandhi 18:6a4db94011d3 194 }
sahilmgandhi 18:6a4db94011d3 195
sahilmgandhi 18:6a4db94011d3 196 void pwmout_period(pwmout_t *obj, float seconds)
sahilmgandhi 18:6a4db94011d3 197 {
sahilmgandhi 18:6a4db94011d3 198 // raught saturation < 0, quasi-max>
sahilmgandhi 18:6a4db94011d3 199 if (seconds > MAX_PWM_PERIOD_S)
sahilmgandhi 18:6a4db94011d3 200 {
sahilmgandhi 18:6a4db94011d3 201 seconds = MAX_PWM_PERIOD_S;
sahilmgandhi 18:6a4db94011d3 202 }
sahilmgandhi 18:6a4db94011d3 203 else if (seconds < 0)
sahilmgandhi 18:6a4db94011d3 204 {
sahilmgandhi 18:6a4db94011d3 205 seconds = 0; // f. pwmout_period_us will set period to min. value
sahilmgandhi 18:6a4db94011d3 206 }
sahilmgandhi 18:6a4db94011d3 207
sahilmgandhi 18:6a4db94011d3 208 int us = seconds * 1000000;
sahilmgandhi 18:6a4db94011d3 209
sahilmgandhi 18:6a4db94011d3 210 pwmout_period_us(obj, us);
sahilmgandhi 18:6a4db94011d3 211 }
sahilmgandhi 18:6a4db94011d3 212
sahilmgandhi 18:6a4db94011d3 213 void pwmout_period_ms(pwmout_t *obj, int ms)
sahilmgandhi 18:6a4db94011d3 214 {
sahilmgandhi 18:6a4db94011d3 215 // reught saturation < 0, quasi-max>
sahilmgandhi 18:6a4db94011d3 216 if (ms > MAX_PWM_PERIOD_MS)
sahilmgandhi 18:6a4db94011d3 217 {
sahilmgandhi 18:6a4db94011d3 218 ms = MAX_PWM_PERIOD_MS;
sahilmgandhi 18:6a4db94011d3 219 }
sahilmgandhi 18:6a4db94011d3 220 else if (ms < 0)
sahilmgandhi 18:6a4db94011d3 221 {
sahilmgandhi 18:6a4db94011d3 222 ms = 0; // f. pwmout_period_us will set period to min. value
sahilmgandhi 18:6a4db94011d3 223 }
sahilmgandhi 18:6a4db94011d3 224
sahilmgandhi 18:6a4db94011d3 225 int us = ms * 1000;
sahilmgandhi 18:6a4db94011d3 226
sahilmgandhi 18:6a4db94011d3 227 pwmout_period_us(obj, us);
sahilmgandhi 18:6a4db94011d3 228 }
sahilmgandhi 18:6a4db94011d3 229
sahilmgandhi 18:6a4db94011d3 230
sahilmgandhi 18:6a4db94011d3 231 void pwmout_period_us(pwmout_t *obj, int us)
sahilmgandhi 18:6a4db94011d3 232 {
sahilmgandhi 18:6a4db94011d3 233 pwm_signal_t * p_pwm_signal = &(((pwm_t*)obj->pwm_struct)->signal);
sahilmgandhi 18:6a4db94011d3 234
sahilmgandhi 18:6a4db94011d3 235 // saturation <1, real-max>
sahilmgandhi 18:6a4db94011d3 236 if (us > MAX_PWM_PERIOD_US)
sahilmgandhi 18:6a4db94011d3 237 {
sahilmgandhi 18:6a4db94011d3 238 us = MAX_PWM_PERIOD_US;
sahilmgandhi 18:6a4db94011d3 239 }
sahilmgandhi 18:6a4db94011d3 240 else if (us < 1)
sahilmgandhi 18:6a4db94011d3 241 {
sahilmgandhi 18:6a4db94011d3 242 us = 1;
sahilmgandhi 18:6a4db94011d3 243 }
sahilmgandhi 18:6a4db94011d3 244
sahilmgandhi 18:6a4db94011d3 245 p_pwm_signal->duty_us = (int)((float)us * p_pwm_signal->duty);
sahilmgandhi 18:6a4db94011d3 246
sahilmgandhi 18:6a4db94011d3 247 p_pwm_signal->period_us = us;
sahilmgandhi 18:6a4db94011d3 248
sahilmgandhi 18:6a4db94011d3 249 internal_pwmout_exe(obj, true, false);
sahilmgandhi 18:6a4db94011d3 250 }
sahilmgandhi 18:6a4db94011d3 251
sahilmgandhi 18:6a4db94011d3 252 void pwmout_pulsewidth(pwmout_t *obj, float seconds)
sahilmgandhi 18:6a4db94011d3 253 {
sahilmgandhi 18:6a4db94011d3 254 // raught saturation < 0, quasi-max>
sahilmgandhi 18:6a4db94011d3 255 if (seconds > MAX_PWM_PERIOD_S)
sahilmgandhi 18:6a4db94011d3 256 {
sahilmgandhi 18:6a4db94011d3 257 seconds = MAX_PWM_PERIOD_S;
sahilmgandhi 18:6a4db94011d3 258 }
sahilmgandhi 18:6a4db94011d3 259 else if (seconds < 0)
sahilmgandhi 18:6a4db94011d3 260 {
sahilmgandhi 18:6a4db94011d3 261 seconds = 0;
sahilmgandhi 18:6a4db94011d3 262 }
sahilmgandhi 18:6a4db94011d3 263
sahilmgandhi 18:6a4db94011d3 264 int us = seconds * 1000000;
sahilmgandhi 18:6a4db94011d3 265
sahilmgandhi 18:6a4db94011d3 266 pwmout_pulsewidth_us(obj,us);
sahilmgandhi 18:6a4db94011d3 267 }
sahilmgandhi 18:6a4db94011d3 268
sahilmgandhi 18:6a4db94011d3 269 void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
sahilmgandhi 18:6a4db94011d3 270 {
sahilmgandhi 18:6a4db94011d3 271 // raught saturation < 0, quasi-max>
sahilmgandhi 18:6a4db94011d3 272 if (ms > MAX_PWM_PERIOD_MS)
sahilmgandhi 18:6a4db94011d3 273 {
sahilmgandhi 18:6a4db94011d3 274 ms = MAX_PWM_PERIOD_MS;
sahilmgandhi 18:6a4db94011d3 275 }
sahilmgandhi 18:6a4db94011d3 276 else if (ms < 0)
sahilmgandhi 18:6a4db94011d3 277 {
sahilmgandhi 18:6a4db94011d3 278 ms = 0;
sahilmgandhi 18:6a4db94011d3 279 }
sahilmgandhi 18:6a4db94011d3 280
sahilmgandhi 18:6a4db94011d3 281 int us = ms * 1000;
sahilmgandhi 18:6a4db94011d3 282
sahilmgandhi 18:6a4db94011d3 283 pwmout_pulsewidth_us(obj, us);
sahilmgandhi 18:6a4db94011d3 284 }
sahilmgandhi 18:6a4db94011d3 285
sahilmgandhi 18:6a4db94011d3 286 void pwmout_pulsewidth_us(pwmout_t *obj, int us)
sahilmgandhi 18:6a4db94011d3 287 {
sahilmgandhi 18:6a4db94011d3 288 // saturation <0, real-max>
sahilmgandhi 18:6a4db94011d3 289 if (us > MAX_PWM_PERIOD_US)
sahilmgandhi 18:6a4db94011d3 290 {
sahilmgandhi 18:6a4db94011d3 291 us = MAX_PWM_PERIOD_US;
sahilmgandhi 18:6a4db94011d3 292 }
sahilmgandhi 18:6a4db94011d3 293 else if (us < 0)
sahilmgandhi 18:6a4db94011d3 294 {
sahilmgandhi 18:6a4db94011d3 295 us = 0;
sahilmgandhi 18:6a4db94011d3 296 }
sahilmgandhi 18:6a4db94011d3 297
sahilmgandhi 18:6a4db94011d3 298 pwm_signal_t * p_pwm_signal = &(((pwm_t*)obj->pwm_struct)->signal);
sahilmgandhi 18:6a4db94011d3 299
sahilmgandhi 18:6a4db94011d3 300 p_pwm_signal->duty_us = us;
sahilmgandhi 18:6a4db94011d3 301 p_pwm_signal->duty = us / p_pwm_signal->period_us;
sahilmgandhi 18:6a4db94011d3 302
sahilmgandhi 18:6a4db94011d3 303 internal_pwmout_exe(obj, false, false);
sahilmgandhi 18:6a4db94011d3 304 }
sahilmgandhi 18:6a4db94011d3 305
sahilmgandhi 18:6a4db94011d3 306
sahilmgandhi 18:6a4db94011d3 307
sahilmgandhi 18:6a4db94011d3 308
sahilmgandhi 18:6a4db94011d3 309
sahilmgandhi 18:6a4db94011d3 310
sahilmgandhi 18:6a4db94011d3 311 static ret_code_t pulsewidth_us_set_get(int period_hwu, int duty_hwu, pulsewidth_set_t * p_settings)
sahilmgandhi 18:6a4db94011d3 312 {
sahilmgandhi 18:6a4db94011d3 313 uint16_t div;
sahilmgandhi 18:6a4db94011d3 314 nrf_pwm_clk_t pwm_clk = NRF_PWM_CLK_16MHz;
sahilmgandhi 18:6a4db94011d3 315
sahilmgandhi 18:6a4db94011d3 316 for(div = 1; div <= 128 ; div <<= 1) // 128 is the maximum of clock prescaler for PWM peripherial
sahilmgandhi 18:6a4db94011d3 317 {
sahilmgandhi 18:6a4db94011d3 318 if (MAX_PWM_COUNTERTOP >= period_hwu)
sahilmgandhi 18:6a4db94011d3 319 {
sahilmgandhi 18:6a4db94011d3 320 p_settings->period_hwu = period_hwu; // unit [us/16 * div]
sahilmgandhi 18:6a4db94011d3 321 p_settings->duty_hwu = duty_hwu; // unit [us/16 * div]
sahilmgandhi 18:6a4db94011d3 322 p_settings->pwm_clk = pwm_clk;
sahilmgandhi 18:6a4db94011d3 323
sahilmgandhi 18:6a4db94011d3 324 return NRF_SUCCESS;
sahilmgandhi 18:6a4db94011d3 325 }
sahilmgandhi 18:6a4db94011d3 326
sahilmgandhi 18:6a4db94011d3 327 period_hwu >>= 1;
sahilmgandhi 18:6a4db94011d3 328 duty_hwu >>= 1;
sahilmgandhi 18:6a4db94011d3 329 pwm_clk++;
sahilmgandhi 18:6a4db94011d3 330 }
sahilmgandhi 18:6a4db94011d3 331
sahilmgandhi 18:6a4db94011d3 332 return NRF_ERROR_INVALID_PARAM;
sahilmgandhi 18:6a4db94011d3 333 }
sahilmgandhi 18:6a4db94011d3 334
sahilmgandhi 18:6a4db94011d3 335
sahilmgandhi 18:6a4db94011d3 336 static void internal_pwmout_exe(pwmout_t *obj, bool new_period, bool initialization)
sahilmgandhi 18:6a4db94011d3 337 {
sahilmgandhi 18:6a4db94011d3 338 pulsewidth_set_t pulsewidth_set;
sahilmgandhi 18:6a4db94011d3 339 pwm_signal_t * p_pwm_signal;
sahilmgandhi 18:6a4db94011d3 340 nrf_drv_pwm_t * p_pwm_driver;
sahilmgandhi 18:6a4db94011d3 341 ret_code_t ret_code;
sahilmgandhi 18:6a4db94011d3 342
sahilmgandhi 18:6a4db94011d3 343 p_pwm_signal = &(((pwm_t*)obj->pwm_struct)->signal);
sahilmgandhi 18:6a4db94011d3 344
sahilmgandhi 18:6a4db94011d3 345 if (NRF_SUCCESS == pulsewidth_us_set_get(p_pwm_signal->period_us * 16, // base clk for PWM is 16 MHz
sahilmgandhi 18:6a4db94011d3 346 p_pwm_signal->duty_us * 16, // base clk for PWM is 16 MHz
sahilmgandhi 18:6a4db94011d3 347 &pulsewidth_set))
sahilmgandhi 18:6a4db94011d3 348 {
sahilmgandhi 18:6a4db94011d3 349 p_pwm_driver = (((pwm_t*)obj->pwm_struct)->p_pwm_driver);
sahilmgandhi 18:6a4db94011d3 350
sahilmgandhi 18:6a4db94011d3 351 const nrf_pwm_sequence_t seq =
sahilmgandhi 18:6a4db94011d3 352 {
sahilmgandhi 18:6a4db94011d3 353 .values.p_common = (nrf_pwm_values_common_t*) (((pwm_t*)obj->pwm_struct)->seq_values),
sahilmgandhi 18:6a4db94011d3 354 .length = 1,
sahilmgandhi 18:6a4db94011d3 355 .repeats = 0,
sahilmgandhi 18:6a4db94011d3 356 .end_delay = 0
sahilmgandhi 18:6a4db94011d3 357 };
sahilmgandhi 18:6a4db94011d3 358
sahilmgandhi 18:6a4db94011d3 359 (((pwm_t*)obj->pwm_struct)->seq_values)[0] = pulsewidth_set.duty_hwu | 0x8000;
sahilmgandhi 18:6a4db94011d3 360
sahilmgandhi 18:6a4db94011d3 361 if (new_period)
sahilmgandhi 18:6a4db94011d3 362 {
sahilmgandhi 18:6a4db94011d3 363 nrf_drv_pwm_config_t config0 =
sahilmgandhi 18:6a4db94011d3 364 {
sahilmgandhi 18:6a4db94011d3 365 .output_pins =
sahilmgandhi 18:6a4db94011d3 366 {
sahilmgandhi 18:6a4db94011d3 367 obj->pin | NRF_DRV_PWM_PIN_INVERTED, // channel 0
sahilmgandhi 18:6a4db94011d3 368 NRF_DRV_PWM_PIN_NOT_USED, // channel 1
sahilmgandhi 18:6a4db94011d3 369 NRF_DRV_PWM_PIN_NOT_USED, // channel 2
sahilmgandhi 18:6a4db94011d3 370 NRF_DRV_PWM_PIN_NOT_USED, // channel 3
sahilmgandhi 18:6a4db94011d3 371 },
sahilmgandhi 18:6a4db94011d3 372 .irq_priority = PWM0_CONFIG_IRQ_PRIORITY,
sahilmgandhi 18:6a4db94011d3 373 .base_clock = pulsewidth_set.pwm_clk,
sahilmgandhi 18:6a4db94011d3 374 .count_mode = NRF_PWM_MODE_UP,
sahilmgandhi 18:6a4db94011d3 375 .top_value = pulsewidth_set.period_hwu,
sahilmgandhi 18:6a4db94011d3 376 .load_mode = NRF_PWM_LOAD_COMMON,
sahilmgandhi 18:6a4db94011d3 377 .step_mode = NRF_PWM_STEP_AUTO
sahilmgandhi 18:6a4db94011d3 378 };
sahilmgandhi 18:6a4db94011d3 379
sahilmgandhi 18:6a4db94011d3 380 if (!initialization)
sahilmgandhi 18:6a4db94011d3 381 {
sahilmgandhi 18:6a4db94011d3 382 nrf_drv_pwm_uninit(p_pwm_driver);
sahilmgandhi 18:6a4db94011d3 383 }
sahilmgandhi 18:6a4db94011d3 384
sahilmgandhi 18:6a4db94011d3 385 ret_code = nrf_drv_pwm_init( p_pwm_driver, &config0, NULL);
sahilmgandhi 18:6a4db94011d3 386
sahilmgandhi 18:6a4db94011d3 387 MBED_ASSERT(ret_code == NRF_SUCCESS); // assert if free instance was not found.
sahilmgandhi 18:6a4db94011d3 388 }
sahilmgandhi 18:6a4db94011d3 389
sahilmgandhi 18:6a4db94011d3 390 nrf_drv_pwm_simple_playback(p_pwm_driver, &seq, 0, NRF_DRV_PWM_FLAG_LOOP);
sahilmgandhi 18:6a4db94011d3 391 }
sahilmgandhi 18:6a4db94011d3 392 else
sahilmgandhi 18:6a4db94011d3 393 {
sahilmgandhi 18:6a4db94011d3 394 MBED_ASSERT(0); // force assertion
sahilmgandhi 18:6a4db94011d3 395 }
sahilmgandhi 18:6a4db94011d3 396
sahilmgandhi 18:6a4db94011d3 397 }
sahilmgandhi 18:6a4db94011d3 398
sahilmgandhi 18:6a4db94011d3 399 #endif // DEVICE_PWMOUT