i2c-bus-0.1.0: source-lib/I2C/Register.hs
--------------------------------------------------------------------------------
-- |
-- Module : I2C.Register
-- SPDX-License-Identifier : MIT
-- Copyright : karamellpelle@hotmail.com
-- Maintainer : karamellpelle@hotmail.com
-- Stability : experimental
--
-- Utilities for working with chips with registers.
--------------------------------------------------------------------------------
{-# OPTIONS_GHC -Wno-deprecations #-}
module I2C.Register
(
-- * Register
Register (..),
-- ** Register addressing
RegisterAddress (..),
fromRegisterAddress,
-- * Read and write registers
regread,
regwrite,
regmodify,
-- * Read and write registers (direct addressing)
regread',
regwrite',
regmodify',
) where
import Relude
import Data.Default
import Text.Show qualified
import Numeric (showHex)
import Data.Char (toUpper)
import Foreign
import I2C.Internal qualified as Internal
import I2C.Chip
import I2C.Types
--------------------------------------------------------------------------------
-- Register
-- | Register addressing inside chips.
newtype RegisterAddress = RegisterAddress Word8
deriving (Num, Storable)
instance Show RegisterAddress where
show (RegisterAddress w) =
(if 0x10 <= w then "0x" else "0x0") <> fmap toUpper (showHex w "")
-- | Convert from 'RegisterAddress'
fromRegisterAddress :: Num b => RegisterAddress -> b
fromRegisterAddress (RegisterAddress addr) = fromIntegral addr
-- | Index to a register of type 'a'.
data Register t a = Register Text RegisterAddress
--------------------------------------------------------------------------------
-- using Register
-- | Read register.
-- May throw 'I2C.Exception.I2CErr'.
regread :: (IsChip t, Storable a, MonadIO m) => Internal.Chip t -> Register t a -> m a
regread chip (Register _name addr) =
regread' chip addr
{-# INLINE regread #-}
-- | Write register.
-- May throw 'I2C.Exception.I2CErr'.
regwrite :: (IsChip t, Storable a, MonadIO m) => Internal.Chip t -> Register t a -> a -> m ()
regwrite chip (Register _name addr) =
regwrite' chip addr
{-# INLINE regwrite #-}
-- | Modify register.
-- May throw 'I2C.Exception.I2CErr'.
regmodify :: (IsChip t, Storable a, MonadIO m) => Internal.Chip t -> Register t a -> (a -> a) -> m a
regmodify = \chip reg f -> do
a <- regread chip reg
let a' = f a
regwrite chip reg a'
pure a'
--------------------------------------------------------------------------------
-- raw addressing, no Register
-- | Read register at address.
-- May throw 'I2C.Exception.I2CErr'.
regread' :: forall a t m . (IsChip t, Storable a, MonadIO m) => Internal.Chip t -> RegisterAddress -> m a
regread' chip addr =
liftIO $ Internal.read chip (sizeOf addr) (flip poke addr) (sizeOf @a undefined) peek
{-# INLINE regread' #-}
-- | Write register at address.
-- May throw 'I2C.Exception.I2CErr'.
regwrite' :: forall a t m . (IsChip t, Storable a, MonadIO m) => Internal.Chip t -> RegisterAddress -> a -> m ()
regwrite' chip addr = \a -> do
let w = StorableAB addr a
liftIO $ Internal.write chip (sizeOf w) (flip poke w)
{-# INLINE regwrite' #-}
-- | Modify register at address.
-- May throw 'I2C.Exception.I2CErr'.
regmodify' :: forall a t m . (IsChip t, Storable a, MonadIO m) => Internal.Chip t -> RegisterAddress -> (a -> a) -> m a
regmodify' = \chip addr f -> do
a <- regread' chip addr
let a' = f a
regwrite' chip addr a'
pure a'