DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/hardware/snd_pc98/sound/opngenc.c
00001 #include    "np2glue.h"
00002 //#include      "compiler.h"
00003 #include        <math.h>
00004 //#include      "pccore.h"
00005 //#include      "iocore.h"
00006 #include        "sound.h"
00007 #include        "fmboard.h"
00008 //#include      "keydisp.h"
00009 
00010 
00011 #define OPM_ARRATE               399128L
00012 #define OPM_DRRATE              5514396L
00013 
00014 #define EG_STEP (96.0 / EVC_ENT)                                        // dB step
00015 #define SC(db)  (SINT32)((db) * ((3.0 / EG_STEP) * (1 << ENV_BITS))) + EC_DECAY
00016 #define D2(v)   (((double)(6 << KF_BITS) * log((double)(v)) / log(2.0)) + 0.5)
00017 #define FMASMSHIFT      (32 - 6 - (OPM_OUTSB + 1 + FMDIV_BITS) + FMVOL_SFTBIT)
00018 #define FREQBASE4096    ((double)OPNA_CLOCK / calcrate / 64)
00019 
00020 
00021         OPNCFG  opncfg;
00022 #ifdef OPNGENX86
00023         char    envshift[EVC_ENT];
00024         char    sinshift[SIN_ENT];
00025 #endif
00026 
00027 
00028 static  SINT32  detunetable[8][32];
00029 static  SINT32  attacktable[94];
00030 static  SINT32  decaytable[94];
00031 
00032 static const SINT32     decayleveltable[16] = {
00033                                         SC( 0),SC( 1),SC( 2),SC( 3),SC( 4),SC( 5),SC( 6),SC( 7),
00034                                         SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)};
00035 static const UINT8 multipletable[] = {
00036                                 1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30};
00037 static const SINT32 nulltable[] = {
00038                                         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
00039                                         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
00040 static const UINT8 kftable[16] = {0,0,0,0,0,0,0,1,2,3,3,3,3,3,3,3};
00041 static const UINT8 dttable[] = {
00042                                         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00043                                         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00044                                         0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
00045                                         2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 8, 8, 8,
00046                                         1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5,
00047                                         5, 6, 6, 7, 8, 8, 9,10,11,12,13,14,16,16,16,16,
00048                                         2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7,
00049                                         8, 8, 9,10,11,12,13,14,16,17,19,20,22,22,22,22};
00050 static const int extendslot[4] = {2, 3, 1, 0};
00051 static const int fmslot[4] = {0, 2, 1, 3};
00052 
00053 
00054 void opngen_initialize(UINT rate) {
00055 
00056         UINT    ratebit;
00057         int             i;
00058         char    sft;
00059         int             j;
00060         double  pom;
00061         long    detune;
00062         UINT32  calcrate;
00063 
00064         if (rate == 44100) {
00065                 ratebit = 0;
00066         }
00067         else if (rate == 22050) {
00068                 ratebit = 1;
00069         }
00070         else {
00071                 ratebit = 2;
00072         }
00073         calcrate = (OPNA_CLOCK / 72) >> ratebit;
00074         opncfg.calc1024 = FMDIV_ENT * 44100 / (OPNA_CLOCK / 72);
00075 
00076         for (i=0; i<EVC_ENT; i++) {
00077 #ifdef OPNGENX86
00078                 sft = ENVTBL_BIT;
00079                 while(sft < (ENVTBL_BIT + 8)) {
00080                         pom = (double)(1 << sft) / pow(10.0, EG_STEP*(EVC_ENT-i)/20.0);
00081                         opncfg.envtable[i] = (long)pom;
00082                         envshift[i] = sft - TL_BITS;
00083                         if (opncfg.envtable[i] >= (1 << (ENVTBL_BIT - 1))) {
00084                                 break;
00085                         }
00086                         sft++;
00087                 }
00088 #else
00089                 pom = (double)(1 << ENVTBL_BIT) / pow(10.0, EG_STEP*(EVC_ENT-i)/20.0);
00090                 opncfg.envtable[i] = (long)pom;
00091 #endif
00092         }
00093         for (i=0; i<SIN_ENT; i++) {
00094 #ifdef OPNGENX86
00095                 char sft;
00096                 sft = SINTBL_BIT;
00097                 while(sft < (SINTBL_BIT + 8)) {
00098                         pom = (double)(1 << sft) * sin(2*PI*i/SIN_ENT);
00099                         opncfg.sintable[i] = (long)pom;
00100                         sinshift[i] = sft;
00101                         if (opncfg.sintable[i] >= (1 << (SINTBL_BIT - 1))) {
00102                                 break;
00103                         }
00104                         if (opncfg.sintable[i] <= -1 * (1 << (SINTBL_BIT - 1))) {
00105                                 break;
00106                         }
00107                         sft++;
00108                 }
00109 #else
00110                 pom = (double)((1 << SINTBL_BIT) - 1) * sin(2*PI*i/SIN_ENT);
00111                 opncfg.sintable[i] = (long)pom;
00112 #endif
00113         }
00114         for (i=0; i<EVC_ENT; i++) {
00115                 pom = pow(((double)(EVC_ENT-1-i)/EVC_ENT), 8) * EVC_ENT;
00116                 opncfg.envcurve[i] = (long)pom;
00117                 opncfg.envcurve[EVC_ENT + i] = i;
00118         }
00119         opncfg.envcurve[EVC_ENT*2] = EVC_ENT;
00120 
00121 //      opmbaserate = (1L << FREQ_BITS) / (rate * x / 44100) * 55466;
00122 //      でも今は x == 55466だから…
00123 
00124 //      ここで FREQ_BITS >= 16が条件
00125         if (rate == 44100) {
00126                 opncfg.ratebit = 0 + (FREQ_BITS - 16);
00127         }
00128         else if (rate == 22050) {
00129                 opncfg.ratebit = 1 + (FREQ_BITS - 16);
00130         }
00131         else {
00132                 opncfg.ratebit = 2 + (FREQ_BITS - 16);
00133         }
00134 
00135         for (i=0; i<4; i++) {
00136                 for (j=0; j<32; j++) {
00137                         detune = dttable[i*32 + j];
00138                         sft = ratebit + (FREQ_BITS - 21);
00139                         if (sft >= 0) {
00140                                 detune <<= sft;
00141                         }
00142                         else {
00143                                 detune >>= (0 - sft);
00144                         }
00145 
00146                         detunetable[i][j]   = detune;
00147                         detunetable[i+4][j] = -detune;
00148                 }
00149         }
00150         for (i=0; i<4; i++) {
00151                 attacktable[i] = decaytable[i] = 0;
00152         }
00153         for (i=4; i<64; i++) {
00154                 double freq = (double)(EVC_ENT << ENV_BITS) * FREQBASE4096;
00155                 if (i < 8) {                                                    // 忘れてます。
00156                         freq *= 1.0 + (i & 2) * 0.25;
00157                 }
00158                 else if (i < 60) {
00159                         freq *= 1.0 + (i & 3) * 0.25;
00160                 }
00161                 freq *= (double)(1 << ((i >> 2) - 1));
00162 #if 0
00163                 attacktable[i] = (long)((freq + OPM_ARRATE - 1) / OPM_ARRATE);
00164                 decaytable[i] = (long)((freq + OPM_DRRATE - 1) / OPM_DRRATE);
00165 #else
00166                 attacktable[i] = (long)(freq / OPM_ARRATE);
00167                 decaytable[i] = (long)(freq / OPM_DRRATE);
00168 #endif
00169                 if (attacktable[i] >= EC_DECAY) {
00170                         TRACEOUT(("attacktable %d %d %ld", i, attacktable[i], EC_DECAY));
00171                 }
00172                 if (decaytable[i] >= EC_DECAY) {
00173                         TRACEOUT(("decaytable %d %d %ld", i, decaytable[i], EC_DECAY));
00174                 }
00175         }
00176         attacktable[62] = EC_DECAY - 1;
00177         attacktable[63] = EC_DECAY - 1;
00178         for (i=64; i<94; i++) {
00179                 attacktable[i] = attacktable[63];
00180                 decaytable[i] = decaytable[63];
00181         }
00182 }
00183 
00184 void opngen_setvol(UINT vol) {
00185 
00186         opncfg.fmvol = vol * 5 / 4;
00187 #if defined(OPNGENX86)
00188         opncfg.fmvol <<= FMASMSHIFT;
00189 #endif
00190 }
00191 
00192 void opngen_setVR(REG8 channel, REG8 value) {
00193 
00194         if ((channel & 3) && (value)) {
00195                 opncfg.vr_en = TRUE;
00196                 opncfg.vr_l = (channel & 1)?value:0;
00197                 opncfg.vr_r = (channel & 2)?value:0;
00198         }
00199         else {
00200                 opncfg.vr_en = FALSE;
00201         }
00202 }
00203 
00204 
00205 // ----
00206 
00207 static void set_algorithm(OPNCH *ch) {
00208 
00209         SINT32  *outd;
00210         UINT8   outslot;
00211 
00212         outd = &opngen.outdc;
00213         if (ch->stereo) {
00214                 switch(ch->pan & 0xc0) {
00215                         case 0x80:
00216                                 outd = &opngen.outdl;
00217                                 break;
00218 
00219                         case 0x40:
00220                                 outd = &opngen.outdr;
00221                                 break;
00222                 }
00223         }
00224         switch(ch->algorithm) {
00225                 case 0:
00226                         ch->connect1 = &opngen.feedback2;
00227                         ch->connect2 = &opngen.feedback3;
00228                         ch->connect3 = &opngen.feedback4;
00229                         outslot = 0x08;
00230                         break;
00231 
00232                 case 1:
00233                         ch->connect1 = &opngen.feedback3;
00234                         ch->connect2 = &opngen.feedback3;
00235                         ch->connect3 = &opngen.feedback4;
00236                         outslot = 0x08;
00237                         break;
00238 
00239                 case 2:
00240                         ch->connect1 = &opngen.feedback4;
00241                         ch->connect2 = &opngen.feedback3;
00242                         ch->connect3 = &opngen.feedback4;
00243                         outslot = 0x08;
00244                         break;
00245 
00246                 case 3:
00247                         ch->connect1 = &opngen.feedback2;
00248                         ch->connect2 = &opngen.feedback4;
00249                         ch->connect3 = &opngen.feedback4;
00250                         outslot = 0x08;
00251                         break;
00252 
00253                 case 4:
00254                         ch->connect1 = &opngen.feedback2;
00255                         ch->connect2 = outd;
00256                         ch->connect3 = &opngen.feedback4;
00257                         outslot = 0x0a;
00258                         break;
00259 
00260                 case 5:
00261                         ch->connect1 = 0;
00262                         ch->connect2 = outd;
00263                         ch->connect3 = outd;
00264                         outslot = 0x0e;
00265                         break;
00266 
00267                 case 6:
00268                         ch->connect1 = &opngen.feedback2;
00269                         ch->connect2 = outd;
00270                         ch->connect3 = outd;
00271                         outslot = 0x0e;
00272                         break;
00273 
00274                 case 7:
00275                 default:
00276                         ch->connect1 = outd;
00277                         ch->connect2 = outd;
00278                         ch->connect3 = outd;
00279                         outslot = 0x0f;
00280         }
00281         ch->connect4 = outd;
00282         ch->outslot = outslot;
00283 }
00284 
00285 static void set_dt1_mul(OPNSLOT *slot, REG8 value) {
00286 
00287         slot->multiple = (SINT32)multipletable[value & 0x0f];
00288         slot->detune1 = detunetable[(value >> 4) & 7];
00289 }
00290 
00291 static void set_tl(OPNSLOT *slot, REG8 value) {
00292 
00293 #if (EVC_BITS >= 7)
00294         slot->totallevel = ((~value) & 0x007f) << (EVC_BITS - 7);
00295 #else
00296         slot->totallevel = ((~value) & 0x007f) >> (7 - EVC_BITS);
00297 #endif
00298 }
00299 
00300 static void set_ks_ar(OPNSLOT *slot, REG8 value) {
00301 
00302         slot->keyscale = ((~value) >> 6) & 3;
00303         value &= 0x1f;
00304         slot->attack = (value)?(attacktable + (value << 1)):nulltable;
00305         slot->env_inc_attack = slot->attack[slot->envratio];
00306         if (slot->env_mode == EM_ATTACK) {
00307                 slot->env_inc = slot->env_inc_attack;
00308         }
00309 }
00310 
00311 static void set_d1r(OPNSLOT *slot, REG8 value) {
00312 
00313         value &= 0x1f;
00314         slot->decay1 = (value)?(decaytable + (value << 1)):nulltable;
00315         slot->env_inc_decay1 = slot->decay1[slot->envratio];
00316         if (slot->env_mode == EM_DECAY1) {
00317                 slot->env_inc = slot->env_inc_decay1;
00318         }
00319 }
00320 
00321 static void set_dt2_d2r(OPNSLOT *slot, REG8 value) {
00322 
00323         value &= 0x1f;
00324         slot->decay2 = (value)?(decaytable + (value << 1)):nulltable;
00325         if (slot->ssgeg1) {
00326                 slot->env_inc_decay2 = 0;
00327         }
00328         else {
00329                 slot->env_inc_decay2 = slot->decay2[slot->envratio];
00330         }
00331         if (slot->env_mode == EM_DECAY2) {
00332                 slot->env_inc = slot->env_inc_decay2;
00333         }
00334 }
00335 
00336 static void set_d1l_rr(OPNSLOT *slot, REG8 value) {
00337 
00338         slot->decaylevel = decayleveltable[value >> 4];
00339         slot->release = decaytable + ((value & 0x0f) << 2) + 2;
00340         slot->env_inc_release = slot->release[slot->envratio];
00341         if (slot->env_mode == EM_RELEASE) {
00342                 slot->env_inc = slot->env_inc_release;
00343                 if (value == 0xff) {
00344                         slot->env_mode = EM_OFF;
00345                         slot->env_cnt = EC_OFF;
00346                         slot->env_end = EC_OFF + 1;
00347                         slot->env_inc = 0;
00348                 }
00349         }
00350 }
00351 
00352 static void set_ssgeg(OPNSLOT *slot, REG8 value) {
00353 
00354         value &= 0xf;
00355         if ((value == 0xb) || (value == 0xd)) {
00356                 slot->ssgeg1 = 1;
00357                 slot->env_inc_decay2 = 0;
00358         }
00359         else {
00360                 slot->ssgeg1 = 0;
00361                 slot->env_inc_decay2 = slot->decay2[slot->envratio];
00362         }
00363         if (slot->env_mode == EM_DECAY2) {
00364                 slot->env_inc = slot->env_inc_decay2;
00365         }
00366 }
00367 
00368 static void channleupdate(OPNCH *ch) {
00369 
00370         int             i;
00371         UINT32  fc = ch->keynote[0];                                            // ver0.27
00372         UINT8   kc = ch->kcode[0];
00373         UINT    evr;
00374         OPNSLOT *slot;
00375 
00376         slot = ch->slot;
00377         if (!(ch->extop)) {
00378                 for (i=0; i<4; i++, slot++) {
00379                         slot->freq_inc = (fc + slot->detune1[kc]) * slot->multiple;
00380                         evr = kc >> slot->keyscale;
00381                         if (slot->envratio != evr) {
00382                                 slot->envratio = evr;
00383                                 slot->env_inc_attack = slot->attack[evr];
00384                                 slot->env_inc_decay1 = slot->decay1[evr];
00385                                 slot->env_inc_decay2 = slot->decay2[evr];
00386                                 slot->env_inc_release = slot->release[evr];
00387                         }
00388                 }
00389         }
00390         else {
00391                 for (i=0; i<4; i++, slot++) {
00392                         int s = extendslot[i];
00393                         slot->freq_inc = (ch->keynote[s] + slot->detune1[ch->kcode[s]])
00394                                                                                                                 * slot->multiple;
00395                         evr = ch->kcode[s] >> slot->keyscale;
00396                         if (slot->envratio != evr) {
00397                                 slot->envratio = evr;
00398                                 slot->env_inc_attack = slot->attack[evr];
00399                                 slot->env_inc_decay1 = slot->decay1[evr];
00400                                 slot->env_inc_decay2 = slot->decay2[evr];
00401                                 slot->env_inc_release = slot->release[evr];
00402                         }
00403                 }
00404         }
00405 }
00406 
00407 
00408 // ----
00409 
00410 void opngen_reset(void) {
00411 
00412         OPNCH   *ch;
00413         UINT    i;
00414         UINT    j;
00415 
00416         ZeroMemory(&opngen, sizeof(opngen));
00417         ZeroMemory(opnch, sizeof(opnch));
00418         opngen.playchannels = 3;
00419 
00420         ch = opnch;
00421         for (i=0; i<OPNCH_MAX; i++) {
00422                 ch->keynote[0] = 0;
00423                 OPNSLOT *slot = ch->slot;
00424                 for (j=0; j<4; j++) {
00425                         slot->env_mode = EM_OFF;
00426                         slot->env_cnt = EC_OFF;
00427                         slot->env_end = EC_OFF + 1;
00428                         slot->env_inc = 0;
00429                         slot->detune1 = detunetable[0];
00430                         slot->attack = nulltable;
00431                         slot->decay1 = nulltable;
00432                         slot->decay2 = nulltable;
00433                         slot->release = decaytable;
00434                         slot++;
00435                 }
00436                 ch++;
00437         }
00438         for (i=0x30; i<0xc0; i++) {
00439                 opngen_setreg(0, i, 0xff);
00440                 opngen_setreg(3, i, 0xff);
00441                 opngen_setreg(6, i, 0xff);
00442                 opngen_setreg(9, i, 0xff);
00443         }
00444 }
00445 
00446 void opngen_setcfg(REG8 maxch, UINT32 flag) {
00447 
00448         OPNCH   *ch;
00449         UINT    i;
00450 
00451         opngen.playchannels = maxch;
00452         ch = opnch;
00453         if ((flag & OPN_CHMASK) == OPN_STEREO) {
00454                 for (i=0; i<OPNCH_MAX; i++) {
00455                         if (flag & (1 << i)) {
00456                                 ch->stereo = TRUE;
00457                                 set_algorithm(ch);
00458                         }
00459                         ch++;
00460                 }
00461         }
00462         else {
00463                 for (i=0; i<OPNCH_MAX; i++) {
00464                         if (flag & (1 << i)) {
00465                                 ch->stereo = FALSE;
00466                                 set_algorithm(ch);
00467                         }
00468                         ch++;
00469                 }
00470         }
00471 }
00472 
00473 void opngen_setextch(UINT chnum, REG8 data) {
00474 
00475         OPNCH   *ch;
00476 
00477         ch = opnch;
00478         ch[chnum].extop = data;
00479 }
00480 
00481 void opngen_setreg(REG8 chbase, UINT reg, REG8 value) {
00482 
00483         UINT    chpos;
00484         OPNCH   *ch;
00485 
00486         chpos = reg & 3;
00487         if (chpos == 3) {
00488                 return;
00489         }
00490         sound_sync();
00491         ch = opnch + chbase + chpos;
00492         if (reg < 0xa0) {
00493                 OPNSLOT *slot = ch->slot + fmslot[(reg >> 2) & 3];
00494                 switch(reg & 0xf0) {
00495                         case 0x30:                                      // DT1 MUL
00496                                 set_dt1_mul(slot, value);
00497                                 channleupdate(ch);
00498                                 break;
00499 
00500                         case 0x40:                                      // TL
00501                                 set_tl(slot, value);
00502                                 break;
00503 
00504                         case 0x50:                                      // KS AR
00505                                 set_ks_ar(slot, value);
00506                                 channleupdate(ch);
00507                                 break;
00508 
00509                         case 0x60:                                      // D1R
00510                                 set_d1r(slot, value);
00511                                 break;
00512 
00513                         case 0x70:                                      // DT2 D2R
00514                                 set_dt2_d2r(slot, value);
00515                                 channleupdate(ch);
00516                                 break;
00517 
00518                         case 0x80:                                      // D1L RR
00519                                 set_d1l_rr(slot, value);
00520                                 break;
00521 
00522                         case 0x90:
00523                                 set_ssgeg(slot, value);
00524                                 channleupdate(ch);
00525                                 break;
00526                 }
00527         }
00528         else {
00529                 UINT fn;
00530                 UINT8 blk;
00531                 switch(reg & 0xfc) {
00532                         case 0xa0:
00533                                 blk = ch->keyfunc[0] >> 3;
00534                                 fn = ((ch->keyfunc[0] & 7) << 8) + value;
00535                                 ch->kcode[0] = (blk << 2) | kftable[fn >> 7];
00536 //                              ch->keynote[0] = fn * opmbaserate / (1L << (22-blk));
00537                                 ch->keynote[0] = (fn << (opncfg.ratebit + blk)) >> 6;
00538                                 channleupdate(ch);
00539                                 break;
00540 
00541                         case 0xa4:
00542                                 ch->keyfunc[0] = value & 0x3f;
00543                                 break;
00544 
00545                         case 0xa8:
00546                                 ch = opnch + chbase + 2;
00547                                 blk = ch->keyfunc[chpos+1] >> 3;
00548                                 fn = ((ch->keyfunc[chpos+1] & 7) << 8) + value;
00549                                 ch->kcode[chpos+1] = (blk << 2) | kftable[fn >> 7];
00550 //                              ch->keynote[chpos+1] = fn * opmbaserate / (1L << (22-blk));
00551                                 ch->keynote[chpos+1] = (fn << (opncfg.ratebit + blk)) >> 6;
00552                                 channleupdate(ch);
00553                                 break;
00554 
00555                         case 0xac:
00556                                 ch = opnch + chbase + 2;
00557                                 ch->keyfunc[chpos+1] = value & 0x3f;
00558                                 break;
00559 
00560                         case 0xb0:
00561                                 ch->algorithm = (UINT8)(value & 7);
00562                                 value = (value >> 3) & 7;
00563                                 if (value) {
00564                                         ch->feedback = 8 - value;
00565                                 }
00566                                 else {
00567                                         ch->feedback = 0;
00568                                 }
00569                                 set_algorithm(ch);
00570                                 break;
00571 
00572                         case 0xb4:
00573                                 ch->pan = (UINT8)(value & 0xc0);
00574                                 set_algorithm(ch);
00575                                 break;
00576                 }
00577         }
00578 }
00579 
00580 void opngen_keyon(UINT chnum, REG8 value) {
00581 
00582         OPNCH   *ch;
00583         OPNSLOT *slot;
00584         REG8    bit;
00585         UINT    i;
00586 
00587         sound_sync();
00588         opngen.keyreg[chnum] = value;
00589         opngen.playing++;
00590         ch = opnch + chnum;
00591         ch->playing |= value >> 4;
00592         slot = ch->slot;
00593         bit = 0x10;
00594         for (i=0; i<4; i++) {
00595                 if (value & bit) {                                                      // keyon
00596                         if (slot->env_mode <= EM_RELEASE) {
00597                                 slot->freq_cnt = 0;
00598                                 if (i == OPNSLOT1) {
00599                                         ch->op1fb = 0;
00600                                 }
00601                                 slot->env_mode = EM_ATTACK;
00602                                 slot->env_inc = slot->env_inc_attack;
00603                                 slot->env_cnt = EC_ATTACK;
00604                                 slot->env_end = EC_DECAY;
00605                         }
00606                 }
00607                 else {                                                                          // keyoff
00608                         if (slot->env_mode > EM_RELEASE) {
00609                                 slot->env_mode = EM_RELEASE;
00610                                 if (!(slot->env_cnt & EC_DECAY)) {
00611                                         slot->env_cnt = (opncfg.envcurve[slot->env_cnt
00612                                                                                 >> ENV_BITS] << ENV_BITS) + EC_DECAY;
00613                                 }
00614                                 slot->env_end = EC_OFF;
00615                                 slot->env_inc = slot->env_inc_release;
00616                         }
00617                 }
00618                 slot++;
00619                 bit <<= 1;
00620         }
00621 //      keydisp_fmkeyon((UINT8)chnum, value);
00622 }
00623