winstar eh1602a SPI interface
See original GitHub issueType of Raspberry Pi
Pi 3 Model B+
Linux Kernel version
Linux moode 5.4.72-v7+ #1356 SMP Thu Oct 22 13:56:54 BST 2020 armv7l GNU/Linux
Expected behaviour
I would like to render text on the display. I already tested the display with an arduino with spi and parallel interface and both works. Here ist the arduino code for the spi interface
#define SPIPORT (PORTB)
#define SPITOGGLE (PINB)
// PB5 (0x20) is SCK (output) green OLED pin 12
#define SPI_SCK_PIN (13)
#define SCK_MASK (0x20)
#define CLR_SCK (PORTB &= ~(SCK_MASK))
#define SET_SCK (PORTB |= (SCK_MASK))
// PB4 (0x10) is MISO (input) blue OLED pin 13
//(reference only, it is an input)
#define SPI_MISO_PIN (12)
#define MISO_MASK (0x10)
#define CLR_MISO (PORTB &= ~(MISO_MASK))
#define SET_MISO (PORTB |= (MISO_MASK))
// PB3 (0x08) is MOSI (output) violet OLED pin 14
#define SPI_MOSI_PIN (11)
#define MOSI_MASK (0x08)
#define CLR_MOSI (PORTB &= ~(MOSI_MASK))
#define SET_MOSI (PORTB |= (MOSI_MASK))
// DB2 (0x04) is SS (output) gray OLED pin 16
#define SPI_SS_PIN (10)
#define SS_MASK (0x04)
#define CLR_SS (PORTB &= ~(SS_MASK))
#define SET_SS (PORTB |= (SS_MASK))
#define DATA (1)
#define COMMAND (0)
//===========================================================================
void write_to_OLED_SPI(uint8_t destination,uint8_t data)
{
//Bits sent in this order:
// data(1)/command(0) flag
// read(1)/write(0) flag
// data.7 (msb)
// data.6
// data.5
// data.4
// data.3
// data.2
// data.1
// data.0 (lsb)
#if(1)
//Pretty fast software SPI 10-bit transfer code
//Several ideas taken from the fastest non-assembly implementation at:
//http://nerdralph.blogspot.com/2015/03/fastest-avr-software-spi-in-west.html
//
// The SS pin is low for ~3.8uS, the clock frequency is ~ 2.6MHz
// 47x faster than above
//Pre-calculate the value that will drive clk and data low in one cycle.
//(Note that this is not interrupt safe if an ISR is writing to the same port)
register uint8_t
force_clk_and_data_low;
//Select the chip
CLR_SS;
//Pre-calculate the value that will drive clk and data low in one
//operation.
force_clk_and_data_low = (SPIPORT & ~(MOSI_MASK | SCK_MASK) );
//Set clock and data low
SPIPORT = force_clk_and_data_low;
//Set the data(1)/command(0) flag
if(DATA==destination)
{
SPITOGGLE = MOSI_MASK;
}
//Use a toggle to bring the clock up
SPITOGGLE = SCK_MASK;
//Set clock and data low
SPIPORT = force_clk_and_data_low;
//MOSI is already 0, for read(1)/write(0) flag as write
//Use a toggle to bring the clock up
SPITOGGLE = SCK_MASK;
//Now clock the 8 bits of data out
SPIPORT = force_clk_and_data_low;
if(data & 0x80)
SPITOGGLE = MOSI_MASK;
SPITOGGLE = SCK_MASK;
SPIPORT = force_clk_and_data_low;
if(data & 0x40)
SPITOGGLE = MOSI_MASK;
SPITOGGLE = SCK_MASK;
SPIPORT = force_clk_and_data_low;
if(data & 0x20)
SPITOGGLE = MOSI_MASK;
SPITOGGLE = SCK_MASK;
SPIPORT = force_clk_and_data_low;
if(data & 0x10)
SPITOGGLE = MOSI_MASK;
SPITOGGLE = SCK_MASK;
SPIPORT = force_clk_and_data_low;
if(data & 0x08)
SPITOGGLE = MOSI_MASK;
SPITOGGLE = SCK_MASK;
SPIPORT = force_clk_and_data_low;
if(data & 0x04)
SPITOGGLE = MOSI_MASK;
SPITOGGLE = SCK_MASK;
SPIPORT = force_clk_and_data_low;
if(data & 0x02)
SPITOGGLE = MOSI_MASK;
SPITOGGLE = SCK_MASK;
SPIPORT = force_clk_and_data_low;
if(data & 0x01)
SPITOGGLE = MOSI_MASK;
SPITOGGLE = SCK_MASK;
//Release the chip
SET_SS;
#else
//Straight-forward software SPI 10-bit transfer code, perhaps
//easier to understand, possibly more portable. Certainly slower.
//
// The SS pin is low for ~180uS, the clock frequency is ~57KHz
// 47x slower than above
//Select the chip, starting a 10-bit SPI transfer
digitalWrite(SPI_SS_PIN, LOW);
//(bit 0) Set the data(1)/command(0) flag
if(DATA==destination)
digitalWrite(SPI_MOSI_PIN, HIGH);
else
digitalWrite(SPI_MOSI_PIN, LOW);
//Clock it in.
digitalWrite(SPI_SCK_PIN, LOW);
digitalWrite(SPI_SCK_PIN, HIGH);
//(bit 1) Clear the read(1)/write(0) flag to write, clock it in.
digitalWrite(SPI_MOSI_PIN, LOW);
//Clock it in.
digitalWrite(SPI_SCK_PIN, LOW);
digitalWrite(SPI_SCK_PIN, HIGH);
//(bits 2-9) Push each of the 8 data bits out.
for(uint8_t mask=0x80;mask;mask>>=1)
{
//Set the MOSI pin high or low depending on if our mask
//corresponds to a 1 or 0 in the data.
if(mask&data)
{
digitalWrite(SPI_MOSI_PIN, HIGH);
}
else
{
digitalWrite(SPI_MOSI_PIN, LOW);
}
//Clock it in.
digitalWrite(SPI_SCK_PIN, LOW);
digitalWrite(SPI_SCK_PIN, HIGH);
}
//Release the chip, ending the 10-bit SPI transfer
digitalWrite(SPI_SS_PIN, HIGH);
#endif
}
//===========================================================================
void position_cursor(uint8_t column, uint8_t line)
{
//Set CGRAM Address, RS=0,R/W=0
// 7654 3210
// 1AAA AAAA
// 0x00 to 0x27 => Line 1
// 0x40 to 0x67 => Line 2
write_to_OLED_SPI(COMMAND,0x80 | (line?0x40:0x00) | (column & 0x3F));
}
//===========================================================================
// According to the WS0010 data sheet, only the clear display time has
// an appreciable execution time of 6mS. All others are listed at 0.
void clear_display(void)
{
//Display Clear RS=0,R/W=0
// 7654 3210
// 0000 0001
write_to_OLED_SPI(COMMAND,0x01);
_delay_ms(6);
}
//===========================================================================
void initialize_display()
{
//Refer to WS0010 data sheet, page 21
// https://www.crystalfontz.com/products/document/3176/WS0010.pdf
//The display controller requests:
// "Wait for power stabilization 500ms:
_delay_ms(500);
//Function set, RS=0,R/W=0
// 7654 3210
// 0011 NFFT
// N = lines: N=1 is 2 lines
// F = Font: 0 = 5x8, 1 = 5x10
// FT = Font Table:
// FT=00 is English/Japanese ~"standard" for character LCDs
// FT=01 is Western European I fractions, circle-c some arrows
// FT=10 is English/Russian
// FT=11 is Western European II my favorite, arrows, Greek letters
write_to_OLED_SPI(COMMAND,0x3B);
//Graphic vs character mode setting, RS=0,R/W=0
// 7654 3210
// 0001 GP11
// G = Mode: 1=graphic, 0=character
// C = Power: 1=0n, 0=off
write_to_OLED_SPI(COMMAND,0x17);
//Display On/Off Control RS=0,R/W=0
// 7654 3210
// 0000 1DCB
// D = Display On
// C = Cursor On
// B = Cursor Blink
write_to_OLED_SPI(COMMAND,0x0E);
//Display Clear RS=0,R/W=0
// 7654 3210
// 0000 0001
clear_display();
//Display home
write_to_OLED_SPI(COMMAND,0x02);
//Entry Mode Set RS=0,R/W=0
// 7654 3210
// 0000 01IS
// I = Increment/or decrement
// S = Shift(scroll) data on line
write_to_OLED_SPI(COMMAND,0x06);
//Display Clear RS=0,R/W=0
// 7654 3210
// 0000 0001
clear_display();
}
//===========================================================================
void setup()
{
//General setup, port directions.
// PB5 (0x20) is SCK (output) green OLED pin 12
pinMode(SPI_SCK_PIN, OUTPUT);
// PB4 (0x10) is MISO (input) blue OLED pin 13
//(reference only, it is an input)
pinMode(SPI_MISO_PIN, INPUT);
// PB3 (0x08) is MOSI (output) violet OLED pin 14
pinMode(SPI_MOSI_PIN, OUTPUT);
// DB2 (0x04) is SS (output) gray OLED pin 16
pinMode(SPI_SS_PIN, OUTPUT);
}
//===========================================================================
void loop()
{
//Simple demo loop, shows a screen of text, including high order characters
//( see page 10 of https://www.crystalfontz.com/controllers/WinstarDisplay/WS0010/378 )
//
//Then there is a screen with solid characters on the left, and 50%
//checkerboard characters on the right.
// Initialize the display
initialize_display();
//Display text screen
// 0123456789012345
char line1[17]=">}CRYSTALFONTZ{<";
line1[ 0]=0xF6; // right triange;
line1[ 1]=0xC7; // right triange;
line1[14]=0xC8; // left triange;
line1[15]=0xF7; // left triange;
// 0123456789012345
char line2[17]="OLED:aaaaaaaaaaS";
line2[ 5]=0xE0; //beta
line2[ 6]=0xA8; //function
line2[ 7]=0xB8; //divide
line2[ 8]=0xDA; //sigma
line2[ 9]=0xEA; //mu (micro)
line2[10]=0xDF; //alpha
line2[11]=0xDE; //omega
line2[12]=0xCF; //circle C
line2[13]=0x1A; //about equal
line2[14]=0xED; //pi
// write to the first line
position_cursor(0,0);
for(int col=0;col<16;col++)
{
write_to_OLED_SPI(DATA,line1[col]);
}
// write to the second line
position_cursor(0,1);
for(int col=0;col<16;col++)
{
write_to_OLED_SPI(DATA,line2[col]);
}
//Show the text message for a bit
_delay_ms(1000);
//Use the custom characters (CGRAM) to make the
//left half solid, the right half checkerboard
//Set CGRAM [0], to solid
write_to_OLED_SPI(COMMAND,0x40 | (0 <<3));
for(int i=1;i<=8;i++)
write_to_OLED_SPI(DATA,0xFF);
//Set CGRAM [1], checkerboard
write_to_OLED_SPI(COMMAND,0x40 | (1 <<3));
for(int i=1;i<=4;i++)
{
write_to_OLED_SPI(DATA,0xAA);
write_to_OLED_SPI(DATA,0x55);
}
// write to the first line
position_cursor(0,0);
for(int col=0;col<8;col++)
{
write_to_OLED_SPI(DATA,0); // CGRAM[0]
}
for(int col=8;col<16;col++)
{
write_to_OLED_SPI(DATA,1); // CGRAM[1]
}
// write to the second line
position_cursor(0,1);
for(int col=0;col<8;col++)
{
write_to_OLED_SPI(DATA,0); // CGRAM[0]
}
for(int col=8;col<16;col++)
{
write_to_OLED_SPI(DATA,1); // CGRAM[1]
}
//Show the pattern for a bit
_delay_ms(1000);
}
//=====================================
Actual behaviour
Nothing happens with following code:
from time import sleep
from luma.core.interface.serial import spi
from luma.oled.device import ws0010
p = spi(device=0, port=0)
d = ws0010(p, selected_font='FT01')
sleep(2)
d.text = 'HELLO'
sleep(10)
I use the 3-wire SPI and connected through a logic level converter SCK, MISO, MOSI, SS (CE0), VSS, VDD. Maybe I missing something like the Data/Command Pin which I want to use inline instead of a extra pin.
My goal is to use the pydPiper lib somehow. The pydPiper lib doesn’t support SPI yet but I saw @dhrone pushing some code here.
Regards
Issue Analytics
- State:
- Created 3 years ago
- Comments:10
Top Results From Across the Web
WEH001602A - Winstar Display
There are different interfaces optional for this model; its default 6800, available options 8080 and SPI. All Winstar standard COB OLED Character types...
Read more >WEH001602A 16X2 COB OLED Character Display 5V ...
There are different interfaces optional for this model; its default 6800, available options 8080 and SPI. All Winstar standard COB OLED Character types...
Read more >Winstar WEH1602 OLED display - SPI - Raspberry Pi Forums
Hello all, I'm working on Winstar WEH1602 OLED display in SPI mode (something like this: http://www.adafruit.com/products/823).
Read more >Interface Winstar OLEDs using the SPI interface - PICAXE Forum
... datasheet for the Winstar OLEDs that Rev-Ed sell as part of the AXE133Y should have noticed a brief mention of the SPI...
Read more >О подключении и работе с текстовыми OLED-дисплеями ...
В HD44780 встроенный резет, возможно, оправдан — автор не имеет достаточно опыта работы с ЖК-экранами, чтобы утверждать это наверняка. Но Winstar, пытаясь в ......
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Solved it!. Rearranged the RS and E pin away from GPIO7/8 which are the SPI pins (SPI is deactivated) and it works now. Startes rearranging because I checked my soundcard pins usage…
Excellent news. Interesting about GPIO pins 7/8. While their use shouldn’t matter if SPI is not enabled perhaps the documentation should be updated to avoid pins that have special purposes. I would still be interested in any materials that you have discovered that describe the SPI interface capabilities of the weh001602a.