NHD-0216CW-AB3 and an Arduino Micro timing problems?

Sorry to post this here but NHD's forum just got filled with spambots.
I'm having some (I think) timing/command issues with the NHD-0216CW-AB3 and an Arduino Micro.
The the first character is cut off on both lines and I'm at a loss. I have seen different delay times used in various spots, some not having any. I've tried various delays, commented some out, added some etc etc. I don't see much of a difference. I'm a pretty green amateur at this stuff so any help would be greatly appreciated!
Here is my code cobbled together from the nhd forum, the us2066 git hub, the mouser ino sketch, and the datasheet example: (try not to laugh at it :stuck_out_tongue: )

/*  Setup for parallel 6800 mode
 *  nhd-0216CW-AB3 oled -> Arduino micro rev 3
 *  (us2066 controller)
 *  
 * Data bits
 *     pin - name         port  -  pin
 *      7 (DB0)         - portb 0 (ss pin used as digital 17)
 *      8 (DB1)         - portb 1 (sck pin used as digital 15)
 *      9 (DB2)         - portb 2 (mosi pin used as digital 16)
 *     10 (DB3)         - portb 3 (miso pin used as digital 14)
 *     11 (DB4)         - portb 4 (digital 8)
 *     12 (DB5)         - portb 5 (digital 9)
 *     13 (DB6)         - portb 6 (digital 10)
 *     14 (DB7)         - portb 7 (digital 11)
 * Interface signal select
 *    pin - name         port  -  pin
 *     17 (BS0)         - portd 0 - (digital pin 3) For 6800 8-bit parallel: 0
 *     18 (BS1)         - portd 1 - (digital pin 2)                          0
 *     19 (BS2)         - portd 4 - (digital pin 4)                          1
 * Power supply
 *    pin - name         pin
 *      1 (VSS)        -   GND
 *      2 (VDD)        -   5V
 *      3 (REGVDD)     -   5V
 *      20 (VSS)       -   GND
 * Operation signals
 *    pin - name
 *      4 - D/C         - portf 0 (analog pin A5)
 *      5 - R/W         - portf 1 (analog pin A4)
 *      6 - E           - portf 4 (analog pin A3)
 *      15 - /CS        - portf 5 (analog pin A2)
 *      16 - /RES       - porff 6 (analog pin A1)
 *
 *Unused pins
 *                      -  portd 3 (digital pin 1) (tx)
 *                      -  portd 2 (digital pin 2) (rx)
 *                      -  portc 6 (digital pin 5)
 *                      -  portd 7 (digital pin 6)
 *                      -  porte 6 (digital pin 7)
 *                      -  portd 6 (digital pin 12)
 *                      -  portc 7 (digital pin 13)
 *                      -  portf 7 (analog pin A0)
  */

void setup() {
  //B76543210 - most -> least
  //DDRX sets output/input
  //PORTX sets high/low
  DDRD = B00010011; // bs2, bs1, bs0 are outputs. 
  DDRB = 0xFF; //Port b set to all output
  DDRF = B01110011; // /res, /cs, e , r/w, d/c 
  PORTD = B00010000; // bs2 high, bs1 low, bs0 low: 6800 parallel 8-bit
  PORTF = B01000000; // /res high (don't reset), /cs low (only 1 display), E, R/W low (always write), D/C 
  PORTB = 0x00;
  delay(10);          //delay
  command(0x2A);     //function set (extended command set)
  command(0x71);     //function selection A
  data(0x5C);        // Set 5V on REGVDD
  command(0x28);     //function set (fundamental command set)
  command(0x08);     //display off, cursor off, blink off
  command(0x2A);     //function set (extended command set)
  command(0x79);     //OLED command set enabled  
  command(0xD5);     //set display clock divide ratio/oscillator frequency
  command(0x70);     //set display clock divide ratio/oscillator frequency
  command(0x78);     //OLED command set disabled
  command(0x08);     //extended function set (2‐lines)
  command(0x06);     //COM SEG direction
  command(0x72);     //function selection B
  data(0x01);        //ROM CGRAM selection (40? 00?)
  command(0x2A);     //function set (extended command set)
  command(0x79);     //OLED command set enabled
  command(0xDA);     //set SEG pins hardware configuration
  command(0x10);     //set SEG pins hardware configuration
  command(0xDC);     //function selection C
  command(0x00);     //function selection C
  command(0x81);     //set contrast control
  command(0x7F);     //set contrast control
  command(0xD9);     //set phase length
  command(0xF1);     //set phase length
  command(0xDB);     //set VCOMH deselect level
  command(0x40);     //set VCOMH deselect level
  command(0x78);     //OLED command set disabled
  command(0x28);     //function set (fundamental command set)
  command(0x01);     //clear display
  delay(2);
  command(0x80);     //set DDRAM address to 0x00
  command(0x0C);     //display ON
  delay(100);        //delay
}  
unsigned char text5[] = {"Newhaven Display"};
unsigned char text6[] = {" 2X16 Character "};
void loop() {
        command(0x01); //clear display
        delay(2);
        command(0x02); //return home
        for(int i = 0; i < 16; i++){
          data(text5[i]);
        }

        command(0xC0); //
        for(int i = 0; i < 16; i++){
          data(text6[i]);
        }
        delay(2000);
}

void command(unsigned char c){  //To send commands
   PORTB = c;                   //command on port
   PORTF &= B11111110;         //D/C set to LOW for command
   PORTF &= ~B00010000;         //e high
   delay(1);
   PORTF |= B00010000;          //e low
    }

   void data(unsigned char d){    //To send data
           PORTB = d;                  //data on port
           PORTF |= B00000001;         //d/c high for data
           PORTF &= ~B00010000;        //e high
           delay(1);
           PORTF |= B00010000;         //e low
        }

and we end up with:


OLED datasheet:

Controller datasheet:

Thanks!

A very quick look at the data sheet and it seems to use the standard LCD character display commands so the display should probably work with the LiquidCrystal library. From what you describe and seeing the image I suspect the problem is hardware related and the display is faulty.

Ah, thanks. I was hesitant to try the lcd library because I wasn't sure if it was compatible with the standard 16 pin Hitachi HD44780 since it was 20 pin. I'll check it out and do some fiddling. Are bad lcds common?

Since you have bought a NHD display and the NHD examples are for a Mega2560, I suggest that you try that first.

Once you have verified that the hardware works properly, you can "port" it to the Micro.
Note that the databus write will be a lot more complex.
e.g. for command() will be

    case 0:   digitalWrite(CS, LOW);
              PORTB = c;

e.g. for data() will be

    case 0:   digitalWrite(CS, LOW);
              PORTB = d;

and the lcd_init() will be:

  digitalWrite(SDIN, HIGH);
  DDRB = 0xFF;
  PORTB = 0x00;

and you need to set up the command signals correctly.

David.

I noticed that if i comment out the clear display command at the end of init it will leave a character in the first slot of each line from the reset. That means the display is functioning correctly and, as david said, it is a timing mess, right? (attached)
Thanks

I suggested that you start with the NHD example code. I bet that the timing works ok.

Looking at the datasheet tCYCLE = 400ns. So I would expect Arduino code will never be too fast.
However your direct GPIO code might be < 400ns. So I would use specific delays to comply with the high and low timing.

You definitely do NOT need delay(1) in the Enable pulse. That is 1ms i.e. 1000000ns when the whole cycle is only 400ns.

If your controller is like a HD44780, the command(1) i.e. CLRHOME and command(2) i.e. HOME need a longer time than the other operations.
And the command(0xC0) GOTOXY might need 400ns to complete before you start to print the data[]

David.

david_prentice:
However your direct GPIO code might be < 400ns.
David.

That was it!
My first attempt I didn't use ports at all, got garbage output (used bitread to feed the data lines)
Found a post that recommend nothing but port registers. Faster? ok sounds good.
Was banging my head against this for awhile now and your post helpfully reminded me to try port register data and directwrite on everything else.
and bam. perfect output now.

Thanks again!