ムライボックス (14) --- ソフトウェア (6)
今回は PIC16F18325 を使用した場合の話です。
ハードウェア回路としては 2017 年 12 月 12 日付けの記事 (→こちら ) に掲載してあります。
MPLAB X IDE に付属の MCC (MPLAB Code Configurator) を利用して作成しています。 プログラム・サイズは 820 ワード、RAM サイズは 171 バイトです。
MCC で生成されるファイルについては省略し、「main.c」の部分だけを下に示します。 (下のリストだけをコンパイルしても動作しません)
XG システム・エクスクルーシブ・メッセージを利用してリマップ/マスク・テーブルを書き換え可能にしてあります。 それについては次回に説明します。
#include "../mcc_generated_files/mcc.h" #include <string.h> // uncomment following line to inhibit ch. remapping //#define REMAP_INH // macro for "OR" mask output port polarity #define MASK_POL(x) ((uint8_t)~(x)) // for '1' output = mask, '0' output = enable // macro for USART RX FIFO buffer empty check #define EUSART_rxbuf_not_empty (0 != eusartRxCount) // "running" mask pattern volatile uint8_t r_mask = 0x00; uint8_t remap_tab[16] = { 0, // ch 1 --> ch 1 (1 origin) 0, // ch 2 --> ch 1 0, // ch 3 --> ch 1 0, // ch 4 --> ch 1 4, // ch 5, no remap 5, // ch 6, no remap 6, // ch 7, no remap 7, // ch 8, no remap 8, // ch 9, no remap 9, // ch 10, (drum ch), no remap 10, // ch 11, no remap 11, // ch 12, no remap 12, // ch 13, no remap 13, // ch 14, no remap 14, // ch 15, no remap 15 // ch 16, no remap }; // uint8_t remap_tab[] uint8_t mask_tab[16] = { 0x01, // ch 1 --> port 1 0x02, // ch 2 --> port 2 0x04, // ch 3 --> port 3 0x08, // ch 4 --> port 4 0x08, // ch 5 --> port 4 0x08, // ch 6 --> port 4 0x08, // ch 7 --> port 4 0x08, // ch 8 --> port 4 0x08, // ch 9 --> port 4 0xff, // ch 10 --> all port (drum ch, broadcast) 0x08, // ch 11 --> port 4 0x08, // ch 12 --> port 4 0x08, // ch 13 --> port 4 0x08, // ch 14 --> port 4 0x08, // ch 15 --> port 4 0x08 // ch 16 --> port 4 }; // uint8_t mask_tab[] // // system common/realtime message to port mask pattern table // port bitmap assignment: // b15 = port16, ... , b1 = port2, b0 = port1 // uint8_t sysmsg_tab[16] = { 0xff, // 0xF0, Start of Exclusive (arbitrary) 0xff, // 0xF1, MTC Quater frame (2 byte) 0xff, // 0xF2, Song Position Pointer (3 byte) 0xff, // 0xF3, Song Select (2 byte) 0x00, // 0xF4, undefined 0x00, // 0xF5, undefined 0xff, // 0xF6, Tune Request (obsolute) 0xff, // 0xF7, End of Exclusive 0xff, // 0xF8, MIDI Clock 0x00, // 0xF9, undefined 0xff, // 0xFA, Start 0xff, // 0xFB, Continue 0xff, // 0xFC, Stop 0x00, // 0xFD, undefined 0xff, // 0xFE, Active sensing 0x00 // 0xFF, System Reset (obsolute) }; // uint8_t sysmsg_tab[] void main( void ) { uint8_t c; // received byte from MIDI-IN uint8_t midi_ch; // MIDI ch / sysmsg type uint8_t bm; // port bitmask pattern // initialize the device SYSTEM_Initialize(); // Enable the Global Interrupts INTERRUPT_GlobalInterruptEnable(); // Enable the Peripheral Interrupts INTERRUPT_PeripheralInterruptEnable(); while (1) { // test for EUSART TX shift reg empty and RX data ready if (TXSTAbits.TRMT && EUSART_rxbuf_not_empty) { c = EUSART_Read(); // get MIDI byte midi_ch = (0x0fu & c); // extract MIDI ch / system msg type bm = r_mask; // use "running" port mask if (0x80u & c) { // status byte if (0xf0u > c) { // ch mode message [0x80..0xef] bm = mask_tab[midi_ch]; // get port mask pattern r_mask = bm; // set "running" port mask pattern #if !defined(REMAP_INH) c = ((c & 0xf0u) | remap_tab[midi_ch]); // remap MIDI channel #endif } else { // system message bm = sysmsg_tab[midi_ch]; // escaping for system realtime if (0xf8u > c) { // system common msg [0xf0..0xf7] r_mask = bm; // set "running" port mask pattern } // if (0xf8u > c) { ... } // if (0xf0u > c) {} else { ... } else { // data byte // no processing required for data byte } // if (0x80u & c) { ... bm = MASK_POL(bm); // adjust mask polarity CM1CON0bits.C1POL = (0x01u & bm); // port 1 mask bm >>= 1; // next bit CM2CON0bits.C2POL = (0x01u & bm); // port 2 mask bm >>= 1; // next bit PWM5CON0bits.PWM5POL = (0x01u & bm); // port 3 mask bm >>= 1; // next bit PWM6CON0bits.PWM6POL = (0x01u & bm); // port 4 mask TX1REG = c; // send MIDI byte sysx_proc(c); } else { // EUSART TX busy or EUSART RX not ready } // if (TXSTAbits.TRMT && ... ) { ... } // while (1) { ... } // void main()
PIC16F18325 は 14 ピンのチップで、出力に使えるピン数も限られています。 CLC (Configurable Logic Cell) を利用して 4 ポートの出力を実現しており、それ以上の拡張は考えていないので、ビットマスク・パターンのビット幅を 16 ビットから 8 ビットに削減しています。
PIC の EUSART では、送信完了の割り込みはなく、ステータス・レジスタのフラグ・ビットをポーリングで監視する必要があります。
そのビットは、
TXSTAbits.TRMT
でアクセスできます。
このビットをメインの無限ループ
while (1) { . . . }
の中でチェックしています。
単なる "OR" ゲートとして構成する CLC へのゲート出力にはコンパレータ・モジュール 1 および 2 の出力と、PWM モジュール 5 および 6 の出力とを使っています。
たとえばコンパレータ 1 では、出力極性を反転するビット
CM1CON0bits.C1POL
を操作しています。
MCC で生成される割り込みを活用した EUSART 送受信ルーチンを使用しています。
Arduino/AVR の所で説明したように、送信側ルーチンは使わなければ何も影響を及ぼさないので、受信側のルーチンとバッファのみを利用しています。
「処理」および「"OR" ゲートへの出力」が済んで、UART 送信バッファへの書き込みも終了した時点、つまり、
TX1REG = c; // send MIDI byte
の後の時点では、そのキャラクタが送信完了になるまで 1 キャラクタ・タイム = 約 0.3 ms の余裕があります。
つまり、そこはユーザ・インターフェース (UI) の処理やシステム・エクスクルーシブ処理を入れるのに適した場所となっています。
上のプログラムでも
sysx_proc(c);
としてシステム・エクスクルーシブの処理を入れています。 (sysx_proc() 自体の記述は省略してあります)
ムライボックスとしての処理と重なる部分もありますが、ムライボックスの処理を優先としてムライボックスの処理の中には組み入れず、システム・エクスクルーシブ処理は別個に行なっています。
システム・エクスクルーシブ処理については次回説明します。