luma.oled: Wrong Init Routine for SSD1322 ? / NHD-2.7-12864WD
RPi3 B+ Linux 4.9.79-v7+ #1086 armv7l GNU/Linux
I got this new display recently for a project and have been trying to get started with it and luma.oled. Datasheet here: https://www.mouser.com/ds/2/291/NHD-2.7-12864WDY3-1116258.pdf It has an SSD1322 controller that I am trying to access via SPI on the raspi.
config is as such:
--display=ssd1322
--interface=spi
--spi-device=0
--spi-port=0
--gpio-reset=23
--gpio-data-command=24
--mode=RGB
Here is a video a first trial where it kind of worked, but now it doesn’t react at all to any of the examples. It is clearly not initialized and driven in the right way. The rotating cube was the only example doing anything surprisingly for some moments, unclear why. https://www.youtube.com/watch?v=jjIOZmPjGdw
Here is the recommended init from the datasheet:
void NHD12864WDY3_Init(void){
digitalWrite(RES, LOW); //pull /RES (pin #16) low
delayUS(200); //keep /RES low for minimum 200μs
digitalWrite(RES, HIGH);//pull /RES high
delayUS(200); //wait minimum 200μs before sending commands
writeCommand(0xAE); //display OFF
writeCommand(0xB3); //set CLK div. & OSC freq.
writeData(0x91);
writeCommand(0xCA); //set MUX ratio
writeData(0x3F);
writeCommand(0xA2); //set offset
writeData(0x00);
writeCommand(0xAB); //function selection
writeData(0x01);
writeCommand(0xA0); //set re-map
writeData(0x16);
writeData(0x11);
writeCommand(0xC7); //master contrast current
writeData(0x0F);
writeCommand(0xC1); //set contrast current
writeData(0x9F);
writeCommand(0xB1); //set phase length
writeData(0xF2);
writeCommand(0xBB); //set pre-charge voltage
writeData(0x1F);
writeCommand(0xB4); //set VSL
writeData(0xA0);
writeData(0xFD);
writeCommand(0xBE); //set VCOMH
writeData(0x04);
writeCommand(0xA6); //set display mode
writeCommand(0xAF); //display ON
}
In luma/oled/device.py in the SSD1322 init function there are many differences to this, so I am wondering if this is the culprit of my problems?
self.command(0xFD, 0x12) # Unlock IC
self.command(0xA4) # Display off (all pixels off)
self.command(0xB3, 0xF2) # Display divide clockratio/freq
self.command(0xCA, 0x3F) # Set MUX ratio
self.command(0xA2, 0x00) # Display offset
self.command(0xA1, 0x00) # Display start Line
self.command(0xA0, 0x14, 0x11) # Set remap & dual COM Line
self.command(0xB5, 0x00) # Set GPIO (disabled)
self.command(0xAB, 0x01) # Function select (internal Vdd)
self.command(0xB4, 0xA0, 0xFD) # Display enhancement A (External VSL)
self.command(0xC7, 0x0F) # Master contrast (reset)
self.command(0xB9) # Set default greyscale table
self.command(0xB1, 0xF0) # Phase length
self.command(0xD1, 0x82, 0x20) # Display enhancement B (reset)
self.command(0xBB, 0x0D) # Pre-charge voltage
self.command(0xB6, 0x08) # 2nd precharge period
self.command(0xBE, 0x00) # Set VcomH
self.command(0xA6) # Normal display (reset)
self.command(0xA9) # Exit partial display
self.contrast(0x7F) # Reset
Here is an edit I attempted but its still not working at all, the display is not activated and I am unsure about some additional steps in the initialization that I got rid of.
self.command(0xAE) # Display off (all pixels off) self.command(0xA4)
self.command(0xB3, 0x91) # Display divide clockratio/freq was: self.command(0xB3, 0xF2)
self.command(0xCA, 0x3F) # Set MUX ratio
self.command(0xA2, 0x00) # Display offset
self.command(0xAB, 0x01) # Display start Line was: self.command(0xA1, 0x00)
self.command(0xA0, 0x16, 0x11) # Set remap & dual COM Line was: self.command(0xA0, 0x14, 0x11)
self.command(0xC7, 0x0F) # Master contrast (reset)
self.command(0xC1, 0x9F) # ADDITION set contrast current
self.command(0xB1, 0xF2) # Phase length was: self.command(0xB1, 0xF0)
self.command(0xBB, 0x1F) # Pre-charge voltage was: self.command(0xBB, 0x0D)
self.command(0xB4, 0xA0, 0xFD) # ADDITION set VSL
self.command(0xBE, 0x04) # Set VcomH was: self.command(0xBE, 0x00)
self.command(0xA6) # Normal display (reset)
self.command(0xAF) # Exit partial display self.command(0xA9)
The question is, do we need to differntiate this display from the other SSD1322 driven ones, is my display “special” or broken or is this init routine generally wrong for the SSD1322 controller or did I do something wrong with SPI on the RPi… I am not very clear on how fast we can drive this display (10Mhz? it sometimes worked for a few seconds at a time as seen in the video with 16Mhz)
I am glad about any pointers you can give me to get this display running and if I/we can find a solution I’ll send a pull request if necessary.
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Comments: 35 (8 by maintainers)
I’ve been having some issues with the same 2.7 New Haven display. Initially the modified _nhd class seemed to work. But grey ramps were messed up and anitalised text looked seriously wonky. I see that the class was writing out byte values rather than nibble encoded 4bit / 16 grey levels. After some experimentation it looks very much like there’s something interesting going on here.
I /think/ every other nibble controls the alternate scan of the pixel. Very strange. Anyway if I write out data for wxh (rather than wxh/2) and duplicate every pixel into both the upper and lower nibble everything looks great - the ramps now display correctly and text renders as expected - where’s previously values like 240 (prior to send to device) would snap to an incredibly low display value which looks effectively black).
If I write a zero nibble then a 4 but it displays dim but full screen. Same if I write a high nibble then zero. So clearly it needs 8bits per pixel. But it’s doing something with both the top and bottom nibble for that same pixel- seemingly it’s a dual scan on the pixel which I don’t get with the mechanics of how oleds work for precharge cycles etc. but nonetheless it appears to work a /lot/ better.
So sorry to reopen this but I think the nhd init routine / display routines are still wrong for things that aren’t pure black / white.
this is the working ramps. I can upload more images to show the diffs as needed.
I will try and tidy up the copious init routine hacks and submit a PR.
George
If pins 19 and 20 weren’t tie to logic 0 (usually ground) and VDD, then those pins are floating. You won’t have a guarantee of the interface mode. Re-wire your setup and the only pins you can leave not counted are the one labeled N.C. (3, 9, 15, and 18). All VSS pins must be connect to ground.
Shoot me an email if you need further assistance.
Here is the entire mod of the ssd1322:
I have the NHD-2.7-12864WDW3 and was able to get the SSD1322 driver to work with the following modifications of the ssd1322 class:
I added a new method called reset_display to the device class in luma.core.device.py
I also added
usleeptoluma.core.util.pyFinally, I added two new methods to bitbang class in luma.core.interface.serial.py.
I used the following command line config:
--display=ssd1322 --interface=spi --width=256 --height=64 --spi-bus-speed=16000000When I used a width of 128, there were horizontal bars (64bit wide) on each side of the display. This was pretty odd, since newhaven lists the display as 128x64. Once I changed the width parameter to 256 the full display was used.
I think I’m still having issues with the fonts that came with luma.examples. I haven’t tried any other fonts. I’m not sure if the default fonts are usable with 256x64 since the wiki does not confirm working with 256x64.
Here is an pic of the default font, C&C Red Alert [INET].ttf, used in sys_info.py
Here is an pic of the font tiny.ttf used in sys_info.py