 
 (defn open-channel-port
   "Opens a port which can be used for listening to value changes.  In addition to the
-  options map for a basic port, the following are available:
+  options map for [[open-port]], the following are available:
   * :event-buffer-size - the size of the change events buffer.  Defaults to 1
   * :timeout - sets a timeout for the OS polling wait time.  Defaults to -1, which waits indefinitely
   * :edge - sets the edge value- :rising, :falling, or :both"

      * :direction - sets the initial direction
      * :active-low? - sets the port as \"active low\", value true or false
      * :initial-value - sets the intitial value of the pin.
      * :from-raw-fn - a converter function, which takes the `char`
          value (\1 or \0) read and converts it into a meaningful value.
          The default converts the values to :high and :low respectively "
  [port & [opts]]
  (export! port)
  (let [{:keys [from-raw-fn direction active-low? initial-value]
         :or {from-raw-fn #(if (= \1 %) :high :low)}} opts
        filename (value-file port)
        raf (random-access filename)
        props {:port port, :file-name filename, :file raf}
        gpio-port (reify
                   clojure.lang.ILookup

                   (valAt [_ k not-found] (get props k not-found))
                   (valAt [_ k] (k props))

                   GpioPort

                   (set-direction! [_ direction] (do-set-direction! port direction))

                   (set-active-low! [_ active-low?] (do-set-active-low port active-low?))

                   (read-value
                    [_]
                    (.seek raf 0)
                    (from-raw-fn (char (.read raf))))

                   (write-value!
                    [_ value]
                    (.seek raf 0)
                    (.writeByte raf (high-low-value value)))

                   Closeable
                   (close! [_]
                           (.close raf)
                           (unexport! port)))]
    (try
      (when direction (set-direction! gpio-port direction))
      (when active-low? (set-active-low! gpio-port active-low?))

          "0"   \0
          value)))

(defn- do-format 
  [raw-value high low]
  (if  (= \1 raw-value) high low))

(defmulti format-raw-digital 
  "Formats the raw values received from digital reads of pin state,
      or digital events.
      
        The type specified is a keyword."
  (fn [type _] type))

(defmethod format-raw-digital :keyword 
  [_ raw-value]
  (do-format raw-value :high :low))

(defmethod format-raw-digital :boolean
  [_ raw-value]
  (= \1 raw-value))

(defmethod format-raw-digital :symbol
  [_ raw-value]
  (do-format raw-value 'high 'low))

(defmethod format-raw-digital :integer
  [_ raw-value]
  (do-format raw-value 1 0))

(defmethod format-raw-digital :char
  [_ raw-value]
  raw-value)

(defmethod format-raw-digital :default
  [_ raw-value]
  raw-value)

(defprotocol Closeable
  (close! [self] "Closes this object"))

