where : ibrtses delphi

Delphi - spacemouse code

disclaimer

the source code of this page may not appear correctly in certain browsers
due to special characters. Have a look at the source of this HTML page
with notepad instead

This unit implements the lower level of the device. 
The communication requires an external package.

###################################################################
{ TSMouse - interfaces to the LOGICAD 3D Magellan/ Space mouse

  based on the manual V2.1 dated 1/99

  currently uses the Asynch Pro for the serial communication
   with the mouse : TAPdComPort component with its
   .putstring(..) method and .ComTriggerAvail(..) event
   they can easily be replaced.

   ** work in progress ** dated 6.nov.99 **

}
unit SMouse;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  AdPort;


type
  TMKeyEvent=procedure(Sender:TComponent;key:word) of object;
  TMMoveEvent=procedure(Sender:TComponent;dx,dy,dz,da,db,dc:smallint) of object;
  TMModeEvent=procedure(Sender:TComponent;mode:word) of object;

  {
   understanding of this component requires the mentioned manual as several parameters
   have a restricted range. There is no 3D yet, the returned values will have to be integrated
   to be useful.
  }
  TSMouse = class(TComponent)
  private
    { Private declarations }
   fversion:shortstring;
   fdx,fdy,fdz:smallint;
   fda,fdb,fdc:smallint;
   fcompress:integer;
   fmode:word;
   fbeep,fmindata,fmaxdata,fsenserot,fsensetrans:byte;
   fkey,flastkey:word;
   fradius:byte;
  protected
    { Protected declarations }
   com:TAPdComPort;
   rxbuffer,txbuffer:shortstring;
   received:boolean;
   fkeyup:TMKeyEvent;
   fkeydown:TMKeyEvent;
   fmousemove:TMMoveEvent;
   fmodechange:TMModeEvent;
   function getversion:shortstring;
   function decodenibble(u:char;var b:byte):boolean; // true=ok
   function codenibble(n:byte):char;
   procedure ComTriggerAvail(CP: TObject; Count: Word);
   procedure setmode(m:word);
   procedure setradius(r:byte);
   procedure settrans(t:boolean);
   procedure setrot(t:boolean);
   procedure setdom(t:boolean);
   procedure setbeep(t:boolean);
   procedure setbeeplen(b:byte);
   procedure setmindata(b:byte);
   procedure setmaxdata(b:byte);
   procedure setSenserot(b:byte);
   procedure setSensetrans(b:byte);
   function gettrans:boolean;
   function getrot:boolean;
   function getdom:boolean;
   function getbeep:boolean;
   function getbeeplen:byte;
  public
    { Public declarations }
    constructor create(AOwner:TComponent); override;
    destructor destroy; override;
    procedure init;
    procedure zero;  virtual;
  published
    { Published declarations }
   property OnKeyUp:TMKeyEvent read fkeyup write fkeyup;
   property OnKeyDown:TMKeyEvent read fKeyDown write fKeyDown;
   property OnMouseMove:TMMoveEvent read fmousemove write fmousemove;
   property OnModeChange:TMModeEvent read fmodechange write fmodechange;
   property version:shortstring read getversion;
   property mode:word read fmode write setmode;
   property radius:byte read fradius write setradius;
   property translations:boolean read gettrans write settrans;
   property rotations:boolean read getrot write setrot;
   property dominantmode:boolean read getdom write setdom;
   property beep:boolean read getbeep write setbeep;
   property beeplen:byte read getbeeplen write setbeeplen;
   property mindataperiod:byte read fmindata write setmindata;
   property maxdataperiod:byte read fmaxdata write setmaxdata;
   property sensitivityRot:byte read fsenserot write setSenserot;
   property sensitivityTrans:byte read fsensetrans write setSensetrans;
  end;


procedure Register;

implementation

function TSMouse.getversion:shortstring;
begin
 if fversion='' then begin
   txbuffer:='vQ'+chr(13);
   com.putstring(txbuffer);
   received:=false;
   sleep(100);
   if received then result:=fversion;
  end
 else result:=fversion;
end;


function TSMouse.decodenibble(u:char;var b:byte):boolean; // true=ok
begin
 case u of
  '0' :begin b:=0; result:=true; end;
  '3' :begin b:=3; result:=true; end;
  '5' :begin b:=5; result:=true; end;
  '6' :begin b:=6; result:=true; end;
  '9' :begin b:=9; result:=true; end;
  ':' :begin b:=10; result:=true; end;
  '<' :begin b:=12; result:=true; end;
  '?' :begin b:=15; result:=true; end;
  'A' :begin b:=1; result:=true; end;
  'B' :begin b:=2; result:=true; end;
  'D' :begin b:=4; result:=true; end;
  'G' :begin b:=7; result:=true; end;
  'H' :begin b:=8; result:=true; end;
  'K' :begin b:=11; result:=true; end;
  'M' :begin b:=13; result:=true; end;
  'N' :begin b:=14; result:=true; end;
  else result:=false;
 end;
end;

var code:array[0..15]of char
    =('0','A','B','3','D','5','6','G','H','9',':','K','<','M','N','?');

function TSMouse.codenibble(n:byte):char;
begin
 result:= code[(n and $0F)];
end;

// this event is provided by the Asynch Pro Comport component and 
// comes for every (or multiple) byte received.
procedure TSMouse.ComTriggerAvail(CP: TObject; Count: Word);
var i:integer;
    ch:char;
    u,v:byte;
    ok:boolean;
    tw:word;
begin
 for i:=1 to count do begin
   ch:=com.getchar;
   rxbuffer:=rxbuffer+ch;
   if ch=chr(13) then begin
     case rxbuffer[1] of
      'b':begin
           ok:=decodenibble(rxbuffer[2],u);
           if ok then fbeep:=u;
          end;
      'c':begin
           ok:=decodenibble(rxbuffer[2],u); tw:=u;
           ok:=ok and decodenibble(rxbuffer[3],u);tw:=tw or (u shl 4);
           if ok then fcompress:=tw;
          end; //c
      'd':begin
           ok:=decodenibble(rxbuffer[2],u);
           fdx:= u shl 12;
           ok:=ok and decodenibble(rxbuffer[3],u); fdx:=fdx or (u shl 8);
           ok:=ok and decodenibble(rxbuffer[4],u); fdx:=fdx or (u shl 4);
           ok:=ok and decodenibble(rxbuffer[5],u); fdx:=fdx or u;
           fdx:=fdx-32768;
           ok:=ok and decodenibble(rxbuffer[6],u); fdy:= u shl 12;
           ok:=ok and decodenibble(rxbuffer[7],u); fdy:=fdy or (u shl 8);
           ok:=ok and decodenibble(rxbuffer[8],u); fdy:=fdy or (u shl 4);
           ok:=ok and decodenibble(rxbuffer[9],u); fdy:=fdy or u;
           fdy:=fdy-32768;
           ok:=ok and decodenibble(rxbuffer[10],u); fdz:= u shl 12;
           ok:=ok and decodenibble(rxbuffer[11],u); fdz:=fdz or (u shl 8);
           ok:=ok and decodenibble(rxbuffer[12],u); fdz:=fdz or (u shl 4);
           ok:=ok and decodenibble(rxbuffer[13],u); fdz:=fdz or u;
           fdz:=fdz-32768;
           ok:=ok and decodenibble(rxbuffer[14],u); fda:= u shl 12;
           ok:=ok and decodenibble(rxbuffer[15],u); fda:=fda or (u shl 8);
           ok:=ok and decodenibble(rxbuffer[16],u); fda:=fda or (u shl 4);
           ok:=ok and decodenibble(rxbuffer[17],u); fda:=fda or u;
           fda:=fda-32768;
           ok:=ok and decodenibble(rxbuffer[18],u); fdb:= u shl 12;
           ok:=ok and decodenibble(rxbuffer[19],u); fdb:=fdb or (u shl 8);
           ok:=ok and decodenibble(rxbuffer[20],u); fdb:=fdb or (u shl 4);
           ok:=ok and decodenibble(rxbuffer[21],u); fdb:=fdb or u;
           fdb:=fdb-32768;
           ok:=ok and decodenibble(rxbuffer[22],u); fdc:= u shl 12;
           ok:=ok and decodenibble(rxbuffer[23],u); fdc:=fdc or (u shl 8);
           ok:=ok and decodenibble(rxbuffer[24],u); fdc:=fdc or (u shl 4);
           ok:=ok and decodenibble(rxbuffer[25],u); fdc:=fdc or u;
           fdc:=fdc-32768;
           if assigned(OnMouseMove) then OnMouseMove(self,fdx,fdy,fdz,fda,fdb,fdc);
          end; //d
      'e':begin
           // a coomunication error occured
           // do nothing now....
          end; //e
      'k':begin
           ok:=decodenibble(rxbuffer[2],u);        tw:=u;
           ok:=ok and decodenibble(rxbuffer[3],u); tw:=tw or (u shl 4);
           ok:=ok and decodenibble(rxbuffer[4],u); tw:=tw or (u shl 8);
           if ok then begin
             fkey:=tw;
             tw:=fkey xor flastkey;
             if (fkey=0) and assigned(OnKeyUp) then OnKeyUp(self,tw);
             if (flastkey=0) and assigned(OnKeyDown) then OnKeyDown(self,tw);
             flastkey:=fkey;
            end;
          end; //k
      'm':begin
           if decodenibble(rxbuffer[2],u) then begin
             fmode:=u;
             if assigned(fmodechange) then OnModeChange(self,fmode);
            end;
          end; //m
      'n':begin
           if decodenibble(rxbuffer[2],u) then begin
             fradius:=u;
            end;
          end;
      'p':begin
           ok:=decodenibble(rxbuffer[2],u);
           ok:=ok and decodenibble(rxbuffer[3],v);
           if ok then begin
            fmaxdata:=u;
            fmindata:=v;
            end;
          end;
      'q':begin
           ok:=decodenibble(rxbuffer[2],u);
           ok:=ok and decodenibble(rxbuffer[3],v);
           if ok then begin
            fsensetrans:=u;
            fsenserot:=v;
            end;
          end;
      'v':begin
           fversion:=rxbuffer;
           received:=true;
          end;
      'z':begin
           // zeroed .. do nothing now
          end;
     end; //case
     rxbuffer:='';
   end;
 end;
end;

constructor TSMouse.create(AOwner:TComponent);
begin
 inherited create(AOwner);
 Com:=TApdComPort.Create(self);
 Com.ComNumber:=1;                // preset to COM1 !!
 Com.Baud:=9600;
 Com.Stopbits:=2;
 Com.Open:=True;
 Com.OnTriggerAvail:=ComTriggerAvail;
 fversion:=''; received:=false;
 OnKeyUp:=nil;
 OnKeyDown:=nil;
 OnMouseMove:=nil;
 OnModeChange:=nil;
 //getversion;
 fmode:=0;
 fbeep:=$09;
 fmindata:=15;
 fmaxdata:=15;
 fsenserot:=0;
 fsensetrans:=0;
end;

destructor TSMouse.destroy;
begin
 If Com.open then Com.open:=false;
 Com.free;
 inherited destroy;
end;

procedure TSMouse.init;
begin
  txbuffer:='kQ'+chr(13);
 com.putstring(txbuffer);
end;

procedure TSMouse.setmode(m:word);
begin
 txbuffer:='m'+codenibble(lo(m) and $0F)+chr(13);
 com.putstring(txbuffer);
end;

procedure TSMouse.setradius(r:byte);
begin
 txbuffer:='n'+codenibble(r and $0F)+chr(13);
 com.putstring(txbuffer);
end;

procedure TSMouse.zero;
begin
 txbuffer:='z'+chr(13);
 com.putstring(txbuffer);
end;

procedure TSMouse.settrans(t:boolean);
begin
 if t then fmode:=fmode or $02 else fmode:=fmode and $FD;
 txbuffer:='m'+codenibble(fmode)+chr(13);
 com.putstring(txbuffer);
end;

procedure TSMouse.setrot(t:boolean);
begin
 if t then fmode:=fmode or $01 else fmode:=fmode and $FE;
 txbuffer:='m'+codenibble(fmode)+chr(13);
 com.putstring(txbuffer);
end;

procedure TSMouse.setdom(t:boolean);
begin
 if t then fmode:=fmode or $04 else fmode:=fmode and $FB;
 txbuffer:='m'+codenibble(fmode)+chr(13);
 com.putstring(txbuffer);
end;

function TSMouse.gettrans:boolean;
begin
 result:=(fmode and $02)<>0;
end;

function TSMouse.getrot:boolean;
begin
 result:=(fmode and $01)<>0;
end;

function TSMouse.getdom:boolean;
begin
 result:=(fmode and $04)<>0;
end;
procedure TSMouse.setbeep(t:boolean);
begin
 if t then fbeep:=fbeep or $08 else fbeep:=fbeep and $F7;
 txbuffer:='b'+codenibble(fbeep)+chr(13);
 com.putstring(txbuffer);
end;
procedure TSMouse.setbeeplen(b:byte);
begin
 fbeep:=fbeep or (b and $07);
 txbuffer:='b'+codenibble(fbeep)+chr(13);
 com.putstring(txbuffer);
end;

function TSMouse.getbeep:boolean;
begin
 result:=((fbeep and $08)<>0);
end;
function TSMouse.getbeeplen:byte;
begin
 result:=(fbeep and $07);
end;
procedure TSMouse.setmindata(b:byte);
begin
 //fmindata:=b;
 txbuffer:='p'+codenibble(fmaxdata)+codenibble(b)+chr(13);
 com.putstring(txbuffer);
end;
procedure TSMouse.setmaxdata(b:byte);
begin
 //fmaxdata:=b;
 txbuffer:='p'+codenibble(b)+codenibble(fmindata)+chr(13);
 com.putstring(txbuffer);
end;
procedure TSMouse.setSenserot(b:byte);
begin
 //fsenserot:=b;
 txbuffer:='q'+codenibble(fsensetrans)+codenibble(b)+chr(13);
 com.putstring(txbuffer);
end;
procedure TSMouse.setSensetrans(b:byte);
begin
 //fsensetrans:=b;
 txbuffer:='q'+codenibble(b)+codenibble(fsenserot)+chr(13);
 com.putstring(txbuffer);
end;

procedure Register;
begin
  RegisterComponents('Samples', [TSMouse]);
end;

end.
#######################################################################################





Feedback is welcome





sponsored links




Delphi
home

last updated: 6.nov.99

Copyright (99,2000) Ing.Büro R.Tschaggelar