Forum Menu




 


Log in Problems?
New User? Sign Up!
AVR Freaks Forum Index

Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Author Message
snickersnee
PostPosted: Feb 08, 2011 - 05:37 PM
Wannabe


Joined: Nov 07, 2010
Posts: 52


The attached Codevision code is for an Atmega32a-based accelerometer mouse that interfaces to the computer via PS/2 protocol. (Notice this is not PlayStation2, it's this: http://www.computer-engineering.org/ps2protocol/)
I have been able to show that the ADC portion works, which is dataFromMouse(), however I'm still not getting any mouse movement. All the outputs of the uC remain at +5V (idle state) all the time.
I honestly don't have a clue where to start debugging this huge program, other than putting LED lighting commands in strategic places. If anyone has any prior experience with this, I would greatly appreciate any suggestions on how to approach this.
Thanks in advance.

I've attached the file with the code, as well as the schematic.
Some differences in my setup:
* Instead of a crystal, I'm using int.RC 8 MHz.
* Not using the buffers.
* AREF has a 100nF capacitor to GND

Also I should mention I don't have an LCD, though there's code for it.
I got a PS/2 cable from an old mouse and am using it to go directly from the uC to the computer. (I don't think the cable is the problem, I made sure the mouse worked before I cannibalized it.) I was able to match the wires to the pins. No converter should be needed in this case. This is an HID device and the Windows built-in driver is supposed to recognize it.
When I google, all I get is PlayStation2, unfortunately that's not what I'm looking for. Confused

(As an aside, when I click on the Msg Icon or Smiles buttons under the quick reply box, I get a window that says "Hacking attempt1".)
 
 View user's profile Send private message  
Reply with quote Back to top
snickersnee
PostPosted: Feb 09, 2011 - 01:56 AM
Wannabe


Joined: Nov 07, 2010
Posts: 52


Here is my understanding of what this code is supposed to do. Rather than regular PS/2, which has 3-byte packets, this uC is emulating a Microsoft Intellimouse, with 4-byte packets. Packet is shown here:
http://www.microsoft.com/whdc/archive/mcompat.mspx#ECF

A PS/2 byte has 11 bits:
0 - - - - - - - - 1
start,(8 bits of data, LSB first),stop

Rx/Tx: 4 states

(1) Idle: outputs float high
(This is where I'm stuck at, all the time)
*Mouse has something to send? Go to (2)

(2) Busy: -set flags (Rx or Tx)
-Host inhibit: pull clk low for >100 us
(clk period=80us, that is, 12.5 kHz)
* Mouse checks for this condition by seeing if clk. output is high but reading low. If true, go to (3)

(3) Inhibit: -Stop all xmit
-clk,data=1
-(If byte interrupted, resend later)
*Host request to send (pull data line low after inhibit; this tells the mouse to start the clock (high first)). Go to (4)

(4) Request: -will go back to Busy in 1 clock cycle
-Clock low: host send PS/2 byte (11 bits)
-High: mouse send ACK (0xFA) after stop bit
-Low: Host reads ACK

* State changes are caused by timer 1 interrupt.
 
 View user's profile Send private message  
Reply with quote Back to top
kk6gm
PostPosted: Feb 09, 2011 - 03:34 AM
Raving lunatic


Joined: Sep 12, 2009
Posts: 2674
Location: Sacramento, CA

As a general approach, I'd write the simplest code possible to output some fixed mouse movement (e.g. up and to the left, repeat). Get that working before moving on to anything else.
 
 View user's profile Send private message  
Reply with quote Back to top
indianajones11
PostPosted: Feb 09, 2011 - 04:09 AM
Raving lunatic


Joined: Nov 28, 2004
Posts: 3896
Location: San Diego, Ca

snickersnee where'd you get the code / circuit from ( No access to explanation of the design ? ) ? You're trying to build a PS/2 mouse from the ground up ? HOW do you KNOW this design even works ?

Like I said in your previous topic, you can't debug if you don't understand it. So ask yourself how much of this code you get,and verify it works up to there. Understand it step by step. I'd get the usart code to work so you can confirm correct PS/2 codes are generated before hooking up to PS/2 port.

There's a PS/2 KEYBOARD effort in pjt. forum. Atmel has app. notes on this.

May help:
http://instruct1.cit.cornell.edu/course ... index.html

_________________
1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1
 
 View user's profile Send private message  
Reply with quote Back to top
snickersnee
PostPosted: Feb 09, 2011 - 03:14 PM
Wannabe


Joined: Nov 07, 2010
Posts: 52


Quote:
I'd get the usart code to work


There's usart code in it? I didn't see that

Let me find where I got the code from, hold on.

The hardware design is an open-collector interface as discussed in the link in my first post. However, this version is simplified; instead of transistors, it uses 600 ohm resistors.
 
 View user's profile Send private message  
Reply with quote Back to top
snickersnee
PostPosted: Feb 09, 2011 - 04:52 PM
Wannabe


Joined: Nov 07, 2010
Posts: 52


Here's the page where the code/circuit are from:


http://courses.cit.cornell.edu/ee476/FinalProjects/s2004/cel27/ece476web2/index.html
 
 View user's profile Send private message  
Reply with quote Back to top
MurMan
PostPosted: Feb 09, 2011 - 05:23 PM
Hangaround


Joined: Jan 14, 2011
Posts: 156


snickersnee wrote:
There's usart code in it? I didn't see that.
The usart is implemented in code. (Hardware usart isn't used.)

Look at the ISR clockGenNrecvNtrans(void) and you'll see the data clocked out on DATA_OUT, defined as PORTD.6.

Take the advice from IndianaJones. You really need to understand how this code works in order to debug it.

Your idea of using spare pins to give debug info is good, but you'll need to manage the flash duration if you want to see the LED flash. If you have a logic probe with pulse detection, you could turn a pin on then off immediately without regard for duration.
 
 View user's profile Send private message  
Reply with quote Back to top
indianajones11
PostPosted: Feb 09, 2011 - 06:07 PM
Raving lunatic


Joined: Nov 28, 2004
Posts: 3896
Location: San Diego, Ca

Sorry about the uart ref. ( ok it's code to emulate the PS/2's DATA / CLK ), then use the lcd to verify vars.

_________________
1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1
 
 View user's profile Send private message  
Reply with quote Back to top
Lennart
PostPosted: Feb 09, 2011 - 06:40 PM
Raving lunatic


Joined: Oct 29, 2006
Posts: 2758
Location: Sweden

Having a scope to reveal what's happening on the data and clock lines would help.
If you don't have one this might be an easy way to get a good enough one for your needs.
http://www.zeitnitz.de/Christian/scope_en
 
 View user's profile Send private message  
Reply with quote Back to top
snickersnee
PostPosted: Feb 09, 2011 - 07:24 PM
Wannabe


Joined: Nov 07, 2010
Posts: 52


Port D.1 (output clock) is also the TXD pin for the USART, but I don't see any USART initialization such as UBRR, UCSRB, etc. That's why I'm confused that you guys keep talking about USART.


Quote:
use the lcd to verify vars


I noticed the lcd code commented out...Ordered one, don't have it yet.
 
 View user's profile Send private message  
Reply with quote Back to top
Jepael
PostPosted: Feb 09, 2011 - 08:22 PM
Raving lunatic


Joined: May 24, 2004
Posts: 6279
Location: Tampere, Finland

Are you sure you got the data transfer directions right? When you describe your state machine, it looks like what the HOST does, not the MOUSE. A bit. It is confusing.

Okay, first of all, the mouse should report only standard 3-byte packets, unless the HOST sends the mouse the correct magic sequence which the mouse recognises and switches to the extended 4-byte protocol.

But even before that, mouse should be in a mode it will not transmit movement packets, unless it receives a command that allows it to enable movement packet transmissions.

Nevertheless, 3 or 4 byte responses from mouse, bytes are sent alike.

1) if both lines are high, mouse can start transmission if there is something to send. Mouse is always the device that drives the clock pulses to transmit bits, no matter which direction the bits are transmitted.

2) if HOST pulls clock low, then, mouse is not able to start transmission until HOST lets clock high again. This is the inhibit state.

3) if HOST pulls data low, it is a sign of request and then mouse must start clocking data out from the host.

Now there is a catch, the HOST may just do a request by setting data pin low without inhibit, or, it may first set clock low to inhibit mouse, then set data low, and release clock, so the mouse sees request when coming out of inhibit mode.

And also I honestly don't understand why put 600 ohm resistors there. It will work without any series resistors, or to be safe, something max 100 ohms should be put there. Pulling the clock/data lines through 600 ohms may not be strong enough to pull the voltage to sane logic low level of about 0.6V.

Speaking of logic levels, what kind of pull-ups you have on the clock/data lines (if any?). If you have something between 2k and 15k you should be fine.

Are you sure you drive the clock and data pins in open-collector mode, not push-pull mode? You are never ever allowed to set the pins as high outputs, only inputs or low outputs.
 
 View user's profile Send private message  
Reply with quote Back to top
indianajones11
PostPosted: Feb 09, 2011 - 09:21 PM
Raving lunatic


Joined: Nov 28, 2004
Posts: 3896
Location: San Diego, Ca

OP wrote:
That's why I'm confused that you guys keep talking about USART.
NO USART code after all, see my previous post.

_________________
1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1
 
 View user's profile Send private message  
Reply with quote Back to top
snickersnee
PostPosted: Feb 09, 2011 - 09:53 PM
Wannabe


Joined: Nov 07, 2010
Posts: 52


Lennart wrote:
Having a scope to reveal what's happening on the data and clock lines would help.


I have pictures and video from the scope which I will upload ASAP, as soon as I can get a hold of my card reader. Basically, Data remains high except a downward spike to 0 that I don't understand (screen looks the same all the time), and Clock is mostly high but actually goes low in a square wave once in a while, which is nice.

----
Update: See later post for picture and video in zip file.



Quote:
Speaking of logic levels, what kind of pull-ups you have on the clock/data lines (if any?). If you have something between 2k and 15k you should be fine.

Are you sure you drive the clock and data pins in open-collector mode, not push-pull mode? You are never ever allowed to set the pins as high outputs, only inputs or low outputs.


I have 10K pullups. (Yay, I did something right) It's supposed to be open-collector, but let me look up push-pull mode and get back to you.


Last edited by snickersnee on Feb 10, 2011 - 02:28 AM; edited 2 times in total
 
 View user's profile Send private message  
Reply with quote Back to top
snickersnee
PostPosted: Feb 09, 2011 - 10:01 PM
Wannabe


Joined: Nov 07, 2010
Posts: 52


Jepael wrote:


Okay, first of all, the mouse should report only standard 3-byte packets, unless the HOST sends the mouse the correct magic sequence which the mouse recognises and switches to the extended 4-byte protocol.



I think the code does have the mouse recognizing the sequence from the host. See below:
(this code is in the processCommand function)

Code:

    if(settingSampleRateFlag) {
        settingSampleRateFlag = 0;


        if(hostCommand >= 10 && hostCommand <= 200) {
            lastlastSampleRate = lastSampleRate;
            lastSampleRate = sampleRate;
            sampleRate = hostCommand;
            if((lastlastSampleRate == 200) && (lastSampleRate == 100) && (sampleRate == 80)) {
                deviceID = 0x03; // enter MS intellimouse mode
            }
            if(deviceID == 0x03 && lastlastSampleRate == 200 && lastSampleRate == 200 && sampleRate == 80) {
                deviceID = 0x03; // enter MS 5-button mouse mode
            }
        } else { // bad sample rate, output an error
            queuePut(ERROR);


Quote:
And also I honestly don't understand why put 600 ohm resistors there. It will work without any series resistors


This is fine with me, the simpler the better. I'll try a low resistor as well as nothing, but then again why would anyone bother with transistors (the classic open-collector interface), or resistors if they weren't needed?

Anyway thanks for the help.
 
 View user's profile Send private message  
Reply with quote Back to top
indianajones11
PostPosted: Feb 09, 2011 - 10:14 PM
Raving lunatic


Joined: Nov 28, 2004
Posts: 3896
Location: San Diego, Ca

snickersnee wrote:
I'll try a low resistor as well as nothing, but then again why would anyone bother with transistors (the classic open-collector interface), or resistors if they weren't needed?
You better double check with the PS/2 "spec." that you might not need anything on those MCU pins.

_________________
1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1
 
 View user's profile Send private message  
Reply with quote Back to top
snickersnee
PostPosted: Feb 09, 2011 - 10:35 PM
Wannabe


Joined: Nov 07, 2010
Posts: 52


Here is the function implementing the four PS/2 states as described previously. In all of them, the uC is monitoring the mouse clock state as well as CLK_IN from the host.
Code:

void clockStateNow(void)
{
    switch (myState)
    { 
    case BUSY:
        //if the clock being hold low when the clock should've been high.
        //Transition to inhibit state
        if ((clockState == HIGH || clockState == RISING) && CLK_IN == 0)
        {         
            inhibited = TRUE;
            myState = INHIBIT;
            clockState = LOW;
            transmitting = 0;
            receiving = 0;   
            count2 = 0;
        }
        else if ( !(transmitting || receiving) ) //if not doing anything, then we go back to idle
            myState = IDLE;
        else myState = BUSY;
        break;
   
    case IDLE:
        //if the clock being hold low when the clock should've been high.
        //Transition to inhibit state
        if ((clockState == HIGH || clockState == RISING) && CLK_IN == 0)
        {   
            inhibited = TRUE;
            myState = INHIBIT;
            clockState = LOW;
            transmitting = 0;
            receiving = 0; 
            count2 = 0;
        }   
        //if there is data in the queue waiting to be sent
        //transition to BUSY state
        else if(queueEmpty == FALSE)
        {
            myState = BUSY;
            transmitting=1;
            nextClockState=RISING;
            position = 0;
        }
        else
        {
            myState = IDLE;
        }
        break;

    case INHIBIT:   
        //if the computer inhibit before we finishing sending the byte
        //we need to resend the byte
        if(position != 0 && position < 10)
        {
            resendFlag = TRUE;
        }
        position = 0;

        //right after the clock get out of inhibit state
        //we need to check if the computer have hold down the data.
        //If the computer pulls low the data line, then the mouse goes into
        //REQUEST state.
        if (outInhibit == TRUE)
        {
            if(DATA_IN == 0)
            {
                //The computer is request to send some data to the mouse
                myState = REQUEST;
                clockState = RISING;
            }
            else
            {
                //If the data line wasn't low.
                //then the computer must have put the mouse into inhibit
                //for processing data.
                myState = IDLE;
                clockState = RISING;               
            }
            outInhibit = FALSE;
        }
        //if the clock high, meaning the computer has released clock line
        if(CLK_IN == 1)
        {
            outInhibit = TRUE;
        }
        else
        {     
            inhibited = TRUE;
            myState = INHIBIT;
            transmitting = 0;
            clockState = LOW;
            receiving = 0;
            outInhibit = FALSE;
        }
        break;

    case REQUEST: 
        position = 0;
        receiving = 1;
        nextClockState = FALLING;

        //if the clock being hold low when the clock should've been high.
        //Transition to inhibit state
        if ((clockState == HIGH || clockState == RISING) && CLK_IN == 0)           
        {       
            inhibited = TRUE;
            myState = INHIBIT;
            clockState = LOW;
            transmitting = 0;
            receiving = 0;
            count2 = 0;
        }
        else if ( transmitting || receiving)
            myState = BUSY;
        else
            myState = REQUEST;
        break; 

    }//end switch

}


Also, a correction to what I said above:
(I was missing the parity bit)
Quote:
A PS/2 byte has 11 bits:
0 - - - - - - - - - 1
start,(8 bits of data, LSB first),odd parity bit, stop

(Odd parity bit=1 when # of 1's is even)


Last edited by snickersnee on Feb 10, 2011 - 02:13 AM; edited 1 time in total
 
 View user's profile Send private message  
Reply with quote Back to top
snickersnee
PostPosted: Feb 09, 2011 - 10:59 PM
Wannabe


Joined: Nov 07, 2010
Posts: 52


indianajones11 wrote:
You better double check with the PS/2 "spec." that you might not need anything on those MCU pins.


The PS/2 "spec" has transistors (see diagram below), I presume that's why it's called an "open-collector interface," but no one actually uses transistors. This project uses 600 ohm resistors instead of transistors, I've seen another similar one that uses 300 ohm resistors, but jepael is telling me both are too high, it should be 100 ohms max, or nothing.

 
 View user's profile Send private message  
Reply with quote Back to top
snickersnee
PostPosted: Feb 10, 2011 - 02:25 AM
Wannabe


Joined: Nov 07, 2010
Posts: 52


Here are the scope pictures I mentioned.
(well, it's a picture and two movies)

In the attachment (scope.zip):
IMG_6103.jpg is output of the data line
MVI_6104.avi is the clock line

(Separate attachment, MVI_6101.zip):
MVI_6101.avi is output of one of the blinking LEDs on Port B (these were to test the ADC)

----
Update to this: I'm now using a better probe, and in all these configurations all 4 output pins stay on +5V all the time. I could attach those pictures, but I think you can imagine how it looks. I previously described the clock line going down once in a while, however I'm not seeing that now and I have a better probe now. It's all just flat +5V. I think what I was seeing before was due to a lousy probe.


Last edited by snickersnee on Feb 11, 2011 - 12:43 AM; edited 1 time in total
 
 View user's profile Send private message  
Reply with quote Back to top
Jepael
PostPosted: Feb 10, 2011 - 08:52 AM
Raving lunatic


Joined: May 24, 2004
Posts: 6279
Location: Tampere, Finland

snickersnee wrote:

This is fine with me, the simpler the better. I'll try a low resistor as well as nothing, but then again why would anyone bother with transistors (the classic open-collector interface), or resistors if they weren't needed?


Different chips have different kind of outputs and different driving capability. If the microcontroller only has push-pull outputs, you must put something there to make it compatible with open-collector. Same applies even if microcontroller supports open-collector directly, but if the internal transistor is too weak.

The external components may also protect the controller from destructive voltage spikes etc.

So 20 years ago microcontrollers were different and thus some external components were needed. Nowadays you can get keyboard encoder chips with everything built-in so direct connection is enough.

Edit: the website that has the picture you posted is almost 10 years old, and it says the picture is an example of the interface, and it also says you can use a single pin on a PIC microcontroller instead.
 
 View user's profile Send private message  
Reply with quote Back to top
snickersnee
PostPosted: Feb 10, 2011 - 04:33 PM
Wannabe


Joined: Nov 07, 2010
Posts: 52


Thanks for the explanation.
Quote:
it also says you can use a single pin on a PIC microcontroller instead

Not sure if it matters, but I'm using AVR. And it shouldn't matter that I'm using Atmega32a and the project calls for Atmega32, right? There are plenty of pins, I might as well use different ones for input and output so I won't have to keep changing DDR. Here is the schematic:



(It shows up too small here, it's also in the attachment.)

Another thing I've thought about is in theory I should be able to power the circuit with the computer, from the +5V pin of the PS/2 cable. However, I rarely get the full voltage from this wire; it's usually more like 2V or 4V or something. This is probably just a consequence of the computer not recognizing the setup as a mouse, but I just thought I'd mention it.

----
Things to try:
-Play with resistor values.
-When compiling it under an older version of Codevision, a lot fewer warnings show up. So I'll try loading this version onto the chip.


Last edited by snickersnee on Feb 11, 2011 - 05:16 AM; edited 1 time in total
 
 View user's profile Send private message  
Reply with quote Back to top
Display posts from previous:     
Jump to:  
All times are GMT + 1 Hour
Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Powered by PNphpBB2 © 2003-2006 The PNphpBB Group
Credits