eadogm.c


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,
31
 *   there are 3 units supported EADOGM081 , EADOGM162 , EADOGM163 To use
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
#define EADOGM162 1  // to use MODEL EADOG162 
107
#define EADOGM_SPI_SW 1
108
109
110
111
112
#define EADOGMVDD  5
113
#define EADOGM_SPI_HW  0
114
115
#ifndef EADOGM_SPI
116
   #define EADOGM_SPI 1
117
118
// some special symbol chrs defined
119
#define EADMSYM_DEG     0b11011111     // degree symbol
120
#define EADMSYM_DARWL   0b11111011     // double <<
121
#define EADMSYM_DARWR   0b11111100     // double >>
122
#define EADMSYM_LT      0b00111100     // less than <
123
#define EADMSYM_GT      0b00111110     // greater than >
124
#define EADMSYM_OHM     0b00011110     // ohm symbol
125
126
// some command defines
127
#define EADMCMD_CONTRAST 0b0111000      // contrast command (0b0111xxxx)
128
129
130
// we noticed some issues with GLOBAL on pic24 devices
131
#ifndef GLOBAL
132
  #define GLOBAL INTR_GLOBAL
133
#endif
134
135
136
// 1x16
137
#ifdef EADOGM081
138
   #define EADOGM_ROWS 1
139
   #if EADOGMVDD == 5
140
     #define EADOGM_INIT_BIAS_SET 0x1C
141
     #define EADOGM_INIT_POWER_CONTROL 0x51
142
     #define EADOGM_INIT_FOLLOWER_CONTROL 0x6A
143
  #define EADOGM_INIT_CONTRAST_SET 0x7C
144
   #else
145
     #define EADOGM_INIT_BIAS_SET 0x14
146
     #define EADOGM_INIT_POWER_CONTROL 0x55
147
     #define EADOGM_INIT_FOLLOWER_CONTROL 0x6D
148
     #define EADOGM_INIT_CONTRAST_SET 0x7C
149
   #endif
150
151
   #define EADOGM_INIT_FS1 0x31
152
   #define EADOGM_INIT_FS2 0x30
153
   #define EADOGM_INIT_CLEAR_DISPLAY 0x01
154
   #define EADOGM_INIT_ENTRY_MODE 0x06
155
   #define EADOGM_COLSPAN 16
156
#endif
157
158
159
// 2x16
160
#ifdef EADOGM162
161
   #define EADOGM_ROWS 2
162
    #if EADOGMVDD == 5
163
     #define EADOGM_INIT_BIAS_SET 0x1C
164
     #define EADOGM_INIT_POWER_CONTROL 0x52
165
     #define EADOGM_INIT_FOLLOWER_CONTROL 0x69
166
  #define EADOGM_INIT_CONTRAST_SET 0x74
167
   #else
168
     #define EADOGM_INIT_BIAS_SET 0x14
169
     #define EADOGM_INIT_POWER_CONTROL 0x55
170
     #define EADOGM_INIT_FOLLOWER_CONTROL 0x6D
171
     #define EADOGM_INIT_CONTRAST_SET 0x78
172
   #endif
173
174
   #define EADOGM_INIT_FS1 0x39
175
   #define EADOGM_INIT_FS2 0x38
176
   #define EADOGM_INIT_CLEAR_DISPLAY 0x01
177
   #define EADOGM_INIT_ENTRY_MODE 0x06
178
   #define EADOGM_COLSPAN 40  // suggested that this be 40 on model 162
179
#endif
180
181
// 3x16
182
#ifdef EADOGM163
183
   #define EADOGM_ROWS 3
184
    #if EADOGMVDD == 5
185
     #define EADOGM_INIT_BIAS_SET 0x1D
186
     #define EADOGM_INIT_POWER_CONTROL 0x50
187
     #define EADOGM_INIT_FOLLOWER_CONTROL 0x6C
188
     #define EADOGM_INIT_CONTRAST_SET 0x7C
189
   #else
190
     #define EADOGM_INIT_BIAS_SET 0x15
191
     #define EADOGM_INIT_POWER_CONTROL 0x55
192
     #define EADOGM_INIT_FOLLOWER_CONTROL 0x6E
193
     #define EADOGM_INIT_CONTRAST_SET 0x72
194
   #endif
195
196
   #define EADOGM_INIT_FS1 0x39
197
   #define EADOGM_INIT_FS2 0x38
198
   #define EADOGM_INIT_CLEAR_DISPLAY 0x01
199
   #define EADOGM_INIT_ENTRY_MODE 0x06
200
   #define EADOGM_COLSPAN 16
201
#endif
202
203
204
#define EADOGM_CMD_CLR 1
205
#define EADOGM_CMD_CURSOR_ON     0b00001111
206
#define EADOGM_CMD_CURSOR_OFF    0b00001100
207
#define EADOGM_CMD_DISPLAY_ON    0b00001100
208
#define EADOGM_CMD_DISPLAY_OFF   0b00001000
209
#define EADOGM_CMD_DDRAM_ADDR    0b10000000
210
#define EADOGM_CMD_CGRAM_ADDR    0b01000000
211
#define EADOGM_CMD_SELECT_R0     0b00011000
212
#define EADOGM_CMD_SELECT_R1     0b00010000
213
#define EADOGM_CMD_SET_TABLE2    0b00101010
214
215
216
// spi hw clock div, v2.03 fix
217
#ifndef EADOGM_SPI_DIV
218
   #define EADOGM_SPI_DIV SPI_CLK_DIV_4
219
#endif
220
221
222
223
// sw spi emulation routine (bit bang)
224
#ifdef EADOGM_SPI_SW
225
   #ifndef EADOGM_SCLK_BB
226
     #define EADOGM_SCLK_BB PIN_C3
227
   #endif
228
   #ifndef EADOGM_MOSI_BB
229
     #define EADOGM_MOSI_BB PIN_C5
230
   #endif
231
232
233
234
void eaDogM_iniSPI_BB(void)
235
{
236
   output_drive(EADOGM_SCLK_BB);
237
   output_drive(EADOGM_MOSI_BB);
238
   output_low(EADOGM_SCLK_BB);
239
   output_low(EADOGM_MOSI_BB);
240
}
241
242
void eaDogM_spiWrite_BB(int8 regData)
243
{
244
245
  int1 bitOut;
246
  int8 SPICount;                               // Counter used to clock out the data
247
  int8 SPIData;                                // Define a data structure for the SPI data.
248
249
  output_low(EADOGM_SCLK_BB);                         // and CK low
250
251
  SPIData = regData;
252
  for (SPICount = 0; SPICount < 8; SPICount++) // Prepare to clock out the Address byte
253
    {
254
    bitOut = bit_test(SPIData,7);
255
    output_bit(EADOGM_MOSI_BB,bitOut);
256
    output_high(EADOGM_SCLK_BB);                      // Toggle the clock line
257
    delay_us(10);
258
    output_low(EADOGM_SCLK_BB);
259
    delay_us(10);
260
    SPIData = SPIData << 1;                    // Rotate to get the next bit
261
    }                                          // and loop back to send the next bit
262
263
  output_low(EADOGM_MOSI_BB);
264
}
265
266
// wrapper for sw spi calls in main program
267
// v2.01 moved to macro define
268
#define eaDogM_outSPI(c) eaDogM_spiWrite_BB(c)
269
#endif
270
271
272
// wrapper for hw spi calls in main program
273
// v2.01 moved to a macro define
274
#if EADOGM_SPI_HW == 1
275
   #define eaDogM_outSPI(c) spi_write(c)
276
#endif
277
278
// wrapper for hw2 spi calls in main program
279
// v2.01 moved to a macro define, v2.03 using EADOGM_SPI_HW to test condition
280
#if EADOGM_SPI_HW == 2
281
   #define eaDogM_outSPI(c) spi_write2(c)
282
#endif
283
284
285
#ifdef EADOGM_8BIT
286
void eaDogM_ini8Bit(void)
287
{
288
#ifndef EADOGM_NOCSB
289
   output_drive(EADOGM_PIN_CSB);
290
   output_high(EADOGM_PIN_CSB);
291
#endif
292
   output_drive(EADOGM_PIN_E);
293
   output_drive(EADOGM_PIN_RW);
294
   output_drive(EADOGM_PIN_RS);
295
   output_low(EADOGM_PIN_E);
296
   output_low(EADOGM_PIN_RS);
297
   output_low(EADOGM_PIN_RW);
298
}
299
#endif
300
301
// v2.01 moved functions to macros
302
#define eaDogM_DoubleHeightOff() eaDogM_WriteCommand(0b00101000)
303
#define eaDogM_Cls()             eaDogM_WriteCommand(EADOGM_CMD_CLR)
304
#define eaDogM_CursorOn()        eaDogM_WriteCommand(EADOGM_CMD_CURSOR_ON)
305
#define eaDogM_CursorOff()       eaDogM_WriteCommand(EADOGM_CMD_CURSOR_OFF)
306
#define eaDogM_DisplayOn()       eaDogM_WriteCommand(EADOGM_CMD_DISPLAY_ON)
307
#define eaDogM_DisplayOff()      eaDogM_WriteCommand(EADOGM_CMD_DISPLAY_OFF)
308
309
310
#ifdef EADOGM_8BIT
311
// 8bit mode
312
void eaDogM_WriteChr(char value)
313
{
314
   output_high(EADOGM_PIN_RS);
315
   output_low(EADOGM_PIN_RW);
316
   output_low(EADOGM_PIN_E);
317
   #ifndef EADOGM_NOCSB
318
     output_low(EADOGM_PIN_CSB);
319
     #endif
320
   output_high(EADOGM_PIN_E);
321
   delay_ms(1);
322
   EADOGM_8BIT_PORT(value);
323
   output_low(EADOGM_PIN_E);
324
   delay_ms(1);
325
   #ifndef EADOGM_NOCSB
326
     output_low(EADOGM_PIN_CSB);
327
     #endif
328
   delay_ms(1);
329
}
330
331
void eaDogM_WriteCommand(int8 cmd)
332
{
333
   output_low(EADOGM_PIN_RS);
334
   output_low(EADOGM_PIN_RW);
335
   output_low(EADOGM_PIN_E);
336
   #ifndef EADOGM_NOCSB
337
     output_low(EADOGM_PIN_CSB);
338
     #endif
339
   output_high(EADOGM_PIN_E);
340
   delay_ms(1);
341
   EADOGM_8BIT_PORT(cmd);
342
   output_low(EADOGM_PIN_E);
343
   delay_ms(1);
344
   #ifndef EADOGM_NOCSB
345
     output_low(EADOGM_PIN_CSB);
346
     #endif
347
   delay_ms(1);
348
}
349
#else
350
// spi mode
351
352
void eaDogM_WriteCommand(int8 cmd)
353
{
354
   output_low(EADOGM_PIN_RS);
355
   output_low(EADOGM_PIN_CSB);
356
   eaDogM_outSPI(cmd);
357
   output_high(EADOGM_PIN_CSB);
358
   delay_ms(1);
359
}
360
361
362
void eaDogM_SetPos(int8 r, int8 c)
363
{
364
   int8 cmdPos;
365
   cmdPos = EADOGM_CMD_DDRAM_ADDR + (r * EADOGM_COLSPAN) + c;
366
   eaDogM_WriteCommand(cmdPos);
367
}
368
369
void eaDogM_WriteChr(char value)
370
{
371
  switch (value)
372
  {
373
    case '\f':
374
      eaDogM_Cls();
375
      delay_ms(2);
376
      break;
377
    case '\n':
378
      eaDogM_SetPos(1,0);
379
      delay_ms(2);
380
      break;
381
  default:
382
    output_high(EADOGM_PIN_RS);
383
    output_low(EADOGM_PIN_CSB);
384
    eaDogM_outSPI(value);
385
    output_high(EADOGM_PIN_CSB);
386
    delay_ms(2);
387
  }
388
}
389
390
#endif
391
392
393
void eaDogM_Initialize(void)
394
{
395
396
// v2.03 fix
397
#if EADOGM_SPI_HW  == 1
398
   setup_spi( SPI_MASTER | SPI_H_TO_L | EADOGM_SPI_DIV );
399
#endif
400
401
// v2.03 fix
402
#if EADOGM_SPI_HW  == 2
403
   setup_spi2( SPI_MASTER | SPI_H_TO_L | EADOGM_SPI_DIV );
404
#endif
405
406
#ifdef EADOGM_SPI_SW
407
   eaDogM_iniSPI_BB();
408
#endif
409
410
#ifdef EADOGM_8BIT
411
   eaDogM_ini8Bit();
412
#else
413
   output_drive(EADOGM_PIN_CSB);
414
   output_drive(EADOGM_PIN_RS);
415
   output_high(EADOGM_PIN_CSB);
416
   output_high(EADOGM_PIN_RS);
417
#endif
418
419
   delay_ms(200);
420
421
   eaDogM_WriteCommand(EADOGM_INIT_FS1);
422
   eaDogM_WriteCommand(EADOGM_INIT_BIAS_SET);
423
   eaDogM_WriteCommand(EADOGM_INIT_POWER_CONTROL);
424
   eaDogM_WriteCommand(EADOGM_INIT_FOLLOWER_CONTROL);
425
   eaDogM_WriteCommand(EADOGM_INIT_CONTRAST_SET);
426
   eaDogM_WriteCommand(EADOGM_INIT_FS2);
427
   eaDogM_WriteCommand(EADOGM_INIT_CLEAR_DISPLAY);
428
   eaDogM_WriteCommand(EADOGM_INIT_ENTRY_MODE);
429
430
}
431
432
// sets contrast, call with a value from 0 to 15
433
// we also mask off upper 4 bits from c
434
// v2.01 moved to a macro define
435
#define eaDogM_SetContrast(c) eaDogM_WriteCommand(EADMCMD_CONTRAST + (c & 0b00001111))
436
437
// only tested on 3 line display at the moment,
438
// thus no constants defined. when fully tested, I will define them
439
void eaDogM_DoubleHeight(int8 row) // row 0 or 1
440
{
441
   eaDogM_WriteCommand(EADOGM_CMD_SET_TABLE2); // set instruction table 2
442
   if (row == 0) {
443
     eaDogM_WriteCommand(EADOGM_CMD_SELECT_R0); // select row 0
444
     }
445
   if (row == 1) {
446
     eaDogM_WriteCommand(EADOGM_CMD_SELECT_R1); // select row 1
447
     }
448
   eaDogM_WriteCommand(0b00101100); // turns on double line mode
449
                                    // and set instruction table back to 0
450
}
451
452
void eaDogM_ClearRow(int8 r)
453
{
454
   int8 i;
455
   eaDogM_SetPos(r,0);
456
   for(i=0; i<EADOGM_COLSPAN; i++) {
457
     eaDogM_WriteChr(' ');
458
   }
459
}
460
461
void eaDogM_WriteString(char *strPtr)
462
{
463
   printf(eaDogM_WriteChr,"%s",strPtr);
464
}
465
466
467
// Optional DisGIE, set to 1 to disable interrupts
468
// v1.4 -- provided by Imaginos
469
void eaDogM_WriteStringAtPos(int8 r, int8 c, char *strPtr, int1 DisGIE=0)
470
{
471
   if (DisGIE) {
472
      disable_interrupts(GLOBAL);
473
      }
474
475
   eaDogM_WriteCommand((EADOGM_CMD_DDRAM_ADDR + (r * EADOGM_COLSPAN) + c));
476
   printf(eaDogM_WriteChr,"%s",strPtr);
477
478
   if (DisGIE) {
479
      enable_interrupts(GLOBAL);
480
      }
481
}
482
483
// Optional DisGIE, set to 1 to disable interrupts
484
// v1.4 -- provided by Imaginos
485
void eaDogM_WriteIntAtPos(int8 r, int8 c, int8 i, int1 DisGIE=0)
486
{
487
   if (DisGIE) {
488
      disable_interrupts(GLOBAL);
489
      }
490
491
   eaDogM_WriteCommand((EADOGM_CMD_DDRAM_ADDR + (r * EADOGM_COLSPAN) + c));
492
493
   eaDogM_WriteChr(i/10+'0');
494
   eaDogM_WriteChr(i%10+'0');
495
496
   if (DisGIE) {
497
      enable_interrupts(GLOBAL);
498
      }
499
}
500
501
// this writes a byte to the internal CGRAM (v2.02)
502
// format for ndx: 00CCCRRR = CCC = character 0 to 7, RRR = row 0 to 7
503
void eaDogM_WriteByteToCGRAM(char ndx, char data)
504
{
505
   unsigned int cmd;
506
507
   cmd = ndx & 0b00111111; // mask off upper to bits
508
   cmd = cmd | EADOGM_CMD_CGRAM_ADDR; // set bit cmd bits
509
510
   eaDogM_WriteCommand(cmd);
511
   eaDogM_WriteChr(data);
512
513
   // this is done to make sure we are back in data mode
514
   eaDogM_SetPos(0,0);
515
}