NHD-0216KZW-AG5 Font Tables in 4-bit Mode
Hi, I've used the NHD-0216KZW-AG5 in 8-bit mode using the Western European 2 font table. It has performed as expected in 8-bit mode.
In a new design, I am using the 4-bit mode.
As long as I never change the font table, it works properly (albeit with the wrong character displayed). Whenever I try to change the font table, the display begins showing characters that are not in any font table, and eventually stops updating all together. I have to set the font table back to English/Japanese and then remove and re-apply power to the LCD to get the display operating again.
Any ideas as to where I'm going wrong?
In a new design, I am using the 4-bit mode.
As long as I never change the font table, it works properly (albeit with the wrong character displayed). Whenever I try to change the font table, the display begins showing characters that are not in any font table, and eventually stops updating all together. I have to set the font table back to English/Japanese and then remove and re-apply power to the LCD to get the display operating again.
Any ideas as to where I'm going wrong?
0
-
Can you send the part of your code that is changing the font table? 0 -
Sorry for the late reply, here is the C++ class that I'm using.
I gave up trying to get the font table to change, and instead used custom characters. However, I ran into a small issue there as well. I was unable program use the first custom character (character 0x00). I just shifted to using characters 0x01 to 0x03 and it worked fine./*
The MIT License (MIT)
Copyright (c) 2014 Cody Browne
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef _LCD_HPP_
#define _LCD_HPP_
#include <stdint.h>
template< class HW >
class LCD {
public:
static const uint16_t WIDTH = 16;
static const uint16_t CHARHEIGHT = 8;
private:
enum {
CMD_CLEAR_DISPLAY = 0x01
, CMD_RETURN_HOME = 0x02
, CMD_SET_ENTRY_MODE = 0x04
, CMD_SET_DISPLAY = 0x08
, CMD_SET_SHIFT = 0x10
, CMD_SET_FUNCTION = 0x28
, CMD_SET_CGRAM_ADDRESS = 0x40
, CMD_SET_DDRAM_ADDRESS = 0x80
, ENTRY_MODE_INCREMENT = 0x02
, ENTRY_MODE_DECREMENT = 0x00
, ENTRY_MODE_SHIFT = 0x01
, ENTRY_MODE_DONTSHIFT = 0x00
, DISPLAY_ON = 0x04
, DISPLAY_OFF = 0x00
, DISPLAY_CURSOR_ON = 0x02
, DISPLAY_CURSOR_OFF = 0x00
, DISPLAY_CURSOR_BLINK = 0x01
, DISPLAY_CURSOR_SOLID = 0x00
, SHIFT_DISPLAY = 0x08
, SHIFT_CURSOR = 0x00
, SHIFT_LEFT = 0x00
, SHIFT_RIGHT = 0x04
, FUNCTION_FT_ENGLISH_JAPANESE = 0x00
, FUNCTION_FT_WESTERN_EUROPE_1 = 0x01
, FUNCTION_FT_ENGLISH_RUSSIAN = 0x02
, FUNCTION_FT_WESTERN_EUROPE_2 = 0x03
, FUNCTION_DL_8BIT = 0x10
, FUNCTION_DL_4BIT = 0x00
, DDRAM_LINE2 = 0x40
};
static uint8_t _displayMode;
static void _probe( void );
static void _write( uint8_t data );
public:
static void Init( void );
static void Clear( void );
static void On( void );
static void Off( void );
static void GoL1( void );
static void GoL2( void );
static void Puts( const uint8_t* str );
static void PutAll( const uint8_t* line1 , const uint8_t* line2 );
static void Putc( uint8_t c );
static void SetCursor( bool ison , bool isblinking = true );
static void MakeCharacter( uint8_t value , const uint8_t* data , uint16_t data_lenght );
};
template< class HW>
uint8_t LCD< HW >::_displayMode;
template< class HW >
void LCD< HW >::PutAll( const uint8_t* line1 , const uint8_t* line2 ){
GoL1();
Puts( line1 );
GoL2();
Puts( line2 );
}
template< class HW >
void LCD< HW >::_probe( void ){
HW::template E<true>();
HW::template E<false>();
}
template< class HW >
void LCD< HW >::_write( uint8_t data ){
HW::SetNibble( data >> 4 );
_probe();
HW::SetNibble( data );
_probe();
}
template< class HW >
void LCD< HW >::Init( void ){
HW::Init();
// Start in command mode.
HW::template RS<false>();
HW::template RW<false>();
// Wake the LCD up in 8-bit mode.
HW::SetNibble( 0x3 );
_probe();
HW::Delay_ms( 100 );
// Wake the LCD up again in 8-bit mode.
HW::SetNibble( 0x3 );
_probe();
HW::Delay_ms( 10 );
// Set 4-bit mode.
HW::SetNibble( 0x2 );
_probe();
HW::Delay_ms( 10 );
// Set 4-bit mode with font table.
//FUNCTION_FT_ENGLISH_JAPANESE
//FUNCTION_FT_WESTERN_EUROPE_2
_write(
CMD_SET_FUNCTION
| FUNCTION_DL_4BIT
| FUNCTION_FT_ENGLISH_JAPANESE
);
HW::Delay_ms( 10 );
// Turn of display and cursor
_displayMode =
CMD_SET_DISPLAY
| DISPLAY_OFF
;
_write( _displayMode );
HW::Delay_ms( 1 );
// Set incrementing address without shifting the display.
_write(
CMD_SET_ENTRY_MODE
| ENTRY_MODE_INCREMENT
| ENTRY_MODE_DONTSHIFT
);
HW::Delay_ms( 1 );
}
template< class HW >
void LCD< HW >::MakeCharacter( uint8_t value , const uint8_t* data , uint16_t data_length ){
_write( 0x40 | ( value << 3 ) );
HW::Delay_ms( 1 );
HW::template RS<true>();
uint16_t i;
for( i = 0; i < data_length; ++i ){
_write( data[ i ] );
HW::Delay_ms( 1 );
}
while( i < CHARHEIGHT ){
_write( 0x00 );
HW::Delay_ms( 1 );
++i;
}
HW::template RS<false>();
_write( 0x80 );
HW::Delay_ms( 1 );
}
template< class HW >
void LCD< HW >::Puts( const uint8_t* str ){
// Set LCD control lines to write character data.
HW::template RS<true>();
HW::template RW<false>();
// Write the string out, limiting the maximum size of the string.
for( uint16_t i = 0; i < WIDTH; ++i ){
if( *str == '\0' ){
// Null termination reached.
break;
}
Putc( *str );
++str;
}
}
template< class HW >
void LCD< HW >::On( void ){
_displayMode |= DISPLAY_ON;
HW::template RS<false>();
HW::template RW<false>();
_write( _displayMode );
HW::Delay_ms( 1 );
}
template< class HW >
void LCD< HW >::Off( void ){
_displayMode &= ~DISPLAY_ON;
HW::template RS<false>();
HW::template RW<false>();
_write( _displayMode );
HW::Delay_ms( 1 );
}
template< class HW >
void LCD< HW >::SetCursor( bool ison , bool isblinking ){
if( ison ){
_displayMode |= DISPLAY_CURSOR_ON;
if( isblinking ){
_displayMode |= DISPLAY_CURSOR_BLINK;
}
else {
_displayMode &= ~DISPLAY_CURSOR_BLINK;
}
}
else {
_displayMode &= ~ DISPLAY_CURSOR_ON;
}
HW::template RS<false>();
HW::template RW<false>();
_write( _displayMode );
HW::Delay_ms( 1 );
}
template< class HW >
void LCD< HW >::Clear( void ){
HW::template RS<false>();
HW::template RW<false>();
_write( CMD_CLEAR_DISPLAY );
HW::Delay_ms( 3 );
}
template< class HW >
void LCD< HW >::GoL1( void ){
HW::template RS<false>();
HW::template RW<false>();
_write( CMD_SET_DDRAM_ADDRESS );
HW::Delay_ms( 1 );
}
template< class HW >
void LCD< HW >::GoL2( void ){
HW::template RS<false>();
HW::template RW<false>();
_write( CMD_SET_DDRAM_ADDRESS | DDRAM_LINE2 );
HW::Delay_ms( 1 );
}
template< class HW >
void LCD< HW >::Putc( uint8_t c ){
HW::template RS<true>();
HW::template RW<false>();
_write( c );
HW::Delay_ms( 1 );
}
#endif /* _LCD_HPP_ */0
Please sign in to leave a comment.
Comments
2 comments