<commit_before>{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}

module Ivory.BSP.STM32.Driver.I2C
  ( i2cTower
  , module Ivory.BSP.STM32.Driver.I2C.Types
  , module Ivory.BSP.STM32.Driver.I2C.I2CDeviceAddr
  ) where

import Ivory.Language
import Ivory.Stdlib
import Ivory.Tower
import Ivory.HW

import Ivory.BSP.STM32.Interrupt
import Ivory.BSP.STM32.ClockConfig

import Ivory.BSP.STM32.Peripheral.GPIOF4
import Ivory.BSP.STM32.Peripheral.I2C.Regs
import Ivory.BSP.STM32.Peripheral.I2C.Peripheral

import Ivory.BSP.STM32.Driver.I2C.Types
import Ivory.BSP.STM32.Driver.I2C.I2CDeviceAddr
import Ivory.BSP.STM32.Driver.I2C.I2CDriverState


i2cTower :: (STM32Interrupt s)
         => (e -> ClockConfig)
         -> I2CPeriph s
         -> GPIOPin
         -> GPIOPin
         -> Tower e ( ChanInput  (Struct "i2c_transaction_request")
                    , ChanOutput (Struct "i2c_transaction_result")
                    , ChanOutput (Stored ITime))
i2cTower tocc periph sda scl = do
  towerDepends i2cTowerTypes
  towerModule  i2cTowerTypes
  reqchan <- channel
  reschan <- channel
  readychan <- channel
  evt_irq <- signalUnsafe
                (Interrupt (i2cIntEvent periph))
                (Microseconds 50)
                (do debugToggle debugPin1
                    modifyReg (i2cRegCR2 periph)
                      (clearBit i2c_cr2_itbufen >> clearBit i2c_cr2_itevten)
                    interrupt_disable (i2cIntEvent periph))

  err_irq <- signalUnsafe
                (Interrupt (i2cIntError periph))
                (Microseconds 50)
                (do debugToggle debugPin2
                    modifyReg (i2cRegCR2 periph)
                      (clearBit i2c_cr2_iterren)
                    interrupt_disable (i2cIntError periph))
  monitor ((i2cName periph) ++ "PeripheralDriver") $
    i2cPeripheralDriver tocc periph sda scl evt_irq err_irq
      (snd reqchan) (fst reschan) (fst readychan)
  return (fst reqchan, snd reschan, snd readychan)

i2cTowerTypes :: Module
i2cTowerTypes = package "i2cTowerTypes" $ do
  defStruct (Proxy :: Proxy "i2c_transaction_request")
  defStruct (Proxy :: Proxy "i2c_transaction_result")


i2cPeripheralDriver :: forall s e
                     . (STM32Interrupt s)
                    => (e -> ClockConfig)
                    -> I2CPeriph s
                    -> GPIOPin
                    -> GPIOPin
                    -> ChanOutput (Stored ITime)
                    -> ChanOutput (Stored ITime)
                    -> ChanOutput (Struct "i2c_transaction_request")
                    -> ChanInput  (Struct "i2c_transaction_result")
                    -> ChanInput  (Stored ITime)
                    -> Monitor e ()
i2cPeripheralDriver tocc periph sda scl evt_irq err_irq req_chan res_chan ready_in = do
  clockConfig <- fmap tocc getEnv
  monitorModuleDef $ hw_moduledef

  driverstate <- stateInit "driverstate" (ival stateInactive)

  handler systemInit "init" $ do
    send_ready <- emitter ready_in 1
    callback $ \ now -> do
      debugSetup     debugPin1
      debugSetup     debugPin2
      debugSetup     debugPin3
      debugSetup     debugPin4
      i2cInit        periph sda scl clockConfig
      -- Setup hardware for interrupts
      interrupt_enable (i2cIntEvent periph)
      interrupt_enable (i2cIntError periph)
      emit send_ready now

  (reqbuffer :: Ref Global (Struct "i2c_transaction_request")) <- state "reqbuffer"
  (reqbufferpos :: Ref Global (Stored (Ix 128)))               <- state "reqbufferpos"
<commit_msg>ivory-bsp-stm32: fix a funny i2c init bug by just waiting 1ms<commit_after>{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}

module Ivory.BSP.STM32.Driver.I2C
  ( i2cTower
  , module Ivory.BSP.STM32.Driver.I2C.Types
  , module Ivory.BSP.STM32.Driver.I2C.I2CDeviceAddr
  ) where

import Ivory.Language
import Ivory.Stdlib
import Ivory.Tower
import Ivory.HW

import Ivory.BSP.STM32.Interrupt
import Ivory.BSP.STM32.ClockConfig

import Ivory.BSP.STM32.Peripheral.GPIOF4
import Ivory.BSP.STM32.Peripheral.I2C.Regs
import Ivory.BSP.STM32.Peripheral.I2C.Peripheral

import Ivory.BSP.STM32.Driver.I2C.Types
import Ivory.BSP.STM32.Driver.I2C.I2CDeviceAddr
import Ivory.BSP.STM32.Driver.I2C.I2CDriverState


i2cTower :: (STM32Interrupt s)
         => (e -> ClockConfig)
         -> I2CPeriph s
         -> GPIOPin
         -> GPIOPin
         -> Tower e ( ChanInput  (Struct "i2c_transaction_request")
                    , ChanOutput (Struct "i2c_transaction_result")
                    , ChanOutput (Stored ITime))
i2cTower tocc periph sda scl = do
  towerDepends i2cTowerTypes
  towerModule  i2cTowerTypes
  reqchan <- channel
  reschan <- channel
  readychan <- channel
  ready_per <- period (Milliseconds 1)
  evt_irq <- signalUnsafe
                (Interrupt (i2cIntEvent periph))
                (Microseconds 50)
                (do debugToggle debugPin1
                    modifyReg (i2cRegCR2 periph)
                      (clearBit i2c_cr2_itbufen >> clearBit i2c_cr2_itevten)
                    interrupt_disable (i2cIntEvent periph))

  err_irq <- signalUnsafe
                (Interrupt (i2cIntError periph))
                (Microseconds 50)
                (do debugToggle debugPin2
                    modifyReg (i2cRegCR2 periph)
                      (clearBit i2c_cr2_iterren)
                    interrupt_disable (i2cIntError periph))
  monitor ((i2cName periph) ++ "PeripheralDriver") $
    i2cPeripheralDriver tocc periph sda scl evt_irq err_irq
      (snd reqchan) (fst reschan) ready_per (fst readychan)
  return (fst reqchan, snd reschan, snd readychan)

i2cTowerTypes :: Module
i2cTowerTypes = package "i2cTowerTypes" $ do
  defStruct (Proxy :: Proxy "i2c_transaction_request")
  defStruct (Proxy :: Proxy "i2c_transaction_result")


i2cPeripheralDriver :: forall s e
                     . (STM32Interrupt s)
                    => (e -> ClockConfig)
                    -> I2CPeriph s
                    -> GPIOPin
                    -> GPIOPin
                    -> ChanOutput (Stored ITime)
                    -> ChanOutput (Stored ITime)
                    -> ChanOutput (Struct "i2c_transaction_request")
                    -> ChanInput  (Struct "i2c_transaction_result")
                    -> ChanOutput (Stored ITime)
                    -> ChanInput  (Stored ITime)
                    -> Monitor e ()
i2cPeripheralDriver tocc periph sda scl evt_irq err_irq req_chan res_chan ready_per ready_in = do
  clockConfig <- fmap tocc getEnv
  monitorModuleDef $ hw_moduledef

  driverstate <- stateInit "driverstate" (ival stateInactive)

  handler systemInit "init" $ do
    callback $ \ now -> do
      debugSetup     debugPin1
      debugSetup     debugPin2
      debugSetup     debugPin3
      debugSetup     debugPin4
      i2cInit        periph sda scl clockConfig
      -- Setup hardware for interrupts
      interrupt_enable (i2cIntEvent periph)
      interrupt_enable (i2cIntError periph)

  ready_sent <- state "ready_sent"
  handler ready_per "readyPeriod" $ do
    send_ready <- emitter ready_in 1
    callback $ \now -> do
      r <- deref ready_sent
      unless r $ emit send_ready now
      store ready_sent true

  (reqbuffer :: Ref Global (Struct "i2c_transaction_request")) <- state "reqbuffer"
  (reqbufferpos :: Ref Global (Stored (Ix 128)))               <- state "reqbufferpos"

{'fraction_non_alphanumeric': 0.08189203354297694, 'fraction_numerical': 0.024240041928721173, 'mean_word_length': 2.2745602745602747, 'pattern_counts': {'":': 0, '<': 26, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4146513', 'n_tokens_mistral': 2636, 'n_tokens_neox': 2468, 'n_words': 557}