File: t6963_low.c

package info (click to toggle)
lcdproc 0.5.9-3
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, buster, sid
  • size: 5,064 kB
  • sloc: ansic: 59,645; sh: 1,740; perl: 681; makefile: 417
file content (208 lines) | stat: -rw-r--r-- 5,289 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
/** \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.
 */
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);
}