module System.Hardware.Arduino.Utils where
import Control.Concurrent (threadDelay)
import Data.Bits ((.|.), shiftL, (.&.), shiftR)
import Data.Char (isAlphaNum, isAscii, isSpace, chr)
import Data.IORef (newIORef, readIORef, writeIORef)
import Data.List (intercalate)
import Data.Word (Word8, Word32)
import Data.Time (getCurrentTime, utctDayTime)
import Numeric (showHex, showIntAtBase)
delay :: Int -> IO ()
delay n = threadDelay (n*1000)
mkDebugPrinter :: Bool -> IO (String -> IO ())
mkDebugPrinter False = return (const (return ()))
mkDebugPrinter True = do
cnt <- newIORef (1::Int)
let f s = do i <- readIORef cnt
writeIORef cnt (i+1)
tick <- utctDayTime `fmap` getCurrentTime
let precision = 1000000 :: Integer
micro = round . (fromIntegral precision *) . toRational $ tick
putStrLn $ "[" ++ show i ++ ":" ++ show (micro :: Integer) ++ "] hArduino: " ++ s
return f
showByte :: Word8 -> String
showByte i | isVisible = [c]
| i <= 0xf = '0' : showHex i ""
| True = showHex i ""
where c = chr $ fromIntegral i
isVisible = isAscii c && isAlphaNum c && isSpace c
showByteList :: [Word8] -> String
showByteList bs = "[" ++ intercalate ", " (map showByte bs) ++ "]"
showBin :: (Integral a, Show a) => a -> String
showBin n = showIntAtBase 2 (head . show) n ""
getString :: [Word8] -> String
getString = map (chr . fromIntegral) . fromArduinoBytes
fromArduinoBytes :: [Word8] -> [Word8]
fromArduinoBytes [] = []
fromArduinoBytes [x] = [x]
fromArduinoBytes (l:h:rest) = c : fromArduinoBytes rest
where c = h `shiftL` 7 .|. l
toArduinoBytes :: Word8 -> [Word8]
toArduinoBytes w = [lo, hi]
where lo = w .&. 0x7F
hi = (w `shiftR` 7) .&. 0x7F
word2Bytes :: Word32 -> [Word8]
word2Bytes i = map fromIntegral [(i `shiftR` 24) .&. 0xFF, (i `shiftR` 16) .&. 0xFF, (i `shiftR` 8) .&. 0xFF, i .&. 0xFF]
bytes2Words :: (Word8, Word8, Word8, Word8) -> Word32
bytes2Words (a, b, c, d) = fromIntegral a `shiftL` 24 .|. fromIntegral b `shiftL` 16 .|. fromIntegral c `shiftL` 8 .|. fromIntegral d