/************************************************************************************ * utilities.h * * synopsis: Function prototypes and #defines for general purpose utility routines * and macros. ************************************************************************************/ #ifndef UTILITIES #define UTILITIES #include "processor.h" //Booleans: #undef TRUE #undef FALSE #undef true #undef false #define TRUE 1 #define FALSE 0 #define true 1 #define false 0 /* The backslash MUST be the last character on the line, or an odd compile error will result */ /* timing macros: delta t & delay in tenths of microseconds */ #if ( (defined(I_AM_MASTER_DSP))||((defined(REV_B))||(defined(REV_C))) ) #define delta_t(t0_) ((TIMER_getCount(timer1) - (t0_)) >> 2) #define delay(x) { \ UINT32 delay_t0; \ delay_t0 = TIMER_getCount(timer1); \ while( ((TIMER_getCount(timer1) - delay_t0) >> 2) < (x)); \ } /* Rev. E RODs have a bug in the silicon when using the timers: if the period is set to the maximum (0xffffffff), and the timer count is greater than ~0x90000000, then the DSP lapses into a state where it stalls for up to 600 micro-seconds on certain function calls. Using a smaller period in the timer prevents this, but means that we must use an inlined function for delta_t instead of a macro since if it wraps the subtraction will no longer automatically handle it (delay is made into an inlined function too). Additionally, the SDSPs run by default at 220 MHz, requiring different mathematics. The inlined functions need access to timer1; this is done using pointers to maintain transparency in the rest of the program. */ #elif (defined(REV_E)) static inline UINT32 delta_t(UINT32 t0); static inline void delay(UINT32 x); #if 0 static inline UINT32 delta_t(UINT32 t0) { UINT32 t1, p1; t1= *((UINT32 *) 0x01980008); //timer 1 count p1= *((UINT32 *) 0x01980004); //timer 1 period if (t1 < t0) return ((t1 -t0 +p1)/5); else return ((t1 -t0)/5); } static inline void delay(UINT32 x) { UINT32 t0, t1, delta, p1; t0= *((UINT32 *) 0x01980008); //timer 1 count p1= *((UINT32 *) 0x01980004); //timer 1 period do { t1= *((UINT32 *) 0x01980008); if (t1 < t0) delta= ((t1 -t0 +p1)/5); else delta= ((t1 -t0)/5); } while (delta < x); } #else static inline UINT32 delta_t(UINT32 t0) { UINT32 t1, p1; t1= *((UINT32 *) 0x01980008); //timer 1 count p1= *((UINT32 *) 0x01980004); //timer 1 period /* Check to be sure that the two times are within the same period and correct t1 if they are not: */ if (t1 < t0) t1+= p1; t1-= t0; /* NOTE: These calculations will be innacurate running the SDSPs at 160 MHz! (220 MHz is the default running speed). At 220 MHz there are 220/4 or 55 clock ticks per us. On the MDSP there are 40 clock ticks per us, so returning the time in 10ths of a us is easy: divide by 4 (right shift by 2). Here, to return the time in the same manner (in 10ths of a us) reuires to divide by 5.5 which would be more expensive to do since there are then multiple conversions which would have to happen (the input & returned times are integer. A quick approximation (to within ~3%) is to return (3/16)*t1 or (1/4 -1/16)*t1: */ return (t1>>2) -(t1>>4); } static inline void delay(UINT32 x) { UINT32 t0, t1, delta, p1; t0= *((UINT32 *) 0x01980008); //timer 1 count p1= *((UINT32 *) 0x01980004); //timer 1 period do { t1= *((UINT32 *) 0x01980008); if (t1 < t0) t1+= p1; delta= (t1>>2) -(t1>>4); } while (delta < x); } #endif #endif /* led macros for quick timing calls */ #if defined(I_AM_MASTER_DSP) #define yellowLed_on (*((UINT32 *) 0x018c0024)|= 1); #define greenLed_on (*((UINT32 *) 0x01900024)|= 1); #define redLed_on (*((UINT32 *) 0x018c0024)|= 4); #define yellowLed_off (*((UINT32 *) 0x018c0024)&= ~1); #define greenLed_off (*((UINT32 *) 0x01900024)&= ~1); #define redLed_off (*((UINT32 *) 0x018c0024)&= ~4); #define yellowLed_toggle (*((UINT32 *) 0x018c0024)^= 1); #define greenLed_toggle (*((UINT32 *) 0x01900024)^= 1); #define redLed_toggle (*((UINT32 *) 0x018c0024)^= 4); #elif defined(I_AM_SLAVE_DSP) #define fsrp0_on (*((UINT32 *) 0x018c0024)|= 4); #define fsxp0_on (*((UINT32 *) 0x018c0024)|= 8); #define fsrp0_off (*((UINT32 *) 0x018c0024)&= ~4); #define fsxp0_off (*((UINT32 *) 0x018c0024)&= ~8); #define fsrp0_toggle (*((UINT32 *) 0x018c0024)^= 4); #define fsxp0_toggle (*((UINT32 *) 0x018c0024)^= 8); /* Rev. B & C RODs have the yellow LED attached to CLKXP1, while Rev. E RODs use external pin #7 as a GPI/O output to drive the LED. However, this is not modelled in the simulation, so the SP is used instead. The Rev. E SDSPs can also signal the MDSP by pulling ext. pin 6 low (drives the signal in the RCF high). Fot the Rev. B/C SDSPs, this signal sets a bit (6) in status reg. 0 (which MDSP polls frequently). */ #if (defined(REV_B)||defined(REV_C)||defined(SIM)) #define yellowLed_on (*((UINT32 *) 0x01900024)&= ~2); #define yellowLed_off (*((UINT32 *) 0x01900024)|= 2); #define yellowLed_toggle (*((UINT32 *) 0x01900024)^= 2); #define setMdspAttention(bit) { \ (*((UINT32 *) 0x80000008)|= (1<> bit) & 1) #define RST_VFLD(var,bit,wid) (var &= (FIELD_OFF(bit,wid))) #define ASGN_VFLD(var,bit,wid,val) \ (var = (RST_VFLD(var,bit,wid)) | (FIELD_VAL(bit,wid,val))) #define GET_VFLD(var,bit,wid) ((FIELD_MASK(bit,wid) & var) >> bit) /* Some of the macros below are essentially the same as those in the Texas * Instruments provided regs.h. The ones in this file should be used in DSP code * authored by the ROD group. If Texas Instruments changes their macro names for * some reason, the DSP code will not be affected. dpf */ #define CONTENTS(adr) (*((volatile UINT32 *)(adr))) #define READ_REG(adr) (CONTENTS(adr)) #define WRITE_REG(adr,val) (CONTENTS(adr) = (val)) #define SET_RBIT(adr,bit) (CONTENTS(adr) |= (1 << (bit))) #define RST_RBIT(adr,bit) (CONTENTS(adr) &= (~(1 << (bit)))) #define ASGN_RBIT(adr,bit,val) (CONTENTS(adr) = (RST_RBIT(adr,bit)) | (val<> bit) & 1) #define RST_RFLD(adr,bit,wid) (CONTENTS(adr) &= (FIELD_OFF(bit,wid))) #define GET_RFLD(adr,bit,wid) ((CONTENTS(adr) & FIELD_MASK(bit,wid)) >> bit) #define ASGN_RFLD(adr,bit,wid,val) (CONTENTS(adr) = \ (RST_RFLD(adr,bit,wid)) | (FIELD_VAL(bit,wid,val))) /* Contexts for waitRegister: */ #define CONTEXT_NULL 0 #define CONTEXT_TASK 1 #define CONTEXT_PRIM 2 #define CONTEXT_ALL 3 /* The copymem & setmem EDMA transfer complete codes. The only available method of monitoring the progress of an EDMA transfer is to allow an interrupt upon completion, and then in the interrupt check the TCC to decide what to do. */ //#define EDMA_SETMEM_ID 14 dpsf not true... //#define EDMA_COPYMEM_ID 15 #endif