15 typedef struct fifo fifo;
18 u8int head, level, headpos;
26 Event *events[NEVENT] = {&timers[0].Event, &timers[1].Event, &timers[2].Event, &timers[3].Event, &evhblank, &evsamp};
30 ARR(sndfifo[0].d), VAR(sndfifo[0].head), VAR(sndfifo[0].level), VAR(sndfifo[0].headpos),
31 ARR(sndfifo[1].d), VAR(sndfifo[1].head), VAR(sndfifo[1].level), VAR(sndfifo[1].headpos),
32 VAR(timers[0].val), VAR(timers[0].clock), VAR(timers[0].sh), VAR(timers[0].snd),
33 VAR(timers[1].val), VAR(timers[1].clock), VAR(timers[1].sh), VAR(timers[1].snd),
34 VAR(timers[2].val), VAR(timers[2].clock), VAR(timers[2].sh), VAR(timers[2].snd),
35 VAR(timers[3].val), VAR(timers[3].clock), VAR(timers[3].sh), VAR(timers[3].snd),
40 addevent(Event *ev, int time)
46 for(p = &elist; (e = *p) != nil; p = &e->next){
63 for(p = &elist; (e = *p) != nil; p = &e->next)
67 e->next->time += e->time;
83 }while((elist->time += t) <= 0);
88 fifoput(int i, u32int s)
94 f->d[(f->head + f->level++) & 7] = s;
98 fifotimer(int b, int n)
102 extern s8int snddma[2];
104 for(i = 0; i < 2; i++){
108 for(j = 0; j < n && f->level > 0; j++){
109 snddma[i] = f->d[f->head] & 0xff;
111 if(++f->headpos == 4){
112 f->head = (f->head + 1) & 7;
128 timers[(v >> 10) & 1].snd |= 1;
130 timers[(v >> 14) & 1].snd |= 2;
131 if((v & 1<<11) != 0){
132 sndfifo[0].level = 0;
134 sndfifo[0].headpos = 0;
136 if((v & 1<<15) != 0){
137 sndfifo[1].level = 0;
139 sndfifo[1].headpos = 0;
149 if((*t->cnt & (COUNTUP|TIMERON)) != TIMERON)
151 return t->val + (clock - t->clock >> t->sh);
155 timerset(int i, u16int nc)
163 if((oc & (PRESC|COUNTUP|TIMERON)) == (nc & (PRESC|COUNTUP|TIMERON)))
165 if((oc & (COUNTUP|TIMERON)) == TIMERON){
166 v = t->val + (clock - t->clock >> t->sh);
170 if((oc & TIMERON) == 0 && (nc & TIMERON) != 0)
173 t->sh = 4 + (nc & 3) * 2;
177 t->clock = clock & -(1 << t->sh);
178 if((nc & (COUNTUP|TIMERON)) == TIMERON)
179 addevent(t, (0x10000 - t->val << t->sh) + (-clock & (1 << t->sh) - 1));
191 clock0 = clock + t->time;
192 t->clock = clock0 & -(1 << t->sh);
193 t->val = -t->time >> t->sh;
197 t->val = v = t->val + t->cnt[-1];
199 }while(v >= 0x10000);
201 addevent(t, (0x10000 - t->val << t->sh) + (-clock0 & (1 << t->sh) - 1));
202 if((*t->cnt & TIMERIRQ) != 0)
203 setif(IRQTIM0 << t->i);
205 fifotimer(t->snd, to);
206 if(++t >= timers + 4 || (*t->cnt & (COUNTUP | TIMERON)) != (COUNTUP|TIMERON))
208 t->val = v = t->val + to;
209 }while(v >= 0x10000);
216 extern void hblanktick(void *);
218 for(i = 0; i < 4; i++){
219 timers[i].f = timertick;
220 timers[i].aux = &timers[i];
222 timers[i].cnt = ®[TM0CNTH + i * 2];
224 evhblank.f = hblanktick;
225 addevent(&evhblank, 240*4);