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 /*
sahilmgandhi 18:6a4db94011d3 2 * Copyright (c) 2012 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
sahilmgandhi 18:6a4db94011d3 40 #include "app_scheduler.h"
sahilmgandhi 18:6a4db94011d3 41 #include <stdlib.h>
sahilmgandhi 18:6a4db94011d3 42 #include <stdint.h>
sahilmgandhi 18:6a4db94011d3 43 #include <string.h>
sahilmgandhi 18:6a4db94011d3 44 #include "nrf_soc.h"
sahilmgandhi 18:6a4db94011d3 45 #include "nrf_assert.h"
sahilmgandhi 18:6a4db94011d3 46 #include "app_util.h"
sahilmgandhi 18:6a4db94011d3 47 #include "app_util_platform.h"
sahilmgandhi 18:6a4db94011d3 48
sahilmgandhi 18:6a4db94011d3 49 /**@brief Structure for holding a scheduled event header. */
sahilmgandhi 18:6a4db94011d3 50 typedef struct
sahilmgandhi 18:6a4db94011d3 51 {
sahilmgandhi 18:6a4db94011d3 52 app_sched_event_handler_t handler; /**< Pointer to event handler to receive the event. */
sahilmgandhi 18:6a4db94011d3 53 uint16_t event_data_size; /**< Size of event data. */
sahilmgandhi 18:6a4db94011d3 54 } event_header_t;
sahilmgandhi 18:6a4db94011d3 55
sahilmgandhi 18:6a4db94011d3 56 STATIC_ASSERT(sizeof(event_header_t) <= APP_SCHED_EVENT_HEADER_SIZE);
sahilmgandhi 18:6a4db94011d3 57
sahilmgandhi 18:6a4db94011d3 58 static event_header_t * m_queue_event_headers; /**< Array for holding the queue event headers. */
sahilmgandhi 18:6a4db94011d3 59 static uint8_t * m_queue_event_data; /**< Array for holding the queue event data. */
sahilmgandhi 18:6a4db94011d3 60 static volatile uint8_t m_queue_start_index; /**< Index of queue entry at the start of the queue. */
sahilmgandhi 18:6a4db94011d3 61 static volatile uint8_t m_queue_end_index; /**< Index of queue entry at the end of the queue. */
sahilmgandhi 18:6a4db94011d3 62 static uint16_t m_queue_event_size; /**< Maximum event size in queue. */
sahilmgandhi 18:6a4db94011d3 63 static uint16_t m_queue_size; /**< Number of queue entries. */
sahilmgandhi 18:6a4db94011d3 64
sahilmgandhi 18:6a4db94011d3 65 #ifdef APP_SCHEDULER_WITH_PROFILER
sahilmgandhi 18:6a4db94011d3 66 static uint16_t m_max_queue_utilization; /**< Maximum observed queue utilization. */
sahilmgandhi 18:6a4db94011d3 67 #endif
sahilmgandhi 18:6a4db94011d3 68
sahilmgandhi 18:6a4db94011d3 69 /**@brief Function for incrementing a queue index, and handle wrap-around.
sahilmgandhi 18:6a4db94011d3 70 *
sahilmgandhi 18:6a4db94011d3 71 * @param[in] index Old index.
sahilmgandhi 18:6a4db94011d3 72 *
sahilmgandhi 18:6a4db94011d3 73 * @return New (incremented) index.
sahilmgandhi 18:6a4db94011d3 74 */
sahilmgandhi 18:6a4db94011d3 75 static __INLINE uint8_t next_index(uint8_t index)
sahilmgandhi 18:6a4db94011d3 76 {
sahilmgandhi 18:6a4db94011d3 77 return (index < m_queue_size) ? (index + 1) : 0;
sahilmgandhi 18:6a4db94011d3 78 }
sahilmgandhi 18:6a4db94011d3 79
sahilmgandhi 18:6a4db94011d3 80
sahilmgandhi 18:6a4db94011d3 81 static __INLINE uint8_t app_sched_queue_full()
sahilmgandhi 18:6a4db94011d3 82 {
sahilmgandhi 18:6a4db94011d3 83 uint8_t tmp = m_queue_start_index;
sahilmgandhi 18:6a4db94011d3 84 return next_index(m_queue_end_index) == tmp;
sahilmgandhi 18:6a4db94011d3 85 }
sahilmgandhi 18:6a4db94011d3 86
sahilmgandhi 18:6a4db94011d3 87 /**@brief Macro for checking if a queue is full. */
sahilmgandhi 18:6a4db94011d3 88 #define APP_SCHED_QUEUE_FULL() app_sched_queue_full()
sahilmgandhi 18:6a4db94011d3 89
sahilmgandhi 18:6a4db94011d3 90
sahilmgandhi 18:6a4db94011d3 91 static __INLINE uint8_t app_sched_queue_empty()
sahilmgandhi 18:6a4db94011d3 92 {
sahilmgandhi 18:6a4db94011d3 93 uint8_t tmp = m_queue_start_index;
sahilmgandhi 18:6a4db94011d3 94 return m_queue_end_index == tmp;
sahilmgandhi 18:6a4db94011d3 95 }
sahilmgandhi 18:6a4db94011d3 96
sahilmgandhi 18:6a4db94011d3 97 /**@brief Macro for checking if a queue is empty. */
sahilmgandhi 18:6a4db94011d3 98 #define APP_SCHED_QUEUE_EMPTY() app_sched_queue_empty()
sahilmgandhi 18:6a4db94011d3 99
sahilmgandhi 18:6a4db94011d3 100
sahilmgandhi 18:6a4db94011d3 101 uint32_t app_sched_init(uint16_t event_size, uint16_t queue_size, void * p_event_buffer)
sahilmgandhi 18:6a4db94011d3 102 {
sahilmgandhi 18:6a4db94011d3 103 uint16_t data_start_index = (queue_size + 1) * sizeof(event_header_t);
sahilmgandhi 18:6a4db94011d3 104
sahilmgandhi 18:6a4db94011d3 105 // Check that buffer is correctly aligned
sahilmgandhi 18:6a4db94011d3 106 if (!is_word_aligned(p_event_buffer))
sahilmgandhi 18:6a4db94011d3 107 {
sahilmgandhi 18:6a4db94011d3 108 return NRF_ERROR_INVALID_PARAM;
sahilmgandhi 18:6a4db94011d3 109 }
sahilmgandhi 18:6a4db94011d3 110
sahilmgandhi 18:6a4db94011d3 111 // Initialize event scheduler
sahilmgandhi 18:6a4db94011d3 112 m_queue_event_headers = p_event_buffer;
sahilmgandhi 18:6a4db94011d3 113 m_queue_event_data = &((uint8_t *)p_event_buffer)[data_start_index];
sahilmgandhi 18:6a4db94011d3 114 m_queue_end_index = 0;
sahilmgandhi 18:6a4db94011d3 115 m_queue_start_index = 0;
sahilmgandhi 18:6a4db94011d3 116 m_queue_event_size = event_size;
sahilmgandhi 18:6a4db94011d3 117 m_queue_size = queue_size;
sahilmgandhi 18:6a4db94011d3 118
sahilmgandhi 18:6a4db94011d3 119 #ifdef APP_SCHEDULER_WITH_PROFILER
sahilmgandhi 18:6a4db94011d3 120 m_max_queue_utilization = 0;
sahilmgandhi 18:6a4db94011d3 121 #endif
sahilmgandhi 18:6a4db94011d3 122
sahilmgandhi 18:6a4db94011d3 123 return NRF_SUCCESS;
sahilmgandhi 18:6a4db94011d3 124 }
sahilmgandhi 18:6a4db94011d3 125
sahilmgandhi 18:6a4db94011d3 126
sahilmgandhi 18:6a4db94011d3 127 #ifdef APP_SCHEDULER_WITH_PROFILER
sahilmgandhi 18:6a4db94011d3 128 static void queue_utilization_check(void)
sahilmgandhi 18:6a4db94011d3 129 {
sahilmgandhi 18:6a4db94011d3 130 uint16_t start = m_queue_start_index;
sahilmgandhi 18:6a4db94011d3 131 uint16_t end = m_queue_end_index;
sahilmgandhi 18:6a4db94011d3 132 uint16_t queue_utilization = (end >= start) ? (end - start) :
sahilmgandhi 18:6a4db94011d3 133 (m_queue_size + 1 - start + end);
sahilmgandhi 18:6a4db94011d3 134
sahilmgandhi 18:6a4db94011d3 135 if (queue_utilization > m_max_queue_utilization)
sahilmgandhi 18:6a4db94011d3 136 {
sahilmgandhi 18:6a4db94011d3 137 m_max_queue_utilization = queue_utilization;
sahilmgandhi 18:6a4db94011d3 138 }
sahilmgandhi 18:6a4db94011d3 139 }
sahilmgandhi 18:6a4db94011d3 140
sahilmgandhi 18:6a4db94011d3 141 uint16_t app_sched_queue_utilization_get(void)
sahilmgandhi 18:6a4db94011d3 142 {
sahilmgandhi 18:6a4db94011d3 143 return m_max_queue_utilization;
sahilmgandhi 18:6a4db94011d3 144 }
sahilmgandhi 18:6a4db94011d3 145 #endif
sahilmgandhi 18:6a4db94011d3 146
sahilmgandhi 18:6a4db94011d3 147
sahilmgandhi 18:6a4db94011d3 148 uint32_t app_sched_event_put(void * p_event_data,
sahilmgandhi 18:6a4db94011d3 149 uint16_t event_data_size,
sahilmgandhi 18:6a4db94011d3 150 app_sched_event_handler_t handler)
sahilmgandhi 18:6a4db94011d3 151 {
sahilmgandhi 18:6a4db94011d3 152 uint32_t err_code;
sahilmgandhi 18:6a4db94011d3 153
sahilmgandhi 18:6a4db94011d3 154 if (event_data_size <= m_queue_event_size)
sahilmgandhi 18:6a4db94011d3 155 {
sahilmgandhi 18:6a4db94011d3 156 uint16_t event_index = 0xFFFF;
sahilmgandhi 18:6a4db94011d3 157
sahilmgandhi 18:6a4db94011d3 158 CRITICAL_REGION_ENTER();
sahilmgandhi 18:6a4db94011d3 159
sahilmgandhi 18:6a4db94011d3 160 if (!APP_SCHED_QUEUE_FULL())
sahilmgandhi 18:6a4db94011d3 161 {
sahilmgandhi 18:6a4db94011d3 162 event_index = m_queue_end_index;
sahilmgandhi 18:6a4db94011d3 163 m_queue_end_index = next_index(m_queue_end_index);
sahilmgandhi 18:6a4db94011d3 164
sahilmgandhi 18:6a4db94011d3 165 #ifdef APP_SCHEDULER_WITH_PROFILER
sahilmgandhi 18:6a4db94011d3 166 // This function call must be protected with critical region because
sahilmgandhi 18:6a4db94011d3 167 // it modifies 'm_max_queue_utilization'.
sahilmgandhi 18:6a4db94011d3 168 queue_utilization_check();
sahilmgandhi 18:6a4db94011d3 169 #endif
sahilmgandhi 18:6a4db94011d3 170 }
sahilmgandhi 18:6a4db94011d3 171
sahilmgandhi 18:6a4db94011d3 172 CRITICAL_REGION_EXIT();
sahilmgandhi 18:6a4db94011d3 173
sahilmgandhi 18:6a4db94011d3 174 if (event_index != 0xFFFF)
sahilmgandhi 18:6a4db94011d3 175 {
sahilmgandhi 18:6a4db94011d3 176 // NOTE: This can be done outside the critical region since the event consumer will
sahilmgandhi 18:6a4db94011d3 177 // always be called from the main loop, and will thus never interrupt this code.
sahilmgandhi 18:6a4db94011d3 178 m_queue_event_headers[event_index].handler = handler;
sahilmgandhi 18:6a4db94011d3 179 if ((p_event_data != NULL) && (event_data_size > 0))
sahilmgandhi 18:6a4db94011d3 180 {
sahilmgandhi 18:6a4db94011d3 181 memcpy(&m_queue_event_data[event_index * m_queue_event_size],
sahilmgandhi 18:6a4db94011d3 182 p_event_data,
sahilmgandhi 18:6a4db94011d3 183 event_data_size);
sahilmgandhi 18:6a4db94011d3 184 m_queue_event_headers[event_index].event_data_size = event_data_size;
sahilmgandhi 18:6a4db94011d3 185 }
sahilmgandhi 18:6a4db94011d3 186 else
sahilmgandhi 18:6a4db94011d3 187 {
sahilmgandhi 18:6a4db94011d3 188 m_queue_event_headers[event_index].event_data_size = 0;
sahilmgandhi 18:6a4db94011d3 189 }
sahilmgandhi 18:6a4db94011d3 190
sahilmgandhi 18:6a4db94011d3 191 err_code = NRF_SUCCESS;
sahilmgandhi 18:6a4db94011d3 192 }
sahilmgandhi 18:6a4db94011d3 193 else
sahilmgandhi 18:6a4db94011d3 194 {
sahilmgandhi 18:6a4db94011d3 195 err_code = NRF_ERROR_NO_MEM;
sahilmgandhi 18:6a4db94011d3 196 }
sahilmgandhi 18:6a4db94011d3 197 }
sahilmgandhi 18:6a4db94011d3 198 else
sahilmgandhi 18:6a4db94011d3 199 {
sahilmgandhi 18:6a4db94011d3 200 err_code = NRF_ERROR_INVALID_LENGTH;
sahilmgandhi 18:6a4db94011d3 201 }
sahilmgandhi 18:6a4db94011d3 202
sahilmgandhi 18:6a4db94011d3 203 return err_code;
sahilmgandhi 18:6a4db94011d3 204 }
sahilmgandhi 18:6a4db94011d3 205
sahilmgandhi 18:6a4db94011d3 206
sahilmgandhi 18:6a4db94011d3 207 /**@brief Function for reading the next event from specified event queue.
sahilmgandhi 18:6a4db94011d3 208 *
sahilmgandhi 18:6a4db94011d3 209 * @param[out] pp_event_data Pointer to pointer to event data.
sahilmgandhi 18:6a4db94011d3 210 * @param[out] p_event_data_size Pointer to size of event data.
sahilmgandhi 18:6a4db94011d3 211 * @param[out] p_event_handler Pointer to event handler function pointer.
sahilmgandhi 18:6a4db94011d3 212 *
sahilmgandhi 18:6a4db94011d3 213 * @return NRF_SUCCESS if new event, NRF_ERROR_NOT_FOUND if event queue is empty.
sahilmgandhi 18:6a4db94011d3 214 */
sahilmgandhi 18:6a4db94011d3 215 static uint32_t app_sched_event_get(void ** pp_event_data,
sahilmgandhi 18:6a4db94011d3 216 uint16_t * p_event_data_size,
sahilmgandhi 18:6a4db94011d3 217 app_sched_event_handler_t * p_event_handler)
sahilmgandhi 18:6a4db94011d3 218 {
sahilmgandhi 18:6a4db94011d3 219 uint32_t err_code = NRF_ERROR_NOT_FOUND;
sahilmgandhi 18:6a4db94011d3 220
sahilmgandhi 18:6a4db94011d3 221 if (!APP_SCHED_QUEUE_EMPTY())
sahilmgandhi 18:6a4db94011d3 222 {
sahilmgandhi 18:6a4db94011d3 223 uint16_t event_index;
sahilmgandhi 18:6a4db94011d3 224
sahilmgandhi 18:6a4db94011d3 225 // NOTE: There is no need for a critical region here, as this function will only be called
sahilmgandhi 18:6a4db94011d3 226 // from app_sched_execute() from inside the main loop, so it will never interrupt
sahilmgandhi 18:6a4db94011d3 227 // app_sched_event_put(). Also, updating of (i.e. writing to) the start index will be
sahilmgandhi 18:6a4db94011d3 228 // an atomic operation.
sahilmgandhi 18:6a4db94011d3 229 event_index = m_queue_start_index;
sahilmgandhi 18:6a4db94011d3 230 m_queue_start_index = next_index(m_queue_start_index);
sahilmgandhi 18:6a4db94011d3 231
sahilmgandhi 18:6a4db94011d3 232 *pp_event_data = &m_queue_event_data[event_index * m_queue_event_size];
sahilmgandhi 18:6a4db94011d3 233 *p_event_data_size = m_queue_event_headers[event_index].event_data_size;
sahilmgandhi 18:6a4db94011d3 234 *p_event_handler = m_queue_event_headers[event_index].handler;
sahilmgandhi 18:6a4db94011d3 235
sahilmgandhi 18:6a4db94011d3 236 err_code = NRF_SUCCESS;
sahilmgandhi 18:6a4db94011d3 237 }
sahilmgandhi 18:6a4db94011d3 238
sahilmgandhi 18:6a4db94011d3 239 return err_code;
sahilmgandhi 18:6a4db94011d3 240 }
sahilmgandhi 18:6a4db94011d3 241
sahilmgandhi 18:6a4db94011d3 242
sahilmgandhi 18:6a4db94011d3 243 void app_sched_execute(void)
sahilmgandhi 18:6a4db94011d3 244 {
sahilmgandhi 18:6a4db94011d3 245 void * p_event_data;
sahilmgandhi 18:6a4db94011d3 246 uint16_t event_data_size;
sahilmgandhi 18:6a4db94011d3 247 app_sched_event_handler_t event_handler;
sahilmgandhi 18:6a4db94011d3 248
sahilmgandhi 18:6a4db94011d3 249 // Get next event (if any), and execute handler
sahilmgandhi 18:6a4db94011d3 250 while ((app_sched_event_get(&p_event_data, &event_data_size, &event_handler) == NRF_SUCCESS))
sahilmgandhi 18:6a4db94011d3 251 {
sahilmgandhi 18:6a4db94011d3 252 event_handler(p_event_data, event_data_size);
sahilmgandhi 18:6a4db94011d3 253 }
sahilmgandhi 18:6a4db94011d3 254 }