-
Notifications
You must be signed in to change notification settings - Fork 3
/
Blinker.hs
68 lines (58 loc) · 1.76 KB
/
Blinker.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
module Blinker where
import Clash.Prelude
import Clash.Annotations.TH
import Control.Monad
import Control.Monad.RWS
import Control.Lens hiding (Index)
import qualified Veldt.Counter as C
import qualified Veldt.PWM as P
import qualified Veldt.Ice40.Rgb as R
type Byte = BitVector 8
data Color = Red | Green | Blue
deriving (NFDataX, Generic, Show, Eq, Enum, Bounded)
data Blinker = Blinker
{ _color :: Color
, _redPWM :: P.PWM Byte
, _greenPWM :: P.PWM Byte
, _bluePWM :: P.PWM Byte
, _timer :: Index 24000000
} deriving (NFDataX, Generic)
makeLenses ''Blinker
mkBlinker :: Blinker
mkBlinker = Blinker
{ _color = Red
, _redPWM = P.mkPWM 0xFF
, _greenPWM = P.mkPWM 0
, _bluePWM = P.mkPWM 0
, _timer = 0
}
toPWM :: Color -> (Byte, Byte, Byte)
toPWM Red = (0xFF, 0, 0 )
toPWM Green = (0, 0xFF, 0 )
toPWM Blue = (0, 0, 0xFF)
blinkerM :: RWS r () Blinker R.Rgb
blinkerM = do
r <- zoom redPWM P.pwm
g <- zoom greenPWM P.pwm
b <- zoom bluePWM P.pwm
t <- timer <<%= C.increment
when (t == maxBound) $ do
c' <- color <%= C.increment
let (redDuty', greenDuty', blueDuty') = toPWM c'
zoom redPWM $ P.setDuty redDuty'
zoom greenPWM $ P.setDuty greenDuty'
zoom bluePWM $ P.setDuty blueDuty'
return (r, g, b)
blinker :: HiddenClockResetEnable dom => Signal dom R.Rgb
blinker = R.rgb $ mealy blinkerMealy mkBlinker $ pure ()
where
blinkerMealy s i = let (a, s', ()) = runRWS blinkerM i s
in (s', a)
{-# NOINLINE topEntity #-}
topEntity
:: "clk" ::: Clock XilinxSystem
-> "led" ::: Signal XilinxSystem R.Rgb
topEntity clk = withClockResetEnable clk rst enableGen blinker
where
rst = unsafeFromHighPolarity $ pure False
makeTopEntityWithName 'topEntity "Blinker"