This device driver uses the buffer and interrupt capability of the analog input section of the VME International Systems, Inc VMIVME-3115 analog input/output board. The buffers are filled at a rate set from the board itself which is asynchronous from the timer clock on the main CPU board that normally gets used by the model code. To use this block, code in rt_main.c needs to be modified so as not to wait for timer interrupts but instead wait for A/D interrupts. The generated code for the Outputs function of this block waits for the A/D interrupt. Thus, by commenting out code in the following 3 places of rt_main.c, proper operation is achieved.
1) In tBaseRate() comment out:
if (semTake(sem,NO_WAIT) != ERROR) { logMsg("Rate for SingleRate task too fast.\n",0,0,0,0,0,0); #ifdef STOPONOVERRUN logMsg("Aborting real-time simulation.\n",0,0,0,0,0,0); semGive(stopSem); return(1); #endif } else { semTake(sem, WAIT_FOREVER); }
2) In tSingleRate() comment out:
if (semTake(sem,NO_WAIT) != ERROR) { logMsg("Rate for SingleRate task too fast.\n",0,0,0,0,0,0); #ifdef STOPONOVERRUN logMsg("Aborting real-time simulation.\n",0,0,0,0,0,0); semGive(stopSem); return(1); #endif } else { semTake(sem, WAIT_FOREVER); }
3) In rt_main() comment out:
if (sysAuxClkConnect((FUNCPTR) semGive, (int_T) rtClockSem) == OK) { rebootHookAdd((FUNCPTR) sysAuxClkDisable); printf("\nSimulation Starting\n"); sysAuxClkEnable(); /%start the real-time simulation%/ }
This block implements a different form of I/O than what is typically used in control systems. In control systems, a point device driver is traditionally implemented, where only 1 data point is collected. While this provides the lowest latency possible, it limits the maximum sample rate that the model can be run at due to the hardware/software overhead involved. To achieve much higher sample rates, buffering in the I/O can be used, at the expense of increased latency. This method is useful when operating on blocks of data, where throughput is more important than the latency. This occurs frequently in signal processing applications such as when filtering an audio signal.
In order to use this block, the timer clock which the model code normally run off of needs to be disabled. This is because the timer clock oscillator and the A/D oscillator are different and thus, thus the rate at which the A/D converts and the rate at which this block is called would never match exactly. Either stale data would have to be output or new data dropped occasionally. This is corrected by running the model code off of the A/D oscillator as well.
Thus, the model code should not use the timer interrupt because it will instead block inside this blocks Outputs function, waiting for the next buffer full interrupt. In between buffer full interrupts, the model runs freely. This means that "real-time" model execution is maintained only at the rate of the A/D interrupt. Faster rates and non-integer multiples of the interrupt rate get executed in a non real-time fashion. For example, if this block is set to a sample time of 128 usec and the buffer size is 512, then an A/D buffer full interrupt will occur every 128 usec * (512 words/4 channels) or every 16.384 msec. Thus, all sample_times faster than .016384 will occur as fast as the CPU can get to them after a A/D interrupt occurs. Likewise, any rates that aren't an integer multiple of .016384 will occur as fast as the CPU can get to them after the appropriate A/D interrupt occurs.