back to buchty.net Casiorama back to Casiorama

The filters Trying to reach me?
The FZ-1's sound generation essentially relies on three custom chips named GAA, GAB, and GAX. Of course, no information about these guys is to be found anywhere — or as the great coder O'bit Wang Kaypro II once said: Use the source, Luke!.

Suggestions, questions, acclamation, or simply curiosity about who that guy is you might want to place here:

rainer@buchty.net


Overview

The sound generation consists of three active custom chips (GAA, GAB, and GAX) and a passive one (GAS). Seemingly, the sound generation was too complex to fit into a single ASIC, or maybe it was just a matter of cost. Anyway, we have:

  • GAA is essentially the address generator. It takes the waveform's start address, loop size, playback direction, and incrementum to perform wave RAM addressing. It also exercises some mystic control over GAX which is volume control for mix according to the FZ20m schematics. The service manual, in term, tells a story about harmonic distortion avoidance, which probably means the same.

  • GAB is the master controller of this setup. It watches over loop/sample end and generates the PCM interrupt. It also provides S&H control, so that the DACs' output is sampled for postprocessing by the DCF/DCA chips.

  • GAX takes the wave RAM's response and feeds it to one of two PCM54 16-Bit DACs. Each of the two DACs serves 4 voices which get demultiplexed by the S&H stages. Whatever it does with those four control signals coming from GAA happens entirely inside GAX. According to a hint in the service manual it controls the cross fading. While this is attributed to GAS, GAX itself is also labeled GAS in the main-board schematics, so it's probably safe to assume that it's just doing crude 16-bit shifting. This could explain the grainy cross-fade sound.

  • GAS is a bus arbiter, granting wave RAM access to either GAA or the FZ's CPU. It also does DRAM address multiplexing and refreshing. Furthermore, it generates the write signal upon sampling.
Electrical interface

Among the obvious pins, the entire setup makes use of a couple of more arcane ones, particularly for interfacing GAA with GAB, and GAA with GAX.

  • GAA to GAX: TB[1:4] do whatever magic inside GAX regarding volume adjustment and harmonic distortion avoidance.

  • GAB to GAX: GAX receives the output sample clock from GAB via GAB32 and YY55, which are called CK1 and CK2 on the GAX side of things. Furthermore, it receives the ZON signal, which probably means sound on. The service manual says it equals write stop to wave memory, which however makes no sense as GAX has no saying in sampling, only playback.

  • GAA to GAB and vice versa: Those guys exchange the current waveform address via C[21:1]. Bad news for anyone who ever wanted to go beyond 2MW of sample memory. GAA just can't handle it. We have a bunch of anonymous YY signals, of which YY3 signals GAA access to waveform memory, and YY5 serving as a clock enable/disable to the GAX clock generation.
    In addition, there's some signals with more speaking names, which are however not quite clear yet. If the abbreviations strike a nerve with you, let me know:
    • PON4, RON4, and LOP probably mean play on, reverse on, and loop mode.
    • There's CFLE, CFLF, and CFLP. No idea so far, but because of the consistent L I'm inclined to attribute it to looping.
    • We then have CFF6 (which might or might not belong to the above group) and OSN6 which I just paired because of the 6. Also no clue yet.
    • Finally, there's ACF. Open for guesses.
    In any case, I'd assume that the YY together with the above group perform some state signaling between GAA and GAB. At an input clock of 13.824MHz and 8 voices and a maximum sample frequency of 36kHz, that leaves a whopping 48 steps for sound generation, so we'd need at least 6 state bits. Since we have YY[3:8] that might be them at first sight, but YY3 is said to be 1MHz. Ho-hum.
Programming GAA/GAB

GAA and GAB each occupy 4 word addresses in I/O space (command, data1/2/3 for GAA; command, n/a, data1/2 for GAB) and feature a uniform access scheme: OS-wise, a command word is handed over in register DX, with additional parameters in AX (only for GAA), BX, and CX. These are written into the four (three) GAx registers in this very order with the command transfer typically taking place via the gaa_write and gab_write routines.

The command word itself dissects into the command itself in DH and the target voice(s) in DL. The latter is handed over as a bit pattern that allows addressing multiple voices at once.

The command set divides into four essential command blocks:

  • Sampling control (GAB-only)
    • 0x20: set sample rate
      BX=8 for initialization, BX=4+srate_index (0:36kHz, 1: 18kHz, 2: 9kHz) otherwise.
      No further parameter.
    • 0x28: start pre-recording (no params)
    • 0x30: start sampling (no params)
    • 0x38: stop sampling (no params)


  • Waveform and loop configuration
    • 0x40: set wave start (GAA) and end (GAB)
      BX provides the lower 16 address bits, CX the upper 5. For GAA, AX is set to 0.

    • 0x41: set loop start (GAA) and end (GAB)
      For GAA, AX/BX provide the loop end address, CX the loop fine setting.
      For GAB, like 0x40, but providing the loop end address.

    • 0x42: playback control
      For GAA, this sets the incrementum as incr>>srate_index (see above) via AX.
      No further parameters.
      Caveat: For synthesized sounds, 0x5d9 needs to be added. For GAB, things get a tad more complex. A table says more than 1000 words ...

    • 0x43: loop control
      For GAA, this sets the loop size. The same encoding as for 0x41 applies.
      For GAB, there's again some control bits. See table.

    • 0x44: loop skipping/tracing
      This is essentially a GAB command: BX=1 means trace, BX=0 skip.
      Upon disabling a voice, GAA gets an AX=0 here, too.

    • 0x45: loop crossfade control
      This is essentially a GAA command, transporting the loop crossfade time in
      AX=[0:4095] and no further parameters.
      This is a tuned value that needs to be computed as loopxf<<8/tune[note].
      Upon initializing a voice, GAB gets a BX=0xffff here.

    • 0x46: get/set interrupt mask (GAB-only)
    • For writing, it will set the interrupt mask via BX.
      Reading will deliver said mask in GAB's first data register.
      This is applied with DL=0xff.


  • Status inquiry
    • 0x80: inquire wave pointer (GAA-only)
      Returns the addressed voice's current wave pointer via GAA's data2/3 registers or BX/CX, respectively. Encoding like 0x40.

    • 0x81: inquire loop pointer (GAA-only)
      While not appearing in the FZ-1 OS, I'm somewhat convinced that it exists and will return the voice's loop pointer in 0x41 encoding.

    • 0x82: inquire status (GAB-only)
      Returns a 16-bit status via GAB's data1 register or BX, respectively; 0x42 encoding.

Apparently, there's no dedicated GAX control with regard to those magic TB[1:4] signals. Presumably, these are set implicitly, corresponding to crossfading settings and, eventually, the number of active voices.

Anything missing? A yes, the tables. Here in gnumeric and Excel format.