stefanopod
Super Member
- Total Posts : 1285
- Reward points : 0
- Joined: 2007/06/25 02:33:59
- Location: Bologna,Italy
- Status: offline
problems in isochronous synchronisation
I tried to implement isochronous transfer, for learning purposes and I thougth that the only real unavoidable problem was to be forced to use a Cypress driver, that forbids, for copyright reasons, to employ it with non cypress chips. But I see in a post by mzoran, that there are problems of synchronization between pc cpu clock and device clock and I open a new thread, because the old one had a different purpose. I didn't experience that problem, for sure because the testing wasn't so deep, and I'm interested to know in which direction to investigate in more depth. If it's a matter of shifting of the frequence between the sampled source and the reconstructed analog signal, what is it the magniude order of the problem? What are audio specs about this problem? Or is it a long term problem of loosing samples or of hanging? (i tested only a real time loopback from HD to HD of a few megabytes, apparently without problems, loosing only the first packet). thanks a lot stefanopod
|
mzoran
Super Member
- Total Posts : 683
- Reward points : 0
- Status: offline
RE: problems in isochronous synchronisation
2007/10/20 00:11:36
(permalink)
I only know about this from the audio side of things. I haven't tried to implement ISO with a generic device such as a sensor array. The USB spec defines a few types of devices( at least this is the best from memory ): 1. Synchronous - The device PLLs the SOF signal. 2. Asynchronous - The clocks are completely unsynchronized. For OUT pipes, the device needs to send feedback to the host telling the host to either increase or decrease the number of bytes per frame. For IN pipes, the host host will adapt to the device clock. 3. Adaptive - The device adapts to the PC clocks possibly by bending the sample rate. I implemented an adaptive device by discarding samples if the buffer in the device gets too full and stretches samples if the buffer gets too low. This is only audable when playing sin waves. The problem is that with ISO you are essentially saying that X bytes will be transfered per frame so the host wants to send exactly that many bytes. If the device clock is off then sometimes more or less then X will be ready per frame. If memory serves, what I saw in Windows XP is if you create an adaptive device and don't try to do any adaption at all the PC will start discarding entire frames worth of data which sounds really really bad. Assume a 1% accurately of either the PC clock or device clock. If you have a signal at 24KHz the device is going to be behind or ahead of the PC by 1 sample every 5ms(Hopefully the math is correct). I don't remember off hand but I think I read somewhere that the USB SOF clock may not be that accurate according to the spec. I could be wrong. What kind of device and catagory of ISO did you implement?
|
stefanopod
Super Member
- Total Posts : 1285
- Reward points : 0
- Joined: 2007/06/25 02:33:59
- Location: Bologna,Italy
- Status: offline
RE: problems in isochronous synchronisation
2007/10/20 02:37:00
(permalink)
I implemented the xiaofan's bare minimum isochronous device with cyusb.sys driver, with a wrapper adapted from cystream.exe Your answer is very interesting (and kind and clear as usual). The problem in not to turn Pavarotti into Callas, but to loose, first or later, a full packet. That would be a long term problem, a kind of leak affecting the driver buffer. I didn't experience that: reading a file into packets, sending to ISO, receiving them back and writing to file, I found no packet lost. Maybe the frequence shift is so little that the problem cames up after a longer time, or I had a lucky chrystal. I'll try longer streamings (but a packet out of more a Mbyte wouldn't be so bad for such a loose spec as audio). Thanks stefanopod
|
stefanopod
Super Member
- Total Posts : 1285
- Reward points : 0
- Joined: 2007/06/25 02:33:59
- Location: Bologna,Italy
- Status: offline
RE: problems in isochronous synchronisation
2007/10/20 03:51:20
(permalink)
I correct myself: if the problem is the one pointed out by mzoran, the problem is obviously not of loosing a packet when the driver queue(if there is any) is full, but of loosing all the packets in the queue, that's really bad. stefanopod
|
sc6po
Senior Member
- Total Posts : 133
- Reward points : 0
- Joined: 2006/06/28 01:52:36
- Location: France
- Status: offline
RE: problems in isochronous synchronisation
2007/10/20 11:41:38
(permalink)
|
stefanopod
Super Member
- Total Posts : 1285
- Reward points : 0
- Joined: 2007/06/25 02:33:59
- Location: Bologna,Italy
- Status: offline
RE: problems in isochronous synchronisation
2007/10/20 14:04:31
(permalink)
Thanks sc6po, i had already read your post about synchronisation, but the issue was too difficult for me (quite simple for you,ok). Now i understand something about your "schrifts" and "plops", but I suspect I can't find "schrifts" and "plops" in my loopback test because the frequency drift in one direction is compensated from the frequency drift in the opposite direction. Or have I to find "shrifts" in one direction and "plops" in the other? I'm not sure that a test HD->PIC->HD has a meaning as a test for an audio project. I'll control better the data stream, and at the end I'll overcome my laziness and I'll try an oscylloscope test; but I really think i'll find "schrifts" and "plops"; what a pity! And facing audio class looks a bit too complicated for me. Tanks anyway. stefanopod
|
sc6po
Senior Member
- Total Posts : 133
- Reward points : 0
- Joined: 2006/06/28 01:52:36
- Location: France
- Status: offline
RE: problems in isochronous synchronisation
2007/10/21 03:21:40
(permalink)
When I say "quite simple", the thing is that is once you have understood, it is "quite simple"...The issue is that the doc is not always very to understand the first time....You got to read it and read it again... Feedback Endpoint is really simple to implement : EPAdress Isoc + Async bRefresh bsyncAdress _EP02_OUT, _ISO | _ASYNC, 0 _EP02_IN, _EP02_IN, _ISO | _FE , 7 0 These are the only information you got to add! This way, the host, if able to handle feedback, will request EP02_IN every 2e7ms. You got to retrieve the correct info : this is also simple, but it took me some time to know which info to send... The info to send is the number of samples per frame 8 if the freq is 8kHz. This has to be sent in 10.14 format. This "8" has to be updated depending on the numbmer of data in the buffer. If you have too much data, sent "8,05" and you will request a lower frequency. Not enough, and you send "7,95", and the host will go faster... If you want to see the host adaptation, you should not set the max packetlonly in bmattributes...So that you check if you have recevied packets that are smaller than exepected... Very easy in fact... In fact I mean that it really does not require much code since the hard part is done on the Host... Bye
|
stefanopod
Super Member
- Total Posts : 1285
- Reward points : 0
- Joined: 2007/06/25 02:33:59
- Location: Bologna,Italy
- Status: offline
RE: problems in isochronous synchronisation
2007/10/21 09:38:05
(permalink)
you are very kind and I'm quite ignorant (or an usb newbie if you prefer); i'll study your post. Now everything looks a bit simpler. I'm still looking in my data stream the traces of the problems i HAVE to find, lacking synchronisation (my first problem is not having problems). As a magnitude order, how often have I to expect your "plops"? One in a second, in a minute, in an hour? thanks again stefanopod
|
stefanopod
Super Member
- Total Posts : 1285
- Reward points : 0
- Joined: 2007/06/25 02:33:59
- Location: Bologna,Italy
- Status: offline
RE: problems in isochronous synchronisation
2007/10/21 10:14:16
(permalink)
in a loopback test of 50 seconds at 30khz, about 1,5 MB, I found corrupted (not missing) only a bunch of bytes involvig only a little part of a 2 msecs interval: is it so dangerous in an audio equipment? 1)Is it a "plop"?(I don't think so). 2) Or I'll have problems after a longer time delay? ( the driver has a huge FIFO that copes with frequency differences) 3)Or my test HD->PIC->HD is meaningless? 4)Or I'm a lucky guy (no frequency shift)? I'll go on searching. That's really healing one's head before it is broken (badly translated proverb). stefanopod
|
stefanopod
Super Member
- Total Posts : 1285
- Reward points : 0
- Joined: 2007/06/25 02:33:59
- Location: Bologna,Italy
- Status: offline
RE: problems in isochronous synchronisation
2007/10/21 14:19:50
(permalink)
I found the "plops" at last; i had to find a proper waveform,changing slowly and fast at a time, an ampiltude modulated sine wave, to show the problem on the monitor :almost 200 wrong samples every 30000, one "plop" per second. Now is time for me to understand well how to fix the problem. stefanopod
|
stefanopod
Super Member
- Total Posts : 1285
- Reward points : 0
- Joined: 2007/06/25 02:33:59
- Location: Bologna,Italy
- Status: offline
RE: problems in isochronous synchronisation
2007/10/22 01:02:54
(permalink)
Hi sc6po, i'm beginng to study seriously the problem, beginning from your post of august 22. It slowly gets more clear (higly appreciated the surviving french comments) but always not "quite simple". You say "the docs". But what docs were the base of your achievements? The old story of teaching how to fish, instead of making a gift of fish. thanks again stefanopod
|
sc6po
Senior Member
- Total Posts : 133
- Reward points : 0
- Joined: 2006/06/28 01:52:36
- Location: France
- Status: offline
RE: problems in isochronous synchronisation
2007/10/22 02:51:54
(permalink)
|
stefanopod
Super Member
- Total Posts : 1285
- Reward points : 0
- Joined: 2007/06/25 02:33:59
- Location: Bologna,Italy
- Status: offline
RE: problems in isochronous synchronisation
2007/10/22 03:14:49
(permalink)
yes,yes, i want to study, but not so much  . thanks
|
stefanopod
Super Member
- Total Posts : 1285
- Reward points : 0
- Joined: 2007/06/25 02:33:59
- Location: Bologna,Italy
- Status: offline
RE: problems in isochronous synchronisation
2007/10/23 00:30:26
(permalink)
Hi sc6po, I read through a lot of times the august post about your successful audio device, and it begins to make some sense to me. I downloaded also the docs you suggested, some of them very intersting. I browsed them, but I lack (or I couldn't find) the core info: docs about isochronous feedback, class specific descriptor format and so on: I can guess from your code the meaning of the bSyncAdress field , but I can't understand from where you retrieved your knowledge. Sorry to be boring, but the forum is also that[8|] Thanks again
|
stefanopod
Super Member
- Total Posts : 1285
- Reward points : 0
- Joined: 2007/06/25 02:33:59
- Location: Bologna,Italy
- Status: offline
RE: problems in isochronous synchronisation
2007/10/23 09:47:57
(permalink)
|
sc6po
Senior Member
- Total Posts : 133
- Reward points : 0
- Joined: 2006/06/28 01:52:36
- Location: France
- Status: offline
RE: problems in isochronous synchronisation
2007/10/23 10:23:39
(permalink)
Hi, Audio1.0 is one part of the info...If you intend to do an audio device...But I was considering that you did not wanted to do an official audio device... If you want Isochronous Information, USB2.0 is your Bible Chapter 5.12, especially 5.12.4. Audio1.0 is a Device Class Definition. It gives you info about how to create a topologie that describes your hardware, create the descriptor, and support functions... Once you got a correct descriptor/behavior, you are compatible with windows or linux...without doing anything on the Host side.
|
stefanopod
Super Member
- Total Posts : 1285
- Reward points : 0
- Joined: 2007/06/25 02:33:59
- Location: Bologna,Italy
- Status: offline
RE: problems in isochronous synchronisation
2007/10/23 11:43:55
(permalink)
Maybe I'm too slow, but I understand that, if I need feedback I need to fill the field bSyncAdress of the EP descriptor whose identifier, in your code, is USB_EP_AS_DSC. I found info about this decriptor in audio specs, and not, maybe I didn't search enough, in USB2.0 bible. I thought I had necessarily to implement an audio device to avoid "plops". I thought feedback is a feature ONLY of audio. How can I set feedback in a generic ISO endpoint? Is it possible? Grateful if you correct my confusion.
|
sc6po
Senior Member
- Total Posts : 133
- Reward points : 0
- Joined: 2006/06/28 01:52:36
- Location: France
- Status: offline
RE: problems in isochronous synchronisation
2007/10/23 12:18:45
(permalink)
Oops...Hum...You make one point!  I remember now I had questions about this also... I guess that the answer may be " audio1.0 is one implementetation of USB2.0"... USB2.0 give the tools, describes solutions, but Audio1.0 gives an implementation... Maybe others CDC gives others solutions for feedback...I don't know... But you're right, and maybe not so slow...I more surely think that this is quite a mess...
|
stefanopod
Super Member
- Total Posts : 1285
- Reward points : 0
- Joined: 2007/06/25 02:33:59
- Location: Bologna,Italy
- Status: offline
RE: problems in isochronous synchronisation
2007/10/23 14:08:54
(permalink)
You made a lot of points. Your projects looks cute and well explained. Bur for shure I'll have a lot of questions more for you ---- frightening!!
|
stefanopod
Super Member
- Total Posts : 1285
- Reward points : 0
- Joined: 2007/06/25 02:33:59
- Location: Bologna,Italy
- Status: offline
RE: problems in isochronous synchronisation
2007/10/24 23:55:57
(permalink)
Hi sc6p0, I'm beginning to browse USB2.0 and Audio1.0 docs, together with your august 22 example,as a base to understand something about ISO synchronization. So, as I threatened, the first couple of a row of questions for you (only the most important ones, not to be too boring). 1)Did you use class specific interface descriptors in your device? (I quote again your code, maybe you don'remember it at all any more, and you will see you viciously([:@]) posted only endpoint descriptors; 2)Iso_Receive() is called from ProcessIO function, i.e in main loop? 3)Your rb2 interrupt handler handles start/stop conditions? 4)Am I wrong or bLockdelayUnits and wLockDelay are meaningless but harmless parameters (in specs they are set to 0 for asyncronous)? 5)Could you show me any other example about the issue (to avoid many more questions?). Audio1.0 example of microphone (that claims to be "quite simple") is really "quite frightening" and not so close to my problems. Neverending thanks //////////////////////////////////////////////////////////////////////////////////////////// I quote again sc6p0 post: // AUDIO stream Data EndPoint Descriptor // ---------------------------------------- // EP Descriptor (standard) sizeof(USB_EP_AS_DSC), // #9 bLength DSC_EP, // #05 ENDPOINT descriptor type _EP02_OUT, // HOST > Device _ISO | _ASYNC, // #5 isochonous + asynchronous ISO_EP_OUT_SIZE, // #48 wMaxPacketSize (3 voies * 2 octets * 8 par seconde) 1, // Interval polling (1ms) 0, // bRefresh _EP02_IN, // bSyncAdress of the feedBack Endpoint // EP Descriptor (class specific isochronous) sizeof(USB_ISO_AS_DSC), // #7 bLength CS_ENDPOINT, // #37 bDescriptorType; EP_GENERAL, // #1 bDescriptorSubType 0x00, // bmAttributes (D7=1 => MaxpacketsOnly) 1, // bLockDelayUnits (1=ms) 2, // wLockDelay (2 ms to produce & consume) // EP Feedback description : IN sizeof(USB_EP_AS_DSC), // #6 bLength DSC_EP, // #05 ENDPOINT descriptor type _EP02_IN, // NUMCOM -> HOST _ISO | _FE , // Isochronous Feedback ISO_FDBCK_EP_IN_SIZE, // Size 1, // Interval polling (1ms) 7, // bRefresh ( 2e7 = 128ms) 0, // bsyncAdress // ---------------------------------------- // AUDIO stream Data EndPoint Descriptor // ---------------------------------------- // EP Descriptor (standard) sizeof(USB_EP_AS_DSC), // #9 bLength DSC_EP, // #5 ENDPOINT descriptor type _EP03_IN, // IN : NUMCOM > HOST _ISO | _ASYNC, // #5 isochonous + asynchronous ISO_EP_IN_SIZE, // wMaxPacketSize (3 voies * 2 octets * 8 par seconde) 1, // Interval polling (1ms) 0, // bRefresh 0, //_EP02_IN, // bSyncAdress . // EP Descriptor (class specific isochronous) sizeof(USB_ISO_AS_DSC), // #7 bLength CS_ENDPOINT, // #37 bDescriptorType; EP_GENERAL, // #1 bDescriptorSubType 0x00, // bmAttributes (D7=1 => MaxpacketsOnly) 1, // bLockDelayUnits (1=ms) 2, // wLockDelay (2 ms to produce & consume) // when are iso datas services ? - When the endpoints is received for OUT - When the data is read for the Feedback ( will induce latency because the data you write in this function is the data that will be read next time the data is request) - IN Iso is serviced in SOF function. SOF is the only stable info that tells you when to switch from one buffer to the other. void audio_Iso_UsbCtrlEPAudioService(void) { if((USTAT & 0x7C) == (EP02_OUT)) { if(ISO_EP_OUT.Stat.PID != SETUP_TOKEN) audio_Iso_Receive(); } else if((USTAT & 0x7C) == (EP02_IN)) { audio_Iso_Feedback(); } } // SOF function - When Alternate Setting is 0 (usb_alt_inf) do nothing (reinit fields) - IN Iso is serviced in SOF function. SOF is the only stable info that tells you when to switch from one buffer to the other. void audio_Iso_SofHandler(void) { audio_Iso_SofTracker=0; if (usb_alt_intf[ISO_INTF_OUT_ID]==1) { if (iso_out_nbDataOutToSend > 48 ) iso_out_it_authorized = TRUE; } else { audio_Iso_Receive_Init(); } if (usb_alt_intf[ISO_INTF_IN_ID]==1) { audio_Iso_Send(); } else { audio_Iso_Send_Init(); } } // Receive ISO OUT - A circular Buffer is used. Data is shifted in by packet ( size of packet is variable, with max size). Data is shifted out one after the other. Means that when shifting in,you can be anywhere. If you are after the threshold, that is the size of the buffer minus max packet size, the index is reset. Amount of data in the buffer is monitored. void audio_Iso_Receive(void) { unsigned char nbDataReceived; if(ISO_EP_OUT.Stat.UOWN==0) // If UOWN=1, SIE is working on regsiter. Data not available for CPU treatment { INTCONbits.GIE = 0; nbDataReceived = ISO_EP_OUT.Cnt; indexAudioDataOutUsb = (indexAudioDataOutUsb + nbDataReceived); if (indexAudioDataOutUsb >= ISO_EP_OUT_USED_BUFFER_SIZE) { indexAudioDataOutBuffEnd = indexAudioDataOutUsb; indexAudioDataOutUsb = 0; } ISO_EP_OUT.ADR = &audio_data_out[indexAudioDataOutUsb]; ISO_EP_OUT.Cnt = ISO_EP_OUT_SIZE; mUSBBufferReady(ISO_EP_OUT); iso_out_nbDataOutToSend +=nbDataReceived; INTCONbits.GIE = 1; } } // Send ISO In : - One buffer after the other. Buffer are Toggled void audio_Iso_Send(void) { iso_in_it_authorized = TRUE; if (ISO_EP_IN.Stat.UOWN==0) // If UOWN=1, SIE is working on regsiter. Data not available for CPU treatment { INTCONbits.GIE = 0; ISO_EP_IN.ADR = &audio_data_in[indexAudioBuffInIt][0]; ISO_EP_IN.Cnt = indexAudioDataInIt; mUSBBufferReady(ISO_EP_IN); if (indexAudioBuffInIt == 0) indexAudioBuffInIt=1; else indexAudioBuffInIt = 0; ptAudioDataInIt = &audio_data_in[indexAudioBuffInIt][0]; indexAudioDataInIt = 0; INTCONbits.GIE = 1; } } // ISO Feedback IN - The feedback send a value, that is an average of the amount of samples received each 1ms for each channel. Mine is a theorcial 8 since it is 8kHz. The real value is usually larger than 8. So you have to send a ratio. The format is 10.14. - You have to perfom a regulation so that your buffer are always filled. - The best, to me, in terms of results, is the simplest...I take 8 and I add 0x05 is I want more data, substract 0x05 if I want less. Efficient for me. (seems very efficient). Could be very different depeding on your parameters. void audio_Iso_Feedback(void) { DWORD Feedback; Feedback._dword = 0x400; // Valeur nominale du nombre d'échantillons recus ( 8 par ms pendant 2e7=128ms) if (iso_out_nbDataOutToSend < 0x50) Feedback._dword += 0x05; else if (iso_out_nbDataOutToSend > 0x80) Feedback._dword -= 0x05; Feedback._dword = Feedback._dword <<7; ISO_FDBCK_EP_IN.ADR[0] = Feedback.byte0; ISO_FDBCK_EP_IN.ADR[1] = Feedback.byte1; ISO_FDBCK_EP_IN.ADR[2] = Feedback.byte2; ISO_FDBCK_EP_IN.Cnt = 3; ISO_FDBCK_EP_IN.Stat._byte = _USIE; /* Turn ownership to SIE */ //mUSBBufferReady(ISO_FDBCK_EP_IN); } // function Called by Interrupt void audio_Iso_ExtItHandler(void) { if (INTCON3bits.INT2IF == 1 ) { INTCON3bits.INT2IF = 0; audio_Iso_SofTracker ++; if ((iso_out_it_authorized==TRUE) && (iso_out_nbDataOutToSend >0)) { ... iso_out_nbDataOutToSend-=6; indexAudioDataOutIt+=6; if (indexAudioDataOutIt == indexAudioDataOutBuffEnd) indexAudioDataOutIt=0; } if ((iso_in_it_authorized==TRUE) && (indexAudioDataInIt<ISO_EP_IN_BUFFER_SIZE ) ) { indexAudioDataInIt+=6; } } } //////////////////////////////////////////////////////////////////////////// End fo quote of sc6po post
|