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;
}