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

Antwort per Email an