The PowerNoise is a fantasy sound chip designed by jvsTSX and The Beesh-Spweesh!. The Hexheld fantasy console incorporates a PowerNoise core into its HiveCraft SoC.
It is equipped with three configurable "noise" channels, as well as a unique "slope" channel for more traditional waveform synthesis. It also has two 8-bit bidirectional GPIO ports (similar to the AY-3-8910), but in the Hexheld these are reserved.
Each channel has a 4-bit "octave" value, which corresponds to the divider that the master clock signal is fed through before it increments the frequency counter. For example, a value of 1 means that the frequency counter is incremented every other cycle.
Unlike some other sound chips, a higher value of the counter actually corresponds to a higher clock frequency: When the frequency counter reaches the maximum value of 4096, the channel it corresponds to is clocked once. Then, the frequency counter is reloaded with the value in the channel's 12-bit frequency register.
Each noise channel is implemented as a 16-bit LFSR with a configurable feedback bit.
There are two taps to the LFSR, labeled A and B. If tap B is disabled, then the feedback will just be the result of tap A.
When the channel is clocked:
- The feedback bit is calculated as the XOR of the two taps.
- The register is shifted left one place, with the most significant bit sent to the channel output.
- The least significant bit of the LFSR is set to the feedback bit.
The noise channel also contains an amplitude modulation feature. When it is enabled, the amplitude of the slope channel will be ANDed with the channel output before being sent to the mixer. (Multiple channels can have AM enabled, in which case the corresponding channel outputs are ANDed together.)
The slope channel uses an interesting method to generate lots of different waveforms. It contains a 7-bit portion counter which can be in one of two states (A or B). The highest 4 bits of this counter are sent to the mixer.
When the channel is clocked:
- The counter gets the current portion's 4-bit offset added to it (or subtracted from it).
- If the current portion has been active for the number of cycles specified in its length register, plus 1, the counter transitions to the opposite state (from B to A, or from A to B).
- If the portion has its "reset" flag set to
1
, the counter is reset to0x00
(or0x7f
, if the count direction is down) before beginning the next portion.
Offset | Description |
---|---|
0x00 |
Audio control register |
0x01 - 0x07 |
Noise channel 1 registers |
0x08 |
GPIO Port A |
0x09 - 0x0F |
Noise channel 2 registers |
0x10 |
GPIO Port B |
0x11 - 0x17 |
Noise channel 3 registers |
0x18 - 0x1F |
Slope channel registers |
EBA- -VVV
||| |||
||| +++-- Master volume (0..7)
||+-------- GPIO Port A direction (0: Output, 1: Input)
|+--------- GPIO Port B direction (0: Output, 1: Input)
+---------- Audio output enable
E--- --AB
| ||
| |+-- Enable Tap B
| +--- Enable amplitude modulation with the slope channel
+---------- Channel output enable
OOOO FFFF FFFF FFFF
|||| |||| |||| ||||
|||| ++++-++++-++++-- Frequency counter reload value
++++----------------- Octave (clock divider)
LLLL LLLL LLLL LLLL
|||| |||| |||| ||||
++++-++++-++++-++++-- LFSR value (this is only stable when the channel output is disabled!)
AAAA BBBB
|||| ||||
|||| ++++-- Tap B location (0: LSB, 15: MSB)
++++------- Tap A location (0: LSB, 15: MSB)
LLLL RRRR
|||| ||||
|||| ++++-- Right volume (0: Mute, 15: Loudest)
++++------- Left volume (0: Mute, 15: Loudest)
-AAA AAAA
||| ||||
+++-++++-- Output counter value (this is only stable when the channel output is disabled!)
ERAB ABAB
|||| ||||
|||| |||+-- Count direction for portion B (0: Up, 1: Down)
|||| ||+--- Count direction for portion A (0: Up, 1: Down)
|||| |+---- Reset the counter at the start of portion B
|||| +----- Reset the counter at the start of portion A
|||+------- Clip the counter during portion B (0: Enable rollover, 1: Prevent rollover)
||+-------- Clip the counter during portion A (0: Enable rollover, 1: Prevent rollover)
|+--------- Waveform reset (this resets both counters, so the wave will restart at the beginning of Portion A)
+---------- Channel output enable
OOOO FFFF FFFF FFFF
|||| |||| |||| ||||
|||| ++++-++++-++++-- Frequency counter reload value
++++----------------- Octave (clock divider)
AAAA AAAA
|||| ||||
++++-++++-- Number of counts for Portion A, minus 1
BBBB BBBB
|||| ||||
++++-++++-- Number of counts for Portion B, minus 1
AAAA BBBB
|||| ||||
|||| ++++-- Value to change counter by during Portion B
++++------- Value to change counter by during Portion A
LLLL RRRR
|||| ||||
|||| ++++-- Right volume (0: Mute, 15: Loudest)
++++------- Left volume (0: Mute, 15: Loudest)