#!/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 \tuse this serial port" puts "\t--record,-r \trecord IR stream into this file" puts "\t--play,-p \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