FFT in BF506
Hello all,
I need help to compute (or define) the ADC sampling frequency.
I am using CCES and BF506 EZ-kit to sample I and Q data and apply FFT.
I am now testing the code I wrote by injecting a sin wave of 1 MHz.
the ADC is sampling the signal and the FFT (rfftf_fr16()) on 512 points is giving a reasonable spectrum.
Nevertheless, the spectrum doesn't seem to give a correct info about the signal frequency.
I think I am misunderstanding the values of the sampling frequency of the ADC.
In the CCES example project (AD7266_and_ACM), the initial variables are defined as follow:
#define ACM_DEV_NUM 0
#define SPORT_DEV_NUM 1
#define ACLK 5000000u
#define MHZTOHZ (1000000)
#define CLKIN (25 * MHZTOHZ)
#define CORE_MAX (400 * MHZTOHZ)
#define SYSTEM_MAX (100 * MHZTOHZ)
#define VCO_MIN (72 * MHZTOHZ)
#define NUM_ACM_EVENTS 6
#define TIME_PER_EVENT 350
#define START_TIME 100
#define GP_TIMER 2
#define PERIOD (START_TIME + NUM_ACM_EVENTS*TIME_PER_EVENT)
#define WIDTH 10
is the ADC sampling rage of 5 MHz?
Is it defined as SCLK/Period? (with SCLK = 100 MHz in this case)?
thanks a lot for your help!
Francesco
cces
bf506
adc rf
fft
sampling rate
Hi Francesco
First of all, I would suggest you to read the ACM chapter give in Hardware Reference Manual of BF506,
The ADC sampling frequency depends on ACM Timer Trigger frequency and number of events per ACM Timer frame.
From the settings you have given, seems like ACM Trigger freq is SCLK/PERIOD = 100M/(100 + 350*6) = 100M/2200 = 45.45KHz
Therefore, sampling freq of ADC = Trigger freq * No of events = 45.454K * 6 = 272KSPS
BTW, if you are using CCES, then after running the code & receiving the ADC samples, open the plot window and plot the ADC sample buffer. Then in the properties setting, check the FFT processing and specify the sampling freq. You can see the freq spectrum in the Plot window now.
Hello Prashant,
thanks for your help.
How can I make the sampling frequency of 1 or 2 MHz?
Should I just modify the length of the period?
Thanks
Hi Francesco,
I am attaching a simple code which explains how ACM can be configured to achieve ADC sampling rate of 1.5MSPS. (I have set SCLK as 100MHz, therefore I could achieve 1.5MSPS through ACLK=25MHz setting. If you want 2MSPS, then you can configure SCLK=64MHz and program the ACM registers such that you will get ADC_CLK=32MHz. Change the trigger freq appropriately).
Let me know if you need more details.
--Prashant
Hello Prashant,
thank you so much for your help! your code was very helpful to understand more about the BF506!
I need to go through it more in details, but here are some additional questions I have (sorry for bothering you so much but I am really learning a lot with you)
- why you have two data buffers (Rx_Data_BUFFx[])?
- if I want to collect sampled data from more than one input channel, where can I save the output data? it seems that the Rx data buffers receive only from channel 0 even if I change the variable ADC_CHANNEL_IP from 0 to 1.
thanks
Francesco
Hi Francesco,
DMA is configured in Descriptor mode for Ping-Pong (while one is getting filled by ACM/SPORT, other can be used for processing); therefore have two buffers. As per your requirement, you can have single buffer and configure DMA in Stop mode or Auto-buffer mode.
Regarding second query, in the current code SPORT DMA will continuously receive the data for enabled ACM events in the same order in which ACM events are handled. I used DMA mode because of higher sampling rate (to avoid core overhead).
But if you have events sampling multiple ADC channels, then you need to use core mode of ACM (instead of DMA based). In the SPORT ISR, you need to check ACM Event completion status register and place the received data in required buffer. That you need to handle in software as per your requirement.
Let me know if you need more details.
--Prashant
Hello Prashant
thanks again for your replay.
In the code you posted, both the primary and secondary channel of SPORT are enabled, is that correct?
If yes, I just need to enable one ADC channel (A1 and B1, keep ADC_CHANNEL_IP to 0) and I don't need the core mode?
If all this assumptions are correct, how do I distinguish the buffer for A1 from the buffer for B1?
Thanks!
Hi Francesco,
Your understanding is correct. If you just need two channels, then use one channel from ADC0 and other from ADC1. In that case, same code would work, but you need to enable secondary channel of SPORT as follow:
*pSPORT1_RCR2 = SLEN(13) | RXSE;
The received data will be interleaved in the RX_BUFF: primary (A1) - Secondary (B1) - primary (A1) - Secondary (B1)- ...... and so on. If required, you can put A1 data in continuously in one sub-buffer and B1 data in another sub-buffer. You need to configure DMA in 2-D mode with XCNT = 2, XMOD = (BUFF_SIZE/2) * 2, YCNT = BUFF_SIZE/2 and YMOD = - ((BUFF_SIZE/2) * 2) + 2
With this primary data would start from start of buffer and secondary data would start from mid of the buffer.
Let me know if you need more details.
--Prashant
Hello Prashant,
I modified your original code with the info you gave to enable the 2D mode.
I modified the function Init_Sport() with the following:
*pDMA4_CONFIG = FLOW_SMALL | NDSIZE_4 | SYNC | DMA2D | WDSIZE_16 | WNR;
*pDMA4_X_COUNT = 0x0002;
*pDMA4_Y_COUNT = BUFF_SIZE/2;
*pDMA4_X_MODIFY = (BUFF_SIZE/2)*2;
*pDMA4_Y_MODIFY = -((BUFF_SIZE)/2)*2+2;
and enabled the sport secondary channel, but I can't read any data anymore from the Rx_Data_BUFFx.
I guess I am doing something wrong.
I can't wrap my head around the method used for the interleaving.
Please log in to reply.