diff chipsetsw/drivers/drv_app/kpd/board/kpd_scan_functions.c @ 0:509db1a7b7b8

initial import: leo2moko-r1
author Space Falcon <falcon@ivan.Harhan.ORG>
date Mon, 01 Jun 2015 03:24:05 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/chipsetsw/drivers/drv_app/kpd/board/kpd_scan_functions.c	Mon Jun 01 03:24:05 2015 +0000
@@ -0,0 +1,375 @@
+/**
+ * @file	kpd_scan_functions.c
+ *
+ * Implementation of hardware keypad interface functions.
+ * These functions implement the keypad interface with the windows.
+ *
+ * @author	Laurent Sollier (l-sollier@ti.com)
+ * @version 0.1
+ */
+
+/*
+ * History:
+ *
+ *	Date       	Author       Modification
+ *  ------------------------------------
+ *  10/10/2001 L Sollier    Create
+ *
+ *
+ * (C) Copyright 2001 by Texas Instruments Incorporated, All Rights Reserved
+ */
+#include "board.cfg"
+
+#include "nucleus.h" /* used for HISR */
+
+#include "kpd/kpd_scan_functions.h"
+#include "kpd/kpd_cfg.h"
+#include "kpd/kpd_physical_key_def.h"
+#include "kpd/kpd_messages_i.h"
+#include "kpd/kpd_env.h"
+
+#include "rvf/rvf_api.h"
+#include "rvm/rvm_use_id_list.h"
+#include "rvf/rvf_env.h"
+
+#if (CHIPSET == 12)
+  #include "inth/sys_inth.h"
+#else
+  #include "armio/armio.h"
+  #include "inth/iq.h"
+#endif
+
+#include "memif/mem.h"
+
+
+#if (CHIPSET == 12)
+  #define KBR_CTRL_REG              (MEM_KEYBOARD + 0x00) /* KBR control reg */
+  #define KBR_DEBOUNCING_TIME       (MEM_KEYBOARD + 0x02) /* KBR debouncing time reg */
+  #define KBR_STATE_MACHINE_STATUS  (MEM_KEYBOARD + 0x0E) /* KBR state machine status reg */
+  #define KBR_IN                    (MEM_KEYBOARD + 0x10) /* KBR inputs (rows) */
+  #define KBR_OUT                   (MEM_KEYBOARD + 0x12) /* KBR outputs (columns) */
+#endif
+
+
+#if (CHIPSET == 12)
+  #define KP_ROW_IN   KBR_IN
+  #define KP_COL_OUT  KBR_OUT
+#else
+  #define KP_ROW_IN   ARMIO_KBR_IN
+  #define KP_COL_OUT  ARMIO_KBR_OUT
+#endif
+
+
+#if (BOARD == 7)
+   #define KP_ROWS      5
+   #define KP_COLS      4
+
+   const T_KPD_PHYSICAL_KEY_ID keypad_layout[KP_ROWS][KP_COLS]=
+   {                           
+   /* Layout of B-Sample */
+   {KPD_PKEY_SOFT_LEFT,  KPD_PKEY_UP,   KPD_PKEY_DOWN, KPD_PKEY_SOFT_RIGHT},
+   {KPD_PKEY_1,          KPD_PKEY_2,    KPD_PKEY_3,    KPD_PKEY_GREEN},
+   {KPD_PKEY_4,          KPD_PKEY_5,    KPD_PKEY_6,    KPD_PKEY_NULL},
+   {KPD_PKEY_7,          KPD_PKEY_8,    KPD_PKEY_9,    KPD_PKEY_NULL},
+   {KPD_PKEY_STAR,       KPD_PKEY_0,    KPD_PKEY_DIESE,KPD_PKEY_NULL},
+   };
+#elif ((BOARD == 8) || (BOARD == 9))
+   #define KP_ROWS      5
+   #define KP_COLS      4
+   const T_KPD_PHYSICAL_KEY_ID keypad_layout[KP_ROWS][KP_COLS]=
+   {                           
+   /* Layout of C-Sample */
+   {KPD_PKEY_UP,    KPD_PKEY_GREEN,KPD_PKEY_SOFT_RIGHT,KPD_PKEY_DOWN},
+   {KPD_PKEY_1,     KPD_PKEY_2,    KPD_PKEY_3,         KPD_PKEY_SOFT_LEFT},
+   {KPD_PKEY_4,     KPD_PKEY_5,    KPD_PKEY_6,         KPD_PKEY_NULL},
+   {KPD_PKEY_7,     KPD_PKEY_8,    KPD_PKEY_9,         KPD_PKEY_NULL},
+   {KPD_PKEY_STAR,  KPD_PKEY_0,    KPD_PKEY_DIESE,     KPD_PKEY_NULL},
+   };
+#elif ((BOARD == 40) || (BOARD == 41) || (BOARD == 42) || (BOARD == 43))
+   #define KP_ROWS      5
+   #define KP_COLS      5
+   const T_KPD_PHYSICAL_KEY_ID keypad_layout[KP_ROWS][KP_COLS]=
+   {                           
+   /* Layout of D-Sample and E-Sample */
+   {KPD_PKEY_GREEN, KPD_PKEY_VOL_DOWN, KPD_PKEY_VOL_UP,KPD_PKEY_SOFT_LEFT,  KPD_PKEY_LEFT},
+   {KPD_PKEY_1,     KPD_PKEY_2,        KPD_PKEY_3,     KPD_PKEY_REC,        KPD_PKEY_RIGHT},
+   {KPD_PKEY_4,     KPD_PKEY_5,        KPD_PKEY_6,     KPD_PKEY_SOFT_RIGHT, KPD_PKEY_UP},
+   {KPD_PKEY_7,     KPD_PKEY_8,        KPD_PKEY_9,     KPD_PKEY_NULL,       KPD_PKEY_DOWN},
+   {KPD_PKEY_STAR,  KPD_PKEY_0,        KPD_PKEY_DIESE, KPD_PKEY_NULL,       KPD_PKEY_NAV_CENTER},
+   };
+#endif
+
+#define KP_ACTIVATE(i)  (~(1<<i))
+#define KP_IS_ACTIVE(rows,i)  ((rows & (1<<i)) == 0)
+#define KP_ALL_OFF  0x1F
+#define KP_ALL_ON   0
+
+extern T_KPD_ENV_CTRL_BLK* kpd_env_ctrl_blk;
+
+typedef struct {  NU_HISR  hisr;
+                  char     hisr_stack[512];
+               } T_HISR_INFOS;
+
+static T_HISR_INFOS hisr_infos = {0};
+
+
+/**
+ * @name Functions implementation
+ *
+ */
+/*@{*/
+
+
+#if (CHIPSET == 12)
+
+/**  kpd_init_ctrl_reg : Initialize the Control register
+ */
+void kpd_init_ctrl_reg(const UINT8 software_nreset, 
+                       const T_KPD_Nsoftware_mode nsoftware_mode, 
+                       const T_KPD_PTV ptv,
+                       const T_KPD_EnableDetection long_key_process_en,
+                       const T_KPD_EnableDetection time_out_empty_en,
+                       const T_KPD_EnableDetection time_out_long_key_en, 
+                       const T_KPD_EnableDetection repeat_mode_en)
+{
+  volatile UINT16 status_reg;
+  status_reg = *(volatile UINT16*) KBR_STATE_MACHINE_STATUS;
+
+  if ( (status_reg != KPD_TEST_TIMER_DEBOUNCING) && (status_reg != KPD_TEST_TIMER_LONG_KEY) &&
+       (status_reg != KPD_TEST_TIMER_TIME_OUT)   && (status_reg != KPD_TEST_TIMER_REPEAT_KEY) )
+  {
+    
+    /* The PTV can be programmed since the timer is not running */
+    
+    *(volatile UINT16*) KBR_CTRL_REG = (software_nreset |
+                                        nsoftware_mode       << 1 |
+                                        ptv                  << 2 |
+                                        long_key_process_en  << 5 |
+                                        time_out_empty_en    << 6 |
+                                        time_out_long_key_en << 7 |
+                                        repeat_mode_en       << 8);
+  }
+  else
+  {
+    
+    /* The PTV must not be programmed when the timer is running */
+
+    SetGroupBits16(*(volatile unsigned short *)(KBR_CTRL_REG), 0, 1, software_nreset);
+    SetGroupBits16(*(volatile unsigned short *)(KBR_CTRL_REG), 1, 1, nsoftware_mode);
+    SetGroupBits16(*(volatile unsigned short *)(KBR_CTRL_REG), 5, 1, long_key_process_en);
+    SetGroupBits16(*(volatile unsigned short *)(KBR_CTRL_REG), 6, 1, time_out_empty_en);
+    SetGroupBits16(*(volatile unsigned short *)(KBR_CTRL_REG), 7, 1, time_out_long_key_en);
+    SetGroupBits16(*(volatile unsigned short *)(KBR_CTRL_REG), 8, 1, repeat_mode_en);
+  }
+}
+
+
+/**  kpd_software_reset : reset software  
+ */
+void kpd_software_reset(void)
+{
+  volatile UINT16 mem_reg;
+  
+  mem_reg = (*(volatile UINT16*) KBR_CTRL_REG) & 0xFFFE;
+  *(volatile UINT16*) KBR_CTRL_REG = mem_reg;
+
+}
+
+
+/**  kpd_set_debouncing_time : Set the desired value of debouncing time
+ */
+void kpd_set_debouncing_time(const UINT8 debouncing_time)
+{
+
+   *(volatile UINT16*) KBR_DEBOUNCING_TIME = debouncing_time;
+  
+}
+
+#endif /* #if (CHIPSET == 12) */
+
+
+
+
+/**
+ * function: hisr_entry
+ */
+static void hisr_entry(void)
+{
+   T_RVF_MB_STATUS mb_status;
+   T_KPD_KEY_PRESSED_MSG* msg_key_pressed;
+   T_KPD_PHYSICAL_KEY_ID key;
+
+   /* Reserve memory for message */
+   mb_status = rvf_get_buf (kpd_env_ctrl_blk->prim_id, sizeof(T_KPD_KEY_PRESSED_MSG), (void **) &msg_key_pressed);	
+
+   if (mb_status != RVF_RED) /* Memory allocation success */
+   {
+      /* Fill the message */
+      msg_key_pressed->hdr.msg_id = KPD_KEY_PRESSED_MSG;
+      /* Virtual key id is not yet known */
+      msg_key_pressed->value = KPD_PKEY_NULL;
+      if (mb_status == RVF_GREEN)
+         msg_key_pressed->key_to_process = TRUE;
+      else
+         msg_key_pressed->key_to_process = FALSE;
+
+      /* Send message to the keypad task */
+      rvf_send_msg(kpd_env_ctrl_blk->addr_id, msg_key_pressed);
+   }
+   else
+   {
+      KPD_SEND_TRACE("KPD: Not enough memory to send new key pressed", RV_TRACE_LEVEL_ERROR);
+      kpd_acknowledge_key_pressed();
+   }
+}
+
+
+/**
+ * function: kpd_initialize_keypad_hardware
+ */
+void kpd_initialize_keypad_hardware(void)
+{
+   /* HISR creation */
+   NU_Create_HISR(&hisr_infos.hisr,
+                  "KPD_HISR",
+                  hisr_entry,
+                  2,
+                  hisr_infos.hisr_stack,
+                  sizeof(hisr_infos.hisr_stack));
+
+
+#if (CHIPSET == 12)
+  /* Init control register ; hardware decoding */
+   kpd_init_ctrl_reg(1, HARDWARE_DECODING, KPD_CLK_DIV32,
+                     KPD_DETECTION_DISABLED, KPD_DETECTION_DISABLED,
+                     KPD_DETECTION_DISABLED, KPD_DETECTION_DISABLED);
+
+   /* Debouncing time = 64ms */
+   kpd_set_debouncing_time(0x3F);
+
+#endif
+
+   /* Activate all outputs */
+   *(volatile UINT16*) KP_COL_OUT = KP_ALL_ON;
+
+   /* Unmask keypad interrupt */
+   #if ((BOARD == 8) || (BOARD == 9) || (BOARD == 40) || (BOARD == 41))
+     AI_UnmaskIT (ARMIO_MASKIT_KBD);
+   #elif (CHIPSET == 12)
+     F_INTH_ENABLE_ONE_IT(C_INTH_KEYBOARD_IT);
+   #else
+     IQ_Unmask (IQ_ARMIO);
+   #endif
+}
+
+
+
+/**
+ * function: kpd_key_handler
+ */
+void kpd_key_handler(void)
+{
+   /* If keypad is not started, return immediately */
+   if ( (kpd_env_ctrl_blk == 0) || (kpd_env_ctrl_blk->swe_is_initialized == FALSE) )
+   {
+      kpd_acknowledge_key_pressed();
+   }
+   else
+   {
+      /* Mask keypad interrupt until key is released */
+#if ((BOARD == 8) || (BOARD == 9) || (BOARD == 40) || (BOARD == 41))
+       AI_MaskIT (ARMIO_MASKIT_KBD);
+#elif (CHIPSET == 12)
+       F_INTH_DISABLE_ONE_IT(C_INTH_KEYBOARD_IT);
+#else
+       IQ_Mask(IQ_ARMIO);
+#endif
+
+      /* Activate HISR to process the key event */
+      NU_Activate_HISR(&hisr_infos.hisr);
+   }
+}
+
+/**
+ * function: kpd_acknowledge_key_pressed
+ */
+void kpd_acknowledge_key_pressed(void)
+{
+   /* Unmask keypad interrupt */
+  #if ((BOARD == 8) || (BOARD == 9) || (BOARD == 40) || (BOARD == 41))
+    AI_UnmaskIT (ARMIO_MASKIT_KBD);
+  #elif (CHIPSET == 12)
+     F_INTH_ENABLE_ONE_IT(C_INTH_KEYBOARD_IT);
+  #else
+    IQ_Unmask (IQ_ARMIO);
+  #endif
+}
+
+
+/*
+ * delay
+ *
+ * Wait a while to let bus settle
+ * Magic value found by trial and error
+ * 
+ */
+static void delay(void)
+{
+   volatile int i;
+
+   for (i=0;i<10;i++) ;
+}
+
+/**
+ * function: kpd_scan_keypad
+ */
+T_KPD_PHYSICAL_KEY_ID kpd_scan_keypad(void)
+{
+   int row, col;
+   volatile UINT16 rows;
+
+   /* Activate all columns to find if any row is active */
+   *(volatile UINT16*) KP_COL_OUT = KP_ALL_ON;
+   delay();
+
+   rows = (*(volatile UINT16*) KP_ROW_IN) & 0x1F;
+   if (rows == KP_ALL_OFF)
+      return KPD_PKEY_NULL;
+
+   /* Deactivate all columns */
+   *(volatile UINT16*) KP_COL_OUT = KP_ALL_OFF;
+
+   /* Activate 1 column at a time */
+   for (col = 0; col < KP_COLS; col++)
+   {
+      *(volatile UINT16*) KP_COL_OUT = (KP_ACTIVATE(col));
+      delay();
+
+      /* Find which row is active */
+      rows = (*(volatile UINT16*) KP_ROW_IN) & 0x1F;
+
+      if (rows != KP_ALL_OFF)
+      {
+         for (row = 0; row < KP_ROWS; row++)
+         {
+            /* first active row */
+            if ( KP_IS_ACTIVE(rows,row))
+            {
+               /* Reactivate all columns */
+               *(volatile UINT16*) KP_COL_OUT = KP_ALL_ON;
+               /* DO NOT remove this comment. It allows to simply define the link physical layout
+                  and physical key Id (for a new keypad) */
+               //KPD_SEND_TRACE_PARAM("KPD: Keypad layout check ", keypad_layout[row][col], RV_TRACE_LEVEL_DEBUG_HIGH);
+               return keypad_layout[row][col];
+            }
+         }
+      }
+   }
+
+   /* No row was active - Reactivate all columns and return */
+   *(volatile UINT16*) KP_COL_OUT = KP_ALL_ON;
+   return KPD_PKEY_NULL;
+}
+
+
+/*@}*/