/* Zeta API - Z/hardware/PSG/NES APU.h
 ___  __ __       __              __
|   \|  |__|____ |  | ____ ____ _|  |____
|  , `  |  |    |_  _|  -_|    | _  |  _ |
|__|\___|__|__|_||__||____|__|_|__,_|____|
 E N T E R T A I N M E N T    S Y S T E M
Copyright (C) 2006-2022 Manuel Sainz de Baranda y Goñi.
Released under the terms of the GNU Lesser General Public License v3. */

#ifndef Z_hardware_PSG_NES_APU_H
#define Z_hardware_PSG_NES_APU_H
/*
	    .----._.----.
 ROUT <-01--|*   \_/    |<-40-- VCC
 COUT <-02--|           |--39-> $4016W.0
 /RES --03->|           |--38-> $4016W.1
  A00 <-04--|           |--37-> $4016W.2
  A01 <-05--|           |--36-> /$4016R
  A02 <-06--|           |--35-> /$4017R
  A03 <-07--|           |--34-> R/W
  A04 <-08--|           |<-33-- /NMI
  A05 <-09--|           |<-32-- /IRQ
  A06 <-10--|    2A03   |--31-> PHI2
  A07 <-11--|           |<-30-- ---
  A08 <-12--|           |<-29-- CLK
  A09 <-13--|           |<-28-> D0
  A10 <-14--|           |<-27-> D1
  A11 <-15--|           |<-26-> D2
  A12 <-16--|           |<-25-> D3
  A13 <-17--|           |<-24-> D4
  A14 <-18--|           |<-23-> D5
  A15 <-19--|           |<-22-> D6
  VEE --20->|           |<-21-> D7
	    '-----------'		*/

#include <Z/types/integral.h>
#include <Z/macros/member.h>

/* Square Wave Register A
.-----------------.
| 7 6 5 4 3 2 1 0 |
'-\_/-|-|-\_____/-'
   |  | |    '----> Volume / Envelope decay rate
   |  | '---------> Envelope decay disable
   |  '-----------> Length counter clock disable / Envelope decay looping enable
   '--------------> Duty cycle type (Unused on noise channel) */

Z_DEFINE_STRICT_STRUCTURE (Z_BIT_FIELD_MEMBERS(8, 4) (
	zuint8 duty_cycle_type		    :2,
	zuint8 disable_envelope_decay	    :1,
	zuint8 disable_length_counter_clock :1,
	zuint8 volume			    :4
)) ZNESSquareWaveA;

/* Square Wave Register B
.-----------------.
| 7 6 5 4 3 2 1 0 |
'-|-\___/-|-\___/-'
  |   |	  |   '---> Right shift amount
  |   |	  '-------> Decrease / Increase (1/0) wavelength
  |   '-----------> Sweep update rate
  '---------------> Sweep enable */

Z_DEFINE_STRICT_STRUCTURE (Z_BIT_FIELD_MEMBERS(8, 4) (
	zuint8 sweep_enable		       :1,
	zuint8 sweep_update_rate	       :3,
	zuint8 decrease_or_increase_wavelength :1,
	zuint8 right_shift_amount	       :3
)) ZNESSquareWaveB;

/* Square Wave Register C */

typedef zuint8 ZNESSquareWaveC;

/* Square Wave Register D
.-----------------.
| 7 6 5 4 3 2 1 0 |
'-\_______/-\___/-'
      |	      '---> 3 MSB of wavelength (Unused on noise channel)
      '-----------> Length counter load register */

Z_DEFINE_STRICT_STRUCTURE (
) ZNESSquareWaveD;

/* Triangle Wave Register A
.-----------------.
| 7 6 5 4 3 2 1 0 |
'-|-\___________/-'
  |	  '-------> Linear counter load register
  '---------------> Length counter clock disable / Linear counter start */

Z_DEFINE_STRICT_STRUCTURE (
) ZNESTriangleWaveA;

/* Triangle Wave Register B
.-----------------.
| 7 6 5 4 3 2 1 0 | Unused
'-----------------'
*/

/* Triangle Wave Register C
.-----------------.
| 7 6 5 4 3 2 1 0 | Eight LSB of wavelength
'-----------------'
*/

typedef zuint8 ZNESTriangleWaveC;

/* Triangle Wave Register D
.-----------------.
| 7 6 5 4 3 2 1 0 |
'-\_______/-\___/-'
      |       '---> 3 MSB of wavelength (Unused on noise channel)
      '-----------> Length counter load register */

Z_DEFINE_STRICT_STRUCTURE (
) ZNESTriangleWaveD;

/* Noise Register A
.-----------------.
| 7 6 5 4 3 2 1 0 |
'-\_/-|-|-\_____/-'
   |  | |    '----> Volume / Envelope decay rate
   |  | '---------> Envelope decay disable
   |  '-----------> Length counter clock disable / Envelope decay looping enable
   '--------------> Duty cycle type (Unused on noise channel) */

Z_DEFINE_STRICT_STRUCTURE (
) ZNESNoiseA;

/* Noise Register B
.-----------------.
| 7 6 5 4 3 2 1 0 |
'-----------------'
      Unused
*/

/* Noise Register C
.-----------------.
| 7 6 5 4 3 2 1 0 |
'-|-\___/-\_____/-'
  |   |	     '----> Playback sample rate
  |   '-----------> Unused
  '---------------> random number type generation */

Z_DEFINE_STRICT_STRUCTURE (
) ZNESNoiseC;

/* Noise Register D
.-----------------.
| 7 6 5 4 3 2 1 0 |
'-\_______/-\___/-'
      |       '---> 3 MSB of wavelength (Unused on noise channel)
      '-----------> Length counter load register */

Z_DEFINE_STRICT_STRUCTURE (
) ZNESNoiseD;


#endif /* Z_hardware_PSG_NES_APU_H */
