235 lines
8.7 KiB
Java
235 lines
8.7 KiB
Java
package fabrik.simulator.pic16f84;
|
|
|
|
import com.gluonhq.charm.glisten.control.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 = Controller_Frontend.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 = Controller_Frontend.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<ToggleButton> 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");
|
|
}
|
|
}
|