// Nano-X-Base V1a V2a Beschreibung
// --------------------------------- -------
+ // BL ........... PC0 PC0 Backlight ON(=1) / OFF(=0)
// 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
- #ifdef LCD_3V3
- #define DATA_PIN PINB
- #endif
-
void Lcd::init () {
- DDRA |= (1 << PA3);
+ DDRA |= (1 << PA3) | (1 << PA0);
DDRB = 0xff;
DDRD |= (1 << PD7) | (1 << PD6);
initLcd();
- #ifdef LCD_3V3
- printf_P(PSTR("init 3.3V LCD (%d)"), status);
- #else
- printf_P(PSTR("init 5V LCD (%d)"), status);
- #endif
+ printf_P(PSTR("init LCD ("));
+ if (status == 1) {
+ printf_P(PSTR("OK)"));
+ } else {
+ printf_P(PSTR("ERROR %d)"), status);
+ }
+ setBacklightOn();
}
void Lcd::cleanup () {
- DDRA &= ~(1 << PA3);
+ clear();
+ PORTA &= ~((1 << PA3) | (1 << PA0));
+ DDRA &= ~((1 << PA3) | (1 << PA0));
+ PORTB = 0;
DDRB = 0;
+ PORTD &= ~((1 << PD7) | (1 << PD6));
DDRD &= ~((1 << PD7) | (1 << PD6));
}
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; }
+ void Lcd::dataDirectionIn () {
+ if (hardwareVersion == 1) {
+ // read back not allowed (missing level shifter 5V -> 3.3V)
+ DDRB = 0xff;
+ } else {
+ DDRB = 0x00;
+ }
+ }
+
uint8_t Lcd::getData () {
- return PINB;
+ if (hardwareVersion == 1) {
+ // read back not allowed (missing level shifter 5V -> 3.3V)
+ _delay_ms(1);
+ return 0x00; // bit 8 (busy) = 0
+ } else {
+ return PINB;
+ }
}
void Lcd::setData (uint8_t data) {
PORTB = data;
}
+
+ void Lcd::setBacklightOn () {
+ PORTA |= (1 << PA0);
+ }
+
+ void Lcd::setBacklightOff () {
+ PORTA &= ~(1 << PA0);
+ }
+
#endif
#ifdef __AVR_ATmega328P__
// Arduino Nano (5V)
// ---------------------------------------------------------------
+
+ // Nano-X-Base V1a V2a Beschreibung
+ // --------------------------------- -------
+ // BL ........... PC0 PC0 Backlight ON(=1) / OFF(=0)
+ // E ........... PC3 PC3 LCD Enable (Verbindung via J25 erforderlich)
+ // R/W .......... PD3 PD3 Read/Write: Read=1, Write=0
+ // RS ........... PD2 PD2 Register Select: Command=0, Data=1
+ // Data0 ........ PD4 PD4
+ // Data1 .........PB0 PB0
+ // Data2 .........PD7 PD7
+ // Data3 .........PD6 PD6
+ // Data4 .........PB2 PB2
+ // Data5 .........PB3 PB3
+ // Data6 .........PB4 PB4
+ // Data7 .........PB5 PB5
+
// PC3 ..... E --> LCD Enable (Verbindung via J25 erforderlich)
// PD3 ..... R/W --> Read/Write: Read=1, Write=0
// PD2 ..... RS --> Register Select: Command=0, Data=1
- // PD4 ..... Data0
- // PB0 ..... Data1
- // PD7 ..... Data2
- // PD6 ..... Data3
- // PB2 ..... Data4
- // PB3 ..... Data5
- // PB4 ..... Data6
- // PB5 ..... Data7
+
void Lcd::init () {
clrRW();
clrE();
setData(0);
DDRB |= (1 << PB5) | (1 << PB4) | (1 << PB3) | (1 << PB2) | (1 << PB0);
- DDRC |= (1 << PC3);
+ DDRC |= (1 << PC3) | (1 << PC0);
DDRD |= (1 << PD7) | (1 << PD6) | (1 << PD4) | (1 << PD3) | (1 << PD2);
initLcd();
- #ifdef LCD_3V3
- printf_P(PSTR("init 3.3V LCD"));
- #else
- printf_P(PSTR("init 5V LCD"));
- #endif
+ printf_P(PSTR("init LCD ("));
+ if (status == 1) {
+ printf_P(PSTR("OK)"));
+ } else {
+ printf_P(PSTR("ERROR %d)"), status);
+ }
+ setBacklightOn();
}
void Lcd::cleanup () {
- clrRW();
- clrRS();
- clrE();
- setData(0);
+ clear();
+ PORTB &= ~((1 << PB5) | (1 << PB4) | (1 << PB3) | (1 << PB2) | (1 << PB0));
+ PORTC &= ~((1 << PC3) | (1 << PC0));
+ PORTD &= ~((1 << PD7) | (1 << PD6) | (1 << PD4) | (1 << PD3) | (1 << PD2));
DDRB &= ~((1 << PB5) | (1 << PB4) | (1 << PB3) | (1 << PB2) | (1 << PB0));
- DDRC &= ~(1 << PC3);
+ DDRC &= ~((1 << PC3) | (1 << PC0));
DDRD &= ~((1 << PD7) | (1 << PD6) | (1 << PD4) | (1 << PD3) | (1 << PD2));
}
if (data & 0x40) PORTB |= (1 << PB4); else PORTB &= ~((1 << PB4));
if (data & 0x80) PORTB |= (1 << PB5); else PORTB &= ~((1 << PB5));
}
+
+ void Lcd::dataDirectionOut () {
+ if (!mode4Bit) {
+ DDRB |= (1 << PB0);
+ DDRD |= ((1 << PD7) | (1 << PD6) | (1 << PD4));
+ }
+ DDRB |= ((1 << PB5) | (1 << PB4) | (1 << PB3) | (1 << PB2));
+ }
+
+ void Lcd::dataDirectionIn () {
+ if (hardwareVersion == 1) {
+ // read back not allowed (missing level shifter 5V -> 3.3V)
+ dataDirectionOut();
+ } else {
+ if (!mode4Bit) {
+ DDRB &= ~(1 << PB0);
+ DDRD &= ~((1 << PD7) | (1 << PD6) | (1 << PD4));
+ }
+ DDRB &= ~((1 << PB5) | (1 << PB4) | (1 << PB3) | (1 << PB2));
+ }
+ }
+
+ uint8_t Lcd::getData () {
+ if (hardwareVersion == 1) {
+ // read back not allowed (missing level shifter 5V -> 3.3V)
+ _delay_ms(1);
+ return 0x00; // bit 8 (busy) = 0
+ } else {
+ uint8_t b = 0;
+ b |= ((PIND & (1 << PD4)) != 0) << 0;
+ b |= ((PINB & (1 << PB0)) != 0) << 1;
+ b |= ((PIND & (1 << PD7)) != 0) << 2;
+ b |= ((PIND & (1 << PD6)) != 0) << 3;
+ b |= ((PINB & (1 << PB2)) != 0) << 4;
+ b |= ((PINB & (1 << PB3)) != 0) << 5;
+ b |= ((PINB & (1 << PB4)) != 0) << 6;
+ b |= ((PINB & (1 << PB5)) != 0) << 7;
+ return b;
+ }
+ }
+
+ void Lcd::setBacklightOn () {
+ PORTC |= (1 << PC0);
+ }
+
+ void Lcd::setBacklightOff () {
+ PORTC &= ~(1 << PC0);
+ }
+
#endif
// Befehle für das Display
#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_MODE4BIT 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
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 (mode4Bit) {
+ setRegister(LCD_CMD_SET_MODE4BIT | 0x08); // 4 Bit, 2/4 Zeilen, 5x7
+ } else {
+ setRegister(0x08); // 8 Bit, 2 Zeilen, 5x7
+ }
if (i == 0) {
_delay_ms(5);
} else {
status = 1;
}
-
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);
+ writeData(cmd);
+}
- setData(cmd << 4); // send Low-Nibble
+void Lcd::writeData (uint8_t data) {
+ clrE();
+ dataDirectionOut();
+ if (mode4Bit) {
+ setData(data & 0xf0); // send High-Nibble
+ setE();
+ _delay_us(LCD_PULSE_LENGTH);
+ clrE();
+ _delay_us(1);
+ setData(data << 4); // send Low-Nibble
+ } else {
+ setData(data); // send data byte
+ }
setE();
_delay_us(LCD_PULSE_LENGTH);
clrE();
}
}
-
bool Lcd::isReady (uint16_t us) {
if (status < 0) {
return false;
}
+ if (hardwareVersion == 1) {
+ // read back not allowed (missing level shifter)
+ _delay_ms(1);
+ return true;
+ }
uint8_t busy;
dataDirectionIn();
void Lcd::setDisplayOn () {
+ if (status != 1) {
+ return;
+ }
waitOnReady();
setRegister(LCD_CMD_DISPLAY_ON_OFF | 0x04); // display on
waitOnReady();
}
void Lcd::setDisplayOff () {
+ if (status != 1) {
+ return;
+ }
waitOnReady();
setRegister(LCD_CMD_DISPLAY_ON_OFF); // display off
waitOnReady();
}
void Lcd::clear () {
+ if (status != 1) {
+ return;
+ }
waitOnReady();
setRegister(LCD_CMD_DISPLAY_CLEAR);
- while (!isReady(1200)) {
- }
+ waitOnReady();
}
void Lcd::setCursor (uint8_t rowIndex, uint8_t columnIndex) {
- if (status != 1 || rowIndex > 1) {
+ if (status != 1 || columnIndex >= 20) {
return;
}
- if (rowIndex) {
- setDRAddr(0x40 + columnIndex);
- } else {
- setDRAddr(columnIndex);
+ uint8_t b;
+ switch (rowIndex) {
+ case 0: b = 0x00 + columnIndex; break;
+ case 1: b = 0x40 + columnIndex; break;
+ case 2: b = 0x14 + columnIndex; break;
+ case 3: b = 0x54 + columnIndex; break;
+ default: return;
}
+ setDRAddr(b);
+ waitOnReady();
}
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);
+ writeData(c);
clrRS();
- _delay_us(1);
+ waitOnReady();
}
void Lcd::puts (const char * str) {
while (*str && status == 1) {
putChar(*str++);
}
- waitOnReady();
}
\ No newline at end of file