<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -16,6 +16,12 @@ http://www.ambx.com
 
 == Device information ==
 
+The device has 3 endpoints
+
+*0x02 - Out 
+*0x81 - In
+*0x83 - In - Constantly polled, used for plug and play detection
+
 == Protocol Information ==
 
 The AmbX Communications protocol works over full-speed USB 2.0. It
@@ -48,6 +54,32 @@ Remaining bytes are parameters to the send command, and are specific
 to the command. In the example, 0x00 0x00 0x00 means that the color to
 be set in the left wall washer unit light is black.
 
+=== Internal Device Addresses
+
+0x0B::
+Left Speaker light
+0x1B::
+Right Speaker light
+0x2B::
+Left (when viewed from front) Wall Washer light
+0x3B::
+Middle Wall Washer light
+0x4B::
+Right Wall Washer light
+0x5B::
+Left Fan
+0x6B::
+Right Fan
+0x7B::
+Vibration Bar
+0x7C::
+Also Vibration Bar?
+
+== Initialization ==
+
+There's some sort of initialization step when the device is
+connected. What is it?
+
 ==  Light Commands ==
 
 === Set Light To Color ===
@@ -68,9 +100,10 @@ Unknown
 to.
 
 ==== Example Command ====
+
+.Set Left Wall Washer Light to Full Blue
 -----------------------
-Index: 01 23 45 67 89 AB
- Data: A1 2B 03 00 00 00 
+A1 2B 03 00 00 FF
 -----------------------
 
 === Timed Color Sequence ===
@@ -131,8 +164,198 @@ This tells the left-most light (0x2B) to iterate through the following
 
 == Fan Commands ==
 
+=== Set Fan to Speed ===
+
+==== Description ====
+Given the address of a fan, sets it to a certain speed
+
+==== Setup Requirements ====
+Unknown
+
+==== Command Index ====
+----
+0x01
+----
+
+==== Parameters ====
+1 byte, speed to set fan to
+
+==== Example Command ====
+
+.Set Right Fan to Full Speed
+-----------------------
+Data: A1 6B 01 FF
+-----------------------
+
+=== Timed Fan Sequence ===
+
+==== Description ====
+Given the address of a fan and a delay value, iterate through a list
+of speeds, holding each speed for the specified delay value.
+
+==== Setup Requirements ====
+Unknown
+
+==== Command Index ====
+----
+0x74
+----
+
+==== Parameters ====
+Byte 3 (Nibbles 6-7) and 4 (Nibbles 8-9) denote the 16-bit delay time,
+in milliseconds. After that, a list of up to 48 8-bit speeds.
+
+==== Example Command ====
+
+.Full Command
+-----------------------------------------------
+61 6B 72 00 8A 68 00 65 00 61 00 5E 00 5B 00 58 
+00 54 00 51 00 4E 00 4B 00 47 00 44 00 41 00 3D 
+00 3A 00 37 00 34 00 30 00 2D 00 2A 00 26 00 23 
+00 20 00 00 00
+-----------------------------------------------
+
+.Command
+--------------
+61 6B 72 00 8A
+--------------
+
+This tells the right fan (0x6B) to iterate through the following
+48 speeds, holding for 138ms (0x008A) at each speed
+
+.Speed Portion
+---------
+68 
+00 
+65 
+00 
+61 
+00 
+5E 
+00 
+5B
+00 
+58 
+00 
+54 
+00 
+51 
+00 
+4E 
+00 
+4B 
+00 
+47 
+00 
+44 
+00 
+41 
+00 
+3D 
+00 
+3A 
+00 
+37 
+00 
+34 
+00 
+30 
+00 
+2D 
+00 
+2A 
+00 
+26 
+00 
+23 
+00 
+20 
+00 
+00 
+00
+---------
+
 == Rumble Commands ==
 
+=== Timed Vibration Sequence ===
+
+==== Description ====
+Given the address of a rumble bar and a delay value, iterate through a list
+of speeds, holding each speed for the specified delay value.
+
+==== Setup Requirements ====
+Unknown
+
+==== Command Index ====
+----
+0x74
+----
+
+==== Parameters ====
+Byte 3 (Nibbles 6-7) and 4 (Nibbles 8-9) denote the 16-bit delay time,
+in milliseconds. After that, a list of up to 24 8-bit pairs (right and left
+motor) of speeds.
+
+==== Example Command ====
+
+.Full Command
+-----------------------------------------------
+61 7B 72 00 8A 68 00 65 00 61 00 5E 00 5B 00 58 
+00 54 00 51 00 4E 00 4B 00 47 00 44 00 41 00 3D 
+00 3A 00 37 00 34 00 30 00 2D 00 2A 00 26 00 23 
+00 20 00 00 00
+-----------------------------------------------
+
+.Command
+--------------
+61 7B 72 00 8A
+--------------
+
+This tells the rumble bar (0x7B) to iterate through the following
+24 speeds, holding for 138ms (0x008A) at each speed
+
+.Speed Portion
+---------
+68 00 
+65 00 
+61 00 
+5E 00 
+5B 00 
+58 00 
+54 00 
+51 00 
+4E 00 
+4B 00 
+47 00 
+44 00 
+41 00 
+3D 00 
+3A 00 
+37 00 
+34 00 
+30 00 
+2D 00 
+2A 00 
+26 00 
+23 00 
+20 00 
+00 00
+---------
+
+== Questions ==
+
+* The 0x7? commands seem to be basically equivilent between devices
+  and usage, i.e 0x72 and 0x74 seem to do the same thing?
+* What is the 0x7C device? The rumble bar reacts to it?
+* What do the following messages mean? They keep showing up (X denotes
+  first iteration nibble, can be ignored)
+** X1 F2 01 07
+** The following pair, which always comes in order
+*** X1 01 03 00 00 3B
+*** X1 01 03 00 3B 3B
+** X1 Y1 00 01 08 - Where Y is 0-8?
+
+
 == Further Information ==
 
 For further information, visit:</diff>
      <filename>doc/ambx_protocol_notes.asciidoc</filename>
    </modified>
    <modified>
      <diff>@@ -1,18 +1,72 @@
-from optparse import OptionParser
+#################################################################
+# python amBX controller object
+# By Kyle Machulis &lt;kyle@nonpolynomial.com&gt;
+# http://www.nonpolynomial.com
+#
+# Distributed as part of the libambx project
+#
+# Website: http://qdot.github.com/libambx
+# Repo: http://www.github.com/qdot/libambx
+#
+# Licensed under the BSD License, as follows
+#
+# Copyright (c) 2009, Kyle Machulis/Nonpolynomial Labs
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, 
+# with or without modification, are permitted provided 
+# that the following conditions are met:
+#
+#    * Redistributions of source code must retain the 
+#      above copyright notice, this list of conditions 
+#      and the following disclaimer.
+#    * Redistributions in binary form must reproduce the 
+#      above copyright notice, this list of conditions and 
+#      the following disclaimer in the documentation and/or 
+#      other materials provided with the distribution.
+#    * Neither the name of the Nonpolynomial Labs nor the names 
+#      of its contributors may be used to endorse or promote 
+#      products derived from this software without specific 
+#      prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+# CONTRIBUTORS &quot;AS IS&quot; AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
+# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#################################################################
+
 import sys
+
+#Requires PyUSB
+#http://pyusb.berlios.de/
+
 import usb
 
 class ambx:
-    #device variables
+    
+    #Device as retreived from the bus listing
     ambx_device = None
+    #Handle to access the device with
     ambx_handle = None
+    #Internal command index holder. Counts to 0xf, rolls over, starts again
     command_index = 0
+    #Set to true to print out debug messages
     debug = False
 
+    #VID/PID for amBX Controller
     AMBX_VENDOR_ID = 0x0471
     AMBX_PRODUCT_ID = 0x083F
     
-    #device addresses
+    #Conveinence strings for device addresses
     LEFT_SP_LIGHT = 0x0B
     RIGHT_SP_LIGHT = 0x1B
     LEFT_WW_LIGHT = 0x2B
@@ -22,27 +76,39 @@ class ambx:
     RIGHT_FAN = 0x6B
     RUMBLE = 0x7B
 
-    #command indexes
+    #Conveinence strings for device commands
     cmd = { 'SetLightColor'     : 0x03, \
                 'SetListWithDelay'  : 0x72, \
                 'SetFanSpeed'       : 0x01  \
                 } 
         
-    #endpoints
+    #Conveinence strings for device endpoints
     ep = { 'in'  : 0x81, \
                'out' : 0x02, \
                'pnp' : 0x83 \
                }
 
-        
+    #Constructor
     def __init__(self):
         return
 
+    #Function for flattening embedded lists
     #found at http://www.daniel-lemire.com/blog/archives/2006/05/10/flattening-lists-in-python/
     def flattenList(self, l):
+        &quot;&quot;&quot; Given a list of embedded lists, flattens them into a 
+        single list 
+        
+        Returns flattened list.
+        &quot;&quot;&quot;
         return reduce(lambda a, b: isinstance(b, (list, tuple)) and a+list(b) or a.append(b) or a, l, [])
 
     def open(self, index = 0):
+        &quot;&quot;&quot; Given an index, opens the related ambx device. The index refers
+        to the position of the device on the USB bus. Index 0 is default, 
+        and will open the first device found.
+
+        Returns True if open successful, False otherwise.
+        &quot;&quot;&quot;
         device_count = 0
         for bus in usb.busses():
             devices = bus.devices
@@ -60,57 +126,107 @@ class ambx:
         return True
 
     def close(self):
+        &quot;&quot;&quot;Closes the amBX device currently held by the object, 
+        if it is open.&quot;&quot;&quot;
         if self.ambx_handle is not None:
             self.ambx_handle.releaseInterface() 
             self.ambx_handle = None
 
     def write(self, command):
+        &quot;&quot;&quot;Given a list of raw bytes, writes them to the out endpoint of the
+        ambx controller.
+
+        Returns total number of bytes written.
+        &quot;&quot;&quot;
         if self.debug:
             [sys.stdout.write(&quot;0x%.2x &quot; % ord(x)) for x in command]        
             print
-        self.ambx_handle.bulkWrite(self.ep['out'], command, 1)
+        return self.ambx_handle.bulkWrite(self.ep['out'], command, 1)
 
-    def read(self, status, size=64):
+    def read(self, size=64):
+        &quot;&quot;&quot;Reads in the requested amount of bytes
+        from the in endpoint of the ambx device.
+        
+        Returns list of bytes read.
+        &quot;&quot;&quot;
         status = self.ambx_handle.bulkRead(self.ep['in'], size, 1)
 
     def compileCommand(self, address, command, parameters):
+        &quot;&quot;&quot;Given an address (1 byte), command (1 byte), and parameter (list),
+        compiles them into a single array of bytes to send to the device. Also
+        manages the incrementing of the command sequence value.&quot;&quot;&quot;
         if self.debug:
             print 'Building Command: %x %x %x %s' % ((((((self.command_index % 16)) &lt;&lt; 4) | 1)), address, self.cmd[command], parameters)
-        compiled_command = [(((self.command_index % 16)) &lt;&lt; 4) | 1, address, self.cmd[command]]
+        compiled_command = [(((self.command_index % 16)) &lt;&lt; 4) | 1, 
+                            address, self.cmd[command]]
         self.command_index += 1        
         compiled_command.extend(self.flattenList(parameters))
         return map(chr, compiled_command)
 
     def expandDelay(self, delay):
+        &quot;&quot;&quot;Given a delay value, expands it into the 2 byte list required for
+        command consumption (i.e. a list consisting of the upper and lower 
+        bytes)&quot;&quot;&quot;
         if delay &lt; 255:
             return [0, delay]
         return [(delay &amp; 0xff00) &gt;&gt; 8, delay &amp; 0xff] 
 
     def setLightColor(self, light, color):
+        &quot;&quot;&quot;Given a light address and a color (list of 3 integers, in R, G, B
+        order), sets the light to that color&quot;&quot;&quot;
         self.write(self.compileCommand(light, 'SetLightColor', color))
         return
 
     def setLightColorList(self, light, delay, color_list):
-        self.write(self.compileCommand(light, 'SetListWithDelay', [self.expandDelay(delay), self.flattenList(color_list)]))
+        &quot;&quot;&quot;Given 
+        
+        - a light address
+        - a delay value, in milliseconds 
+        - a list of up to 16 colors 
+        -- one list of 3 integers per color, in R, G, B order
+
+        replays the list at that address, holding at each value for the 
+        specified delay time&quot;&quot;&quot;
+        self.write(self.compileCommand(light, 'SetListWithDelay',[self.expandDelay(delay), self.flattenList(color_list)]))
         return
         
     def setFanSpeed(self, fan, speed):
+        &quot;&quot;&quot;Given a fan address and a speed, sets the fan to that speed&quot;&quot;&quot;
         self.write(self.compileCommand(fan, 'SetFanSpeed', [speed]))
         return
 
     def setFanSpeedList(self, fan, delay, speed_list):
+        &quot;&quot;&quot;Given 
+
+        - a fan address 
+        - a delay value, in milliseconds
+        - a list of up to 48 speeds
+        -- speed is just a bare integer, so a single list of up to 48 integers
+
+        replays the list at that address, holding at each value for the 
+        specified delay time&quot;&quot;&quot;
         self.write(self.compileCommand(fan, 'SetListWithDelay', [self.expandDelay(delay), speed_list]))
         return
 
     def setRumbleSpeed(self, rumble, speed):
+        &quot;&quot;&quot;Given a rumble address and a speed (list of two values, for right and
+        left rumble motors), sets the rumble strip to that speed&quot;&quot;&quot;
         return
 
     def setRumbleSpeedList(self, rumble, delay, speed_list):
+        &quot;&quot;&quot;Given 
+
+        - a rumble address
+        - a delay value
+        - a list of up to 24 speeds
+        -- one list of 2 integers per speed, for left/right motor
+
+        replays the list at that address, holding at each value for the 
+        specified delay time
+        &quot;&quot;&quot;
         self.write(self.compileCommand(rumble, cmd['SetListWithDelay'], [self.expandDelay(delay), speed_list]))
         return
     
-
-
 def main(argv=None):
     ambx_device = ambx()
     ambx_device.debug = True</diff>
      <filename>python/ambx.py</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>499b77e38c8a9599c8c595a527fccf55af17a331</id>
    </parent>
  </parents>
  <author>
    <name>Kyle Machulis</name>
    <email>kyle@nonpolynomial.com</email>
  </author>
  <url>http://github.com/qdot/libambx/commit/c40bc8bea57e053459f61cdfdd2d27e8f22e5bb7</url>
  <id>c40bc8bea57e053459f61cdfdd2d27e8f22e5bb7</id>
  <committed-date>2009-05-03T20:00:20-07:00</committed-date>
  <authored-date>2009-05-03T20:00:20-07:00</authored-date>
  <message>Added endpoint information and device addresses to asciidoc
Updated documentation in ambx python object</message>
  <tree>c84917f54ee9837ba9287134f5634eee2585890d</tree>
  <committer>
    <name>Kyle Machulis</name>
    <email>kyle@nonpolynomial.com</email>
  </committer>
</commit>
