Mouse code for the MacroRat

Dependencies:   ITG3200 QEI

Committer:
sahilmgandhi
Date:
Sat Jun 03 00:22:44 2017 +0000
Revision:
46:b156ef445742
Parent:
18:6a4db94011d3
Final code for internal battlebot competition.

Who changed what in which revision?

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