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 "include/dsp-pci32/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 0xd0000
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     wait_queue_head_t 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     init_waitqueue_head(&spa[BB_CARD_NO].waitq);
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       spa[BB_CARD_NO].scanp.rotoffx = spa[BB_CARD_NO].scanp.X0;
00392       spa[BB_CARD_NO].scanp.rotoffy = spa[BB_CARD_NO].scanp.Y0;
00393       BB_SetVolt(0., 0.);
00394       BB_SetEnergy(spa[BB_CARD_NO].scanp.E);
00395       DSPack;
00396       break;
00397 
00398   case DSP_CMD_SPACTRL_SET:
00399       spa[BB_CARD_NO].extractor = GetParamF(DSP_SPACTRL_EXTRACTOR);
00400       spa[BB_CARD_NO].chanhv    = GetParamF(DSP_SPACTRL_CHANHV);
00401       spa[BB_CARD_NO].chanrepeller = GetParamF(DSP_SPACTRL_CHANREPELLER);
00402       spa[BB_CARD_NO].cryfocus  = GetParamF(DSP_SPACTRL_CRYFOCUS);
00403       spa[BB_CARD_NO].filament  = GetParamF(DSP_SPACTRL_FILAMENT);
00404       spa[BB_CARD_NO].gunfocus  = GetParamF(DSP_SPACTRL_GUNFOCUS);
00405       spa[BB_CARD_NO].gunanode  = GetParamF(DSP_SPACTRL_GUNANODE);
00406       spa[BB_CARD_NO].smpdist   = GetParamF(DSP_SPACTRL_SMPDIST);
00407       spa[BB_CARD_NO].smptemp   = GetParamF(DSP_SPACTRL_SMPTEMP);
00408       spa[BB_CARD_NO].growing   = GetParamF(DSP_SPACTRL_GROWING);
00409       DSPack;
00410       break;
00411 
00412   case DSP_CMD_SCAN_START:
00413       spa[BB_CARD_NO].scanp.len = GetParamF(DSP_len);
00414       spa[BB_CARD_NO].scanp.E   = GetParamF(DSP_E);
00415       
00416       spa[BB_CARD_NO].LastSPAMode = spa[BB_CARD_NO].SPAMode;
00417       spa[BB_CARD_NO].SPAMode = (spa[BB_CARD_NO].SPAMode & ~(MD_CMD)) | MD_SCAN;
00418       linescan(0, GetParamF(DSP_Y0));
00419       spa[BB_CARD_NO].SPAMode = spa[BB_CARD_NO].LastSPAMode;
00420       DSPack;
00421       break;
00422 
00423   case DSP_CMD_SWAPDPRAM:
00424       DSPack;
00425       break;
00426 
00427   case DSP_CMD_SCAN2D:
00428       spa[BB_CARD_NO].scanp.Nx  = GetParamI(DSP_NX);
00429       spa[BB_CARD_NO].scanp.Ny  = GetParamI(DSP_NY);
00430       spa[BB_CARD_NO].scanp.lenxy = GetParamF(DSP_LXY);
00431       spa[BB_CARD_NO].LastSPAMode = spa[BB_CARD_NO].SPAMode;
00432       spa[BB_CARD_NO].SPAMode = (spa[BB_CARD_NO].SPAMode & ~(MD_CMD)) | MD_SCAN;
00433       scan2d();
00434       spa[BB_CARD_NO].SPAMode = spa[BB_CARD_NO].LastSPAMode;
00435       DSPack;
00436       break;
00437 
00438   case DSP_CMD_GETCNT:
00439       spa[BB_CARD_NO].scanp.ms  = GetParamF(DSP_ms);
00440       spa[BB_CARD_NO].scanp.E   = GetParamF(DSP_E);
00441 
00442       spa[BB_CARD_NO].scanp.ms = BB_InitCnt(spa[BB_CARD_NO].scanp.ms);
00443       BB_SetEnergy(spa[BB_CARD_NO].scanp.E);
00444 
00445       *(BUFFERL) = ChanneltronCounts(0., 0.);
00446 
00447       DSPack;
00448       break;
00449 
00450   default: break;
00451   }
00452   REQD_DSP = FALSE;
00453 }
00454 
00455 void scan2d(void){
00456     double x,y,Ux, dUx, Uy, dUy;
00457     int   i,j,k;
00458     if(spa[BB_CARD_NO].scanp.Nx > 1)
00459         Ux  = -spa[BB_CARD_NO].scanp.lenxy/2.;
00460     else
00461         Ux = 0.;
00462     dUx = spa[BB_CARD_NO].scanp.lenxy/spa[BB_CARD_NO].scanp.Nx;
00463     
00464     if(spa[BB_CARD_NO].scanp.Ny > 1)
00465     Uy = spa[BB_CARD_NO].scanp.lenxy/2.;
00466     else
00467         Uy = 0.;
00468     dUy = spa[BB_CARD_NO].scanp.lenxy/spa[BB_CARD_NO].scanp.Ny;
00469     
00470     spa[BB_CARD_NO].scanp.ms = BB_InitCnt(spa[BB_CARD_NO].scanp.ms);
00471     BB_SetEnergy(spa[BB_CARD_NO].scanp.E);
00472 
00473     for(y=Uy, k=j=0; j<spa[BB_CARD_NO].scanp.Ny; j++, y-=dUy){
00474         BB_SetVolt(Ux, y);
00475         mysleep(3);
00476         for(x=Ux, i=0; i<spa[BB_CARD_NO].scanp.Nx; i++, k++, x+=dUx){
00477             if( k >= MAXSCANPOINTS )
00478                 return;
00479             *(BUFFERL + k) = ChanneltronCounts(x, y);
00480         }
00481     }
00482 }
00483 
00484 void linescan(int n, float y){
00485     float x, dx;
00486     int nmax;
00487     nmax = n + spa[BB_CARD_NO].scanp.N + 4;
00488     if( nmax > MAXSCANPOINTS )
00489         nmax = MAXSCANPOINTS;
00490 
00491     dx = spa[BB_CARD_NO].scanp.len/(float)spa[BB_CARD_NO].scanp.N;
00492     x = -spa[BB_CARD_NO].scanp.len/2.;
00493 
00494     spa[BB_CARD_NO].scanp.ms = BB_InitCnt(spa[BB_CARD_NO].scanp.ms);
00495     BB_SetEnergy(spa[BB_CARD_NO].scanp.E);
00496     BB_SetVolt(x, y);
00497     mysleep(3);
00498     for(; n<nmax; n++, x+=dx)
00499         *(BUFFERL + n) = ChanneltronCounts(x, y);
00500 }
00501 
00502 #ifndef BB_POLLING_MODE
00503 static void bb_irq_timeout(unsigned long data){
00504     SPALEED *thisspa = &spa[data];
00505     ++thisspa->bb_timeout_flg;
00506     wake_up_interruptible( &thisspa->waitq );
00507 #ifdef BB_TEST_CNT
00508     ++timeout_count;
00509 #endif
00510 }
00511 #endif
00512 
00513 #define MAKE_MY_TIMEOUT_TMR(tmr) \
00514   struct timer_list tmr; \
00515   init_timer(&tmr); \
00516   tmr.function = timeout; \
00517   tmr.data = 0
00518 
00519 
00520 unsigned long ChanneltronCounts(float x, float y){
00521 
00522 #ifdef BB_POLLING_MODE
00523   /* no IRQ is used */
00524   MAKE_MY_TIMEOUT_TMR(timeout_tmr);
00525 
00526     BB_SetVolt(x, y);
00527     BB_SetCnt();
00528 
00529     if(spa[BB_CARD_NO].scanp.ms > 12.)
00530         mysleep( (unsigned long) (spa[BB_CARD_NO].scanp.ms/10.) );
00531     else{
00532         wakeups=1000;
00533         while( BB_ReadyCnt() && --wakeups);
00534         if( ! BB_ReadyCnt() )
00535             return BB_CntRead();
00536     }
00537 
00538     wakeups=0;
00539     while( BB_ReadyCnt() && wakeups < 100){
00540         del_timer(&timeout_tmr);
00541         timeout_tmr.expires = jiffies + 1;
00542         add_timer(&timeout_tmr);
00543         interruptible_sleep_on( &waitq );
00544         wakeups++;
00545     } 
00546 
00547 #else
00548 # ifdef bboldtestversion
00549     // use IRQ
00550 
00551     BB_SetVolt(x, y);
00552     BB_SetCnt();
00553 
00554     // use bb_irq_timeout function to wakeup if irq is missed
00555     init_timer( &spa[BB_CARD_NO].timeout_tmr );
00556     spa[BB_CARD_NO].timeout_tmr.expires  = jiffies + 1 + (unsigned long)(spa[BB_CARD_NO].scanp.ms/10.) ;
00557     spa[BB_CARD_NO].timeout_tmr.data     = BB_CARD_NO;
00558     spa[BB_CARD_NO].timeout_tmr.function = bb_irq_timeout;
00559     spa[BB_CARD_NO].bb_timeout_flg       = 0;
00560     add_timer( &spa[BB_CARD_NO].timeout_tmr );
00561 
00562     sti();
00563     interruptible_sleep_on( &spa[BB_CARD_NO].waitq );
00564     cli();
00565 
00566     del_timer( &spa[BB_CARD_NO].timeout_tmr );
00567 # else
00568     DECLARE_WAITQUEUE(wait, current);
00569     unsigned long data;
00570     ssize_t retval;
00571 
00572     BB_SetVolt(x, y);
00573     BB_SetCnt();
00574 
00575     add_wait_queue(&spa[BB_CARD_NO].waitq, &wait);
00576     current->state = TASK_INTERRUPTIBLE;
00577 
00578     schedule();
00579 # endif
00580 #endif
00581     if( ! BB_ReadyCnt() )
00582         return BB_CntRead();
00583     else
00584         return 13;
00585 }
00586 
00587 // BB implementation
00588 // BurrBrown Stuff is following
00589 
00590 
00591 void BB_SetVolt(double x, double y){
00592     double xt,yt;
00593     xt = x*spa[BB_CARD_NO].scanp.rotmxx + y*spa[BB_CARD_NO].scanp.rotmxy 
00594         + spa[BB_CARD_NO].scanp.rotoffx;
00595     yt = x*spa[BB_CARD_NO].scanp.rotmyx + y*spa[BB_CARD_NO].scanp.rotmyy 
00596         + spa[BB_CARD_NO].scanp.rotoffy;
00597 
00598     BB_DAC_X( (int)(xt), BB_XY_DEFLECTON_BOARD );
00599     BB_DAC_Y( (int)(yt), BB_XY_DEFLECTON_BOARD );
00600     BB_DAC_OUT( BB_XY_DEFLECTON_BOARD );
00601 }
00602 
00603 
00604 void BB_SetEnergy(double En){
00605     BB_DAC_X( U2INT(En), BB_ENERGY_BOARD );
00606     BB_DAC_Y( U2INT(En), BB_ENERGY_BOARD );
00607     BB_DAC_OUT( BB_ENERGY_BOARD );
00608 }
00609 
00610 unsigned long BB_CntRead(void){
00611     unsigned long lb0, hb0, lb1, hb1, cnt, stat0, stat1;
00612     writeb( 0xc6, BB_TMR_CNT012CTRL );
00613     cnt = 0;
00614 
00615     stat0 = readb( BB_TMR_CNT0REG ) & BB_CRTL_MSK;
00616     lb0 = 0xff - readb( BB_TMR_CNT0REG );
00617     hb0 = 0xff - readb( BB_TMR_CNT0REG );
00618     if(stat0 == 0) 
00619         cnt = (((hb0<<8) | lb0) + 1) << 16;
00620 
00621     stat1 = readb( BB_TMR_CNT1REG ) & BB_CRTL_MSK;
00622     lb1 = 0xff - readb( BB_TMR_CNT1REG );
00623     hb1 = 0xff - readb( BB_TMR_CNT1REG );
00624     if(stat1 == 0){
00625         cnt |= (hb1<<8) | lb1;
00626         ++cnt;
00627     }
00628     
00629     return cnt;
00630 }
00631 
00632 double BB_InitCnt(double gate){
00633     // gate in ms
00634     long n0, n1;
00635     double factor;
00636 
00637     if( gate < 0.1 ) 
00638         factor = 1.;
00639     else 
00640         if( gate < 1. ) 
00641             factor = 10.;
00642         else
00643             if( gate < 10. )
00644                 factor = 100.;
00645             else
00646                 if( gate < 100. )
00647                     factor = 1000.;
00648                 else
00649                     factor = 10000.;
00650 
00651     n1 = (long)(2.*factor);
00652     n0 = (long)(4000.*gate/factor);
00653 
00654     if( n0 < 2 ){
00655         n0 = 2;
00656         gate = (double)n0 * (double)n1 / 8000.;
00657     }
00658 
00659     spa[BB_CARD_NO].bb_gate_reg.lb0 = (n0&0xff);
00660     spa[BB_CARD_NO].bb_gate_reg.hb0 = ((n0>>8)&0xff);
00661     spa[BB_CARD_NO].bb_gate_reg.lb1 = (n1&0xff);
00662     spa[BB_CARD_NO].bb_gate_reg.hb1 = ((n1>>8)&0xff);
00663 
00664     return gate;
00665 }
00666 
00667 void BB_SetCnt(void){
00668     writeb( 0x34, BB_TMR_CNT012CTRL );  // Counter 0 in mode 2
00669     writeb( 0xff, BB_TMR_CNT0REG );     // divides threw    65532
00670     writeb( 0xff, BB_TMR_CNT0REG );
00671 
00672     writeb( 0x74, BB_TMR_CNT012CTRL );  // Counter 1 in mode 2
00673     writeb( 0xff, BB_TMR_CNT1REG );     // divides threw    65532
00674     writeb( 0xff, BB_TMR_CNT1REG );
00675 
00676     writeb( 0x34, BB_TMR_RTGCNT3CTRL );          // rategenerator 0 in mode 2
00677     writeb( spa[BB_CARD_NO].bb_gate_reg.lb0, BB_TMR_RTGREG_LO ); // divides threw lb0*hb0
00678     writeb( spa[BB_CARD_NO].bb_gate_reg.hb0, BB_TMR_RTGREG_LO );
00679 
00680     writeb( 0x70, BB_TMR_RTGCNT3CTRL );          // rategenerator 1 in mode 0
00681     writeb( spa[BB_CARD_NO].bb_gate_reg.lb1, BB_TMR_RTGREG_HI ); // as interrupt on terminalcount
00682     writeb( spa[BB_CARD_NO].bb_gate_reg.hb1, BB_TMR_RTGREG_HI ); // after lb1rg*hb1rg periods
00683 
00684     writeb( 0xff, BB_TMR_CNTGATECTRL );          // softgate on, count started 
00685     // Softgate Stuff ... missing right now
00686     //    writeb( 0x00, BB_TMR_CNTGATECTRL );    // end of scans   Softgate off
00687 }
00688 
00689 int BB_ReadyCnt(void){
00690     writeb( 0xe4, BB_TMR_RTGCNT3CTRL );
00691     return ( (readb(BB_TMR_RTGREG_HI) & 0x80) == 0 ); // Gate = Low ?
00692 }
00693 
00694 // IRQ Handler
00695 static void bb_gate_interrupt(int irq, void *dev_id, struct pt_regs *regs){
00696 //    SPALEED *thisspa = (SPALEED *) dev_id;
00697     SPALEED *thisspa = &spa[BB_CARD_NO];
00698     wake_up_interruptible( &thisspa->waitq );
00699 #ifdef BB_TEST_CNT
00700     ++irq_count;
00701 #endif
00702 
00703 }

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