sranger_hwi_spm.C

Go to the documentation of this file.
00001 /* Gxsm - Gnome X Scanning Microscopy
00002  * universal STM/AFM/SARLS/SPALEED/... controlling and
00003  * data analysis software
00004  * 
00005  * Copyright (C) 1999,2000,2001,2002,2003 Percy Zahl
00006  *
00007  * Authors: Percy Zahl <zahl@users.sf.net>
00008  * additional features: Andreas Klust <klust@users.sf.net>
00009  * WWW Home: http://gxsm.sf.net
00010  *
00011  * This program is free software; you can redistribute it and/or modify
00012  * it under the terms of the GNU General Public License as published by
00013  * the Free Software Foundation; either version 2 of the License, or
00014  * (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software
00023  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
00024  */
00025 
00026 /* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 8 c-style: "K&R" -*- */
00027 
00028 /* irnore this module for docuscan
00029 % PlugInModuleIgnore
00030  */
00031 
00032 
00033 #include <locale.h>
00034 #include <libintl.h>
00035 
00036 
00037 #include "glbvars.h"
00038 #include "plug-ins/hard/modules/dsp.h"
00039 #include <fcntl.h>
00040 #include <sys/ioctl.h>
00041 
00042 #include "sranger_hwi.h"
00043 
00044 #include "dsp-pci32/xsm/xsmcmd.h"
00045 
00046 // need some SRanger io-controls 
00047 // HAS TO BE IDENTICAL TO THE DRIVER's FILE!
00048 #include "../plug-ins/hard/modules/sranger_ioctl.h"
00049 
00050 // important notice:
00051 // ----------------------------------------------------------------------
00052 // all numbers need to be byte swaped on i386 (no change on ppc!!) via 
00053 // int_2_sranger_int() or long_2_sranger_long()
00054 // before use from DSP and before writing back
00055 // ----------------------------------------------------------------------
00056 
00057 // enable debug:
00058 #define SRANGER_DEBUG(S) XSM_DEBUG (DBG_L4, "sranger_hwi_spm: " << S )
00059 
00060 extern GxsmPlugin sranger_hwi_pi;
00061 extern DSPControl *DSPControlClass;
00062 extern DSPMoverControl *DSPMoverClass;
00063 
00064 /* 
00065  * Init things
00066  */
00067 
00068 sranger_hwi_spm::sranger_hwi_spm():sranger_hwi_dev(){
00069         SRANGER_DEBUG("Init Sranger SPM");
00070         ScanningFlg=0;  
00071 }
00072 
00073 /*
00074  * Clean up
00075  */
00076 
00077 sranger_hwi_spm::~sranger_hwi_spm(){
00078         SRANGER_DEBUG("Finish Sranger SPM");
00079 }
00080 
00081 /* 
00082  * SRanger Read/Write procedure:
00083 
00084  int ret;
00085  ret=lseek (dsp, address, SRANGER_SEEK_DATA_SPACE);
00086  ret=read (dsp, data, length<<1); 
00087  ret=write (dsp, data, length<<1); 
00088 
00089  *
00090  */
00091 
00092 #define CONV_16(X) X = int_2_sranger_int (X)
00093 
00094 gint sranger_hwi_spm::RTQuery (gchar *property, double &val1, double &val2, double &val3){
00095         static ANALOG_VALUES    dsp_analog;
00096         lseek (dsp_alternative, magic_data.AIC_in, SRANGER_SEEK_DATA_SPACE);
00097         read  (dsp_alternative, &dsp_analog, sizeof (dsp_analog));
00098 
00099         // from DSP to PC
00100         CONV_16 (dsp_analog.x_scan);
00101         CONV_16 (dsp_analog.y_scan);
00102         CONV_16 (dsp_analog.z_scan);
00103 
00104         CONV_16 (dsp_analog.x_offset);
00105         CONV_16 (dsp_analog.y_offset);
00106         CONV_16 (dsp_analog.z_offset);
00107 
00108         val1 =  gapp->xsm->Inst->VZ() * gapp->xsm->Inst->Dig2VoltOut((double)dsp_analog.z_scan);
00109         val2 =  gapp->xsm->Inst->VX() * gapp->xsm->Inst->Dig2VoltOut((double)dsp_analog.x_scan);
00110         val3 =  gapp->xsm->Inst->VY() * gapp->xsm->Inst->Dig2VoltOut((double)dsp_analog.y_scan);
00111 
00112         if (gapp->xsm->Inst->OffsetMode () == OFM_ANALOG_OFFSET_ADDING){
00113                 val1 +=  gapp->xsm->Inst->VZ0() * gapp->xsm->Inst->Dig2VoltOut((double)dsp_analog.z_offset);
00114                 val2 +=  gapp->xsm->Inst->VX0() * gapp->xsm->Inst->Dig2VoltOut((double)dsp_analog.x_offset);
00115                 val3 +=  gapp->xsm->Inst->VY0() * gapp->xsm->Inst->Dig2VoltOut((double)dsp_analog.y_offset);
00116         }
00117 
00118 //      val1 =  (double)dsp_analog.z_scan;
00119 //      val2 =  (double)dsp_analog.x_scan;
00120 //      val3 =  (double)dsp_analog.y_scan;
00121 
00122         return TRUE;
00123 }
00124 
00125 void sranger_hwi_spm::ExecCmd(int Cmd){
00126         // ----------------------------------------------------------------------
00127         // all numbers need to be byte swaped on i386 (no change on ppc!!) via 
00128         // int_2_sranger_int() or long_2_sranger_long()
00129         // before use from DSP and before writing back
00130         // ----------------------------------------------------------------------
00131 
00132         switch (Cmd){
00133         case DSP_CMD_START: // enable Feedback
00134         {
00135                 static SPM_STATEMACHINE dsp_state;
00136                 if (IS_AFM_CTRL){ // AFM
00137                         // ensure use of linear feedback mode
00138                         dsp_state.set_mode = int_2_sranger_int(0);
00139                         dsp_state.clr_mode = int_2_sranger_int(MD_LOG);
00140                 } else { // STM, ...
00141                         // ensure use of logarithm feedback mode
00142                         dsp_state.set_mode = int_2_sranger_int(MD_LOG);
00143                         dsp_state.clr_mode = int_2_sranger_int(0);
00144                 }
00145                 lseek (dsp, magic_data.statemachine, SRANGER_SEEK_DATA_SPACE);
00146                 write (dsp, &dsp_state, MAX_WRITE_SPM_STATEMACHINE<<1); 
00147 
00148                 dsp_state.set_mode = int_2_sranger_int(MD_PID); // enable feedback
00149                 dsp_state.clr_mode = int_2_sranger_int(0);
00150                 lseek (dsp, magic_data.statemachine, SRANGER_SEEK_DATA_SPACE);
00151                 write (dsp, &dsp_state, MAX_WRITE_SPM_STATEMACHINE<<1); 
00152                 break;
00153         }
00154         case DSP_CMD_HALT: // disable Feedback
00155         {
00156                 static SPM_STATEMACHINE dsp_state;
00157                 dsp_state.set_mode = int_2_sranger_int(0);
00158                 dsp_state.clr_mode = int_2_sranger_int(MD_PID);
00159                 lseek (dsp, magic_data.statemachine, SRANGER_SEEK_DATA_SPACE);
00160                 write (dsp, &dsp_state, MAX_WRITE_SPM_STATEMACHINE<<1); 
00161                 break;
00162         }
00163         case DSP_CMD_APPROCH_MOV_XP: // auto approch "Mover"
00164         {
00165                 if (DSPMoverClass->mover_param.MOV_mode & AAP_MOVER_WAVE){
00166                         // scale waveform
00167                         // download waveform
00168                         DSPMoverClass->create_waveform (DSPMoverClass->mover_param.AFM_Amp, DSPMoverClass->mover_param.AFM_Speed);
00169                         lseek (dsp, EXTERN_DATA_FIFO_ADDRESS, SRANGER_SEEK_DATA_SPACE);
00170                         write (dsp, &DSPMoverClass->mover_param.MOV_waveform[0], DSPMoverClass->mover_param.MOV_wave_len<<1); 
00171                 }
00172                 static AUTOAPPROACH dsp_aap;
00173                 dsp_aap.start = int_2_sranger_int(1);           /* Initiate =WO */
00174                 dsp_aap.stop  = int_2_sranger_int(0);           /* Cancel   =WO */
00175                 dsp_aap.mover_mode = int_2_sranger_int(AAP_MOVER_XP_AUTO_APP | AAP_MOVER_XP | DSPMoverClass->mover_param.MOV_mode | DSPMoverClass->mover_param.MOV_output);
00176                 dsp_aap.piezo_steps = int_2_sranger_int((int)DSPMoverClass->mover_param.AFM_Steps);     /* max number of repetitions */
00177                 dsp_aap.n_wait      = int_2_sranger_int((int)(22100.0*1e-3*DSPMoverClass->mover_param.final_delay));                     /* delay inbetween cycels */
00178                 dsp_aap.u_piezo_amp = int_2_sranger_int((int)(32767*DSPMoverClass->mover_param.AFM_Amp/5)); /* Amplitude, Peak2Peak */
00179                 if (DSPMoverClass->mover_param.MOV_mode & AAP_MOVER_WAVE){
00180                         dsp_aap.u_piezo_max = int_2_sranger_int(DSPMoverClass->mover_param.MOV_wave_len); /* Length of Waveform*/
00181                         dsp_aap.piezo_speed = int_2_sranger_int(1);     /* Speed */
00182                 }else{
00183                         dsp_aap.u_piezo_max = int_2_sranger_int((int)(32767*DSPMoverClass->mover_param.AFM_Amp/5)/2); /* Amplitude, Peak */
00184                         dsp_aap.piezo_speed = (int)DSPMoverClass->mover_param.AFM_Speed;     /* Speed */
00185                         dsp_aap.piezo_speed = int_2_sranger_int(dsp_aap.piezo_speed >= 1 ? dsp_aap.piezo_speed : 1);
00186                 }
00187                 lseek (dsp, magic_data.autoapproach, SRANGER_SEEK_DATA_SPACE);
00188                 write (dsp, &dsp_aap,  MAX_WRITE_AUTOAPPROACH<<1); 
00189                 break;
00190         }
00191         case DSP_CMD_APPROCH: // auto approch "Slider"
00192                 break;
00193         case DSP_CMD_CLR_PA: // Stop all
00194         {
00195                 static AUTOAPPROACH dsp_aap;
00196                 dsp_aap.start = int_2_sranger_int(0);           /* Initiate =WO */
00197                 dsp_aap.stop  = int_2_sranger_int(1);           /* Cancel   =WO */
00198                 lseek (dsp, magic_data.autoapproach, SRANGER_SEEK_DATA_SPACE);
00199                 write (dsp, &dsp_aap,  2<<1); 
00200                 break;
00201         }
00202         case DSP_CMD_AFM_MOV_XM: // manual move X-
00203         case DSP_CMD_AFM_MOV_XP: // manual move X+
00204         case DSP_CMD_AFM_MOV_YM: // manual move Y-
00205         case DSP_CMD_AFM_MOV_YP: // manual move Y+
00206         {
00207                 if (DSPMoverClass->mover_param.MOV_mode & AAP_MOVER_WAVE){
00208                         // download waveform
00209                         // scale waveform
00210                         DSPMoverClass->create_waveform (DSPMoverClass->mover_param.AFM_Amp, DSPMoverClass->mover_param.AFM_Speed);
00211                         lseek (dsp, EXTERN_DATA_FIFO_ADDRESS, SRANGER_SEEK_DATA_SPACE);
00212                         write (dsp, &DSPMoverClass->mover_param.MOV_waveform[0], DSPMoverClass->mover_param.MOV_wave_len<<1); 
00213                 }
00214                 static AUTOAPPROACH dsp_aap;
00215                 dsp_aap.start = int_2_sranger_int(1);           /* Initiate =WO */
00216                 dsp_aap.stop  = int_2_sranger_int(0);           /* Cancel   =WO */
00217                 switch (Cmd){
00218                 case DSP_CMD_AFM_MOV_XM: dsp_aap.mover_mode = AAP_MOVER_XM; break;
00219                 case DSP_CMD_AFM_MOV_XP: dsp_aap.mover_mode = AAP_MOVER_XP; break;
00220                 case DSP_CMD_AFM_MOV_YM: dsp_aap.mover_mode = AAP_MOVER_YM; break;
00221                 case DSP_CMD_AFM_MOV_YP: dsp_aap.mover_mode = AAP_MOVER_YP; break;
00222                 }
00223 
00224                 dsp_aap.mover_mode = int_2_sranger_int(dsp_aap.mover_mode | DSPMoverClass->mover_param.MOV_mode | DSPMoverClass->mover_param.MOV_output);
00225 
00226                 dsp_aap.piezo_steps = int_2_sranger_int((int)DSPMoverClass->mover_param.AFM_Steps);     /* max number of repetitions */
00227                 dsp_aap.n_wait      = int_2_sranger_int(2);                         /* delay inbetween cycels */
00228                 dsp_aap.u_piezo_amp = int_2_sranger_int((int)(32767*DSPMoverClass->mover_param.AFM_Amp/5)); /* Amplitude, Peak2Peak */
00229                 if (DSPMoverClass->mover_param.MOV_mode & AAP_MOVER_WAVE){
00230                         dsp_aap.u_piezo_max = int_2_sranger_int(DSPMoverClass->mover_param.MOV_wave_len); /* Length of Waveform*/
00231                         dsp_aap.piezo_speed = int_2_sranger_int(1);     /* Speed */
00232                 }else{
00233                         dsp_aap.u_piezo_max = int_2_sranger_int((int)(32767*DSPMoverClass->mover_param.AFM_Amp/5)/2); /* Amplitude, Peak */
00234                         dsp_aap.piezo_speed = (int)DSPMoverClass->mover_param.AFM_Speed;     /* Speed */
00235                         dsp_aap.piezo_speed = int_2_sranger_int(dsp_aap.piezo_speed >= 1 ? dsp_aap.piezo_speed : 1);
00236                 }
00237                 lseek (dsp, magic_data.autoapproach, SRANGER_SEEK_DATA_SPACE);
00238                 write (dsp, &dsp_aap,  MAX_WRITE_AUTOAPPROACH<<1); 
00239                 break;
00240         }
00241 
00242 //              case DSP_CMD_:
00243 //                              break;
00244         default: break;
00245         }
00246 }
00247 
00248 // just note that we are scanning next...
00249 void sranger_hwi_spm::StartScan2D(){
00250         DSPControlClass->StartScanPreCheck ();
00251         ScanningFlg=1; 
00252         KillFlg=FALSE; // if this gets TRUE while scanning, you should stopp it!!
00253 }
00254 
00255 // and its done now!
00256 void sranger_hwi_spm::EndScan2D(){ 
00257         static AREA_SCAN dsp_scan;
00258         static DATA_FIFO dsp_fifo;
00259         ScanningFlg=0; 
00260         lseek (dsp, magic_data.scan, SRANGER_SEEK_DATA_SPACE);
00261         read  (dsp, &dsp_scan, sizeof (dsp_scan));
00262         // cancel scanning?
00263         if (dsp_scan.pflg) {
00264                 dsp_scan.start = int_2_sranger_int(0);
00265                 dsp_scan.stop  = int_2_sranger_int(1);
00266                 lseek (dsp, magic_data.scan, SRANGER_SEEK_DATA_SPACE);
00267                 write (dsp, &dsp_scan, MAX_WRITE_SCAN<<1);
00268         }
00269         // wait until ready
00270         do {
00271                 usleep (50000); // give some time
00272                 read  (dsp, &dsp_scan, sizeof (dsp_scan));
00273         } while (dsp_scan.pflg);
00274 
00275         read  (dsp, &dsp_scan, sizeof (dsp_scan));
00276 
00277         // reset DSP fifo read position
00278         dsp_fifo.r_position = int_2_sranger_int(0);
00279         dsp_fifo.w_position = int_2_sranger_int(0);
00280         dsp_fifo.fill  = int_2_sranger_int(0);
00281         dsp_fifo.stall = int_2_sranger_int(0); // unlock scan now
00282         lseek (dsp, magic_data.datafifo, SRANGER_SEEK_DATA_SPACE);
00283         write (dsp, &dsp_fifo, (MAX_WRITE_DATA_FIFO+3)<<1);
00284 
00285         // from current position to Origin
00286         dsp_scan.Xpos = long_2_sranger_long (dsp_scan.Xpos);
00287         dsp_scan.Ypos = long_2_sranger_long (dsp_scan.Ypos);
00288         SRANGER_DEBUG("SR:EndScan2D last XYPos: " << (dsp_scan.Xpos>>16) << ", " << (dsp_scan.Ypos>>16));
00289 
00290         double Mdx = - (double)dsp_scan.Xpos;
00291         double Mdy = - (double)dsp_scan.Ypos;
00292         double mvspd = (1<<16) * sranger_hwi_pi.app->xsm->Inst->X0A2Dig (DSPControlClass->move_speed_x) 
00293                 / DSPControlClass->frq_ref;
00294         double steps = round (sqrt (Mdx*Mdx + Mdy*Mdy) / mvspd);
00295         dsp_scan.fm_dx = (long)round(Mdx/steps);
00296         dsp_scan.fm_dy = (long)round(Mdy/steps);
00297         dsp_scan.num_steps_move_xy = (long)steps;
00298 
00299         // setup scan for zero size scan and move to 0,0 in scan coord sys
00300         dsp_scan.fm_dx = long_2_sranger_long (dsp_scan.fm_dx);
00301         dsp_scan.fm_dy = long_2_sranger_long (dsp_scan.fm_dy);
00302         dsp_scan.num_steps_move_xy = long_2_sranger_long (dsp_scan.num_steps_move_xy);
00303         dsp_scan.start = int_2_sranger_int(1);
00304         dsp_scan.srcs_xp  = int_2_sranger_int(0);
00305         dsp_scan.srcs_xm  = int_2_sranger_int(0);
00306         dsp_scan.dnx_probe = int_2_sranger_int(-1);
00307         dsp_scan.nx_pre = int_2_sranger_int(0);
00308         dsp_scan.nx = int_2_sranger_int(0);
00309         dsp_scan.ny = int_2_sranger_int(0);
00310         dsp_scan.Xpos = long_2_sranger_long (dsp_scan.Xpos);
00311         dsp_scan.Ypos = long_2_sranger_long (dsp_scan.Ypos);
00312 
00313         // initiate "return to origin" "dummy" scan now
00314         lseek (dsp, magic_data.scan, SRANGER_SEEK_DATA_SPACE);
00315         write (dsp, &dsp_scan, (MAX_WRITE_SCAN)<<1);
00316 
00317         // verify Pos,
00318         // wait until ready
00319         do {
00320                 usleep (100000); // give some time
00321                 read  (dsp, &dsp_scan, sizeof (dsp_scan));
00322         } while (dsp_scan.pflg);
00323         dsp_scan.Xpos = long_2_sranger_long (dsp_scan.Xpos);
00324         dsp_scan.Ypos = long_2_sranger_long (dsp_scan.Ypos);
00325         SRANGER_DEBUG("SR:EndScan2D return XYPos: " << (dsp_scan.Xpos>>16) << ", " << (dsp_scan.Ypos>>16));
00326 }
00327 
00328 // we are paused
00329 void sranger_hwi_spm::PauseScan2D(){
00330         ScanningFlg=0;
00331 }
00332 
00333 // and its going againg
00334 void sranger_hwi_spm::ResumeScan2D(){
00335         ScanningFlg=1;
00336 }
00337 
00338 // this does almost the same as the XSM_Hardware base class would do, 
00339 // but you may want to do sth. yourself here
00340 void sranger_hwi_spm::SetOffset(long x, long y){
00341         static long old_x=123456789, old_y=123456789;
00342         static MOVE_OFFSET dsp_move;
00343         double dx,dy,steps;
00344         const double fract = 1<<16;
00345 
00346         if (old_x == x && old_y == y) return;
00347 
00348         SRANGER_DEBUG("SetOffset: " << x << ", " << y);
00349         old_x = x; old_y = y;
00350         
00351         do {
00352                 lseek (dsp, magic_data.move, SRANGER_SEEK_DATA_SPACE);
00353                 read  (dsp, &dsp_move, sizeof (dsp_move)); 
00354                 if (int_2_sranger_int (dsp_move.pflg)){
00355                         if (long_2_sranger_long (dsp_move.num_steps)){
00356                                 usleep (50000);
00357                         }
00358                 }
00359         } while (int_2_sranger_int (dsp_move.pflg) && long_2_sranger_long (dsp_move.num_steps)); // wait if there is a move in progress
00360 
00361         // convert -- only on i386 necessary
00362         dsp_move.start = int_2_sranger_int (1);
00363         dsp_move.Xnew  = int_2_sranger_int (x);
00364         dsp_move.Ynew  = int_2_sranger_int (y);
00365 
00366         dx = ((double)x * fract) - (double)long_2_sranger_long (dsp_move.XPos);
00367         dy = ((double)y * fract) - (double)long_2_sranger_long (dsp_move.YPos);
00368         double mvspd = fract * sranger_hwi_pi.app->xsm->Inst->X0A2Dig (DSPControlClass->move_speed_x) / DSPControlClass->frq_ref;
00369         steps = round (sqrt (dx*dx + dy*dy) / mvspd);
00370         dsp_move.f_dx = long_2_sranger_long ((long)round(dx/steps));
00371         dsp_move.f_dy = long_2_sranger_long ((long)round(dy/steps));
00372         dsp_move.num_steps = long_2_sranger_long ((long)steps);
00373         
00374         lseek (dsp, magic_data.move, SRANGER_SEEK_DATA_SPACE);
00375         write (dsp, &dsp_move, MAX_WRITE_MOVE<<1);
00376 }
00377 
00378 
00379 /*
00380  * Do ScanLine in multiple Channels Mode
00381  *
00382  * yindex:  Index of Line
00383  * xdir:    Scanning Direction (1:+X / -1:-X) eg. for/back scan
00384  * lsscrs:  LineScan Sources, MUX/Channel Configuration
00385  * PC31 has can handle 2 Channels of 16bit data simultan, using 4-fold Mux each
00386  *      additional the PID-Outputvalue can be used and the PID Src is set by MUXA
00387  *      it may be possible to switch MUXB while scanning -- test it !!!
00388  * bit     0 1 2 3  4 5 6 7  8 9 10 11  12 13 14 15 ...
00389  * PC31:   ==PID==  =MUX-A=  ==MUX-B==  
00390  * PCI32:  ==PID==  A======  B========  C==== D====
00391  * SR:     
00392  *    eg.  Z-Value  Fz/I     Fric...
00393  * example:
00394  * value   1 0 0 0  1 0 0 0  1 0  0  0  0...
00395  * buffers B0       B1       B2
00396  * 3 buffers used for transfer (B0:Z, B1:Force, B2:Friction)
00397  *
00398  * Mob:     List of MemObjs. to store Data
00399  *
00400  * 
00401  */
00402 
00403 void sranger_hwi_spm::ScanLineM(int yindex, int xdir, int lssrcs, Mem2d *Mob[MAX_SRCS_CHANNELS], int ix0 ){
00404                 static Mem2d **Mob0, **Mob1, **Mob2, **Mob3;
00405                 static int ydir=0;
00406                 static int nsrcs0, nsrcs1, nsrcs2, nsrcs3;
00407                 static int running = FALSE;
00408                 static AREA_SCAN dsp_scan;
00409                 static DATA_FIFO dsp_fifo;
00410 
00411                 int num_srcs = 0;
00412                 int bi = 0;
00413                 // calc # of srcs
00414                 do{
00415                                 if(lssrcs & (1<<bi++))
00416                                                 ++num_srcs;
00417                 }while(bi<16);
00418 
00419                 // ix0 not used yet, not subscan
00420                 if (yindex == -2 && xdir == 1){ // first init step of XP (->)
00421                                 // cancel any running scan now
00422                                 lseek (dsp, magic_data.scan, SRANGER_SEEK_DATA_SPACE);
00423                                 read  (dsp, &dsp_scan, sizeof (dsp_scan));
00424                                 // cancel scanning?
00425                                 if (dsp_scan.pflg) {
00426                                                 dsp_scan.start = int_2_sranger_int (0);
00427                                                 dsp_scan.stop  = int_2_sranger_int (1);
00428                                                 lseek (dsp, magic_data.scan, SRANGER_SEEK_DATA_SPACE);
00429                                                 write (dsp, &dsp_scan, MAX_WRITE_SCAN<<1);
00430                                                 usleep (50000); // give some time to stop
00431                                 }
00432 
00433                                 // reset DSP fifo read position
00434                                 lseek (dsp, magic_data.datafifo, SRANGER_SEEK_DATA_SPACE);
00435                                 dsp_fifo.r_position = int_2_sranger_int (0);
00436                                 dsp_fifo.w_position = int_2_sranger_int (0);
00437                                 dsp_fifo.fill = int_2_sranger_int (0);
00438                                 dsp_fifo.stall = int_2_sranger_int (1); // lock scan now, released at start of fifo read thread
00439                                 write (dsp, &dsp_fifo, (MAX_WRITE_DATA_FIFO+3)<<1);
00440                                 
00441                                 // clean up any old vector probe data
00442                                 DSPControlClass->free_probedata_arrays ();
00443 
00444                                 // get current params and position
00445                                 // Note: current Xpos/Ypos should be 0/0, so we can change the rot.matrix now!
00446                                 // ------> SRanger::EndScan2D always returns to 0/0 <------
00447                                 lseek (dsp, magic_data.scan, SRANGER_SEEK_DATA_SPACE);
00448                                 read  (dsp, &dsp_scan, sizeof (dsp_scan));
00449 
00450                                 // convert
00451                                 dsp_scan.Xpos = long_2_sranger_long (dsp_scan.Xpos);
00452                                 dsp_scan.Ypos = long_2_sranger_long (dsp_scan.Ypos);
00453 
00454                                 SRANGER_DEBUG("SR:Start/Rot XYPos: " << (dsp_scan.Xpos>>16) << ", " << (dsp_scan.Ypos>>16));
00455 
00456                                 // setup scan
00457                                 dsp_scan.start = int_2_sranger_int (1);
00458 
00459                                 // 1st XP scan here
00460                                 //   enable do probe at XP?
00461                                 if (DSPControlClass->Source && DSPControlClass->probe_trigger_raster_points > 0)
00462                                         dsp_scan.srcs_xp  = int_2_sranger_int (lssrcs | 0x0008);
00463                                 else
00464                                         dsp_scan.srcs_xp  = int_2_sranger_int (lssrcs);
00465 
00466                                 dsp_scan.srcs_xm  = int_2_sranger_int (0); // init to zero, set later
00467 
00468                                 // 2nd scan, setup later, see below
00469                                 dsp_scan.srcs_2nd_xp  = int_2_sranger_int (0); // init to zero, set later
00470                                 dsp_scan.srcs_2nd_xm  = int_2_sranger_int (0); // init to zero, set later
00471 
00472                                 dsp_scan.Zoff_2nd_xp  = int_2_sranger_int (0);
00473                                 dsp_scan.Zoff_2nd_xm  = int_2_sranger_int (0);
00474 
00475                                 // enable probe?
00476                                 if (DSPControlClass->Source && DSPControlClass->probe_trigger_raster_points){
00477                                         if (DSPControlClass->Source && DSPControlClass->probe_trigger_raster_points > 0){
00478                                                 dsp_scan.dnx_probe = int_2_sranger_int (DSPControlClass->probe_trigger_raster_points);
00479                                                 dsp_scan.raster_a = int_2_sranger_int ((int)(1.+ceil((DSPControlClass->probe_trigger_raster_points-1.)/2)));
00480                                                 dsp_scan.raster_b = int_2_sranger_int ((int)(1.+floor((DSPControlClass->probe_trigger_raster_points-1.)/2)));
00481                                         } else {
00482                                                 dsp_scan.dnx_probe = int_2_sranger_int ((int)fabs((double)DSPControlClass->probe_trigger_raster_points));
00483                                                 dsp_scan.raster_a = int_2_sranger_int (0);
00484                                                 dsp_scan.raster_b = int_2_sranger_int (0);
00485                                         }
00486                                 }
00487                                 else{
00488                                         dsp_scan.dnx_probe = int_2_sranger_int (-1); // not yet, auto probe trigger
00489                                         dsp_scan.raster_a = int_2_sranger_int (0);
00490                                         dsp_scan.raster_b = int_2_sranger_int (0);
00491                                 }
00492 
00493                                 // rotation matrix -- where is the round() function gone in math.h ???
00494                                 dsp_scan.rotxx = int_2_sranger_int ((int)(rotmxx*(1<<15)));
00495                                 dsp_scan.rotxy = int_2_sranger_int ((int)(rotmxy*(1<<15)));
00496                                 dsp_scan.rotyx = int_2_sranger_int ((int)(rotmyx*(1<<15)));
00497                                 dsp_scan.rotyy = int_2_sranger_int ((int)(rotmyy*(1<<15)));
00498 
00499                                 dsp_scan.nx = int_2_sranger_int (Nx); // num datapoints in X to take
00500                                 dsp_scan.ny = int_2_sranger_int (Ny); // num datapoints in Y to take
00501 
00502                                 double frac  = (1<<16);
00503                                 double fs_dx = frac * sranger_hwi_pi.app->xsm->Inst->XA2Dig (DSPControlClass->scan_speed_x) 
00504                                         / DSPControlClass->frq_ref;
00505                                 double fs_dy = frac * sranger_hwi_pi.app->xsm->Inst->YA2Dig (DSPControlClass->scan_speed_x) 
00506                                         / DSPControlClass->frq_ref;
00507                                         
00508                                 // fs_dx * N =!= frac*Dx  -> N = ceil [frac*Dx/fs_dx]  -> fs_dx' = frac*Dx/N
00509 
00510                                 // N: dnx
00511                                 dsp_scan.dnx = (DSP_INT) ceil (frac * Dx / fs_dx);
00512                                 dsp_scan.dny = (DSP_INT) ceil (frac * Dy / fs_dy);
00513                                 
00514                                 dsp_scan.fs_dx = (DSP_LONG) (frac*Dx / ceil (frac * Dx / fs_dx));
00515                                 dsp_scan.fs_dy = (DSP_LONG) (frac*Dy / ceil (frac * Dy / fs_dy));
00516                                 
00517                                 // from current position to Origin/Start
00518                                 // init .dsp_scan for initial move to scan start pos
00519                                 double Mdx = -(double)Nx*dsp_scan.dnx*dsp_scan.fs_dx/2. - (double)dsp_scan.Xpos;
00520                                 double Mdy =  (double)Ny*dsp_scan.dny*dsp_scan.fs_dy/2. - (double)dsp_scan.Ypos;
00521                                 double mvspd = frac * sranger_hwi_pi.app->xsm->Inst->X0A2Dig (DSPControlClass->move_speed_x) 
00522                                         / DSPControlClass->frq_ref;
00523                                 double steps = round (sqrt (Mdx*Mdx + Mdy*Mdy) / mvspd);
00524                                 dsp_scan.fm_dx = (long)round(Mdx/steps);
00525                                 dsp_scan.fm_dy = (long)round(Mdy/steps);
00526                                 dsp_scan.num_steps_move_xy = (long)steps;
00527 
00528                                 // convert to DSP
00529                                 dsp_scan.fs_dx = long_2_sranger_long (dsp_scan.fs_dx);
00530                                 dsp_scan.fs_dy = long_2_sranger_long (dsp_scan.fs_dy);
00531                                 dsp_scan.dnx = int_2_sranger_int (dsp_scan.dnx);
00532                                 dsp_scan.dny = int_2_sranger_int (dsp_scan.dny);
00533 
00534                                 dsp_scan.fm_dx = long_2_sranger_long (dsp_scan.fm_dx);
00535                                 dsp_scan.fm_dy = long_2_sranger_long (dsp_scan.fm_dy);
00536                                 dsp_scan.num_steps_move_xy = long_2_sranger_long (dsp_scan.num_steps_move_xy);
00537 
00538                                 dsp_scan.fm_dzx = long_2_sranger_long (0);
00539                                 dsp_scan.fm_dzy = long_2_sranger_long (0);
00540 
00541                                 dsp_scan.nx_pre = int_2_sranger_int(dsp_scan.dnx * DSPControlClass->pre_points);
00542 
00543 
00544                                 // and start fifo read thread, it releases the
00545                                 // scan-lock (dspfifo.stall flag) and it terminates if it is
00546                                 // done or scan stop is requested!
00547                                 nsrcs0 = num_srcs;
00548                                 Mob0   = Mob;
00549                                 nsrcs1 = nsrcs2 = nsrcs3 = 0;
00550                                 Mob1   = Mob2   = Mob3   =  NULL;
00551                                 running= FALSE;
00552                                 return;
00553                 }
00554                 if (yindex == -2 && xdir == -1){ // second init step of XM (<-)
00555                                 dsp_scan.srcs_xm = int_2_sranger_int (lssrcs);
00556                                 nsrcs1 = num_srcs;
00557                                 Mob1   = Mob;
00558                                 return;
00559                 }
00560                 if (yindex == -2 && xdir == 2){ // ... init step of 2ND_XP (2>)
00561                                 dsp_scan.srcs_2nd_xp = int_2_sranger_int (lssrcs);
00562                                 nsrcs2 = num_srcs;
00563                                 Mob2   = Mob;
00564                                 return;
00565                 }
00566                 if (yindex == -2 && xdir == -2){ // ... init step of 2ND_XM (<2)
00567                                 dsp_scan.srcs_2nd_xm = int_2_sranger_int (lssrcs);
00568                                 nsrcs3 = num_srcs;
00569                                 Mob3   = Mob;
00570                                 return;
00571                 }
00572                 if (! running && yindex >= 0){ // now send scan setup and start reading data fifo
00573                                 running = TRUE;
00574 
00575                                 if (yindex > 0){ // bottom up, negate move and scan dY
00576                                                 ydir = -1;
00577                                                 dsp_scan.fm_dy = -long_2_sranger_long (dsp_scan.fm_dy);
00578                                                 dsp_scan.fs_dy = -long_2_sranger_long (dsp_scan.fs_dy);
00579                                                 dsp_scan.fm_dy = long_2_sranger_long (dsp_scan.fm_dy);
00580                                                 dsp_scan.fs_dy = long_2_sranger_long (dsp_scan.fs_dy);
00581                                 }else
00582                                                 ydir = 1;
00583 
00584                                 // initiate scan now, this starts a 2D scan process!!!
00585                                 lseek (dsp, magic_data.scan, SRANGER_SEEK_DATA_SPACE);
00586                                 write (dsp, &dsp_scan, (MAX_WRITE_SCAN)<<1); // write ix,iy - only here
00587 
00588                                 start_fifo_read (yindex, nsrcs0, nsrcs1, nsrcs2, nsrcs3, Mob0, Mob1, Mob2, Mob3);
00589                 }
00590 
00591                 // call this while waiting for background data updates on screen...
00592                 //              ReadScanData (yindex, num_srcs, Mob); has moved into the thread now
00593 
00594                 // wait for data, updated display, data move is done in background by the fifo read thread
00595                 do {
00596                                 usleep (20000); // release cpu time
00597                                 gapp->check_events (); // do not lock
00598                                 DSPControlClass->Probing_eventcheck_callback (NULL, DSPControlClass);
00599                                 if (ydir > 0 && yindex <= fifo_data_y_index) break;
00600                                 if (ydir < 0 && yindex >= fifo_data_y_index) break;
00601 
00602                 } while (ScanningFlg);
00603 
00604                 // update line, only if not canceled
00605                 if (ScanningFlg)
00606                                 CallIdleFunc ();
00607 
00608                 // pop all remaining events
00609                 DSPControlClass->Probing_eventcheck_callback (NULL, DSPControlClass);
00610 }

Generated on Sat Apr 1 09:04:19 2006 for GXSM by  doxygen 1.4.6