This is a collaborative space. In order to contribute, send an email to maximilien.chaumon@icm-institute.org
On any page, type the letter L on your keyboard to add a "Label" to the page, which will make search easier.
Joystick curdes
Utilisation du Joystick Current Design au CENIR
Prise en main par le sujet
Le joystick peut être utilisé de deux manières différentes :
- Avec le manche, il se tient dans toute la paume de la main. Il est plus facile d'effectuer de grands déplacements dans une direction donnée.
- Sans le manche, il est utilisé à la manière d'un fingerstick, entre le pouce et l'index. Il est plus aisé de suivre des courbes avec précisions.
Installation du joystick dans l'IRM
Confort d'utilisation
Le CENIR possède un support joystick qui se visse au lit de l'IRM. Il assure la stabilité et une bonne prise en main, le manche est disposé horizontalement dans la continuation du bras du sujet. Cette configuration est très conseillée pour l'utilisation du joystick avec manche.
Le joystick peut également être posé sur le ventre du sujet. Cette disposition est viable sans le manche.
Branchements
Le CENIR dispose actuellement de deux fORP, de deux faisceau de fibres optiques ainsi que de deux joystick amagnétiques.
Le faisceau de fibres optiques fait, comme pour les boîtiers réponse, le lien entre le fORP (boîtier électronique) et le joystick. Cependant, il faut bien veiller à toujours utiliser le joystick avec le même faisceau de fibres optiques, car le joystick a été calibré sur un faisceau donné. Si on en change entre deux sujets, on obtiendra une différence de sensibilité des déplacements en X et Y du manche du joystick.
Modes du fORP associés au Joystick
Du point de vue de l'ordinateur de stimulation, le joystick Current Design peut être utilisé de deux manières différentes :
- Il peut émuler un dispositif HID USB géré automatiquement par DirectX (sous Windows). Dans ce cas, il faut tourner la fléche du sélecteur de mode du fORP en mode 5.
- Il peut être utilisé via le port série avec une plus grande précision temporelle : plus de 1000 points par seconde (débit de 57600 bauds). Dans ce cas, il faut configurer le fORP en mode 7.
Utilisation du joystick en mode 7
Pour obtenir plus de points sur le décours temporel du déplacement du manche selon les deux axes, il convient d'utiliser le mode 7 et de se brancher en série sur l'ordinateur de stimulation. Les données provenant du joystick passent par le fORP qui les transforme en un train de quatre octets. Ceci présuppose un peu de programmation.
Format des trains d'octets
En mode 7, des trains de quatre octets sont envoyés en continu sur le port série selon le modèle suivant :
n° d'octet |
d7 |
d6 |
d5 |
d4 |
d3 |
d2 |
d1 |
d0 |
---|---|---|---|---|---|---|---|---|
1 |
1 |
gch |
trg |
dte |
y10 |
y9 |
y8 |
y7 |
2 |
0 |
x6 |
x5 |
x4 |
x3 |
x2 |
x1 |
x0 |
3 |
0 |
y6 |
y5 |
y4 |
y3 |
y2 |
y1 |
y0 |
4 |
0 |
0 |
0 |
0 |
x10 |
x9 |
x8 |
x7 |
Le premier bit du premier octet est le bit de synchronisation. Il sert à repérer le début d'un train d'octet.
gch et dte représentent respectivement les boutons gauche et droite du joystick. Ils valent 1 si le bouton correspondant a été appuyé, 0 sinon.
trg est le trigger provenant de l'entrée BNC du [fORP]. Il vaut 1 si un trigger a été reçu.
x10 -> x0 définit le déplacement en X codé sur 11 bits : les valeurs s'échelonnent donc de -2||10|| à +2||10||-1. ([-1024; 1023])
y10 -> y0 définit le déplacement en Y codé sur 11 bits.
Code source en Matlab
Voila le code Matlab, utilisant la librairie port série de Cogent afin de faire fonctionner le joystick en série :
- Initialisation du port série
global cogent ... % initializations % Cogent configuration config_serial(serport, 57600); % serport is the serial port number ... % the rest of cogent configuration start_cogent porthandle = cogent.serial{serport}.hPort; ... % initialization after Cogent start while time < 60*1000 % loop example [X, Y] = fORP7_getdata (porthandle); ... % block of instructions using X and Y variables end
- Code source de la fonction qui récupère et décode les données
function [ X, Y, LB, RB, trigger, Time ] = fORP7_getdata (porthandle) % ------------------------------------------------------------------------- % fORP7_getdata : % % This function translates the bytes coming through a serial port from % Current Design fORP with switch position 7: "programmer's joystick" into % unscrambled variables : X and Y moves, left and right buttons, trigger. % % The serial port must have been opened with the following arguments : % 57600 bauds, 8 data bits, no parity, 1 stop bit. % % % Syntax : % [ X, Y, LB, RB, trigger, Time ] = fORP7_getdata ( porthandle ) % % Input : % - porthandle : handle to the serial (COM) port onto which the fORP is % plugged. % % Outputs : % - X : vector of X since last translation [-1024;1024]. % - Y : vector of Y since last translation [-1024;1024]. % - LB : vector of left button status, '1' means the button is pressed. % - RB : vector of right button status, '1' means the button is pressed. % - trigger : vector of TTL synchronization with the MRI trigger, % '1' means the fORP has been triggered. % - Time : the absolute time vector of each point in the Cogent time basis. % ------------------------------------------------------------------------- persistent residu; if isempty(residu) residu = {[], []}; end mask.SyncBit = 128; % Bit de reperage dans les trains d'octets mask.LB = 64; % Bouton de gauche mask.trigger = 32; % Bouton du milieu emule : trigger provenant de l'entree BNC du fORP mask.RB = 16; % Bouton de droite mask.low = 127; % Bits de poids faible des deplacements en X ou Y mask.high = 15; % Bits de poids fort des deplacements en X ou Y ind = 1; X = []; Y = []; LB = []; trigger = []; RB = []; Time = []; [ vector, time_v ] = CogSerial( 'GetEvents', porthandle ); vector = [residu{1} vector']; time_v = [residu{2} time_v']; lgvect = length(vector); if ~lgvect time_v = []; end while ( ind < lgvect-2 ) if ( bitand(vector(ind), mask.SyncBit) == mask.SyncBit ) LB = [LB, bitand(vector(ind), mask.LB)/mask.LB]; RB = [RB, bitand(vector(ind), mask.RB)/mask.RB]; trig_temp = bitand(vector(ind), mask.trigger); if trig_temp trigger = [trigger, time_v(ind)*1000]; end Xw = 128*bitand(vector(ind+3), mask.high) + bitand(vector(ind+1), mask.low); if Xw > 1023 Xw = Xw - 2047; end Yw = 128*bitand(vector(ind), mask.high) + bitand(vector(ind+2), mask.low); if Yw > 1023 Yw = Yw - 2047; end X = [X, Xw]; Y = [Y, Yw]; Time = [Time, time_v(ind)]; ind = ind+4; else ind = ind+1; end end if (ind < lgvect) residu = {vector(ind:lgvect), time_v(ind:lgvect)}; else residu = {[], []}; end