/************************************/
/*port2 LED A 0-4*/
/*port1 LED k 0-7*/
/*出力は反転されるので注意*/
/*LED側でNOTが入っている*/
/*60fpsは出そう(16ms)*/
/************************************/
#include <3048f.h>

/************************************/
/*led配列のBuffer*/
int buff[7][5];

const int	buff1[7][5]={
	{1,0,1,0,1},
	{0,1,0,1,0},
	{1,0,1,0,1},
	{0,1,0,1,0},
	{1,0,1,0,1},
	{0,1,0,1,0},
	{1,0,1,0,1}
};

const int	buff0[7][5]={
	{0,1,0,1,0},
	{1,0,1,0,1},
	{0,1,0,1,0},
	{1,0,1,0,1},
	{0,1,0,1,0},
	{1,0,1,0,1},
	{0,1,0,1,0}
};

void timer_set(void){
	ITU0.TCR.BYTE = 0x23;   /*GRA 2MHz 0010.0011*/
	ITU0.GRA      = 0x07d0; /*GRA 2000に設定 */
	ITU.TSTR.BIT.STR0 = 0;  /*カウント停止状態 */
	return;
}

/* 正確にsec秒はかるところ（実際はsec*1msをやっている）*/
void wait(int sec){
	int j;
	ITU.TSTR.BIT.STR0 = 1;   /*カウント開始 */
    for(j=0;j<sec;j++){
		do{
		}while(ITU0.TSR.BIT.IMFA==0); /*=1で1msです！*/
		ITU0.TSR.BIT.IMFA = 0; /*初期化　*/
	}
	ITU.TSTR.BIT.STR0 = 0; /*カウント終了*/
	return;
}

/*ロギケン*/
const int led[7][20] = {
	{1,1,1,1,1,0,1,0,0,1,0,1,0,0,0,1,1,0,0,0},
	{1,0,0,0,1,0,1,1,1,0,0,1,1,1,1,0,0,1,0,0},
	{1,0,0,0,1,1,0,1,0,0,0,1,0,1,0,0,0,0,0,0},	
	{1,0,0,0,1,0,0,1,1,1,1,0,0,1,0,0,0,0,0,1},	
	{1,0,0,0,1,1,1,1,0,0,1,0,0,1,0,0,0,0,0,1},	
	{1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0},
	{1,1,1,1,1,0,0,0,1,0,0,0,1,0,0,1,1,1,0,0}
};

/*Bufferの初期化*/
void buff_0(int i){
	int x,y;
	for(y=4;y>=i;y--){
		for(x=0;x<7;x++){
			buff[x][y] = 0;
		}
	}
}

void buff_01(int i){
	int x,y;
	for(x=6;x>=i;x--){
		for(y=0;y<5;y++){
			buff[x][y] = 0;
		}
	}
}

/*Bufferにled配列を列単位で代入*/
void buff_change0(int j,int i){ 
	int k;
	for(k=0;k<7;k++){
		buff[k][j]  = led[k][i];
	}
}

void buff_change1(int j,int i,int h){ 
	int k;
	for(k=0;k<5;k++){
		buff[j][k]  = led[i][h+k];
	}
}
/*buffのj列目からi列目を入れる*/
void buff_change2_0(int a,int i){ 
	int k;
	int j;

  for(j=a;j<5;j++){	
		for(k=0;k<7;k++){
				buff[k][j] = led[k][i];
		}
		i++;
	}	
}
void buff_change2(int a,int i){ 
	int k;
	int j;

  for(j=a;j<5;j++){	
		for(k=0;k<7;k++){
			if(j+i>=20){
				buff[k][j] = 0;
			}else{
				buff[k][j] = led[k][i+j];
			}
		}
	}	
}

void buff_dec(int i){
	P1.DR.BIT.B0 = buff[0][i]; 
	P1.DR.BIT.B1 = buff[1][i]; 
	P1.DR.BIT.B2 = buff[2][i]; 
	P1.DR.BIT.B3 = buff[3][i]; 
	P1.DR.BIT.B4 = buff[4][i]; 
	P1.DR.BIT.B5 = buff[5][i]; 
	P1.DR.BIT.B6 = buff[6][i]; 
}	

/*Bufferを表示10ms*/
void buff_show(){
	P2.DR.BIT.B0 = 0;
		buff_dec(0);
		wait(2);
		P2.DR.BIT.B0 = 1;
	P2.DR.BIT.B1 = 0;
		buff_dec(1);
		wait(2);
		P2.DR.BIT.B1 = 1;
	P2.DR.BIT.B2 = 0;
		buff_dec(2);
		wait(2);
		P2.DR.BIT.B2 = 1;
	P2.DR.BIT.B3 = 0;
		buff_dec(3);
		wait(2);
		P2.DR.BIT.B3 = 1;
	P2.DR.BIT.B4 = 0;
		buff_dec(4);
		wait(2);
		P2.DR.BIT.B4 = 1;
}
/*実際に出力*/
void led_dec(int i){
	P1.DR.BIT.B0 = led[0][i]; 
	P1.DR.BIT.B1 = led[1][i]; 
	P1.DR.BIT.B2 = led[2][i]; 
	P1.DR.BIT.B3 = led[3][i]; 
	P1.DR.BIT.B4 = led[4][i]; 
	P1.DR.BIT.B5 = led[5][i]; 
	P1.DR.BIT.B6 = led[6][i]; 
}	

/*ledを実際に表示させる*/
void led_show(int i){
	P2.DR.BIT.B0 = 0;
		led_dec(i);
		wait(2);
		P2.DR.BIT.B0 = 1;
	P2.DR.BIT.B1 = 0;
		led_dec(i+1);
		wait(2);
		P2.DR.BIT.B1 = 1;
	P2.DR.BIT.B2 = 0;
		led_dec(i+2);
		wait(2);
		P2.DR.BIT.B2 = 1;
	P2.DR.BIT.B3 = 0;
		led_dec(i+3);
		wait(2);
		P2.DR.BIT.B3 = 1;
	P2.DR.BIT.B4 = 0;
		led_dec(i+4);
		wait(2);
		P2.DR.BIT.B4 = 1;
}

/***main*****************************/
main(){
	
	int time,i,j,k,x,y;
		
	P2.DDR      = 0xff; /*port2入力 */
	P2.PCR.BYTE = 0x00; /*port2プルアップoff */
	P1.DDR      = 0xff; /*port1出力 */

	P4.DDR = 0x00;        /*port4入力に設定 操作用sw1〜4*/
	P4.PCR.BYTE = 0xff; /*port4プルアップon                   */

	/*タイマー作動*/
	timer_set();
	
	/*初期設定*/
	P1.DR.BYTE=0xff;
	P2.DR.BYTE=0x00;

	while(1){
		if(P4.DR.BIT.B4 == 0){
			/*19=横の長さ-1 5=LEDの横の長さ i=何文字目か(5の倍数で)*/
			for(i=0;i<20;i=i+5){
				for(j=0;j<5;j++){
					for(k=4;k>=j;k--){
						time=0;
						buff_0(j);
						buff_change0(k,i+j);
						
						while(1){
							buff_show();
							time++;
							if(time>10){break;}
						}
					}
				}

				time=0;

				while(1){
					led_show(i);
					time++;
					/*100 10ms=1000ms*/
					if(time>100){break;}
				}
			}
		}
		
		else if(P4.DR.BIT.B5 == 0){
			/*19=横の長さ-1 5=LEDの横の長さ i=何文字目か(5の倍数で)*/
			for(i=0;i<20;i=i+5){
				for(j=0;j<7;j++){
					for(k=6;k>=j;k--){
						time=0;
						buff_01(k);
						buff_change1(k,j,i);

						while(1){
							buff_show();
							time++;
							if(time>10){break;}
						}
					}
				}
					
				time=0;
				while(1){
					led_show(i);
					time++;
					/*100 10ms=1000ms*/
					if(time>100){break;}
				}
			}
		}
		
		else if(P4.DR.BIT.B6 == 0){
			buff_0(0);
			/*19=横の長さ-1 5=LEDの横の長さ i=何文字目か(5の倍数で)*/
			for(k=4;k>0;k--){
				time=0;
				buff_change2_0(k,0);

				while(1){
					buff_show();
					time++;
					if(time>10){break;}
				}
			}
			
			for(i=0;i<20;i++){
				time=0;
				buff_change2(0,i);
				while(1){
					buff_show();
					time++;
					if(time>10){break;}
				}
			}
		}
		else if(P4.DR.BIT.B7 == 0){
			
			for(x=0;x<7;x++){
				for(y=0;y<5;y++){
					buff[x][y] = buff1[x][y];
				}
			}
			
			time=0;
			while(1){
				buff_show();
				time++;
				if(time>10){break;}
			}

			for(x=0;x<7;x++){
				for(y=0;y<5;y++){
					buff[x][y] = buff0[x][y];
				}
			}
			
			time=0;

			while(1){
				buff_show();
				time++;
				if(time>10){break;}
			}
		}
		else{;}
	}
}
