00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
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
00037 #define AD_MAX_VOLT 10.
00038 #define DA_MAX_VOLT 10.
00039 #define DA_MAX_VAL 0x7ffe
00040 #define UDA_MAX_VAL 0xffff
00041
00042
00043
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
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)
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
00067 #define MD_SCAN 0x10
00068 #define MD_BLK 0x80
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;
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
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;
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;
00207 spa.emission = 100.*(x*x*x*x/10.);
00208 }
00209
00210 x = (spa.chanhv*1e-3-3.);
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
00239
00240
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
00303 case DSP_CMD_GETINFO:
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
00393
00394
00395
00396
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 }