/* System	: 二足歩行ロボット(walk)
* File		: vb_detect.c
* function	: 電池電圧入力検知 (BD3,4)
* Version	: 1.0
* Date		: 2019/5/7
* CPU		: RL78/G12 ROM:16KB RAM:1.5KB fCLK:24MHz
* IDE		: CS+ for CC V6.01.00 [01 Dec 2017]
* Programmer	: Hajime Sugiyama
* Note		: */

/* 特殊機能レジスタ（SFR）へのアクセス記述を使用する(RL78/R5F1026A) */
#include "iodefine.h"
#include "vb_detect.h"

#pragma interrupt adc_interrupt(vect=INTAD)

/* 電池電圧判定値（分圧抵抗　7.5kΩ（VB側）：2.2kΩ（GND側） */
#define VB_UPPER_LIMIT	0x03E0			/* モータ電圧上限 6.01V */
#define VB_LOWER_LIMIT	0x02D0			/* モータ電圧下限 4.5V */

struct _F_VB_ALARM f_vb_alarm = {0,0,0,0};	/* 電池電圧異常警報 */
static unsigned char u8_fadc = 0U;		/* A/D変換完了フラグ */

/* 電池電圧入力検知初期化処理ユニット(BD3,4) */
void init_vb_detect(void){
	/* 電池電圧A/Dコンバータ入力初期化 */
	ADCEN = 1U;				/* A/Dコンバータにクロック供給 */
	ADPC = 0x02;				/* ANI0/P20 をアナログ入力に設定 */
						/* P21-P23 をデジタル入出力に設定 */
	ADMK = 1U;  				/* disable INTAD interrupt */
	ADIF = 0U;  				/* clear INTAD interrupt flag */
	/* Set INTAD low priority */
	ADPR1 = 1U;
	ADPR0 = 1U;
	PM2_bit.no0 = 1U;			/* ANI0/P20 ポートを入力モードに設定 */
	ADM0 = 0x28;				/* 10ビット変換時間：3.96μs */
	ADM1 = 0x20;				/* ソフトウェアトリガ・ワンショット変換モード */
	ADM2 = 0x80;				/* 内部基準電圧(1.45V)使用 */
	ADUL = 0xFF;				/* A/D INT 上限電圧(上位8ビット) */
	ADLL = 0x00;				/* A/D INT 下限電圧(上位8ビット) */
	ADS = 0x00;				/* 入力チャネル ANI0 */
}

/* A/D電圧コンパレータ動作許可処理ユニット(BD3,4) */
void enable_vbad(void){
	ADCE = 1U;				/* enable AD comparator */
	/* ADM2のADREFP1, ADREFP0 = 1, 0に変更する場合120クロック(24MHz)以上のウェイトが必要 */
}

/* 電池電圧入力検知処理ユニット(BD3,4) */
void vb_detect(void){
	auto unsigned int u16_vb_temp = 0U;	/* バッファ */
	static unsigned int u16_vb_average = 0U;/* 平均値 */
	static unsigned int u16_vb_sum = 0U;	/* 累積値 */
	static unsigned int u16_vb_max = 0U;	/* 最大値 */
	static unsigned int u16_vb_min = 0xFFFF;/* 最小値 */
	static unsigned char u8_vb_count = 0U;	/* 取得データ数カウンタ */
	if(u8_fadc == 1U){			/* A/D変換完了？ */
		u8_fadc = 0U;

		/* A/D変換停止 */
		ADCS = 0U;			/* disable AD conversion */
		ADMK = 1U;			/* disable INTAD interrupt */
		ADIF = 0U;			/* clear INTAD interrupt flag */

		u16_vb_temp = ADCR >> 6U;	/* A/D変換結果下位10ビットを格納 */
		u16_vb_sum = u16_vb_sum + u16_vb_temp;	/* A/D値を累積 */
		if(u16_vb_temp > u16_vb_max){	/* 最大値を記憶 */
			u16_vb_max = u16_vb_temp;
		}
		if(u16_vb_temp < u16_vb_min){	/* 最小値を記憶 */
			u16_vb_min = u16_vb_temp;
		}
		if(++u8_vb_count >= 10){	/* 10データ取得？ */
			u8_vb_count = 0U;
			/* 最大値と最小値を除き8データで平均値算出 */
			u16_vb_average = (u16_vb_sum - u16_vb_max - u16_vb_min) >> 3;
			u16_vb_sum = 0U;
			if(u16_vb_average > VB_UPPER_LIMIT){/* 6.0Vを超えれば */
				f_vb_alarm.high = 1U;/* 電池高電圧 */
				f_vb_alarm.abnormal = 1U;/* 電池電圧異常 */
			}else{			/* 6.0V以内であれば */
				f_vb_alarm.high = 0U;/* 電池高電圧クリア */
			}
			if(u16_vb_average < VB_LOWER_LIMIT){/* 4.5V未満であれば */
				f_vb_alarm.low = 1U;/* 電池低電圧 */
				f_vb_alarm.abnormal = 1U;/* 電池電圧異常 */
			}else{			/* 4.5V以上であれば */
				f_vb_alarm.low = 0U;/* 電池低電圧クリア */
			}
		}
	}

	/* A/D変換開始 */
	ADIF = 0U;  /* clear INTAD interrupt flag */
	ADMK = 0U;  /* enable INTAD interrupt */
	ADCS = 1U;  /* enable AD conversion */
}

static void adc_interrupt(void){		/* A/D変換割込処理ユニット(BD3,4) */
	u8_fadc = 1U;				/* A/D変換完了フラグセット */
}
