ir-cock-grenade/usb ir toy/ir.rb

210 lines
4.9 KiB
Ruby
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env ruby
# encoding: UTF-8
# tested with ruby 1.9.1 and 1.9.3
# USB IR Toy tool
# based on http://dangerousprototypes.com/docs/USB_IR_Toy:_Sampling_mode
require 'serialport'
# display debug messages
@debug = false
def help
puts "USB IR Toy tool"
puts ""
puts "option:"
puts "\t--help,-h\t\tdisplay this help"
puts "\t--device,-d <device>\tuse this serial port"
puts "\t--record,-r <file>\trecord IR stream into this file"
puts "\t--play,-p <file>\tplay IR activity from this file"
puts "\t--freq,-f\t\tdetect frequency of IR signal"
puts "\t--laser,-l\t\tuse lasertag frequency (56kHz) when transmitting"
puts "\t--traffic,-t\t\tshow communication traffic with USB IR toy"
exit 0
end
device = "/dev/ttyACM0"
mode = :record
file = nil
fast = false # false = default 38.4kHz, true = 56kHz
while argument = ARGV.shift do
case argument
when "--help","-h"
help
when "--device","-d"
raise "no device specified" unless device = ARGV.shift
when "--record","-r"
raise "no file specified" unless file = ARGV.shift
file = File.open(file,"w")
mode = :record
when "--play","-p"
raise "no file specified" unless file = ARGV.shift
file = File.open(file,"r")
mode = :play
when "--freq","-f"
mode = :freq
when "--laser","-l"
fast = true
when "--traffic","-t"
@debug = true
else
help
end
end
# read n bytes from serial
def read(bytes)
data = @serial.read bytes
str = "> "
data.bytes {|b| str += "%02x " % b}
puts str if @debug
return data
end
# write data to serial
def write(data)
to_send = nil
to_send = case data
when Fixnum
[data].pack "C"
when Array
data.pack "C*"
when String
data
else
raise "unknown data format to send"
end
str = "< "
to_send.bytes {|b| str += "%02x " % b}
puts str if @debug
@serial.write to_send
end
# open serial to USB IR Toy (adapt device path. any baudrate is accepted)
print "opening serial port #{device}"
$stdout.flush
@serial = SerialPort.new(device,115200)
@serial.read_timeout = 0
puts ""
print "reseting … "
$stdout.flush
# empty buffer
@serial.read_timeout = 500
loop while @serial.read(1)
@serial.read_timeout = 0
5.times do
write [0x00]
end
puts ""
sleep 0.5
print "getting version … "
$stdout.flush
write 'v'
@serial.read_timeout = 500
version = read 4
@serial.read_timeout = 0
if version and version.length==4 then
puts "HW v#{version[1,1]}, FW v#{version[2,2]}"
else
puts "USB IR Toy is stuck. un- and re-plug it"
exit 0
end
print "enter sampling mode … "
$stdout.flush
write 's'
protocol = nil
begin
protocol = read 3
end until protocol and protocol.length==3
puts "protocol version: #{protocol}"
case mode
when :record
STATES = ["","_"]
state = 0
unit = 21.3333 #us
loop do
data = read 2
time = data.unpack('n')[0]
if time==0xffff then
puts "|"
else
print "#{STATES[state%2]}#{(time*unit/100).round}#{STATES[state%2]}"
end
$stdout.flush
state += 1
file.write data if file
end
when :play
if fast then
puts "setting transmit modulation to 56kHz used by lasertag"
# use command http://dangerousprototypes.com/docs/USB_IR_Toy:_Sampling_mode#Setup_transmit_modulation_.280x06.29
# use value from http://www.micro-examples.com/public/microex-navig/doc/097-pwm-calculator (55555.56kHz)
write [0x06,0x35,0x00]
end
print "enter transmit mode (with handshake) … "
$stdout.flush
write 0x24 # enable by count report
write 0x25 # notify on complete
write 0x26 # handshake
puts ""
buffer = 0 # free buffer size
burst = true # start new burst transmittion
while data = file.read(2) do
if burst then
burst = false
buffer = 0
write 0x03 # transmit
puts "transmitting burst"
end
# wait for free buffer
if buffer<=0 then
buffer=read(1).unpack("C")[0]
puts "new buffer size: #{buffer}"
end
write data
buffer -= data.size
if data.unpack('n')[0]==0xffff then
# restart transmit
burst = true
# last handshake(s) until count byte
begin
report = read(1)
sleep 1
end until report and report[0]=='t'
# byte count
count = read(2)
puts "#{count[0,2].unpack('n')[0]} bytes processed"
# notification
case tmp=read(1)
when "C"
puts "transmission complete"
when "F"
puts "buffer underrun"
else
puts "unknown notification: #{tmp}"
end
sleep 1
end
end
when :freq
print "waiting for a burst … "
loop until read(2).unpack('n')[0]==0xffff
$stdout.flush
puts ""
write 0x04
data = read(8).unpack('n*')
# PIC clock is 12MHz
clock = 1.0/12E6
freq1 = (1/(clock*(data[0])))/(1E3)
freq2 = (1/(clock*(data[1]-data[0])))/(1E3)
freq3 = (1/(clock*(data[2]-data[1])))/(1E3)
puts "detected frequency: #{freq1.round(2)}kHz, #{freq2.round(2)}kHz, #{freq3.round(2)}kHz"
else
puts "unknown mode #{mode}"
end