package fabrik.simulator.pic16f84; import fabrik.simulator.pic16f84.frontendspecifics.FrontendSpecificToggleButtonGroup; import fabrik.simulator.pic16f84.frontendspecifics.ToggleButtonGroup; import fabrik.simulator.pic16f84.interfaces.*; import javafx.collections.ObservableList; import javafx.scene.control.ToggleButton; import javafx.scene.paint.Color; import javafx.scene.paint.RadialGradient; import javafx.scene.paint.Stop; import javafx.scene.shape.Circle; import java.io.IOException; public class IOPorts extends PICComponent implements IOPortInterface { private final int A = 0; private final int B = 1; private final int PORTA = 5; private final int PORTB = 6; private final int TRISA = 0x85; private final int TRISB = 0x86; private int [] trisLatch = {0xFF, 0xFF}; private int [] dataLatch = new int[2]; private boolean isLEDenabledA = false; private boolean isLEDenabledB = false; private Circle[] allLEDsA; private Circle[] allLEDsB; private int RB4 = 0x10; private int RB5 = 0x20; private int RB6 = 0x40; private int RB7 = 0x80; public IOPorts(){ super(); } public void setBit (int address, int bit){ if (address < 7) { dataLatch[address - PORTA] |= (1 << bit); } else{ trisLatch[address - TRISA] |= (1 << bit); } refreshPorts(); } public void clearBit(int address, int bit) { if (address < 7) { if (((dataLatch[address-PORTA] >> bit)&1) == 1){ dataLatch[address-PORTA] -= (int) Math.pow(2, bit); } } else{ if (((trisLatch[address-TRISA] >> bit)&1) == 1){ trisLatch[address-TRISA] -= (int) Math.pow(2, bit); } } refreshPorts(); } public void setRegister(int address, int content) { if (address < 7) { dataLatch[address - PORTA] = content; } else{ trisLatch[address - TRISA] = content; } refreshPorts(); } private void refreshPorts() { dataRegister.setDirectRegister(PORTA, ((~((~dataLatch[A])&0x1F | trisLatch[A])) | (trisLatch[A] & dataRegister.getDirectRegister(PORTA))) & 0xFF); dataRegister.setDirectRegister(PORTB, ((~((~dataLatch[B])&0xFF | trisLatch[B])) | (trisLatch[B] & dataRegister.getDirectRegister(PORTB))) & 0xFF); dataRegister.setDirectRegister(TRISA, trisLatch[A]); dataRegister.setDirectRegister(TRISB, trisLatch[B]); if (((trisLatch[A] >> 4) & 1 )== 1) timer.incrementFromPin(dataRegister.getDirectRegister(PORTA)); ToggleButtonGroup[] buttons = (ToggleButtonGroup[]) frontendController.getPORTbuttons(); for (int i = 0; i < buttons.length; i++){ int port = (i < 8) ? PORTA : PORTB; int bit = i % 8; boolean value = ((dataRegister.getDirectRegister(port) >> bit) & 1) == 1; buttons[i].getToggles().get(0).setSelected(!value); buttons[i].getToggles().get(1).setSelected(value); } } public void refreshUI(ToggleButtonGroup[] buttonsTRIS, ToggleButtonGroup[] buttonsPORT) { for (int i = 0; i< buttonsTRIS.length; i++){ int tris = (i < 8) ? trisLatch[A] : trisLatch[B]; boolean val = isInput(tris, i%8); buttonsPORT[i].setDisable(!val); buttonsTRIS[i].getToggles().get(0).setSelected(val); buttonsTRIS[i].getToggles().get(1).setSelected(!val); updateLEDs(true, i, val); } } private void updateLEDs(boolean updateAll, int index, boolean val) { if (updateAll) { if (index < 8) { if (isLEDenabledA && !val) { if (dataRegister.getDirectBit(PORTA, index) == 1) allLEDsA[index].setFill(new RadialGradient(0, 0, 0.5, 0.5, 0.7, true, null, new Stop(0, Color.BLACK), new Stop(1, Color.DARKGRAY))); else allLEDsA[index].setFill(new RadialGradient(0, 0, 0.5, 0.5, 0.7, true, null, new Stop(0, Color.BLACK), new Stop(1, Color.DARKGRAY))); } } else { if (isLEDenabledB && !val) { if (dataRegister.getDirectBit(PORTB, index - 8) == 1) allLEDsB[index - 8].setFill(new RadialGradient(0, 0, 0.5, 0.5, 0.7, true, null, new Stop(0, Color.RED), new Stop(1, Color.DARKGRAY))); else allLEDsB[index - 8].setFill(new RadialGradient(0, 0, 0.5, 0.5, 0.7, true, null, new Stop(0, Color.BLACK), new Stop(1, Color.DARKGRAY))); } } } else { if (index < 8) if (val || dataRegister.getDirectBit(PORTA, index) == 0) allLEDsA[index].setFill(new RadialGradient(0, 0, 0.5, 0.5, 0.7, true, null, new Stop(0, Color.BLACK), new Stop(1, Color.DARKGRAY))); else allLEDsA[index].setFill(new RadialGradient(0, 0, 0.5, 0.5, 0.7, true, null, new Stop(0, Color.RED), new Stop(1, Color.DARKGRAY))); else if (val || dataRegister.getDirectBit(PORTB, index - 8) == 0) allLEDsB[index - 8].setFill(new RadialGradient(0, 0, 0.5, 0.5, 0.7, true, null, new Stop(0, Color.BLACK), new Stop(1, Color.DARKGRAY))); else allLEDsB[index - 8].setFill(new RadialGradient(0, 0, 0.5, 0.5, 0.7, true, null, new Stop(0, Color.RED), new Stop(1, Color.DARKGRAY))); } } private boolean isInput(int i, int bit) { return (i >> bit & 1) == 1; } public void setTRISfromUI(ToggleButtonGroup parent) throws IOException { int [] params = getToggleParams(parent); int tris = params[0]; int bit = params[1]; int value = params[2]; ToggleButtonGroup [] buttonsPORT = (ToggleButtonGroup[]) frontendController.getPORTbuttons(); if (value == 1){ setBit(tris, bit); buttonsPORT[(tris-TRISA)*8 + bit].setDisable(false); } else{ clearBit(tris, bit); buttonsPORT[(tris-TRISA)*8 + bit].setDisable(true); } updateLEDs(false, (tris-TRISA)*8 + bit, value == 1); refreshPorts(); refreshTable(parent); } public void setPORTfromUI(ToggleButtonGroup parent) throws IOException { int [] params = getToggleParams(parent); int port = params[0]; int bit = params[1]; int value = params [2]; value = (value == 1) ? 0 : 1; int oldValue = dataRegister.getDirectBit(port, bit); dataRegister.setDirectBit(port, bit, value); refreshPorts(); refreshTable(parent); if (port == PORTB && bit >= 4) interrupts.triggerRBInterrupt(oldValue, value); else if (port == PORTB && bit == 0) interrupts.triggerRB0Interrupt(oldValue, value); } public void setLEDs (boolean[] leds) { boolean isAnowDisabled = isLEDenabledA && !leds[0]; isLEDenabledA = leds[0]; boolean isBnowDisabled = isLEDenabledB && !leds[1]; isLEDenabledB = leds[1]; if (isAnowDisabled){ for (Circle circle : allLEDsA) { circle.setFill(new RadialGradient(0, 0, 0.5, 0.5, 0.7, true, null, new Stop(0, Color.BLACK), new Stop(1, Color.DARKGRAY))); } } if (isBnowDisabled){ for (Circle circle : allLEDsB) { circle.setFill(new RadialGradient(0, 0, 0.5, 0.5, 0.7, true, null, new Stop(0, Color.BLACK), new Stop(1, Color.DARKGRAY))); } } } public void setLEDs (Circle[] a, Circle[] b){ allLEDsA = a; allLEDsB = b; } public void refreshTable(ToggleButtonGroup parent) { table.refresh(); CreateWindow.refreshTable(); } private int[] getToggleParams(ToggleButtonGroup parent) { String group = parent.getId(); ObservableList toggles = parent.getToggles(); int fileAddress; if (group.contains("TRIS")) if (group.contains("A")) fileAddress = TRISA; else fileAddress = TRISB; else if (group.contains("A")) fileAddress = PORTA; else fileAddress = PORTB; char index =group.charAt(group.length()-1); int bit = Integer.parseInt(String.valueOf(index)); int value = (toggles.get(0).isSelected()) ? 1 : 0; return new int[]{fileAddress, bit, value}; } public void reset() { trisLatch = new int[]{0xFF, 0xFF}; dataLatch = new int[2]; refreshPorts(); } public void resetTRIS (){ // Only Backend trisLatch = new int[] {0xFF, 0xFF}; } @Override public void initialize(PICComponentLocator locator) { super.initialize(locator); System.out.println("IOPorts.\n"); } @Override public void setPORTfromUI(FrontendSpecificToggleButtonGroup parent) throws IOException { setPORTfromUI((ToggleButtonGroup) parent); } @Override public void setTRISfromUI(FrontendSpecificToggleButtonGroup parent) throws IOException { setTRISfromUI((ToggleButtonGroup) parent); } @Override public void refreshUI(FrontendSpecificToggleButtonGroup[] trisButtons, FrontendSpecificToggleButtonGroup[] portButtons) { refreshUI((ToggleButtonGroup[]) trisButtons, (ToggleButtonGroup[]) portButtons); } }