View previous topic :: View next topic |
Author |
Message |
Jim McBride
Joined: 24 Mar 2004 Posts: 21
|
Look-up table for 16 bit values How-to? |
Posted: Tue Jul 20, 2010 11:40 am |
|
|
I have never used a look-up table and can't seem to find any helpful posts to get me the basics. Neither have (yet) I been able to find any direct example code in my "old" compiler sample code.
I need to set and execute 32 different constant delays depending on a 10 bit adc/32. A case statement takes way to long. Would it be possible (faster) to use a look-up table to return a 16 bit constant (or two bytes hi and low) to insert into my delays?
Any samples/links greatly appreciated. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Jul 20, 2010 11:48 am |
|
|
The Ex_sine.c file has a look-up table in it. They declare it as a byte
table, so change it so it's declared as an 'int16'. Here's the file location:
Quote: | c:\program files\picc\examples\ex_sine.c |
There are limitations on the size of 'const' tables for the 16F-series PICs
with the PCM compiler. But your total size of 32 words (64 bytes) is
well within the limit of 256 bytes, so no problem. |
|
|
Jim McBride
Joined: 24 Mar 2004 Posts: 21
|
|
Posted: Tue Jul 20, 2010 1:00 pm |
|
|
Wow, I did not expect the data table would be so easy. But I am not sure if it will work for me.
ide v3.43
pch v3.188
PIC12F675
As you pointed out previously (in another post), my compiler version can handle delay_us(byte) as variable or delay_us(1 - 65536) as constant. I was hoping to put a 16bit constant in there using this code (snippet), but it does not work. See anything wrong or am I out of luck doing it this way with my compiler version?
Code: | int x;
int16 CONST delay_table[2] = {255,256};
x = 0;
delay_us(delay_table[x]);// simulates to 294uS
x = 1:
delay_us(delay_table[x]);// simulates to 43uS |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Jul 20, 2010 1:07 pm |
|
|
But the parameter is not a constant. The compiler doesn't know the
delay value at compile-time. It doesn't qualify as a 16-bit constant. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
|
Jim McBride
Joined: 24 Mar 2004 Posts: 21
|
|
Posted: Tue Jul 20, 2010 1:21 pm |
|
|
I guess that makes sense, bummer. Lets go about this from a different angle. I want 32 different delays ranging from 10hZ to 7kHz. A case statement takes longer and longer to get to the last case and 7kHz is not possible. Currently, case zero is my longest delay and case 31 is my shortest. One possibility would be to reverse the logic and put the shorter delays first. Do you see any other way of jumping to 32 different constant delay options? |
|
|
Jim McBride
Joined: 24 Mar 2004 Posts: 21
|
|
Posted: Tue Jul 20, 2010 1:40 pm |
|
|
Thank you ckielstra,
I have looked and thought about that but unless I am just missing something, it does not solve my problem.
Long delays are not a problem, I can use delay_ms(byte).
It is the really short delays that are killing me. Anything fancy I try to do kills me with the overhead.
In a loop that is capable of running up to 7khz (~143uS) I have to read in an ADC, pulse a pin to a frequency determined by the ADC as well as ramp up to and down from that frequency from zero. (All running at 4Mhz) This is easily done with a home brewed delay as a while() loop but the relationship between the ADC number and the frequency is logarithmic. I don't have enough time in the loop to do that math, so I chop it up into 32 "set" delays that follow the scale needed. I just can't figure out how to test for and get to the individual delays fast enough.
Any ideas? |
|
|
collink
Joined: 08 Jan 2010 Posts: 137 Location: Michigan
|
|
Posted: Tue Jul 20, 2010 1:47 pm |
|
|
Jim McBride wrote: |
In a loop that is capable of running up to 7khz (~143uS) I have to read in an ADC, pulse a pin to a frequency determined by the ADC as well as ramp up to and down from that frequency from zero. (All running at 4Mhz) This is easily done with a home brewed delay as a while() loop but the relationship between the ADC number and the frequency is logarithmic. I don't have enough time in the loop to do that math, so I chop it up into 32 "set" delays that follow the scale needed. I just can't figure out how to test for and get to the individual delays fast enough.
Any ideas? |
Shouldn't be too hard.
Code: |
int16 CONST Lookup[32] = {1,2,3,4,5,6,7,8,9,10,
11,12,13,14,15,16,17,18,19,20,
21,22,23,24,25,26,27,28,29,30,31,32};
int16 adc_input;
int16 delay_time;
delay_time = Lookup[adc_input / 32];
|
Obviously you'd want to use real delay values and not the linear progression I used but you get the point. How you go about ramping up and down is a different story but that's not so bad either. You could have the current and target values as well as a step. You step from one to the other in the loop until you get the target. Or, if the value changed again then the target changed and so the step changes. Let's say you want to step in 100 increments. Then you set your step to 1/100th of the difference between the current and target when a new target is set. Make sense? |
|
|
Jim McBride
Joined: 24 Mar 2004 Posts: 21
|
|
Posted: Tue Jul 20, 2010 2:15 pm |
|
|
You have me thinking in a new direction. Well actually two old directions, that for individual reasons, failed, but might work combined.
Delay_time being used in a while(x){x--;} loop delay?
The ramp is a little tricky. It is logarithmic as well. ie the delay time for a delay that is 10Hz needs to drop off much quicker than one for 5kHz. Otherwise the slower the pulses come, the longer it takes to slow down/speed up to the targeted speed. I should be able to combine two paired Lookup tables, one for delay_time and one for step (gain).
Thanks for helping me get unstuck, back to bangin' on duh keyboard.... |
|
|
|