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

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