[BACK]Return to p64lcd.c CVS log [TXT][DIR] Up to [local] / funnyos / arch / sam7s64 / dev

File: [local] / funnyos / arch / sam7s64 / dev / p64lcd.c (download)

Revision 1.1, Mon Jan 7 20:24:49 2008 UTC (16 years, 4 months ago) by nbrk
Branch: MAIN
CVS Tags: HEAD

initial bits of driver for Hitachi HD44780-compatible LCD controllers.
machine dependent part sits in p64lcd.c;
it doesn't initialize LCD properly - missed some timings, i think.

unfortunately, i have fryed my brand-new 16x4 LCD and can't continue work right now..
very sadly, R.I.P :(

/*
 * $Id: p64lcd.c,v 1.1 2008/01/07 20:24:49 nbrk Exp $
 */
#include <sys/types.h>
#include <sys/device.h>
#include <sys/gpio.h>
#include <dev/lcd/44780var.h>

#include <arch/sam7s64/dev/at91sam7.h>

/*
 * 44780-based LCD connected to my p64 board.
 * Wiring for chip logic:
 *	RS  -> PA10
 *	R/W -> PA9
 *	E -> PA8
 *	D{0..7} -> PA{7,6,5,4,3,2,1,0}
 *
 * We will fake-up as a 10-bit bus for our child (real 44780 driver).
 * This 10-bit bus is: MSB <RS><R/W><D7>..<D0> LSB
 * Please note that p64lcd_read() returns 8-bit D0..D7.
 */
int		p64lcd_attach(struct device *self, uint32_t loc, uint8_t flags);
void	p64lcd_write(void *pldd, uint16_t data);
uint8_t p64lcd_read(void *pldd);
uint8_t	p64lcd_readbf(void *pldd);
void	p64lcd_strobe(void *pldd);

/* our devdata */
struct p64lcd_dd {
	struct gpio_controller	*pl_gcp;
	
	struct h44780_busops		pl_bus;			/* our 10-bit control bus for driver */
};

struct driver p64lcd_dr = {
	sizeof(struct p64lcd_dd),
	p64lcd_attach,
	NULL,
	NULL
};


int
p64lcd_attach(struct device *self, uint32_t loc, uint8_t flags)
{
	struct p64lcd_dd *ddp = self->dv_devdata;
	struct gpio_pin pin;
	uint8_t i;
	int j;

	/* grab parent's gpio_controller */
	ddp->pl_gcp = self->dv_parent->dv_aux;

	/* configure pins */
	pin.gp_pio = 1;
	pin.gp_flags = GPIO_PIN_OUTPUT; /* XXX what about read? */
	pin.gp_value = 0;
	for(i = 0; i < 11; i++) {
		pin.gp_pinno = i;
		ddp->pl_gcp->gc_pinset(ddp->pl_gcp->gc_selfdd, pin);
	}

	/* XXX enable synchronous data output on our data lines */
	*AT91C_PIOA_OWER = 0xff;
//	*AT91C_PIOA_ODSR = 0xaa;
//	*AT91C_PIOA_ODSR = ~0xaa;

	printf("p64 10-bit bus for LCD, dedicated E strobe\n");

	/* link 44780_ops */
	ddp->pl_bus.write = p64lcd_write;
	ddp->pl_bus.read = p64lcd_read;
	ddp->pl_bus.readbf = p64lcd_readbf;
	ddp->pl_bus.strobe = p64lcd_strobe;
	ddp->pl_bus.selfdd = ddp;

	/* export */
	self->dv_aux = &ddp->pl_bus;

	return(0);
}

void
p64lcd_write(void *pldd, uint16_t data)
{
	uint32_t setmask = 0;
	uint8_t i, rs, rw = rs = 0;
	/*
	 * Decode and place given 10-bit data on the wires.
	 * We will use raw PIOA registers instead of gpio_controller abstraction
	 * so we can hit all pins in one shoot.
	 */
	/*
	 * Caller gives us: <RS><RW><D7><D6><D5><D4><D3><D2><D1><D0> (LSB)
	 */
	/* strip unneeded bits */
	data = data & 0x3ff;

	/* XXX bring all our lines to high */
	//*AT91C_PIOA_CODR = 0x3ff;

	/* check if caller requested to assert RS */
	if (data & 0x200)
		rs = 1;
//		setmask |= 1 << 10; /* 'RS' is PA10 */
//		*AT91C_PIOA_CODR = 1 << 10;
//	else *AT91C_PIOA_SODR = 1 << 10;

	/* check if caller requested to assert R/W */
	if (data & 0x100)
		rw = 1;
//		setmask |= 1 << 9; /* 'RW' is PA9 */
//		*AT91C_PIOA_CODR = 1 << 9;
//	else *AT91C_PIOA_SODR = 1 << 9;

	/*
	 * Deal with LSB of data which contains D0..D7 value.
	 * Since D0..D7 is wired to PA7..PA0 we need to reverse bits.
	 */

	for(i = 0; i < 7; i++)
		if (data & (1 << i))
			setmask |= 1 << (7 - i);
//	setmask = data & 0xff;

	printf("p64lcd_write: rs=%d rw=%d setmask=0x%x\n", rs, rw, setmask);

//	*AT91C_PIOA_SODR = setmask;
//	*AT91C_PIOA_CODR = (uint8_t)(~setmask);
	if (rs)
		*AT91C_PIOA_SODR = 1 << 10;
	else
		*AT91C_PIOA_CODR = 1 << 10;

	if (rw)
		*AT91C_PIOA_SODR = 1 << 9;
	else
		*AT91C_PIOA_CODR = 1 << 9;

	/* E high */
	*AT91C_PIOA_SODR = 1 << 8;

	*AT91C_PIOA_ODSR = setmask;

	/* E low */
	*AT91C_PIOA_CODR = 1 << 8;

	//*AT91C_PIOA_ODSR = ~setmask;
}


uint8_t
p64lcd_read(void *pldd)
{
	/* TODO */


	return(1);
}


uint8_t
p64lcd_readbf(void *pldd)
{
	/* TODO */

	return(1);
}


void
p64lcd_strobe(void *pldd)
{
	volatile int i;
	*AT91C_PIOA_SODR = 1 << 8;
	/* XXX delay? */
	for(i = 0; i < 10; i++)
		;
	*AT91C_PIOA_CODR = 1 << 8;
}