Contents of file 'dogm16x.c':
1 /*=============================================================================
2 * File: dogm16x.c
3 * Created: September 12, 2010 [v.1.0]
4 * Last change: September 3, 2011 [v.1.4]
5 * Author: Fredrik Jonsson <http://jonsson.eu/>
6 *
7 * Copyright (C) 2011, Fredrik Jonsson <http://jonsson.eu/>
8 * Non-commercial copying welcome.
9 *
10 * Summary
11 *
12 * The set of routines in dogm16x.c provides a driver for the Electronic
13 * Assembly DOG-M family of LCD displays [1,2] for the Microchip PIC32
14 * microcontroller, employing the Parallel Master Port (PMP), with data
15 * on pins PMD0-PMD7 and PMP control signals on pins PMWR, PMRD and PMA0.
16 *
17 * Hardware connections
18 *
19 * The connections between the Parallel Master Port (PMP, data on pins
20 * PMD0-PMD7; PMP control signals on pins PMWR, PMRD, and PMA0) of the
21 * PIC32MX processor and the Electronic Assembly DOGM display are as
22 * follows:
23 *
24 * PIC32 pin OLIMEX PCB LCD pin
25 * --------------------------------------------------------------------------
26 * PMD7 --- RE7 --- 28 (D7) Display data, MSB
27 * PMD6 --- RE6 --- 29 (D6) Display data
28 * PMD5 --- RE5 --- 30 (D5) Display data
29 * PMD4 --- RE4 --- 31 (D4) Display data
30 * PMD3 --- RE3 --- 32 (D3) Display data
31 * PMD2 --- RE2 --- 33 (D2) Display data
32 * PMD1 --- RE1 --- 34 (D1) Display data
33 * PMD0 --- RE0 --- 35 (D0) Display data, LSB
34 * PMWR --- RD4 --- 36 (E) Enable, falling edge
35 * PMRD --- RD5 --- 37 (R/W) Low=Write, High=Read
36 * PMA0 --- RB15 --- 39 (RS) Low=Control, High=Data
37 *
38 * In addition, the following connections to the LCD provide power supply and
39 * proper ground:
40 * PIC32 pin OLIMEX PCB LCD pin
41 * GROUND --- 38 (CSB) Chip select
42 * GROUND --- 27 (VSS) Power supply, 0V
43 * +3.3V --- 26 (VDD) Power supply, +3.3V
44 * +3.3V --- 25 (VIN)
45 * +3.3V --- 23 (PSB)
46 * +3.3V --- 40 (RESET)
47 * +3.3V --- X ohm resistor --- 20 Power supply 3.3V, illumination
48 * +3.3V --- X ohm resistor --- 1 Power supply 3.3V, illumination
49 * GROUND --- 2 (VSS) Power supply 0V, illumination
50 * GROUND --- 19 (VSS) Power supply 0V, illumination
51 * |------------ 21 (CAP1N)
52 * === 2.2 uF Capacitor
53 * |------------ 22 (CAP1P)
54 * |------------ 24 (VOUT)
55 * === 2.2 uF
56 * +3.3V -------|
57 *
58 * Installing the driver as a shared library
59 *
60 * See enclosed file README.txt.
61 *
62 * Examples of usage
63 *
64 * Example 1. High-level usage of the library, writing entire strings of data:
65 *
66 * char buf[128];
67 * float x=0.4711;
68 * write_string_to_display("Hello World!\n");
69 * sprintf(buf,"sin(%f)=%f\n",x,sin(x));
70 * write_string_to_display(buf);
71 *
72 * Example 2. Low-level usage of the library, writing individual characters
73 * and positioning the cursor by direct access to the LCD registers:
74 *
75 * write_to_display_register(LCDCMD,0x80|0x00); // Set position to 1st row, 1st col
76 * write_to_display_register(LCDDATA,'A'); // Write 'A' at 1st row, 1st col
77 * write_to_display_register(LCDCMD,0x80|0x00); // Reposition to 1st row, 1st col
78 * write_to_display_register(LCDDATA,'B'); // Overwrites the previous 'A'
79 * write_to_display_register(LCDDATA,'C'); // Writes a 'C' next after the 'B'
80 * write_to_display_register(LCDCMD,0x80|0x05); // Reposition to 1st row, 6th col
81 * write_to_display_register(LCDDATA,'D'); // Writes a 'C' at 1st row, 5th col
82 * write_to_display_register(LCDDATA,'E'); // Writes a 'E' next after the 'D'
83 * write_to_display_register(LCDCMD,0x80|0x10); // Set position to 2nd row, 1st col
84 * write_to_display_register(LCDDATA,'G'); // Write 'G' at 1st row, 1st col
85 * sprintf(buf,"%d",read_display_register(0x02)&0x7f);
86 * write_string_to_display(buf);
87 *
88 *
89 * [1] See the Electronic Assembly web site on their display-on-glass (DOG)
90 * series at http://www.lcd-module.com/products/dog.html
91 * [2] For suppliers of the Electronic Assembly DOG-M series and corresponding
92 * backlights, see https://www.elfa.se/elfa3~se_en/elfa/init.do?query=DC-76206&in=fam
93 * (display) and https://www.elfa.se/elfa3~se_en/elfa/init.do?query=DC-76207&in=fam
94 * (backlight modules).
95 *===========================================================================*/
96 #include <p32xxxx.h> /* Microchip PIC32-family specifics/generics */
97 #include <plib.h> /* To access the PIC32 Peripheral Library */
98 #include "dogm16x.h"
99
100 /*
101 * Directly from the PIC32 Family Reference Manual [1]: The Parallel Master
102 * Port (PMP) is a parallel 8-bit/16-bit I/O module specifically designed to
103 * communicate with a wide variety of parallel devices such as communications
104 * peripherals, LCDs, external memory devices and microcontrollers. Because
105 * the interfaces to parallel peripherals vary significantly, the PMP module
106 * is highly configurable.
107 *
108 * The driver makes use of the Parallell Master Port (PMP) in Master mode (mode
109 * set by PMP_MASTER_1), in which the following Special Function Registers
110 * (SFRs) apply:
111 *
112 * PMCON: Parallel Port Control Register
113 * This register (Register 13-1) contains the bits that control much of the
114 * module?s basic functionality. A key bit is the ON control bit, which is
115 * used to Reset, enable or disable the module. When the module is disabled,
116 * all of the associated I/O pins revert to their designated I/O function.
117 * In addition, any read or write operations active or pending are stopped,
118 * and the BUSY bit is cleared. The data within the module registers is
119 * retained, including the data in PMSTAT register. Therefore, the module
120 * could be disabled after a reception, and the last received data and status
121 * would still be available for processing. When the module is enabled, all
122 * buffer control logic is reset, along with PMSTAT. All other bits in PMCON
123 * control address multiplexing, enable various port control signals, and
124 * select control signal polarity. For futher details, see PIC32 Family
125 * Reference Manual [1] Chapter 13.3.1 ?Parallel Master Port Configuration
126 * Options?.
127 *
128 * PMMODE: Parallel Port Mode Register
129 * This register (Register 13-2) contains bits that control the operational
130 * modes of the module. Master/Slave mode selection, as well as configuration
131 * options for both modes, are set by this register. It also contains the
132 * universal status flag BUSY, used in Master modes to indicate that an
133 * operation by the module in progress. For futher details, see PIC32 Family
134 * Reference Manual [1], Chapters 13.4 ?Slave Modes of Operation? and 13.3
135 * ?Master Modes of Operation?.
136 *
137 * PMADDR: Parallel Port Address Register
138 * This register (Register 13-3) functions as PMADDR in master modes. It
139 * contains the address to which outgoing data is to be written, as well
140 * as the Chip Select control bits for addressing parallel slave devices.
141 * The PMADDR register is not used in any of the Slave modes.
142 *
143 * PMAEN: Parallel Port Pin Enable Register
144 * This register (Register 13-6) controls the operation of address and Chip
145 * Select pins associated to this module. Setting these bits allocates the
146 * corresponding microcontroller pins to the PMP module; clearing the bits
147 * allocates the pins to port I/O or other peripheral modules associated
148 * with the pin.
149 */
150
151 /*
152 * In order to avoid any conflicts with these settings (via pragmas),
153 * ensure that the MPLAB IDE settings are Configure -> Configuration
154 * Bits -> Configuration Bits set in code.
155 *
156 * For details on these config settings for the oscillator frequency
157 * dividers of the PIC32MX, see Di Lucio page 151.
158 */
159 #pragma config POSCMOD=XT, FNOSC=PRIPLL
160 #pragma config FPLLIDIV=DIV_2, FPLLMUL=MUL_18, FPLLODIV=DIV_1
161 #pragma config FPBDIV=DIV_2, FWDTEN=OFF, CP=OFF, BWP=OFF
162
163 #undef FPB
164 #define FPB (36000000L)
165 void delayms(unsigned t)
166 {
167 int fpbthresh=FPB/1000;
168 T1CON = 0x8000; /* Enable TMR1, Tpb, 1:1 */
169 while (t--) { /* t x 1ms loop */
170 TMR1 = 0;
171 while (TMR1 < fpbthresh);
172 }
173 }
174 #undef FPB
175
176 int row, col;
177
178 /*
179 * The initialize_display() routine performs the initialization of the Parallel Master
180 * Port (PMP) key parameters of the Microchip PIC32MX (here PIC32MX340F512)
181 * using the mPMPOpen() macro as defined in pmp.h [1].
182 *
183 * The significance of the bits of the PMCON (Parallel Port Control Register)
184 * are as follows:
185 *
186 * bit 31-16 Reserved: Write ?0?; ignore read
187 *
188 * bit 15 ON: Parallel Master Port Enable bit
189 * 1 = PMP enabled
190 * 0 = PMP disabled, no off-chip access performed
191 * Note: When using 1:1 PBCLK divisor, the user?s software should not read/write
192 * the peripheral?s SFRs in the SYSCLK cycle immediately following the instruction
193 * that clears the module?s ON control bit.
194 *
195 * bit 14 FRZ: Freeze in Debug Exception Mode bit
196 * 1 = Freeze operation when CPU is in Debug Exception mode
197 * 0 = Continue operation even when CPU is in Debug Exception mode
198 * Note: FRZ is writable in Debug Exception mode only, it is forced to ?0? in normal mode.
199 *
200 * bit 13 SIDL: Stop in Idle Mode bit
201 * 1 = Discontinue module operation when device enters Idle mode
202 * 0 = Continue module operation in Idle mode
203 *
204 * bit 12-11 ADRMUX<1:0>: Address/Data Multiplexing Selection bits
205 * 11 = All 16 bits of address are multiplexed on PMD<15:0> pins
206 * 10 = All 16 bits of address are multiplexed on PMD<7:0> pins
207 * 01 = Lower 8 bits of address are multiplexed on PMD<7:0> pins,
208 * upper 8 bits are on PMA<15:8>
209 * 00 = Address and data appear on separate pins
210 *
211 * bit 10 PMPTTL: PMP Module TTL Input Buffer Select bit
212 * 1 = PMP module uses TTL input buffers
213 * 0 = PMP module uses Schmitt Trigger input buffer
214 *
215 * bit 9 PTWREN: Write Enable Strobe Port Enable bit
216 * 1 = PMWR/PMENB port enabled
217 * 0 = PMWR/PMENB port disabled
218 *
219 * bit 8 PTRDEN: Read/Write Strobe Port Enable bit
220 * 1 = PMRD/PMWR port enabled
221 * 0 = PMRD/PMWR port disabled
222 *
223 * bit 7-6 CSF<1:0>: Chip Select Function bits(4)
224 * 11 = Reserved
225 * 10 = PMCS2 and PMCS1 function as Chip Select
226 * 01 = PMCS2 functions as Chip Select, PMCS1 functions as address bit 14
227 * 00 = PMCS2 and PMCS1 function as address bits 15 and 14
228 *
229 * bit 5 ALP: Address Latch Polarity bit(4)
230 * 1 = Active-high (PMALL and PMALH)
231 * 0 = Active-low (PMALL and PMALH)
232 *
233 * bit 4 CS2P: Chip Select 1 Polarity bit(4)
234 * 1 = Active-high (PMCS2)
235 * 0 = Active-low (PMCS2)
236 *
237 * bit 3 CS1P: Chip Select 0 Polarity bit(4)
238 * 1 = Active-high (PMCS1)
239 * 0 = Active-low (PMCS1)
240 *
241 * bit 2 Reserved: Write ?0?; ignore read
242 *
243 * bit 1 WRSP: Write Strobe Polarity bit
244 * For Slave Modes and Master mode 2 (PMMODE<9:8> = 00,01,10):
245 * 1 = Write strobe active-high (PMWR)
246 * 0 = Write strobe active-low (PMWR)
247 * For Master mode 1 (PMMODE<9:8> = 11):
248 * 1 = Enable strobe active-high (PMENB)
249 * 0 = Enable strobe active-low (PMENB)
250 *
251 * bit 0 RDSP: Read Strobe Polarity bit
252 * For Slave modes and Master mode 2 (PMMODE<9:8> = 00,01,10):
253 * 1 = Read Strobe active-high (PMRD)
254 * 0 = Read Strobe active-low (PMRD)
255 * For Master mode 1 (PMMODE<9:8> = 11):
256 * 1 = Read/write strobe active-high (PMRD/PMWR)
257 * 0 = Read/write strobe active-low (PMRD/PMWR)
258 *
259 * [1] The pmp.h header file is located in the peripheral include directory
260 * /Microchip/MPLAB\ C32\ Suite/pic32mx/include/peripheral/pmp.h).
261 */
262 void initialize_display(void)
263 {
264 unsigned int control, mode, port, interrupt;
265
266 /*
267 * PMCON - Initialization pattern for the PMP control register
268 *
269 * The definitions of the positions PMCON_*_POSITION are for the
270 * PIC32MX340F512 made in
271 * /Microchip/MPLAB\ C32\ Suite/pic32mx/include/proc/p32mx340f512h.h
272 * To get a listing, simply run
273 * $ grep -R PMCON_ /cygdrive/c/Microchip/MPLAB\ C32\ Suite/pic32mx/include/proc/p32mx340f512h.h
274 *
275 * The initialization pattern for the PMP control register is composed from
276 * the following terms:
277 * 1000000000000000 (=1<<15 = 0x8000), from PMP_ON
278 * | 0000001100000000 (=3<<8 = 0x0300), from PMP_READ_WRITE_EN
279 * | 0000000000100000 (=1<<5 = 0x0020), from PMP_LATCH_POL_HI
280 * | 0000000000000010 (=1<<1 = 0x0002), from PMP_WRITE_POL_HI
281 * | 0000000000000001 (=1<<0 = 0x0001), from PMP_READ_POL_HI
282 * --------------------
283 * = 1000001100100011 (= 0x8323), resulting control pattern
284 *
285 * Note: The control setting recommended by Di Lucio [1] is 0x83FB; however,
286 * this implies that the reserved control bit 2 of the PMCON register is
287 * set to '1', in contrary to the recommended value of '0' as written in
288 * the PIC32MX Family Reference Manual, Chapter 13 (DS61128E, page 13-6).
289 *
290 * [1] Jasio Di Lucio, "Programming 32-bit microcontrollers in C" (Newnes,
291 * Amsterdam, 2008).
292 */
293 control = PMP_ON /* 0x8000: (1 << _PMCON_ON_POSITION), with _PMCON_ON_POSITION=0x0000000F=15: Configure PMP enabled */
294 | PMP_IDLE_CON /* 0x0000: Operate during IDLE (default) */
295 | PMP_MUX_OFF /* 0x0000: No 16-bit multilplexing (default) */
296 | PMP_ST /* 0x0000: PMP Input buffer type as Schmidt Trigger inputs (default) */
297 | PMP_READ_WRITE_EN /* 0x0300: (3 << _PMCON_PTRDEN_POSITION), with _PMCON_PTRDEN_POSITION=0x00000008=8: Configure RD, RD/WR strobe = ON; WR, WR/ENB strobe = ON */
298 | PMP_LATCH_POL_HI /* 0x0020: (1 << _PMCON_ALP_POSITION), with _PMCON_ALP_POSITION = 0x00000005 */
299 | PMP_WRITE_POL_HI /* 0x0002: (1 << _PMCON_WRSP_POSITION), with _PMCON_WRSP_POSITION = 0x00000001 */
300 | PMP_READ_POL_HI; /* 0x0001: (1 << _PMCON_RDSP_POSITION), with _PMCON_RDSP_POSITION = 0x00000000 */
301 /* 0x8323: Result after bitwise OR on the above patterns */
302
303 /*
304 * PMMODE - Initialization pattern for the PMP mode
305 *
306 * The initialization pattern for the PMP mode register is composed from
307 * the following terms:
308 * 0000000000000000 (0x0000), from PMP_IRQ_OFF (default)
309 * | 0000000000000000 (0x0000), from PMP_AUTO_ADDR_OFF (default)
310 * | 0000000000000000 (0x0000), from PMP_DATA_BUS_8 (default)
311 * | 0000001100000000 (=3<<8 = 0x0300), from PMP_MODE_MASTER1
312 * | 0000000011000000 (=3<<6 = 0x00c0), from PMP_WAIT_BEG_4
313 * | 0000000000111100 (=15<<2 = 0x003c), from PMP_WAIT_MID_15
314 * | 0000000000000011 (=3<<0 = 0x0003), from PMP_WAIT_END_4
315 * --------------------
316 * = 0000001111111111 (=0x03FF), resulting mode pattern
317 */
318 mode = PMP_IRQ_OFF /* 0x0000: PMP interrupt mode OFF */
319 | PMP_AUTO_ADDR_OFF /* 0x0000: Auto Increment/Decrement OFF */
320 | PMP_DATA_BUS_8 /* 0x0000: Configure 8-bit data mode (default) */
321 | PMP_MODE_MASTER1 /* 0x0300: (3 << _PMMODE_MODE_POSITION), with _PMMODE_MODE_POSITION = 0x00000008; Configure MASTER mode 1 */
322 | PMP_WAIT_BEG_4 /* 0x00c0: (3 << _PMMODE_WAITB_POSITION), with _PMMODE_WAITB_POSITION = 0x00000006; Beginning phase wait state as "4 Tpb WAIT" */
323 | PMP_WAIT_MID_15 /* 0x003c: (15 << _PMMODE_WAITM_POSITION), with _PMMODE_WAITM_POSITION = 0x00000002; Middle phase wait state as "3 Tpb WAIT" */
324 | PMP_WAIT_END_4; /* 0x0003: (3 << _PMMODE_WAITE_POSITION), with _PMMODE_WAITE_POSITION = 0x00000000; End phase wait state as "4 Tpb WAIT" */
325 /* 0x03FF: Result after bitwise OR on the above patterns */
326
327 port = PMP_PEN_0; /* 0x0001: PMA0 enabled as the address line for register selection */
328
329 interrupt=PMP_INT_OFF; /* 0x0000: No interrupts used here */
330
331 /*
332 * Employ the mPMPOpen(control, mode, port, interrupt) macro for the actual
333 * assignment of the control, mode and port patterns to the PMCON (control),
334 * PMMODE (mode) and PMAEN (port) registers. Also configure any interrupts
335 * (which, however, are not used here).
336 * The mPMPOpen(control, mode, port, interrupt) macro is simply defined as
337 * #define mPMPOpen(control, mode, port, interrupt)\
338 * (\
339 * PMCON = (control),\
340 * PMMODE = (mode),\
341 * PMAEN = (port),\
342 * mPMPClearIntFlag(),\
343 * mPMPSetIntPriority(((interrupt) & 7)),\
344 * mPMPSetIntSubPriority((((interrupt)>> 4) & 3)),\
345 * mPMPIntEnable(((interrupt) >> 15))\
346 * )
347 */
348 mPMPOpen(control, mode, port, interrupt);
349 delayms(32); /* wait for >30ms */
350
351 /*
352 * Initiate the DOGM163 display with 8-bit initialization sequence. For details,
353 * see the Electronic Assembly DOG-M data sheet "DOG Series 3.3V", Issue 1.2010,
354 * page 7, "Examples for initialisation", available at
355 * http://www.lcd-module.de/eng/pdf/doma/dog-me.pdf.
356 *
357 * Notice that the PMPSetAddress(unsigned int addrs) function (defined as an
358 * inline function directly in the pmp.h header file) simply consists of the
359 * two lines
360 *
361 * while(mIsPMPBusy());
362 * PMADDR = addrs;
363 *
364 * while PMPMasterWrite(unsigned short value) consists of
365 *
366 * while(mIsPMPBusy());
367 * PMDIN = value;
368 */
369 PMPSetAddress(LCDCMD);/* Select command register */
370 PMPMasterWrite(DOGM_FUNCTION_SET /* Function Set: 00100000 (= 0x20) */
371 |DOGM_EIGHT_BIT_INTERFACE /* 8 bit data: |00010000 (= 0x10) */
372 |DOGM_NUM_LINE_IS_TWO /* 2 lines: |00001000 (= 0x08) */
373 |DOGM_SINGLE_HEIGHT_FONT /* Single height: |00000000 (= 0x00) */
374 |DOGM_INSTRUCTION_TABLE_ONE);/* Select Table 1:|00000001 (= 0x01) */
375 delayms(32); /* >30 us */ /* Result pattern: 00111001 (= 0x39) */
376
377 PMPMasterWrite(DOGM_BIAS_SET /* Bias set: 00010100 (= 0x14) */
378 |DOGM_ONE_FIFTH_BIAS /* 1/5:th bias: |00000000 (= 0x00) */
379 |DOGM_THREELINE_BIAS); /* 3 lines: |00000001 (= 0x01) */
380 delayms(32); /* >30 us */ /* Result pattern: 00010101 (= 0x15) */
381
382 PMPMasterWrite(0x55); /* Power Control Set: Booster on, contrast C5, set C4 */
383 delayms(32); /* > 30 us */
384
385 PMPMasterWrite(0x6e); /* Follower Control Set: Set voltage follower and gain */
386 delayms(32); /* > 30 us */
387
388 PMPMasterWrite(0x72); /* Contrast Set: Set contrast C3, C2, C1 */
389 delayms(32); /* > 30 us */
390
391 PMPMasterWrite(0x38); /* Function Set: Switch back to instruction table 0 */
392 delayms(32); /* > 30 us */
393
394 PMPMasterWrite(DOGM_DISPLAY_ON /* Display Settings: */
395 |DOGM_ENTIRE_DISPLAY_ON /* Set display ON, ... */
396 |DOGM_CURSOR_OFF /* ... cursor ON, ... */
397 |DOGM_CURSOR_POSITION_OFF); /* ... cursor blink ON. */
398 delayms(32); /* > 30 us */
399
400 PMPMasterWrite(DOGM_CLEAR__DISPLAY); /* Clear display, cursor to home */
401 delayms(32); /* > 30 us */
402 PMPMasterWrite(DOGM_ENTRY_MODE_SET
403 |DOGM_CURSOR_MOVE_DIR_FORWARD
404 |DOGM_CURSOR_SHIFT_DIR_DOWN);
405 delayms(32); /* > 30 us */
406
407 return;
408 }
409
410 /*
411 * The delay: Needed or not?
412 */
413 #define READ_DISPLAY_REGISTER_DELAY (7)
414 char read_display_register(int addr)
415 {
416 PMPSetAddress(addr); /* Select register */
417 /* delayms(READ_DISPLAY_REGISTER_DELAY); */
418 mPMPMasterReadByte(); /* Initiate read sequence */
419 /* delayms(READ_DISPLAY_REGISTER_DELAY); */
420 return(mPMPMasterReadByte()); /* Read actual data */
421 }
422 #undef READ_DISPLAY_REGISTER_DELAY
423
424 /*
425 * Read the address counter of the LCD using R/W=1(high), RS=0(low), implying
426 * a 0x02 address mask. The address counter is returned in the 7 lowest bits
427 * of the ACx register, hence the masking by 0x7f=01111111.
428 */
429 int read_current_address_counter(void)
430 {
431 return(read_display_register(0x02)&0x3F);
432 }
433
434 /*
435 * The display_is_busy() routine obtains the status of the display and returns
436 * 0 if the display is ready to receive commands; otherwise a non-zero value is
437 * returned. Essentially, the routine reads the LCDCMD register via the PMP and
438 * masks out the BF bit using R/W=1(high), RS=0(low); see "Read Busy Flag and
439 * Address" in DOGM data sheet, available at
440 * http://www.lcd-module.com/eng/pdf/doma/dog-me.pdf
441 */
442 char display_is_busy(void)
443 {
444 return (read_display_register(LCDCMD)&0x80);
445 }
446
447 void write_to_display_register(int addr, char c)
448 {
449 while (display_is_busy());
450 while (PMMODEbits.BUSY);
451 PMPSetAddress(addr);
452 PMPMasterWrite(c);
453 return;
454 }
455
456 void write_character_to_display(char c)
457 {
458 write_to_display_register(LCDDATA,c);
459 col++;
460 if (col>DOGM163_NUM_COLS) {
461 col=1;
462 row++;
463 if (row>DOGM163_NUM_ROWS) row=1;
464 }
465 return;
466 }
467
468 void send_command_to_display(char c) /*cmdLCD*/
469 {
470 write_to_display_register(LCDCMD,c);
471 return;
472 }
473
474 void setLCDG(char a)
475 {
476 send_command_to_display((a&0x3F)|0x40);
477 return;
478 }
479
480 void setLCDC(char a) {
481 send_command_to_display((a&0x7F)|0x80);
482 return;
483 }
484
485 void clear_display(void)
486 {
487 send_command_to_display(DOGM_CLEAR__DISPLAY);
488 row=1;
489 col=1;
490 delayms(1);
491 return;
492 }
493
494 void move_to_position_on_display(int rowpos, int colpos)
495 {
496 int k;
497
498 row=rowpos;
499 col=colpos;
500 if (row>DOGM163_NUM_ROWS) row=1;
501 if (col>DOGM163_NUM_COLS) col=1;
502 if (row==1) {
503 k=col-1; /* Avoid multiplication if possible */
504 } else {
505 k=col-1+(row-1)*DOGM163_NUM_COLS;
506 }
507 send_command_to_display(0x80|k); /* Set address counter to identified position */
508 return;
509 }
510
511 /*
512 * Move to upper left corner of display, but do not wipe out any characters
513 * already written to the display (in contrary to the clear_display() routine).
514 */
515 void move_to_beginning_of_display(void)
516 {
517 send_command_to_display(DOGM_RETURN_HOME);
518 row=1;
519 col=1;
520 return;
521 }
522
523 /*
524 * Move cursor to the beginning of the current line.
525 */
526 void move_to_beginning_of_line(void)
527 {
528 move_to_position_on_display(row, 1); /* Same row, first column */
529 return;
530 }
531
532 /*
533 * Move cursor to the beginning of the next line.
534 */
535 void advance_to_next_line(void)
536 {
537 move_to_position_on_display(row+1, 1); /* Next row, first column */
538 return;
539 }
540
541 void write_string_to_display(char *s)
542 {
543 char k;
544
545 while(*s!='\0') { /* Until termination character of string */
546 switch (*s) {
547
548 case '\t': /* Print out DOGM_TAB_LENGTH tab characters */
549 for (k=0;k<DOGM_TAB_LENGTH;k++)
550 write_character_to_display(' ');
551 break;
552
553 case '\r': /* Carriage return */
554 move_to_beginning_of_line();
555 break;
556
557 case '\n': /* Newline; also wipe out rest of line */
558 for (;col<DOGM163_NUM_COLS;col++) write_character_to_display(' ');
559 advance_to_next_line();
560 break;
561
562 default: /* Simply print the character pointed out by *s */
563 write_character_to_display(*s);
564 break;
565 }
566 s++;
567 }
568 }
569
Generated by ::viewsrc::