From c4f6098a812b39aa2fbf9028ffc2db5bec949fae Mon Sep 17 00:00:00 2001 From: Nathael Pajani Date: Sun, 16 Oct 2016 17:37:52 +0200 Subject: [PATCH] First part of SSD130x Oled controller support - Init - Set pixels and tiles (8x8) in RAM - Update whole or partial(untested) GDDRAM --- extdrv/ssd130x_oled_driver.c | 410 +++++++++++++++++++++++++++ include/extdrv/ssd130x_oled_driver.h | 338 ++++++++++++++++++++++ 2 files changed, 748 insertions(+) create mode 100644 extdrv/ssd130x_oled_driver.c create mode 100644 include/extdrv/ssd130x_oled_driver.h diff --git a/extdrv/ssd130x_oled_driver.c b/extdrv/ssd130x_oled_driver.c new file mode 100644 index 0000000..f8b2d20 --- /dev/null +++ b/extdrv/ssd130x_oled_driver.c @@ -0,0 +1,410 @@ +/**************************************************************************** + * extdrv/ssd130x_oled_driver.c + * + * I2C Driver for 128x64 oled display drivers + * + * Copyright 2016 Nathael Pajani + * + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + *************************************************************************** */ + + + +#include "core/system.h" +#include "core/systick.h" +#include "core/pio.h" +#include "lib/stdint.h" +#include "lib/errno.h" +#include "lib/string.h" +#include "drivers/gpio.h" +#include "drivers/i2c.h" + +#include "extdrv/ssd130x_oled_driver.h" + + +/***************************************************************************** */ + +/* SSD1306 starts with control reg set to 0x7F and in normal display mode, + * which is equivalent to 0xA4 command. + * (Refer to chapter 8.5 of SSD1306 manual) + * + * The power on sequence is described in chapter 8.9 of SSD1306 manual. + * After VDD power stable, Reset signal should be pulled low for at least 3us + * and then VCC turned on. + * Once VCC stable, send 0xAF command to turn display ON and wait for 100ms. + * + * The power off sequence starts by sending 0xAE command, then turn off VCC, + * wait for 100ms, and turn off VDD. + * + * The Graphic Display Data RAM (GDDRAM) is 128 x 64 bits divided in 8 pages + * of 128 bytes each. One page represents 8 lines of 128 dots. + * When writing one byte to one page, the byte fills one collumn (8 vertical + * pixels), and the next byte fills the next collumn, and so on. + * (Refer to chapter 8.7 of SSD1306 manual) + * + * No data read is available in serial (SPI and I2C ?) mode. + * The serial interface mode is always in write mode. + * + * The GDDRAM column address pointer will be increased automatically by one + * after each data write. + */ + + + /* + * Note : This driver does not implemment and support page adressing. All page + * addressing commands are not supported. + * This affects the following commands : + * - All commands 0x00 to 0x1F are not supported (set column start for page + * addressing mode). + * - ssd130x_set_mem_addressing_mode() (0x20) supports only + * SSD130x_ADDR_TYPE_HORIZONTAL and SSD130x_ADDR_TYPE_VERTICAL + * - Set page start address (0xB0 to 0xB7) + * + * Note some other commands are not supported: + * - Set display start line (0x40 to 0x7F) + * - Set segment remap (0xA0 and 0xA1) + * - Set multiplex ratio (0xA8) + * - Set display clock divide ration and oscilator frequency (0xD5) + * - Set pre-charge period (0xD9) + * - Set COM pins hardware configuration (0xDA) + * - Set Vcomh deselect level (0xDB) + * - No OP (0xE3) + */ + +/***************************************************************************** */ +/* Commands */ +#define CMD_BUF_SIZE 24 +int ssd130x_send_command(struct oled_display* conf, uint8_t cmd, uint8_t* data, uint8_t len) +{ + char cmd_buf[CMD_BUF_SIZE] = { conf->address, SSD130x_NEXT_BYTE_CMD, cmd, }; + int ret = 0; + + if (len > (CMD_BUF_SIZE - 3)) { + return -EINVAL; + } + + if (len != 0) { + int i = 0; + for (i = 0; i < len; i++) { + cmd_buf[ 3 + (2 * i) ] = SSD130x_NEXT_BYTE_CMD; + cmd_buf[ 4 + (2 * i) ] = data[i]; + } + } + ret = i2c_write(conf->bus_num, cmd_buf, (3 + (len * 2)), NULL); + if (ret != (3 + (len * 2))) { + conf->probe_ok = 0; + return ret; + } + return 0; +} + + +/* Set memory adressing mode (0x20) + * There are 3 different memory addressing mode in SSD130x: page addressing + * mode, horizontal addressing mode and vertical addressing mode. + * This command sets the way of memory addressing into one of the above three + * modes. + * (Refer to chapter 10.1.3 of SSD1306 manual) + * + * Note : This driver does not implemment and support page adressing. All page + * addressing commands are not supported. + */ +int ssd130x_set_mem_addressing_mode(struct oled_display* conf, uint8_t type) +{ + return ssd130x_send_command(conf, SSD130x_CMD_ADDR_TYPE, &type, 1); +} + +/* Set column address (0x21) + * This triple byte command specifies column start address and end address of + * the display data RAM. + * This command also sets the column address pointer to column start address. + * This pointer is used to define the current read/write column address in + * graphic display data RAM. + * If horizontal address increment mode is enabled by command 20h, after + * finishing read/write one column data, it is incremented automatically to + * the next column address. + * Whenever the column address pointer finishes accessing the end column + * address, it is reset back to start column address and the row address is + * incremented to the next row. + */ +int ssd130x_set_column_address(struct oled_display* conf, uint8_t col_start, uint8_t col_end) +{ + uint8_t buf[2] = { col_start, col_end }; + return ssd130x_send_command(conf, SSD130x_CMD_COL_ADDR, buf, 2); +} + +/* Set page address (0x22) + * This triple byte command specifies page start address and end address of the + * display data RAM. + * This command also sets the page address pointer to page start address. + * This pointer is used to define the current read/write page address in + * graphic display data RAM. + * If vertical address increment mode is enabled by command 20h, after + * finishing read/write one page data, it is incremented automatically to the + * next page address. + * Whenever the page address pointer finishes accessing the end page address, + * it is reset back to start page address. + */ +int ssd130x_set_page_address(struct oled_display* conf, uint8_t page_start, uint8_t page_end) +{ + uint8_t buf[2] = { page_start, page_end, }; + return ssd130x_send_command(conf, SSD130x_CMD_PAGE_ADDR, buf, 2); +} + +/* Set contrast (0x81) + * The contrast value is between 0 and 256 + */ +int ssd130x_set_contrast(struct oled_display* conf) +{ + return ssd130x_send_command(conf, SSD130x_CMD_CONTRAST, &(conf->contrast), 1); +} + +/* Set display ON from GDDRAM (0xA4) or regardless of GDDRAM (0xA5) + * use_ram is either SSD130x_DISP_RAM or SSD130x_DISP_BLANK + */ +int ssd130x_set_display_on(struct oled_display* conf, uint8_t use_ram) +{ + if (use_ram == SSD130x_DISP_BLANK) { + return ssd130x_send_command(conf, SSD130x_CMD_DISP_NORAM, NULL, 0); + } else { + return ssd130x_send_command(conf, SSD130x_CMD_DISP_RAM, NULL, 0); + } +} + +/* Set display to normal or reverse video + * status is either SSD130x_DISP_NORMAL or SSD130x_DISP_REVERSE + */ +int ssd130x_display_video_reverse(struct oled_display* conf) +{ + if (conf->video_mode == SSD130x_DISP_REVERSE) { + return ssd130x_send_command(conf, SSD130x_CMD_DISP_REVERSE, NULL, 0); + } else { + return ssd130x_send_command(conf, SSD130x_CMD_DISP_NORMAL, NULL, 0); + } +} + +/* Set display ON/OFF + * status is either SSD130x_DISP_ON or SSD130x_DISP_OFF + */ +int ssd130x_display_power(struct oled_display* conf, uint8_t status) +{ + if (status == SSD130x_DISP_OFF) { + return ssd130x_send_command(conf, SSD130x_CMD_DISP_OFF, NULL, 0); + } else { + return ssd130x_send_command(conf, SSD130x_CMD_DISP_ON, NULL, 0); + } +} + +/* Set scan direction (0xC0 / 0xC8) + * Scan direction is either SSD130x_SCAN_TOP_BOTTOM or SSD130x_SCAN_BOTTOM_TOP + */ +int ssd130x_set_scan_direction(struct oled_display* conf) +{ + if (conf->scan_dir == SSD130x_SCAN_TOP_BOTTOM) { + return ssd130x_send_command(conf, SSD130x_CMD_COM_SCAN_NORMAL, NULL, 0); + } else { + return ssd130x_send_command(conf, SSD130x_CMD_COM_SCAN_REVERSE, NULL, 0); + } +} +/* Set read direction (0xA0 / 0xA1) + * Scan direction is either SSD130x_CMD_SEG0_MAP_RIGHT or SSD130x_CMD_SEG0_MAP_LEFT + */ +int ssd130x_set_read_direction(struct oled_display* conf) +{ + if (conf->read_dir == SSD130x_RIGHT_TO_LEFT) { + return ssd130x_send_command(conf, SSD130x_CMD_SEG0_MAP_RIGHT, NULL, 0); + } else { + return ssd130x_send_command(conf, SSD130x_CMD_SEG0_MAP_LEFT, NULL, 0); + } +} + +/* Set display offset + * Move the display up or down by a given number of lines + * FIXME : Check influence of COM output scan direction. + */ +int ssd130x_set_display_offset(struct oled_display* conf, uint8_t dir, uint8_t nb_lines) +{ + uint8_t offset = 0; + if (nb_lines >= SSD130x_NB_LINES) { + return -EINVAL; + } + if (dir == SSD130x_MOVE_TOP) { + offset = SSD130x_OFFSET_DATA(nb_lines); + } else { + offset = SSD130x_OFFSET_DATA(64 - nb_lines); + } + return ssd130x_send_command(conf, SSD130x_CMD_DISPLAY_OFFSET, &offset, 1); +} + + + +/***************************************************************************** */ +/* Init */ +int ssd130x_display_off(struct oled_display* conf) +{ + return ssd130x_display_power(conf, SSD130x_DISP_OFF); +} + +int ssd130x_display_on(struct oled_display* conf) +{ + int ret = 0; + + /* Display OFF */ + ret = ssd130x_display_power(conf, SSD130x_DISP_OFF); + if (ret != 0) { + return ret; + } + ret = ssd130x_set_mem_addressing_mode(conf, SSD130x_ADDR_TYPE_HORIZONTAL); + if (ret != 0) { + return ret; + } + ret = ssd130x_set_scan_direction(conf); + if (ret != 0) { + return ret; + } + ret = ssd130x_set_read_direction(conf); + if (ret != 0) { + return ret; + } + ret = ssd130x_set_display_on(conf, SSD130x_DISP_RAM); + if (ret != 0) { + return ret; + } + + return ssd130x_display_power(conf, SSD130x_DISP_ON); +} + + + +/***************************************************************************** */ +/* Data */ + +/* Our internal buffer for the whole display. + * Graphical data starts at byte 4. The first four bytes are here for temporary + * storage of display data during I2C frame transfer. + */ +#define GDDRAM_SIZE (128 * 8) +static uint8_t gddram[ 4 + GDDRAM_SIZE ]; +static uint8_t* gddram_start = (gddram + 4); + + +int ssd130x_send_data(struct oled_display* conf, uint8_t* start, uint16_t len) +{ + int ret = 0; + + /* Check that start and satrt + len are within buffer */ + + /* Copy previous two bytes to storage area (gddram[0] and gddram[1]) */ + gddram[0] = *(start - 2); + gddram[1] = *(start - 1); + + /* Setup I2C transfer */ + *(start - 2) = conf->address; + *(start - 1) = SSD130x_DATA_ONLY; + + /* Send data on I2C bus */ + ret = i2c_write(conf->bus_num, (start - 2), (2 + len), NULL); + + /* Restore gddram data */ + *(start - 2) = gddram[0]; + *(start - 1) = gddram[1]; + + if (ret != (2 + len)) { + return ret; + } + return len; +} + +/* Set whole display to given value */ +int ssd130x_display_set(struct oled_display* conf, uint8_t val) +{ + memset(gddram_start, val, GDDRAM_SIZE); + return 0; +} + + +/* Update what is really displayed */ +int ssd130x_display_full_screen(struct oled_display* conf) +{ + int ret = 0; + + ret = ssd130x_set_column_address(conf, 0, 127); + if (ret != 0) { + return ret; + } + ret = ssd130x_set_page_address(conf, 0, 7); + if (ret != 0) { + return ret; + } + ret = ssd130x_send_data(conf, gddram_start, GDDRAM_SIZE); + if (ret != GDDRAM_SIZE) { + return ret; + } + return 0; +} + +/* Change a "tile" in the GDDRAM memory. + * A tile is a 8x8 pixels region, aligned on a 8x8 grid representation of the display. + * x0 and y0 are in number of tiles. + */ +int ssd130x_update_tile(struct oled_display* conf, uint8_t x0, uint8_t y0) +{ + uint8_t* addr = gddram_start + ((y0 >> 3) * 128) + x0; + int ret = 0; + + ret = ssd130x_set_column_address(conf, (x0 * 8), (((x0 + 1) * 8) - 1)); + if (ret != 0) { + return ret; + } + ret = ssd130x_set_page_address(conf, y0, y0); + if (ret != 0) { + return ret; + } + ret = ssd130x_send_data(conf, addr, 8); + if (ret != 0) { + return ret; + } + return 0; +} + +int ssd130x_update_modified(struct oled_display* conf) +{ + return 0; +} + +/* Change our internal buffer, without actually displaying the changes */ +int ssd130x_set_pixel(struct oled_display* conf, uint8_t x0, uint8_t y0, uint8_t state) +{ + uint8_t* addr = gddram_start + ((y0 >> 3) * 128) + x0; + if (state != 0) { + *addr |= (0x01 << (7 - (x0 & 0x03))); + } else { + *addr &= ~(0x01 << (7 - (x0 & 0x03))); + } + return 0; +} + +/* Change a "tile" in the bitmap memory. + * A tile is a 8x8 pixels region, aligned on a 8x8 grid representation of the display. + * x0 and y0 are in number of tiles. + */ +int ssd130x_set_tile(struct oled_display* conf, uint8_t x0, uint8_t y0, uint8_t* tile) +{ + uint8_t* addr = gddram_start + (y0 * 128) + (x0 * 8); + memcpy(addr, tile, 8); + return 0; +} + diff --git a/include/extdrv/ssd130x_oled_driver.h b/include/extdrv/ssd130x_oled_driver.h new file mode 100644 index 0000000..19f055d --- /dev/null +++ b/include/extdrv/ssd130x_oled_driver.h @@ -0,0 +1,338 @@ +/**************************************************************************** + * extdrv/ssd130x_oled_driver.h + * + * I2C Driver for 128x64 oled display drivers + * + * Copyright 2016 Nathael Pajani + * + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + *************************************************************************** */ + +#ifndef EXTDRV_SSD130X_OLED_DRIVER_H +#define EXTDRV_SSD130X_OLED_DRIVER_H + +#include "lib/stdint.h" + + +/***************************************************************************** */ +/* Oled Display */ +struct oled_display { + uint8_t address; /* 8 bits address */ + uint8_t bus_num; /* I2C bus number */ + uint8_t probe_ok; + uint8_t video_mode; + uint8_t contrast; + uint8_t scan_dir; + uint8_t read_dir; + uint8_t display_offset_dir; + uint8_t display_offset; +}; + +#define SSD130x_NB_LINES 64 +#define SSD130x_NB_PAGES 8 +#define SSD130x_NB_COL 128 + +enum ssd130x_defs { + SSD130x_DISP_OFF = 0, + SSD130x_DISP_ON, + SSD130x_DISP_RAM, + SSD130x_DISP_BLANK, + /* For reverse video */ + SSD130x_DISP_NORMAL, + SSD130x_DISP_REVERSE, + /* For scan dirrection */ + SSD130x_SCAN_TOP_BOTTOM, + SSD130x_SCAN_BOTTOM_TOP, + SSD130x_RIGHT_TO_LEFT, + SSD130x_LEFT_TO_RIGHT, + /* For display offset */ + SSD130x_MOVE_TOP, + SSD130x_MOVE_BOTTOM, +}; + + +#define SSD130x_DATA_ONLY 0x40 +#define SSD130x_NEXT_BYTE_DATA 0xC0 +#define SSD130x_NEXT_BYTE_CMD 0x80 + +/* Display controll */ +#define SSD130x_CMD_CONTRAST 0x81 +#define SSD130x_CMD_DISP_RAM 0xA4 +#define SSD130x_CMD_DISP_NORAM 0xA5 +#define SSD130x_CMD_DISP_NORMAL 0xA6 +#define SSD130x_CMD_DISP_REVERSE 0xA7 +#define SSD130x_CMD_DISP_OFF 0xAE +#define SSD130x_CMD_DISP_ON 0xAF + +/* Scrolling controll */ +#define SSD130x_CMD_SCROLL_RIGHT 0x26 +#define SSD130x_CMD_SCROLL_LEFT 0x27 +#define SSD130x_CMD_VSCROLL_RIGHT 0x29 +#define SSD130x_CMD_VSCROLL_LEFT 0x2A +#define SSD130x_CMD_STOP_SCROLL 0x2E +#define SSD130x_CMD_START_SCROLL 0x2F +#define SSD130x_CMD_VSCROLL_REGION 0xA3 +/* Data bytes for scrolling controll */ +#define SSD130x_SCROLL_DATA_DUMMY 0x00 +#define SSD130x_SCROLL_DATA_END 0xFF +#define SSD130x_SCROLL_DATA_START_PAGE(x) ((x) & 0x07) +#define SSD130x_SCROLL_DATA_END_PAGE(x) ((x) & 0x07) +#define SSD130x_SCROLL_DATA_ROWS(x) ((x) & 0x3F) +#define SSD130x_SCROLL_DATA_STEP(x) ((x) & 0x07) +/* Scroll steps definitions */ +#define SSD130x_SCROLL_2_FRAMES 0x07 +#define SSD130x_SCROLL_3_FRAMES 0x04 +#define SSD130x_SCROLL_4_FRAMES 0x05 +#define SSD130x_SCROLL_5_FRAMES 0x00 +#define SSD130x_SCROLL_25_FRAMES 0x06 +#define SSD130x_SCROLL_64_FRAMES 0x01 +#define SSD130x_SCROLL_128_FRAMES 0x02 +#define SSD130x_SCROLL_256_FRAMES 0x03 + +/* GDDRAM Adressing */ +#define SSD130x_CMD_ADDR_TYPE 0x20 +/* Data bytes for adressing mode election */ +#define SSD130x_ADDR_TYPE_HORIZONTAL 0x00 +#define SSD130x_ADDR_TYPE_VERTICAL 0x01 +#define SSD130x_ADDR_TYPE_PAGE 0x02 + +/* GDDRAM Page adressing mode */ +#define SSD130x_CMD_COL_LOW_NIBLE(x) (0x00 + ((x) & 0x0F)) +#define SSD130x_CMD_COL_HIGH_NIBLE(x) (0x10 + ((x) & 0x0F)) +#define SSD130x_CMD_PAGE_START_ADDR(x) (0xB0 + ((x) & 0x07)) + +/* GDDRAM horizontal or vertical addressing mode */ +#define SSD130x_CMD_COL_ADDR 0x21 +#define SSD130x_CMD_PAGE_ADDR 0x22 +/* Data bytes for horizontal or vertical adressing mode */ +#define SSD130x_ADDR_COL(x) ((x) & 0x7F) +#define SSD130x_ADDR_PAGE(x) ((x) & 0x07) + +/* Hardware configuration */ +#define SSD130x_CMD_START_LINE(x) (0x40 + ((x) & 0x3F)) +#define SSD130x_CMD_SEG0_MAP_RIGHT 0xA1 +#define SSD130x_CMD_SEG0_MAP_LEFT 0xA0 + +/* Hardware configuration : Mux ratio */ +#define SSD130x_CMD_SET_MUX 0xA8 +/* Set mux ratio Data to N+1 (Values for N from 0 to 14 are invalid) */ +#define SSD130x_MUX_DATA(x) ((x) & 0x3F) /* Reset is N=63 (64 mux) */ + +/* Hardware configuration : COM Scan */ +#define SSD130x_CMD_COM_SCAN_NORMAL 0xC0 /* Reset mode : top to bottom */ +#define SSD130x_CMD_COM_SCAN_REVERSE 0xC8 /* Bottom to top */ +#define SSD130x_CMD_DISPLAY_OFFSET 0xD3 +/* Data for display offset (COM shift) */ +#define SSD130x_OFFSET_DATA(x) ((x) & 0x3F) +#define SSD130x_CMD_COM_PIN_CONF 0xDA +/* Data for COM pins hardware configuration */ +#define SSD130x_COM_SEQUENTIAL (0x00 << 4) +#define SSD130x_COM_ALTERNATIVE (0x01 << 4) /* Reset mode */ +#define SSD130x_COM_NO_REMAP (0x00 << 5) /* Reset mode */ +#define SSD130x_COM_REMAP (0x01 << 5) + +/* Timing and driving scheme : Clock */ +#define SSD130x_CMD_DISP_CLK_DIV 0xD5 +#define SSD130x_CLK_DIV(x) ((x) & 0x0F) /* Set to N+1 (Default is 0+1) */ +#define SSD130x_CLK_FREQ(x) (((x) & 0x0F) << 4) /* Reset is 0x80 */ + +/* Timing and driving scheme : Precharge */ +#define SSD130x_CMD_SET_PRECHARGE 0xD9 +#define SSD130x_PRECHARGE_PHASE1(x) ((x) & 0x0F) /* Default to 2, 0 is invalid */ +#define SSD130x_PRECHARGE_PHASE2(x) (((x) & 0x0F) << 4) /* Default to 2, 0 is invalid */ + +/* Timing and driving scheme : Voltage */ +#define SSD130x_CMD_VCOM_LEVEL 0xDB +#define SSD130x_VCOM_065 0x00 +#define SSD130x_VCOM_077 0x20 +#define SSD130x_VCOM_083 0x30 + +/* NO-OP */ +#define SSD130x_CMD_NOP 0xE3 + +/* Status register read */ +#define SSD130x_STATUS_ON (0x01 << 6) + + +/* SSD1306 starts with control reg set to 0x7F and in normal display mode, + * which is equivalent to 0xA4 command. + * (Refer to chapter 8.5 of SSD1306 manual) + * + * The power on sequence is described in chapter 8.9 of SSD1306 manual. + * After VDD power stable, Reset signal should be pulled low for at least 3us + * and then VCC turned on. + * Once VCC stable, send 0xAF command to turn display ON and wait for 100ms. + * + * The power off sequence starts by sending 0xAE command, then turn off VCC, + * wait for 100ms, and turn off VDD. + * + * The Graphic Display Data RAM (GDDRAM) is 128 x 64 bits divided in 8 pages + * of 128 bytes each. One page represents 8 lines of 128 dots. + * When writing one byte to one page, the byte fills one collumn (8 vertical + * pixels), and the next byte fills the next collumn, and so on. + * (Refer to chapter 8.7 of SSD1306 manual) + * + * No data read is available in serial (SPI and I2C ?) mode. + * The serial interface mode is always in write mode. + * + * The GDDRAM column address pointer will be increased automatically by one + * after each data write. + */ + + + /* + * Note : This driver does not implemment and support page adressing. All page + * addressing commands are not supported. + * This affects the following commands : + * - All commands 0x00 to 0x1F are not supported (set column start for page + * addressing mode). + * - ssd130x_set_mem_addressing_mode() (0x20) supports only + * SSD130x_ADDR_TYPE_HORIZONTAL and SSD130x_ADDR_TYPE_VERTICAL + * - Set page start address (0xB0 to 0xB7) + * + * Note some other commands are not supported: + * - Set display start line (0x40 to 0x7F) + * - Set segment remap (0xA0 and 0xA1) + * - Set multiplex ratio (0xA8) + * - Set display clock divide ration and oscilator frequency (0xD5) + * - Set pre-charge period (0xD9) + * - Set COM pins hardware configuration (0xDA) + * - Set Vcomh deselect level (0xDB) + * - No OP (0xE3) + */ + +/***************************************************************************** */ +/* Commands */ +int ssd130x_send_command(struct oled_display* conf, uint8_t cmd, uint8_t* data, uint8_t len); + + +/* Set memory adressing mode (0x20) + * There are 3 different memory addressing mode in SSD130x: page addressing + * mode, horizontal addressing mode and vertical addressing mode + * - SSD130x_ADDR_TYPE_HORIZONTAL + * - SSD130x_ADDR_TYPE_VERTICAL + * - SSD130x_ADDR_TYPE_PAGE + * This command sets the way of memory addressing into one of the above three + * modes. + * (Refer to chapter 10.1.3 of SSD1306 manual) + * + * Note : This driver does not implemment and support page adressing. All page + * addressing commands are not supported. + */ +int ssd130x_set_mem_addressing_mode(struct oled_display* conf, uint8_t type); + +/* Set column address (0x21) + * This triple byte command specifies column start address and end address of + * the display data RAM. + * This command also sets the column address pointer to column start address. + * This pointer is used to define the current read/write column address in + * graphic display data RAM. + * If horizontal address increment mode is enabled by command 20h, after + * finishing read/write one column data, it is incremented automatically to + * the next column address. + * Whenever the column address pointer finishes accessing the end column + * address, it is reset back to start column address and the row address is + * incremented to the next row. + */ +int ssd130x_set_column_address(struct oled_display* conf, uint8_t col_start, uint8_t col_end); + +/* Set page address (0x22) + * This triple byte command specifies page start address and end address of the + * display data RAM. + * This command also sets the page address pointer to page start address. + * This pointer is used to define the current read/write page address in + * graphic display data RAM. + * If vertical address increment mode is enabled by command 20h, after + * finishing read/write one page data, it is incremented automatically to the + * next page address. + * Whenever the page address pointer finishes accessing the end page address, + * it is reset back to start page address. + */ +int ssd130x_set_page_address(struct oled_display* conf, uint8_t page_start, uint8_t page_end); + +/* Set contrast (0x81) + * The contrast value is between 0 and 256 + */ +int ssd130x_set_contrast(struct oled_display* conf); + +/* Set display ON from GDDRAM (0xA4) or regardless of GDDRAM (0xA5) + * use_ram is either SSD130x_DISP_RAM or SSD130x_DISP_BLANK + */ +int ssd130x_set_display_on(struct oled_display* conf, uint8_t use_ram); + +/* Set display to normal or reverse video + * status is either SSD130x_DISP_NORMAL or SSD130x_DISP_REVERSE + */ +int ssd130x_display_video_reverse(struct oled_display* conf); + +/* Set display ON/OFF + * status is either SSD130x_DISP_ON or SSD130x_DISP_OFF + */ +int ssd130x_display_power(struct oled_display* conf, uint8_t status); + +/* Set scan direction (0xC0 / 0xC8) + * Scan direction is either SSD130x_SCAN_TOP_BOTTOM or SSD130x_SCAN_BOTTOM_TOP + */ +int ssd130x_set_scan_direction(struct oled_display* conf); + +/* Set read direction (0xA0 / 0xA1) + * Scan direction is either SSD130x_CMD_SEG0_MAP_RIGHT or SSD130x_CMD_SEG0_MAP_LEFT + */ +int ssd130x_set_read_direction(struct oled_display* conf); + +/* Set display offset + * Move the display up or down by a given number of lines + * FIXME : Check influence of COM output scan direction. + */ +int ssd130x_set_display_offset(struct oled_display* conf, uint8_t dir, uint8_t nb_lines); + + + +/***************************************************************************** */ +/* Init */ +int ssd130x_display_on(struct oled_display* conf); +int ssd130x_display_off(struct oled_display* conf); + +int ssd130x_display_init(struct oled_display* conf); + + + +/***************************************************************************** */ +/* Data */ + +/* Our internal buffer for the whole display. + * Graphical data starts at byte 4. The first four bytes are here for temporary + * storage of display data during I2C frame transfer. + */ +int ssd130x_send_data(struct oled_display* conf, uint8_t* start, uint16_t len); + +/* Set whole display to given value */ +int ssd130x_display_set(struct oled_display* conf, uint8_t val); + + +/* Update what is really displayed */ +int ssd130x_display_full_screen(struct oled_display* conf); +int ssd130x_update_tile(struct oled_display* conf, uint8_t x0, uint8_t y0); +int ssd130x_update_region(struct oled_display* conf, + uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1); +int ssd130x_update_modified(struct oled_display* conf); + +/* Change our internal buffer, without actually displaying the changes */ +int ssd130x_set_pixel(struct oled_display* conf, uint8_t x0, uint8_t y0, uint8_t state); +int ssd130x_set_tile(struct oled_display* conf, uint8_t x0, uint8_t y0, uint8_t* tile); + + +#endif /* EXTDRV_SSD130X_OLED_DRIVER_H */ -- 2.43.0