|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Did you know...
|
Serial Wombat HD44780 Generic Channel ModeBased on user feedback, a generic HD44780 LCD controller driver is available beginning in version 2.0 of the firmware. This Channel mode doesn't do as much to hide the internal details of the HD44780 as the other HD44780 mode does, but rather than working for a specific 2 x 24 layout, this driver should work for any HD44780 LCD. In addition, characters and graphics can be placed on the LCD without using any internal Wombat user RAM. In order to use an HD44780 controller with this mode there are a few things you need to know about it:
Message format:Message 200 does a typical initialization for an HD44780 based display. The user must supply the pin numbers for the LCD's R/S line, and D4, D5, D6 and D7 lines.
The 202 message is used to download custom characters into the LCD's character generation ram. HD44780 lcd displays hold up to eight custom characters, which are stored in 64 bytes of the LCD's memory. Each character is 5 pixels wide, by 8 pixels long. In order to program a custom character, send two 203 messages to the Wombat containing the 8 bytes making up the bitmap. In each message, provide an offset into the character-generation RAM, and four bytes of the bitmap. This message should be sent after the 202 message. This message may take up to 600uS to complete, and processing of other functions will be suspended during this time. This command should only be used after a 200 configuration command has been issued for the LCD.
Message 203 is used to configure the HD44780 generic driver to continuously update the HD44780's internal data memory from the Wombat's User RAM area. The user provides an address in the Wombat User RAM area. 80 bytes starting at that address are copied into the HD44780, one byte per Wombat Frame (1ms by default). After 80 bytes are copied, the Wombat returns to the first byte, and begins the copy again. Since the driver is generic for any HD44780 display, 80 bytes are always used. Bytes in Wombat RAM will be wasted for LCDs smaller than 80 characters, and the string in Wombat Memory may not line up directly on the LCD. This mode is provided primarily for use with the forthcoming Pin Mode Software Development kit, so that pin modes can display strings on an LCD attached to another pin. This command should only be used after a 200 configuration command has been issued for the LCD.
Message 204 is used to send command or data bytes to the LCD. Up to two command or data bytes can be sent per 8 byte packet. These commands can be used to change the way the LCD functions, such as making the character visible, or making the LCD scroll. See the HD44780 datasheet for details.
Example:Display the string "Hello World" on an HD44780 based LCD with E on pin 33, RS on pin 34, and D4-D7 on pins 35-38, and make the cursor visible 200 33 27 34 35 36 37 38 ; Set pin 33 to HD44780 mode,
; RS pin is 34
; D4 - D7 ar 36 - 38
201 33 27 0 "Hell" ; Set pin 33 to HD44780 mode
; Put the characters "HELL" in
; the display starting at address 0
201 33 27 4 "O WO" ; Set pin 33 to HD44780 mode
; Put the characters "O WO" in
; the display starting at address 4
201 33 27 4 "RLD " ; Set pin 33 to HD44780 mode
; Put the characters "RLD " in
; the display starting at address 8
; Note that we added a space to complete
; the 4 bytes.
204 33 27 1 0x07 0 0x55 0x55 ; Send a command byte 0x07. This
; causes the display to turn on the
; cursor. (see datasheet for HD44780)
; Second byte for this command is
; Discarded.
Pin Mode Source CodeThe following code is what creates the pin mode for this function inside of the Wombat. You don't need to know this to use the pin mode, but some people find it interesting. See the SDK for some insight into how pin modes work. Hold your mouse over various words and variables for definitions. #ifndef COMPILING_FIRMWARE#include <stdio.h> #endif #include "types.h" #include "utilities.h" #include "global_data.h" #ifndef COMPILING_FIRMWARE #include "test.h" #endif #pragma code APPLICATION #pragma romdata APPLICATION_DATA #ifdef __18F4620 #define HD44780_GENERIC_BUFFER #endif #ifndef COMPILING_FIRMWARE #define HD44780_GENERIC_BUFFER #endif void hd44780_setdata(uint8 a) { local_j = a; local_j >>=4; vpin_high(); set_pin(tp.hd44780.D4pin,(local_j & 0x01)) ; local_j >>=1; set_pin(tp.hd44780.D5pin,(local_j &0x01) ); local_j >>=1; set_pin(tp.hd44780.D6pin,(local_j & 0x01)) ; local_j >>=1; set_pin(tp.hd44780.D7pin,(local_j & 0x01) ); vpin_low(); local_j = a; vpin_high(); set_pin(tp.hd44780.D4pin,(local_j & 0x01)) ; local_j >>=1; set_pin(tp.hd44780.D5pin,(local_j &0x01) ); local_j >>=1; set_pin(tp.hd44780.D6pin,(local_j & 0x01)) ; local_j >>=1; set_pin(tp.hd44780.D7pin,(local_j & 0x01) ); vpin_low(); } static void clock_data(uint8 data); static void clock_cmd(uint8 data) ; void init_hd44780_generic(void) { uint8 i; if (rxbuffer[0] == CONFIGURE_CHANNEL_MODE_0) { //Set up pins tp.hd44780.state = 81; tp.hd44780.RSpin = map_pin(rxbuffer[3]); set_mode(tp.hd44780.RSpin, PIN_MODE_CONTROLLED); tp.hd44780.D4pin = map_pin(rxbuffer[4]); set_mode(tp.hd44780.D4pin, PIN_MODE_CONTROLLED); tp.hd44780.D5pin = map_pin(rxbuffer[5]); set_mode(tp.hd44780.D5pin, PIN_MODE_CONTROLLED); tp.hd44780.D6pin = map_pin(rxbuffer[6]); set_mode(tp.hd44780.D6pin, PIN_MODE_CONTROLLED); tp.hd44780.D7pin = map_pin(rxbuffer[7]); set_mode(tp.hd44780.D7pin, PIN_MODE_CONTROLLED); } else if (rxbuffer[0] == CONFIGURE_CHANNEL_MODE_1) { //clock in address plus 4 bytes rxbuffer[3] |= 0x80; clock_cmd(rxbuffer[3]); delay_cycles16(500); clock_data(rxbuffer[4]); delay_cycles16(500); clock_data(rxbuffer[5]); delay_cycles16(500); clock_data(rxbuffer[6]); delay_cycles16(500); clock_data(rxbuffer[7]); } else if (rxbuffer[0] == CONFIGURE_CHANNEL_MODE_2) { local_i = rxbuffer[3]; //Set CGRAM location clock_cmd(0x40 | (local_i & 0x3F)); delay_cycles16(500); clock_data(rxbuffer[4]); delay_cycles16(500); clock_data(rxbuffer[5]); delay_cycles16(500); clock_data(rxbuffer[6]); delay_cycles16(500); clock_data(rxbuffer[7]); } #ifdef HD44780_GENERIC_BUFFER else if (rxbuffer[0] == CONFIGURE_CHANNEL_MODE_3) { //Give memory address, and initialize //Will constantly clock in 80 bytes into ram tp.generic.buffer = RXBUFFER16(3); tp.hd44780.state = 0; } #endif else if (rxbuffer[0] == CONFIGURE_CHANNEL_MODE_4) { if (rxbuffer[3] == 1) { clock_cmd(rxbuffer[4]); } else if (rxbuffer[3] == 2) { clock_data(rxbuffer[4]); } delay_cycles16(500); if (rxbuffer[5] == 1) { clock_cmd(rxbuffer[6]); } else if (rxbuffer[5] == 2) { clock_data(rxbuffer[6]); } } } void update_hd44780_generic(void) { #ifdef HD44780_GENERIC_BUFFER uint16 actual_offset; #endif switch (tp.hd44780.state) { case 81: clock_cmd(0x20); // 4 bit interface ++ tp.hd44780.state; break; case 82: clock_cmd(0x28); // 4bit interface, two lines ++ tp.hd44780.state; break; case 83: clock_cmd(0x0C); // Display On ++ tp.hd44780.state; break; case 84: clock_cmd(0x06); // Cursor increment, no shift ++ tp.hd44780.state; break; case 85: clock_cmd(0x80); // Display address 0 ++ tp.hd44780.state; break; case 86: clock_cmd(0x02); //Cursor home ++ tp.hd44780.state; break; case 87: ++ tp.hd44780.state; break; case 88: tp.hd44780.state = 254; break; break; default: #ifdef HD44780_GENERIC_BUFFER if (tp.hd44780.state == 80) { clock_cmd(0x80); // Display address 0 tp.hd44780.state = 0; } else { tp2.hd44780.offset = tp.hd44780.state; tp2.hd44780.offset += tp.generic.buffer; clock_data(get_user_buffer(tp2.hd44780.offset)); ++tp.hd44780.state; } #endif break; case 254: break; } executive_settings.buffer_dirty = 1; } void clock_data(uint8 data) { pin_high(tp.hd44780.RSpin) ; hd44780_setdata(data); } void clock_cmd(uint8 data) { pin_low(tp.hd44780.RSpin) ; hd44780_setdata(data); } ///////////////////////////////////////////////////////////////////////// // CODE FROM HERE DOWN IS TESTING CODE FOR USE ON PC, not FIRMWARE #ifndef COMPILING_FIRMWARE #ifdef TEST_HD44780_GENERIC void test_lcd_callback(void) { hd44780sim_update(0); return; } int main (void) { int i; uint8 string[200]; int overall_return = 0; system_init(); for (i = 0; i < 200 ; ++i) { user_buffer[i] = (i %('z' - '0' + 1)) + '0'; } init_hd44780sim(0, //uint8 instance map_pin(20), // uint8 Epin map_pin(2), // uint8 RSpin map_pin(7), // uint8 datapin7 map_pin(6), // uint8 datapin6 map_pin(5), // uint8 datapin5 map_pin(4), // uint8 datapin4 2, // uint8 lines 40, // uint8 width 0, // uint8 linestart0 40, // uint8 linestart1 255, // uint8 linestart2 255); // uint8 linestart3) register_update_func( test_lcd_callback); rxbuffer[0] = CONFIGURE_CHANNEL_MODE_0; rxbuffer[1] = 20; rxbuffer[2] = PIN_MODE_HD44780_GENERIC; rxbuffer[3] = 2; rxbuffer[4] = 4 ; rxbuffer[5] = 5 ; rxbuffer[6] = 6 ; rxbuffer[7] = 7 ; process_rxbuffer(); for (i = 0; i < 10; ++i) { process_pins(); } rxbuffer[0] = CONFIGURE_CHANNEL_MODE_3; rxbuffer[1] = 20; rxbuffer[2] = PIN_MODE_HD44780_GENERIC; rxbuffer[3] = 0; rxbuffer[4] = 0 ; rxbuffer[5] = 0 ; rxbuffer[6] = 0 ; rxbuffer[7] = 0 ; process_rxbuffer(); for (i = 0; i < 2000; ++i) { process_pins(); } print_hd44780sim(0,1,1); hd44780sim_getstring(0,string); if (strcmp(string,"0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz01234") != 0) { printf ("ERROR: String %s didn't match %s\n",string, "0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz01234"); overall_return = 1; } else { printf ("User buffer test passed\n"); } printf ("\n\n"); init_hd44780sim(0, //uint8 instance map_pin(20), // uint8 Epin map_pin(2), // uint8 RSpin map_pin(7), // uint8 datapin7 map_pin(6), // uint8 datapin6 map_pin(5), // uint8 datapin5 map_pin(4), // uint8 datapin4 2, // uint8 lines 40, // uint8 width 0, // uint8 linestart0 40, // uint8 linestart1 255, // uint8 linestart2 255); // uint8 linestart3) register_update_func( test_lcd_callback); rxbuffer[0] = CONFIGURE_CHANNEL_MODE_0; rxbuffer[1] = 20; rxbuffer[2] = PIN_MODE_HD44780_GENERIC; rxbuffer[3] = 2; rxbuffer[4] = 4 ; rxbuffer[5] = 5 ; rxbuffer[6] = 6 ; rxbuffer[7] = 7 ; process_rxbuffer(); for (i = 0; i < 10; ++i) { process_pins(); } rxbuffer[0] = CONFIGURE_CHANNEL_MODE_1; rxbuffer[1] = 20; rxbuffer[2] = PIN_MODE_HD44780_GENERIC; rxbuffer[3] = 10; rxbuffer[4] = 'A' ; rxbuffer[5] = 'B' ; rxbuffer[6] = 'C' ; rxbuffer[7] = 'D' ; process_rxbuffer(); for (i = 0; i < 2000; ++i) { process_pins(); } print_hd44780sim(0,1,1); hd44780sim_getstring(0,string); if (strncmp(string,"}}}}}}}}}}ABCD", 14) != 0) { printf ("ERROR: String %s didn't match %s\n",string, "}}}}}}}}}}ABCD"); overall_return = 1; } else { printf ("LCD buffer test passed\n"); } return overall_return; } #endif #endif |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Copyright Wombat Interface Products, 2005-2008. All Rights Reserved.