Post Reply  Post Thread 
IDI language clarifications
Author Message
MrWoo
Junior Member
**


Posts: 14
Group: Registered
Joined: Sep 2008
Status: Offline
Reputation: 0
Post: #1
IDI language clarifications

So I have not had my amp working since I got it because it did not work with my MS sidewinder mouse. Recently I was looking at something from OCZ called the neuralizer or something. It was supposed to use brainwaves/facial movements to give some feedback (ie. button pressing). Sounded cool. Some reviewer said it worked great, but you have to have a stone face and remain calm to use it. That is not me at all. So I decided to see what was up at GWS. I seen an updated IDI pack was made last fall, with a fix for the sidewinder. Cooool.

So I put in on and installed it. Sure enough, it works with my mouse now. On to the scripting then.

While there are lots of example scripts, they all assume you want to change timings or keys. That is nice, but I still feel there is vital data missing. Let me explain.

I want to use a shift level 1. Ok, I set it up. Then on shift one, I want left mouse to send 'g' keystroke. Ok, simple to do using IDI config. But now I want to do it in macro. Ok, seems to be no problem initially. So you use this

Code:
THREAD Profile
VAR PressTime

Start:    
        // set or reset variable to 0
    PressTime = 0

Continue:
    // for this, wait until desired button is pressed
    WaitForButton(Button, ButtonMask)
        // set variable to current time
    PressTime = CurrentTimeMs
        // show that button has been pressed
    TypeText("Pressed\r",16)
    // if button is pressed wait 5000ms for release
    DO
        // delay for 10 while waiting to see if button released
        DelayForMs(10)
           // compare start time to current time
           // if over 5000 send text and go back to beginning
        IF CurrentTimeMs > PressTime + 5000 THEN
                TypeText("Time exceeded 5000\r",16)
                GOTO Start
        FI
        
    WHILE ((GetButtonState & ButtonMask) == Button)
        // the button was released after 5000 ms, send message
    TypeText("Released\r",16)
        // go back to beginning, reset variable to 0 and wait for button press
    GOTO Start

END


So you see in simple commenting how much easier it could be to understand. This is a pretty simple example, as it only uses IF and Do/While statements to loop and check values.

However, the part I find is lacking is the understanding of just what is happening with the GetButtonState() function. I know it is being BITAND'd with ButtonMask. But this is so atypical of most scripting languages. What does GetButtonState return? How do you use it? The manual is no help really, it actually is more confusing.

Let me explain.

One would think it would work like this

var = GetButtonState() // this should be the combined value of all buttons??

IF var == 5 THEN // 5 could be button 1 & 3 are down

It seems you could also do this
IF GetButtonState(1,1) THEN // this should be button 1 is down, and return should be true

I don't really see explained anywhere these constants Button and ButtonMask. What are thier values? Where can you use them?

So you have these common statments.
WaitForButton(Button,ButtonMask)
this one, I assume is waiting for Button which is what the IDI config set for this button? And button mask is the pressed state?

But then this is thrown in.
((GetButtonState & ButtonMask) == Button)
You are using GetButtonState without the braces (). This is not declared as legal anywhere. And what is ButtonMask? Is it a function ever, like ButtonMask()? and the == Button ?? What is Button? Where does it derive it's value?

So I was trying something that should be simple. If button 1 is pressed, wait for 500ms, and if within that time button 2 is pressed, send XYZ, else if 500ms goes by send ABC. Simple enough.

Looking at the .pdf, it would seem that since I am using a shift, that the following are the button values and mask values

button 1 value 1, mask of 'pressed' 1 (these are not hex, is it restricted to hex?)
button 2 value 2, mask of 'pressed' 2
button 5 value 16, mask of 'pressed' 16 (this is the shift button)

From what I am reading, the GetButtonState() should return the state of all buttons pressed, and not buttons not pressed. So the total would be 19 for button and 19 for mask which should be 38. If the docs are correct, then GetButtonState() should return 38. Or, would it be that GetButtonState(19,19) should = TRUE if buttons 1,2 & 5 are pressed.

That did not work. I then tried IF ((GetButtonState & ButtonMask) == 38) THEN, but that did not work either.

So, how about some more advanced scripts utilizing these functions and values in ways that show thier use, with comments that explicitly describe what is happening.

I should state that I have an early excel spreadsheet with stuff in it that might not be in the .pdf, I have not checked.

Thanks for the progress so far. Looking better than it was for sure.

MrWoo

03-16-2009 01:06 AM
Find all posts by this user Quote this message in a reply
MrWoo
Junior Member
**


Posts: 14
Group: Registered
Joined: Sep 2008
Status: Offline
Reputation: 0
Post: #2
RE: IDI language clarifications

This is quite frustrating. I see now that ButtonMask and Button are interpereted from what the configurator has them set to. So if you set this macro to button one, Button will be 1 or 0x01 and ButtonMask will be the state of the button. OK.

Now, for simplicity sake, it seems as if when you state the function GetButtonState(), that you don't actually have anything to pass to it? Scripts seem to fail compiling when I use () on it, much less anything within it. It is like the CurrentTimeMs(). You actually use it without the braces.

So here is aline that compiles
IF (GetButtonState < 16) THEN

but, lol, it can be < 20000 and still it does the THEN portion. Am I missing something? I tried both dec and hex values, and it always is < than whatever value I use. What exactly am I checking for, since I can't seem to pass any parameters to the GetButtonState function.

MrWoo

03-16-2009 02:27 AM
Find all posts by this user Quote this message in a reply
MrWoo
Junior Member
**


Posts: 14
Group: Registered
Joined: Sep 2008
Status: Offline
Reputation: 0
Post: #3
RE: IDI language clarifications

So I have found out how to work it. It seems that you only need the button count, not the button mask.

Because I want to watch for buttons 1,2 and 5 being down at same time, you have 2 sets of values. The first set is the values for those buttons which is 19. The second set is the button mask, and total value of buttons 1,2 and 5 IF pressed should be 19. 19 + 19 = 38. But, you don't look for 38 evidentily, although the excel spreadsheet says

Quote:
Returns composite of all buttons, 1 for button 1, 2 for 2, 4 for 3, 9 means button 1 and 4 are down, the rest up, etc.


and the latest .pdf says

Quote:
returns the up/down status of the device buttons


and

Quote:
GetButtonState() returns a value representing the current state (up/down) of the set (1-8) of the device buttons
GetButtonState() uses the ButtonMask constants to specify the current state of the device buttons. When multiple
buttons are down concurrently, GetButtonState() returns a value equals to the sum of the ButtonMask ID values for the
pressed buttons


It sounds like you need to know both. In fact, I am unsure of exactly which one is used. Regardless, only one set is used, not both together.

Here is a script to find your combinations.

Code:
THREAD Profile
VAR PressTime
VAR ii
Start:    
    // give message of end of loops
    // why does this not get written at start??
    TypeText("Stop\r",16)

Continue:
    // wait until button is pressed
    WaitForButton(Button, ButtonMask)
    
    // desired button has been pressed
    
    // do the loop below until button is released or
    // the FOR/ENDFOR loop finishes
    DO
        // delay for 10 milliseconds
        DelayForMs(10)
        
        // step through this loop up to 40 times
        // if the button state = variable ii, show the text 'found'
        // change the value from 40 to higher if needed
        FOR ii = 1,40
            
            // type out each line, representing ii
            // i see no way to type out variables
            TypeText("**;\r",16)
            
            // when ii is found, you can count the lines to see
            // what value was returned
            // this value is the combination of pressed buttons
            IF (GetButtonState == ii) THEN
                TypeText("found\r",16)
                GOTO Start
            FI
        
        ENDFOR
        
    WHILE ((GetButtonState & ButtonMask) == Button)
    // button was just released
    
    // in case the do/while loop fails, releasing the button
    // might get out of endless loop
    GOTO Start

END


MrWoo

03-16-2009 03:27 AM
Find all posts by this user Quote this message in a reply
MrWoo
Junior Member
**


Posts: 14
Group: Registered
Joined: Sep 2008
Status: Offline
Reputation: 0
Post: #4
RE: IDI language clarifications

After some more playing, here is a working example of how to use a shift level, then pressing mouse 2. If after x amount of milliseconds nothing else is pressed, something occurs. However, if while holding down the shift button and mouse 2, and also then you were to press mouse 1, a timing sequence is started. Depending on how long you hold down all 3 keys, other things occur.

It is possible for 5 different events to happen with this type of macro

Code:
// This is a Template Macro for a shift level button and mouse button 2 pressed at same time
// If no other button is pressed, after 1 second event fires.
// If mouse 1 pressed before 1 second, based on how long all 3 buttons are
// held down, one of 3 events happens based on the time all 3 buttons were
// held down.

// your buttons may result in a different buttonmask value, so edit accordingly

THREAD Profile
VAR PressTime
VAR Press2

Start:    
    // give indication of macro ending
    // and waiting for button to be pressed again
    TypeText("Stop\r",8)
    PressTime = 0

Continue:
    // wait until shift button and button 2 is pressed
    WaitForButton(Button, ButtonMask)
    // button has been pressed

    // set the variable PressTime
    PressTime = CurrentTimeMs
    
    // give message that button was pressed
    TypeText("Pressed\r",16)

    // this DO loop waits for shift & mouse 2 to be released
    // or if 1000 ms passes, it acts as if released
    DO
        // delay for 10 ms
        DelayForMs(10)

        // compare time, checking if 1 second has passed
        // with no other button activity
        IF CurrentTimeMs > PressTime + 1000 THEN
                // no other button was pressed, do the default event
                // you could insert KeyPress() or other events here
                
                // give message of event
                TypeText("Time exceeded 1000\r",16)
                
                // go bact to start, wait for next button pressing
                GOTO Start
                
        // here we check to see if mouse 1 was also pressed
        // the value below ** 19 ** may be different depending on
        // the keys you used. Find your value and use it both here
        // and in the DO/WHILE statement just below this
        
        ELSEIF (GetButtonState == 19) THEN
        
            // set the second time keeping variable
            Press2 = CurrentTimeMs
            
            // this do loop will wait indefinately for the release of
            // one of the 3 buttons being held down
            // depending on how long that was, different events happen
            DO
            
                // create small delay
                DelayForMs(5)
                
            WHILE (GetButtonState == 19)
            
            // all 3 buttons are no longer held down
            // now examine the time they were held down for
            // and perform an event based on the time
            
            IF CurrentTimeMs - Press2 <= 150 THEN
                // this is a very quick TAP
                // do the following event
                // insert your function here
                TypeText("<150ms pause\r",8)
                
            ELSEIF CurrentTimeMs - Press2 < 300 THEN
                // this is a button press
                // do the following event
                // insert your function here
                TypeText("<300ms pause\r",8)
                
            ELSEIF CurrentTimeMs - Press2 >= 301 THEN
                // this is a button hold. It can
                // be only a slight hold, or an
                // indefinate hold.
                // insert your function here
                TypeText(">300ms pause\r",8)
                
            ENDIF
            
            // the event was triggered, go back to start and wait for next button pressing
            GOTO Start
        FI
        
    WHILE ((GetButtonState & ButtonMask) == Button)
    
    
    // if you pressed shift and mouse 2, then released, this is the normal event
    // it is probably the same event used if you pressed shift and mouse 2
    // and held for 1 second but did not press another button, but does
    // not have to be
    
    // give message of event
    TypeText("Released\r",16)
    
    // go back to start and wait for next pressing
    GOTO Start
        
END


MrWoo

03-17-2009 09:48 AM
Find all posts by this user Quote this message in a reply
earlboy
Account not Activated


Posts: 4
Group: Awaiting Activation
Joined: Jul 2009
Status: Offline
Post: #5
RE: IDI language clarifications

I'll reply to this even though this thread is quite old for clarification. I'll discuss WaitForButton and GetButtonState.

WaitForButton(Button,ButtonMask) is a bit weird, since "Button" and "ButtonMask" is automatically supplied if you put it in a macro assigned to a mouse button in AMP (Notice you never declare them e.g. VAR Button?). So If you put a WaitForButton in a macro assigned to button3, ButtonMask will automatically be 0x04 and "Button" will be supplied with a value of 0x04 (Please refer to the scripting guide for the values.). I believe this was done to enable the same macro to be assigned to a different button without modifying the code.

Now on to the purpose of the parameters. "Button" determines what state WaitForButton should trigger, "ButtonMask" determines which button it will wait for. So WaitForButton(0x04,0x04) will wait until Button3 is pressed and WaitForButton(0x00,0x04) will wait until Button3 is release.

So if you assign this macro to any button and try it in notepad...

Code:
THREAD Profile
    Continue:
    WaitForButton(0x04,0x04)          // Wait for button3 to be pressed
    TypeText("Button Pressed.",10)

    WaitForButton(0x00,0x04)          // Wait for button3 to be released
    TypeText("Button Release.\r",10)
    GOTO Continue
END

Pressing button3 will result in AMP typing "Button Pressed.", and releasing button3 will result in AMP typing "Button Release.". A quick tap of button3 will result in both phrases being type in sequence. Notice that no matter which button you assign this macro to, it will only trigger if button3 is pressed.

For GetButtonState, it simply returns the state of all seven buttons including the lift sensor. Each button is represented by a bit in the return value. Bit 1 is for buton1, bit 2 is for button2 and so on. So if GetButtonState returns a value of 0x00, none of the buttons are pressed. A return value of 0x01 (bit1 is set), means that button1 is pressed, a value of 0x03 (bit 1 & 2 is set) means button1 and button2 are pressed (bit1 and bit2 is set to 1). That's why GetButtonState is tested with the bitwise operation & (bitwise AND).

Here is a hardcoded version of the sample code in the reference guide for GetButtonState (modified a bit). Remember since this is hardcoded for button3, no matter which button you assign this macro, it will only trigger if button3 is pressed.
I simply replaced "Button" and "ButtonMask" with a hardcoded value of 0x04 for button3.

Code:
THREAD Profile
    Continue:
    WaitForButton(0x04,0x04)     // Wait for button 3 to be pressed
    TypeText("Pressed.",10)
    DO
        DelayForMs(100)
    WHILE ((GetButtonState & 0x04) == 0x04 )// Don't exit the loop until button3 is released
    TypeText("Released.\r",10)
    GOTO Continue
END

Hope this clears up WaitForButton and GetButtonState.

08-05-2009 07:08 AM
Find all posts by this user Quote this message in a reply
Post Reply  Post Thread 

[-]
Quick Reply
Message
Type your reply to this message here.



Image Verification
Image Verification Please enter the text within the image on the left in to the text box below. This process is used to prevent automated posts.

View a Printable Version
Send this Thread to a Friend
Subscribe to this Thread | Add Thread to Favorites
Rate This Thread:

Forum Jump: