Shrink OLED driver code. (#296)

* Precompute command header.
* Update data header on-demand.
* Use more aggressive inlining.
* Do not clear number buffer twice.
This commit is contained in:
Alessandro Gatti
2018-05-11 04:32:37 +02:00
committed by Ben V. Brown
parent 215fe8e9e8
commit 8bf65351ea
2 changed files with 85 additions and 96 deletions

View File

@@ -13,7 +13,6 @@
/*http://www.displayfuture.com/Display/datasheet/controller/SSD1307.pdf*/
/*All commands are prefixed with 0x80*/
/*Data packets are prefixed with 0x40*/
const uint8_t configLength = 50;
uint8_t OLED_Setup_Array[] = { /**/
0x80, 0xAE,/*Display off*/
0x80, 0xD5,/*Set display clock divide ratio / osc freq*/
@@ -43,54 +42,42 @@ uint8_t OLED_Setup_Array[] = { /**/
};
//Setup based on the SSD1307 and modified for the SSD1306
const uint8_t REFRESH_COMMANDS[17] = {
0x80, 0xAF,
0x80, 0x21,
0x80, 0x20,
0x80, 0x7F,
0x80, 0xC0,
0x80, 0x22,
0x80, 0x00,
0x80, 0x01,
0x40
};
OLED::OLED(FRToSI2C* i2cHandle) {
i2c = i2cHandle;
cursor_x = cursor_y = 0;
currentFont = FONT_12;
fontWidth = 12;
inLeftHandedMode = false;
firstStripPtr = &screenBuffer[16 + 1];
secondStripPtr = &screenBuffer[16 + 1 + 96];
firstStripPtr = &screenBuffer[FRAMEBUFFER_START];
secondStripPtr = &screenBuffer[FRAMEBUFFER_START + OLED_WIDTH];
fontHeight = 16;
fontWidth = 12;
displayOffset = 0;
displayOnOffState = true;
}
void OLED::initialize() {
memcpy(&screenBuffer[0], &REFRESH_COMMANDS[0], sizeof(REFRESH_COMMANDS));
HAL_Delay(5);
HAL_GPIO_WritePin(OLED_RESET_GPIO_Port, OLED_RESET_Pin, GPIO_PIN_SET);
HAL_Delay(10);
//Send the setup settings
i2c->Transmit( DEVICEADDR_OLED, (uint8_t*) OLED_Setup_Array, configLength);
i2c->Transmit( DEVICEADDR_OLED, (uint8_t*) OLED_Setup_Array, sizeof(OLED_Setup_Array));
displayOnOff(true);
}
//Write out the buffer to the OLEd & call any rendering objects
void OLED::refresh() {
screenBuffer[0] = 0x80;
screenBuffer[1] = displayOnOffState ? 0xAF : 0xAE;
screenBuffer[2] = 0x80;
screenBuffer[3] = 0x21;
screenBuffer[4] = 0x80;
screenBuffer[5] = inLeftHandedMode ? 0 : 32; //display is shifted by 32 in left handed mode as driver ram is 128 wide
screenBuffer[6] = 0x80;
screenBuffer[7] = inLeftHandedMode ? 95 : 0x7F; //End address of the ram segment we are writing to (96 wide)
screenBuffer[8] = 0x80; /*Set COM Scan direction*/
screenBuffer[9] = inLeftHandedMode ? 0xC8 : 0xC0;
screenBuffer[10] = 0x80; //Set pages to rollover after 2
screenBuffer[11] = 0x22;
screenBuffer[12] = 0x80;
screenBuffer[13] = 0x00; //start page 0
screenBuffer[14] = 0x80;
screenBuffer[15] = 0x01;
screenBuffer[16] = 0x40; //start of data marker
i2c->Transmit( DEVICEADDR_OLED, screenBuffer, 16 + (96 * 2) + 1);
}
/*
* Prints a char to the screen.
* UTF font handling is done using the two input chars.
@@ -151,25 +138,26 @@ void OLED::drawChar(char c, char PrecursorCommand) {
cursor_x += fontWidth;
}
void OLED::displayOnOff(bool on) {
displayOnOffState = on;
}
void OLED::setRotation(bool leftHanded) {
if (inLeftHandedMode != leftHanded) {
//send command struct again with changes
if (leftHanded == 1) {
if (inLeftHandedMode == leftHanded) {
return;
}
//send command struct again with changes
if (leftHanded) {
OLED_Setup_Array[11] = 0xC8; //c1?
OLED_Setup_Array[19] = 0xA1;
} else if (leftHanded == 0) {
} else {
OLED_Setup_Array[11] = 0xC0;
OLED_Setup_Array[19] = 0xA0;
}
i2c->Transmit( DEVICEADDR_OLED, (uint8_t*) OLED_Setup_Array,
configLength);
i2c->Transmit( DEVICEADDR_OLED, (uint8_t*) OLED_Setup_Array, sizeof(OLED_Setup_Array));
inLeftHandedMode = leftHanded;
screenBuffer[5] = inLeftHandedMode ? 0 : 32; //display is shifted by 32 in left handed mode as driver ram is 128 wide
screenBuffer[7] = inLeftHandedMode ? 95 : 0x7F; //End address of the ram segment we are writing to (96 wide)
screenBuffer[9] = inLeftHandedMode ? 0xC8 : 0xC0;
}
}
//print a string to the current cursor location
void OLED::print(const char* str) {
@@ -183,14 +171,6 @@ void OLED::print(const char* str) {
}
}
void OLED::setCursor(int16_t x, int16_t y) {
cursor_x = x;
cursor_y = y;
}
void OLED::setCharCursor(int16_t x, int16_t y) {
cursor_x = x * fontWidth;
cursor_y = y * fontHeight;
}
void OLED::setFont(uint8_t fontNumber) {
if (fontNumber == 1) {
//small font
@@ -208,58 +188,35 @@ void OLED::setFont(uint8_t fontNumber) {
}
}
void OLED::drawImage(const uint8_t* buffer, uint8_t x, uint8_t width) {
drawArea(x, 0, width, 16, buffer);
}
//maximum places is 5
void OLED::printNumber(uint16_t number, uint8_t places) {
char buffer[6];
buffer[5] = 0; //null
char buffer[6] = { 0 };
if (places == 5) {
buffer[4] = '0' + number % 10;
number /= 10;
} else
buffer[4] = 0;
}
if (places > 3) {
buffer[3] = '0' + number % 10;
number /= 10;
} else
buffer[3] = 0;
}
if (places > 2) {
buffer[2] = '0' + number % 10;
number /= 10;
} else
buffer[2] = 0;
}
if (places > 1) {
buffer[1] = '0' + number % 10;
number /= 10;
} else
buffer[1] = 0;
}
buffer[0] = '0' + number % 10;
number /= 10;
print(buffer);
}
void OLED::clearScreen() {
memset(firstStripPtr, 0, 96);
memset(secondStripPtr, 0, 96);
}
bool OLED::getRotation() {
return inLeftHandedMode;
}
void OLED::drawBattery(uint8_t state) {
if (state > 10)
state = 10;
drawSymbol(3 + state);
}
void OLED::drawCheckbox(bool state) {
drawSymbol((state) ? 16 : 17);
}
void OLED::drawSymbol(uint8_t symbolID) {
//draw a symbol to the current cursor location
setFont(2);