DFB to average ADC convertion results [Kit 059].

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
cadi_1014291
Level 6
Level 6
25 likes received 10 likes received 10 likes given

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

0 Likes
1 Solution
GeonaP_26
Moderator
Moderator
Moderator
250 solutions authored 100 solutions authored 50 solutions authored

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().

View solution in original post

0 Likes
13 Replies
odissey1
Level 9
Level 9
First comment on KBA 1000 replies posted 750 replies posted
        Carlos, I believe that 10-bit DMA configuration for ADC_SAR-DFB transfer should be the same as for 12-bit.   
0 Likes
GeonaP_26
Moderator
Moderator
Moderator
250 solutions authored 100 solutions authored 50 solutions authored

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().

0 Likes
cadi_1014291
Level 6
Level 6
25 likes received 10 likes received 10 likes given

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

0 Likes
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

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

cadi_1014291
Level 6
Level 6
25 likes received 10 likes received 10 likes given

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

0 Likes
lock attach
Attachments are accessible only for community members.
cadi_1014291
Level 6
Level 6
25 likes received 10 likes received 10 likes given

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

0 Likes
Anonymous
Not applicable

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

0 Likes
cadi_1014291
Level 6
Level 6
25 likes received 10 likes received 10 likes given

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

0 Likes
lock attach
Attachments are accessible only for community members.
cadi_1014291
Level 6
Level 6
25 likes received 10 likes received 10 likes given

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

0 Likes
Anonymous
Not applicable

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.

0 Likes
cadi_1014291
Level 6
Level 6
25 likes received 10 likes received 10 likes given

Hi Magnus,

   

Sorry for the delayed reply, thanks for all the information about the DFB, is getting less difficult to use :D.

   

 

   

Regards

   

Carlos

0 Likes
Anonymous
Not applicable

Good hear your starting to feel confident with the DFB.

   

I think there could be a systematic way to develop DFB algorithms, I will try to develop it and formulate over xmas, but some of the ideas are:

   
        
  • Identify key algorithm computation steps
  •     
  • Design the data flow - there are no instructions for the datapath, but the datapath contains the ALU of previous instruction
  •     
  • Map data to RAM locations
  •     
  • Think of states - identify loop states,  and preparations for computations and postcomputation operations
  •     
  • Use the ALU as a loop counter and to address RAM blocks
  •    
   

Lately I have been using a spreadsheet with one column each for

   

STATENAME, RAMA, RAMB, ACU, ALU, MAC, DATAPATH jumps and comments

   

There I try to fill in the necessary parts of the algorithm structure, and only enter what is necessary. After that I try to fill in the complete code in the DFB assembler using the spreadsheet as a blueprint.

   

I have a few example project that I work on - PID controller, square root function and a filter implementation. They need some work to be presented but they could perhaps illustrate the above ideas.

0 Likes
cadi_1014291
Level 6
Level 6
25 likes received 10 likes received 10 likes given

Hi Magnus,

   

I saw your new post on your blog last night, is this part of the project you are working on?

   

Have you think about posting that information here on the forum? it would be great as DFB examples are almost not existing!

   

 

   

Carlos

0 Likes