|
|
View previous topic :: View next topic |
Author |
Message |
abo_shreek11
Joined: 27 Sep 2008 Posts: 10
|
Need help with PS/2 keyboard code |
Posted: Mon Nov 24, 2008 3:57 pm |
|
|
Hi Guys
I used the above code in the following topic with some of my spices
http://www.ccsinfo.com/forum/viewtopic.php?p=107151#107151
Please read my configuration first and at the end you will find my question:
PIC in use: F184550
OSC : 20 Mhz
First, The configuration registers:
Code: |
#include <18F4550.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPROTECT //Code not protected from reading
#FUSES BROWNOUT_SW //Brownout controlled by configuration bit in special file register
#FUSES BORV43 //Brownout reset at 4.3V
#FUSES PUT //Power Up Timer
#FUSES NOCPD //No EE protection
#FUSES NOSTVREN //Stack full/underflow will not cause reset
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT //Program memory not write protected
#FUSES NOWRTD //Data EEPROM not write protected
#FUSES NOIESO //Internal External Switch Over mode disabled
#FUSES NOFCMEN //Fail-safe clock monitor disabled
#FUSES PBADEN //PORTB pins are configured as analog input channels on RESET
#FUSES NOWRTC //configuration not registers write protected
#FUSES NOWRTB //Boot block not write protected
#FUSES NOEBTR //Memory not protected from table reads
#FUSES NOEBTRB //Boot block not protected from table reads
#FUSES NOCPB //No Boot Block code protection
#FUSES MCLR //Master Clear pin enabled
#FUSES NOLPT1OSC //Timer1 configured for higher power operation
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES PLL1 //No PLL PreScaler
#FUSES CPUDIV1 //No System Clock Postscaler
#FUSES NOUSBDIV //USB clock source comes from primary oscillator
#FUSES NOVREGEN //USB voltage regulator disabled
#FUSES NOICPRT //ICPRT disabled
#use delay(clock=20000000)
|
Then, the LCD driver I used to display the key stroked on keyboard. By the way, I tested the LCD driver and connection before going into the keyboard stuff, and it is working fine, here is the code:
http://www.ccsinfo.com/forum/viewtopic.php?t=24661
Code: |
// flex_lcd.c
#define LCD_DB4 PIN_D0
#define LCD_DB5 PIN_D1
#define LCD_DB6 PIN_D2
#define LCD_DB7 PIN_D3
#define LCD_E PIN_C2
#define LCD_RS PIN_C0
#define LCD_RW PIN_C1
// If you only want a 6-pin interface to your LCD, then
// connect the R/W pin on the LCD to ground, and comment
// out the following line.
#define USE_LCD_RW 1
|
And here is my program, which have to read from keyboard and display on LCD:
Code: |
#include "D:\My Documents\PIC Projects\Keyboard Test(2) pic18 by CCS\main.h"
#include "flex_lcd.c"
//D0 - Clock
//D1 - Data
// Clock must be the interrupt pin
#define CLOCK PIN_B0
#define DATA PIN_C4
unsigned char bData[16];
unsigned char idx=0;
unsigned char tmp=0;
unsigned char readByte();
unsigned char processByte();
unsigned char waitKey();
byte keyhit();
unsigned char translate(unsigned char scancode);
volatile byte shiftSet = 0;
byte kbBuffer[16];
byte kbPos = 0;
byte kbSize = 0;
byte capsSet = 0;
volatile byte extFlag = 0;
volatile byte relFlag = 0;
volatile byte key=0;
void sendByte(byte b)
{
byte a=0;
byte p = 1;
byte t = 0;
return; // THIS IS NOT FULLY WORKING ON ALL KEYBOARDS
// SO IT IS COMMENTED OUT
// Some kind of timing issue or something. Whatever, they're just LEDs
disable_interrupts(GLOBAL);
output_low(CLOCK);
delay_us(300);
output_low(DATA);
input(CLOCK);
for(a=0; a<8; a++)
{
t = b&(1<<a);
while(input(CLOCK) == 1); //wait for 0
output_bit(DATA, t);
if(t)
p++;
while(input(CLOCK) == 0); //wait for 1
}
while(input(CLOCK) == 1); //wait for 0
output_bit(DATA, p&0x01);
while(input(CLOCK) == 0); //wait for 1
input(DATA);
while(input(DATA) == 1); //wait for 0
while(input(CLOCK) == 1); //wait for 0
delay_ms(10);
clear_interrupt(INT_EXT);
enable_interrupts(GLOBAL);
}
main()
{
int locx=1;
unsigned char k=0;
lcd_init(); // Always call this first.
//printf("READY >");
lcd_gotoxy(1,1);
lcd_putc("READY >");
output_b(0x00);
input(CLOCK);
delay_ms(100);
ext_int_edge(H_to_L);
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
while(1)
{
if (locx>16)
locx=0;
if(keyhit())
{
k = waitKey();
lcd_putc(k);
locx++;
lcd_gotoxy(locx,2);
}
}
}
byte keyhit()
{
return kbSize != 0;
}
unsigned char waitKey()
{
unsigned char k = 0;
while(kbSize == 0);
k = kbBuffer[(kbPos - kbSize)&0x0F];
kbSize--;
return k;
}
#int_ext
void kbInterrupt()
{
volatile byte k=0;
k = processByte();
if(k != 0)
{
kbBuffer[kbPos] = k;
kbPos = ++kbPos & 0x0F;
kbSize++;
}
return;
}
unsigned char readByte()
{
int i=0, t=0;
idx=0;
tmp=0;
i=0;
goto dataread;
// while(INPUT(CLOCK) != 0); // Wait for a keypress
t=0;
while(INPUT(CLOCK) != 0 && t<255) // Wait for clock, time out if needed
{
delay_us(1);
t++;
}
for(i=0; i<11; i++)
{
t=0;
while(INPUT(CLOCK) != 0 && t<255) // Wait for clock, time out if needed
{
delay_us(1);
t++;
}
dataread:
bData[idx]=INPUT(DATA);
idx++;
if(idx==9)
{
for(idx=1; idx<9; idx++)
if(bData[idx]!=0)
tmp|=(1<<(idx-1));
return tmp;
idx=0;
tmp=0;
}
// while(INPUT(CLOCK) == 0);
t=0;
while(INPUT(CLOCK) == 0 && t<255) // Wait for clock, time out if needed
{
delay_us(1);
t++;
}
}
}
static const unsigned char scantableAZ[]={
0x1C, 0x32, 0x21, 0x23, 0x24, 0x2B, 0x34, 0x33, 0x43, 0x3B, 0x42, 0x4B, 0x3A, // A-Z
0x31, 0x44, 0x4D, 0x15, 0x2D, 0x1B, 0x2C, 0x3C, 0x2A, 0x1D, 0x22, 0x35, 0x1A};
// Normal numeric scancodes, starting with ',' .
static const unsigned char scantable09n[]=
{
0x41, 0x4E, 0x49, 0x4A, // , - . /
0x45, 0x16, 0x1E, 0x26, 0x25, 0x2E, 0x36, 0x3D, 0x3E, 0x46, //Digits 0-9
0x00, 0x4C, 0x00, 0x55 // 0 ; 0 =
};
// Shift scancodes, starting at '!'
static const unsigned char scantable09s[]=
{
0x16, 0x52, 0x26, 0x25, 0x2E, 0x3D, 0x00, 0x46, 0x45, 0x3E, 0x55
};
// Normal misc. scancode map. Scancode, ASCII value
static const unsigned char scanmapn[]=
{0x54, '[', 0x5B, ']', 0x0E, '`', 0x5D, '\\', 0x52, '\''};
// Shifted misc. scancode map. Scancode, ASCII value
static const unsigned char scanmaps[]=
{0x1E, '@', 0x36, '^', 0x4E, '_', 0x54, '{', 0x5B, '}', 0x5D, '|',
0x4C, ':', 0x41, '<', 0x49, '>', 0x4A, '?', 0x0E, '~'};
// Scancode map independent of Shift
static const unsigned char scanmapx[]=
{0x29, ' ', 0x5A, '\r', 0x0D, '\t', 0x76, 27, 0x66, 0x08};
// Extended scancode map
static const unsigned char scanmape[]=
{
0x71, 0x7F
};
unsigned char translate(unsigned char scancode)
{
int i=0;
if(extFlag == 0)
{
for(i=0; i<10; i+=2)
if(scanmapx[i] == scancode)
return scanmapx[i+1];
for(i=0; i<26; i++)
if(scantableAZ[i] == scancode)
if(shiftSet ^ capsSet)
return i+65;
else
return i+65 + 32;
if(shiftSet)
{
for(i=0; i<11; i++)
if(scantable09s[i] == scancode)
return i+'!';
for(i=0; i<22; i+=2)
if(scanmaps[i] == scancode)
return scanmaps[i+1];
} else
{
for(i=0; i<18; i++)
if(scantable09n[i] == scancode)
return i+',';
for(i=0; i<10; i+=2)
if(scanmapn[i] == scancode)
return scanmapn[i+1];
}
} else // Extended keys
{
for(i=0; i<2; i+=2)
if(scanmape[i] == scancode)
return scanmape[i+1];
}
return '?';
}
unsigned char processByte()
{
unsigned char i, j;
i = readByte();
if(i == 0xF0) //A key is being released
{
relFlag = 1;
return 0;
}
if(i == 0xE0) // Extended key operation
{
extFlag = 1;
relFlag = 0; //0xE0 always first in sequence, OK to clear this
return 0;
}
if(relFlag == 0) // Pressing a key
{
if(extFlag == 0) // Non-extended key pressed
{
if(i == 0x12 || i == 0x59)
{
shiftSet = 1;
return 0;
}
if(i == 0x58)
{
sendByte(0xED);
if(capsSet == 0)
{
capsSet = 1;
sendByte(0x04);
} else
{
capsSet = 0;
sendByte(0x00);
}
return 0;
}
}
j = translate(i);
extFlag = 0;
return j;
}
if(relFlag == 1) //Releasing a key
{
relFlag = 0; //If a flag was set but not handled, we wouldn't have gotten here
extFlag = 0; //OK to clear this here
if(extFlag == 0) // Releasing a nonextended key
{
if(i == 0x12 || i == 0x59)
{
shiftSet = 0;
return 0;
}
}
// } else // Releasing an extended key
// {
// return 0;
// }
// return 0;
}
return 0;
}
|
Now to the important part. When I power up my circuit, the LCD displays the "Ready" line and the keyboard Num Lock and Caps Lock LEDs light up. 1 or 2 seconds later, the LEDs start to blink and the LCD starts to shows " : " character on the second line.
Any suggestion on what is going on ? I doubt the microcontroller inside the keyboard is not well initialized.
Please Contribute |
|
|
stevenm86
Joined: 11 Jun 2006 Posts: 11
|
|
Posted: Mon Nov 24, 2008 10:07 pm |
|
|
Wow, it certainly has been a while....
The LEDs on the keyboard blink?
They shouldn't... Are you sure the keyboard is hooked up correctly? Does it go to the right pins on your chip?
The only thing I can think of that would cause the LEDs to blink is if you were somehow sending random LED commands to the keyboard. |
|
|
abo_shreek11
Joined: 27 Sep 2008 Posts: 10
|
|
Posted: Tue Nov 25, 2008 1:50 am |
|
|
Hi Steve
I am using "mini-din 6 pins" female connector, and the only connectivty which at least turned the keyboard on is the only on which blinks the led. I have doubt that I damaged the keyboard microcontroller with one of the connection combinations I used , and I don't think I am sending a random command as the code above shows. Do you think configuring portb as analog or digital has something to do with this "interrupt pin" ? In the project configuration wizard, I chose portb to be analog input. What do you think ? |
|
|
Ttelmah Guest
|
|
Posted: Tue Nov 25, 2008 5:26 am |
|
|
First, have you got pull-up resistors on the keyboard interface lines?. These are _required_. The bus is an 'open collector' link, and once you switch to 'input' mode at the PIC, there is nothing to drive the lines 'high', unless these resistors are present.
You probably need a slightly longer pause after dropping the clock line, before switching to reading it. When you pull the clock 'low' on boot, it disables the interface to the keyboard, and it does take a moment for the keyboard to respond to this. You are normally meant ot then release the line, wait for the keyboard to respond, and write a two bytes to the command register (at address 0x64), normally 0x60, then 0x8. Unless this is done, the keyboard will be in 'inhibit' mode, and not able to send data to the host. It may be that your keyboard gives an 'error' display if this is not done.
Best Wishes |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|