void InitializeVGAPort() { // Turn on peripherals. EnableAHB1PeripheralClock(RCC_AHB1ENR_GPIOBEN|RCC_AHB1ENR_GPIOEEN|RCC_AHB1ENR_DMA2EN); EnableAPB2PeripheralClock(RCC_APB2ENR_TIM8EN|RCC_APB2ENR_TIM9EN|RCC_APB2ENR_SYSCFGEN); // Configure DAC pins, and set to black. SetGPIOOutputMode(GPIOE,0xff00); SetGPIOPushPullOutput(GPIOE,0xff00); SetGPIOSpeed50MHz(GPIOE,0xff00); SetGPIOPullUpResistor(GPIOE,0xff00); GPIOE->BSRRH=0xff00; // Configure sync pins and drive them high. SetGPIOOutputMode(GPIOB,(1<<11)|(1<<12)); SetGPIOPushPullOutput(GPIOB,(1<<11)|(1<<12)); SetGPIOSpeed50MHz(GPIOB,(1<<11)|(1<<12)); SetGPIOPullUpResistor(GPIOB,(1<<11)|(1<<12)); GPIOB->BSRRL=(1<<11)|(1<<12); }
void InitializeVGA() { VGALine=-1; VGAFrame=0; HBlankInterruptHandler=NULL; // Turn on peripherals. EnableAHB1PeripheralClock(RCC_AHB1ENR_GPIOBEN|RCC_AHB1ENR_GPIOEEN|RCC_AHB1ENR_DMA2EN); EnableAPB2PeripheralClock(RCC_APB2ENR_TIM8EN|RCC_APB2ENR_SYSCFGEN); EnableAPB1PeripheralClock(RCC_APB1ENR_TIM2EN); // Configure DAC pins, and set to black. SetGPIOOutputMode(GPIOE,0xff00); SetGPIOPushPullOutput(GPIOE,0xff00); SetGPIOSpeed50MHz(GPIOE,0xff00); SetGPIOPullUpResistor(GPIOE,0xff00); GPIOE->BSRRH=0xff00; // Configure sync pins and drive them high. // Also link HSync-pin (PB11) to TIM2 CC-channel 4. SetGPIOAlternateFunctionMode(GPIOB,1<<11); SelectAlternateFunctionForGPIOPin(GPIOB,11,1); // TIM2_CH4 SetGPIOOutputMode(GPIOB,1<<12); SetGPIOPushPullOutput(GPIOB,(1<<11)|(1<<12)); SetGPIOSpeed50MHz(GPIOB,(1<<11)|(1<<12)); SetGPIOPullUpResistor(GPIOB,(1<<11)|(1<<12)); GPIOB->BSRRL=(1<<11)|(1<<12); // Configure timer 2 as the HSync timer. Timer 2 runs at half frequency, thus 84 MHz. // CC4 is used to generate the HSync pulse, using PWM mode and driving the pin directly. // CC3 is used to generate a trigger signal for TIM8, which drives the pixel DMA. TIM2->CR1=TIM_CR1_ARPE; TIM2->CR2=(6*TIM_CR2_MMS_0); // Trigger-out on CCR3. TIM2->DIER=TIM_DIER_UIE; // Enable update interrupt. TIM2->CCER=0; // Disable CC, so we can program it. TIM2->CCMR1=0; // PWM-mode: Channel 4 set to active level on reload, passive level after CC4-match. // Channel 3 set to passive level on reload, active level after CC3-match. TIM2->CCMR2=(6*TIM_CCMR2_OC4M_0)|(7*TIM_CCMR2_OC3M_0); TIM2->CCER=TIM_CCER_CC4E|TIM_CCER_CC4P; // Channel 4 enabled, reversed polarity (active low). TIM2->PSC=0; // Prescaler = 1 #ifdef EnableOverclocking TIM2->ARR=2796-1; // 88 MHz / 31.46875 kHz = 2796.42502483 // On CNT==0: sync pulse start TIM2->CCR4=336; // 88 MHz * 3.813 microseconds = 335.544 - sync pulse end TIM2->CCR3=503-14; // 88 MHz * (3.813 + 1.907) microseconds = 503.36 - back porch end, start pixel clock // -14 is a kludge to account for slow start of timer. TIM2->CCR2=503; // 88 MHz * (3.813 + 1.907) microseconds = 503.36 - back porch end, start pixel clock #else TIM2->ARR=2669-1; // 84 MHz / 31.46875 kHz = 2669.31479643 // On CNT==0: sync pulse start TIM2->CCR4=320; // 84 MHz * 3.813 microseconds = 320.292 - sync pulse end TIM2->CCR3=480; // 84 MHz * (3.813 + 1.907) microseconds = 480.48 - back porch end, start pixel clock TIM2->CCR2=480; // 84 MHz * (3.813 + 1.907) microseconds = 480.48 - back porch end, start pixel clock #endif // Enable HSync timer. TIM2->CNT=-10; // Make sure it hits ARR. TIM2->CR1|=TIM_CR1_CEN; }