static void init_dma() { /* open and configure the DMA channels DMA 0 is for SPI -> buffer DMA 1 is for buffer -> SPI */ DmaChnOpen(DMA_CHANNEL0, DMA_CHN_PRI3, DMA_OPEN_AUTO); DmaChnOpen(DMA_CHANNEL1, DMA_CHN_PRI3, DMA_OPEN_AUTO); /* DMA channels trigger on SPI RX/TX */ DmaChnSetEventControl(DMA_CHANNEL0, DMA_EV_START_IRQ(_SPI2_RX_IRQ)); DmaChnSetEventControl(DMA_CHANNEL1, DMA_EV_START_IRQ(_SPI2_TX_IRQ)); /* transfer 8bits at a time */ DmaChnSetTxfer(DMA_CHANNEL0, (void *)&SPI2BUF, (void *)rxBuf, 1, SPIBUFSIZE, 1); DmaChnSetTxfer(DMA_CHANNEL1, (void *)txBuf, (void *)&SPI2BUF, SPIBUFSIZE, 1, 1); /* start DMA 0 */ DmaChnEnable(0); DmaChnEnable(1); }
/************************************************************************************************** Timer 3 interrupt. Used to generate the horiz and vert sync pulse under control of the state machine ***************************************************************************************************/ void __ISR(_TIMER_3_VECTOR, IPL7SOFT) T3Interrupt(void) { static int *VPtr; static unsigned char AlternateField = 0; // used to count odd/even fields in composite video static unsigned int LineCnt = 1; switch ( VState) { // vertical state machine case SV_PREEQ: // 0 // prepare for the new horizontal line VPtr = VideoBuf; LineCnt = 1; break; case SV_SYNC: // 1 /* if(!vga) { // if the video is composite P_VID_OC_REG = SvSyncT; // start the vertical sync pulse for composite VCount += AlternateField; // in composite video the alternative field has one extra line AlternateField ^= 1; } */ P_VERT_SET_LO; // start the vertical sync pulse for vga break; case SV_POSTEQ: // 2 //if(!vga) P_VID_OC_REG = C_HSYNC_T; // end of the vertical sync pulse for composite P_VERT_SET_HI; // end of the vertical sync pulse for vga break; case SV_LINE: // 3 P_SPI_INPUT = 0; // preload the SPI with 4 zero bytes to pad the start of the video //if(vga) DCH1SSA = KVA_TO_PA((void*) (VPtr)); // update the DMA1 source address (DMA1 is used for VGA data) //else // DCH0SSA = KVA_TO_PA((void*) (VPtr - 1)); // update the DMA0 source address (DMA0 is used for composite data) if(!Display24Lines || LineCnt++ % 3) VPtr += HBuf/32; // move the pointer to the start of the next line DmaChnEnable(1); // arm the DMA transfer break; } if (--VCount == 0) { // count down the number of lines VCount = VC[VState&3]; // set the new count VState = VS[VState&3]; // and advance the state machine } mT3ClearIntFlag(); // clear the interrupt flag }
int main(void) { int dmaChn=0; // the DMA channel to use // first let us set the LED I/O ports as digital outputs mPORTASetPinsDigitalOut(0xff); mPORTAClearBits(0xff); // start with all LED's turned off // Open the desired DMA channel. // We enable the AUTO option, we'll keep repeating the sam transfer over and over. DmaChnOpen(dmaChn, 0, DMA_OPEN_AUTO); // set the transfer parameters: source & destination address, source & destination size, number of bytes per event DmaChnSetTxfer(dmaChn, LED_pattern, (void*)&LATA, sizeof(LED_pattern), 1, 1); // set the transfer event control: what event is to start the DMA transfer DmaChnSetEventControl(dmaChn, DMA_EV_START_IRQ(_TIMER_3_IRQ)); // once we configured the DMA channel we can enable it // now it's ready and waiting for an event to occur... DmaChnEnable(dmaChn); // now use the 32 bit timer to generate an interrupt at the desired LED_BLINK_RATE { int pbFreq=SYS_FREQ/(1<<mOSCGetPBDIV()); // get the PB frequency the timer is running at // use 1:1 prescaler for max resolution, the PB clock OpenTimer23(T2_ON | T2_SOURCE_INT | T2_PS_1_1, (pbFreq/1000)*LED_BLINK_RATE); } while(1) { // do some other useful work } }
// === Animation Thread ============================================= static PT_THREAD (protothread_anim_balls(struct pt *pt)) { PT_BEGIN(pt); while(1) { PT_YIELD_TIME_msec(20); iterator = initial_ball; while(iterator != NULL) { iterator2 = iterator->next; tft_fillCircle(fix2int16(iterator->xc), fix2int16(iterator->yc), RADIUS, ILI9340_BLACK); (iterator->xc) = (iterator->xc) + multfix16((iterator->vxc), drag); (iterator->yc) = (iterator->yc) + multfix16((iterator->vyc), drag); tft_fillCircle(fix2int16(iterator->xc), fix2int16(iterator->yc), RADIUS, ILI9340_WHITE); while(iterator2 != NULL) { if (balls_collide(iterator, iterator2) && (iterator->hit_counter <= 0) && (iterator2->hit_counter <= 0)) computeVelocityChange(iterator, iterator2); else if (balls_collide(iterator, iterator2)) { iterator->hit_counter = COUNTER; iterator2->hit_counter = COUNTER; } else{ iterator->hit_counter--; iterator2->hit_counter--; } iterator2 = iterator2->next; } // If the ball hits the paddle if ((myPaddle->xc+DIAMETER >= fix2int16(iterator->xc)) && (myPaddle->yc <= fix2int16(iterator->yc)) && ((myPaddle->yc+PADDLE_LEN) >= fix2int16(iterator->yc))){ iterator->vxc = -(iterator->vxc); iterator->vyc = iterator->vyc + multfix16(int2fix16(myPaddle->vyc),pdrag); //DmaChnSetTxfer(dmaChn, sine_table2, (void*)&CVRCON, sizeof(sine_table2), 1, 1); //DmaChnEnable(dmaChn); //PT_YIELD_TIME_msec(2); //DmaChnDisable(dmaChn); } // Else the ball went off the right edge else if (myPaddle->xc+DIAMETER >= fix2int16(iterator->xc)) { DmaChnSetTxfer(dmaChn, ball_scored, (void*)&CVRCON, sizeof(ball_scored), 1, 1); DmaChnEnable(dmaChn); PT_YIELD_TIME_msec(2); DmaChnDisable(dmaChn); deleteBall(iterator); score--; } // Calculate top bin else if ((iterator->xc) <= int2fix16(250+2) && iterator->xc >= int2fix16(175-2) && iterator->yc <= int2fix16(25+9)) { deleteBall(iterator); score++;} // Calculate bottom bin else if ((iterator->xc) <= int2fix16(250+2) && iterator->xc >= int2fix16(175-2) && iterator->yc >= int2fix16(233-2)) { deleteBall(iterator); score++;} // Bounce off right wall else if ((iterator->xc) >= int2fix16(315)) (iterator->vxc) = -(iterator->vxc); // Bounce off top or bottom wall else if ((iterator->yc) <= int2fix16(25) ||(iterator->yc) >= int2fix16(233)) (iterator->vyc) = -(iterator->vyc); iterator = iterator->next; } } // END WHILE(1) PT_END(pt); } // animation thread
//======================= Refresh ========================= // //Does Ball calculations and Draws the necessary elements on the screen static PT_THREAD (protothread_refresh(struct pt *pt)) { PT_BEGIN(pt); PT_YIELD_TIME_msec(100); //waits for the scoreboard to be set up while(1) { while (timeElapsed <=60) { PT_YIELD_TIME_msec(10); DmaChnDisable(dmaChn); DmaChnDisable(dmaChn2); //Generates a new ball at a given interval if(ballgen >= 10) { int troll1 = -((rand()) % 2)-1; int troll2 = ((rand()) % 6) - 3; struct Ball *temp = Ball_create(320,120,troll1,troll2,(numBalls+1)*500,0,NULL); temp->b = head; head = temp; ballgen = 0; numBalls++; } else ballgen ++; //collision calculations struct Ball *ti = head; struct Ball *tj = NULL; if(ti != NULL) tj = ti->b; while(ti !=NULL){ //Calculates the collisions between every ball while(tj != NULL) { int rij_x = ti->xpos - tj->xpos; int rij_y = ti->ypos - tj->ypos; int mag_rij = pow(rij_x,2) + pow(rij_y,2); //Checks if ti and tj are not pointing to the same ball, //If they close enough for a collision and there is no collision //delay. if( ti->delay + tj->delay == 0 && mag_rij < dist) { int vij_x = ti->xvel - tj->xvel; int vij_y = ti->yvel - tj->yvel; if (mag_rij==0) { mag_rij=dist; } int deltaVi_x = (int)((-1*(rij_x) * ((((rij_x * vij_x)+ (rij_y*vij_y)) << 7)/mag_rij)) >> 7); int deltaVi_y = (int)((-1*(rij_y) * ((((rij_x * vij_x)+ (rij_y*vij_y)) << 7)/mag_rij)) >> 7); /* tft_fillRoundRect(0,30, 320, 14, 1, ILI9340_BLACK);// x,y,w,h,radius,color tft_setCursor(0, 30); tft_setTextColor(ILI9340_WHITE); tft_setTextSize(2); sprintf(buffer,"%d:%d", (-1*(rij_x)/128 * (128*((rij_x * vij_x)+ (rij_y*vij_y))/mag_rij)), mag_rij); tft_writeString(buffer); */ //Updates the velocity ti->xvel = ti->xvel + deltaVi_x; ti->yvel = ti->yvel + deltaVi_y; tj->xvel = tj->xvel - deltaVi_x; tj->yvel = tj->yvel - deltaVi_y; ti->delay = delay_master; tj->delay = delay_master; } tj = tj->b; } //checks for wall collisions if(ti->xpos >= 320*scale || ti->xpos <= 0) ti->xvel = -1*ti->xvel; if(ti->ypos >= 240*scale || ti->ypos <= 35*scale) { ti->yvel = -1*ti->yvel; if (ti->xpos > 120*scale && ti->xpos < 200*scale) { //check for catch bin ti->delay=-1; //set to -1 to indicate +1 point } } //calculates the drag if(ti->xvel > 0) ti->xvel = ti->xvel - ti->xvel/drag; else ti->xvel = ti->xvel + ti->xvel/drag; if(ti->yvel > 0) ti->yvel = ti->yvel - ti->yvel/drag; else ti->yvel = ti->yvel - ti->yvel/drag; // Check for paddle Collisions if(abs(paddle_xpos-ti->xpos/scale) <= ballradius && ti->delay == 0) if(ti->ypos/scale > paddle_ypos - half_paddle_length && ti->ypos/scale < paddle_ypos + half_paddle_length) { ti->xvel = -1*ti->xvel; ti->yvel = ti->yvel + paddle_drag*paddle_v; ti->delay=delay_master; } //Decrement the collide delay if(ti->delay > 0) ti->delay = ti->delay -1; //iterates through the next set ti = ti->b; if(ti != NULL) tj = ti->b; //removes the last element if the limit is reached if(numBalls > maxBalls && tj->b == NULL) { tft_fillCircle(tj->xpos/scale,tj->ypos/scale,ballradius,ILI9340_BLACK); //erases from the screen ti->b = NULL; numBalls--; score++; //free(tj); } } // Calculates position of the paddle and draw //TODO: Calculate paddle position tft_drawLine(paddle_xpos,paddle_ypos - half_paddle_length, paddle_xpos, paddle_ypos + half_paddle_length, ILI9340_BLACK); paddle_v=paddle_ypos; paddle_ypos=(adc_9*240)/1023; paddle_v=paddle_ypos-paddle_v; tft_drawLine(paddle_xpos,paddle_ypos - half_paddle_length, paddle_xpos, paddle_ypos + half_paddle_length, ILI9340_WHITE); // Now it calculates the new position ti = head; tj = head; while(ti != NULL){ //"Clears" the image of the last ball tft_fillCircle(ti->xpos/scale,ti->ypos/scale,ballradius,ILI9340_BLACK); //Updates the new position of the ball ti->xpos = ti->xpos + ti->xvel; ti->ypos = ti->ypos + ti->yvel; //ensures the positions are within bounds //If the pos is less than 0 then we remove it //delay must also not be -1 (ie >=0) if(ti->xpos > paddle_xpos && ti->delay != -1) { if(ti->xpos > 320*scale) ti->xpos = 320*scale; if(ti->ypos > 240*scale) ti->ypos = 240*scale; else if(ti->ypos < 35*scale) ti->ypos = 35*scale; if(ti->delay > 0) tft_fillCircle(ti->xpos/scale, ti->ypos/scale, ballradius, ILI9340_WHITE); else tft_fillCircle(ti->xpos/scale, ti->ypos/scale, ballradius, ti->color); } else { //REMOVES THE BALL IF IT CROSSES THE BOUNDARY if (ti->delay==-1) { //check if went into catch bins score++; DmaChnEnable(dmaChn2); } else { DmaChnEnable(dmaChn); score--; } if(ti == head) head = head->b; else tj->b = ti->b; numBalls--; //free(ti); } tj = ti;//what does this do? ti = ti->b; } frames ++; } tft_fillRoundRect(0,35, 320, 205, 1, ILI9340_BLACK);// x,y,w,h,radius,color DmaChnDisable(dmaChn); DmaChnDisable(dmaChn2); DmaChnEnable(dmaChn3); while (1) { tft_setCursor(20, 120); tft_setTextColor(ILI9340_WHITE); tft_setTextSize(4); sprintf(buffer,"Game Over!"); tft_writeString(buffer); } }
void ResetDevice(void) { DMACONbits.SUSPEND =1; //Suspend ALL DMA transfers BMXCONbits.BMXARB = 0x02; //Faster Refresh Rate BMXCONbits.BMXCHEDMA = 1; LCD_DC_TRIS =0; HSYNC_TRIS =0; LCD_CS_TRIS =0; VSYNC_TRIS =0; LCD_RESET_TRIS =0; BACKLIGHT_TRIS=0; DATA_ENABLE_TRIS=0; SRAM_TRIS =0; ADDR15_TRIS=0; ADDR16_TRIS=0; ADDR17_TRIS =0; ADDR18_TRIS =0; LCD_RESET =1; LCD_CS =1; LCD_DC =1; SRAM_CS =0; ADDR17 =0; ADDR18 =0; PIXELCLOCK_TRIS =0; #ifdef DISP_INV_LSHIFT PIXELCLOCK =1; #else PIXELCLOCK =0; #endif #if defined(USE_TCON_MODULE) GfxTconInit(); #endif // setup the PMP mPMPOpen(PMP_CONTROL, PMP_MODE, PMP_ADDRESS_LINES, PMP_INT_ON); PMADDR = 0x0000; // Open the desired DMA channel. DmaChnOpen(1, 0, DMA_OPEN_DEFAULT); // set the transfer event control: what event is to start the DMA transfer DmaChnSetEventControl(1, DMA_EV_START_IRQ(_TIMER_2_IRQ)); // set the transfer parameters: source & destination address, source & destination size, number of bytes per event #ifdef LCC_INTERNAL_MEMORY BACKLIGHT =0; //Turn Backlight on #ifdef USE_PALETTE DmaChnSetTxfer(1, &GraphicsFrame[0], (void*)&PMDIN, HBackPorch, 2, 2); #else DmaChnSetTxfer(1, &GraphicsFrame[0], (void*)&PMDIN, HBackPorch, 1, 2); #endif #else #if defined(GFX_USE_DISPLAY_PANEL_TFT_G240320LTSW_118W_E) BACKLIGHT =0; //Turn Backlight on DmaChnSetTxfer(1, (void*)&PMDIN ,&GraphicsFrame[0] , 1, HBackPorch, 2); #else BACKLIGHT =1; DmaChnSetTxfer(1, (void*)&PMDIN ,&GraphicsFrame[0] , 1, HBackPorch, 16); #endif #endif INTSetVectorPriority(INT_VECTOR_DMA(1), INT_PRIORITY_LEVEL_6); // set INT controller priority DmaChnSetEvEnableFlags(1, DMA_EV_BLOCK_DONE); // enable the transfer done interrupt, when all buffer transferred INTEnable(INT_SOURCE_DMA(1), INT_ENABLED); // enable the chn interrupt in the INT controller DCH1CONbits.CHPRI = 0b11; //DMA channel has highest priority // once we configured the DMA channel we can enable it DmaChnEnable(1); #ifdef LCC_INTERNAL_MEMORY #ifdef USE_PALETTE OpenTimer2(T2_ON | T2_SOURCE_INT | T2_PS_1_1, 70); //Start Timer #else OpenTimer2(T2_ON | T2_SOURCE_INT | T2_PS_1_1, 27); //Start Timer #endif #else //External Memory OpenTimer2(T2_ON | T2_SOURCE_INT | T2_PS_1_1, 2); //Start Timer #endif DMACONbits.SUSPEND = 0; #ifdef USE_DOUBLE_BUFFERING // initialize double buffering feature blInvalidateAll = 1; blDisplayUpdatePending = 0; NoOfInvalidatedRectangleAreas = 0; _drawbuffer = GFX_BUFFER1; SetActivePage(_drawbuffer); SwitchOnDoubleBuffering(); #endif //USE_DOUBLE_BUFFERING }
int main(void) { int ix; int errCnt=0; int dmaChn=0; // the DMA channel to use // Configure the device for maximum performance but do not change the PBDIV // Given the options, this function will change the flash wait states, RAM // wait state and enable prefetch cache but will not change the PBDIV. // The PBDIV value is already set via the pragma FPBDIV option above.. SYSTEMConfig(SYS_FREQ, SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE); // init the pseudo-random generator srand(ReadCoreTimer()); // fill the bufffers with some random data for(ix=0; ix<sizeof(srcBuff); ix++) { srcBuff[ix]=rand(); dstBuff[ix]=rand(); } // setup the PMP mPMPOpen(PMP_CONTROL, PMP_MODE,PMP_PORT_PINS ,PMP_INTERRUPT); // setup the external memory device address PMPSetAddress(PMP_EXT_ADDR); // Open the desired DMA channel. We use priority 0. DmaChnOpen(dmaChn, 0, DMA_OPEN_DEFAULT); // set the transfer event control: what event is to start the DMA transfer DmaChnSetEventControl(dmaChn, DMA_EV_START_IRQ(_PMP_IRQ)); // set the transfer parameters: source & destination address, source & destination size, number of bytes per event DmaChnSetTxfer(dmaChn, srcBuff, (void*)&PMDIN, sizeof(srcBuff), 2, 2); // once we configured the DMA channel we can enable it // now it's ready and waiting for an event to occur... DmaChnEnable(dmaChn); // force the first transfer, the PMP is quiet DmaChnForceTxfer(dmaChn); // wait for the transfer to be completed while(!(DmaChnGetEvFlags(dmaChn)&DMA_EV_BLOCK_DONE)) { // do some other useful work } // setup the external memory device address PMPSetAddress(PMP_EXT_ADDR); // flush the PMP data latches PMPMasterRead(); // set the transfer parameters: source & destination address, source & destination size, number of bytes per event DmaChnSetTxfer(dmaChn, (void*)&PMDIN, dstBuff, 2, sizeof(dstBuff), 2); DmaChnEnable(dmaChn); DmaChnForceTxfer(dmaChn); // wait for the transfer to be completed while(!(DmaChnGetEvFlags(dmaChn)&DMA_EV_BLOCK_DONE)) { // do some other useful work } // compare the transfer completed ok for(ix=0; ix<sizeof(srcBuff); ix++) { if(srcBuff[ix]!=dstBuff[ix]) { errCnt++; } } // close the PMP mPMPClose(); while(1); return errCnt; }