-
Notifications
You must be signed in to change notification settings - Fork 6.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for SSD1322 OLED display driver #68608
Conversation
67f53dc
to
1153b68
Compare
drivers/display/ssd1322.c
Outdated
uint16_t column_offset; | ||
}; | ||
|
||
static inline int ssd1322_write_bus(const struct device *dev, uint8_t *buf, size_t len, bool cmd) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This display looks like it could use the new MIPI DBI API. Shouldn't be too hard to transition (mostly just need to update this function and the display_write
implementation)
Can you investigate if this is possible?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it is possible. Thank you for pointing this out, I didn't notice that there is a dedicated interface for that. I have switched to MIPI-DBI in current version.
drivers/display/ssd1322.c
Outdated
return 0; | ||
} | ||
|
||
static int ssd1322_read(const struct device *dev, const uint16_t x, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These stub functions can be dropped, see 0096a98
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
drivers/display/ssd1322.c
Outdated
if (gpio_pin_set_dt(&config->reset, 1) < 0) { | ||
return -1; | ||
} | ||
k_sleep(K_MSEC(10)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No reason, that values was copied from some sample driver I have found. Now they are reduced to values from the datasheet.
drivers/display/ssd1322.c
Outdated
{ | ||
const struct ssd1322_config *config = dev->config; | ||
|
||
if (gpio_pin_set_dt(&config->reset, 1) < 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please don't return an arbitrary value here. Propigate the return value from the GPIO API, like so:
ret = gpio_pin_set_dt;
if (ret < 0) {
return ret;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Changed also in few other places.
drivers/display/ssd1322.c
Outdated
uint8_t cmd, data[2]; | ||
|
||
cmd = SSD1322_DISPLAY_OFF; | ||
ret |= ssd1322_write_bus(dev, &cmd, sizeof(cmd), true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I get the idea here, but I think we should be checking ret
after each call, and returning if there is an error. This implementation will be more challenging to debug, since you won't know where something failed without stepping through with a debugger and watching the value of ret
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
1153b68
to
d51f2ec
Compare
const struct ssd1322_config *config = dev->config; | ||
struct display_buffer_descriptor mipi_desc; | ||
|
||
mipi_desc.buf_size = len; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should propagate the height
and width
for the display buffer descriptor here as well- some controllers depend on these values being set to determine how much data to send.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because of the 1 bit -> 4bit conversion and sending data in chunks I cannot propagate width and height that I am receiving from upper layer. I hope that current solution will be acceptable :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be ok. Any MIPI controller that relies on the height and width will likely not work with this solution, but truthfully given that we are also lying to the controller about the true format of the pixel data (IE that each pixel is a nibble, not a bit), controllers of this style probably won't work either way.
d51f2ec
to
255cd7d
Compare
size_t buf_len; | ||
int ret; | ||
|
||
if (desc->pitch < desc->width) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should add a check to verify the buf_size
field in the display_buffer_descriptor
is sufficient for the provided height and width- this will provide more robust defense against reading out of bounds in the buffer the application provides
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please look few lines below:
buf_len = MIN(desc->buf_size, desc->height * desc->width / 8);
I think that this should protect us from out of bounds access to the buffer, what do you think? Reading is limited either to buf_size
, or to height and width.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that will be fine- sorry for missing that check.
properties: | ||
column_offset: | ||
type: int | ||
description: First visible column number, default 0. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If there is a default value, should we add default
key here so that the user does not have to specify column_offset = <0>
?
Also:
- Please add a justification for the default. Can be as simple as "reset setting for the controller" if this is the case
- property names should be styled like "column-offset"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have rethought that and providing a default value here maybe is not the best option. I guess that this value is different for each display model, so there is not a default one. I have change this property to be required.
3ec74db
to
d745d02
Compare
Initial support for SSD1322 OLED display driver. Only 1 bit color mode is supported. Signed-off-by: Lukasz Hawrylko <lukasz@hawrylko.pl>
size_t buf_len; | ||
int ret; | ||
|
||
if (desc->pitch < desc->width) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that will be fine- sorry for missing that check.
This pull request has been marked as stale because it has been open (more than) 60 days with no activity. Remove the stale label or add a comment saying that you would like to have the label removed otherwise this pull request will automatically be closed in 14 days. Note, that you can always re-open a closed pull request at any time. |
@jfischer-no could you provide feedback on this PR to move it forwards? |
ping @jfischer-no |
#define SSD1322_SET_COLUMN_ADDR 0x15 | ||
#define SSD1322_ENABLE_RAM_WRITE 0x5C | ||
#define SSD1322_SET_ROW_ADDR 0x75 | ||
#define SSD1322_SET_REMAP 0xA0 | ||
#define SSD1322_BLANKING_ON 0xA4 | ||
#define SSD1322_BLANKING_OFF 0xA6 | ||
#define SSD1322_EXIT_PARTIAL 0xA9 | ||
#define SSD1322_DISPLAY_OFF 0xAE | ||
#define SSD1322_DISPLAY_ON 0xAF | ||
#define SSD1322_SET_PHASE_LENGTH 0xB1 | ||
#define SSD1322_SET_CLOCK_DIV 0xB3 | ||
#define SSD1322_SET_GPIO 0xB5 | ||
#define SSD1322_SET_SECOND_PRECHARGE 0xB6 | ||
#define SSD1322_DEFAULT_GREYSCALE 0xB9 | ||
#define SSD1322_SET_PRECHARGE 0xBB | ||
#define SSD1322_SET_VCOMH 0xBE | ||
#define SSD1322_SET_CONTRAST 0xC1 | ||
#define SSD1322_SET_MUX_RATIO 0xCA | ||
#define SSD1322_COMMAND_LOCK 0xFD |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
19 lines could be moved to ssd1322.c
|
||
if (desc->pitch < desc->width) { | ||
LOG_ERR("Pitch is smaller than width"); | ||
return -1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return -EINVAL;
}
?
LOG_DBG("x %u, y %u, pitch %u, width %u, height %u, buf_len %u", x, y, desc->pitch, | ||
desc->width, desc->height, buf_len); | ||
|
||
uint8_t cmd_data[2]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Variable definition should be at the top of a block.
uint8_t cmd_data[2]; | ||
|
||
cmd_data[0] = config->column_offset + (x >> 2); | ||
cmd_data[1] = config->column_offset + (((x + desc->width) >> 2) - 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cmd_data[1] = config->column_offset + ((x + desc->width) >> 2) - 1;
} | ||
|
||
cmd_data[0] = y; | ||
cmd_data[1] = (y + desc->height - 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Acute overparenthesesis.
cmd_data[1] = y + desc->height - 1;
return ret; | ||
} | ||
|
||
uint8_t *buff_ptr = (uint8_t *)buf; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
buf is a buffer pointer, maybe data_ptr is better. You do not need explicit conversion here. Variable definition should be at the top of a block.
} | ||
ret = ssd1322_write_data(dev, pixel_buff, sizeof(pixel_buff)); | ||
if (ret < 0) { | ||
return ret; | ||
} | ||
buff_ptr++; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
}
ret = ssd1322_write_data(dev, pixel_buff, sizeof(pixel_buff));
if (ret < 0) {
return ret;
}
buff_ptr++;
} | ||
|
||
int ret = ssd1322_init_device(dev); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can remove this empty line.
This pull request has been marked as stale because it has been open (more than) 60 days with no activity. Remove the stale label or add a comment saying that you would like to have the label removed otherwise this pull request will automatically be closed in 14 days. Note, that you can always re-open a closed pull request at any time. |
Initial support for SSD1322 OLED display driver. Only 1 bit color mode is supported. It it inspired by existing driver for SSD1306. Tested on 3.2 inch 256x64 module (https://www.buydisplay.com/white-3-2-inch-arduino-raspberry-pi-oled-display-module-256x64-spi)