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

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

unix.superglobalmegacorp.com

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