デモプログラムを改造した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バンドパスフィルタの特性

dsp_filter1.jpg

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で生成

dsp_filter2.jpg

基本波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)