#if defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__)
- // Nano-644
+ // Nano-644 / Nano-1284
// ---------------------------------------------------------------
- // PA3 ..... E --> LCD Enable (Verbindung via J25 erforderlich)
- // PD6 ..... R/W --> Read/Write: Read=1, Write=0
- // PD7 ..... RS --> Register Select: Command=0, Data=1
- // PB7:0 ... Data --> Achtung von 5V LCD nicht lesen!
+
+ // Nano-X-Base V1a V2a Beschreibung
+ // --------------------------------- -------
+ // E ........... PA3 PA3 LCD Enable (Verbindung via J25 erforderlich)
+ // R/W .......... PD6 PD6 Read/Write: Read=1, Write=0
+ // RS ........... PD7 PD7 Register Select: Command=0, Data=1
+ // Data ......... PB7:0 PB7:0 Achtung von 5V LCD nicht lesen!
// #define LCD_3V3
DDRD |= (1 << PD7) | (1 << PD6);
initLcd();
#ifdef LCD_3V3
- printf_P(PSTR("init 3.3V LCD"));
+ printf_P(PSTR("init 3.3V LCD (%d)"), status);
#else
- printf_P(PSTR("init 5V LCD"));
+ printf_P(PSTR("init 5V LCD (%d)"), status);
#endif
}
void Lcd::clrRW () { PORTD &= ~(1 << PD6); }
void Lcd::setE () { PORTA |= (1 << PA3); }
void Lcd::clrE () { PORTA &= ~(1 << PA3); }
+ void Lcd::dataDirectionIn () { DDRB = 0x00; }
+ void Lcd::dataDirectionOut () { DDRB = 0xff; }
+
+ uint8_t Lcd::getData () {
+ return PINB;
+ }
void Lcd::setData (uint8_t data) {
PORTB = data;
#define BLINK_ON 0b00001111 // Cursor Blink
#define BLINK_OFF 0b00001110 // Cursor No Blink
+#define LCD_PULSE_LENGTH 15
+#define LCD_CMD_DISPLAY_CLEAR 0x01 // Display clear
+#define LCD_CMD_CURSOR_HOME 0x02 // Move cursor digit 1
+#define LCD_CMD_SET_ENTRY_MODE 0x04 // Entry Mode Set
+#define LCD_CMD_DISPLAY_ON_OFF 0x08 // Display on/off
+#define LCD_CMD_SHIFT 0x10 // Display shift
+#define LCD_CMD_SET_FUNCTION 0x20 // 4/8 Bits...
+#define LCD_CMD_SET_CGRAM_ADDR 0x40 // Character Generator ROM
+#define LCD_CMD_SET_DDRAM_ADDR 0x80 // Display Data RAM
+#define LCD_BUSY_FLAG 0x80
+
+
+
int8_t Lcd::run (uint8_t subtest) {
if (subtest == 0) {
for (uint8_t i = 0; i < 20 * 4; i++) {
char c = (char)(i + 32);
if (i % 20 == 0) {
- setCursor(i / 20 + 1, 1);
+ setCursor(i / 20, 0);
}
- writeData(c);
- while (isBusy()) {};
+ putChar(c);
+ waitOnReady();
+ }
+ printf_P(PSTR("LCD "));
+ if (status == 1) {
+ printf_P(PSTR("OK"));
+ } else {
+ printf_P(PSTR("ERROR(%d)"), status);
}
- // setCursor(1, 1);
- // writeString(" 1234567890<>,;.:-_#+");
- // setCursor(2, 1);
- // writeString("abcdefghijklmnopqrst");
- // setCursor(3, 1);
- // writeString("uvwxyzABCDEFGHIJKLMN");
- // setCursor(4, 1);
- // writeString("OPQRSTUVWXYZ ");
- printf_P(PSTR("LCD beschrieben"));
while (wait(1) == EOF) {
}
return 0;
}
+// void Lcd::initLcd () {
+// _delay_ms(16); // min 15ms warten für Reset des Displays
+
+// if (mode8Bit) {
+// setData( 0b00111011 ); // 8bit Modus, 5x7 Zeichen, Mehrzeilen Display
+// clrRW(); // write
+// clrRS(); // command
+// setE(); // E = 1 (transfer start)
+// _delay_us(10); // min. 10us
+// clrE(); // E = 0 (transfer end)
+// _delay_ms(5); // min. 4.1ms
+
+// setData( 0b00111011 ); // 8bit Modus, 5x7 Zeichen, Mehrzeilen Display
+// clrRW(); // write
+// clrRS(); // command
+// setE(); // E = 1 (transfer start)
+// _delay_us(10); // min. 10us
+// clrE(); // E = 0 (transfer end)
+// _delay_us(100); // min. 100us
+
+// setData( 0b00111011 ); // 8bit Modus, 5x7 Zeichen, Mehrzeilen Display
+// clrRW(); // write
+// clrRS(); // command
+// setE(); // E = 1 (transfer start)
+// _delay_us(10); // min. 10us
+// clrE(); // E = 0 (transfer end)
+// _delay_us(100); // min. 100us
+
+// } else {
+// setData( 0b0010 << 4 ); // 4bit Modus, 5x7 Zeichen, Mehrzeilen Display
+// }
+
+// writeCommand(DISP_OFF); // Display aus
+// while(isBusy()) {};
+// writeCommand(DISP_ON); // Display ein
+// while(isBusy()) {};
+// writeCommand( BLINK_OFF & CURSOR_OFF); // Blink aus und Cursor aus
+// while(isBusy()) {};
+// writeCommand(DISP_CLEAR);// Clear display
+// while(isBusy()) {};
+// }
+
+// uint8_t Lcd::isBusy () {
+// #ifdef LCD_3V3
+// // DIR_DATA_PORT = 0;
+// // SET_RW_PIN; // read
+// // CLR_RS_PIN; // command
+// // SET_E_PIN; // E = 1 (transfer start)
+// // _delay_us(10);
+// // uint8_t busy = DATA_PIN & 0x80; // read bit 7 (busy bit)
+// // CLR_E_PIN; // E = 0 (transfer end)
+// // CLR_RW_PIN;
+// // DIR_DATA_PORT = 0xff;
+// // return busy != 0;
+// _delay_us(200);
+// #else
+// _delay_us(200);
+// #endif
+// return 0;
+// }
+
+// void Lcd::writeCommand (uint8_t cmd) {
+// setData(cmd);
+// clrRW(); // write
+// clrRS(); // command
+// setE(); // E = 1 (transfer start)
+// _delay_us(10); // min. 10us
+// clrE(); // E = 0 (transfer end)
+// setData(0);
+// }
+
+// void Lcd::setDDRamAddr (uint8_t address) {
+// setData(address | 0x80);
+// clrRW(); // write
+// clrRS(); // command
+// setE(); // E = 1 (transfer start)
+// _delay_us(10); // min. 10us
+// clrE(); // E = 0 (transfer end)
+// _delay_us(10); // min. 10us
+// setData(0);
+// }
+
+// void Lcd::writeString (const char *s) {
+// while (*s) {
+// writeData(*s++);
+// while (isBusy()) {};
+// }
+// }
+
+// void Lcd::writeData (uint8_t data) {
+// setData(data);
+// setRS(); // data
+// clrRW(); // write
+// setE(); // E = 1 (transfer start)
+// _delay_us(10); // min. 10us
+// clrE(); // E = 0 (transfer end)
+// _delay_us(10); // min. 10us
+// clrRS();
+// setData(0);
+// }
+
+// void Lcd::setCursor (uint8_t row, uint8_t column) {
+// uint8_t b;
+// if (column > 20) {
+// return;
+// }
+// switch (row) {
+// case 1: b = 0x00 + column - 1; break;
+// case 2: b = 0x40 + column - 1; break;
+// case 3: b = 0x14 + column - 1; break;
+// case 4: b = 0x54 + column - 1; break;
+// default: return;
+// }
+// setDDRamAddr(b);
+// while (isBusy()) {};
+// }
+
+
+
void Lcd::initLcd () {
+
+ setData(0x00);
+ dataDirectionOut();
+
+ // setE();
+ // _delay_us(200);
+ // clrE();
+ // for (uint8_t i = 0; i < 16; i++) {
+ // setData(i << 4);
+ // _delay_us(200);
+ // }
+
+ // for (uint8_t i = 0; i < 10; i++) {
+ // clrRS();
+ // setRW();
+ // _delay_us(200);
+ // setRS();
+ // clrRW();
+ // _delay_us(200);
+ // }
+
_delay_ms(16); // min 15ms warten für Reset des Displays
+ status = 0;
+ for (uint8_t i = 0; i < 4; i++) {
+ setRegister(LCD_CMD_SET_FUNCTION | 0x08); // 4 Bit, 2 Zeilen, 5x7
+ if (i == 0) {
+ _delay_ms(5);
+ } else {
+ _delay_us(100);
+ }
+ }
- setData( 0b00111011 ); // 8bit Modus, 5x7 Zeichen, Mehrzeilen Display
- clrRW(); // write
- clrRS(); // command
- setE(); // E = 1 (transfer start)
- _delay_us(10); // min. 10us
- clrE(); // E = 0 (transfer end)
- _delay_ms(5); // min. 4.1ms
-
- setData( 0b00111011 ); // 8bit Modus, 5x7 Zeichen, Mehrzeilen Display
- clrRW(); // write
- clrRS(); // command
- setE(); // E = 1 (transfer start)
- _delay_us(10); // min. 10us
- clrE(); // E = 0 (transfer end)
- _delay_us(100); // min. 100us
-
- setData( 0b00111011 ); // 8bit Modus, 5x7 Zeichen, Mehrzeilen Display
- clrRW(); // write
- clrRS(); // command
- setE(); // E = 1 (transfer start)
- _delay_us(10); // min. 10us
- clrE(); // E = 0 (transfer end)
- _delay_us(100); // min. 100us
-
- writeCommand(DISP_OFF); // Display aus
- while(isBusy()) {};
- writeCommand(DISP_ON); // Display ein
- while(isBusy()) {};
- writeCommand( BLINK_OFF & CURSOR_OFF); // Blink aus und Cursor aus
- while(isBusy()) {};
- writeCommand(DISP_CLEAR);// Clear display
- while(isBusy()) {};
+ setRegister(LCD_CMD_DISPLAY_ON_OFF | 0x04); // display on, cursor off
+ if (!isReady(50)) {
+ status = -1;
+ return;
+ }
+
+ setRegister(LCD_CMD_DISPLAY_ON_OFF | 0x04); // display on, cursor off
+ if (!isReady(50)) {
+ status = -3;
+ return;
+ }
+
+ setRegister(LCD_CMD_DISPLAY_CLEAR);
+ if (!isReady(1200)) {
+ status = -4;
+ return;
+ }
+
+ status = 1;
}
-uint8_t Lcd::isBusy () {
- #ifdef LCD_3V3
- // DIR_DATA_PORT = 0;
- // SET_RW_PIN; // read
- // CLR_RS_PIN; // command
- // SET_E_PIN; // E = 1 (transfer start)
- // _delay_us(10);
- // uint8_t busy = DATA_PIN & 0x80; // read bit 7 (busy bit)
- // CLR_E_PIN; // E = 0 (transfer end)
- // CLR_RW_PIN;
- // DIR_DATA_PORT = 0xff;
- // return busy != 0;
- _delay_us(200);
- #else
- _delay_us(200);
- #endif
- return 0;
+
+void Lcd::setRegister (uint8_t cmd) {
+
+ setData(0x00);
+ dataDirectionOut();
+
+ clrE();
+ clrRW();
+ clrRS();
+
+ setData(cmd & 0xf0); // send High-Nibble
+ setE();
+ _delay_us(LCD_PULSE_LENGTH);
+ clrE();
+ _delay_us(1);
+
+ setData(cmd << 4); // send Low-Nibble
+ setE();
+ _delay_us(LCD_PULSE_LENGTH);
+ clrE();
+ _delay_us(1);
}
-void Lcd::writeCommand (uint8_t cmd) {
- setData(cmd);
- clrRW(); // write
- clrRS(); // command
- setE(); // E = 1 (transfer start)
- _delay_us(10); // min. 10us
- clrE(); // E = 0 (transfer end)
- setData(0);
+void Lcd::setDRAddr (uint8_t address) {
+ waitOnReady();
+ setRegister(LCD_CMD_SET_DDRAM_ADDR | address);
+ waitOnReady();
}
-void Lcd::setDDRamAddr (uint8_t address) {
- setData(address | 0x80);
- clrRW(); // write
- clrRS(); // command
- setE(); // E = 1 (transfer start)
- _delay_us(10); // min. 10us
- clrE(); // E = 0 (transfer end)
- _delay_us(10); // min. 10us
- setData(0);
+void Lcd::waitOnReady () {
+ if (isReady(50) == 0) {
+ status = -6;
+ }
}
-void Lcd::writeString (const char *s) {
- while (*s) {
- writeData(*s++);
- while (isBusy()) {};
+
+bool Lcd::isReady (uint16_t us) {
+ if (status < 0) {
+ return false;
+ }
+
+ uint8_t busy;
+ dataDirectionIn();
+ setData(0xff); // enable internal pull up
+
+ do {
+ uint8_t data = 0;
+ setRW();
+ clrRS();
+
+ _delay_us(1);
+ setE();
+ _delay_us(LCD_PULSE_LENGTH);
+ data = getData() & 0xf0; // High Nibble
+ clrE();
+
+ _delay_us(1);
+ setE();
+ _delay_us(LCD_PULSE_LENGTH);
+ data |= getData() >> 4; // Low Nibble
+
+ clrE();
+ _delay_us(1);
+ clrRW();
+
+ busy = data & LCD_BUSY_FLAG;
+ us = (us >= 11) ? us - 11 : 0;
+ } while (us > 0 && busy);
+
+ if (status == 1 && busy) {
+ status = -5;
}
+
+ setData(0x00);
+ dataDirectionOut();
+
+ return busy == 0;
}
-void Lcd::writeData (uint8_t data) {
- setData(data);
- setRS(); // data
- clrRW(); // write
- setE(); // E = 1 (transfer start)
- _delay_us(10); // min. 10us
- clrE(); // E = 0 (transfer end)
- _delay_us(10); // min. 10us
- clrRS();
- setData(0);
+
+void Lcd::setDisplayOn () {
+ waitOnReady();
+ setRegister(LCD_CMD_DISPLAY_ON_OFF | 0x04); // display on
+ waitOnReady();
+}
+
+void Lcd::setDisplayOff () {
+ waitOnReady();
+ setRegister(LCD_CMD_DISPLAY_ON_OFF); // display off
+ waitOnReady();
+}
+
+void Lcd::clear () {
+ waitOnReady();
+ setRegister(LCD_CMD_DISPLAY_CLEAR);
+ while (!isReady(1200)) {
+ }
}
-void Lcd::setCursor (uint8_t row, uint8_t column) {
- uint8_t b;
- if (column > 20) {
- return;
- }
- switch (row) {
- case 1: b = 0x00 + column - 1; break;
- case 2: b = 0x40 + column - 1; break;
- case 3: b = 0x14 + column - 1; break;
- case 4: b = 0x54 + column - 1; break;
- default: return;
- }
- setDDRamAddr(b);
- while (isBusy()) {};
+void Lcd::setCursor (uint8_t rowIndex, uint8_t columnIndex) {
+ if (status != 1 || rowIndex > 1) {
+ return;
+ }
+ if (rowIndex) {
+ setDRAddr(0x40 + columnIndex);
+ } else {
+ setDRAddr(columnIndex);
+ }
}
+
+void Lcd::putChar (char c) {
+ if (status != 1) {
+ return;
+ }
+
+ waitOnReady();
+
+ setData(0x00);
+ dataDirectionOut();
+ clrE();
+ clrRW();
+ setRS();
+
+ PORTB &= 0x0f;
+ setData(c & 0xf0); // send High-Nibble
+ setE();
+ _delay_us(LCD_PULSE_LENGTH);
+ clrE();
+ _delay_us(1);
+
+ setData(c << 4); // send Low-Nibble
+ setE();
+ _delay_us(LCD_PULSE_LENGTH);
+ clrE();
+ _delay_us(1);
+ clrRS();
+ _delay_us(1);
+}
+
+void Lcd::puts (const char * str) {
+ while (*str && status == 1) {
+ putChar(*str++);
+ }
+ waitOnReady();
+}
\ No newline at end of file