You are here

DFB to average ADC convertion results [Kit 059]. | Cypress Semiconductor

DFB to average ADC convertion results [Kit 059].

Summary: 13 Replies, Latest post by Carlos on 05 Dec 2016 03:52 PM PST
Verified Answers: 2
Last post
Log in to post new comments.
user_365962704's picture
User
165 posts

Hi,

There´s not a lot of topics about DFB and i would like to know if i can use the DFB to average ADC results. The ADC will be configured with 10bits of resolution, sample rate will be controlled with the soc terminal (~10sps). I would like to use the DFB to sum 10 results of the ADC and then calculate the average, generate a interrupt after the average calculation.

My biggest doubt is the format on the input Stage of the DFB, can i pass it directly the results of the ADC?

All this project is for learning purposes, the calculation can be easily done with the CPU and interrupts. The DFB block is scary lol.

 

Thanks in advance

Carlos

user_342122993's picture
User
580 posts

Carlos,
I believe that 10-bit DMA configuration for ADC_SAR-DFB transfer should be the same as for 12-bit.

Geona Mary's picture
Cypress Employee
4 posts

Hello Carlos,

This can be achieved either by loading the ADC converted values to Data RAMs (DFB_LoadDataRAMA() / DFB_LoadDataRAMB() ) or through staging registers (DFB_LoadInputValue() ). Since the no of samples is not a power of two, you can either go for CPU or IIR filter with appropriate weights for division. (DFB has got an inbuilt shifter, which could have used for division otherwise). Additionally, set coherency to mid byte to take care 10 bit resolution using API DFB_SetCoherency().

user_365962704's picture
User
165 posts

Hi @Geona, yes i notice that 10 is not a power of two after making the post, it can be 8 or 16 with no problem, i will try to make a project and post more questions when i get stuck.

@oddisey, i will try the 12bit resolution :)

Thanks for the help

Carlos

Magnus Lundin's picture
User
33 posts

The following project could be a help to play with.

I am not finished testing it completely or writing up all notes and comments, but it seems to run quite ok.

I test it by connecting a voltage divider, run it in the debugger and check the resulting values with debugger.

Have fun

Magnus

 

user_365962704's picture
User
165 posts

Great @Magnus, i never thought about multiplying the input by 0.1 (to get rid of the division), it's a very clever "trick". I guess the main thing with DFB is think with a Multiply and Accumulate mindset.

I printed the DFB code in a paper to start getting familiar, understanding the VLIW set is hard at the beginning, at least it's being hard to me.

Thanks for the example, it's very helpful

Carlos

 

user_365962704's picture
User
165 posts

Hi Magnus,

Just tested you project, i changed a couple of things to get it "working":

* On the last instructions when you write the result to the bus of the DFB, you use the command write(bus), reading the datasheet seems that is better to use write(abus) (check the table about the write instruction in page 39).

* And cleared the interrupt status after enter in the for loop.

Attached is your example project with this fixes.

 

Thanks a lot for the projects you upload here in the forum and your blog.

Carlos

Magnus Lundin's picture
User
33 posts

Hi Carlos,

Good that you are getting things to work. Your comments are correct, but I don't think the changes are really necessary, it works for me without changes and:

* addr(1) write(bus)   is equivalent to write(abus), see the last entry in the table on p.39

* The interrupt status flag is cleared by hardware when reading the holding register

The interrupt flag is only used as a status flag in this example and not connected to the interrupt system, it would be nice to attach an interrupt object and then handle the output in the interrupt handler,  just to se how this works.

I getting to like the DFB, seems it can do some nice things, and its nice that you are using it not just saying that DFB is hard and dont bother.

Best regards,

Magnus

 

 

 

user_365962704's picture
User
165 posts

Hi Magnus,

Thanks for letting me know the interrupt status flag is cleared by hardware reading the HOLDA reg, it can save some time.

About the addr(1) write(bus) vs write(abus) i think is matter of personal preference hehe, i think using the former is maintained just for backwards compatibility by cypress, but at the end both commands do the same, anyways i'm not an expert here lol.

I'm modifying the project to run at 10sps, then adding a second TD on the DMA to save the ADC results on a memory array, btw i'm using a interrupt component on the interrupt output of the DFB to set a flag on the interrupt handler and clearing the interrupt status flag, will upload the project when it's finished.

 

Thanks again for the help.

Carlos

 

user_365962704's picture
User
165 posts

Here is the almost finished project, the ADC runs at 10sps, the value given by the DFB is printed to the console via UART@115200, it seems pretty accurate, offset of some 10mV.

@Magnus, the data on the hold registers are in q23 or hex format? i'm still trying to figure out that data format, iirc data in acu area can be in hex format, but q23 in data_a and data_b areas.

 

Carlos

Magnus Lundin's picture
User
33 posts

All data is in 24 bit signed binary, 48 bit inside the MAC but we never see that. When entering data for the RAM blocks the simulator only accept unsigned numbers in decimal or hex format, I have not been able to get it to accept any q23 number format, so that scaling must be done by the programmer. The generated code has data in unsigned hex format and can be seen in the DFB_xxx_RAM.c file.

The way the multiplication in the MAC works, signed multiplication that returns the top valid 23 bits is mathematically the same as dividing the product by 2^-23, that is A*B>>23. The natural way to interpret these numbers, without having to worry about the 23 bit scaling is to interpret all numbers as q0.23 decimal numbers.

So the operation of the MAC can be interpreted as

y = y + (a*b>>23)    as signed integers, with 24 bits of decimal fraction in the lover bits of the MAC so its not really integer arithmetic

or

y = y + a*b as q23 numbers

The high alignment shifts the input up to make a q16 number, or a signed 16 bit integer, to the same q23 value, with lover 8 bits set to 0. The high output alignment shifts the q23 to a q16 value corresponding to a valid signed 16 bit integer.

The results are always sign extended to 32 bits if read as 32 bit integers from the holding registers.

So the short answer is that the results are 24 bit signed integers or q23 depending on how you decide to interpret them.

 

 

Log in to post new comments.