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 /*
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 "nrf.h"
sahilmgandhi 18:6a4db94011d3 48 #include "nrf_drv_timer.h"
sahilmgandhi 18:6a4db94011d3 49 #include "app_pwm.h"
sahilmgandhi 18:6a4db94011d3 50
sahilmgandhi 18:6a4db94011d3 51 #define PWM_INSTANCE_COUNT 2
sahilmgandhi 18:6a4db94011d3 52 #define PWM_CHANNELS_PER_INSTANCE 2
sahilmgandhi 18:6a4db94011d3 53 #define PWM_DEFAULT_PERIOD_US 20000
sahilmgandhi 18:6a4db94011d3 54 #define PWM_PERIOD_MIN 3
sahilmgandhi 18:6a4db94011d3 55
sahilmgandhi 18:6a4db94011d3 56 typedef struct
sahilmgandhi 18:6a4db94011d3 57 {
sahilmgandhi 18:6a4db94011d3 58 const app_pwm_t * const instance;
sahilmgandhi 18:6a4db94011d3 59 NRF_TIMER_Type * const timer_reg;
sahilmgandhi 18:6a4db94011d3 60 uint8_t channels_allocated;
sahilmgandhi 18:6a4db94011d3 61 uint32_t pins[PWM_CHANNELS_PER_INSTANCE];
sahilmgandhi 18:6a4db94011d3 62 uint16_t period_us;
sahilmgandhi 18:6a4db94011d3 63 uint16_t duty_ticks[PWM_CHANNELS_PER_INSTANCE];
sahilmgandhi 18:6a4db94011d3 64 } pwm_t;
sahilmgandhi 18:6a4db94011d3 65
sahilmgandhi 18:6a4db94011d3 66
sahilmgandhi 18:6a4db94011d3 67 APP_PWM_INSTANCE(m_pwm_instance_0, 1); //PWM0: Timer 1
sahilmgandhi 18:6a4db94011d3 68 APP_PWM_INSTANCE(m_pwm_instance_1, 2); //PWM1: Timer 2
sahilmgandhi 18:6a4db94011d3 69
sahilmgandhi 18:6a4db94011d3 70
sahilmgandhi 18:6a4db94011d3 71 static pwm_t m_pwm[] = {
sahilmgandhi 18:6a4db94011d3 72 {.instance = &m_pwm_instance_0, .timer_reg = NRF_TIMER1, .channels_allocated = 0},
sahilmgandhi 18:6a4db94011d3 73 {.instance = &m_pwm_instance_1, .timer_reg = NRF_TIMER2, .channels_allocated = 0}
sahilmgandhi 18:6a4db94011d3 74 };
sahilmgandhi 18:6a4db94011d3 75
sahilmgandhi 18:6a4db94011d3 76 static inline void pwm_ticks_set(pwm_t* pwm, uint8_t channel, uint16_t ticks)
sahilmgandhi 18:6a4db94011d3 77 {
sahilmgandhi 18:6a4db94011d3 78 pwm->duty_ticks[channel] = ticks;
sahilmgandhi 18:6a4db94011d3 79 while (app_pwm_channel_duty_ticks_set(pwm->instance, channel, ticks) != NRF_SUCCESS);
sahilmgandhi 18:6a4db94011d3 80 }
sahilmgandhi 18:6a4db94011d3 81
sahilmgandhi 18:6a4db94011d3 82 static void pwm_reinit(pwm_t * pwm)
sahilmgandhi 18:6a4db94011d3 83 {
sahilmgandhi 18:6a4db94011d3 84 app_pwm_uninit(pwm->instance);
sahilmgandhi 18:6a4db94011d3 85 app_pwm_config_t pwm_cfg = APP_PWM_DEFAULT_CONFIG_2CH(pwm->period_us,
sahilmgandhi 18:6a4db94011d3 86 pwm->pins[0],
sahilmgandhi 18:6a4db94011d3 87 pwm->pins[1]);
sahilmgandhi 18:6a4db94011d3 88 app_pwm_init(pwm->instance, &pwm_cfg, NULL);
sahilmgandhi 18:6a4db94011d3 89 app_pwm_enable(pwm->instance);
sahilmgandhi 18:6a4db94011d3 90
sahilmgandhi 18:6a4db94011d3 91 for (uint8_t channel = 0; channel < PWM_CHANNELS_PER_INSTANCE; ++channel) {
sahilmgandhi 18:6a4db94011d3 92 if ((pwm->channels_allocated & (1 << channel)) && (pwm->pins[channel] != APP_PWM_NOPIN)) {
sahilmgandhi 18:6a4db94011d3 93 app_pwm_channel_duty_ticks_set(pwm->instance, channel, pwm->duty_ticks[channel]);
sahilmgandhi 18:6a4db94011d3 94 }
sahilmgandhi 18:6a4db94011d3 95 }
sahilmgandhi 18:6a4db94011d3 96 }
sahilmgandhi 18:6a4db94011d3 97
sahilmgandhi 18:6a4db94011d3 98 void GPIOTE_IRQHandler(void);// exported from nrf_drv_gpiote.c
sahilmgandhi 18:6a4db94011d3 99
sahilmgandhi 18:6a4db94011d3 100 void TIMER1_IRQHandler(void);
sahilmgandhi 18:6a4db94011d3 101 void TIMER2_IRQHandler(void);
sahilmgandhi 18:6a4db94011d3 102
sahilmgandhi 18:6a4db94011d3 103 static const peripheral_handler_desc_t timer_handlers[] =
sahilmgandhi 18:6a4db94011d3 104 {
sahilmgandhi 18:6a4db94011d3 105 {
sahilmgandhi 18:6a4db94011d3 106 TIMER1_IRQn,
sahilmgandhi 18:6a4db94011d3 107 (uint32_t)TIMER1_IRQHandler
sahilmgandhi 18:6a4db94011d3 108 },
sahilmgandhi 18:6a4db94011d3 109 {
sahilmgandhi 18:6a4db94011d3 110 TIMER2_IRQn,
sahilmgandhi 18:6a4db94011d3 111 (uint32_t)TIMER2_IRQHandler
sahilmgandhi 18:6a4db94011d3 112 }
sahilmgandhi 18:6a4db94011d3 113 };
sahilmgandhi 18:6a4db94011d3 114
sahilmgandhi 18:6a4db94011d3 115 void pwmout_init(pwmout_t *obj, PinName pin)
sahilmgandhi 18:6a4db94011d3 116 {
sahilmgandhi 18:6a4db94011d3 117 if (pin == NC) {
sahilmgandhi 18:6a4db94011d3 118 error("PwmOut init failed. Invalid pin name.");
sahilmgandhi 18:6a4db94011d3 119 }
sahilmgandhi 18:6a4db94011d3 120
sahilmgandhi 18:6a4db94011d3 121 // Check if pin is already initialized and find the next free channel.
sahilmgandhi 18:6a4db94011d3 122 uint8_t free_instance = 0xFF;
sahilmgandhi 18:6a4db94011d3 123 uint8_t free_channel = 0xFF;
sahilmgandhi 18:6a4db94011d3 124
sahilmgandhi 18:6a4db94011d3 125 for (uint8_t inst = 0; inst < PWM_INSTANCE_COUNT; ++inst) {
sahilmgandhi 18:6a4db94011d3 126 if (m_pwm[inst].channels_allocated) {
sahilmgandhi 18:6a4db94011d3 127 for (uint8_t channel = 0; channel < PWM_CHANNELS_PER_INSTANCE; ++channel) {
sahilmgandhi 18:6a4db94011d3 128 if (m_pwm[inst].channels_allocated & (1 << channel)) {
sahilmgandhi 18:6a4db94011d3 129 if (m_pwm[inst].pins[channel] == (uint32_t)pin) {
sahilmgandhi 18:6a4db94011d3 130 error("PwmOut init failed. Pin is already in use.");
sahilmgandhi 18:6a4db94011d3 131 return;
sahilmgandhi 18:6a4db94011d3 132 }
sahilmgandhi 18:6a4db94011d3 133 }
sahilmgandhi 18:6a4db94011d3 134 else {
sahilmgandhi 18:6a4db94011d3 135 if (free_instance == 0xFF) {
sahilmgandhi 18:6a4db94011d3 136 free_instance = inst;
sahilmgandhi 18:6a4db94011d3 137 free_channel = channel;
sahilmgandhi 18:6a4db94011d3 138 }
sahilmgandhi 18:6a4db94011d3 139 }
sahilmgandhi 18:6a4db94011d3 140 }
sahilmgandhi 18:6a4db94011d3 141 }
sahilmgandhi 18:6a4db94011d3 142 else {
sahilmgandhi 18:6a4db94011d3 143 if (free_instance == 0xFF) {
sahilmgandhi 18:6a4db94011d3 144 free_instance = inst;
sahilmgandhi 18:6a4db94011d3 145 free_channel = 0;
sahilmgandhi 18:6a4db94011d3 146 }
sahilmgandhi 18:6a4db94011d3 147 }
sahilmgandhi 18:6a4db94011d3 148 }
sahilmgandhi 18:6a4db94011d3 149
sahilmgandhi 18:6a4db94011d3 150 if (free_instance == 0xFF)
sahilmgandhi 18:6a4db94011d3 151 {
sahilmgandhi 18:6a4db94011d3 152 error("PwmOut init failed. All available PWM channels are in use.");
sahilmgandhi 18:6a4db94011d3 153 return;
sahilmgandhi 18:6a4db94011d3 154 }
sahilmgandhi 18:6a4db94011d3 155
sahilmgandhi 18:6a4db94011d3 156 // Init / reinit PWM instance.
sahilmgandhi 18:6a4db94011d3 157 m_pwm[free_instance].pins[free_channel] = (uint32_t) pin;
sahilmgandhi 18:6a4db94011d3 158 m_pwm[free_instance].duty_ticks[free_channel] = 0;
sahilmgandhi 18:6a4db94011d3 159 if (!m_pwm[free_instance].channels_allocated) {
sahilmgandhi 18:6a4db94011d3 160
sahilmgandhi 18:6a4db94011d3 161 NVIC_SetVector(GPIOTE_IRQn, (uint32_t) GPIOTE_IRQHandler);
sahilmgandhi 18:6a4db94011d3 162
sahilmgandhi 18:6a4db94011d3 163 NVIC_SetVector(timer_handlers[free_instance].IRQn, timer_handlers[free_instance].vector);
sahilmgandhi 18:6a4db94011d3 164
sahilmgandhi 18:6a4db94011d3 165 m_pwm[free_instance].period_us = PWM_DEFAULT_PERIOD_US;
sahilmgandhi 18:6a4db94011d3 166 for (uint8_t channel = 1; channel < PWM_CHANNELS_PER_INSTANCE; ++channel) {
sahilmgandhi 18:6a4db94011d3 167 m_pwm[free_instance].pins[channel] = APP_PWM_NOPIN;
sahilmgandhi 18:6a4db94011d3 168 m_pwm[free_instance].duty_ticks[channel] = 0;
sahilmgandhi 18:6a4db94011d3 169 }
sahilmgandhi 18:6a4db94011d3 170 app_pwm_config_t pwm_cfg = APP_PWM_DEFAULT_CONFIG_1CH(PWM_DEFAULT_PERIOD_US, pin);
sahilmgandhi 18:6a4db94011d3 171 app_pwm_init(m_pwm[free_instance].instance, &pwm_cfg, NULL);
sahilmgandhi 18:6a4db94011d3 172 app_pwm_enable(m_pwm[free_instance].instance);
sahilmgandhi 18:6a4db94011d3 173 }
sahilmgandhi 18:6a4db94011d3 174 else {
sahilmgandhi 18:6a4db94011d3 175 pwm_reinit(&m_pwm[free_instance]);
sahilmgandhi 18:6a4db94011d3 176 }
sahilmgandhi 18:6a4db94011d3 177 m_pwm[free_instance].channels_allocated |= (1 << free_channel);
sahilmgandhi 18:6a4db94011d3 178
sahilmgandhi 18:6a4db94011d3 179 obj->pin = pin;
sahilmgandhi 18:6a4db94011d3 180 obj->pwm_struct = (void *) &m_pwm[free_instance];
sahilmgandhi 18:6a4db94011d3 181 obj->pwm_channel = free_channel;
sahilmgandhi 18:6a4db94011d3 182 }
sahilmgandhi 18:6a4db94011d3 183
sahilmgandhi 18:6a4db94011d3 184 void pwmout_free(pwmout_t *obj)
sahilmgandhi 18:6a4db94011d3 185 {
sahilmgandhi 18:6a4db94011d3 186 MBED_ASSERT(obj->pwm_name != (PWMName)NC);
sahilmgandhi 18:6a4db94011d3 187 MBED_ASSERT(obj->pwm_channel < PWM_CHANNELS_PER_INSTANCE);
sahilmgandhi 18:6a4db94011d3 188
sahilmgandhi 18:6a4db94011d3 189 pwm_t * pwm = (pwm_t *) obj->pwm_struct;
sahilmgandhi 18:6a4db94011d3 190 pwm->channels_allocated &= ~(1 << obj->pwm_channel);
sahilmgandhi 18:6a4db94011d3 191 pwm->pins[obj->pwm_channel] = APP_PWM_NOPIN;
sahilmgandhi 18:6a4db94011d3 192 pwm->duty_ticks[obj->pwm_channel] = 0;
sahilmgandhi 18:6a4db94011d3 193
sahilmgandhi 18:6a4db94011d3 194 app_pwm_uninit(pwm->instance);
sahilmgandhi 18:6a4db94011d3 195 if (pwm->channels_allocated) {
sahilmgandhi 18:6a4db94011d3 196 pwm_reinit(pwm);
sahilmgandhi 18:6a4db94011d3 197 }
sahilmgandhi 18:6a4db94011d3 198
sahilmgandhi 18:6a4db94011d3 199 obj->pwm_struct = NULL;
sahilmgandhi 18:6a4db94011d3 200 }
sahilmgandhi 18:6a4db94011d3 201
sahilmgandhi 18:6a4db94011d3 202 void pwmout_write(pwmout_t *obj, float value)
sahilmgandhi 18:6a4db94011d3 203 {
sahilmgandhi 18:6a4db94011d3 204 pwm_t * pwm = (pwm_t *) obj->pwm_struct;
sahilmgandhi 18:6a4db94011d3 205 if (value > 1.0f) {
sahilmgandhi 18:6a4db94011d3 206 value = 1.0f;
sahilmgandhi 18:6a4db94011d3 207 }
sahilmgandhi 18:6a4db94011d3 208
sahilmgandhi 18:6a4db94011d3 209 app_pwm_channel_duty_set(pwm->instance, obj->pwm_channel, (app_pwm_duty_t)(value * 100.0f) );
sahilmgandhi 18:6a4db94011d3 210 }
sahilmgandhi 18:6a4db94011d3 211
sahilmgandhi 18:6a4db94011d3 212 float pwmout_read(pwmout_t *obj)
sahilmgandhi 18:6a4db94011d3 213 {
sahilmgandhi 18:6a4db94011d3 214 pwm_t * pwm = (pwm_t *) obj->pwm_struct;
sahilmgandhi 18:6a4db94011d3 215 MBED_ASSERT(pwm != NULL);
sahilmgandhi 18:6a4db94011d3 216 return ((float)pwm->duty_ticks[obj->pwm_channel] / (float)app_pwm_cycle_ticks_get(pwm->instance));
sahilmgandhi 18:6a4db94011d3 217 }
sahilmgandhi 18:6a4db94011d3 218
sahilmgandhi 18:6a4db94011d3 219 void pwmout_period(pwmout_t *obj, float seconds)
sahilmgandhi 18:6a4db94011d3 220 {
sahilmgandhi 18:6a4db94011d3 221 pwmout_period_us(obj, seconds * 1000000.0f);
sahilmgandhi 18:6a4db94011d3 222 }
sahilmgandhi 18:6a4db94011d3 223
sahilmgandhi 18:6a4db94011d3 224 void pwmout_period_ms(pwmout_t *obj, int ms)
sahilmgandhi 18:6a4db94011d3 225 {
sahilmgandhi 18:6a4db94011d3 226 pwmout_period_us(obj, ms * 1000);
sahilmgandhi 18:6a4db94011d3 227 }
sahilmgandhi 18:6a4db94011d3 228
sahilmgandhi 18:6a4db94011d3 229 void pwmout_period_us(pwmout_t *obj, int us)
sahilmgandhi 18:6a4db94011d3 230 {
sahilmgandhi 18:6a4db94011d3 231 pwm_t * pwm = (pwm_t *) obj->pwm_struct;
sahilmgandhi 18:6a4db94011d3 232 MBED_ASSERT(pwm != NULL);
sahilmgandhi 18:6a4db94011d3 233 if (us < PWM_PERIOD_MIN) {
sahilmgandhi 18:6a4db94011d3 234 us = PWM_PERIOD_MIN;
sahilmgandhi 18:6a4db94011d3 235 }
sahilmgandhi 18:6a4db94011d3 236 pwm->period_us = (uint32_t)us;
sahilmgandhi 18:6a4db94011d3 237 pwm_reinit(pwm);
sahilmgandhi 18:6a4db94011d3 238 }
sahilmgandhi 18:6a4db94011d3 239
sahilmgandhi 18:6a4db94011d3 240 void pwmout_pulsewidth(pwmout_t *obj, float seconds)
sahilmgandhi 18:6a4db94011d3 241 {
sahilmgandhi 18:6a4db94011d3 242 pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
sahilmgandhi 18:6a4db94011d3 243 }
sahilmgandhi 18:6a4db94011d3 244
sahilmgandhi 18:6a4db94011d3 245 void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
sahilmgandhi 18:6a4db94011d3 246 {
sahilmgandhi 18:6a4db94011d3 247 pwmout_pulsewidth_us(obj, ms * 1000);
sahilmgandhi 18:6a4db94011d3 248 }
sahilmgandhi 18:6a4db94011d3 249
sahilmgandhi 18:6a4db94011d3 250 void pwmout_pulsewidth_us(pwmout_t *obj, int us)
sahilmgandhi 18:6a4db94011d3 251 {
sahilmgandhi 18:6a4db94011d3 252 pwm_t * pwm = (pwm_t *) obj->pwm_struct;
sahilmgandhi 18:6a4db94011d3 253 MBED_ASSERT(pwm);
sahilmgandhi 18:6a4db94011d3 254
sahilmgandhi 18:6a4db94011d3 255 uint16_t ticks = nrf_timer_us_to_ticks((uint32_t)us, nrf_timer_frequency_get(pwm->timer_reg));
sahilmgandhi 18:6a4db94011d3 256 pwm_ticks_set(pwm, obj->pwm_channel, ticks);
sahilmgandhi 18:6a4db94011d3 257 }
sahilmgandhi 18:6a4db94011d3 258
sahilmgandhi 18:6a4db94011d3 259 #endif // DEVICE_PWMOUT