2ch出力
少しがんばって2ch出力させてみた。
1Hzと0.5Hzのサイン波を生成して、LEDを点滅させている。
SPIクロックとサンプリング周波数
System Clockは48MHzに設定。TopDesign
TCPWM_P4のConfigureダイアログ
TC_Sampling_TimerのPeriodを249に設定した。
0..249でカウントアップしてオーバーフローしたらISR_Sampling_Timerの割り込みがかかる。
12MHz / 250 = 48kHz今まで(ぴゅんぴゅん3号など)250に設定していたので、間違っていたかも。
割り込みと同時にOVからPin_Sampling_ClockにH/Lの信号が出力される。
→オシロをあてればサンプリング周波数が測定できる。
main.c
/* ========================================
*
* Copyright YOUR COMPANY, THE YEAR
* All Rights Reserved
* UNPUBLISHED, LICENSED SOFTWARE.
*
* CONFIDENTIAL AND PROPRIETARY INFORMATION
* WHICH IS THE PROPERTY OF your company.
*
* 2015.10.07 2ch同時出力
* 2015.10.06 2ch DACに対応(2ch同時出力は不可)
* 2015.10.06 TC_Sampling_TimerのOVをPINに出力
* 2015.10.03 MCP4922に12bitデータを送信
* ========================================
*/
#include <project.h>
#include <math.h>
#include "wavetable.h"
#define SAMPLE_CLOCK (48000.0f)
#define WAVE_FREQUENCY_A (1000.0f)
#define WAVE_FREQUENCY_B (2000.0f)
// ERROR CODE
#define ERR_DAC_CHANNEL_OUT_OF_RANGE 0x01
volatile uint32 phaseRegisterA;
volatile uint32 phaseRegisterB;
volatile uint32 tuningWordA;
volatile uint32 tuningWordB;
void DACSetVoltage(uint16 value, int channel)
{
uint16 txData;
switch (channel) {
case 0:
// Highバイト(0x30=OUTA/BUFなし/1x/シャットダウンなし)
txData = (value & ~0xF000) | 0x3000;
break;
case 1:
// Highバイト(0xB0=OUTB/BUFなし/1x/シャットダウンなし)
txData = (value & ~0xF000) | 0xB000;
break;
default:
;
// error(ERR_DAC_CHANNEL_OUT_OF_RANGE);
}
Pin_LDAC_Write(1u);
SPIM_DAC_SpiUartWriteTxData(txData);
while(0u == (SPIM_DAC_GetMasterInterruptSource() & SPIM_DAC_INTR_MASTER_SPI_DONE))
{
/* Wait while Master completes transfer */
}
Pin_LDAC_Write(0u);
/* Clear interrupt source after transfer completion */
SPIM_DAC_ClearMasterInterruptSource(SPIM_DAC_INTR_MASTER_SPI_DONE);
}
CY_ISR(ISR_Sampling_Timer_Handler)
{
uint32 index;
// Caluclate Wave Value A
//
phaseRegisterA += tuningWordA;
// 32bitのphaseRegisterをテーブルの10bit(1024個)に丸める
index = phaseRegisterA >> 22;
uint16 waveValueA = waveTableSine[index];
// Caluclate Wave Value B
//
phaseRegisterB += tuningWordB;
index = phaseRegisterB >> 22;
uint16 waveValueB = waveTableSine[index];
// Output
//
DACSetVoltage(waveValueA, 0);
DACSetVoltage(waveValueB, 1);
TC_Sampling_Timer_ClearInterrupt(TC_Sampling_Timer_INTR_MASK_TC);
}
int main()
{
// 変数の初期化
tuningWordA = WAVE_FREQUENCY_A * pow(2.0, 32) / SAMPLE_CLOCK;
phaseRegisterA = 0;
tuningWordB = WAVE_FREQUENCY_B * pow(2.0, 32) / SAMPLE_CLOCK;
phaseRegisterB = 0;
// コンポーネントの初期化
TC_Sampling_Timer_Start();
ISR_Sampling_Timer_StartEx(ISR_Sampling_Timer_Handler);
SPIM_DAC_Start();
CyGlobalIntEnable;
for(;;)
{
}
}
/* [] END OF FILE */
MCP4922のchannelAから1kHz、channelBから2kHzのサイン波を出力するプログラムだ。
オシロで出力をチェック
ch1:TimerのOVの出力 ch2:DACのchannelBの出力
(1)F:47.94kHzchannelBは2kHzのはずなのでおかしい。
(2)F:998.0Hz
ch1:TimerOV ch2:LDAC(DACのラッチ)
よく見てみるとサンプリング区間の2回に1回しかラッチ信号が出力されていない。(ラッチ信号は2ch分あるので連続で2回出力される)
SPIのクロックを上げる
SPIMのConfigureダイアログSPIクロックを4MHzから8MHzにあげてみた。
また、TX data bitsを16に変更(デフォルトは8)。これで16bitまとめて出力できる。main.cもこれに合わせて変更した。
4MHzのSPI信号
ch1:MOSI ch2:SCK
SCKは4MHzになっている
8MHzに変更したSPI信号
SCKはだいたい8MHzになっている
オシロで出力をチェック
ch1:TimerOV ch2:LDAC
サンプリング区間ごとにラッチ信号が2回ずつ出力されている。
ch1:TimerOV ch2:DACのchannelB
出力周波数も無事2kHzに(^q^/)
メモ:
- MCP4922の2ch同時出力はできたが、SPIの信号出力で相当時間が食われている。SPIの出力が終わるまで非同期で別の処理ができればいいが、波形生成の演算はSPI出力の前に終わらせる必要があるし、2ch出力は努力目標ということにしようかな。
- リズムマシンはDecayやLevel、トラックの合成など結構計算量がありそうだし、無理そうならサンプリング周波数を32kHzに落とすとか。
- DACの片チャンネルは仮想GNDの電位を出力する?
- 出力段のLPFは必須
PSoC Creatorのプロジェクト
https://github.com/ryood/PSoC-DDS-MCP4922
0 件のコメント:
コメントを投稿