Annotation of hatari/src/mfp.c, revision 1.1.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.