I'm awfully keen on the T7's output streaming capabilities. I'm writing code to use looping to make a poor-man's function generator, but as I read the example code and documentation, some of the details elude me. There is good documentation on the relevant modbus registers, there is a great example with the ljm drivers (o_stream_only.c), and there has been some discussion on the legacy forum; as well as here. Still, there are a few questions that I imagine might be obvious to an LJ developer, but that aren't quite clear to this mere mortal.
1) The STREAM_OUT#_ENABLE register "enables" the output stream, but what does that mean? Streaming can't be done unless STREAM_ENABLE is also set, and the appropriate STREAM_OUT#_TARGET is set, and STREAM_OUT# has been added to the STREAM_SCANLIST_ADDRESS list. It seems like membership in the scanlist is all that is needed to "enable" the stream.
2) The STREAM_OUT#_SET_LOOP register is a write-only register that accepts three values (Output Streaming); 1 - accept immediately, 2 - wait until Sync, and 3 - Sync. The documentation is a little vague about exactly what this register does, and what other values it affects. My best interpretation is below:
The STREAM_OUT#_LOOP_SIZE register (curiously appearing STREAM_OUT#_LOOP_NUM_VALUES in Kiping) and the buffer itself can be written to, but their new values will not be adopted into the stream immediately. This will allow the user to configure multiple output streams and trigger them to begin all at once. If STREAM_OUT#_SET_LOOP is passed 1, certain recent settings (which?) will be put into effect immediately. If a 2 is written to STREAM_OUT#_SET_LOOP, the T7 will wait for you to configure other channels. If a 3 is written to STREAM_OUT#_SET_LOOP, the T7 will immediately apply the settings of this and any other output streams that have been configured.
3) The STREAM_OUT#_LOOP_SIZE register behavior is not clear to me. New values are not adopted until STREAM_OUT#_SET_LOOP has been poked, but that behavior seems to depend on STREAM_OUT#_ENABLE. When I manually follow the sequence of writes spelled out in the o_stream_only.c example, Kipling does NOT accept my loop size. The only sequence that has worked for me in Kipling is as follows:
0 -> STREAM_OUT#_ENABLE, N -> STREAM_OUT#_LOOP_SIZE, 1 -> STREAM_OUT#_SET_LOOP, 1 -> STREAM_OUT#_ENABLE
Kipling only shows the value, N, after the final STREAM_OUT#_ENABLE command. Before that, it reads 0. This behavior is even more perplexing in code. I have attempted to make compiled c-code perform this operation only to see no corresponding change in Kipling.
The smart moderator will ask to see my code. It is currently a part of a 1500-line header. I am working on distilling the problem to a small C-file that replicates problem and I will happily share it when I do. I figured the broader questions of what these registers are and how they work seemed worth some discussion independent of my little problem.
I managed to get a single channel of output streaming to work reliably. When I try to configure two channels, only the first one configured works. This is good enough for me now. If anyone can make use of the code, please do. The code is described in the readme attached, and is documented in detail in the comments of the header itself.
Happy scripting!
Sorry for the delay. The to-do list exploded over the last couple weeks.
1) Enable checks some error conditions and allocates RAM.
2) A value of 1 will instruct the output-stream channel to start using new a data set and loop size. A value of 2 will instruct an o-stream channel to use new data and loop size when a different o-stream channel is set to 2. A value of 2 will instruct an o-stream channel to use a new data set and loop size as well as any channel that was set to 2.
3) Loop size tells the output stream channel how many values to repeat after reaching the end of the supplied data. Reading the loop size returns the current loop size. Writing to loop size sets the next loops size, which sill not be used until loop-set is written.
Thanks for the answers. I have a functional solution for now, so this is not a high priority. I'd like full functionality in the long-term, so I'll keep pressing my question slowly.
That pretty well lines up with my interpretation of the documentation. Unfortunately, I've had a terrible time getting the device to implement my changes. When I write a 1 to STREAM_OUT#_SET_LOOP I only see the new loop size settings adopted when in combination with an awfully specific sequence of enabling and disabling the output stream. My attempts to extend that lesson to multiple channels have failed.
When I look at the other OSTREAM example codes, they succeed in establishing outputs on both DAC channels by pushing out loop updates every stream read cycle. My compile of that code succeeds, and it works just fine. In my application, I want a single cyclic waveform to repeat ad infinitum, so I have been setting it up before starting the stream (like in the single-channel example code).
In summary: There seems to be some additional conditions on when and how new loop settings or new loop data are accepted. Are they undocumented, is this a bug, or am I mistaken? Thinking back, I am fully prepared to accept the idea that I have approached something incorrectly, but I have yet to find it.
Possible problems: (1) I am using different loop sizes for the two DAC channels. (2) Can the T7 not accept multiple loop updates at once? (3) Are there
How is your project going?
Stream-Out will work regardless of whether started before or after stream. Stream out channels operate independently unless using the synchronize option. Disabling Stream-Out channels is not necessary to load new data or loop sizes. Disabling is only necessary if you need to change the buffer size.
I fell off the forums for a while since data was streaming in. I never did get both AO channels to work simultaneously. I saw all kinds of inconsistent behaviors both from kipling and from my C-code. The problem still isn't critical for me, but one day I'd like to figure out what went wrong.
I now have an entire laboratory built around two T7s and a U12 using my lconfig header to configure the devices. I want to be clear; apart from this one anomaly, I have absolutely no complaints. For the money, Labjack is the best show in town.
The dev to-do list is pretty long at the moment, but if you get around to looking at stream-out again we will bump your issues up the list.
OK, I've spent a couple of hours diving back into my code, and I recreated the problem. I'll save a long description and summarize it briefly: This was entirely my fault.
Long answer: I had a bug in my code; I treated the STREAM_OUT# registers as if they were 32 bits wide, so I was incrementing their addresses by 2 instead of by 1 in a loop. As a result, I had a stream pointer pointing to an uninitialized output stream any time I tried to use more than 1 output stream. I've looked above at the peculiar behaviors I documented when I tried to manually recreate the problems in Kippling, and it's possible that they are consequences of my original foul-up.
I now have sensible outputs on both channels; thanks for your follow-up! The problem was certainly subtle (on line 1868 of lconfig.h).