OpenCores
URL https://opencores.org/ocsvn/openarty/openarty/trunk

Subversion Repositories openarty

[/] [openarty/] [trunk/] [sw/] [board/] [oledtest.c] - Rev 34

Go to most recent revision | Compare with Previous | Blame | View Log

#include "artyboard.h"
#include "zipsys.h"
 
void	idle_task(void) {
	while(1)
		zip_idle();
}
 
extern int	splash[], mug[];
 
#define	OLED_PMODEN		0x0010001
#define	OLED_PMODEN_OFF		0x0010000
#define	OLED_IOPWR		OLED_PMODEN
#define	OLED_VCCEN		0x0020002
#define	OLED_VCC_DISABLE	0x0020000
#define	OLED_RESET		0x0040000
#define	OLED_RESET_CLR		0x0040004
#define	OLED_PWRRESET		(OLED_PMODEN|OLED_RESET) // 5
#define	OLED_FULLPOWER		(OLED_PMODEN|OLED_VCCEN|OLED_RESET_CLR) // 3->7
#define	OLED_POWER_DOWN		(OLED_PMODEN_OFF|OLED_VCC_DISABLE)
#define	OLED_BUSY		1
#define	OLED_DISPLAYON		0x0af
 
 
#define	MICROSECOND		(CLOCKFREQ_HZ/1000000)
 
#define	OLED_DISPLAY_OFF
 
	const int	init_sequence[] = {
		//  Unlock commands
		0x01fd12,
		//  Display off
		0x0ae,
		//  Set remap and data format
		0x01a072,
		//  Set the start line
		0x01a100,
		//  Set the display offset
		0x01a200,
		//  Normal display mode
		0x0000a4,
		//  Set multiplex ratio
		0x01a83f,
		//  Set master configuration:
		//	Use External VCC
		0x01ad8e,
		//  Disable power save mode
		0x01b00b,
		//  Set phase length
		0x01b131,
		//  Set clock divide
		0x01b3f0,
		//  Set Second Pre-change Speed For ColorA
		0x018a64,
		//  5l) Set Set Second Pre-charge Speed of Color B
		0x018b78,
		//  5m) Set Second Pre-charge Speed of Color C
		0x018c64,
		//  5n) Set Pre-Charge Voltage
		0x01bb3a,
		//  50) Set VCOMH Deselect Level
		0x01be3e,
		//  5p) Set Master Current
		0x018706,
		//  5q) Set Contrast for Color A
		0x018191,
		//  5r) Set Contrast for Color B
		0x018250,
		//  5s) Set Contrast for Color C
		0x01837D,
		//  disable scrolling
		0x02e };
 
void	timer_delay(int counts) {
	// Clear the PIC.  We want to exit from here on timer counts alone
	zip->pic = CLEARPIC;
 
	if (counts > 10) {
		// Set our timer to count down the given number of counts
		zip->tma = counts;
		zip->pic = EINT(SYSINT_TMA);
		zip_rtu();
		zip->pic = CLEARPIC;
	} // else anything less has likely already passed
}
 
void oled_clear(void);
 
void	oled_init(void) {
	int	i;
 
	for(i=0; i<sizeof(init_sequence); i++) {
		while(sys->io_oled.o_ctrl & OLED_BUSY)
			;
		sys->io_oled.o_ctrl = init_sequence[i];
	}
 
	// 5u) Clear Screen
	oled_clear();
 
	zip->tma = (CLOCKFREQ_HZ/200);
	zip->pic = EINT(SYSINT_TMA);
	zip_rtu();
	zip->pic = CLEARPIC;
 
 
	// Turn on VCC and wait 100ms
	sys->io_oled.o_data = OLED_VCCEN;
	// Wait 100 ms
	timer_delay(CLOCKFREQ_HZ/10);
 
	// Send Display On command
	sys->io_oled.o_ctrl = 0xaf;
}	
 
void	oled_clear(void) {
	while(sys->io_oled.o_ctrl & OLED_BUSY)
		;
	sys->io_oled.o_a = 0x5f3f0000;
	sys->io_oled.o_ctrl = 0x40250000;
	while(sys->io_oled.o_ctrl & OLED_BUSY)
		;
}
 
void	oled_fill(int c, int r, int w, int h, int pix) {
	int	ctrl; // We'll send this value out the control/command port
 
	if (c > 95) c = 95;
	if (c <  0) c =  0;
	if (r > 63) r = 63;
	if (r <  0) r =  0;
	if (w <  0) w = 0;
	if (h <  0) h = 0;
	if (c+w > 95) w = 95-c;
	if (r+h > 63) h = 63-r;
 
	// Enable a rectangle to fill
	while(sys->io_oled.o_ctrl & OLED_BUSY)
		;
	sys->io_oled.o_ctrl = 0x12601;
 
	// Now, let's build the actual copy command
	ctrl = 0xa0220000 | ((c&0x07f)<<8) | (r&0x03f);
	sys->io_oled.o_a = (((c+w)&0x07f)<<24) | (((r+h)&0x03f)<<16);
	sys->io_oled.o_a|= ((pix >> 11) & 0x01f)<< 9;
	sys->io_oled.o_a|= ((pix >>  5) & 0x03f)    ;
	sys->io_oled.o_b = ((pix >> 11) & 0x01f)<<17;
	sys->io_oled.o_b|= ((pix >>  5) & 0x03f)<< 8;
	sys->io_oled.o_b|= ((pix      ) & 0x01f)<< 1;
 
	// Make certain we had finished with the port (should've ...)
	while(sys->io_oled.o_ctrl & OLED_BUSY)
		;
 
	// and send our new command
	sys->io_oled.o_ctrl = ctrl;
 
	// To be nice to whatever routine follows, we'll wait 'til the port
	// is clear again.
	while(sys->io_oled.o_ctrl & OLED_BUSY)
		;
}
 
void	entry(void) {
	unsigned	user_regs[16];
	for(int i=0; i<15; i++)
		user_regs[i] = 0;
	user_regs[15] = (unsigned int)idle_task;
	zip_restore_context(user_regs);
 
	// Clear the PIC.  We'll come back and use it later.
	zip->pic = CLEARPIC;
 
	if (0) { // Wait till we've had power for at least a quarter second
		int pwrcount = sys->io_pwrcount;
		do {
			pwrcount = sys->io_pwrcount;
		} while((pwrcount>0)&&(pwrcount < CLOCKFREQ_HZ/4));
	} else {
		int pwrcount = sys->io_pwrcount;
		if ((pwrcount > 0)&&(pwrcount < CLOCKFREQ_HZ/4)) {
			pwrcount = CLOCKFREQ_HZ/4 - pwrcount;
			timer_delay(pwrcount);
		}
	}
 
 
	// If the OLED is already powered, such as might be the case if
	// we rebooted but the board was still hot, shut it down
	if (sys->io_oled.o_data & 0x07) {
		sys->io_oled.o_data = OLED_VCC_DISABLE;
		// Wait 100 ms
		timer_delay(CLOCKFREQ_HZ/10);
		// Shutdown the entire devices power
		sys->io_oled.o_data = OLED_POWER_DOWN;
		// Wait 100 ms
		timer_delay(CLOCKFREQ_HZ/10);
 
		// Now let's try to restart it
	}
 
	// 1. Power up the OLED by applying power to VCC
	//	This means we need to apply power to both the VCCEN line as well
	//	as the PMODEN line.  We'll also set the reset line low, so the
	//	device starts in a reset condition.
	sys->io_oled.o_data = OLED_PMODEN|OLED_RESET_CLR;
	timer_delay(4*MICROSECOND);
	sys->io_oled.o_data = OLED_RESET;
	timer_delay(4*MICROSECOND);
 
	// 2. Send the Display OFF command
	//	This isn't necessary, since we already pulled RESET low.
	//
	// sys->io_oled.o_ctrl = OLED_DISPLAY_OFF;
	//
 
	// However, we must hold the reset line low for at least 3us, as per
	// the spec.  We may also need to wait another 2us after that.  Let's
	// hold reset low for 4us here.
	timer_delay(4*MICROSECOND);
 
	// Clear the reset condition.
	sys->io_oled.o_data = OLED_RESET_CLR;
	// Wait another 4us.
	timer_delay(4*MICROSECOND);
 
	// 3. Initialize the display to the default settings
	//	This just took place during the reset cycle we just completed.
	//
	oled_init();
 
	// 4. Clear screen
	// sys->io_oled.o_ctrl = OLED_CLEAR_SCREEN;
 
	// Wait for the command to complete
	while(sys->io_oled.o_ctrl & OLED_BUSY)
		;
 
	// 5. Apply power to VCCEN
	sys->io_oled.o_data = OLED_FULLPOWER;
 
	// 6. Delay 100ms
	timer_delay(CLOCKFREQ_HZ/10);
 
	while(1) {
	// 7. Send Display On command
	// sys->io_oled.o_ctrl = OLED_CLEAR_SCREEN; // ?? What command is this?
		sys->io_ledctrl = 0x0ff;
 
		sys->io_oled.o_ctrl = OLED_DISPLAYON;
 
		oled_clear();
 
		while(sys->io_oled.o_ctrl & OLED_BUSY)
			;
		sys->io_oled.o_ctrl = 0x2015005f;
 
		while(sys->io_oled.o_ctrl & OLED_BUSY)
			;
		sys->io_oled.o_ctrl = 0x2075003f;
 
		sys->io_ledctrl = 0x0fe;
		// Now ... finally ... we can send our image.
		for(int i=0; i<6144; i++) {
			while(sys->io_oled.o_ctrl & OLED_BUSY)
				;
			sys->io_oled.o_data = splash[i];
		}
		sys->io_ledctrl = 0x0fc;
		timer_delay(CLOCKFREQ_HZ*5);
		timer_delay(CLOCKFREQ_HZ*5);
		timer_delay(CLOCKFREQ_HZ*5);
		timer_delay(CLOCKFREQ_HZ*5);
		timer_delay(CLOCKFREQ_HZ*5);
 
 
		for(int i=0; i<6144; i++) {
			while(sys->io_oled.o_ctrl & OLED_BUSY)
				;
			sys->io_oled.o_data = mug[i];
		}
 
		sys->io_ledctrl = 0x0f0;
		timer_delay(CLOCKFREQ_HZ*5);
	}
 
	zip_halt();
}
 
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.