aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tdisp/HD44780/tdisp_lld.c
blob: 988f35c74c166575845003e8f540e8242b4b892f (plain)
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
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
/*
 * This file is subject to the terms of the GFX License, v1.0. If a copy of
 * the license was not distributed with this file, you can obtain one at:
 *
 *              http://chibios-gfx.com/license.html
 */

/**
 * @file    drivers/tdisp/HD44780/tdisp_lld.c
 * @brief   TDISP driver subsystem low level driver source for the HD44780 display
 *
 * @addtogroup TDISP
 * @{
 */

#include "gfx.h"

#if GFX_USE_TDISP /*|| defined(__DOXYGEN__)*/

/* check first if the user has defined his/her own lowlevel-board file */
#if defined(TDISP_USE_CUSTOM_BOARD) && TDISP_USE_CUSTOM_BOARD
	/* Include the user supplied board definitions */
	#include "tdisp_lld_board.h"
#elif defined(BOARD_OLIMEX_STM32_E407)
	#include "tdisp_lld_board_olimex_e407.h"
#elif defined(BOARD_ST_STM32F4_DISCOVERY)
	#include "tdisp_lld_board_example.h"
#endif

/* Controller Specific Properties */
#define CUSTOM_CHAR_COUNT		8
#define CUSTOM_CHAR_XBITS		5
#define CUSTOM_CHAR_YBITS		8

/* Define the properties of our controller */
tdispStruct	TDISP = {
	TDISP_COLUMNS, TDISP_ROWS,		/* cols, rows */
	CUSTOM_CHAR_XBITS, CUSTOM_CHAR_YBITS,	/* charBitsX, charBitsY */
	CUSTOM_CHAR_COUNT			/* maxCustomChars */
};

/* display control settings */
#define TDISP_DISPLAY_ON		0x04
#define TDISP_CURSOR_ON			0x02
#define TDISP_CURSOR_BLINK		0x01

/* cursor movement settings */
#define TDISP_SHIFT_ON			0x01
#define	TDISP_CURSOR_INC		0x02

/* display scroll settings */
#define TDISP_SCROLL_DISPLAY		0x08
#define TDISP_SCROLL_RIGHT		0x04

static uint8_t	displaycontrol;
static uint8_t	cursorcontrol;

bool_t tdisp_lld_init(void) { 
	/* initialise hardware */
	init_board();
	
	/* The first part is the initialing code.
	 * In this part only the lower nibble of the
	 * byte is written directly to the display, thus
	 * without write_cmd, which sends both high and
	 * low nibble.
	 */
	
	/* Give the LCD a little time to wake up */
	gfxSleepMilliseconds(15);
	
	/* clear the RS-line to the display */
	palClearPad(PORT_CTRL, PIN_RS);
// 	#if BUS_4BITS
		/* write three times 0x03 to display (4-bit mode only)
		* with RS = low.
		*/
		writeToLCD(0x03); // 1x
		gfxSleepMilliseconds(20);
		writeToLCD(0x03); // 2x
// 		gfxSleepMilliseconds(20);
		writeToLCD(0x03); // 3x
// 		gfxSleepMilliseconds(20);
		/* Put display in 4-bit mode by
		* write 0x02 to display.
		*/
		writeToLCD(0x02); // 4bit-modus
// 		gfxSleepMilliseconds(20);
// 	#else
		/* write three times 0x30 to display (8-bit mode only)
		* with RS = low.
		*/
// 		writeToLCD(0x30); // 1x
// 		writeToLCD(0x30); // 2x
// 		writeToLCD(0x30); // 3x
// 	#endif	

	/* From this point on, the LCD accepts
	 * bytes sent with highnibbel first and than
	 *the lownibble if working in 4-bit mode.
	 * In 8-bit mode bytes are written in 1 action.
	 */
	
	/* 4-bit modus, 2 lines en 5x7 characters */
	write_cmd(0x28);
// 	gfxSleepMilliseconds(20);
	
	/* set display on, cursor off and no blinking */
	write_cmd(0x0C);
// 	gfxSleepMilliseconds(20);
	/* set cursor increase and direction */
	write_cmd(0x06);
// 	gfxSleepMilliseconds(20);
	
	displaycontrol = TDISP_DISPLAY_ON;
	cursorcontrol = TDISP_CURSOR_INC;
	/* END OF INITIALISATION */

	return TRUE;
}

/* Clears the display. The display needs
 * a long time to process this command. So
 * an extra delay is insterted.
 */
void tdisp_lld_clear(void) {
	write_cmd(0x01);
}

/* Writes a character to the display */
void tdisp_lld_draw_char(char c) {
	write_data(c);
}

/* Set cursor position */
void tdisp_lld_set_cursor(coord_t col, coord_t row) {
	static const uint8_t row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };

	/*
	 *  Short-cut:
	 *
	 *  If x and y = 0 then use the home command.
	 *
	 *  Note: There is probably no advantage as both commands are a single byte
	 */
//	if (col == 0 && row == 0) {
//		write_cmd(0x02);
//		return;
//	}

	write_cmd(0x80 | (col + row_offsets[row]));
// 	write_cmd(0x80 | (0x40 + col));
}

/* Create a custom character to the display */
void tdisp_lld_create_char(uint8_t address, uint8_t *charmap) {
	int i;

	write_cmd(0x40 | (address << 3));
	for(i = 0; i < CUSTOM_CHAR_YBITS; i++) {
		write_data(charmap[i]);
	}

}

/* Write display control commands to the display */
void tdisp_lld_control(uint16_t what, uint16_t value) {
	switch(what) {
		      case TDISP_CTRL_DISPLAY:
				switch (value) {
					case displayOff:
						displaycontrol &= ~TDISP_DISPLAY_ON;
						break;
					case displayOn:
						displaycontrol |= TDISP_DISPLAY_ON;
						break;
				}
				write_cmd(0x08 | displaycontrol);
				break;
		      case TDISP_CTRL_CURSOR:
				switch (value) {
					case cursorBlinkingBlock:
					case cursorBlinkingUnderline:
					case cursorBlinkingBar:
						displaycontrol |= TDISP_CURSOR_ON + TDISP_CURSOR_BLINK;
						break;
					case cursorBlock:
					case cursorUnderline:
					case cursorBar:
						displaycontrol = (displaycontrol | TDISP_CURSOR_ON) & ~TDISP_CURSOR_BLINK;
						break;
					case cursorOff:
					default:
						displaycontrol &= ~(TDISP_CURSOR_ON | TDISP_CURSOR_BLINK); // zet alleen de cursor uit. Bewaar de overige instellingen
						break;
				}
				write_cmd(0x08 | displaycontrol);
				break;
			case TDISP_CTRL_MOVE:
				switch (value) {
					case cursorIncrease:
						cursorcontrol |= TDISP_CURSOR_INC; // increase cursor position
						break;
					case cursorDecrease:
						cursorcontrol &= ~TDISP_CURSOR_INC; // decrease cursor position
						break;
				}
				write_cmd(0x04 | cursorcontrol);
				break;
			case TDISP_CTRL_SHIFT:
				switch (value) {
					case shiftOn:
						cursorcontrol |= TDISP_SHIFT_ON;
						break;
					case shiftOff:
						cursorcontrol &= ~TDISP_SHIFT_ON;
						break;
				}
				write_cmd(0x04 | cursorcontrol);
				break;
	}
}

/* Scrolls the display in a particular direction with an amount of characters and delays the scroll between each scroll step */
void tdisp_lld_scroll(uint16_t direction, uint16_t amount, uint16_t delay) {
  uint16_t scrollcontrol = 0;
  uint16_t i;
  
  switch (direction) {
    case displayScrollLeft:
      scrollcontrol = TDISP_SCROLL_DISPLAY;
      break;
    case displayScrollRight:
      scrollcontrol = TDISP_SCROLL_DISPLAY | TDISP_SCROLL_RIGHT;
      break;
  }
  
  for(i = 0; i < amount; i++) {
    write_cmd(0x10 | scrollcontrol);
    gfxSleepMilliseconds(delay);	
  }
}

#if TDISP_USE_BACKLIGHT
/* sets the brightness of the display backlight */
void tdisp_lld_set_backlight(uint16_t percentage) {
  set_backlight(percentage);
}
#endif

#endif /* GFX_USE_TDISP */
/** @} */