packages feed

HPi 0.2.0 → 0.3.0

raw patch · 2 files changed

+33/−30 lines, 2 files

Files

HPi.cabal view
@@ -2,7 +2,7 @@ -- see http://haskell.org/cabal/users-guide/
 
 name:                HPi
-version:             0.2.0
+version:             0.3.0
 synopsis:            GPIO and I2C functions for the Raspberry Pi.
 description:         This package is a FFI wrapper around the bcm2835 library by Mike McCauley, it also includes a few utility functions for easier use of the imported functions.
 homepage:            https://github.com/WJWH/HPi
@@ -10,7 +10,7 @@ license-file:        LICENSE
 author:              Wander Hillen	
 maintainer:          wjw.hillen@gmail.com
--- copyright:           
+copyright:           (c) 2013 Wander Hillen
 category:            System
 build-type:          Simple
 cabal-version:       >=1.8
@@ -18,4 +18,8 @@ library
   exposed-modules:     System.RaspberryPi.GPIO
   -- other-modules:       
-  build-depends:       base ==4.5.*, bytestring ==0.9.*+  build-depends:       base ==4.5.*, bytestring ==0.9.*
+  
+source-repository head
+  type:     git
+  location: git://github.com/WJWH/HPi.git
System/RaspberryPi/GPIO.hs view
@@ -34,7 +34,7 @@ import Foreign.C
 import Foreign.C.String
 import qualified Data.ByteString as BS
-import qualified Data.ByteString.Char8 as BSC
+-- import qualified Data.ByteString.Char8 as BSC
 import GHC.IO.Exception
 
 ------------------------------------------------------------------------------------------------------------------------------------
@@ -93,7 +93,7 @@ -- writes some bytes to the bus
 foreign import ccall unsafe "bcm2835.h bcm2835_i2c_write" c_writeI2C :: CString -> CUInt -> IO CUChar
 --read some bytes from the bus
-foreign import ccall unsafe "bcm2835.h bcm2835_i2c_read" c_readI2c :: CString -> CUShort -> IO CUChar
+foreign import ccall unsafe "bcm2835.h bcm2835_i2c_read" c_readI2C :: CString -> CUShort -> IO CUChar
 --reads a certain register with the repeated start method
 foreign import ccall unsafe "bcm2835.h bcm2835_i2c_read_register_rs" c_writeReadI2C :: CString -> CString -> CUShort -> IO CUChar
 
@@ -112,13 +112,22 @@ 
 -- |Any IO computation that uses the I2C bus using this library should be wrapped with this function; ie @withI2C $ do foo@.
 -- It prepares the relevant pins for use with the I2C protocol and makes sure everything is safely returned to normal if an exception
--- occurs. WARNING: after this function returns, the I2C pins will be set to Input, so use 'setPinFunction' if you want to use them 
--- for output.
+-- occurs. If you only use the GPIO pins for I2C, you can do @withGPIO . withI2C $ do foo@ and it will work as expected. WARNING: 
+-- after this function returns, the I2C pins will be set to Input, so use 'setPinFunction' if you want to use them for output.
 withI2C :: IO a -> IO a
 withI2C f = bracket_    initI2C
                         stopI2C
                         f
 
+--
+actOnResult :: CUChar -> CString -> IO BS.ByteString
+actOnResult rr buf = case rr of
+    0x01 -> throwIO $ IOError Nothing IllegalOperation "I2C: " "Received an unexpected NACK." Nothing Nothing
+    0x02 -> throwIO $ IOError Nothing IllegalOperation "I2C: " "Received Clock Stretch Timeout." Nothing Nothing 
+    0x04 -> throwIO $ IOError Nothing IllegalOperation "I2C: " "Not all data was read." Nothing Nothing
+    0x00 -> BS.packCString buf --convert C buffer to a bytestring
+
+
 -- Mapping raspberry pi pin number to internal bmc2835 pin number, ugly solution, but meh. Also, the existence of mutiple versions
 -- of the pin layout makes this the most elegant solution without resorting to state monads (which I don't want to do because that
 -- would hamper the simplicity of having writePin and readPin be simple IO actions). As this function isn't exported anyway, the
@@ -192,39 +201,29 @@ setI2cBaudRate :: Word32 -> IO ()
 setI2cBaudRate a = c_setBaudRateI2C $ fromIntegral a
 
--- |Writes the data in the 'ByteString' to the specified adress.
-writeI2C :: Address -> BS.ByteString -> IO (Either BSC.ByteString ())	--writes a bytestring to the specified address
+-- |Writes the data in the 'ByteString' to the specified adress. Throws an IOException if an error occurs.
+writeI2C :: Address -> BS.ByteString -> IO ()	--writes a bytestring to the specified address
 writeI2C address by = BS.useAsCString by $ \bs -> do
     setI2cAddress address
     readresult <- c_writeI2C bs (fromIntegral $ BS.length by)
     case readresult of
-        0x01 -> return (Left "Received a NACK.")
-        0x02 -> return (Left "Received Clock Stretch Timeout.")
-        0x04 -> return (Left "Not all data was read.")
-        0x00 -> return (Right ())
+        0x01 -> throwIO $ IOError Nothing IllegalOperation "I2C: " "Received an unexpected NACK." Nothing Nothing
+        0x02 -> throwIO $ IOError Nothing IllegalOperation "I2C: " "Received Clock Stretch Timeout." Nothing Nothing 
+        0x04 -> throwIO $ IOError Nothing IllegalOperation "I2C: " "Not all data was read." Nothing Nothing
+        0x00 -> return ()
 
--- |Reads num bytes from the specified address.
-readI2C :: Address -> Int -> IO (Either BSC.ByteString BS.ByteString) --reads num bytes from the specified address
+-- |Reads num bytes from the specified address. Throws an IOException if an error occurs.
+readI2C :: Address -> Int -> IO BS.ByteString --reads num bytes from the specified address
 readI2C address num = allocaBytes (num+1) $ \buf -> do --is the +1 necessary??
     setI2cAddress address
-    readresult <- c_readI2c buf (fromIntegral num)
-    case readresult of
-        0x01 -> return (Left "Received a NACK.")
-        0x02 -> return (Left "Received Clock Stretch Timeout.")
-        0x04 -> return (Left "Not all data was read.")
-        0x00 -> do  bs <- BS.packCString buf --convert C buffer to a bytestring
-                    return (Right bs)
+    readresult <- c_readI2C buf (fromIntegral num)
+    actOnResult readresult buf
 
 -- |Writes a 'ByteString' containing a register address to the specified address, then reads num bytes from
--- it, using the \"repeated start\" I2C method
-writeReadI2C :: Address -> BS.ByteString -> Int -> IO (Either BSC.ByteString BS.ByteString)
+-- it, using the \"repeated start\" I2C method. Throws an IOException if an error occurs.
+writeReadI2C :: Address -> BS.ByteString -> Int -> IO BS.ByteString
 writeReadI2C address by num = BS.useAsCString by $ \bs -> do --marshall the register-containing bytestring
     allocaBytes (num+1) $ \buf -> do	--allocate a buffer for the response
         setI2cAddress address
         readresult <- c_writeReadI2C bs buf (fromIntegral num)
-        case readresult of
-            0x01 -> return (Left "Received a NACK.")
-            0x02 -> return (Left "Received Clock Stretch Timeout.")
-            0x04 -> return (Left "Not all data was read.")
-            0x00 -> do  bs <- BS.packCString buf --convert C buffer to a bytestring
-                        return (Right bs)+        actOnResult readresult buf