Copy Link
Add to Bookmark
Report
GP32 demo code (mummu)
Yet another stuuuupid demo.. featuring slightly modified crossfade (tm) routine by Costis (tm).. I was just experimenting some DMA and MMU stuff.
Btw the screen is 640x480x16bits and won't fit into BIOS provided memory area. Blah blah blah blah..
mummu.c
// DMA & MMU demo (c) 2002 Jouni 'Mr.Spiv' korhonen
// Really simple & stuuuupid
//
// The 'crossfade' routine originally (c) Costis
// from his Crossfade-demo
#include "gpdef.h"
#include "gpstdlib.h"
#include "gpgraphic.h"
#include "gpmain.h"
#include "gpfont.h"
#include "gpmem.h"
#include <stdlib.h>
#include <string.h>
//
volatile long* tpal = (long*)0x14a00050;
volatile long* lcdcon1 = (long*)0x14a00000;
volatile long* lcdcon2 = (long*)0x14a00004;
volatile long* lcdcon3 = (long*)0x14a00008;
volatile long* lcdcon4 = (long*)0x14a0000c;
volatile long* lcdcon5 = (long*)0x14a00010;
volatile long* lcdaddr1 = (long*)0x14a00014;
volatile long* lcdaddr2 = (long*)0x14a00018;
volatile long* lcdaddr3 = (long*)0x14a0001c;
volatile long* hwpal = (long*)0x14a00400;
// dma0
volatile long* disrc0 = (long*)0x14600000;
volatile long* didst0 = (long*)0x14600004;
volatile long* dcon0 = (long*)0x14600008;
volatile long* dstat0 = (long*)0x1460000c;
volatile long* dcsrc0 = (long*)0x14600010;
volatile long* dcdst0 = (long*)0x14600014;
volatile long* dmasktrig0 = (long*)0x14600018;
//
extern unsigned char BK_Pic_c1[];
extern unsigned char BK_Pic_c2[];
extern long sin_tbl[]; // 256
//
#define FRAMEBUFFER_SIZE (640*480*2)
//
static unsigned short mempic1[640*480] = {0};
static unsigned short mempic2[640*480] = {0};
//
//
//
void waitline( int line ) {
while (line != ((*lcdcon1 >> 18) & 0x1ff) );
}
//
// DMA0 memory to memory copy routine..
// Note: size = number or words to copy.
//
// This DMA copy routine does not use interrupts to inform when the
// DMA has finished.. which is kinda lame. The caller must use the
// 'DMA0WaitEnd()' function to check/busywait to see when DMA has finished
// the data transfer.
//
void DMA0CopyStart( unsigned char *s, unsigned char *d, long size ) {
// Stop DMA0
*dmasktrig0 |= 0x04;
// Setup source...
// select system bus (AHB)
// select address increment
*disrc0 = (long)s;
// Setup destination...
// select system bus (AHB)
// select address increment
*didst0 = (long)d;
// DMA0 con..
*dcon0 = (0 << 30) | // demand mode
(1 << 29) | // DREQ & DACK are synched to HCLK (AHB)
(0 << 28) | // disable DMA0 int
(0 << 27) | // unit transfer
(1 << 26) | // whole servmode
(0x00 << 24) | // HWSRCSEL ?? not used
(0 << 23) | // sw request mode
(1 << 22) | // auto reload off
(0x02 << 20) | // data size == word
(size >> 2); // count..
// start DMA.. and don't wait for it to finish..
*dmasktrig0 = 0x03;
}
//
void DMA0WaitEnd( void ) {
// poll for end..
while ((*dstat0 >> 20) & 0x03);
}
//
//
//
//
//
void GpMain(void *arg)
{
unsigned char* framebuf;
unsigned char* framebuffer_strt;
unsigned char* framebuffer_stop;
long up,lo;
long ptr;
int m,n,i,j,k,l,xc,yc;
unsigned short *dst;
unsigned short *src;
//
// Allocate memory.. add 4KB extra to be sure there's enough
// memory to tolerate page size and alignment requirements
//
framebuf = (unsigned char*)gm_malloc(FRAMEBUFFER_SIZE+4096);
if (framebuf == NULL) {
// lamah..
GpAppExit();
}
// Ensure 4KB alignment..
framebuffer_strt = (unsigned char*)((long)(framebuf + 4095) & 0xfffff000);
framebuffer_stop = framebuffer_strt + FRAMEBUFFER_SIZE;
// Do the MMU mapping.. remember 4KB pages!
// for the mmu flags: 0xff2 -> no cache, no writeback
swi_mmu_change(framebuffer_strt,framebuffer_stop-1,0x00000ff2);
// copy & double to frame buffer
dst = mempic1;
src = (unsigned short*)BK_Pic_c1;
for (m = 0; m < 320; m++) {
for (n = 0; n < 240; n++) {
*dst++ = *src;
*dst++ = *src++;
}
for (n = 0; n < 480; n++) {
*dst = dst[-480];
dst++;
}
}
DMA0CopyStart( (unsigned char*)mempic1, framebuffer_strt, 640*480*2 );
// copy & double to mem buffer
dst = mempic2;
src = (unsigned short*)BK_Pic_c2;
for (m = 0; m < 320; m++) {
for (n = 0; n < 240; n++) {
*dst++ = *src;
*dst++ = *src++;
}
for (n = 0; n < 480; n++) {
*dst = dst[-480];
dst++;
}
}
DMA0WaitEnd();
// 320x240x16 screen mode, 0 pixel offscreen
// expects 33MHz HCLK
*lcdcon1 = ((3 << 8) | (0 << 7) | (3 << 5) | (12 << 1) | (0));
// CLKVAL=3, VNMODE=0, PNRMODE=TFT, BPPMODE=1100 (16bits), ENDID=0
*lcdcon2 = ((1 << 24) | (319 << 14) | (2 << 6) | 1);
// VBPD=1, LINEVAL=319, VFPD=2, VSPW=1
*lcdcon3 = ((6 << 19) | (239 << 8) | (2));
// HBPD=6, HOZVAL=239, HFPD=2
*lcdcon4 = ((0 << 24) | (0 << 16) | (4));
// PALADDEN=0, ADDVAL=0, HSPW=4
*lcdcon5 = ((1 << 10) | (1 << 9) | (1 << 8) | (0 << 7) | (0 << 6) | (0 << 4) | (0 << 2) | (1));
// INVVCLK=1, INVVLINE=1, INVVFRAME=1, INVVD=0, INVVDEN=0
// INVENDLINE=0, ENLEND=0, BSWP=0, HWSWP=1
*tpal = 0;
ptr = (long)framebuffer_strt;
*lcdaddr1 = ((ptr & 0x0fc00000) >> 1) | ((ptr & 0x3ffffe) >> 1);
*lcdaddr2 = ((ptr & 0x003ffffe) >> 1) + (240+240) * (319+1);
*lcdaddr3 = ((240 << 11) | (240));
// OFFSIZE=240, PAGEWIDTH=240 halfwords -> 240 pixels
//*lcdaddr3 = ((360 << 11) | (120));
// // OFFSIZE=240, PAGEWIDTH=240 halfwords -> 240 pixels
*lcdcon1 |= 1; // enable lcd
up = *lcdaddr1;
lo = *lcdaddr2;
n = 0;
m = 64;
i = 0;
j = 0;
k = 0;
xc = 0; yc = 0;
while ((GpKeyGet() & (GPC_VK_FL | GPC_VK_FR)) != (GPC_VK_FL | GPC_VK_FR)) {
unsigned short *bk0;
unsigned short *bk1;
unsigned short r,g,b,R,G,B;
dst = (unsigned short*)framebuffer_strt + k*480;
bk0 = dst;
if (k == 0) { yc = 0; }
if (j) {
bk1 = mempic2 + k*2*240;
} else {
bk1 = mempic1 + k*2*240;
}
for (l = 0, xc = 0; l < 480*20; l++) {
r=(*(bk0 + l) & 0xF800) >> 11;
g=(*(bk0 + l) & 0x7C0) >> 6;
b=(*(bk0 + l) & 0x3E) >> 1;
R=(*(bk1 + l) & 0xF800) >> 11;
G=(*(bk1 + l) & 0x7C0) >> 6;
B=(*(bk1 + l) & 0x3E) >> 1;
xc = 3;
if (r > R) r-=1; else if (r < R) r+=1; else xc--;
if (g > G) g-=1; else if (g < G) g+=1; else xc--;
if (b > B) b-=1; else if (b < B) b+=1; else xc--;
if (xc > 0) { yc++; }
*dst++ = ((r << 11) | (g<<6) | (b<<1));
}
waitline(2);
*lcdaddr1 = up + 480*sin_tbl[n] + sin_tbl[m];
*lcdaddr2 = lo + 480*sin_tbl[n] + sin_tbl[m];
waitline(1);
n = (n + 1) % 256;
m = (m + 1) % 256;
i = (i + 1) % 640;
k = (k + 20) % 640;
if (yc == 0) {
j ^= 1;
yc = 0;
}
}
// free memory & reboot
gm_free(framebuf);
GpAppExit();
}