//***************************************************
// A/D converter -> 127th order LPF (FIR type) -> PWM output
// 7.37MHz Internal RC oscillator, 16x PLL enabled
// Fcy=7.37MHzx16/4=29.48MHz, Tcy=33.92ns
// Toshio Iwata at DIGITALFILTER.COM all rights reserved
// Last modified on 2008/07/07
//***************************************************

#include <p30f2012.h>
#include <adc12.h>
#include <timer.h>
#include <outcompare.h>
#include <dsp.h>

// configuration
_FWDT(WDT_OFF);
_FGS(CODE_PROT_OFF);
_FOSC(CSW_FSCM_OFF & FRC_PLL16);
_FBORPOR(PBOR_OFF & PWRT_64 & MCLR_EN);

// A/D control register
unsigned int _ADCON1;
unsigned int _ADCON2;
unsigned int _ADCON3;
unsigned int _ADCHS;
unsigned int _ADPCFG;
unsigned int _ADCSSL;

// PWM control register
unsigned int _PTCON;
unsigned int _PWMCON1;
unsigned int _PWMCON2;

// data
unsigned int adData;
unsigned int pwmData;
fractional filterOutData;
fractional filterInData;

//Coefficients are generated by DSPLinks
//http://digitalfilter.com/products/dsplinks/jpdsplinks.html
//U_4
//Remez Algorithm LPF
//Sampling Frequency =    28800.0
//cutoff1 = 2100.0000000
//cutoff2 = 2900.0000000
//Tap Count = 127
//attenuate =   -80.00
//ripple factor =    0.1000000
//Quantized by 16 [bits]
const fractional firCoeff[] __attribute__ ((space(auto_psv))) = {
0	, -5	, -9	, -15	, -20	, -24	, -25	, -21	,
-11	, 1	, 17	, 30	, 37	, 35	, 22	, 0	,
-26	, -50	, -64	, -62	, -41	, -4	, 39	, 80	,
104	, 102	, 69	, 11	, -60	, -125	, -163	, -160	,
-109	, -18	, 91	, 191	, 250	, 244	, 166	, 26	,
-141	, -294	, -383	, -373	, -250	, -34	, 228	, 467	,
609	, 594	, 397	, 40	, -406	, -831	, -1105	, -1109	,
-762	, -44	, 989	, 2214	, 3458	, 4528	, 5251	, 5507	,
5251	, 4528	, 3458	, 2214	, 989	, -44	, -762	, -1109	,
-1105	, -831	, -406	, 40	, 397	, 594	, 609	, 467	,
228	, -34	, -250	, -373	, -383	, -294	, -141	, 26	,
166	, 244	, 250	, 191	, 91	, -18	, -109	, -160	,
-163	, -125	, -60	, 11	, 69	, 102	, 104	, 80	,
39	, -4	, -41	, -62	, -64	, -50	, -26	, 0	,
22	, 35	, 37	, 30	, 17	, 1	, -11	, -21	,
-25	, -24	, -20	, -15	, -9	, -5	, 0	};

//fractional firDelay[] __attribute__ ((section (".ydata, data, ymemory"), aligned (256)));      
fractional __attribute__ ((space(ymemory), aligned (256))) firDelay[127]; // for MPLAB 8.10

FIRStruct firFilter;

// Timer subroutine
void __attribute__((__interrupt__, __shadow__)) _AltT3Interrupt(void) {
	// --- A/D converter -> 127th order LPF (FIR type) -> PWM output
	while(!IFS0bits.ADIF);	// wait A/D

	adData = ReadADC12(0);	// A-Dからデータを受け取る。12ビット、符号なし
	filterInData = (adData << 2) - 8192; // 14ビット、符号付きにする

	// FIRフィルタの出力を1個計算する（DSP関数）
	FIR( 1, &filterOutData, &filterInData, &firFilter );

	pwmData = (filterOutData >> 4) + 512; // 10ビット、符号なしにする

	if(pwmData > 1024-1) pwmData = 1024-1; // オーバフローリミッタ
	if(pwmData < 0) pwmData = 0; // アンダーフローリミッタ

	if(PORTBbits.RB0 == 0) { // プッシュスイッチ（SW1)が押されたとき
		pwmData = adData >> 2; // スルーで出力（10ビット）
	}
	SetDCOC2PWM(pwmData); // PWMに渡す

	IFS0bits.ADIF = 0;	// clear A/D interuppt flag
	IFS0bits.T3IF = 0;	// clear T3 interuppt flag
}

// Main routine
int main(void)
{

	// port init
	TRISB=0x01FF;
	// Use Alternate Interrupt Vector Table
	INTCON2bits.ALTIVT=1;
	// Confirm to turn off ADC
	ADCON1bits.ADON=0;
	// ADC init
	_ADCHS=	ADC_CH0_POS_SAMPLEA_AN3 &
			ADC_CH0_NEG_SAMPLEA_NVREF;		// A-D channel-3 select
	SetChanADC12(_ADCHS);
	_ADCON1=ADC_MODULE_ON &
			ADC_IDLE_CONTINUE &
			ADC_FORMAT_INTG &
			ADC_CLK_TMR &
			ADC_AUTO_SAMPLING_ON &
			ADC_SAMP_OFF;
	_ADCON2=ADC_VREF_AVDD_AVSS &
			ADC_SCAN_OFF &
			ADC_SAMPLES_PER_INT_1 &
			ADC_ALT_BUF_OFF &
			ADC_ALT_INPUT_OFF;
	// Tad={Tcy(ADCS+1)}/2>334ns, Then ADCS>18.7, Tad=10*Tcy
	_ADCON3=ADC_SAMPLE_TIME_1 &
			ADC_CONV_CLK_SYSTEM &
			ADC_CONV_CLK_10Tcy;
	_ADPCFG=ENABLE_AN3_ANA;	// A-D channel-3 analog input
	_ADCSSL=SCAN_NONE;
	OpenADC12(_ADCON1, _ADCON2, _ADCON3, _ADPCFG, _ADCSSL);

	// Timer3 setting 
	OpenTimer3(T3_ON & T3_GATE_OFF & T3_PS_1_1 & T3_SOURCE_INT, 1024-1);	// 28.8kHz sampling by Iwata
	ConfigIntTimer3(T3_INT_PRIOR_5 & T3_INT_ON);

	// Timer2 setting 
	OpenTimer2(T2_ON & T2_GATE_OFF & T2_PS_1_1 & T2_SOURCE_INT, 1024-1);	// 28.8kHz carrier PWM
	OpenOC2(OC_IDLE_CON & OC_TIMER2_SRC &
		OC_PWM_FAULT_PIN_DISABLE, 0, 0);

	// enable interrupt
	DISICNT = 0x0000;

	FIRStructInit( &firFilter, 127, (fractional *)firCoeff, __builtin_psvpage( firCoeff ), firDelay );
	FIRDelayInit( &firFilter );

	// main loop
	while(1)
	{
		// A/D result store in ResultData
	}
}
