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

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: 
1.1.1.2 ! root       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) */
1.1       root       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[] = {
1.1.1.2 ! root       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 */
1.1       root       88: };
                     89: 
                     90: 
1.1.1.2 ! root       91: /*-----------------------------------------------------------------------*/
1.1       root       92: /*
                     93:   Reset all MFP variables and start interrupts on their way!
                     94: */
                     95: void MFP_Reset(void)
                     96: {
1.1.1.2 ! root       97:   /* Reset MFP internal variables */
1.1       root       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: 
1.1.1.2 ! root      110:   /* Clear counters */
1.1       root      111:   TimerAClockCycles = TimerBClockCycles = TimerCClockCycles = TimerDClockCycles = 0;
                    112: }
                    113: 
1.1.1.2 ! root      114: 
        !           115: /*-----------------------------------------------------------------------*/
1.1       root      116: /*
                    117:   Save/Restore snapshot of local variables('MemorySnapShot_Store' handles type)
                    118: */
                    119: void MFP_MemorySnapShot_Capture(BOOL bSave)
                    120: {
1.1.1.2 ! root      121:   /* Save/Restore details */
1.1       root      122:   MemorySnapShot_Store(&MFP_GPIP,sizeof(MFP_GPIP));
                    123:   MemorySnapShot_Store(&MFP_AER,sizeof(MFP_AER));
                    124:   MemorySnapShot_Store(&MFP_DDR,sizeof(MFP_DDR));
                    125:   MemorySnapShot_Store(&MFP_IERA,sizeof(MFP_IERA));
                    126:   MemorySnapShot_Store(&MFP_IERB,sizeof(MFP_IERB));
                    127:   MemorySnapShot_Store(&MFP_IPRA,sizeof(MFP_IPRA));
                    128:   MemorySnapShot_Store(&MFP_IPRB,sizeof(MFP_IPRB));
                    129:   MemorySnapShot_Store(&MFP_ISRA,sizeof(MFP_ISRA));
                    130:   MemorySnapShot_Store(&MFP_ISRB,sizeof(MFP_ISRB));
                    131:   MemorySnapShot_Store(&MFP_IMRA,sizeof(MFP_IMRA));
                    132:   MemorySnapShot_Store(&MFP_IMRB,sizeof(MFP_IMRB));
                    133:   MemorySnapShot_Store(&MFP_VR,sizeof(MFP_VR));
                    134:   MemorySnapShot_Store(&MFP_TACR,sizeof(MFP_TACR));
                    135:   MemorySnapShot_Store(&MFP_TBCR,sizeof(MFP_TBCR));
                    136:   MemorySnapShot_Store(&MFP_TCDCR,sizeof(MFP_TCDCR));
                    137:   MemorySnapShot_Store(&MFP_TADR,sizeof(MFP_TADR));
                    138:   MemorySnapShot_Store(&MFP_TBDR,sizeof(MFP_TBDR));
                    139:   MemorySnapShot_Store(&MFP_TCDR,sizeof(MFP_TCDR));
                    140:   MemorySnapShot_Store(&MFP_TDDR,sizeof(MFP_TDDR));
                    141:   MemorySnapShot_Store(&MFP_TA_MAINCOUNTER,sizeof(MFP_TA_MAINCOUNTER));
                    142:   MemorySnapShot_Store(&MFP_TB_MAINCOUNTER,sizeof(MFP_TB_MAINCOUNTER));
                    143:   MemorySnapShot_Store(&MFP_TC_MAINCOUNTER,sizeof(MFP_TC_MAINCOUNTER));
                    144:   MemorySnapShot_Store(&MFP_TD_MAINCOUNTER,sizeof(MFP_TD_MAINCOUNTER));
                    145:   MemorySnapShot_Store(&TimerAClockCycles,sizeof(TimerAClockCycles));
                    146:   MemorySnapShot_Store(&TimerBClockCycles,sizeof(TimerBClockCycles));
                    147:   MemorySnapShot_Store(&TimerCClockCycles,sizeof(TimerCClockCycles));
                    148:   MemorySnapShot_Store(&TimerDClockCycles,sizeof(TimerDClockCycles));
                    149: }
                    150: 
1.1.1.2 ! root      151: 
        !           152: /*-----------------------------------------------------------------------*/
1.1       root      153: /*
                    154:   Call MFP interrupt - NOTE when the MFP is in Auto interrupt (AEI), the MFP
                    155:   puts the interrupt number on the data bus and then the 68000 reads it, multiplies
                    156:   it by 4 and adds in a base(usually 0x100) to give the vector. Some programs
                    157:   change this offset, eg RoboCod. This offset is stored in the top 4 bits of register
                    158:   0xfffa17(0x40 is the default=0x100)
                    159:   Many thanks to Steve Bak for that one!
                    160: */
                    161: void MFP_Exception(int Interrupt)
                    162: {
                    163:   unsigned int Vec;
                    164: 
                    165:   Vec = (unsigned int)(MFP_VR&0xf0)<<2;
                    166:   Vec += Interrupt<<2;
                    167:   ExceptionVector = Vec;
                    168:   M68000_Exception();
                    169: }
                    170: 
1.1.1.2 ! root      171: 
        !           172: /*-----------------------------------------------------------------------*/
1.1       root      173: /*
                    174:   Test interrupt request to see if can cause exception,return TRUE if pass vector
                    175: */
                    176: 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)
                    177: {
1.1.1.2 ! root      178:   /* Are any higher priority interupts in service? */
1.1       root      179:   if ( ((MFP_ISRA&PriorityMaskLow)==0) && ((MFP_ISRB&PriorityMaskHigh)==0) ) {
1.1.1.2 ! root      180:     /* Is masked? */
1.1       root      181:     if (MaskRegister&Bit) {
                    182: //u      if (7>FIND_IPL) {
1.1.1.2 ! root      183: //u        *pPendingReg &= ~Bit;        /* Clear pending bit */
1.1       root      184: //u        MFP_UpdateFlags();
                    185: //u      }
                    186: 
1.1.1.2 ! root      187:       /* CPU allows interrupt of an MFP level? */
1.1       root      188:       if (6>FIND_IPL) {
1.1.1.2 ! root      189:         *pPendingReg &= ~Bit;           /* Clear pending bit */
1.1       root      190:         MFP_UpdateFlags();
                    191: 
1.1.1.2 ! root      192:         /* Are we in 'auto' interrupt or 'manual'? */
        !           193:         if (MFP_VR&0x08)                /* Software End-of-Interrupt (SEI) */
        !           194:           *pInServiceReg |= Bit;        /* Set interrupt in service register */
1.1       root      195:         else
1.1.1.2 ! root      196:           *pInServiceReg &= ~Bit;       /* Clear interrupt in service register */
1.1       root      197: 
1.1.1.2 ! root      198:         /* Call interrupt, adds in base (default 0x100) */
1.1       root      199:         MFP_Exception(Exception);
                    200:         return(TRUE);
                    201:       }
                    202:     }
                    203:   }
                    204: 
                    205:   return(FALSE);
                    206: }
                    207: 
1.1.1.2 ! root      208: 
        !           209: /*-----------------------------------------------------------------------*/
1.1       root      210: /*
                    211:   MFP circuit has pending interrupt, request
                    212: */
                    213: void MFP_RequestInterrupt_TimerA(void)
                    214: {
                    215:   InterruptRequest(MFP_EXCEPT_TIMERA,MFP_TIMER_A_BIT,MFP_IERA,&MFP_IPRA,MFP_IMRA,0xe0,0x00&IGNORE_FDC_PRIORITY,&MFP_ISRA);
                    216: }
                    217: void MFP_RequestInterrupt_TimerB(void)
                    218: {
                    219:   InterruptRequest(MFP_EXCEPT_TIMERB,MFP_TIMER_B_BIT,MFP_IERA,&MFP_IPRA,MFP_IMRA,0xff,0x00&IGNORE_FDC_PRIORITY,&MFP_ISRA);
                    220: }
                    221: void MFP_RequestInterrupt_TimerC(void)
                    222: {
                    223:   InterruptRequest(MFP_EXCEPT_TIMERC,MFP_TIMER_C_BIT,MFP_IERB,&MFP_IPRB,MFP_IMRB,0xff,0xe0&IGNORE_FDC_PRIORITY,&MFP_ISRB);
                    224: }
                    225: void MFP_RequestInterrupt_TimerD(void)
                    226: {
                    227:   InterruptRequest(MFP_EXCEPT_TIMERD,MFP_TIMER_D_BIT,MFP_IERB,&MFP_IPRB,MFP_IMRB,0xff,0xf0&IGNORE_FDC_PRIORITY,&MFP_ISRB);
                    228: }
                    229: void MFP_RequestInterrupt_Keyboard(void)
                    230: {
                    231:   InterruptRequest(MFP_EXCEPT_KEYBOARD,MFP_KEYBOARD_BIT,MFP_IERB,&MFP_IPRB,MFP_IMRB,0xff,0xc0&IGNORE_FDC_PRIORITY,&MFP_ISRB);
                    232: }
                    233: void MFP_RequestInterrupt_Floppy(void)
                    234: {
                    235:   InterruptRequest(MFP_EXCEPT_GPIP5,MFP_FDCHDC_BIT,MFP_IERB,&MFP_IPRB,MFP_IMRB,0xff,0x80&IGNORE_FDC_PRIORITY,&MFP_ISRB);
                    236: }
                    237: 
1.1.1.2 ! root      238: 
        !           239: /*-----------------------------------------------------------------------*/
1.1       root      240: /*
                    241:   Check 'pending' registers to see if any MFP interrupts need servicing
                    242: */
                    243: void MFP_CheckPendingInterrupts(void)
                    244: {
                    245:  unsigned short i;
                    246: 
                    247:  i = (MFP_IPRA<<8) | MFP_IPRB;
                    248: 
                    249:  if( (i&0x21f0)==0 )
                    250:   {    /* Should never get here, but if do just clear flag (see 'MFP_UpdateFlags') */
                    251:    PendingInterruptFlag &= CLEAR_PENDING_INTERRUPT_FLAG_MFP;
                    252:    return;
                    253:   }
                    254: 
                    255:  if( i&0x2000 )  MFP_RequestInterrupt_TimerA();    /* Check Timer A (bit 5) */
                    256:  if( i&0x0100 )  MFP_RequestInterrupt_TimerB();    /* Check Timer B (bit 0) */
                    257:  if( i&0x0080 )  MFP_RequestInterrupt_Floppy();    /* Check FDC (bit 7) */
                    258:  if( i&0x0040 )  MFP_RequestInterrupt_Keyboard();  /* Check Keyboard (bit 6) */
                    259:  if( i&0x0020 )  MFP_RequestInterrupt_TimerC();    /* Check Timer C (bit 5) */
                    260:  if( i&0x0010 )  MFP_RequestInterrupt_TimerD();    /* Check Timer D (bit 4) */
                    261: }
                    262: 
1.1.1.2 ! root      263: 
        !           264: /*-----------------------------------------------------------------------*/
1.1       root      265: /*
                    266:   This is called whenever the MFP_IPRA or MFP_IPRB registers are modified.
                    267:   We set the 'PendingInterruptFlag' accordingly (to say if an MFP interrupt
                    268:   is to be checked) so we only have one compare during the decode
                    269:   instruction loop.
                    270: */
                    271: void MFP_UpdateFlags(void)
                    272: {
                    273:  if( MFP_IPRA|MFP_IPRB )
                    274:    {
                    275:     PendingInterruptFlag |= PENDING_INTERRUPT_FLAG_MFP;
                    276:    }
                    277:   else
                    278:    {
                    279:     PendingInterruptFlag &= CLEAR_PENDING_INTERRUPT_FLAG_MFP;
                    280:    }
                    281: }
                    282: 
1.1.1.2 ! root      283: 
        !           284: /*-----------------------------------------------------------------------*/
1.1       root      285: /*
                    286:   Interrupt Channel is active, set pending bit so can be serviced
                    287: */
                    288: void MFP_InputOnChannel(unsigned char Bit,unsigned char EnableBit,unsigned char *pPendingReg)
                    289: {
1.1.1.2 ! root      290:   /* Input has occurred on MFP channel, set interrupt pending to request interrupt when able */
1.1       root      291:   if (EnableBit&Bit)
1.1.1.2 ! root      292:     *pPendingReg |= Bit;           /* Set bit */
1.1       root      293:   else
1.1.1.2 ! root      294:     *pPendingReg &= ~Bit;          /* Clear bit */
1.1       root      295:   MFP_UpdateFlags();
                    296: }
                    297: 
1.1.1.2 ! root      298: 
        !           299: /*-----------------------------------------------------------------------*/
1.1       root      300: /*
                    301:   Generate Timer A Interrupt when in Event Count mode
                    302: */
                    303: void MFP_TimerA_EventCount_Interrupt(void)
                    304: {
1.1.1.2 ! root      305:   if (MFP_TA_MAINCOUNTER==1) {          /* Timer expired? If so, generate interrupt */
        !           306:     MFP_TA_MAINCOUNTER = MFP_TADR;      /* Reload timer from data register */
1.1       root      307: 
1.1.1.2 ! root      308:     /* Acknowledge in MFP circuit, pass bit,enable,pending */
1.1       root      309:     MFP_InputOnChannel(MFP_TIMER_A_BIT,MFP_IERA,&MFP_IPRA);
                    310:   }
                    311:   else
1.1.1.2 ! root      312:     MFP_TA_MAINCOUNTER--;               /* Subtract timer main counter */
1.1       root      313: }
                    314: 
1.1.1.2 ! root      315: 
        !           316: /*-----------------------------------------------------------------------*/
1.1       root      317: /*
                    318:   Generate Timer B Interrupt when in Event Count mode
                    319: */
                    320: void MFP_TimerB_EventCount_Interrupt(void)
                    321: {
1.1.1.2 ! root      322:   if (MFP_TB_MAINCOUNTER==1) {          /* Timer expired? If so, generate interrupt */
        !           323:     MFP_TB_MAINCOUNTER = MFP_TBDR;      /* Reload timer from data register */
1.1       root      324: 
1.1.1.2 ! root      325:     /* Acknowledge in MFP circuit, pass bit,enable,pending */
1.1       root      326:     MFP_InputOnChannel(MFP_TIMER_B_BIT,MFP_IERA,&MFP_IPRA);
                    327:   }
                    328:   else
1.1.1.2 ! root      329:     MFP_TB_MAINCOUNTER--;               /* Subtract timer main counter */
1.1       root      330: }
                    331: 
1.1.1.2 ! root      332: 
        !           333: /*-----------------------------------------------------------------------*/
1.1       root      334: /*
                    335:   Start Timer A or B - EventCount mode is done in HBL handler to time correctly
                    336: */
                    337: int MFP_StartTimer_AB(unsigned char TimerControl, unsigned int TimerData, int Handler, BOOL bFirstTimer)
                    338: {
                    339:   int TimerClockCycles;
                    340: 
                    341:   /* If we are in event-count mode ignore this(done on HBL) */
                    342:   if (TimerControl!=0x08) {
                    343:     /* Find number of CPU cycles for when timer is due(include preset and counter) */
                    344:     /* As timer occurs very often we multiply by counter to speed up emulator */
                    345:     if (TimerData==0)                   /* Data=0 is actually Data=256 */
                    346:       TimerData = 256;
                    347:     TimerClockCycles = ROUND_CYCLES_TO4( TimerData*MFPTimerToCPUCycleTable[TimerControl&0x7] );
                    348: 
                    349:     /* And add to our internal interrupt list, if timer cycles is zero then timer is stopped */
                    350:     Int_RemovePendingInterrupt(Handler);
                    351:     if (TimerClockCycles) {
                    352:       /* Start timer from now? If not continue timer so from original offset */
                    353:       if (bFirstTimer)
                    354:         nCyclesOver = 0;
                    355:       Int_AddRelativeInterrupt(TimerClockCycles,Handler);
                    356:     }
                    357:   }
                    358:   else {
                    359:     /* Make sure no outstanding interrupts in list if channel is disabled */
                    360:     Int_RemovePendingInterrupt(Handler);
                    361:   }
                    362: 
                    363:   return(TimerClockCycles);
                    364: }
                    365: 
1.1.1.2 ! root      366: 
        !           367: /*-----------------------------------------------------------------------*/
1.1       root      368: /*
                    369:   Start Timer C or D
                    370: */
                    371: int MFP_StartTimer_CD(unsigned char TimerControl, unsigned int TimerData, int Handler, BOOL bFirstTimer)
                    372: {
                    373:   int TimerClockCycles;
                    374: 
                    375:   /* Is timer on? */
                    376:   if ((TimerControl&0x7)!=0) {
                    377:     /* Find number of cycles for when timer is due(include preset and counter) */
                    378:     /* As timer occurs very often we multiply by counter to speed up emulator */
                    379:     if (TimerData==0)                   /* Data=0 is actually Data=256 */
                    380:       TimerData = 256;
                    381:     TimerClockCycles = ROUND_CYCLES_TO4( TimerData*MFPTimerToCPUCycleTable[TimerControl&0x7] );
                    382: 
                    383:     /* And add to our internal interrupt list, if timer cycles is zero then timer is stopped */
                    384:     Int_RemovePendingInterrupt(Handler);
                    385:     if (TimerClockCycles) {
                    386:       /* Start timer from now? If not continue timer so from original offset */
                    387:       if (bFirstTimer)
                    388:         nCyclesOver = 0;
                    389:       Int_AddRelativeInterrupt(TimerClockCycles,Handler);
                    390:     }
                    391:   }
                    392:   else {
                    393:     /* Make sure no outstanding interrupts in list if channel is disabled */
                    394:     Int_RemovePendingInterrupt(Handler);
                    395:   }
                    396: 
                    397:   return(TimerClockCycles);
                    398: }
                    399: 
1.1.1.2 ! root      400: 
        !           401: /*-----------------------------------------------------------------------*/
1.1       root      402: /*
                    403:   Read Timer A or B - If in EventCount MainCounter already has correct value
                    404: */
                    405: unsigned char MFP_ReadTimer_AB(unsigned char TimerControl, unsigned char MainCounter, int TimerCycles, int Handler)
                    406: {
                    407:   int TimerCyclesPassed;
                    408: 
                    409:   /* Find TimerAB count, if no interrupt assume in Event Count mode so already up-to-date as kept by HBL */
                    410:   if (Int_InterruptActive(Handler)) {
                    411:     /* Find cycles passed since last interrupt */
                    412:     TimerCyclesPassed = TimerCycles-Int_FindCyclesPassed(Handler);
                    413:     MainCounter = TimerCyclesPassed/(MFPTimerToCPUCycleTable[TimerControl&0x7]);
                    414:   }
                    415:   
                    416:   return(MainCounter);
                    417: }
                    418: 
1.1.1.2 ! root      419: 
        !           420: /*-----------------------------------------------------------------------*/
1.1       root      421: /*
                    422:   Read Timer C or D
                    423: */
                    424: unsigned char MFP_ReadTimerCD(unsigned char TimerControl,unsigned char TimerData,  unsigned char MainCounter, int TimerCycles, int Handler)
                    425: {
                    426:   int TimerCyclesPassed;
                    427: 
1.1.1.2 ! root      428:   /* Find TimerCD count. If not one then timer should be off and can find count from main counter */
1.1       root      429:   if (Int_InterruptActive(Handler)) {
1.1.1.2 ! root      430:     /* Find cycles passed since last interrupt */
1.1       root      431:     TimerCyclesPassed = TimerCycles-Int_FindCyclesPassed(Handler);
                    432:     MainCounter = TimerCyclesPassed/(MFPTimerToCPUCycleTable[TimerControl&0x7]);
                    433:   }
                    434:   else {
                    435:     MainCounter = TimerData;
                    436:   }
                    437: 
                    438:   return(MainCounter);
                    439: }
                    440: 
1.1.1.2 ! root      441: 
        !           442: /*-----------------------------------------------------------------------*/
1.1       root      443: /*
                    444:   Start Timer A
                    445:   (This does not start the EventCount mode time as this is taken care of by the HBL)
                    446: */
                    447: void MFP_StartTimerA(void)
                    448: {
                    449:   TimerAClockCycles = MFP_StartTimer_AB(MFP_TACR,MFP_TADR,INTERRUPT_MFP_TIMERA,TRUE);
                    450: }
                    451: 
                    452: 
1.1.1.2 ! root      453: /*-----------------------------------------------------------------------*/
1.1       root      454: /*
                    455:   Read Timer A
                    456: */
                    457: void MFP_ReadTimerA(void)
                    458: {
                    459:   MFP_TA_MAINCOUNTER = MFP_ReadTimer_AB(MFP_TACR,MFP_TA_MAINCOUNTER,TimerAClockCycles,INTERRUPT_MFP_TIMERA);
                    460: }
                    461: 
                    462: 
1.1.1.2 ! root      463: /*-----------------------------------------------------------------------*/
1.1       root      464: /*
                    465:   Start Timer B
                    466:   (This does not start the EventCount mode time as this is taken care of by the HBL)
                    467: */
                    468: void MFP_StartTimerB(void)
                    469: {
                    470:   TimerBClockCycles = MFP_StartTimer_AB(MFP_TBCR,MFP_TBDR,INTERRUPT_MFP_TIMERB,TRUE);
                    471: }
                    472: 
                    473: 
1.1.1.2 ! root      474: /*-----------------------------------------------------------------------*/
1.1       root      475: /*
                    476:   Read Timer B
                    477: */
                    478: void MFP_ReadTimerB(void)
                    479: {
                    480:   MFP_TB_MAINCOUNTER = MFP_ReadTimer_AB(MFP_TBCR,MFP_TB_MAINCOUNTER,TimerBClockCycles,INTERRUPT_MFP_TIMERB);
                    481: }
                    482: 
                    483: 
1.1.1.2 ! root      484: /*-----------------------------------------------------------------------*/
1.1       root      485: /*
                    486:   Start Timer C
                    487: */
                    488: void MFP_StartTimerC(void)
                    489: {
                    490:   TimerCClockCycles = MFP_StartTimer_CD(MFP_TCDCR>>4,MFP_TCDR,INTERRUPT_MFP_TIMERC,TRUE);
                    491: }
                    492: 
                    493: 
1.1.1.2 ! root      494: /*-----------------------------------------------------------------------*/
1.1       root      495: /*
                    496:   Read Timer C
                    497: */
                    498: void MFP_ReadTimerC(void)
                    499: {
                    500:   MFP_TC_MAINCOUNTER = MFP_ReadTimerCD(MFP_TCDCR>>4,MFP_TCDR,MFP_TC_MAINCOUNTER,TimerCClockCycles,INTERRUPT_MFP_TIMERC);
                    501: }
                    502: 
                    503: 
1.1.1.2 ! root      504: /*-----------------------------------------------------------------------*/
1.1       root      505: /*
                    506:   Start Timer D
                    507: */
                    508: void MFP_StartTimerD(void)
                    509: {
                    510:   TimerDClockCycles = MFP_StartTimer_CD(MFP_TCDCR,MFP_TDDR,INTERRUPT_MFP_TIMERD,TRUE);
                    511: }
                    512: 
                    513: 
1.1.1.2 ! root      514: /*-----------------------------------------------------------------------*/
1.1       root      515: /*
                    516:   Read Timer D
                    517: */
                    518: void MFP_ReadTimerD(void)
                    519: {
                    520:   MFP_TD_MAINCOUNTER = MFP_ReadTimerCD(MFP_TCDCR,MFP_TDDR,MFP_TC_MAINCOUNTER,TimerDClockCycles,INTERRUPT_MFP_TIMERD);
                    521: }
                    522: 
                    523: 
1.1.1.2 ! root      524: /*-----------------------------------------------------------------------*/
1.1       root      525: /*
                    526:   Handle Timer A Interrupt
                    527: */
                    528: void MFP_InterruptHandler_TimerA(void)
                    529: {
1.1.1.2 ! root      530:   /* Remove this interrupt from list and re-order */
1.1       root      531:   Int_AcknowledgeInterrupt();
                    532: 
1.1.1.2 ! root      533:   /* Acknowledge in MFP circuit, pass bit,enable,pending */
        !           534:   if ((MFP_TACR&0xf)!=0)                /* Is timer OK? */
1.1       root      535:     MFP_InputOnChannel(MFP_TIMER_A_BIT,MFP_IERA,&MFP_IPRA);
                    536: 
1.1.1.2 ! root      537:   /* Start next interrupt, if need one - from current cycle count */
1.1       root      538:   TimerAClockCycles = MFP_StartTimer_AB(MFP_TACR,MFP_TADR,INTERRUPT_MFP_TIMERA,FALSE);
                    539: }
                    540: 
                    541: 
1.1.1.2 ! root      542: /*-----------------------------------------------------------------------*/
1.1       root      543: /*
                    544:   Handle Timer B Interrupt
                    545: */
                    546: void MFP_InterruptHandler_TimerB(void)
                    547: {
1.1.1.2 ! root      548:   /* Remove this interrupt from list and re-order */
1.1       root      549:   Int_AcknowledgeInterrupt();
                    550: 
1.1.1.2 ! root      551:   /* Acknowledge in MFP circuit, pass bit, enable, pending */
        !           552:   if ((MFP_TBCR&0xf)!=0)                /* Is timer OK? */
1.1       root      553:     MFP_InputOnChannel(MFP_TIMER_B_BIT,MFP_IERA,&MFP_IPRA);
                    554: 
1.1.1.2 ! root      555:   /* Start next interrupt, if need one - from current cycle count */
1.1       root      556:   TimerBClockCycles = MFP_StartTimer_AB(MFP_TBCR,MFP_TBDR,INTERRUPT_MFP_TIMERB,FALSE);
                    557: }
                    558: 
                    559: 
1.1.1.2 ! root      560: /*-----------------------------------------------------------------------*/
1.1       root      561: /*
                    562:   Handle Timer C Interrupt
                    563: */
                    564: void MFP_InterruptHandler_TimerC(void)
                    565: {
1.1.1.2 ! root      566:   /* Remove this interrupt from list and re-order */
1.1       root      567:   Int_AcknowledgeInterrupt();
                    568: 
1.1.1.2 ! root      569:   /* Acknowledge in MFP circuit, pass bit, enable, pending */
        !           570:   if ((MFP_TCDCR&0x70)!=0)              /* Is timer OK? */
1.1       root      571:     MFP_InputOnChannel(MFP_TIMER_C_BIT,MFP_IERB,&MFP_IPRB);
                    572: 
1.1.1.2 ! root      573:   /* Start next interrupt, if need one - from current cycle count */
1.1       root      574:   TimerCClockCycles = MFP_StartTimer_CD(MFP_TCDCR>>4,MFP_TCDR,INTERRUPT_MFP_TIMERC,FALSE);
                    575: }
                    576: 
                    577: 
1.1.1.2 ! root      578: /*-----------------------------------------------------------------------*/
1.1       root      579: /*
                    580:   Handle Timer D Interrupt
                    581: */
                    582: void MFP_InterruptHandler_TimerD(void)
                    583: {
1.1.1.2 ! root      584:   /* Remove this interrupt from list and re-order */
1.1       root      585:   Int_AcknowledgeInterrupt();
                    586: 
1.1.1.2 ! root      587:   /* Acknowledge in MFP circuit, pass bit, enable, pending */
        !           588:   if ((MFP_TCDCR&0x07)!=0)              /* Is timer OK? */
1.1       root      589:     MFP_InputOnChannel(MFP_TIMER_D_BIT,MFP_IERB,&MFP_IPRB);
                    590: 
1.1.1.2 ! root      591:   /* Start next interrupt, if need one - from current cycle count */
1.1       root      592:   TimerDClockCycles = MFP_StartTimer_CD(MFP_TCDCR,MFP_TDDR,INTERRUPT_MFP_TIMERD,FALSE);
                    593: }
                    594: 

unix.superglobalmegacorp.com

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