innovative_dsp_hwi_dev.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,2002,2003 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 /* irnore this module for docuscan
00029 % PlugInModuleIgnore
00030  */
00031 
00032 
00033 #include <locale.h>
00034 #include <libintl.h>
00035 
00036 
00037 #include "glbvars.h"
00038 #include "plug-ins/hard/modules/dsp.h"
00039 #include <fcntl.h>
00040 #include <sys/ioctl.h>
00041 
00042 #include "dsp-pci32/xsm/dpramdef.h"
00043 #include "dsp-pci32/xsm/xsmcmd.h"
00044 
00045 #include "innovative_dsp_hwi.h"
00046 
00047 /* ============================================================
00048  * Hardwareimplementation hilevel DSP:
00049  * Virtuelle Funktionen der Basisklasse werden überschrieben
00050  * ============================================================ 
00051  */
00052 
00053 /* Konstruktor: initialisiert Hardware
00054  * ==================================================
00055  * - device öffnen
00056  */
00057 innovative_dsp_hwi_dev::innovative_dsp_hwi_dev(int ver):XSM_Hardware(){
00058         EventCheckOn();
00059 
00060         dsp_cmd  = open(xsmres.DSPDev, O_RDWR);
00061         dsp_usr  = open(xsmres.DSPDev, O_RDWR);
00062         dsp_data = open(xsmres.DSPDev, O_RDWR);
00063         if(dsp_cmd <= 0){ 
00064                 printf("open %s failed, err=%d\nPlease do \"insmod pci32, pc31, ccd, dspspaemu or dspbbspa...\" (you need root for this) !\n\n"
00065                        "Or if you want to go without hardware, you can temporary disable hardware access:\n use: \"gxsm -h no\"\n",
00066                        xsmres.DSPDev, dsp_cmd);
00067                 exit(0);
00068         }
00069         if(dsp_data <= 0 || dsp_usr <= 0){
00070                 printf("second open %s failed, err=%d\nsorry, something goes wrong !\n", xsmres.DSPDev, dsp_data);
00071                 close(dsp_cmd);
00072                 exit(0);
00073         }
00074 
00075         switch(ioctl(dsp_cmd, PCDSP_GETMODID)){
00076         case PCDSP_MODID_SIM: InfoString = g_strdup("Module is SIM"); break;
00077         case PCDSP_MODID_PC31: InfoString = g_strdup("Module is PC31"); break;
00078         case PCDSP_MODID_PCI32: InfoString = g_strdup("Module is PCI32"); break;
00079         default: 
00080                 InfoString = g_strdup("Module Typ is unknown!");
00081         }
00082         /* SEM0: default, MBOX */
00083         ioctl(dsp_cmd, PCDSP_SEM1START, DSP_CTRL_REGION);
00084         ioctl(dsp_cmd, PCDSP_SEM1LEN,   DSP_CTRL_REG_LEN);
00085 
00086         ioctl(dsp_usr, PCDSP_SEM2START, DSP_USR_REGION);
00087         ioctl(dsp_usr, PCDSP_SEM2LEN,   DSP_USR_REG_LEN);
00088 
00089         ioctl(dsp_data, PCDSP_SEM3START, DSP_DATA_REGION);
00090         ioctl(dsp_data, PCDSP_SEM3LEN,   DSP_DATA_REG_LEN);
00091 
00092         lseek(dsp_cmd,  BYTSIZE(DSP_CTRL_REGION), SEEK_SET);
00093         lseek(dsp_usr,  BYTSIZE(DSP_USR_REGION),  SEEK_SET);
00094         lseek(dsp_data, BYTSIZE(DSP_DATA_REGION), SEEK_SET);
00095 
00096         in_use_count=0;
00097 
00098         // ask DSP for software version and config report
00099         g_free(get_DSP_softinfo ());
00100 }
00101 
00102 /* Destruktor:
00103  * ==================================================
00104  * Hardware "abtrennen"
00105  */
00106 innovative_dsp_hwi_dev::~innovative_dsp_hwi_dev(){
00107         close(dsp_cmd);
00108         close(dsp_usr);
00109         close(dsp_data);
00110 }
00111 
00112 void innovative_dsp_hwi_dev::ExecCmd(int Cmd){ 
00113         unsigned long dspctrl, l;
00114         clock_t timeout;
00115         dspctrl = (unsigned long)Cmd;
00116 
00117         if(write(dsp_cmd, &dspctrl, BYTSIZE(DSP_CTRL_PARAM)))
00118                 XSM_SHOW_ALERT(N_("Attention"), N_("ExecCmd: DSP write failed!"), " ", 0);
00119 
00120         timeout=clock()+DSP_TIMEOUT*CLOCKS_PER_SEC;
00121         while(!(l=ioctl(dsp_cmd, PCDSP_MBOX_WRITE_NOWAIT, dspctrl)) && timeout > clock())
00122                 gapp->check_events();
00123         if(!l)
00124                 XSM_SHOW_ALERT(N_("Attention"), N_("ExecCmd: Timeout, DSP write mbox failed!"), " ", 0);
00125 }
00126 
00127 int  innovative_dsp_hwi_dev::WaitExec(int data){
00128         return 0;
00129 }
00130 
00131 void innovative_dsp_hwi_dev::Evchk(){ gapp->check_events(); usleep(5000); };
00132 
00133 void innovative_dsp_hwi_dev::NoEvchk(){ usleep(5000); }; // don´t waste power here !
00134 
00135 
00136 // Parameterliste an DSP <FC>bergeben und Cmd absetzten
00137 void innovative_dsp_hwi_dev::SetParameter(PARAMETER_SET &hps, int scanflg){
00138         static clock_t last_error_time = 0;
00139         static int error_count = 0;
00140         static int errmsg_disable = 0;
00141 #define CHECK_ERR_DTIME { \
00142                 if (last_error_time+5 > clock()) errmsg_disable = 1;\
00143                 if (++error_count > 20) errmsg_disable = 1;\
00144                 last_error_time = clock(); \
00145                         }
00146 #define SHOW_MSG(A,B) { \
00147                 if (errmsg_disable) \
00148                         std::cerr << "innovative_dsp_hwi_dev::SetParameter Error Message: (to many, redirected to console)" << std::endl \
00149                              << "--  " << A << std::endl \
00150                              << "--  " << B << std::endl; \
00151                 else \
00152                         gapp->alert (N_("Attention"), A, B, 0); \
00153         }
00154         clock_t timeout;
00155         unsigned long l;
00156         unsigned long dspctrl[DSP_CTRL_REG_LEN];
00157         union fl { float  f; unsigned long hl; } Fl;
00158        
00159         static int busy=0;
00160         XSM_DEBUG (DBG_L2, "Calling instance #"<< busy <<" of SetParameter.");
00161         busy++; // set mutex
00162         // simple mutex mechanism -- got some trouble with "recursive" calls
00163         int k=0;
00164         while (busy > 1) { 
00165                 usleep (50000); //gapp->check_events(); 
00166                 if (k==0)
00167                   XSM_DEBUG (DBG_L2, "SetParameter is busy [" << busy << "] - waiting.");
00168                 if (++k > 20){
00169                   XSM_DEBUG (DBG_L2, "-- Giving up waiting on DSP and trying to force setting parameters. Releasing Mutex "<< busy<<" --");
00170                   --busy; // Releasing Mutex
00171                   break;
00172                 }
00173         }
00174        
00175         dspctrl[DSP_CTRL_CMD] = (unsigned long)hps.Cmd;
00176         for(int i=0; i<hps.N; i++){
00177                 Fl.f = hps.hp[i].value;
00178                 dspctrl[i + DSP_CTRL_PARAM] = Fl.hl;
00179         }
00180 
00181         // set timeout
00182         timeout=clock()+DSP_TIMEOUT*CLOCKS_PER_SEC;
00183 
00184         // wait until last cmd finished ? (new here)
00185         while(!(l=ioctl(dsp_cmd, PCDSP_MBOX_EMPTY, FALSE)) && timeout > clock())
00186                 (*EventCheck)();
00187 
00188         // write Cmd and parameters
00189         if(write(dsp_cmd, dspctrl, BYTSIZE(hps.N+DSP_CTRL_PARAM))){
00190                 CHECK_ERR_DTIME;
00191                 SHOW_MSG (N_("DSP write parameters failed !"),
00192                           N_("cause: error while writing to device.")
00193                           );
00194         }
00195 
00196         // send cmd (Mailbox write)
00197         if(scanflg){
00198                 while(!(l=ioctl(dsp_cmd, PCDSP_MBOX_WRITE_NOWAIT,  hps.Cmd)) && timeout > clock())
00199                         (*EventCheck)();
00200                 if(!l){
00201                         CHECK_ERR_DTIME;
00202                         SHOW_MSG (N_("SetParameter: DSP write mbox failed."),
00203                                   N_("cause: timeout, in scan, cmd=PCDSP_MBOX_WRITE_NOWAIT"));
00204                 }
00205 
00206                 // Do some drawing, view update, etc inbetween?
00207                 CallIdleFunc();
00208 
00209                 // wait for Cmd execute OK (Mailbox empty)
00210     
00211                 int k=0;
00212                 while(!(l=ioctl(dsp_cmd, PCDSP_MBOX_EMPTY, FALSE)) && timeout > clock()){
00213                         if(k-- >= 0)
00214                                 NoEvchk();
00215                         else
00216                                 (*EventCheck)();
00217                         // scan stopped ?
00218                         if(KillFlg){
00219                           XSM_DEBUG (DBG_L2, "Release Mutex "<<busy<<" due to KillFlag set.");
00220                           --busy; // release mutex
00221                         }
00222                         return;
00223                 }
00224         }else{
00225                 while(!(l=ioctl(dsp_cmd, PCDSP_MBOX_WRITE_NOWAIT, hps.Cmd)) && timeout > clock())
00226                         Evchk();
00227                 if(!l){
00228                         CHECK_ERR_DTIME;
00229                         SHOW_MSG (N_("SetParameter: DSP write mbox failed."),
00230                                   N_("cause: timeout, no scan"));
00231                 }
00232                 // wait for Cmd execute OK (Mailbox empty)
00233                 while(!(l=ioctl(dsp_cmd, PCDSP_MBOX_EMPTY, FALSE)) && timeout > clock())
00234                         Evchk();
00235         }
00236         if(!l){
00237                 gchar *tt=g_strdup_printf("timeout=%ds reached: waiting since %gs", 
00238                                           DSP_TIMEOUT, (double)((clock()-timeout)/CLOCKS_PER_SEC));
00239                 CHECK_ERR_DTIME;
00240                 SHOW_MSG (N_("SetParameter: DSP wait for mbox empty failed. \n"
00241                              "--  cause: timeout; write data and cmd exec OK"),
00242                           tt);
00243                 g_free(tt);
00244         }
00245         XSM_DEBUG (DBG_L2, "Release Mutex " <<busy<<" due to end of function call");
00246         --busy; //release mutex
00247 }
00248 
00249 // Parameter von DSP anfordern
00250 void innovative_dsp_hwi_dev::GetParameter(PARAMETER_SET &hps){
00251         unsigned long dspctrl[DSP_CTRL_REG_LEN];
00252         union fl { float  f; unsigned long hl; } Fl;
00253   
00254         // read parameter-area
00255         if(read(dsp_cmd, dspctrl, BYTSIZE(hps.N+DSP_CTRL_PARAM)))
00256                 gapp->alert("Achtung", "DSP read parameters failed !", " ", 0);
00257 
00258         for(int i=0; i<hps.N; i++){
00259                 Fl.hl = dspctrl[i + DSP_CTRL_PARAM];
00260                 hps.hp[i].value = Fl.f;
00261         }
00262 }
00263 
00264 gchar* innovative_dsp_hwi_dev::get_DSP_softinfo (){
00265         PARAMETER_SET hardpar;
00266         #define TMPSIZE 1000
00267         gchar infotxt[TMPSIZE+1];
00268         int i;
00269 
00270         scan_data_mode = SCAN_DATA_SWAP_SHORT;
00271         prb_data_mode = PRB_SHORT;
00272         max_points_per_line = DSP_DATA_REG_LEN<<1;
00273 
00274         XSM_DEBUG (DBG_L2, "innovative_dsp_hwi_dev::get_DSP_softinfo -- Asking DSP to report software info." );
00275 
00276         hardpar.N   = 1;
00277         hardpar.Cmd = DSP_CMD_GETINFO;
00278         hardpar.hp[0].value = 0.;
00279         SetParameter(hardpar, FALSE);
00280         
00281         long infobuffer[DSP_DATA_REG_LEN];
00282 
00283         // read info data buffer
00284         ReadData(infobuffer, DSP_DATA_REG_LEN*sizeof(long));
00285 
00286         memset (infotxt, 0, sizeof(infotxt));
00287         // check for alignement, DSP has long, kernel doese char
00288         if (!strncmp ((char*)infobuffer, "*123-567-9abXdef", 16)){
00289                 XSM_DEBUG(DBG_L2, "++ KERNEL-EMU-DETECTED" );
00290                 strcpy (infotxt, 
00291                         "*--XSM-DSP-SOFT-INFO--*\n"
00292                         "--*Kernel-Emu-Detected*--\n");
00293                 memcpy ((void*)&infotxt[strlen(infotxt)], (void*)&infobuffer[92/4], 
00294                         MIN ((strlen ((char*)&infobuffer[92/4])-1), (TMPSIZE-100)));
00295         }else{
00296                 XSM_DEBUG(DBG_L2, "-- DSP-W-LONGMODE-DPRAM-SUGGESTED" );
00297                 for(i=0; i<TMPSIZE && infobuffer[i]!='@'; ++i)
00298                         infotxt[i] = (gchar)infobuffer[i];
00299                 infotxt[i]=0;
00300         }
00301         if (strncmp (infotxt, "*--XSM-DSP-SOFT-INFO--*", 23)){
00302                 XSM_DEBUG(DBG_L2, "-- AUTOMATIC DEVICE IDENTIFY FAILED" );
00303                 infobuffer[24] = 0;
00304                 gchar *tmp = g_strdup_printf ("Sorry, this DSP software does not support reports!\n"
00305                                               "Identify String found:\n"
00306                                               "<%s>\n",
00307                                               (char*)infobuffer);
00308                 XSM_DEBUG_PLAIN (DBG_L2, tmp);
00309                 return  (tmp);
00310         }
00311         XSM_DEBUG(DBG_L2, "++ AUTOMATIC DEVICE IDENTIFY OK, REPORT:" );
00312         XSM_DEBUG_PLAIN (DBG_L2, infotxt );
00313         XSM_DEBUG(DBG_L2, "** END OF REPORT" );
00314 
00315         // now check some options:
00316         if (strstr (infotxt, "ProbeDataMode: short")){
00317                 prb_data_mode = PRB_SHORT;
00318                 XSM_DEBUG(DBG_L2, "DSP ProbeData Mode is SHORT." );
00319         } else if (strstr (infotxt, "ProbeDataMode: float")){
00320                 prb_data_mode = PRB_FLOAT;
00321                 XSM_DEBUG(DBG_L2, "DSP ProbeData Mode is FLOAT." );
00322         } else
00323                 XSM_DEBUG(DBG_L2, "DSP ProbeData Mode not reported, using SHORT." );
00324 
00325         if (strstr (infotxt, "DPRAMDATAMOVE: yes")){
00326                 scan_data_mode = SCAN_DATA_MOVE2DPRAM_SHORT;
00327                 XSM_DEBUG(DBG_L2, "Scan Data Mode is MOVE2DPRAM." );
00328         } else if (strstr (infotxt, "DPRAMSWAP: yes")){
00329                 scan_data_mode = SCAN_DATA_SWAP_SHORT;
00330                 XSM_DEBUG(DBG_L2, "Scan Data Mode is SWAP (deprecated mode)." );
00331         } else
00332                 XSM_DEBUG(DBG_L2, "Scan Data ModeDSP not reported, using old SWAP method." );
00333 
00334         gchar *dpl;
00335         if ((dpl = strstr (infotxt, "DATABUFFERLEN: "))){
00336                 max_points_per_line = atoi (dpl + 15)<<1;
00337                 XSM_DEBUG(DBG_L2, "Found DATABUFFERLEN, setting max points per line to " << max_points_per_line );
00338         }
00339 
00340         return (g_strdup (infotxt));
00341 }
00342 
00343 size_t innovative_dsp_hwi_dev::ReadData(void *buf, size_t count) { 
00344         // may be adding auto-swap-mode later... PZ
00345         return read(dsp_data, buf, count); 
00346 }
00347 
00348 int innovative_dsp_hwi_dev::ReadScanData(int y_index, int num_srcs, Mem2d *m[MAX_SRCS_CHANNELS]){
00349         int len = m[0]->GetNx();
00350         if (scan_data_mode == SCAN_DATA_MOVE2DPRAM_SHORT){
00351                 if( len & 1 ) ++len; // is always even!
00352                 int mv_buf_len  = len*num_srcs; // max bufer size for data move
00353                 if (y_index == -1) // get all HS_areascan data!
00354                         mv_buf_len *= m[0]->GetNy();
00355                 int dataset_len = mv_buf_len;   // total dataset buffer size
00356                 if (mv_buf_len > (DSP_DATA_REG_LEN<<1))
00357                         mv_buf_len = (DSP_DATA_REG_LEN<<1); 
00358                 SHT *linebuffer = new SHT[dataset_len];
00359                 // move full dataset to buffer first
00360                 int mv_len = mv_buf_len;
00361                 int offset = 0;
00362                 do{
00363                         ReadData (&linebuffer[offset], mv_len*sizeof(SHT));
00364                         offset += mv_buf_len;
00365                         if (offset < dataset_len){
00366                                 PARAMETER_SET hardpar;
00367                                 hardpar.N   = DSP_LSSRCS+1;
00368                                 hardpar.Cmd = DSP_CMD_MOVE_DATA2DPRAM;
00369                                 hardpar.hp[DSP_MVD_CMD_START].value = offset>>1; // index in DPRAM dwords
00370                                 hardpar.hp[DSP_MVD_CMD_LEN  ].value = (mv_len = ((dataset_len-offset) > mv_buf_len 
00371                                                                                  ? mv_buf_len : dataset_len-offset)) >> 1;
00372                                 SetParameter (hardpar, TRUE);
00373                         } else break;
00374                 }while (1);
00375 
00376                 int y = y_index == -1 ? 0:y_index;
00377                 for (int offset=0; y < m[0]->GetNy(); ++y){
00378                         for (int i=0; i<num_srcs; ++i)
00379                                 if (m[i])
00380                                         m[i]->PutDataLine (y, linebuffer+ i*len + offset);
00381                         if (y_index == -1)
00382                                 offset += len*num_srcs;
00383                         else
00384                                 break; // single line mode
00385                 }
00386 
00387                 delete[] linebuffer;
00388         }else{
00389                 if (y_index < 0) return 0; // HS Capture not supported!
00390                 // Transfer Data, using old SWAP method
00391                 SHT linebuffer[DSP_DATA_REG_LEN<<1]; // Max Size for LineData "at once"
00392                 size_t elem_size=sizeof(SHT);
00393                 size_t bsz = (len*elem_size);
00394                 int i = 0;
00395                 int n = 0;
00396                 do{
00397                         size_t sz = 0;
00398                         int bin = 0;
00399                         while (n < num_srcs && (sz+bsz) < (DSP_DATA_REG_LEN<<2)){
00400                                 sz += bsz;
00401                                 ++n;
00402                                 ++bin;
00403                         }
00404                         if (sz > 0){
00405                                 // read data buffer(s)
00406                                 ReadData(linebuffer, sz);
00407                                 int j = 0;
00408                                 do{
00409                                         m[i++]->PutDataLine (y_index, linebuffer+(j++)*len);
00410                                 }while(--bin && (i < MAX_SRCS_CHANNELS) ? m[i] != NULL : FALSE);
00411                         }
00412                         else 
00413                                 break;
00414                         // Swap DPRAM Buffers...
00415                         ExecCmd(DSP_CMD_SWAPDPRAM);
00416                 }while ((i < MAX_SRCS_CHANNELS) ? m[i]!=NULL : FALSE);
00417         }
00418         return 0;
00419 }
00420 
00421 int innovative_dsp_hwi_dev::ReadProbeData(int nsrcs, int nprobe, int kx, int ky, Mem2d *m, double scale){
00422         if (prb_data_mode == PRB_SHORT){
00423                 size_t data_set_size =  nprobe * nsrcs * sizeof(SHT);
00424                 if (data_set_size >= (DSP_DATA_REG_LEN<<2))
00425                         return 0;
00426                 SHT linebuffer[DSP_DATA_REG_LEN<<1];
00427                 ReadData(linebuffer, data_set_size);
00428 
00429                 if (kx == -1 && ky == -1)
00430                         for (int i=0; i < nsrcs; ++i)
00431                                 for (int k=0; k < nprobe; ++k)
00432                                         m->PutDataPkt (((double)linebuffer[k+i*nprobe]) * scale, 
00433                                                        k, i);
00434                 else
00435                         for (int k=0; k < nprobe; ++k)
00436                                 m->PutDataPkt (((double)linebuffer[k]) * scale, 
00437                                                kx, ky, k);
00438                 return 1;
00439 
00440         } else if (prb_data_mode == PRB_FLOAT){
00441                 size_t data_set_size =  nprobe * nsrcs * sizeof(float);
00442                 if (data_set_size >= (DSP_DATA_REG_LEN<<2))
00443                         return 0;
00444                 float linebuffer[DSP_DATA_REG_LEN<<2];
00445                 ReadData(linebuffer, data_set_size);
00446 
00447                 if (kx == -1 && ky == -1)
00448                         for (int i=0; i < nsrcs; ++i)
00449                                 for (int k=0; k < nprobe; ++k)
00450                                         m->PutDataPkt (((double)linebuffer[k+i*nprobe]) * scale, 
00451                                                        k, i);
00452                 else
00453                         for (int k=0; k < nprobe; ++k)
00454                                 m->PutDataPkt (((double)linebuffer[k]) * scale, 
00455                                                kx, ky, k);
00456                 return 1;
00457         } else return 0;
00458 }
00459 
00460 /* nur für DSP */
00461 
00462 /* ENDE MODUL DSPCOM */

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