title: how do I send ACK using ruby's serialport gem?
body: <h3>gems</h3>
  
  <p>serialport (1.0.4)<br>
  Authors: Guillaume Pierronnet, Alan Stern, Daniel E. Shipton, Tobin<br>
  Richard, Hector Parra, Ryan C. Payne<br>
  Homepage: <a href="http://github.com/hparra/ruby-serialport/" rel="nofollow">http://github.com/hparra/ruby-serialport/</a><br>
  Library for using RS-232 serial ports.  </p>
  
  <h3>ruby</h3>
  
  <p>ruby 1.9.3p0 (2011-10-30 revision 33570) [x86_64-darwin11.2.0]<br>
  running under rvm 1.10.2</p>
  
  <hr>
  
  <p>I am using this gem on <strong>Mac Lion</strong>, and my device's specifications are as follows.</p>
  
  <ul>
  <li>9600bps</li>
  <li>7bits</li>
  <li>1 stop bit</li>
  <li>EVEN parity</li>
  <li><strong>RTS/CTS</strong> are used for send/receive control</li>
  </ul>
  
  <p>The driver I am using is md_PL2303_MacOSX10.6_dmg_v1.4.0.zip
  <a href="http://www.prolific.com.tw/eng/downloads.asp?id=31" rel="nofollow">http://www.prolific.com.tw/eng/downloads.asp?id=31</a></p>
  
  <p>After receiving data, I should send ACK back, to let the device know the data was ok.
  Here's how I am currently doing.</p>
  
  <pre class="lang-rb prettyprint-override"><code>sp = SerialPort.new("/dev/serial-device", 9600, 7, 1, SerialPort::EVEN)
  sp.flow_control = (SerialPort::SOFT | SerialPort::HARD)
  loop do
    data = sp.gets
    p data
    while sp.cts() == 0; end #waiting for the device if it's ok to send
    sp.putc 0x06.chr #ACK
  end
  </code></pre>
  
  <p>If the device doesn't receive ACK within 1 second after I get data (<code>data = sp.gets</code>), it will send another same data to make sure I get it ok. Currently, I am getting the 2nd same data although I am trying to send ACK like above.<br>
  *note <code>while sp.cts() == 0; end</code> doesn't take 1 second</p>
  
  <p>To be honest, I am not sure if my code is correct to send ACK.   If anybody can point out where I am doing wrong, it will be a big help.<br>
  Thanks</p>
  
  <hr>
  
  <h3>update</h3>
  
  <blockquote>
    <p><a href="http://ruby-doc.org/core-1.9.3/IO.html#method-i-putc" rel="nofollow">http://ruby-doc.org/core-1.9.3/IO.html#method-i-putc</a><br>
    putc(obj)  </p>
    
    <p>If obj is Numeric, write the character whose code is the
    least-significant byte of obj, otherwise write the first byte of the
    string representation of obj to ios. Note: This method is not safe for
    use with multi-byte characters as it will truncate them.</p>
  </blockquote>
  
  <p>so it turns out any of the 4 below will output the same.  This is what I have found so far, but the device doesn't yet recognize any of these as <code>ACK</code> and sends me the second same data...<br>
  I am thinking it's maybe beacuse of <code>flow_control</code>??  (although I tried SOFT, HARD, NONE, SOFT | HARD)</p>
  
  <pre><code>~ $ irb
  1.9.3p0 :001 &gt;
  1.9.3p0 :002 &gt;   File.open('putc.txt', 'w') do |file|
  1.9.3p0 :003 &gt;     file.putc 0x06.chr
  1.9.3p0 :004?&gt;   file.putc 0x06.ord
  1.9.3p0 :005?&gt;   file.putc 0x06
  1.9.3p0 :006?&gt;   file.putc 6
  1.9.3p0 :007?&gt;   end
   =&gt; 6
  1.9.3p0 :008 &gt;
  1.9.3p0 :009 &gt;
  1.9.3p0 :010 &gt;   data = File.read('putc.txt')
   =&gt; "\x06\x06\x06\x06"
  1.9.3p0 :011 &gt; data.bytes.to_a
   =&gt; [6, 6, 6, 6]
  1.9.3p0 :012 &gt;
  1.9.3p0 :013 &gt;   exit
  ~ $
  ~ $ od -a putc.txt
  0000000  ack ack ack ack
  0000004
  ~ $
  </code></pre>
  
  <hr>
  
  <h3>update 2</h3>
  
  <p>I tried tail -f /dev/serial-device but it didn't display, or it exited with "busy" error.<br>
   1. using tty.usbserial to send &amp; receive, tailing tty.usbserial. both didn't show anything.<br>
   2. using cu.usbserial to send &amp; receive, tailing cu.usbserial. tail gave me "busy".  </p>
  
  <p>so instead, I searched around and found dtruss command to see what's going on behind the scene.</p>
  
  <pre class="lang-rb prettyprint-override"><code>Process.pid #find this PID
  serial_port = SerialPort.new("/dev/tty.usbserial", 9600, 7, 1, SerialPort::EVEN)
  serial_port.flow_control = (SerialPort::SOFT | SerialPort::HARD)
  loop do 
    serial_port.gets
    while serial_port.cts() == 0; end
    p "before putc"
    serial_port.putc 0x06.chr
    p "after putc"
  end
  </code></pre>
  
  <p>I ran this on a terminal, and open another with <code>sudo dtruss -a -p __PID_FROM_THE_RUBY_CODE__</code> and I got something like this</p>
  
  <pre><code>11812/0xfdd0:   5737859     772     11 read(0xB2, "0\0", 0x2000)         = 1 0
  11812/0xfdd0:   5737866     208      0 sigprocmask(0x1, 0x0, 0x7FFF6FA7B340)         = 0x0 0
  11812/0xfdd0:   5737869       5      0 sigaltstack(0x0, 0x7FFF6FA7B330, 0x0)         = 0 0
  ...
  ...
  11812/0xfdd0:   5739675      16     11 write(0x1, "\"before putc\"\n\0", 0xE)        = 14 0
  11812/0xfdd0:   5739685       4      0 sigprocmask(0x1, 0x0, 0x7FFF6FA7B150)         = 0x0 0
  11812/0xfdd0:   5739686       4      0 sigaltstack(0x0, 0x7FFF6FA7B140, 0x0)         = 0 0
  11812/0xfdd0:   5739694       9      6 write(0xB2, "\006\0", 0x1)        = 1 0
  11812/0xfdd0:   5739709       5      0 sigprocmask(0x1, 0x0, 0x7FFF6FA7B1B0)         = 0x0 0
  11812/0xfdd0:   5739710       3      0 sigaltstack(0x0, 0x7FFF6FA7B1A0, 0x0)         = 0 0
  11812/0xfdd0:   5739716       8      4 write(0x1, "\"after putc\"\n\0", 0xD)         = 13 0
  </code></pre>
  
  <p><code>write(0xB2, "\006\0", 0x1)</code> this seems like it's writing <code>0x06</code>.  but I am not sure how to read this at all..<br>
  the elapsed time 5739694 - 5737859 (receiving data <code>gets</code> - sending ACK) = 1,835 micro sec, I believe. so I think I am sending ACK before 1 sec expires...</p>
  
  <p>still no clues why I get the 2nd data. (unless otherwise 1 sec is already passed before I get to send ACK..?)</p>