Annotation of hatari/src/mfp.c, revision 1.1

1.1     ! root        1: /*
        !             2:   Hatari
        !             3: 
        !             4:   MFP - Multi Functional Peripheral. In emulation terms it's the 'chip from hell' - most differences between
        !             5:   a real machine and an emulator are down to this chip. It seems very simple at first but the implementation
        !             6:   is very difficult. The following code is the most accurate in an ST emulator to date as it is able to
        !             7:   perform Spectrum 512 raster effects as well as simulate the quirks found in the chip.
        !             8:   The easiest way to 'see' the MFP chip is to look at the diagram - this shows the main details of the chip's
        !             9:   behaviour with regard to interrupts and pending/service bits.
        !            10: */
        !            11: 
        !            12: #include "main.h"
        !            13: #include "debug.h"
        !            14: #include "decode.h"
        !            15: #include "fdc.h"
        !            16: #include "ikbd.h"
        !            17: #include "int.h"
        !            18: #include "m68000.h"
        !            19: #include "memAlloc.h"
        !            20: #include "memorySnapShot.h"
        !            21: #include "mfp.h"
        !            22: #include "misc.h"
        !            23: #include "psg.h"
        !            24: #include "screen.h"
        !            25: #include "shortcut.h"
        !            26: #include "sound.h"
        !            27: #include "stMemory.h"
        !            28: #include "ymFormat.h"
        !            29: #include "video.h"
        !            30: #include "view.h"
        !            31: 
        !            32: /*
        !            33:   MFP interrupt channel circuit:-
        !            34: 
        !            35:   EdgeRegister   EnableRegister                         MaskRegister             SBit
        !            36:         |                |                                     |                     |
        !            37:         |                |                                     |                     |          ------------------------
        !            38:         |                |         ------------------------    ---\                  |---\      |                      |
        !            39:         |                o--\      |                      |        AND---o----------------AND---| S InterruptInService |
        !            40:         ---\             |   AND---| S InterruptPending O |-------/      |           |---/      |                      |
        !            41:             XOR----------)--/      |          R           |              |           |          ------------------------
        !            42: Input -----/             |         ------------------------              |           |
        !            43:                          |                    |                   InterruptRequest   |
        !            44:                         NOT                  OR                                      |
        !            45:                          |                  |  |                                     |
        !            46:                          --------------------  --------------------------------------o--- PassVector
        !            47: */
        !            48: 
        !            49: #define  IGNORE_FDC_PRIORITY    0xff    /* Set 0xff if FDC has higher priority than Keyboard/Midi, or 0x7f if not - Dragon's Breath will now work! */
        !            50: 
        !            51: // MFP Registers
        !            52: unsigned char MFP_GPIP;               // General Purpose Pins
        !            53: unsigned char MFP_AER,MFP_DDR;        // Active Edge Register, Data Direction Register
        !            54: unsigned char MFP_IERA,MFP_IERB;      // Interrupt Enable Registers A,B  0xfffa07,0xfffa09
        !            55: unsigned char MFP_IPRA,MFP_IPRB;      // Interrupt Pending Registers A,B  0xfffa0b,0xfffa0d
        !            56: unsigned char MFP_ISRA,MFP_ISRB;      // Interrupt In-Service Registers A,B  0xfffa0f,0xfffa11
        !            57: unsigned char MFP_IMRA,MFP_IMRB;      // Interrupt Mask Registers A,B    0xfffa13,0xfffa15
        !            58: unsigned char MFP_VR;                 // Vector Register            0xfffa17
        !            59: unsigned char MFP_TACR,MFP_TBCR,MFP_TCDCR;    // Timer A,B,C+D Control Registers
        !            60: unsigned char MFP_TADR,MFP_TBDR;      // Timer A,B Data Registers
        !            61: unsigned char MFP_TCDR,MFP_TDDR;      // Timer C,D Data Registers
        !            62: unsigned char MFP_TA_MAINCOUNTER;     // Timer A Main Counter(internal to MFP)
        !            63: unsigned char MFP_TB_MAINCOUNTER;     // Timer B Main Counter
        !            64: unsigned char MFP_TC_MAINCOUNTER;     // Timer C Main Counter(these are temp's, set when read as)
        !            65: unsigned char MFP_TD_MAINCOUNTER;     // Timer D Main Counter(as done via interrupts)
        !            66: 
        !            67: /* CPU clock cycle counts for each timer */
        !            68: int TimerAClockCycles=0;
        !            69: int TimerBClockCycles=0;
        !            70: int TimerCClockCycles=0;
        !            71: int TimerDClockCycles=0;
        !            72: 
        !            73: /*
        !            74:  Number of CPU cycles for Timer C+D
        !            75:  These figures were based on 50Hz=160256cycles, so 200Hz=40064
        !            76:  Now, Timer C set on a delay of 192($C0) and a preset DIV of 64 is 200Hz
        !            77:  This makes the table entry 208.66666*192=40064(200Hz)
        !            78: */
        !            79: float MFPTimerToCPUCycleTable[] = {
        !            80:    0,        // Timer Stop
        !            81:    13.04166667f,  // Div by 4
        !            82:    32.60416667f,  // Div by 10
        !            83:    52.16666667f,  // Div by 16
        !            84:   163.02083333f,  // Div by 50
        !            85:   208.66666667f,  // Div by 64
        !            86:   326.04166667f,  // Div by 100
        !            87:   652.08333333f  // Div by 200
        !            88: };
        !            89: 
        !            90: 
        !            91: //-----------------------------------------------------------------------
        !            92: /*
        !            93:   Reset all MFP variables and start interrupts on their way!
        !            94: */
        !            95: void MFP_Reset(void)
        !            96: {
        !            97:   // Reset MFP internal variables
        !            98:   MFP_GPIP = 0xff;          /* Set GPIP register (all 1's = no interrupts) */
        !            99:   MFP_AER = MFP_DDR = 0;
        !           100:   MFP_IERA = MFP_IERB = 0;
        !           101:   MFP_IPRA = MFP_IPRB = 0;
        !           102:   MFP_ISRA = MFP_ISRB = 0;
        !           103:   MFP_IMRA = MFP_IMRB = 0;
        !           104:   MFP_VR = 0;
        !           105:   MFP_TACR = MFP_TBCR = MFP_TCDCR = 0;
        !           106:   MFP_TADR = MFP_TBDR = 0;
        !           107:   MFP_TCDR = MFP_TDDR = 0;
        !           108:   MFP_TA_MAINCOUNTER = MFP_TB_MAINCOUNTER = MFP_TC_MAINCOUNTER = MFP_TD_MAINCOUNTER = 0;
        !           109: 
        !           110:   // Clear counters
        !           111:   TimerAClockCycles = TimerBClockCycles = TimerCClockCycles = TimerDClockCycles = 0;
        !           112: }
        !           113: 
        !           114: //-----------------------------------------------------------------------
        !           115: /*
        !           116:   Save/Restore snapshot of local variables('MemorySnapShot_Store' handles type)
        !           117: */
        !           118: void MFP_MemorySnapShot_Capture(BOOL bSave)
        !           119: {
        !           120:   // Save/Restore details
        !           121:   MemorySnapShot_Store(&MFP_GPIP,sizeof(MFP_GPIP));
        !           122:   MemorySnapShot_Store(&MFP_AER,sizeof(MFP_AER));
        !           123:   MemorySnapShot_Store(&MFP_DDR,sizeof(MFP_DDR));
        !           124:   MemorySnapShot_Store(&MFP_IERA,sizeof(MFP_IERA));
        !           125:   MemorySnapShot_Store(&MFP_IERB,sizeof(MFP_IERB));
        !           126:   MemorySnapShot_Store(&MFP_IPRA,sizeof(MFP_IPRA));
        !           127:   MemorySnapShot_Store(&MFP_IPRB,sizeof(MFP_IPRB));
        !           128:   MemorySnapShot_Store(&MFP_ISRA,sizeof(MFP_ISRA));
        !           129:   MemorySnapShot_Store(&MFP_ISRB,sizeof(MFP_ISRB));
        !           130:   MemorySnapShot_Store(&MFP_IMRA,sizeof(MFP_IMRA));
        !           131:   MemorySnapShot_Store(&MFP_IMRB,sizeof(MFP_IMRB));
        !           132:   MemorySnapShot_Store(&MFP_VR,sizeof(MFP_VR));
        !           133:   MemorySnapShot_Store(&MFP_TACR,sizeof(MFP_TACR));
        !           134:   MemorySnapShot_Store(&MFP_TBCR,sizeof(MFP_TBCR));
        !           135:   MemorySnapShot_Store(&MFP_TCDCR,sizeof(MFP_TCDCR));
        !           136:   MemorySnapShot_Store(&MFP_TADR,sizeof(MFP_TADR));
        !           137:   MemorySnapShot_Store(&MFP_TBDR,sizeof(MFP_TBDR));
        !           138:   MemorySnapShot_Store(&MFP_TCDR,sizeof(MFP_TCDR));
        !           139:   MemorySnapShot_Store(&MFP_TDDR,sizeof(MFP_TDDR));
        !           140:   MemorySnapShot_Store(&MFP_TA_MAINCOUNTER,sizeof(MFP_TA_MAINCOUNTER));
        !           141:   MemorySnapShot_Store(&MFP_TB_MAINCOUNTER,sizeof(MFP_TB_MAINCOUNTER));
        !           142:   MemorySnapShot_Store(&MFP_TC_MAINCOUNTER,sizeof(MFP_TC_MAINCOUNTER));
        !           143:   MemorySnapShot_Store(&MFP_TD_MAINCOUNTER,sizeof(MFP_TD_MAINCOUNTER));
        !           144:   MemorySnapShot_Store(&TimerAClockCycles,sizeof(TimerAClockCycles));
        !           145:   MemorySnapShot_Store(&TimerBClockCycles,sizeof(TimerBClockCycles));
        !           146:   MemorySnapShot_Store(&TimerCClockCycles,sizeof(TimerCClockCycles));
        !           147:   MemorySnapShot_Store(&TimerDClockCycles,sizeof(TimerDClockCycles));
        !           148: }
        !           149: 
        !           150: //-----------------------------------------------------------------------
        !           151: /*
        !           152:   Call MFP interrupt - NOTE when the MFP is in Auto interrupt (AEI), the MFP
        !           153:   puts the interrupt number on the data bus and then the 68000 reads it, multiplies
        !           154:   it by 4 and adds in a base(usually 0x100) to give the vector. Some programs
        !           155:   change this offset, eg RoboCod. This offset is stored in the top 4 bits of register
        !           156:   0xfffa17(0x40 is the default=0x100)
        !           157:   Many thanks to Steve Bak for that one!
        !           158: */
        !           159: void MFP_Exception(int Interrupt)
        !           160: {
        !           161:   unsigned int Vec;
        !           162: 
        !           163:   Vec = (unsigned int)(MFP_VR&0xf0)<<2;
        !           164:   Vec += Interrupt<<2;
        !           165:   ExceptionVector = Vec;
        !           166:   M68000_Exception();
        !           167: }
        !           168: 
        !           169: //-----------------------------------------------------------------------
        !           170: /*
        !           171:   Test interrupt request to see if can cause exception,return TRUE if pass vector
        !           172: */
        !           173: BOOL InterruptRequest(int Exception,unsigned char Bit,unsigned long EnableAddr,unsigned char *pPendingReg,unsigned char MaskRegister,unsigned char PriorityMaskLow,unsigned char PriorityMaskHigh,unsigned char *pInServiceReg)
        !           174: {
        !           175:   // Are any higher priority interupts in service?
        !           176:   if ( ((MFP_ISRA&PriorityMaskLow)==0) && ((MFP_ISRB&PriorityMaskHigh)==0) ) {
        !           177:     // Is masked?
        !           178:     if (MaskRegister&Bit) {
        !           179: //u      if (7>FIND_IPL) {
        !           180: //u        *pPendingReg &= ~Bit;        // Clear pending bit
        !           181: //u        MFP_UpdateFlags();
        !           182: //u      }
        !           183: 
        !           184:       // CPU allows interrupt of an MFP level?
        !           185:       if (6>FIND_IPL) {
        !           186:         *pPendingReg &= ~Bit;           // Clear pending bit
        !           187:         MFP_UpdateFlags();
        !           188: 
        !           189:         // Are we in 'auto' interrupt or 'manual'?
        !           190:         if (MFP_VR&0x08)                // Software End-of-Interrupt (SEI)
        !           191:           *pInServiceReg |= Bit;        // Set interrupt in service register
        !           192:         else
        !           193:           *pInServiceReg &= ~Bit;       // Clear interrupt in service register
        !           194: 
        !           195:         // Call interrupt, adds in base(default 0x100)
        !           196:         MFP_Exception(Exception);
        !           197:         return(TRUE);
        !           198:       }
        !           199:     }
        !           200:   }
        !           201: 
        !           202:   return(FALSE);
        !           203: }
        !           204: 
        !           205: //-----------------------------------------------------------------------
        !           206: /*
        !           207:   MFP circuit has pending interrupt, request
        !           208: */
        !           209: void MFP_RequestInterrupt_TimerA(void)
        !           210: {
        !           211:   InterruptRequest(MFP_EXCEPT_TIMERA,MFP_TIMER_A_BIT,MFP_IERA,&MFP_IPRA,MFP_IMRA,0xe0,0x00&IGNORE_FDC_PRIORITY,&MFP_ISRA);
        !           212: }
        !           213: void MFP_RequestInterrupt_TimerB(void)
        !           214: {
        !           215:   InterruptRequest(MFP_EXCEPT_TIMERB,MFP_TIMER_B_BIT,MFP_IERA,&MFP_IPRA,MFP_IMRA,0xff,0x00&IGNORE_FDC_PRIORITY,&MFP_ISRA);
        !           216: }
        !           217: void MFP_RequestInterrupt_TimerC(void)
        !           218: {
        !           219:   InterruptRequest(MFP_EXCEPT_TIMERC,MFP_TIMER_C_BIT,MFP_IERB,&MFP_IPRB,MFP_IMRB,0xff,0xe0&IGNORE_FDC_PRIORITY,&MFP_ISRB);
        !           220: }
        !           221: void MFP_RequestInterrupt_TimerD(void)
        !           222: {
        !           223:   InterruptRequest(MFP_EXCEPT_TIMERD,MFP_TIMER_D_BIT,MFP_IERB,&MFP_IPRB,MFP_IMRB,0xff,0xf0&IGNORE_FDC_PRIORITY,&MFP_ISRB);
        !           224: }
        !           225: void MFP_RequestInterrupt_Keyboard(void)
        !           226: {
        !           227:   InterruptRequest(MFP_EXCEPT_KEYBOARD,MFP_KEYBOARD_BIT,MFP_IERB,&MFP_IPRB,MFP_IMRB,0xff,0xc0&IGNORE_FDC_PRIORITY,&MFP_ISRB);
        !           228: }
        !           229: void MFP_RequestInterrupt_Floppy(void)
        !           230: {
        !           231:   InterruptRequest(MFP_EXCEPT_GPIP5,MFP_FDCHDC_BIT,MFP_IERB,&MFP_IPRB,MFP_IMRB,0xff,0x80&IGNORE_FDC_PRIORITY,&MFP_ISRB);
        !           232: }
        !           233: 
        !           234: //-----------------------------------------------------------------------
        !           235: /*
        !           236:   Check 'pending' registers to see if any MFP interrupts need servicing
        !           237: */
        !           238: void MFP_CheckPendingInterrupts(void)
        !           239: {
        !           240:  unsigned short i;
        !           241: 
        !           242:  i = (MFP_IPRA<<8) | MFP_IPRB;
        !           243: 
        !           244:  if( (i&0x21f0)==0 )
        !           245:   {    /* Should never get here, but if do just clear flag (see 'MFP_UpdateFlags') */
        !           246:    PendingInterruptFlag &= CLEAR_PENDING_INTERRUPT_FLAG_MFP;
        !           247:    return;
        !           248:   }
        !           249: 
        !           250:  if( i&0x2000 )  MFP_RequestInterrupt_TimerA();    /* Check Timer A (bit 5) */
        !           251:  if( i&0x0100 )  MFP_RequestInterrupt_TimerB();    /* Check Timer B (bit 0) */
        !           252:  if( i&0x0080 )  MFP_RequestInterrupt_Floppy();    /* Check FDC (bit 7) */
        !           253:  if( i&0x0040 )  MFP_RequestInterrupt_Keyboard();  /* Check Keyboard (bit 6) */
        !           254:  if( i&0x0020 )  MFP_RequestInterrupt_TimerC();    /* Check Timer C (bit 5) */
        !           255:  if( i&0x0010 )  MFP_RequestInterrupt_TimerD();    /* Check Timer D (bit 4) */
        !           256: }
        !           257: 
        !           258: //-----------------------------------------------------------------------
        !           259: /*
        !           260:   This is called whenever the MFP_IPRA or MFP_IPRB registers are modified.
        !           261:   We set the 'PendingInterruptFlag' accordingly (to say if an MFP interrupt
        !           262:   is to be checked) so we only have one compare during the decode
        !           263:   instruction loop.
        !           264: */
        !           265: void MFP_UpdateFlags(void)
        !           266: {
        !           267:  if( MFP_IPRA|MFP_IPRB )
        !           268:    {
        !           269:     PendingInterruptFlag |= PENDING_INTERRUPT_FLAG_MFP;
        !           270:    }
        !           271:   else
        !           272:    {
        !           273:     PendingInterruptFlag &= CLEAR_PENDING_INTERRUPT_FLAG_MFP;
        !           274:    }
        !           275: }
        !           276: 
        !           277: //-----------------------------------------------------------------------
        !           278: /*
        !           279:   Interrupt Channel is active, set pending bit so can be serviced
        !           280: */
        !           281: void MFP_InputOnChannel(unsigned char Bit,unsigned char EnableBit,unsigned char *pPendingReg)
        !           282: {
        !           283:   // Input has occurred on MFP channel, set interrupt pending to request interrupt when able
        !           284:   if (EnableBit&Bit)
        !           285:     *pPendingReg |= Bit;           // Set bit
        !           286:   else
        !           287:     *pPendingReg &= ~Bit;          // Clear bit
        !           288:   MFP_UpdateFlags();
        !           289: }
        !           290: 
        !           291: //-----------------------------------------------------------------------
        !           292: /*
        !           293:   Generate Timer A Interrupt when in Event Count mode
        !           294: */
        !           295: void MFP_TimerA_EventCount_Interrupt(void)
        !           296: {
        !           297:   if (MFP_TA_MAINCOUNTER==1) {          // Timer expired? If so, generate interrupt
        !           298:     MFP_TA_MAINCOUNTER = MFP_TADR;      // Reload timer from data register
        !           299: 
        !           300:     // Acknowledge in MFP circuit, pass bit,enable,pending
        !           301:     MFP_InputOnChannel(MFP_TIMER_A_BIT,MFP_IERA,&MFP_IPRA);
        !           302:   }
        !           303:   else
        !           304:     MFP_TA_MAINCOUNTER--;               // Subtract timer main counter
        !           305: }
        !           306: 
        !           307: //-----------------------------------------------------------------------
        !           308: /*
        !           309:   Generate Timer B Interrupt when in Event Count mode
        !           310: */
        !           311: void MFP_TimerB_EventCount_Interrupt(void)
        !           312: {
        !           313:   if (MFP_TB_MAINCOUNTER==1) {          // Timer expired? If so, generate interrupt
        !           314:     MFP_TB_MAINCOUNTER = MFP_TBDR;      // Reload timer from data register
        !           315: 
        !           316:     // Acknowledge in MFP circuit, pass bit,enable,pending
        !           317:     MFP_InputOnChannel(MFP_TIMER_B_BIT,MFP_IERA,&MFP_IPRA);
        !           318:   }
        !           319:   else
        !           320:     MFP_TB_MAINCOUNTER--;               // Subtract timer main counter
        !           321: }
        !           322: 
        !           323: //-----------------------------------------------------------------------
        !           324: /*
        !           325:   Start Timer A or B - EventCount mode is done in HBL handler to time correctly
        !           326: */
        !           327: int MFP_StartTimer_AB(unsigned char TimerControl, unsigned int TimerData, int Handler, BOOL bFirstTimer)
        !           328: {
        !           329:   int TimerClockCycles;
        !           330: 
        !           331:   /* If we are in event-count mode ignore this(done on HBL) */
        !           332:   if (TimerControl!=0x08) {
        !           333:     /* Find number of CPU cycles for when timer is due(include preset and counter) */
        !           334:     /* As timer occurs very often we multiply by counter to speed up emulator */
        !           335:     if (TimerData==0)                   /* Data=0 is actually Data=256 */
        !           336:       TimerData = 256;
        !           337:     TimerClockCycles = ROUND_CYCLES_TO4( TimerData*MFPTimerToCPUCycleTable[TimerControl&0x7] );
        !           338: 
        !           339:     /* And add to our internal interrupt list, if timer cycles is zero then timer is stopped */
        !           340:     Int_RemovePendingInterrupt(Handler);
        !           341:     if (TimerClockCycles) {
        !           342:       /* Start timer from now? If not continue timer so from original offset */
        !           343:       if (bFirstTimer)
        !           344:         nCyclesOver = 0;
        !           345:       Int_AddRelativeInterrupt(TimerClockCycles,Handler);
        !           346:     }
        !           347:   }
        !           348:   else {
        !           349:     /* Make sure no outstanding interrupts in list if channel is disabled */
        !           350:     Int_RemovePendingInterrupt(Handler);
        !           351:   }
        !           352: 
        !           353:   return(TimerClockCycles);
        !           354: }
        !           355: 
        !           356: //-----------------------------------------------------------------------
        !           357: /*
        !           358:   Start Timer C or D
        !           359: */
        !           360: int MFP_StartTimer_CD(unsigned char TimerControl, unsigned int TimerData, int Handler, BOOL bFirstTimer)
        !           361: {
        !           362:   int TimerClockCycles;
        !           363: 
        !           364:   /* Is timer on? */
        !           365:   if ((TimerControl&0x7)!=0) {
        !           366:     /* Find number of cycles for when timer is due(include preset and counter) */
        !           367:     /* As timer occurs very often we multiply by counter to speed up emulator */
        !           368:     if (TimerData==0)                   /* Data=0 is actually Data=256 */
        !           369:       TimerData = 256;
        !           370:     TimerClockCycles = ROUND_CYCLES_TO4( TimerData*MFPTimerToCPUCycleTable[TimerControl&0x7] );
        !           371: 
        !           372:     /* And add to our internal interrupt list, if timer cycles is zero then timer is stopped */
        !           373:     Int_RemovePendingInterrupt(Handler);
        !           374:     if (TimerClockCycles) {
        !           375:       /* Start timer from now? If not continue timer so from original offset */
        !           376:       if (bFirstTimer)
        !           377:         nCyclesOver = 0;
        !           378:       Int_AddRelativeInterrupt(TimerClockCycles,Handler);
        !           379:     }
        !           380:   }
        !           381:   else {
        !           382:     /* Make sure no outstanding interrupts in list if channel is disabled */
        !           383:     Int_RemovePendingInterrupt(Handler);
        !           384:   }
        !           385: 
        !           386:   return(TimerClockCycles);
        !           387: }
        !           388: 
        !           389: //-----------------------------------------------------------------------
        !           390: /*
        !           391:   Read Timer A or B - If in EventCount MainCounter already has correct value
        !           392: */
        !           393: unsigned char MFP_ReadTimer_AB(unsigned char TimerControl, unsigned char MainCounter, int TimerCycles, int Handler)
        !           394: {
        !           395:   int TimerCyclesPassed;
        !           396: 
        !           397:   /* Find TimerAB count, if no interrupt assume in Event Count mode so already up-to-date as kept by HBL */
        !           398:   if (Int_InterruptActive(Handler)) {
        !           399:     /* Find cycles passed since last interrupt */
        !           400:     TimerCyclesPassed = TimerCycles-Int_FindCyclesPassed(Handler);
        !           401:     MainCounter = TimerCyclesPassed/(MFPTimerToCPUCycleTable[TimerControl&0x7]);
        !           402:   }
        !           403:   
        !           404:   return(MainCounter);
        !           405: }
        !           406: 
        !           407: //-----------------------------------------------------------------------
        !           408: /*
        !           409:   Read Timer C or D
        !           410: */
        !           411: unsigned char MFP_ReadTimerCD(unsigned char TimerControl,unsigned char TimerData,  unsigned char MainCounter, int TimerCycles, int Handler)
        !           412: {
        !           413:   int TimerCyclesPassed;
        !           414: 
        !           415:   // Find TimerCD count. If not one then timer should be off and can find count from main counter
        !           416:   if (Int_InterruptActive(Handler)) {
        !           417:     // Find cycles passed since last interrupt
        !           418:     TimerCyclesPassed = TimerCycles-Int_FindCyclesPassed(Handler);
        !           419:     MainCounter = TimerCyclesPassed/(MFPTimerToCPUCycleTable[TimerControl&0x7]);
        !           420:   }
        !           421:   else {
        !           422:     MainCounter = TimerData;
        !           423:   }
        !           424: 
        !           425:   return(MainCounter);
        !           426: }
        !           427: 
        !           428: //-----------------------------------------------------------------------
        !           429: /*
        !           430:   Start Timer A
        !           431:   (This does not start the EventCount mode time as this is taken care of by the HBL)
        !           432: */
        !           433: void MFP_StartTimerA(void)
        !           434: {
        !           435:   TimerAClockCycles = MFP_StartTimer_AB(MFP_TACR,MFP_TADR,INTERRUPT_MFP_TIMERA,TRUE);
        !           436: }
        !           437: 
        !           438: 
        !           439: //-----------------------------------------------------------------------
        !           440: /*
        !           441:   Read Timer A
        !           442: */
        !           443: void MFP_ReadTimerA(void)
        !           444: {
        !           445:   MFP_TA_MAINCOUNTER = MFP_ReadTimer_AB(MFP_TACR,MFP_TA_MAINCOUNTER,TimerAClockCycles,INTERRUPT_MFP_TIMERA);
        !           446: }
        !           447: 
        !           448: 
        !           449: //-----------------------------------------------------------------------
        !           450: /*
        !           451:   Start Timer B
        !           452:   (This does not start the EventCount mode time as this is taken care of by the HBL)
        !           453: */
        !           454: void MFP_StartTimerB(void)
        !           455: {
        !           456:   TimerBClockCycles = MFP_StartTimer_AB(MFP_TBCR,MFP_TBDR,INTERRUPT_MFP_TIMERB,TRUE);
        !           457: }
        !           458: 
        !           459: 
        !           460: //-----------------------------------------------------------------------
        !           461: /*
        !           462:   Read Timer B
        !           463: */
        !           464: void MFP_ReadTimerB(void)
        !           465: {
        !           466:   MFP_TB_MAINCOUNTER = MFP_ReadTimer_AB(MFP_TBCR,MFP_TB_MAINCOUNTER,TimerBClockCycles,INTERRUPT_MFP_TIMERB);
        !           467: }
        !           468: 
        !           469: 
        !           470: //-----------------------------------------------------------------------
        !           471: /*
        !           472:   Start Timer C
        !           473: */
        !           474: void MFP_StartTimerC(void)
        !           475: {
        !           476:   TimerCClockCycles = MFP_StartTimer_CD(MFP_TCDCR>>4,MFP_TCDR,INTERRUPT_MFP_TIMERC,TRUE);
        !           477: }
        !           478: 
        !           479: 
        !           480: //-----------------------------------------------------------------------
        !           481: /*
        !           482:   Read Timer C
        !           483: */
        !           484: void MFP_ReadTimerC(void)
        !           485: {
        !           486:   MFP_TC_MAINCOUNTER = MFP_ReadTimerCD(MFP_TCDCR>>4,MFP_TCDR,MFP_TC_MAINCOUNTER,TimerCClockCycles,INTERRUPT_MFP_TIMERC);
        !           487: }
        !           488: 
        !           489: 
        !           490: //-----------------------------------------------------------------------
        !           491: /*
        !           492:   Start Timer D
        !           493: */
        !           494: void MFP_StartTimerD(void)
        !           495: {
        !           496:   TimerDClockCycles = MFP_StartTimer_CD(MFP_TCDCR,MFP_TDDR,INTERRUPT_MFP_TIMERD,TRUE);
        !           497: }
        !           498: 
        !           499: 
        !           500: //-----------------------------------------------------------------------
        !           501: /*
        !           502:   Read Timer D
        !           503: */
        !           504: void MFP_ReadTimerD(void)
        !           505: {
        !           506:   MFP_TD_MAINCOUNTER = MFP_ReadTimerCD(MFP_TCDCR,MFP_TDDR,MFP_TC_MAINCOUNTER,TimerDClockCycles,INTERRUPT_MFP_TIMERD);
        !           507: }
        !           508: 
        !           509: 
        !           510: //-----------------------------------------------------------------------
        !           511: /*
        !           512:   Handle Timer A Interrupt
        !           513: */
        !           514: void MFP_InterruptHandler_TimerA(void)
        !           515: {
        !           516:   // Remove this interrupt from list and re-order
        !           517:   Int_AcknowledgeInterrupt();
        !           518: 
        !           519:   // Acknowledge in MFP circuit, pass bit,enable,pending
        !           520:   if ((MFP_TACR&0xf)!=0)                // Is timer OK?
        !           521:     MFP_InputOnChannel(MFP_TIMER_A_BIT,MFP_IERA,&MFP_IPRA);
        !           522: 
        !           523:   // Start next interrupt, if need one - from current cycle count
        !           524:   TimerAClockCycles = MFP_StartTimer_AB(MFP_TACR,MFP_TADR,INTERRUPT_MFP_TIMERA,FALSE);
        !           525: }
        !           526: 
        !           527: 
        !           528: //-----------------------------------------------------------------------
        !           529: /*
        !           530:   Handle Timer B Interrupt
        !           531: */
        !           532: void MFP_InterruptHandler_TimerB(void)
        !           533: {
        !           534:   // Remove this interrupt from list and re-order
        !           535:   Int_AcknowledgeInterrupt();
        !           536: 
        !           537:   // Acknowledge in MFP circuit, pass bit,enable,pending
        !           538:   if ((MFP_TBCR&0xf)!=0)                // Is timer OK?
        !           539:     MFP_InputOnChannel(MFP_TIMER_B_BIT,MFP_IERA,&MFP_IPRA);
        !           540: 
        !           541:   // Start next interrupt, if need one - from current cycle count
        !           542:   TimerBClockCycles = MFP_StartTimer_AB(MFP_TBCR,MFP_TBDR,INTERRUPT_MFP_TIMERB,FALSE);
        !           543: }
        !           544: 
        !           545: 
        !           546: //-----------------------------------------------------------------------
        !           547: /*
        !           548:   Handle Timer C Interrupt
        !           549: */
        !           550: void MFP_InterruptHandler_TimerC(void)
        !           551: {
        !           552:   // Remove this interrupt from list and re-order
        !           553:   Int_AcknowledgeInterrupt();
        !           554: 
        !           555:   // Acknowledge in MFP circuit, pass bit,enable,pending
        !           556:   if ((MFP_TCDCR&0x70)!=0)              // Is timer OK?
        !           557:     MFP_InputOnChannel(MFP_TIMER_C_BIT,MFP_IERB,&MFP_IPRB);
        !           558: 
        !           559:   // Start next interrupt, if need one - from current cycle count
        !           560:   TimerCClockCycles = MFP_StartTimer_CD(MFP_TCDCR>>4,MFP_TCDR,INTERRUPT_MFP_TIMERC,FALSE);
        !           561: }
        !           562: 
        !           563: 
        !           564: //-----------------------------------------------------------------------
        !           565: /*
        !           566:   Handle Timer D Interrupt
        !           567: */
        !           568: void MFP_InterruptHandler_TimerD(void)
        !           569: {
        !           570:   // Remove this interrupt from list and re-order
        !           571:   Int_AcknowledgeInterrupt();
        !           572: 
        !           573:   // Acknowledge in MFP circuit, pass bit,enable,pending
        !           574:   if ((MFP_TCDCR&0x07)!=0)              // Is timer OK?
        !           575:     MFP_InputOnChannel(MFP_TIMER_D_BIT,MFP_IERB,&MFP_IPRB);
        !           576: 
        !           577:   // Start next interrupt, if need one - from current cycle count
        !           578:   TimerDClockCycles = MFP_StartTimer_CD(MFP_TCDCR,MFP_TDDR,INTERRUPT_MFP_TIMERD,FALSE);
        !           579: }
        !           580: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.