CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Converting signed 9 bit int to signed 8 bit int (question)

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
uN_Eof



Joined: 17 May 2010
Posts: 29
Location: I live in Spain, with the toros, paella and tortilla

View user's profile Send private message

Converting signed 9 bit int to signed 8 bit int (question)
PostPosted: Mon Oct 31, 2011 8:27 am     Reply with quote

Hey all. I need to convert data. I'm not such a great C programmer so I don't know how to do this.

I'm working in a PS/2 mouse driver. The mouse sends the movement data in 9 bit 2's complement integer in this way: It sends the movement sign bits (2 bits, one for X and other for Y) in the first packet, and the 2 other packets are the actual movement register. I want to convert this 9 bit signed int into a 8 bit signed int but I have no idea on how to do this. Any help will be valued. Thanks.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Oct 31, 2011 3:01 pm     Reply with quote

1. Try to come up with an idea for an algorithm in your mind.
2. Make a test program (or programs) to study it.

For example, you might decide that dividing a signed 9-bit number by 2
will give you an 8-bit result. Sounds logical. But can you also do it by
the shortcut way of right-shifting it ? Sounds possible. So, make a
test program. First make a program to print out the Hex values and
look at the bit patterns. Study 2's complement articles on the internet.
Then make a larger test program (shown below) to study the proposed
method of division (right-shifting), by looking at values near the
boundaries. (Lower limit, zero-crossing, and upper limit).

In other words, if you don't already know the answer (from previous
programming experience, or taking a class, or reading a textbook),
then you still have the power in your hands (and your mind) to work
through the problem.

Note: In 9-bit 2's complement numbers, the minimum number is -256
and the maximum is 255. But, all the webpages the on PS/2 mouse that
I browsed say it's output is from -255 to +255. I don't know if this is true.
I didn't see an official document. I don't have time to search for one.
I am just mentioning this as something that I noted.

Program output:
Quote:

Value: -255 Result: -128
Value: -254 Result: -127
Value: -253 Result: -127
Value: -252 Result: -126
Value: -251 Result: -126
Value: -5 Result: -3
Value: -4 Result: -2
Value: -3 Result: -2
Value: -2 Result: -1
Value: -1 Result: -1
Value: 0 Result: 0
Value: 1 Result: 0
Value: 2 Result: 1
Value: 3 Result: 1
Value: 4 Result: 2
Value: 5 Result: 2
Value: 250 Result: 125
Value: 251 Result: 125
Value: 252 Result: 126
Value: 253 Result: 126
Value: 254 Result: 127
Value: 255 Result: 127


Code:

#include <18F452.h>       
#fuses HS,NOWDT,PUT,BROWNOUT,NOLVP
#use delay (clock = 20M)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

//===============================
void main()
{
signed int16 value;
signed int16 value9;
signed int8 result;

for(value = -255; value < -250; value +=1)
   {
    value9 = value & 0x1FF;  // Emulate 9-bit value from mouse.
    result = value9 >> 1;  // Right-shift it
    printf("Value: %ld  Result: %d \r", value, result);           
   }


for(value = -5; value < 6; value +=1)
   {
    value9 = value & 0x1FF;
    result = value9 >> 1;  // Right-shift it
    printf("Value: %ld  Result: %d \r", value, result);           
   }

for(value = 250; value < 256; value +=1)
   {
    value9 = value & 0x1FF;
    result = value9 >> 1;  // Right-shift it
    printf("Value: %ld  Result: %d \r", value, result);           
   }


while(1);
}
temtronic



Joined: 01 Jul 2010
Posts: 9226
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Oct 31, 2011 5:05 pm     Reply with quote

There is a Microchip application done eons ago making a mouse using I think a 16C84(been awhile) but it does explain in detail the details !
Might be a good reference for you.
uN_Eof



Joined: 17 May 2010
Posts: 29
Location: I live in Spain, with the toros, paella and tortilla

View user's profile Send private message

PostPosted: Tue Nov 01, 2011 10:30 am     Reply with quote

Thank you very very much for your help PCM Programmer.
Thats similar to what I tried to do, but your program is correct, and mine didn't work correctly.

I still have one problem that I can't seem to solve by my self.
When I move the mouse to the right or up (signs 0 I think) the movement in the display (I send the data to my pc as a HID joystick) is correct. The faster I move the mouse the bigger the value is. But if I move it down or to the left, the movement data is correct, but the miniun vaue is the maximun. I'll try to explain better. If i move to the left or down the Z axis or Z rotation goes up to the maximun value, and the faster i move the mouse left or down, the lower the value is, never being less than the middle of the bar, thats 0. I don't know if you understand what I mean. If you don't, I'll upload a video or a picture to explain better.

Of course I'd like to solve this by my sef, and it's what I'm going to try, but in case I don't get it solved, I'm asking here, to save time.

BTW, I tried to find some official documents about the PS/2 protocol with no result at all. I guess the minimun value is -256. Maybe I'll send a mail or something to IBM to see where I can find the official PS/2 protocol description.

Again, thank you so much. You're very kind, I always read you helping other people Wink

EDIT:Forgot to paste it, this is the code I'm using right now to conver data.
Code:
void calc_mov(){
   pkt_xs16 = (pkt_x | (__xmsign << 8) & 0x1FF);
   pkt_ys16 = (pkt_y | (__ymsign << 8) & 0x1FF);
   pkt_xs8 = pkt_xs16 >> 1;
   pkt_ys8 = pkt_ys16 >> 1;
}

I call this as soon as I get the 3 bytes frm the mouse.
pkt_xs16 -> signed 16bit int
pkt_ys16 -> signed 16bit int
pkt_xs8 -> signed 8 bit int
pkt_ys8 -> signed 8bit int
pkt_x -> actual data read from the mouse
pkt_y -> same but for y
__xmsign -> X sign
__ymsign -> Y sign

I send to the pc pkt_xs8 and pkt_ys8 as signed 8 bit ints.


@temtronic
Yep in fact some time ago I took apart a broken quite old microsoft wheel mouse and I discovered a 16C84 inside. Now that OLD pic is in my old IC collection.
BTW I'n not triyng to mimic a mouse, I'm reading data from it.
Ttelmah



Joined: 11 Mar 2010
Posts: 19509

View user's profile Send private message

PostPosted: Tue Nov 01, 2011 10:48 am     Reply with quote

This actually suggests the value _isn't_ 2's complement.

This was what was worrying PCMprogrammer about the notes he had found.

A 2's complement 9bit value, can represent +255 to -256. However the note talked about the value range being -255 to +255, suggesting the value is actually just an absolute movement value (0 to 255), with a sign bit.
If so, the way to convert it, is to just divide the 8bit movement value by 2, and then if the sign bit is set, take this away from 0.
A glance at my old IBM Bios reference manuals, suggests that the movement is indeed just an absolute value, not 2's complement.

Best Wishes
uN_Eof



Joined: 17 May 2010
Posts: 29
Location: I live in Spain, with the toros, paella and tortilla

View user's profile Send private message

PostPosted: Tue Nov 01, 2011 11:21 am     Reply with quote

Ttelmah wrote:
This actually suggests the value _isn't_ 2's complement.

This was what was worrying PCMprogrammer about the notes he had found.

A 2's complement 9bit value, can represent +255 to -256. However the note talked about the value range being -255 to +255, suggesting the value is actually just an absolute movement value (0 to 255), with a sign bit.
If so, the way to convert it, is to just divide the 8bit movement value by 2, and then if the sign bit is set, take this away from 0.
A glance at my old IBM Bios reference manuals, suggests that the movement is indeed just an absolute value, not 2's complement.

Best Wishes


pkt_xs8 = (pkt_x / 2) | (__xmsign << 7);
pkt_ys8 = (pkt_y / 2) | (__ymsign << 7);

Thats the code now. It does a very similar thing now.
Anyway I'm not sure what you mean with "take it away from 0". Can you explain please?
Thank you.
Ttelmah



Joined: 11 Mar 2010
Posts: 19509

View user's profile Send private message

PostPosted: Tue Nov 01, 2011 3:33 pm     Reply with quote

Code:

if (__xmsign)
    pkt_xs8 = 0-(pkt_x / 2);
else
    pkt_xs8=pkt/2;


and similar for the y.

Best Wishes
uN_Eof



Joined: 17 May 2010
Posts: 29
Location: I live in Spain, with the toros, paella and tortilla

View user's profile Send private message

PostPosted: Wed Nov 02, 2011 11:08 am     Reply with quote

Hello,

I tried that code and the behaviour is quite similar, if not the same.
I'm starting to think that it can be the USB descriptor... maybe. I don't know.

Code:
    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
    0x09, 0x04,                    // USAGE (Joystick)
    0xa1, 0x01,                    // COLLECTION (Application)
    0xa1, 0x02,                    //   COLLECTION (Logical)
    0xa1, 0x00,                    //     COLLECTION (Physical)
    0x75, 0x08,                    //       REPORT_SIZE (8)
    0x95, 0x04,                    //       REPORT_COUNT (4)
    0x25, 0x7f,                    //       LOGICAL_MAXIMUM (127)
    0x15, 0x80,                    //       LOGICAL_MINIMUM (-128)
    0x35, 0x80,                    //       PHYSICAL_MINIMUM (-128)
    0x45, 0x7f,                    //       PHYSICAL_MAXIMUM (127)
    0x09, 0x30,                    //       USAGE (X)
    0x09, 0x31,                    //       USAGE (Y)
    0x09, 0x32,                    //       USAGE (Z)
    0x09, 0x35,                    //       USAGE (Rz)
    0x81, 0x02,                    //       INPUT (Data,Var,Abs)
    0xc0,                          //     END_COLLECTION
    0x05, 0x09,                    //     USAGE_PAGE (Button)
    0x19, 0x01,                    //     USAGE_MINIMUM (Button 1)
    0x29, 0x08,                    //     USAGE_MAXIMUM (Button 8)
    0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
    0x95, 0x08,                    //     REPORT_COUNT (8)
    0x75, 0x01,                    //     REPORT_SIZE (1)
    0x81, 0x02,                    //     INPUT (Data,Var,Abs)
    0x05, 0x09,                    //     USAGE_PAGE (Button)
    0x19, 0x09,                    //     USAGE_MINIMUM (Button 9)
    0x29, 0x10,                    //     USAGE_MAXIMUM (Button 16)
    0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
    0x95, 0x08,                    //     REPORT_COUNT (8)
    0x75, 0x01,                    //     REPORT_SIZE (1)
    0x81, 0x02,                    //     INPUT (Data,Var,Abs)
    0x05, 0x09,                    //     USAGE_PAGE (Button)
    0x19, 0x11,                    //     USAGE_MINIMUM (Button 17)
    0x29, 0x13,                    //     USAGE_MAXIMUM (Button 19)
    0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
    0x95, 0x08,                    //     REPORT_COUNT (8)
    0x75, 0x01,                    //     REPORT_SIZE (1)
    0x81, 0x02,                    //     INPUT (Data,Var,Abs)
    0xc0,                          //   END_COLLECTION
    0xc0                           // END_COLLECTION


I used the USB HID desccriptor tool.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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