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 "pci32/dspC32/spa/spacmd.h"
00033
00034
00035 #define AD_MAX_VOLT 10.
00036 #define DA_MAX_VOLT 10.
00037 #define DA_MAX_VAL 0x7ffe
00038 #define UDA_MAX_VAL 0xffff
00039
00040
00041
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
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)
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
00065 #define MD_SCAN 0x10
00066 #define MD_BLK 0x80
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
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;
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;
00197 spa.emission = 100.*(x*x*x*x/10.);
00198 }
00199
00200 x = (spa.chanhv*1e-3-3.);
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
00226
00227
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
00339
00340
00341
00342
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 }