Am Monday 08 February 2010 21:42:35 schrieb Alexander Tuschen: > Ok, hier kommt der Code. Funktioniert soweit. > > Es wäre mir sehr lieb, wenn jemand mit besseren C-Kentnissen nocheinmal > drüberschaut (Konventionen, Stil, etc.) - ich bin da noch recht grün hinter > den Ohren. > > Ebenfalls wäre es nicht schlecht, die geänderten Funktionen "output_nibble" > und "hd44780_init" evtl. in Ethersex einzupflegen. > > Ich habe der Einfachheit halber den kompletten Readback-Support > rausgenommen, da ich ihn nicht verwende. > > 90% sind der originale Code von hd44780.c > > > > /* > * hd44780 driver library > * > * (c) by Alexander Neumann <alexan...@bumpern.de> > * > * This program is free software; you can redistribute it and/or modify it > * under the terms of the GNU General Public License (either version 2 or > * version 3) as published by the Free Software Foundation. > * > * This program is distributed in the hope that it will be useful, > * but WITHOUT ANY WARRANTY; without even the implied warranty of > * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > * GNU General Public License for more details. > * > * You should have received a copy of the GNU General Public License > * along with this program; if not, write to the Free Software > * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. > * > * For more information on the GPL, please go to: > * http://www.gnu.org/copyleft/gpl.html > */ > > /* > * HD44780-Display über PCF8574 ansteuern. > * Belegung Pollin Add-On-Board: > * > * Pin PCF8574 Pin am LCD > * 4 (P0) -> 11 (DB4) > * 5 (P1) -> 12 (DB5) > * 6 (P2) -> 13 (DB6) > * 7 (P3) -> 14 (DB7) > * 9 (P4) -> 4 (RS) > * 10 (P5) -> 5 (R/W) nicht benutzt ! > * 11 (P6) -> 6 (EN) > * 12 (P7) -> 15 (Beleuchtung) > * > * Die LCD-Beleuchtung an Pin 12 wird über einen > * PNP-Transistor geschaltet. > * Beleuchtung an: Bit 7=0 > * Beleuchtung aus: Bit 7=1 > * TODO: Beleuchtung per ECMD schalten > * Die Address-Eingänge A0 bis A2 des PCF8574 liegen alle auf GND. > * Die Basis-Addresse des Chips ist daher immer 0x20. > * > * ACHTUNG: Kein Readback-Support! > */ > > #include <avr/io.h> > #include <util/delay.h> > > #include "hd44780.h" > #include "config.h" > #include "hardware/i2c/master/i2c_pcf8574x.h" > > /* global variables */ > FILE *lcd; > uint8_t current_pos = 0; > > > /* display commands */ > #define HIGH_NIBBLE(x) ((uint8_t)((x) >> 4 )) > #define LOW_NIBBLE(x) ((uint8_t)((x) & 0x0f )) > > #define CMD_CLEAR_DISPLAY() _BV(0) > #define CMD_HOME() _BV(1) > #define CMD_ENTRY_MODE(dir, shift) \ > (_BV(2) | (shift) << 0 | (dir) << 1) > #define CMD_POWER(display, cursor, blink) \ > (_BV(3) | (display) << 2 | (cursor) << 1 | (blink) << 0) > #define CMD_SHIFT(cursor, dir) \ > (_BV(4) | (cursor) << 3 | (dir) << 2) > #define CMD_FUNCTIONSET(datalength, lines, font) \ > (_BV(5) | (datalength) << 4 | (lines) << 3 | (font) << 2) > #define CMD_SETCRAMADR(addr) (_BV(6) | (addr)) > #define CMD_SETDRAMADR(addr) (_BV(7) | (addr)) > > /* other macros */ > #define noinline __attribute__((noinline)) > > /* own prototypes */ > static noinline void output_nibble(uint8_t rs, uint8_t nibble); > static noinline void output_byte(uint8_t rs, uint8_t data); > > void output_nibble(uint8_t rs, uint8_t nibble) > { > uint8_t data; //Variable für Datenbyte > data = nibble; //Nutzdaten laden (Bit 0 bis 3) > data |= _BV(6); //Bit 6 (EN) setzen > > if (rs) //Falls rs==1 > data |= _BV(4); //Bit 4 (RS) setzen > > i2c_pcf8574x_set(0x20,data); //Datenbyte an PCF senden > > data &= ~(_BV(6)); //Bit 6 (EN) löschen > i2c_pcf8574x_set(0x20,data); //Datenbyte erneut senden > } > > void output_byte(uint8_t rs, uint8_t data) > { > output_nibble(rs, HIGH_NIBBLE(data)); > output_nibble(rs, LOW_NIBBLE(data)); > > /* just wait the maximal time a command can take... */ > _delay_ms(2); > } > > void hd44780_clear(void) > { > output_byte(0, CMD_CLEAR_DISPLAY()); > } > > void hd44780_home(void) > { > output_byte(0, CMD_HOME()); > } > > void hd44780_goto(uint8_t line, uint8_t pos) > { > current_pos = (line * 20 + pos) % 80; > } > > void hd44780_shift(uint8_t right) > { > output_byte(0, CMD_SHIFT(1, right?1:0)); > } > > void > hd44780_define_char(uint8_t n_char, uint8_t *data) > { > if (n_char > 7) return; > /* set cgram pointer to char number n */ > output_byte(0, CMD_SETCRAMADR(n_char * 8)); > n_char = 0; > while (n_char < 8) { > /* send the data to lcd into cgram */ > output_byte(1, *(data + n_char)); > n_char++; > } > } > > void hd44780_init(void) > { > uint8_t data = 0; > > /* init io pins */ > i2c_pcf8574x_set(0x20,data); // Alle Ausgänge auf 0 > _delay_ms(40); // kurz warten > > data |= (_BV(0) | _BV(1) | _BV(6)); // Bits 0,1 und 6 (EN) setzen > i2c_pcf8574x_set(0x20,data); // Byte senden > > data &= ~(_BV(6)); // Bit 6 (EN) löschen > i2c_pcf8574x_set(0x20,data); // Byte senden > > _delay_ms(4); // kurz warten > data |= _BV(6); // Bit 6 (EN) setzen > i2c_pcf8574x_set(0x20,data); // Byte senden > data &= ~(_BV(6)); // Bit 6 (EN) löschen > i2c_pcf8574x_set(0x20,data); // Byte senden > > > _delay_ms(1); // warten > data |= _BV(6); // Bit 6 (EN) setzen > i2c_pcf8574x_set(0x20,data); // Byte senden > data &= ~(_BV(6)); // Bit 6 (EN) löschen > i2c_pcf8574x_set(0x20,data); // Byte senden > > /* init done */ > _delay_ms(1); // warten > data &= ~(_BV(0)); // Bit 0 löschen > data |= _BV(6); // Bit 6 (EN) setzen > i2c_pcf8574x_set(0x20,data); // Byte senden > data &= ~(_BV(6)); // Bit 6 (EN) löschen > i2c_pcf8574x_set(0x20,data); // Byte senden > _delay_ms(1); // warten > > data = 0; > i2c_pcf8574x_set(0x20,data); // Alle Ausgänge auf 0 > > /* configure for 4 bit, 2 lines, 5x9 font (datasheet, page 24) */ > output_byte(0, CMD_FUNCTIONSET(0, 1, 0)); > > /* turn on display, cursor and blinking */ > hd44780_config(0,0); > > /* clear display */ > hd44780_clear(); > > /* set shift and increment */ > output_byte(0, CMD_ENTRY_MODE(1, 0)); > > /* set ddram address */ > output_byte(0, CMD_SETDRAMADR(0)); > > /* open file descriptor */ > lcd = fdevopen(hd44780_put, NULL); > > /* set current virtual postion */ > current_pos = 0; > } > > void hd44780_config(uint8_t cursor, uint8_t blink) > { > output_byte(0, CMD_POWER(1, cursor, blink)); > } > > int hd44780_put(char d, FILE *stream) > { > uint8_t start = 0; > > if (d == '\n') { > while (current_pos % 20 > 0) > hd44780_put(' ', stream); > > if (current_pos >= 80) > current_pos -= 80; > > return 0; > } else if (d == '\r') { > current_pos -= current_pos % 20; > return 0; > } > > #if HD44780_TYPE == HD44780_ORIGINAL > if (current_pos <= 19) > start = 0x00 - 00 + current_pos; > else if (current_pos <= 39) > start = 0x20 - 20 + current_pos; > else if (current_pos <= 59) > start = 0x40 - 40 + current_pos; > else if (current_pos <= 79) > start = 0x60 - 60 + current_pos; > #elif HD44780_TYPE == HD44780_DISPTECH > if (current_pos <= 19) > start = 0x00 - 0 + current_pos; > else if (current_pos <= 39) > start = 0x40 - 20 + current_pos; > else if (current_pos <= 59) > start = 0x10 - 40 + current_pos; > else if (current_pos <= 79) > start = 0x50 - 60 + current_pos; > #elif HD44780_TYPE == HD44780_KS0067B > if (current_pos <= 19) > start = 0x00 - 0 + current_pos; > else if (current_pos <= 39) > start = 0x40 - 20 + current_pos; > else if (current_pos <= 59) > start = 0x14 - 40 + current_pos; > else if (current_pos <= 79) > start = 0x54 - 60 + current_pos; > #else > #error "unknown hd44780 compatible controller type!" > #endif > > output_byte(0, CMD_SETDRAMADR(start)); > output_byte(1, d); > current_pos++; > > if (current_pos == 80) > current_pos = 0; > > return 0; > } > > /* > -- Ethersex META -- > header(hardware/lcd/hd44780.h) > init(hd44780_init) > */ > > > > _______________________________________________ > Ethersex-devel mailing list > Ethersex-devel@list.zerties.org > https://list.zerties.org/cgi-bin/mailman/listinfo/ethersex-devel
_______________________________________________ Ethersex-devel mailing list Ethersex-devel@list.zerties.org https://list.zerties.org/cgi-bin/mailman/listinfo/ethersex-devel