carl9170: Update to latest upstream
[linux-libre-firmware.git] / aica / arm / aica.c
1 /* KallistiOS ##version##
2
3    aica.c
4    (c)2000-2002 Dan Potter
5
6    ARM support routines for using the wavetable channels
7 */
8
9 #include "aica_cmd_iface.h"
10 #include "aica.h"
11
12 extern volatile aica_channel_t *chans;
13
14 void aica_init() {
15     int i, j;
16
17     /* Initialize AICA channels */
18     SNDREG32(0x2800) = 0x0000;
19
20     for(i = 0; i < 64; i++) {
21         CHNREG32(i, 0) = 0x8000;
22
23         for(j = 4; j < 0x80; j += 4)
24             CHNREG32(i, j) = 0;
25
26         CHNREG32(i, 20) = 0x1f;
27     }
28
29     SNDREG32(0x2800) = 0x000f;
30 }
31
32 /* Translates a volume from linear form to logarithmic form (required by
33    the AICA chip */
34 static int logs[] = {
35     0, 15, 22, 27, 31, 35, 39, 42, 45, 47, 50, 52, 55, 57, 59, 61,
36     63, 65, 67, 69, 71, 73, 74, 76, 78, 79, 81, 82, 84, 85, 87, 88,
37     90, 91, 92, 94, 95, 96, 98, 99, 100, 102, 103, 104, 105, 106,
38     108, 109, 110, 111, 112, 113, 114, 116, 117, 118, 119, 120, 121,
39     122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
40     135, 136, 137, 138, 138, 139, 140, 141, 142, 143, 144, 145, 146,
41     146, 147, 148, 149, 150, 151, 152, 152, 153, 154, 155, 156, 156,
42     157, 158, 159, 160, 160, 161, 162, 163, 164, 164, 165, 166, 167,
43     167, 168, 169, 170, 170, 171, 172, 173, 173, 174, 175, 176, 176,
44     177, 178, 178, 179, 180, 181, 181, 182, 183, 183, 184, 185, 185,
45     186, 187, 187, 188, 189, 189, 190, 191, 191, 192, 193, 193, 194,
46     195, 195, 196, 197, 197, 198, 199, 199, 200, 200, 201, 202, 202,
47     203, 204, 204, 205, 205, 206, 207, 207, 208, 209, 209, 210, 210,
48     211, 212, 212, 213, 213, 214, 215, 215, 216, 216, 217, 217, 218,
49     219, 219, 220, 220, 221, 221, 222, 223, 223, 224, 224, 225, 225,
50     226, 227, 227, 228, 228, 229, 229, 230, 230, 231, 232, 232, 233,
51     233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 239, 239, 240,
52     240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246, 246,
53     247, 247, 248, 248, 249, 249, 250, 250, 251, 251, 252, 252, 253, 254, 255
54 };
55
56 static inline int calc_aica_vol(int x) {
57     return 0xff - logs[x & 0xff];
58 }
59
60 static inline int calc_aica_pan(int x) {
61     if(x == 0x80)
62         return 0;
63     else if(x < 0x80) {
64         return 0x10 | ((0x7f - x) >> 3);
65     }
66     else {
67         return (x - 0x80) >> 3;
68     }
69 }
70
71 /* Sets up a sound channel completely. This is generally good if you want
72    a quick and dirty way to play notes. If you want a more comprehensive
73    set of routines (more like PC wavetable cards) see below.
74
75    ch is the channel to play on (0 - 63)
76    smpptr is the pointer to the sound data; if you're running off the
77      SH4, then this ought to be (ptr - 0xa0800000); otherwise it's just
78      ptr. Basically, it's an offset into sound ram.
79    mode is one of the mode constants (16 bit, 8 bit, ADPCM)
80    nsamp is the number of samples to play (not number of bytes!)
81    freq is the sampling rate of the sound
82    vol is the volume, 0 to 0xff (0xff is louder)
83    pan is a panning constant -- 0 is left, 128 is center, 255 is right.
84
85    This routine (and the similar ones) owe a lot to Marcus' sound example --
86    I hadn't gotten quite this far into dissecting the individual regs yet. */
87 void aica_play(int ch, int delay) {
88     uint32 smpptr   = chans[ch].base;
89     uint32 mode     = chans[ch].type;
90     uint32 loopst   = chans[ch].loopstart;
91     uint32 loopend  = chans[ch].loopend;
92     uint32 freq     = chans[ch].freq;
93     uint32 vol      = chans[ch].vol;
94     uint32 pan      = chans[ch].pan;
95     uint32 loopflag = chans[ch].loop;
96
97     uint32 freq_lo, freq_base = 5644800;
98     int freq_hi = 7;
99     uint32 playCont;
100
101     /* Stop the channel (if it's already playing) */
102     aica_stop(ch);
103
104     /* Need to convert frequency to floating point format
105        (freq_hi is exponent, freq_lo is mantissa)
106        Formula is freq = 44100*2^freq_hi*(1+freq_lo/1024) */
107     while(freq < freq_base && freq_hi > -8) {
108         freq_base >>= 1;
109         --freq_hi;
110     }
111
112     freq_lo = (freq << 10) / freq_base;
113
114     /* Envelope setup. The first of these is the loop point,
115        e.g., where the sample starts over when it loops. The second
116        is the loop end. This is the full length of the sample when
117        you are not looping, or the loop end point when you are (though
118        storing more than that is a waste of memory if you're not doing
119        volume enveloping). */
120     CHNREG32(ch, 8) = loopst & 0xffff;
121     CHNREG32(ch, 12) = loopend & 0xffff;
122
123     /* Write resulting values */
124     CHNREG32(ch, 24) = (freq_hi << 11) | (freq_lo & 1023);
125
126     /* Convert the incoming pan into a hardware value and set it */
127     CHNREG8(ch, 36) = calc_aica_pan(pan);
128     CHNREG8(ch, 37) = 0xf;
129     /* turn off Low Pass Filter (LPF) */
130     CHNREG8(ch, 40) = 0x24;
131     /* Convert the incoming volume into a hardware value and set it */
132     CHNREG8(ch, 41) = calc_aica_vol(vol);
133
134     /* If we supported volume envelopes (which we don't yet) then
135        this value would set that up. The top 4 bits determine the
136        envelope speed. f is the fastest, 1 is the slowest, and 0
137        seems to be an invalid value and does weird things). The
138        default (below) sets it into normal mode (play and terminate/loop).
139     CHNREG32(ch, 16) = 0xf010;
140     */
141     CHNREG32(ch, 16) = 0x1f;    /* No volume envelope */
142
143
144     /* Set sample format, buffer address, and looping control. If
145        0x0200 mask is set on reg 0, the sample loops infinitely. If
146        it's not set, the sample plays once and terminates. We'll
147        also set the bits to start playback here. */
148     CHNREG32(ch, 4) = smpptr & 0xffff;
149     playCont = (mode << 7) | (smpptr >> 16);
150
151     if(loopflag)
152         playCont |= 0x0200;
153
154     if(delay) {
155         CHNREG32(ch, 0) = playCont;         /* key off */
156     }
157     else {
158         CHNREG32(ch, 0) = 0xc000 | playCont;    /* key on */
159     }
160 }
161
162 /* Start sound on all channels specified by chmap bitmap */
163 void aica_sync_play(uint32 chmap) {
164     int i = 0;
165
166     while(chmap) {
167         if(chmap & 0x1)
168             CHNREG32(i, 0) = CHNREG32(i, 0) | 0xc000;
169
170         i++;
171         chmap >>= 1;
172     }
173 }
174
175 /* Stop the sound on a given channel */
176 void aica_stop(int ch) {
177     CHNREG32(ch, 0) = (CHNREG32(ch, 0) & ~0x4000) | 0x8000;
178 }
179
180
181 /* The rest of these routines can change the channel in mid-stride so you
182    can do things like vibrato and panning effects. */
183
184 /* Set channel volume */
185 void aica_vol(int ch) {
186     CHNREG8(ch, 41) = calc_aica_vol(chans[ch].vol);
187 }
188
189 /* Set channel pan */
190 void aica_pan(int ch) {
191     CHNREG8(ch, 36) = calc_aica_pan(chans[ch].pan);
192 }
193
194 /* Set channel frequency */
195 void aica_freq(int ch) {
196     uint32 freq = chans[ch].freq;
197     uint32 freq_lo, freq_base = 5644800;
198     int freq_hi = 7;
199
200     while(freq < freq_base && freq_hi > -8) {
201         freq_base >>= 1;
202         freq_hi--;
203     }
204
205     freq_lo = (freq << 10) / freq_base;
206     CHNREG32(ch, 24) = (freq_hi << 11) | (freq_lo & 1023);
207 }
208
209 /* Get channel position */
210 int aica_get_pos(int ch) {
211     int i;
212
213     /* Observe channel ch */
214     SNDREG8(0x280d) = ch;
215
216     /* Wait a while */
217     for(i = 0; i < 20; i++)
218         __asm__ volatile ("nop");  /* Prevent loop from being optimized out */
219
220     /* Update position counters */
221     chans[ch].pos = SNDREG32(0x2814) & 0xffff;
222
223     return chans[ch].pos;
224 }