// プログラム名	: Xport実験
// ファイル名	: xport01.c

#include 
#include 
#include 

//*******************************************************************************
// 各種定義
//*******************************************************************************

const prog_char vtbl[] PROGMEM =	{
	0x00,0x05,0x0A,0x0F,0x14,0x1A,0x1F,0x24,0x29,0x2E,		//0.0~0.9V
	0x33,0x38,0x3D,0x42,0x47,0x4D,0x52,0x57,0x5C,0x61,		//1.0~1.9V
	0x66,0x6B,0x70,0x75,0x7A,0x80,0x85,0x8A,0x8F,0x94,		//2.0~2.9V
	0x99,0x9E,0xA3,0xA8,0xAD,0xB3,0xB8,0xBD,0xC2,0xC7,		//3.0~3.9V
	0xCC,0xD1,0xD6,0xDB,0xE0,0xE6,0xEB,0xF0,0xF5,0xFA,		//4.0~4.9V
	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF		//5.0V
	};													

#define	B_IOVF0		0					//タイマ0オーバーフロー
#define	B_LED0		0					//LED0
#define	B_LED1		1					//LED1
#define	B_LED2		2					//LED2
#define	ASKII_CR	0x0D				//アスキーコードCR
#define	ASKII_LF	0x0A				//アスキーコードLF

#define get_vtbl(n)	pgm_read_byte(vtbl + n)

unsigned char		STACK;
unsigned char		R_FLAG1;			// 割込状態他
unsigned int		R_TMR0;				// タイマ0カウント領域(10mS単位)

//*******************************************************************************
// 割込みルーチン
//*******************************************************************************
//***************************************
// タイマ0 
//***************************************

ISR (TIMER0_OVF_vect)
{
//----  ステータスレジスタの内容を退避 -----------

	STACK	=	SREG;
	
	R_TMR0--;

	if	(R_TMR0==0){
		R_FLAG1	|=	(1<<B_IOVF0);		//タイマ0オーバーフローフラグセット
		}
	else{
		TCNT0	=	0xB2;				//割込時間10mS
	}

//----  ステータスレジスタの内容を復帰 -----------

	SREG	=	STACK;
}

//*******************************************************************************
// 関数
//*******************************************************************************
//***************************************
// タイマ0 
//***************************************

void STMR0(void)
{

//---- タイマ割込許可 -----------

	TIMSK0	|=	(1<<TOIE0);

//---- タイマ0 フラグクリア----

	R_FLAG1	&=	~(1<<B_IOVF0);			//タイマ0オーバーフローフラグクリア

//----  カウント値 セット -----------

	TCNT0	=	0xB2;					//割込時間10mS

//---- カウンタ 起動 ----

	TCCR0B	=	0x05;					//プリスケーラ1024

//---- タイマ0カウント完了判定 ----

	while ((R_FLAG1 & (1<<B_IOVF0))==0);
	
//----  カウンタ 停止 -----------

	TCCR0B	=	0x00;

//---- タイマ割込禁止 -----------

	TIMSK0	&=	~(1<<TOIE0);

}

//***************************************
// USART 送信
//***************************************

void UARTS(unsigned char r_temp)
{
	while ((UCSR0A & (1<<UDRE0))==0);

	UDR0	=	r_temp;
}

//*****************************
// AD変換ルーチン
//*****************************

unsigned char ADCV(void)
{
	ADCSRA	|=	((1<<ADIF)+(1<<ADSC));	//A-D変換完了割込み要求フラグクリア+変換開始

//---- A/D変換完了判定 ----

	while((ADCSRA & (1<<ADIF))==0);

	return(ADCH);						//AD変換値を返す
}

//*****************************
// 電圧値表示
//*****************************

void DSPV(unsigned char vdat)
{
unsigned char vdisp1;
unsigned char vdisp10;
unsigned char i;

	vdisp1  = 0x00;
	vdisp10 = 0x00;

//---- 比較用 電圧値テーブル ----------------------

	for	(i=0 ; i<50 ; i++){

		if	(vdat >= get_vtbl(i)){		//比較用電圧値との比較
			if	(vdisp1	==0x09){
				vdisp1 = 0x00;
				vdisp10++;
				}
			else
				vdisp1++;
			}
		else {
			
//---- 1V桁カウント値をアスキー文字に変換 ----

			vdisp10	+=	0x30;
			UARTS(vdisp10);

//---- ドット(.)表示 ----

			UARTS('.');

//---- 0.1V桁カウント値をアスキー文字に変換 ----

			vdisp1	+=	0x30;
			UARTS(vdisp1);

//---- CR送付 ----

			UARTS(ASKII_CR);

			break;
		}
	}
}

//*******************************************************************************
// メインルーチン(MAIN)
//*******************************************************************************
int main(void)
{
unsigned char vdat;

//---- 全割込み禁止----

	cli();

//---- PORT 設定 ----

	DDRB	=	0b11111111;
	PORTB	=	0b00000111;
	
	DDRC	=	0b11111110;
	PORTC	=	0b00000000;
	
	DDRD	=	0b11111111;
	PORTD	=	0b00000000;	

//---- USART 初期化 ----

	UBRR0L	=	51;							//ボーレート2400
	UBRR0H	=	0;
	UCSR0C	|=	((1<<UCSZ01)+(1<<UCSZ00));	//ノンパリティ/1ストップビット/8ビット長
	UCSR0B	|=	((1<<RXEN0)+(1<<TXEN0));	//送受信イネーブル
	
//---- AD変換(初期値)設定 ----

	ADMUX	=	0x60;					//Aref選択/変換結果左詰/ADC0選択
	ADCSRA	=	0x86;					//変換許可および変換プリスケーラ設定
	ADCSRB	=	0x00;					//設定項目なし

//---- ユーザフラグ初期化 ----

	R_FLAG1	=	0x00;

//---- 全割込み許可----

	sei();

	while(1){

//---- AD変換 開始 ----

		vdat = ADCV();

//----  電圧表示 ----------------------

		DSPV(vdat);

//---- タイマ(1秒) ----

		R_TMR0 = 0x64;
		STMR0();

//---- LED ON/OFFを切り替え -----------

		PINB	=	(1<<B_LED0);	

	}

}