/* ======================================================== 藤田@開技 nintendo '09 Apr ======================================================== */ #include "incs.h" #include "adc.h" #include "pm.h" #include "led.h" bit adc_updated; /* ======================================================== ADC設定と、開始 以下のピンは主にここで操作・監視されます。 ・BT_TEMP,_P ・ADIN1 ・VOL 関係ありそうですが別のところで管理しています ・PM_BT_DET,_P PM_init ・8tics毎に呼ばれ、3チャンネル分取り込むとADCを停止します。  タスク起動時、レジスタには前回の取り込み値が入っています。 ======================================================== */ task_interval tsk_adc(){ static u8 old_tune; static u8 old_sndvol; static u8 sndvol_codec; // static u8 bt_temp_old; if(( system_status.pwr_state == ON ) || ( system_status.pwr_state == SLEEP )){ if( adc_updated ){ #if 0 tune と Vol の変化では割り込みを入れない // tune if( abs( old_tune - vreg_ctr[ VREG_TUNE ] ) >= 4 ){ old_tune = vreg_ctr[ VREG_TUNE ]; vreg_ctr[ VREG_C_IRQ0 ] |= REG_BIT_VR_TUNE_CHANGE; if( ( vreg_ctr[ VREG_C_IRQ_MASK0 ] & REG_BIT_VR_TUNE_CHANGE ) == 0 ){ IRQ0_ast; } } // Volume if( abs( old_sndvol - vreg_ctr[ VREG_C_SND_VOL ] ) >= 4 ){ old_sndvol = vreg_ctr[ VREG_C_SND_VOL ]; vreg_ctr[ VREG_C_IRQ0 ] |= REG_BIT_VR_SNDVOL_CHANGE; if( ( vreg_ctr[ VREG_C_IRQ_MASK0 ] & REG_BIT_VR_SNDVOL_CHANGE ) == 0 ){ IRQ0_ast; } } #endif // codecに伝える if( vreg_ctr[ VREG_C_SND_VOL ] != sndvol_codec ){ sndvol_codec = vreg_ctr[ VREG_C_SND_VOL ]; #ifndef _CODEC_CTR_ iic_mcu_write_a_byte( IIC_SLA_DCP, 0, sndvol_codec ); #else なんとかする iic_mcu_write_a_byte( IIC_SLA_CODEC, REG_ADRS_CODEC_VOL, sndvol_codec ); #endif } adc_updated = 0; } ADCEN = 1; ADM = 0b00011011; // セレクトモード、章圧、fCLK/6 ///ここから ADPC = 0x06; // ADCポートのセレクト ADS = ADC_SEL_TUNE; // NOP(); ADCS = 1; // AD開始。 /// ここまでに、1us以上開ける ADIF = 0; ADMK = 0; LED_duty_TUNE = ((u16)( vreg_ctr[ VREG_C_TUNE ] ) << 2); return( 8 ); } } /* ========================================================  過去3つのminでもMAXでもない値を返す  突発的なノイズを除く。  根本対策ではないが、これはこれで使い道がある。 ======================================================== */ static u8 getmean3( u8* hist ){ u8 temp; if( *hist < *( hist+1 ) ){ temp = *hist; *hist = *(hist+1); *(hist+1) = temp; } if( !( *hist > *(hist+1) )){ return *hist; }else{ if( *(hist+1) > *(hist+2) ){ return *(hist+1); }else{ return *(hist+2); } } } /* ========================================================  自前で次のチャンネル   一通り終わったら止める ======================================================== */ __interrupt void int_adc(){ static u8 hist_tune[3]; static u8 hist_snd_vol[3]; static u8 hist_bt_temp[3]; static u8 index; u8 temp; EI(); switch( ADS ){ case( ADC_SEL_TUNE ): hist_tune[ index ] = ADCRH; vreg_ctr[ VREG_C_TUNE ] = getmean3( hist_tune ); break; case( ADC_SEL_VOL ): temp = ADCRH; if( temp > 200 ){ temp = 200; } hist_snd_vol[ index ] = temp; vreg_ctr[ VREG_C_SND_VOL ] = getmean3( hist_snd_vol ); break; case( ADC_SEL_BATT_TEMP ): hist_bt_temp[ index ] = ADCRH; raw_adc_temperature = getmean3( hist_tune ); renge_task_immed_add( PM_bt_temp_update ); break; case( ADC_SEL_BATT_DET ): // vreg_ctr[ VREG_C_DBG_BATT_DET ] = ADCRH; break; } // もっとまともな書き方がありそうだ // if( ADS == ADC_SEL_BATT_DET ){ if( ADS != ADC_SEL_BATT_TEMP ){ // 電池判別は電源投入の一回のみ ADS += 1; // 次のチャンネル }else{ ADCEN = 0; // 止めてしまう adc_updated = 1; index = ( index == 2 )? 0: ( index + 1 ); } } /* ======================================================== tsk_adcと競合することを考慮していません。 ======================================================== */ u8 get_adc( u8 ch ){ u8 temp; ADMK = 1; ADIF = 0; ADCEN = 1; ADCS = 0; ADM = 0b00100011; // セレクトモード、章圧、fCLK/6 ///ここから ADPC = 0x06; // ADCポートのセレクト ADS = ch; ADCS = 1; // AD開始。 /// ここまでに、1us以上開ける ADMK = 0; while( ADIF == 0 ){;} temp = ADCRH; ADCEN = 0; return( temp ); }