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); }
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 } }
/************************************************************************************************** Initialise the video components ***************************************************************************************************/ void initVideo(void) { AutoLineWrap = 1; // test if there is a monitor plugged into the VGA connector CNPUASET = (1 << 4); // set a pullup on the video output pin uSec(300); // allow it to settle //vga = !PORTAbits.RA4; // the pin will be pulled low if the monitor is there CNPUACLR = (1 << 4); //////////////////////////// // setup SPI2 which is the video generator. the output of this module is a stream of bits which are the pixels in a horiz scan line //if(vga) PPSOutput(3, RPA4, SDO2); // B5 is the video out for VGA [color]] //else // PPSOutput(3, RPB2, SDO2); // B2 is the video out for composite PPSInput(4, SS2, RPB9); // B9 is the framing input [horizontal synch] #define P_VIDEO_SPI 2 // the SPI peripheral used for video #define P_SPI_INPUT SPI2BUF // input buffer for the SPI peripheral #define P_SPI_INTERRUPT _SPI2_TX_IRQ // interrupt used by the SPI peripheral when it needs more data //////////////////////////// // the horizontal sync uses Timer 3 and Output Compare 3 to generate the pulse and interrupt level 7 PPSOutput(4, RPB14, OC3); // B14 is the horizontal sync output (ie, the output from OC3) #define P_VID_OC_OPEN OpenOC3 // the function used to open the output compare #define P_VID_OC_REG OC3R // the output compare register //////////////////////////// // the vertical sync uses B13 TRISBCLR = (1<<13); // Vert sync output used by VGA #define P_VERT_SET_HI LATBSET = (1 << 13) // set vert sync hi #define P_VERT_SET_LO LATBCLR = (1 << 13) // set vert sync lo // calculate the paramaters for each video mode and setup Timer 3 to generate the horiz synch and interrupt on its leading edge //if(vga) { // set up for VGA output HRes = VGA_HRES; // HRes is the number of horiz pixels to use HBuf = VGA_HBUFF * 32; // HBuf is the horiz buffer size (in pixels) ConfigBuffers(Option[O_LINES24]); // setup the buffer pointers and VBuf, VRes VC[0] = VGA_VSYNC_N; // setup the table used to count lines VC[1] = VGA_POSTEQ_N; P_VID_OC_OPEN(OC_ON | OC_TIMER3_SRC | OC_CONTINUE_PULSE, 0, VGA_HSYNC_T); // enable the output compare which is used to time the width of the horiz sync pulse OpenTimer3( T3_ON | T3_PS_1_1 | T3_SOURCE_INT, VGA_LINE_T-1); // enable timer 3 and set to the horizontal scanning frequency //} /*else if(Option[O_PAL]) { // this is for the PAL composite output and is the same as VGA with timing differences VBuf = VRes = PAL_VRES; HRes = PAL_HRES; HBuf = PAL_HBUFF * 32; // HBuf is the horiz buffer size (in pixels) ConfigBuffers(0); SvSyncT = PAL_LINE_T - C_HSYNC_T; VC[0] = C_VSYNC_N; VC[1] = PAL_POSTEQ_N; VC[2] = PAL_VRES; VC[3] = PAL_PREEQ_N; P_VID_OC_OPEN(OC_ON | OC_TIMER3_SRC | OC_CONTINUE_PULSE, 0, C_HSYNC_T); // enable the output compare which is used to time the width of the horiz sync pulse OpenTimer3(T3_ON | T3_PS_1_1 | T3_SOURCE_INT, PAL_LINE_T-1); // enable timer 3 and set to the horizontal scanning frequency } */ /* else { // this is for the NTSC composite output and is similar again VBuf = VRes = NTSC_VRES; HRes = NTSC_HRES; HBuf = NTSC_HBUFF * 32; // HBuf is the horiz buffer size (in pixels) ConfigBuffers(0); SvSyncT = NTSC_LINE_T - C_HSYNC_T; VC[0] = C_VSYNC_N; VC[1] = NTSC_POSTEQ_N; VC[2] = NTSC_VRES; VC[3] = NTSC_PREEQ_N; P_VID_OC_OPEN(OC_ON | OC_TIMER3_SRC | OC_CONTINUE_PULSE, 0, C_HSYNC_T); // enable the output compare which is used to time the width of the horiz sync pulse OpenTimer3(T3_ON | T3_PS_1_1 | T3_SOURCE_INT, NTSC_LINE_T-1); // enable timer 3 and set to the horizontal scanning frequency } */ // set priority level 7 for the timer 3 interrupt (horiz synch) and enable it mT3SetIntPriority(7); mT3IntEnable(1); // initialise the state machine and set the count so that the first interrupt will increment the state VState = SV_PREEQ; VCount = 1; // setup the SPI channel then DMA channel which will copy the memory bitmap buffer to the SPI channel //if(vga) { // open the SPI in framing mode. Note that SPI_OPEN_DISSDI will disable the input (which we do not need) SpiChnOpen(P_VIDEO_SPI, SPICON_ON | SPICON_MSTEN | SPICON_MODE32 | SPICON_FRMEN | SPICON_FRMSYNC | SPICON_FRMPOL | SPI_OPEN_DISSDI, VGA_PIX_T); SPI2CON2 = (1<<9) | (1<<8); // instruct the SPI module to ignore any errors that might occur DmaChnOpen(1, 1, DMA_OPEN_DEFAULT); // setup DMA 1 to send data to SPI channel 2 DmaChnSetEventControl(1, DMA_EV_START_IRQ_EN | DMA_EV_START_IRQ(P_SPI_INTERRUPT)); DmaChnSetTxfer(1, (void*)VideoBuf, (void *)&P_SPI_INPUT, HBuf/8, 4, 4); //} /* else { SpiChnOpen(P_VIDEO_SPI, SPICON_ON | SPICON_MSTEN | SPICON_MODE32 | SPICON_FRMEN | SPICON_FRMSYNC | SPICON_FRMPOL | SPI_OPEN_DISSDI, C_PIX_T); SPI2CON2 = (1<<9) | (1<<8); // instruct the SPI module to ignore any errors that might occur DmaChnOpen(1, 1, DMA_OPEN_DEFAULT); // setup DMA 1 is the blank padding at the start of a scan line DmaChnSetEventControl(1, DMA_EV_START_IRQ_EN | DMA_EV_START_IRQ(P_SPI_INTERRUPT)); DmaChnSetTxfer(1, (void*)zero, (void *)&P_SPI_INPUT, C_BLANKPAD, 4, 4); DmaChnOpen( 0, 0, DMA_OPEN_DEFAULT); // setup DMA 0 to pump the data from the graphics buffer to the SPI peripheral DmaChnSetEventControl(0, DMA_EV_START_IRQ_EN | DMA_EV_START_IRQ(P_SPI_INTERRUPT)); DmaChnSetTxfer(0, (void*)VideoBuf, (void *)&P_SPI_INPUT, HBuf/8 + 6, 4, 4); DmaChnSetControlFlags(0, DMA_CTL_CHAIN_EN | DMA_CTL_CHAIN_DIR); // chain DMA 0 so that it will start on completion of the DMA 1 transfer } */ }
// === Main ====================================================== void main(void) { //SYSTEMConfigPerformance(PBCLK); ANSELA = 0; ANSELB = 0; // === config threads ========== // turns OFF UART support and debugger pin, unless defines are set PT_setup(); // === setup system wide interrupts ======== INTEnableSystemMultiVectoredInt(); CloseADC10(); // ensure the ADC is off before setting the configuration #define PARAM1 ADC_FORMAT_INTG16 | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_OFF // // define setup parameters for OpenADC10 // ADC ref external | disable offset test | disable scan mode | do 1 sample | use single buf | alternate mode off #define PARAM2 ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_OFF | ADC_SAMPLES_PER_INT_1 | ADC_ALT_BUF_OFF | ADC_ALT_INPUT_OFF // Define setup parameters for OpenADC10 // use peripherial bus clock | set sample time | set ADC clock divider // ADC_CONV_CLK_Tcy2 means divide CLK_PB by 2 (max speed) // ADC_SAMPLE_TIME_5 seems to work with a source resistance < 1kohm #define PARAM3 ADC_CONV_CLK_PB | ADC_SAMPLE_TIME_5 | ADC_CONV_CLK_Tcy2 //ADC_SAMPLE_TIME_15| ADC_CONV_CLK_Tcy2 // define setup parameters for OpenADC10 // set AN11 and as analog inputs #define PARAM4 ENABLE_AN11_ANA // pin 24 // define setup parameters for OpenADC10 // do not assign channels to scan #define PARAM5 SKIP_SCAN_ALL // use ground as neg ref for A | use AN11 for input A // configure to sample AN11 SetChanADC10( ADC_CH0_NEG_SAMPLEA_NVREF | ADC_CH0_POS_SAMPLEA_AN11 ); // configure to sample AN4 OpenADC10( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ); // configure ADC using the parameters defined above EnableADC10(); // Enable the ADC OpenTimer2(T2_ON | T2_SOURCE_INT | T2_PS_1_1, 400); mPORTAClearBits(BIT_0 ); //Clear bits to ensure light is off. mPORTASetPinsDigitalOut(BIT_0 ); //Set port as output int CVRCON_setup; // set up the Vref pin and use as a DAC // enable module| eanble output | use low range output | use internal reference | desired step CVREFOpen( CVREF_ENABLE | CVREF_OUTPUT_ENABLE | CVREF_RANGE_LOW | CVREF_SOURCE_AVDD | CVREF_STEP_0 ); // And read back setup from CVRCON for speed later // 0x8060 is enabled with output enabled, Vdd ref, and 0-0.6(Vdd) range CVRCON_setup = CVRCON; //CVRCON = 0x8060 // Open the desired DMA channel. // We enable the AUTO option, we'll keep repeating the same 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 // Setting the last parameter to one makes the DMA output one byte/interrut //DmaChnSetTxfer(dmaChn, sine_table, (void*) &CVRCON, sizeof(sine_table), 1, 1); // set the transfer event control: what event is to start the DMA transfer // In this case, timer2 DmaChnSetEventControl(dmaChn, DMA_EV_START_IRQ(_TIMER_2_IRQ)); // once we configured the DMA channel we can enable it // now it's ready and waiting for an event to occur... //DmaChnEnable(dmaChn); int i; for(i=0; i <256; i++){ ball_scored[i] = 0x60|((unsigned char)((float)255/2*(sin(6.2832*(((float)i)/(float)256))+1))) ; //ball_lost[i] // game_over } // init the threads PT_INIT(&pt_timer); PT_INIT(&pt_adc); PT_INIT(&pt_launch); PT_INIT(&pt_anim); // init the display tft_init_hw(); tft_begin(); tft_fillScreen(ILI9340_BLACK); tft_setRotation(1); // Use tft_setRotation(1) for 320x240 while (1){ PT_SCHEDULE(protothread_timer(&pt_timer)); PT_SCHEDULE(protothread_adc(&pt_adc)); PT_SCHEDULE(protothread_launch_balls(&pt_launch)); PT_SCHEDULE(protothread_anim_balls(&pt_anim)); } } // main
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; }