Mulithreading



  • Was genau tun die Threads? Irgendetwas, was wenigstens mal ein paar Millisekunden/Sekunden dauert oder nur 3 mal addieren und tschüss?



  • Thread 1: dauert länger (führt eine Bewegung über Motoren etc aus)
    Thread 2: soll Messungen machen



  • Ich würde dann eher wagen zu behaupten, dass das Problem in den Run-Funktionen selbst liegt... Denn derartiges Verhalten ist mir noch nie aufgefallen.



  • mmmmmm müsste also ein Timing Problem sein?
    Ich habe in den Funktionen selbst kein Timing oder ähnliches drinne auch kein Sleep() oder sowas.

    Ich starte sogar zuerst das Messen und dann das Fahren. Allerdings wird erst das Fahren und dann das Messen ausgeführt.



  • Hast du irgendwelche Arten von Synchronisation ( Mutexes, CritSects, etc.. ) eingebaut, die das vielleicht verursachen könnten?



  • Hallo,

    danke schonmal für die schnelle Antwort jedesmal.
    Also ich erzeuge zwar Mutex nutze sie aber nicht
    am anfang steht also

    hScreenMutex	= CreateMutex( NULL, FALSE, NULL );
    hRunMutex       = CreateMutex( NULL, TRUE , NULL );   
    ThreadNr = 0;
    

    und am Ende

    hConsoleOut = GetStdHandle( STD_OUTPUT_HANDLE );
    GetConsoleScreenBufferInfo( hConsoleOut, &csbiInfo );
    ClearScreen();
    WriteTitle( 0 );
    
    ShutDown();
    CloseHandle( hScreenMutex );
    CloseHandle( hRunMutex );
    CloseHandle( hConsoleOut );
    


  • Kommunizieren die Threads auf irgendeine Art und Weise mit einander?



  • Habe auf deine Idee hin einfach mal alles was ich oben gepostet habe auskommentiert. Jetzt werden wirklich nur die threads gestartet mehr nicht und trotzdem habe ich denselben Fehler in den Messergebnissen.



  • Hallo,

    die beiden Threads kommunizieren nicht. Es sollen nur beide starten und parallel laufen.



  • Zäume doch das Pferd mal nicht von hinten auf.

    Schmeiß mal die ganze Funktionalität aus den Run-Funktionen raus und mach (Endlos)Schleifen mit Sleep und Textausgabe rein und prüfe dann das Ergebnis.

    Wenn die dann immmer noch nicht gleichzeitig ticken, dann fällt mir langsam auch nichts mehr ein 😉



  • benutzt dein "motor - thread" evtl irgendwelche funktionen die den thread an sich blockieren lassen (sprich positionierung oder sowas)?



  • hallo,

    also die Idee mit dem auskommentieren hat funktioniert.
    Es liegt irgendwie an dem Messthread.

    Der Fahrenthread läuft einwandfrei und blockiert eigentlich auch nix. Es waren vorher 2 einzelne Programme die nun kombiniert werden.

    Eine Frage laufen Threads parallel oder nur quasiparallel?

    Würde erklären warum immer nur eins von beidem ausgeführt wird.

    Mein Test war :
    beginthread(messen)
    beginthread(fahren)

    in der funktion messen habe ich dann erstmal die Funktionen zum Messen auskommentiert und habe nur ein* ausgeben lassen.
    Ergebnis:
    Motor fährt und parallel werden * ausgegeben.

    Also muss es ja an der Messfunktion liegen.

    Kann es evtl an einem Trigger liegen? Das die Messevents auslöst ?


  • Mod

    Threads laufen parallel wenn Du einen Prozessor mit mehreren Kernen hast.
    Die Ausgabe führt letzten Endesnatürlich auch zu einer Synchronisation weil diese auch immer nur für einen Thread zu einer zeit möglich ist.

    Was hast Du denn für Synchronisationsmethoden verwendet? Critical Sections Mutex???
    Wodurch willst Du wissen, dass ein Thread nicht läuft?



  • Hallo,

    ich sehe das der 2te Thread nicht läuft, da die Messergebnisse dies deutlich machen. sonst wäre mir das gar nicht aufgefallen.

    Ich habe gar keine Synchromethodenverwendet. 😮 😕
    Die Ausgabe war auch nur ein Test damit ich etwas auf der Konsole sehe.

    Zur Zeit ist es so:
    Motor fährt danach werden die Messungen gemacht, obwohl ich zu erst den Messthread starte und danach den Motorthread.

    Ziel:
    Starten von Motorthread
    Starten von Messthread
    = Messungen während der Bewegung sind möglich


  • Mod

    1. Wie willst Du bitte ohne Threadsynchronisation etwas messen, was sich verändert?
    2. Wenn Du keine Synchronisation verwendest dann laufen die Threads auch.



  • Die Threads laufen ja auch, allerdings leider nacheinander.

    Die Messungen funktionieren auch allerdings werden die Bilder nach Beendigung der Bewegung gemacht.

    Ich rufe die Threads jeweils mit

    _beginthread(messen	, 0	,	NULL );
    _beginthread(fahren	, 0	,	NULL );
    

    auf.

    Oder muss ich den Thread verschiedene Prios verteilen?
    Oder was mit Mutex anstellen?

    Gibts nicht einfach so was wie
    Starte Threads so das diese einfach nur anfangen zu laufen.
    Ich benötige erstmal keine Synchro dazwischen, es greift auch keine auf die andere zu. Sie sollen einfach nur beide anfangen zu laufen und das wenns geht einigermaßen gleichmäßig.
    Jetzt starten sie nacheinander bzw die 2te läuft erst dann weiter wenn die 1te zu Ende ist.


  • Mod

    Dann besorge Dir einen langsameren Rechner.
    Oder verwende Tasks die länger dauern... 😉





  • Aus zwei zeilen Code laesst sich schlecht etwas ablesen.



  • ok hier der gesammt code wenn euch das hilft ^^

    //***************************************************************************
    //Headerdateien
    //***************************************************************************
    #include <windows.h>
    #include <stdlib.h>
    #include <string.h>
    #include <stdio.h>
    #include <conio.h>
    #include <process.h>
    #include <time.h>
    #include <iostream>
    #include <ShellAPI.h>
    #include "OmsUmxMC.h"
    #include "dlltyp.h"
    #include "regs.h"
    #include "spcerr.h"
    #include "spcm_drv.h"
    #include "spcm_lib_card.h"
    #include "spcm_lib_data.h"
    #include "spcm_oswrap.h"
    #include "spcm_ostools.h"
    //***************************************************************************
    //Defines
    //***************************************************************************
    #define ANZAHL_SPALTEN 16384	//Spalten	(Messwerte pro Messung)
    #define ANZAHL_ZEILEN 100		//Zeilen	(Anzahl der Messungen)
    #define SPALTENBREITE 10
    #define ANZAHL_ZEILENENDE 2
    #define MAX_THREADS  32
    #define getrandom( min, max ) (SHORT)((rand() % (int)(((max) + 1) - \ (min))) + (min))
    //***************************************************************************
    //Funktionsprototypen
    //***************************************************************************
    //int		main( void ); 
    int		main( int); // Thread 1: main 
    void	KbdFunc( void  );               // Keyboard input, thread dispatch
    void	ClearScreen( void );            // Screen clear 
    void	ShutDown( void );               // Program shutdown 
    void	WriteTitle( int ThreadNum );    // Display title bar information 
    void	stoppuhr( void *ch);
    void	vDoCardSetup (ST_SPCM_CARDINFO *pstCard);
    int16	nShowDigitalInputData (ST_SPCM_CARDINFO *pstCard, void* pvBuffer, uint32 dwNrOfSamplesToShow);
    int16	nShowAnalogData (ST_SPCM_CARDINFO *pstCard, void* pvBuffer,int k);
    int16	nShowDigitalData (ST_SPCM_CARDINFO *pstCard, void* pvBuffer, uint32 dwNrOfSamplesToShow);
    void	scan (void *pMyID);
    
    //void	scan ();
    int		scannen(int k);
    int		links();
    void	reset();
    void	fahren(void *pMyID);
    
    //void	fahren();
    int		initMesskarte();
    //***************************************************************************
    //Globale Variablen
    //***************************************************************************
    HANDLE  hConsoleOut;                 // Handle to the console 
    HANDLE  hRunMutex;                   // "Keep Running" mutex 
    HANDLE  hScreenMutex;                // "Screen update" mutex
    int     ThreadNr;                    // Number of threads started 
    CONSOLE_SCREEN_BUFFER_INFO csbiInfo; // Console information 
    char	ControllerModel[128] = {0};
    char    Response[128] = {0};
    HANDLE  OmsUmxHandle;
    long    PortNumber;
    long    BaudRate;
    int     Status = 0,		TimeLimit = 0;
    BOOL    Done;
    long    StatusFlags;
    int		zahl,			weiter = 1,		count = 0;
    char	teil2[]		= "120000";	//Länge der Drehung 
    char	teil1[25]	= "axmr+" ;//Achs- und Richtungsangabe //	-:hoch			+:runter
    char	teil3[]		= ";goid" ;//Startbefehl
    char	kette[50];
    short	wert[16384][100];
    int		a=0;
    int		b=0;
    
    	char                szBuffer[1024];     //Array zur Speicherung von Daten
        ST_SPCM_CARDINFO    stCard;             //Informationsstrucktur
        uint64              qwMemInBytes;
        void*               pvBuffer;
        int32               lValue;	
    
    //***************************************************************************
    //Main
    //***************************************************************************
    int main(int a) 
    {	
        ThreadNr = 0;
    
    	//Threads
    	int KeyInfo;
    	//initMesskarte();
    	do
       {
    		KeyInfo = _getch();
    		if ( tolower( KeyInfo ) == 'a' && ThreadNr < MAX_THREADS )
    		{	//Threads starten		
    			//_beginthread(scan	, 0	,	&ThreadNr );
    			//_beginthread(fahren	, 0	,	&ThreadNr );
    			_beginthread(scan	, 1	,	NULL );
    			SetThreadAffinityMask(scan,1); 
    			_beginthread(fahren	, 0	,	NULL );
    			SetThreadAffinityMask(fahren,2); 
    		}
    			//printf("%i",Done);
    	} while( tolower( KeyInfo ) != 'q' );//Fenster schließen
    
    	//while (Done!=1)
    	//{
    	//	while(Done==1)
    	//	{
    			//Datenspeicherung
    			FILE *fp=fopen("C:/Messergebnis.txt","w"); //Zieldatei
    			int s,z;	
    			for (s=0;s<ANZAHL_ZEILEN;s++)
    			{
    				for(z=0;z<ANZAHL_SPALTEN;z++)
    				{
    					fprintf(fp, "%*d", SPALTENBREITE,wert[z][s]);
    				}
    				fprintf(fp,"\n");
    			}
    	//	}
    	//}
    
    }
    //***************************************************************************
    //Funktionen
    //***************************************************************************
    void ShutDown( void ) // Shut down threads 
    {
        while ( ThreadNr > 0 )
        {
            // Tell thread to die and record its death.
            ReleaseMutex( hRunMutex );
            ThreadNr--;   
        }
        // Clean up display when done
        WaitForSingleObject( hScreenMutex, INFINITE );
        ClearScreen();
    }
    //
    void WriteTitle( int ThreadNum )
    {
        enum 
    	{ 
            sizeOfNThreadMsg = 80 
        };
        char    NThreadMsg[sizeOfNThreadMsg];
        sprintf_s( NThreadMsg, sizeOfNThreadMsg, " Start= 'A'  Beenden='Q'", ThreadNum );
        SetConsoleTitle( NThreadMsg );
    }
    //
    void ClearScreen( void )
    {
        DWORD    dummy;
        COORD    Home = { 0, 0 };
        FillConsoleOutputCharacter( hConsoleOut, ' ', csbiInfo.dwSize.X * csbiInfo.dwSize.Y, Home, &dummy );
    }
    //
    void fahren (void *pMyID)
    {	
    	//Motion Controller initialisieren
    	//PORT Nummer und Baudrate setzen
    	PortNumber = 3;
    	BaudRate = 9600;
    	reset();
    	//Überprüfung ob Controller erreichbar ist
    	Status = SendAndGetString(OmsUmxHandle, "wy", ControllerModel);
    	if(Status == SUCCESS)//Cotroller erreichbar
    	{
    		//printf("\n MC bereit! \n");
    	}
    	else	//Cotroller nicht erreichbar
    	{ 
    		printf("ERROR -----> Der Motion Controller antwortet nicht!!!\n");
    		CloseOmsUmxHandle(OmsUmxHandle);
    	}
    	//Stringerstellung zur Schrittanzahlübergabe
    	strcat_s(teil1,teil2);
    	strcat_s(teil1,teil3);
    	strcpy_s(kette,teil1);
    	links();
    }
    //
    void scan (void *pMyID)//void scan ()	
    {//Einstellung wieviele Messungen durchgeführt werden
    	for (int i=0; i<ANZAHL_ZEILEN; i++)
    	{		//printf("\n *");
    	//Anzahl der Messungen==ANZAHL_ZEILEN
    		scannen(i);	
    	}
    }
    //
    int initMesskarte()
    {	
    
        // Initialisierung der Messkarte
        if (bSpcMInitCardByIdx (&stCard, 0))
        {    
    		//printf (pszSpcMPrintCardInfo (&stCard, szBuffer, sizeof (szBuffer)));
    	}
        else
    	{
            return nSpcMErrorMessageStdOut (&stCard, "ERROR -----> Motion Controller kannnicht geöffnet weren\n", true);
    	}
        // Check ob Karte unterstützt wird 
        if (stCard.eCardFunction != AnalogIn && stCard.eCardFunction != DigitalOut && stCard.eCardFunction != DigitalIO)
    	{
            return nSpcMErrorMessageStdOut (&stCard, "Error\n", false);
    	}
        // Messkartensetup
        if (!stCard.bSetError)
    	{
            vDoCardSetup (&stCard);//Einstellung von Trigger/Samplerate/Offset etc
    	}
        // Allokiere Speicherbedarf
        if (!stCard.bSetError)
        {
            switch (stCard.eCardFunction)
            {
                case AnalogIn:
                    qwMemInBytes = stCard.llSetMemsize * stCard.lBytesPerSample * stCard.lSetChannels;     
                    break;
                case DigitalIO:
                    qwMemInBytes = stCard.llSetMemsize;     
                    break;
            }
           pvBuffer = (void*) new uint8[(int) qwMemInBytes];
            if (!pvBuffer)
                return nSpcMErrorMessageStdOut (&stCard, "ERROR -----> Speicherallokation\n", false);
        }
    }
    //
    int links()
    {	//Sleep(2000);
    
    	//Funktion fährt auf +90°//int links()
    	Status  = SendString(OmsUmxHandle, kette);		
    	if(Status == SUCCESS)
    	{
    		// Wait for a Done event, a Overtravel event or one second to pass 
    		TimeLimit = 5000;
    		do
    		{
    			Done = GlobalDoneEvent(OmsUmxHandle);
    			GetStatusFlags(OmsUmxHandle, &StatusFlags);
    			Sleep(10);
    			TimeLimit -= 10;
    		}
    		while (!Done && ((StatusFlags & OVERTRAVEL_ERROR) != OVERTRAVEL_ERROR) && (TimeLimit > 0)); 	
    		//if (Done==1)//DONE EVENT wenn befehl fertig ausgeführt worden ist
    		//{
    		//	
    			//a=1;
    			//ShutDown();
    			//return (a);
    		//}
    			// If the move did not time out 
    			if(TimeLimit > 0)
    			{
    				// If the move was successful 
    				if((StatusFlags & OVERTRAVEL_ERROR) != OVERTRAVEL_ERROR)
    				{
    					// Ask the controller for the new X axis position 
    					//Status = SendAndGetString(OmsUmxHandle, "axrp", Response);
    					if(Status == SUCCESS)
    					{
    						printf("\n  %s \n",Response);
    						CloseOmsUmxHandle(OmsUmxHandle);
    						return(0);
    					} 
    					else
    					{
    						printf("\nERROR -----> Der Motion Controller ist nicht in der Lage rechtzeitig aus die Abfrage zu reagieren\n");
    						CloseOmsUmxHandle(OmsUmxHandle);
    						return(1);
    					}}	
    				else // Report the overtravel 
    				{
    					printf("ERROR -----> Achsenüberlauf error\n");
    					CloseOmsUmxHandle(OmsUmxHandle);
    					return(1);
    				}}
    			else
    			{
    				printf("\nERROR -----> Timeout bevor die Bewegung fertig ausgeführt wurde\n");
    				CloseOmsUmxHandle(OmsUmxHandle);
    				return(1);
    			}}
    		else
    		{
    			printf("\nERROR -----> während des Senden des Bewegungsbefehls\n");
    			CloseOmsUmxHandle(OmsUmxHandle);
    			return(1);
    		}
    }
    //
    void reset()
    {//Resetet die gesetzten Werte
    	OmsUmxHandle = GetOmsUmxHandle(PortNumber, BaudRate);
    	if(OmsUmxHandle == (HANDLE)NULL)
    	{
    		printf("ERROR -----> Port ist nicht erreichbar!!! \n");
    	}
    	//Query the global done flag to set it false 
    	Done = GlobalDoneEvent(OmsUmxHandle);
    	//Clear all controller error status flags
    	ClrStatusFlags(OmsUmxHandle, (COMMAND_ERROR + SLIP_ERROR + OVERTRAVEL_ERROR));
    	// Command a relative move and request notification when the move is complete.
    }
    //
    int scannen (int k)
    {//eigentliche Funktion zu Aufnahme der Daten
        //char                szBuffer[1024];     //Array zur Speicherung von Daten
        //ST_SPCM_CARDINFO    stCard;             //Informationsstrucktur
        //uint64              qwMemInBytes;
        //void*               pvBuffer;
        //int32               lValue;	
        // Initialisierung der Messkarte
    
    	if (bSpcMInitCardByIdx (&stCard, 0))
        {    
    		//printf (pszSpcMPrintCardInfo (&stCard, szBuffer, sizeof (szBuffer)));
    	}
        else
    	{
            return nSpcMErrorMessageStdOut (&stCard, "ERROR -----> Motion Controller kannnicht geöffnet weren\n", true);
    	}
        // Check ob Karte unterstützt wird 
        if (stCard.eCardFunction != AnalogIn && stCard.eCardFunction != DigitalOut && stCard.eCardFunction != DigitalIO)
    	{
            return nSpcMErrorMessageStdOut (&stCard, "Error\n", false);
    	}
    
        // Messkartensetup
        if (!stCard.bSetError)
    	{
            vDoCardSetup (&stCard);//Einstellung von Trigger/Samplerate/Offset etc
    	}
        // Allokiere Speicherbedarf
        if (!stCard.bSetError)
        {
            switch (stCard.eCardFunction)
            {
                case AnalogIn:
                    qwMemInBytes = stCard.llSetMemsize * stCard.lBytesPerSample * stCard.lSetChannels;     
                    break;
                case DigitalIO:
                    qwMemInBytes = stCard.llSetMemsize;     
                    break;
            }
            pvBuffer = (void*) new uint8[(int) qwMemInBytes];
            if (!pvBuffer)
                return nSpcMErrorMessageStdOut (&stCard, "ERROR -----> Speicherallokation\n", false);
        }
    
        // Aquisitation und Daten holen
        if (!stCard.bSetError)
        {
            // Start der Karte und warte bis Karte bereit ist
    		spcm_dwSetParam_i32 (stCard.hDrv, SPC_TIMEOUT, 10000);
            //starte Karte und warte auf Interrupt: READY
    		if (spcm_dwSetParam_i32 (stCard.hDrv, SPC_M2CMD, M2CMD_CARD_START | M2CMD_CARD_ENABLETRIGGER | M2CMD_CARD_WAITREADY) == ERR_TIMEOUT)
            {
                delete [] ((uint8*) pvBuffer);
                return nSpcMErrorMessageStdOut (&stCard, "ERROR ----> Timeout\n", false);
            }
            else
            {
    
                // definiere Speicher für den Transfer  und Starte ihn
    			spcm_dwDefTransfer_i64	(stCard.hDrv, SPCM_BUF_DATA, SPCM_DIR_CARDTOPC, 0, pvBuffer, 0, qwMemInBytes);
                spcm_dwSetParam_i32		(stCard.hDrv, SPC_M2CMD, M2CMD_DATA_STARTDMA | M2CMD_DATA_WAITDMA);
                // Fehlercheck
    
                if (spcm_dwGetErrorInfo_i32 (stCard.hDrv, NULL, NULL, szBuffer))
                {
                    delete [] ((uint8*) pvBuffer);
                    return nSpcMErrorMessageStdOut (&stCard, szBuffer, false);
                }} }    
        // Aufteilen der Daten in die verschiedenen Kanäle
        if (!stCard.bSetError)
    
            switch (stCard.eCardFunction)
            {
                case AnalogIn:
    				do
    				{
    
                    spcm_dwGetParam_i32 (stCard.hDrv, SPC_READDIGITAL, &lValue);		//Messaufnahme
    
                    // Digitale Inputs gesetz?
    					if (lValue)
    					{
    						// Speicheralokation
    						void* pvAnalogData  = (void*) new uint8[(int) qwMemInBytes]; 
    						void* pvDigitalData = (void*) new uint8[(int) (qwMemInBytes / stCard.lBytesPerSample)];                    
    						// Aufsplitten der Daten in digital/analog
    						bSpcMSplitAnalogAndDigitalData (&stCard, pvBuffer, (uint32)(qwMemInBytes / stCard.lBytesPerSample), pvAnalogData, pvDigitalData);                    
    						// zeige Digitaledaten
    						nShowDigitalInputData (&stCard, pvDigitalData, 10);
    						// zeige Analogdaten
    						nShowAnalogData (&stCard, pvAnalogData,k);
    
                        }
                    else
                        nShowAnalogData (&stCard, pvBuffer,k);		//Darstellung
    
    				}while(Done!=1);
    
                    break;
                case DigitalIO:
                    nShowDigitalData (&stCard, pvBuffer, 10);  
                    break;
                }
        // Fehlermeldung
        if (stCard.bSetError)
    	{
    		return nSpcMErrorMessageStdOut (&stCard, "ERROR ----> Motion Controller kann nicht programmiert werden\n", true);
    	}
    
        // Speicher löschen und Karte schließen
        vSpcMCloseCard (&stCard);
    	//printf("\n geschlossen");
    
    	delete [] ((uint8*) pvBuffer);
    	//printf("\n gelöscht");
    
        return 1;
    }
    //
    void vDoCardSetup (ST_SPCM_CARDINFO *pstCard)
    {//vDoCardSetup
        int i;
        int64 llChannelMask;
        // Kanalmasken setzten
        if (pstCard->lMaxChannels >= 64)
            llChannelMask = -1; // -1 is all bits set to 1 = 0xffffffffffffffff
        else
            llChannelMask = ((int64) 1 << pstCard->lMaxChannels) - 1;
    
    	//Triggereinstellung
    	//	|<------Memsize------->|
    	//	|<--Pre--->||<--Post-->|
    	//bSpcMSetupModeRecStdSingle (pstCard,	llChannelMask,		MEMSIZE,	POSTTRIGGER;//original
        bSpcMSetupModeRecStdSingle (pstCard,	llChannelMask,		KILO_B(16), KILO_B(16));
    
    	// Samplerate 
        //bSpcMSetupClockPLL (pstCard, pstCard->lMaxSamplerate / 4, false); //original
    	bSpcMSetupClockPLL (pstCard, pstCard->lMaxSamplerate , false);
    	//bSpcMSetupClockPLL (pstCard, 1000000 , false);
    
    	//Triggereinstellungen (Software/Extern/Kanal)
    	//bSpcMSetupTrigSoftware (pstCard, false); //original				//Software
    	bSpcMSetupTrigExternal (pstCard, SPC_TM_POS);						//Extern USD15S
        //bSpcMSetupTrigChannel(pstCard,SPC_TRIG_CH0_MODE, SPC_TM_POS);		//Kanal
    
        switch (pstCard->eCardFunction)
            {
            case AnalogIn:
    			//Offset einstellen
                for (i=0; i < pstCard->lMaxChannels; i++)
    				//bSpcMSetupInputChannel (	pstCard, i,		OFFSET, true);
    				bSpcMSetupInputChannel (	pstCard, i,		10000,	true);
                   // bSpcMSetupPathInputCh (		pstCard, i, 0,		10000,	false, true, true); // setup for M3i card series including new features
                // aktiviere digitale Inputs
                if (pstCard->lFeatureMap & SPCM_FEAT_DIGITAL)
                    spcm_dwSetParam_i32 (pstCard->hDrv, SPC_READDIGITAL, 1);            
                break;
            case DigitalIn:
            case DigitalIO:
                // Eingangswiderstände setzetn
                for (i=0; i < pstCard->uCfg.stDIO.lGroups; i++)
                    bSpcMSetupDigitalInput (pstCard, i, true);
                break;
            }
        }
    //
    int16 nShowAnalogData (ST_SPCM_CARDINFO *pstCard, void* pvBuffer,int k)
    {//nShowAnalogData 
    
        int     i;
        double  dAverage;
        int16   nMin;
        int16   nMax;
        int16*  ppnChannelData[SPCM_MAX_AICHANNEL];
        // Kanaldaten
        for (i=0; i<pstCard->lSetChannels; i++)
        {
            ppnChannelData[i] = new int16[(int32) pstCard->llSetMemsize];
            if (!ppnChannelData[i])
    		{
                return nSpcMErrorMessageStdOut (pstCard, "ERROR -----> Speicherallokation\n", false);
    		}
        }   
        // Aufsplitten der Daten
        bSpcMDemuxAnalogDataToInt16 (pstCard, pvBuffer, (int32) pstCard->llSetMemsize, ppnChannelData);
        // Daten aus Speicher holen
       for (i=0; i<pstCard->lSetChannels; i++)
       {
            dAverage =dSpcMCalcAverage(ppnChannelData[0], (uint32) pstCard->llSetMemsize, k);	
    
       }
       for (i=0; i<pstCard->lSetChannels; i++)
       {
          delete [] (ppnChannelData[i]);
       }
    
        return 0;
    }
    //
    int16 nShowDigitalInputData (ST_SPCM_CARDINFO *pstCard, void* pvBuffer, uint32 dwNrOfSamplesToShow)
    {//nShowDigitalInputData 
        int32 lNrOfDigCh, lCh, lBitShift, i;
        uint32 dwSampleIdx;
        uint8 byDigMask, byBitVal;
        uint8* ppbyChannelData[SPCM_MAX_AICHANNEL];
        lNrOfDigCh = 16 - pstCard->uCfg.stAI.lResolution;
        // allocate channel data
        for (i = 0; i < pstCard->lSetChannels; i++)
            {
            ppbyChannelData[i] = new uint8[(int32)pstCard->llSetMemsize];
            if (!ppbyChannelData[i])
                return nSpcMErrorMessageStdOut (pstCard, "ERROR -----> Speicherallokation\n", false);
            }
        bSpcMDemuxDigitalInputDataToUInt8 (pstCard, pvBuffer, (int32)pstCard->llSetMemsize, ppbyChannelData);
        for (dwSampleIdx = 0; dwSampleIdx < dwNrOfSamplesToShow; dwSampleIdx++)
            {
            for (lCh = 0; lCh < pstCard->lSetChannels; lCh++)
                {
                byDigMask = ppbyChannelData[lCh][dwSampleIdx]; 	
                lBitShift = 0;
                do 
                    {
                    byBitVal  = byDigMask & 0x01;
                    byDigMask = byDigMask >> 1;
                    lBitShift++;
                    }while (lBitShift < lNrOfDigCh);
                }}
        for (i = 0; i < pstCard->lSetChannels; i++)
            delete [] (ppbyChannelData[i]);
        return 0;	
     }
    //
    int16 nShowDigitalData (ST_SPCM_CARDINFO *pstCard, void* pvBuffer, uint32 dwNrOfSamplesToShow)
    {//nShowDigitalData 
        int32 i, lChIdx;
        uint32 dwSampleIdx;
        int8* ppbyChannelData[SPCM_MAX_DIOCHANNEL];
        // allocate channel data
        for (i=0; i<pstCard->lSetChannels; i++)
        {
            ppbyChannelData[i] = new int8[(int32) pstCard->llSetMemsize];
            if (!ppbyChannelData[i])
                return nSpcMErrorMessageStdOut (pstCard, "ERROR -----> Speicherallokation\n", false);
        }
        bSpcMDemuxDigitalDataToInt8 (pstCard, pvBuffer, (int32) (pstCard->llSetMemsize), ppbyChannelData);
        for (dwSampleIdx=0; dwSampleIdx<dwNrOfSamplesToShow; dwSampleIdx++)
        {
                if (pstCard->lSetChannels < 16)
                {
                    lChIdx = pstCard->lSetChannels-1;
                    while (lChIdx >= 0)
                    {
                      // printf ("[D%d] = %d ", lChIdx, ppbyChannelData[lChIdx][dwSampleIdx]);
                        lChIdx--;
                    }
    
                    //printf ("\n\n");
                }
                else
                {
    				lChIdx = pstCard->lSetChannels-1;
                    while (lChIdx > 0)
                    {
                        //printf ("[D%d ......... D%d] ", lChIdx, lChIdx - 15);
                        lChIdx -= 16;
                    }
                    lChIdx = pstCard->lSetChannels-1;
                    while (lChIdx >= 0)
                    {
                        if (!(lChIdx%16))
    					{
    					}
                        else
    					{
                            if (!(lChIdx%4))
    						{
    						}
    					}
                        lChIdx--;
                    }}	}
        for (i=0; i<pstCard->lSetChannels; i++)
            delete [] (ppbyChannelData[i]);
        return 0;
    }
    

Anmelden zum Antworten