Register description style

Discussion about the site's wikis, including bugs/issues encountered.

Moderator: Moderators

Post Reply
User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Register description style

Post by blargg »

I'd like to get thinking on how to present register behavior in the new Wiki, since I think it's going to take some experimentation. I think it's the biggest concrete style issue. Doing a good job can make a big difference on the overall Wiki. Some requirements:

* Clearly document what individual bits of a register do.
* Relatively easy to write.
* Vertically compact.

Take something like the APU noise channel, register $400E. The essential information present there is

$400E
Write-only
Controls loop and period
Bits 0-3 set period based on table [table here]
Bits 4-6 do nothing
Bit 7 is loop flag

Ideally we could let the Wiki convert this into a tabular form, so that we can easily change the way register behaviors are displayed, without having to edit every page. But this is probably not practical, or would involve some overly-complex solution.

The style in the linked APU noise page above works, but I'm not completely satisfied with it. I don't like the style as used on things like the MMC3 page, partly because it's more difficult to write. It's also less pleasant to read, as the text tends to run together. I definitely think the register descriptions need to be in a table, allowing styles, links, etc.

The style I developed for the APU on the old Wiki has the first line summarize the register, then the following ones elaborate. This allows a summary of multiple registers to just show the first line for each, with a link to show the full description.
User avatar
cpow
NESICIDE developer
Posts: 1097
Joined: Mon Oct 13, 2008 7:55 pm
Location: Minneapolis, MN
Contact:

Post by cpow »

I think the clearest style is that used by many datasheets...easy to read, easy to tabularize, easy to beef up with more info about particular bits or bit groups...

Something like:

Code: Select all

$400E: APU Noise Channel Control
This register controls the looping and period of the APU Noise Channel.
+===================================================+
|    7  |  6  |  5  |  4  |  3  |  2  |  1  |  0    |
+-------+-----------------+-------------------------+
|  LOOP |XXXXXXXXXXXXXXXXX|             PERIOD      |
+=========+=========================================+
|         | Write-only                              |
| LOOP    | 0: Do not loop noise                    |
|         | 1: Loop noise                           |
+---------+-----------------------------------------+
|         | Write-only                              |
| PERIOD  | Set noise channel period, valid         |
|         | values range from 0 - 15 and internally |
|         | are translated to the following values: |
|         | [insert table]                          |
+=========+=========================================+
Reset value: $00
The arrows and other line-art used to try to point at the register bits in other documenting styles are unnecessary clutter and hard to follow if there's too many, like if the 8-bit register has 8 different control bits. In the above form each bit or 'bit group' is given a name that can be used as a reference throughout other documentation. For example, instead of referencing "when the APU noise channel loop flag, bit 7 of $400E, is set", it becomes "when LOOP is set" or, in other sections of the document perhaps, "when LOOP in APU Noise Channel Control register is set, ...".

One of the things I found hard to follow when reading through APU documentation to try to understand how to implement my APU was it was not very clear when the item being referenced was an internal flag of one of the channel blocks (ie. the linear counter halt flag) or if it was a bit in one of the APU registers.

If each register, bit, and bit group, and internal machinery (flags, counters, temporary storage, etc.) is given a name and the name is carried through the rest of the documentation, the result can be an easy-to-follow and very powerful document.
User avatar
Banshaku
Posts: 2417
Joined: Tue Jun 24, 2008 8:38 pm
Location: Japan
Contact:

Post by Banshaku »

NESICIDE wrote:If each register, bit, and bit group, and internal machinery (flags, counters, temporary storage, etc.) is given a name and the name is carried through the rest of the documentation, the result can be an easy-to-follow and very powerful document.
This is an interesting approach. The only burden at the beginning is to define the name for every bit/register etc. It may not always be easy to give them a name.
User avatar
cpow
NESICIDE developer
Posts: 1097
Joined: Mon Oct 13, 2008 7:55 pm
Location: Minneapolis, MN
Contact:

Post by cpow »

Banshaku wrote: This is an interesting approach. The only burden at the beginning is to define the name for every bit/register etc. It may not always be easy to give them a name.
The names can be reused. LOOP and PERIOD, for example, can be used for each channel. If the "reference" name of the register was APU_NOISE_CTRL then the signal-reference can be "if LOOP is set" (if in a section referring only to the APU Noise Channel, or "if APU_NOISE_CTRL.LOOP is set" if elsewhere in the document.

Names are much easier on the eyes and brain...if single letters are used, one is forced to explain oneself over and over again for fear that the reader may not remember. "If APU_NOISE_CTRL.L (Loop flag) is set...".

I might take a stab at coming up with the register set descriptions further in this style.

I would really love to see a comprehensive NES Programmer's Reference Guide much like that of the C=64. I know this has been a goal of many individuals (on NesDev) and also many groups (the Wiki). There's lots of great stuff out there...but like anything rolling along with technology, it keeps getting segmented. I am now suffering through MMC3 IRQ counter emulation because I have two reference materials that describe its behavior completely differently and conflictingly.
User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Post by blargg »

I definitely think this naming idea is worth using. As mentioned above, one snag is that names must be chosen in advance. But if everything is going to be named, there would HAVE to be an assembler file to go along with it, so one could use such names in assembly code. This would require that all the names be distinct, AND that we not go changing them over and over, so the names we choose would need to be GOOD names from the start. Still, I like the idea. It's better to remember to set the ENV_DISABLED bit of SQ1_ENV than to set bit 5 (or whatever) of $4000.

The example register description also fits another requirement of mine: that the top row of the register description serves as a summary of the register, so that we can easily show a summary of a unit's registers in the same format as the full descriptions.
mic_
Posts: 922
Joined: Thu Oct 05, 2006 6:29 am

Post by mic_ »

One possibility is to do it in the style of gbatek/pandocs:

$400E - REG_NOISECNT - APU Noise channel control (W)
Bit 7 - Loop flag (1=On, 0=Off)
Bit 4-6 - Not used
Bit 0-3 - Noise period

[Noise period table goes here]

and in the code listing you'd have:

.EQU REG_NOISECNT $400E
.EQU NOISE_LOOP $80

etc..
User avatar
cpow
NESICIDE developer
Posts: 1097
Joined: Mon Oct 13, 2008 7:55 pm
Location: Minneapolis, MN
Contact:

Post by cpow »

mic_ wrote:One possibility is to do it in the style of gbatek/pandocs:

$400E - REG_NOISECNT - APU Noise channel control (W)
Bit 7 - Loop flag (1=On, 0=Off)
Bit 4-6 - Not used
Bit 0-3 - Noise period

[Noise period table goes here]

and in the code listing you'd have:

.EQU REG_NOISECNT $400E
.EQU NOISE_LOOP $80

etc..
The problem with this approach is it lacks traceability from the design documentation to the code. When the documentation uses the names that appear in the code, clarity follows for free. In your example nothing except common sense (I don't have much...) tells me that "NOISE_LOOP" is equivalent to "Bit 7 - Loop flag". I spend a lot of time at work arguing for less ambiguous product requirements or documentation, and most of it comes down to "how do I know specifically what is being referenced in the code from this design? it uses the same name...".

Also, in tabular form it is much easier to associate a table of values such as that for period with the signal itself...just put it in the signal description column. If a register has more than one multi-bit signal that needs a table then there's a direct link between the signal and its value descriptions...they're in the same row.
User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Post by blargg »

I'd like to apologize for apparently abandoning this. I've been unable to work on any projects for a few weeks, not sure why, I just try and find no energy or motivation. The snag I ran into with doing a test write of the general APU documentation is that I need names for all the registers and flags, that work well as constants in assembler. I'll see if I can post the issues with this sub-problem so that those like NESICIDE can offer some ideas and we can work out a decent set of names, and what all we'll name and NOT name.

OK, I guess I can post the beginnings I had:

Code: Select all

SQ1_ENV         = $4000
SQ1_SWEEP       = $4001
SQ1_TUNE        = $4002
SQ1_NOTE        = $4003

SQ2_ENV         = $4004
SQ2_SWEEP       = $4005
SQ2_TUNE        = $4006
SQ2_NOTE        = $4007

TRI_LINEAR      = $4008
TRI_TUNE        = $400A
TRI_NOTE        = $400B

NOI_ENV         = $400C
NOI_PERIOD      = $400E
NOI_NOTE        = $400F

DMC_FREQ        = $4010
DMC_DAC         = $4011
DMC_ADDR        = $4012
DMC_LENGTH      = $4013

CHAN_FLAGS      = $4015

APU_MODE        = $4017
I used an underscore for clarity, though we may decide that all names should lack underscores. I think they should all be uppercase, as that's the very common convention for hardware constants in assembler.

Then, for accessing particular fields, you use these constants:

Code: Select all

SQ_DUTY         = $40 ; 2 bits

ENV_LOOP        = $20
ENV_DISABLE     = $10
ENV_PERIOD      = $01 ; 4 bits

SWEEP_ENABLE    = $80
SWEEP_PERIOD    = $10 ; 3 bits
SWEEP_NEGATE    = $08
SWEEP_SHIFT     = $01 ; 3 bits

NOTE_LENGTH     = $08 ; 5 bits

LINEAR_CONTROL  = $80

NOISE_LOOPED    = $80
I didn't think having SQ_DUTY_13, SQ_DUTY_25, etc. would do much, since you can just do SQ_DUTY*0, SQ_DUTY*1, SQ_DUTY*2, and SQ_DUTY*3 to get the four duties. This is the idea for other multi-bit fields, like NOTE_LENGTH.

I don't think the constants can specify every detail (like the duties above), but they can remove arbitrary constants from code, making it clearer what the constant means.

The other requirement of course is that every field be named so that it can be referred to in the documentation merely by the constant. For example, the documentation could state "the envelope decrements the volume every ENV_PERIOD+1 envelope clocks" and not lack any precision as to exactly what bits this refers to.

The main issue is the naming style, and how fields are named so that they are suggestive of the registers they apply to. It seems that programmers won't accept names that are excessively long (which even these might be), so they must be fairly terse.
User avatar
MetalSlime
Posts: 186
Joined: Tue Aug 19, 2008 11:01 pm
Location: Japan

Post by MetalSlime »

blargg wrote:
OK, I guess I can post the beginnings I had:

Code: Select all

SQ1_ENV         = $4000
SQ1_SWEEP       = $4001
SQ1_TUNE        = $4002
SQ1_NOTE        = $4003
...cut

CHAN_FLAGS      = $4015

APU_MODE        = $4017
One thing that jumps out at me is that XXX_TUNE and XXX_NOTE could be easily mixed up since the terms are close in meaning. In my head, I differentiate the two by thinking of $4002/6/A as the low 8 bits of the period and $4003/7/B as the high 3 bits. So something like this makes more sense to me, and is less ambiguous:

Code: Select all

SQ1_LO = $4002
SQ1_HI = $4003

SQ2_LO = $4006
SQ2_HI = $4007

TRI_LO = $400A
TRI_HI = $400B
You could spell out LOW and HIGH if you wanted to.

Using XXX_HI doesn't tell us anything about the length counter, but I don't think it needs to.

Another one I'd change would be CHAN_FLAGS. If I were to see that somewhere outside of APU-specific documentation, it wouldn't be obvious to me that we were talking about the APU. APU_FLAGS is better.
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples »

I agree with MetalSlime's names (_LO and _HI).
Post Reply