 (defrecord SimBoard
   [pin-state pin-modes edge-channels config]
   pcp/PBoard
-  (pin-modes [_] (:pin-modes config))
-  (current-pin-modes [_] @pin-modes)
-  (get-config [_] config)
-  (update-config [this f] (update-in this [:config] f))
+  (available-pin-modes [_] (:pin-modes config))
+  (pin-modes [_] @pin-modes)
 
   pcp/POverwireBoard
   (reset-board! [_]


;; This stuff really needs to be part of the core library

(def full-available-modes
  #{:input :output :ain :aout :pwm})

(def available-modes
  #{:gpio :ain :aout :pwm})

(def mode-mapping
  {:gpio [:input :output :input-rising :input-falling :input-both]
   :ain  [:ain]
   :aout [:aout]
   :pwm  [:pwm]})

(def cannonical-value
  {:high  :high
   "high" :high
   1      :high
   \1     :high
   :low   :low
   "low"  :low
   0      :low
   \0     :low})


;; Here we're going to declare some of the things we'll need in the implementation that we'd rather leave at
;; the end of this namespace for logical flow.

(declare current-pin-mode writeable-pin? ok-val?)

(defmulti read-pin*
  "Inner method for reading from a pin; dispatches on pin mode"
  (fn [board pin-n]
    (pc/current-pin-modes board) pin-n))


;; In addition to the standard protocol functions, we also need something which let's us set the state of
;; _input_ input pins for the purposes of simulation, since (for obvious reasons) this is not supported via

    (swap! pin-modes assoc pin-n mode))

  pcp/PReadablePin
  (read-value [board pin-n mode]
    (get (deref (:pin-state board)) pin-n))

  pcp/PWriteablePin
  (write-value! [board pin-n mode val]
    (swap! pin-state assoc pin-n val))

  pcp/PEdgeDetectablePin
  (set-edge! [board pin-n edge ch]
    (let [match (case edge
                  (:none "edge")       #{}
                  (:rising "rising")   #{:high}
                  (:falling "falling") #{:low}
                  (:both "both")       #{:high :low})]
      (add-watch pin-state
                 ; May have to have board ids involved in this scheme for overwire; 
                 ; should have global registry of these board ids XXX
                 (symbol (str "edge-detection-watch-simulator" pin-n))
                 (fn [_ _ _ new-val]
                   (when (match new-val)
                     (>!! ch new-val))))))

  PSimControl
  (set-state! [board pin-n val]
    (assert (ok-val? board pin-n val)
            (str "The value " val " is not an acceptable value for pins of type " (current-pin-mode board pin-n)))
    (swap! pin-state assoc pin-n)))

;; Now we'll flesh out some of the various reading/writing functions

(defn pin-mode
  [board pin-n]
  (get (pcp/pin-modes board) pin-n))

(defn writeable-pin?
  [board pin-n]
  (#{:output :pwm} (pin-mode board pin-n)))

(defn ok-val?
  [board pin-n val]
  (case (current-pin-mode board pin-n)
    :output (#{0 1 \0 \1 :high :low} val)
    :pwm    #(and (<= 0 %) (>= 1 %))
    false))


