/*
 * A/D変換を行うルーチン
 * 
 * @author fenrir (M.Naruoka)
 * @since 04/06/02
 * @version 1.0
 */
#include "AKI3694.h"
#include <common.h>
#include <util/fifo_num.h>
#include "ad.h"

static num_t buffer_ad[(AD_BUFFER_SIZE + 1) * AD_CH];
fifo_num_t fifo_ad[AD_CH];

/**
 * A/D変換の初期設定をする関数
 * 
 */
void ad_init(){
	
	/* A/D変換後用のFIFOの初期化 */
	int i;
	for(i = 0; i < AD_CH; i++){
		fifo_num_init(&(fifo_ad[i]), &(buffer_ad[(AD_BUFFER_SIZE + 1) * i]), (AD_BUFFER_SIZE + 1));
	}
	
	/* A/D変換停止 */
	AD.ADCSR.BIT.ADST = 0;
	
	/* スキャンモード
	 * 高速変換
	 * 割り込み可
	 * はじめはグループ0のAD0〜AD3を変換
	 * 8チャンネル時はさらにその後グループ1のAD4〜AD7を変換
	 */
  AD.ADCSR.BYTE = 0x5b;  //5
}

/**
 * A/D変換の開始をする関数
 * インターバルタイマの割り込みによって、
 * またグループ0のAD変換終了後に呼び出してもらう。
 * 
 * @see ad_end();
 */
void ad_start(){
	AD.ADCSR.BIT.ADST = 1; /* A/D変換スタート */
}

/**
 * A/D変換の終了後に起動される関数
 * 割り込みで呼び出してもらう
 * 
 * @see int_ad();
 */
void ad_end(){

	AD.ADCSR.BYTE &= 0x5f;  /* 終了フラグをクリア & AD変換を完全停止*/

#if AD_CH > 4
	/* どっちのグループを変換していたか */
	if((AD.ADCSR.BYTE & 0x04) == 0){
#endif

		/* グループ0(AD0〜AD3)を変換していた */
		
#if DEBUG > 2
		fifo_num_write(&fifo_ad[0], 230);
		fifo_num_write(&fifo_ad[1], 340);
		fifo_num_write(&fifo_ad[2], 560);
		fifo_num_write(&fifo_ad[3], 780);
#else
		/*fifo_num_write(&fifo_ad[0], ((AD.ADDRA_H << 8) | AD.ADDRA_L)); 旧方式 */
    fifo_num_write(&fifo_ad[0], AD.ADDRA.u16);
		fifo_num_write(&fifo_ad[1], AD.ADDRB.u16);
		fifo_num_write(&fifo_ad[2], AD.ADDRC.u16);
		fifo_num_write(&fifo_ad[3], AD.ADDRD.u16);
#endif

#if AD_CH > 4
		AD.ADCSR.BYTE |= 0x04; /* グループ1に切り替えて */
		ad_start(); /* 再度AD変換 */
	}else{
		
		/* グループ1(AD4〜AD7)を変換していた */

#if DEBUG > 2
		fifo_num_write(&fifo_ad[4], 230);
		fifo_num_write(&fifo_ad[5], 340);
		fifo_num_write(&fifo_ad[6], 560);
		fifo_num_write(&fifo_ad[7], 780);
#else
		fifo_num_write(&fifo_ad[4], AD.ADDRA.u16);
		fifo_num_write(&fifo_ad[5], AD.ADDRB.u16);
		fifo_num_write(&fifo_ad[6], AD.ADDRC.u16);
		fifo_num_write(&fifo_ad[7], AD.ADDRD.u16);
#endif
		
		AD.ADCSR.BYTE &= ~(0x04); /* グループ0に切り替え */
	}
#endif
}

/**
 * A/D変換の終了によって呼びだされる割り込み関数
 * 
 * @see ad_end
 */
#pragma interrupt
void int_ad(){
	if(AD.ADCSR.BIT.ADF){AD.ADCSR.BIT.ADF = 0;}
	ad_end();
}
