Test mode for NHD-0420CW-xxx displays?
I am having a hell of a time getting these to work.
I get absolutely nothing out of them.
So I was wondering.. as the subject says.. if there is any way to test these at power on?
Usually I get OLEDs or LCDs working within an hour.... these I have been working on for two days now and I haven't even gotten them so much as flicker and all of the example code is written for the Arduino crowd.
I am using Quartus and a Cyclone 2 and can verify the bus is running @ 100Khz so it's not going too fast.
Suppose as a last resort I can pull out an ATmega and load up Atmel Studio and give that a shot.
I am hoping Digi-Key didn't send me a bunch of duds
Thanks in advance!
BTW, the captcha images are hard to read for us old, grey guys :)
-
Ok, so a colleague remembered that he gave his son an Arduino a couple years ago.
We were able to get a demo program running on the Arduino so now I have to figure out why we can't get this working with our code.
At least we have something that works to probe to death.0 -
Would you be able to share some more information about your code:
- Are you sending the data via. SPI or I2C?
- What are the voltage levels for your devices?
Would you also be able to provide how you are sending the data to these displays from the Cyclone 2? (Bit Format)0 -
I can't share anything on that because it's proprietary.. one of the things that makes this a little hard when asking for help.
We are looking for a display to work in an existing product and the physical dimensions of this display fit the bill.
We went simple - For now we are just trying to get it to work on one on our Atmel prototyping boards.
We see it working with the Arduino example and just trying to sort out what exactly it's doing in the bowels.
Tons of overhead in the Arduino code and I suspect that we are looking at timing issues because that.
But, we are still scratching our heads.
Tomorrow is another day.
Might have better luck. Who knows.0 -
Because I just can't put it down....
Some test code below... ideas what's being fouled up on the bus?
#define F_CPU 20000000UL
#include <avr/io.h>
#include <util/delay.h>
const uint8_t ROW_N = 4; // Number of display rows
const uint8_t COLUMN_N = 20; // Number of display columns
const uint8_t SLAVE2W = 0x3C; // Display I2C address, in 7-bit form: 0x3C if SA0=LOW, 0x3D if SA0=HIGH
uint8_t new_line[4] = {0x80, 0xA0, 0xC0, 0xE0}; // DDRAM address for each line of the display
uint8_t rows = 0x08; // Display mode: 1/3 lines or 2/4 lines; default 2/4 (0x08)
uint8_t tx_packet[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; // Packet to be transmitted (max 20 bytes)
void i2c_init(void)
{
TWSR = 0;
TWBR = ((F_CPU / 100000L) - 16) / 2;
//TWBR = 0xC0;
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA);
}
void i2c_begin(void)
{
TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE) | _BV(TWSTA);
while (!(TWCR & _BV(TWINT)));
}
void i2c_end(void)
{
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTO);
}
void i2c_write(uint8_t data)
{
TWDR = data;
TWCR = _BV(TWINT) | _BV(TWEN);
while (!(TWCR & _BV(TWINT)));
}
void send_packet(uint8_t x) // SUBROUTINE: SEND TO THE DISPLAY THE x BYTES STORED IN tx_packet
{
uint8_t ix = 0; // Bytes index
i2c_begin();
i2c_write(SLAVE2W); // Begin the transmission via I2C to the display with the given address
for(ix=0; ix<x; ix++) // One byte at a time,
{
i2c_write(tx_packet[ix]); // queue bytes for transmission
}
i2c_end(); // Transmits the bytes that were queued
}
void command(uint8_t c) // SUBROUTINE: PREPARES THE TRANSMISSION OF A COMMAND
{
tx_packet[0] = 0x00; // Control Byte; C0_bit=0, D/C_bit=0 -> following Data Byte contains command
tx_packet[1] = c; // Data Byte: the command to be executed by the display
send_packet(2); // Transmits the two bytes
}
void data(uint8_t d) // SUBROUTINE: PREPARES THE TRANSMISSION OF A BYTE OF DATA
{
tx_packet[0] = 0x40; // Control Byte; C0_bit=0, D/C_bit=1 -> following Data Byte contains data
tx_packet[1] = d; // Data Byte: the character to be displayed
send_packet(2); // Transmits the two bytes
}
void initlcd(void) // INITIAL SETUP
{
_delay_us(200); // Waits 200 us for stabilization purpose
i2c_init(); // Initiate the Wire library and join the I2C bus as a master
_delay_ms(10); // Waits 10 ms for stabilization purpose
if (ROW_N == 2 || ROW_N == 4)
rows = 0x08; // Display mode: 2/4 lines
else
rows = 0x00; // Display mode: 1/3 lines
command(0x22 | rows); // Function set: extended command set (RE=1), lines #
command(0x71); // Function selection A:
data(0x5C); // enable internal Vdd regulator at 5V I/O mode (def. value) (0x00 for disable, 2.8V I/O)
command(0x20 | rows); // Function set: fundamental command set (RE=0) (exit from extended command set), lines #
command(0x08); // Display ON/OFF control: display off, cursor off, blink off (default values)
command(0x22 | rows); // Function set: extended command set (RE=1), lines #
command(0x79); // OLED characterization: OLED command set enabled (SD=1)
command(0xD5); // Set display clock divide ratio/oscillator frequency:
command(0x70); // divide ratio=1, frequency=7 (default values)
command(0x78); // OLED characterization: OLED command set disabled (SD=0) (exit from OLED command set)
if (ROW_N > 2)
command(0x09); // Extended function set (RE=1): 5-dot font, B/W inverting disabled (def. val.), 3/4 lines
else
command(0x08); // Extended function set (RE=1): 5-dot font, B/W inverting disabled (def. val.), 1/2 lines
command(0x06); // Entry Mode set - COM/SEG direction: COM0->COM31, SEG99->SEG0 (BDC=1, BDS=0)
command(0x72); // Function selection B:
data(0x0A); // ROM/CGRAM selection: ROM C, CGROM=250, CGRAM=6 (ROM=10, OPR=10)
command(0x79); // OLED characterization: OLED command set enabled (SD=1)
command(0xDA); // Set SEG pins hardware configuration:
command(0x10); // alternative odd/even SEG pin, disable SEG left/right remap (default values)
command(0xDC); // Function selection C:
command(0x00); // internal VSL, GPIO input disable
command(0x81); // Set contrast control:
command(0x7F); // contrast=127 (default value)
command(0xD9); // Set phase length:
command(0xF1); // phase2=15, phase1=1 (default: 0x78)
command(0xDB); // Set VCOMH deselect level:
command(0x40); // VCOMH deselect level=1 x Vcc (default: 0x20=0,77 x Vcc)
command(0x78); // OLED characterization: OLED command set disabled (SD=0) (exit from OLED command set)
command(0x20 | rows); // Function set: fundamental command set (RE=0) (exit from extended command set), lines #
command(0x01); // Clear display
_delay_ms(2); // After a clear display, a minimum pause of 1-2 ms is required
command(0x80); // Set DDRAM address 0x00 in address counter (cursor home) (default value)
command(0x0C); // Display ON/OFF control: display ON, cursor off, blink off
_delay_ms(250); // Waits 250 ms for stabilization purpose after display on
if (ROW_N == 2)
new_line[1] = 0xC0; // DDRAM address for each line of the display (only for 2-line mode)
}
void blocks(void) // SUBROUTINE: FILLS THE ENTIRE DISPLAY WITH THE CHARACTER "BLOCK"
{
uint8_t r = 0; // Row index
uint8_t c = 0; // Column index
command(0x01); // Clear display (and cursor home)
_delay_ms(2); // After a clear display, a minimum pause of 1-2 ms is required
for (r=0; r<ROW_N; r++) // One row at a time,
{
command(new_line[r]); // moves the cursor to the first column of that line
for (c=0; c<COLUMN_N; c++) // One character at a time,
{
data(0xDB); // displays the character 0xDB (block)
_delay_ms(10); // Waits, only for visual effect purpose
}
_delay_ms(100); // Waits, only for visual effect purpose
}
}
int main(void)
{
i2c_init();
initlcd();
/* Replace with your application code */
while (1)
{
blocks();
}
}0 -
Wanted to post the solution to the above....
Spotted by an AVRFreaks member.
The address needed to be shifted to the left by 1 bit.
I do indeed have egg on my face
Fixed code:void send_packet(uint8_t x) // SUBROUTINE: SEND TO THE DISPLAY THE x BYTES STORED IN tx_packet
{
uint8_t ix = 0; // Bytes index
uint8_t address = 0;
address |= SLAVE2W << 1;
i2c_begin();
i2c_write(address); // Begin the transmission via I2C to the display with the given address
for(ix=0; ix<x; ix++) // One byte at a time,
{
i2c_write(tx_packet[ix]); // queue bytes for transmission
}
i2c_end(); // Transmits the bytes that were queued
}« Last Edit: May 05, 2016, 10:36:24 PM by LoyalServant »0 -
Hi,
Glad to see you have it figured out.
For this controller the I²C address will be 7-bits wide, and the 8th-bit (LSB) will determine whether you are reading from or writing to the display.0 -
Hi,
Glad to see you have it figured out.
For this controller the I²C address will be 7-bits wide, and the 8th-bit (LSB) will determine whether you are reading from or writing to the display.
Yeah we missed that teensy little bit (no pun intended) in our other code as well.
That leads me to another question regarding mounting...
Why are the boards castellated? The full holes would have been nice.
We can still mount it just that it makes it a tad interesting.0 -
We wanted to minimize the overall size of the display. This helped reduce the overall size.
0
Please sign in to leave a comment.
Comments
8 comments