This repository has been archived on 2025-03-02. You can view files and clone it, but cannot push or open issues or pull requests.
rc2007-soccer/source/ct-Bot/mcu/display.c
2007-02-11 18:32:03 +00:00

272 lines
7.3 KiB
C
Raw Permalink Blame History

/*
* 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