YM2610 registers: Difference between revisions
Jump to navigation
Jump to search
m (Playback rate) |
(Layout, timer and individual bit details) |
||
Line 1: | Line 1: | ||
= SSG part = | =Timers= | ||
To do: Page. | |||
{| class="regdef" | |||
|'''Address (Z80 port 4)''' | |||
|'''Data (Z80 port 5)''' | |||
|- | |||
|$24 | |||
|{{8BitRegister|TA counter load bits 9-2|8}} | |||
|- | |||
|$25 | |||
|{{8BitRegister|-|6|TA counter load bits 1-0|2}} | |||
|- | |||
|$26 | |||
|{{8BitRegister|TB counter load bits 0-7|8}} | |||
|- | |||
|$27 | |||
|{{8BitRegister|CSM mode|1|3-slot mode|1|Reset TB|1|Reset TA|1|Enable TB IRQ|1|Enable TA IRQ|1|Load TB|1|Load TA|1}} | |||
|} | |||
*TA = Timer A (10bit), TB = Timer B (8bit) | |||
*Timers will tick until they have reached zero, at which point an [[Z80 interrupts|IRQ]] will be generated if enabled. Reading port $04 will show which timer caused it (see below). | |||
*The actual timer counter registers are not directly accessible. They can be reset to zero or initialised from load registers $24~$26 | |||
**Writing 0 to the load bits in register $27 will reset the timer counter registers to zero | |||
**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. | |||
*Timer flag reset refers to the same flags that are read from port $04 | |||
*CSM mode is for automatic key on for operators on the second FM channel when timer A expires ? | |||
* Timer A IRQ frequency: 8M / 2 / 12 (prescaler) / 12 / TA load = 27.1Hz ~ 27.8kHz ? | |||
* Timer A IRQ frequency: 8M / 16 / 12 (prescaler) / 12 / TB load = 13.6Hz ~ 3.47kHz ? | |||
=SSG part= | |||
See [[SSG]] for details on this part's operation. | See [[SSG]] for details on this part's operation. | ||
Line 62: | Line 94: | ||
|} | |} | ||
= | =FM part= | ||
See [[FM]] for details on this part's operation. | |||
==Common FM | ==Common FM registers== | ||
{| class="regdef" | {| class="regdef" | ||
Line 107: | Line 114: | ||
|} | |} | ||
LFO | LFO frequency values are as follows: | ||
*0 – 3. | *0 – 3.98Hz | ||
*1 – 5. | *1 – 5.56Hz | ||
*2 – 6. | *2 – 6.02Hz | ||
*3 – 6. | *3 – 6.37Hz | ||
*4 – 6. | *4 – 6.88Hz | ||
*5 – 9. | *5 – 9.63Hz | ||
*6 – 48. | *6 – 48.1Hz | ||
*7 – 72.2 | *7 – 72.2Hz | ||
==Overall channel registers== | |||
The first value listed in the Address column is for channels 1/3; the second is for channels 2/4. | |||
{|class="regdef" | |||
| '''Address (Z80 port 4 or 6)''' || '''Data (Z80 port 5 or 7)''' || | |||
|- | |||
| $A1,$A2 | |||
| {{8BitRegister|F-Num 1|8}} | |||
| F-Numbers and Block (1/2) | |||
|- | |||
| $A5,$A6 | |||
| {{8BitRegister|-|2|Block|3|F-Num 2|3}} | |||
| F-Numbers and Block (2/2)<br/>(must set this first) | |||
|- | |||
| $A9,$AA | |||
| {{8BitRegister|2CH * F-Num 1|8}} | |||
| 2CH - 2 Slot F-Numbers/Block (1/2) | |||
|- | |||
| $AD,$AE | |||
| {{8BitRegister|-|2|2CH * Block|3|2CH * F-Num 2|3}} | |||
| 2CH - 2 Slot F-Numbers/Block (1/2)<br/>(must set this first) | |||
|- | |||
| $B1,$B2 | |||
| {{8BitRegister|-|2|FB|3|ALGO|3}} | |||
| Feedback (FB) and Algorithm (ALGO) | |||
|- | |||
| $B5,B6 | |||
| {{8BitRegister|L|1|R|1|AMS|2|-|1|PMS|3}} | |||
| Left (L)/Right (R) output, AM Sense (AMS), and PM Sense (PMS) | |||
|} | |||
== Channel | ==Channel registers== | ||
Depending on which channel you want to write to, the ports used are different: | Depending on which channel you want to write to, the ports used are different: | ||
* Channels 1 | * Channels 1 & 2: Ports 4/5 | ||
* Channels 3 | * Channels 3 & 4: Ports 6/7 | ||
===Per- | ===Per-operator registers=== | ||
The ranges given for the address represent all of the parameter values. Each channel's operators are laid out as follows: | The ranges given for the address represent all of the parameter values. Each channel's operators are laid out as follows: | ||
Line 167: | Line 205: | ||
|} | |} | ||
== | =ADPCM part= | ||
See [[ADPCM]] for details on this part's operation. | |||
{|class="regdef" | {| class="regdef" | ||
| '''Address (Z80 port 4 | |'''Address (Z80 port 4)''' | ||
|'''Data (Z80 port 5)''' | |||
|Value on [[reset]] | |||
|- | |- | ||
| $ | |$1C | ||
| {{8BitRegister| | |{{8BitRegister|B|1|-|1|A6|1|A5|1|A4|1|A3|1|A2|1|A1|1|}} | ||
| | |$00 | ||
| | |||
| | |||
| | |||
| | |||
| | |||
| | |||
|} | |} | ||
= ADPCM-A part = | * 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 reaches its end address. This means you have to write 1 to clear the flag, then 0 to keep it active. | |||
** Flags must be manually cleared, playing a new sample on the channel won't clear it. | |||
==ADPCM-A part== | |||
' | See [[ADPCM]] for details on this part's operation. | ||
{| class="regdef" | {| class="regdef" | ||
|'''Address (Z80 port 6)''' | |'''Address (Z80 port 6)''' | ||
|'''Data (Z80 port 7)''' | |'''Data (Z80 port 7)''' | ||
|Value on [[reset]] | |||
| | |||
|- | |- | ||
|$00 | |$00 | ||
|{{8BitRegister|Dump|1|-|1|CH6 ON|1|CH5 ON|1|CH4 ON|1|CH3 ON|1|CH2 ON |1|CH1 ON|1}} | |{{8BitRegister|Dump|1|-|1|CH6 ON|1|CH5 ON|1|CH4 ON|1|CH3 ON|1|CH2 ON |1|CH1 ON|1}} | ||
|$00 | |||
|'Dump' is the key on/off bit. Write 0 to start playing specified channels and write 1 to stop playing. | |||
|- | |- | ||
|$01 | |$01 | ||
|{{8BitRegister|-|2|Master volume|6}} | |{{8BitRegister|-|2|Master volume|6}} | ||
|$00 | |||
|Actually an attenuator, 0 is the loudest. | |||
|- | |- | ||
|$08~$0D (one for each channel) | |$08~$0D (one for each channel) | ||
|{{8BitRegister|L|1|R|1|-|1|Channel volume|5}} | |{{8BitRegister|L|1|R|1|-|1|Channel volume|5}} | ||
|$00 | |||
|Actually an attenuator, 0 is the loudest. L/R routes the output to the left and/or right channels. | |||
|- | |- | ||
|$10~$15 (one for each channel) | |$10~$15 (one for each channel) | ||
|{{8BitRegister|Sample's start address/256 LSB|8}} | |{{8BitRegister|Sample's start address/256 LSB|8}} | ||
|$00 | |||
|rowspan="4"|All ADPCM addresses must match a 256-byte boundary (bits 0~7 = 0) | |||
|- | |- | ||
|$18~$1D (one for each channel) | |$18~$1D (one for each channel) | ||
|{{8BitRegister|Sample's start address/256 MSB|8}} | |{{8BitRegister|Sample's start address/256 MSB|8}} | ||
|$00 | |||
|- | |- | ||
|$20~$25 (one for each channel) | |$20~$25 (one for each channel) | ||
|{{8BitRegister|Sample's stop address/256 LSB|8}} | |{{8BitRegister|Sample's stop address/256 LSB|8}} | ||
|$00 | |||
|- | |- | ||
|$28~$2D (one for each channel) | |$28~$2D (one for each channel) | ||
|{{8BitRegister|Sample's stop address/256 MSB|8}} | |{{8BitRegister|Sample's stop address/256 MSB|8}} | ||
|$00 | |||
|} | |} | ||
= ADPCM-B part = | ==ADPCM-B part== | ||
See [[ADPCM]] for details on this part's operation. | |||
{| class="regdef" | {| class="regdef" | ||
|'''Address (Z80 port 4)''' | |'''Address (Z80 port 4)''' | ||
|'''Data (Z80 port 5)''' | |'''Data (Z80 port 5)''' | ||
|Value on [[reset]] | |||
| | | | ||
|- | |- | ||
|$10 | |$10 | ||
|{{8BitRegister|Start|1|-|2|Repeat|1|-|3|Reset|1|}} | |{{8BitRegister|Start|1|-|2|Repeat|1|-|3|Reset|1|}} | ||
|Start | |$00 | ||
|Repeat: loop when end address is reached. Reset: clears Start and Repeat. | |||
|- | |- | ||
|$11 | |$11 | ||
|{{8BitRegister|L|1|R|1|-|6|}} | |{{8BitRegister|L|1|R|1|-|6|}} | ||
|Left/Right | |$00 | ||
|Left/Right channel output | |||
|- | |- | ||
|$12 | |$12 | ||
|{{8BitRegister|Sample's start address/256 LSB|8}} | |{{8BitRegister|Sample's start address/256 LSB|8}} | ||
| | |? | ||
|rowspan="4"|All ADPCM addresses must match a 256-byte boundary (bits 0~7 = 0) | |||
|- | |- | ||
|$13 | |$13 | ||
|{{8BitRegister|Sample's start address/256 MSB|8}} | |{{8BitRegister|Sample's start address/256 MSB|8}} | ||
| | |? | ||
|- | |- | ||
|$14 | |$14 | ||
|{{8BitRegister|Sample's stop address/256 LSB|8}} | |{{8BitRegister|Sample's stop address/256 LSB|8}} | ||
| | |? | ||
|- | |- | ||
|$15 | |$15 | ||
|{{8BitRegister|Sample's stop address/256 MSB|8}} | |{{8BitRegister|Sample's stop address/256 MSB|8}} | ||
| | |? | ||
|- | |- | ||
|$19 | |$19 | ||
|{{8BitRegister|Delta-N (L)|8}} | |{{8BitRegister|Delta-N (L)|8}} | ||
|rowspan="2"| | |? | ||
|rowspan="2"|Playback rate is f = 8M / 12 / 12 / (65535 / Delta-N) = 55555 * (Delta-N / 65535) Hz | |||
|- | |- | ||
|$1A | |$1A | ||
|{{8BitRegister|Delta-N (H)|8}} | |{{8BitRegister|Delta-N (H)|8}} | ||
|? | |||
|- | |- | ||
|$1B | |$1B | ||
|{{8BitRegister|ADPCM-B channel volume|8}} | |{{8BitRegister|ADPCM-B channel volume|8}} | ||
| | |? | ||
| | |Loudest is $FF | ||
|} | |} | ||
=Reading= | |||
= Reading = | |||
The only writable registers that can also be read are from the SSG. All other ports and addresses return different data. | The only writable registers that can also be read are from the SSG. All other ports and addresses return different data. |
Revision as of 00:35, 17 November 2016
Timers
To do: Page.
Address (Z80 port 4) | Data (Z80 port 5) | ||||||||||||||||||
$24 |
| ||||||||||||||||||
$25 |
| ||||||||||||||||||
$26 |
| ||||||||||||||||||
$27 |
|
- TA = Timer A (10bit), TB = Timer B (8bit)
- 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 (see below).
- The actual timer counter registers are not directly accessible. They can be reset to zero or initialised from load registers $24~$26
- Writing 0 to the load bits in register $27 will reset the timer counter registers to zero
- 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.
- Timer flag reset refers to the same flags that are read from port $04
- CSM mode is for automatic key on for operators on the second FM channel when timer A expires ?
- Timer A IRQ frequency: 8M / 2 / 12 (prescaler) / 12 / TA load = 27.1Hz ~ 27.8kHz ?
- Timer A IRQ frequency: 8M / 16 / 12 (prescaler) / 12 / TB load = 13.6Hz ~ 3.47kHz ?
SSG part
See SSG for details on this part's operation.
Address (Z80 port 4) | Data (Z80 port 5) | |||||||||||||||||||
$00 |
|
Channel A | ||||||||||||||||||
$01 |
| |||||||||||||||||||
$02 |
|
Channel B | ||||||||||||||||||
$03 |
| |||||||||||||||||||
$04 |
|
Channel C | ||||||||||||||||||
$05 |
| |||||||||||||||||||
$06 |
|
Noise channel | ||||||||||||||||||
$07 |
|
/Enable for Noise and Tone | ||||||||||||||||||
$08 |
|
Channel A | ||||||||||||||||||
$09 |
|
Channel B | ||||||||||||||||||
$0A |
|
Channel C | ||||||||||||||||||
$0B |
|
|||||||||||||||||||
$0C |
|
|||||||||||||||||||
$0D |
|
See diagram. |
FM part
See FM for details on this part's operation.
Common FM registers
Address (Z80 port 4) | Data (Z80 port 5) | |||||||||||||||||||
$22 |
|
LFO Frequency | ||||||||||||||||||
$28 |
|
Key On/Off |
LFO frequency values are as follows:
- 0 – 3.98Hz
- 1 – 5.56Hz
- 2 – 6.02Hz
- 3 – 6.37Hz
- 4 – 6.88Hz
- 5 – 9.63Hz
- 6 – 48.1Hz
- 7 – 72.2Hz
Overall channel registers
The first value listed in the Address column is for channels 1/3; the second is for channels 2/4.
Address (Z80 port 4 or 6) | Data (Z80 port 5 or 7) | |||||||||||||||||||
$A1,$A2 |
|
F-Numbers and Block (1/2) | ||||||||||||||||||
$A5,$A6 |
|
F-Numbers and Block (2/2) (must set this first) | ||||||||||||||||||
$A9,$AA |
|
2CH - 2 Slot F-Numbers/Block (1/2) | ||||||||||||||||||
$AD,$AE |
|
2CH - 2 Slot F-Numbers/Block (1/2) (must set this first) | ||||||||||||||||||
$B1,$B2 |
|
Feedback (FB) and Algorithm (ALGO) | ||||||||||||||||||
$B5,B6 |
|
Left (L)/Right (R) output, AM Sense (AMS), and PM Sense (PMS) |
Channel registers
Depending on which channel you want to write to, the ports used are different:
- Channels 1 & 2: Ports 4/5
- Channels 3 & 4: Ports 6/7
Per-operator registers
The ranges given for the address represent all of the parameter values. Each channel's operators are laid out as follows:
Operator | 1 | 2 | 3 | 4 |
---|---|---|---|---|
Channels 1, 3 | $x1 | $x5 | $x9 | $xD |
Channels 2, 4 | $x2 | $x6 | $xA | $xE |
Address (Z80 port 4 or 6) | Data (Z80 port 5 or 7) | |||||||||||||||||||
$31-$3E |
|
Detune (DT) and Multiple (MUL) | ||||||||||||||||||
$41-$4E |
|
Total Level (Volume) | ||||||||||||||||||
$51-$5E |
|
Key Scale (KS) and Attack Rate (AR) | ||||||||||||||||||
$61-$6E |
|
AM On (AM) and Decay Rate (DR) | ||||||||||||||||||
$71-$7E |
|
Sustain Rate (SR) | ||||||||||||||||||
$81-$8E |
|
Sustain Level (SL) and Release Rate (RR) | ||||||||||||||||||
$91-$9E |
|
SSG-EG |
ADPCM part
See ADPCM for details on this part's operation.
Address (Z80 port 4) | Data (Z80 port 5) | Value on reset | ||||||||||||||||||
$1C |
|
$00 |
- 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 reaches its end address. This means you have to write 1 to clear the flag, then 0 to keep it active.
- Flags must be manually cleared, playing a new sample on the channel won't clear it.
ADPCM-A part
See ADPCM for details on this part's operation.
Address (Z80 port 6) | Data (Z80 port 7) | Value on reset | |||||||||||||||||||
$00 |
|
$00 | 'Dump' is the key on/off bit. Write 0 to start playing specified channels and write 1 to stop playing. | ||||||||||||||||||
$01 |
|
$00 | Actually an attenuator, 0 is the loudest. | ||||||||||||||||||
$08~$0D (one for each channel) |
|
$00 | Actually an attenuator, 0 is the loudest. L/R routes the output to the left and/or right channels. | ||||||||||||||||||
$10~$15 (one for each channel) |
|
$00 | All ADPCM addresses must match a 256-byte boundary (bits 0~7 = 0) | ||||||||||||||||||
$18~$1D (one for each channel) |
|
$00 | |||||||||||||||||||
$20~$25 (one for each channel) |
|
$00 | |||||||||||||||||||
$28~$2D (one for each channel) |
|
$00 |
ADPCM-B part
See ADPCM for details on this part's operation.
Address (Z80 port 4) | Data (Z80 port 5) | Value on reset | |||||||||||||||||||
$10 |
|
$00 | Repeat: loop when end address is reached. Reset: clears Start and Repeat. | ||||||||||||||||||
$11 |
|
$00 | Left/Right channel output | ||||||||||||||||||
$12 |
|
? | All ADPCM addresses must match a 256-byte boundary (bits 0~7 = 0) | ||||||||||||||||||
$13 |
|
? | |||||||||||||||||||
$14 |
|
? | |||||||||||||||||||
$15 |
|
? | |||||||||||||||||||
$19 |
|
? | Playback rate is f = 8M / 12 / 12 / (65535 / Delta-N) = 55555 * (Delta-N / 65535) Hz | ||||||||||||||||||
$1A |
|
? | |||||||||||||||||||
$1B |
|
? | Loudest is $FF |
Reading
The only writable registers that can also be read are from the SSG. All other ports and addresses return different data.
Z80 port # | Data | Notes | ||||||||||||||||||
$04 |
|
When a timer expires and IRQ is enabled for the timer, the respective bit is set | ||||||||||||||||||
$05 |
|
Attempting to read non-SSG registers will fail | ||||||||||||||||||
$06 |
|
When a channel has reached the end address and stops, the respective bit is set, unless masked | ||||||||||||||||||
$07 | not implemented | Always returns $00 |