123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- #include "Display_SH1106_I2C.h"
- #include <utility>
- #include <AP_HAL/AP_HAL.h>
- #include <AP_HAL/I2CDevice.h>
- Display_SH1106_I2C::Display_SH1106_I2C(AP_HAL::OwnPtr<AP_HAL::Device> dev) :
- _dev(std::move(dev))
- {
- }
- Display_SH1106_I2C::~Display_SH1106_I2C()
- {
- }
- Display_SH1106_I2C *Display_SH1106_I2C::probe(AP_HAL::OwnPtr<AP_HAL::Device> dev)
- {
- Display_SH1106_I2C *driver = new Display_SH1106_I2C(std::move(dev));
- if (!driver || !driver->hw_init()) {
- delete driver;
- return nullptr;
- }
- return driver;
- }
- bool Display_SH1106_I2C::hw_init()
- {
- struct PACKED {
- uint8_t reg;
- uint8_t seq[26];
- } init_seq = { 0x0, {
- 0xAE,
- 0xA1,
- 0xC8,
- 0xA8, 0x3F,
- 0xD5, 0x50,
- 0xD3, 0x00,
- 0xDB, 0x40,
- 0x81, 0xCF,
- 0xAD, 0x8B,
- 0x40,
- 0xDA, 0x12,
- 0xD9, 0xF1,
- 0xA4,
- 0xA6,
- 0xAF,
- 0xB0,
- 0x02, 0x10
- } };
- memset(_displaybuffer, 0, SH1106_COLUMNS * SH1106_ROWS_PER_PAGE);
-
- if (!_dev || !_dev->get_semaphore()->take(HAL_SEMAPHORE_BLOCK_FOREVER)) {
- return false;
- }
-
- bool success = _dev->transfer((uint8_t *)&init_seq, sizeof(init_seq), nullptr, 0);
-
- _dev->get_semaphore()->give();
- if (success) {
- _need_hw_update = true;
- _dev->register_periodic_callback(20000, FUNCTOR_BIND_MEMBER(&Display_SH1106_I2C::_timer, void));
- }
- return success;
- }
- void Display_SH1106_I2C::hw_update()
- {
- _need_hw_update = true;
- }
- void Display_SH1106_I2C::_timer()
- {
- if (!_need_hw_update) {
- return;
- }
- _need_hw_update = false;
- struct PACKED {
- uint8_t reg;
- uint8_t column_0_3;
- uint8_t column_4_7;
- uint8_t page;
- } command = { 0x0, 0x2, 0x10, 0xB0 };
- struct PACKED {
- uint8_t reg;
- uint8_t db[SH1106_COLUMNS/2];
- } display_buffer = { 0x40, {} };
-
- for (uint8_t i = 0; i < (SH1106_ROWS / SH1106_ROWS_PER_PAGE); i++) {
- command.page = 0xB0 | (i & 0x0F);
- _dev->transfer((uint8_t *)&command, sizeof(command), nullptr, 0);
- memcpy(&display_buffer.db[0], &_displaybuffer[i * SH1106_COLUMNS], SH1106_COLUMNS/2);
- _dev->transfer((uint8_t *)&display_buffer, SH1106_COLUMNS/2 + 1, nullptr, 0);
- memcpy(&display_buffer.db[0], &_displaybuffer[i * SH1106_COLUMNS + SH1106_COLUMNS/2 ], SH1106_COLUMNS/2);
- _dev->transfer((uint8_t *)&display_buffer, SH1106_COLUMNS/2 + 1, nullptr, 0);
- }
- }
- void Display_SH1106_I2C::set_pixel(uint16_t x, uint16_t y)
- {
-
- if ((x >= SH1106_COLUMNS) || (y >= SH1106_ROWS)) {
- return;
- }
-
- _displaybuffer[x + (y / 8 * SH1106_COLUMNS)] |= 1 << (y % 8);
- }
- void Display_SH1106_I2C::clear_pixel(uint16_t x, uint16_t y)
- {
-
- if ((x >= SH1106_COLUMNS) || (y >= SH1106_ROWS)) {
- return;
- }
-
- _displaybuffer[x + (y / 8 * SH1106_COLUMNS)] &= ~(1 << (y % 8));
- }
- void Display_SH1106_I2C::clear_screen()
- {
- memset(_displaybuffer, 0, SH1106_COLUMNS * SH1106_ROWS_PER_PAGE);
- }
|