spaleed_bb.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 "/home/czubanowski/Gxsm/pci32/dspC32/spa/spacmd.h"
00033 
00034 
00035 #define BB_TEST_CNT       // Test ChanneltronCounting on startup 0.1-100ms
00036 #define BB_POLLING_MODE   // use polling Mode for Gate, else use IRQ
00037 
00038 
00039 // Burr Brow Configuration:
00040 #define  BB_MEM_BASE 0xcd000
00041 
00042 #define  BB_MEM_AUTOPROBE  0
00043 #define  BB_MEM_BASE_START 0xc0000
00044 #define  BB_MEM_BASE_END   0xe0000
00045 #define  BB_MEM_SIZE 0x400
00046 #define  BB_IRQLINE  5
00047 
00048 #define  BB_XY_DEFLECTON_BOARD 3
00049 #define  BB_ENERGY_BOARD 1
00050 
00051 
00052 // BB Id's
00053 #define  BB_PCI20001C1         (0x1+0x2+0x8+0x10)
00054 #define  BB_PCI20001C2         (0x1+0x4+0x8+0x10)
00055 #define  BB_IDMSK              0x1f
00056 
00057 #define  BB_PCI20006M2         0xe2 // Analog Output 16bit single channel DAC
00058 #define  BB_PCI20006M3         0xe3 // Analog Output 16bit two channel DAC
00059 #define  BB_PCI20007M          0xea // Counter, Timer, Puls
00060 
00061 #define  BB_BASE_MODULE(N)     ( spa[BB_CARD_NO].BB_membase + (((N)&3)<<8) )
00062 // carrier register
00063 #define  BB_MODULE_PRESENT(M)  (readb( BB_BASE_MODULE(0) ) & (1<<(8-(M))))
00064 #define  BB_IRQ_STATUS         readb( BB_BASE_MODULE(0) + 0x40 )
00065 
00066 // PCI-20006M 16-Bit DAC Module register offsets
00067 // N=3 für X,Y
00068 // N=1 für X,E
00069 // BB 16bit DACs module on position N
00070 #define  BB_DAC_X(X,N)         writew( (X), BB_BASE_MODULE(N) + 0x0d)
00071 #define  BB_DAC_Y(X,N)         writew( (X), BB_BASE_MODULE(N) + 0x15)
00072 #define  BB_DAC_OUT(N)         writeb(0xff, BB_BASE_MODULE(N) + 0x1b)
00073 
00074 // BB Timer/Counter module on position 2
00075 #define  BB_TMR_MODULE_ID      2
00076 // PCI-20006M 16-Bit DAC Module register offsets
00077 #define  BB_TMR_BASE           ( BB_BASE_MODULE(BB_TMR_MODULE_ID) )
00078 #define  BB_TMR_RTGREG         ( BB_TMR_BASE + 0x04 )  // BB TimerCounter Module Base Address
00079 #define  BB_TMR_RTGREG_LO      ( BB_TMR_RTGREG )       // 0x04 Rate Generator count Reg. low 16, (rw)
00080 #define  BB_TMR_RTGREG_HI      ( BB_TMR_RTGREG + 1)    // 0x05 Rate Generator count Reg. hi 16, (rw)
00081 
00082 #define  BB_TMR_CNT0REG        ( BB_TMR_BASE + 0x08 )  // Counter 0 count register (rw)
00083 #define  BB_TMR_CNT1REG        ( BB_TMR_BASE + 0x09 )  // Counter 1 count register (rw)  
00084 #define  BB_TMR_CNT2REG        ( BB_TMR_BASE + 0x0A )  // Counter 2 count register (rw)  
00085 #define  BB_TMR_CNT3REG        ( BB_TMR_BASE + 0x06 )  // Counter 3 count register (rw)  
00086 
00087 #define  BB_TMR_RTGCNT3CTRL    ( BB_TMR_BASE + 0x07 )  // Rate Generator and Counter 3 control register (w)
00088 #define  BB_TMR_CNT012CTRL     ( BB_TMR_BASE + 0x0B )  // Counter 0,1,2 control register (w)
00089 #define  BB_TMR_CNTGATECTRL    ( BB_TMR_BASE + 0x0C )  // Counter gate control (w)
00090 
00091 #define  BB_CRTL_MSK           0x40
00092 
00093 typedef struct{
00094     short lb0;
00095     short hb0;
00096     short lb1;
00097     short hb1;
00098 } BB_GATEGEN;
00099 
00100 #ifdef BB_TEST_CNT
00101 static int irq_count=0;
00102 static int timeout_count=0;
00103 #endif
00104 
00105 
00106 
00107 /* Konstanten für DSP  */
00108 #define AD_MAX_VOLT 10.     /* Max Spannung bei Wert DA_MAX_VAL */
00109 #define DA_MAX_VOLT 10.     /* Max Spannung bei Wert DA_MAX_VAL */
00110 #define DA_MAX_VAL  0x7ffe  /* Max Wert für signed 16 Bit Wandler */
00111 #define UDA_MAX_VAL  0xffff  /* Max Wert für unsigend 16 Bit Wandler */
00112 
00113 /* Spannung <==> Int-Wert Umrechenfaktoren */
00114 /* Bipolar */
00115 #define         U2FLT(X) ((X)*(float)(DA_MAX_VAL)/AD_MAX_VOLT)
00116 #define         U2INT(X) (int)((X)*(float)(DA_MAX_VAL)/AD_MAX_VOLT)
00117 #define         INT2U(X) ((float)(X)/DA_MAX_VAL*AD_MAX_VOLT)
00118 
00119 /* Uinpolar */
00120 #define         UNI_U2FLT(X) ((X)*(float)(UDA_MAX_VAL)/AD_MAX_VOLT)
00121 #define         UNI_U2INT(X) (int)((X)*(float)(UDA_MAX_VAL)/AD_MAX_VOLT)
00122 #define         UNI_INT2U(X) ((float)(X)/UDA_MAX_VAL*AD_MAX_VOLT)
00123 
00124 
00125 #define  DPRAMBASE     (volatile int*)  (spa[BB_CARD_NO].dsp->virtual_dpram)
00126 
00127 #define  CMD_BUFFER    (volatile int*)  (DPRAMBASE+0x00)   /* cmd buffer */
00128 #define  CMD_PARM      (volatile int*)  (DPRAMBASE+0x01)   /* */
00129 #define  BUFFER        (volatile int*)  (DPRAMBASE+DSP_BUFFER_START)   /* */
00130 #define  BUFFERL       (volatile unsigned long*)  (DPRAMBASE+DSP_BUFFER_START)   /* */
00131 #define  DPRAML        (volatile unsigned long*)  (DPRAMBASE)   /* */
00132 #define  LCDBUFFER     (volatile unsigned long*)  (DPRAMBASE+DSP_LCDBUFFER)
00133 #define  MAXSCANPOINTS (DSP_DATA_REG_LEN)
00134 
00135 #define  DSPack  spa[BB_CARD_NO].dsp->SrvReqAck=TRUE
00136 
00137 #define MD_CMD          0x08    /* Komando (SRQ) abfragen, ausführen aktiv */
00138 #define MD_SCAN         0x10    /* Beamfinder aktiv */
00139 #define MD_BLK          0x80    /* Blinken zur Kontrolle */
00140 
00141 #define LEDPORT(X)       *((unsigned long*)(DPRAMBASE+DSP_USR_DIO))=X
00142 
00143 void LCDclear(void);
00144 int LCDprintf(const char *format, ...);
00145 
00146 void scan2d(void);
00147 void linescan(int n, float y);
00148 
00149 unsigned long ChanneltronCounts(float x, float y);
00150 
00151 int GetParamI(unsigned int N);
00152 float GetParamF(unsigned int N);
00153 
00154 void BB_SetVolt(double x, double y);
00155 void BB_SetEnergy(double En);
00156 unsigned long BB_CntRead(void);
00157 double BB_InitCnt(double gate);
00158 void BB_SetCnt(void);
00159 int BB_ReadyCnt(void);
00160 
00161 static void bb_gate_interrupt(int irq, void *dev_id, struct pt_regs *regs);
00162 
00163 #define MAX_BB_CARDS 1
00164 #define BB_CARD_NO 0
00165 
00166 typedef struct{
00167     float ms;
00168     float X0, Y0;
00169     float len;
00170     int   N;
00171     int   Nx,Ny;
00172     float lenxy;
00173     float alpha, alphaAlt;
00174     float E;
00175     double rotmxx, rotmyy, rotmxy, rotmyx, rotoffx, rotoffy;
00176 } SCANP;
00177 
00178 typedef struct{
00179     struct dspsim_thread_data *dsp;
00180     SCANP scanp;
00181 
00182     BB_GATEGEN bb_gate_reg;
00183 
00184     char *BB_membase;
00185     unsigned char bbid;
00186     unsigned char bbmodid[3];
00187 
00188     int    major, minor;
00189     int    bb_irq;
00190     struct wait_queue *waitq;
00191     struct timer_list timeout_tmr;
00192     unsigned long bb_timeout_flg;
00193 
00194     int LastSPAMode;
00195     int SPAMode;
00196 
00197     double extractor;
00198     double chanhv;
00199     double chanrepeller;
00200     double cryfocus;
00201     double filament, expfilament;
00202     double gunfocus;
00203     double gunanode;
00204     double smpdist;
00205     double smptemp;
00206     double S,d,ctheta,sens;
00207     double growing;
00208 } SPALEED;
00209 
00210 static SPALEED spa[MAX_BB_CARDS];
00211 
00212 
00213 #ifdef BB_TEST_CNT
00214 void bb_test_counting(double E, double ms){
00215    unsigned long n;
00216    BB_SetEnergy(E);
00217    ms=BB_InitCnt(ms);
00218    spa[BB_CARD_NO].scanp.ms  = ms;
00219    KDEBUG("BB_SPA: irqcount %d, tmoutcount: %d\n", irq_count, timeout_count);
00220    n=jiffies;
00221    KDEBUG("BB_SPA: Testing,   %d/10ms, Cnt(0,0)=%d\n",(int)(ms*10.), (int)ChanneltronCounts(0., 0.));
00222    n=jiffies-n;
00223    KDEBUG("BB_SPA: irqcount %d, tmoutcount: %d jiffies: %d\n", irq_count, timeout_count, (int)n);
00224 }
00225 #endif
00226 
00227 int InitEmu(struct dspsim_thread_data *dsp){
00228     int err=0;
00229     int i;
00230     // BB init
00231 
00232     KDEBUG("BurrBrow PCI20001CX module\nBB auto detection: %d\n", BB_MEM_AUTOPROBE );
00233 
00234     spa[BB_CARD_NO].dsp   = dsp;
00235     spa[BB_CARD_NO].major = pcdsp_major;
00236     spa[BB_CARD_NO].minor = BB_CARD_NO;
00237 
00238     spa[BB_CARD_NO].BB_membase = (unsigned char*)BB_MEM_BASE;
00239     
00240     switch( spa[BB_CARD_NO].bbid = (readb( BB_BASE_MODULE(0) ) & BB_IDMSK) ){
00241     case BB_PCI20001C1: KDEBUG("BB carrier PCI20001C1 found\n"); break;
00242     case BB_PCI20001C2: KDEBUG("BB carrier PCI20001C2 found\n"); break;
00243     default: KDEBUG("no BB found at %x, id=%x. Trying to autodetect.\n", 
00244                     (int)spa[BB_CARD_NO].BB_membase, spa[BB_CARD_NO].bbid); err=1; break;
00245     }
00246 
00247     if( err && BB_MEM_AUTOPROBE )
00248         for(spa[BB_CARD_NO].BB_membase = (unsigned char*)BB_MEM_BASE_START;
00249             err && (unsigned long)(spa[BB_CARD_NO].BB_membase) < BB_MEM_BASE_END; spa[BB_CARD_NO].BB_membase += BB_MEM_SIZE)
00250             switch( spa[BB_CARD_NO].bbid = (readb( BB_BASE_MODULE(0) ) & BB_IDMSK) ){
00251             case BB_PCI20001C1: KDEBUG("BB carrier PCI20001C1 found\n"); err=0; break;
00252             case BB_PCI20001C2: KDEBUG("BB carrier PCI20001C2 found\n"); err=0; break;
00253             default: continue;
00254             }
00255 
00256     if(err){
00257         spa[BB_CARD_NO].BB_membase = (unsigned char*)BB_MEM_BASE;
00258         KDEBUG("Error: BB SPA-LEED module can't find BB card.\n" );
00259         return 1;
00260     }
00261     else
00262         KDEBUG("BB SPA-LEED module, BB baseaddr: %x\n", (int)spa[BB_CARD_NO].BB_membase );
00263                                      
00264     for(i=0; i<3; ++i){
00265         spa[BB_CARD_NO].bbmodid[i]=0;
00266         if( BB_MODULE_PRESENT(i+1) == 0 )
00267             switch( (spa[BB_CARD_NO].bbmodid[i] = readb( BB_BASE_MODULE(i+1) )) ){
00268             case BB_PCI20006M2: KDEBUG("BB module %d is a PCI20006M, single DAC 16bit\n", i+1); break;
00269             case BB_PCI20006M3: KDEBUG("BB module %d is a PCI20006M, two DAC 16bit\n", i+1); break;
00270             case BB_PCI20007M:  KDEBUG("BB module %d is a PCI20007M, Counter, Timer, Puls\n", i+1); break;
00271             default: KDEBUG("unknown BB module with id=%x found\n", spa[BB_CARD_NO].bbmodid[i]); break;
00272             }
00273         else
00274             KDEBUG("BB module is %d not present.\n", i+1);
00275     }
00276 
00277     spa[BB_CARD_NO].waitq  = NULL;
00278     spa[BB_CARD_NO].bb_irq = request_irq(BB_IRQLINE, 
00279                                          bb_gate_interrupt, 
00280                                          0,
00281                                          PCDSP_DEVICE_NAME,
00282                                          NULL );
00283 //                                       &spa[BB_CARD_NO] );
00284 
00285     KDEBUG("requested irq is %d, id=%d\n", BB_IRQLINE, spa[BB_CARD_NO].bb_irq );
00286     KDEBUG("BB Irq Status is: %x\n", BB_IRQ_STATUS );
00287     KDEBUG("BB detection OK.\n" );
00288 
00289     // DSP-EMU init
00290     *CMD_BUFFER=0;
00291     spa[BB_CARD_NO].LastSPAMode = spa[BB_CARD_NO].SPAMode = MD_CMD;
00292     LCDclear();
00293     LCDprintf("-* DSP Emu *-");
00294     LEDPORT(spa[BB_CARD_NO].SPAMode);  
00295 
00296     spa[BB_CARD_NO].scanp.rotmxx = spa[BB_CARD_NO].scanp.rotmyy = 1.;
00297     spa[BB_CARD_NO].scanp.rotmxy = spa[BB_CARD_NO].scanp.rotmyx 
00298         = spa[BB_CARD_NO].scanp.rotoffx = spa[BB_CARD_NO].scanp.rotoffy = 0.;
00299 
00300     spa[BB_CARD_NO].scanp.ms  = 1.;
00301     spa[BB_CARD_NO].scanp.X0  = spa[BB_CARD_NO].scanp.Y0 = 0.;
00302     spa[BB_CARD_NO].scanp.Nx  = spa[BB_CARD_NO].scanp.Ny = 40;
00303     spa[BB_CARD_NO].scanp.N   = 100;
00304     spa[BB_CARD_NO].scanp.len = 100.;
00305     spa[BB_CARD_NO].scanp.lenxy = 100.;
00306     spa[BB_CARD_NO].scanp.E   = 1.;
00307 
00308     spa[BB_CARD_NO].scanp.alpha = spa[BB_CARD_NO].scanp.alphaAlt = 0.;
00309 
00310     spa[BB_CARD_NO].extractor = 0.5;
00311     spa[BB_CARD_NO].chanhv    = 2000.0;
00312     spa[BB_CARD_NO].chanrepeller = 1.0;
00313     spa[BB_CARD_NO].cryfocus  = 0.5;
00314     spa[BB_CARD_NO].filament  = 2.4;
00315     spa[BB_CARD_NO].gunfocus  = 0.5;
00316     spa[BB_CARD_NO].gunanode  = 1.1;
00317     spa[BB_CARD_NO].smpdist   = 20.;
00318     spa[BB_CARD_NO].smptemp   = 300.;
00319     spa[BB_CARD_NO].sens      = 100.;
00320     spa[BB_CARD_NO].d         = 3.141;
00321     spa[BB_CARD_NO].ctheta    = 0.996155128; /*cos(5./57.);*/
00322     spa[BB_CARD_NO].S         = 1.;
00323     spa[BB_CARD_NO].growing   = 0.;
00324 
00325 #ifdef BB_TEST_CNT
00326     bb_test_counting(1., 0.1);
00327     bb_test_counting(1., 0.5);
00328     bb_test_counting(1., 1.0);
00329     bb_test_counting(1., 5.0);
00330     bb_test_counting(1., 10.0);
00331     bb_test_counting(1., 50.0);
00332     bb_test_counting(1., 100.0);
00333     bb_test_counting(1., 500.0);
00334     spa[BB_CARD_NO].scanp.ms  = 1.;
00335 #endif
00336 
00337    return 0;
00338 }
00339 
00340 void ExitEmu(void){
00341     KDEBUG("BB cleanup\n");
00342 #ifdef BB_TEST_CNT
00343     KDEBUG("BB_SPA: irqcount %d, tmoutcount: %d\n", irq_count, timeout_count);
00344 #endif
00345     free_irq(BB_IRQLINE, NULL);
00346 }
00347 
00348 int GetParamI(unsigned int N){ 
00349     float *ptr = (float*)(CMD_PARM + N);
00350     return (int)(*ptr);
00351     //    union { int i; float f; unsigned int u;} u; u.i = *(CMD_PARM + N); return u.i; 
00352 }
00353 
00354 float GetParamF(unsigned int N){ 
00355     float *ptr = (float*)(CMD_PARM + N);
00356     return *ptr;
00357 }
00358 
00359 void LCDclear(void){
00360     int n;
00361     for(n=0; n < DSP_LCDBUFFERLEN;)
00362         *(LCDBUFFER+n++) = ' ';
00363 }
00364 
00365 int LCDprintf(const char *format, ...){
00366     va_list ap;                                                                 
00367     int nr_of_chars;                                                            
00368     va_start (ap, format);
00369     nr_of_chars = vsprintf ((char*)LCDBUFFER, format, ap);
00370     va_end (ap);
00371     return (nr_of_chars);
00372 }                                                                             
00373    
00374 void ServiceRequest(struct dspsim_thread_data *dsp){
00375   switch(*CMD_BUFFER & 0xff){
00376 
00377   case DSP_CMD_SCAN_PARAM:
00378       spa[BB_CARD_NO].scanp.X0  = GetParamF(DSP_X0);
00379       spa[BB_CARD_NO].scanp.Y0  = GetParamF(DSP_Y0);
00380       spa[BB_CARD_NO].scanp.len = GetParamF(DSP_len);
00381       spa[BB_CARD_NO].scanp.N   = GetParamI(DSP_N);
00382       spa[BB_CARD_NO].scanp.alpha = GetParamF(DSP_alpha);
00383       spa[BB_CARD_NO].scanp.ms  = GetParamF(DSP_ms);
00384       spa[BB_CARD_NO].scanp.E   = GetParamF(DSP_E);
00385 
00386       spa[BB_CARD_NO].scanp.rotmxx = GetParamF(DSP_MXX);
00387       spa[BB_CARD_NO].scanp.rotmxy = GetParamF(DSP_MXY);
00388       spa[BB_CARD_NO].scanp.rotmyx = GetParamF(DSP_MYX);
00389       spa[BB_CARD_NO].scanp.rotmyy = GetParamF(DSP_MYY);
00390      
00391      KDEBUG("MXX %d\n", (int)(100*spa[BB_CARD_NO].scanp.rotmxx));
00392      KDEBUG("MYY %d\n", (int)(100*spa[BB_CARD_NO].scanp.rotmyy));
00393 
00394      /*
00395      if(spa[BB_CARD_NO].scanp.alpha != spa[BB_CARD_NO].scanp.alphaAlt){
00396           spa[BB_CARD_NO].scanp.rotmyy = spa[BB_CARD_NO].scanp.rotmxx 
00397               = cos((double)spa[BB_CARD_NO].scanp.alpha);
00398           spa[BB_CARD_NO].scanp.rotmyx = -(spa[BB_CARD_NO].scanp.rotmxy
00399               = sin((double)spa[BB_CARD_NO].scanp.alpha));
00400           spa[BB_CARD_NO].scanp.alphaAlt = spa[BB_CARD_NO].scanp.alpha;
00401       }
00402       */
00403       
00404       spa[BB_CARD_NO].scanp.rotoffx = spa[BB_CARD_NO].scanp.X0;
00405       spa[BB_CARD_NO].scanp.rotoffy = spa[BB_CARD_NO].scanp.Y0;
00406       BB_SetVolt(0., 0.);
00407       BB_SetEnergy(spa[BB_CARD_NO].scanp.E);
00408       DSPack;
00409       break;
00410 
00411   case DSP_CMD_SPACTRL_SET:
00412       spa[BB_CARD_NO].extractor = GetParamF(DSP_SPACTRL_EXTRACTOR);
00413       spa[BB_CARD_NO].chanhv    = GetParamF(DSP_SPACTRL_CHANHV);
00414       spa[BB_CARD_NO].chanrepeller = GetParamF(DSP_SPACTRL_CHANREPELLER);
00415       spa[BB_CARD_NO].cryfocus  = GetParamF(DSP_SPACTRL_CRYFOCUS);
00416       spa[BB_CARD_NO].filament  = GetParamF(DSP_SPACTRL_FILAMENT);
00417       spa[BB_CARD_NO].gunfocus  = GetParamF(DSP_SPACTRL_GUNFOCUS);
00418       spa[BB_CARD_NO].gunanode  = GetParamF(DSP_SPACTRL_GUNANODE);
00419       spa[BB_CARD_NO].smpdist   = GetParamF(DSP_SPACTRL_SMPDIST);
00420       spa[BB_CARD_NO].smptemp   = GetParamF(DSP_SPACTRL_SMPTEMP);
00421       spa[BB_CARD_NO].growing   = GetParamF(DSP_SPACTRL_GROWING);
00422       DSPack;
00423       break;
00424 
00425   case DSP_CMD_SCAN_START:
00426       spa[BB_CARD_NO].scanp.len = GetParamF(DSP_len);
00427       spa[BB_CARD_NO].scanp.E   = GetParamF(DSP_E);
00428       
00429       spa[BB_CARD_NO].LastSPAMode = spa[BB_CARD_NO].SPAMode;
00430       spa[BB_CARD_NO].SPAMode = (spa[BB_CARD_NO].SPAMode & ~(MD_CMD)) | MD_SCAN;
00431       linescan(0, GetParamF(DSP_Y0));
00432       spa[BB_CARD_NO].SPAMode = spa[BB_CARD_NO].LastSPAMode;
00433       DSPack;
00434       break;
00435 
00436   case DSP_CMD_SWAPDPRAM:
00437       DSPack;
00438       break;
00439 
00440   case DSP_CMD_SCAN2D:
00441       spa[BB_CARD_NO].scanp.Nx  = GetParamI(DSP_NX);
00442       spa[BB_CARD_NO].scanp.Ny  = GetParamI(DSP_NY);
00443       spa[BB_CARD_NO].scanp.lenxy = GetParamF(DSP_LXY);
00444       spa[BB_CARD_NO].LastSPAMode = spa[BB_CARD_NO].SPAMode;
00445       spa[BB_CARD_NO].SPAMode = (spa[BB_CARD_NO].SPAMode & ~(MD_CMD)) | MD_SCAN;
00446       scan2d();
00447       spa[BB_CARD_NO].SPAMode = spa[BB_CARD_NO].LastSPAMode;
00448       DSPack;
00449       break;
00450 
00451   case DSP_CMD_GETCNT:
00452       spa[BB_CARD_NO].scanp.ms  = GetParamF(DSP_ms);
00453       spa[BB_CARD_NO].scanp.E   = GetParamF(DSP_E);
00454 
00455       spa[BB_CARD_NO].scanp.ms = BB_InitCnt(spa[BB_CARD_NO].scanp.ms);
00456       BB_SetEnergy(spa[BB_CARD_NO].scanp.E);
00457 
00458       *(BUFFERL) = ChanneltronCounts(0., 0.);
00459 
00460       DSPack;
00461       break;
00462 
00463   default: break;
00464   }
00465   REQD_DSP = FALSE;
00466 }
00467 
00468 void scan2d(void){
00469     float x,y,Ux, dUx, Uy, dUy;
00470     int   i,j,k;
00471     if(spa[BB_CARD_NO].scanp.Nx > 1)
00472         Ux  = -spa[BB_CARD_NO].scanp.lenxy/2.;
00473     else
00474         Ux = 0.;
00475     dUx = spa[BB_CARD_NO].scanp.lenxy/spa[BB_CARD_NO].scanp.Nx;
00476     
00477     if(spa[BB_CARD_NO].scanp.Ny > 1)
00478     Uy = spa[BB_CARD_NO].scanp.lenxy/2.;
00479     else
00480         Uy = 0.;
00481     dUy = spa[BB_CARD_NO].scanp.lenxy/spa[BB_CARD_NO].scanp.Ny;
00482     
00483     spa[BB_CARD_NO].scanp.ms = BB_InitCnt(spa[BB_CARD_NO].scanp.ms);
00484     BB_SetEnergy(spa[BB_CARD_NO].scanp.E);
00485 
00486     for(y=Uy, k=j=0; j<spa[BB_CARD_NO].scanp.Ny; j++, y-=dUy){
00487         BB_SetVolt(Ux, y);
00488         mysleep(3);
00489         for(x=Ux, i=0; i<spa[BB_CARD_NO].scanp.Nx; i++, k++, x+=dUx){
00490             if( k >= MAXSCANPOINTS )
00491                 return;
00492             *(BUFFERL + k) = ChanneltronCounts(x, y);
00493         }
00494     }
00495 }
00496 
00497 void linescan(int n, float y){
00498     float x, dx;
00499     int nmax;
00500     nmax = n + spa[BB_CARD_NO].scanp.N + 4;
00501     if( nmax > MAXSCANPOINTS )
00502         nmax = MAXSCANPOINTS;
00503 
00504     dx = spa[BB_CARD_NO].scanp.len/(float)spa[BB_CARD_NO].scanp.N;
00505     x = -spa[BB_CARD_NO].scanp.len/2.;
00506 
00507     spa[BB_CARD_NO].scanp.ms = BB_InitCnt(spa[BB_CARD_NO].scanp.ms);
00508     BB_SetEnergy(spa[BB_CARD_NO].scanp.E);
00509     BB_SetVolt(x, y);
00510     mysleep(3);
00511     for(; n<nmax; n++, x+=dx)
00512         *(BUFFERL + n) = ChanneltronCounts(x, y);
00513 }
00514 
00515 #ifndef BB_POLLING_MODE
00516 static void bb_irq_timeout(unsigned long data){
00517     SPALEED *thisspa = &spa[data];
00518     ++thisspa->bb_timeout_flg;
00519     wake_up_interruptible( &thisspa->waitq );
00520 #ifdef BB_TEST_CNT
00521     ++timeout_count;
00522 #endif
00523 }
00524 #endif
00525 
00526 unsigned long ChanneltronCounts(float x, float y){
00527 
00528 #ifdef BB_POLLING_MODE
00529     // no IRQ is used
00530     static struct timer_list timeout_tmr = { NULL, NULL, 0, 0, timeout };
00531 
00532     BB_SetVolt(x, y);
00533     BB_SetCnt();
00534 
00535     if(spa[BB_CARD_NO].scanp.ms > 12.)
00536         mysleep( (unsigned long) (spa[BB_CARD_NO].scanp.ms/10.) );
00537     else{
00538         wakeups=1000;
00539         while( BB_ReadyCnt() && --wakeups);
00540         if( ! BB_ReadyCnt() )
00541             return BB_CntRead();
00542     }
00543 
00544     wakeups=0;
00545     while( BB_ReadyCnt() && wakeups < 100){
00546         del_timer(&timeout_tmr);
00547         timeout_tmr.expires = jiffies + 1;
00548         add_timer(&timeout_tmr);
00549         interruptible_sleep_on( &waitq );
00550         wakeups++;
00551     } 
00552 
00553 #else
00554     // use IRQ
00555 
00556     BB_SetVolt(x, y);
00557     BB_SetCnt();
00558 
00559     // use bb_irq_timeout function to wakeup if irq is missed
00560     init_timer( &spa[BB_CARD_NO].timeout_tmr );
00561     spa[BB_CARD_NO].timeout_tmr.expires  = jiffies + 1 + (unsigned long)(spa[BB_CARD_NO].scanp.ms/10.) ;
00562     spa[BB_CARD_NO].timeout_tmr.data     = BB_CARD_NO;
00563     spa[BB_CARD_NO].timeout_tmr.function = bb_irq_timeout;
00564     spa[BB_CARD_NO].bb_timeout_flg       = 0;
00565     add_timer( &spa[BB_CARD_NO].timeout_tmr );
00566 
00567     sti();
00568     interruptible_sleep_on( &spa[BB_CARD_NO].waitq );
00569     cli();
00570 
00571     del_timer( &spa[BB_CARD_NO].timeout_tmr );
00572     
00573 #endif
00574     if( ! BB_ReadyCnt() )
00575         return BB_CntRead();
00576     else
00577         return 13;
00578 }
00579 
00580 // BB implementation
00581 // BurrBrown Stuff is following
00582 
00583 
00584 void BB_SetVolt(double x, double y){
00585     double xt,yt;
00586     xt = x*spa[BB_CARD_NO].scanp.rotmxx + y*spa[BB_CARD_NO].scanp.rotmxy 
00587         + spa[BB_CARD_NO].scanp.rotoffx;
00588     yt = x*spa[BB_CARD_NO].scanp.rotmyx + y*spa[BB_CARD_NO].scanp.rotmyy 
00589         + spa[BB_CARD_NO].scanp.rotoffy;
00590 
00591     BB_DAC_X( (int)(xt), BB_XY_DEFLECTON_BOARD );
00592     BB_DAC_Y( (int)(yt), BB_XY_DEFLECTON_BOARD );
00593     BB_DAC_OUT( BB_XY_DEFLECTON_BOARD );
00594 }
00595 
00596 
00597 void BB_SetEnergy(double En){
00598     BB_DAC_X( U2INT(En), BB_ENERGY_BOARD );
00599     BB_DAC_Y( U2INT(En), BB_ENERGY_BOARD );
00600     BB_DAC_OUT( BB_ENERGY_BOARD );
00601 }
00602 
00603 unsigned long BB_CntRead(void){
00604     unsigned long lb0, hb0, lb1, hb1, cnt, stat0, stat1;
00605     writeb( 0xc6, BB_TMR_CNT012CTRL );
00606     cnt = 0;
00607 
00608     stat0 = readb( BB_TMR_CNT0REG ) & BB_CRTL_MSK;
00609     lb0 = 0xff - readb( BB_TMR_CNT0REG );
00610     hb0 = 0xff - readb( BB_TMR_CNT0REG );
00611     if(stat0 == 0) 
00612         cnt = (((hb0<<8) | lb0) + 1) << 16;
00613 
00614     stat1 = readb( BB_TMR_CNT1REG ) & BB_CRTL_MSK;
00615     lb1 = 0xff - readb( BB_TMR_CNT1REG );
00616     hb1 = 0xff - readb( BB_TMR_CNT1REG );
00617     if(stat1 == 0){
00618         cnt |= (hb1<<8) | lb1;
00619         ++cnt;
00620     }
00621     
00622     return cnt;
00623 }
00624 
00625 double BB_InitCnt(double gate){
00626     // gate in ms
00627     long n0, n1;
00628     double factor;
00629 
00630     if( gate < 0.1 ) 
00631         factor = 1.;
00632     else 
00633         if( gate < 1. ) 
00634             factor = 10.;
00635         else
00636             if( gate < 10. )
00637                 factor = 100.;
00638             else
00639                 if( gate < 100. )
00640                     factor = 1000.;
00641                 else
00642                     factor = 10000.;
00643 
00644     n1 = (long)(2.*factor);
00645     n0 = (long)(4000.*gate/factor);
00646 
00647     if( n0 < 2 ){
00648         n0 = 2;
00649         gate = (double)n0 * (double)n1 / 8000.;
00650     }
00651 
00652     spa[BB_CARD_NO].bb_gate_reg.lb0 = (n0&0xff);
00653     spa[BB_CARD_NO].bb_gate_reg.hb0 = ((n0>>8)&0xff);
00654     spa[BB_CARD_NO].bb_gate_reg.lb1 = (n1&0xff);
00655     spa[BB_CARD_NO].bb_gate_reg.hb1 = ((n1>>8)&0xff);
00656 
00657     return gate;
00658 }
00659 
00660 void BB_SetCnt(void){
00661     writeb( 0x34, BB_TMR_CNT012CTRL );  // Counter 0 in mode 2
00662     writeb( 0xff, BB_TMR_CNT0REG );     // divides threw    65532
00663     writeb( 0xff, BB_TMR_CNT0REG );
00664 
00665     writeb( 0x74, BB_TMR_CNT012CTRL );  // Counter 1 in mode 2
00666     writeb( 0xff, BB_TMR_CNT1REG );     // divides threw    65532
00667     writeb( 0xff, BB_TMR_CNT1REG );
00668 
00669     writeb( 0x34, BB_TMR_RTGCNT3CTRL );          // rategenerator 0 in mode 2
00670     writeb( spa[BB_CARD_NO].bb_gate_reg.lb0, BB_TMR_RTGREG_LO ); // divides threw lb0*hb0
00671     writeb( spa[BB_CARD_NO].bb_gate_reg.hb0, BB_TMR_RTGREG_LO );
00672 
00673     writeb( 0x70, BB_TMR_RTGCNT3CTRL );          // rategenerator 1 in mode 0
00674     writeb( spa[BB_CARD_NO].bb_gate_reg.lb1, BB_TMR_RTGREG_HI ); // as interrupt on terminalcount
00675     writeb( spa[BB_CARD_NO].bb_gate_reg.hb1, BB_TMR_RTGREG_HI ); // after lb1rg*hb1rg periods
00676 
00677     writeb( 0xff, BB_TMR_CNTGATECTRL );          // softgate on, count started 
00678     // Softgate Stuff ... missing right now
00679     //    writeb( 0x00, BB_TMR_CNTGATECTRL );    // end of scans   Softgate off
00680 }
00681 
00682 int BB_ReadyCnt(void){
00683     writeb( 0xe4, BB_TMR_RTGCNT3CTRL );
00684     return ( (readb(BB_TMR_RTGREG_HI) & 0x80) == 0 ); // Gate = Low ?
00685 }
00686 
00687 // IRQ Handler
00688 static void bb_gate_interrupt(int irq, void *dev_id, struct pt_regs *regs){
00689 //    SPALEED *thisspa = (SPALEED *) dev_id;
00690     SPALEED *thisspa = &spa[BB_CARD_NO];
00691     wake_up_interruptible( &thisspa->waitq );
00692 #ifdef BB_TEST_CNT
00693     ++irq_count;
00694 #endif
00695 
00696 }

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