{-# LANGUAGE TemplateHaskell #-}

module Nes.APU.State (
    -- * Definition
    APUState (..),
    newAPUState,

    -- * Lens
    frameCounter,
    pulse1,
    pulse2,
    triangle,
    noise,
    dmc,
    cycle,
    filterThread,
    samplePeriod,
    sampleTimer,
    pushSampleCallback,
) where

import Control.Lens (makeLenses)
import Nes.APU.State.DMC
import Nes.APU.State.Filter.Constants (defaultOutputRate)
import Nes.APU.State.Filter.Thread (FilterThread)
import Nes.APU.State.FrameCounter
import Nes.APU.State.Noise
import Nes.APU.State.Pulse
import Nes.APU.State.Triangle
import Prelude hiding (cycle)

data APUState = MkAPUState
    { APUState -> FrameCounter
_frameCounter :: !FrameCounter
    , APUState -> Pulse
_pulse1 :: !Pulse
    , APUState -> Pulse
_pulse2 :: !Pulse
    , APUState -> Triangle
_triangle :: !Triangle
    , APUState -> Noise
_noise :: !Noise
    , APUState -> DMC
_dmc :: !DMC
    , APUState -> Int
_cycle :: {-# UNPACK #-} !Int
    -- ^ Number of CPU cycles since the start
    , APUState -> FilterThread
_filterThread :: !FilterThread
    , APUState -> Float
_sampleTimer :: {-# UNPACK #-} !Float
    -- ^ The number of CPU cycles since the last call to 'pushSampleCallback'
    , APUState -> Float
_samplePeriod :: {-# UNPACK #-} !Float
    -- ^ The number of CPU cycles between each call to 'pushSampleCallback'
    , APUState -> Float -> IO ()
_pushSampleCallback :: Float -> IO ()
    }

newAPUState :: (Float -> IO ()) -> FilterThread -> APUState
newAPUState :: (Float -> IO ()) -> FilterThread -> APUState
newAPUState Float -> IO ()
_pushSampleCallback FilterThread
_filterThread = MkAPUState{Float
Int
FilterThread
FrameCounter
Noise
Pulse
Triangle
DMC
Float -> IO ()
_frameCounter :: FrameCounter
_pulse1 :: Pulse
_pulse2 :: Pulse
_triangle :: Triangle
_noise :: Noise
_dmc :: DMC
_cycle :: Int
_filterThread :: FilterThread
_sampleTimer :: Float
_samplePeriod :: Float
_pushSampleCallback :: Float -> IO ()
_pushSampleCallback :: Float -> IO ()
_filterThread :: FilterThread
_frameCounter :: FrameCounter
_cycle :: Int
_pulse1 :: Pulse
_pulse2 :: Pulse
_triangle :: Triangle
_noise :: Noise
_dmc :: DMC
_samplePeriod :: Float
_sampleTimer :: Float
..}
  where
    _frameCounter :: FrameCounter
_frameCounter = FrameCounter
newFrameCounter
    _cycle :: Int
_cycle = Int
0
    _pulse1 :: Pulse
_pulse1 = Bool -> Pulse
newPulse Bool
True
    _pulse2 :: Pulse
_pulse2 = Bool -> Pulse
newPulse Bool
False
    _triangle :: Triangle
_triangle = Triangle
newTriangle
    _noise :: Noise
_noise = Noise
newNoise
    _dmc :: DMC
_dmc = DMC
newDMC
    _samplePeriod :: Float
_samplePeriod = (Float
21477272 Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
12) Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
defaultOutputRate
    _sampleTimer :: Float
_sampleTimer = Float
_samplePeriod

makeLenses ''APUState