/* ======================================================== 藤田@開技 nintendo '09 Apr ======================================================== */ #include "incs.h" #include "adc.h" #include "pm.h" #include "led.h" bit adc_updated; #define INTERVAL_TSK_ADC 16 /* ======================================================== ADC設定と、開始 以下のピンは主にここで操作・監視されます。 ・BT_TEMP,_P ・ADIN1 ・VOL 関係ありそうですが別のところで管理しています ・PM_BT_DET,_P PM_init ・8tics毎に呼ばれ、3チャンネル分取り込むとADCを停止します。  タスク起動時、レジスタには前回の取り込み値が入っています。 ======================================================== */ void tsk_adc( ) { static u8 task_interval = 0; static u8 old_tune; static u8 sndvol_codec; static u8 bt_temp_old; if( ( system_status.pwr_state == ON ) || ( system_status.pwr_state == SLEEP ) ) { if( adc_updated ) { if( task_interval != 0 ) { task_interval -= 1; return; } else { task_interval = ( INTERVAL_TSK_ADC / SYS_INTERVAL_TICK ); } #if 0 tune ・フ変化では割り込みを入れない // 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; } } #endif // Volume { static u8 vol_old; static u8 class_old; u8 class; static u8 direction = 0; // 0:上り方向 u8 comp; // 補正値 if( abs( vol_old - vreg_ctr[VREG_C_SND_VOL] ) > 3 ) { vol_old = vreg_ctr[VREG_C_SND_VOL]; vreg_twl[ REG_TWL_INT_ADRS_VOL ] = vol_old / ( 256 / 32 ); class = vreg_ctr[VREG_C_SND_VOL] / ( 256 / 8 ); if( class != class_old ) { class_old = class; set_irq( VREG_C_IRQ0, REG_BIT_VR_SNDVOL_CHANGE ); } } } // codecに伝える if( vreg_ctr[VREG_C_SND_VOL] != sndvol_codec ) { sndvol_codec = ( vreg_ctr[VREG_C_SND_VOL] / 2 + vreg_ctr[VREG_C_SND_VOL] / 4 ) / 2; #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; // TUNE_LED ここかよ! switch ( vreg_ctr[VREG_C_LED_TUNE] ) { case ( 1 ): // 点灯 LED_duty_TUNE = vreg_ctr[VREG_C_LED_BRIGHT]; break; case ( 2 ): // LED_duty_TUNE = LED_BRIGHT_MAX - vreg_ctr[VREG_C_TUNE]; break; default: // 消灯 LED_duty_TUNE = 0; break; } } } /* ========================================================  過去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 ): hist_snd_vol[index] = ADCRH; 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 ); }