@@ -2,50 +2,85 @@ package org.strykeforce.thirdcoast.device
22
33import com.ctre.phoenix.motorcontrol.ControlMode
44import com.ctre.phoenix.motorcontrol.NeutralMode
5+ import com.ctre.phoenix.motorcontrol.can.SlotConfiguration
56import com.ctre.phoenix.motorcontrol.can.TalonSRX
67import com.ctre.phoenix.motorcontrol.can.TalonSRXConfiguration
78import mu.KotlinLogging
8- import org.strykeforce.thirdcoast.talon.TalonParameterCommand
99import org.strykeforce.thirdcoast.talon.SelectFeedbackSensorCommand
10+ import org.strykeforce.thirdcoast.talon.TalonParameterCommand
1011import org.strykeforce.thirdcoast.telemetry.TelemetryService
1112
1213private val logger = KotlinLogging .logger {}
1314
15+ private val CONTROL_MODE_DEFAULT = ControlMode .PercentOutput
1416private const val ACTIVE_SLOT_DEFAULT = 0
15- private const val VOLTAGE_COMPENSATION_DEFAULT = true
16- private const val SENSOR_PHASE_DEFAULT = false
17- private const val CURRENT_LIMIT_DEFAULT = false
18- private const val INVERTED_DEFAULT = false
17+ private val NEUTRAL_MODE_DEFAULT = NeutralMode .EEPROMSetting
18+ private const val VOLTAGE_COMPENSATION_ENABLED_DEFAULT = true
19+ private const val CURRENT_LIMIT_ENABLED_DEFAULT = false
20+ private const val SENSOR_PHASE_INVERTED_DEFAULT = false
21+ private const val OUTPUT_INVERTED_DEFAULT = false
1922
23+ /* *
24+ * Holds the active state for all Talons that have been activated by the user. Talons that are currently active
25+ * can be configured and ran. All Talons that have been made active will be available to the telemetry client (Grapher),
26+ * for the remainder of the `tct` session, even if not currently active.
27+ *
28+ * Persistent configuration settings will be refreshed from the Talon when the `TalonService` is marked as *dirty*. This
29+ * prevents repeated, time-consuming Phoenix API calls to read Talon state.
30+ *
31+ * For non-persistent settings, Talons will be set to a known state when made active. These include:
32+ * - control mode = PercentOutput
33+ * - active slot index = 0
34+ * - brake in neutral mode = EEPROM setting
35+ * - voltage compensation = enabled
36+ * - current limit = enabled
37+ * - sensor phase = not inverted
38+ * - output = not inverted
39+ *
40+ *
41+ * @param telemetryService the telemetry service.
42+ * @param factory a factory lambda expression to instantiate Talons.
43+ */
2044class TalonService (private val telemetryService : TelemetryService , factory : (id: Int ) -> TalonSRX ) :
2145 AbstractDeviceService <TalonSRX >(factory) {
2246
2347 val timeout = 10
48+ var dirty = true
49+ var controlMode = CONTROL_MODE_DEFAULT
2450 var activeSlotIndex: Int = ACTIVE_SLOT_DEFAULT
25- var controlMode = ControlMode .PercentOutput
26- var neutralMode = NeutralMode .EEPROMSetting
27- var voltageCompensation = VOLTAGE_COMPENSATION_DEFAULT
28- var sensorPhase = SENSOR_PHASE_DEFAULT
29- var currentLimit = CURRENT_LIMIT_DEFAULT
51+ var neutralMode = NEUTRAL_MODE_DEFAULT
52+ var voltageCompensation = VOLTAGE_COMPENSATION_ENABLED_DEFAULT
53+ var sensorPhase = SENSOR_PHASE_INVERTED_DEFAULT
54+ var currentLimit = CURRENT_LIMIT_ENABLED_DEFAULT
3055
3156 var activeConfiguration = TalonSRXConfiguration ()
3257 get() {
58+ if (! dirty) return field
3359 active.firstOrNull()?.getAllConfigs(field) ? : logger.debug(" no active talons, returning default config" )
60+ dirty = false
3461 return field
3562 }
3663
37- val outputReverse: Boolean
38- get() = active.firstOrNull()?.inverted ? : INVERTED_DEFAULT
64+ val activeSlot: SlotConfiguration
65+ get() = when (activeSlotIndex) {
66+ 0 -> activeConfiguration.slot0
67+ 1 -> activeConfiguration.slot1
68+ 2 -> activeConfiguration.slot2
69+ 3 -> activeConfiguration.slot3
70+ else -> throw IllegalStateException (" invalid slot: $activeSlotIndex " )
71+ }
72+
73+ val outputInverted: Boolean
74+ get() = active.firstOrNull()?.inverted ? : OUTPUT_INVERTED_DEFAULT
3975
4076 override fun activate (ids : Collection <Int >) {
41- TalonParameterCommand .reset = true
42- SelectFeedbackSensorCommand .reset = true
77+ dirty = true
4378 activeSlotIndex = ACTIVE_SLOT_DEFAULT
44- controlMode = ControlMode . PercentOutput
45- neutralMode = NeutralMode . EEPROMSetting
46- voltageCompensation = VOLTAGE_COMPENSATION_DEFAULT
47- sensorPhase = SENSOR_PHASE_DEFAULT
48- currentLimit = CURRENT_LIMIT_DEFAULT
79+ controlMode = CONTROL_MODE_DEFAULT
80+ neutralMode = NEUTRAL_MODE_DEFAULT
81+ voltageCompensation = VOLTAGE_COMPENSATION_ENABLED_DEFAULT
82+ sensorPhase = SENSOR_PHASE_INVERTED_DEFAULT
83+ currentLimit = CURRENT_LIMIT_ENABLED_DEFAULT
4984
5085 super .activate(ids)
5186 telemetryService.stop()
@@ -54,7 +89,7 @@ class TalonService(private val telemetryService: TelemetryService, factory: (id:
5489 it.selectProfileSlot(activeSlotIndex, 0 )
5590 it.enableVoltageCompensation(voltageCompensation)
5691 it.setSensorPhase(sensorPhase)
57- it.inverted = INVERTED_DEFAULT
92+ it.inverted = OUTPUT_INVERTED_DEFAULT
5893 it.enableCurrentLimit(currentLimit)
5994 telemetryService.register(it)
6095 }
0 commit comments