Convert SSD1306 driver to new driver format.
This driver requires the new flush operation.
This commit is contained in:
parent
1b3297aeae
commit
f4b9f0bcfe
9 changed files with 513 additions and 930 deletions
121
drivers/gdisp/SSD1306/board_SSD1306_i2c.h
Normal file
121
drivers/gdisp/SSD1306/board_SSD1306_i2c.h
Normal file
|
@ -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 */
|
||||||
|
|
||||||
|
|
122
drivers/gdisp/SSD1306/board_SSD1306_spi.h
Normal file
122
drivers/gdisp/SSD1306/board_SSD1306_spi.h
Normal file
|
@ -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 */
|
||||||
|
|
116
drivers/gdisp/SSD1306/board_SSD1306_template.h
Normal file
116
drivers/gdisp/SSD1306/board_SSD1306_template.h
Normal file
|
@ -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 */
|
||||||
|
/** @} */
|
||||||
|
|
|
@ -5,642 +5,219 @@
|
||||||
* http://ugfx.org/license.html
|
* 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__)
|
#if GFX_USE_GDISP || defined(__DOXYGEN__)
|
||||||
|
|
||||||
/* Include the emulation code for things we don't support */
|
#define GDISP_DRIVER_VMT GDISPVMT_SSD1306
|
||||||
#include "gdisp/lld/emulation.c"
|
#include "../drivers/gdisp/SSD1306/gdisp_lld_config.h"
|
||||||
|
#include "gdisp/lld/gdisp_lld.h"
|
||||||
|
|
||||||
|
#include "board_SSD1306.h"
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
/* Driver local definitions. */
|
/* Driver local definitions. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
|
||||||
#ifndef GDISP_SCREEN_HEIGHT
|
#ifndef GDISP_SCREEN_HEIGHT
|
||||||
#define GDISP_SCREEN_HEIGHT 64
|
#define GDISP_SCREEN_HEIGHT 64 // This controller should support 32 (untested) or 64
|
||||||
#endif
|
#endif
|
||||||
#ifndef GDISP_SCREEN_WIDTH
|
#ifndef GDISP_SCREEN_WIDTH
|
||||||
#define GDISP_SCREEN_WIDTH 128
|
#define GDISP_SCREEN_WIDTH 128
|
||||||
#endif
|
#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. */
|
/* Driver local functions. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
|
||||||
// Include wiring specific header
|
// Some common routines and macros
|
||||||
#include "gdisp_lld_board_example_i2c.h"
|
#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
|
// Some common routines and macros
|
||||||
#define delay(us) gfxSleepMicroseconds(us)
|
#define delay(us) gfxSleepMicroseconds(us)
|
||||||
#define delayms(ms) gfxSleepMilliseconds(ms)
|
#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. */
|
/* Driver exported functions. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
|
||||||
/* ---- Required Routines ---- */
|
|
||||||
/*
|
|
||||||
The following 2 routines are required.
|
|
||||||
All other routines are optional.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Low level GDISP driver initialization.
|
* 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
|
||||||
* @notapi
|
* 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.
|
LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
|
||||||
setpin_reset(TRUE);
|
// The private area is the display surface.
|
||||||
delayms(1);
|
g->priv = gfxAlloc(GDISP_SCREEN_HEIGHT * GDISP_SCREEN_WIDTH / 8);
|
||||||
setpin_reset(FALSE);
|
|
||||||
delayms(10);
|
|
||||||
setpin_reset(TRUE);
|
|
||||||
|
|
||||||
// Get the bus for the following initialization commands.
|
// Initialise the board interface
|
||||||
acquire_bus();
|
init_board(g);
|
||||||
|
|
||||||
display_off();
|
// Hardware reset
|
||||||
set_display_clock_ratio_and_frequency(0, 8);
|
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
|
#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
|
#endif
|
||||||
#if GDISP_SCREEN_HEIGHT == 32
|
write_cmd2(g, SSD1306_SETCONTRAST, (uint8_t)(GDISP_INITIAL_CONTRAST*256/101)); // Set initial contrast.
|
||||||
set_multiplex_ratio(0x1F); // 1/32 duty
|
write_cmd2(g, SSD1306_SETVCOMDETECT, 0x10);
|
||||||
#endif
|
write_cmd(g, SSD1306_DISPLAYON);
|
||||||
set_precharge_period(0xF, 0x01); //
|
write_cmd(g, SSD1306_NORMALDISPLAY);
|
||||||
set_display_offset(0); //
|
write_cmd3(g, SSD1306_HV_COLUMN_ADDRESS, 0, GDISP_SCREEN_WIDTH-1);
|
||||||
set_display_start_line(0); //
|
write_cmd3(g, SSD1306_HV_PAGE_ADDRESS, 0, GDISP_SCREEN_HEIGHT/8-1);
|
||||||
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); //
|
|
||||||
|
|
||||||
release_bus();
|
// Finish Init
|
||||||
|
post_init_board(g);
|
||||||
|
|
||||||
gdisp_lld_display();
|
// Release the bus
|
||||||
|
release_bus(g);
|
||||||
|
|
||||||
// Initialize the GDISP structure
|
/* Initialise the GDISP structure */
|
||||||
GDISP.Width = GDISP_SCREEN_WIDTH;
|
g->g.Width = GDISP_SCREEN_WIDTH;
|
||||||
GDISP.Height = GDISP_SCREEN_HEIGHT;
|
g->g.Height = GDISP_SCREEN_HEIGHT;
|
||||||
GDISP.Orientation = GDISP_ROTATE_0;
|
g->g.Orientation = GDISP_ROTATE_0;
|
||||||
GDISP.Powermode = powerOn;
|
g->g.Powermode = powerOn;
|
||||||
GDISP.Contrast = GDISP_INITIAL_CONTRAST;
|
g->g.Backlight = GDISP_INITIAL_BACKLIGHT;
|
||||||
#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
|
g->g.Contrast = GDISP_INITIAL_CONTRAST;
|
||||||
GDISP.clipx0 = 0;
|
|
||||||
GDISP.clipy0 = 0;
|
|
||||||
GDISP.clipx1 = GDISP.Width;
|
|
||||||
GDISP.clipy1 = GDISP.Height;
|
|
||||||
#endif
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#if GDISP_HARDWARE_FLUSH
|
||||||
* @brief Draws a pixel on the display.
|
LLDSPEC void gdisp_lld_flush(GDisplay *g) {
|
||||||
*
|
unsigned i;
|
||||||
* @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 (color == SSD1306_WHITE)
|
// Don't flush if we don't need it.
|
||||||
gdisp_buffer[x+ (y/8)*GDISP_SCREEN_WIDTH] |= (1<<y%8);
|
if (!(g->flags & GDISP_FLG_NEEDFLUSH))
|
||||||
else
|
return;
|
||||||
gdisp_buffer[x+ (y/8)*GDISP_SCREEN_WIDTH] &= ~(1<<y%8);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gdisp_lld_display() {
|
write_cmd(g, SSD1306_SETSTARTLINE | 0);
|
||||||
set_display_start_line(0);
|
|
||||||
|
|
||||||
/* We're sending half a line in one X-mission.*/
|
for(i=0; i < GDISP_SCREEN_WIDTH * GDISP_SCREEN_HEIGHT/8; i+=GDISP_BUS_MAX_TRANSFER_SIZE)
|
||||||
uint8_t command[GDISP_SCREEN_WIDTH/2],
|
write_data(g, RAM(g)+i, GDISP_BUS_MAX_TRANSFER_SIZE);
|
||||||
cmdLength = sizeof(command)/sizeof(command[0]),
|
|
||||||
parts = GDISP_SCREEN_WIDTH/cmdLength;
|
|
||||||
|
|
||||||
for(int i=0; i<GDISP_SCREEN_HEIGHT/8; i++){
|
|
||||||
for(int j = 0; j<parts; j++){
|
|
||||||
memmove(command, &gdisp_buffer[i*GDISP_SCREEN_WIDTH + j*cmdLength], cmdLength);
|
|
||||||
write_data(command, cmdLength);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
#endif
|
||||||
|
|
||||||
/* ---- Optional Routines ---- */
|
#if GDISP_HARDWARE_DRAWPIXEL
|
||||||
/*
|
LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) {
|
||||||
All the below routines are optional.
|
if (g->p.color != Black)
|
||||||
Defining them will increase speed but everything
|
RAM(g)[g->p.x + (g->p.y>>3)*GDISP_SCREEN_WIDTH] |= (1<<(g->p.y&7));
|
||||||
will work if they are not defined.
|
else
|
||||||
If you are not using a routine - turn it off using
|
RAM(g)[g->p.x + (g->p.y>>3)*GDISP_SCREEN_WIDTH] &= ~(1<<(g->p.y&7));
|
||||||
the appropriate GDISP_HARDWARE_XXXX macro.
|
g->flags |= GDISP_FLG_NEEDFLUSH;
|
||||||
Don't bother coding for obvious similar routines if
|
|
||||||
there is no performance penalty as the emulation software
|
|
||||||
makes a good job of using similar routines.
|
|
||||||
eg. If gfillarea() is defined there is little
|
|
||||||
point in defining clear() unless the
|
|
||||||
performance bonus is significant.
|
|
||||||
For good performance it is suggested to implement
|
|
||||||
fillarea() and blitarea().
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if (GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL) || defined(__DOXYGEN__)
|
|
||||||
/**
|
|
||||||
* @brief Scroll vertically a section of the screen.
|
|
||||||
* @note Optional.
|
|
||||||
* @note If x,y + cx,cy is off the screen, the result is undefined.
|
|
||||||
* @note If lines is >= 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; i++){
|
|
||||||
set_display_start_line(i);
|
|
||||||
gfxSleepMilliseconds(10);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Shift buffer up a font line.*/
|
|
||||||
for (int i = 0; i < GDISP_SCREEN_WIDTH*(GDISP_SCREEN_HEIGHT/8-1); i++) {
|
|
||||||
gdisp_buffer[i] = gdisp_buffer[i+GDISP_SCREEN_WIDTH*(fHeight/8)] >> 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();
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
#if GDISP_HARDWARE_PIXELREAD
|
||||||
* @warning Implementation only fully supports left and right...some command issues here.
|
LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay *g) {
|
||||||
* Activate a scroll for rows start through stop.
|
return (RAM(g)[g->p.x + (g->p.y>>3)*GDISP_SCREEN_WIDTH] & (1<<(g->p.y&7))) ? White : Black;
|
||||||
* 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);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
#if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
|
||||||
* Sets vertical scroll area of display.
|
LLDSPEC void gdisp_lld_control(GDisplay *g) {
|
||||||
* @param[in] start The start of the area to be scrolled [y coordinate]
|
switch(g->p.x) {
|
||||||
* @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; i<x+cx; i++) {
|
|
||||||
for(int j=y; j<y+cy; j++) {
|
|
||||||
gdisp_lld_draw_pixel(i,j,color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // GDISP_HARDWARE_FILLS
|
|
||||||
|
|
||||||
#if (GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL) || defined(__DOXYGEN__)
|
|
||||||
/**
|
|
||||||
* @brief Driver Control
|
|
||||||
* @details Unsupported control codes are ignored.
|
|
||||||
* @note The value parameter should always be typecast to (void *).
|
|
||||||
* @note There are some predefined and some specific to the low level driver.
|
|
||||||
* @note GDISP_CONTROL_POWER - Takes a gdisp_powermode_t
|
|
||||||
* GDISP_CONTROL_ORIENTATION - Takes a gdisp_orientation_t
|
|
||||||
* GDISP_CONTROL_BACKLIGHT - Takes an int from 0 to 100. For a driver
|
|
||||||
* that only supports off/on anything other
|
|
||||||
* than zero is on.
|
|
||||||
* GDISP_CONTROL_CONTRAST - Takes an int from 0 to 100.
|
|
||||||
* GDISP_CONTROL_LLD - Low level driver control constants start at
|
|
||||||
* this value.
|
|
||||||
*
|
|
||||||
* @param[in] what What to do.
|
|
||||||
* @param[in] value The value to use (always cast to a void *).
|
|
||||||
*
|
|
||||||
* @notapi
|
|
||||||
*/
|
|
||||||
void gdisp_lld_control(unsigned what, void *value) {
|
|
||||||
switch(what) {
|
|
||||||
case GDISP_CONTROL_POWER:
|
case GDISP_CONTROL_POWER:
|
||||||
if (GDISP.Powermode == (gdisp_powermode_t)value)
|
if (g->g.Powermode == (powermode_t)g->p.ptr)
|
||||||
return;
|
return;
|
||||||
switch((gdisp_powermode_t)value) {
|
switch((powermode_t)g->p.ptr) {
|
||||||
case powerOff:
|
case powerOff:
|
||||||
display_off();
|
|
||||||
case powerSleep:
|
case powerSleep:
|
||||||
display_off();
|
|
||||||
case powerDeepSleep:
|
case powerDeepSleep:
|
||||||
display_off();
|
acquire_bus(g);
|
||||||
|
write_cmd(g, SSD1306_DISPLAYOFF);
|
||||||
|
release_bus(g);
|
||||||
|
break;
|
||||||
case powerOn:
|
case powerOn:
|
||||||
display_on();
|
acquire_bus(g);
|
||||||
|
write_cmd(g, SSD1306_DISPLAYON);
|
||||||
|
release_bus(g);
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
GDISP.Powermode = (gdisp_powermode_t)value;
|
g->g.Powermode = (powermode_t)g->p.ptr;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case GDISP_CONTROL_ORIENTATION:
|
case GDISP_CONTROL_ORIENTATION:
|
||||||
if (GDISP.Orientation == (gdisp_orientation_t)value)
|
if (g->g.Orientation == (orientation_t)g->p.ptr)
|
||||||
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;
|
|
||||||
return;
|
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:
|
case GDISP_CONTROL_CONTRAST:
|
||||||
if ((unsigned)value > 100)
|
if ((unsigned)g->p.ptr > 100)
|
||||||
value = (void *)100;
|
g->p.ptr = (void *)100;
|
||||||
if (GDISP.Contrast == (uint8_t)((float)((uint8_t)value) * 256.0/100.0) )
|
acquire_bus(g);
|
||||||
return;
|
write_cmd2(g, SSD1306_SETCONTRAST, (((uint16_t)value)<<8)/101);
|
||||||
set_contrast((uint8_t)((float)((uint8_t)value) * 256.0/100.0) );
|
release_bus(g);
|
||||||
GDISP.Contrast = (unsigned)value;
|
g->g.Contrast = (unsigned)g->p.ptr;
|
||||||
return;
|
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
|
#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
|
#endif // GFX_USE_GDISP
|
||||||
/** @} */
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,2 @@
|
||||||
# List the required driver.
|
|
||||||
GFXSRC += $(GFXLIB)/drivers/gdisp/SSD1306/gdisp_lld.c
|
|
||||||
|
|
||||||
# Required include directories
|
|
||||||
GFXINC += $(GFXLIB)/drivers/gdisp/SSD1306
|
GFXINC += $(GFXLIB)/drivers/gdisp/SSD1306
|
||||||
|
GFXSRC += $(GFXLIB)/drivers/gdisp/SSD1306/gdisp_lld.c
|
||||||
|
|
|
@ -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 */
|
|
||||||
/** @} */
|
|
||||||
|
|
|
@ -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 */
|
|
||||||
/** @} */
|
|
||||||
|
|
|
@ -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 */
|
|
||||||
/** @} */
|
|
||||||
|
|
|
@ -14,17 +14,17 @@
|
||||||
/* Driver hardware support. */
|
/* Driver hardware support. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
|
||||||
#define GDISP_DRIVER_NAME "SSD1306"
|
#define GDISP_HARDWARE_FLUSH TRUE // This controller requires flushing
|
||||||
|
#define GDISP_HARDWARE_DRAWPIXEL TRUE
|
||||||
#define GDISP_HARDWARE_CLEARS FALSE
|
#define GDISP_HARDWARE_PIXELREAD TRUE
|
||||||
#define GDISP_HARDWARE_FILLS TRUE
|
|
||||||
#define GDISP_HARDWARE_BITFILLS FALSE
|
|
||||||
#define GDISP_HARDWARE_SCROLL TRUE
|
|
||||||
#define GDISP_HARDWARE_PIXELREAD FALSE
|
|
||||||
#define GDISP_HARDWARE_CONTROL TRUE
|
#define GDISP_HARDWARE_CONTROL TRUE
|
||||||
|
|
||||||
#define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_MONO
|
#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 /* GFX_USE_GDISP */
|
||||||
|
|
||||||
#endif /* _GDISP_LLD_CONFIG_H */
|
#endif /* _GDISP_LLD_CONFIG_H */
|
||||||
|
|
Loading…
Add table
Reference in a new issue