Hello,
I'm attempting to utilize the ESP32 with the CC1120 in CFM (custom frequency modulation) mode. This mode requires me to write the deviation required for the modulation scheme require to a register. The issue is obviously SPI comm based. I simply cannot get the speed out of the SPI peripherals required without first creating a large array to the transmission.
I was curious if its possible to connect the Cosine generator output to the DMA and then the DMA to the SPI. I would like to do a continuous SPI write and vary the Cosine generator values.
ESP32 Cosine Generator to SPI via DMA
-
- Posts: 9759
- Joined: Thu Nov 26, 2015 4:08 am
Re: ESP32 Cosine Generator to SPI via DMA
That's not possible, but it's not that hard to generate cosines manually (e.g. using a lookup table and a fractional divider). Probably costs a bit of CPU time, but not too much.
-
- Posts: 12
- Joined: Tue Jan 15, 2019 5:12 am
Re: ESP32 Cosine Generator to SPI via DMA
Thanks for the quick response!
I agree it's not that hard. The real issue is with SPI communications / possibly inexperience. I have to send a large amount of data using tones (BELL202). The tones are emulated via an external DAC over SPI.
I end up pushing SPI pretty hard with the current driver (9uS) between SPI transactions to just run through a sine table to reach my fastest tone of 2200Hz. My DAC is 7bits but I'm willing to go to 5bits. The real issue I have comes with how I can switch between my two different tones, maintain a fixed update rate, and preform the necessary logic to select the next tone required to be sent?
I have ideas on how I would implement this if I was running closer to the metal, but in the RTOS environment I'm not sure with all the extra overhead.
Is setting up a timer interrupt to trigger an SPI transaction a valid method? Do you think I should start looking at the Remote Control Unit?
Thank you for your time!
I agree it's not that hard. The real issue is with SPI communications / possibly inexperience. I have to send a large amount of data using tones (BELL202). The tones are emulated via an external DAC over SPI.
I end up pushing SPI pretty hard with the current driver (9uS) between SPI transactions to just run through a sine table to reach my fastest tone of 2200Hz. My DAC is 7bits but I'm willing to go to 5bits. The real issue I have comes with how I can switch between my two different tones, maintain a fixed update rate, and preform the necessary logic to select the next tone required to be sent?
I have ideas on how I would implement this if I was running closer to the metal, but in the RTOS environment I'm not sure with all the extra overhead.
Is setting up a timer interrupt to trigger an SPI transaction a valid method? Do you think I should start looking at the Remote Control Unit?
Thank you for your time!
-
- Posts: 9759
- Joined: Thu Nov 26, 2015 4:08 am
Re: ESP32 Cosine Generator to SPI via DMA
What does the SPI communication you have to do look like? Can you send a number of samples at one time to the chip, and will it 'play them back' at an independent, fixed speed, or do you have to send it a new SPI sample precisely in time with the sample rate?
-
- Posts: 12
- Joined: Tue Jan 15, 2019 5:12 am
Re: ESP32 Cosine Generator to SPI via DMA
Hello Sprite,What does the SPI communication you have to do look like? Can you send a number of samples at one time to the chip, and will it 'play them back' at an independent, fixed speed, or do you have to send it a new SPI sample precisely in time with the sample rate?
Thanks for the response again. The SPI communication will require a fixed rate. The DAC output is updated when the data is finished being written to the DAC's register. (CC1120 CFM Mode - I'm setting up the FM deviation manually to send an analog FM signal with a digital RF transceiver). Therefore, I have to send the data at a fixed rate. The DAC can provide a GPIO line to toggle when the new sample is required from the ESP32 to help assist with timing.
The DAC will permit me to burst write to the register so I don't have to keep initializing new SPI transactions for each DAC update. I thought about setting the SPI data rate so that it will equal my required sample rate, but the amount of data I'll need to pre-assemble for a single transaction seems a bit daunting to me. Let me run some numbers by you and you can tell me if you think I'll have RAM issues in the future or if there is a method to stream data to the SPI buffer while it's writing...
First let me provide a bit of background, I'm assembling an APRS packet which utilizes BELL202 modulation. BELL202 is a janky AFSK method of sending binary data over a voice channel which consists of sending two different tones 1200Hz and 2200Hz with a data rate of 1200bps. Therefore, we'll be switching between the tones at 1200Hz.
If we decided to pre-assemble an array with every value SPI value we need to send to the DAC, it seems to get pretty hairy pretty quick.
For example, if we do a not-so-conservative estimate and say I need to send a packet consisting of 200 bytes (big packet).
Our Fs is fixed by our fastest tone and the resolution of our DAC. I calculate Fs based on 2 possible resolutions 5 bits and 7 bits.
Fs = (2200Hz * 2^7) = 281.6kHz
Fs = (2200Hz * 2^5) = 70.5kHz
We'll use 5 bits for this example...so I need to send 70kBytes per second. A pretty easily achievable SPI rate The problem is this: If the packet is 200 bytes and the data rate is 1200bps, we'll be sending data for 200*8/1200 = 1.33s. 1.33s*70.5kHz = 94,000 bytes I'll need to pre-allocate
Please let me know if I can provide any additional information or if if I royally bodged any math!
-
- Posts: 9759
- Joined: Thu Nov 26, 2015 4:08 am
Re: ESP32 Cosine Generator to SPI via DMA
Gotcha. Hmm. This means that you almost need a 'streaming' mode for a SPI transaction, like the I2S peripheral has. At the moment, the driver has nothing of that kind, but the hardware supports it; worst case you could hack the driver to get something like this.
About your calculations... first of all, I'm not entirely sure what your 5/7-bit resolution is about; as far as I can see, the CC1120 accepts 8-bit SPI transfers? You keep talking about an external DAC; are you planning to use some analog way of controlling the modulation of the CC1120 with an external DAC chip? If so, why not use the internal DAC of the ESP32?
Assuming 8-bit transfers to the cc1120s CFM_TX_DATA_OUT register in burst mode from now on, so no external DAC and 1 byte per sample: The max frequency you need to reproduce is 2200 Hz. According to the Nyquist-Shannon sampling theorem, you'd need 4400Hz sampling frequency to adequately reproduce this. Let's go a bit higher so we have some headroom and make it 8KHz.
200 bytes is 1600 bits, at 1200BPS is indeed 1.3 seconds. Times 8KHz is about 10KByte. Not sure how you arrive at 9 times that much, to be honest...
Edit: Wait, you're talking about oversampling the waveform by a factor of 2^5 or 2^7? Why'd you do that, that's pretty insane! I'm not sure how demodulation in the average receiver works, but if it only needs a 1200/2200Hz signal, it would be insanity if it didn't do lowpass filtering at 3000Hz or so, which means that you can easily get away with only oversampling it twice or so.
About your calculations... first of all, I'm not entirely sure what your 5/7-bit resolution is about; as far as I can see, the CC1120 accepts 8-bit SPI transfers? You keep talking about an external DAC; are you planning to use some analog way of controlling the modulation of the CC1120 with an external DAC chip? If so, why not use the internal DAC of the ESP32?
Assuming 8-bit transfers to the cc1120s CFM_TX_DATA_OUT register in burst mode from now on, so no external DAC and 1 byte per sample: The max frequency you need to reproduce is 2200 Hz. According to the Nyquist-Shannon sampling theorem, you'd need 4400Hz sampling frequency to adequately reproduce this. Let's go a bit higher so we have some headroom and make it 8KHz.
200 bytes is 1600 bits, at 1200BPS is indeed 1.3 seconds. Times 8KHz is about 10KByte. Not sure how you arrive at 9 times that much, to be honest...
Edit: Wait, you're talking about oversampling the waveform by a factor of 2^5 or 2^7? Why'd you do that, that's pretty insane! I'm not sure how demodulation in the average receiver works, but if it only needs a 1200/2200Hz signal, it would be insanity if it didn't do lowpass filtering at 3000Hz or so, which means that you can easily get away with only oversampling it twice or so.
-
- Posts: 12
- Joined: Tue Jan 15, 2019 5:12 am
Re: ESP32 Cosine Generator to SPI via DMA
Okay cool! I'm guessing the I2S driver might be a good place to start on this?Thanks for the insight.Gotcha. Hmm. This means that you almost need a 'streaming' mode for a SPI transaction, like the I2S peripheral has. At the moment, the driver has nothing of that kind, but the hardware supports it; worst case you could hack the driver to get something like this.
I was using DAC kinda as analogy. Setting the CFM_TX_DATA_OUT register sets the deviation from the carrier. The resolution provided is only 7-bits even that the SPI transfer is 8-bits. The resolution used generate the tones will affect the SNR of the symbol in the baseband, and I need to do further research to determine how reducing the SNR in the base-band will affect the ability of other receivers to decode the signal. At the time, I'd figure I would max out the resolution to best simulate how the current systems function. The APRS network isn't standardized on equipment. It is hodgepodge of legacy and new hardware so I leveraged my bet on making the baseband signal as best as possible.About your calculations... first of all, I'm not entirely sure what your 5/7-bit resolution is about; as far as I can see, the CC1120 accepts 8-bit SPI transfers? You keep talking about an external DAC; are you planning to use some analog way of controlling the modulation of the CC1120 with an external DAC chip? If so, why not use the internal DAC of the ESP32?
The output will not be low-pass filtered on transmission (basically it will be M-FSK; where M is the resolution of the DAC used), but on the receiving side the RX filter and audio filters I assume would low-pass filter the signal.
If I go with the limited number of samples to create the tones (2), I could then simply use the CC1120 normal digital modes to generate the tones theoretically without the use of CFM_MODE. I would still need CFM_MODE I believe to receive analog FM, but that's a problem for another day, lol.
Yes. You're right. I need to put some more though into this. Sorry, I'm still learning too, and I didn't assume it'd be this hard to dump this amount of data over SPI. The typical RX filter bandwidth is 5kHz for narrow voice FM so I might get something at 4400Hz. Different equipment based on my research uses different methods to determine the audio tone post FM demodulation: Gorenztel (signal bin FFT basically), Correlation banks, and Zero-crossing.Edit: Wait, you're talking about oversampling the waveform by a factor of 2^5 or 2^7? Why'd you do that, that's pretty insane! I'm not sure how demodulation in the average receiver works, but if it only needs a 1200/2200Hz signal, it would be insanity if it didn't do lowpass filtering at 3000Hz or so, which means that you can easily get away with only oversampling it twice or so.
Thanks for your help Sprite!
P.S. Let me know if Espressif is hiring if I manage to make this SPI driver support streaming. (j.k.)
-
- Posts: 12
- Joined: Tue Jan 15, 2019 5:12 am
Re: ESP32 Cosine Generator to SPI via DMA
I did a few experiments and Nyquist seems to be fine based on the outputs of the FFTs post the output of the receiver. Thanks!
Who is online
Users browsing this forum: No registered users and 129 guests