//
/* ----------------------------------------------------------------------------------------------
    counter2.java	カウンタの原理								ver. 1.00 (JDK 1.02)
    															ueyama@infonet.co.jp  2000.03.20
---------------------------------------------------------------------------------------------- */

import java.applet.*;
import java.awt.*;


public class counter2 extends Applet implements Runnable
{
	int			Clk;												// 入力信号(クロック)
	int			X0,X1,X2,X3;										// ゲート出力
	int			Q0,_Q0,Q1,_Q1;										// ラッチ出力
	int			Bx[]={34,34,34,34,129,129,146,146,247,247,4,298};
	int			By[]={4,53,107,154,15,145,60,100,26,134,107,27};
	int			Gx[]={64,64,183,183};
	int			Gy[]={13,117,25,105};
	int			S[]=new int[12];
	int			C[]=new int[12];
	int			G[]=new int[4];
	int			Step=5;
	int			Wait=2048;
	int			Bgc;
	boolean		Run=false;
	Image		Img;
	Graphics	gr;
	Thread		th=null;
	
	public void start()
	{
		if(th==null)
		{
			th=new Thread(this);
			th.start();
		}
	}
	
	public void init()
	{
		String bg=getParameter("BgColor");
		Bgc=Integer.valueOf(bg,16).intValue();
		setBackground(new Color(Bgc));
		MediaTracker mt=new MediaTracker(this);
		Img=getImage(getCodeBase(), getParameter("figure"));
		mt.addImage(Img, 0);
		try
		{
			mt.waitForID(0);
		}
		catch(InterruptedException e){};
		gr=getGraphics();
		clear();
	}
	
	public boolean inside(int x, int a, int b)
	{
		return (x<=Math.max(a,b) && x>=Math.min(a,b)) ? true:false;
	}
	
	public int nand(int a, int b)
	{
		return (a*b==1) ? 0:1;
	}
	
	public int not(int a)
	{
		return (a==1) ? 0:1;
	}
	
	public void clear()
	{
		Clk=0; X0=1; X1=1; X2=1; X3=1; Q0=0; _Q0=1; Q1=0; _Q1=1;
		for(int i=0;i<4;i++) G[i]=1;
		for(int i=0;i<10;i++) C[i]=2;
		C[10]=C[11]=0;
	}
	
	public void dsp_b(int x, int y, int n, int c)					// 図、文字の表示
	{
		Graphics	gx=gr.create();
		int			w=12, h=16, ox=632, oy=0;
		switch(n)
		{
			case  0: w=12; h=16; ox=314; oy=  0;	break;			// 数字 0 or 1
			case  1: w=62; h=46; ox=314; oy= 16;	break;			// NAND gate
			case  2: w=62; h=46; ox=314; oy= 62;	break;			// NAND gate
			case  3: w=26; h=23; ox=314; oy=108;	break;			// FAST ボタン
			case  4: w=26; h=23; ox=314; oy=131;	break;			// SLOW ボタン
			case  5: w=26; h=23; ox=376; oy= 16;	break;			// 入力 ボタン
			case  6: w=26; h=23; ox=376; oy= 39;	break;			// STEP ボタン
			case  7: w=26; h=23; ox=376; oy= 62;	break;			// RUN ボタン
			case  8: w=26; h=23; ox=376; oy= 85;	break;			// STOP ボタン
			case  9: w=28; h= 7; ox=314; oy=154;	break;			// 説明の文字
			case 10: w=49; h=16; ox=392; oy=108;	break;			// "STEP"
			case 11: w=11; h=16; ox=410; oy=  0;	break;			// 数字 1〜6
		}
		gx.clipRect(x,y,w,h);
		gx.clearRect(x,y,w,h);
		gx.drawImage(Img,x-(ox+c*w),y-oy,this);
		gx.dispose();
	}
	
	public void signal_read()
	{
		S[0]=_Q0; S[1]=Clk; S[2]=Clk; S[3]=Q0; S[4]=X0; S[5]=X1;
		S[6]=_Q0; S[7]=Q0; S[8]=Q0; S[9]=_Q0; S[10]=Clk; S[11]=Q0;
	}
	
	public void paint(Graphics g)
	{
		int i;
		g.clearRect(0,0,size().width,size().height);
		g.drawImage(Img,0,0,this);
		signal_read();
		for(i=0;i< 2;i++) dsp_b(Gx[i],Gy[i],(Step==1 || Step==2)?2:1,0);	// NAND gate の表示
		for(   ;i< 4;i++) dsp_b(Gx[i],Gy[i],(Step==3 || Step==4)?2:1,0);
		for(i=0;i<12;i++) dsp_b(Bx[i],By[i],0,S[i]+C[i]);					// 信号の表示
		dsp_b(164,197,(Step>4)?5:6,0); dsp_b(163,223,9,(Step>4)?0:1);	// Clock ボタン
		dsp_b(198,197,(Run)?8:7,0); dsp_b(197,223,9,(Run)?5:2);			// RUN ボタン
		dsp_b(232,197,4,0); dsp_b(231,223,9,3);							// SLOW ボタン
		dsp_b(266,197,3,(Wait==256)?2:0); dsp_b(265,223,9,4);			// FAST ボタン
		if(Step<5)														// STEP 数
		{
			dsp_b(45,200,10,0); dsp_b(100,200,11,Step);
		}
	}
	
	public void dsp_status()
	{
		int i=0;
		switch(Step)
		{
			case 0:	Clk=not(Clk); C[1]=C[2]=6;	break;
			case 1: for(i=0;i<4;i++) C[i]=4;
					G[0]=G[1]=2;				break;
			case 2: X0=nand(Clk,_Q0); X1=nand(Clk,Q0);
					for(i=0;i<4;i++) C[i]=2;
					for(i=0;i<2;i++) C[i+4]=6;	break;
			case 3: for(i=0;i<4;i++) C[i+4]=4;
					G[0]=G[1]=1; G[2]=G[3]=2;	break;
			case 4: Q0=(X0==0)?1:0; _Q0=not(Q0);
					Clk=not(Clk);
					X0=nand(Clk,_Q0); X1=nand(Clk,Q0);
					for(i=0;i<4;i++) C[i+4]=2;
					for(i=0;i<2;i++) C[i+8]=6;	break;
			case 5: for(i=0;i<2;i++) C[i+8]=2;
					G[2]=G[3]=1;
					gr.setColor(new Color(Bgc));
					gr.fillRect(45,200,66,16);
					dsp_b(164,197,5,0); dsp_b(163,223,9,0);	break;
		}
		signal_read();
		for(i=0;i<12;i++) dsp_b(Bx[i],By[i],0,S[i]+C[i]);
		for(i=0;i<4;i++) dsp_b(Gx[i],Gy[i],G[i],0);
		if(Step<5)
		{
			dsp_b(45,200,10,0); dsp_b(100,200,11,Step);
		}
	}
	
	public void run()
	{
		while(th!=null)
		{
			if(Run && Step<6)
			{
				dsp_status();
				Step++;
			}
			try
			{
				th.sleep(Wait);
			}
			catch (InterruptedException e){}
		}
	}
	
	public boolean mouseDown(Event e, int mx, int my)
	{
		int m=(mx-164)/30, n=(mx-164)%30;
		if(my>197 && inside(n,0,26))
		{
			switch (m)
			{
				case 0: if(Run && Step>4)
						{
							Step=0; dsp_b(164,197,5,1);
						}
						if(!Run)
						{
							if(Step>4) Step=0;
							else Step++;
							dsp_status();
							dsp_b(164,197,(Step==0)?5:6,1);
						}
						break;
				case 1: Run=!Run; dsp_b(198,197,(Run)?8:7,1);	break;
				case 2: Wait*=2; dsp_b(232,197,4,1);			break;
				case 3: if(Wait>256)
						{
							Wait/=2; dsp_b(266,197,3,1);
						}
			}
		}
		return true;
	}
	
	public boolean mouseUp(Event e, int mx, int my)
	{
		int m=(mx-164)/30, n=(mx-164)%30;
		if(my>197 && inside(n,0,26))
		{
			switch (m)
			{
				case 0: if(Step==5) dsp_b(164,197,5,0);
						else		dsp_b(164,197,6,(Run)?2:0);
						dsp_b(163,223,9,(Step>4)?0:1);			break;
				case 1: dsp_b(198,197,(Run)?8:7,0); dsp_b(197,223,9,(Run)?5:2);
						dsp_b(164,197,(Step==5)?5:6,0);			break;
				case 2: dsp_b(232,197,4,0); dsp_b(266,197,3,0); break;
				case 3: dsp_b(266,197,3,(Wait==256)?2:0);		break;
			}
		}
		return true;
	}
	
	public void stop()
	{
		if(th!=null)
		{
			th.stop();
			th=null;
		}
	}
}
//
戻る