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

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

unix.superglobalmegacorp.com

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