summaryrefslogtreecommitdiffstats
path: root/source/ct-Bot/mcu/display.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/ct-Bot/mcu/display.c')
-rw-r--r--source/ct-Bot/mcu/display.c272
1 files changed, 272 insertions, 0 deletions
diff --git a/source/ct-Bot/mcu/display.c b/source/ct-Bot/mcu/display.c
new file mode 100644
index 0000000..f94ce16
--- /dev/null
+++ b/source/ct-Bot/mcu/display.c
@@ -0,0 +1,272 @@
+/*
+ * c't-Bot
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307, USA.
+ *
+ */
+
+/*! @file display.c
+ * @brief Routinen zur Displaysteuerung
+ * @author Benjamin Benz (bbe@heise.de)
+ * @date 20.12.05
+*/
+#include "global.h"
+#include "ct-Bot.h"
+
+#ifdef MCU
+#ifdef DISPLAY_AVAILABLE
+
+#include <avr/io.h>
+#ifdef NEW_AVR_LIB
+ #include <util/delay.h>
+#else
+ #include <avr/delay.h>
+#endif
+#include <stdarg.h>
+#include <stdio.h>
+#include "command.h"
+
+#include "display.h"
+#include "led.h"
+#include "delay.h"
+#include "shift.h"
+#include "display.h"
+
+/*! Puffergroesse fuer eine Zeile in bytes */
+#define DISPLAY_BUFFER_SIZE (DISPLAY_LENGTH + 1)
+
+uint8 display_update=0; /*!< Muss das Display aktualisiert werden? */
+#ifdef DISPLAY_SCREENS_AVAILABLE
+ #ifdef LOG_DISPLAY_AVAILABLE
+ uint8 display_screen=4; /*!< Muss das Display aktualisiert werden? */
+ #else
+ uint8 display_screen=0; /*!< Muss das Display aktualisiert werden? */
+ #endif
+#endif
+static char display_buf[DISPLAY_BUFFER_SIZE]; /*!< Pufferstring fuer Displayausgaben */
+
+#define DISPLAY_CLEAR 0x01 /*!< Kommando zum Löschen */
+#define DISPLAY_CURSORHOME 0x02 /*!< Kommando für den Cursor */
+
+#define DISPLAY_OUT 0x07 /*!< Output-Pins Display */
+#define DISPLAY_IN (1<<5) /*!< Input-Pins Display */
+
+#define DISPLAY_PORT PORTC /*!< Port an dem das Display hängt */
+#define DISPLAY_DDR DDRC /*!< Port an dem das Display hängt */
+#define DPC (DISPLAY_PORT & ~DISPLAY_OUT) /*!< Port des Displays */
+//#define DRC (DDRC & ~DISPLAY_PINS)
+
+//#define DISPLAY_READY_PINR PINC /*!< Port an dem das Ready-Flag des Display hängt */
+#define DISPLAY_READY_DDR DDRC /*!< Port an dem das Ready-Flag des Display hängt */
+#define DISPLAY_READY_PIN (1<<5) /*!< Pin an dem das Ready-Flag des Display hängt */
+
+/*! RS-Leitung
+ * legt fest, ob die Daten an das Display in den Textpuffer (RS=1) kommen
+ * oder als Steuercode interpretiert werden (RS=0)
+ */
+#define DISPLAY_RS (1<<0) /*!< Pin an dem die RS-Leitung des Displays hängt */
+
+/*! RW-Leitung
+ * legt fest, ob zum Display geschrieben wird (RW=0)
+ * oder davon gelesen wird (RW=1)
+ */
+#define DISPLAY_RW (1<<1) /*!< Pin an dem die RW-Leitung des Displays hängt */
+
+/*! Enable Leitung
+ * schaltet das Interface ein (E=1).
+ * Nur wenn Enable auf High-Pegel liegt, läßt sich das Display ansprechen
+ */
+#define DISPLAY_EN (1<<2) /*!< Pin an dem die EN-Leitung des Displays hängt */
+
+/*
+ * Im Moment der Low-High-Flanke von ENABLE liest das Dislplay
+ * die Werte von RS und R/W ein. Ist zu diesem Zeitpunkt R/W=0,
+ * dann liest das Display mit der folgenden High-Low-Flanke von ENABLE
+ * den Datenbus ein (Schreibzyklus).
+ * War aber R/W=1, dann legt das Display ein Datenword auf den
+ * Datenbus (Lese-Zyklus), solange bis die High-Low-Flanke von ENABLE
+ * das Interface wieder deaktiviert.
+ */
+
+/*!
+ * Übertrage Kommando an das Display
+ * @param cmd Kommando
+ */
+void display_cmd(uint8 cmd){ //ein Kommando cmd an das Display senden
+ uint8 i;
+ shift_data_out(cmd,SHIFT_LATCH,SHIFT_REGISTER_DISPLAY);
+ // Enable muss für mind. 450 ns High bleiben, bevor es fallen darf!
+ // ==> Also mind. 8 Zyklen warten
+ for (i=0; i<150; i++){
+ asm volatile("nop");
+ }
+ DISPLAY_PORT=DPC; // Alles zurück setzen ==> Fallende Flanke von Enable
+}
+
+
+/*!
+ * Ein Zeichen auf das Display schreiben
+ * @param data Das Zeichen
+ */
+void display_data(char data){ //ein Zeichen aus data in den Displayspeicher schreiben
+ uint8 i;
+ shift_data_out(data,SHIFT_LATCH,SHIFT_REGISTER_DISPLAY|DISPLAY_RS);
+
+ // Enable muss für mind. 450 ns High bleiben, bevor es fallen darf!
+ // ==> Also mind. 8 Zyklen warten
+ for (i=0; i<150; i++){
+ asm volatile("nop");
+ }
+ DISPLAY_PORT=DPC; // Alles zurück setzen ==> Fallende Flanke von Enable
+}
+
+/*!
+ * Löscht das ganze Display
+ */
+void display_clear(void){
+ display_cmd(DISPLAY_CLEAR); // Display loeschen, Cursor Home
+ #ifdef DISPLAY_REMOTE_AVAILABLE
+ command_write(CMD_AKT_LCD, SUB_LCD_CLEAR, NULL, NULL,0);
+ #endif
+}
+
+/*!
+ * Positioniert den Cursor
+ * @param row Zeile
+ * @param column Spalte
+ */
+void display_cursor (uint8 row, uint8 column) {
+ switch (row) {
+ case 1:
+ display_cmd (0x80 + column - 1);
+ break;
+ case 2:
+ display_cmd (0xc0 + column - 1);
+ break;
+ case 3:
+ display_cmd (0x94 + column - 1);
+ break;
+ case 4:
+ display_cmd (0xd4 + column - 1);
+ break;
+ default: break;
+ }
+
+ #ifdef DISPLAY_REMOTE_AVAILABLE
+ int16 r=row-1;
+ int16 c=column-1;
+ command_write(CMD_AKT_LCD, SUB_LCD_CURSOR, &c,&r,0);
+ #endif
+
+}
+
+/*!
+ * Init Display
+ */
+void display_init(void){
+ shift_init();
+
+ DISPLAY_DDR |= DISPLAY_OUT; // Ausgänge
+ DISPLAY_DDR &= ~DISPLAY_IN; // Eingänge
+
+ delay(12); // Display steht erst 10ms nach dem Booten bereit
+
+ // Register in 8-Bit-Modus 3x Übertragen, dazwischen warten
+ shift_data_out(0x38,SHIFT_LATCH,SHIFT_REGISTER_DISPLAY);
+ DISPLAY_PORT= DPC;
+ delay(5);
+ shift_data_out(0x38,SHIFT_LATCH,SHIFT_REGISTER_DISPLAY);
+ DISPLAY_PORT= DPC;
+ delay(5);
+ shift_data_out(0x38,SHIFT_LATCH,SHIFT_REGISTER_DISPLAY);
+ DISPLAY_PORT= DPC;
+ delay(5);
+
+ display_cmd(0x0f); //Display On, Cursor On, Cursor Blink
+
+ display_cmd(DISPLAY_CLEAR); // Display loeschen, Cursor Home
+
+ display_data('i');
+}
+
+/*!
+ * Zeigt einen String an
+ * @return -1 falls string zuende 0 falls Zeile (20 zeichen) zuende
+ */
+/*int display_string(char data[20]){
+ int i=0;
+
+ while ((i<20) && (data[i] != 0x00)){ // Abbruch, sobald ein Nullstring erreicht wird
+ // oder 20 Zeichen gesendet sind
+ display_data(data[i++]); // einzelnes Zeichen schicken
+ }
+
+ // return -1 falls string zuende, 0 falls zeile (20 zeichen) zuende
+ if (data[i]==0x00) return -1; else return 0;
+}
+*/
+
+/*!
+ * Schreibt einen String auf das Display.
+ * @param format Format, wie beim printf
+ * @param ... Variable Argumentenliste, wie beim printf
+ */
+void display_printf(char *format, ...) {
+
+ unsigned int run = 0;
+ va_list args;
+
+ /* Sicher gehen, das der zur Verfuegung stehende Puffer nicht
+ * ueberschrieben wird.
+ */
+ va_start(args, format);
+ vsnprintf(display_buf, DISPLAY_BUFFER_SIZE, format, args);
+ va_end(args);
+
+ /* Ausgeben bis Puffer leer ist */
+ while(display_buf[run] != '\0') {
+ display_data(display_buf[run]);
+ run++;
+ }
+
+ #ifdef DISPLAY_REMOTE_AVAILABLE
+ command_write_data(CMD_AKT_LCD, SUB_LCD_DATA, NULL, NULL, display_buf);
+ #endif
+
+ return;
+}
+
+/*
+void display_test(){
+ shift_init();
+
+// shift_data_out(0xAA,SHIFT_LATCH,SHIFT_REGISTER_DISPLAY);
+
+ display_cmd(0x38); //Display auf 8 Bit Betrieb
+ for(;;){}
+ display_cmd(0x0f); //Display On, Cursor On, Cursor Blink
+
+ display_cmd(DISPLAY_CLEAR); // Display l�schen, Cursor Home
+ display_cursor(2,2);
+
+ display_string("Hallo");
+ for(;;){
+ }
+}
+*/
+
+#endif
+
+#endif