Skip to content

Commit

Permalink
[software][cli] cli support for sending ir commands
Browse files Browse the repository at this point in the history
  • Loading branch information
Kezii committed Sep 5, 2024
1 parent 84e416f commit 2ddc522
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 32 deletions.
10 changes: 10 additions & 0 deletions antani_sw/src/capnp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,16 @@ pub fn deserialize_message(data: &mut &[u8]) -> Result<TaskCommand, capnp::Error
scene,
)));
}
usb_messages_capnp::badge_bound::Which::SendNecCommand(command) => {
let command = command?;

let address = command.get_address();
let _command = command.get_command();
let repeat = command.get_repeat();

return Ok(TaskCommand::SendIrNec(address, _command, repeat));
}

usb_messages_capnp::badge_bound::Which::Null(_) => {}
}

Expand Down
16 changes: 8 additions & 8 deletions antani_sw/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,12 +196,12 @@ impl LedMatrix {
#[derive(Clone, Debug)]
enum TaskCommand {
ThermalThrottleMultiplier(f32), // 1.0 = no throttle, 0.0 = full throttle
IrCommand(u8, u8, bool), // add, cmd, repeat
ReceivedIrNec(u8, u8, bool), // add, cmd, repeat
ShortButtonPress,
LongButtonPress,
MidiSetPixel(u8, u8, u8, u8), // x y channel (0=r 1=g 2=b) value
SetWorkingMode(WorkingMode),
SendIr(u8, u8, bool),
SendIrNec(u8, u8, bool),
IrTxDone,
NextPattern,
IncreaseBrightness,
Expand Down Expand Up @@ -345,7 +345,7 @@ async fn main(spawner: Spawner) {

info!("Starting loop");
mega_publisher
.publish(TaskCommand::SendIr(0, 66, false))
.publish(TaskCommand::SendIrNec(0, 66, false))
.await;

let mut timer_offset = 0.0;
Expand All @@ -368,7 +368,7 @@ async fn main(spawner: Spawner) {
warn!("Thermal throttling! {}", gain);
}
}
TaskCommand::IrCommand(addr, cmd, repeat) => {
TaskCommand::ReceivedIrNec(addr, cmd, repeat) => {
if is_transmitting {
warn!("Ignoring IR command, we are transmitting");
continue;
Expand Down Expand Up @@ -443,7 +443,7 @@ async fn main(spawner: Spawner) {
working_mode = WorkingMode::RawFramebuffer(midi_framebuffer);
}

TaskCommand::SendIr(_, _, _) => {
TaskCommand::SendIrNec(_, _, _) => {
is_transmitting = true;
}

Expand Down Expand Up @@ -561,13 +561,13 @@ async fn ir_receiver(ir_sensor: u8, publisher: MegaPublisher) {

if let Ok(Some(cmd)) = samsung_receiver.event_instant(now) {
publisher
.publish(TaskCommand::IrCommand(cmd.addr, cmd.cmd, cmd.repeat))
.publish(TaskCommand::ReceivedIrNec(cmd.addr, cmd.cmd, cmd.repeat))
.await;
}

if let Ok(Some(cmd)) = nec_receiver.event_instant(now) {
publisher
.publish(TaskCommand::IrCommand(cmd.addr, cmd.cmd, cmd.repeat))
.publish(TaskCommand::ReceivedIrNec(cmd.addr, cmd.cmd, cmd.repeat))
.await;
}
}
Expand All @@ -592,7 +592,7 @@ async fn ir_blaster_tsk(
}

loop {
if let TaskCommand::SendIr(addr, cmd, repeat) = subscriber.next_message_pure().await {
if let TaskCommand::SendIrNec(addr, cmd, repeat) = subscriber.next_message_pure().await {
const FREQUENCY: u32 = 20000;

let mut buffer: infrared::sender::PulsedataSender<128> =
Expand Down
12 changes: 9 additions & 3 deletions antani_sw/usb_messages.capnp
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

struct BadgeBound {
union {
setFrameBuffer @0 :SetFrameBuffer;
setSolidColor @1 :RGB8;
null @2 :Void;
null @0 :Void;
setFrameBuffer @1 :SetFrameBuffer;
setSolidColor @2 :RGB8;
sendNecCommand @3 :NecCommand;
}
}

Expand All @@ -18,3 +19,8 @@ struct RGB8 {
b @2 :UInt8;
}

struct NecCommand {
address @0 :UInt8;
command @1 :UInt8;
repeat @2 :Bool;
}
30 changes: 28 additions & 2 deletions minibage-cli/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ To run the CLI tool, just run `cargo run -- --help` in this directory.

```
> cargo run -q -- --help
Usage: minibage-cli [OPTIONS]
Usage: minibage-cli [OPTIONS] [COMMAND]
Commands:
send-nec Use the badge to send an infrared NEC command
help Print this message or the help of the given subcommand(s)
Options:
-s, --serial-port <SERIAL_PORT>
Expand All @@ -31,12 +35,30 @@ Options:
-m, --midi-demo <MIDI_DEMO>
Demo application to use the badge with the midi interface This does not do anything useful, it's just a demo to show how to use the midi interface
The argument is the path to a midi device For example: /dev/midi3
The argument is the path to a midi device For example: /dev/midi3c
-h, --help
Print help (see a summary with '-h')
```

### Infrared subcommand

```
> cargo run -q -- help send-nec
Use the badge to send an infrared NEC command
Usage: minibage-cli send-nec [OPTIONS] --address <ADDRESS> --command <COMMAND>
Options:
-a, --address <ADDRESS> NEC address
-c, --command <COMMAND> NEC command
-r, --repeat Repeat
-h, --help Print help
```

IR commands can be debugged / received with the badge itself, just open the debug CDC interface with a serial terminal.

## Examples

```sh
Expand All @@ -49,4 +71,8 @@ cargo run -q -- -s /dev/ttyACM0 -f "#ff0000 #00ff00 #0000ff #ff00ff #00ffff #fff

```sh
cargo run -q -- -m /dev/midi3
```

```sh
cargo run -q -- -s /dev/ttyACM0 send-nec --address 7 --command 22
```
70 changes: 55 additions & 15 deletions minibage-cli/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
use std::{
io::Write,
time::Duration,
};
use std::{io::Write, time::Duration};

mod midi;

use clap::Parser;
use clap::{Args, Parser, Subcommand};

use capnp::message::Builder;
use capnp::serialize;
Expand All @@ -16,12 +13,12 @@ pub mod usb_messages_capnp {
include!(concat!(env!("OUT_DIR"), "/usb_messages_capnp.rs"));
}

#[derive(Parser, Debug)]
struct Args {
#[derive(Parser)]
struct Cli {
/// Serial port for communicating with the badge
///
///
/// This is the management interface with capnp, not the debug interface
///
///
/// Defaults to /dev/ttyACM0
#[arg(short, long)]
serial_port: Option<String>,
Expand All @@ -32,20 +29,42 @@ struct Args {
solid_color: Option<String>,

/// Frame buffer to send to the badge.
///
///
/// The frame buffer is a string with 9 "css" colors separated by spaces
/// like "#ff0000 #00ff00 [...]"
#[arg(short, long)]
frame_buffer: Option<String>,

/// Demo application to use the badge with the midi interface
/// This does not do anything useful, it's just a demo to show
/// This does not do anything useful, it's just a demo to show
/// how to use the midi interface
///
///
/// The argument is the path to a midi device
/// For example: /dev/midi3c
#[arg(short, long)]
midi_demo: Option<String>,

#[command(subcommand)]
subcommand: Option<Subcommands>,
}

#[derive(Subcommand)]
enum Subcommands {
/// Use the badge to send an infrared NEC command
SendNec(SendNec),
}

#[derive(Args, Debug)]
struct SendNec {
/// NEC address
#[arg(short, long)]
address: u8,
/// NEC command
#[arg(short, long)]
command: u8,
/// Repeat
#[arg(short, long)]
repeat: bool,
}

fn hex_color_to_rgb(color: String) -> RGB8 {
Expand All @@ -70,7 +89,7 @@ fn midi_demo(file: String) {
}

fn main() {
let args = Args::parse();
let args = Cli::parse();

// we don't need serial for the midi demo
// let it f*ck off before everything else
Expand All @@ -88,9 +107,30 @@ fn main() {
.open()
.expect("Failed to open port");

if let Some(fb) = args.frame_buffer {
#[allow(clippy::single_match)]
match args.subcommand {
Some(Subcommands::SendNec(send_nec)) => {
let mut message = Builder::new_default();

let badgebound = message.init_root::<usb_messages_capnp::badge_bound::Builder>();

let mut nec = badgebound.init_send_nec_command();
nec.set_address(send_nec.address);
nec.set_command(send_nec.command);
nec.set_repeat(send_nec.repeat);

let data = serialize::write_message_to_words(&message);

let split = fb.split(" ").map(|s| s.to_string()).collect::<Vec<String>>();
port.write_all(&data).expect("Failed to write to port");
}
None => {}
}

if let Some(fb) = args.frame_buffer {
let split = fb
.split(" ")
.map(|s| s.to_string())
.collect::<Vec<String>>();

if split.len() != 9 {
println!("Frame buffer must be 9 elements long");
Expand Down
2 changes: 0 additions & 2 deletions minibage-cli/src/midi.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@


use std::{
fs::OpenOptions,
io::{self, Read, Write},
Expand Down
5 changes: 3 additions & 2 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ This is the first official ESC badge with a microcontroller!
- JTAG and expansion pads

## Software Features
- Somewhat fully featured and composable animation engine for light effects and patterns
- Fully featured and composable animation engine for light effects and patterns
- A lot of built-in animations, more can be added easily
- IR remote control support
- IR remote control support (NEC and Samsung NEC), commands can be added easily
- IR transmitter (NEC), badge-to-badge communication
- USB CDC for debug and control
- USB MIDI for control (you can send standard MIDI messages to control the lights)
- Automatic overheating protection
Expand Down

0 comments on commit 2ddc522

Please sign in to comment.