/**
 * Instances of this class are system registers of PICs.
 * <BR>You can read the source of this class <A HREF="./SystemRegisters.java.html"> here</A>.
 */
public class SystemRegisters {

// Public constants for both Banks
	/**
	 * Address of PCL system register.
	 */
	public static final int PCL = 2;
	/**
	 * Address of STATUS system register.
	 */
	public static final int STATUS = 3;
	/**
	 * Address of FSR system register.
	 */
	public static final int FSR = 4;
	/**
	 * Address of PCLATH system register.
	 */
	public static final int PCLATH = 10;
	/**
	 * Address of INTCON system register.
	 */
	public static final int INTCON = 11;

// Public constants for Bank0
	/**
	 * Address of TMR0 system register.
	 */
	public static final int TMR0 = 1;
	/**
	 * Address of PORTA system register.
	 */
	public static final int PORTA = 5;
	/**
	 * Address of PORTB system register.
	 */
	public static final int PORTB = 6;
	/**
	 * Address of EEDATA system register.
	 */
	public static final int EEDATA = 8;
	/**
	 * Address of EEADR system register.
	 */
	public static final int EEADR = 9;

// Public constants for Bank1
	/**
	 * Address of OPTION system register.
	 */
	public static final int OPTION = 1;
	/**
	 * Address of TRISA system register.
	 */
	public static final int TRISA = 5;
	/**
	 * Address of TRISB system register.
	 */
	public static final int TRISB = 6;
	/**
	 * Address of EECON1 system register.
	 */
	public static final int EECON1 = 8;
	/**
	 * Address of EECON2 system register.
	 */
	public static final int EECON2 = 9;

// Public constants for STATUS register
	/**
	 * Bit IRP of STATUS file register.
	 */
	public static final int IRP = 7;
	/**
	 * Bit RP1 of STATUS file register.
	 */
	public static final int RP1 = 6;
	/**
	 * Bit RP0 of STATUS file register.
	 */
	public static final int RP0 = 5;
	/**
	 * Bit TO of STATUS file register.
	 */
	public static final int TO = 4;
	/**
	 * Bit PD of STATUS file register.
	 */
	public static final int PD = 3;
	/**
	 * Bit Z (Zero) of STATUS file register.
	 */
	public static final int Z = 2;
	/**
	 * Bit DC (DigitCarry) of STATUS file register.
	 */
	public static final int DC = 1;
	/**
	 * Bit C (Carry) of STATUS file register.
	 */
	public static final int C = 0;

// Public methods
	/**
	 * Creates a new SystemRegisters.
	 */
	public SystemRegisters() {
		Bank0 = new int[12];
		Bank1 = new int[12];
	}

	/**
	 * Returns byte at address address in system registers.
	 * @param address Address to read from.
	 */
	public int Read(int address) {
		return ActiveBank()[address];
	}

	/**
	 * Writes byte n at address address in system registers.
	 * @param address Address to write to.
	 * @param n Byte to write.
	 */
	public void Write(int address, int n) {
		ActiveBank()[address] = n;

		if((address == 0) ||
		   (address == PCL) ||
		   (address == STATUS) ||
		   (address == FSR) ||
		   (address == PCLATH) ||
		   (address == INTCON))	{	// These registers are mapped in both banks
			Bank0[address] = n;
			Bank1[address] = n;  // we don't use UnactiveBank because of the case when STATUS is modified to change the active bank
		}

	}

	/**
	 * Returns byte at address address in bank Bank of system registers.
	 * @param address Address to read from.
	 * @param Bank Bank to read from.
	 */
	public int Read(int address, int Bank) {
		if(Bank == 0)
			return Bank0[address];
		else
			return Bank1[address];
	}

	/**
	 * Writes byte n at address address in bank Bank of system registers.
	 * @param address Address to write to.
	 * @param n Byte to write.
	 * @param Bank Bank to write to.
	 */
	public void Write(int address, int n, int Bank) {
		if(Bank == 0) 
			Bank0[address] = n;
		else
			Bank1[address] = n;

		if((address == 0) ||
		   (address == PCL) ||
		   (address == STATUS) ||
		   (address == FSR) ||
		   (address == PCLATH) ||
		   (address == INTCON))		// These registers are mapped in both banks
			if(Bank == 0)
				Bank1[address] = n;
			else
				Bank0[address] = n;
	}
// Private methods
	protected int[] ActiveBank() {
		if((Bank0[STATUS] & Utils.Puiss2(RP0)) == 0)
			return Bank0;
		else
			return Bank1;
	}

	protected int[] UnactiveBank() {
		if((Bank0[STATUS] & Utils.Puiss2(RP0)) != 0)
			return Bank0;
		else
			return Bank1;
	}


// Private variables
	protected int Bank0[], Bank1[];
}