akira.keiのアイコン画像
akira.kei 2025年02月10日作成 (2025年02月10日更新) © GPL-3.0+
セットアップや使用方法 セットアップや使用方法 閲覧数 126
akira.kei 2025年02月10日作成 (2025年02月10日更新) © GPL-3.0+ セットアップや使用方法 セットアップや使用方法 閲覧数 126

8ピンPICのPIC16F18313を使う(その12)NCOでシンセサイザ

<前の記事 : 次の記事>

NCOでDCOにできないか

PIC 16F18313に内蔵されてるNCOの出力周波数は20bitで指定できる。これだけ分解能があればシンセサイザーのオシレータ部分に使用できるかも。EXCELで0〜127のMIDIノート番号に対する周波数を計算して、NCOで得られるはずの周波数との誤差を求めてみた。
Foscが1MHzの場合だとノート番号77以降で誤差が0セントになる。実際には10セント程度は人の耳では識別できないし、これはこれで味があるとも言えるが、せっかくデジタルなんだからもう少し頑張りたい。
1MHz
源振の1MHzを下げられれば周波数分解能が上がり、誤差が出にくくなるのだが、NCOへの入力は以下の3つしか選べない。

  1. HFINTOSC
  2. Fosc
  3. LC1_out

実質的に上の2つはほぼ同じなので、LC1_outしか選択肢が無いが、鬼門のCLCモジュールを使わなくてはいけなくなる。ここでCLCモジュールにLFINTOSC(31kHz)が入力できればいい。
31.25kHz

CLCモジュール

CLCモジュールはとにかく意味がわからない。データシートを見ても機能がピンと来ないわけで、これはツールに頼るしかない!と、これも苦手なMCC(Classic)で設定してみた。
CLC
とにかく入力元はLFINTOSC(31kHz)に設定し、4-input ANDに突っ込んだ。RA5をPPS経由で出力モニタにすれば、LFINTOSCが本当は何Hzなのかが測れる。

pragma-config.h

将来的にUSARTからMIDI信号を受けたいので、動作周波数は速い方が通信エラーが少ない。今回はとりあえず1MHz駆動にしたが、32MHz駆動の方が妥当かもしれない。(いつもと同じなので省略)

mainルーチン

まずは冒頭はxc.hとpragma_config.hを忘れずにインクルードし、出力バッファ無効、アナログ無効にする。テンプレートのようなものだ。

#include <xc.h> #include "pragma_config.h" void main(void) { TRISA=0xff; ANSELA=0;

CLCモジュールの設定はMCC classicに頼ったが、出来た中身を見てみるとなんとなく作法がわかってくる。4つのCLC1SELyには全部LFINOSCを指定、4つのCLC1GLSyもゲートを一つだけ選ぶことで、ここは単なるバッファになっている。最後にCLC1CONでモジュールを有効にして、RA5にPPS経由で出力するだけだ。

// CLC1POL = 0x00; CLC1SEL0 = 0x1D; CLC1SEL1 = 0x1D; CLC1SEL2 = 0x1D; CLC1SEL3 = 0x1D; CLC1GLS0 = 0x02; CLC1GLS1 = 0x02; CLC1GLS2 = 0x02; CLC1GLS3 = 0x02; CLC1CON = 0x82; RA5PPSbits.RA5PPS=0b00100; // CLC1OUT TRISAbits.TRISA5=0;

あとはNCO1を設定すればいい。入力はCLCにしてRA2に出力する。インクリメントの0x07358はLFINTOSC周波数が31.25kHzの場合の440Hz出力のための値であり、測定するとかなりいいとこまでイケてるし、微調整も可能だろう。
今回は最後は空の無限ループだが、UARTからMIDIノートを受け取ってNCO 1INCに設定する割り込みルーチンを入れればある程度までは良さそうだ。実際はポルタメントとか変調をどう受け取るかが難しそうだが。

// NCO1INC=0x07358; NCO1CLKbits.N1CKS=0b10; // CLC1OUT NCO1CONbits.N1PFM=0; NCO1CONbits.N1EN=1; RA2PPSbits.RA2PPS=0b11101; // NCO1 TRISAbits.TRISA2=0; while(1) { } }

440Hz&LFINTOSC

akira.keiのアイコン画像
機械系エンジニアだが電子工作を趣味としている。週末はひとりバーベキュー。
ログインしてコメントを投稿する