computePortData :: IPin -> Bool -> Arduino (Word8, Word8)
computePortData curPin newValue = do
  let curPort  = pinPort curPin
  let curIndex = pinPortIndex curPin
  bs <- gets boardState
  liftIO $ modifyMVar bs $ \bst -> do
     let values = [(pinPortIndex p, pinValue pd) | (p, pd) <- M.assocs (pinStates bst), curPort == pinPort p, pinMode pd `elem` [INPUT, OUTPUT]]
         getVal i
           | i == curIndex                             = newValue
           | Just (Just (Left v)) <- i `lookup` values = v
           | True                                      = False
         [b0, b1, b2, b3, b4, b5, b6, b7] = map getVal [0 .. 7]
         lsb = foldr (\(i, b) m -> if b then m `setBit` i     else m) 0 (zip [0..] [b0, b1, b2, b3, b4, b5, b6])
         msb = foldr (\(i, b) m -> if b then m `setBit` (i-7) else m) 0 (zip [7..] [b7])
         bst' = bst{pinStates = M.insert curPin PinData{pinMode = OUTPUT, pinValue = Just (Left newValue)}(pinStates bst)}
     return (bst', (lsb, msb))

-- | Keep track of listeners on a digital message
computePortData :: IPin -> Bool -> Arduino (Word8, Word8)
computePortData curPin newValue = do
  let curPort  = pinPort curPin
  let curIndex = pinPortIndex curPin
  bs <- gets boardState
  liftIO $ modifyMVar bs $ \bst -> do
     let values = [(pinPortIndex p, pinValue pd) | (p, pd) <- M.assocs (pinStates bst), curPort == pinPort p, pinMode pd `elem` [INPUT, OUTPUT]]
         getVal i
           | i == curIndex                             = newValue
           | Just (Just (Left v)) <- i `lookup` values = v
           | True                                      = False
         [b0, b1, b2, b3, b4, b5, b6, b7] = map getVal [0 .. 7]
         lsb = foldr (\(i, b) m -> if b then m `setBit` i     else m) 0 (zip [0..] [b0, b1, b2, b3, b4, b5, b6])
         msb = foldr (\(i, b) m -> if b then m `setBit` (i-7) else m) 0 (zip [7..] [b7])
         bst' = bst{pinStates = M.insert curPin PinData{pinMode = OUTPUT, pinValue = Just (Left newValue)}(pinStates bst)}
     return (bst', (lsb, msb))

-- | Keep track of listeners on a digital message
computePortData curPin newValue = do
  let curPort  = pinPort curPin
  let curIndex = pinPortIndex curPin
  bs <- gets boardState
  liftIO $ modifyMVar bs $ \bst -> do
     let values = [(pinPortIndex p, pinValue pd) | (p, pd) <- M.assocs (pinStates bst), curPort == pinPort p, pinMode pd `elem` [INPUT, OUTPUT]]
         getVal i
           | i == curIndex                             = newValue
           | Just (Just (Left v)) <- i `lookup` values = v
           | True                                      = False
         [b0, b1, b2, b3, b4, b5, b6, b7] = map getVal [0 .. 7]
         lsb = foldr (\(i, b) m -> if b then m `setBit` i     else m) 0 (zip [0..] [b0, b1, b2, b3, b4, b5, b6])
         msb = foldr (\(i, b) m -> if b then m `setBit` (i-7) else m) 0 (zip [7..] [b7])
         bst' = bst{pinStates = M.insert curPin PinData{pinMode = OUTPUT, pinValue = Just (Left newValue)}(pinStates bst)}
     return (bst', (lsb, msb))

-- | Keep track of listeners on a digital message