Diff for /np2/io/pit.c between versions 1.15 and 1.23

version 1.15, 2004/01/22 01:10:04 version 1.23, 2004/07/03 17:25:39
Line 8 Line 8
 #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アイドル時のカウンタをα倍に  #define BEEPCOUNTEREX                                   // BEEPアイドル時のカウンタをα倍に
   #if defined(CPUCORE_IA32)
   #define uPD71054
   #endif
   
   
 // --- Interval timer  // --- Interval timer
   
 static void setsystimerevent(BOOL absolute) {  static void setsystimerevent(UINT32 cnt, BOOL absolute) {
   
         SINT32  cnt;  
   
         cnt = pit.value[0];  
         if (cnt > 8) {                                                                  // 根拠なし          if (cnt > 8) {                                                                  // 根拠なし
                 cnt *= pccore.multiple;                  cnt *= pccore.multiple;
         }          }
Line 32  static void setsystimerevent(BOOL absolu Line 32  static void setsystimerevent(BOOL absolu
   
 void systimer(NEVENTITEM item) {  void systimer(NEVENTITEM item) {
   
           PITCH   pitch;
   
         if (item->flag & NEVENT_SETEVENT) {          if (item->flag & NEVENT_SETEVENT) {
                 if (pit.intr[0]) {                  pitch = pit.ch + 0;
                         pit.intr[0] = 0;                  if (pitch->flag & PIT_FLAG_I) {
                           pitch->flag &= ~PIT_FLAG_I;
                         pic_setirq(0);                          pic_setirq(0);
                 }                  }
                 if ((pit.mode[0] & 0x0c) == 0x04) {                  if ((pitch->ctrl & 0x0c) == 0x04) {
                         // レートジェネレータ                          // レートジェネレータ
                         pit.intr[0] = 1;                          pitch->flag |= PIT_FLAG_I;
                         setsystimerevent(NEVENT_RELATIVE);                          setsystimerevent(pitch->value, NEVENT_RELATIVE);
                 }                  }
                 else {                  else {
                         nevent_set(NEVENT_ITIMER, pccore.multiple << 16,                          setsystimerevent(0, NEVENT_RELATIVE);
                                                                                                 systimer, NEVENT_RELATIVE);  
                 }                  }
         }          }
 }  }
Line 53  void systimer(NEVENTITEM item) { Line 55  void systimer(NEVENTITEM item) {
 // --- Beep  // --- Beep
   
 #if defined(BEEPCOUNTEREX)  #if defined(BEEPCOUNTEREX)
 static void setbeepeventex(BOOL absolute) {  static void setbeepeventex(UINT32 cnt, BOOL absolute) {
   
         UINT32  cnt;  
   
         cnt = pit.value[1];  
         if (cnt > 2) {          if (cnt > 2) {
                 cnt *= pccore.multiple;                  cnt *= pccore.multiple;
         }          }
Line 71  static void setbeepeventex(BOOL absolute Line 70  static void setbeepeventex(BOOL absolute
 }  }
 #endif  #endif
   
 static void setbeepevent(BOOL absolute) {  static void setbeepevent(UINT32 cnt, BOOL absolute) {
   
         SINT32  cnt;  
   
         cnt = pit.value[1];  
         if (cnt > 2) {          if (cnt > 2) {
                 cnt *= pccore.multiple;                  cnt *= pccore.multiple;
         }          }
Line 87  static void setbeepevent(BOOL absolute)  Line 83  static void setbeepevent(BOOL 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);
                 }                  }
 #if defined(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
                 {                  {
 #if defined(BEEPCOUNTEREX)  #if defined(BEEPCOUNTEREX)
                         setbeepeventex(NEVENT_RELATIVE);                          setbeepeventex(pitch->value, NEVENT_RELATIVE);
 #else  #else
                         setbeepevent(NEVENT_RELATIVE);                          setbeepevent(pitch->value, NEVENT_RELATIVE);
 #endif  #endif
                 }                  }
         }          }
Line 109  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 (pit.value[2] > 1) {          if (cnt > 1) {
                 cnt = pccore.multiple * pit.value[2] * rs232c.mul;                  cnt *= pccore.multiple;
         }          }
         else {          else {
                 cnt = (pccore.multiple << 16) * rs232c.mul;                  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->ctrl & 0x0c) == 0x04) {
                         // レートジェネレータ                          // レートジェネレータ
                         setrs232cevent(NEVENT_RELATIVE);                          setrs232cevent(pitch->value, NEVENT_RELATIVE);
                 }                  }
         }          }
         rs232c_callback();          rs232c_callback();
Line 136  void rs232ctimer(NEVENTITEM item) { Line 137  void rs232ctimer(NEVENTITEM item) {
   
 // ---------------------------------------------------------------------------  // ---------------------------------------------------------------------------
   
 static UINT pit_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:
                           clock = nevent_getremain(NEVENT_ITIMER);
                           break;
   
                   case 1:
                           switch(pitch->ctrl & 0x06) {
 #ifdef uPD71054                         // ?  #ifdef uPD71054                         // ?
                         case 0x00:  //                              case 0x00:
 #endif  #endif
                         case 0x04:                                  case 0x04:
                                 return(pit.value[1]);                                          return(pitch->value);
 #ifdef uPD71054  #ifdef uPD71054
                         case 0x06:                                  case 0x06:
                                 return(pit.value[1] & (~1));                                          return(pitch->value & (~1));
 #endif  #endif
                 }                          }
                           clock = nevent_getremain(NEVENT_BEEP);
 #if defined(BEEPCOUNTEREX)  #if defined(BEEPCOUNTEREX)
                 clock = nevent_getremain(NEVENT_ITIMER + ch);                          if (clock >= 0) {
                 if (clock < 0) {                                  clock /= pccore.multiple;
                         return(0);                                  if (pitch->value > 2) {
                 }                                          clock %= pitch->value;
                 clock /= pccore.multiple;                                  }
                 if (pit.value[1] > 2) {                                  else {
                         clock %= pit.value[1];                                          clock = LOW16(clock);
                 }                                  }
                 else {                                  return(clock);
                         clock = LOW16(clock);                          }
                 }  #else
                 return(clock);                          break;
   #endif
   
                   case 2:
                           clock = nevent_getremain(NEVENT_RS232C);
                           break;
   
   #if !defined(DISABLE_SOUND)
                   case 3:
                           return(board14_pitcount());
 #endif  #endif
   
                   default:
                           clock = 0;
                           break;
         }          }
         clock = nevent_getremain(NEVENT_ITIMER + ch);          if (clock > 0) {
         if (clock >= 0) {  
                 return(clock / pccore.multiple);                  return(clock / pccore.multiple);
         }          }
         return(0);          return(0);
 }  }
   
 void pit_setflag(int ch, REG8 value) {  static void latchcmd(PITCH pitch, REG8 ctrl) {
   
           UINT8   flag;
   
         pit.flag[ch] = 0;          flag = pitch->flag;
         if (value & 0x30) {          if (!(ctrl & PIT_LATCH_S)) {
                 pit.mode[ch] = (UINT8)value;                  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 pit_setflag(PITCH pitch, REG8 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.mode[ch] &= ~0x30;                  latchcmd(pitch, ~PIT_LATCH_C);
                 pit.latch[ch] = (UINT16)pit_latch(ch);  
         }          }
 }  }
   
 BOOL pit_setcount(int ch, REG8 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] = value;                          pitch->value = value;
                         break;                          break;
   
                 case 0x20:              // access high                  case PIT_RL_H:          // access high
                         pit.value[ch] = 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] &= 0xff00;                          pitch->flag = flag ^ PIT_FLAG_W;
                                 pit.value[ch] += value;                          if (!(flag & PIT_FLAG_W)) {
                                 pit.flag[ch] ^= 2;                                  pitch->value &= 0xff00;
                                   pitch->value += value;
                                 return(TRUE);                                  return(TRUE);
                         }                          }
                         pit.value[ch] &= 0x00ff;                          pitch->value &= 0x00ff;
                         pit.value[ch] += 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);
 }  }
   
 REG8 pit_getcount(int ch) {  REG8 pit_getstat(PITCH pitch) {
   
           UINT8   flag;
           UINT8   rl;
           UINT16  w;
         REG8    ret;          REG8    ret;
         REG16   w;  
   
         if (!(pit.mode[ch] & 0x30)) {  
                 w = pit.latch[ch];  
         }  
         else {  
                 w = pit_latch(ch);  
         }  
         switch(pit.mode[ch] & 0x30) {  
                 case 0x10:                                              // access low  
                         return((UINT8)w);  
   
                 case 0x20:                                              // access high          flag = pitch->flag;
                         return((UINT8)(w >> 8));  #if defined(uPD71054)
         }          if (flag & PIT_FLAG_S) {
         if (!(pit.flag[ch] & 1)) {                      // access word                  flag &= ~PIT_FLAG_S;
                 ret = (UINT8)w;                  ret = pitch->stat;
         }          }
         else {          else
                 ret = (UINT8)(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 246  REG8 pit_getcount(int ch) { Line 315  REG8 pit_getcount(int ch) {
 // system timer  // system timer
 static void IOOUTCALL pit_o71(UINT port, REG8 dat) {  static void IOOUTCALL pit_o71(UINT port, REG8 dat) {
   
 //      TRACEOUT(("pic o71: %x", dat));          PITCH   pitch;
         if (pit_setcount(0, dat)) {  
           pitch = pit.ch + 0;
           if (pit_setcount(pitch, dat)) {
                 return;                  return;
         }          }
         pic.pi[0].irr &= (~1);          pic.pi[0].irr &= (~1);
         pit.intr[0] = 1;          pitch->flag |= PIT_FLAG_I;
         setsystimerevent(NEVENT_ABSOLUTE);          setsystimerevent(pitch->value, NEVENT_ABSOLUTE);
         (void)port;          (void)port;
 }  }
   
 // beep  // beep
 static void IOOUTCALL pit_o73(UINT port, REG8 dat) {  static void IOOUTCALL pit_o73(UINT port, REG8 dat) {
   
         if (pit_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]);  
         }          }
         (void)port;          (void)port;
 }  }
Line 275  static void IOOUTCALL pit_o73(UINT port, Line 347  static void IOOUTCALL pit_o73(UINT port,
 // rs-232c  // rs-232c
 static void IOOUTCALL pit_o75(UINT port, REG8 dat) {  static void IOOUTCALL pit_o75(UINT port, REG8 dat) {
   
         if (pit_setcount(2, dat)) {          PITCH   pitch;
   
           pitch = pit.ch + 2;
           if (pit_setcount(pitch, dat)) {
                 return;                  return;
         }          }
         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, REG8 dat) {  static void IOOUTCALL pit_o77(UINT port, REG8 dat) {
   
         int             ch;          UINT    chnum;
           PITCH   pitch;
   
 //      TRACEOUT(("pic o77: %x", dat));          chnum = (dat >> 6) & 3;
         ch = (dat >> 6) & 3;          if (chnum != 3) {
         if (ch != 3) {                  pitch = pit.ch + chnum;
                 pit_setflag(ch, dat);                  pit_setflag(pitch, dat);
                 if (ch == 0) {                  // 書込みで itimerのirrがリセットされる…                  if (chnum == 0) {               // 書込みで itimerのirrがリセットされる…
                         pic.pi[0].irr &= (~1);                          pic.pi[0].irr &= (~1);
                         if (dat & 0x30) {       // 一応ラッチ時は割り込みをセットしない                          if (dat & 0x30) {       // 一応ラッチ時は割り込みをセットしない
                                 pit.intr[0] = 1;                                  pitch->flag |= PIT_FLAG_I;
 //                              setsystimerevent(NEVENT_ABSOLUTE);  
                         }                          }
                 }                  }
                 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 REG8 IOINPCALL pit_i71(UINT port) {  static REG8 IOINPCALL pit_i71(UINT port) {
   
         return(pit_getcount((port >> 1) & 3));          return(pit_getstat(pit.ch + ((port >> 1) & 3)));
 }  }
   
   
Line 322  static const IOINP piti71[4] = { Line 407  static const IOINP piti71[4] = {
   
 void itimer_reset(void) {  void itimer_reset(void) {
   
           UINT16  beepcnt;
   
         ZeroMemory(&pit, sizeof(pit));          ZeroMemory(&pit, sizeof(pit));
         if (pccore.cpumode & CPUMODE_8MHz) {          beepcnt = (pccore.cpumode & CPUMODE_8MHZ)?998:1229;
                 pit.value[1] = 998;                             // 4MHz          pit.ch[0].ctrl = 0x30;
         }          pit.ch[0].ch = 0;
         else {          pit.ch[0].flag = PIT_FLAG_I;
                 pit.value[1] = 1229;                    // 5MHz          pit.ch[0].ctrl = 0x56 & 0x3f;
         }          pit.ch[1].ch = 1;
         pit.intr[0] = 1;          pit.ch[1].value = beepcnt;
         pit.mode[0] = 0x30;          pit.ch[2].ctrl = 0xb6 & 0x3f;
         pit.mode[1] = 0x56;          pit.ch[2].ch = 2;
         pit.mode[2] = 0xb6;  #if !defined(DISABLE_SOUND)
         pit.mode[3] = 0x36;          pit.ch[3].ctrl = 0x36;
         setsystimerevent(NEVENT_ABSOLUTE);          pit.ch[3].ch = 3;
         beep_hzset(pit.value[1]);          pit.ch[4].ctrl = 0x36;
           pit.ch[4].ch = 4;
   #endif
           setsystimerevent(0, NEVENT_ABSOLUTE);
           beep_lheventset(1);                                                                                             // ver0.79
           beep_hzset(beepcnt);
 }  }
   
 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.15  
changed lines
  Added in v.1.23


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