/******************************************************************************
*
* Copyright (C) 2009-2017  Brian Berlin
* 
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* 
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************
*
* FILENAME: pokeysound.h
*
* DESCRIPTION:  This contains function declarations for Pokey sound functions
*
* AUTHORS:  bberlin
*
* CHANGE LOG
*
*  VER     DATE     CHANGED BY   DESCRIPTION OF CHANGE
* ------  --------  ----------   ------------------------------------
* 0.6.3   12/04/09  bberlin      Creation
******************************************************************************/
#ifndef pokeysound_h
#define pokeysound_h

#define MAXPOKEYS 4

/* 
 * Only define Pokey registers this module uses
 */
#define AUDF1_C     0x00
#define AUDC1_C     0x01
#define AUDF2_C     0x02
#define AUDC2_C     0x03
#define AUDF3_C     0x04
#define AUDC3_C     0x05
#define AUDF4_C     0x06
#define AUDC4_C     0x07
#define AUDCTL_C    0x08
#define STIMER_C    0x09
#define SKCTL_C     0x0f

/*
 * Poly Sel Values
 */
#define NO_SEL 0
#define POLY4_SEL 1
#define POLY17_SEL 2
#define POLY9_SEL 3
#define MAX_POLY 4

typedef enum {
    INVALID,
    START_INIT,
    END_INIT,
    S_TIMER,
    GTIA,
    CHAN
} ps_etype;

typedef struct {
    unsigned int sampCount;
    ps_etype type;
    int chip;
    int chan;
    int counter;
    int baseClock;
    int polySel;
    int poly5En;
    int volume;
    int volumeOnly;
    int filterEn;
} ps_event;

typedef struct {
    int chan;
    int enabled;
    int counter;
    int baseClock;
    int toggle; /* relative # cpu clocks<<8 to next rising edge */
    unsigned int toggleClk; /*actual cpu clock of toggle */
    unsigned int lastEventTime;
    int polySel;
    int poly5En;
    int filterEn;
    int ffMainOut;
    int ffPoly5Out;
    int ffFilterOut;
    int volume;
    int volumeOnly;
} ps_chan;

typedef struct {
    unsigned int lastClock;
    unsigned int inInit;
    unsigned int clockPolyStart[4]; /* I hate it, but track polys seperate */
    unsigned int clockPoly5Start; /*    because of pokey zero cross      */
    unsigned int clock114Time; /* track seperate due to pokey time zero cross */
    unsigned int clock28Time;
    unsigned int sampleCounter;  /* 8-bit precision cpu clocks per samp */
    unsigned int volChanBits;    /* holds a bit for each channel plus GTIA */
    unsigned int volTable[0x20];
    unsigned int reg[0x10];
    ps_chan chan[4];
} ps_chip;

void pokey_sound_init ( int sample_freq, int chips );
void pokey_sound_update_freq ( int sample_freq, int silence_vol );
void pokey_sound_determine_poly (int chip, int chan, int *polySel, int *poly5En);
void pokey_sound_determine_timer (int chip, int chan, int *baseClock, int *counter);
void pokey_sound_determine_filter (int chip, int chan, int *filterEn);
int pokey_sound_shift_clock ( int shift );
void pokey_sound_reg_update ( unsigned int addr, unsigned int val, int chip, 
                                int gain );
void pokey_sound_process ( unsigned char *buffer, int n, int clks );
int pokey_is_channel_enabled ( int chip, int chan, int upd_partner_ch );
void pokey_sound_update_gtia_consol ( unsigned int val );
void pokey_sound_volume_update ( int chip );

#endif
