bsodmike
New Member
Wow, today has been a complete waste of my time, but let me detail it out for you.
I spent 7hrs (straight) working on the PS/2 code to have my 16F877 communicate with the mouse. I spent the first hour adding a 'breakout' board to shift from the 16F648 over to the 877, this was quite relaxing. I started holding my head and tearing my hair out somewhere at around the 4th hour, when WEE the darn thing generated a clock signal.
To my horror it was a MESSED UP signal, the frames starting block would vary in length (between 150 - 250us) randomly and only 9 pulses were coming out of the M$ mouse...so I switched to a different mouse - wee clean signal, and I could count around 11 pulses (low) between the start and end of each frame.
The biggest problem I'm having is that everything is mostly visible at around 100uS timescale, but things fly off the screen fast (and even with run/hold) not too easy to keep track of when you have Tx/Rx stuff to check.
I've literally re-coded the Tx routine and it halts in the Rx routine as the mouse doesn't seem to 'acknowledge' the Txed data.
Notes:
Using PICC-Lite v9.50PL1. The setdataclock() allows easy swapping of state of the lines. There is a 330ohm resistor on both DATA and CLK to prevent shorting the mouse *if* by mistake a '1' is outputted (should never happen). As they are in open-collector mode and PortB pull-ups are enabled to make it high, simply set as input. For low, write 0 to pin and set as output!
I also write output to the lcd now and then to let me know where in the code it is...
----------------------------------------
What you can do to help me:
A) Anyone out there that has IBM's official Tech Ref for the PS/2 protocol, wow you'd be a life saver here!
B) Once I post the code, please say anything you like, all comments/hints are needed as I'm starting to see a bright light at the end of the tunnel, oh wait it's an ultrabright LED ... (ohh boy, see I'm going crazy now )
C) Detail to me in steps (with required delays) the requirements for Tx and Rx with PS/2? I've seen all; the online sites to see about PS/2 (the Alan Chapswke, and few others...) and still not much luck I'm afraid.
--------------------------------------
Question: Would it make more sense to use interrupts on the clock like to detect each clock transition OR stick to polling such as:
while(!clock); // wait for high
while(clock); // wait for low
---do stuff
??
--------------------------------------
Thanks guys, your help will mean that I won't decide to kill my self buy hanging my self with an oscillator probe (haha..ok I'm kidding but who knows )
A very tired and depressed,
--Mike
I spent 7hrs (straight) working on the PS/2 code to have my 16F877 communicate with the mouse. I spent the first hour adding a 'breakout' board to shift from the 16F648 over to the 877, this was quite relaxing. I started holding my head and tearing my hair out somewhere at around the 4th hour, when WEE the darn thing generated a clock signal.
To my horror it was a MESSED UP signal, the frames starting block would vary in length (between 150 - 250us) randomly and only 9 pulses were coming out of the M$ mouse...so I switched to a different mouse - wee clean signal, and I could count around 11 pulses (low) between the start and end of each frame.
The biggest problem I'm having is that everything is mostly visible at around 100uS timescale, but things fly off the screen fast (and even with run/hold) not too easy to keep track of when you have Tx/Rx stuff to check.
I've literally re-coded the Tx routine and it halts in the Rx routine as the mouse doesn't seem to 'acknowledge' the Txed data.
Code:
/*------------------ Function Prototypes -----------------*/
extern short int calcparity(char parcel);
extern void ps2_transmit(char packet);
extern int ps2_receive(void);
extern char ps2_init(void);
extern void setdataclock(int datastate, int clockstate);
extern short int ps2_receive_packet(void);
/*--------------------------------------------------------*/
/*---------------------- Definitions ---------------------*/
//#define settlingdelay 7 // Arbitrary guess
#define bitset(var,bitno) ((var) |= (1 << (bitno))) // C alternative to bsf
#define bitclr(var,bitno) ((var) &= ~(1 << (bitno))) // C alternative to bcf
#define bittst(var,bitno) (var & (1 << (bitno))) // C alternative to btfss/btfsc
/*--------------------------------------------------------*/
/*-------------- Global Veriable Declaration -------------*/
char ps2_data_in;
int packet3[3];
/*--------------------------------------------------------*/
/*-------------- Mouse I/O Pin Assignments ---------------*/
static bit CLK @ ((unsigned)&PORTB*8+0); // Connected to pin 5 of PS/2 mouse
static bit DATA @ ((unsigned)&PORTB*8+4); // Connected to pin 1 of PS/2 mouse
/*--------------------------------------------------------*/
void setdataclock(int datastate, int clockstate)
{
//RB0-CLK, RB4-DATA
if(datastate)
bitset(TRISB,4);//set TRIS register bit associated with data line to input
else
{
DATA=0;
bitclr(TRISB,4);//set TRIS register bit associated wtih data line to output
}
if(clockstate)
bitset(TRISB,0);//set TRIS register bit associated with clock line to input
else
{
CLK=0;
bitclr(TRISB,0);//set TRIS register bit associated wtih clock line to output
}
}
short int calcparity(char parcel)
{
short int i;
short int parity = 1;
for (i=0;i<7;++i)
{
if (bittst(parcel,i) == 1)parity = parity^1;
}
return parity;
}
void ps2_transmit(char packet)
{
short int parity, i;
snd_cls();snd_string("Inside ps2_Tx");
Delay(2);
ps2_data_in=0;
// TRISD = 0x00;
// PORTD = 0x00;
do
{
parity = calcparity(packet);
setdataclock(1,0); //pull clock low
DelayMs_100(3); //must be greater than 100ms
setdataclock(0,0); //pull data low
DelayMs_100(3);
setdataclock(0,1); //release clock - device will start generating clock
while(!CLK); //wait for rising edge
while(CLK); //wait for falling edge
setdataclock(0,1);
//while(1){snd_cls;snd_string("Code halted.");}
for (i=0;i<7;++i)
{
while(!CLK); //wait for rising edge
while(CLK); //wait for falling edge
if (bittst(packet,i)){setdataclock(1,1);}else{setdataclock(0,1);}
}
//while(1){snd_cls;snd_string("Code halted.");}
while(!CLK){}
while(CLK){}
if (parity){setdataclock(1,1);}else{setdataclock(0,1);}
while(!CLK){}
while(CLK){}
setdataclock(1,1); //set stop bit and release Data line
while(CLK || DATA){} //wait for device to pull clock & data low (ACK)
while((!CLK) || (!DATA)){} //wait for device to release clock & data
snd_cls;snd_string("ACK OK!");
while(!ps2_receive()){} //wait for acknowledge byte from mouse
//hextoascii(ps2_data_in); << Fix! This is for BoostC!
/*
todo: bitwise hex to ascii conversion...
*/
}while(ps2_data_in!=0xFA);
snd_cls();
snd_string("Tx OK!");
Delay(2);
}
int ps2_receive(void)
{
int i;
char packet;
snd_cls();snd_string("Inside ps2_Rx");
packet=0;
setdataclock(1,0); //pull clock line low to inhibit communication
DelayMs_100(3); //must be greater than 100ms
setdataclock(1,1); //release clock line, data line ready for input
while((CLK)||(DATA)); //wait for data AND clock to be low
snd_cls();snd_string("after while");
for (i=0;i<7; ++i)
{
while(!CLK){} //wait for clock high
while(CLK){} //wait for clock low (falling edge);
if (DATA){bitset(packet,0);}else{bitclr(packet,0);}
}
while(!CLK){}
while(CLK){}//We do not perform a parity check on the data!
while(!CLK){}
while(CLK){} //wait for last 2 clock pulses (parity and stop)
snd_cls();
snd_string("Rx OK!");
setdataclock(1,0); //pull clock line low to inhibit communication
ps2_data_in=packet;
return 1;
}
short int ps2_receive_packet(void)
{
int a;
packet3[0]=0;
packet3[1]=0;
packet3[2]=0;
for(a=0; a<10; a++) //try 5 times to receive 1st data byte
{
if(ps2_receive())
break;
if(a==9)
return 0;
}
packet3[0]=ps2_data_in;
if(!ps2_receive())
return 0;
packet3[1]=ps2_data_in;
if(!ps2_receive())
return 0;
packet3[2]=ps2_data_in;
return 1;
}
//function returns 0 if mouse initializes properly
//returns 1 if mouse error (0xFC) is received
//returns 2 if other code received
char ps2_init(void)
{
char temp;
setdataclock(1,1);
snd_cls();
snd_string("Inside ps2_int()");
Delay(2);
ps2_transmit(0xFF); //reset command
while(!ps2_receive()){} //mouse init results
temp=ps2_data_in;
while(!ps2_receive()){} //mouse ID
if(temp==0xAA) //0xAA = mouse initialized OK (self test)
{
snd_cls();
snd_string("0xAA Received OK");
Delay(2);
ps2_transmit(0xF3);
ps2_transmit(10);
ps2_transmit(0xF4);//enable data reporting, begin operation
}
else if(temp==0xFC) //0xFC = mouse had init error
{
snd_cls();
snd_string("0xFC Init Error!");
Delay(2);
return 1;
}else
{
snd_cls();
snd_string("Unknown Error!");
Delay(2);
return 2; //code other than 0xAA or 0xFC returned by mouse
}
return 0;
}
Notes:
Using PICC-Lite v9.50PL1. The setdataclock() allows easy swapping of state of the lines. There is a 330ohm resistor on both DATA and CLK to prevent shorting the mouse *if* by mistake a '1' is outputted (should never happen). As they are in open-collector mode and PortB pull-ups are enabled to make it high, simply set as input. For low, write 0 to pin and set as output!
I also write output to the lcd now and then to let me know where in the code it is...
----------------------------------------
What you can do to help me:
A) Anyone out there that has IBM's official Tech Ref for the PS/2 protocol, wow you'd be a life saver here!
B) Once I post the code, please say anything you like, all comments/hints are needed as I'm starting to see a bright light at the end of the tunnel, oh wait it's an ultrabright LED ... (ohh boy, see I'm going crazy now )
C) Detail to me in steps (with required delays) the requirements for Tx and Rx with PS/2? I've seen all; the online sites to see about PS/2 (the Alan Chapswke, and few others...) and still not much luck I'm afraid.
--------------------------------------
Question: Would it make more sense to use interrupts on the clock like to detect each clock transition OR stick to polling such as:
while(!clock); // wait for high
while(clock); // wait for low
---do stuff
??
--------------------------------------
Thanks guys, your help will mean that I won't decide to kill my self buy hanging my self with an oscillator probe (haha..ok I'm kidding but who knows )
A very tired and depressed,
--Mike