* Wrote about that one time I got really drunk and tried to put every global variable...
[pineappletracker.git] / oldchip.c
blob8ff6225766c7e30e2cd3b6176235caf48b1bdb3d
1 /* vi:set ts=4 sts=4 sw=4: */
2 #include "pineapple.h"
4 volatile u8 callbackwait;
5 u8 callbacktime = 180;
7 u8 trackwait;
8 u8 trackpos;
9 u8 songpos;
11 u8 playsong;
12 u8 playtrack;
14 u8 interruptwait = 0;
16 /*const u16 freqtable[] = {
17 0x010b, 0x011b, 0x012c, 0x013e, 0x0151, 0x0165, 0x017a, 0x0191, 0x01a9,
18 0x01c2, 0x01dd, 0x01f9, 0x0217, 0x0237, 0x0259, 0x027d, 0x02a3, 0x02cb,
19 0x02f5, 0x0322, 0x0352, 0x0385, 0x03ba, 0x03f3, 0x042f, 0x046f, 0x04b2,
20 0x04fa, 0x0546, 0x0596, 0x05eb, 0x0645, 0x06a5, 0x070a, 0x0775, 0x07e6,
21 0x085f, 0x08de, 0x0965, 0x09f4, 0x0a8c, 0x0b2c, 0x0bd6, 0x0c8b, 0x0d4a,
22 0x0e14, 0x0eea, 0x0fcd, 0x10be, 0x11bd, 0x12cb, 0x13e9, 0x1518, 0x1659,
23 0x17ad, 0x1916, 0x1a94, 0x1c28, 0x1dd5, 0x1f9b, 0x217c, 0x237a, 0x2596,
24 0x27d3, 0x2a31, 0x2cb3, 0x2f5b, 0x322c, 0x3528, 0x3851, 0x3bab, 0x3f37,
25 0x42f9, 0x46f5, 0x4b2d, 0x4fa6, 0x5462, 0x5967, 0x5eb7, 0x6459, 0x6a51,
26 0x70a3, 0x7756, 0x7e6f
27 };*/
29 // for 16kHz
30 /*const u16 freqtable[] = {
31 0x0085, 0x008d, 0x0096, 0x009f, 0x00a8, 0x00b2, 0x00bd, 0x00c8, 0x00d4,
32 0x00e1, 0x00ee, 0x00fc, 0x010b, 0x011b, 0x012c, 0x013e, 0x0151, 0x0165,
33 0x017a, 0x0191, 0x01a9, 0x01c2, 0x01dd, 0x01f9, 0x0217, 0x0237, 0x0259,
34 0x027d, 0x02a3, 0x02cb, 0x02f5, 0x0322, 0x0352, 0x0385, 0x03ba, 0x03f3,
35 0x042f, 0x046f, 0x04b2, 0x04fa, 0x0546, 0x0596, 0x05eb, 0x0645, 0x06a5,
36 0x070a, 0x0775, 0x07e6, 0x085f, 0x08de, 0x0965, 0x09f4, 0x0a8c, 0x0b2c,
37 0x0bd6, 0x0c8b, 0x0d4a, 0x0e14, 0x0eea, 0x0fcd, 0x10be, 0x11bd, 0x12cb,
38 0x13e9, 0x1518, 0x1659, 0x17ad, 0x1916, 0x1a94, 0x1c28, 0x1dd5, 0x1f9b,
39 0x217c, 0x237a, 0x2596, 0x27d3, 0x2a31, 0x2cb3, 0x2f5b, 0x322c, 0x3528,
40 0x3851, 0x3bab, 0x3f37
41 };*/
43 // for 48kHz
44 const u16 freqtable[] = {
45 0x002c, 0x002f, 0x0032, 0x0035, 0x0038, 0x003b, 0x003f, 0x0042, 0x0046,
46 0x004b, 0x004f, 0x0054, 0x0059, 0x005e, 0x0064, 0x006a, 0x0070, 0x0077,
47 0x007e, 0x0085, 0x008d, 0x0096, 0x009f, 0x00a8, 0x00b2, 0x00bd, 0x00c8,
48 0x00d4, 0x00e1, 0x00ee, 0x00fc, 0x010b, 0x011b, 0x012c, 0x013e, 0x0151,
49 0x0165, 0x017a, 0x0190, 0x01a8, 0x01c2, 0x01dc, 0x01f9, 0x0217, 0x0237,
50 0x0258, 0x027c, 0x02a2, 0x02ca, 0x02f4, 0x0321, 0x0351, 0x0384, 0x03b9,
51 0x03f2, 0x042e, 0x046e, 0x04b1, 0x04f8, 0x0544, 0x0594, 0x05e9, 0x0643,
52 0x06a3, 0x0708, 0x0773, 0x07e4, 0x085c, 0x08dc, 0x0962, 0x09f1, 0x0a89,
53 0x0b29, 0x0bd3, 0x0c87, 0x0d46, 0x0e10, 0x0ee6, 0x0fc9, 0x10b9, 0x11b8,
54 0x12c5, 0x13e3, 0x1512
57 const s8 sinetable[] = {
58 0, 12, 25, 37, 49, 60, 71, 81, 90, 98, 106, 112, 117, 122, 125, 126,
59 127, 126, 125, 122, 117, 112, 106, 98, 90, 81, 71, 60, 49, 37, 25, 12,
60 0, -12, -25, -37, -49, -60, -71, -81, -90, -98, -106, -112, -117, -122,
61 -125, -126, -127, -126, -125, -122, -117, -112, -106, -98, -90, -81,
62 -71, -60, -49, -37, -25, -12
65 struct channel {
66 u8 tnum;
67 s8 transp;
68 u8 tnote;
69 u8 lastinstr;
70 u8 inum;
71 u8 iptr;
72 u8 iwait;
73 u8 inote;
74 s8 bendd;
75 s16 bend;
76 s8 volumed;
77 s16 dutyd;
78 u8 vdepth;
79 u8 vrate;
80 u8 vpos;
81 s16 inertia;
82 u16 slur;
83 } channel[4];
85 void silence(){
86 u8 i;
88 for(i = 0; i < 4; i++){
89 osc[i].volume = 0;
91 playsong = 0;
92 playtrack = 0;
95 void runcmd(u8 ch, u8 cmd, u8 param){
96 switch(cmd){
97 case 0:
98 channel[ch].inum = 0;
99 break;
100 case 'd':
101 osc[ch].duty = param << 8;
102 break;
103 case 'f':
104 channel[ch].volumed = param;
105 break;
106 case 'i':
107 channel[ch].inertia = param << 1;
108 break;
109 case '@':
110 channel[ch].iptr = param;
111 break;
112 case 's':
113 channel[ch].bendd = param;
114 break;
115 case 'm':
116 channel[ch].dutyd = param << 6;
117 break;
118 case 't':
119 channel[ch].iwait = (param*6);
120 break;
121 case 'v':
122 osc[ch].volume = param;
123 break;
124 case 'w':
125 osc[ch].waveform = param;
126 break;
127 case '+':
128 channel[ch].inote = param + channel[ch].tnote - 12 * 4;
129 break;
130 case '=':
131 channel[ch].inote = param;
132 break;
133 case '~':
134 if(channel[ch].vdepth != (param >> 4)){
135 channel[ch].vpos = 0;
137 channel[ch].vdepth = param >> 4;
138 channel[ch].vrate = (param/2) & 0xf;
139 //channel[ch].vrate = param & 0xf;
140 break;
141 case '*':
142 callbacktime = -param;
143 break;
147 void iedplonk(int note, int instr){
148 channel[0].tnote = note;
149 channel[0].inum = instr;
150 channel[0].iptr = 0;
151 channel[0].iwait = 0;
152 channel[0].bend = 0;
153 channel[0].bendd = 0;
154 channel[0].volumed = 0;
155 channel[0].dutyd = 0;
156 channel[0].vdepth = 0;
159 void startplaytrack(int t){
160 channel[0].tnum = t;
161 channel[1].tnum = 0;
162 channel[2].tnum = 0;
163 channel[3].tnum = 0;
164 trackpos = 0;
165 trackwait = 0;
166 playtrack = 1;
167 playsong = 0;
170 void startplaysong(int p){
171 songpos = p;
172 trackpos = 0;
173 trackwait = 0;
174 playtrack = 0;
175 playsong = 1;
178 void playroutine(){ // called at 50 Hz
179 u8 ch;
181 if(playtrack || playsong){
182 if(trackwait){
183 trackwait--;
184 }else{
185 trackwait = 12;
186 //trackwait = 4;
188 if(!trackpos){
189 if(playsong){
190 if(songpos >= songlen){
191 playsong = 0;
192 }else{
193 for(ch = 0; ch < 4; ch++){
194 u8 tmp[2];
196 readsong(songpos, ch, tmp);
197 channel[ch].tnum = tmp[0];
198 channel[ch].transp = tmp[1];
200 songpos++;
205 if(playtrack || playsong){
206 for(ch = 0; ch < 4; ch++){
207 if(channel[ch].tnum){
208 struct trackline tl;
209 u8 instr = 0;
211 readtrack(channel[ch].tnum, trackpos, &tl);
212 if(tl.note){
213 channel[ch].tnote = tl.note + channel[ch].transp;
214 instr = channel[ch].lastinstr;
216 if(tl.instr){
217 instr = tl.instr;
219 if(instr){
220 channel[ch].lastinstr = instr;
221 channel[ch].inum = instr;
222 channel[ch].iptr = 0;
223 channel[ch].iwait = 0;
224 channel[ch].bend = 0;
225 channel[ch].bendd = 0;
226 channel[ch].volumed = 0;
227 channel[ch].dutyd = 0;
228 channel[ch].vdepth = 0;
230 if(tl.cmd[0])
231 runcmd(ch, tl.cmd[0], tl.param[0]);
232 if(tl.cmd[1])
233 runcmd(ch, tl.cmd[1], tl.param[1]);
237 trackpos++;
238 trackpos &= 31;
243 for(ch = 0; ch < 4; ch++){
244 s16 vol;
245 u16 duty;
246 u16 slur;
248 // i dunno if that last condition is correct...........................
249 while((channel[ch].inum && !channel[ch].iwait) || channel[0].iptr == 0){
250 u8 il[2];
252 readinstr(channel[ch].inum, channel[ch].iptr, il);
253 channel[ch].iptr++;
255 runcmd(ch, il[0], il[1]);
257 if(channel[ch].iwait) channel[ch].iwait--;
259 if(channel[ch].inertia){
260 s16 diff;
262 slur = channel[ch].slur;
263 diff = freqtable[channel[ch].inote] - slur;
264 //diff >>= channel[ch].inertia;
265 if(diff > 0){
266 if(diff > channel[ch].inertia) diff = channel[ch].inertia;
267 }else if(diff < 0){
268 if(diff < -channel[ch].inertia) diff = -channel[ch].inertia;
270 slur += diff;
271 channel[ch].slur = slur;
272 }else{
273 slur = freqtable[channel[ch].inote];
275 osc[ch].freq =
276 slur +
277 channel[ch].bend +
278 ((channel[ch].vdepth * sinetable[channel[ch].vpos & 63]) >> 2);
279 channel[ch].bend += channel[ch].bendd;
280 vol = osc[ch].volume + channel[ch].volumed;
281 if(vol < 0) vol = 0;
282 if(vol > 255) vol = 255;
283 osc[ch].volume = vol;
285 duty = osc[ch].duty + channel[ch].dutyd;
286 if(duty > 0xe000) duty = 0x2000;
287 if(duty < 0x2000) duty = 0xe000;
288 osc[ch].duty = duty;
290 channel[ch].vpos += channel[ch].vrate;
294 void initchip(){
295 trackwait = 0;
296 trackpos = 0;
297 playsong = 0;
298 playtrack = 0;
300 osc[0].volume = 0;
301 channel[0].inum = 0;
302 osc[1].volume = 0;
303 channel[1].inum = 0;
304 osc[2].volume = 0;
305 channel[2].inum = 0;
306 osc[3].volume = 0;
307 channel[3].inum = 0;
310 u8 interrupthandler() // called at 9000 Hz
312 u8 i;
313 u8 j = 0;
314 s16 acc;
315 static u32 noiseseed = 1;
316 u8 newbit = 0;
318 if(noiseseed & 0x80000000L) newbit ^= 1;
319 if(noiseseed & 0x01000000L) newbit ^= 1;
320 if(noiseseed & 0x00000040L) newbit ^= 1;
321 if(noiseseed & 0x00000200L) newbit ^= 1;
322 noiseseed = (noiseseed << 1) | newbit;
324 if(callbackwait){
325 callbackwait--;
326 }else{
327 playroutine();
328 callbackwait = callbacktime - 1;
331 acc = 0;
332 for(i = 0; i < 4; i++){
333 s8 value; // [-32,31]
335 switch(osc[i].waveform){
336 case WF_TRI:
337 if(osc[i].phase < 0x8000){
338 value = -32 + (osc[i].phase >> 9);
339 }else{
340 value = 31 - ((osc[i].phase - 0x8000) >> 9);
342 break;
343 case WF_SAW:
344 value = -32 + (osc[i].phase >> 10);
345 break;
346 case WF_PUL:
347 value = (osc[i].phase > osc[i].duty)? -32 : 31;
348 break;
349 case WF_NOI:
350 value = (noiseseed & 63) - 32;
351 break;
352 case WF_SINE:
353 value = sinetable[j];
354 if(j >= sizeof(sinetable)-1) j = 0;
355 else j++;
356 default:
357 value = 0;
358 break;
361 osc[i].phase += osc[i].freq;
363 acc += value * osc[i].volume; // rhs = [-8160,7905]
366 // acc [-32640,31620]
367 return 128 + (acc >> 8); // [1,251]