Skip to content

Commit 4300d7d

Browse files
committed
Merge branch 'feature/dio'
2 parents 5c0b901 + 58142ab commit 4300d7d

File tree

6 files changed

+130
-14
lines changed

6 files changed

+130
-14
lines changed

src/main/kotlin/org/strykeforce/thirdcoast/Koin.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ import com.ctre.phoenix.motorcontrol.FeedbackDevice
44
import com.ctre.phoenix.motorcontrol.NeutralMode
55
import com.ctre.phoenix.motorcontrol.can.TalonSRX
66
import com.ctre.phoenix.motorcontrol.can.TalonSRXConfiguration
7+
import edu.wpi.first.wpilibj.DigitalOutput
78
import edu.wpi.first.wpilibj.Servo
89
import org.jline.reader.LineReader
910
import org.jline.reader.LineReaderBuilder
1011
import org.jline.terminal.Terminal
1112
import org.jline.terminal.TerminalBuilder
1213
import org.koin.dsl.module.module
1314
import org.strykeforce.thirdcoast.command.Command
15+
import org.strykeforce.thirdcoast.device.DigitalOutputService
1416
import org.strykeforce.thirdcoast.device.ServoService
1517
import org.strykeforce.thirdcoast.device.TalonService
1618
import org.strykeforce.thirdcoast.swerve.SwerveDrive
@@ -35,6 +37,8 @@ val tctModule = module {
3537

3638
single { ServoService { id -> Servo(id) } }
3739

40+
single { DigitalOutputService { id -> DigitalOutput(id) } }
41+
3842
single { (command: Command) -> Shell(command, get()) }
3943

4044
single<Terminal> { TerminalBuilder.terminal() }

src/main/kotlin/org/strykeforce/thirdcoast/command/Command.kt

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import org.jline.utils.AttributedString
77
import org.jline.utils.AttributedStyle
88
import org.koin.standalone.KoinComponent
99
import org.koin.standalone.inject
10+
import org.strykeforce.thirdcoast.dio.RunDigitalOutputsCommand
11+
import org.strykeforce.thirdcoast.dio.SelectDigitalOutputsCommand
1012
import org.strykeforce.thirdcoast.servo.RunServosCommand
1113
import org.strykeforce.thirdcoast.servo.SelectServosCommand
1214
import org.strykeforce.thirdcoast.swerve.AdjustAzimuthCommand
@@ -35,20 +37,7 @@ interface Command {
3537
val type = toml.getString(TYPE_KEY) ?: throw Exception("$key: $TYPE_KEY missing")
3638

3739
return when (type) {
38-
"menu" -> {
39-
val command = MenuCommand(parent, key, toml)
40-
toml.keySet().filter(toml::isTable)
41-
.forEach { k ->
42-
val child =
43-
createFromToml(
44-
toml.getTable(k)!!,
45-
command,
46-
k
47-
)
48-
command.children.add(child)
49-
}
50-
command
51-
}
40+
"menu" -> createMenuCommand(parent, key, toml)
5241
"talon.select" -> SelectTalonsCommand(parent, key, toml)
5342
"talon.mode" -> SelectControlModeCommand(parent, key, toml)
5443
"talon.brake" -> SelectBrakeModeCommand(parent, key, toml)
@@ -63,13 +52,25 @@ interface Command {
6352
"talon.hard.normal" -> SelectHardLimitNormalCommand(parent, key, toml)
6453
"servo.select" -> SelectServosCommand(parent, key, toml)
6554
"servo.run" -> RunServosCommand(parent, key, toml)
55+
"digital_output.select" -> SelectDigitalOutputsCommand(parent, key, toml)
56+
"digital_output.run" -> RunDigitalOutputsCommand(parent, key, toml)
6657
"swerve.azimuth" -> SetAzimuthCommand(parent, key, toml)
6758
"swerve.azimuth.save" -> SaveZeroCommand(parent, key, toml)
6859
"swerve.azimuth.select" -> SelectAzimuthCommand(parent, key, toml)
6960
"swerve.azimuth.adjust" -> AdjustAzimuthCommand(parent, key, toml)
7061
else -> DefaultCommand(parent, key, toml)
7162
}
7263
}
64+
65+
private fun createMenuCommand(parent: MenuCommand?, key: String, toml: TomlTable): MenuCommand {
66+
val command = MenuCommand(parent, key, toml)
67+
toml.keySet().filter(toml::isTable)
68+
.forEach { k ->
69+
val child = createFromToml(toml.getTable(k)!!, command, k)
70+
command.children.add(child)
71+
}
72+
return command
73+
}
7374
}
7475
}
7576

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package org.strykeforce.thirdcoast.device
2+
3+
import edu.wpi.first.wpilibj.DigitalOutput
4+
5+
class DigitalOutputService(factory: (id: Int) -> DigitalOutput) : AbstractDeviceService<DigitalOutput>(factory)
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package org.strykeforce.thirdcoast.dio
2+
3+
import edu.wpi.first.wpilibj.DigitalOutput
4+
import mu.KotlinLogging
5+
import net.consensys.cava.toml.TomlTable
6+
import org.koin.standalone.inject
7+
import org.strykeforce.thirdcoast.command.AbstractCommand
8+
import org.strykeforce.thirdcoast.command.Command
9+
import org.strykeforce.thirdcoast.command.prompt
10+
import org.strykeforce.thirdcoast.device.DigitalOutputService
11+
import org.strykeforce.thirdcoast.readInt
12+
import org.strykeforce.thirdcoast.warn
13+
14+
private val logger = KotlinLogging.logger {}
15+
16+
class RunDigitalOutputsCommand(
17+
parent: Command?,
18+
key: String,
19+
toml: TomlTable
20+
) : AbstractCommand(parent, key, toml) {
21+
22+
private val digitalOutputService: DigitalOutputService by inject()
23+
24+
override val menu: String
25+
get() = formatMenu(digitalOutputService.active.map(DigitalOutput::getInt).joinToString())
26+
27+
override fun execute(): Command {
28+
if (digitalOutputService.active.isEmpty()) {
29+
terminal.warn("no digital outputs selected")
30+
return super.execute()
31+
}
32+
var done = false
33+
34+
while (!done) {
35+
try {
36+
val setpoints = mutableListOf<Int>()
37+
digitalOutputService.active.forEach {
38+
val setpoint = reader.readInt(this.prompt("digital output ${it.channel}"), it.getInt())
39+
if (!(0..1).contains(setpoint)) throw IllegalArgumentException()
40+
setpoints += setpoint
41+
}
42+
digitalOutputService.active.forEachIndexed { i, digitalOutput ->
43+
digitalOutput.set(setpoints[i] == 1)
44+
logger.info { "set digital output ${digitalOutput.channel} to ${setpoints[i]}" }
45+
}
46+
done = true
47+
} catch (e: Exception) {
48+
terminal.warn("please enter a 0 or 1")
49+
}
50+
}
51+
52+
return super.execute()
53+
}
54+
55+
}
56+
57+
private fun DigitalOutput.getInt() = if (this.get()) 1 else 0
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package org.strykeforce.thirdcoast.dio
2+
3+
import edu.wpi.first.wpilibj.DigitalOutput
4+
import net.consensys.cava.toml.TomlTable
5+
import org.koin.standalone.inject
6+
import org.strykeforce.thirdcoast.command.AbstractCommand
7+
import org.strykeforce.thirdcoast.command.Command
8+
import org.strykeforce.thirdcoast.command.prompt
9+
import org.strykeforce.thirdcoast.device.DigitalOutputService
10+
import org.strykeforce.thirdcoast.readIntList
11+
import org.strykeforce.thirdcoast.warn
12+
13+
class SelectDigitalOutputsCommand(
14+
parent: Command?,
15+
key: String,
16+
toml: TomlTable
17+
) : AbstractCommand(parent, key, toml) {
18+
private val digitalOutputService: DigitalOutputService by inject()
19+
20+
override val menu: String
21+
get() = formatMenu(digitalOutputService.active.map(DigitalOutput::getChannel).joinToString())
22+
23+
override fun execute(): Command {
24+
while (true) {
25+
try {
26+
val channels = reader.readIntList(this.prompt("channels"))
27+
digitalOutputService.activate(channels)
28+
return super.execute()
29+
} catch (e: IllegalArgumentException) {
30+
terminal.warn("Please enter a list of Digital Output channels separated by ','")
31+
}
32+
}
33+
}
34+
}

src/main/resources/commands.toml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,21 @@ type = "menu"
335335
order = 20
336336
menu = "active servos"
337337

338+
[digital_output]
339+
type = "menu"
340+
order = 25
341+
menu = "work with digital outputs"
342+
[digital_output.set]
343+
type = "digital_output.run"
344+
order = 10
345+
menu = "set digital output"
346+
[digital_output.select]
347+
type = "digital_output.select"
348+
order = 20
349+
menu = "active digital outputs"
350+
351+
352+
338353
[swerve]
339354
type = "menu"
340355
order = 30

0 commit comments

Comments
 (0)