{-|
Module      : Ice40.Led
Description : LED Ice40 hard IP primitive
Copyright   : (c) David Cox, 2021
License     : BSD 3-Clause
Maintainer  : standardsemiconductor@gmail.com

LED hard IP primitive from [Lattice Ice Technology Library](https://github.com/standardsemiconductor/VELDT-info/blob/master/SBTICETechnologyLibrary201708.pdf). See [iCE40 LED Driver Usage Guide](https://github.com/standardsemiconductor/VELDT-info/blob/master/ICE40LEDDriverUsageGuide.pdf) for more information.
-}
module Ice40.Led ( led ) where

import Clash.Prelude
import Clash.Annotations.Primitive
import Data.String.Interpolate (i)
import Data.String.Interpolate.Util (unindent)

{-# ANN ledPrim (InlinePrimitive [Verilog] $ unindent [i|
  [  { "BlackBox" :
       { "name" : "Ice40.Led.ledPrim"
       , "kind" : "Declaration"
       , "type" :
  "ledPrim
  :: Signal dom Bit       -- ARG[0]  leddcs
  -> Clock dom            -- ARG[1]  leddclk
  -> Signal dom Bit       -- ARG[2]  ledddat7
  -> Signal dom Bit       -- ARG[3]  ledddat6
  -> Signal dom Bit       -- ARG[4]  ledddat5
  -> Signal dom Bit       -- ARG[5]  ledddat4
  -> Signal dom Bit       -- ARG[6]  ledddat3
  -> Signal dom Bit       -- ARG[7]  ledddat2
  -> Signal dom Bit       -- ARG[8]  ledddat1
  -> Signal dom Bit       -- ARG[9]  ledddat0
  -> Signal dom Bit       -- ARG[10] leddaddr3
  -> Signal dom Bit       -- ARG[11] leddaddr2
  -> Signal dom Bit       -- ARG[12] leddaddr1
  -> Signal dom Bit       -- ARG[13] leddaddr0
  -> Signal dom Bool      -- ARG[14] leddden
  -> Signal dom Bool      -- ARG[15] leddexe
  -> Unbundled dom ( Bit  -- pwmOut0
                   , Bit  -- pwmOut1
                   , Bit  -- pwmOut2
                   , Bool -- leddon
                   )"
      , "template" :
  "//SB_LEDDA_IP begin
  wire ~GENSYM[pwmOut0][0];
  wire ~GENSYM[pwmOut1][1];
  wire ~GENSYM[pwmOut2][2];
  wire ~GENSYM[leddon][3];

  SB_LEDDA_IP SB_LEDDA_IP_INST (
    .LEDDCS    ( ~ARG[0]  ),
    .LEDDCLK   ( ~ARG[1]  ),
    .LEDDDAT7  ( ~ARG[2]  ),
    .LEDDDAT6  ( ~ARG[3]  ),
    .LEDDDAT5  ( ~ARG[4]  ),
    .LEDDDAT4  ( ~ARG[5]  ),
    .LEDDDAT3  ( ~ARG[6]  ),
    .LEDDDAT2  ( ~ARG[7]  ),
    .LEDDDAT1  ( ~ARG[8]  ),
    .LEDDDAT0  ( ~ARG[9]  ),
    .LEDDADDR3 ( ~ARG[10] ),
    .LEDDADDR2 ( ~ARG[11] ),
    .LEDDADDR1 ( ~ARG[12] ),
    .LEDDADDR0 ( ~ARG[13] ),
    .LEDDDEN   ( ~ARG[14] ),
    .LEDDEXE   ( ~ARG[15] ),

    .PWMOUT0   ( ~SYM[0]  ),
    .PWMOUT1   ( ~SYM[1]  ),
    .PWMOUT2   ( ~SYM[2]  ),
    .LEDDON    ( ~SYM[3]  )
  );

  assign ~RESULT = {~SYM[0], ~SYM[1], ~SYM[2], ~SYM[3]};
  //SB_LEDDA_IP end"
      }
    }
  ]
  |]) #-}

{-# NOINLINE ledPrim #-}
ledPrim
  :: Signal dom Bit       -- ARG[0]  leddcs - CS to write LEDD IP registers
  -> Clock dom            -- ARG[1]  leddclk - Clock to write LEDD IP registers
  -> Signal dom Bit       -- ARG[2]  ledddat7 - bit 7 data to write into the LEDD IP registers
  -> Signal dom Bit       -- ARG[3]  ledddat6 - bit 6 data to write into the LEDD IP registers
  -> Signal dom Bit       -- ARG[4]  ledddat5 - bit 5 data to write into the LEDD IP registers
  -> Signal dom Bit       -- ARG[5]  ledddat4 - bit 4 data to write into the LEDD IP registers
  -> Signal dom Bit       -- ARG[6]  ledddat3 - bit 3 data to write into the LEDD IP registers
  -> Signal dom Bit       -- ARG[7]  ledddat2
  -> Signal dom Bit       -- ARG[8]  ledddat1
  -> Signal dom Bit       -- ARG[9]  ledddat0
  -> Signal dom Bit       -- ARG[10] leddaddr3
  -> Signal dom Bit       -- ARG[11] leddaddr2
  -> Signal dom Bit       -- ARG[12] leddaddr1
  -> Signal dom Bit       -- ARG[13] leddaddr0
  -> Signal dom Bool      -- ARG[14] leddden
  -> Signal dom Bool      -- ARG[15] leddexe
  -> Unbundled dom ( Bit  -- pwmOut0
                   , Bit  -- pwmOut1
                   , Bit  -- pwmOut2
                   , Bool -- leddon
                   )
ledPrim :: Signal dom Bit
-> Clock dom
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bool
-> Signal dom Bool
-> Unbundled dom (Bit, Bit, Bit, Bool)
ledPrim !Signal dom Bit
_ !Clock dom
_ !Signal dom Bit
_ !Signal dom Bit
_ !Signal dom Bit
_ !Signal dom Bit
_ !Signal dom Bit
_ !Signal dom Bit
_ !Signal dom Bit
_ !Signal dom Bit
_ !Signal dom Bit
_ !Signal dom Bit
_ !Signal dom Bit
_ !Signal dom Bit
_ !Signal dom Bool
_ !Signal dom Bool
_ = (Bit -> Signal dom Bit
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure Bit
0, Bit -> Signal dom Bit
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure Bit
0, Bit -> Signal dom Bit
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure Bit
0, Bool -> Signal dom Bool
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure Bool
False)

-- | SB_LEDDA_IP primitive generates the RGB PWM outputs for the RGB LED drivers. 
-- 
-- LED Control Bus Addressable Registers
--
-- +---------------+----------+-------------------------------------------+--------+
-- | LEDD_ADR[3:0] | Name     | Usage                                     | Access |
-- +===============+==========+===========================================+========+
-- | 1000          | LEDDCR0  | LED Driver Control Register 0             | W      |
-- +---------------+----------+-------------------------------------------+--------+
-- | 1001          | LEDDBR   | LED Driver Pre-scale Register             | W      |
-- +---------------+----------+-------------------------------------------+--------+
-- | 1010          | LEDDONR  | LED Driver ON Time Register               | W      |
-- +---------------+----------+-------------------------------------------+--------+
-- | 1011          | LEDDOFR  | LED Driver OFF Time Register              | W      |
-- +---------------+----------+-------------------------------------------+--------+
-- | 0101          | LEDDBCRR | LED Driver Breathe On Control Register    | W      |
-- +---------------+----------+-------------------------------------------+--------+
-- | 0110          | LEDDBCFR | LED Driver Breate Off Control Register    | W      |
-- +---------------+----------+-------------------------------------------+--------+
-- | 0001          | LEDDPWRR | LED Driver Pulse Width Register for RED   | W      |
-- +---------------+----------+-------------------------------------------+--------+
-- | 0010          | LEDDPWRG | LED Driver Pulse Width Register for GREEN | W      |
-- +---------------+----------+-------------------------------------------+--------+
-- | 0011          | LEDDPWRB | LED Driver Pulse Width Register for BLUE  | W      |
-- +---------------+----------+-------------------------------------------+--------+
led
  :: HiddenClock dom
  => Signal dom Bit           -- ^ cs - CS to write LEDD IP registers
  -> Signal dom (BitVector 8) -- ^ dat - data to write into the LEDD IP registers
  -> Signal dom (BitVector 4) -- ^ addr - LEDD IP register address
  -> Signal dom Bool          -- ^ en - data enable input to indicate data and address are stable
  -> Signal dom Bool          -- ^ exe - enable to IP to run the blinking sequence. When it is LOW, the sequence stops at the nearest OFF state
  -> Unbundled dom ( Bit 
                   , Bit 
                   , Bit 
                   , Bool
                   ) -- ^ (pwmOut0, pwmOut1, pwmOut2, LED on indicator)
led :: Signal dom Bit
-> Signal dom (BitVector 8)
-> Signal dom (BitVector 4)
-> Signal dom Bool
-> Signal dom Bool
-> Unbundled dom (Bit, Bit, Bit, Bool)
led Signal dom Bit
cs Signal dom (BitVector 8)
dat Signal dom (BitVector 4)
addr Signal dom Bool
en Signal dom Bool
exe = (Signal dom Bit
pwmOut0, Signal dom Bit
pwmOut1, Signal dom Bit
pwmOut2, Signal dom Bool
on)
  where
    (Signal dom Bit
pwmOut0, Signal dom Bit
pwmOut1, Signal dom Bit
pwmOut2, Signal dom Bool
on) = Signal dom Bit
-> Clock dom
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bool
-> Signal dom Bool
-> Unbundled dom (Bit, Bit, Bit, Bool)
forall (dom :: Domain).
Signal dom Bit
-> Clock dom
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bool
-> Signal dom Bool
-> Unbundled dom (Bit, Bit, Bit, Bool)
ledPrim Signal dom Bit
cs
                                              Clock dom
forall (dom :: Domain). HiddenClock dom => Clock dom
hasClock
                                              (Index 8 -> Signal dom (BitVector 8) -> Signal dom Bit
forall (n :: Nat) (dom :: Domain).
KnownNat n =>
Index n -> Signal dom (BitVector n) -> Signal dom Bit
bitAt Index 8
7 Signal dom (BitVector 8)
dat)
                                              (Index 8 -> Signal dom (BitVector 8) -> Signal dom Bit
forall (n :: Nat) (dom :: Domain).
KnownNat n =>
Index n -> Signal dom (BitVector n) -> Signal dom Bit
bitAt Index 8
6 Signal dom (BitVector 8)
dat)
                                              (Index 8 -> Signal dom (BitVector 8) -> Signal dom Bit
forall (n :: Nat) (dom :: Domain).
KnownNat n =>
Index n -> Signal dom (BitVector n) -> Signal dom Bit
bitAt Index 8
5 Signal dom (BitVector 8)
dat)
                                              (Index 8 -> Signal dom (BitVector 8) -> Signal dom Bit
forall (n :: Nat) (dom :: Domain).
KnownNat n =>
Index n -> Signal dom (BitVector n) -> Signal dom Bit
bitAt Index 8
4 Signal dom (BitVector 8)
dat)
                                              (Index 8 -> Signal dom (BitVector 8) -> Signal dom Bit
forall (n :: Nat) (dom :: Domain).
KnownNat n =>
Index n -> Signal dom (BitVector n) -> Signal dom Bit
bitAt Index 8
3 Signal dom (BitVector 8)
dat)
                                              (Index 8 -> Signal dom (BitVector 8) -> Signal dom Bit
forall (n :: Nat) (dom :: Domain).
KnownNat n =>
Index n -> Signal dom (BitVector n) -> Signal dom Bit
bitAt Index 8
2 Signal dom (BitVector 8)
dat)
                                              (Index 8 -> Signal dom (BitVector 8) -> Signal dom Bit
forall (n :: Nat) (dom :: Domain).
KnownNat n =>
Index n -> Signal dom (BitVector n) -> Signal dom Bit
bitAt Index 8
1 Signal dom (BitVector 8)
dat)
                                              (Index 8 -> Signal dom (BitVector 8) -> Signal dom Bit
forall (n :: Nat) (dom :: Domain).
KnownNat n =>
Index n -> Signal dom (BitVector n) -> Signal dom Bit
bitAt Index 8
0 Signal dom (BitVector 8)
dat)
                                              (Index 4 -> Signal dom (BitVector 4) -> Signal dom Bit
forall (n :: Nat) (dom :: Domain).
KnownNat n =>
Index n -> Signal dom (BitVector n) -> Signal dom Bit
bitAt Index 4
3 Signal dom (BitVector 4)
addr)
                                              (Index 4 -> Signal dom (BitVector 4) -> Signal dom Bit
forall (n :: Nat) (dom :: Domain).
KnownNat n =>
Index n -> Signal dom (BitVector n) -> Signal dom Bit
bitAt Index 4
2 Signal dom (BitVector 4)
addr)
                                              (Index 4 -> Signal dom (BitVector 4) -> Signal dom Bit
forall (n :: Nat) (dom :: Domain).
KnownNat n =>
Index n -> Signal dom (BitVector n) -> Signal dom Bit
bitAt Index 4
1 Signal dom (BitVector 4)
addr)
                                              (Index 4 -> Signal dom (BitVector 4) -> Signal dom Bit
forall (n :: Nat) (dom :: Domain).
KnownNat n =>
Index n -> Signal dom (BitVector n) -> Signal dom Bit
bitAt Index 4
0 Signal dom (BitVector 4)
addr)
                                              Signal dom Bool
en
                                              Signal dom Bool
exe

 
bitAt :: KnownNat n => Index n -> Signal dom (BitVector n) -> Signal dom Bit
bitAt :: Index n -> Signal dom (BitVector n) -> Signal dom Bit
bitAt Index n
n = (BitVector n -> Bit) -> Signal dom (BitVector n) -> Signal dom Bit
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap (BitVector n -> Index n -> Bit
forall a i. (BitPack a, Enum i) => a -> i -> Bit
! Index n
n)