00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "pic24_all.h"
00031
00038 #define C0 _RB9
00039 #define C1 _RB8
00040 #define C2 _RB7
00041 #define C3 _RB6
00042
00043 static inline void CONFIG_COLUMN() {
00044 CONFIG_RB9_AS_DIG_INPUT();
00045 ENABLE_RB9_PULLUP();
00046 CONFIG_RB8_AS_DIG_INPUT();
00047 ENABLE_RB8_PULLUP();
00048 CONFIG_RB7_AS_DIG_INPUT();
00049 ENABLE_RB7_PULLUP();
00050 CONFIG_RB6_AS_DIG_INPUT();
00051 ENABLE_RB6_PULLUP();
00052 }
00053
00054 #define R0 _LATB5
00055 #define R1 _LATB4
00056 #define R2 _LATB3
00057
00058 #define CONFIG_R0_DIG_OUTPUT() CONFIG_RB5_AS_DIG_OUTPUT()
00059 #define CONFIG_R1_DIG_OUTPUT() CONFIG_RB4_AS_DIG_OUTPUT()
00060 #define CONFIG_R2_DIG_OUTPUT() CONFIG_RB3_AS_DIG_OUTPUT()
00061
00062 void CONFIG_ROW() {
00063 CONFIG_R0_DIG_OUTPUT();
00064 CONFIG_R1_DIG_OUTPUT();
00065 CONFIG_R2_DIG_OUTPUT();
00066 }
00067
00068 static inline void DRIVE_ROW_LOW() {
00069 R0 = 0;
00070 R1 = 0;
00071 R2 = 0;
00072 }
00073
00074 static inline void DRIVE_ROW_HIGH() {
00075 R0 = 1;
00076 R1 = 1;
00077 R2 = 1;
00078 }
00079
00080 void configKeypad(void) {
00081 CONFIG_ROW();
00082 DRIVE_ROW_LOW();
00083 CONFIG_COLUMN();
00084 DELAY_US(1);
00085 }
00086
00087
00088 void setOneRowLow(uint8 u8_x) {
00089 switch (u8_x) {
00090 case 0:
00091 R0 = 0;
00092 R1 = 1;
00093 R2 = 1;
00094 break;
00095 case 1:
00096 R0 = 1;
00097 R1 = 0;
00098 R2 = 1;
00099 break;
00100 default:
00101 R0 = 1;
00102 R1 = 1;
00103 R2 = 0;
00104 break;
00105 }
00106 }
00107 #define NUM_ROWS 3
00108 #define NUM_COLS 4
00109 const uint8 au8_keyTable[NUM_ROWS][NUM_COLS] = { {'1', '4', '7', '*'},
00110 {'2', '5', '8', '0'},
00111 {'3', '6', '9', '#'}
00112 };
00113
00114 #define KEY_PRESSED() (!C0 || !C1 || !C2 || !C3) //any low
00115 #define KEY_RELEASED() (C0 && C1 && C2 && C3) //all high
00116
00117 uint8 doKeyScan(void) {
00118 uint8 u8_row, u8_col;
00119
00120 if (!C0) u8_col = 0;
00121 else if (!C1) u8_col = 1;
00122 else if (!C2) u8_col = 2;
00123 else if (!C3) u8_col = 3;
00124 else return('E');
00125
00126 for (u8_row = 0; u8_row < NUM_ROWS; u8_row++) {
00127 setOneRowLow(u8_row);
00128 if (KEY_PRESSED()) {
00129 DRIVE_ROW_LOW();
00130 return(au8_keyTable[u8_row][u8_col]);
00131 }
00132 }
00133 DRIVE_ROW_LOW();
00134 return('E');
00135 }
00136
00137
00138 typedef enum {
00139 STATE_WAIT_FOR_PRESS = 0,
00140 STATE_WAIT_FOR_PRESS2,
00141 STATE_WAIT_FOR_RELEASE,
00142 } ISRSTATE;
00143
00144 ISRSTATE e_isrState = STATE_WAIT_FOR_PRESS;
00145 volatile uint8 u8_newKey = 0;
00146
00147
00148 void _ISR _T3Interrupt (void) {
00149 switch (e_isrState) {
00150 case STATE_WAIT_FOR_PRESS:
00151 if (KEY_PRESSED() && (u8_newKey == 0)) {
00152
00153 e_isrState = STATE_WAIT_FOR_PRESS2;
00154 }
00155 break;
00156 case STATE_WAIT_FOR_PRESS2:
00157 if (KEY_PRESSED()) {
00158
00159 u8_newKey = doKeyScan();
00160 e_isrState = STATE_WAIT_FOR_RELEASE;
00161 } else e_isrState = STATE_WAIT_FOR_PRESS;
00162 break;
00163
00164 case STATE_WAIT_FOR_RELEASE:
00165
00166 if (KEY_RELEASED()) {
00167 e_isrState = STATE_WAIT_FOR_PRESS;
00168 }
00169 break;
00170 default:
00171 e_isrState = STATE_WAIT_FOR_PRESS;
00172 break;
00173 }
00174 _T3IF = 0;
00175 }
00176
00177 #define ISR_PERIOD 15 // in ms
00178
00179 void configTimer3(void) {
00180
00181 T2CONbits.T32 = 0;
00182
00183
00184 T3CON = T3_OFF | T3_IDLE_CON | T3_GATE_OFF
00185 | T3_SOURCE_INT
00186 | T3_PS_1_64 ;
00187 PR3 = msToU16Ticks (ISR_PERIOD, getTimerPrescale(T3CONbits)) - 1;
00188 TMR3 = 0;
00189 _T3IF = 0;
00190 _T3IP = 1;
00191 _T3IE = 1;
00192 T3CONbits.TON = 1;
00193 }
00194
00195 int main (void) {
00196 configBasic(HELLO_MSG);
00198 configKeypad();
00200 configTimer3();
00201 while (1) {
00202 if (u8_newKey) {
00203 outChar(u8_newKey);
00204 u8_newKey = 0;
00205 }
00206 doHeartbeat();
00207 }
00208 }