fsl_kpp.c 6.8 KB

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