Hi!
MPU401, the most widely-used midi interface now works under my midi driver framework. Another new thing is a fine timer at a period of 156us, called directly from hardclock(). You can try the patch at: http://www.naklab.dnj.ynu.ac.jp/~tanimura/freebsd-serialmidi/patch/ newmidi-19990706.diff.gz The instruction is at: http://www.naklab.dnj.ynu.ac.jp/~tanimura/freebsd-serialmidi/ Here is the introduction of my new timer: Unlike 16550, MPU401 does not generate an interrupt on TX-ready. So we have to choose one of the following two options to drive MPU401: A. polling the status to wait until TX-ready, B. emulating a TX-ready interrupt by a timer. The option A, used by VoxWare(sys/i386/isa/sound/sb16_midi.c:sb16midi_out()), consumes most of syscall time to wait for MPU401 to come TX-ready. One byte of midi message takes 0.32ms to transmit. Some certain midi sequences contain continuous long sysexes summed up to 200 bytes or more, leaving a latency of 0.32 * 200 = 60ms or something like that. This latency results in an unstable tempo. I have chosen the option B to eliminate the latency on message transmission. In this case, the timer needs to be capable of a period less than 0.32ms. The conventional timeout(9) has a period of 1/hz[s], which is generally 10ms. (hz = 100) While raising hz to, eg 3000 seems to shorten the period of timeout(9) enough, many parts of the kernel would be affected by this change, likely to end up with poor stability. To solve this problem, I propose a new *fine* callout mechanism. The realtime clock interrupt is at (hz * (1 << hzmul))[Hz], where (1 << hzmul) is the mutiplication ratio of hz. Although the ratio can be any natural number in theory, I have chosen the power of two to reduce the computational cost of the clock divider. (discussed later) As desceribed above, (for i386) clkintr() is called at (hz * (1 << hzmul))[Hz], calling hardclock() at the same frequency. hardclock() has two elements in it: a callout detector and a clock divider. A callout detector traverses the callout list and makes a callout, as in softclock(), except that the IPL stays at splclock. A clock divider reduces the frequency to hz[Hz], to process the conventional hardclock(), which is now renamed to hardclock1(), and softclock(). Although dividing a clock tick generally involves a costing division operation of the dividor counter by (1 << hzmul), a ratio of 2^n allows us to replace the operation with a simple shift of (clkdiv >> hzmul), where clkdiv is the dividor counter incremented one by one on a hardclock(). Fig 1 shows the frequency and the IPL of the new timer handlers. Frequency IPL Timer ^ ^ Generator | | | | | v (hz * (1 << hzmul))[Hz] splclock clkintr() | | | | | v v v hardclock() -> Fine ________________________________________ | Callouts ^ ^ v | | hardclock1() | | | hz[Hz] splsoftclock v | | softclock() -> Conventional | | Callouts v v Fig 1: Call Frequency and IPL under New Timer Handling I have implemented the new fine callout system discussed above in the latest patch of my midi driver. hzmul is 6, to multiply the timer frequency to 6400Hz. The usage of the fine callout is the same as timeout(9), except for the prefix of fine-, and that the granularity of the ticks is (1/(hz * (1 << hzmul)))[s]. Although I have not done any quantitative evaluation yet, I played some midi sequences with sysex messages to show a picture on the LCD of my SC-88, recognizing no latency like VoxWare. This result states the effectiveness of my proposing fine callout system. The future works include porting to alpha and PC98, and tuning hzmul. Whew, that was some kind of a paper to write! I would be pleased very much if you let me know how you think of my idea. Thanks in advance! Seigo Tanimura <tanim...@naklab.dnj.ynu.ac.jp> To Unsubscribe: send mail to majord...@freebsd.org with "unsubscribe freebsd-hackers" in the body of the message