Announcement

Collapse
No announcement yet.

Direct I/Q demodulation

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • #46
    Sled, you can use the Injection feature to insert a marker. So when you get to the start of your sinewave, you inject a single sample of say channel 5. You tie the channel 5 input put to a voltage such that it will saturate the ADC to get 0xFFFF. As soon as the injected sequence finishes, the programmed conversion will continue. NOW, you have a marker in your recieved data (a saturated value of 0xFFFF to indicate the zero point of the generated waveform......

    Comment


    • #47
      Originally posted by scrungy_doolittle View Post
      Sled, you can use the Injection feature to insert a marker. So when you get to the start of your sinewave, you inject a single sample of say channel 5. You tie the channel 5 input put to a voltage such that it will saturate the ADC to get 0xFFFF. As soon as the injected sequence finishes, the programmed conversion will continue. NOW, you have a marker in your recieved data (a saturated value of 0xFFFF to indicate the zero point of the generated waveform......

      Ideally you should not have to mark anything as you know the timing of the TX signal ... if you have to "mark" a conversion sequence a simple ring buffer is made to wait till the required sample arrives and then stored at location "zero" ... the start of the conversion sequence will always start at the "zero" location without injecting any markers ( which is a code overhead ). Alternatively use a correlation / cross correlation function to synchronise the sample buffers.

      Comment


      • #48
        Originally posted by moodz View Post
        Ideally you should not have to mark anything as you know the timing of the TX signal ... if you have to "mark" a conversion sequence a simple ring buffer is made to wait till the required sample arrives and then stored at location "zero" ... the start of the conversion sequence will always start at the "zero" location without injecting any markers ( which is a code overhead ). Alternatively use a correlation / cross correlation function to synchronise the sample buffers.
        At the moment everything is running synchronously, no need for markers. However theoretically I could have the TX spinning freely and start to sample the RX anywhere in the TX cycle since I'm only interest in the relative change of the phase? This assumes every RX sample is 90degrees apart with respect to the TX frequency.

        Comment


        • #49
          Originally posted by sled View Post
          At the moment everything is running synchronously, no need for markers. However theoretically I could have the TX spinning freely and start to sample the RX anywhere in the TX cycle since I'm only interest in the relative change of the phase? This assumes every RX sample is 90degrees apart with respect to the TX frequency.
          Correct ... in a synchronous system there is no need for markers ...However if your TX was spinning freely it would have to be fairly stable for a relative phase shift detection system ....

          However because of no fixed reference phase ... would you still be able to discriminate correctly ??

          hmm.

          Comment


          • #50
            Originally posted by moodz View Post
            Ideally you should not have to mark anything as you know the timing of the TX signal ... if you have to "mark" a conversion sequence a simple ring buffer is made to wait till the required sample arrives and then stored at location "zero" ... the start of the conversion sequence will always start at the "zero" location without injecting any markers ( which is a code overhead ). Alternatively use a correlation / cross correlation function to synchronise the sample buffers.
            This assumes that you trigger the adc in sync with the TX signal. However, if you just let the adc run, using DMA to move the data to the buffer, without marking some kind of synchronization signal you don't have a correlation. So the adc is rolling along sampling continuously, and putting the data into memory. That is running with no interrupts, or at most one at the end of the buffer. of you want to trigger another DMA channel to move the acquired data.

            You are assuming that you would start the transmission of one cycle, arm the ADC and capture data for one full cycle, then process it and repeat. That was the idea with the golden goose, that I got
            involved in, but did not have time to do anything with.
            While that will work, it does not model an analog transmit and receive very well.

            My concept is that the transmit and receive happen contentiously, and you are looking at a window in a rolling buffer of data, that is always aligned on some start address. So you need a way
            to mark the timing between the transmit and receive, so you can determine the phase shift simply.

            The transmit is running on interrupts, as it is stepping through the buffer at some fixed rate. The buffers get out of sync. I know I do reatime programming for a living....
            These are asynchronous operations, so you really have to have some marker to correlate things.

            Comment


            • #51
              Originally posted by scrungy_doolittle View Post
              This assumes that you trigger the adc in sync with the TX signal. However, if you just let the adc run, using DMA to move the data to the buffer, without marking some kind of synchronization signal you don't have a correlation. So the adc is rolling along sampling continuously, and putting the data into memory. That is running with no interrupts, or at most one at the end of the buffer. of you want to trigger another DMA channel to move the acquired data.

              You are assuming that you would start the transmission of one cycle, arm the ADC and capture data for one full cycle, then process it and repeat. That was the idea with the golden goose, that I got
              involved in, but did not have time to do anything with.
              While that will work, it does not model an analog transmit and receive very well.

              My concept is that the transmit and receive happen contentiously, and you are looking at a window in a rolling buffer of data, that is always aligned on some start address. So you need a way
              to mark the timing between the transmit and receive, so you can determine the phase shift simply.

              The transmit is running on interrupts, as it is stepping through the buffer at some fixed rate. The buffers get out of sync. I know I do reatime programming for a living....
              These are asynchronous operations, so you really have to have some marker to correlate things.
              I see where you are coming from ... I recently had a similiar problem where the ADC could not be synced to the "TX" because there was no ADC sync input to sync the ADC with the CPU .. the solution was to take the "sample ready" clock from the ADC as the reference sync signal for the TX .... thus the TX was synced to the RX clock ( ie ADC sampler ). The ADC was driven by a crystal based clocked so the TX effectively slave referenced.

              Comment


              • #52
                That's the benefit of audio codec, the ADC is perfectly in sync with the DAC, however the sampling rate is fixed, so mixing with the local oscillator and low pass filtering is needed.

                Comment


                • #53
                  >>"Couldn't this be done using the op-amp as comparator to detect the zero crossing, triggering an interrupt and then look up at what angle the transmitter is at?"
                  Simple TX oscillator + Schmitt trigger + STM32 comparator generating IRQ to start ADC -> DMA buffer batch cycle maybe could be used; It could be simpler, less noise than DAC based TX

                  Comment


                  • #54
                    Stm32f103 is good but if you want to get more power go to f4 I just get 1 from arrow with free shipping with cirrus logic 24 bit ADC and cortex m4 if you want easy and fast programming get 1 with mbed support minimaple is supported with mbed you can after using mbed export your work to Kiel and you can use debugging tool like stlink .or You switch to Texas Instrument had a good software like arduino his name is energia and had a good customer support and good examples

                    Comment


                    • #55
                      Originally posted by chafik View Post
                      Stm32f103 is good but if you want to get more power go to f4 I just get 1 from arrow with free shipping with cirrus logic 24 bit ADC and cortex m4 if you want easy and fast programming get 1 with mbed support minimaple is supported with mbed you can after using mbed export your work to Kiel and you can use debugging tool like stlink .or You switch to Texas Instrument had a good software like arduino his name is energia and had a good customer support and good examples
                      I'd go with the new L4 series, less power, more peripherals, 80MHz, FPU, DSP instructions.
                      Cirrus Logic have really nice codecs but they're quite power hungry. AKM offers good codecs with low power capabilities: http://www.akm.com/akm/en/product/detail/0020/

                      Comment


                      • #56
                        Originally posted by moodz View Post
                        I see where you are coming from ... I recently had a similiar problem where the ADC could not be synced to the "TX" because there was no ADC sync input to sync the ADC with the CPU .. the solution was to take the "sample ready" clock from the ADC as the reference sync signal for the TX .... thus the TX was synced to the RX clock ( ie ADC sampler ). The ADC was driven by a crystal based clocked so the TX effectively slave referenced.
                        hmm. Nice trick. However, we need to reverse. In this case the using the "sample ready" flag, means that you are forcing TX to be in Synch with the ADC. What you need, is for the ADC to know WHEN the tx crosses zero. One way to do this, is whenever your DDS comes to the end of the cycle, some how tag the ADC signal so yo can find that point. The problem there, is with the ADC being read and the values written under DMA control, you can't just insert a marker in the digitized data directly. Which is why, you could set a second channel up to be saturated, and inject a ADC sample cycle.
                        In that case, when you triggered the injection from within the DDS transmit routine, the ADC stops it's normal conversion, and converts the injected channel, then resumes converting it's normal
                        channel. The result is you can inject a saturated marker in the ADC stream even though it is being put into memory by the DMA engine. We don't want the ADC Synched to the TX because then you would not be able to measure the phase shift in the signal relative to the TX, so you would not be able to sample relative to the TX, which is how the X and Y demodulators work in an analog system.

                        Comment


                        • #57
                          To sync ADC with DAC:
                          0) set acqDone = false;
                          1) setup DAC in circular DMA mode; it will generate IRQ every time on hitting the end of the buffer; start DAC DMA
                          2) in the IRQ handler for the DAC DMA done: if acqDone == false then -> start the ADC DMA buffer acquisition; Make sure to enable end of the end of the ADC conversion IRQ in setup
                          3) in the IRQ handler for end of ADC sampling set flag acqDone = true;
                          4) in the main:
                          while(1)
                          {
                          if(acqDone)
                          {
                          //process buffer


                          acqDone = false;
                          }
                          }

                          this will sync ADC to DAC

                          Comment


                          • #58
                            Originally posted by Daren View Post
                            To sync ADC with DAC:
                            0) set acqDone = false;
                            1) setup DAC in circular DMA mode; it will generate IRQ every time on hitting the end of the buffer; start DAC DMA
                            2) in the IRQ handler for the DAC DMA done: if acqDone == false then -> start the ADC DMA buffer acquisition; Make sure to enable end of the end of the ADC conversion IRQ in setup
                            3) in the IRQ handler for end of ADC sampling set flag acqDone = true;
                            4) in the main:
                            while(1)
                            {
                            if(acqDone)
                            {
                            //process buffer


                            acqDone = false;
                            }
                            }

                            this will sync ADC to DAC
                            with circular double buffering it should be even simpler, I get an interrupt for:

                            - half full ADC, sets adcReady=true
                            - half empty DAC
                            - full ADC, sets adcReady=true
                            - empty DAC

                            The main loop just waits for adcReady==true and then does the processing, the processing must be done before the next interrupt happens. The DMA never stops.

                            Comment


                            • #59
                              Originally posted by sled View Post
                              the processing must be done before the next interrupt happens.
                              The scheme I posted does not make this assumption. You can take as long as you need to process, and you signal that you are ready to accept more samples using flag when you done. When display needs to be updated processing can take a while...
                              Using double buffer is a good idea. Concurrent sample acquisition using ADC->DMA and processing previous samples with CPU will almost double data throughput. The CPU processed buffer can't be updated by ADC->DMA; logic for it can be handled in the IRQ handler (looking a the acqDone flag.. and pointing DMA for the next cycle to correct DMA buffer) This sometimes called ping-pong buffering. The flag signaling is not needed if you can guarantee that you can always finish processing before buffer switch, but unless you have another CPU to do user interaction that can't be the case.

                              Comment


                              • #60
                                Originally posted by Daren View Post
                                The scheme I posted does not make this assumption. You can take as long as you need to process, and you signal that you are ready to accept more samples using flag when you done. When display needs to be updated processing can take a while...
                                Using double buffer is a good idea. Concurrent sample acquisition using ADC->DMA and processing previous samples with CPU will almost double data throughput. The CPU processed buffer can't be updated by ADC->DMA; logic for it can be handled in the IRQ handler (looking a the acqDone flag.. and pointing DMA for the next cycle to correct DMA buffer) This sometimes called ping-pong buffering. The flag signaling is not needed if you can guarantee that you can always finish processing before buffer switch, but unless you have another CPU to do user interaction that can't be the case.
                                My approach was to set the ADC into double buffer mode, set the DAC to use DMA to generate the frequency continously. Use double buffering in the ADC with DMA, when buffer one fills, change the pointer to the second buffer, AND then use DMA to move the second buffer into a working buffer, then use another DMA to shift the working buffer down in memory into a "window" that I do the processing in.

                                dac-----buffer 1
                                change to buffer 2, dma into rolling buffer r1 r2 wb where R1 is a buffer the same size the ADC buffer, as are R2 and wb. They are consecutive in memory.
                                set DMA channel to transfer buffer in the R1.
                                when that is finished, set DMA to shift r1,r2, wb in memory such that R2 overwrites wb, r1 overwrites r2, freeing r1 up for the next buffer, at the end of that DMA, trigger a call to a buffering routine that moves
                                wb into your WORK_BUFFER (NOTE: you do NOT want that under control of dma. The danger of working in buffer wb, is that DMA can come along and clobber your data. You want the data in your working buffer to
                                change only when you need it to, but when it does, it will always be at least one sample block behind the current buffering.

                                If you need more time, simply increase the buffer size to the max you can use., r1,r2,r3,r4 etc. OR You don't want to get it to deep of a delay, otherwise your user indications will be wrong (i.e. you will be off the target before you notify the user.) Set the ADC to sample two channels and interleave them. Also set the hardware oversampling. for a 12 bit ADC, you need to oversample 256 times the frequency to get 16 bits
                                using the 16 bit delta sigma in the PIC24GJ128GC010) you can oversample by 0 SDOSR<2:0>: S/D Oversampling Ratio (OSR) Selection bits111 = Reserved110 = 16 (fastest result, lowest quality)101 = 32100 = 64011 = 128010 = 256001 = 512000 = 1024 (slowest result, best quality) at 1024, you get only 244 samples per second. 16-Bit Sigma-Delta A/DConverter” (DS30687) at 16x oversampling, your sample rate us 62 khz, which is more than sufficient for up to 20 khz.

                                The STM32 family, I believe also has automatic oversampling.
                                But in either case, you use pingpong buffering and DMA to move memory around.

                                There are at least 3 philosophies to approaching this:

                                1. transmit, sample, process and repeat. While you are processing, the transmit, and sample process are not working, so you will cover ground with your swing, and you will miss areas of the ground based on your swing and processing time. Assume that you can process things in 100 msec, and your swing rate is 1 second across 5 feet you are getting 10 samples in that time, so you are only getting the signal once every 6 inches.
                                The better option in this cse, is to continuously transmit and sample, and process as you can. so if you have 100 msec processing time, you will at least have captured the ground between your processing blocks.

                                2. Continuously transmit, sample and process. This emulates the operation of a true analog detector, where the processing is in real time. Here everything runs in the background on interrupts and DMA, and all you are
                                doing is processing. in a loop. Your processing time can only be 2 dma buffers worth of time, before the data in the window changes. There is nothing to prevent you from taking 100 msec to process, but you need to move the wb buffer to a different working area so DMA doesn't change it on you.

                                3. continuously transmit, burst sample, process and repeat the burst sampling and processing.

                                Comment

                                Working...