package edu.wpi.first.wpilibj.hal; import edu.wpi.first.wpilibj.PWMConfigDataResult; import jaci.openrio.toast.core.loader.simulation.SimulationData; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.nio.IntBuffer; import java.util.function.Function; public class PWMJNI extends DIOJNI { public static boolean initializePWMPort(int digital_port_pointer) { return true; } public static boolean checkPWMChannel(int channel) { return true; } public static void freePWMChannel(int digital_port_pointer) { } public static void setPWMConfigRaw(int pwmPortHandle, int maxPwm, int deadbandMaxPwm, int centerPwm, int deadbandMinPwm, int minPwm) { try { Constructor<PWMConfigDataResult> constructor = PWMConfigDataResult.class.getDeclaredConstructor(Integer.class, Integer.class, Integer.class, Integer.class, Integer.class); constructor.setAccessible(true); PWMConfigDataResult result = constructor.newInstance(maxPwm, deadbandMaxPwm, centerPwm, deadbandMinPwm, minPwm); SimulationData.pwmConfigs[pwmPortHandle] = result; } catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) { } } public static void setPWMConfig(int pwmPortHandle, double maxPwm, double deadbandMaxPwm, double centerPwm, double deadbandMinPwm, double minPwm) { try { double loopTime = DIOJNI.getLoopTiming() / (ConstantsJNI.getSystemClockTicksPerMicrosecond() * 1e3); Function<Double, Integer> convert = (a) -> { return (int)((a - 1.5) / loopTime + 999); }; Constructor<PWMConfigDataResult> constructor = PWMConfigDataResult.class.getDeclaredConstructor(Integer.class, Integer.class, Integer.class, Integer.class, Integer.class); constructor.setAccessible(true); PWMConfigDataResult result = constructor.newInstance(convert.apply(maxPwm), convert.apply(deadbandMaxPwm), convert.apply(centerPwm), convert.apply(deadbandMinPwm), convert.apply(minPwm)); SimulationData.pwmConfigs[pwmPortHandle] = result; } catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) { } } public static PWMConfigDataResult getPWMConfigRaw(int pwmPortHandle) { return SimulationData.pwmConfigs[pwmPortHandle]; // This function is never called, so I'm going to leave this for now } public static void setPWMEliminateDeadband(int pwmPortHandle, boolean eliminateDeadband) { SimulationData.pwmEliminateDeadband[pwmPortHandle] = eliminateDeadband; } public static boolean getPWMEliminateDeadband(int pwmPortHandle) { return SimulationData.pwmEliminateDeadband[pwmPortHandle]; } public static double clamp(double val, double min, double max) { if (val < min) val = min; else if (val > max) val = max; return val; } public static double minPositive(int pwmPortHandle) { PWMConfigDataResult config = getPWMConfigRaw(pwmPortHandle); boolean deadbandElim = getPWMEliminateDeadband(pwmPortHandle); return deadbandElim ? config.deadbandMax : config.center + 1; } public static double maxNegative(int pwmPortHandle) { PWMConfigDataResult config = getPWMConfigRaw(pwmPortHandle); boolean deadbandElim = getPWMEliminateDeadband(pwmPortHandle); return deadbandElim ? config.deadbandMin : config.center - 1; } public static double posScaleFactor(int pwmPortHandle) { PWMConfigDataResult config = getPWMConfigRaw(pwmPortHandle); double max = config.max; double min = minPositive(pwmPortHandle); return max - min; } public static double negScaleFactor(int pwmPortHandle) { PWMConfigDataResult config = getPWMConfigRaw(pwmPortHandle); double max = maxNegative(pwmPortHandle); double min = config.min; return max - min; } public static double fullScaleFactor(int pwmPortHandle) { PWMConfigDataResult config = getPWMConfigRaw(pwmPortHandle); boolean deadbandElim = getPWMEliminateDeadband(pwmPortHandle); return config.max - config.min; } public static void setPWMRaw(int digital_port_pointer, short value) { SimulationData.setPWM((byte)digital_port_pointer, (double) (value - 1012) / 255); } public static void setPWMSpeed(int pwmPortHandle, double speed) { speed = clamp(speed, -1.0, 1.0); PWMConfigDataResult config = getPWMConfigRaw(pwmPortHandle); int raw; if (speed == 0.0) raw = config.center; else if (speed > 0.0) { raw = (int)(speed * ((double) posScaleFactor(pwmPortHandle)) + ((double) minPositive(pwmPortHandle)) + 0.5); } else { raw = (int)(speed * ((double) negScaleFactor(pwmPortHandle)) + ((double) maxNegative(pwmPortHandle)) + 0.5); } setPWMRaw(pwmPortHandle, (short)raw); } public static void setPWMPosition(int pwmPortHandle, double position) { PWMConfigDataResult config = getPWMConfigRaw(pwmPortHandle); position = clamp(position, 0.0, 1.0); setPWMRaw(pwmPortHandle, (short) ((position * (double) fullScaleFactor(pwmPortHandle)) + config.min)); } public static short getPWMRaw(int digital_port_pointer) { return (short) (SimulationData.pwmValues[(byte)digital_port_pointer] * 255 + 1012); } public static double getPWMSpeed(int pwmPortHandle) { int val = getPWMRaw(pwmPortHandle); PWMConfigDataResult config = getPWMConfigRaw(pwmPortHandle); if (val > config.max) return 1.0; if (val < config.min) return -1.0; if (val > minPositive(pwmPortHandle)) { return (double) (val - minPositive(pwmPortHandle)) / (double) posScaleFactor(pwmPortHandle); } if (val < maxNegative(pwmPortHandle)) { return (double) (val - maxNegative(pwmPortHandle)) / (double) negScaleFactor(pwmPortHandle); } return 0.0; } public static double getPWMPosition(int pwmPortHandle) { int val = getPWMRaw(pwmPortHandle); PWMConfigDataResult config = getPWMConfigRaw(pwmPortHandle); if (val > config.max) return 1.0; if (val < config.min) return 0.0; return (double) (val - config.min) / (double) fullScaleFactor(pwmPortHandle); } public static void setPWMDisabled(int pwmPortHandle) { setPWMRaw(pwmPortHandle, (short)0); } public static void latchPWMZero(int pwmPortHandle) { } public static void setPWMPeriodScale(int pwmPortHandle, int squelchMask) { } }