2007/07/12

Ni-Visa Observer pattern

Some days a go, I wrote something about the bridge pattern, and about where I want to apply it on my control software development. Now I am witting the VISA class from the diagram that I propose, that is a subclass of the ControlEnvironment class, this is an implementation in the bridge pattern.

In the way to reduce the number of data transmisions, the ni-visa protocol allows to subscribe your proces to a handler, this is a new thread, who will do the read() operation only when something new is able to be transmitted. Further than this, I want to have shared memory segments in side the agent to minimize also the internals memmove().

But it does not work! The ni-visa library sends me an error when I am trying to do this subscription. Without copy the error handlering my procedure is:

VISA::VISA(char *instrName,int timeout){
    sprintf(_rsrcName,"TCPIP0::%s::INSTR\0",instrName);
    _timeout = timeout;
    _status = viOpenDefaultRM(&_defaultRM);
}


int VISA::Open(){
    _status = viOpen(_defaultRM, _rsrcName, VI_NULL, VI_NULL, &_instr);
    _status = viSetAttribute(_instr, VI_ATTR_TMO_VALUE, _timeout);
    viClear(_instr);
    return _status;
}


int VISA::Open(const unsigned int ch){
    if (shmMalloc(ch) != VI_SUCCESS) return -1;
    if (Handlering(ch)!= VI_SUCCESS) return -1;
    return 0;
}


ViStatus VISA::Handlering(unsigned int ch){
    ViEventType event=VI_EVENT_SERVICE_REQ;
    _status = viInstallHandler(_instr, event, callback, _bufferHandler[ch]);
    _status = viEnableEvent(_instr, event, VI_HNDLR, VI_NULL);
    _status = openAChannel(ch);
    return _status;
}


ViStatus VISA::openAChannel(const unsigned int ch){
    char cmd[MAX_CNT];
    memset(cmd,0,sizeof(cmd));
    sprintf(cmd,"READ:WAVFM:CH%d",ch);
    _status = viWrite(_instr, (ViByte*)cmd, strlen(cmd), &_retCount);
    return _status;
}


I Really don't know what I am doing wrong.

Actualization:
I am trying to communicate with the instrument asynchronous but without the handler. Only asking for the spectrum, and waiting for it to be served. The Open() method change and a new one appears under the name EnqueueRead().



int VISA::Open(const unsigned int ch){
    if (shmMalloc(ch) != VI_SUCCESS) return -1;
    if (EnqueueRead(ch)!= VI_SUCCESS) return -1;
    return 0;
}


ViStatus VISA::EnqueueRead(unsigned int ch){
    ViEventType event=VI_EVENT_IO_COMPLETION;
    _status = viEnableEvent(_instr,event,VI_QUEUE,VI_NULL);
    _status = openAChannel(ch);
    _status = viWaitOnEvent (_instr, event, _timeout, VI_NULL, VI_NULL);
    _status = viReadSTB(_instr,&stb);
    _status = viReadAsync(_instr,(ViBuf)_bufferHandler[ch],MAX_CNT,&jobID);
    _status = viDisableEvent(_instr,event,VI_QUEUE);
    return _status;
}


ViStatus VISA::openAChannel(const unsigned int ch){
    char cmd[MAX_CNT];
    memset(cmd,0,sizeof(cmd));
    sprintf(cmd,"READ:WAVFM:CH%d",ch);
    _status = viWrite(_instr, (ViByte*)cmd, strlen(cmd), &_retCount);
    return _status;
}


Actualization:
The question (problem, issue,...) has been send to Tektronix, and they redirect it to National Instruments...

No comments: