---------------------------------------------------------------------------- -- | -- Module : STM32.SPI -- Copyright : (c) Marc Fontaine 2017 -- License : BSD3 -- -- Maintainer : Marc.Fontaine@gmx.de -- Stability : experimental -- Portability : GHC-only -- -- The SPI periveral {-# LANGUAGE OverloadedStrings #-} module STM32.SPI where import Device import STM32.MachineInterface import STM32.Utils import qualified STM32.RCC as RCC import Control.Monad import Data.Word data Config = Config { _direction :: Direction , _mode :: Mode , _dataSize :: DataSize , _CPOL :: ClockPolarity , _CPHA :: ClockPhase , _NSS :: SlaveSelect , _baudRatePrescaler :: BaudPrescaler , _firstBit :: FirstBit , _CRCPolynomial :: Word16 } deriving Show defaultConfig :: Config defaultConfig = Config { _direction = Two_Lines_FullDuplex , _mode = Slave , _dataSize = Eight , _CPOL = Low , _CPHA = OneEdge , _NSS = Hard , _baudRatePrescaler = Prescaler_2 , _firstBit = MSB , _CRCPolynomial = 7 } data Direction = Two_Lines_FullDuplex -- ((u16)0x0000) | Two_Lines_RxOnly -- ((u16)0x0400) | One_Line_Rx -- ((u16)0x8000) | One_Line_Tx -- ((u16)0xC000) deriving (Show) data Mode = Master | Slave deriving Show data DataSize = Eight | Sixteen deriving Show data ClockPolarity = Low | High deriving Show data ClockPhase = OneEdge | TwoEdge deriving Show data SlaveSelect = Soft | Hard deriving Show data BaudPrescaler = Prescaler_2 | Prescaler_4 | Prescaler_8 | Prescaler_16 | Prescaler_32 | Prescaler_64 | Prescaler_128 | Prescaler_256 deriving Show instance RegisterField BaudPrescaler where toBits b = case b of Prescaler_2 -> "000" Prescaler_4 -> "001" Prescaler_8 -> "010" Prescaler_16 -> "011" Prescaler_32 -> "100" Prescaler_64 -> "101" Prescaler_128 -> "110" Prescaler_256 -> "111" toField = const CR1_BR data FirstBit = MSB | LSB deriving Show deInit :: Peripheral -> MI () deInit = RCC.peripheralResetToggle init :: Peripheral -> Config -> MI () init p conf = do let write field rs = bitWrite p field rs write CR1_MSTR $ case _mode conf of Slave -> False Master -> True write CR1_SSI $ case _mode conf of Slave -> False Master -> True write CR1_DFF $ case _dataSize conf of Eight -> False Sixteen -> True write CR1_CPOL $ case _CPOL conf of Low -> False High -> True write CR1_CPHA $ case _CPHA conf of OneEdge -> False TwoEdge -> True write CR1_SSM $ case _NSS conf of Hard -> False Soft -> True fieldWrite p $ _baudRatePrescaler conf write CR1_LSBFIRST $ case _firstBit conf of MSB -> False LSB -> True pokeReg p CRCPR $ fromIntegral $ _CRCPolynomial conf enable :: Peripheral -> MI () enable p = bitSet p CR1_SPE disable :: Peripheral -> MI () disable p = bitReset p CR1_SPE sendData8 :: Peripheral -> Word8 -> MI () sendData8 p b = pokeReg p DR $ fromIntegral b sendData :: Peripheral -> Word16 -> MI () sendData p b = pokeReg p DR $ fromIntegral b receiveData8 :: Peripheral -> MI Word8 receiveData8 p = fmap fromIntegral $ peekReg p DR receiveData :: Peripheral -> MI Word16 receiveData p = fmap fromIntegral $ peekReg p DR ssOutputCmd :: Peripheral -> Bool -> MI () ssOutputCmd p = bitWrite p CR2_SSOE