
デモプログラムを改造したDSPフィルタ(DM330011)
投稿日 2013/04/21
microchip社のdsPIC33F DSCスターターキット(DM330011)に付属のデモプログラムを改造してDSPフィルタを作ってみました。
デモプログラムはDCIでCODECを制御するものと、OCPWMを使用したものが提供されていますが、今回はOCPWM方式の方を改造しました。
このデモプログラムは、簡単なボイスメモリなので、ADコンバータでサンプリングしたデータをG.711でエンコードしてフラッシュメモリに記録して、再生時はそれを読みだしてデコードし、OCPWMで出力しています。
DSPフィルタはエンコード/デコード、フラッシュメモリへの記録は必要ないので切り落とします。
大まかな流れは以下のようになります。
オーディオ信号 -> ADコンバータ サンプリング -> DSPフィルタ -> OCPWM出力
OCPWM出力はフィルターを経由してヘッドホンアンプへと流れ、音になります。
ADコンバータのサンプリングは8KHzとしました。
DSPフィルタはFIR 通過帯域650Hzから850Hzのバンドパスフィルタです。
フィルタの係数は、microchip社のDigital Filter Design Tool Liteで作りました。
通過帯域200HzのCW用フィルタとして十分使える性能です。
FIRバンドパスフィルタの特性

Sampling Frequency 8000Hz
Passband Frequencies 650 - 850Hz
Stopband Frequencies 600 - 900Hz
Passband Ripple 1(-dB)
Stopband Ripple 50(-dB)
Filter Taps 64
Window Kiser
波形観測(入力(Ch.1上) 750Hz矩形波 出力(Ch.2下)) 入力信号はSSGで生成

基本波750Hzのきれいな正弦波になっている。
ソースコード (main.cのみ)
#include "..\h\p33FJ256GP506.h"
#include "..\h\OCPWMDrv.h"
#include "..\h\sask.h"
#include "..\h\ADCChannelDrv.h"
#include "dsp.h"
_FGS(GWRP_OFF & GCP_OFF);
_FOSCSEL(FNOSC_FRC);
_FOSC(FCKSM_CSECMD & OSCIOFNC_ON & POSCMD_NONE);
_FWDT(FWDTEN_OFF);
//DSP Filter Struct
extern FIRStruct bandpass650_850Filter;
//FRAME_SIZE - Size of audio frame
#define FRAME_SIZE 128
//Allocate memory for buffers and drivers
int adcBuffer [ADC_CHANNEL_DMA_BUFSIZE] __attribute__((space(dma)));
int ocPWMBuffer [OCPWM_DMA_BUFSIZE] __attribute__((space(dma)));
fractional Signal_in[FRAME_SIZE];
fractional Signal_out[FRAME_SIZE];
//Instantiate the drivers
ADCChannelHandle adcChannelHandle;
OCPWMHandle ocPWMHandle;
//Create the driver handles
ADCChannelHandle *pADCChannelHandle = &adcChannelHandle;
OCPWMHandle *pOCPWMHandle = &ocPWMHandle;
int main(void)
{
//Configure Oscillator to operate the device at 40MHz.
//Fosc= Fin*M/(N1*N2), Fcy=Fosc/2
//Fosc= 7.37M*40/(2*2)=80Mhz for 7.37M input clock
PLLFBD=41; //M=39
CLKDIVbits.PLLPOST=0; //N1=2
CLKDIVbits.PLLPRE=0; //N2=2
OSCTUN=0;
__builtin_write_OSCCONH(0x01); //Initiate Clock Switch to FRC with PLL
__builtin_write_OSCCONL(0x01);
while (OSCCONbits.COSC != 0b01); //Wait for Clock switch to occur
while(!OSCCONbits.LOCK);
//Intialize the board and the drivers
SASKInit(); //For the GPIO
ADCChannelInit(pADCChannelHandle,adcBuffer); //For the ADC
OCPWMInit(pOCPWMHandle,ocPWMBuffer); //For the OCPWM
//Start Audio input and output function
ADCChannelStart(pADCChannelHandle);
OCPWMStart(pOCPWMHandle);
//Initialize FIR Filter
FIRDelayInit(&bandpass650_850Filter);
//Main processing loop. Executed for every input and output frame
while(1)
{
//Obtaing the ADC samples
while(ADCChannelIsBusy(pADCChannelHandle));
ADCChannelRead(pADCChannelHandle,Signal_in,FRAME_SIZE);
//Processing DSP filter
FIR(FRAME_SIZE, &Signal_out[0], &Signal_in[0], &bandpass650_850Filter);
//Wait till the OC is available for a new frame
while(OCPWMIsBusy(pOCPWMHandle));
//Write the frame to the output
OCPWMWrite (pOCPWMHandle,Signal_out,FRAME_SIZE);
}
}
フィルタ係数ファイル(bandpass650_850.s) Degital Signal Design Tool Liteで作成
; ..............................................................................
; File bandpass650_850.s
; ..............................................................................
.equ bandpass650_850NumTaps, 64
; ..............................................................................
; Allocate and initialize filter taps
.section .xdata, data, xmemory
.align 128
bandpass650_850Taps:
.hword 0x0002, 0x0006, 0x0002, 0xFFEF, 0xFFCC, 0xFFA8, 0xFFA1, 0xFFD0, 0x0040
.hword 0x00D9, 0x015C, 0x017A, 0x00F3, 0xFFC5, 0xFE3C, 0xFCED, 0xFC7D, 0xFD60
.hword 0xFF8D, 0x026A, 0x04F4, 0x0613, 0x0515, 0x020A, 0xFDD7, 0xF9F2, 0xF7DC
.hword 0xF886, 0xFBE4, 0x00E0, 0x05BD, 0x08B7, 0x08B7, 0x05BD, 0x00E0, 0xFBE4
.hword 0xF886, 0xF7DC, 0xF9F2, 0xFDD7, 0x020A, 0x0515, 0x0613, 0x04F4, 0x026A
.hword 0xFF8D, 0xFD60, 0xFC7D, 0xFCED, 0xFE3C, 0xFFC5, 0x00F3, 0x017A, 0x015C
.hword 0x00D9, 0x0040, 0xFFD0, 0xFFA1, 0xFFA8, 0xFFCC, 0xFFEF, 0x0002, 0x0006
.hword 0x0002
; ..............................................................................
; Allocate delay line in (uninitialized) Y data space
.section .ybss, bss, ymemory
.align 128
bandpass650_850Delay:
.space bandpass650_850NumTaps*2
; ..............................................................................
; Allocate and intialize filter structure
.section .data
.global _bandpass650_850Filter
_bandpass650_850Filter:
.hword bandpass650_850NumTaps
.hword bandpass650_850Taps
.hword bandpass650_850Taps+bandpass650_850NumTaps*2-1
.hword 0xff00
.hword bandpass650_850Delay
.hword bandpass650_850Delay+bandpass650_850NumTaps*2-1
.hword bandpass650_850Delay
(JF1VRR)