Diff for /np2/io/pit.c between versions 1.1 and 1.25

version 1.1, 2003/10/16 17:57:57 version 1.25, 2005/05/20 13:59:47
Line 3 Line 3
 //   // 
   
 #include        "compiler.h"  #include        "compiler.h"
 #include        "i286.h"  #include        "cpucore.h"
 #include        "pccore.h"  #include        "pccore.h"
 #include        "iocore.h"  #include        "iocore.h"
 #include        "sound.h"  #include        "sound.h"
 #include        "beep.h"  #include        "beep.h"
   #include        "board14.h"
   
   
 // #define      uPD71054                                                                // NP2はuPD8253Cベース  #define BEEPCOUNTEREX                                   // BEEPアイドル時のカウンタをα倍に
   #if defined(CPUCORE_IA32)
   #define uPD71054
   #endif
   
   
 // --- Interval timer  // --- Interval timer
   
 // ver0.31 常に回す…  static void setsystimerevent(UINT32 cnt, BOOL absolute) {
 static void setsystimerevent_noint(BOOL absolute) {  
   
         nevent_set(NEVENT_ITIMER, pc.multiple << 16, systimer_noint, absolute);  
 }  
   
 void systimer_noint(NEVENTITEM item) {  
   
         if (item->flag & NEVENT_SETEVENT) {  
                 setsystimerevent_noint(NEVENT_RELATIVE);  
         }  
 }  
   
 static void setsystimerevent(BOOL absolute) {  
   
         SINT32  cnt;  
   
         cnt = pit.value[0].w;  
         if (cnt > 8) {                                                                  // 根拠なし          if (cnt > 8) {                                                                  // 根拠なし
                 cnt *= pc.multiple;                  cnt *= pccore.multiple;
         }          }
         else {          else {
                 cnt = pc.multiple << 16;                  cnt = pccore.multiple << 16;
         }          }
         nevent_set(NEVENT_ITIMER, cnt, systimer, absolute);          nevent_set(NEVENT_ITIMER, cnt, systimer, absolute);
 }  }
   
 void systimer(NEVENTITEM item) {  void systimer(NEVENTITEM item) {
   
           PITCH   pitch;
   
         if (item->flag & NEVENT_SETEVENT) {          if (item->flag & NEVENT_SETEVENT) {
                 if ((pit.mode[0] & 0x0c) == 0x04) {                  pitch = pit.ch + 0;
                   if (pitch->flag & PIT_FLAG_I) {
                           pitch->flag &= ~PIT_FLAG_I;
                           pic_setirq(0);
                   }
                   if ((pitch->ctrl & 0x0c) == 0x04) {
                         // レートジェネレータ                          // レートジェネレータ
                         setsystimerevent(NEVENT_RELATIVE);                          pitch->flag |= PIT_FLAG_I;
                           setsystimerevent(pitch->value, NEVENT_RELATIVE);
                 }                  }
                 else {                  else {
                         setsystimerevent_noint(NEVENT_RELATIVE);                          setsystimerevent(0, NEVENT_RELATIVE);
                 }                  }
         }          }
         pic_setirq(0);  
 }  }
   
   
 // --- Beep  // --- Beep
   
 static void setbeepevent(BOOL absolute) {  #if defined(BEEPCOUNTEREX)
   static void setbeepeventex(UINT32 cnt, BOOL absolute) {
   
           if (cnt > 2) {
                   cnt *= pccore.multiple;
           }
           else {
                   cnt = pccore.multiple << 16;
           }
           while(cnt < 0x100000) {
                   cnt <<= 1;
           }
           nevent_set(NEVENT_BEEP, (SINT32)cnt, beeponeshot, absolute);
   }
   #endif
   
         SINT32  cnt;  static void setbeepevent(UINT32 cnt, BOOL absolute) {
   
         cnt = pit.value[1].w;  
         if (cnt > 2) {          if (cnt > 2) {
                 cnt *= pc.multiple;                  cnt *= pccore.multiple;
         }          }
         else {          else {
                 cnt = pc.multiple << 16;                  cnt = pccore.multiple << 16;
         }          }
         nevent_set(NEVENT_BEEP, cnt, beeponeshot, absolute);          nevent_set(NEVENT_BEEP, cnt, beeponeshot, absolute);
 }  }
   
 void beeponeshot(NEVENTITEM item) {  void beeponeshot(NEVENTITEM item) {
   
           PITCH   pitch;
   
         if (item->flag & NEVENT_SETEVENT) {          if (item->flag & NEVENT_SETEVENT) {
                 if (!(pit.mode[1] & 0x0c)) {                                                            // ver0.30                  pitch = pit.ch + 1;
                   if (!(pitch->ctrl & 0x0c)) {
                         beep_lheventset(0);                          beep_lheventset(0);
                 }                  }
 #ifdef uPD71054  #if defined(uPD71054)
                 if ((pit.mode[1] & 0x06) == 0x02)                  if ((pitch->ctrl & 0x06) == 0x02)
 #else  #else
                 if (pit.mode[1] & 0x02)                  if (pitch->ctrl & 0x02)
 #endif  #endif
                 {                  {
                         setbeepevent(NEVENT_RELATIVE);  #if defined(BEEPCOUNTEREX)
                           setbeepeventex(pitch->value, NEVENT_RELATIVE);
   #else
                           setbeepevent(pitch->value, NEVENT_RELATIVE);
   #endif
                 }                  }
         }          }
 }  }
Line 93  void beeponeshot(NEVENTITEM item) { Line 108  void beeponeshot(NEVENTITEM item) {
   
 // --- RS-232C  // --- RS-232C
   
 static void setrs232cevent(BOOL absolute) {  static void setrs232cevent(UINT32 cnt, BOOL absolute) {
   
         SINT32  cnt;          if (cnt > 1) {
                   cnt *= pccore.multiple;
         if (pit.value[2].w > 1) {  
                 cnt = pc.multiple * pit.value[2].w * rs232c.mul;                        // ver0.29  
         }          }
         else {          else {
                 cnt = (pc.multiple << 16) * rs232c.mul;                                         // ver0.29                  cnt = pccore.multiple << 16;
         }          }
           cnt *= rs232c.mul;
         nevent_set(NEVENT_RS232C, cnt, rs232ctimer, absolute);          nevent_set(NEVENT_RS232C, cnt, rs232ctimer, absolute);
 }  }
   
 void rs232ctimer(NEVENTITEM item) {  void rs232ctimer(NEVENTITEM item) {
   
           PITCH   pitch;
   
         if (item->flag & NEVENT_SETEVENT) {          if (item->flag & NEVENT_SETEVENT) {
                 if ((pit.mode[2] & 0x0c) == 0x04) {                  pitch = pit.ch + 2;
                   if (pitch->flag & PIT_FLAG_I) {
                           pitch->flag &= ~PIT_FLAG_I;
                           rs232c_callback();
                   }
                   if ((pitch->ctrl & 0x0c) == 0x04) {
                         // レートジェネレータ                          // レートジェネレータ
                         setrs232cevent(NEVENT_RELATIVE);                          setrs232cevent(pitch->value, NEVENT_RELATIVE);
                   }
                   else {
                           setrs232cevent(0, NEVENT_RELATIVE);
                 }                  }
         }          }
         rs232c_callback();  
 }  }
   
   
 // ---------------------------------------------------------------------------  // ---------------------------------------------------------------------------
   
 static UINT16 itimer_latch(int ch) {  static UINT getcount(const _PITCH *pitch) {
   
         SINT32  clock;          SINT32  clock;
   
         if (ch == 1) {          switch(pitch->ch) {
                 switch(pit.mode[1] & 0x06) {                  case 0:
                         case 0x00:                          clock = nevent_getremain(NEVENT_ITIMER);
                         case 0x04:                          break;
                                 return(pit.value[1].w);  
                   case 1:
                           switch(pitch->ctrl & 0x06) {
   #ifdef uPD71054                         // ?
   //                              case 0x00:
   #endif
                                   case 0x04:
                                           return(pitch->value);
 #ifdef uPD71054  #ifdef uPD71054
                         case 0x06:                                  case 0x06:
                                 return(pit.value[1].w & 0xfffe);                                          return(pitch->value & (~1));
 #endif  #endif
                 }                          }
                           clock = nevent_getremain(NEVENT_BEEP);
   #if defined(BEEPCOUNTEREX)
                           if (clock >= 0) {
                                   clock /= pccore.multiple;
                                   if (pitch->value > 2) {
                                           clock %= pitch->value;
                                   }
                                   else {
                                           clock = LOW16(clock);
                                   }
                                   return(clock);
                           }
   #else
                           break;
   #endif
   
                   case 2:
                           clock = nevent_getremain(NEVENT_RS232C);
                           break;
   
   #if !defined(DISABLE_SOUND)
                   case 3:
                           return(board14_pitcount());
   #endif
   
                   default:
                           clock = 0;
                           break;
         }          }
         clock = nevent_getremain(NEVENT_ITIMER + ch);          if (clock > 0) {
         if (clock >= 0) {                  return(clock / pccore.multiple);
                 return((UINT16)(clock / pc.multiple));  
         }          }
         return(0);          return(0);
 }  }
   
   static void latchcmd(PITCH pitch, REG8 ctrl) {
   
           UINT8   flag;
   
           flag = pitch->flag;
           if (!(ctrl & PIT_LATCH_S)) {
                   flag |= PIT_FLAG_S;
                   pitch->stat = pitch->ctrl;
           }
           if (!(ctrl & PIT_LATCH_C)) {
                   flag |= PIT_FLAG_C;
                   flag &= ~PIT_FLAG_L;
                   pitch->latch = getcount(pitch);
           }
           pitch->flag = flag;
   }
   
   
 void itimer_setflag(int ch, BYTE value) {  // ----
   
         pit.flag[ch] = 0;  void pit_setflag(PITCH pitch, REG8 value) {
         if (value & 0x30) {  
                 pit.mode[ch] = value;          if (value & PIT_CTRL_RL) {
                   pitch->ctrl = (UINT8)((value & 0x3f) | PIT_STAT_CMD);
                   pitch->flag &= ~(PIT_FLAG_R | PIT_FLAG_W | PIT_FLAG_L |
                                                                                                           PIT_FLAG_S | PIT_FLAG_C);
         }          }
         else {                                                                                                          // latch          else {                                                                                                          // latch
                 pit.latch[ch].w = itimer_latch(ch);                  latchcmd(pitch, ~PIT_LATCH_C);
         }          }
 }  }
   
 BOOL itimer_setcount(int ch, BYTE value) {  BOOL pit_setcount(PITCH pitch, REG8 value) {
   
           UINT8   flag;
   
         switch(pit.mode[ch] & 0x30) {          switch(pitch->ctrl & PIT_CTRL_RL) {
                 case 0x10:              // access low                  case PIT_RL_L:          // access low
                         pit.value[ch].w = value;                          pitch->value = value;
                         break;                          break;
   
                 case 0x20:              // access high                  case PIT_RL_H:          // access high
                         pit.value[ch].w = value << 8;                          pitch->value = value << 8;
                         break;                          break;
   
                 case 0x30:              // access word                  case PIT_RL_ALL:        // access word
                         if (!(pit.flag[ch] & 2)) {                          flag = pitch->flag;
                                 pit.value[ch].w &= 0xff00;                          pitch->flag = flag ^ PIT_FLAG_W;
                                 pit.value[ch].w += value;                          if (!(flag & PIT_FLAG_W)) {
                                 pit.flag[ch] ^= 2;                                  pitch->value &= 0xff00;
                                   pitch->value += value;
                                 return(TRUE);                                  return(TRUE);
                         }                          }
                         pit.value[ch].w &= 0x00ff;                          pitch->value &= 0x00ff;
                         pit.value[ch].w += value << 8;                          pitch->value += value << 8;
                         pit.flag[ch] ^= 2;  
                         break;                          break;
         }          }
           pitch->ctrl &= ~PIT_STAT_CMD;
           if (((pitch->ctrl & 0x06) == 0x02) && (pitch->flag & PIT_FLAG_I)) {
                   return(TRUE);
           }
         return(FALSE);          return(FALSE);
 }  }
   
 BYTE itimer_getcount(int ch) {  REG8 pit_getstat(PITCH pitch) {
   
         BYTE    ret;          UINT8   flag;
         union {          UINT8   rl;
                 BYTE    b[2];          UINT16  w;
                 UINT16  w;          REG8    ret;
         } tim;  
           flag = pitch->flag;
         if (!(pit.mode[ch] & 0x30)) {  #if defined(uPD71054)
                 tim.w = pit.latch[ch].w;          if (flag & PIT_FLAG_S) {
         }                  flag &= ~PIT_FLAG_S;
         else {                  ret = pitch->stat;
                 tim.w = itimer_latch(ch);                                                                       // ver0.30  
         }  
         switch(pit.mode[ch] & 0x30) {  
                 case 0x10:                                              // access low  
                         return((BYTE)tim.w);  
   
                 case 0x20:                                              // access high  
                         return((BYTE)(tim.w >> 8));  
         }  
                                                                                 // access word  
         if (!(pit.flag[ch] & 1)) {  
                 ret = (BYTE)tim.w;  
         }          }
         else {          else
                 ret = (BYTE)(tim.w >> 8);  #endif
           {
                   rl = pitch->ctrl & PIT_CTRL_RL;
                   if (flag & (PIT_FLAG_C | PIT_FLAG_L)) {
                           flag &= ~PIT_FLAG_C;
                           if (rl == PIT_RL_ALL) {
                                   flag ^= PIT_FLAG_L;
                           }
                           w = pitch->latch;
                   }
                   else {
                           w = getcount(pitch);
                   }
                   switch(rl) {
                           case PIT_RL_L:                                          // access low
                                   ret = (UINT8)w;
                                   break;
   
                           case PIT_RL_H:
                                   ret = (UINT8)(w >> 8);
                                   break;
   
                           case PIT_RL_ALL:
                           default:
                                   if (!(flag & PIT_FLAG_R)) {
                                           ret = (UINT8)w;
                                   }
                                   else {
                                           ret = (UINT8)(w >> 8);
                                   }
                                   flag ^= PIT_FLAG_R;
                                   break;
                   }
         }          }
         pit.flag[ch] ^= 1;          pitch->flag = flag;
         return(ret);          return(ret);
 }  }
   
Line 215  BYTE itimer_getcount(int ch) { Line 319  BYTE itimer_getcount(int ch) {
 // ---- I/O  // ---- I/O
   
 // system timer  // system timer
 static void IOOUTCALL pit_o71(UINT port, BYTE dat) {  static void IOOUTCALL pit_o71(UINT port, REG8 dat) {
   
           PITCH   pitch;
   
         if (itimer_setcount(0, dat)) {          pitch = pit.ch + 0;
           if (pit_setcount(pitch, dat)) {
                 return;                  return;
         }          }
         pic.pi[0].irr &= (~1);          pic.pi[0].irr &= (~1);
         setsystimerevent(NEVENT_ABSOLUTE);          pitch->flag |= PIT_FLAG_I;
           setsystimerevent(pitch->value, NEVENT_ABSOLUTE);
         (void)port;          (void)port;
 }  }
   
 // beep  // beep
 static void IOOUTCALL pit_o73(UINT port, BYTE dat) {  static void IOOUTCALL pit_o73(UINT port, REG8 dat) {
   
         if (itimer_setcount(1, dat)) {          PITCH   pitch;
   
           pitch = pit.ch + 1;
           if (pit_setcount(pitch, dat)) {
                 return;                  return;
         }          }
         setbeepevent(NEVENT_ABSOLUTE);          setbeepevent(pitch->value, NEVENT_ABSOLUTE);
         if (!(pit.mode[1] & 0x0c)) {          beep_lheventset(1);                                                                                             // ver0.79
                 beep_lheventset(1);          if (pitch->ctrl & 0x0c) {
         }                  beep_hzset(pitch->value);
         else {  
                 beep_hzset(pit.value[1].w);  
         }          }
         (void)port;          (void)port;
 }  }
   
 // rs-232c  // rs-232c
 static void IOOUTCALL pit_o75(UINT port, BYTE dat) {  static void IOOUTCALL pit_o75(UINT port, REG8 dat) {
   
         if (itimer_setcount(2, dat)) {          PITCH   pitch;
   
           pitch = pit.ch + 2;
           if (pit_setcount(pitch, dat)) {
                 return;                  return;
         }          }
           pitch->flag |= PIT_FLAG_I;
         rs232c_open();          rs232c_open();
         setrs232cevent(NEVENT_ABSOLUTE);          setrs232cevent(pitch->value, NEVENT_ABSOLUTE);
         (void)port;          (void)port;
 }  }
   
 // ctrl  // ctrl
 static void IOOUTCALL pit_o77(UINT port, BYTE dat) {  static void IOOUTCALL pit_o77(UINT port, REG8 dat) {
   
         int             ch;          UINT    chnum;
           PITCH   pitch;
   
         ch = (dat >> 6) & 3;          chnum = (dat >> 6) & 3;
         if (ch != 3) {          if (chnum != 3) {
                 itimer_setflag(ch, dat);                  pitch = pit.ch + chnum;
                 if (ch == 0) {                  // 書込みで itimerのirrがリセットされる…                  pit_setflag(pitch, dat);
                   if (chnum == 0) {               // 書込みで itimerのirrがリセットされる…
                         pic.pi[0].irr &= (~1);                          pic.pi[0].irr &= (~1);
                           if (dat & 0x30) {       // 一応ラッチ時は割り込みをセットしない
                                   pitch->flag |= PIT_FLAG_I;
                           }
                 }                  }
                 if (ch == 1) {                  if (chnum == 1) {
                         beep_modeset();                          beep_modeset();
                 }                  }
         }          }
   #if defined(uPD71054)
           else {
                   TRACEOUT(("multiple latch commands - %x", dat));
                   for (chnum=0; chnum<3; chnum++) {
                           if (dat & (2 << chnum)) {
                                   latchcmd(pit.ch + chnum, dat);
                           }
                   }
           }
   #endif
         (void)port;          (void)port;
 }  }
   
 static BYTE IOINPCALL pit_i71(UINT port) {  static REG8 IOINPCALL pit_i71(UINT port) {
   
         return(itimer_getcount((port >> 1) & 3));          return(pit_getstat(pit.ch + ((port >> 1) & 3)));
 }  }
   
   
Line 286  static const IOINP piti71[4] = { Line 414  static const IOINP piti71[4] = {
   
 void itimer_reset(void) {  void itimer_reset(void) {
   
           UINT16  beepcnt;
   
         ZeroMemory(&pit, sizeof(pit));          ZeroMemory(&pit, sizeof(pit));
         if (pc.cpumode & CPUMODE_8MHz) {          beepcnt = (pccore.cpumode & CPUMODE_8MHZ)?998:1229;
                 pit.value[1].w = 998;                   // 4MHz          pit.ch[0].ctrl = 0x30;
         }          pit.ch[0].ch = 0;
         else {          pit.ch[0].flag = PIT_FLAG_I;
                 pit.value[1].w = 1229;                  // 5MHz          pit.ch[0].ctrl = 0x56 & 0x3f;
         }          pit.ch[1].ch = 1;
         pit.mode[0] = 0x30;          pit.ch[1].value = beepcnt;
         pit.mode[1] = 0x56;          pit.ch[2].ctrl = 0xb6 & 0x3f;
         pit.mode[2] = 0xb6;          pit.ch[2].ch = 2;
         pit.mode[3] = 0x36;  #if !defined(DISABLE_SOUND)
         setsystimerevent(NEVENT_ABSOLUTE);          pit.ch[3].ctrl = 0x36;
         beep_hzset(pit.value[1].w);          pit.ch[3].ch = 3;
           pit.ch[4].ctrl = 0x36;
           pit.ch[4].ch = 4;
   #endif
           setsystimerevent(0, NEVENT_ABSOLUTE);
           beep_lheventset(1);                                                                                             // ver0.79
           beep_hzset(beepcnt);
   //      setrs232cevent(0, NEVENT_ABSOLUTE);
 }  }
   
 void itimer_bind(void) {  void itimer_bind(void) {
   
         iocore_attachsysoutex(0x0071, 0x0cf1, pito71, 4);          iocore_attachsysoutex(0x0071, 0x0cf1, pito71, 4);
         iocore_attachsysinpex(0x0071, 0x0cf1, piti71, 4);          iocore_attachsysinpex(0x0071, 0x0cf1, piti71, 4);
           iocore_attachout(0x3fd9, pit_o71);
         iocore_attachout(0x3fdb, pit_o73);          iocore_attachout(0x3fdb, pit_o73);
           iocore_attachout(0x3fdd, pit_o75);
         iocore_attachout(0x3fdf, pit_o77);          iocore_attachout(0x3fdf, pit_o77);
           iocore_attachinp(0x3fd9, pit_i71);
         iocore_attachinp(0x3fdb, pit_i71);          iocore_attachinp(0x3fdb, pit_i71);
           iocore_attachinp(0x3fdd, pit_i71);
 }  }
   

Removed from v.1.1  
changed lines
  Added in v.1.25


RetroPC.NET-CVS <cvs@retropc.net>