Mouse code for the MacroRat

Dependencies:   ITG3200 QEI

Committer:
sahilmgandhi
Date:
Fri May 26 17:21:04 2017 +0000
Revision:
34:69342782fb68
Parent:
18:6a4db94011d3
Added small reverse turns before the break so that we can stop faster.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
sahilmgandhi 18:6a4db94011d3 1 /* mbed Microcontroller Library
sahilmgandhi 18:6a4db94011d3 2 * Copyright (c) 2016 u-blox
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
sahilmgandhi 18:6a4db94011d3 17 /* The LP Ticker performs two functions for mbed:
sahilmgandhi 18:6a4db94011d3 18 *
sahilmgandhi 18:6a4db94011d3 19 * 1. Allows tracking of the passage of time.
sahilmgandhi 18:6a4db94011d3 20 * 2. Allows the system to enter the lowest power
sahilmgandhi 18:6a4db94011d3 21 * state for a given time.
sahilmgandhi 18:6a4db94011d3 22 *
sahilmgandhi 18:6a4db94011d3 23 * For this to work the single RTC interrupt needs
sahilmgandhi 18:6a4db94011d3 24 * to perform two functions. It needs to increment
sahilmgandhi 18:6a4db94011d3 25 * an overflow counter at every 32-bit overflow without
sahilmgandhi 18:6a4db94011d3 26 * otherwise affecting the system state (i.e. not waking it
sahilmgandhi 18:6a4db94011d3 27 * up and not putting it to sleep) and, when requested,
sahilmgandhi 18:6a4db94011d3 28 * it *also* needs to wake the system up from sleep
sahilmgandhi 18:6a4db94011d3 29 * at a specific time. Note also that the units of time
sahilmgandhi 18:6a4db94011d3 30 * from an mbed perspective are useconds, whereas the RTC
sahilmgandhi 18:6a4db94011d3 31 * is clocked at 32 kHz, hence there is conversion to be done.
sahilmgandhi 18:6a4db94011d3 32 *
sahilmgandhi 18:6a4db94011d3 33 * Since it is not possible to reset the RTC, we maintain
sahilmgandhi 18:6a4db94011d3 34 * a 32-bit window on it, starting at g_last_32bit_overflow_value
sahilmgandhi 18:6a4db94011d3 35 * and ending at g_next_32bit_overflow_value. All values
sahilmgandhi 18:6a4db94011d3 36 * fed back up to mbed are relative to g_last_32bit_overflow_value.
sahilmgandhi 18:6a4db94011d3 37 */
sahilmgandhi 18:6a4db94011d3 38
sahilmgandhi 18:6a4db94011d3 39 #include "lp_ticker_api.h"
sahilmgandhi 18:6a4db94011d3 40 #include "sleep_api.h"
sahilmgandhi 18:6a4db94011d3 41 #include "mbed_critical.h"
sahilmgandhi 18:6a4db94011d3 42
sahilmgandhi 18:6a4db94011d3 43 /* ----------------------------------------------------------------
sahilmgandhi 18:6a4db94011d3 44 * MACROS
sahilmgandhi 18:6a4db94011d3 45 * ----------------------------------------------------------------*/
sahilmgandhi 18:6a4db94011d3 46
sahilmgandhi 18:6a4db94011d3 47 /* The maximum value of the RTC (48 bits) */
sahilmgandhi 18:6a4db94011d3 48 #define RTC_MAX 0x0000FFFFFFFFFFFFULL
sahilmgandhi 18:6a4db94011d3 49
sahilmgandhi 18:6a4db94011d3 50 /* RTC modulo */
sahilmgandhi 18:6a4db94011d3 51 #define RTC_MODULO (RTC_MAX + 1)
sahilmgandhi 18:6a4db94011d3 52
sahilmgandhi 18:6a4db94011d3 53 /* The 32-bit overflow value */
sahilmgandhi 18:6a4db94011d3 54 #define MODULO_32BIT 0x100000000ULL
sahilmgandhi 18:6a4db94011d3 55
sahilmgandhi 18:6a4db94011d3 56 /* Macro to increment a 64-bit RTC value x by y, with wrap */
sahilmgandhi 18:6a4db94011d3 57 #define INCREMENT_MOD(x, y) (x = ((uint64_t) x + (uint64_t) y) % RTC_MODULO)
sahilmgandhi 18:6a4db94011d3 58
sahilmgandhi 18:6a4db94011d3 59 /* Macro to get MSBs from a 64-bit integer */
sahilmgandhi 18:6a4db94011d3 60 #define MSBS(x) ((uint32_t) ((uint64_t) (x) >> 32))
sahilmgandhi 18:6a4db94011d3 61
sahilmgandhi 18:6a4db94011d3 62 /* Macro to get LSBs from a 64-bit integer */
sahilmgandhi 18:6a4db94011d3 63 #define LSBS(x) ((uint32_t) (x))
sahilmgandhi 18:6a4db94011d3 64
sahilmgandhi 18:6a4db94011d3 65 /* ----------------------------------------------------------------
sahilmgandhi 18:6a4db94011d3 66 * TYPES
sahilmgandhi 18:6a4db94011d3 67 * ----------------------------------------------------------------*/
sahilmgandhi 18:6a4db94011d3 68
sahilmgandhi 18:6a4db94011d3 69 /* ----------------------------------------------------------------
sahilmgandhi 18:6a4db94011d3 70 * GLOBAL VARIABLES
sahilmgandhi 18:6a4db94011d3 71 * ----------------------------------------------------------------*/
sahilmgandhi 18:6a4db94011d3 72
sahilmgandhi 18:6a4db94011d3 73 /* Incremented each time the RTC goes over 32 bits */
sahilmgandhi 18:6a4db94011d3 74 static uint32_t g_overflow_count = 0;
sahilmgandhi 18:6a4db94011d3 75
sahilmgandhi 18:6a4db94011d3 76 /* Set when a user interrupt has been requested but an overflow
sahilmgandhi 18:6a4db94011d3 77 * interrupt needs to happen first */
sahilmgandhi 18:6a4db94011d3 78 static bool g_user_interrupt_pending = false;
sahilmgandhi 18:6a4db94011d3 79
sahilmgandhi 18:6a4db94011d3 80 /* Set when a user interrupt is the next interrupt to happen */
sahilmgandhi 18:6a4db94011d3 81 static bool g_user_interrupt_set = false;
sahilmgandhi 18:6a4db94011d3 82
sahilmgandhi 18:6a4db94011d3 83 /* Initialised flag, used to protect against interrupts going
sahilmgandhi 18:6a4db94011d3 84 * off before we're initialised */
sahilmgandhi 18:6a4db94011d3 85 static bool g_initialised = false;
sahilmgandhi 18:6a4db94011d3 86
sahilmgandhi 18:6a4db94011d3 87 /* The next overflow value to be used */
sahilmgandhi 18:6a4db94011d3 88 static uint64_t g_next_32bit_overflow_value;
sahilmgandhi 18:6a4db94011d3 89
sahilmgandhi 18:6a4db94011d3 90 /* The next match-compare value to be used */
sahilmgandhi 18:6a4db94011d3 91 static uint64_t g_next_compare_value;
sahilmgandhi 18:6a4db94011d3 92
sahilmgandhi 18:6a4db94011d3 93 /* Keep track of the previous 32-bit overflow
sahilmgandhi 18:6a4db94011d3 94 * value so that we can report 32-bit time
sahilmgandhi 18:6a4db94011d3 95 * correctly */
sahilmgandhi 18:6a4db94011d3 96 static uint64_t g_last_32bit_overflow_value;
sahilmgandhi 18:6a4db94011d3 97
sahilmgandhi 18:6a4db94011d3 98 /* ----------------------------------------------------------------
sahilmgandhi 18:6a4db94011d3 99 * FUNCTION PROTOTYPES
sahilmgandhi 18:6a4db94011d3 100 * ----------------------------------------------------------------*/
sahilmgandhi 18:6a4db94011d3 101
sahilmgandhi 18:6a4db94011d3 102 static void set_interrupt_to_32bit_overflow(void);
sahilmgandhi 18:6a4db94011d3 103 static void set_interrupt_to_user_value(void);
sahilmgandhi 18:6a4db94011d3 104
sahilmgandhi 18:6a4db94011d3 105 /* ----------------------------------------------------------------
sahilmgandhi 18:6a4db94011d3 106 * STATIC FUNCTIONS
sahilmgandhi 18:6a4db94011d3 107 * ----------------------------------------------------------------*/
sahilmgandhi 18:6a4db94011d3 108
sahilmgandhi 18:6a4db94011d3 109 /* Convert a tick value (32,768 Hz) into a microsecond value */
sahilmgandhi 18:6a4db94011d3 110 static inline uint32_t ticksToUSeconds(uint32_t x)
sahilmgandhi 18:6a4db94011d3 111 {
sahilmgandhi 18:6a4db94011d3 112 /* TODO: find a way to avoid the multiply by 1000000
sahilmgandhi 18:6a4db94011d3 113 * Shift by 20 would introduce a 5% error, which is
sahilmgandhi 18:6a4db94011d3 114 * probably too much */
sahilmgandhi 18:6a4db94011d3 115 uint64_t result = ((((uint64_t) x) * 1000000) >> 15);
sahilmgandhi 18:6a4db94011d3 116
sahilmgandhi 18:6a4db94011d3 117 if (result > 0xFFFFFFFF) {
sahilmgandhi 18:6a4db94011d3 118 result = 0xFFFFFFFF;
sahilmgandhi 18:6a4db94011d3 119 }
sahilmgandhi 18:6a4db94011d3 120
sahilmgandhi 18:6a4db94011d3 121 return (uint32_t) result;
sahilmgandhi 18:6a4db94011d3 122 }
sahilmgandhi 18:6a4db94011d3 123
sahilmgandhi 18:6a4db94011d3 124 /* Convert a microsecond value into a tick value (32,768 Hz) */
sahilmgandhi 18:6a4db94011d3 125 static inline uint32_t uSecondsToTicks(uint32_t x)
sahilmgandhi 18:6a4db94011d3 126 {
sahilmgandhi 18:6a4db94011d3 127 /* TODO: find a way to avoid the divide by 1000000
sahilmgandhi 18:6a4db94011d3 128 * Shift by 20 would introduce a 5% error, which is
sahilmgandhi 18:6a4db94011d3 129 * probably too much */
sahilmgandhi 18:6a4db94011d3 130 return (uint32_t) ((((uint64_t) x) << 15) / 1000000);
sahilmgandhi 18:6a4db94011d3 131 }
sahilmgandhi 18:6a4db94011d3 132
sahilmgandhi 18:6a4db94011d3 133 /* Take g_next_32bit_overflow_value and apply it to g_next_compare_value and
sahilmgandhi 18:6a4db94011d3 134 * then the chip registers
sahilmgandhi 18:6a4db94011d3 135 * NOTE: the RTC interrupt should be disabled when calling this function */
sahilmgandhi 18:6a4db94011d3 136 static inline void set_interrupt_to_32bit_overflow()
sahilmgandhi 18:6a4db94011d3 137 {
sahilmgandhi 18:6a4db94011d3 138 /* Load up the values */
sahilmgandhi 18:6a4db94011d3 139 g_next_compare_value = g_next_32bit_overflow_value;
sahilmgandhi 18:6a4db94011d3 140
sahilmgandhi 18:6a4db94011d3 141 /* Set up the match register values */
sahilmgandhi 18:6a4db94011d3 142 RTC_IRQ_TIME_MSBS = MSBS(g_next_compare_value);
sahilmgandhi 18:6a4db94011d3 143 RTC_IRQ_TIME_LSBS = LSBS(g_next_compare_value);
sahilmgandhi 18:6a4db94011d3 144 }
sahilmgandhi 18:6a4db94011d3 145
sahilmgandhi 18:6a4db94011d3 146 /* Take g_next_compare_value and apply it to the chip registers
sahilmgandhi 18:6a4db94011d3 147 * NOTE: the RTC interrupt should be disabled when calling this function */
sahilmgandhi 18:6a4db94011d3 148 static inline void set_interrupt_to_user_value()
sahilmgandhi 18:6a4db94011d3 149 {
sahilmgandhi 18:6a4db94011d3 150 g_user_interrupt_set = true;
sahilmgandhi 18:6a4db94011d3 151
sahilmgandhi 18:6a4db94011d3 152 /* Write MSBS first, then the value is latched on LSBS write */
sahilmgandhi 18:6a4db94011d3 153 RTC_IRQ_TIME_MSBS = MSBS(g_next_compare_value);
sahilmgandhi 18:6a4db94011d3 154 RTC_IRQ_TIME_LSBS = LSBS(g_next_compare_value);
sahilmgandhi 18:6a4db94011d3 155 }
sahilmgandhi 18:6a4db94011d3 156
sahilmgandhi 18:6a4db94011d3 157 /* Get the RTC value
sahilmgandhi 18:6a4db94011d3 158 * NOTE: the RTC interrupt should be disabled when calling this function */
sahilmgandhi 18:6a4db94011d3 159 static inline uint64_t get_rtc_value()
sahilmgandhi 18:6a4db94011d3 160 {
sahilmgandhi 18:6a4db94011d3 161 uint64_t rtc_value;
sahilmgandhi 18:6a4db94011d3 162
sahilmgandhi 18:6a4db94011d3 163 rtc_value = ((uint64_t) RTC_TIME_MSBS) << 32;
sahilmgandhi 18:6a4db94011d3 164 rtc_value |= RTC_TIME_LSBS;
sahilmgandhi 18:6a4db94011d3 165
sahilmgandhi 18:6a4db94011d3 166 return rtc_value;
sahilmgandhi 18:6a4db94011d3 167 }
sahilmgandhi 18:6a4db94011d3 168
sahilmgandhi 18:6a4db94011d3 169 /* ----------------------------------------------------------------
sahilmgandhi 18:6a4db94011d3 170 * NON-API FUNCTIONS
sahilmgandhi 18:6a4db94011d3 171 * ----------------------------------------------------------------*/
sahilmgandhi 18:6a4db94011d3 172
sahilmgandhi 18:6a4db94011d3 173 /* RTC handler */
sahilmgandhi 18:6a4db94011d3 174 void IRQ0_RTC_Handler(void)
sahilmgandhi 18:6a4db94011d3 175 {
sahilmgandhi 18:6a4db94011d3 176 /* Have seen this interrupt occurring before initialisation, so guard
sahilmgandhi 18:6a4db94011d3 177 * against that */
sahilmgandhi 18:6a4db94011d3 178 if (g_initialised) {
sahilmgandhi 18:6a4db94011d3 179 if (g_user_interrupt_pending) {
sahilmgandhi 18:6a4db94011d3 180 /* If there was a user interrupt pending, set it now */
sahilmgandhi 18:6a4db94011d3 181 set_interrupt_to_user_value();
sahilmgandhi 18:6a4db94011d3 182
sahilmgandhi 18:6a4db94011d3 183 /* Reset the pending flag */
sahilmgandhi 18:6a4db94011d3 184 g_user_interrupt_pending = false;
sahilmgandhi 18:6a4db94011d3 185
sahilmgandhi 18:6a4db94011d3 186 /* This must have been a 32-bit overflow interrupt so
sahilmgandhi 18:6a4db94011d3 187 * increment the count */
sahilmgandhi 18:6a4db94011d3 188 g_overflow_count++;
sahilmgandhi 18:6a4db94011d3 189 g_last_32bit_overflow_value = g_next_32bit_overflow_value;
sahilmgandhi 18:6a4db94011d3 190 INCREMENT_MOD(g_next_32bit_overflow_value, MODULO_32BIT);
sahilmgandhi 18:6a4db94011d3 191 } else {
sahilmgandhi 18:6a4db94011d3 192 if (g_user_interrupt_set) {
sahilmgandhi 18:6a4db94011d3 193 /* It's a user interrupt, so wake from sleep but don't
sahilmgandhi 18:6a4db94011d3 194 * increment the overflow count as this is not an
sahilmgandhi 18:6a4db94011d3 195 * overflow interrupt */
sahilmgandhi 18:6a4db94011d3 196
sahilmgandhi 18:6a4db94011d3 197 /* Reset the user interrupt flag and call mbed */
sahilmgandhi 18:6a4db94011d3 198 g_user_interrupt_set = false;
sahilmgandhi 18:6a4db94011d3 199 lp_ticker_irq_handler();
sahilmgandhi 18:6a4db94011d3 200 } else {
sahilmgandhi 18:6a4db94011d3 201 /* Increment the count as this was a 32-bit overflow
sahilmgandhi 18:6a4db94011d3 202 * interrupt rather than a user interrupt */
sahilmgandhi 18:6a4db94011d3 203 g_overflow_count++;
sahilmgandhi 18:6a4db94011d3 204 g_last_32bit_overflow_value = g_next_32bit_overflow_value;
sahilmgandhi 18:6a4db94011d3 205 INCREMENT_MOD(g_next_32bit_overflow_value, MODULO_32BIT);
sahilmgandhi 18:6a4db94011d3 206 }
sahilmgandhi 18:6a4db94011d3 207
sahilmgandhi 18:6a4db94011d3 208 /* Set the next interrupt to be at the 32-bit overflow */
sahilmgandhi 18:6a4db94011d3 209 set_interrupt_to_32bit_overflow();
sahilmgandhi 18:6a4db94011d3 210 }
sahilmgandhi 18:6a4db94011d3 211 }
sahilmgandhi 18:6a4db94011d3 212
sahilmgandhi 18:6a4db94011d3 213 /* Clear the interrupt */
sahilmgandhi 18:6a4db94011d3 214 RTC_IRQ_CLR = 0xFFFFFFFF;
sahilmgandhi 18:6a4db94011d3 215 }
sahilmgandhi 18:6a4db94011d3 216
sahilmgandhi 18:6a4db94011d3 217 /* ----------------------------------------------------------------
sahilmgandhi 18:6a4db94011d3 218 * MBED API CALLS
sahilmgandhi 18:6a4db94011d3 219 * ----------------------------------------------------------------*/
sahilmgandhi 18:6a4db94011d3 220
sahilmgandhi 18:6a4db94011d3 221 /* This will be called once at start of day to get the RTC running */
sahilmgandhi 18:6a4db94011d3 222 void lp_ticker_init(void)
sahilmgandhi 18:6a4db94011d3 223 {
sahilmgandhi 18:6a4db94011d3 224 if (!g_initialised) {
sahilmgandhi 18:6a4db94011d3 225 /* Reset the overflow count and the flags */
sahilmgandhi 18:6a4db94011d3 226 g_overflow_count = 0;
sahilmgandhi 18:6a4db94011d3 227 g_user_interrupt_pending = false;
sahilmgandhi 18:6a4db94011d3 228 g_user_interrupt_set = false;
sahilmgandhi 18:6a4db94011d3 229
sahilmgandhi 18:6a4db94011d3 230 /* Setup the next natural 32-bit overflow value */
sahilmgandhi 18:6a4db94011d3 231 g_next_32bit_overflow_value = get_rtc_value();
sahilmgandhi 18:6a4db94011d3 232 g_last_32bit_overflow_value = g_next_32bit_overflow_value;
sahilmgandhi 18:6a4db94011d3 233 INCREMENT_MOD(g_next_32bit_overflow_value, MODULO_32BIT);
sahilmgandhi 18:6a4db94011d3 234
sahilmgandhi 18:6a4db94011d3 235 /* Clear the interrupt */
sahilmgandhi 18:6a4db94011d3 236 RTC_IRQ_CLR = 0xFFFFFFFF;
sahilmgandhi 18:6a4db94011d3 237
sahilmgandhi 18:6a4db94011d3 238 /* Interrupt at 32-bit overflow */
sahilmgandhi 18:6a4db94011d3 239 set_interrupt_to_32bit_overflow();
sahilmgandhi 18:6a4db94011d3 240
sahilmgandhi 18:6a4db94011d3 241 /* Enable the interrupt */
sahilmgandhi 18:6a4db94011d3 242 g_initialised = true;
sahilmgandhi 18:6a4db94011d3 243 NVIC_EnableIRQ(RTC_IRQn);
sahilmgandhi 18:6a4db94011d3 244 }
sahilmgandhi 18:6a4db94011d3 245 }
sahilmgandhi 18:6a4db94011d3 246
sahilmgandhi 18:6a4db94011d3 247 uint32_t lp_ticker_read(void)
sahilmgandhi 18:6a4db94011d3 248 {
sahilmgandhi 18:6a4db94011d3 249 uint64_t rtcNow;
sahilmgandhi 18:6a4db94011d3 250
sahilmgandhi 18:6a4db94011d3 251 /* Disable interrupts to avoid collisions */
sahilmgandhi 18:6a4db94011d3 252 core_util_critical_section_enter();
sahilmgandhi 18:6a4db94011d3 253
sahilmgandhi 18:6a4db94011d3 254 /* Just in case this is called before initialisation has been performed */
sahilmgandhi 18:6a4db94011d3 255 if (!g_initialised) {
sahilmgandhi 18:6a4db94011d3 256 lp_ticker_init();
sahilmgandhi 18:6a4db94011d3 257 }
sahilmgandhi 18:6a4db94011d3 258
sahilmgandhi 18:6a4db94011d3 259 /* What mbed expects here is a 32 bit timer value. There is no
sahilmgandhi 18:6a4db94011d3 260 * way to reset the RTC so, to pretend it is 32 bits, we have to
sahilmgandhi 18:6a4db94011d3 261 * maintain a 32-bit window on it using the remembered overflow
sahilmgandhi 18:6a4db94011d3 262 * value */
sahilmgandhi 18:6a4db94011d3 263 rtcNow = get_rtc_value();
sahilmgandhi 18:6a4db94011d3 264
sahilmgandhi 18:6a4db94011d3 265 /* Put interrupts back */
sahilmgandhi 18:6a4db94011d3 266 core_util_critical_section_exit();
sahilmgandhi 18:6a4db94011d3 267
sahilmgandhi 18:6a4db94011d3 268 return ticksToUSeconds(rtcNow - g_last_32bit_overflow_value);
sahilmgandhi 18:6a4db94011d3 269 }
sahilmgandhi 18:6a4db94011d3 270
sahilmgandhi 18:6a4db94011d3 271 void lp_ticker_set_interrupt(timestamp_t time)
sahilmgandhi 18:6a4db94011d3 272 {
sahilmgandhi 18:6a4db94011d3 273 uint32_t timeNow = get_rtc_value() - g_last_32bit_overflow_value;
sahilmgandhi 18:6a4db94011d3 274 uint32_t timeOffset = uSecondsToTicks(time) - timeNow;
sahilmgandhi 18:6a4db94011d3 275
sahilmgandhi 18:6a4db94011d3 276 /* Disable interrupts to avoid collisions */
sahilmgandhi 18:6a4db94011d3 277 core_util_critical_section_enter();
sahilmgandhi 18:6a4db94011d3 278
sahilmgandhi 18:6a4db94011d3 279 g_user_interrupt_pending = false;
sahilmgandhi 18:6a4db94011d3 280 g_user_interrupt_set = false;
sahilmgandhi 18:6a4db94011d3 281
sahilmgandhi 18:6a4db94011d3 282 /* Handle time slipping into the past */
sahilmgandhi 18:6a4db94011d3 283 if (timeOffset > 0xEFFFFFFF) {
sahilmgandhi 18:6a4db94011d3 284 timeOffset = 100;
sahilmgandhi 18:6a4db94011d3 285 }
sahilmgandhi 18:6a4db94011d3 286
sahilmgandhi 18:6a4db94011d3 287 /* Read the current time */
sahilmgandhi 18:6a4db94011d3 288 g_next_compare_value = get_rtc_value();
sahilmgandhi 18:6a4db94011d3 289
sahilmgandhi 18:6a4db94011d3 290 /* Add the offset */
sahilmgandhi 18:6a4db94011d3 291 INCREMENT_MOD(g_next_compare_value, timeOffset);
sahilmgandhi 18:6a4db94011d3 292
sahilmgandhi 18:6a4db94011d3 293 /* We must let the normal overflow interrupt occur as
sahilmgandhi 18:6a4db94011d3 294 * well as setting this interrupt so, if the value
sahilmgandhi 18:6a4db94011d3 295 * of 'time' would occur after the overflow point,
sahilmgandhi 18:6a4db94011d3 296 * put the change of compare-value off until afterwards. */
sahilmgandhi 18:6a4db94011d3 297 /* TODO: this needs proper testing. */
sahilmgandhi 18:6a4db94011d3 298 if (g_next_32bit_overflow_value > g_next_compare_value) {
sahilmgandhi 18:6a4db94011d3 299 /* The easy case, no overlap */
sahilmgandhi 18:6a4db94011d3 300 } else {
sahilmgandhi 18:6a4db94011d3 301 /* Could be because g_next_compare_value has wrapped (around the
sahilmgandhi 18:6a4db94011d3 302 * 48-bit limit of the RTC) */
sahilmgandhi 18:6a4db94011d3 303 if (g_next_32bit_overflow_value - g_next_compare_value >= MODULO_32BIT) {
sahilmgandhi 18:6a4db94011d3 304 /* The wrap case, we're OK */
sahilmgandhi 18:6a4db94011d3 305 } else {
sahilmgandhi 18:6a4db94011d3 306 /* There is an overlap, apply the value later */
sahilmgandhi 18:6a4db94011d3 307 g_user_interrupt_pending = true;
sahilmgandhi 18:6a4db94011d3 308
sahilmgandhi 18:6a4db94011d3 309 if (g_next_32bit_overflow_value == g_next_compare_value) {
sahilmgandhi 18:6a4db94011d3 310 /* If they are on top of each other, bump this
sahilmgandhi 18:6a4db94011d3 311 * one forward to avoid losing the interrupt */
sahilmgandhi 18:6a4db94011d3 312 INCREMENT_MOD(g_next_compare_value, 2);
sahilmgandhi 18:6a4db94011d3 313 }
sahilmgandhi 18:6a4db94011d3 314 }
sahilmgandhi 18:6a4db94011d3 315 }
sahilmgandhi 18:6a4db94011d3 316
sahilmgandhi 18:6a4db94011d3 317 if (!g_user_interrupt_pending) {
sahilmgandhi 18:6a4db94011d3 318 /* Make the change immediately */
sahilmgandhi 18:6a4db94011d3 319 set_interrupt_to_user_value();
sahilmgandhi 18:6a4db94011d3 320 }
sahilmgandhi 18:6a4db94011d3 321
sahilmgandhi 18:6a4db94011d3 322 /* Put interrupts back */
sahilmgandhi 18:6a4db94011d3 323 core_util_critical_section_exit();
sahilmgandhi 18:6a4db94011d3 324 }
sahilmgandhi 18:6a4db94011d3 325
sahilmgandhi 18:6a4db94011d3 326 void lp_ticker_disable_interrupt(void)
sahilmgandhi 18:6a4db94011d3 327 {
sahilmgandhi 18:6a4db94011d3 328 /* Can't disable interrupts as we need them to manage
sahilmgandhi 18:6a4db94011d3 329 * overflow. Instead, switch off the user part. */
sahilmgandhi 18:6a4db94011d3 330 g_user_interrupt_pending = false;
sahilmgandhi 18:6a4db94011d3 331 g_user_interrupt_set = false;
sahilmgandhi 18:6a4db94011d3 332 }
sahilmgandhi 18:6a4db94011d3 333
sahilmgandhi 18:6a4db94011d3 334 void lp_ticker_clear_interrupt(void)
sahilmgandhi 18:6a4db94011d3 335 {
sahilmgandhi 18:6a4db94011d3 336 /* Can't disable interrupts as we need them to manage
sahilmgandhi 18:6a4db94011d3 337 * overflow. Instead, switch off the user part. */
sahilmgandhi 18:6a4db94011d3 338 g_user_interrupt_pending = false;
sahilmgandhi 18:6a4db94011d3 339 g_user_interrupt_set = false;
sahilmgandhi 18:6a4db94011d3 340 }