adns2080.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. /**
  2. * Copyright (c) 2009 - 2020, Nordic Semiconductor ASA
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without modification,
  7. * are permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright notice, this
  10. * list of conditions and the following disclaimer.
  11. *
  12. * 2. Redistributions in binary form, except as embedded into a Nordic
  13. * Semiconductor ASA integrated circuit in a product or a software update for
  14. * such product, must reproduce the above copyright notice, this list of
  15. * conditions and the following disclaimer in the documentation and/or other
  16. * materials provided with the distribution.
  17. *
  18. * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * 4. This software, with or without modification, must only be used with a
  23. * Nordic Semiconductor ASA integrated circuit.
  24. *
  25. * 5. Any software provided in binary form under this license must not be reverse
  26. * engineered, decompiled, modified and/or disassembled.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
  29. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  30. * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
  31. * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
  32. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  33. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  34. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  37. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  38. *
  39. */
  40. #include <stdbool.h>
  41. #include <stdint.h>
  42. #include "adns2080.h"
  43. #include "sdio.h"
  44. /*lint ++flb "Enter library region" */
  45. #define ADNS2080_PRODUCT_ID (0x2AU) /*!< ADNS2080 product id */
  46. #define ADNS2080_RESET_NUMBER (0x5AU) /*!< ADNS2080 reset code */
  47. /* ADNS2080 register addresses */
  48. #define REG_PROD_ID (0x00U) /*!< Product ID. Default value : 0x2A */
  49. #define REG_REV_ID (0x01U) /*!< Revision ID. Default value : 0x00 */
  50. #define REG_MOTION_ST (0x02U) /*!< Motion Status. Default value : 0x00 */
  51. #define REG_DELTA_X (0x03U) /*!< Lower byte of Delta_X. Default value : 0x00 */
  52. #define REG_DELTA_Y (0x04U) /*!< Lower byte of Delta_Y. Default value : 0x00 */
  53. #define REG_SQUAL (0x05U) /*!< Squal Quality. Default value : 0x00 */
  54. #define REG_SHUT_HI (0x06U) /*!< Shutter Open Time (Upper 8-bit). Default value : 0x00 */
  55. #define REG_SHUT_LO (0x07U) /*!< Shutter Open Time (Lower 8-bit). Default value : 0x64 */
  56. #define REG_PIX_MAX (0x08U) /*!< Maximum Pixel Value. Default value : 0xD0 */
  57. #define REG_PIX_ACCUM (0x09U) /*!< Average Pixel Value. Default value : 0x80 */
  58. #define REG_PIX_MIN (0x0AU) /*!< Minimum Pixel Value. Default value : 0x00 */
  59. #define REG_PIX_GRAB (0x0BU) /*!< Pixel Grabber. Default value : 0x00 */
  60. #define REG_DELTA_XY_HIGH (0x0CU) /*!< Upper 4 bits of Delta X and Y displacement. Default value : 0x00 */
  61. #define REG_MOUSE_CTRL (0x0DU) /*!< Mouse Control. Default value : 0x01 */
  62. #define REG_RUN_DOWNSHIFT (0x0EU) /*!< Run to Rest1 Time. Default value : 0x08 */
  63. #define REG_REST1_PERIOD (0x0FU) /*!< Rest1 Period. Default value : 0x01 */
  64. #define REG_REST1_DOWNSHIFT (0x10U) /*!< Rest1 to Rest2 Time. Default value : 0x1f */
  65. #define REG_REST2_PERIOD (0x11U) /*!< Rest2 Period. Default value : 0x09 */
  66. #define REG_REST2_DOWNSHIFT (0x12U) /*!< Rest2 to Rest3 Time. Default value : 0x2f */
  67. #define REG_REST3_PERIOD (0x13U) /*!< Rest3 Period. Default value : 0x31 */
  68. #define REG_PERFORMANCE (0x22U) /*!< Performance. Default value : 0x00 */
  69. #define REG_RESET (0x3aU) /*!< Reset. Default value : 0x00 */
  70. #define REG_NOT_REV_ID (0x3fU) /*!< Inverted Revision ID. Default value : 0xff */
  71. #define REG_LED_CTRL (0x40U) /*!< LED Control. Default value : 0x00 */
  72. #define REG_MOTION_CTRL (0x41U) /*!< Motion Control. Default value : 0x40 */
  73. #define REG_BURST_READ_FIRST (0x42U) /*!< Burst Read Starting Register. Default value : 0x03 */
  74. #define REG_BURST_READ_LAST (0x44U) /*!< Burst Read Ending Register. Default value : 0x09 */
  75. #define REG_REST_MODE_CONFIG (0x45U) /*!< Rest Mode Confi guration. Default value : 0x00 */
  76. #define REG_MOTION_BURST (0x63U) /*!< Burst Read. Default value : 0x00 */
  77. /* ADNS2080 register bits */
  78. #define REG_MOUSE_CTRL_POWERDOWN (0x02U) /*!< Mouse control register powerdown bit */
  79. #define REG_MOTION_CTRL_MOT_A (0x80U) /*!< Motion control register polarity bit */
  80. #define REG_MOTION_CTRL_MOT_S (0x40U) /*!< Motion control register edge sensitivity bit */
  81. #define REG_MOUSE_CTRL_RES_EN (0x40U) /*!< Mouse control register resolution enable bit */
  82. #define REG_MOUSE_CTRL_BIT_REPORTING (0x80U) /*!< Mouse control register "number of motion bits" bit*/
  83. void adns2080_movement_read(int16_t * deltaX, int16_t * deltaY)
  84. {
  85. uint8_t delta_x; /*!< Stores REG_DELTA_X contents */
  86. uint8_t delta_y; /*!< Stores REG_DELTA_Y contents */
  87. uint8_t delta_xy_high; /*!< Stores REG_DELTA_XY contents which contains upper 4 bits for both delta_x and delta_y when 12 bit mode is used */
  88. uint8_t delta_x_high; /*!< Stores delta_x 4 MSB bits */
  89. uint8_t delta_y_high; /*!< Stores delta_y 4 MSB bits */
  90. uint16_t u16_deltaX; /*!< This is used to buffer the result and will be cast later to int16_t */
  91. uint16_t u16_deltaY; /*!< This is used to buffer the result and will be cast later to int16_t */
  92. delta_x = sdio_read_byte(REG_DELTA_X);
  93. delta_y = sdio_read_byte(REG_DELTA_Y);
  94. if (adns2080_motion_bits_read() == ADNS2080_MOTION_BITS_12)
  95. {
  96. // In 12 bit mode the upper 4 bits are stored in a separate register
  97. // where first 4 upper bits are for delta_x and lower 4 bits for delta_y.
  98. delta_xy_high = sdio_read_byte(REG_DELTA_XY_HIGH);
  99. delta_x_high = ((delta_xy_high & 0xF0) >> 4);
  100. delta_y_high = (delta_xy_high & 0x0F);
  101. // Check if MSB is 1. If it is, this is a negative number and we have
  102. // to fill the upper unused bits with 1s.
  103. if (delta_x_high & 0x08)
  104. {
  105. u16_deltaX = 0xF000;
  106. }
  107. else
  108. {
  109. u16_deltaX = 0x0000;
  110. }
  111. // Check if MSB is 1. If it is, this is a negative number and we have
  112. // to fill the upper unused bits with 1s.
  113. if (delta_y_high & 0x08)
  114. {
  115. u16_deltaY = 0xF000;
  116. }
  117. else
  118. {
  119. u16_deltaY = 0x0000;
  120. }
  121. u16_deltaX |= (delta_x_high << 4) | delta_x;
  122. u16_deltaY |= (delta_y_high << 4) | delta_y;
  123. }
  124. else // Only 8 bits is used for motion data
  125. {
  126. // Check if MSB is 1. If it is, this is a negative number and we have
  127. // to fill the upper unused bits with 1s.
  128. if (delta_x & 0x80)
  129. {
  130. u16_deltaX = 0xFF00;
  131. }
  132. else
  133. {
  134. u16_deltaX = 0x0000;
  135. }
  136. // Check if MSB is 1. If it is, this is a negative number and we have
  137. // to fill the upper unused bits with 1s.
  138. if (delta_y & 0x80)
  139. {
  140. u16_deltaY = 0xFF00;
  141. }
  142. else
  143. {
  144. u16_deltaY = 0x0000;
  145. }
  146. u16_deltaX |= delta_x;
  147. u16_deltaY |= delta_y;
  148. }
  149. *deltaX = (int16_t)u16_deltaX;
  150. *deltaY = (int16_t)u16_deltaY;
  151. }
  152. adns2080_motion_bits_t adns2080_motion_bits_read(void)
  153. {
  154. /* Read the most significant bit */
  155. return (adns2080_motion_bits_t)((sdio_read_byte(REG_MOUSE_CTRL) >> 7) & 0x01);
  156. }
  157. bool adns2080_is_motion_detected(void)
  158. {
  159. return ((sdio_read_byte(REG_MOTION_ST) & 0x80) != 0);
  160. }
  161. uint8_t adns2080_product_id_read(void)
  162. {
  163. return sdio_read_byte(REG_PROD_ID);
  164. }
  165. uint8_t adns2080_revision_id_read(void)
  166. {
  167. return sdio_read_byte(REG_REV_ID);
  168. }
  169. adns2080_status_t adns2080_init(void)
  170. {
  171. sdio_init();
  172. adns2080_reset();
  173. if (adns2080_product_id_read() != ADNS2080_PRODUCT_ID)
  174. {
  175. return ADNS2080_CHIP_NOT_DETECTED;
  176. }
  177. sdio_write_byte(REG_BURST_READ_FIRST, REG_DELTA_X);
  178. sdio_write_byte(REG_BURST_READ_LAST, REG_DELTA_Y);
  179. return ADNS2080_OK;
  180. }
  181. void adns2080_reset(void)
  182. {
  183. sdio_write_byte(REG_RESET, ADNS2080_RESET_NUMBER);
  184. }
  185. void adns2080_powerdown(void)
  186. {
  187. sdio_write_byte(REG_MOUSE_CTRL, REG_MOUSE_CTRL_POWERDOWN);
  188. }
  189. void adns2080_wakeup(void)
  190. {
  191. adns2080_reset();
  192. }
  193. adns2080_status_t adns2080_motion_interrupt_set(motion_output_polarity_t polarity, motion_output_sensitivity_t sensitivity)
  194. {
  195. uint8_t databyte = 0;
  196. adns2080_status_t status = ADNS2080_OK;
  197. switch (polarity)
  198. {
  199. case ADNS2080_MOTION_OUTPUT_POLARITY_LOW:
  200. databyte = 0; // Clear REG_MOTION_CTRL_MOT_A bit
  201. break;
  202. case ADNS2080_MOTION_OUTPUT_POLARITY_HIGH:
  203. databyte = REG_MOTION_CTRL_MOT_A;
  204. break;
  205. default:
  206. status = ADNS2080_INVALID_PARAMETER;
  207. break;
  208. }
  209. switch (sensitivity)
  210. {
  211. case ADNS2080_MOTION_OUTPUT_SENSITIVITY_LEVEL:
  212. databyte &= ~(REG_MOTION_CTRL_MOT_S);
  213. break;
  214. case ADNS2080_MOTION_OUTPUT_SENSITIVITY_EDGE:
  215. databyte |= (REG_MOTION_CTRL_MOT_S);
  216. break;
  217. default:
  218. status = ADNS2080_INVALID_PARAMETER;
  219. break;
  220. }
  221. if (status == ADNS2080_OK)
  222. {
  223. sdio_write_byte(REG_MOTION_CTRL, databyte);
  224. }
  225. return status;
  226. }
  227. adns2080_status_t adns2080_resolution_set(adns2080_resolution_t resolution)
  228. {
  229. uint8_t databyte = sdio_read_byte(REG_MOUSE_CTRL);
  230. adns2080_status_t status = ADNS2080_OK;
  231. // Enable resolution settings on REG_MOUSE_CTRL [4:2]
  232. databyte |= (REG_MOUSE_CTRL_RES_EN);
  233. switch (resolution)
  234. {
  235. case ADNS2080_RESOLUTION_250DPI:
  236. case ADNS2080_RESOLUTION_500DPI:
  237. case ADNS2080_RESOLUTION_1000DPI:
  238. case ADNS2080_RESOLUTION_1250DPI:
  239. case ADNS2080_RESOLUTION_1500DPI:
  240. case ADNS2080_RESOLUTION_1750DPI:
  241. case ADNS2080_RESOLUTION_2000DPI:
  242. // Clear resolution bits [4:2]
  243. databyte &= ~(0x1C); // 0b00011100;
  244. // Set resolution bits
  245. databyte |= (uint8_t)((uint8_t)resolution << 2);
  246. break;
  247. default:
  248. status = ADNS2080_INVALID_PARAMETER;
  249. break;
  250. }
  251. if (status == ADNS2080_OK)
  252. {
  253. sdio_write_byte(REG_MOUSE_CTRL, databyte);
  254. }
  255. return status;
  256. }
  257. adns2080_status_t adns2080_motion_bits_set(adns2080_motion_bits_t motion_bits)
  258. {
  259. uint8_t databyte = sdio_read_byte(REG_MOUSE_CTRL);
  260. adns2080_status_t status = ADNS2080_OK;
  261. switch (motion_bits)
  262. {
  263. case ADNS2080_MOTION_BITS_8:
  264. databyte &= ~(REG_MOUSE_CTRL_BIT_REPORTING);
  265. break;
  266. case ADNS2080_MOTION_BITS_12:
  267. databyte |= (REG_MOUSE_CTRL_BIT_REPORTING);
  268. break;
  269. default:
  270. status = ADNS2080_INVALID_PARAMETER;
  271. break;
  272. }
  273. if (status == ADNS2080_OK)
  274. {
  275. sdio_write_byte(REG_MOUSE_CTRL, databyte);
  276. }
  277. return status;
  278. }
  279. void adns2080_rest_periods_set(uint8_t rest1_period, uint8_t rest2_period, uint8_t rest3_period)
  280. {
  281. adns2080_mode_t current_mode = adns2080_force_mode_read();
  282. adns2080_force_mode_set(ADNS2080_MODE_RUN1);
  283. sdio_write_byte(REG_REST1_PERIOD, rest1_period);
  284. sdio_write_byte(REG_REST2_PERIOD, rest2_period);
  285. sdio_write_byte(REG_REST3_PERIOD, rest3_period);
  286. adns2080_force_mode_set(current_mode);
  287. }
  288. void adns2080_downshift_times_set(uint8_t run_to_rest1_mode_time, uint8_t rest1_to_rest2_mode_time, uint8_t rest2_to_rest3_mode_time)
  289. {
  290. adns2080_mode_t current_mode = adns2080_force_mode_read();
  291. adns2080_force_mode_set(ADNS2080_MODE_RUN1);
  292. sdio_write_byte(REG_RUN_DOWNSHIFT, run_to_rest1_mode_time);
  293. sdio_write_byte(REG_REST1_DOWNSHIFT, rest1_to_rest2_mode_time);
  294. sdio_write_byte(REG_REST2_DOWNSHIFT, rest2_to_rest3_mode_time);
  295. adns2080_force_mode_set(current_mode);
  296. }
  297. adns2080_mode_t adns2080_force_mode_read(void)
  298. {
  299. return (adns2080_mode_t)((sdio_read_byte(REG_PERFORMANCE) >> 4) & 0x07);
  300. }
  301. void adns2080_force_mode_set(adns2080_mode_t mode)
  302. {
  303. sdio_write_byte(REG_PERFORMANCE, (uint8_t)((uint8_t)mode << 4));
  304. }
  305. /*lint --flb "Leave library region" */