package fabrik.simulator.pic16f84; import com.gluonhq.charm.glisten.control.ToggleButtonGroup; import fabrik.simulator.pic16f84.interfaces.*; import fabrik.simulator.pic16f84.interfaces.WatchdogTimerInterface; import javafx.application.Platform; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.Scene; import javafx.scene.control.*; import javafx.scene.layout.VBox; import javafx.scene.shape.Circle; import javafx.stage.FileChooser; import java.io.File; import java.io.IOException; import java.io.BufferedReader; import java.io.FileReader; import javafx.scene.control.Label; import javafx.scene.control.TableView; import javafx.stage.Stage; import javafx.util.Callback; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; import static java.lang.Math.max; public class Controller_Frontend extends PICComponent implements FrontendControllerInterface { private int [] prog; private int [][] read; private int [] ind; private PICComponents picComponents; private double executionTimeMultiplier = 1; public double getExecutionTimeMultiplier(){ return executionTimeMultiplier; } private boolean isBreakpointReached = false; private boolean continueExecutionAfterBreakpoint = false; @FXML private ComboBox executionTimeComboBox; @FXML private Button stepintoButton; @FXML private TableView tableView; @FXML private ListView lstContentListView; @FXML private Button autoRunGUI; @FXML private Button stopButton; @FXML private Label totalExecutionTimeLabel; @FXML private CheckBox wdtCheck; private static volatile boolean isAutoRunActive = false; private static volatile boolean isSleeping = false; public Controller_Frontend() { super(); System.out.println(this); } public boolean isSleeping (){ return isSleeping; } public void stopRunFromBackend(String message){ isAutoRunActive = false; if (isSleeping) wakeUpFromSleep(); else dataRegister.resetPC(); Stage stoppedStage = new Stage(); stoppedStage.setTitle("Programm unterbrochen!"); VBox vbox = new VBox(); vbox.setAlignment(javafx.geometry.Pos.CENTER); Label grundlabel = new Label("Grund: " + message); grundlabel.setStyle("-fx-font-size: 16px; -fx-font-weight: bold;"); Label ueberlabel = new Label("Programm unterbrochen!"); vbox.getChildren().add(ueberlabel); vbox.getChildren().add(grundlabel); VBox.setMargin(grundlabel, new javafx.geometry.Insets(10, 10, 10, 10)); Scene scene = new Scene(vbox, 300, 90); stoppedStage.setAlwaysOnTop(true); stoppedStage.setScene(scene); stoppedStage.show(); } public void sleep() { isSleeping = true; } public void wakeUpFromSleep() { isSleeping = false; } @FXML private void stopAutoRun(ActionEvent event) { isAutoRunActive = false; } @FXML public void autoRunGUI(ActionEvent event) { if (!isAutoRunActive) { isAutoRunActive = true; } Thread autoRunThread = new Thread(() -> { try { while (dataRegister.getPC() < prog.length && isAutoRunActive){ Platform.runLater(() -> { try { stepintoButton(null); } catch (IOException e) { e.printStackTrace(); } }); Thread.sleep(80); //Verzögerungszeit in Millisekunden } } catch (InterruptedException e) { e.printStackTrace(); } }); autoRunThread.setDaemon(true); autoRunThread.start(); } private void updateExecutionTimeMultiplier() { String selectedOption = executionTimeComboBox.getValue(); switch (selectedOption) { case "8 MHZ": executionTimeMultiplier = 0.5; break; case "4 MHZ": executionTimeMultiplier = 1; break; case "1 MHZ": executionTimeMultiplier = 4; break; case "500 HZ": executionTimeMultiplier = 8; break; case "100 HZ": executionTimeMultiplier = 40; break; case "32 HZ": executionTimeMultiplier = 125; break; } } @FXML public void stepintoButton(ActionEvent event) throws IOException { if (lstContentListView.getItems().isEmpty()) { // Datei ist nicht geladen oder leer return; } int currentIndex; // Aktuelle Zeile abrufen if (!isSleeping) currentIndex = ind[dataRegister.getPC()]; else currentIndex = ind[dataRegister.getPC()]-1; // Überprüfung ob ein Breakpoint gesetzt ist testte if (breakpoints.contains(currentIndex)) { if (!continueExecutionAfterBreakpoint){ isBreakpointReached = true; stopAutoRun(null); System.out.println("Breakpoint erreicht bei Zeile: " + currentIndex); continueExecutionAfterBreakpoint = true; return; } } else { isBreakpointReached = false; continueExecutionAfterBreakpoint = false; } // Scrollen zur ausgewählten Zeile lstContentListView.scrollTo(currentIndex -2); // Zeile auswählen lstContentListView.getSelectionModel().clearSelection(); lstContentListView.getSelectionModel().select(currentIndex); String selectedRowStyle; if (!isSleeping) selectedRowStyle = "-fx-background-color: red; -fx-text-fill: white;"; else selectedRowStyle = "-fx-background-color: teal; -fx-text-fill: white;"; markSelectedRow(currentIndex, selectedRowStyle); if (!isSleeping) { commands.decode(prog[dataRegister.getPC()]); dataRegister.increasePC(); } else { commands.decode(0); } watchdogTimer.testAndTrigger(); Table.refresh(); CreateWindow.refreshTable(); ioPorts.refreshUI(getTRISbuttons(), getPORTbuttons()); updateStack(); updateWatchdog(); double totalExecutionTime = commands.getTotalExecutionTime(); totalExecutionTimeLabel.setText("Total Execution Time: " + totalExecutionTime + "µs"); } private void markSelectedRow(int currentIndex, String selectedRowStyle) { lstContentListView.setCellFactory(column -> new ListCell() { @Override protected void updateItem(String item, boolean empty) { super.updateItem(item, empty); setText(item); if (getIndex() == currentIndex) { setStyle(selectedRowStyle); } else { setStyle(""); } CheckBox breakpointCheckBox = new CheckBox(); breakpointCheckBox.setOnAction(event -> { int index = getIndex(); if (breakpointCheckBox.isSelected()) { breakpoints.add(index); } else { breakpoints.remove(index); } }); breakpointCheckBox.setSelected(breakpoints.contains(getIndex())); setGraphic(breakpointCheckBox); } }); } private Set breakpoints = new HashSet<>(); @FXML protected void selectFileLST(ActionEvent event) throws IOException { File selectedFile = chooseLSTFile(); stopAutoRun(null); if(selectedFile != null){ String fileAddress = selectedFile.getAbsolutePath(); System.out.println(dataRegister); if (null == dataRegister) dataRegister = (DataRegisterInterface) picComponents.getComponent(DataRegisterInterface.class); dataRegister.initDataRegister(); dataRegister.resetPC(); toggleLEDs(null); ioPorts.reset(); for (ToggleButtonGroup toggleButtonGroup : allPORTbuttons) { try { toggleButtonGroup.getToggles().get(0).setSelected(true); toggleButtonGroup.getToggles().get(1).setSelected(false); ioPorts.setPORTfromUI(toggleButtonGroup); } catch (NullPointerException ignored) {} } programStack.reset(); wakeUpFromSleep(); breakpoints.clear(); ioPorts.refreshUI(getTRISbuttons(), getPORTbuttons()); commands.resetTotalExecutionTime(); watchdogTimer.reset(); wdtCheck.setSelected(false); Table.refresh(); read = ParseFile.parseDatei(fileAddress); prog = read [0]; ind = read[1]; updateStack(); System.out.println(Arrays.toString(Arrays.stream(prog).toArray())); displayLSTFileContent(selectedFile); markSelectedRow(0, "-fx-background-color: red; -fx-text-fill: white;"); initializeBreakpoints(); int lastSlash = max (fileAddress.lastIndexOf('/'), fileAddress.lastIndexOf('\\')); int lastDot = fileAddress.lastIndexOf('.'); String stageTitle; if (lastDot > lastSlash) stageTitle = "Simulator - " + fileAddress.substring(lastSlash + 1, lastDot); else { stageTitle = "Simulator - " + fileAddress.substring(lastSlash + 1); } Stage stage = (Stage) stepintoButton.getScene().getWindow(); stage.setTitle(stageTitle); } } private void initializeBreakpoints() { lstContentListView.setCellFactory(createBreakpointCell()); } private boolean checkBreakpoint(int pc) { // Hier wird überprüft, ob ein Breakpoint am angegebenen Programmzähler gesetzt ist return breakpoints.contains(pc); } private Callback, ListCell> createBreakpointCell() { return listView -> new ListCell() { private final CheckBox breakpointCheckBox = new CheckBox(); { breakpointCheckBox.setOnAction(event -> { int index = getIndex(); if (breakpointCheckBox.isSelected()) { breakpoints.add(index); } else { breakpoints.remove(index); } }); } @Override protected void updateItem(String item, boolean empty) { super.updateItem(item, empty); if (empty || item == null) { setGraphic(null); } else { setText(item); setGraphic(breakpointCheckBox); breakpointCheckBox.setSelected(breakpoints.contains(getIndex())); } } }; } @FXML protected void loadLSTFileContent(String fileContent) { ObservableList items = FXCollections.observableArrayList(fileContent.split("\n")); lstContentListView.setItems(items); } private File chooseLSTFile() { FileChooser fileChooser = new FileChooser(); fileChooser.getExtensionFilters().addAll( new FileChooser.ExtensionFilter("LST Files", "*.lst", "*.LST"), new FileChooser.ExtensionFilter("All Files", "*.*")); return fileChooser.showOpenDialog(null); } @FXML private void displayLSTFileContent(File selectedFile) { try (BufferedReader reader = new BufferedReader(new FileReader(selectedFile))) { ObservableList contentList = FXCollections.observableArrayList(); String line; while ((line = reader.readLine()) != null) { contentList.add(line); } lstContentListView.setItems(contentList); } catch (IOException e) { e.printStackTrace(); } } @FXML public void toggleWatchdog(ActionEvent actionEvent) { if (wdtCheck.isSelected()){ watchdogTimer.enable(); } else{ watchdogTimer.disable(); } } @FXML private ToggleButtonGroup bgTRISA0; @FXML private ToggleButtonGroup bgTRISA1; @FXML private ToggleButtonGroup bgTRISA2; @FXML private ToggleButtonGroup bgTRISA3; @FXML private ToggleButtonGroup bgTRISA4; @FXML private ToggleButtonGroup bgTRISB0; @FXML private ToggleButtonGroup bgTRISB1; @FXML private ToggleButtonGroup bgTRISB2; @FXML private ToggleButtonGroup bgTRISB3; @FXML private ToggleButtonGroup bgTRISB4; @FXML private ToggleButtonGroup bgTRISB5; @FXML private ToggleButtonGroup bgTRISB6; @FXML private ToggleButtonGroup bgTRISB7; @FXML private ToggleButtonGroup bgPORTA0; @FXML private ToggleButtonGroup bgPORTA1; @FXML private ToggleButtonGroup bgPORTA2; @FXML private ToggleButtonGroup bgPORTA3; @FXML private ToggleButtonGroup bgPORTA4; @FXML private ToggleButtonGroup bgPORTB0; @FXML private ToggleButtonGroup bgPORTB1; @FXML private ToggleButtonGroup bgPORTB2; @FXML private ToggleButtonGroup bgPORTB3; @FXML private ToggleButtonGroup bgPORTB4; @FXML private ToggleButtonGroup bgPORTB5; @FXML private ToggleButtonGroup bgPORTB6; @FXML private ToggleButtonGroup bgPORTB7; private static ToggleButtonGroup[] allTRISbuttons; private static ToggleButtonGroup[] allPORTbuttons; private static Circle[] allLEDsA; private static Circle[] allLEDsB; private static ToggleButtonGroup dummy = new ToggleButtonGroup(new ToggleButton(), new ToggleButton()); public void initialize() { ToggleButtonGroup [] allTRISButtons = {bgTRISA0, bgTRISA1, bgTRISA2, bgTRISA3, bgTRISA4, dummy, dummy, dummy, bgTRISB0, bgTRISB1, bgTRISB2, bgTRISB3, bgTRISB4, bgTRISB5, bgTRISB6, bgTRISB7}; ToggleButtonGroup [] allPORTButtons = {bgPORTA0, bgPORTA1, bgPORTA2, bgPORTA3, bgPORTA4, dummy, dummy, dummy, bgPORTB0, bgPORTB1, bgPORTB2, bgPORTB3, bgPORTB4, bgPORTB5, bgPORTB6, bgPORTB7}; Circle[] allLEDsA = {ledA0, ledA1, ledA2, ledA3, ledA4}; Circle[] allLEDsB = {ledB0, ledB1, ledB2, ledB3, ledB4, ledB5, ledB6, ledB7}; for (int i = 0; i updateExecutionTimeMultiplier()); } private static void setTRISbuttons(ToggleButtonGroup[] allButtons) { allTRISbuttons = allButtons; } public static ToggleButtonGroup [] getTRISbuttons() { return allTRISbuttons; } private static void setPORTbuttons(ToggleButtonGroup[] allButtons) { allPORTbuttons = allButtons; } public static ToggleButtonGroup [] getPORTbuttons() { return allPORTbuttons; } public static Circle[] getLEDsA() { return allLEDsA; } public static Circle[] getLEDsB() { return allLEDsB; } @FXML private CheckBox ledCheckA; @FXML private CheckBox ledCheckB; @FXML private Circle ledA0; @FXML private Circle ledA1; @FXML private Circle ledA2; @FXML private Circle ledA3; @FXML private Circle ledA4; @FXML private Circle ledB0; @FXML private Circle ledB1; @FXML private Circle ledB2; @FXML private Circle ledB3; @FXML private Circle ledB4; @FXML private Circle ledB5; @FXML private Circle ledB6; @FXML private Circle ledB7; @FXML public void toggleLEDs (ActionEvent actionEvent) { ioPorts.setLEDs(new boolean[]{ledCheckA.isSelected(), ledCheckB.isSelected()}); } @FXML private Label stackIndex; @FXML private ListView stackVisual; private static String format (String s) { return (s.length() == 1) ? "0" + s : s; } private void updateStack (){ stackIndex.setText("Stack-Pointer: " + programStack.getStackPointer()); ObservableList observedList = FXCollections.observableArrayList(); List stackList = programStack.getStack(); for (Integer integer : stackList) { observedList.add("0x" + format(Integer.toHexString(integer).toUpperCase())); } stackVisual.setItems(observedList); } private void updateWatchdog (){ wdtCheck.setText("Watchdog-Timer: " + watchdogTimer.get() + "µs"); } @Override public void initialize(PICComponents picComponents) { super.initialize(picComponents); this.picComponents = picComponents; System.out.println("Frontend"); } }