Serial Wombat 18AB Firmware
Classes | Macros | Typedefs | Functions | Variables
vga.c File Reference
#include "serialWombat.h"
#include <stdint.h>
#include "asciiConversion.h"

Classes

struct  vga_n
 

Macros

#define VGA_BYTES_PER_LINE   21
 160 bits, plus a 0 at the end to pull SPI line low More...
 
#define VGA_VSYNC_PIN   18
 
#define VGA_HSYNC_PIN   17
 
#define VGA_R_PIN   16
 
#define VGA_G_PIN   15
 
#define VGA_B_PIN   14
 

Typedefs

typedef struct vga_n vga_t
 

Functions

void vga_SPI1_Initialize (void)
 
void VGAStartDMA (volatile uint8_t *address)
 
void VGAStopDMA ()
 
void initVGA (void)
 
void VGA_dma_interrupt (void)
 
void updateVGA ()
 update the VGA state machine More...
 
void __attribute__ ((interrupt, no_auto_psv))
 

Variables

bool vgaEnable = false
 This global variable signals to interrupt routines to go into VGA specific code. This is required for high performance operation; A calling a registered function pointer takes too long. More...
 
volatile uint16_t vgaNextLine = 0
 For this we're going to use global variables for items used in the interrupt. More...
 
volatile uint8_t * vgaBufferAddress
 Pointer to the next line of pixels we're going to clock out. Global to increase performance, not an issue because there can be only one instance. More...
 
volatile uint8_t * vgaZeroBuffer
 Pointer to the zero array for blank lines and such. Global to increase performance, not an issue because there can be only one instance. More...
 
uint16_t vgaFrameBuffer = 0
 Offset into the User buffer where the frame is stored. Global to increase performance, not an issue because there can be only one instance. More...
 
uint8_t * vgaColorBufferAddress
 Pointer to the buffer location where the line-color array is stored. More...
 
volatile uint8_t vgaNextColor = 7
 Global to store the next color output (0 to 7). Used so we can figure next color at the end of a line where we have some free processing time. More...
 
volatile uint8_t vgaLineCopy = 0
 
volatile uint8_t vgaDisplayLine = 0
 

Detailed Description

This file/pin mode is designed to drive a VGA monitor RGB and H and V Sync lines. The output is essentially 1 bit, with the ability to change the color between 8 colors (including black) by horizonal line.

This pin mode is unusual among SW18AB pin modes because it requires specific pins to be used for certain things. Pins must be:

VGA VSYNC (VGA Pin 14) -> 100 ohm Resistor -> SW Pin 18 VGA HSYNC (VGA Pin 13) -> 100 ohm Resistor ->SW Pin 17 VGA Red (VGA Pin 1) -> 280 ohm Resistor -> SW Pin 16 VGA Blue (VGA Pin 2) -> 280 ohm Resistor -> SW Pin 15 VGA Green (VGA Pin 3) -> 280 ohm Resistor -> SW Pin 14

Thank you to Nick Gammon who published a very informative article on driving a VGA monitor here: http://www.gammon.com.au/forum/?id=11608

See timingResource.c for additional important code int he MCCP3 interrupt handler.

A few notes based on Nick's info: VSYNC: 60Hz, (16666.67 uS) pulse is 63.9uS (2 sync lines)

Vertical is 525 lines. Each line is 31.74uS or 31500Hz "V Back porch" is 33 lines Image area is 480 lines

"V Front Porch" is 10 lines

Each line is made up of 800 pixels: a hoizontal sync pulse (96 pixels, 3.8us) Horizontal back porch (48 pixels, 1.9us) 640 pixels: 25.39 uS Horizontal Front porch is 16 pixels, 635 nS

The Serial Wombat 18AB chip will use the SPI data line to output the brightness signal that will be fed to the monitor.

The SPI output maxes out at 8MHz, or 125nS per bit, so that will determine how many pixels we can display. A VGA pixel at 640 by 480 is 25.39uS long, with a total of 800 pixels per line including front and back porch areas.
We will display 160 pixels per line, essentially combining pixels 4 at a time. We will output 120 vertical pixels to maintain a 4:3 aspect ratio. We will start the image 21 pixels to the right and accept a black border around the screen.

Chip resources: SPI - Output pixels DMA5 - Feed the SPI OC1 - Generate vSync pulse. Resets the vgaNextLine variable to 0 in interrupt MCCP3 - Generate hSync Pulse and trigger DMA and update PPS for the R/G/B output in interrupt. Highest priority interrupt.

Set up OC PWM with a period of 16666uS (Acutally a perfect multiple of whatever HSync is) and a pulse of 63.9 uS for v sync Set up OC PWM with a period of 31.74 uS and a pulse of 3.8 uS Set up OC PWM with a period of 31.74 us and a pulse of 96 + 48 + 21 pixels and use that interrupt to fire the DMA. DMA is 20 bytes of data, plus 1 byte of blank End of DMA fires an interrupt which resets and updates (every 4th line) the DMA. DMA is pointed to empty array during porches

Macro Definition Documentation

◆ VGA_B_PIN

#define VGA_B_PIN   14

◆ VGA_BYTES_PER_LINE

#define VGA_BYTES_PER_LINE   21

160 bits, plus a 0 at the end to pull SPI line low

◆ VGA_G_PIN

#define VGA_G_PIN   15

◆ VGA_HSYNC_PIN

#define VGA_HSYNC_PIN   17

◆ VGA_R_PIN

#define VGA_R_PIN   16

◆ VGA_VSYNC_PIN

#define VGA_VSYNC_PIN   18

Typedef Documentation

◆ vga_t

typedef struct vga_n vga_t

Function Documentation

◆ __attribute__()

void __attribute__ ( (interrupt, no_auto_psv)  )

◆ initVGA()

void initVGA ( void  )
\brief Initialization routine for WS2812B driver 

CONFIGURE_CHANNEL_MODE_0:

Initialize VGA Driver

BYTE 0 BYTE 1 BYTE 2 BYTE 3 BYTE 4 BYTE 5 BYTE 6 BYTE 7
0xC0 Pin To Set (must be 18) 0x1F (VGA Mode) 0x55 0x55 Frame buffer index LSB Frame buffer index MSB Unused 0x55*

*0x55 is recommended, but any byte is acceptable

Response:

Command is echoed back.

Examples:

Set pin 18 to VGA, user buffer index of 0x180

0xC0 0x12 0x1F 0x55 0x55 0x80 0x01 0x55

CONFIGURE_CHANNEL_MODE_1:

Draw a Primiative (Primative based on Byte 3)

Set or clear a pixel:

BYTE 0 BYTE 1 BYTE 2 BYTE 3 BYTE 4 BYTE 5 BYTE 6 BYTE 7
0xC1 Pin To Set (must be 18) 0x1F (VGA Mode) 0 (Set pixel) X (0-159) Y (0-119) Color (0 for black, 1 for On) Unused 0x55*

*0x55 is recommended, but any byte is acceptable

Response:

Command is echoed back.

Examples:

Set Pixel (59,111) on

0xC1 0x12 0x1F 0x0 0x3B 0x6F 0x01 0x55

Fill the Screen

BYTE 0 BYTE 1 BYTE 2 BYTE 3 BYTE 4 BYTE 5 BYTE 6 BYTE 7
0xC1 Pin To Set (must be 18) 0x1F (VGA Mode) 1 (Fill Screen) Color (0 for black, 1 for On) Unused 0x55* Unused 0x55* Unused 0x55*

*0x55 is recommended, but any byte is acceptable

Response:

Command is echoed back.

Examples:

Set the screen to all black

0xC1 0x12 0x1F 0x1 0x00 0x55 0x55 0x55

Fill A Rectangle

BYTE 0 BYTE 1 BYTE 2 BYTE 3 BYTE 4 BYTE 5 BYTE 6 BYTE 7
0xC1 Pin To Set (must be 18) 0x1F (VGA Mode) 2 (Fill Rectangle) Upper Left X Upper Left Y Lower Right X inclusive Lower Right Y inclusive

Response:

Command is echoed back.

Examples:

Set Fill A rectanle from (5,10) to (20,30)

0xC1 0x12 0x1F 0x2 0x05 0x5A 0x14 0x1E

Clear A Rectangle

BYTE 0 BYTE 1 BYTE 2 BYTE 3 BYTE 4 BYTE 5 BYTE 6 BYTE 7
0xC1 Pin To Set (must be 18) 0x1F (VGA Mode) 3 (Clear Rectangle) Upper Left X Upper Left Y Lower Right X inclusive Lower Right Y inclusive

Response:

Command is echoed back.

Examples:

Set Clear A rectanle from (5,10) to (20,30)

0xC1 0x12 0x1F 0x3 0x05 0x5A 0x14 0x1E


CONFIGURE_CHANNEL_MODE_2:

Set Line Colors. Each line can turn On/Off the RGB channels

|BYTE 0 |BYTE 1 |BYTE 2 |BYTE 3 |BYTE 4 |BYTE 5 |BYTE 6 |BYTE 7 | |:------------—|:------------—|:------------—|:------------—|:------------—|:------------—|:------------—|:------------—| |0xC2|Pin To Set (must be 18) |0x1F (VGA Mode) | Top Line to Set (0-119) | Bottom Line to set (Byte 3 to 119) | Color ( 0 to 7 where 0x04 is R, 0x02 is G, 0x01 B ) |Unused 0x55* |

*0x55 is recommended, but any byte is acceptable

Response:

Command is echoed back.

Examples:

Set Lines 50 to 60 to Yellow (Red and Green)

0xC2 0x12 0x1F 0x03 0x32 0x3C 0x06 0x55

◆ updateVGA()

void updateVGA ( )

update the VGA state machine

◆ VGA_dma_interrupt()

void VGA_dma_interrupt ( void  )

◆ vga_SPI1_Initialize()

void vga_SPI1_Initialize ( void  )

◆ VGAStartDMA()

void VGAStartDMA ( volatile uint8_t *  address)
inline

◆ VGAStopDMA()

void VGAStopDMA ( )

Variable Documentation

◆ vgaBufferAddress

volatile uint8_t* vgaBufferAddress

Pointer to the next line of pixels we're going to clock out. Global to increase performance, not an issue because there can be only one instance.

◆ vgaColorBufferAddress

uint8_t* vgaColorBufferAddress

Pointer to the buffer location where the line-color array is stored.

◆ vgaDisplayLine

volatile uint8_t vgaDisplayLine = 0

◆ vgaEnable

bool vgaEnable = false

This global variable signals to interrupt routines to go into VGA specific code. This is required for high performance operation; A calling a registered function pointer takes too long.

◆ vgaFrameBuffer

uint16_t vgaFrameBuffer = 0

Offset into the User buffer where the frame is stored. Global to increase performance, not an issue because there can be only one instance.

◆ vgaLineCopy

volatile uint8_t vgaLineCopy = 0

◆ vgaNextColor

volatile uint8_t vgaNextColor = 7

Global to store the next color output (0 to 7). Used so we can figure next color at the end of a line where we have some free processing time.

◆ vgaNextLine

volatile uint16_t vgaNextLine = 0

For this we're going to use global variables for items used in the interrupt.

◆ vgaZeroBuffer

volatile uint8_t* vgaZeroBuffer

Pointer to the zero array for blank lines and such. Global to increase performance, not an issue because there can be only one instance.