[linrad] Re: Network standards for SDR
On Sat, 6 Jan 2007 05:59:55 +0100 J.D. Bakker [EMAIL PROTECTED] wrote: typedef struct { short header_len; // This field is always present, and always first short data_len;// This field is always present, and always second [ header contents, including header version, type, etc. goes here ] char data[NET_MULTICAST_PAYLOAD]; } NET_RX_STRUCT; NET_RX_STRUCT msg; rxin_char=(void*)(timf1_char[timf1p_pa]); timf1p_pa=(timf1p_pa+ad_read_bytes)timf1_bytemask; for(j=0; jad_read_bytes; j+=NET_MULTICAST_PAYLOAD) { recvfrom(netfd.rec_rx,msg,sizeof(NET_RX_STRUCT),0, (struct sockaddr *) rx_addr,addrlen); memcpy(rxin_char[j], ((void *)msg) + msg.header_len, NET_MULTICAST_PAYLOAD); } OK, now you just added an extra copy operation and the ReadData does not return a pointer. This was exactly what I referred to from the start. For the time being I kept the data size constant, to not mix the issues (variable data size adds 5-6 lines). And yes, there is a memcpy. But read below... By the way, there appears to be an inconsistency in your program. Here: timf1p_pa=(timf1p_pa+ad_read_bytes)timf1_bytemask; you make sure that the address pointer for the circular buffer wraps around, but I see no such protection in the for() loop. Or am I missing something ? Yes. ad_read_bytes is a power of two so it always goes even in the buffer. An extra memcpy makes little difference in this loop. Note that the recvfrom() needs to do the equivalent of a memcpy() anyway. I wrote a little test program (see the bottom of this mail) to test the speed difference between 1 and 2 copy instructions if the destination buffer is larger than the cache. On a Pentium MMX 166MHz, a Thinkpad laptop with X running, I get: Single copy: 1000 loops in 129.44 seconds, or 79.11 MiBps. Double copy: 1000 loops in 147.21 seconds, or 69.56 MiBps. Hmmm, actually changing the Linrad code to do the double copy as you suggest increases the CPU load from 47.5% to 48.5% when 16 bit raw data is received on a 200 MHz Pentium MMX. This makes me believe that receiving fft1 transforms which will be necessary for this computer to do meaningful work will lead to an extra load of 4 percent units and that is not insignificant at all. (32 bit floats, interleaved transforms) The fft1 mode does not yet work so I can not test right now, but I hav reasons to believe that the MMX routines will allow this computer to work well as a slave with two channels at 96 kHz bandwidth. Is there any way at all that you can avoid that, and process the data as it comes in ? My first big multi-threaded program was a real-time streaming video encoder for a quad Pentium Pro machine, and switching processing from a frame at a time to a macroblock (16x16pixels) at a time sped the encoder up tremendously, even though the required number of operations almost doubled. I do not know, but it is going to be difficult if possible at all. The most demanding task is the full bandwidth, full dynamic range FFT. It would be identical in all computers and it does not make any sense to do it in more than one computer. Why ? Because this one computer would be much faster than the others ? Yes. Amateurs typically have one modern computer (running Windows) plus a couple of scrap computers that would be perfectly adequate as slaves. So would it be correct to say that: (a) if all computers were equally fast, there is little advantage in cooked mode over raw mode (other than energy conservation), and Right now yes, but with future add-ons this might change because the master might do only front-end processing because it is not fast enough to do everything. Actually I think it will be possible to use two Pentium MMX with one doing fft1 and nothing more while the other is doing fft2 and down conversion. It will be near the limits for what these computers can do - one of them is just a little to slow. At the moment CPU time is no problem at all because we do not yet have the wideband hardware that modern computers could serve. (b) cooked mode allows slow slaves that would normally not be able to keep up with the FFTs to still display the data. There are many FFTs in Linrad. fft1(forward full bw) - fft1(backward 2 * full bw) - fft2(forward full bw) - fft2(backward narrow bw) - fft3(forward narrow bw) - fft3(backward narrow bw) There is dsp processing alternating between the frequency domain and the time domain. Only the very first fft needs full dynamic range and uses float. The remaining wideband processing uses MMX. This was necessary when a modern computer was Pentium 3. Today floats can be used, but not if one wants to monitor several microwave bands on the same computer. Because of the much higher speed of 16 bit MMX routines the first fft takes as much time as all the other tasks together. Since the processing of all the other transforms depends on what frequency
[linrad] Re: Network standards for SDR
Hi Leif and all, - I would want a timestamp in there somewhere. It might be derived from block_no, but why not make it explicit ? I do not see what it would be good for. Why do you want the clock from the master while there is another one in the slave? Surely I could add this, but there is a cost to it. The packages are sent out at maybe 1 kHz. The corresponding time resolution is 1 ms. There is an appreciable time jitter however and it is not obvious what time to put into a specific package. Presumably it should be the time when the first sample within the package was taken from the hardware. What would it be good for? It is not trivial to evaluate. I agree that a timestamp will be useful. For what I am thinking about, very high precision and high accuracy are not required. JT65 wants to know the UTC of a data block to within a second or so. (Relative timing among successive blocks is of course maintained by the fixed and nominally known sample rate.) Of course the slave computer could use its own time, but that will add another level of jitter. As a minimum, I suggest that each packet include as a 32-bit integer the number of seconds since the Unix epoch, according to the master computer's system clock. So much the better if you include a number of milliseconds as a second number, or combine both into a double. Never mind about jitter; the receiving program would need to know that jitter in the time values will exist, and behave accordingly. Together with the block number, these approaches will suffice very nicely for JT65, anyway. They will work better and more reliably than having the slave computer use its own system clock. Please let me know when a broadcast-enabled Linrad version is available for testing with MAP65. And if you have some example code for use by the receiving program -- or, say, a stand-alone dummy receiving program that can receive broadcast packets, I would be happy to see the code! -- Joe, K1JT # This message is sent to you because you are subscribed to the mailing list linrad@antennspecialisten.se. To unsubscribe, E-mail to: [EMAIL PROTECTED] To switch to the DIGEST mode, E-mail to [EMAIL PROTECTED] To switch to the INDEX mode, E-mail to [EMAIL PROTECTED] Send administrative queries to [EMAIL PROTECTED]
[linrad] Re: Network standards for SDR
Hi Joe and all, I agree that a timestamp will be useful. For what I am thinking about, very high precision and high accuracy are not required. JT65 wants to know the UTC of a data block to within a second or so. (Relative timing among successive blocks is of course maintained by the fixed and nominally known sample rate.) Of course the slave computer could use its own time, but that will add another level of jitter. As a minimum, I suggest that each packet include as a 32-bit integer the number of seconds since the Unix epoch, according to the master computer's system clock. So much the better if you include a number of milliseconds as a second number, or combine both into a double. Never mind about jitter; the receiving program would need to know that jitter in the time values will exist, and behave accordingly. Together with the block number, these approaches will suffice very nicely for JT65, anyway. They will work better and more reliably than having the slave computer use its own system clock. OK. This is what it looks like under Windows: int lir_get_epoch_seconds(void) { // Here we have to add a calendar to add the number // of seconds from todays (year, month, day) to Jan 1 1970. // The epoch time is needed for moon position computations. SYSTEMTIME tim; GetLocalTime(tim); return 3600.*tim.wHour+60.*tim.wMinute+tim.wSecond; } I can put the number of seconds since the Unix epoch if someone supplies the code needed in Windows. (It is needed anyway to make moon computations correct under Windows) Would it not be more convenient to supply an integer with the number of milliseconds since midnight? The accuracy (jitter) might be a few ms and that should allow averaging to find the sync tone provided that each station has adequate stability and a correction for his own part of the doppler shift. Please let me know when a broadcast-enabled Linrad version is available for testing with MAP65. And if you have some example code for use by the receiving program -- or, say, a stand-alone dummy receiving program that can receive broadcast packets, I would be happy to see the code! Pretty soon, but I will await further comments on the way it will be implemented. You already talked me into adding a time stamp. I can see that it should have less time jitter than the time stamp you can add from the system clock in MAP65. The time stamp will not necessarily be the time at which the samples arrive for each block however. The SDR-14 for example sends 8192 bytes and all 8 network packages from one read will then have the same time stamp. (Of course this can be corrected at a later stage.) Would you agree on milliseconds since midnight? From JDB I learned that a double with seconds since Unix epoch would be a bad idea since conversion may be difficult on non-PC platforms. (It is the internal time format within Linrad however) 73 Leif # This message is sent to you because you are subscribed to the mailing list linrad@antennspecialisten.se. To unsubscribe, E-mail to: [EMAIL PROTECTED] To switch to the DIGEST mode, E-mail to [EMAIL PROTECTED] To switch to the INDEX mode, E-mail to [EMAIL PROTECTED] Send administrative queries to [EMAIL PROTECTED]
[linrad] Re: Network standards for SDR
Leif and all, Would you agree on milliseconds since midnight? From JDB I learned that a double with seconds since Unix epoch would be a bad idea since conversion may be difficult on non-PC platforms. (It is the internal time format within Linrad however) Yes, milliseconds since UTC would be OK. Maybe you should send BOTH this quantity AND a double with seconds since Unix epoch (which I would actually prefer). I don't see the conversion issue as a big deal; little-endian to big-endian copnversion is trivial, and doesn't nearly everybody use IEEE floating point these days? -- Joe # This message is sent to you because you are subscribed to the mailing list linrad@antennspecialisten.se. To unsubscribe, E-mail to: [EMAIL PROTECTED] To switch to the DIGEST mode, E-mail to [EMAIL PROTECTED] To switch to the INDEX mode, E-mail to [EMAIL PROTECTED] Send administrative queries to [EMAIL PROTECTED]
[linrad] Re: Network standards for SDR
A general point: in virtually all communications protocols the (descriptive) header comes before the data block, since the receiver usually needs to decode the header to be sure what to do with the data. This also makes it possible to vary the length of the data block, if desired (for instance, to tune to FFT block sizes or sampling hardware word length). - I would want a timestamp in there somewhere. It might be derived from block_no, but why not make it explicit ? I do not see what it would be good for. Why do you want the clock from the master while there is another one in the slave? Array processing. It would be very useful for a situation where you have multiple masters on one network (either during a contest, or -in my case- with a few servers each connected to an antenna+receiver). Time sync is not hard over either GPS/TAC or ntp. Even in one-master situations it could be useful: with timestamps, it is very easy to make something similar to the Time Machine. - how is the sampling rate communicated ? The slave(client) asks the server for the meaning of the data. Number of channels, nominal sampling rate, whether the format is real or complex etc. That, too, makes it harder for dedicated hardware receivers; ideally these would not need _any_ communication from the slave to the master. As I see it, encoding this information in the header of each package is a low-overhead way to reduce ambiguity, too. - if you are not doing so already, please please _please_ use the functions htons() / ntohs() and friends to convert between host byte order and network byte order (or forever determine that linrad communicates with either little endian (IA32) or big endian (Alpha, PowerPC etc) byte order. I would want to be able to use a PC as the server and my PowerBook as the client, for instance. I do not see how it matters. Linrad does not put port numbers or addresses in the packages, that is done by the operating system and the inner workings of Linrad is not visible from the network. Byte ordering is not restricted to port numbers or addresses. Every time you put an integer which is larger than one byte into a packet, the transmitter and receiver need to agree on the byte order. See http://en.wikipedia.org/wiki/Endianness for details. Taking my example, if the master runs on an Intel machine and the slave on my PowerBook, if the master transmits a block_no of 0x01020304, my PowerBook will see that as 0x04030201. Not good. JDB. -- Years from now, if you are doing something quick and dirty, you imagine that I am looking over your shoulder and say to yourself, Dijkstra would not like this, well that would be immortality for me. -- Edsger Dijkstra, 1930 - 2002 # This message is sent to you because you are subscribed to the mailing list linrad@antennspecialisten.se. To unsubscribe, E-mail to: [EMAIL PROTECTED] To switch to the DIGEST mode, E-mail to [EMAIL PROTECTED] To switch to the INDEX mode, E-mail to [EMAIL PROTECTED] Send administrative queries to [EMAIL PROTECTED]