YM2610 registers: Difference between revisions

From NeoGeo Development Wiki
Jump to navigation Jump to search
m (→‎ADPCM-B part: add some descriptions)
 
(13 intermediate revisions by 3 users not shown)
Line 1: Line 1:
= SSG part =
Pages detailing the different YM2610 parts:
[[File:ym2610egshapes.png|thumb|right|Selectable EG shapes of the SSG]]
 
* [[SSG]]
* [[FM]]
* [[ADPCM]]
* [[YM2610 timers]]
 
=Reading=
 
The only writable registers that can be read back are the SSG ones.
To read register X, write X to Z80 port 4, then read Z80 port 5 (needs clarification).


{| class="regdef"
{| class="regdef"
|'''Address ([[Z80]] port 4)'''
|'''Z80 port'''
|'''Data ([[Z80]] port 5)'''
|'''Data'''
|
|Notes
|-
|$00
|{{8BitRegister|Fine tune|8}}
|rowspan="2"|Channel A
|-
|$01
|{{8BitRegister|-|4|Coarse tune|4}}
|-
|$02
|{{8BitRegister|Fine tune|8}}
|rowspan="2"|Channel B
|-
|$03
|{{8BitRegister|-|4|Coarse tune|4}}
|-
|-
|$04
|$04
|{{8BitRegister|Fine tune|8}}
|{{8BitRegister|Busy|1|-|5|Timer B flag|1|Timer A flag|1}}
|rowspan="2"|Channel C
|When a timer expires and IRQ is enabled for that timer, the respective flag is set.
|-
|-
|$05
|$05
|{{8BitRegister|-|4|Coarse tune|4}}
|{{8BitRegister|SSG register data|8}}
|Attempting to read non-SSG registers will return 0.
|-
|-
|$06
|$06
|{{8BitRegister|-|3|Noise tune|5}}
|{{8BitRegister|ADPCM-B end|1|-|1|CH6 end|1|CH5 end|1|CH4 end|1|CH3 end|1|CH2 end|1|CH1 end|1}}
|Noise channel
|When a channel has reached the end address and stops, the respective bit is set (unless masked). See [[ADPCM#Status_register|Status register]] for more details.
|-
|-
|$07
|$07
|{{8BitRegister|-|2|/EN noise C|1|/EN noise B|1|/EN noise A|1|/EN C|1|/EN B|1|/EN A|1}}
|Not implemented
|/Enable for Noise and Tone
|Always returns $00
|-
|-
|$08
|}
|{{8BitRegister|-|3|Mode|1|Volume|4}}
 
|Channel A
=Map=
 
This is a quick reference table to help visualize the whole chip mapping, check the individual sections below for more complete information.
 
CHx stands for channel x, OPx for operator x.
 
Color codes:
{| class="regdef"
|-
|-
|$09
  | colspan="3" style="background: #ffe699;" |  
|{{8BitRegister|-|3|Mode|1|Volume|4}}
  | [[SSG]]
|Channel B
|-
|-
|$0A
  | colspan="3" style="background: lightskyblue;" |  
|{{8BitRegister|-|3|Mode|1|Volume|4}}
  | [[FM]]
|Channel C
|-
|-
|$0B
  | colspan="3" style="background: #cc99ff;" |  
|{{8BitRegister|Volume envelope period fine tune|8}}
  | [[YM2610_timers|TIMERS]]
|
|-
|-
|$0C
  | width="20" style="background: #e2efda;" |  
|{{8BitRegister|Volume envelope period coarse tune|8}}
  | width="20" style="background: #c6e0b4;" |
|
  | width="20" style="background: #a9d08e;" |  
  | [[ADPCM]]
|-
|-
|$0D
  | colspan="3" style="background: silver;" |  
|{{8BitRegister|-|4|Volume envelop shape|4}}
  | Unused/Test
|See diagram.
|}
|}


If 'Mode' = 1, the EG is used instead of the 4bit volume value.
f = 8M / (Coarse*256 + Fine) ?
= Timers =


{| class="regdef"
{| class="regdef"
|'''Address (Z80 port 4)'''
|'''Data (Z80 port 5)'''
|-
|-
|$24
  | width="50" |
|{{8BitRegister|TA counter load bits 9-2|8}}
  | align="center" colspan="2" | '''Port 0 (Z80 writes to port 4/5)'''
  | align="center" colspan="2" | '''Port 1 (Z80 writes to port 6/7)'''
|-
  | 0x00
  | width="80" rowspan="2" style="background: #ffe699;" | CHA
  | width="480" align="center" style="background: #ffe699;" | {{8BitRegister|Fine tune|8}}
  | align="center" colspan="2" style="background: #c6e0b4;" | {{8BitRegister|Dump|1|-|1|CH6 ON|1|CH5 ON|1|CH4 ON|1|CH3 ON|1|CH2 ON |1|CH1 ON|1}}
|-
  | 0x01
  | align="center" style="background: #ffe699;" | {{8BitRegister|-|4|Coarse tune|4}}
  | align="center" colspan="2" style="background: #c6e0b4;" | {{8BitRegister|-|2|Master volume|6}}
|-
  | 0x02
  | rowspan="2" style="background: #ffe699;" | CHB
  | align="center" style="background: #ffe699;" | {{8BitRegister|Fine tune|8}}
  | align="center" colspan="2" style="background: silver;" | {{8BitRegister|?|8}}
|-
  | 0x03
  | align="center" style="background: #ffe699;" | {{8BitRegister|-|4|Coarse tune|4}}
  | colspan="2" style="background: silver;" |
|-
  | 0x04
  | rowspan="2" style="background: #ffe699;" | CHC
  | align="center" style="background: #ffe699;" | {{8BitRegister|Fine tune|8}}
  | colspan="2" style="background: silver;" |
|-
  | 0x05
  | align="center" style="background: #ffe699;" | {{8BitRegister|-|4|Coarse tune|4}}
  | colspan="2" style="background: silver;" |
|-
  | 0x06
  | style="background: #ffe699;" | Noise
  | align="center" style="background: #ffe699;" | {{8BitRegister|-|3|Noise tune|5}}
  | colspan="2" style="background: silver;" |
|-
  | 0x07
  | align="center" colspan="2" style="background: #ffe699;" | {{8BitRegister|-|2|/EN noise C|1|/EN noise B|1|/EN noise A|1|/EN tone C|1|/EN tone B|1|/EN tone A|1}}
  | colspan="2" style="background: silver;" |
|-
  | 0x08
  | style="background: #ffe699;" | CHA
  | align="center" style="background: #ffe699;" | {{8BitRegister|-|3|Mode|1|Volume|4}}
  | width="480" align="center" style="background: #c6e0b4;" rowspan="6" | {{8BitRegister|L|1|R|1|-|1|Channel volume|5}}
  | width="80" style="background: #c6e0b4;" align="right" | CH1
|-
  | 0x09
  | style="background: #ffe699;" | CHB
  | align="center" style="background: #ffe699;" | {{8BitRegister|-|3|Mode|1|Volume|4}}
  | style="background: #c6e0b4;" align="right" | CH2
|-
  | 0x0a
  | style="background: #ffe699;" | CHC
  | align="center" style="background: #ffe699;" | {{8BitRegister|-|3|Mode|1|Volume|4}}
  | style="background: #c6e0b4;" align="right" | CH3
|-
  | 0x0b
  | align="center" colspan="2" style="background: #ffe699;" | {{8BitRegister|Volume envelope period fine tune|8}}
  | style="background: #c6e0b4;" align="right" | CH4
|-
  | 0x0c
  | align="center" colspan="2" style="background: #ffe699;" | {{8BitRegister|Volume envelope period coarse tune|8}}
  | style="background: #c6e0b4;" align="right" | CH5
|-
  | 0x0d
  | align="center" colspan="2" style="background: #ffe699;" | {{8BitRegister|-|4|Volume envelope shape|4}}
  | style="background: #c6e0b4;" align="right" | CH6
|-
  | 0x0e
  | colspan="2" style="background: silver;" |
  | colspan="2" style="background: silver;" |
|-
  | 0x0f
  | colspan="2" style="background: silver;" |
  | colspan="2" style="background: silver;" |
|-
  | 0x10
  | align="center" colspan="2" style="background: #e2efda;" | {{8BitRegister|Start|1|-|2|Repeat|1|-|3|Reset|1|}}
  | align="center" style="background: #c6e0b4;" rowspan="6" | {{8BitRegister|Sample's start address/256 LSB|8}}
  | style="background: #c6e0b4;" align="right" | CH1
|-
|-
|$25
  | 0x11
|{{8BitRegister|-|6|TA counter load bits 1-0|2}}
  | align="center" colspan="2" style="background: #e2efda;" | {{8BitRegister|L|1|R|1|-|6|}}
  | style="background: #c6e0b4;" align="right" | CH2
|-
|-
|$26
  | 0x12
|{{8BitRegister|TB counter load bits 0-7|8}}
  | align="center" colspan="2" style="background: #e2efda;" | {{8BitRegister|Sample's start address/256 LSB|8}}
  | style="background: #c6e0b4;" align="right" | CH3
|-
|-
|$27
  | 0x13
|{{8BitRegister|CSM Mode|1|3 slot mode|1|Reset TB flag|1|Reset TA flag|1|Enable TB IRQ|1|Enable TA IRQ|1|Load TB|1|Load TA|1}}
  | align="center" colspan="2" style="background: #e2efda;" | {{8BitRegister|Sample's start address/256 MSB|8}}
|}
  | style="background: #c6e0b4;" align="right" | CH4
*TA = Timer A, TB = Timer B
|-
*Timers will tick until they have reached zero, at which point an IRQ will be generated if enabled.  Reading port $04 will show which timer caused it.
  | 0x14
*The actual timer counter registers are not directly accessable.  They can be reset to zero or initialised from load registers $24-$26
  | align="center" colspan="2" style="background: #e2efda;" | {{8BitRegister|Sample's stop address/256 LSB|8}}
**Writing 0 to the load bits in register $27 will reset the timer counter registers to zero
  | style="background: #c6e0b4;" align="right" | CH5
**Writing 1 to the load bits will copy the respective timer load register to the timer counter.  This only works when the timer is at zero.
|-
*When a timer expires, it is automatically reloaded from the load registers and continues.
  | 0x15
*Timer flag reset refers to the same flags that are read from port $04
  | align="center" colspan="2" style="background: #e2efda;" | {{8BitRegister|Sample's stop address/256 MSB|8}}
*CSM mode is for automatic key on for operators on the second FM channel when timer A expires?
  | style="background: #c6e0b4;" align="right" | CH6
 
|-
= FM part =
  | 0x16
 
  | colspan="2" style="background: silver;" |
==Common FM Registers==
  | colspan="2" style="background: silver;" |
 
|-
{| class="regdef"
  | 0x17
|'''Address (Z80 port 4)'''
  | colspan="2" style="background: silver;" |
|'''Data (Z80 port 5)'''
  | colspan="2" style="background: silver;" |
|
|-
  | 0x18
  | colspan="2" style="background: silver;" |
  | align="center" style="background: #c6e0b4;" rowspan="6" | {{8BitRegister|Sample's start address/256 MSB|8}}
  | style="background: #c6e0b4;" align="right" | CH1
|-
  | 0x19
  | align="center" colspan="2" style="background: #e2efda;" | {{8BitRegister|Delta-N (L)|8}}
  | style="background: #c6e0b4;" align="right" | CH2
|-
  | 0x1a
  | align="center" colspan="2" style="background: #e2efda;" | {{8BitRegister|Delta-N (H)|8}}
  | style="background: #c6e0b4;" align="right" | CH3
|-
  | 0x1b
  | align="center" colspan="2" style="background: #e2efda;" | {{8BitRegister|ADPCM-B channel volume|8}}
  | style="background: #c6e0b4;" align="right" | CH4
|-
  | 0x1c
  | align="center" colspan="2" style="background: #a9d08e;" | {{8BitRegister|B|1|-|1|A6|1|A5|1|A4|1|A3|1|A2|1|A1|1|}}
  | style="background: #c6e0b4;" align="right" | CH5
|-
  | 0x1d
  | colspan="2" style="background: silver;" |
  | style="background: #c6e0b4;" align="right" | CH6
|-
  | 0x1e
  | colspan="2" style="background: silver;" |
  | colspan="2" style="background: silver;" |
|-
  | 0x1f
  | colspan="2" style="background: silver;" |
  | colspan="2" style="background: silver;" |
|-
  | 0x20
  | colspan="2" style="background: silver;" |
  | align="center" style="background: #c6e0b4;" rowspan="6" | {{8BitRegister|Sample's stop address/256 LSB|8}}
  | style="background: #c6e0b4;" align="right" | CH1
|-
  | 0x21
  | align="center" colspan="2" style="background: silver;" | {{8BitRegister|?|8}}
  | style="background: #c6e0b4;" align="right" | CH2
|-
  | 0x22
  | align="center" colspan="2" style="background: lightskyblue;" | {{8BitRegister|-|4|On|1|Control|3}}
  | style="background: #c6e0b4;" align="right" | CH3
|-
  | 0x23
  | colspan="2" style="background: silver;" |
  | style="background: #c6e0b4;" align="right" | CH4
|-
  | 0x24
  | align="center" colspan="2" style="background: #cc99ff;" | {{8BitRegister|TA counter load bits MSBs|8}}
  | style="background: #c6e0b4;" align="right" | CH5
|-
  | 0x25
  | align="center" colspan="2" style="background: #cc99ff;" | {{8BitRegister|-|6|TA counter load bits LSBs|2}}
  | style="background: #c6e0b4;" align="right" | CH6
|-
  | 0x26
  | align="center" colspan="2" style="background: #cc99ff;" | {{8BitRegister|TB counter load|8}}
  | colspan="2" style="background: silver;" |
|-
  | 0x27
  | align="center" colspan="2" style="background: #cc99ff;" | {{8BitRegister|CSM mode|1|2CH mode|1|Flag reset TB|1|Flag reset TA|1|Enable TB IRQ|1|Enable TA IRQ|1|Load TB|1|Load TA|1}}
  | colspan="2" style="background: silver;" |
|-
  | 0x28
  | align="center" colspan="2" style="background: lightskyblue;" | {{8BitRegister|Slot|4|-|1|Channel|3|}}
  | align="center" style="background: #c6e0b4;" rowspan="6" | {{8BitRegister|Sample's stop address/256 MSB|8}}
  | style="background: #c6e0b4;" align="right" | CH1
|-
  | 0x29
  | colspan="2" style="background: silver;" |
  | style="background: #c6e0b4;" align="right" | CH2
|-
  | 0x2a
  | colspan="2" style="background: silver;" |
  | style="background: #c6e0b4;" align="right" | CH3
|-
  | 0x2b
  | colspan="2" style="background: silver;" |
  | style="background: #c6e0b4;" align="right" | CH4
|-
  | 0x2c
  | colspan="2" style="background: silver;" |
  | style="background: #c6e0b4;" align="right" | CH5
|-
  | 0x2d
  | colspan="2" style="background: silver;" |
  | style="background: #c6e0b4;" align="right" | CH6
|-
  | 0x2e
  | colspan="2" style="background: silver;" |
  | colspan="2" style="background: silver;" |
|-
  | 0x2f
  | colspan="2" style="background: silver;" |
  | colspan="2" style="background: silver;" |
|-
  | 0x30
  | colspan="2" style="background: silver;" |
  | colspan="2" style="background: silver;" |
|-
  | 0x31
  | style="background: lightskyblue;" | CH1/OP1
  | align="center" style="background: lightskyblue;" colspan="2" rowspan="14" | {{8BitRegister|-|1|DT|3|MUL|4}}
  | style="background: lightskyblue;" align="right" | CH3/OP1
|-
  | 0x32
  | style="background: lightskyblue;" | CH2/OP1
  | style="background: lightskyblue;" align="right" | CH4/OP1
|-
  | 0x33
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x34
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x35
  | style="background: lightskyblue;" | CH1/OP3
  | style="background: lightskyblue;" align="right" | CH3/OP3
|-
  | 0x36
  | style="background: lightskyblue;" | CH2/OP3
  | style="background: lightskyblue;" align="right" | CH4/OP3
|-
  | 0x37
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x38
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x39
  | style="background: lightskyblue;" | CH1/OP2
  | style="background: lightskyblue;" align="right" | CH3/OP2
|-
  | 0x3a
  | style="background: lightskyblue;" | CH2/OP2
  | style="background: lightskyblue;" align="right" | CH4/OP2
|-
  | 0x3b
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x3c
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x3d
  | style="background: lightskyblue;" | CH1/OP4
  | style="background: lightskyblue;" align="right" | CH3/OP4
|-
  | 0x3e
  | style="background: lightskyblue;" | CH2/OP4
  | style="background: lightskyblue;" align="right" | CH4/OP4
|-
  | 0x3f
  | colspan="2" style="background: silver;" |
  | colspan="2" style="background: silver;" |
|-
  | 0x40
  | colspan="2" style="background: silver;" |
  | colspan="2" style="background: silver;" |
|-
  | 0x41
  | style="background: lightskyblue;" | CH1/OP1
  | align="center" style="background: lightskyblue;" colspan="2" rowspan="14" | {{8BitRegister|-|1|Total Level|7|}}
  | style="background: lightskyblue;" align="right" | CH3/OP1
|-
  | 0x42
  | style="background: lightskyblue;" | CH2/OP1
  | style="background: lightskyblue;" align="right" | CH4/OP1
|-
  | 0x43
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x44
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x45
  | style="background: lightskyblue;" | CH1/OP3
  | style="background: lightskyblue;" align="right" | CH3/OP3
|-
  | 0x46
  | style="background: lightskyblue;" | CH2/OP3
  | style="background: lightskyblue;" align="right" | CH4/OP3
|-
  | 0x47
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x48
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x49
  | style="background: lightskyblue;" | CH1/OP2
  | style="background: lightskyblue;" align="right" | CH3/OP2
|-
  | 0x4a
  | style="background: lightskyblue;" | CH2/OP2
  | style="background: lightskyblue;" align="right" | CH4/OP2
|-
  | 0x4b
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x4c
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x4d
  | style="background: lightskyblue;" | CH1/OP4
  | style="background: lightskyblue;" align="right" | CH3/OP4
|-
  | 0x4e
  | style="background: lightskyblue;" | CH2/OP4
  | style="background: lightskyblue;" align="right" | CH4/OP4
|-
  | 0x4f
  | colspan="2" style="background: silver;" |
  | colspan="2" style="background: silver;" |
|-
  | 0x50
  | colspan="2" style="background: silver;" |
  | colspan="2" style="background: silver;" |
|-
  | 0x51
  | style="background: lightskyblue;" | CH1/OP1
  | align="center" style="background: lightskyblue;" colspan="2" rowspan="14" | {{8BitRegister|KS|2|-|1|AR|5}}
  | style="background: lightskyblue;" align="right" | CH3/OP1
|-
  | 0x52
  | style="background: lightskyblue;" | CH2/OP1
  | style="background: lightskyblue;" align="right" | CH4/OP1
|-
  | 0x53
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x54
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x55
  | style="background: lightskyblue;" | CH1/OP3
  | style="background: lightskyblue;" align="right" | CH3/OP3
|-
  | 0x56
  | style="background: lightskyblue;" | CH2/OP3
  | style="background: lightskyblue;" align="right" | CH4/OP3
|-
  | 0x57
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x58
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x59
  | style="background: lightskyblue;" | CH1/OP2
  | style="background: lightskyblue;" align="right" | CH3/OP2
|-
  | 0x5a
  | style="background: lightskyblue;" | CH2/OP2
  | style="background: lightskyblue;" align="right" | CH4/OP2
|-
  | 0x5b
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x5c
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x5d
  | style="background: lightskyblue;" | CH1/OP4
  | style="background: lightskyblue;" align="right" | CH3/OP4
|-
  | 0x5e
  | style="background: lightskyblue;" | CH2/OP4
  | style="background: lightskyblue;" align="right" | CH4/OP4
|-
  | 0x5f
  | colspan="2" style="background: silver;" |
  | colspan="2" style="background: silver;" |
|-
  | 0x60
  | colspan="2" style="background: silver;" |
  | colspan="2" style="background: silver;" |
|-
  | 0x61
  | style="background: lightskyblue;" | CH1/OP1
  | align="center" style="background: lightskyblue;" colspan="2" rowspan="14" | {{8BitRegister|AM|1|-|2|DR|5}}
  | style="background: lightskyblue;" align="right" | CH3/OP1
|-
  | 0x62
  | style="background: lightskyblue;" | CH2/OP1
  | style="background: lightskyblue;" align="right" | CH4/OP1
|-
  | 0x63
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x64
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x65
  | style="background: lightskyblue;" | CH1/OP3
  | style="background: lightskyblue;" align="right" | CH3/OP3
|-
  | 0x66
  | style="background: lightskyblue;" | CH2/OP3
  | style="background: lightskyblue;" align="right" | CH4/OP3
|-
  | 0x67
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x68
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x69
  | style="background: lightskyblue;" | CH1/OP2
  | style="background: lightskyblue;" align="right" | CH3/OP2
|-
  | 0x6a
  | style="background: lightskyblue;" | CH2/OP2
  | style="background: lightskyblue;" align="right" | CH4/OP2
|-
  | 0x6b
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x6c
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x6d
  | style="background: lightskyblue;" | CH1/OP4
  | style="background: lightskyblue;" align="right" | CH3/OP4
|-
  | 0x6e
  | style="background: lightskyblue;" | CH2/OP4
  | style="background: lightskyblue;" align="right" | CH4/OP4
|-
  | 0x6f
  | colspan="2" style="background: silver;" |
  | colspan="2" style="background: silver;" |
|-
  | 0x70
  | colspan="2" style="background: silver;" |
  | colspan="2" style="background: silver;" |
|-
  | 0x71
  | style="background: lightskyblue;" | CH1/OP1
  | align="center" style="background: lightskyblue;" colspan="2" rowspan="14" | {{8BitRegister|-|3|SR|5}}
  | style="background: lightskyblue;" align="right" | CH3/OP1
|-
  | 0x72
  | style="background: lightskyblue;" | CH2/OP1
  | style="background: lightskyblue;" align="right" | CH4/OP1
|-
  | 0x73
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x74
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x75
  | style="background: lightskyblue;" | CH1/OP3
  | style="background: lightskyblue;" align="right" | CH3/OP3
|-
  | 0x76
  | style="background: lightskyblue;" | CH2/OP3
  | style="background: lightskyblue;" align="right" | CH4/OP3
|-
  | 0x77
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x78
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x79
  | style="background: lightskyblue;" | CH1/OP2
  | style="background: lightskyblue;" align="right" | CH3/OP2
|-
  | 0x7a
  | style="background: lightskyblue;" | CH2/OP2
  | style="background: lightskyblue;" align="right" | CH4/OP2
|-
  | 0x7b
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x7c
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x7d
  | style="background: lightskyblue;" | CH1/OP4
  | style="background: lightskyblue;" align="right" | CH3/OP4
|-
  | 0x7e
  | style="background: lightskyblue;" | CH2/OP4
  | style="background: lightskyblue;" align="right" | CH4/OP4
|-
  | 0x7f
  | colspan="2" style="background: silver;" |
  | colspan="2" style="background: silver;" |
|-
  | 0x80
  | colspan="2" style="background: silver;" |
  | colspan="2" style="background: silver;" |
|-
  | 0x81
  | style="background: lightskyblue;" | CH1/OP1
  | align="center" style="background: lightskyblue;" colspan="2" rowspan="14" | {{8BitRegister|SL|4|RR|4}}
  | style="background: lightskyblue;" align="right" | CH3/OP1
|-
  | 0x82
  | style="background: lightskyblue;" | CH2/OP1
  | style="background: lightskyblue;" align="right" | CH4/OP1
|-
  | 0x83
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x84
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x85
  | style="background: lightskyblue;" | CH1/OP3
  | style="background: lightskyblue;" align="right" | CH3/OP3
|-
  | 0x86
  | style="background: lightskyblue;" | CH2/OP3
  | style="background: lightskyblue;" align="right" | CH4/OP3
|-
  | 0x87
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x88
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x89
  | style="background: lightskyblue;" | CH1/OP2
  | style="background: lightskyblue;" align="right" | CH3/OP2
|-
  | 0x8a
  | style="background: lightskyblue;" | CH2/OP2
  | style="background: lightskyblue;" align="right" | CH4/OP2
|-
  | 0x8b
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x8c
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x8d
  | style="background: lightskyblue;" | CH1/OP4
  | style="background: lightskyblue;" align="right" | CH3/OP4
|-
  | 0x8e
  | style="background: lightskyblue;" | CH2/OP4
  | style="background: lightskyblue;" align="right" | CH4/OP4
|-
  | 0x8f
  | colspan="2" style="background: silver;" |
  | colspan="2" style="background: silver;" |
|-
  | 0x90
  | colspan="2" style="background: silver;" |
  | colspan="2" style="background: silver;" |
|-
  | 0x91
  | style="background: lightskyblue;" | CH1/OP1
  | align="center" style="background: lightskyblue;" colspan="2" rowspan="14" | {{8BitRegister|-|4|SSG-EG|4}}
  | style="background: lightskyblue;" align="right" | CH3/OP1
|-
  | 0x92
  | style="background: lightskyblue;" | CH2/OP1
  | style="background: lightskyblue;" align="right" | CH4/OP1
|-
  | 0x93
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x94
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x95
  | style="background: lightskyblue;" | CH1/OP3
  | style="background: lightskyblue;" align="right" | CH3/OP3
|-
  | 0x96
  | style="background: lightskyblue;" | CH2/OP3
  | style="background: lightskyblue;" align="right" | CH4/OP3
|-
  | 0x97
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x98
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x99
  | style="background: lightskyblue;" | CH1/OP2
  | style="background: lightskyblue;" align="right" | CH3/OP2
|-
  | 0x9a
  | style="background: lightskyblue;" | CH2/OP2
  | style="background: lightskyblue;" align="right" | CH4/OP2
|-
  | 0x9b
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x9c
  | style="background: silver;" |
  | style="background: silver;" |
|-
  | 0x9d
  | style="background: lightskyblue;" | CH1/OP4
  | style="background: lightskyblue;" align="right" | CH3/OP4
|-
  | 0x9e
  | style="background: lightskyblue;" | CH2/OP4
  | style="background: lightskyblue;" align="right" | CH4/OP4
|-
  | 0x9f
  | colspan="2" style="background: silver;" |
  | colspan="2" style="background: silver;" |
|-
  | 0xa0
  | colspan="2" style="background: silver;" |
  | colspan="2" style="background: silver;" |
|-
  | 0xa1
  | style="background: lightskyblue;" | CH1
  | align="center" style="background: lightskyblue;" colspan="2" rowspan="2" | {{8BitRegister|F-Num 1|8}}
  | style="background: lightskyblue;" align="right" | CH3
|-
  | 0xa2
  | style="background: lightskyblue;" | CH2 /OP4
  | style="background: lightskyblue;" align="right" | CH4
|-
  | 0xa3
  | colspan="2" style="background: silver;" |
  | colspan="2" style="background: silver;" |
|-
  | 0xa4
  | colspan="2" style="background: silver;" |  
  | colspan="2" style="background: silver;" |  
|-
|-
|$22
  | 0xa5
|{{8BitRegister|-|4|On|1|Control|3}}
  | style="background: lightskyblue;" | CH1
| LFO Frequency
  | align="center" style="background: lightskyblue;" colspan="2" rowspan="2" | {{8BitRegister|-|2|Block|3|F-Num 2|3}}
  | style="background: lightskyblue;" align="right" | CH3
|-
|-
|$28
  | 0xa6
|{{8BitRegister|Slot|4|-|1|Channel|3|}}
  | style="background: lightskyblue;" | CH2 / OP4
| Key On/Off
  | style="background: lightskyblue;" align="right" | CH4
|}
 
LFO Frequency values are as follows:
*0 – 3.98
*1 – 5.56
*2 – 6.02
*3 – 6.37
*4 – 6.88
*5 – 9.63
*6 – 48.1
*7 – 72.2
 
= ADPCM-A part =
 
'Dump' in register $00 is the key on/off bit.  Write 0 to start playing specified channels and write 1 to stop playing.
 
{| class="regdef"
|'''Address (Z80 port 6)'''
|'''Data (Z80 port 7)'''
|-
|-
|$00
  | 0xa7
|{{8BitRegister|Dump|1|-|1|CH6 ON|1|CH5 ON|1|CH4 ON|1|CH3 ON|1|CH2 ON |1|CH1 ON|1}}
  | colspan="2" style="background: silver;" |  
  | colspan="2" style="background: silver;" |  
|-
|-
|$01
  | 0xa8
|{{8BitRegister|-|2|Master volume|6}}
  | style="background: lightskyblue;" | OP3
  | align="center" style="background: lightskyblue;" rowspan="3" | {{8BitRegister|2CH * F-Num 1|8}}
  | colspan="2" style="background: silver;" |  
|-
|-
|$08~$0D (one for each channel)
  | 0xa9
|{{8BitRegister|L|1|R|1|-|1|Channel volume|5}}
  | style="background: lightskyblue;" | OP1
  | colspan="2" style="background: silver;" |  
|-
|-
|$10~$15 (one for each channel)
  | 0xaa
|{{8BitRegister|Sample's start address/256 LSB|8}}
  | style="background: lightskyblue;" | OP2
  | colspan="2" style="background: silver;" |  
|-
|-
|$18~$1D (one for each channel)
  | 0xab
|{{8BitRegister|Sample's start address/256 MSB|8}}
  | colspan="2" style="background: silver;" |  
  | colspan="2" style="background: silver;" |  
|-
|-
|$20~$25 (one for each channel)
  | 0xac
|{{8BitRegister|Sample's stop address/256 LSB|8}}
  | style="background: lightskyblue;" | OP3
  | align="center" style="background: lightskyblue;" rowspan="3" | {{8BitRegister|-|2|2CH * Block|3|2CH * F-Num 2|3}}
  | colspan="2" style="background: silver;" |
|-
|-
|$28~$2D (one for each channel)
  | 0xad
|{{8BitRegister|Sample's stop address/256 MSB|8}}
  | style="background: lightskyblue;" | OP1
|}
  | colspan="2" style="background: silver;" |  
 
= ADPCM-B part =
 
{| class="regdef"
|'''Address (Z80 port 4)'''
|'''Data (Z80 port 5)'''
|
|-
|-
|$10
  | 0xae
|{{8BitRegister|Start|1|-|2|Repeat|1|-|3|Reset|1|}}
  | style="background: lightskyblue;" | OP2
|Start/Repeat/Reset flags
  | colspan="2" style="background: silver;" |  
|-
|-
|$11
  | 0xaf
|{{8BitRegister|L|1|R|1|-|6|}}
  | colspan="2" style="background: silver;" |  
|Left/Right Output
  | colspan="2" style="background: silver;" |  
|-
|-
|$12
  | 0xb0
|{{8BitRegister|Sample's start address/256 LSB|8}}
  | colspan="2" style="background: silver;" |  
|
  | colspan="2" style="background: silver;" |  
|-
|-
|$13
  | 0xb1
|{{8BitRegister|Sample's start address/256 MSB|8}}
  | style="background: lightskyblue;" | CH1
|
  | align="center" style="background: lightskyblue;" colspan="2" rowspan="2" | {{8BitRegister|-|2|FB|3|ALGO|3}}
  | style="background: lightskyblue;" align="right" | CH3
|-
|-
|$14
  | 0xb2
|{{8BitRegister|Sample's stop address/256 LSB|8}}
  | style="background: lightskyblue;" | CH2
|
  | style="background: lightskyblue;" align="right" | CH4
|-
|-
|$15
  | 0xb3
|{{8BitRegister|Sample's stop address/256 MSB|8}}
  | colspan="2" style="background: silver;" |  
|
  | colspan="2" style="background: silver;" |  
|-
|-
|$19
  | 0xb4
|{{8BitRegister|Delta-N (L)|8}}
  | colspan="2" style="background: silver;" |  
|rowspan="2"|Determines sample playback rate
  | colspan="2" style="background: silver;" |  
|-
|-
|$1A
  | 0xb5
|{{8BitRegister|Delta-N (H)|8}}
  | style="background: lightskyblue;" | CH1
  | align="center" style="background: lightskyblue;" colspan="2" rowspan="2" | {{8BitRegister|L|1|R|1|AMS|2|-|1|PMS|3}}
  | style="background: lightskyblue;" align="right" | CH3
|-
|-
|$1B
  | 0xb6
|{{8BitRegister|ADPCM-B channel volume|8}}
  | style="background: lightskyblue;" | CH2
|
  | style="background: lightskyblue;" align="right" | CH4
|-
|-
|$1C
  | 0xb7
|{{8BitRegister|B|1|-|1|A6|1|A5|1|A4|1|A3|1|A2|1|A1|1|}}
  | colspan="2" style="background: silver;" |  
|ADPCM-A & B channels flag control
  | colspan="2" style="background: silver;" |  
|-
|-
|}
  | 0xb8
 
  | colspan="2" style="background: silver;" |
*Datasheet states playback formula as F=[Delta-N / 256] x 55.5KHz (correct?)
  | colspan="2" style="background: silver;" |  
*Write to flag control to reset/mask channel end flags
**Write 1 to reset and/or mask selected flag
**Write 0 to unmask selected flag
**Masking a flag will prevent it from being raised when a channel sample reach its end, this means you have to write 1, then 0 to clear a flag and keep it active.
**Flags must be manually cleared, playing a new sample on the channel won't clear it.
 
= Reading =
 
The only writable registers that can also be read are from the SSG.  All other ports and addresses return different data.
 
{| class="regdef"
|'''Z80 port #'''
|'''Data'''
|Notes
|-
|-
|$04
  | 0xb9
|{{8BitRegister|Busy|1|-|5|Timer B flag|1|Timer A flag|1}}
  | colspan="2" style="background: silver;" |  
|When a timer expires and IRQ is enabled for the timer, the respective bit is set
  | colspan="2" style="background: silver;" |  
|-
|-
|$05
  | '''...'''
|{{8BitRegister|SSG register data|8}}
  | colspan="4" align="center" style="background: silver;" | '''...'''
|Attempting to read non-SSG registers will fail
|-
|-
|$06
  | 0xfd
|{{8BitRegister|ADPCM-B end|1|-|1|CH6 end|1|CH5 end|1|CH4 end|1|CH3 end|1|CH2 end|1|CH1 end|1}}
  | colspan="2" style="background: silver;" |  
|When a channel has reached the end address and stops, the respective bit is set, unless masked
  | colspan="2" style="background: silver;" |  
|-
|-
|$07
  | 0xfe
|not implemented
  | colspan="2" style="background: silver;" |  
|Always returns $00
  | colspan="2" style="background: silver;" |  
|-
|-
  | 0xff
  | colspan="2" style="background: silver;" |
  | colspan="2" style="background: silver;" |
|}
|}


[[Category:Code]]
[[Category:Code]]
[[Category:Audio system]]
[[Category:Audio system]]

Latest revision as of 00:34, 8 August 2021

Pages detailing the different YM2610 parts:

Reading

The only writable registers that can be read back are the SSG ones. To read register X, write X to Z80 port 4, then read Z80 port 5 (needs clarification).

Z80 port Data Notes
$04
Bit 7 6 5 4 3 2 1 0
Def Busy -Timer B flagTimer A flag
When a timer expires and IRQ is enabled for that timer, the respective flag is set.
$05
Bit 7 6 5 4 3 2 1 0
Def SSG register data
Attempting to read non-SSG registers will return 0.
$06
Bit 7 6 5 4 3 2 1 0
Def ADPCM-B end -CH6 endCH5 endCH4 endCH3 endCH2 endCH1 end
When a channel has reached the end address and stops, the respective bit is set (unless masked). See Status register for more details.
$07 Not implemented Always returns $00

Map

This is a quick reference table to help visualize the whole chip mapping, check the individual sections below for more complete information.

CHx stands for channel x, OPx for operator x.

Color codes:

SSG
FM
TIMERS
ADPCM
Unused/Test


Port 0 (Z80 writes to port 4/5) Port 1 (Z80 writes to port 6/7)
0x00 CHA
Bit 7 6 5 4 3 2 1 0
Def Fine tune
Bit 7 6 5 4 3 2 1 0
Def Dump -CH6 ONCH5 ONCH4 ONCH3 ONCH2 ON CH1 ON
0x01
Bit 7 6 5 4 3 2 1 0
Def - Coarse tune
Bit 7 6 5 4 3 2 1 0
Def - Master volume
0x02 CHB
Bit 7 6 5 4 3 2 1 0
Def Fine tune
Bit 7 6 5 4 3 2 1 0
Def ?
0x03
Bit 7 6 5 4 3 2 1 0
Def - Coarse tune
0x04 CHC
Bit 7 6 5 4 3 2 1 0
Def Fine tune
0x05
Bit 7 6 5 4 3 2 1 0
Def - Coarse tune
0x06 Noise
Bit 7 6 5 4 3 2 1 0
Def - Noise tune
0x07
Bit 7 6 5 4 3 2 1 0
Def - /EN noise C/EN noise B/EN noise A/EN tone C/EN tone B/EN tone A
0x08 CHA
Bit 7 6 5 4 3 2 1 0
Def - ModeVolume
Bit 7 6 5 4 3 2 1 0
Def L R-Channel volume
CH1
0x09 CHB
Bit 7 6 5 4 3 2 1 0
Def - ModeVolume
CH2
0x0a CHC
Bit 7 6 5 4 3 2 1 0
Def - ModeVolume
CH3
0x0b
Bit 7 6 5 4 3 2 1 0
Def Volume envelope period fine tune
CH4
0x0c
Bit 7 6 5 4 3 2 1 0
Def Volume envelope period coarse tune
CH5
0x0d
Bit 7 6 5 4 3 2 1 0
Def - Volume envelope shape
CH6
0x0e
0x0f
0x10
Bit 7 6 5 4 3 2 1 0
Def Start -Repeat-Reset
Bit 7 6 5 4 3 2 1 0
Def Sample's start address/256 LSB
CH1
0x11
Bit 7 6 5 4 3 2 1 0
Def L R-
CH2
0x12
Bit 7 6 5 4 3 2 1 0
Def Sample's start address/256 LSB
CH3
0x13
Bit 7 6 5 4 3 2 1 0
Def Sample's start address/256 MSB
CH4
0x14
Bit 7 6 5 4 3 2 1 0
Def Sample's stop address/256 LSB
CH5
0x15
Bit 7 6 5 4 3 2 1 0
Def Sample's stop address/256 MSB
CH6
0x16
0x17
0x18
Bit 7 6 5 4 3 2 1 0
Def Sample's start address/256 MSB
CH1
0x19
Bit 7 6 5 4 3 2 1 0
Def Delta-N (L)
CH2
0x1a
Bit 7 6 5 4 3 2 1 0
Def Delta-N (H)
CH3
0x1b
Bit 7 6 5 4 3 2 1 0
Def ADPCM-B channel volume
CH4
0x1c
Bit 7 6 5 4 3 2 1 0
Def B -A6A5A4A3A2A1
CH5
0x1d CH6
0x1e
0x1f
0x20
Bit 7 6 5 4 3 2 1 0
Def Sample's stop address/256 LSB
CH1
0x21
Bit 7 6 5 4 3 2 1 0
Def ?
CH2
0x22
Bit 7 6 5 4 3 2 1 0
Def - OnControl
CH3
0x23 CH4
0x24
Bit 7 6 5 4 3 2 1 0
Def TA counter load bits MSBs
CH5
0x25
Bit 7 6 5 4 3 2 1 0
Def - TA counter load bits LSBs
CH6
0x26
Bit 7 6 5 4 3 2 1 0
Def TB counter load
0x27
Bit 7 6 5 4 3 2 1 0
Def CSM mode 2CH modeFlag reset TBFlag reset TAEnable TB IRQEnable TA IRQLoad TBLoad TA
0x28
Bit 7 6 5 4 3 2 1 0
Def Slot -Channel
Bit 7 6 5 4 3 2 1 0
Def Sample's stop address/256 MSB
CH1
0x29 CH2
0x2a CH3
0x2b CH4
0x2c CH5
0x2d CH6
0x2e
0x2f
0x30
0x31 CH1/OP1
Bit 7 6 5 4 3 2 1 0
Def - DTMUL
CH3/OP1
0x32 CH2/OP1 CH4/OP1
0x33
0x34
0x35 CH1/OP3 CH3/OP3
0x36 CH2/OP3 CH4/OP3
0x37
0x38
0x39 CH1/OP2 CH3/OP2
0x3a CH2/OP2 CH4/OP2
0x3b
0x3c
0x3d CH1/OP4 CH3/OP4
0x3e CH2/OP4 CH4/OP4
0x3f
0x40
0x41 CH1/OP1
Bit 7 6 5 4 3 2 1 0
Def - Total Level
CH3/OP1
0x42 CH2/OP1 CH4/OP1
0x43
0x44
0x45 CH1/OP3 CH3/OP3
0x46 CH2/OP3 CH4/OP3
0x47
0x48
0x49 CH1/OP2 CH3/OP2
0x4a CH2/OP2 CH4/OP2
0x4b
0x4c
0x4d CH1/OP4 CH3/OP4
0x4e CH2/OP4 CH4/OP4
0x4f
0x50
0x51 CH1/OP1
Bit 7 6 5 4 3 2 1 0
Def KS -AR
CH3/OP1
0x52 CH2/OP1 CH4/OP1
0x53
0x54
0x55 CH1/OP3 CH3/OP3
0x56 CH2/OP3 CH4/OP3
0x57
0x58
0x59 CH1/OP2 CH3/OP2
0x5a CH2/OP2 CH4/OP2
0x5b
0x5c
0x5d CH1/OP4 CH3/OP4
0x5e CH2/OP4 CH4/OP4
0x5f
0x60
0x61 CH1/OP1
Bit 7 6 5 4 3 2 1 0
Def AM -DR
CH3/OP1
0x62 CH2/OP1 CH4/OP1
0x63
0x64
0x65 CH1/OP3 CH3/OP3
0x66 CH2/OP3 CH4/OP3
0x67
0x68
0x69 CH1/OP2 CH3/OP2
0x6a CH2/OP2 CH4/OP2
0x6b
0x6c
0x6d CH1/OP4 CH3/OP4
0x6e CH2/OP4 CH4/OP4
0x6f
0x70
0x71 CH1/OP1
Bit 7 6 5 4 3 2 1 0
Def - SR
CH3/OP1
0x72 CH2/OP1 CH4/OP1
0x73
0x74
0x75 CH1/OP3 CH3/OP3
0x76 CH2/OP3 CH4/OP3
0x77
0x78
0x79 CH1/OP2 CH3/OP2
0x7a CH2/OP2 CH4/OP2
0x7b
0x7c
0x7d CH1/OP4 CH3/OP4
0x7e CH2/OP4 CH4/OP4
0x7f
0x80
0x81 CH1/OP1
Bit 7 6 5 4 3 2 1 0
Def SL RR
CH3/OP1
0x82 CH2/OP1 CH4/OP1
0x83
0x84
0x85 CH1/OP3 CH3/OP3
0x86 CH2/OP3 CH4/OP3
0x87
0x88
0x89 CH1/OP2 CH3/OP2
0x8a CH2/OP2 CH4/OP2
0x8b
0x8c
0x8d CH1/OP4 CH3/OP4
0x8e CH2/OP4 CH4/OP4
0x8f
0x90
0x91 CH1/OP1
Bit 7 6 5 4 3 2 1 0
Def - SSG-EG
CH3/OP1
0x92 CH2/OP1 CH4/OP1
0x93
0x94
0x95 CH1/OP3 CH3/OP3
0x96 CH2/OP3 CH4/OP3
0x97
0x98
0x99 CH1/OP2 CH3/OP2
0x9a CH2/OP2 CH4/OP2
0x9b
0x9c
0x9d CH1/OP4 CH3/OP4
0x9e CH2/OP4 CH4/OP4
0x9f
0xa0
0xa1 CH1
Bit 7 6 5 4 3 2 1 0
Def F-Num 1
CH3
0xa2 CH2 /OP4 CH4
0xa3
0xa4
0xa5 CH1
Bit 7 6 5 4 3 2 1 0
Def - BlockF-Num 2
CH3
0xa6 CH2 / OP4 CH4
0xa7
0xa8 OP3
Bit 7 6 5 4 3 2 1 0
Def 2CH * F-Num 1
0xa9 OP1
0xaa OP2
0xab
0xac OP3
Bit 7 6 5 4 3 2 1 0
Def - 2CH * Block2CH * F-Num 2
0xad OP1
0xae OP2
0xaf
0xb0
0xb1 CH1
Bit 7 6 5 4 3 2 1 0
Def - FBALGO
CH3
0xb2 CH2 CH4
0xb3
0xb4
0xb5 CH1
Bit 7 6 5 4 3 2 1 0
Def L RAMS-PMS
CH3
0xb6 CH2 CH4
0xb7
0xb8
0xb9
... ...
0xfd
0xfe
0xff