//
/* ----------------------------------------------------------------------------------------------
    dram.java	DRAM									ver. 1.00 (JDK 1.02)
    														ueyama@infonet.co.jp  1998.10.10
---------------------------------------------------------------------------------------------- */

import java.applet.Applet;
import java.awt.*;
import java.util.*;

public class dram extends Applet implements Runnable
{
	int			Charge=96;									// コンデンサの電荷。色の変化で表す。
	int			Cell[][]=new int[4][4];						// 1:bit select  2:word select  3:select cell
	int			Data[][]=new int[4][4];						// セルのデータ 0 or 1
	int			Ofsx=40, Ofsy=26;							// セルを表示するオフセット
	int			Sx=0, Sy=0;									// mouse で Select された cell の座標
	boolean		Sel=false;									// true: mouse で Select されている(データ表示のため)
	boolean		Write=false;								// true: データ変更中
	Image		Gif;
	Image		buf;
	int			Wait=128;
	Random		r=new Random();
	Thread		th=null;
	Graphics	ong,offg;
	Button		bt_fast,bt_slow,bt_clear,bt_write;

	public void start()
	{
		if(th==null)
		{
			th=new Thread(this);
			th.start();
		}
	}
	
	public void cellClear()
	{
		int i,j;
		for(i=0;i<4;i++) for(j=0;j<4;j++) Cell[i][j]=0;
	}
	
	public void init()
	{
		int i,j;
		
		MediaTracker mt=new MediaTracker(this);
		Gif=getImage(getCodeBase(),"dram.gif");
		mt.addImage(Gif, 0);
		try
		{
			mt.waitForID(0);
		}
		catch(InterruptedException e){};
		
		setBackground(new Color(247,255,247));
		buf=createImage(size().width,size().height);
		setLayout(new BorderLayout());
		Panel p=new Panel();
		p.setLayout(new FlowLayout());
		p.add(bt_slow=new Button("<<"));
		p.add(bt_fast=new Button(">>"));
		p.add(bt_write=new Button("WRITE"));
		p.add(bt_clear=new Button("CLEAR"));
		add("South",p);
		cellClear();
		for(i=0;i<4;i++) for(j=0;j<4;j++) Data[i][j]=r.nextInt() & 1;
	}
	
	public void dsp_arrow(int x, int y, Graphics g)
	{
		for(int m=0,n=8; m<5; m++,n-=2)
		{
			g.fillRect(x+m,  y+m*2,2,2);
			g.fillRect(x+m+n,y+m*2,2,2);
		}
	}
	
	public void dsp_g(int x, int y, int n, Graphics g)				// セル・数字の表示
	{
		Graphics	gx=g.create();
		gx.clipRect(x,y,(n<4)?80:16,(n<4)?80:18);
		gx.clearRect(x,y,(n<4)?80:16,(n<4)?80:18);
		gx.drawImage(Gif,x-((n<4)?80*n:320+(n-4)*16),y,this);
		gx.dispose();
	}
	
	public void dsp_c(int x, int y, int n, Graphics g)				// ビット線・ワード線の表示
	{
		Graphics	gx=g.create();
		gx.clipRect(x,y,(n==0)?11:39,(n==0)?38:11);
		gx.drawImage(Gif,x-((n==0)?320:332),y-18,this);
		gx.dispose();
	}
	
	public void paint(Graphics g)
	{
		int a,i,j,k,m,n,x0,y0;
		String s,c;
		
		g.setColor(new Color(247,255,247));
		g.fillRect(0,0,360,Ofsy);
		g.fillRect(0,320+Ofsy,360,64);
		g.fillRect(0,Ofsy,Ofsx,320);
		
		g.setColor(new Color(229,Charge,252));
		for(i=0;i<4;i++)											// memory cell を描く
		{
			for(j=0;j<4;j++)
			{
				x0=i*80+Ofsx; y0=j*80+Ofsy;
				dsp_g(x0, y0, Cell[i][j], g);
				if(Data[i][j]==1) g.fillRect(x0+49,y0+48,20,6);		// Charge の表示
			}
		}
		for(i=0;i<4;i++)											// bit線 address
		{
			a=(Sx==i && Sel)?1:0;
			s=Integer.toString(i,2);
			if(s.length()==1) s="0"+s;
			for(j=0;j<2;j++)
			{
				k=Integer.parseInt(s.substring(j,j+1));
				dsp_g(i*80+j*16+Ofsx, 2, 4+a*2+k, g);
			}
		}
		for(i=0;i<4;i++)											// word線 address
		{
			a=(Sy==i && Sel)?1:0;
			s=Integer.toString(i,2);
			if(s.length()==1) s="0"+s;
			for(j=0;j<2;j++)
			{
				k=Integer.parseInt(s.substring(j,j+1));
				dsp_g(Ofsx-40+j*16, i*80+15, 4+a*2+k, g);
			}
		}
		if(Sel)														// data 矢印線
		{
			g.setColor(new Color(229,96,252));
			for(i=0;i<4;i++)
			{
				if(Data[i][Sy]==1)
				{
					for(j=Sy;j<4;j++)
					{
						x0=i*80+Ofsx; y0=j*80+Ofsy;
						if(j==Sy)									// ON の Cell
						{
							g.fillRect(x0+21,y0+40,25,2);			// 横線
							g.drawArc(x0+11,y0+40,19,19,90,90);		// 円弧
							g.drawArc(x0+12,y0+41,17,17,90,90);
							if(j==3)								// 一番下なら矢印を描く
							{
								g.fillRect(x0+11,y0+49,2,21);
								dsp_arrow(x0+7,y0+62,g);
							}
							else g.fillRect(x0+11,y0+49,2,31);		// 線のみ
						}
						else if(j==3)								// いちばん下の Cell. 矢印を描く
						{
							g.fillRect(x0+11,y0,2,70);
							dsp_arrow(x0+7,y0+62,g);
						}
						else g.fillRect(x0+11,y0,2,80);				// 途中の Cell. 線のみ
					}
				}
			}
			g.setColor(new Color(224,0,80));
			x0=Sx*80+Ofsx; y0=3*80+Ofsy;
			dsp_arrow(x0-1,y0+70,g);
			s=Integer.toString(Sx*4+Sy,2);
			while(s.length()<4) s="0"+s;
			g.setColor(new Color(102,102,102));
			g.setFont(new Font("Helvetica",Font.BOLD,15));
			g.drawString("Address = "+s+";  Data = "+Data[Sx][Sy],92,390);
			
			dsp_g(x0-6, y0+86, 6+Data[Sx][Sy], g);					// 出力データの表示
			dsp_c((Sx-1)*80+Ofsx+69,Sy*80+Ofsy+7,0,g);				// 「ビット線」の表示
			dsp_c(Sx*80+Ofsx+40,Sy*80+Ofsy+6,1,g);					// 「ワード線」の表示
		}
	}

	public void run()
	{
		while(th!=null)
		{
			offg=buf.getGraphics();
			paint(offg);
			ong=getGraphics();
			ong.drawImage(buf,0,0,this);
			try
			{
				Thread.sleep((Sel)? 256:Wait);
			}
			catch (InterruptedException e){}
			if(!Sel) Charge+=4;
			if(Charge>208) Charge=96;
		}
	}
	
	public boolean mouseDown(Event e, int mx, int my)
	{
		int i,j;
		
		i=mx-Ofsx; j=my-Ofsy;
		if(i>0 && i<4*80 && j>0 && j<4*80)
		{
			Sx=i/80; Sy=j/80;
			if(Write)
			{
				Data[Sx][Sy]=(Data[Sx][Sy]==0)?1:0;
				Write=false;
				bt_write.enable();
			}
			else
			{
				cellClear();
				for(i=0;i<4;i++) Cell[i][Sy]=1;
				for(j=0;j<4;j++) Cell[Sx][j]=2;
				Cell[Sx][Sy]=3;
				Sel=true;
				bt_write.disable();
			}
		}
		return true;
	}
	
	public boolean action(Event e, Object o)
	{
		if(e.target==bt_fast)
		{
			if(Wait>64)	{Wait/=2; bt_slow.enable();}
			else	bt_fast.disable();
		}
		else if(e.target==bt_slow)
		{
			if(Wait<1024) {Wait*=2; bt_fast.enable();}
			else bt_slow.disable();
		}
		else if(e.target==bt_clear)
		{
			cellClear();
			Sel=false;
			bt_write.enable();
		}
		else if(e.target==bt_write && !Sel)
		{
			Write=true;
			bt_write.disable();
		}
		return true;
	}
	
	public void stop()
	{
		if(th==null)
		{
			th.stop();
		}
	}
}
//
戻る