|
|
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.5 ! root 17: static char rcsid[] = "Hatari $Id: mfp.c,v 1.5 2003/03/08 11:29:53 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: } 429: 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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.