package fabrik.simulator.pic16f84; import fabrik.simulator.pic16f84.interfaces.DataRegisterInterface; import fabrik.simulator.pic16f84.interfaces.EEPROMInterface; import fabrik.simulator.pic16f84.interfaces.IOPortInterface; import java.util.Arrays; public class DataRegister extends PICComponent implements DataRegisterInterface { private final int INDF = 0x0; private final int PCL = 0x2; private final int STATUS = 0x3; private final int FSR = 0x4; private final int PORTA = 0x5; private final int PORTB = 0x6; private final int PCLATH = 0xA; private final int INTCON = 0xB; private final int EEDATA = 0x08; private final int EEADR = 0x09; private final int EECON1 = 0x88; private final int EECON2 = 0x89; private final int TRISA = 0x85; private final int TRISB = 0x86; private final int C = 0x0; private final int DC = 0x1; private final int Z = 0x2; private final int RP0 = 0x5; private final int [] dataRegister = new int[0xFF]; private final int [] syncedRegisters = {INDF, PCL, STATUS, FSR, PCLATH, INTCON}; private final int [] eepromRegisters = {EEDATA, EEADR, EECON1, EECON2}; public final int [] ioRegisters = {PORTA, PORTB, TRISA, TRISB}; public DataRegister () { super(); } @Override public void initialize(PICComponents picComponents) { super.initialize(picComponents); System.out.println("DataRegister.\n"); initOrReset(); } private void initOrReset () { dataRegister[PCL] = 0b0; dataRegister[STATUS] = 0b00011000; dataRegister[PCLATH] = 0b0; dataRegister[INTCON] = 0b0; dataRegister[0x81] = 0b11111111; dataRegister[0x80 + PCL] = dataRegister[PCL]; dataRegister[0x80 + STATUS] = dataRegister[STATUS]; dataRegister[TRISA] = 0b11111111; dataRegister[TRISB] = 0b11111111; dataRegister[0x80 + PCLATH] = dataRegister[PCLATH]; dataRegister[0x80 + INTCON] = dataRegister[INTCON]; carryFlag = 0; zeroFlag = 0; digitCarryFlag = 0; super.ioPorts.resetTRIS(); System.out.println(Arrays.toString(dataRegister)); } public void initDataRegister() { initOrReset(); } private boolean isSyncedRegister (int address){ for (int register : syncedRegisters){ if (address == register || address == 0x80 + register){ return true; } } return false; } public int[] getDataRegister() { return dataRegister; } private int determineIndirectAndChange (int address){ if (address == INDF || address == 0x80 + INDF) { return dataRegister[FSR]; } else return address; } public int getFSR (){ return dataRegister[FSR]; } private int bank() { return ((dataRegister[STATUS] >> RP0) & 1) * 0x80; } public int getRegister(int fileAddress){ int address = determineIndirectAndChange (fileAddress); if (bank () + address == EECON2) return 0; return dataRegister[bank() + address]; } public void setRegister(int fileAddress, int content){ int address = determineIndirectAndChange (fileAddress); if (Arrays.stream(ioRegisters).anyMatch(i -> i == address)){ ioPorts.setRegister(bank() + address, content); return; } if (Arrays.stream(eepromRegisters).anyMatch(i -> i == address)){ eeprom.parse(bank() + address, content, 0b11); return; } if (fileAddress == PCL || fileAddress == 0x80 + PCL){ programCounter = content + (dataRegister[PCLATH] << 8); } if (!isSyncedRegister(address)) dataRegister[bank() + address] = content; else { dataRegister[address] = content; dataRegister[0x80 + address] = content; if (address == STATUS){ setFlags(); } } if (address == 1) preScaler.resetFromRegister(); } public int getBit(int fileAddress, int bit) { int address = determineIndirectAndChange (fileAddress); if (bank() + address == EECON2) return 0; return (dataRegister[bank() + address] >> bit) & 1; } public int getDirectBit(int address, int bit){ return (dataRegister[address] >> bit) & 1; } public void clearBit(int fileAddress, int bit) { int address = determineIndirectAndChange (fileAddress); if (Arrays.stream(ioRegisters).anyMatch(i -> i == address)){ ioPorts.clearBit(bank() + address, bit); return; } if (Arrays.stream(eepromRegisters).anyMatch(i -> i == address)){ eeprom.parse(bank () + address, bit, 0b00); return; } if (!isSyncedRegister(address)) { if (getBit(address, bit) == 1) { dataRegister[bank() + address] -= (int) Math.pow(2, bit); } } else { if (getBit(address, bit) == 1) { dataRegister[address] -= (int) Math.pow(2, bit); dataRegister[0x80 + address] = dataRegister[address]; if (address == STATUS){ setFlags(); } } } if (address == 1) preScaler.resetFromRegister(); } public void setBit(int fileAddress, int bit) { int address = determineIndirectAndChange (fileAddress); if (Arrays.stream(ioRegisters).anyMatch(i -> i == address)){ ioPorts.setBit(bank() + address, bit); return; } if (Arrays.stream(eepromRegisters).anyMatch(i -> i == address)){ eeprom.parse(bank () + address, bit, 0b10); return; } if (!isSyncedRegister(address)) { if (getBit(address, bit) == 0) { dataRegister[bank() + address] += (int) Math.pow(2, bit); } } else { if (getBit(address, bit) == 0) { dataRegister[address] += (int) Math.pow(2, bit); dataRegister[0x80 + address] = dataRegister[address]; if (address == STATUS){ setFlags(); } } } if (address == 1) preScaler.resetFromRegister(); } public void setDirectBit (int fileAddress, int bit, int value){ if (getDirectBit(fileAddress, bit) == 0 && value == 1){ dataRegister[fileAddress] += (int) Math.pow(2, bit); } else if (getDirectBit(fileAddress, bit) == 1 && value == 0){ dataRegister[fileAddress] -= (int) Math.pow(2, bit); } } private int programCounter = 0; private void writeToPCL(){ dataRegister[PCL] = programCounter & 0xFF; dataRegister[0x80 + PCL] = dataRegister[PCL]; } public void increasePC (){ if (programCounter != 0x3FF) { programCounter++; } else { programCounter = 0; } writeToPCL(); } public void setPC (int value){ programCounter = value + ((getRegister(PCLATH) & 0b11000) << 8); writeToPCL(); } public void resetPC () { programCounter = 0; } public int getPC(){ return programCounter; } private void setFlags() { carryFlag = getDirectBit(STATUS, C); digitCarryFlag = getDirectBit(STATUS, DC); zeroFlag = getDirectBit(STATUS, Z); } private int zeroFlag = 0; public void determineZeroFlag(int result){ if (result == 0){ zeroFlag = 1; if (getBit(STATUS, Z) == 0){ dataRegister[STATUS] += 0b100; dataRegister[0x80 + STATUS] = dataRegister[STATUS]; } } else { zeroFlag = 0; if (getBit(STATUS, Z) == 1){ dataRegister[STATUS] -= 0b100; dataRegister[0x80 + STATUS] = dataRegister[STATUS]; } } } public int getZeroFlag(){ return zeroFlag; } private int carryFlag = 0; public void setCarryFlag(int value){ carryFlag = value; if (value == 1){ if (getBit(STATUS, C) == 0){ dataRegister[STATUS] += 0b1; dataRegister[0x80 + STATUS] = dataRegister[STATUS]; } } else { if (getBit(STATUS, C) == 1){ dataRegister[STATUS] -= 0b1; dataRegister[0x80 + STATUS] = dataRegister[STATUS]; } } } public void determineCarryFlag (int result){ if (result > 0xFF){ setCarryFlag(1); } else { setCarryFlag(0); } } public int getCarryFlag (){ return carryFlag; } private int digitCarryFlag = 0; public void setDigitCarryFlag(int value){ digitCarryFlag = value; if (value == 1){ if (getBit(STATUS, DC) == 0){ dataRegister[STATUS] += 0b10; dataRegister[0x80 + STATUS] = dataRegister[STATUS]; } } else { if (getBit(STATUS, DC) == 1){ dataRegister[STATUS] -= 0b10; dataRegister[0x80 + STATUS] = dataRegister[STATUS]; } } } public void determineDigitCarryFlag(int result){ if (result >> 4 == 1){ setDigitCarryFlag(1); } else { setDigitCarryFlag(0); } } public int getDigitCarryFlag(){ return digitCarryFlag; } public void setDirectRegister(int fileAddress, int content) { dataRegister[fileAddress] = content; } public int getPCL() { return PCL; } public int getSTATUS() { return STATUS; } public int getPCLATH() { return PCLATH; } public int getINTCON() { return INTCON; } public int getDirectRegister(int address) { return dataRegister[address]; } }