mbed library sources for airmote

Fork of mbed-src by mbed official

Committer:
zskdan
Date:
Thu Sep 10 21:51:18 2015 +0000
Revision:
622:c3f37705f4fa
Parent:
340:28d1f895c6fe
stop pwm timer on free

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbed_official 85:e1a8e879a6a9 1 /* mbed Microcontroller Library
mbed_official 104:a6a92e2e5a92 2 * Copyright (c) 2013 Nordic Semiconductor
mbed_official 85:e1a8e879a6a9 3 *
mbed_official 85:e1a8e879a6a9 4 * Licensed under the Apache License, Version 2.0 (the "License");
mbed_official 85:e1a8e879a6a9 5 * you may not use this file except in compliance with the License.
mbed_official 85:e1a8e879a6a9 6 * You may obtain a copy of the License at
mbed_official 85:e1a8e879a6a9 7 *
mbed_official 85:e1a8e879a6a9 8 * http://www.apache.org/licenses/LICENSE-2.0
mbed_official 85:e1a8e879a6a9 9 *
mbed_official 85:e1a8e879a6a9 10 * Unless required by applicable law or agreed to in writing, software
mbed_official 85:e1a8e879a6a9 11 * distributed under the License is distributed on an "AS IS" BASIS,
mbed_official 85:e1a8e879a6a9 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
mbed_official 85:e1a8e879a6a9 13 * See the License for the specific language governing permissions and
mbed_official 85:e1a8e879a6a9 14 * limitations under the License.
mbed_official 85:e1a8e879a6a9 15 */
mbed_official 227:7bd0639b8911 16 #include "mbed_assert.h"
mbed_official 85:e1a8e879a6a9 17 #include "pwmout_api.h"
mbed_official 85:e1a8e879a6a9 18 #include "cmsis.h"
mbed_official 85:e1a8e879a6a9 19 #include "pinmap.h"
mbed_official 285:31249416b6f9 20 #include "mbed_error.h"
mbed_official 85:e1a8e879a6a9 21
mbed_official 229:9bd26d142f33 22 #define NO_PWMS 3
mbed_official 300:55638feb26a4 23 #define TIMER_PRECISION 4 //4us ticks
mbed_official 229:9bd26d142f33 24 #define TIMER_PRESCALER 6 //4us ticks = 16Mhz/(2**6)
mbed_official 85:e1a8e879a6a9 25 static const PinMap PinMap_PWM[] = {
mbed_official 85:e1a8e879a6a9 26 {p0, PWM_1, 1},
mbed_official 85:e1a8e879a6a9 27 {p1, PWM_1, 1},
mbed_official 85:e1a8e879a6a9 28 {p2, PWM_1, 1},
mbed_official 85:e1a8e879a6a9 29 {p3, PWM_1, 1},
mbed_official 85:e1a8e879a6a9 30 {p4, PWM_1, 1},
mbed_official 85:e1a8e879a6a9 31 {p5, PWM_1, 1},
mbed_official 85:e1a8e879a6a9 32 {p6, PWM_1, 1},
mbed_official 85:e1a8e879a6a9 33 {p7, PWM_1, 1},
mbed_official 85:e1a8e879a6a9 34 {p8, PWM_1, 1},
mbed_official 85:e1a8e879a6a9 35 {p9, PWM_1, 1},
mbed_official 85:e1a8e879a6a9 36 {p10, PWM_1, 1},
mbed_official 85:e1a8e879a6a9 37 {p11, PWM_1, 1},
mbed_official 85:e1a8e879a6a9 38 {p12, PWM_1, 1},
mbed_official 85:e1a8e879a6a9 39 {p13, PWM_1, 1},
mbed_official 85:e1a8e879a6a9 40 {p14, PWM_1, 1},
mbed_official 85:e1a8e879a6a9 41 {p15, PWM_1, 1},
mbed_official 85:e1a8e879a6a9 42 {p16, PWM_1, 1},
mbed_official 85:e1a8e879a6a9 43 {p17, PWM_1, 1},
mbed_official 85:e1a8e879a6a9 44 {p18, PWM_1, 1},
mbed_official 85:e1a8e879a6a9 45 {p19, PWM_1, 1},
mbed_official 85:e1a8e879a6a9 46 {p20, PWM_1, 1},
mbed_official 85:e1a8e879a6a9 47 {p21, PWM_1, 1},
mbed_official 227:7bd0639b8911 48 {p22, PWM_1, 1},
mbed_official 227:7bd0639b8911 49 {p23, PWM_1, 1},
mbed_official 85:e1a8e879a6a9 50 {p24, PWM_1, 1},
mbed_official 85:e1a8e879a6a9 51 {p25, PWM_1, 1},
mbed_official 85:e1a8e879a6a9 52 {p28, PWM_1, 1},
mbed_official 85:e1a8e879a6a9 53 {p29, PWM_1, 1},
mbed_official 85:e1a8e879a6a9 54 {p30, PWM_1, 1},
mbed_official 85:e1a8e879a6a9 55 {NC, NC, 0}
mbed_official 85:e1a8e879a6a9 56 };
mbed_official 85:e1a8e879a6a9 57
mbed_official 85:e1a8e879a6a9 58 static NRF_TIMER_Type *Timers[1] = {
mbed_official 227:7bd0639b8911 59 NRF_TIMER2
mbed_official 85:e1a8e879a6a9 60 };
mbed_official 85:e1a8e879a6a9 61
mbed_official 300:55638feb26a4 62 uint16_t PERIOD = 20000 / TIMER_PRECISION; //20ms
mbed_official 300:55638feb26a4 63 uint8_t PWM_taken[NO_PWMS] = {0, 0, 0};
mbed_official 300:55638feb26a4 64 uint16_t PULSE_WIDTH[NO_PWMS] = {1, 1, 1}; //set to 1 instead of 0
mbed_official 300:55638feb26a4 65 uint16_t ACTUAL_PULSE[NO_PWMS] = {0, 0, 0};
mbed_official 85:e1a8e879a6a9 66
mbed_official 85:e1a8e879a6a9 67
mbed_official 85:e1a8e879a6a9 68 /** @brief Function for handling timer 2 peripheral interrupts.
mbed_official 85:e1a8e879a6a9 69 */
mbed_official 300:55638feb26a4 70 #ifdef __cplusplus
mbed_official 85:e1a8e879a6a9 71 extern "C" {
mbed_official 300:55638feb26a4 72 #endif
mbed_official 85:e1a8e879a6a9 73 void TIMER2_IRQHandler(void)
mbed_official 85:e1a8e879a6a9 74 {
mbed_official 229:9bd26d142f33 75 NRF_TIMER2->EVENTS_COMPARE[3] = 0;
mbed_official 300:55638feb26a4 76 NRF_TIMER2->CC[3] = PERIOD;
mbed_official 300:55638feb26a4 77
mbed_official 300:55638feb26a4 78 if (PWM_taken[0]) {
mbed_official 300:55638feb26a4 79 NRF_TIMER2->CC[0] = PULSE_WIDTH[0];
mbed_official 229:9bd26d142f33 80 }
mbed_official 300:55638feb26a4 81 if (PWM_taken[1]) {
mbed_official 300:55638feb26a4 82 NRF_TIMER2->CC[1] = PULSE_WIDTH[1];
mbed_official 229:9bd26d142f33 83 }
mbed_official 300:55638feb26a4 84 if (PWM_taken[2]) {
mbed_official 300:55638feb26a4 85 NRF_TIMER2->CC[2] = PULSE_WIDTH[2];
mbed_official 229:9bd26d142f33 86 }
mbed_official 300:55638feb26a4 87
mbed_official 229:9bd26d142f33 88 NRF_TIMER2->TASKS_START = 1;
mbed_official 300:55638feb26a4 89 }
mbed_official 85:e1a8e879a6a9 90
mbed_official 85:e1a8e879a6a9 91 #ifdef __cplusplus
mbed_official 85:e1a8e879a6a9 92 }
mbed_official 300:55638feb26a4 93 #endif
mbed_official 85:e1a8e879a6a9 94 /** @brief Function for initializing the Timer peripherals.
mbed_official 85:e1a8e879a6a9 95 */
mbed_official 85:e1a8e879a6a9 96 void timer_init(uint8_t pwmChoice)
mbed_official 85:e1a8e879a6a9 97 {
mbed_official 229:9bd26d142f33 98 NRF_TIMER_Type *timer = Timers[0];
mbed_official 229:9bd26d142f33 99 timer->TASKS_STOP = 0;
mbed_official 300:55638feb26a4 100
mbed_official 300:55638feb26a4 101 if (pwmChoice == 0) {
mbed_official 85:e1a8e879a6a9 102 timer->POWER = 0;
mbed_official 300:55638feb26a4 103 timer->POWER = 1;
mbed_official 300:55638feb26a4 104 timer->MODE = TIMER_MODE_MODE_Timer;
mbed_official 85:e1a8e879a6a9 105 timer->BITMODE = TIMER_BITMODE_BITMODE_16Bit << TIMER_BITMODE_BITMODE_Pos;
mbed_official 300:55638feb26a4 106 timer->PRESCALER = TIMER_PRESCALER;
mbed_official 229:9bd26d142f33 107 timer->CC[3] = PERIOD;
mbed_official 85:e1a8e879a6a9 108 }
mbed_official 300:55638feb26a4 109
mbed_official 229:9bd26d142f33 110 timer->CC[pwmChoice] = PULSE_WIDTH[pwmChoice];
mbed_official 300:55638feb26a4 111
mbed_official 85:e1a8e879a6a9 112 //high priority application interrupt
mbed_official 85:e1a8e879a6a9 113 NVIC_SetPriority(TIMER2_IRQn, 1);
mbed_official 85:e1a8e879a6a9 114 NVIC_EnableIRQ(TIMER2_IRQn);
mbed_official 300:55638feb26a4 115
mbed_official 85:e1a8e879a6a9 116 timer->TASKS_START = 0x01;
mbed_official 85:e1a8e879a6a9 117 }
mbed_official 300:55638feb26a4 118
mbed_official 85:e1a8e879a6a9 119 /** @brief Function for initializing the GPIO Tasks/Events peripheral.
mbed_official 85:e1a8e879a6a9 120 */
mbed_official 300:55638feb26a4 121 void gpiote_init(PinName pin, uint8_t channel_number)
mbed_official 85:e1a8e879a6a9 122 {
mbed_official 85:e1a8e879a6a9 123 // Connect GPIO input buffers and configure PWM_OUTPUT_PIN_NUMBER as an output.
mbed_official 85:e1a8e879a6a9 124 NRF_GPIO->PIN_CNF[pin] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
mbed_official 85:e1a8e879a6a9 125 | (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
mbed_official 85:e1a8e879a6a9 126 | (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos)
mbed_official 85:e1a8e879a6a9 127 | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
mbed_official 85:e1a8e879a6a9 128 | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
mbed_official 85:e1a8e879a6a9 129 NRF_GPIO->OUTCLR = (1UL << pin);
mbed_official 85:e1a8e879a6a9 130 // Configure GPIOTE channel 0 to toggle the PWM pin state
mbed_official 85:e1a8e879a6a9 131 // @note Only one GPIOTE task can be connected to an output pin.
mbed_official 85:e1a8e879a6a9 132 /* Configure channel to Pin31, not connected to the pin, and configure as a tasks that will set it to proper level */
mbed_official 300:55638feb26a4 133 NRF_GPIOTE->CONFIG[channel_number] = (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos) |
mbed_official 300:55638feb26a4 134 (31UL << GPIOTE_CONFIG_PSEL_Pos) |
mbed_official 85:e1a8e879a6a9 135 (GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos);
mbed_official 300:55638feb26a4 136 /* Three NOPs are required to make sure configuration is written before setting tasks or getting events */
mbed_official 300:55638feb26a4 137 __NOP();
mbed_official 85:e1a8e879a6a9 138 __NOP();
mbed_official 85:e1a8e879a6a9 139 __NOP();
mbed_official 85:e1a8e879a6a9 140 /* Launch the task to take the GPIOTE channel output to the desired level */
mbed_official 85:e1a8e879a6a9 141 NRF_GPIOTE->TASKS_OUT[channel_number] = 1;
mbed_official 300:55638feb26a4 142
mbed_official 300:55638feb26a4 143 /* Finally configure the channel as the caller expects. If OUTINIT works, the channel is configured properly.
mbed_official 85:e1a8e879a6a9 144 If it does not, the channel output inheritance sets the proper level. */
mbed_official 300:55638feb26a4 145 NRF_GPIOTE->CONFIG[channel_number] = (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos) |
mbed_official 300:55638feb26a4 146 ((uint32_t)pin << GPIOTE_CONFIG_PSEL_Pos) |
mbed_official 300:55638feb26a4 147 ((uint32_t)GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos) |
mbed_official 300:55638feb26a4 148 ((uint32_t)GPIOTE_CONFIG_OUTINIT_Low << GPIOTE_CONFIG_OUTINIT_Pos); // ((uint32_t)GPIOTE_CONFIG_OUTINIT_High <<
mbed_official 300:55638feb26a4 149 // GPIOTE_CONFIG_OUTINIT_Pos);//
mbed_official 85:e1a8e879a6a9 150
mbed_official 85:e1a8e879a6a9 151 /* Three NOPs are required to make sure configuration is written before setting tasks or getting events */
mbed_official 85:e1a8e879a6a9 152 __NOP();
mbed_official 85:e1a8e879a6a9 153 __NOP();
mbed_official 300:55638feb26a4 154 __NOP();
mbed_official 85:e1a8e879a6a9 155 }
mbed_official 300:55638feb26a4 156
mbed_official 85:e1a8e879a6a9 157 /** @brief Function for initializing the Programmable Peripheral Interconnect peripheral.
mbed_official 85:e1a8e879a6a9 158 */
mbed_official 85:e1a8e879a6a9 159 static void ppi_init(uint8_t pwm)
mbed_official 85:e1a8e879a6a9 160 {
mbed_official 300:55638feb26a4 161 //using ppi channels 0-7 (only 0-7 are available)
mbed_official 300:55638feb26a4 162 uint8_t channel_number = 2 * pwm;
mbed_official 300:55638feb26a4 163 NRF_TIMER_Type *timer = Timers[0];
mbed_official 300:55638feb26a4 164
mbed_official 85:e1a8e879a6a9 165 // Configure PPI channel 0 to toggle ADVERTISING_LED_PIN_NO on every TIMER1 COMPARE[0] match
mbed_official 85:e1a8e879a6a9 166 NRF_PPI->CH[channel_number].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[pwm];
mbed_official 300:55638feb26a4 167 NRF_PPI->CH[channel_number + 1].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[pwm];
mbed_official 300:55638feb26a4 168 NRF_PPI->CH[channel_number].EEP = (uint32_t)&timer->EVENTS_COMPARE[pwm];
mbed_official 300:55638feb26a4 169 NRF_PPI->CH[channel_number + 1].EEP = (uint32_t)&timer->EVENTS_COMPARE[3];
mbed_official 300:55638feb26a4 170
mbed_official 85:e1a8e879a6a9 171 // Enable PPI channels.
mbed_official 300:55638feb26a4 172 NRF_PPI->CHEN |= (1 << channel_number) |
mbed_official 300:55638feb26a4 173 (1 << (channel_number + 1));
mbed_official 85:e1a8e879a6a9 174 }
mbed_official 85:e1a8e879a6a9 175
mbed_official 300:55638feb26a4 176 void setModulation(pwmout_t *obj, uint8_t toggle, uint8_t high)
mbed_official 85:e1a8e879a6a9 177 {
mbed_official 300:55638feb26a4 178 if (high) {
mbed_official 85:e1a8e879a6a9 179 NRF_GPIOTE->CONFIG[obj->pwm] |= ((uint32_t)GPIOTE_CONFIG_OUTINIT_High << GPIOTE_CONFIG_OUTINIT_Pos);
mbed_official 300:55638feb26a4 180 if (toggle) {
mbed_official 300:55638feb26a4 181 NRF_GPIOTE->CONFIG[obj->pwm] |= (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos) |
mbed_official 300:55638feb26a4 182 ((uint32_t)GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos);
mbed_official 300:55638feb26a4 183 } else {
mbed_official 300:55638feb26a4 184 NRF_GPIOTE->CONFIG[obj->pwm] &= ~((uint32_t)GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos);
mbed_official 300:55638feb26a4 185 NRF_GPIOTE->CONFIG[obj->pwm] |= ((uint32_t)GPIOTE_CONFIG_POLARITY_LoToHi << GPIOTE_CONFIG_POLARITY_Pos);
mbed_official 85:e1a8e879a6a9 186 }
mbed_official 300:55638feb26a4 187 } else {
mbed_official 85:e1a8e879a6a9 188 NRF_GPIOTE->CONFIG[obj->pwm] &= ~((uint32_t)GPIOTE_CONFIG_OUTINIT_High << GPIOTE_CONFIG_OUTINIT_Pos);
mbed_official 300:55638feb26a4 189
mbed_official 300:55638feb26a4 190 if (toggle) {
mbed_official 300:55638feb26a4 191 NRF_GPIOTE->CONFIG[obj->pwm] |= (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos) |
mbed_official 300:55638feb26a4 192 ((uint32_t)GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos);
mbed_official 300:55638feb26a4 193 } else {
mbed_official 300:55638feb26a4 194 NRF_GPIOTE->CONFIG[obj->pwm] &= ~((uint32_t)GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos);
mbed_official 300:55638feb26a4 195 NRF_GPIOTE->CONFIG[obj->pwm] |= ((uint32_t)GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos);
mbed_official 85:e1a8e879a6a9 196 }
mbed_official 85:e1a8e879a6a9 197 }
mbed_official 85:e1a8e879a6a9 198 }
mbed_official 300:55638feb26a4 199
mbed_official 300:55638feb26a4 200 void pwmout_init(pwmout_t *obj, PinName pin)
mbed_official 300:55638feb26a4 201 {
mbed_official 85:e1a8e879a6a9 202 // determine the channel
mbed_official 85:e1a8e879a6a9 203 uint8_t pwmOutSuccess = 0;
mbed_official 300:55638feb26a4 204 PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM);
mbed_official 300:55638feb26a4 205
mbed_official 227:7bd0639b8911 206 MBED_ASSERT(pwm != (PWMName)NC);
mbed_official 300:55638feb26a4 207
mbed_official 300:55638feb26a4 208 if (PWM_taken[(uint8_t)pwm]) {
mbed_official 300:55638feb26a4 209 for (uint8_t i = 1; !pwmOutSuccess && (i<NO_PWMS); i++) {
mbed_official 300:55638feb26a4 210 if (!PWM_taken[i]) {
mbed_official 85:e1a8e879a6a9 211 pwm = (PWMName)i;
mbed_official 85:e1a8e879a6a9 212 PWM_taken[i] = 1;
mbed_official 85:e1a8e879a6a9 213 pwmOutSuccess = 1;
mbed_official 85:e1a8e879a6a9 214 }
mbed_official 85:e1a8e879a6a9 215 }
mbed_official 300:55638feb26a4 216 } else {
mbed_official 85:e1a8e879a6a9 217 pwmOutSuccess = 1;
mbed_official 85:e1a8e879a6a9 218 PWM_taken[(uint8_t)pwm] = 1;
mbed_official 85:e1a8e879a6a9 219 }
mbed_official 300:55638feb26a4 220
mbed_official 300:55638feb26a4 221 if (!pwmOutSuccess) {
mbed_official 85:e1a8e879a6a9 222 error("PwmOut pin mapping failed. All available PWM channels are in use.");
mbed_official 85:e1a8e879a6a9 223 }
mbed_official 300:55638feb26a4 224
mbed_official 85:e1a8e879a6a9 225 obj->pwm = pwm;
mbed_official 85:e1a8e879a6a9 226 obj->pin = pin;
mbed_official 300:55638feb26a4 227
mbed_official 300:55638feb26a4 228 gpiote_init(pin, (uint8_t)pwm);
mbed_official 85:e1a8e879a6a9 229 ppi_init((uint8_t)pwm);
mbed_official 300:55638feb26a4 230
mbed_official 300:55638feb26a4 231 if (pwm == 0) {
mbed_official 85:e1a8e879a6a9 232 NRF_POWER->TASKS_CONSTLAT = 1;
mbed_official 85:e1a8e879a6a9 233 }
mbed_official 300:55638feb26a4 234
mbed_official 85:e1a8e879a6a9 235 timer_init((uint8_t)pwm);
mbed_official 300:55638feb26a4 236
mbed_official 85:e1a8e879a6a9 237 //default to 20ms: standard for servos, and fine for e.g. brightness control
mbed_official 85:e1a8e879a6a9 238 pwmout_period_ms(obj, 20);
mbed_official 85:e1a8e879a6a9 239 pwmout_write (obj, 0);
mbed_official 85:e1a8e879a6a9 240 }
mbed_official 85:e1a8e879a6a9 241
mbed_official 300:55638feb26a4 242 void pwmout_free(pwmout_t *obj)
mbed_official 300:55638feb26a4 243 {
mbed_official 340:28d1f895c6fe 244 MBED_ASSERT(obj->pwm != (PWMName)NC);
mbed_official 340:28d1f895c6fe 245 PWM_taken[obj->pwm] = 0;
mbed_official 340:28d1f895c6fe 246 pwmout_write(obj, 0);
zskdan 622:c3f37705f4fa 247 NRF_TIMER2->EVENTS_COMPARE[3] = 0;
zskdan 622:c3f37705f4fa 248 NRF_TIMER2->TASKS_STOP = 1;
mbed_official 85:e1a8e879a6a9 249 }
mbed_official 85:e1a8e879a6a9 250
mbed_official 300:55638feb26a4 251 void pwmout_write(pwmout_t *obj, float value)
mbed_official 300:55638feb26a4 252 {
mbed_official 85:e1a8e879a6a9 253 uint16_t oldPulseWidth;
mbed_official 300:55638feb26a4 254
mbed_official 229:9bd26d142f33 255 NRF_TIMER2->EVENTS_COMPARE[3] = 0;
mbed_official 300:55638feb26a4 256 NRF_TIMER2->TASKS_STOP = 1;
mbed_official 300:55638feb26a4 257
mbed_official 85:e1a8e879a6a9 258 if (value < 0.0f) {
mbed_official 85:e1a8e879a6a9 259 value = 0.0;
mbed_official 85:e1a8e879a6a9 260 } else if (value > 1.0f) {
mbed_official 85:e1a8e879a6a9 261 value = 1.0;
mbed_official 85:e1a8e879a6a9 262 }
mbed_official 300:55638feb26a4 263
mbed_official 300:55638feb26a4 264 oldPulseWidth = ACTUAL_PULSE[obj->pwm];
mbed_official 300:55638feb26a4 265 ACTUAL_PULSE[obj->pwm] = PULSE_WIDTH[obj->pwm] = value * PERIOD;
mbed_official 300:55638feb26a4 266
mbed_official 300:55638feb26a4 267 if (PULSE_WIDTH[obj->pwm] == 0) {
mbed_official 300:55638feb26a4 268 PULSE_WIDTH[obj->pwm] = 1;
mbed_official 300:55638feb26a4 269 setModulation(obj, 0, 0);
mbed_official 300:55638feb26a4 270 } else if (PULSE_WIDTH[obj->pwm] == PERIOD) {
mbed_official 300:55638feb26a4 271 PULSE_WIDTH[obj->pwm] = PERIOD - 1;
mbed_official 300:55638feb26a4 272 setModulation(obj, 0, 1);
mbed_official 300:55638feb26a4 273 } else if ((oldPulseWidth == 0) || (oldPulseWidth == PERIOD)) {
mbed_official 300:55638feb26a4 274 setModulation(obj, 1, oldPulseWidth == PERIOD);
mbed_official 85:e1a8e879a6a9 275 }
mbed_official 300:55638feb26a4 276
mbed_official 300:55638feb26a4 277 NRF_TIMER2->INTENSET = TIMER_INTENSET_COMPARE3_Msk;
mbed_official 300:55638feb26a4 278 NRF_TIMER2->SHORTS = TIMER_SHORTS_COMPARE3_CLEAR_Msk | TIMER_SHORTS_COMPARE3_STOP_Msk;
mbed_official 229:9bd26d142f33 279 NRF_TIMER2->TASKS_START = 1;
mbed_official 85:e1a8e879a6a9 280 }
mbed_official 85:e1a8e879a6a9 281
mbed_official 300:55638feb26a4 282 float pwmout_read(pwmout_t *obj)
mbed_official 300:55638feb26a4 283 {
mbed_official 300:55638feb26a4 284 return ((float)PULSE_WIDTH[obj->pwm] / (float)PERIOD);
mbed_official 85:e1a8e879a6a9 285 }
mbed_official 85:e1a8e879a6a9 286
mbed_official 300:55638feb26a4 287 void pwmout_period(pwmout_t *obj, float seconds)
mbed_official 300:55638feb26a4 288 {
mbed_official 85:e1a8e879a6a9 289 pwmout_period_us(obj, seconds * 1000000.0f);
mbed_official 85:e1a8e879a6a9 290 }
mbed_official 85:e1a8e879a6a9 291
mbed_official 300:55638feb26a4 292 void pwmout_period_ms(pwmout_t *obj, int ms)
mbed_official 300:55638feb26a4 293 {
mbed_official 85:e1a8e879a6a9 294 pwmout_period_us(obj, ms * 1000);
mbed_official 85:e1a8e879a6a9 295 }
mbed_official 85:e1a8e879a6a9 296
mbed_official 85:e1a8e879a6a9 297 // Set the PWM period, keeping the duty cycle the same.
mbed_official 300:55638feb26a4 298 void pwmout_period_us(pwmout_t *obj, int us)
mbed_official 300:55638feb26a4 299 {
mbed_official 300:55638feb26a4 300 uint32_t periodInTicks = us / TIMER_PRECISION;
mbed_official 300:55638feb26a4 301
mbed_official 229:9bd26d142f33 302 NRF_TIMER2->EVENTS_COMPARE[3] = 0;
mbed_official 300:55638feb26a4 303 NRF_TIMER2->TASKS_STOP = 1;
mbed_official 300:55638feb26a4 304
mbed_official 300:55638feb26a4 305 if (periodInTicks>((1 << 16) - 1)) {
mbed_official 300:55638feb26a4 306 PERIOD = (1 << 16) - 1; //131ms
mbed_official 300:55638feb26a4 307 } else if (periodInTicks<5) {
mbed_official 300:55638feb26a4 308 PERIOD = 5;
mbed_official 300:55638feb26a4 309 } else {
mbed_official 300:55638feb26a4 310 PERIOD = periodInTicks;
mbed_official 85:e1a8e879a6a9 311 }
mbed_official 300:55638feb26a4 312 NRF_TIMER2->INTENSET = TIMER_INTENSET_COMPARE3_Msk;
mbed_official 300:55638feb26a4 313 NRF_TIMER2->SHORTS = TIMER_SHORTS_COMPARE3_CLEAR_Msk | TIMER_SHORTS_COMPARE3_STOP_Msk;
mbed_official 300:55638feb26a4 314 NRF_TIMER2->TASKS_START = 1;
mbed_official 85:e1a8e879a6a9 315 }
mbed_official 85:e1a8e879a6a9 316
mbed_official 300:55638feb26a4 317 void pwmout_pulsewidth(pwmout_t *obj, float seconds)
mbed_official 300:55638feb26a4 318 {
mbed_official 85:e1a8e879a6a9 319 pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
mbed_official 85:e1a8e879a6a9 320 }
mbed_official 85:e1a8e879a6a9 321
mbed_official 300:55638feb26a4 322 void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
mbed_official 300:55638feb26a4 323 {
mbed_official 85:e1a8e879a6a9 324 pwmout_pulsewidth_us(obj, ms * 1000);
mbed_official 85:e1a8e879a6a9 325 }
mbed_official 85:e1a8e879a6a9 326
mbed_official 300:55638feb26a4 327 void pwmout_pulsewidth_us(pwmout_t *obj, int us)
mbed_official 300:55638feb26a4 328 {
mbed_official 300:55638feb26a4 329 uint32_t pulseInTicks = us / TIMER_PRECISION;
mbed_official 85:e1a8e879a6a9 330 uint16_t oldPulseWidth = ACTUAL_PULSE[obj->pwm];
mbed_official 300:55638feb26a4 331
mbed_official 229:9bd26d142f33 332 NRF_TIMER2->EVENTS_COMPARE[3] = 0;
mbed_official 300:55638feb26a4 333 NRF_TIMER2->TASKS_STOP = 1;
mbed_official 300:55638feb26a4 334
mbed_official 85:e1a8e879a6a9 335 ACTUAL_PULSE[obj->pwm] = PULSE_WIDTH[obj->pwm] = pulseInTicks;
mbed_official 300:55638feb26a4 336
mbed_official 300:55638feb26a4 337 if (PULSE_WIDTH[obj->pwm] == 0) {
mbed_official 85:e1a8e879a6a9 338 PULSE_WIDTH[obj->pwm] = 1;
mbed_official 300:55638feb26a4 339 setModulation(obj, 0, 0);
mbed_official 300:55638feb26a4 340 } else if (PULSE_WIDTH[obj->pwm] == PERIOD) {
mbed_official 300:55638feb26a4 341 PULSE_WIDTH[obj->pwm] = PERIOD - 1;
mbed_official 300:55638feb26a4 342 setModulation(obj, 0, 1);
mbed_official 300:55638feb26a4 343 } else if ((oldPulseWidth == 0) || (oldPulseWidth == PERIOD)) {
mbed_official 300:55638feb26a4 344 setModulation(obj, 1, oldPulseWidth == PERIOD);
mbed_official 85:e1a8e879a6a9 345 }
mbed_official 300:55638feb26a4 346 NRF_TIMER2->INTENSET = TIMER_INTENSET_COMPARE3_Msk;
mbed_official 300:55638feb26a4 347 NRF_TIMER2->SHORTS = TIMER_SHORTS_COMPARE3_CLEAR_Msk | TIMER_SHORTS_COMPARE3_STOP_Msk;
mbed_official 300:55638feb26a4 348 NRF_TIMER2->TASKS_START = 1;
mbed_official 85:e1a8e879a6a9 349 }