PIC32 Composite video problems - Page 1
Forum section: electronics / general

author: Lesterwyatt
author_rank: Regular Contributor
timestamp: August 13, 2015, 09:30:18 pm
content: Hi.I have been trying to display a test signal via composite into an old portable DVD player. All i seem to be getting is a black screen,i have tested signals on scope. My Vsync, Hsync, are all good my timings match the protocol, however no signal on video line.I have been working from a book called Exploring the PIC32 by Lucio Di Jasio. I am aware that the author is using PIC32MX360F512L which is different to my PIC (PIC32MX170F256B).I was wondering if somebody could look over my code and give me some pointers?My code bellow, I have left out configuration bits#include <p32xxxx.h>#include <xc.h>#include <string.h>#include <peripheral/dma.h>#include <pic32-libs/include/plib.h>#include <stdio.h>#include <stdlib.h>#include <plib.h>#include <sys/attribs.h>// NTFC#define LINE_N 262#define LINE_T 2284//#define LINE_N 312//#define LINE_T 2304#define VSYNC_N 3#define VBLANK_N (LINE_N -VRES -VSYNC_N)#define PREEQ_N VBLANK_N/2#define POSTEQ_N VBLANK_N -PREEQ_N#define SV_PREEQ 0#define SV_SYNC 1#define SV_POSTEQ 2#define SV_LINE 3#define PIX_T 4#define HSYNC_T 180#define BPORCH_T 340#define VRES 200#define HRES 256int VMap1[VRES*(HRES/32)];int *VA = VMap1;volatile int *VPtr;volatile short VCount;volatile short VState;short VS = { SV_SYNC, SV_POSTEQ, SV_LINE, SV_PREEQ};short int VC={ VSYNC_N, POSTEQ_N, VRES, PREEQ_N};int zero= {0x0,0x0};extern int * VA;void __ISR(_TIMER_3_VECTOR, IPL7DEFAULT)T3Interrupt( void){if( --VCount == 0){VCount = VC[ VState & 3];VState = VS[ VState & 3];}// vertical state machineswitch ( VState) {case SV_SYNC:// 1// vertical sync pulseOC3R = LINE_T - HSYNC_T - BPORCH_T;break;case SV_POSTEQ:// 2// horizontal sync pulseOC3R = HSYNC_T;break;case SV_PREEQ:// 0// prepare for the new frameVPtr = VA;break;default:case SV_LINE: // 3SPI1BUF = 0;DCH0SSA = KVA_TO_PA((void*) VPtr);VPtr += HRES/32;DmaChnEnable( 1);break;} //switch// clear the interrupt flagmT3ClearIntFlag();}void initVideo(void){SpiChnOpen( 1, SPICON_ON | SPICON_MSTEN | SPICON_MODE32| SPICON_FRMEN | SPICON_FRMSYNC | SPICON_FRMPOL, PIX_T);OpenOC3( OC_ON | OC_TIMER3_SRC | OC_CONTINUE_PULSE, 0, HSYNC_T);OpenTimer3( T3_ON | T3_PS_1_1 | T3_SOURCE_INT, LINE_T-1);VState = SV_LINE;VCount = 1;VA = VMap1;DmaChnOpen( 1, 1, DMA_OPEN_AUTO);DmaChnSetEventControl( 1, DMA_EV_START_IRQ_EN |DMA_EV_START_IRQ(_SPI1_TX_IRQ));DmaChnSetTxfer( 1, (void*)zero, (void *) & SPI1BUF,8, 4, 4);DmaChnOpen(0,0,DMA_OPEN_AUTO);DmaChnSetEventControl( 0, DMA_EV_START_IRQ_EN |DMA_EV_START_IRQ(_SPI1_TX_IRQ));DmaChnSetTxfer( 0, (void*)VPtr, (void *) & SPI1BUF,HRES/8, 4, 4);DmaChnSetControl( 0, DMA_CTL_CHAIN_EN | DMA_CTL_CHAIN_DIR);mT3SetIntPriority( 7);mT3IntEnable( 1);}void clearScreen(void ){memset( VA, 0, VRES*( HRES/8));}void haltVideo(void ){T3CONbits.TON = 0;}main(){int x,y;TRISBbits.TRISB7 = 1;CFGCON = 0;RPB6R = 0x03; // mapped to SD0 (VIDEO)RPB0R = 0x05; //mapped to SSI (SLAVE)SS1R = 0x04; // mapped to OC3 (SYNC)INTEnableSystemMultiVectoredInt();INTConfigureSystem(INT_SYSTEM_CONFIG_MULT_VECTOR);mT3IntEnable( 1);clearScreen();initVideo();for(y=0; y<VRES; y++)for(x=0; x<HRES/32; x++)VA[y*HRES/32+x]=y; // OUTPUT TEST PATTERNwhile( 1){} // main loop}

author: Unknown
author_rank: Unknown
timestamp: August 13, 2015, 10:33:57 pm
content: Please use the "insert code" option in the forum editor.Isn't composite video on one wire?Configure the pins you are using as digital and output.

author: Bruce Abbott
author_rank: Frequent Contributor
timestamp: August 13, 2015, 11:13:53 pm
content: Which pin number is the video line connected to? Do you have sync connected to SS1, and what pin is that on?

author: Lesterwyatt
author_rank: Regular Contributor
timestamp: August 14, 2015, 12:02:25 am
content: Hi.SDO (Video) mapped to pin RB6SS1 (Slave) mapped to pin RB0OC3 (Sync) mapped to pin RB7Thanks.

author: Chris C
author_rank: Frequent Contributor
timestamp: August 14, 2015, 05:01:58 pm
content: A few years back I toyed with NTSC signal generation on a PIC24. So far as I could tell, all signals and timing were correct, but I also got black screen on a LCD display.Then I tried hooking up a very old CRT. This proved more forgiving, and at least produced a display rather than blanking the screen; but neither horizontal/vertical sync were working properly. I modified the program so that I could increment/decrement each of the timing parameters on-the-fly, by pressing keys on an attached serial terminal. Eventually I found an acceptable range for each parameter, and set them to default to the middle of the range.At that point I tried the LCD again, and it worked. Even though the new timings were technically incorrect. I never did find the reason for this.

author: andersm
author_rank: Super Contributor
timestamp: August 14, 2015, 06:32:20 pm
content: Quote from: Lesterwyatt on August 13, 2015, 09:30:18 pmJustCode:#include <xc.h>#include <plib.h>#include <string.h>#include <stdio.h>#include <stdlib.h>will do.

author: westfw
author_rank: Super Contributor
timestamp: August 14, 2015, 07:52:36 pm
content: Quote"No signal" AT ALL on video, as shown by the scope? Or just no picture on a screen?Code:if( --VCount == 0){VCount = VC[ VState & 3];VState = VS[ VState & 3];}Shouldn't you update VState before you update VCount? Vcount is the number of linesin the current state, right?

author: Lesterwyatt
author_rank: Regular Contributor
timestamp: August 15, 2015, 10:59:15 am
content: Quote from: westfw on August 14, 2015, 07:52:36 pmI have no signal on video line (flat line). It looks like the DMA is not sending data. My state machine is fine and SPI. I'm stumped on this one.

author: Bruce Abbott
author_rank: Frequent Contributor
timestamp: August 15, 2015, 08:19:42 pm
content: When SPICON_FRMSYNC is enabled, SPI output won't start until it sees a sync transition on Slave Select. What does your scope show on the SS1 pin?QuoteI'm confused. Your code to map the pins is-Code:RPB6R = 0x03; // mapped to SD0 (VIDEO)RPB0R = 0x05; //mapped to SSI (SLAVE)SS1R = 0x04; // mapped to OC3 (SYNC)But according to the PIC32MX1XX/2XX datasheet RPB0R=0x05 maps OC3 to RB0, and SS1R=0x04 maps SS1 to RB7.What package is your PIC in (eg. QFN, SOIC/SSOP/DIP) and what pinnumbersare your signals connected to?

author: westfw
author_rank: Super Contributor
timestamp: August 15, 2015, 11:59:32 pm
content: Code:default:case SV_LINE: // 3SPI1BUF = 0;DCH0SSA = KVA_TO_PA((void*) VPtr);VPtr += HRES/32;DmaChnEnable( 1);If you put a breakpoint in this case, does it get hit? (obviously it won't generate proper video, but that's not the point...)(if you want to debug in real time, sneak a pin-toggle command in there, and watch it on a separate scope channel.)

author: Lesterwyatt
author_rank: Regular Contributor
timestamp: August 16, 2015, 10:31:56 am
content: Quote from: Bruce Abbott on August 15, 2015, 08:19:42 pmI put the mapped description in for the original message I sent. You are correct in saying the above. I have checked and the pins are where they should be. I just screwed the description up.

author: Lesterwyatt
author_rank: Regular Contributor
timestamp: August 16, 2015, 10:33:25 am
content: Quote from: westfw on August 15, 2015, 11:59:32 pmThanks I'll try later

author: Lesterwyatt
author_rank: Regular Contributor
timestamp: August 18, 2015, 05:07:46 pm
content: Quote from: westfw on August 15, 2015, 11:59:32 pmI have placed a break point as you suggested and yes it does get a hit. One weird thing though, i placed a break point at 'clearScreen()' function in the main bodyand toggled through code. The function called ok but it would not go any further, in the debugger console an error message says "Unknown error while attempting to unwind callstack!". Do you think my program may be halted at this point, while running in real time?Thanks Lester

author: andersm
author_rank: Super Contributor
timestamp: August 19, 2015, 03:46:56 am
content: You are probably trashing the stack:Code:int VMap1[VRES*(HRES/32)];int *VA = VMap1;void clearScreen(void ){memset( VA, 0, VRES*( HRES/8));}

author: helius
author_rank: Super Contributor
timestamp: August 19, 2015, 04:46:31 am
content: I would assume that anintwas 4 bytes on a PIC32. You should document the requirement that HRES is divisible by 32, however.The more portable way to do it ismemset(VA, 0, VRES*HRES/32*sizeof(int));Addendum: or justmemset(VA, 0, sizeof(VMap1));

author: westfw
author_rank: Super Contributor
timestamp: August 19, 2015, 05:10:36 am
content: QuoteIt does make me nervous that the compiler will probably put these next to each other in memory, which means that any write that overflows VMAP1 would trash the pointer that you use to reference the frame buffer.Are you sure VMAP1 doesn't need to be volatile?

author: andersm
author_rank: Super Contributor
timestamp: August 19, 2015, 05:41:19 am
content: Quote from: helius on August 19, 2015, 04:46:31 amYes, of course. You'd think I'd have learned not to post on forums first thing in the morning by now.

author: helius
author_rank: Super Contributor
timestamp: August 20, 2015, 06:13:21 am
content: If the array won't be cleared later in the program, there is no need for theclearScreen()function.Arrays in static storage are initialized to 0 by default.

author: Bruce Abbott
author_rank: Frequent Contributor
timestamp: August 22, 2015, 08:25:09 am
content: I tried your code on a PIC32MX150F128B, and here's what I found:-In Master with Framed Slave mode the SPI transmitter will lock up if its buffer underruns while SS is active. This occurs in the blank area on the right side of the screen, after the 32 bytes of video data on a line have been sent but before the HSYNC pulse occurs. It may be possible to unlock the transmitter by resetting flags etc., but I did it by simply turning SPI off and on again at the start of each line.For some reason when two DMA channels are chained the second channel seems to eat the first word and only send the next 7. To fix this I subtracted 4 from its DMA start pointer and added 4 to the length.I used the internal 8MHZ RC oscillator with PLL to get a 36MHZ system clock. This got the correct 64us per line, but the pixels seemed a little too narrow so I increased the SPI clock divider (PIX_T in your code) from 4 to 6. With the RC oscillator the picture had a slight shimmer, so I switched to an external 8MHz crystal and it was rock solid.Code:#include <xc.h>#define _SUPPRESS_PLIB_WARNING#define _DISABLE_OPENADC10_CONFIGPORT_WARNING#include <plib.h>// DEVCFG3// USERID = No Setting#pragma config PMDL1WAY = OFF // Peripheral Module Disable Configuration (Allow only one reconfiguration)#pragma config IOL1WAY = OFF // Peripheral Pin Select Configuration (Allow only one reconfiguration)#pragma config FUSBIDIO = OFF // USB USID Selection#pragma config FVBUSONIO = OFF // USB VBUS ON Selection// DEVCFG2#pragma config FPLLIDIV = DIV_2 // PLL Input 8MHz / 2 = 4MHz#pragma config FPLLMUL = MUL_18 // PLL Multiplier *18 = 72MHz#pragma config FPLLODIV = DIV_2 // PLL Output Clock Divider /2 = 36MHz// DEVCFG1#pragma config FNOSC = PRIPLL // Oscillator Selection Bits = primary (8MHZ) XTAL oscillator with PLL#pragma config FSOSCEN = OFF // Secondary Oscillator Enable#pragma config IESO = ON // Internal/External Switch Over#pragma config POSCMOD = HS // Primary Oscillator Configuration = High Speed XTAL#pragma config OSCIOFNC = OFF // CLKO Output Signal Active on the OSCO Pin#pragma config FPBDIV = DIV_1 // Peripheral Clock Divisor#pragma config FCKSM = CSDCMD // Clock Switching and Monitor Selection (Clock Switch Disable, FSCM Disabled)#pragma config WDTPS = PS1048576 // Watchdog Timer Postscaler (1:1048576)#pragma config WINDIS = OFF // Watchdog Timer Window Enable (Watchdog Timer is in Non-Window Mode)#pragma config FWDTEN = OFF // Watchdog Timer Enable (WDT Disabled (SWDTEN Bit Controls))#pragma config FWDTWINSZ = WINSZ_25 // Watchdog Timer Window Size (Window Size is 25%)// DEVCFG0#pragma config JTAGEN = OFF // JTAG Enable (JTAG Port Enabled)#pragma config ICESEL = ICS_PGx1 // ICE/ICD Comm Channel Select (Communicate on PGEC1/PGED1)#pragma config PWP = OFF // Program Flash Write Protect (Disable)#pragma config BWP = OFF // Boot Flash Write Protect bit (Protection Disabled)#pragma config CP = OFF // Code Protect (Protection Disabled)// NTSC#define VRES 200#define HRES 256#define LINE_N 262#define LINE_T 2284//#define LINE_N 312//#define LINE_T 2304#define VSYNC_N 3#define VBLANK_N (LINE_N -VRES -VSYNC_N)#define PREEQ_N VBLANK_N/2#define POSTEQ_N VBLANK_N -PREEQ_N#define SV_PREEQ 0#define SV_SYNC 1#define SV_POSTEQ 2#define SV_LINE 3#define PIX_T 6 // 4#define HSYNC_T 180#define BPORCH_T 340int VMap1[VRES*(HRES/32)];int *VA = VMap1;volatile int *VPtr;volatile short VCount;volatile short VState;short VS = { SV_SYNC, SV_POSTEQ, SV_LINE, SV_PREEQ};short int VC={ VSYNC_N, POSTEQ_N, VRES, PREEQ_N};int zero= {0x0,0x0};extern int * VA;void __ISR(_TIMER_3_VECTOR, IPL7SOFT)T3Interrupt( void){if( --VCount == 0){VCount = VC[ VState & 3];VState = VS[ VState & 3];}// vertical state machineswitch ( VState) {case SV_SYNC:// 1// vertical sync pulseOC3R = LINE_T - HSYNC_T - BPORCH_T;break;case SV_POSTEQ:// 2// horizontal sync pulseOC3R = HSYNC_T;break;case SV_PREEQ:// 0// prepare for the new frameVPtr = VA;break;default:case SV_LINE: // 3SPI1CONbits.ON = 0; // turn off SPISPI1BUF = 0;DCH0SSA = KVA_TO_PA((void*) VPtr)-4;VPtr += HRES/32;DmaChnEnable( 1);SPI1CONbits.ON = 1; // turn on SPIbreak;} //switch// clear the interrupt flagmT3ClearIntFlag();}void initVideo(void){SpiChnOpen( 1, SPICON_ON | SPICON_MSTEN | SPICON_MODE32 | SPICON_FRMEN | SPICON_FRMSYNC | SPICON_FRMPOL, PIX_T);OpenOC3( OC_ON | OC_TIMER3_SRC | OC_CONTINUE_PULSE, 0, HSYNC_T);OpenTimer3( T3_ON | T3_PS_1_1 | T3_SOURCE_INT, LINE_T-1);VState = SV_LINE;VCount = 1;VA = VMap1;DmaChnOpen( 1, 1, DMA_OPEN_DEFAULT);DmaChnSetEventControl( 1, DMA_EV_START_IRQ_EN |DMA_EV_START_IRQ(_SPI1_TX_IRQ));DmaChnSetTxfer( 1, (void*)zero, (void *) & SPI1BUF,8, 4, 4);DmaChnOpen(0,0,DMA_OPEN_DEFAULT);DmaChnSetEventControl( 0, DMA_EV_START_IRQ_EN |DMA_EV_START_IRQ(_SPI1_TX_IRQ));DmaChnSetTxfer( 0, (void*)VPtr, (void *) & SPI1BUF,HRES/8+4, 4, 4);DmaChnSetControl( 0, DMA_CTL_CHAIN_EN | DMA_CTL_CHAIN_DIR);mT3SetIntPriority( 7);mT3IntEnable( 1);}void clearScreen(void ){memset( VA, 0, VRES*( HRES/8));}void haltVideo(void ){T3CONbits.TON = 0;}main(){int x,y;TRISBbits.TRISB7 = 1;CFGCON = 0;RPB6R = 0x03; // SD0 -> PB6 pin 15 video dataRPB0R = 0x05; // OC3 -> PB0 pin 4 video syncSS1R = 0x04; // SS1 -> PB7 pin 16 frame sync (connect to OC3)INTEnableSystemMultiVectoredInt();INTConfigureSystem(INT_SYSTEM_CONFIG_MULT_VECTOR);mT3IntEnable( 1);clearScreen();initVideo();for(y=0; y<VRES; y++)for(x=0; x<HRES/32; x++)VA[y*HRES/32+x]=y; // OUTPUT TEST PATTERNwhile( 1){} // main loop}

author: Lesterwyatt
author_rank: Regular Contributor
timestamp: August 27, 2015, 08:52:45 pm
content: Quote from: Bruce Abbott on August 22, 2015, 08:25:09 am