diff --git a/drivers/gdisp/SSD1306/board_SSD1306_i2c.h b/drivers/gdisp/SSD1306/board_SSD1306_i2c.h new file mode 100644 index 00000000..c89562e0 --- /dev/null +++ b/drivers/gdisp/SSD1306/board_SSD1306_i2c.h @@ -0,0 +1,121 @@ +/* + * This file is subject to the terms of the GFX License. If a copy of + * the license was not distributed with this file, you can obtain one at: + * + * http://ugfx.org/license.html + */ + +/** + * @file drivers/gdisp/SSD1306/board_SSD1306_i2c.h + * @brief GDISP Graphic Driver subsystem board interface for the SSD1306 display. + */ + +#ifndef _GDISP_LLD_BOARD_H +#define _GDISP_LLD_BOARD_H + +#define GDISP_BUS_MAX_TRANSFER_SIZE 64 + +// For a multiple display configuration we would put all this in a structure and then +// set g->board to that structure. +#define SSD1306_RESET_PORT GPIOB +#define SSD1306_RESET_PIN 5 + +/** + * The default slave address is 0x3D, (talking about + * only the real address part here) and the slave + * address can be changed to 0x3C by soldering the + * SA0 pads on the bottom side of the module. + * + * b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 + * -------------------------------------- + * 0 | 1 | 1 | 1 | 1 | 0 |SA0 | R/W + */ +#define SSD1306_I2C_ADDRESS 0x3D +#define SSD1306_SDA_PORT GPIOB +#define SSD1306_SDA_PIN 7 +#define SSD1306_SCL_PORT GPIOB +#define SSD1306_SCL_PIN 6 +#define SET_RST palSetPad(SSD1306_RESET_PORT, SSD1306_RESET_PIN); +#define CLR_RST palClearPad(SSD1306_RESET_PORT, SSD1306_RESET_PIN); + +// I2C configuration structure. +static I2CConfig i2cconfig; + +static inline void init_board(GDisplay *g) { + + // As we are not using multiple displays we set g->board to NULL as we don't use it. + g->board = 0; + + switch(g->controllerdisplay) { + case 0: // Set up for Display 0 + // RESET pin. + palSetPadMode(SSD1306_RESET_PORT, SSD1306_RESET_PIN, PAL_MODE_OUTPUT_PUSHPULL); + + + /* + * Initializes the I2C driver 1. The I2C1 signals are routed as follows: + * PB6 - SCL. + * PB7 - SDA. + * Timing value comes from ST I2C config tool (xls): + * 0x00901D2B; // 100kHz Standard Mode + * 0x00300444; // 100kHz Fast Mode + * 0x0030020A; // 400kHz Fast Mode + * 0x00100002; // 800kHz Fast Mode + + */ + i2cconfig.timingr = 0x00100002; // 800kHz Fast Mode+ + i2cInit(); + palSetPadMode(SSD1306_SCL_PORT, SSD1306_SCL_PIN, PAL_MODE_ALTERNATE(1)); + palSetPadMode(SSD1306_SDA_PORT, SSD1306_SDA_PIN, PAL_MODE_ALTERNATE(1)); + break; + } +} + +static inline void post_init_board(GDisplay *g) { + (void) g; +} + +static inline void setpin_reset(GDisplay *g, bool_t state) { + (void) g; + if(state) + CLR_RST + else + SET_RST +} + +static inline void acquire_bus(GDisplay *g) { + (void) g; + i2cAcquireBus(&I2CD1); +} + +static inline void release_bus(GDisplay *g) { + (void) g; + i2cReleaseBus(&I2CD1); +} + +static inline void write_cmd(GDisplay *g, uint8_t cmd) { + uint8_t command[2]; + (void) g; + + command[0] = 0x00; // Co = 0, D/C = 0 + command[1] = cmd; + + i2cStart(&I2CD1, &i2cconfig); + i2cMasterTransmitTimeout(&I2CD1, SSD1306_I2C_ADDRESS, command, 2, NULL, 0, MS2ST(10)); + i2cStop(&I2CD1); +} + +static inline void write_data(GDisplay *g, uint8_t* data, uint16_t length) { + uint8_t command[1]; + (void) g; + + command[0] = 0x40; // Co = 0, D/C = 1 + + i2cStart(&I2CD1, &i2cconfig); + i2cMasterTransmitTimeout(&I2CD1, SSD1306_I2C_ADDRESS, command, 1, NULL, 0, MS2ST(10)); + i2cMasterTransmitTimeout(&I2CD1, SSD1306_I2C_ADDRESS, command, data, NULL, length, MS2ST(10)); + i2cStop(&I2CD1); +} + +#endif /* _GDISP_LLD_BOARD_H */ + + diff --git a/drivers/gdisp/SSD1306/board_SSD1306_spi.h b/drivers/gdisp/SSD1306/board_SSD1306_spi.h new file mode 100644 index 00000000..e206a517 --- /dev/null +++ b/drivers/gdisp/SSD1306/board_SSD1306_spi.h @@ -0,0 +1,122 @@ +/* + * This file is subject to the terms of the GFX License. If a copy of + * the license was not distributed with this file, you can obtain one at: + * + * http://ugfx.org/license.html + */ + +/** + * @file drivers/gdisp/SSD1306/board_SSD1306_spi.h + * @brief GDISP Graphic Driver subsystem board interface for the SSD1306 display. + */ + +#ifndef _GDISP_LLD_BOARD_H +#define _GDISP_LLD_BOARD_H + +#define GDISP_BUS_MAX_TRANSFER_SIZE 64 + +// For a multiple display configuration we would put all this in a structure and then +// set g->board to that structure. +#define SSD1306_RESET_PORT GPIOB +#define SSD1306_RESET_PIN 5 +#define SSD1306_MISO_PORT GPIOB +#define SSD1306_MISO_PIN 8 +#define SSD1306_MOSI_PORT GPIOB +#define SSD1306_MOSI_PIN 7 +#define SSD1306_SCK_PORT GPIOB +#define SSD1306_SCK_PIN 6 +#define SSD1306_CS_PORT GPIOB +#define SSD1306_CS_PIN 5 +#define SET_RST palSetPad(SSD1306_RESET_PORT, SSD1306_RESET_PIN); +#define CLR_RST palClearPad(SSD1306_RESET_PORT, SSD1306_RESET_PIN); + +/* + * SPI1 configuration structure. + * Speed 42MHz, CPHA=0, CPOL=0, 8bits frames, MSb transmitted first. + * The slave select line is the pin 4 on the port GPIOA. + */ +static const SPIConfig spi1config = { + NULL, + /* HW dependent part.*/ + SSD1306_MISO_PORT, + SSD1306_MISO_PIN, + 0 + //SPI_CR1_BR_0 +}; + +static inline void init_board(GDisplay *g) { + + // As we are not using multiple displays we set g->board to NULL as we don't use it. + g->board = 0; + + switch(g->controllerdisplay) { + case 0: // Set up for Display 0 + // RESET pin. + palSetPadMode(SSD1306_RESET_PORT, SSD1306_RESET_PIN, PAL_MODE_OUTPUT_PUSHPULL); + + spiInit(); + palSetPadMode(SSD1306_MISO_PORT, SSD1306_MISO_PIN, PAL_MODE_ALTERNATE(1)| + PAL_STM32_OSPEED_HIGHEST); + palSetPadMode(SSD1306_MOSI_PORT, SSD1306_MOSI_PIN, PAL_MODE_ALTERNATE(1)| + PAL_STM32_OSPEED_HIGHEST); + palSetPadMode(SSD1306_SCK_PORT, SSD1306_SCK_PIN, PAL_MODE_ALTERNATE(1)| + PAL_STM32_OSPEED_HIGHEST); + palSetPad(SSD1306_CS_PORT, SSD1306_CS_PIN); + palSetPadMode(SSD1306_CS_PORT, SSD1306_CS_PIN, PAL_MODE_ALTERNATE(1)| + PAL_STM32_OSPEED_HIGHEST); + break; + } +} + +static inline void post_init_board(GDisplay *g) { + (void) g; +} + +static inline void setpin_reset(GDisplay *g, bool_t state) { + (void) g; + if(state) + CLR_RST + else + SET_RST +} + +static inline void acquire_bus(GDisplay *g) { + (void) g; + spiAcquireBus(&SPID1); +} + +static inline void release_bus(GDisplay *g) { + (void) g; + spiReleaseBus(&SPID1); +} + +static inline void write_cmd(GDisplay *g, uint8_t cmd) { + uint8_t command[2]; + + command[0] = 0x00; // Co = 0, D/C = 0 + command[1] = cmd; + + spiStart(&SPID1, &spi1config); + spiSelect(&SPID1); + spiStartSend(&SPID1, 2, command); + spiUnselect(&SPID1); + spiStop(&SPID1); +} + +static inline void write_data(GDisplay *g, uint8_t* data, uint16_t length) { + uint8_t command[1]; + (void) g; + + command[0] = 0x40; // Co = 0, D/C = 1 + + spiStart(&SPID1, &spi1config); + spiSelect(&SPID1); + spiStartSend(&SPID1, 1, command); + spiStartSend(&SPID1, length, data); + spiUnselect(&SPID1); + spiStop(&SPID1); +} + + +#endif /* _GDISP_LLD_BOARD_H */ + diff --git a/drivers/gdisp/SSD1306/board_SSD1306_template.h b/drivers/gdisp/SSD1306/board_SSD1306_template.h new file mode 100644 index 00000000..ec7f44f5 --- /dev/null +++ b/drivers/gdisp/SSD1306/board_SSD1306_template.h @@ -0,0 +1,116 @@ +/* + * This file is subject to the terms of the GFX License. If a copy of + * the license was not distributed with this file, you can obtain one at: + * + * http://ugfx.org/license.html + */ + +/** + * @file drivers/gdisp/SSD1306/board_SSD1306_template.h + * @brief GDISP Graphic Driver subsystem board interface for the SSD1306 display. + * + * @addtogroup GDISP + * @{ + */ + +#ifndef _GDISP_LLD_BOARD_H +#define _GDISP_LLD_BOARD_H + +/** + * @brief How many bytes to write in one operation when updating the display. + * @note The screen size (in bytes) must evenly divide by this number. + * + * @notapi + */ +#define GDISP_BUS_MAX_TRANSFER_SIZE 64 + +/** + * @brief Initialise the board for the display. + * + * @param[in] g The GDisplay structure + * + * @note Set the g->board member to whatever is appropriate. For multiple + * displays this might be a pointer to the appropriate register set. + * + * @notapi + */ +static inline void init_board(GDisplay *g) { + (void) g; +} + +/** + * @brief After the initialisation. + * + * @param[in] g The GDisplay structure + * + * @notapi + */ +static inline void post_init_board(GDisplay *g) { + (void) g; +} + +/** + * @brief Set or clear the lcd reset pin. + * + * @param[in] g The GDisplay structure + * @param[in] state TRUE = lcd in reset, FALSE = normal operation + * + * @notapi + */ +static inline void setpin_reset(GDisplay *g, bool_t state) { + (void) g; + (void) state; +} + +/** + * @brief Take exclusive control of the bus + * + * @param[in] g The GDisplay structure + * + * @notapi + */ +static inline void acquire_bus(GDisplay *g) { + (void) g; +} + +/** + * @brief Release exclusive control of the bus + * + * @param[in] g The GDisplay structure + * + * @notapi + */ +static inline void release_bus(GDisplay *g) { + (void) g; +} + +/** + * @brief Send a command to the controller. + * + * @param[in] g The GDisplay structure + * @param[in] cmd The command to send * + * + * @notapi + */ +static inline void write_cmd(GDisplay *g, uint8_t cmd) { + (void) g; + (void) cmd; +} + +/** + * @brief Send data to the lcd. + * + * @param[in] g The GDisplay structure + * @param[in] data The data to send + * + * @notapi + */ +static inline void write_data(GDisplay *g, uint8_t* data, uint16_t length) { + (void) g; + (void) data; + (void) length; +} + +#endif /* _GDISP_LLD_BOARD_H */ +/** @} */ + diff --git a/drivers/gdisp/SSD1306/gdisp_lld.c b/drivers/gdisp/SSD1306/gdisp_lld.c index 5f337b54..36ba9686 100644 --- a/drivers/gdisp/SSD1306/gdisp_lld.c +++ b/drivers/gdisp/SSD1306/gdisp_lld.c @@ -5,642 +5,219 @@ * http://ugfx.org/license.html */ -#include "gfx.h" +/** + * @file drivers/gdisp/SSD1306/gdisp_lld.c + * @brief GDISP Graphics Driver subsystem low level driver source for the SSD1306 display. + */ -#include "SSD1306.h" +#include "gfx.h" #if GFX_USE_GDISP || defined(__DOXYGEN__) -/* Include the emulation code for things we don't support */ -#include "gdisp/lld/emulation.c" +#define GDISP_DRIVER_VMT GDISPVMT_SSD1306 +#include "../drivers/gdisp/SSD1306/gdisp_lld_config.h" +#include "gdisp/lld/gdisp_lld.h" + +#include "board_SSD1306.h" /*===========================================================================*/ /* Driver local definitions. */ /*===========================================================================*/ #ifndef GDISP_SCREEN_HEIGHT - #define GDISP_SCREEN_HEIGHT 64 + #define GDISP_SCREEN_HEIGHT 64 // This controller should support 32 (untested) or 64 #endif #ifndef GDISP_SCREEN_WIDTH #define GDISP_SCREEN_WIDTH 128 #endif +#ifndef GDISP_INITIAL_CONTRAST + #define GDISP_INITIAL_CONTRAST 100 +#endif +#ifndef GDISP_INITIAL_BACKLIGHT + #define GDISP_INITIAL_BACKLIGHT 100 +#endif -#define GDISP_INITIAL_CONTRAST 0xFF +#define GDISP_FLG_NEEDFLUSH (GDISP_FLG_DRIVER<<0) + +#include "SSD1306.h" /*===========================================================================*/ /* Driver local functions. */ /*===========================================================================*/ -// Include wiring specific header -#include "gdisp_lld_board_example_i2c.h" +// Some common routines and macros +#define RAM(g) ((uint8_t *)g->priv) +#define write_cmd2(g, cmd1, cmd2) { write_cmd(g, cmd1); write_cmd(g, cmd2); } +#define write_cmd3(g, cmd1, cmd2, cmd3) { write_cmd(g, cmd1); write_cmd(g, cmd2); write_cmd(g, cmd3); } // Some common routines and macros #define delay(us) gfxSleepMicroseconds(us) #define delayms(ms) gfxSleepMilliseconds(ms) -// The memory buffer for the display -static uint8_t gdisp_buffer[GDISP_SCREEN_HEIGHT * GDISP_SCREEN_WIDTH / 8]; - -/** Set the display to normal or inverse. - * @param[in] value 0 for normal mode, or 1 for inverse mode. - * @notapi - */ -static void invert_display(uint8_t i) { - write_cmd(i ? SSD1306_INVERTDISPLAY : SSD1306_NORMALDISPLAY); -} - -/** Turn the whole display off. - * Sends the display to sleep, but leaves RAM intact. - * @notapi - */ -static void display_off(){ - write_cmd(SSD1306_DISPLAYOFF); -} - -/** Turn the whole display on. - * Wakes up this display following a sleep() call. - * @notapi - */ -static void display_on() { - write_cmd(SSD1306_DISPLAYON); -} - -/** Set the vertical shift by COM. - * @param[in] value The number of rows to shift, from 0 - 63. - * @notapi -*/ -static void set_display_offset(unsigned char value) { - write_cmd(SSD1306_SETDISPLAYOFFSET); - write_cmd(value & 0x3F); -} - -/** Set the display contrast. - * @param[in] value The contrast, from 1 to 256. - * @notapi - */ -static void set_contrast(unsigned char value) { - write_cmd(SSD1306_SETCONTRAST); - write_cmd(value); -} - -/** Set the display start line. This is the line at which the display will start rendering. - * @param[in] value A value from 0 to 63 denoting the line to start at. - * @notapi - */ -static void set_display_start_line(unsigned char value) { - write_cmd(SSD1306_SETSTARTLINE | value); -} - -/** Set the segment remap state. This allows the module to be addressed as if flipped horizontally. - * NOTE: Changing this setting has no effect on data already in the module's GDDRAM. - * @param[in] value 0 = column address 0 = segment 0 (the default), 1 = column address 127 = segment 0 (flipped). - * @notapi - */ -static void set_segment_remap(unsigned char value) { - write_cmd(value ? SSD1306_SEGREMAP+1 : SSD1306_SEGREMAP); -} - -/** Set the multiplex ratio. - * @param[in] value MUX will be set to (value+1). Valid values range from 15 to 63 - MUX 16 to 64. - * @notapi - */ -static void set_multiplex_ratio(unsigned char value) { - write_cmd(SSD1306_SETMULTIPLEX); - write_cmd(value & 0x3F); -} - -/** Set COM output scan direction. If the display is active, this will immediately vertically - * flip the display. - * @param[in] value 0 = Scan from COM0 (default), 1 = reversed (scan from COM[N-1]). - * @notapi - */ -static void set_com_output_scan_direction(unsigned char value) { - write_cmd(value ? SSD1306_COMSCANDEC : SSD1306_COMSCANINC); -} - -static void set_com_pins_hardware_configuration(unsigned char sequential, unsigned char lr_remap) { - write_cmd(SSD1306_SETCOMPINS); - write_cmd(0x02 | ((sequential & 1) << 4) | ((lr_remap & 1) << 5)); -} - -/** Flip display content horizontally. - * NOTE: This only flips display content, but doesn't turn the char writing around. - * You have to unmirror everything manually. - * @param[in] value 0 = column address 0 = segment 0 (the default), 1 = column address 127 = segment 0 (flipped). - * @notapi - */ -static void flip_display(unsigned char enable) { - if( enable && GDISP.Orientation == GDISP_ROTATE_0) { - set_com_output_scan_direction(0); - set_segment_remap(0); - GDISP.Orientation = GDISP_ROTATE_0; - } - if( !enable && GDISP.Orientation == GDISP_ROTATE_180) { - set_com_output_scan_direction(1); - set_segment_remap(1); - GDISP.Orientation = GDISP_ROTATE_180; - } - else - return; -} - -/** Perform a "no operation". - * @notapi - */ -static void nop() { - write_cmd(0xE3); -} - -/** Page Addressing Mode: Set the column start address register for - * page addressing mode. - * @param[in] address The address (full byte). - * @notapi - */ -static void set_start_address_pam(unsigned char address) -{ - // "Set Lower Column Start Address for Page Addressing Mode" - write_cmd(address & 0x0F); - - // "Set Higher Column Start Address for Page Addressing Mode" - write_cmd((address << 4) & 0x0F); -} - -/** Set memory addressing mode to the given value. - * @param[in] mode 0 for Horizontal addressing mode,\n 1 for Vertical addressing mode,\n or 2 for Page addressing mode (PAM). 2 is the default. - * @notapi - */ -static void set_memory_addressing_mode(unsigned char mode) -{ - write_cmd(SSD1306_MEMORYMODE); - write_cmd(mode & 0x3); -} - -/** Set column address range for horizontal/vertical addressing mode. - * @param[in] start Column start address, 0 - 127. - * @param[in] end Column end address, 0 - 127. - * @notapi - */ -static void set_column_address_hvam(unsigned char start, unsigned char end) -{ - write_cmd(SSD1306_HV_COLUMN_ADDRESS); - write_cmd(start & 0x7F); - write_cmd(end & 0x7F); -} - -/** Set page start and end address for horizontal/vertical addressing mode. - * @param[in] start The start page, 0 - 7. - * @param[in] end The end page, 0 - 7. - * @notapi - */ -static void set_page_address_hvam(unsigned char start, unsigned char end) -{ - write_cmd(SSD1306_HV_PAGE_ADDRESS); - write_cmd(start & 0x07); - write_cmd(end & 0x07); -} - -/** Set the GDDRAM page start address for page addressing mode. - * @param[in] address The start page, 0 - 7. - * @notapi - */ -static void set_page_start_pam(unsigned char address) -{ - write_cmd(SSD1306_PAM_PAGE_START | (address & 0x07)); -} - -/** Set the display clock divide ratio and the oscillator frequency. - * @param[in] ratio The divide ratio, default is 0. - * @param[in] frequency The oscillator frequency, 0 - 127. Default is 8. - * @notapi - */ -static void set_display_clock_ratio_and_frequency(unsigned char ratio, unsigned char frequency) -{ - write_cmd(SSD1306_SETDISPLAYCLOCKDIV); - write_cmd((ratio & 0x0F) | ((frequency & 0x0F) << 4)); -} - -/** Set the precharge period. - * @param[in] phase1 Phase 1 period in DCLK clocks. 1 - 15, default is 2. - * @param[in] phase2 Phase 2 period in DCLK clocks. 1 - 15, default is 2. - * @notapi - */ -static void set_precharge_period(unsigned char phase1, unsigned char phase2) -{ - write_cmd(SSD1306_SETPRECHARGE); - write_cmd((phase1 & 0x0F) | ((phase2 & 0x0F ) << 4)); -} - -/** Set the Vcomh deselect level. - * @param[in] level @p 0 = 0.65 x Vcc, @p 1 = 0.77 x Vcc (default), @p 2 = 0.83 x Vcc. - * @notapi - */ -static void set_vcomh_deselect_level(unsigned char level) -{ - write_cmd(SSD1306_SETVCOMDETECT); - write_cmd((level & 0x03) << 4); -} - -/** Enable/disable charge pump. - * @param[in] enable 0 to disable, 1 to enable the internal charge pump. - * @notapi - */ -static void set_charge_pump(unsigned char enable) -{ - write_cmd(SSD1306_ENABLE_CHARGE_PUMP); - write_cmd(enable ? 0x14 : 0x10); -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - /*===========================================================================*/ /* Driver exported functions. */ /*===========================================================================*/ -/* ---- Required Routines ---- */ -/* - The following 2 routines are required. - All other routines are optional. -*/ - /** - * @brief Low level GDISP driver initialization. - * - * @notapi + * As this controller can't update on a pixel boundary we need to maintain the + * the entire display surface in memory so that we can do the necessary bit + * operations. Fortunately it is a small display in monochrome. + * 64 * 128 / 8 = 1024 bytes. */ -bool_t gdisp_lld_init(void) { - // Initialize your display - init_board(); - // Hardware reset. - setpin_reset(TRUE); - delayms(1); - setpin_reset(FALSE); - delayms(10); - setpin_reset(TRUE); +LLDSPEC bool_t gdisp_lld_init(GDisplay *g) { + // The private area is the display surface. + g->priv = gfxAlloc(GDISP_SCREEN_HEIGHT * GDISP_SCREEN_WIDTH / 8); - // Get the bus for the following initialization commands. - acquire_bus(); + // Initialise the board interface + init_board(g); - display_off(); - set_display_clock_ratio_and_frequency(0, 8); + // Hardware reset + setpin_reset(g, TRUE); + gfxSleepMilliseconds(20); + setpin_reset(g, FALSE); + gfxSleepMilliseconds(20); + + acquire_bus(g); + + write_cmd(g, SSD1306_DISPLAYOFF); + write_cmd2(g, SSD1306_SETDISPLAYCLOCKDIV, 0x80); + write_cmd2(g, SSD1306_SETMULTIPLEX, GDISP_SCREEN_HEIGHT-1); + write_cmd2(g, SSD1306_SETPRECHARGE, 0x1F); + write_cmd2(g, SSD1306_SETDISPLAYOFFSET, 0); + write_cmd(g, SSD1306_SETSTARTLINE | 0); + write_cmd2(g, SSD1306_ENABLE_CHARGE_PUMP, 0x14); + write_cmd2(g, SSD1306_MEMORYMODE, 0); + write_cmd(g, SSD1306_SEGREMAP+1); + write_cmd(g, SSD1306_COMSCANDEC); #if GDISP_SCREEN_HEIGHT == 64 - set_multiplex_ratio(0x3F); // 1/64 duty + write_cmd2(g, SSD1306_SETCOMPINS, 0x12); + #else + write_cmd2(g, SSD1306_SETCOMPINS, 0x22); #endif - #if GDISP_SCREEN_HEIGHT == 32 - set_multiplex_ratio(0x1F); // 1/32 duty - #endif - set_precharge_period(0xF, 0x01); // - set_display_offset(0); // - set_display_start_line(0); // - set_charge_pump(1); // Enable internal charge pump. - set_memory_addressing_mode(0); // horizontal addressing mode; across then down //act like ks0108 (horizontal addressing mode) - set_segment_remap(1); // - set_com_output_scan_direction(1); // - #if GDISP_SCREEN_HEIGHT == 64 - set_com_pins_hardware_configuration(1, 0); - #endif - #if GDISP_SCREEN_HEIGHT == 32 - set_com_pins_hardware_configuration(0, 1); - #endif - set_contrast(GDISP_INITIAL_CONTRAST); // Set initial contrast. - set_vcomh_deselect_level(1); // - display_on(); // Turn on OLED panel. - invert_display(0); // Disable Inversion of display. - set_column_address_hvam(0, 127); // - set_page_address_hvam(0, 7); // + write_cmd2(g, SSD1306_SETCONTRAST, (uint8_t)(GDISP_INITIAL_CONTRAST*256/101)); // Set initial contrast. + write_cmd2(g, SSD1306_SETVCOMDETECT, 0x10); + write_cmd(g, SSD1306_DISPLAYON); + write_cmd(g, SSD1306_NORMALDISPLAY); + write_cmd3(g, SSD1306_HV_COLUMN_ADDRESS, 0, GDISP_SCREEN_WIDTH-1); + write_cmd3(g, SSD1306_HV_PAGE_ADDRESS, 0, GDISP_SCREEN_HEIGHT/8-1); - release_bus(); + // Finish Init + post_init_board(g); - gdisp_lld_display(); + // Release the bus + release_bus(g); - // Initialize the GDISP structure - GDISP.Width = GDISP_SCREEN_WIDTH; - GDISP.Height = GDISP_SCREEN_HEIGHT; - GDISP.Orientation = GDISP_ROTATE_0; - GDISP.Powermode = powerOn; - GDISP.Contrast = GDISP_INITIAL_CONTRAST; - #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP - GDISP.clipx0 = 0; - GDISP.clipy0 = 0; - GDISP.clipx1 = GDISP.Width; - GDISP.clipy1 = GDISP.Height; - #endif + /* Initialise the GDISP structure */ + g->g.Width = GDISP_SCREEN_WIDTH; + g->g.Height = GDISP_SCREEN_HEIGHT; + g->g.Orientation = GDISP_ROTATE_0; + g->g.Powermode = powerOn; + g->g.Backlight = GDISP_INITIAL_BACKLIGHT; + g->g.Contrast = GDISP_INITIAL_CONTRAST; return TRUE; } -/** - * @brief Draws a pixel on the display. - * - * @param[in] x X location of the pixel - * @param[in] y Y location of the pixel - * @param[in] color The color of the pixel - * - * @notapi - */ -void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) { - #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP - if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return; - #endif +#if GDISP_HARDWARE_FLUSH + LLDSPEC void gdisp_lld_flush(GDisplay *g) { + unsigned i; - if (color == SSD1306_WHITE) - gdisp_buffer[x+ (y/8)*GDISP_SCREEN_WIDTH] |= (1<flags & GDISP_FLG_NEEDFLUSH)) + return; -void gdisp_lld_display() { - set_display_start_line(0); + write_cmd(g, SSD1306_SETSTARTLINE | 0); - /* We're sending half a line in one X-mission.*/ - uint8_t command[GDISP_SCREEN_WIDTH/2], - cmdLength = sizeof(command)/sizeof(command[0]), - parts = GDISP_SCREEN_WIDTH/cmdLength; - - for(int i=0; i= cy, it is equivalent to a area fill with bgcolor. - * - * @param[in] x, y The start of the area to be scrolled - * @param[in] cx, cy The size of the area to be scrolled - * @param[in] lines The number of lines to scroll (Can be positive or negative) - * @param[in] bgcolor The color to fill the newly exposed area. - * - * @notapi - */ - void gdisp_lld_vertical_scroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) { - #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP - if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; } - if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; } - if (!lines || cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return; - if (x+cx > GDISP.clipx1) cx = GDISP.clipx1 - x; - if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y; - #endif - - /* See datasheet table T10-1 for this*/ - uint8_t fHeight = (uint8_t)gdispGetFontMetric(gwinGetDefaultFont(), fontLineSpacing); - set_multiplex_ratio(GDISP_SCREEN_HEIGHT - fHeight+1); - set_display_offset(fHeight-2); - - /* Scrolling animation.*/ - for(int i=0; i> fHeight % 8; - gdisp_buffer[i] |= gdisp_buffer[i+GDISP_SCREEN_WIDTH*(fHeight/8 + 1)] << (8 - fHeight%8); - } - - /* Clear last page.*/ - memset( &gdisp_buffer[GDISP_SCREEN_HEIGHT*GDISP_SCREEN_WIDTH/8 - GDISP_SCREEN_WIDTH*2], SSD1306_BLACK, GDISP_SCREEN_WIDTH*2); - - /* Update display.*/ - gdisp_lld_display(); +#if GDISP_HARDWARE_DRAWPIXEL + LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) { + if (g->p.color != Black) + RAM(g)[g->p.x + (g->p.y>>3)*GDISP_SCREEN_WIDTH] |= (1<<(g->p.y&7)); + else + RAM(g)[g->p.x + (g->p.y>>3)*GDISP_SCREEN_WIDTH] &= ~(1<<(g->p.y&7)); + g->flags |= GDISP_FLG_NEEDFLUSH; } +#endif - /** - * @warning Implementation only fully supports left and right...some command issues here. - * Activate a scroll for rows start through stop. - * Hint, the display is 16 rows tall. To scroll the whole display, run: - * @code - * display.scrollright(0x00, 0x0F) - * @endcode - * @param[in] start The start of the area to be scrolled - * @param[in] stop The size of the area to be scrolled - * @param[in] dir direction of scrolling - * [left, right, up, down, up_right, up_left, down_left, down_right] - * @note Optional. * - * - * @notapi - */ - void gdisp_lld_start_scroll(uint8_t dir, uint8_t start, uint8_t stop, uint8_t interval){ -// if(dir == GDISP_SCROLL_RIGHT || GDISP_SCROLL_LEFT || GDISP_SCROLL_UP) { -// switch (dir) { -// case GDISP_SCROLL_RIGHT: -// write_cmd(SSD1306_SCROLL_HORIZONTAL_RIGHT); -// break; -// case GDISP_SCROLL_LEFT: -// write_cmd(SSD1306_SCROLL_HORIZONTAL_LEFT); -// break; -// } -// write_cmd(0X00); // Dummy byte. -// write_cmd(start & 0x07); // Define start page address. -// switch (interval) { // Set time interval between each scroll step (5 frames) -// case 2: write_cmd(0x07); break; // 111b -// case 3: write_cmd(0x04); break; // 100b -// case 4: write_cmd(0x05); break; // 101b -// case 5: write_cmd(0x00); break; // 000b -// case 25: write_cmd(0x06); break; // 110b -// case 64: write_cmd(0x01); break; // 001b -// case 128: write_cmd(0x02); break; // 010b -// case 256: write_cmd(0x03); break; // 011b -// default: -// // default to 2 frame interval -// write_cmd(0x07); break; -// } -// write_cmd(stop & 0x07); // Define stop page address -// write_cmd(0X01); // Set vertical scrolling offset as no row. -// write_cmd(0XFF); // Undocumented but needed. -// write_cmd(SSD1306_SCROLL_ACTIVATE); -// } -// else if(dir == GDISP_SCROLL_UP || GDISP_SCROLL_DOWN) { -// switch (dir) { -// case GDISP_SCROLL_UP: -// gdisp_lld_set_vertical_scroll_area(0x00, GDISP_SCREEN_HEIGHT); -// write_cmd(SSD1306_SCROLL_VERTICAL_AND_HORIZONTAL_RIGHT); -// break; -// -// case GDISP_SCROLL_DOWN: -// gdisp_lld_set_vertical_scroll_area(0x00, GDISP_SCREEN_HEIGHT); -// write_cmd(SSD1306_SCROLL_VERTICAL_AND_HORIZONTAL_LEFT); -// break; -// } -// write_cmd(0X00); // Dummy byte. -// write_cmd(start); // Define start page address. -// write_cmd(0X00); // Set time interval between each scroll step (5 frames) -// write_cmd(stop); // Define stop page address -// write_cmd(0X01); // Set vertical scrolling offset as no row. -// write_cmd(SSD1306_SCROLL_ACTIVATE); -// gdisp_lld_set_vertical_scroll_area(0x00, GDISP_SCREEN_HEIGHT-10); -// write_cmd(SSD1306_SCROLL_VERTICAL_AND_HORIZONTAL_RIGHT); -// write_cmd(0X00); // Dummy byte. -// write_cmd(start); // Define start page address. -// write_cmd(0X00); // Set time interval between each scroll step (5 frames) -// write_cmd(stop); // Define stop page address -// write_cmd(0X03); // Set vertical scrolling offset as no row. -// write_cmd(SSD1306_SCROLL_ACTIVATE); -// } +#if GDISP_HARDWARE_PIXELREAD + LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay *g) { + return (RAM(g)[g->p.x + (g->p.y>>3)*GDISP_SCREEN_WIDTH] & (1<<(g->p.y&7))) ? White : Black; } +#endif - /** - * Sets vertical scroll area of display. - * @param[in] start The start of the area to be scrolled [y coordinate] - * @param[in] stop The size of the area to be scrolled [y coordinate] - * @note Optional. * - * - * @notapi - */ - void gdisp_lld_set_vertical_scroll_area(uint8_t start, uint8_t stop){ - write_cmd(SSD1306_SCROLL_SET_VERTICAL_SCROLL_AREA); - write_cmd(start); - write_cmd(stop); - } - - /** Deactivate the continuous scroll set up with start_horizontal_scroll() or - * start_vertical_and_horizontal_scroll(). - * @see set_horizontal_scroll, set_vertical_and_horizontal_scroll - * @notapi - */ - void gdisp_lld_stop_scroll(void){ - write_cmd(SSD1306_SCROLL_DEACTIVATE); - } -#endif // GDISP_NEED_SCROLL - -#if GDISP_HARDWARE_FILLS || defined(__DOXYGEN__) - void gdisp_lld_fill_area(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { - #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP - if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; } - if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; } - if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return; - if (x+cx > GDISP.clipx1) cx = GDISP.clipx1 - x; - if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y; - #endif - - for(int i=x; ip.x) { case GDISP_CONTROL_POWER: - if (GDISP.Powermode == (gdisp_powermode_t)value) + if (g->g.Powermode == (powermode_t)g->p.ptr) return; - switch((gdisp_powermode_t)value) { + switch((powermode_t)g->p.ptr) { case powerOff: - display_off(); case powerSleep: - display_off(); case powerDeepSleep: - display_off(); + acquire_bus(g); + write_cmd(g, SSD1306_DISPLAYOFF); + release_bus(g); + break; case powerOn: - display_on(); + acquire_bus(g); + write_cmd(g, SSD1306_DISPLAYON); + release_bus(g); default: return; } - GDISP.Powermode = (gdisp_powermode_t)value; + g->g.Powermode = (powermode_t)g->p.ptr; return; + case GDISP_CONTROL_ORIENTATION: - if (GDISP.Orientation == (gdisp_orientation_t)value) - return; - switch((gdisp_orientation_t)value) { - case GDISP_ROTATE_0: - flip_display(0); - GDISP.Height = GDISP_SCREEN_HEIGHT; - GDISP.Width = GDISP_SCREEN_WIDTH; - break; - case GDISP_ROTATE_180: - flip_display(1); - GDISP.Height = GDISP_SCREEN_HEIGHT; - GDISP.Width = GDISP_SCREEN_WIDTH; - break; - default: - return; - } - #if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION - GDISP.clipx0 = 0; - GDISP.clipy0 = 0; - GDISP.clipx1 = GDISP.Width; - GDISP.clipy1 = GDISP.Height; - #endif - GDISP.Orientation = (gdisp_orientation_t)value; + if (g->g.Orientation == (orientation_t)g->p.ptr) return; + switch((orientation_t)g->p.ptr) { + case GDISP_ROTATE_0: + acquire_bus(g); + write_cmd(g, SSD1306_COMSCANDEC); + write_cmd(g, SSD1306_SEGREMAP+1); + GDISP.Height = GDISP_SCREEN_HEIGHT; + GDISP.Width = GDISP_SCREEN_WIDTH; + release_bus(g); + break; + case GDISP_ROTATE_180: + acquire_bus(g); + write_cmd(g, SSD1306_COMSCANINC); + write_cmd(g, SSD1306_SEGREMAP); + GDISP.Height = GDISP_SCREEN_HEIGHT; + GDISP.Width = GDISP_SCREEN_WIDTH; + release_bus(g); + break; + default: + return; + } + g->g.Orientation = (orientation_t)value; + return; + case GDISP_CONTROL_CONTRAST: - if ((unsigned)value > 100) - value = (void *)100; - if (GDISP.Contrast == (uint8_t)((float)((uint8_t)value) * 256.0/100.0) ) - return; - set_contrast((uint8_t)((float)((uint8_t)value) * 256.0/100.0) ); - GDISP.Contrast = (unsigned)value; - return; + if ((unsigned)g->p.ptr > 100) + g->p.ptr = (void *)100; + acquire_bus(g); + write_cmd2(g, SSD1306_SETCONTRAST, (((uint16_t)value)<<8)/101); + release_bus(g); + g->g.Contrast = (unsigned)g->p.ptr; + return; + + // Our own special controller code to inverse the display + // 0 = normal, 1 = inverse + case GDISP_CONTROL_INVERT: + acquire_bus(g); + write_cmd(g, g->p.ptr ? SSD1306_INVERTDISPLAY : SSD1306_NORMALDISPLAY); + release_bus(g); + return; } } #endif // GDISP_NEED_CONTROL -/** - * Let the display blink several times by means of invert and invert back. - * @param num number of blink cycles to do - * @param speed milliseconds to wait between toggling inversion - * @param wait milliseconds to wait before start of all blink cycles and after finishing blink cycles - * @notapi - */ - void gdisp_lld_display_blink(uint8_t num, uint16_t speed, uint16_t wait){ - uint8_t inv = 0; - - gfxSleepMilliseconds(wait); - for(int i=0; i<2*num; i++) { - inv ^= 1; - invert_display(inv); - gfxSleepMilliseconds(speed); - } - gfxSleepMilliseconds(wait); -} - #endif // GFX_USE_GDISP -/** @} */ diff --git a/drivers/gdisp/SSD1306/gdisp_lld.mk b/drivers/gdisp/SSD1306/gdisp_lld.mk index 2a2e1364..ad320292 100644 --- a/drivers/gdisp/SSD1306/gdisp_lld.mk +++ b/drivers/gdisp/SSD1306/gdisp_lld.mk @@ -1,5 +1,2 @@ -# List the required driver. -GFXSRC += $(GFXLIB)/drivers/gdisp/SSD1306/gdisp_lld.c - -# Required include directories GFXINC += $(GFXLIB)/drivers/gdisp/SSD1306 +GFXSRC += $(GFXLIB)/drivers/gdisp/SSD1306/gdisp_lld.c diff --git a/drivers/gdisp/SSD1306/gdisp_lld_board_example_i2c.h b/drivers/gdisp/SSD1306/gdisp_lld_board_example_i2c.h deleted file mode 100644 index 0e7e153a..00000000 --- a/drivers/gdisp/SSD1306/gdisp_lld_board_example_i2c.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - * This file is subject to the terms of the GFX License. If a copy of - * the license was not distributed with this file, you can obtain one at: - * - * http://ugfx.org/license.html - */ - -#ifndef _GDISP_LLD_BOARD_H -#define _GDISP_LLD_BOARD_H - -#define SSD1306_RESET_PORT GPIOB -#define SSD1306_RESET_PIN 5 - -/** - * The default slave address is 0x3D, (talking about - * only the real address part here) and the slave - * address can be changed to 0x3C by soldering the - * SA0 pads on the bottom side of the module. - * - * b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 - * -------------------------------------- - * 0 | 1 | 1 | 1 | 1 | 0 |SA0 | R/W - */ -#define SSD1306_I2C_ADDRESS 0x3D -#define SSD1306_SDA_PORT GPIOB -#define SSD1306_SDA_PIN 7 -#define SSD1306_SCL_PORT GPIOB -#define SSD1306_SCL_PIN 6 -#define SET_RST palSetPad(SSD1306_RESET_PORT, SSD1306_RESET_PIN); -#define CLR_RST palClearPad(SSD1306_RESET_PORT, SSD1306_RESET_PIN); -int8_t vccstate; -int32_t row_offset = 0; - -// I2C configuration structure. -static I2CConfig i2cconfig; - - -/** - * @brief Initialize the board for the display. - * @notes This board definition uses GPIO and assumes exclusive access to these GPIO pins - * @notapi - */ -static inline void init_board(void) { - - // RESET pin. - palSetPadMode(SSD1306_RESET_PORT, SSD1306_RESET_PIN, PAL_MODE_OUTPUT_PUSHPULL); - - - /* - * Initializes the I2C driver 1. The I2C1 signals are routed as follows: - * PB6 - SCL. - * PB7 - SDA. - * Timing value comes from ST I2C config tool (xls): - * 0x00901D2B; // 100kHz Standard Mode - * 0x00300444; // 100kHz Fast Mode - * 0x0030020A; // 400kHz Fast Mode - * 0x00100002; // 800kHz Fast Mode + - */ - i2cconfig.timingr = 0x00100002; // 800kHz Fast Mode+ - i2cInit(); - palSetPadMode(SSD1306_SCL_PORT, SSD1306_SCL_PIN, PAL_MODE_ALTERNATE(1)); - palSetPadMode(SSD1306_SDA_PORT, SSD1306_SDA_PIN, PAL_MODE_ALTERNATE(1)); - vccstate = SSD1306_SWITCHCAPVCC; -} - -/** - * @brief Set or clear the lcd reset pin. - * @param[in] state TRUE = lcd in reset, FALSE = normal operation - * @notapi - */ -static inline void setpin_reset(bool_t state) { - if(state) - SET_RST - else - CLR_RST -} - -/** - * @brief Set the lcd back-light level. - * @param[in] percent 0 to 100% - * @notapi - */ -static inline void set_backlight(uint8_t percent) { - // Since we are on OLED no backlight needed -} - -/** - * @brief Take exclusive control of the bus - * @notapi - */ -static inline void acquire_bus(void) { - i2cAcquireBus(&I2CD1); -} - -/** - * @brief Release exclusive control of the bus - * @notapi - */ -static inline void release_bus(void) { - i2cReleaseBus(&I2CD1); -} - -/** - * @brief Send command to the display. - * @param[in] cmd The command to send * - * @notapi - */ -static inline void write_cmd(uint8_t cmd) { - uint8_t command[] = { 0x00, // Co = 0, D/C = 0 - cmd }, - txLength = sizeof(command)/sizeof(command[0]), - rxLength = 0; - i2cStart(&I2CD1, &i2cconfig); - i2cMasterTransmitTimeout(&I2CD1, SSD1306_I2C_ADDRESS, command, txLength, NULL, rxLength, MS2ST(10)); - i2cStop(&I2CD1); -} - -/** - * @brief Send data to the display. - * @param[in] data The data to send - * @notapi - */ -static inline void write_data(uint8_t* data, uint16_t length) { - uint8_t command[length+1], - txLength = length+1, - rxLength = 0; - command[0] = 0x40; // Co = 0, D/C = 1 - memmove(&command[1], data, length); - - i2cStart(&I2CD1, &i2cconfig); - i2cMasterTransmitTimeout(&I2CD1, SSD1306_I2C_ADDRESS, command, txLength, NULL, rxLength, MS2ST(10)); - i2cStop(&I2CD1); -} - -#endif /* _GDISP_LLD_BOARD_H */ -/** @} */ - diff --git a/drivers/gdisp/SSD1306/gdisp_lld_board_example_spi.h b/drivers/gdisp/SSD1306/gdisp_lld_board_example_spi.h deleted file mode 100644 index 232cd58c..00000000 --- a/drivers/gdisp/SSD1306/gdisp_lld_board_example_spi.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - * This file is subject to the terms of the GFX License. If a copy of - * the license was not distributed with this file, you can obtain one at: - * - * http://ugfx.org/license.html - */ - -#ifndef _GDISP_LLD_BOARD_H -#define _GDISP_LLD_BOARD_H - -#define SSD1306_RESET_PORT GPIOB -#define SSD1306_RESET_PIN 5 -#define SSD1306_MISO_PORT GPIOB -#define SSD1306_MISO_PIN 8 -#define SSD1306_MOSI_PORT GPIOB -#define SSD1306_MOSI_PIN 7 -#define SSD1306_SCK_PORT GPIOB -#define SSD1306_SCK_PIN 6 -#define SSD1306_CS_PORT GPIOB -#define SSD1306_CS_PIN 5 -#define SET_RST palSetPad(SSD1306_RESET_PORT, SSD1306_RESET_PIN); -#define CLR_RST palClearPad(SSD1306_RESET_PORT, SSD1306_RESET_PIN); -int8_t vccstate; -int32_t row_offset = 0; - -/* - * SPI1 configuration structure. - * Speed 42MHz, CPHA=0, CPOL=0, 8bits frames, MSb transmitted first. - * The slave select line is the pin 4 on the port GPIOA. - */ -static const SPIConfig spi1config = { - NULL, - /* HW dependent part.*/ - SSD1306_MISO_PORT, - SSD1306_MISO_PIN, - 0 - //SPI_CR1_BR_0 -}; - -/** - * @brief Initialize the board for the display. - * @notes This board definition uses GPIO and assumes exclusive access to these GPIO pins - * @notapi - */ -static inline void init_board(void) { - - // RESET pin. - palSetPadMode(SSD1306_RESET_PORT, SSD1306_RESET_PIN, PAL_MODE_OUTPUT_PUSHPULL); - - spiInit(); - palSetPadMode(SSD1306_MISO_PORT, SSD1306_MISO_PIN, PAL_MODE_ALTERNATE(1)| - PAL_STM32_OSPEED_HIGHEST); - palSetPadMode(SSD1306_MOSI_PORT, SSD1306_MOSI_PIN, PAL_MODE_ALTERNATE(1)| - PAL_STM32_OSPEED_HIGHEST); - palSetPadMode(SSD1306_SCK_PORT, SSD1306_SCK_PIN, PAL_MODE_ALTERNATE(1)| - PAL_STM32_OSPEED_HIGHEST); - palSetPad(SSD1306_CS_PORT, SSD1306_CS_PIN); - palSetPadMode(SSD1306_CS_PORT, SSD1306_CS_PIN, PAL_MODE_ALTERNATE(1)| - PAL_STM32_OSPEED_HIGHEST); - vccstate = SSD1306_SWITCHCAPVCC; -} - -/** - * @brief Set or clear the lcd reset pin. - * @param[in] state TRUE = lcd in reset, FALSE = normal operation - * @notapi - */ -static inline void setpin_reset(bool_t state) { - if(state) - SET_RST - else - CLR_RST -} - -/** - * @brief Set the lcd back-light level. - * @param[in] percent 0 to 100% - * @notapi - */ -static inline void set_backlight(uint8_t percent) { - // Since we are on OLED no backlight needed -} - -/** - * @brief Take exclusive control of the bus - * @notapi - */ -static inline void acquire_bus(void) { - spiAcquireBus(&SPID1); -} - -/** - * @brief Release exclusive control of the bus - * @notapi - */ -static inline void release_bus(void) { - spiReleaseBus(&SPID1); -} - -/** - * @brief Send command to the display. - * @param[in] cmd The command to send * - * @notapi - */ -static inline void write_cmd(uint8_t cmd) { - uint8_t command[] = { 0x00, // Co = 0, D/C = 0 - cmd }, - txLength = sizeof(command)/sizeof(command[0]), - rxLength = 0; - - spiStart(&SPID1, &spi1config); - spiSelect(&SPID1); - spiStartSend(&SPID1, txLength, command); - spiUnselect(&SPID1); - spiStop(&SPID1); -} - -/** - * @brief Send data to the display. - * @param[in] data The data to send - * @notapi - */ -static inline void write_data(uint8_t* data, uint16_t length) { - uint8_t command[length+1], - txLength = length+1; - command[0] = 0x40; // Co = 0, D/C = 1 - memmove(&command[1], data, length); - - spiStart(&SPID1, &spi1config); - spiSelect(&SPID1); - spiStartSend(&SPID1, txLength, command); - spiUnselect(&SPID1); - spiStop(&SPID1); -} - - -#endif /* _GDISP_LLD_BOARD_H */ -/** @} */ - diff --git a/drivers/gdisp/SSD1306/gdisp_lld_board_template.h b/drivers/gdisp/SSD1306/gdisp_lld_board_template.h deleted file mode 100644 index 48028e83..00000000 --- a/drivers/gdisp/SSD1306/gdisp_lld_board_template.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * This file is subject to the terms of the GFX License. If a copy of - * the license was not distributed with this file, you can obtain one at: - * - * http://ugfx.org/license.html - */ - -#ifndef _GDISP_LLD_BOARD_H -#define _GDISP_LLD_BOARD_H - -/** - * @brief Initialize the board for the display. - * @notes This board definition uses GPIO and assumes exclusive access to these GPIO pins - * @notapi - */ -static inline void init_board(void) { - -} - -/** - * @brief Set or clear the lcd reset pin. - * @param[in] state TRUE = lcd in reset, FALSE = normal operation - * @notapi - */ -static inline void setpin_reset(bool_t state) { - -} - -/** - * @brief Set the lcd back-light level. - * @param[in] percent 0 to 100% - * @notapi - */ -static inline void set_backlight(uint8_t percent) { - // Since we are on OLED no backlight needed -} - -/** - * @brief Take exclusive control of the bus - * @notapi - */ -static inline void acquire_bus(void) { - -} - -/** - * @brief Release exclusive control of the bus - * @notapi - */ -static inline void release_bus(void) { - -} - -/** - * @brief Send command to the display. - * @param[in] cmd The command to send * - * @notapi - */ -static inline void write_cmd(uint8_t cmd) { - -} - -/** - * @brief Send data to the display. - * @param[in] data The data to send - * @notapi - */ -static inline void write_data(uint8_t* data, uint16_t length) { - -} - -#endif /* _GDISP_LLD_BOARD_H */ -/** @} */ - diff --git a/drivers/gdisp/SSD1306/gdisp_lld_config.h b/drivers/gdisp/SSD1306/gdisp_lld_config.h index f0efc18e..8580f933 100644 --- a/drivers/gdisp/SSD1306/gdisp_lld_config.h +++ b/drivers/gdisp/SSD1306/gdisp_lld_config.h @@ -14,17 +14,17 @@ /* Driver hardware support. */ /*===========================================================================*/ -#define GDISP_DRIVER_NAME "SSD1306" - -#define GDISP_HARDWARE_CLEARS FALSE -#define GDISP_HARDWARE_FILLS TRUE -#define GDISP_HARDWARE_BITFILLS FALSE -#define GDISP_HARDWARE_SCROLL TRUE -#define GDISP_HARDWARE_PIXELREAD FALSE +#define GDISP_HARDWARE_FLUSH TRUE // This controller requires flushing +#define GDISP_HARDWARE_DRAWPIXEL TRUE +#define GDISP_HARDWARE_PIXELREAD TRUE #define GDISP_HARDWARE_CONTROL TRUE #define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_MONO +// This controller supports a special gdispControl() to inverse the display. +// Pass a parameter of 1 for inverse and 0 for normal. +#define GDISP_CONTROL_INVERSE (GDISP_CONTROL_LLD+0) + #endif /* GFX_USE_GDISP */ #endif /* _GDISP_LLD_CONFIG_H */