packages feed

i2c-bus-0.1.0: tests/GHCI.hs

{-# LANGUAGE TemplateHaskell #-}
{-# OPTIONS_GHC -ddump-splices #-}
{-# OPTIONS_GHC -Wno-type-defaults #-}
{-# OPTIONS_GHC -Wno-missing-export-lists #-}
module GHCI where

import Relude 
import Relude.Extra.Newtype
import I2C
import I2C.Register
import I2C.Raw
import Data.Default
import Text.Show qualified
import Numeric
import Data.Bits
import Data.Char (toUpper)
import Text.Printf
import Control.Concurrent
import Foreign
import Language.Haskell.TH
import Language.Haskell.TH.Syntax
import Language.Haskell.TH.Lib


--------------------------------------------------------------------------------
--
-- * load ghci:
--
--    $ stack ghci
--
-- then load this file:
--
--    ghci> :l tests/GHCI.hs
--  
-- if you get link errors, run `stack build` first which will build the FFI parts,
-- and those symbols should then be available in GHCi
--  
--------------------------------------------------------------------------------


--------------------------------------------------------------------------------
-- test data

$(chip "MYCHIP")

$(setShowBinary)
$(register8 ''MYCHIP 0x22 "MY8" 0x83)
$(field ''MY8   "A_FIELD"  "0000***0")
$(field ''MY8   "A_BIT"    "00*00000")

-- 'MY64' types will be shown as a 64 character binary string
-- because of the imperative call '$(setShowBinary)' above.
$(register64BE ''MYCHIP 0x22 "MY64" 0x83)

$(setShowHex)
$(register16LE ''MYCHIP 0x44 "MY16" 0x1122)
$(field ''MY16  "B_FIELD"  "00000000000****0")
$(field ''MY16  "B_BIT"    "00*0000000000000")

my8 :: MY8
my8 = MY8 0b00000110

my16 :: MY16
my16 = MY16 0b0000111100011000

my64 :: MY64
my64 = MY64 0x0123456789ABCDEF 


--------------------------------------------------------------------------------
-- PCF8575
-- 
-- this is a GPIO expander chip with 2 bytes => 16 pins.
-- no registers, only write and read 2 bytes.
--
--  * https://www.ti.com/lit/ds/symlink/pcf8575.pdf
--
$(chip "PCF8575")

testPCF8575 :: IO ()
testPCF8575 = do
    chip <- openChip @PCF8575 "/dev/i2c-1" 0x20
    
    forM_ [0..0x00FF] $ \ix -> do
        rawwrite @Word16LE chip ix
        threadDelay 400000


--------------------------------------------------------------------------------
-- MPU6050
-- 
-- this is a accelerometer and gyroscope chip with registers
--
--  * https://randomnerdtutorials.com/arduino-mpu-6050-accelerometer-gyroscope/
--  * https://github.com/adafruit/Adafruit_MPU6050/blob/master/Adafruit_MPU6050.cpp
--  * https://www.invensense.tdk.com/en-us/download-resource/ps-mpu-6000a-00-mpu-6000-and-mpu-6050-datasheet
--  * https://www.invensense.tdk.com/download-resource/rm-mpu-6000a-00-mpu-6000-and-mpu-6050-register-map-and-descriptions
--
$(chip "MPU6050")

data TemperatureC = TemperatureC Double

instance Show TemperatureC where
    show (TemperatureC n) = printf "%+ 3.1f °C" n

-- Temperature in degrees C = (TemperatureC Register Value as a signed quantity)/340 + 36.53
-- this Storable instance is relative to the MPU6050's hardware
instance Storable TemperatureC where
    sizeOf a    = 2
    alignment a = 1
    peek ptr    = do
        n <- peek @Int16BE $ castPtr ptr
        pure $ TemperatureC $ (fromIntegral n) / 340.0 + 36.53
    poke ptr (TemperatureC a) = do
        poke @Int16BE (castPtr ptr) $ truncate $ (a - 36.53) * 340.0

$(register  ''MPU6050 0x41 "TEMP_OUT" ''TemperatureC)

$(register8 ''MPU6050 0x6A "USER_CTRL" 0x00)
$(field ''USER_CTRL "FIFO_RESET"      "00000*00")
$(field ''USER_CTRL "I2C_MST_RESET"   "000000*0")
$(field ''USER_CTRL "SIG_COND_RESET"  "0000000*")

$(register8 ''MPU6050 0x6B "PWR_MGMT_1" 0x40)
$(field ''PWR_MGMT_1 "CLKSEL"         "00000***")

-- this adds INLINE pragma to functions generated by '$(field)' below; see splice output.
-- (nothing special about the PWR_MGMT_1, this is just for demonstration)
$(setFieldInline True) 
$(field ''PWR_MGMT_1 "SLEEP"          "0*000000")


testMPU6050 :: IO ()
testMPU6050 = do
    chip <- openChip "/dev/i2c-1" 0x68

    regwrite chip regUSER_CTRL  $ def & bitsetFIFO_RESET 
                                      & bitsetI2C_MST_RESET 
                                      & bitsetSIG_COND_RESET

    regwrite chip regPWR_MGMT_1 $ def & setCLKSEL 2 
                                      & bitclearSLEEP

    forever $ do

        t <- regread chip regTEMP_OUT
        print t

        --a <- regread' @TemperatureC chip 0x41
        --print a

        threadDelay 400000