Hi Glen,
there are a few things you can do to improve the code wrt. the table-lookup, avoiding a lot of calculations and stuff. It is a tradeoff between ROM/FLASH usage for the table on one side, and codesize & execution speed on the other side. But since you are using the table a lot with lots of code calculating it, i guess the overall ROM/FLASH used will be less, plus a faster processing speed.
First, make the lookup-table 256 entries large. The native data size of the PIC is 8 bits, using that as table size allows for some really fast methods for reversing the lookup direction and inverting the value.
Then, the PIC has a 10-bit ADC. Use that! This will make things even simpler. To store the result, the PIC uses two registers, ADRESL and ADRESH. Configure the ADC to give you a right-justified result. (register ADCON1 bit ADFM set to 1). This will result in the lower 8 bits of the readout to be stored in ADRESL, and the upper 2 bits into the lower 2 bits of ADRESH.
The effect of this is that in ADRESH you get only the value 0, 1, 2 or 3 over the full range. Now, 4 values, 4 quadrants, a table with 256 entries and a ADRESL of 8 bits... I guess you can already start to see where this goes.
Now about how to access it using simple methods and the ADRESH bits of the result. The lookup table contains the first 90° of a sinewave here. If you invert the index value, you read that table backwards. That way you now have 180°. To decide wether to read forwards or backwwards, you use bit 0 of ADRESH. If it is set, you simply invert the index into the table.
In code this would look something like this:
if (ADRESH & 0x01)
{
result = sintab[~ADRESL];
}
else
{
result = sintab[ADRESL];
}
Now for the inverting of the read value of the lookup. You use bit 1 of ADRESL to do that. If it set to 1, you simply invert the value you just read from the lookup-table. Again, in code this looks like:
if (ADRESH & 0x02)
{
result = ~result;
}
OK, this was just for sine lookup from the table. The bits of ADRESH for those 4 quadrants in sequence look like this:
00000000 - first sine quadrant
00000001 - second sine quadrant
00000010 - third sine quadrant
00000011 - fourth sine quadrant
Which is, of course, also the same sequence you get in ADRESH in 10 bit ADC mode when going from 0 to maximum.
If you want to read a cosine instead, you simply add 1 to ADRESH. The resulting sequence of ADRESH will then be:
00000001
00000010
00000011
00000100
This is OK because only the lowest two bits are evaluated anyways. Now, if you want to have the full sine or cosine inverted, you simply add another 2 to ADRESH. Doing all the above allows you to write a single routine that does this. With a little more bit-magic the polarity bits that you use to control the actual output can also be set. You can also combine those bits into a single byte instead of spreading it over four int's. There is the nifty thing of #define, which allows you to define things with a name.
Attached is a textfile with some ad-hoc example code of all that with lots of comments. Of course not tested for bugs, just to show you the overall process. Hope that helps. If you have any questions, let me know.
Greetings,
Chris