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

210 lines
4.9 KiB
Ruby
Raw Normal View History

2015-02-21 10:23:02 +01:00
#!/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