static void __attribute__ ((optimize("-O3"))) refresh_screen(SDL_Surface *scr) // uses global line + vga_odd { uint16_t *dst = (uint16_t*)scr->pixels; draw_buffer = mybuffer1; graph_frame(); for (vga_line=0;vga_line<screen_height;vga_line++) { vga_odd=0; graph_line(); // using line, updating draw_buffer ... #ifdef VGA_SKIPLINE vga_odd=1; graph_line(); // a second time for SKIPLINE modes #endif // copy to screen at this position (cheating) uint16_t *src = (uint16_t*) draw_buffer; for (int i=0;i<screen_width;i++) *dst++= pixelconv(*src++); // swap lines buffers to simulate double line buffering draw_buffer = (draw_buffer == &mybuffer1[0] ) ? &mybuffer2[0] : &mybuffer1[0]; } }
static void refresh_screen() // uses global line + vga_odd { draw_buffer = mybuffer1; for (vga_line=0;vga_line<VGA_V_PIXELS;vga_line++) { #ifdef VGA_SKIPLINE vga_odd=0; graph_line(); // using line, updating draw_buffer ... vga_odd=1; graph_line(); // a second time for SKIPLINE modes #else graph_line(); // a second time for SKIPLINE modes #endif // swap lines buffers to simulate double line buffering draw_buffer = (draw_buffer == &mybuffer1[0] ) ? &mybuffer2[0] : &mybuffer1[0]; } for (;vga_line<VGA_V_PIXELS+VGA_V_SYNC;vga_line++) { #ifdef VGA_SKIPLINE vga_odd=0; graph_vsync(); // using line, updating draw_buffer ... vga_odd=1; graph_vsync(); // a second time for SKIPLINE modes #else graph_vsync(); // once #endif } }
static void refresh_screen() // uses global line + vga_odd { draw_buffer = mybuffer1; graph_frame(); for (vga_line=0;vga_line<screen_height;vga_line++) { vga_odd=0; graph_line(); // using line, updating draw_buffer ... #ifdef VGA_SKIPLINE vga_odd=1; graph_line(); // a second time for SKIPLINE modes #endif // swap lines buffers to simulate double line buffering draw_buffer = (draw_buffer == &mybuffer1[0] ) ? &mybuffer2[0] : &mybuffer1[0]; } }
static void __attribute__ ((optimize("-O3"))) refresh_screen (SDL_Surface *scr) // uses global line + vga_odd, scale two times { uint32_t * restrict dst = (uint32_t*)scr->pixels; // will render 2 pixels at a time horizontally draw_buffer = mybuffer1; // currently 16bit data for (vga_line=0;vga_line<screen_height;vga_line++) { #ifdef VGA_SKIPLINE vga_odd=0; graph_line(); // using line, updating draw_buffer ... #if VGA_BPP==8 expand_buffer(); #endif vga_odd=1; graph_line(); // a second time for SKIPLINE modes #if VGA_BPP==8 expand_buffer(); #endif #else graph_line(); #if VGA_BPP==8 expand_buffer(); #endif #endif // copy to screen at this position uint16_t *restrict src = (uint16_t*) draw_buffer; switch (scale) { case 1 : // copy to screen at this position (cheating) for (int i=0;i<screen_width;i++) *dst++= pixelconv32(*src++); break; case 2 : for (int i=0;i<screen_width;i++, dst+=2) { uint32_t pix = pixelconv32(*src++); *dst = pix; // blit line *(dst+1) = pix; // blit line *(dst+scr->pitch/sizeof(uint32_t))=pix; // also next line *(dst+scr->pitch/sizeof(uint32_t)+1)=pix; // also next line } dst += scr->pitch/sizeof(uint32_t); // we already drew the line after, skip it break; } // swap lines buffers to simulate double line buffering draw_buffer = ( draw_buffer == &mybuffer1[0] ) ? &mybuffer2[0] : &mybuffer1[0]; } for (;vga_line<screen_height+VSYNC_LINES;vga_line++) { #ifdef VGA_SKIPLINE vga_odd=0; graph_vsync(); // using line, updating draw_buffer ... vga_odd=1; graph_vsync(); // a second time for SKIPLINE modes #else graph_vsync(); // once #endif } }
// HSYNC interrupt handler void __attribute__ ((used)) TIM3_IRQHandler(void) // attribute used neded if called from ASM { TIM3->SR=0; // clear status // only double-line modes on micro vga_line+=vga_odd; vga_odd=1-vga_odd; // starting from line #1, line #0 already in drawbuffer if (vga_line < VGA_V_PIXELS) { if (!vga_odd) // swap display & draw buffers, effectively draws line-1. does not swap on odd lines if not needed { uint8_t *t; t=display_buffer; display_buffer = draw_buffer; draw_buffer = t; } if (vga_line>0) // This doesn't happen only when we just set up vga_line=0 and now vga_odd=1 prepare_pixel_DMA(); // will be triggered after #ifdef PROFILE line_time = DWT->CYCCNT; // reset the perf counter #endif graph_line(); // Game graph callback ! draw_buffer[0]=0; #ifdef PROFILE line_time = DWT->CYCCNT - line_time; // read the counter line_time /= VGA_PIXELCLOCK; // scale it to screen width // plot from 0 to VGA_V_PIXELS a green or red element uint8_t c=0b11001; //green if (line_time>VGA_H_PIXELS) // start over but red { line_time-=VGA_H_PIXELS; c=0b11100000; // red } draw_buffer[line_time-1]=0; draw_buffer[line_time]=c; draw_buffer[line_time+1]=0; #endif } else { graph_vsync(); // always call, odd or not if (!vga_odd) // only once { if (vga_line== VGA_V_PIXELS) { vga_frame++; // new frame sync now. } else if (vga_line==VGA_V_PIXELS+1) { #ifndef NO_AUDIO audio_frame(); #endif } else if (vga_line==VGA_V_PIXELS+VGA_V_FRONTPORCH+1) { GPIOB->BSRRH |= GPIO_BSRR_BS_15; // lower VSync line } else if(vga_line==VGA_V_PIXELS+1+VGA_V_FRONTPORCH+VGA_V_SYNC) { GPIOB->BSRRL |= GPIO_BSRR_BS_15; // raise VSync line } } if(vga_line==VGA_V_PIXELS+VGA_V_FRONTPORCH+VGA_V_SYNC+VGA_V_BACKPORCH+1) { vga_line=0; graph_line(); // first line next frame! } } // audio generation each vga line #ifndef NO_AUDIO audio_line(); #endif }
void __attribute__ ((used)) TIM5_IRQHandler() // Hsync Handler { TIM5->SR=0; // clear pending interrupts #ifdef VGA_SKIPLINE vga_line+=vga_odd; vga_odd=1-vga_odd; #else vga_line++; #endif // starting from line #1, line #0 already in drawbuffer if (vga_line < VGA_V_PIXELS) { #ifdef VGA_SKIPLINE if (!vga_odd) #endif // swap display & draw buffers, effectively draws line-1 { pixel_t *t; t=display_buffer; display_buffer = draw_buffer; draw_buffer = t; } #ifdef VGA_SKIPLINE if (vga_line>0) // This doesn't happens only when we just set up vga_line=0 and now vga_odd=1 #endif prepare_pixel_DMA(); // will be triggered #ifdef PROFILE line_time = DWT->CYCCNT; // reset the perf counter #endif graph_line(); // Game callback ! #if VGA_BPP==8 expand_drawbuffer(); #endif #ifdef PROFILE line_time = DWT->CYCCNT - line_time; // read the counter line_time /= VGA_PIXELCLOCK; // scale it to screen width // plot from 0 to VGA_V_PIXELS a green or red element uint16_t c=0b1111100000; //green if (line_time>VGA_H_PIXELS) // start over but red { line_time-=VGA_H_PIXELS; c=0b111110000000000; // red } draw_buffer[line_time-1]=0; draw_buffer[line_time]=c; draw_buffer[line_time+1]=0; #endif } else { graph_vsync(); // always call, odd or not if (!vga_odd) { if (vga_line == VGA_V_PIXELS) { vga_frame++; // new frame sync starts just at vsync. } if (vga_line==VGA_V_PIXELS+VGA_V_FRONTPORCH+1) { GPIOA->BSRRH |= GPIO_BSRR_BS_0; // raise VSync line } else if(vga_line==VGA_V_PIXELS+1+VGA_V_FRONTPORCH+VGA_V_SYNC) { GPIOA->BSRRL |= GPIO_BSRR_BS_0; // raise VSync line } else if(vga_line==VGA_V_PIXELS+VGA_V_FRONTPORCH+VGA_V_SYNC+VGA_V_BACKPORCH) { vga_line=0; // we're on vga_odd=0, next time will be a vga_odd=1 and vga_line=0 graph_line(); // first line next frame! } } } }