spaleed_emu.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 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 // SPA-LEED Emu by kernel
00029 
00030 #include <linux/kernel.h>
00031 #include <math.h>
00032 #include "pci32/dspC32/spa/spacmd.h"
00033 
00034 /* Konstanten für DSP  */
00035 #define AD_MAX_VOLT 10.     /* Max Spannung bei Wert DA_MAX_VAL */
00036 #define DA_MAX_VOLT 10.     /* Max Spannung bei Wert DA_MAX_VAL */
00037 #define DA_MAX_VAL  0x7ffe  /* Max Wert für signed 16 Bit Wandler */
00038 #define UDA_MAX_VAL  0xffff  /* Max Wert für unsigend 16 Bit Wandler */
00039 
00040 /* Spannung <==> Int-Wert Umrechenfaktoren */
00041 /* Bipolar */
00042 #define         U2FLT(X) ((X)*(float)(DA_MAX_VAL)/AD_MAX_VOLT)
00043 #define         U2INT(X) (int)((X)*(float)(DA_MAX_VAL)/AD_MAX_VOLT+.5)
00044 #define         INT2U(X) ((float)(X)/DA_MAX_VAL*AD_MAX_VOLT)
00045 
00046 /* Uinpolar */
00047 #define         UNI_U2FLT(X) ((X)*(float)(UDA_MAX_VAL)/AD_MAX_VOLT)
00048 #define         UNI_U2INT(X) (int)((X)*(float)(UDA_MAX_VAL)/AD_MAX_VOLT+.5)
00049 #define         UNI_INT2U(X) ((float)(X)/UDA_MAX_VAL*AD_MAX_VOLT)
00050 
00051 
00052 #define  DPRAMBASE     (volatile int*)  (spa.dsp->virtual_dpram)
00053 
00054 #define  CMD_BUFFER    (volatile int*)  (DPRAMBASE+0x00)   /* cmd buffer */
00055 #define  CMD_PARM      (volatile int*)  (DPRAMBASE+0x01)   /* */
00056 #define  BUFFER        (volatile int*)  (DPRAMBASE+DSP_BUFFER_START)   /* */
00057 #define  BUFFERL       (volatile unsigned long*)  (DPRAMBASE+DSP_BUFFER_START)   /* */
00058 #define  DPRAML        (volatile unsigned long*)  (DPRAMBASE)   /* */
00059 #define  LCDBUFFER     (volatile unsigned long*)  (DPRAMBASE+DSP_LCDBUFFER)
00060 #define  MAXSCANPOINTS (DSP_DATA_REG_LEN)
00061 
00062 #define  DSPack  spa.dsp->SrvReqAck=TRUE
00063 
00064 #define MD_CMD          0x08    /* Komando (SRQ) abfragen, ausführen aktiv */
00065 #define MD_SCAN         0x10    /* Beamfinder aktiv */
00066 #define MD_BLK          0x80    /* Blinken zur Kontrolle */
00067 
00068 #define LEDPORT(X)       *((unsigned long*)(DPRAMBASE+DSP_USR_DIO))=X
00069 
00070 void LCDclear(void);
00071 int LCDprintf(const char *format, ...);
00072 
00073 void calc_spaparam(void);
00074 
00075 void scan2d(void);
00076 void linescan(int n, float y);
00077 
00078 unsigned long ChanneltronCounts(float x, float y);
00079 
00080 int GetParamI(unsigned int N);
00081 float GetParamF(unsigned int N);
00082 
00083 typedef struct{
00084     float ms;
00085     float X0, Y0;
00086     float len;
00087     int   N;
00088     int   Nx,Ny;
00089     float lenxy;
00090     float alpha, alphaAlt;
00091     float E;
00092     double rotmxx, rotmyy, rotmxy, rotmyx, rotoffx, rotoffy;
00093 } SCANP;
00094 
00095 SCANP scanp;
00096 
00097 typedef struct{
00098     struct dspsim_thread_data *dsp;
00099     SCANP scanp;
00100     int LastSPAMode;
00101     int SPAMode;
00102 
00103     double extractor;
00104     double chanhv, chanmult;
00105     double chanrepeller;
00106     double cryfocus;
00107     double filament, emission;
00108     double gunfocus, focusval;
00109     double gunanode;
00110     double smpdist;
00111     double smptemp;
00112     double S,d,ctheta,sens;
00113     double growing;
00114 } SPALEED;
00115 
00116 SPALEED spa;
00117 
00118 int InitEmu(struct dspsim_thread_data *dsp){
00119     spa.dsp    = dsp;
00120     *CMD_BUFFER=0;
00121     spa.LastSPAMode = spa.SPAMode = MD_CMD;
00122     LCDclear();
00123     LCDprintf("-* DSP Emu *-");
00124     LEDPORT(spa.SPAMode);  
00125 
00126     spa.scanp.rotmxx = spa.scanp.rotmyy = 1.;
00127     spa.scanp.rotmxy = spa.scanp.rotmyx = spa.scanp.rotoffx = spa.scanp.rotoffy = 0.;
00128 
00129     spa.scanp.ms  = 1.;
00130     spa.scanp.X0  = spa.scanp.Y0 = 0.;
00131     spa.scanp.Nx  = spa.scanp.Ny = 40;
00132     spa.scanp.N   = 100;
00133     spa.scanp.len = 100.;
00134     spa.scanp.lenxy = 100.;
00135     spa.scanp.E   = 72.;
00136 
00137     spa.scanp.alpha = spa.scanp.alphaAlt = 0.;
00138 
00139     spa.extractor = 0.5;
00140     spa.chanhv    = 2000.0;
00141     spa.chanrepeller = 1.0;
00142     spa.cryfocus  = 0.5;
00143     spa.filament  = 2.4;
00144     spa.gunfocus  = 0.5;
00145     spa.gunanode  = 1.1;
00146     spa.smpdist   = 20.;
00147     spa.smptemp   = 300.;
00148     spa.sens      = 100.;
00149     spa.d         = 3.141;
00150     spa.ctheta    = cos(5./57.);
00151     spa.S         = 2*spa.d*spa.ctheta*sqrt(spa.scanp.E/150.4);
00152     spa.growing   = 0.;
00153 
00154     calc_spaparam();
00155 
00156     return 0;
00157 }
00158 
00159 void ExitEmu(void){
00160     ;
00161 }
00162 
00163 int GetParamI(unsigned int N){ 
00164     float *ptr = (float*)(CMD_PARM + N);
00165     return (int)(*ptr);
00166     //    union { int i; float f; unsigned int u;} u; u.i = *(CMD_PARM + N); return u.i; 
00167 }
00168 
00169 float GetParamF(unsigned int N){ 
00170     float *ptr = (float*)(CMD_PARM + N);
00171     return *ptr;
00172 }
00173 
00174 void LCDclear(void){
00175     int n;
00176     for(n=0; n < DSP_LCDBUFFERLEN;)
00177         *(LCDBUFFER+n++) = ' ';
00178 }
00179 
00180 int LCDprintf(const char *format, ...){
00181     va_list ap;                                                                 
00182     int nr_of_chars;                                                            
00183     va_start (ap, format);
00184     nr_of_chars = vsprintf ((char*)LCDBUFFER, format, ap);
00185     va_end (ap);
00186     return (nr_of_chars);
00187 }                                                                             
00188    
00189 void calc_spaparam(){
00190   double x;
00191   x = spa.gunfocus-0.5; // Peak Foucus Parameter
00192   spa.focusval = 50.*x*x+0.05;
00193 
00194   if(spa.filament > 2.85) spa.emission=0.0;
00195   else{ 
00196     x = spa.filament; // Filament Emission
00197     spa.emission = 100.*(x*x*x*x/10.);
00198   }
00199 
00200   x = (spa.chanhv*1e-3-3.); // Channeltron Characteristic
00201   x = 1.+x*x*x*x*x/50.;
00202   if( x < 0. ) spa.chanmult = 0.;
00203   else  spa.chanmult = x;
00204 }
00205 
00206 void ServiceRequest(struct dspsim_thread_data *dsp){
00207   switch(*CMD_BUFFER & 0xff){
00208 
00209   case DSP_CMD_SCAN_PARAM:
00210       spa.scanp.X0  = GetParamF(DSP_X0);
00211       spa.scanp.Y0  = GetParamF(DSP_Y0);
00212       spa.scanp.len = GetParamF(DSP_len);
00213       spa.scanp.N   = GetParamI(DSP_N);
00214       spa.scanp.alpha = GetParamF(DSP_alpha);
00215       spa.scanp.ms  = GetParamF(DSP_ms);
00216       spa.scanp.E   = GetParamF(DSP_E);
00217       spa.S     = 2*spa.d*spa.ctheta*sqrt(spa.scanp.E/150.4);
00218       if(spa.scanp.alpha != spa.scanp.alphaAlt){
00219           spa.scanp.rotmyy = spa.scanp.rotmxx = cos((double)scanp.alpha);
00220           spa.scanp.rotmyx = -(spa.scanp.rotmxy = sin((double)spa.scanp.alpha));
00221           spa.scanp.alphaAlt = spa.scanp.alpha;
00222       }
00223       spa.scanp.rotoffx = spa.scanp.X0;
00224       spa.scanp.rotoffy = spa.scanp.Y0;
00225       //      set_dacXY(0.,0.); 
00226       //      set_dac(DAC_E_CHANNEL, U2INT(spa.scanp.E));
00227       //      CountMaxAllow = (unsigned long)(3e6*1e-3*spa.scanp.ms);
00228       DSPack;
00229       break;
00230 
00231   case DSP_CMD_SPACTRL_SET:
00232       spa.extractor = GetParamF(DSP_SPACTRL_EXTRACTOR);
00233       spa.chanhv    = GetParamF(DSP_SPACTRL_CHANHV);
00234       spa.chanrepeller = GetParamF(DSP_SPACTRL_CHANREPELLER);
00235       spa.cryfocus  = GetParamF(DSP_SPACTRL_CRYFOCUS);
00236       spa.filament  = GetParamF(DSP_SPACTRL_FILAMENT);
00237       spa.gunfocus  = GetParamF(DSP_SPACTRL_GUNFOCUS);
00238       spa.gunanode  = GetParamF(DSP_SPACTRL_GUNANODE);
00239       spa.smpdist   = GetParamF(DSP_SPACTRL_SMPDIST);
00240       spa.smptemp   = GetParamF(DSP_SPACTRL_SMPTEMP);
00241       spa.growing   = GetParamF(DSP_SPACTRL_GROWING);
00242       calc_spaparam();
00243       DSPack;
00244       break;
00245 
00246   case DSP_CMD_SCAN_START:
00247       spa.scanp.len = GetParamF(DSP_len);
00248       spa.scanp.E   = GetParamF(DSP_E);
00249       
00250       spa.LastSPAMode = spa.SPAMode;
00251       spa.SPAMode = (spa.SPAMode & ~(MD_CMD)) | MD_SCAN;
00252       linescan(0, GetParamF(DSP_Y0));
00253       spa.SPAMode = spa.LastSPAMode;
00254       DSPack;
00255       break;
00256 
00257   case DSP_CMD_SWAPDPRAM:
00258       DSPack;
00259       break;
00260 
00261   case DSP_CMD_SCAN2D:
00262       spa.scanp.Nx  = GetParamI(DSP_NX);
00263       spa.scanp.Ny  = GetParamI(DSP_NY);
00264       spa.scanp.lenxy = GetParamF(DSP_LXY);
00265       spa.LastSPAMode = spa.SPAMode;
00266       spa.SPAMode = (spa.SPAMode & ~(MD_CMD)) | MD_SCAN;
00267       scan2d();
00268       spa.SPAMode = spa.LastSPAMode;
00269       DSPack;
00270       break;
00271 
00272   case DSP_CMD_GETCNT:
00273       spa.scanp.ms  = GetParamF(DSP_ms);
00274       spa.scanp.E   = GetParamF(DSP_E);
00275 
00276       *(BUFFERL) = ChanneltronCounts(0., 0.);
00277 
00278       DSPack;
00279       break;
00280 
00281   default: break;
00282   }
00283   REQD_DSP = FALSE;
00284 }
00285 
00286 void scan2d(void){
00287     float x,y,Ux, dUx, Uy, dUy;
00288     int   i,j,k;
00289     if(spa.scanp.Nx > 1)
00290         Ux  = -spa.scanp.lenxy/2.;
00291     else
00292         Ux = 0.;
00293     dUx = spa.scanp.lenxy/spa.scanp.Nx;
00294     
00295     if(spa.scanp.Ny > 1)
00296     Uy = spa.scanp.lenxy/2.;
00297     else
00298         Uy = 0.;
00299     dUy = spa.scanp.lenxy/spa.scanp.Ny;
00300     
00301     for(y=Uy, k=j=0; j<spa.scanp.Ny; j++, y-=dUy)
00302         for(x=Ux, i=0; i<spa.scanp.Nx; i++, k++, x+=dUx){
00303             if( k >= MAXSCANPOINTS )
00304                 return;
00305             *(BUFFERL + k) = ChanneltronCounts(x, y);
00306         }
00307 }
00308 
00309 void linescan(int n, float y){
00310     float x, dx;
00311     int nmax;
00312     nmax = n + spa.scanp.N + 4;
00313     if( nmax > MAXSCANPOINTS )
00314         nmax = MAXSCANPOINTS;
00315 
00316     dx = spa.scanp.len/(float)spa.scanp.N;
00317     x = -spa.scanp.len/2.;
00318 
00319     for(; n<nmax; n++, x+=dx)
00320         *(BUFFERL + n) = ChanneltronCounts(x, y);
00321 }
00322 
00323 double phi_xy(double dx, double dy){
00324     double q23=0.;
00325     if(dx<0.)
00326         q23=180.;
00327     if(fabs(dx)>1e-5)
00328         return q23+180.*atan(dy/dx)/M_PI;
00329     else return dy>0.?90.:-90.;
00330 }
00331 
00332 unsigned long ChanneltronCounts(float x, float y){
00333     static unsigned long noise=957456292L;
00334     unsigned long bits;
00335     double xt,yt,r,a,cntnoise,peak,gaus,lor,timefac;
00336     xt = x*spa.scanp.rotmxx + y*spa.scanp.rotmxy + spa.scanp.rotoffx;
00337     yt = x*spa.scanp.rotmyx + y*spa.scanp.rotmyy + spa.scanp.rotoffy;
00338     // rotoffx,y
00339     // rotmxx,yy,xy,yx
00340     // spa.scanp.E
00341     // spa.scanp.ms
00342     // x,y in Volt
00343     r  = sqrt(xt*xt+yt*yt)/spa.scanp.E;
00344     if(r > 10000.){
00345         a = fmod(phi_xy(xt,yt)+180.,45.)-22.5;
00346         a *= 2.;
00347         r -= a*a;
00348         if(r>12000)
00349             return 0;
00350     }
00351     xt *= spa.S/spa.sens;
00352     yt *= spa.S/spa.sens;
00353     r  = 1.+sqrt(xt*xt+yt*yt);
00354     xt = xt > 0. ? fmod(xt+5., 10.) - 5. : fmod(xt-5., 10.) + 5.;
00355     yt = yt > 0. ? fmod(yt+5., 10.) - 5. : fmod(yt-5., 10.) + 5.;
00356     bits = (noise & 0x80000000 ? 0:1) + (noise & 0x400000 ? 0:1);
00357     noise <<= 1;
00358     noise |= bits;
00359     if(spa.growing>0.){
00360       timefac = cos((double)jiffies/1000. * M_PI * spa.growing);
00361     } else timefac = 1.;
00362     gaus     = timefac*exp((-xt*xt-yt*yt)/spa.focusval/spa.focusval)/spa.focusval;
00363     lor      = 1./(spa.focusval+xt*xt+yt*yt);
00364     peak     = spa.emission*spa.scanp.ms*(gaus+lor)/r;
00365     cntnoise = sqrt(peak/spa.scanp.ms/100) * (10.-spa.chanrepeller) * (noise&0x5f) + (noise&3);
00366     return (unsigned long)((cntnoise + peak)*spa.chanmult);
00367 }

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