module System.PIO.Linux.PWM ( Channel, Period, DutyCycle, setEnable, getEnable, setValue, getValue ) where import System.IO (writeFile, readFile) -- | PWM channel numbers are values of type Int type Channel = Int -- | PWM period is a value of type Int type Period = Int -- | PWM duty cycle is a value of type Int type DutyCycle = Int interfaceFilePath :: Int -> String -> String interfaceFilePath n file = "/sys/class/pwm/pwmchip0/pwm" ++ (show n) ++ file enableFilePath :: Int -> String enableFilePath n = interfaceFilePath n "/enable" periodFilePath :: Int -> String periodFilePath n = interfaceFilePath n "/period" dutyCycleFilePath :: Int -> String dutyCycleFilePath n = interfaceFilePath n "/duty_cycle" -- | Computation 'setEnable' @channel@ @True@ makes corresponding PWM channel enabled. -- Computation 'setEnable' @channel@ @False@ makes corresponding PWM channel disabled. setEnable :: Channel -> Bool -> IO () setEnable n flag = writeFile (enableFilePath n) $ show $ fromEnum flag -- | Computation 'getEnable' @channel@ obtain status of corresponding PWM channel. getEnable :: Channel -> IO Bool getEnable n = (\flag -> toEnum $ read flag) <$> readFile (enableFilePath n) -- | 'setValue' @channel@ @period@ @dutyCycle@ generates PWM signal on corresponding PWM channel. @period@ and @dutyCycle@ are value of nanoseconds. setValue :: Channel -> Period -> DutyCycle -> IO () setValue n period dutyCycle = do let dutyCycleFilePath' = dutyCycleFilePath n writeFile dutyCycleFilePath' $ show 0 writeFile (periodFilePath n) $ show period writeFile dutyCycleFilePath' $ show dutyCycle -- | 'getValue' @channel@ obtain status of current PWM signal on corresponding PWM channel. getValue :: Channel -> IO (Period, DutyCycle) getValue n = (\p dc -> (read p, read dc)) <$> readFile (periodFilePath n) <*> readFile (dutyCycleFilePath n)