/* ======================================================== 簡易I2C(内蔵ペリフェラル使用)通信 de JHL 藤田@開技 '09 Feb - $Id$ ======================================================== */ #ifndef _WIN32 #pragma sfr #pragma di #pragma ei #pragma nop #pragma inline // memcpy()をインライン展開する(の方が小さい!) #endif #include "incs.h" #include "i2c_mcu.h" #include "loader.h" #include "util_funcs.h" #include "i2c_mcu_sub.h" #include "pm.h" /// やりたくなかった…CODECのレジスタ名をひくため // ======================================================== // ワークアラウンド用 static void iic_mcu_simple_dummy_write(); static i2c_err iic_mcu_codec_write_low( u8 adrs, u8 dat ); // i2c_mcu.c にいる extern void iic_mcu_send_re_st( ); extern void iic_mcu_send_sp( ); extern i2c_err iic_mcu_send_a_byte( u8 ); extern i2c_err iic_mcu_call_slave( u8 slave ); /* yamaha codecから不用意に割り込みが入ることがあるが、タスクが登録されて 実際に読み出すときには書き戻した後なので何事もなかったように動くはず */ /********************************************//** コーデックに 『1バイト』 ライト iic_mcu_write_a_byte CODEC不具合ワークアラウンド ***********************************************/ #define YAMAHA_CODEC_ERRATA_CHECK_MASK ( 0x7D ) i2c_err iic_mcu_write_a_byte_codec( u8 adrs, u8 dat ) { u8 pm_reg_original; i2c_err rv; // ヤマハcodecワークアラウンド SPIとの共用レジスタの中身を取得 if(( rv = iic_mcu_read( IIC_SLA_CODEC, CODEC_REG_PM, 1, &pm_reg_original )) != I2C_ERR_OK ) { return( rv ); } // phase1 ここまで // 書き込み! if( ( rv = iic_mcu_codec_write_low( adrs, dat ) ) != I2C_ERR_OK ) { return( rv ); } // ヤマハcodecワークアラウンド if( ( pm_reg_original & YAMAHA_CODEC_ERRATA_CHECK_MASK ) == 0 ) // はじめから共有レジスタが0だったらテストもしない // (& リセット要求が立ってたらどうせリセットかかるので) { return( I2C_ERR_OK ); } { // 共有レジスタが 0x00 に書き換わっている(エラッタ発生!)ようなら書き戻す u8 pm_reg_after; if(( rv = iic_mcu_read( IIC_SLA_CODEC, CODEC_REG_PM, 1, &pm_reg_after )) != I2C_ERR_OK ) { return( rv ); } if( ( pm_reg_after & YAMAHA_CODEC_ERRATA_CHECK_MASK ) != 0x00 ) { // コンフリクトはなかった or リセット要求など return( I2C_ERR_OK ); } // else { rv = iic_mcu_codec_write_low( CODEC_REG_PM, pm_reg_original ); // 書き戻すが、再チェックはしない return ( rv ); // エラーが返ることもあるかも // リトライなどは無し } return( rv ); // no reach // } static i2c_err iic_mcu_codec_write_low( u8 adrs, u8 dat ) { IICMK10 = 1; // DMA用のISRに飛ばさないためにマスク if( iic_mcu_call_slave( IIC_SLA_CODEC ) != I2C_ERR_OK ) { iic_mcu_busy = false; return ( I2C_ERR_NOSLAVE ); } iic_mcu_send_a_byte( adrs ); iic_mcu_send_a_byte( dat ); // TIワークアラウンド codec_dummy_write(); iic_mcu_send_sp( ); iic_mcu_busy = false; return( I2C_ERR_OK ); } // re-stでダミーライト void codec_dummy_write() { iic_mcu_send_re_st( ); iic_mcu_send_a_byte( IIC_SLA_CODEC ); // ダミーライト iic_mcu_send_a_byte( 0x20 ); // ゴミを書いても問題ないアドレス iic_mcu_send_a_byte( 0xAA ); // 何でもよい }