1 /*
2 * file: EA-DOGM_MIO.c
3 * version: 2.03
4 * description: Multi I/O driver for EA DOGM displays
5 * : Uses 8Bit, SPI HW or SPI SW (bitbang)
6 * written by : Michael Bradley (mbradley@mculabs.com)
7 * contributions: Imaginos (CCS forum), Emil Nad (8Bit testing)
8 * jgschmidt (CCS forum)
9 *
10 * Changelog:
11 * 04/22/2010 v2.03 Minor update, changed EADOGM_SPI_HW for HW SPI 1 and 2
12 * Added setup_spi() for HW SPI use, and spi_clk_div option
13 * thanks to jgschmidt (ccs forum) for noticing hw setup issues
14 * 12/03/2009 v2.02 bug fix and printChr change, no user change needed for use
15 * 11/25/2009 v2.01 Minor changes, replaced some functions with macros
16 * 09/17/2009 v2.00 Major change, IO is now 8Bit or SPI (hw or sw)
17 * rewrote some defines as related to pins
18 * 09/15/2009 v1.13 added function eaDogM_WriteIntAtPos()
19 * and eaDogM_WriteStringAtPos()
20 * added some defines to clean source
21 * 08/28/2009 v1.12 EADOGM_COLSPAN defined internally, allowing for
22 * 162 model to position correctly (noted by Imaginos, CCS forum)
23 * Added support for 2nd SPI HW port (suggested by Imaginos, CCS forum)
24 * defined a few more special chr's
25 * 07/12/2009 v1.11 Fixed #define error surrounding BB SPI ini
26 * added eaDogM_ClearRow(row);
27 * 07/11/2009 Created/Consolidated this file from my testing sets
28 *
29 * Usage:
30 * In your source, you need to define which EA DOGM display you are using,
32 * define with a 1.
33 *
34 * #define EADOGM081 1 // to use MODEL EADOG081
35 * #define EADOGM162 1 // to use MODEL EADOG162
36 * #define EADOGM163 1 // to use MODEL EADOG163
37 * #define EADOGMVDD 5 // 5v LCD Vdd
38 * //#define EADOGMVDD 3 // 3.3v LCD Vdd
39 *
40 *
41 * // we need to define the IO mode we want, select only one of these, set to 1
42 * #define EADOGM_SPI_HW 1 // hw spi, uses on chip spi
43 * #define EADOGM_SPI_HW 2 // hw spi, 2nd on chip spi
44 * #define EADOGM_SPI_DIV SPI_CLK_DIV_64 // used to slow hw spi clock (you can use other constants)
45 * #define EADOGM_SPI_SW 1 // sw bit bang, can use any io pins
46 * #define EADOGM_8BIT 1 // 8 bit data bus
47 *
48 * // for 8Bit mode only, we need to define the output port
49 * // however, this can be our own function if need be.
50 * // example shows output to port b
51 * #define EADOGM_8BIT_PORT(d) output_b(d); // we need to define how the byte goes out
52 * //#define EADOGM_8BIT_PORT(d) your_func(d); // we need to define how the byte goes out
53 *
54 *
55 * // we need to define a few pins
56 * #define EADOGM_PIN_RS PIN_C1 // RS line, (pin 39 on the LCD)
57 * #define EADOGM_PIN_CSB PIN_C2 // /CSB line, (pin 38 on the LCD) Req for SPI Opt for 8BIT
58 *
59 * // for 8 bit mode, we need to define a few more pins
60 * #define EADOGM_NOCSB 1 // set to 1 if pin 38 (CSB) on lcd is tied to Vss
61 * #define EADOGM_PIN_E PIN_C2 // E (pin 36 on the LCD)
62 * #define EADOGM_PIN_RW PIN_C6 // RW (pin 37 on the LCD)
63 *
64 * // set these if you are using EADOGM_SPI_SW (bit bang)
65 * #define EADOGM_SCLK_BB PIN_C3 // Connects to pin 29 on LCD
66 * #define EADOGM_MOSI_BB PIN_C5 // Connects to pin 28 on LCD
67 *
68 *
69 *
70 * #include "EA-DOGM_MIO.c"
71 *
72 * In your main code, do an ini call
73 * eaDogM_Initialize();
74 * eaDogM_DisplayOn();
75 *
76 *
77 * Available Functions:
78 * -------------------------------------------------------------------------------
79 * eaDogM_Cls(); // clears the screen, homes cursor
80 * eaDogM_ClearRow(row); // clears a row (v1.11)
81 * eaDogM_CursorOn(); // turns on the cursor
82 * eaDogM_CursorOff(); // turns of the cursor
83 * eaDogM_DisplayOn(); // turns on display with cursor off
84 * eaDogM_DisplayOff(); // turns off display
85 * eaDogM_SetPos(row, col); // sets position row:0-2, col:0-15
86 * eaDogM_WriteChr(byte); // writes a single chr to the display
87 * eaDogM_WriteString(char str); // writes a string to the display
88 * // note: add this line after device selection
89 * // to do this: eaDogM_WriteString("Constant")
90 * // #device PASS_STRINGS=IN_RAM
91 *
92 * // writes a 2 digit integer at row,col set flag = 1 to disable interrupts
93 * eaDogM_WriteIntAtPos(row,col,int[,flag])
94 *
95 * // writes a string at row,col set flag = 1 to disable interrupts
96 * eaDogM_WriteStringAtPos(row,col,char str[,flag])
97 *
98 * eaDogM_SetContrast(c); // set contrast 0 to 15
99 * eaDogM_DoubleHeight(row); // turn on double height, row = 0 or 1
100 * eaDogM_DoubleHeightOff(); // turn off double height
101 * -------------------------------------------------------------------------------
102 *
103 */
104
105
106
107 #ifndef EADOGM_SPI
108 #define EADOGM_SPI 1
109
110 // some special symbol chrs defined
111 #define EADMSYM_DEG 0b11011111 // degree symbol
112 #define EADMSYM_DARWL 0b11111011 // double <<
113 #define EADMSYM_DARWR 0b11111100 // double >>
114 #define EADMSYM_LT 0b00111100 // less than <
115 #define EADMSYM_GT 0b00111110 // greater than >
116 #define EADMSYM_OHM 0b00011110 // ohm symbol
117
118 // some command defines
119 #define EADMCMD_CONTRAST 0b0111000 // contrast command (0b0111xxxx)
120
121
122 // we noticed some issues with GLOBAL on pic24 devices
123 #ifndef GLOBAL
124 #define GLOBAL INTR_GLOBAL
125 #endif
126
127
128 // 1x16
130 #define EADOGM_ROWS 1
131 #if EADOGMVDD == 5
132 #define EADOGM_INIT_BIAS_SET 0x1C
133 #define EADOGM_INIT_POWER_CONTROL 0x51
134 #define EADOGM_INIT_FOLLOWER_CONTROL 0x6A
135 #define EADOGM_INIT_CONTRAST_SET 0x74
136 #else
137 #define EADOGM_INIT_BIAS_SET 0x14
138 #define EADOGM_INIT_POWER_CONTROL 0x55
139 #define EADOGM_INIT_FOLLOWER_CONTROL 0x6D
140 #define EADOGM_INIT_CONTRAST_SET 0x7C
141 #endif
142
143 #define EADOGM_INIT_FS1 0x31
144 #define EADOGM_INIT_FS2 0x30
145 #define EADOGM_INIT_CLEAR_DISPLAY 0x01
146 #define EADOGM_INIT_ENTRY_MODE 0x06
147 #define EADOGM_COLSPAN 16
148 #endif
149
150
151 // 2x16
153 #define EADOGM_ROWS 2
154 #if EADOGMVDD == 5
155 #define EADOGM_INIT_BIAS_SET 0x1C
156 #define EADOGM_INIT_POWER_CONTROL 0x52
157 #define EADOGM_INIT_FOLLOWER_CONTROL 0x69
158 #define EADOGM_INIT_CONTRAST_SET 0x74
159 #else
160 #define EADOGM_INIT_BIAS_SET 0x14
161 #define EADOGM_INIT_POWER_CONTROL 0x55
162 #define EADOGM_INIT_FOLLOWER_CONTROL 0x6D
163 #define EADOGM_INIT_CONTRAST_SET 0x78
164 #endif
165
166 #define EADOGM_INIT_FS1 0x39
167 #define EADOGM_INIT_FS2 0x38
168 #define EADOGM_INIT_CLEAR_DISPLAY 0x01
169 #define EADOGM_INIT_ENTRY_MODE 0x06
170 #define EADOGM_COLSPAN 40 // suggested that this be 40 on model 162
171 #endif
172
173 // 3x16
175 #define EADOGM_ROWS 3
176 #if EADOGMVDD == 5
177 #define EADOGM_INIT_BIAS_SET 0x1D
178 #define EADOGM_INIT_POWER_CONTROL 0x50
179 #define EADOGM_INIT_FOLLOWER_CONTROL 0x6C
180 #define EADOGM_INIT_CONTRAST_SET 0x7C
181 #else
182 #define EADOGM_INIT_BIAS_SET 0x15
183 #define EADOGM_INIT_POWER_CONTROL 0x55
184 #define EADOGM_INIT_FOLLOWER_CONTROL 0x6E
185 #define EADOGM_INIT_CONTRAST_SET 0x72
186 #endif
187
188 #define EADOGM_INIT_FS1 0x39
189 #define EADOGM_INIT_FS2 0x38
190 #define EADOGM_INIT_CLEAR_DISPLAY 0x01
191 #define EADOGM_INIT_ENTRY_MODE 0x06
192 #define EADOGM_COLSPAN 16
193 #endif
194
195
196 #define EADOGM_CMD_CLR 1
197 #define EADOGM_CMD_CURSOR_ON 0b00001111
198 #define EADOGM_CMD_CURSOR_OFF 0b00001100
199 #define EADOGM_CMD_DISPLAY_ON 0b00001100
200 #define EADOGM_CMD_DISPLAY_OFF 0b00001000
201 #define EADOGM_CMD_DDRAM_ADDR 0b10000000
202 #define EADOGM_CMD_CGRAM_ADDR 0b01000000
203 #define EADOGM_CMD_SELECT_R0 0b00011000
204 #define EADOGM_CMD_SELECT_R1 0b00010000
205 #define EADOGM_CMD_SET_TABLE2 0b00101010
206
207
208 // spi hw clock div, v2.03 fix
209 #ifndef EADOGM_SPI_DIV
210 #define EADOGM_SPI_DIV SPI_CLK_DIV_4
211 #endif
212
213
214
215 // sw spi emulation routine (bit bang)
216 #ifdef EADOGM_SPI_SW
217 #ifndef EADOGM_SCLK_BB
218 #define EADOGM_SCLK_BB PIN_C3
219 #endif
220 #ifndef EADOGM_MOSI_BB
221 #define EADOGM_MOSI_BB PIN_C5
222 #endif
223
224
225 void eaDogM_iniSPI_BB(void)
226 {
227 output_drive(EADOGM_SCLK_BB);
228 output_drive(EADOGM_MOSI_BB);
229 output_low(EADOGM_SCLK_BB);
230 output_low(EADOGM_MOSI_BB);
231 }
232
233 void eaDogM_spiWrite_BB(int8 regData)
234 {
235
236 int1 bitOut;
237 int8 SPICount; // Counter used to clock out the data
238 int8 SPIData; // Define a data structure for the SPI data.
239
240 output_low(EADOGM_SCLK_BB); // and CK low
241
242 SPIData = regData;
243 for (SPICount = 0; SPICount < 8; SPICount++) // Prepare to clock out the Address byte
244 {
245 bitOut = bit_test(SPIData,7);
246 output_bit(EADOGM_MOSI_BB,bitOut);
247 output_high(EADOGM_SCLK_BB); // Toggle the clock line
248 //delay_us(10);
249 output_low(EADOGM_SCLK_BB);
250 //delay_us(10);
251 SPIData = SPIData << 1; // Rotate to get the next bit
252 } // and loop back to send the next bit
253
254 output_low(EADOGM_MOSI_BB);
255 }
256
257 // wrapper for sw spi calls in main program
258 // v2.01 moved to macro define
259 #define eaDogM_outSPI(c) eaDogM_spiWrite_BB(c)
260 #endif
261
262 // wrapper for hw spi calls in main program
263 // v2.01 moved to a macro define
264 #if EADOGM_SPI_HW == 1
265 #define eaDogM_outSPI(c) spi_write(c)
266 #endif
267
268 // wrapper for hw2 spi calls in main program
269 // v2.01 moved to a macro define, v2.03 using EADOGM_SPI_HW to test condition
270 #if EADOGM_SPI_HW == 2
271 #define eaDogM_outSPI(c) spi_write2(c)
272 #endif
273
274
275 #ifdef EADOGM_8BIT
276 void eaDogM_ini8Bit(void)
277 {
278 #ifndef EADOGM_NOCSB
279 output_drive(EADOGM_PIN_CSB);
280 output_high(EADOGM_PIN_CSB);
281 #endif
282 output_drive(EADOGM_PIN_E);
283 output_drive(EADOGM_PIN_RW);
284 output_drive(EADOGM_PIN_RS);
285 output_low(EADOGM_PIN_E);
286 output_low(EADOGM_PIN_RS);
287 output_low(EADOGM_PIN_RW);
288 }
289 #endif
290
291
292
293 #ifdef EADOGM_8BIT
294 // 8bit mode
295 void eaDogM_WriteChr(char value)
296 {
297 output_high(EADOGM_PIN_RS);
298 output_low(EADOGM_PIN_RW);
299 output_low(EADOGM_PIN_E);
300 #ifndef EADOGM_NOCSB
301 output_low(EADOGM_PIN_CSB);
302 #endif
303 output_high(EADOGM_PIN_E);
304 delay_ms(1);
305 EADOGM_8BIT_PORT(value);
306 output_low(EADOGM_PIN_E);
307 delay_ms(1);
308 #ifndef EADOGM_NOCSB
309 output_low(EADOGM_PIN_CSB);
310 #endif
311 delay_ms(1);
312 }
313
314 void eaDogM_WriteCommand(int8 cmd)
315 {
316 output_low(EADOGM_PIN_RS);
317 output_low(EADOGM_PIN_RW);
318 output_low(EADOGM_PIN_E);
319 #ifndef EADOGM_NOCSB
320 output_low(EADOGM_PIN_CSB);
321 #endif
322 output_high(EADOGM_PIN_E);
323 delay_ms(1);
324 EADOGM_8BIT_PORT(cmd);
325 output_low(EADOGM_PIN_E);
326 delay_ms(1);
327 #ifndef EADOGM_NOCSB
328 output_low(EADOGM_PIN_CSB);
329 #endif
330 delay_ms(1);
331 }
332 #else
333 // spi mode
334 void eaDogM_WriteChr(char value)
335 {
336 output_high(EADOGM_PIN_RS);
337 output_low(EADOGM_PIN_CSB);
338 eaDogM_outSPI(value);
339 output_high(EADOGM_PIN_CSB);
340 delay_ms(1);
341 }
342
343 void eaDogM_WriteCommand(int8 cmd)
344 {
345 output_low(EADOGM_PIN_RS);
346 output_low(EADOGM_PIN_CSB);
347 eaDogM_outSPI(cmd);
348 output_high(EADOGM_PIN_CSB);
349 delay_ms(1);
350 }
351 #endif
352
353
354 void eaDogM_Initialize(void)
355 {
356
357 // v2.03 fix
358 #if EADOGM_SPI_HW == 1
359 setup_spi( SPI_MASTER | SPI_H_TO_L | EADOGM_SPI_DIV );
360 #endif
361
362 // v2.03 fix
363 #if EADOGM_SPI_HW == 2
364 setup_spi2( SPI_MASTER | SPI_H_TO_L | EADOGM_SPI_DIV );
365 #endif
366
367 #ifdef EADOGM_SPI_SW
368 eaDogM_iniSPI_BB();
369 #endif
370
371 #ifdef EADOGM_8BIT
372 eaDogM_ini8Bit();
373 #else
374 output_drive(EADOGM_PIN_CSB);
375 output_drive(EADOGM_PIN_RS);
376 output_high(EADOGM_PIN_CSB);
377 output_high(EADOGM_PIN_RS);
378 #endif
379
380 delay_ms(200);
381
382 eaDogM_WriteCommand(EADOGM_INIT_FS1);
383 eaDogM_WriteCommand(EADOGM_INIT_BIAS_SET);
384 eaDogM_WriteCommand(EADOGM_INIT_POWER_CONTROL);
385 eaDogM_WriteCommand(EADOGM_INIT_FOLLOWER_CONTROL);
386 eaDogM_WriteCommand(EADOGM_INIT_CONTRAST_SET);
387 eaDogM_WriteCommand(EADOGM_INIT_FS2);
388 eaDogM_WriteCommand(EADOGM_INIT_CLEAR_DISPLAY);
389 eaDogM_WriteCommand(EADOGM_INIT_ENTRY_MODE);
390
391 }
392
393 // sets contrast, call with a value from 0 to 15
394 // we also mask off upper 4 bits from c
395 // v2.01 moved to a macro define
396 #define eaDogM_SetContrast(c) eaDogM_WriteCommand(EADMCMD_CONTRAST + (c & 0b00001111))
397
398 // only tested on 3 line display at the moment,
399 // thus no constants defined. when fully tested, I will define them
400 void eaDogM_DoubleHeight(int8 row) // row 0 or 1
401 {
402 eaDogM_WriteCommand(EADOGM_CMD_SET_TABLE2); // set instruction table 2
403 if (row == 0) {
404 eaDogM_WriteCommand(EADOGM_CMD_SELECT_R0); // select row 0
405 }
406 if (row == 1) {
407 eaDogM_WriteCommand(EADOGM_CMD_SELECT_R1); // select row 1
408 }
409 eaDogM_WriteCommand(0b00101100); // turns on double line mode
410 // and set instruction table back to 0
411 }
412
413 // v2.01 moved functions to macros
414 #define eaDogM_DoubleHeightOff() eaDogM_WriteCommand(0b00101000)
415 #define eaDogM_Cls() eaDogM_WriteCommand(EADOGM_CMD_CLR)
416 #define eaDogM_CursorOn() eaDogM_WriteCommand(EADOGM_CMD_CURSOR_ON)
417 #define eaDogM_CursorOff() eaDogM_WriteCommand(EADOGM_CMD_CURSOR_OFF)
418 #define eaDogM_DisplayOn() eaDogM_WriteCommand(EADOGM_CMD_DISPLAY_ON)
419 #define eaDogM_DisplayOff() eaDogM_WriteCommand(EADOGM_CMD_DISPLAY_OFF)
420
421
422 void eaDogM_SetPos(int8 r, int8 c)
423 {
424 int8 cmdPos;
425 cmdPos = EADOGM_CMD_DDRAM_ADDR + (r * EADOGM_COLSPAN) + c;
426 eaDogM_WriteCommand(cmdPos);
427 }
428
429 void eaDogM_ClearRow(int8 r)
430 {
431 int8 i;
432 eaDogM_SetPos(r,0);
433 for(i=0; i<EADOGM_COLSPAN; i++) {
434 eaDogM_WriteChr(' ');
435 }
436 }
437
438 void eaDogM_WriteString(char *strPtr)
439 {
440 printf(eaDogM_WriteChr,"%s",strPtr);
441 }
442
443
444 // Optional DisGIE, set to 1 to disable interrupts
445 // v1.4 -- provided by Imaginos
446 void eaDogM_WriteStringAtPos(int8 r, int8 c, char *strPtr, int1 DisGIE=0)
447 {
448 if (DisGIE) {
449 disable_interrupts(GLOBAL);
450 }
451
452 eaDogM_WriteCommand((EADOGM_CMD_DDRAM_ADDR + (r * EADOGM_COLSPAN) + c));
453 printf(eaDogM_WriteChr,"%s",strPtr);
454
455 if (DisGIE) {
456 enable_interrupts(GLOBAL);
457 }
458 }
459
460 // Optional DisGIE, set to 1 to disable interrupts
461 // v1.4 -- provided by Imaginos
462 void eaDogM_WriteIntAtPos(int8 r, int8 c, int8 i, int1 DisGIE=0)
463 {
464 if (DisGIE) {
465 disable_interrupts(GLOBAL);
466 }
467
468 eaDogM_WriteCommand((EADOGM_CMD_DDRAM_ADDR + (r * EADOGM_COLSPAN) + c));
469
470 eaDogM_WriteChr(i/10+'0');
471 eaDogM_WriteChr(i%10+'0');
472
473 if (DisGIE) {
474 enable_interrupts(GLOBAL);
475 }
476 }
477
478 // this writes a byte to the internal CGRAM (v2.02)
479 // format for ndx: 00CCCRRR = CCC = character 0 to 7, RRR = row 0 to 7
480 void eaDogM_WriteByteToCGRAM(char ndx, char data)
481 {
482 unsigned int cmd;
483
484 cmd = ndx & 0b00111111; // mask off upper to bits
485 cmd = cmd | EADOGM_CMD_CGRAM_ADDR; // set bit cmd bits
486
487 eaDogM_WriteCommand(cmd);
488 eaDogM_WriteChr(data);
489
490 // this is done to make sure we are back in data mode
491 eaDogM_SetPos(0,0);
492 }
493
494
495 #endif
496