fsl_kpp.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /*
  2. * The Clear BSD License
  3. * Copyright 2017 NXP
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without modification,
  7. * are permitted (subject to the limitations in the disclaimer below) provided
  8. * that the following conditions are met:
  9. *
  10. * o Redistributions of source code must retain the above copyright notice, this list
  11. * of conditions and the following disclaimer.
  12. *
  13. * o Redistributions in binary form must reproduce the above copyright notice, this
  14. * list of conditions and the following disclaimer in the documentation and/or
  15. * other materials provided with the distribution.
  16. *
  17. * o Neither the name of the copyright holder nor the names of its
  18. * contributors may be used to endorse or promote products derived from this
  19. * software without specific prior written permission.
  20. *
  21. * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
  22. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  23. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  24. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  25. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  26. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  27. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  28. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  29. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  30. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  31. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. */
  33. #include "fsl_kpp.h"
  34. /*******************************************************************************
  35. * Definitions
  36. ******************************************************************************/
  37. /* Component ID definition, used by tools. */
  38. #ifndef FSL_COMPONENT_ID
  39. #define FSL_COMPONENT_ID "platform.drivers.kpp"
  40. #endif
  41. #define KPP_KEYPAD_SCAN_TIMES (3U)
  42. /*******************************************************************************
  43. * Prototypes
  44. ******************************************************************************/
  45. /*******************************************************************************
  46. * Variables
  47. ******************************************************************************/
  48. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  49. /*! @brief Pointers to SEMC clocks for each instance. */
  50. static const clock_ip_name_t s_kppClock[FSL_FEATURE_SOC_KPP_COUNT] = KPP_CLOCKS;
  51. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  52. /*! @brief Pointers to SEMC bases for each instance. */
  53. static KPP_Type *const s_kppBases[] = KPP_BASE_PTRS;
  54. /*! @brief Pointers to KPP IRQ number for each instance. */
  55. static const IRQn_Type s_kppIrqs[] = KPP_IRQS;
  56. /*******************************************************************************
  57. * Code
  58. ******************************************************************************/
  59. static uint32_t KPP_GetInstance(KPP_Type *base)
  60. {
  61. uint32_t instance;
  62. /* Find the instance index from base address mappings. */
  63. for (instance = 0; instance < ARRAY_SIZE(s_kppBases); instance++)
  64. {
  65. if (s_kppBases[instance] == base)
  66. {
  67. break;
  68. }
  69. }
  70. assert(instance < ARRAY_SIZE(s_kppBases));
  71. return instance;
  72. }
  73. static void KPP_Mdelay(uint64_t tickets)
  74. {
  75. while (tickets--)
  76. {
  77. __NOP();
  78. }
  79. }
  80. void KPP_Init(KPP_Type *base, kpp_config_t *configure)
  81. {
  82. assert(configure);
  83. uint32_t instance = KPP_GetInstance(base);
  84. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  85. /* Un-gate sdram controller clock. */
  86. CLOCK_EnableClock(s_kppClock[KPP_GetInstance(base)]);
  87. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  88. /* Clear all. */
  89. base->KPSR &= ~(KPP_KPSR_KRIE_MASK | KPP_KPSR_KDIE_MASK);
  90. /* Enable the keypad row and set the column strobe output to open drain. */
  91. base->KPCR = KPP_KPCR_KRE(configure->activeRow);
  92. base->KPDR = KPP_KPDR_KCD((uint8_t)~(configure->activeColumn));
  93. base->KPCR |= KPP_KPCR_KCO(configure->activeColumn);
  94. /* Set the input direction for row and output direction for column. */
  95. base->KDDR = KPP_KDDR_KCDD(configure->activeColumn) | KPP_KDDR_KRDD((uint8_t)~(configure->activeRow));
  96. /* Clear the status flag and enable the interrupt. */
  97. base->KPSR =
  98. KPP_KPSR_KPKR_MASK | KPP_KPSR_KPKD_MASK | KPP_KPSR_KDSC_MASK | configure->interrupt;
  99. if (configure->interrupt)
  100. {
  101. /* Enable at the Interrupt */
  102. EnableIRQ(s_kppIrqs[instance]);
  103. }
  104. }
  105. void KPP_Deinit(KPP_Type *base)
  106. {
  107. /* Disable interrupts and disable all rows. */
  108. base->KPSR &= ~(KPP_KPSR_KRIE_MASK | KPP_KPSR_KDIE_MASK);
  109. base->KPCR = 0;
  110. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  111. /* Disable KPP clock. */
  112. CLOCK_DisableClock(s_kppClock[KPP_GetInstance(base)]);
  113. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  114. }
  115. void KPP_keyPressScanning(KPP_Type *base, uint8_t *data, uint32_t clockSrc_Hz)
  116. {
  117. assert(data);
  118. uint16_t kppKCO = base->KPCR & KPP_KPCR_KCO_MASK;
  119. uint8_t columIndex = 0;
  120. uint8_t activeColumn = (base->KPCR & KPP_KPCR_KCO_MASK) >> KPP_KPCR_KCO_SHIFT;
  121. uint8_t times;
  122. uint8_t rowData[KPP_KEYPAD_SCAN_TIMES][KPP_KEYPAD_COLUMNNUM_MAX];
  123. bool press = false;
  124. uint8_t column;
  125. /* Initialize row data to zero. */
  126. memset(&rowData[0][0], 0, sizeof(rowData));
  127. /* Scanning. */
  128. /* Configure the column data to 1 according to column numbers. */
  129. base->KPDR = KPP_KPDR_KCD_MASK;
  130. /* Configure column to totem pole for quick discharge of keypad capacitance. */
  131. base->KPCR &= (uint16_t)(((uint16_t)~kppKCO) | KPP_KPCR_KRE_MASK);
  132. /* Recover. */
  133. base->KPCR |= kppKCO;
  134. /* Three times scanning. */
  135. for (times = 0; times < KPP_KEYPAD_SCAN_TIMES; times++)
  136. {
  137. for (columIndex = 0; columIndex < KPP_KEYPAD_COLUMNNUM_MAX; columIndex++)
  138. {
  139. column = activeColumn & (1U << columIndex);
  140. if (column)
  141. {
  142. /* Set the single column line to 0. */
  143. base->KPDR = KPP_KPDR_KCD(~(uint16_t)column);
  144. /* Take 100us delays. */
  145. KPP_Mdelay(clockSrc_Hz / 10000000);
  146. /* Read row data. */
  147. rowData[times][columIndex] = ~(base->KPDR & KPP_KPDR_KRD_MASK);
  148. }
  149. else
  150. {
  151. /* Read row data. */
  152. rowData[times][columIndex] = 0;
  153. }
  154. }
  155. }
  156. /* Return all columns to 0 in preparation for standby mode. */
  157. base->KPDR &= ~KPP_KPDR_KCD_MASK;
  158. /* Check if three time scan data is the same. */
  159. for (columIndex = 0; columIndex < KPP_KEYPAD_COLUMNNUM_MAX; columIndex++)
  160. {
  161. if ((uint8_t)(rowData[0][columIndex] & rowData[1][columIndex]) & rowData[2][columIndex])
  162. {
  163. press = true;
  164. }
  165. }
  166. if (press)
  167. {
  168. memcpy((void *)data, &rowData[0][0], sizeof(rowData[0]));
  169. }
  170. else
  171. {
  172. memset((void *)data, 0, sizeof(rowData[0]));
  173. }
  174. }