📄 keypad.c
字号:
/*
* Copyright (C) 2001, Spectrum Digital, Inc. All Rights Reserved.
*/
#include "5509.h"
#include "util.h"
#define I2C_POT1 (I2C_ADS7823 + 2)
#define I2C_POT2 (I2C_ADS7823 + 1)
#define NUMSWITCHES 12
#define SWITCH_ERROR 0x10
#define SWITCH_OFF 0x300
#define SWITCH_NOCHANGE 0
#define SWITCH_CHANGE 1
#define AIN_KEY 1
#define AIN_JOG 0
typedef struct {
int adcval;
int keymapping;
} SWITCH_LIST_ENTRY;
SWITCH_LIST_ENTRY keylist[] = {
{0x150, 0x01}, // Switch 01
{0x0f2, 0x02}, // Switch 02
{0x17c, 0x03}, // Switch 03
{0x0bf, 0x04}, // Switch 04
{0x1b9, 0x05}, // Switch 05
{0x07b, 0x06}, // Switch 06
{0x200, 0x07}, // Switch 07
{0x03d, 0x08}, // Switch 08
{0x23a, 0x09}, // Switch 09
{0x000, 0x00}
};
SWITCH_LIST_ENTRY joglist[] = {
{0x07b, 0x0A}, // Switch 0A (Jog down)
{0x150, 0x0B}, // Switch 0B (Jog up)
{0x200, 0x0C}, // Switch 0C (Jog in)
{0x000, 0x00}
};
unsigned short keymatrix[17] = {
0x00, 0x71, 0x72, 0x73, 0x74, 0x75, 0x66, 0x60,
0x50, 0x56, 0x07, 0x27, 0x17, 0x00, 0x00, 0x00,
0x00};
unsigned char open_key[] = {0x1c, 0x22, 0x41, 0x41, 0x41, 0x22, 0x1c};
unsigned char closed_key[] = {0x1c, 0x2a, 0x5d, 0x5d, 0x5d, 0x2a, 0x1c};
unsigned char arrow[] = {0x08, 0x08, 0x3e, 0x1c, 0x08, 0x00};
unsigned char exitsymbol[] = {0x14, 0x08, 0x14};
unsigned short potbuf[16];
unsigned int switch_history[8];
int switch_accumulator, switch_pos, switch_prevkey, switch_currkey, switch_channel;
int Pot_Read(int potnum)
{
unsigned short acc, sample, *bufptr, i2caddr;
int i;
// Make sure potnum is valid
if ((potnum == 1) || (potnum == 2))
i2caddr = I2C_ADS7823 + (3 - potnum);
else
return 0xfff;
// Send command
potbuf[0] = 0; // Command byte
I2C_Write(i2caddr, 1, potbuf);
// Read 4 samples
I2C_Read(i2caddr, 8, potbuf);
// Average the 4 samples
bufptr = potbuf;
acc = 0;
for (i = 0; i < 4; i++)
{
sample = (*bufptr++ & 0xf) << 8;
sample += *bufptr++ & 0xff;
acc += sample;
}
return (acc >> 2);
}
void Pot_Init()
{
I2C_Init();
}
#if(0)
unsigned short Key_Test()
{
unsigned short keydata[16];
int pot1, pot2, pot3;
LCD_Init();
Key_Init();
while(1)
{
Key_ReadPot(1, keydata);
pot1 = (keydata[0] << 8) + keydata[1];
Key_ReadPot(2, keydata);
pot2 = (keydata[0] << 8) + keydata[1];
Key_ReadPot(3, keydata);
pot3 = (keydata[0] << 8) + keydata[1];
LCD_HexPos(0, 0, pot1);
LCD_HexPos(0, 1, pot2);
LCD_HexPos(0, 2, pot3);
SWDelayMsec(100);
}
while(1);
return 0;
}
#endif
unsigned short Pot_Test()
{
// Initialize devices for test
LCD_Init();
Pot_Init();
// Display field names
LCD_TextPos(4, 3, "POT1 =");
LCD_TextPos(4, 4, "POT2 =");
while(1)
{
LCD_HexPos(11, 3, Pot_Read(1));
LCD_HexPos(11, 4, Pot_Read(2));
}
}
int Switch_KeyMap(int adcreading, SWITCH_LIST_ENTRY *list)
{
int diff;
SWITCH_LIST_ENTRY *s;
s = list;
while (s -> keymapping != 0)
{
diff = s -> adcval - adcreading;
if (diff < 0)
diff = -diff;
if (diff <= SWITCH_ERROR)
return s -> keymapping;
s++;
}
if (adcreading < SWITCH_OFF)
return -1;
else
return 0;
}
int Switch_ReadRaw(switchno)
{
PC55XX_ADC pADC = (PC55XX_ADC)C55XX_ADC_ADDR;
// Trigger ADC conversion
WriteMask(pADC -> adcr, 0x8000 + (switchno << 12), 0xf000);
// Wait until complete
while (ReadMask(pADC -> addr, ADDR_ADCBUSY));
// Take reading
return ReadMask(pADC -> addr, ADDR_ADCDATA_MASK);
}
/*
* Switch_Sample() - Return SWITCH_CHANGE if an event such as a switch press
* or release has been detected. The currently pressed key number is
* stored in *keynum, the previous state is stored in *prevkey. The
* function samples once each time it is called until 4 samples have
* been collected. The fifth time through the samples are checked to
* see if a stable level has been reached and what the new state is.
* The calling function calls Switch_Sample until it returns
* SWITCH_CHANGE, which indicates that a switch event has occurred.
* Further calls will continue to sample the keypad but will return
* SWITCH_NOCHANGE if the switch state is the same. Analog channel
* alternates when jog and switches are both idle, stays with same
* channel until switch is released.
*/
int Switch_Sample(int *keynum, int *prevkey)
{
PC55XX_ADC pADC = (PC55XX_ADC)C55XX_ADC_ADDR;
int diff, adcval, returnval, tmpval, i;
// Accumulate 4 samples
if (switch_pos < 4)
{
// Reset accumulator with first sample
if (switch_pos == 0)
switch_accumulator = 0;
// Add ADC value to accumulator
adcval = Switch_ReadRaw(switch_channel);
switch_history[switch_pos++] = adcval;
switch_accumulator += adcval;
// Report no switch pressed
*keynum = switch_currkey;
*prevkey = switch_currkey;
return SWITCH_NOCHANGE;
}
// After the 4th sample, check for stable value
if (switch_pos == 4)
{
// Average ADC values
switch_pos = 0;
adcval = switch_accumulator >> 2;
diff = switch_history[3] - switch_history[0];
if ((diff < -8) || (diff > 8))
{
// No reading, treat as if last key still pressed
returnval = SWITCH_NOCHANGE;
} else
{
// Check key mapping
if (switch_channel == AIN_KEY)
{
switch_currkey = Switch_KeyMap(adcval, keylist);
} else
{
tmpval = Switch_KeyMap(adcval, joglist);
if (tmpval > 0)
for (i = 0; i < 1; i++);
if ((switch_currkey == 0x0a) || (switch_currkey == 0x0b))
{
if (tmpval == 0)
switch_currkey = 0;
}
else
switch_currkey = tmpval;
}
// Generate return value
*prevkey = switch_prevkey;
returnval = (switch_currkey != switch_prevkey) ? SWITCH_CHANGE : SWITCH_NOCHANGE;
switch_prevkey = switch_currkey;
}
if (switch_currkey == 0)
switch_channel = 1 - switch_channel;
// Swap channels and return
*keynum = switch_currkey;
return returnval;
}
}
unsigned short int Switch_Init()
{
PC55XX_ADC pADC = (PC55XX_ADC)C55XX_ADC_ADDR;
int adcval, i;
// Set up the conversion clocks
WriteField(pADC -> adccr, (dspclk.freq >> 2) - 1, ADCCR_SYSDIV_MASK);
WriteMask(pADC -> adcdr,
ADCDR_CONVDIV_2,
ADCDR_CONVDIV_MASK);
// Set up the sample and hold time
WriteMask(pADC -> adcdr, ADCDR_SAMPDIV_255, ADCDR_SAMPDIV_MASK);
// Set up switch history
for (i = 0; i < 8; i++)
switch_history[i] = 0;
switch_accumulator = 0;
switch_pos = 0;
switch_prevkey = 0;
switch_currkey = 0;
switch_channel = AIN_JOG;
return 0;
}
unsigned short int Switch_Debug()
{
int currreading, prevreading;
Switch_Init();
LCD_Init();
while(1)
{
// Wait for key press
while ((currreading = Switch_ReadRaw(1)) > 0x3f8)
LCD_HexPos(0, 0, currreading);
// Wait for stable input
prevreading = 0x3ff;
while ((currreading = Switch_ReadRaw(1)) != prevreading)
{
prevreading = currreading;
SWDelayUsec(1000);
}
LCD_HexPos(0, 1, currreading);
// Check key mapping
LCD_HexPos(0, 2, Switch_KeyMap(currreading, keylist));
// Wait for key release
while ((currreading = Switch_ReadRaw(1)) <= 0x3f0)
LCD_HexPos(0, 3, currreading);
}
return 0;
}
int hpos(int col)
{
return 9 + ((col << 1) << 3);
}
void Switch_Display(int keynum, unsigned char *keyimage)
{
LCD_RawPos(hpos(keymatrix[keynum] & 0xf), ((keymatrix[keynum] & 0xf0) >> 4), keyimage, 7);
}
unsigned short Switch_Test()
{
int i, iter, keynum, keyaction, prevkey, changes, pot;
// Initialize board resources
LCD_Init();
Switch_Init();
Pot_Init();
// Display keyboard
for (i = 1; i <= NUMSWITCHES; i++)
Switch_Display(i, open_key);
// Display welcome message
LCD_TextPos(0, 0, "Events");
LCD_TextPos(0, 1, "POT1 =");
LCD_TextPos(0, 2, "POT2 =");
LCD_TextPos(6, 5, "PRESS KEY");
LCD_RawPos(114, 5, exitsymbol, 3);
changes = 0;
iter = 0;
while(1)
{
// Display event counter
LCD_HexPos(7, 0, changes);
// Display pots but only sample at 1/16 freq of switches
if ((iter++ & 0x0f) == 0x00)
{
LCD_HexPos(7, 1, Pot_Read(1));
LCD_HexPos(7, 2, Pot_Read(2));
}
// Wait for key press
if (Switch_Sample(&keynum, &prevkey) == SWITCH_CHANGE)
{
if (prevkey > 0)
Switch_Display(prevkey, open_key);
if (keynum > 0)
Switch_Display(keynum, closed_key);
changes++;
}
// Exit if SW9 is pressed
if (keynum == 9)
break;
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -