Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

PIC32, DMA, PMP and color LCD.

Status
Not open for further replies.

Gobbledok

Active Member
Hi guys I'm using a PIC32MX795F512L to write to a 320 x 240 ILI9325 LCD screen.

The program is (mostly) working fine and I am getting about 30 FPS when writing from the double buffered memory area using PMP and DMA.

The problem is when I try to write a single value to the whole screen, rather than writing from the double-buffered memory area.

First, here's my code for the successful PMP/DMA write from the double-buffered memory area:

Code:
void LCDWriteBuffer()
{
	SetWindow(0,0,189,319);                   // Sets the memory (display) area on the LCD to write to

	// Open the desired DMA channel. Priority 0/channel 0, priority 1/channel 1.
	DmaChnOpen(0, 0, DMA_OPEN_DEFAULT);
	DmaChnOpen(1, 1, DMA_OPEN_CHAIN_HI);

	// set the transfer event control: what event is to start the DMA transfer
	DmaChnSetEventControl(0, DMA_EV_START_IRQ(_PMP_IRQ));
	DmaChnSetEventControl(1, DMA_EV_START_IRQ(_PMP_IRQ));


	// set the transfer parameters: source & destination address, source & destination size, number of bytes per event
	DmaChnSetTxfer(0, LCD_Buffer_1, (void*)&PMDIN, 60800, 2, 2);
	DmaChnSetTxfer(1, LCD_Buffer_1+30400, (void*)&PMDIN, 60800, 2, 2);

 	LCD_RS=1;

	// once we configured the DMA channel we can enable it
	// now it's ready and waiting for an event to occur...
	DmaChnEnable(0);

	// force the first transfer to get the PMP and DMA started
	DmaChnForceTxfer(0);
}

Basically, I set up the 2 DMA channels. Channel 1 is set to go after channel 0 finishes. Both of them copy from the LCD_Buffer_1 to PMDIN (the PMP register) for a total of 60800 bytes per DMA channel.

The problem comes if I want to write the whole screen with a single value.

Using the exact same code, except I change the DmaSetChnTxfer code to:

Code:
	DmaChnSetTxfer(0, (void*)&BackgroundColor, (void*)&PMDIN, pixels, 2, 2);
	DmaChnSetTxfer(1, (void*)&BackgroundColor, (void*)&PMDIN, pixels, 2, 2);
it doesn't work. It fills about 10 pixels (some are the background color, some not) and then stops transferring through the PMP and the DMA channel doesn't finish.

With this function I am trying to fill the screen with 'BackgroundColor' up to an amount 'pixels'. There are 2 bytes per transfer (16 bit PMP).

As far as I can tell it should work fine.

So yeh basically just wondering if anybody more experienced than myself (I'm only just making the leap from assembler to C) can see why this bit of code doesn't work as it should?

.
 
Last edited:
Could it be because BackgroundColor is a 32-bit register instead of a 16-bit register (what the PMP expects)?

I'm at work ATM, otherwise I'd try it. Edit: nope, not that.



OK more info.

I actually have to use 3 chained DMA channels due to the 65536 maximum bytes transferred per channel at a time. I need to transfer up to 153KB at a time. The DMA chaining works fine, however.

The DMA *appears* to transfer the first word correctly (the first pixel is 'BackgroundColor). After that, the next 5 - 6 pixels are black, and then the rest of the pixels come from the buffer!

It does the same for each DMA channel (as in, when the first channel changes and the second one starts, the first pixel transferred by the next channel is red).

Therefore I assume that the channel is treating '(void*)&BackgroundColor' as a pointer and increasing the address after every write.

Here is my new code for the FillScreen function:
Code:
void FillScreen(unsigned int data, unsigned int pixels)
{
	BackgroundColor = Red;
	SetWindow(0,0,239,319);

	// Open the desired DMA channel. We use priority 0.
	DmaChnOpen(0, 2, DMA_OPEN_DEFAULT);
	DmaChnOpen(1, 3, DMA_OPEN_CHAIN_HI);
	DmaChnOpen(2, 3, DMA_OPEN_CHAIN_HI);

	// set the transfer event control: what event is to start the DMA transfer
	DmaChnSetEventControl(0, DMA_EV_START_IRQ(_PMP_IRQ));
	DmaChnSetEventControl(1, DMA_EV_START_IRQ(_PMP_IRQ));
	DmaChnSetEventControl(2, DMA_EV_START_IRQ(_PMP_IRQ));

	// set the transfer parameters: source & destination address, source & destination size, number of bytes per event
	DmaChnSetTxfer(0, (void*)&BackgroundColor, (void*)&PMDIN, pixels*2/3+1, 2, 2);
	DmaChnSetTxfer(1, (void*)&BackgroundColor, (void*)&PMDIN, pixels*2/3+1, 2, 2);
	DmaChnSetTxfer(2, (void*)&BackgroundColor, (void*)&PMDIN, pixels*2/3+1, 2, 2);

	LCD_RS=1;

	// once we configured the DMA channel we can enable it
	// now it's ready and waiting for an event to occur...
	DmaChnEnable(0);

	// force the first transfer to get the PMP and DMA started
	DmaChnForceTxfer(0);

	 //wait for the transfer to be completed
	while(!(DmaChnGetEvFlags(2)&DMA_EV_BLOCK_DONE));
}

If anybody can tell me how to get the DMA routine to treat '(void*)&BackgroundColor' as a register/value instead of a pointer (at least I think it's treating it as a pointer) it would be much appreciated :)
 
Last edited:
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top