YMF825をRaspberry PI(PI 3 model B)につないて、サンプルプログラムを動作させてみました。YMF825はFM音源です。
接続
3.3V でも動作するかと思ったのですが、今は5Vでないと動作しませんでした。
サンプルプログラム
動作させたサンプルプログラムはこちら です。
コンパイルするには、
- common の下の全ファイル
- raspi の下のfmsd1_raspi.c
- main 関数 ( fm825test.cと名前を付けました。 )
-
bcm2835 ライブラリ
が必要です。1,2,3 は全部まとめて同じフォルダーにコピーしました。
makefile
OBJS= fmasgn.o fmif.o fmnote.o\
fmpart.o fmtone.o fmvoice.o fmsd1_raspi.o\
fm825test.o
fm825test: $(OBJS)
gcc -o fm825test $(OBJS) -l bcm2835
fmasgn.o: fmasgn.c fmasgn.h fmtype.h
fmif.o: fmif.c fmif.h
fmnote.o: fmnote.c fmnote.h fmtype.h
fmpart.o: fmpart.c fmpart.h fmtype.h
fmtone.o: fmtone.c fmtone.h fmtype.h
fmvoice.o: fmvoice.c fmvoice.h fmtype.h
fmsd1_raspi.o: fmsd1_raspi.c
fm825test.o: fm825test.c fmif.h fmsd1.h
.c.o:
gcc -c $<
Main 関数
fm825test.c
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include <unistd.h>
#include <bcm2835.h>
#include "fmif.h"
#include "fmsd1.h"
int main()
{
int note=0x3c;
if (!bcm2835_init()) return 1;
initSPI();
initSD1();
Fmdriver_init();
while(1){
Fmdriver_sendMidi(0x90);
Fmdriver_sendMidi(note);
Fmdriver_sendMidi(0x7f);
sleep(2);
Fmdriver_sendMidi(0x80);
Fmdriver_sendMidi(note);
Fmdriver_sendMidi(0x7f);
sleep(2);
note++;
if(note>0x48){ note=0x3c; }
}
}
fmsd1_raspi.cにコード追加
一行だけ、fmsd1_raspi.cにプログラムを追加しました。Reset にGPIO 16(36番ピン)がアサインされていますが、GPIO 16 を出力モードにセットする、という行がないと動作しませんでした。
fmsd1_raspi.c
void initSD1( void )
{
// set Output Mode
bcm2835_gpio_fsel(RST,BCM2835_GPIO_FSEL_OUTP); // <- 追加
バグかも
fmtone.cの中の、void Tone_sendTone( void )の中で、以下コメントアウトした行は、
riPtr[0] = (td->voiceCommon & 0x60)>>5;
// riPtr[1] = ((td->voiceCommon & 0xc0)>>3) | (td->voiceCommon & 0x07);
riPtr[1] = ((td->voiceCommon & 0x18)<<3) | (td->voiceCommon & 0x07);
for ( j=0; j<MAX_FM_OPERATOR; j++ ){
// riPtr[MAX_ELEMENT_PRM+OPERATOR_PRM_REG_SZ*j+0] = (td->opPrm[j][3] << 4) | (td->opPrm[j][0] & 0x08) | ((td->opPrm[j][0] & 0x01)<<2);
riPtr[MAX_ELEMENT_PRM+OPERATOR_PRM_REG_SZ*j+0] = (td->opPrm[j][3] << 4) | (td->opPrm[j][0] & 0x08) | ((td->opPrm[j][0] & 0x04)>>2);
riPtr[MAX_ELEMENT_PRM+OPERATOR_PRM_REG_SZ*j+1] = (td->opPrm[j][4] << 4) | td->opPrm[j][2];
riPtr[MAX_ELEMENT_PRM+OPERATOR_PRM_REG_SZ*j+2] = (td->opPrm[j][1] << 4) | td->opPrm[j][5];
riPtr[MAX_ELEMENT_PRM+OPERATOR_PRM_REG_SZ*j+3] = (td->opPrm[j][6] << 2) | (td->opPrm[j][0] & 0x03);
riPtr[MAX_ELEMENT_PRM+OPERATOR_PRM_REG_SZ*j+4] = td->opPrm[j][7];
riPtr[MAX_ELEMENT_PRM+OPERATOR_PRM_REG_SZ*j+5] = ((td->opPrm[j][8] & 0x0f) << 4) | ((td->opPrm[j][8] & 0xf0) >> 4);
riPtr[MAX_ELEMENT_PRM+OPERATOR_PRM_REG_SZ*j+6] = (td->opPrm[j][9] << 3) | ((td->opPrm[j][0] & 0x70) >> 4);
}
だと思われます。