209 lines
5.2 KiB
C
209 lines
5.2 KiB
C
/** \file server/drivers/t6963_low.c
|
|
* Low level output routines for Toshiba T6963 based LCD displays connected
|
|
* to a parallel port.
|
|
*
|
|
* Wiring (no pins for the display given. Check with your datasheet!)
|
|
*
|
|
*\verbatim
|
|
* Parallel: LCD:
|
|
* 1 (Strobe) ----------- /WR
|
|
* 2-9 (Data) ----------- DB0-DB7
|
|
* 14 (Autofeed) -------- /CE
|
|
* 16 (Init) ------------ C/D
|
|
* 17 (Slct) ------------ /RD
|
|
* + 5V --- FS (6x8 font, used for t6963 driver)
|
|
* GND --- FS (8x8 font, used for glcd connection type)
|
|
*\endverbatim
|
|
*
|
|
*/
|
|
|
|
/*-
|
|
* Parts of this file are based on the kernel driver by
|
|
* Alexander Frink <Alexander.Frink@Uni-Mainz.DE>
|
|
*
|
|
* Copyright (c) 2001 Manuel Stahl <mythos@xmythos.de>
|
|
* 2011 Markus Dolze
|
|
*
|
|
* This file is released under the GNU General Public License. Refer to the
|
|
* COPYING file distributed with this package.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "port.h"
|
|
#include "lpt-port.h"
|
|
#include "timing.h"
|
|
#include "t6963_low.h"
|
|
|
|
/* Define the wiring */
|
|
#define nWR nSTRB
|
|
#define nRD nSEL
|
|
#define nCE nLF
|
|
#define T_CMD INIT
|
|
#define T_DATA 0x00 /* ~INIT didn't work here */
|
|
|
|
|
|
/**
|
|
* Acquires access to parallel port and initializes timing. The parallel port
|
|
* must be an I/O-address between 0x200 and 0x400.
|
|
* \param p Pointer to port configuration.
|
|
* \return 0 on success, -1 if an error occured.
|
|
*/
|
|
int
|
|
t6963_low_init(T6963_port *p) {
|
|
if ((p->port < 0x200) || (p->port > 0x400))
|
|
return -1;
|
|
|
|
if (port_access_multiple(p->port, 3))
|
|
return -1;
|
|
|
|
if (timing_init() == -1)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/**
|
|
* Releases access to the parallel port.
|
|
* \param p Pointer to port configuration.
|
|
*/
|
|
void
|
|
t6963_low_close(T6963_port *p) {
|
|
if ((p->port >= 0x200) && (p->port <= 0x400))
|
|
port_deny_multiple(p->port, 3);
|
|
}
|
|
|
|
/**
|
|
* Send one data byte to the display.
|
|
* \param p Pointer to port configuration.
|
|
* \param byte Data byte.
|
|
*/
|
|
void
|
|
t6963_low_data(T6963_port *p, u8 byte)
|
|
{
|
|
t6963_low_dsp_ready(p, STA0|STA1);
|
|
t6963_low_send(p, T_DATA, byte);
|
|
}
|
|
|
|
/**
|
|
* Send one command byte to the display.
|
|
* \param p Pointer to port configuration.
|
|
* \param byte Command byte.
|
|
*/
|
|
void
|
|
t6963_low_command(T6963_port *p, u8 byte)
|
|
{
|
|
t6963_low_dsp_ready(p, STA0|STA1);
|
|
t6963_low_send(p, T_CMD, byte);
|
|
}
|
|
|
|
/**
|
|
* Write one byte of data to display in AUTO mode (needs a different ready
|
|
* check).
|
|
* \param p Pointer to port configuration.
|
|
* \param byte Data byte.
|
|
*/
|
|
void
|
|
t6963_low_auto_write(T6963_port *p, u8 byte)
|
|
{
|
|
t6963_low_dsp_ready(p, STA3);
|
|
t6963_low_send(p, T_DATA, byte);
|
|
}
|
|
|
|
/**
|
|
* Send one byte of data followed by one command byte to the display.
|
|
* \param p Pointer to port configuration.
|
|
* \param cmd Command byte.
|
|
* \param byte Data value.
|
|
*/
|
|
void
|
|
t6963_low_command_byte(T6963_port *p, u8 cmd, u8 byte)
|
|
{
|
|
t6963_low_data(p, byte);
|
|
t6963_low_command(p, cmd);
|
|
}
|
|
|
|
/**
|
|
* Send one word (two bytes) of data followed by one command byte to the
|
|
* display. Low byte is output first.
|
|
* \param p Pointer to port configuration.
|
|
* \param cmd Command byte.
|
|
* \param word Data value (2 bytes)
|
|
*/
|
|
void
|
|
t6963_low_command_word(T6963_port *p, u8 cmd, u16 word)
|
|
{
|
|
t6963_low_data(p, word & 0xFF);
|
|
t6963_low_data(p, (word >> 8) & 0xFF);
|
|
t6963_low_command(p, cmd);
|
|
}
|
|
|
|
/**
|
|
* Check display status.
|
|
* \param p Pointer to port configuration.
|
|
* \param sta Bitmap of expected STA flags
|
|
* \return 0 on success, -1 if ready could not be read
|
|
*/
|
|
int
|
|
t6963_low_dsp_ready(T6963_port *p, u8 sta)
|
|
{
|
|
int portcontrol = 0;
|
|
|
|
if (p->bidirectLPT == 1) {
|
|
int val;
|
|
int loop = 0;
|
|
|
|
do {
|
|
portcontrol = T_CMD | nWR | nRD | nCE;
|
|
port_out(T6963_CONTROL_PORT(p->port), portcontrol ^ OUTMASK);
|
|
/* lower nRD, nCE, set bi-directional mode */
|
|
portcontrol = T_CMD | nWR | ENBI;
|
|
port_out(T6963_CONTROL_PORT(p->port), portcontrol ^ OUTMASK);
|
|
/* possible wait required here: tACC = 150 ns max */
|
|
if (p->delayBus)
|
|
timing_uPause(1);
|
|
val = port_in(T6963_DATA_PORT(p->port));
|
|
portcontrol = T_CMD | nWR | nRD | nCE;
|
|
port_out(T6963_CONTROL_PORT(p->port), portcontrol ^ OUTMASK);
|
|
loop++;
|
|
if (loop == 100)
|
|
return -1;
|
|
} while ((val & sta) != sta);
|
|
}
|
|
else {
|
|
portcontrol = T_CMD | nWR | nRD | nCE;
|
|
port_out(T6963_CONTROL_PORT(p->port), portcontrol ^ OUTMASK);
|
|
portcontrol = T_CMD | nWR;
|
|
port_out(T6963_CONTROL_PORT(p->port), portcontrol ^ OUTMASK);
|
|
timing_uPause(150);
|
|
portcontrol = T_CMD | nWR | nRD | nCE;
|
|
port_out(T6963_CONTROL_PORT(p->port), portcontrol ^ OUTMASK);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Write a single command / or byte to the parallel port.
|
|
* \param p Pointer to port configuration.
|
|
* \param type Command or Data
|
|
* \param byte Data byte.
|
|
*/
|
|
inline void
|
|
t6963_low_send(T6963_port *p, u8 type, u8 byte)
|
|
{
|
|
int portcontrol = 0;
|
|
|
|
portcontrol = type | nWR | nRD | nCE;
|
|
port_out(T6963_CONTROL_PORT(p->port), portcontrol ^ OUTMASK);
|
|
port_out(T6963_DATA_PORT(p->port), byte);
|
|
portcontrol = type | nRD; /* lower nWR, nCE */
|
|
port_out(T6963_CONTROL_PORT(p->port), portcontrol ^ OUTMASK);
|
|
/* possible wait required here: tWR */
|
|
if (p->delayBus)
|
|
timing_uPause(1);
|
|
portcontrol = type | nWR | nRD | nCE;
|
|
port_out(T6963_CONTROL_PORT(p->port), portcontrol ^ OUTMASK);
|
|
}
|