gt: 		val = 0x800000 | addr | cmd | data;
context: package jbe.kfl;
  
  /**
  *	system functions and constants.
  *	Version for BB KFL (clock frequ)!
  */
  
  public class JopSys {
  
  	static int byteAvail;
  	static int triacVal;
  	static int impCnt;
  	/**
  	 * Simulate BB IO for benchmark.
  	 */
  	static int rd(int addr) {
  		if (addr==IO_CNT) {
  			return Native.rd(Const.IO_CNT);
  		} else if (addr==Msg.IO_STATUS && byteAvail>0) {
  			// simulate a byte in rs485 uart
  			return 32;
  		} else if (addr==Msg.IO_RS485) {
  			if (byteAvail>0) {
  				--byteAvail;
  				return buf[byteAvail];
  			}
  		} else if (addr==BBSys.IO_TRIAC) {
  			// all Us are ok;
  			return BBSys.MSK_U;
  		} else if (addr==BBSys.IO_IADC) {
  			if (triacVal!=0) {
  				return Triac.MIN_STROM + 
  					(Triac.MIN_STROM<<10) + 
  					(Triac.MIN_STROM<<20); 
  			} else {
  				return 0;
  			}
  		} else if (addr==BBSys.IO_SENSOR) {
  			int sens = 0;
  			if (triacVal!=0) {
  				if ((cnt&0x03)==1) {
  					sens |= BBSys.BIT_SENSI;
  					if (Mast.state==BBSys.MS_UP) {
  						++impCnt;
  					} else if (Mast.state==BBSys.MS_DOWN) {
  						--impCnt;
  					}
  				}
  			}
  			if (impCnt<4) sens |= BBSys.BIT_SENSU;
  			if (impCnt>20) sens |= BBSys.BIT_SENSO;
  			return sens;
  		}
  		return 0;
  	}
  	static void wr(int val, int addr){
  		if (addr==BBSys.IO_WD) {
  			Native.wr(val, Const.IO_WD);
  		} else if (addr==BBSys.IO_TRIAC) {
  			triacVal = val;
  			Native.wr(val, Const.IO_LED);
  		}
  	}
  	public static final int IO_CNT = 0; // is 0 in actual hardware
  
  	public static final int INTERVAL = 73728/2;	// five ms
  	public static final int MS = 7373;
  
  	static int min, max;
  	static boolean first;
  	static int simState;
  	static int[] buf;
  
  	/**
  	 * Initialization for benchmarking KFL Mast loop.
  	 */
  	public static void initBench() {
  		
  		min = 1000000000;
  		max = 0;
  		first = true;
  		simState = 0;
  		impCnt = 0;
  		buf = new int[4];
  		byteAvail = 0;
  /*
  		util.Dbg.initSerWait();
  		util.Dbg.wr("Benchmark started\n");
  */
  	}
  	
  	static int cnt;
  	static int timestamp;
  	static int startTime;
  	/**
  	 * Called once per loop instead of waitForNextInterval.
  	 */
  	public static void benchLoop() {
  		
  /*
  		if (first) {
  			first = false;
  			timestamp = Native.rd(Const.IO_CNT);
  			startTime = timestamp;
  		} else {
  			int time = Native.rd(Const.IO_CNT);
  			int diff = time-timestamp;
  			if (diff > max) max = diff;
  			if (diff < min) min = diff;
  			timestamp = time;
  		}
  */
  		++cnt;
  		if ((cnt&0x07) == 0) {
  			masterCmd();
  		} else if ((cnt&0x03)==3) {
  			masterPoll();
  		}
  
  //	Don't wait for the next interval.
  //	We want to measure performance of workload in
  //	execution time.
  //
  //		Timer.waitForNextInterval();
  /*
  
  		if (cnt==10000) {
  			endBench();
  		}
  */
  	}
  	
  /*
  	static void endBench() {
  		startTime = Native.rd(Const.IO_CNT)-startTime;
  		util.Dbg.wr("\nBenchmark finished in ");
  		util.Dbg.intVal(startTime);
  		util.Dbg.wr("cycles\n");
  		dbgOut();
  //		for (;;);
  	}
  */
  	
  	// invoked every 8 cycles
  	
  	static void masterPoll() {
  		simMsg(BBSys.CMD_STATUS, 0);
  	}
  	
  	static int waitTime;
  	
  	static void masterCmd() {
  		
  		if (simState==0) {
  			simMsg(BBSys.CMD_SET_STATE, BBSys.MS_RDY);
  			simState = 1;
  		} else if (simState==1) {
  			simMsg(BBSys.CMD_SET_MAXCNT, 1000);
  			simState = 2;
  			waitTime = 2;
  		} else if (simState==2) {
  			if (Mast.state==BBSys.MS_RDY) {
  				if (waitTime==0) {
  					simMsg(BBSys.MS_UP, 0);
  // util.Dbg.wr("up ");
  					waitTime = 4;	// minimum 20 cycles (4*8)
  					simState = 3;		
  				} else {
  					--waitTime;
  				}
  			}
  		} else if (simState==3) {
  			if (Mast.state==BBSys.MS_RDY) {
  				if (waitTime==0) {
  					simMsg(BBSys.MS_DOWN, 0);
  // util.Dbg.wr("down ");
  					waitTime = 4;	// minimum 20 cycles (4*8)
  					simState = 2;		
  				} else {
  					--waitTime;
  				}
  			}
  		}
  	}
  
  	static void dbgOut() {
  
  /*
  		util.Dbg.intVal(Mast.state);
  		util.Dbg.intVal(Mast.lastErr);
  		util.Dbg.intVal(cnt);
  		util.Dbg.intVal(min);
  		util.Dbg.intVal(max);
  		util.Dbg.wr('\n');
  */
  		
  	}
  
  	private static final int ADDR_MSK = 0x7c0000;
  	private static final int CMD_MSK  = 0x03f000;
  	private static final int DATA_MSK = 0x000fff;
  	
  	static void simMsg(int cmd, int data) {
  
  		int val;
  		int i;
  
  		int addr = 1;
  		addr <<= 18;
  		cmd <<= 12;
  		data &= DATA_MSK;
  