I am writing my own custom library for the SH1106 132×64 display. From this datasheet I would gather, leaving all the various configurations as default, that page 0
would be at the top of the display.
It however never specifies that in writing. There is only a table on page 16 (Figure. 8) that would suggests that.
I tried multiple displays and they all had page 0
at the bottom. I also tried various combinations of all the different addressing modes but none solved the issue.
I then tried to display something using the Adafruit SSD1306 library and that put page 0 at the top.
What the heck is wrong here?
HEADER FILE
#define SH1106_WIDTH 132
#define SH1106_HEIGHT 64
#define SH1106_COMMAND 0x00
#define SH1106_DATA 0x40
#define DISPLAY_OFF 0xAE
#define DISPLAY_ON_NORMAL_MODE 0xAF
#define DISPLAY_ON_RAM_CONTENT 0xA4
#define DISPLAY_ON_RAM_IGNORE 0xA5
#define SET_DISPLAY_NORMAL 0xA6
#define SET_DISPLAY_INVERSE 0xA7
#define SET_CONTRAST_CONTROL 0x81
#define SET_MEMORY_ADDRESSING_MODE 0x20
#define SET_DISPLAY_START_LINE 0x40 // Allowed Values: 0x40 to 0x7F, Reset Value: 0x40 / x100 0000
#define SET_PAGE_ADDRESS_FOR_PAGE_ADDRESSING_MODE 0xB0
#define SET_COM_OUTPUT_SCAN_DIRECTION_NORMAL_MODE 0xC0
#define SET_COM_OUTPUT_SCAN_DIRECTION_REMAPPED_MODE 0xC8
#define SET_SEGMENT_REMAP_SEG0_0 0xA0
#define SET_SEGMENT_REMAP_SEG0_131 0xA1
#define SET_MULTIPLEX_RATIO 0xA8
#define SET_DISPLAY_OFFSET 0xD3
#define SET_DISPLAY_CLOCK_DIVIDE_RATIO 0xD5
#define SET_PRECHARGE_PERIOD 0xD9
#define SET_COM_PINS_HARDWARE_CONFIGURATION 0xDA
#define SET_VCOMH_DESELECT_LEVEL 0xDB
#define CHARGE_PUMP_SETTING 0x8D
#define DEACTIVATE_SCROLL 0x2E
C FILE
uint8_t dynamicInitDataArray[] = {
SH1106_COMMAND, DISPLAY_OFF,
SH1106_COMMAND, SET_MULTIPLEX_RATIO, 0x3F, // Reset Value: 0x3F / xx11 1111
SH1106_COMMAND, SET_DISPLAY_OFFSET, 0x00, // No Offset
SH1106_COMMAND, SET_DISPLAY_START_LINE,
SH1106_COMMAND, SET_SEGMENT_REMAP_SEG0_131,
SH1106_COMMAND, SET_COM_OUTPUT_SCAN_DIRECTION_NORMAL_MODE,
SH1106_COMMAND, SET_COM_PINS_HARDWARE_CONFIGURATION, 0x12, // 0x02 or 0x12 (POR)
SH1106_COMMAND, SET_CONTRAST_CONTROL, 0x7F,
SH1106_COMMAND, SET_DISPLAY_CLOCK_DIVIDE_RATIO, 0xA0, // Suggested Ratio: 0x80
SH1106_COMMAND, CHARGE_PUMP_SETTING, 0x14, // Enable: 0x14, Disable: 0x10
SH1106_COMMAND, SET_MEMORY_ADDRESSING_MODE, 0x02, // Horizontal: 0x00, Vertical: 0x01, Page: 0x02
SH1106_COMMAND, SET_PRECHARGE_PERIOD, 0x22,
SH1106_COMMAND, SET_VCOMH_DESELECT_LEVEL, 0x20,
SH1106_COMMAND, SET_DISPLAY_NORMAL,
SH1106_COMMAND, DISPLAY_ON_RAM_CONTENT,
SH1106_COMMAND, DEACTIVATE_SCROLL
};
/**
* @brief This function initializes the display.
* @param *hi2c: i2c-handle pointer
* @param deviceAddress: i2c device address
*/
void SH1106_Init(I2C_HandleTypeDef *hi2c, uint8_t deviceAddress) {
size_t totalBytesToTransmit = sizeof(dynamicInitDataArray)
/ sizeof(dynamicInitDataArray[0]);
HAL_I2C_Master_Transmit(hi2c, deviceAddress, dynamicInitDataArray,
totalBytesToTransmit, 1000);
}
/**
* @brief This function sets the page.
* @param *hi2c: i2c-handle pointer
* @param deviceAddress: i2c device address
* @param page: page number from 0-7
*/
void SH1106_Set_Page_Address(I2C_HandleTypeDef *hi2c, uint8_t deviceAddress, uint8_t page) {
if(page > 7) {
return; // Check if page is in bounds.
}
uint8_t setPageAddress[2] = {SH1106_COMMAND, SET_PAGE_ADDRESS_FOR_PAGE_ADDRESSING_MODE + page};
HAL_I2C_Master_Transmit(hi2c, deviceAddress, setPageAddress, 2, 1000);
}