効果音の発生回路

効果音を発生し、車両のさまざまな状態を音で通知します。

音源には、YAMAHAのYMZ294を使用しています。

プログラム

コンパイラはCCS Cを使用しています。

#include <16f876.h>

#fuses HS, NOWDT, NOPROTECT, PUT, BROWNOUT, NOLVP

#use delay( Clock = 20000000 )        // クロック周波数指定
#use i2c( slave, SDA=PIN_C4, SCL=PIN_C3, ADDRESS=0x10, FAST, FORCE_HW )    // I2Cアドレス[ 0x10 ]

// 入出力ピン定義(入出力モード固定)
#use fixed_io( a_outputs=PIN_A0, PIN_A1, PIN_A2, PIN_A3, PIN_A5 )
#use fixed_io( b_outputs=PIN_B0, PIN_B1, PIN_B2, PIN_B3, PIN_B4, PIN_B5, PIN_B6, PIN_B7 )


// A0-A3:CPU Interface
// B0-B7:Data Bus
// C3:I2C_SCL(in)
// C4:I2C_SDA(in)
set_tris_a( 0b00010000 );
set_tris_b( 0b00000000 );
set_tris_c( 0b00011000 );


#define    WR    0x04    // WriteEnable
#define    CS    0x02    // ChipSelect
#define    A0    0x01    // ModeSelect
#define    IC    0x08    // Reset

#define    LED         PIN_C0
#define    SwitchOn    PIN_A4

// プロトタイプ宣言
void MixVol();
void mute();
void SoundTest();

void Sound( int Address, int Data );
void scale( int Part, int Octave, int Scale );
void Envel( long freq, int form );
void Melodious( int select );

// 音階周波数(イ長調)
#define    freq_C        440
#define    freq_D        494
#define    freq_E        554
#define    freq_F        587
#define    freq_G        659
#define    freq_A        740
#define    freq_B        831

// ft = fsc / (16 * tp)
#define    fsc            4000000 / 2

#define    Scale_0C    fsc / ( 16 * freq_C / 2 )    // ド
#define    Scale_0D    fsc / ( 16 * freq_D / 2 )    // レ
#define    Scale_0E    fsc / ( 16 * freq_E / 2 )    // ミ
#define    Scale_0F    fsc / ( 16 * freq_F / 2 )    // ファ
#define    Scale_0G    fsc / ( 16 * freq_G / 2 )    // ソ
#define    Scale_0A    fsc / ( 16 * freq_A / 2 )    // ラ
#define    Scale_0B    fsc / ( 16 * freq_B / 2 )    // シ

#define    Scale_1C    fsc / ( 16 * freq_C )        // ド
#define    Scale_1D    fsc / ( 16 * freq_D )        // レ
#define    Scale_1E    fsc / ( 16 * freq_E )        // ミ
#define    Scale_1F    fsc / ( 16 * freq_F )        // ファ
#define    Scale_1G    fsc / ( 16 * freq_G )        // ソ
#define    Scale_1A    fsc / ( 16 * freq_A )        // ラ
#define    Scale_1B    fsc / ( 16 * freq_B )        // シ

#define    Scale_2C    fsc / ( 16 * freq_C * 2 )    // ド
#define    Scale_2D    fsc / ( 16 * freq_D * 2 )    // レ
#define    Scale_2E    fsc / ( 16 * freq_E * 2 )    // ミ
#define    Scale_2F    fsc / ( 16 * freq_F * 2 )    // ファ
#define    Scale_2G    fsc / ( 16 * freq_G * 2 )    // ソ
#define    Scale_2A    fsc / ( 16 * freq_A * 2 )    // ラ
#define    Scale_2B    fsc / ( 16 * freq_B * 2 )    // シ

struct ft_freq
{
    int freq_low;
    int freq_high;
};

struct ft_oct
{
    struct ft_freq freq[ 7 ];
};

const struct ft_oct ft[ 3 ] =
{
    {
        Scale_0C % 256, Scale_0C / 256,
        Scale_0D % 256, Scale_0D / 256,
        Scale_0E % 256, Scale_0E / 256,
        Scale_0F % 256, Scale_0F / 256,
        Scale_0G % 256, Scale_0G / 256,
        Scale_0A % 256, Scale_0A / 256,
        Scale_0B % 256, Scale_0B / 256
    },
    {
        Scale_1C % 256, Scale_1C / 256,
        Scale_1D % 256, Scale_1D / 256,
        Scale_1E % 256, Scale_1E / 256,
        Scale_1F % 256, Scale_1F / 256,
        Scale_1G % 256, Scale_1G / 256,
        Scale_1A % 256, Scale_1A / 256,
        Scale_1B % 256, Scale_1B / 256
    },
    {
        Scale_2C % 256, Scale_2C / 256,
        Scale_2D % 256, Scale_2D / 256,
        Scale_2E % 256, Scale_2E / 256,
        Scale_2F % 256, Scale_2F / 256,
        Scale_2G % 256, Scale_2G / 256,
        Scale_2A % 256, Scale_2A / 256,
        Scale_2B % 256, Scale_2B / 256
    }
};

// =====================================================================
// SSP割り込み処理
#int_ssp
void ssp_interupt()
{
    int Receive;
    if( i2c_poll() )
    {
        // 受信
        Receive = i2c_read();

        Melodious( Receive );
    }
}

// =====================================================================
// メイン関数
void main()
{
    setup_adc_ports( NO_ANALOGS );   // A/D Converter - OFF
    setup_adc( ADC_OFF );

    enable_interrupts( INT_SSP );    // SSP
    enable_interrupts( GLOBAL );     // グローバル割り込み許可

    output_A( IC );     // (The 4th bit of PORTA Register must be High in Every time,)
    MixVol();


    while( 1 )
    {
        if( input( SwitchOn ) == FALSE )
        {
            SoundTest();
        }
    }
}

// =====================================================================
// ミキサー/ボリュームセッティング
void MixVol()
{
    Sound( 0x07, 0b00111000 );    // Mixer Settings

    Sound( 0x08, 0b00001111 );    // Ach Volume Setting
    Sound( 0x09, 0b00001111 );    // Bch Volume Setting
    Sound( 0x0A, 0b00001111 );    // Cch Volume Setting
}

// ミュート
void mute()
{
    Sound( 0, 0x00 );
    Sound( 1, 0x00 );
    Sound( 2, 0x00 );
    Sound( 3, 0x00 );
    Sound( 4, 0x00 );
    Sound( 5, 0x00 );
}

// サウンド テスト
void SoundTest()
{
    static int test;

    Melodious( test );

    test++;
    if( test > 4 )
    {
        test = 0;
    }
}

// =====================================================================
// アドレス/データセット
void Sound( int Address, int Data )
{
    output_A( ( IC ) );     // Address write enabled
    output_B( Address );    // Address input

    output_A( ( IC | WR | CS ) );   // Address write disabled
    output_A( ( IC | A0 ) );        // Data write enabled

    output_B( Data );                    // Data input
    output_A( ( IC | WR | CS | A0 ) );   // Data write disabled
}

// 単音の発生
void scale( int Part, int Octave, int Scale )
{
    Sound( ( Part * 2 ) - 2, ft[ Octave ].freq[ Scale ].freq_low );
    Sound( ( Part * 2 ) - 1, ft[ Octave ].freq[ Scale ].freq_high );
}

// エンベローブ設定
void Envel( long freq, int form )
{
    Sound( 0x0B, freq >> 8 );
    Sound( 0x0C, freq );
    Sound( 0x0D, form );
}

// =====================================================================
// 効果音選択
void Melodious( int select )
{
    int i, k;
    output_high( LED );

    switch( select )
    {
        // ドレミ~♪
        case 0:
        {
            for( k = 0; k < 3; k++ )
            {
                for( i = 0; i < 7; i++ )
                {
                    scale( 1, k, i );
                    delay_ms( 200 );
                }
            }

            mute();
        }
        break;

        // ティロリー♪
        case 1:
        {
            scale( 1, 1, 6 );
            scale( 2, 1, 7 );
            delay_ms( 40 );

            scale( 1, 1, 3 );
            delay_ms( 40 );

            scale( 1, 1, 4 );
            delay_ms( 40 );

            scale( 1, 1, 5 );
            delay_ms( 40 );

            scale( 1, 1, 6 );
            scale( 2, 1, 4 );
            delay_ms( 200 );

            mute();
        }
        break;

        // ポーン♪
        case 2:
        {
            Sound( 0x08, 0b00011111 );    // Ach Volume Setting

            scale( 1, 1, 0 );
            Envel( 0x0050, 0b00001000 );
            delay_ms( 500 );

            mute();
        }
        break;

        // ファーン♪
        case 3:
        {
            Sound( 0x08, 0b00011111 );    // Ach Volume Setting
            Sound( 0x09, 0b00011111 );    // Bch Volume Setting

            scale( 1, 2, 0 );
            scale( 2, 2, 2 );

            Envel( 0x000A, 0b00001110 );
            delay_ms( 500 );

            mute();
        }
        break;

        // ピーピッピッ♪
        case 4:
        {
            Sound( 0x08, 0b00001111 );    // Ach Volume Setting
            scale( 1, 2, 4 );
            delay_ms( 200 );

            Sound( 0x08, 0b00000000 );    // Ach Volume Setting
            delay_ms( 100 );

            Sound( 0x08, 0b00001111 );    // Ach Volume Setting
            scale( 1, 2, 4 );
            delay_ms( 50 );

            Sound( 0x08, 0b00000000 );    // Ach Volume Setting
            delay_ms( 50 );

            Sound( 0x08, 0b00001111 );    // Ach Volume Setting
            scale( 1, 2, 4 );
            delay_ms( 50 );

            mute();
        }
        break;

        default:

    }

    output_low( LED );
}

sound.c