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 /* mbed Microcontroller Library
sahilmgandhi 18:6a4db94011d3 2 * Copyright (c) 2006-2015 ARM Limited
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 <stddef.h>
sahilmgandhi 18:6a4db94011d3 17 #include "us_ticker_api.h"
sahilmgandhi 18:6a4db94011d3 18 #include "PeripheralNames.h"
sahilmgandhi 18:6a4db94011d3 19 #include "clk_freqs.h"
sahilmgandhi 18:6a4db94011d3 20
sahilmgandhi 18:6a4db94011d3 21 #define PIT_TIMER PIT->CHANNEL[0]
sahilmgandhi 18:6a4db94011d3 22 #define PIT_TIMER_IRQ PIT0_IRQn
sahilmgandhi 18:6a4db94011d3 23 #define PIT_TICKER PIT->CHANNEL[1]
sahilmgandhi 18:6a4db94011d3 24 #define PIT_TICKER_IRQ PIT1_IRQn
sahilmgandhi 18:6a4db94011d3 25
sahilmgandhi 18:6a4db94011d3 26 static void timer_init(void);
sahilmgandhi 18:6a4db94011d3 27 static void ticker_init(void);
sahilmgandhi 18:6a4db94011d3 28
sahilmgandhi 18:6a4db94011d3 29
sahilmgandhi 18:6a4db94011d3 30 static int us_ticker_inited = 0;
sahilmgandhi 18:6a4db94011d3 31 static uint32_t clk_mhz;
sahilmgandhi 18:6a4db94011d3 32
sahilmgandhi 18:6a4db94011d3 33 void us_ticker_init(void) {
sahilmgandhi 18:6a4db94011d3 34 if (us_ticker_inited)
sahilmgandhi 18:6a4db94011d3 35 return;
sahilmgandhi 18:6a4db94011d3 36 us_ticker_inited = 1;
sahilmgandhi 18:6a4db94011d3 37
sahilmgandhi 18:6a4db94011d3 38 SIM->SCGC6 |= SIM_SCGC6_PIT_MASK; // Clock PIT
sahilmgandhi 18:6a4db94011d3 39 PIT->MCR = 0; // Enable PIT
sahilmgandhi 18:6a4db94011d3 40
sahilmgandhi 18:6a4db94011d3 41 clk_mhz = bus_frequency() / 1000000;
sahilmgandhi 18:6a4db94011d3 42
sahilmgandhi 18:6a4db94011d3 43 timer_init();
sahilmgandhi 18:6a4db94011d3 44 ticker_init();
sahilmgandhi 18:6a4db94011d3 45 }
sahilmgandhi 18:6a4db94011d3 46
sahilmgandhi 18:6a4db94011d3 47 /******************************************************************************
sahilmgandhi 18:6a4db94011d3 48 * Timer for us timing.
sahilmgandhi 18:6a4db94011d3 49 *
sahilmgandhi 18:6a4db94011d3 50 * The K20D5M does not have a prescaler on its PIT timer nor the option
sahilmgandhi 18:6a4db94011d3 51 * to chain timers, which is why a software timer is required to get 32-bit
sahilmgandhi 18:6a4db94011d3 52 * word length.
sahilmgandhi 18:6a4db94011d3 53 ******************************************************************************/
sahilmgandhi 18:6a4db94011d3 54 static volatile uint32_t msb_counter = 0;
sahilmgandhi 18:6a4db94011d3 55 static uint32_t timer_ldval = 0;
sahilmgandhi 18:6a4db94011d3 56
sahilmgandhi 18:6a4db94011d3 57 static void timer_isr(void) {
sahilmgandhi 18:6a4db94011d3 58 if (PIT_TIMER.TFLG == 1) {
sahilmgandhi 18:6a4db94011d3 59 msb_counter++;
sahilmgandhi 18:6a4db94011d3 60 PIT_TIMER.TFLG = 1;
sahilmgandhi 18:6a4db94011d3 61 }
sahilmgandhi 18:6a4db94011d3 62 }
sahilmgandhi 18:6a4db94011d3 63
sahilmgandhi 18:6a4db94011d3 64 static void timer_init(void) {
sahilmgandhi 18:6a4db94011d3 65 //CLZ counts the leading zeros, returning number of bits not used by clk_mhz
sahilmgandhi 18:6a4db94011d3 66 timer_ldval = clk_mhz << __CLZ(clk_mhz);
sahilmgandhi 18:6a4db94011d3 67
sahilmgandhi 18:6a4db94011d3 68 PIT_TIMER.LDVAL = timer_ldval; // 1us
sahilmgandhi 18:6a4db94011d3 69 PIT_TIMER.TCTRL |= PIT_TCTRL_TIE_MASK;
sahilmgandhi 18:6a4db94011d3 70 PIT_TIMER.TCTRL |= PIT_TCTRL_TEN_MASK; // Start timer 0
sahilmgandhi 18:6a4db94011d3 71
sahilmgandhi 18:6a4db94011d3 72 NVIC_SetVector(PIT_TIMER_IRQ, (uint32_t)timer_isr);
sahilmgandhi 18:6a4db94011d3 73 NVIC_EnableIRQ(PIT_TIMER_IRQ);
sahilmgandhi 18:6a4db94011d3 74 }
sahilmgandhi 18:6a4db94011d3 75
sahilmgandhi 18:6a4db94011d3 76 uint32_t us_ticker_read() {
sahilmgandhi 18:6a4db94011d3 77 if (!us_ticker_inited)
sahilmgandhi 18:6a4db94011d3 78 us_ticker_init();
sahilmgandhi 18:6a4db94011d3 79
sahilmgandhi 18:6a4db94011d3 80 uint32_t retval;
sahilmgandhi 18:6a4db94011d3 81 __disable_irq();
sahilmgandhi 18:6a4db94011d3 82 retval = (timer_ldval - PIT_TIMER.CVAL) / clk_mhz; //Hardware bits
sahilmgandhi 18:6a4db94011d3 83 retval |= msb_counter << __CLZ(clk_mhz); //Software bits
sahilmgandhi 18:6a4db94011d3 84
sahilmgandhi 18:6a4db94011d3 85 if (PIT_TIMER.TFLG == 1) { //If overflow bit is set, force it to be handled
sahilmgandhi 18:6a4db94011d3 86 timer_isr(); //Handle IRQ, read again to make sure software/hardware bits are synced
sahilmgandhi 18:6a4db94011d3 87 NVIC_ClearPendingIRQ(PIT_TIMER_IRQ);
sahilmgandhi 18:6a4db94011d3 88 return us_ticker_read();
sahilmgandhi 18:6a4db94011d3 89 }
sahilmgandhi 18:6a4db94011d3 90
sahilmgandhi 18:6a4db94011d3 91 __enable_irq();
sahilmgandhi 18:6a4db94011d3 92 return retval;
sahilmgandhi 18:6a4db94011d3 93 }
sahilmgandhi 18:6a4db94011d3 94
sahilmgandhi 18:6a4db94011d3 95 /******************************************************************************
sahilmgandhi 18:6a4db94011d3 96 * Timer Event
sahilmgandhi 18:6a4db94011d3 97 *
sahilmgandhi 18:6a4db94011d3 98 * It schedules interrupts at given (32bit)us interval of time.
sahilmgandhi 18:6a4db94011d3 99 * It is implemented using PIT channel 1, since no prescaler is available,
sahilmgandhi 18:6a4db94011d3 100 * some bits are implemented in software.
sahilmgandhi 18:6a4db94011d3 101 ******************************************************************************/
sahilmgandhi 18:6a4db94011d3 102 static void ticker_isr(void);
sahilmgandhi 18:6a4db94011d3 103
sahilmgandhi 18:6a4db94011d3 104 static void ticker_init(void) {
sahilmgandhi 18:6a4db94011d3 105 /* Set interrupt handler */
sahilmgandhi 18:6a4db94011d3 106 NVIC_SetVector(PIT_TICKER_IRQ, (uint32_t)ticker_isr);
sahilmgandhi 18:6a4db94011d3 107 NVIC_EnableIRQ(PIT_TICKER_IRQ);
sahilmgandhi 18:6a4db94011d3 108 }
sahilmgandhi 18:6a4db94011d3 109
sahilmgandhi 18:6a4db94011d3 110 void us_ticker_disable_interrupt(void) {
sahilmgandhi 18:6a4db94011d3 111 PIT_TICKER.TCTRL &= ~PIT_TCTRL_TIE_MASK;
sahilmgandhi 18:6a4db94011d3 112 }
sahilmgandhi 18:6a4db94011d3 113
sahilmgandhi 18:6a4db94011d3 114 void us_ticker_clear_interrupt(void) {
sahilmgandhi 18:6a4db94011d3 115 // we already clear interrupt in lptmr_isr
sahilmgandhi 18:6a4db94011d3 116 }
sahilmgandhi 18:6a4db94011d3 117
sahilmgandhi 18:6a4db94011d3 118 static uint32_t us_ticker_int_counter = 0;
sahilmgandhi 18:6a4db94011d3 119
sahilmgandhi 18:6a4db94011d3 120 inline static void ticker_set(uint32_t count) {
sahilmgandhi 18:6a4db94011d3 121 PIT_TICKER.TCTRL = 0;
sahilmgandhi 18:6a4db94011d3 122 PIT_TICKER.LDVAL = count;
sahilmgandhi 18:6a4db94011d3 123 PIT_TICKER.TCTRL = PIT_TCTRL_TIE_MASK | PIT_TCTRL_TEN_MASK;
sahilmgandhi 18:6a4db94011d3 124 }
sahilmgandhi 18:6a4db94011d3 125
sahilmgandhi 18:6a4db94011d3 126 static void ticker_isr(void) {
sahilmgandhi 18:6a4db94011d3 127 // Clear IRQ flag
sahilmgandhi 18:6a4db94011d3 128 PIT_TICKER.TFLG = 1;
sahilmgandhi 18:6a4db94011d3 129
sahilmgandhi 18:6a4db94011d3 130 if (us_ticker_int_counter > 0) {
sahilmgandhi 18:6a4db94011d3 131 ticker_set(0xFFFFFFFF);
sahilmgandhi 18:6a4db94011d3 132 us_ticker_int_counter--;
sahilmgandhi 18:6a4db94011d3 133 } else {
sahilmgandhi 18:6a4db94011d3 134 // This function is going to disable the interrupts if there are
sahilmgandhi 18:6a4db94011d3 135 // no other events in the queue
sahilmgandhi 18:6a4db94011d3 136 us_ticker_irq_handler();
sahilmgandhi 18:6a4db94011d3 137 }
sahilmgandhi 18:6a4db94011d3 138 }
sahilmgandhi 18:6a4db94011d3 139
sahilmgandhi 18:6a4db94011d3 140 void us_ticker_set_interrupt(timestamp_t timestamp) {
sahilmgandhi 18:6a4db94011d3 141 int delta = (int)((uint32_t)timestamp - us_ticker_read());
sahilmgandhi 18:6a4db94011d3 142 if (delta <= 0) {
sahilmgandhi 18:6a4db94011d3 143 // This event was in the past:
sahilmgandhi 18:6a4db94011d3 144 us_ticker_irq_handler();
sahilmgandhi 18:6a4db94011d3 145 return;
sahilmgandhi 18:6a4db94011d3 146 }
sahilmgandhi 18:6a4db94011d3 147
sahilmgandhi 18:6a4db94011d3 148 //Calculate how much falls outside the 32-bit after multiplying with clk_mhz
sahilmgandhi 18:6a4db94011d3 149 //We shift twice 16-bit to keep everything within the 32-bit variable
sahilmgandhi 18:6a4db94011d3 150 us_ticker_int_counter = (uint32_t)(delta >> 16);
sahilmgandhi 18:6a4db94011d3 151 us_ticker_int_counter *= clk_mhz;
sahilmgandhi 18:6a4db94011d3 152 us_ticker_int_counter >>= 16;
sahilmgandhi 18:6a4db94011d3 153
sahilmgandhi 18:6a4db94011d3 154 uint32_t us_ticker_int_remainder = (uint32_t)delta * clk_mhz;
sahilmgandhi 18:6a4db94011d3 155 if (us_ticker_int_remainder == 0) {
sahilmgandhi 18:6a4db94011d3 156 ticker_set(0xFFFFFFFF);
sahilmgandhi 18:6a4db94011d3 157 us_ticker_int_counter--;
sahilmgandhi 18:6a4db94011d3 158 } else {
sahilmgandhi 18:6a4db94011d3 159 ticker_set(us_ticker_int_remainder);
sahilmgandhi 18:6a4db94011d3 160 }
sahilmgandhi 18:6a4db94011d3 161 }