ST7735 driver

User avatar
russian
Posts: 284
Joined: Mon Oct 29, 2012 3:17 am
Location: Jersey City, USA
Has thanked: 2 times
Been thanked: 2 times

ST7735 driver

Postby russian » Sat Jun 15, 2013 2:28 am

This thing is tiny but on the cheaper side - 1.8" for $5.65 delivered.
http://www.ebay.com/itm/130906317995

I've ported the minimal required set of methods into gfx

gdisp_lld_board.h

Code: Select all

#ifndef GDISP_LLD_BOARD_H_
#define GDISP_LLD_BOARD_H_

// hardware reset pin
#define    LCD_RESET_PIN       14
#define      LCD_RESET_PORT      GPIOB

// chip select
#define      LCD_CS_PIN         10
#define      LCD_CS_PORT         GPIOB

// CMD/DATA mode line
#define      LCD_CMD_DATA_PIN   12
#define      LCD_CMD_DATA_PORT   GPIOB

#define    LCD_SPI_GPIO      GPIOB

#define      LCD_SDA_PIN         15
#define      LCD_SCK_PIN         13

#define      LCD_SPI            &SPID2
#define      LCD_SPI_AF         5 /*GPIO_AF_SPI2*/

#endif /* GDISP_LLD_BOARD_H_ */


gdisp_lld_config.h:

Code: Select all

/**
 * @file    drivers/gdisp/ST7735/gdisp_lld_config.h
 * @brief   GDISP Graphic Driver subsystem low level driver header for the ST7735 display.
 *
 * @addtogroup GDISP
 * @{
 */

#ifndef _GDISP_LLD_CONFIG_H
#define _GDISP_LLD_CONFIG_H

#if GFX_USE_GDISP

/*===========================================================================*/
/* Driver hardware support.                                                  */
/*===========================================================================*/

#define GDISP_DRIVER_NAME            "ST7735"

#define GDISP_HARDWARE_CLEARS         FALSE
#define GDISP_HARDWARE_FILLS         FALSE
#define GDISP_HARDWARE_BITFILLS         FALSE
#define GDISP_HARDWARE_SCROLL         FALSE
#define GDISP_HARDWARE_PIXELREAD      FALSE
#define GDISP_HARDWARE_CONTROL         FALSE

#define GDISP_PIXELFORMAT            GDISP_PIXELFORMAT_RGB565

#endif   /* GFX_USE_GDISP */

#endif   /* _GDISP_LLD_CONFIG_H */
/** @} */


gdisp_lld.c:

Code: Select all

/**
 * @file    drivers/gdisp/ST7735/gdisp_lld.c
 * @brief   GDISP Graphics Driver subsystem low level driver source for the SSD1289 display.
 *
 * @addtogroup GDISP
 * @{
 */

#include "ch.h"
#include "hal.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"

#include "gdisp_lld_board.h"

/*===========================================================================*/
/* Driver local definitions.                                                 */
/*===========================================================================*/

#ifndef GDISP_SCREEN_HEIGHT
   #define GDISP_SCREEN_HEIGHT      160
#endif
#ifndef GDISP_SCREEN_WIDTH
   #define GDISP_SCREEN_WIDTH      128
#endif

static SPIConfig spicfg = { NULL, LCD_CS_PORT, LCD_CS_PIN,
      0
      //| SPI_CR1_BR_2 | SPI_CR1_BR_1
      //| SPI_CR1_DFF /*16 bit*/
};

#define ST7735_SLEEP_OUT 0x11

#define ST7735_DISPLAY_ON 0x29
#define ST7735_CASET 0x2A
#define ST7735_RASET 0x2B
#define ST7735_RAMWR 0x2C

#define ST7735_MADCTL 0x36
#define ST7735_COLOR_MODE 0x3A

/*===========================================================================*/
/* Driver local functions.                                                   */
/*===========================================================================*/

#if defined(GDISP_USE_CUSTOM_BOARD) && GDISP_USE_CUSTOM_BOARD
   /* Include the user supplied board definitions */
   #include "gdisp_lld_board.h"
#endif

// Some common routines and macros
#define delayms(ms)               chThdSleepMilliseconds(ms)

// CMD/DATA line
#define LCD_DATA_MODE_ON()    palSetPort(LCD_CMD_DATA_PORT, PAL_PORT_BIT(LCD_CMD_DATA_PIN))
#define LCD_DATA_MODE_OFF()   palClearPort(LCD_CMD_DATA_PORT, PAL_PORT_BIT(LCD_CMD_DATA_PIN))
// chip select line
#define release_bus()   palSetPort(LCD_CS_PORT, PAL_PORT_BIT(LCD_CS_PIN))
#define acquire_bus()   palClearPort(LCD_CS_PORT, PAL_PORT_BIT(LCD_CS_PIN))


static void init_board() {
   spiStart(LCD_SPI, &spicfg);

   // SPI clock pin configuration
   palSetPadMode(LCD_SPI_GPIO, LCD_SCK_PIN, PAL_MODE_ALTERNATE(LCD_SPI_AF));

   // SPI data pin configuration
   palSetPadMode(LCD_SPI_GPIO, LCD_SDA_PIN, PAL_MODE_ALTERNATE(LCD_SPI_AF));

   palSetPadMode(LCD_RESET_PORT, LCD_RESET_PIN, PAL_STM32_MODE_OUTPUT);
   palSetPadMode(LCD_CMD_DATA_PORT, LCD_CMD_DATA_PIN, PAL_STM32_MODE_OUTPUT);
   palSetPadMode(LCD_CS_PORT, LCD_CS_PIN, PAL_STM32_MODE_OUTPUT);
}


/**
 * @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) {
   (void) state;
   if (state)
      palClearPad(LCD_RESET_PORT, LCD_RESET_PIN);
   else
      palSetPad(LCD_RESET_PORT, LCD_RESET_PIN);
}

static void lcd7735_init_lcd() {
   acquire_bus();

   // hardware display reset
   setpin_reset(TRUE);
   delayms(120);
   setpin_reset(FALSE);
   delayms(120);

   // actual LCD initialization
   lcd7735_sendCmd(ST7735_SLEEP_OUT); // wake up

   delayms(120);

   lcd7735_sendCmd(ST7735_COLOR_MODE);
   lcd7735_sendData(0x05); //     16 bit

   lcd7735_sendCmd(ST7735_MADCTL); // orientation & format
//#ifdef RGB
   lcd7735_sendData(0x1C);// RGB
//#else
//   lcd7735_sendData(0x14); // BGR
//#endif

   lcd7735_sendCmd(ST7735_DISPLAY_ON);

   release_bus();
}

// send a byte to display
void lcd7735_senddata(unsigned char data) {
   spiSend(LCD_SPI, 1, &data);
}

// send a command to display
void lcd7735_sendCmd(unsigned char cmd) {
   LCD_DATA_MODE_OFF();
   lcd7735_senddata(cmd);
}

static void lcd7735_sendData2(int value) {
   lcd7735_sendData((unsigned char) ((value & 0xFF00) >> 8));
   lcd7735_sendData((unsigned char) (value & 0x00FF));
}

void lcd7735_sendData(unsigned char data) {
   LCD_DATA_MODE_ON();
   lcd7735_senddata(data);
}

static void set_viewport(coord_t startX, coord_t startY, coord_t stopX,
      coord_t stopY) {
   lcd7735_sendCmd(ST7735_CASET);
   LCD_DATA_MODE_ON();
   lcd7735_senddata(0x00);
   lcd7735_senddata(startX);
   lcd7735_senddata(0x00);
   lcd7735_sendData(stopX);

   lcd7735_sendCmd(ST7735_RASET);
   LCD_DATA_MODE_ON();
   lcd7735_senddata(0x00);
   lcd7735_senddata(startY);
   lcd7735_senddata(0x00);
   lcd7735_sendData(stopY);
}

/*===========================================================================*/
/* 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
 */
bool_t gdisp_lld_init(void) {

   init_board();
   lcd7735_init_lcd();

   /* Initialise the GDISP structure */
   GDISP.Width = GDISP_SCREEN_WIDTH;
   GDISP.Height = GDISP_SCREEN_HEIGHT;
   GDISP.Orientation = GDISP_ROTATE_0;
   GDISP.Powermode = powerOn;
//   GDISP.Backlight = GDISP_INITIAL_BACKLIGHT;
//   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
   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
   
   acquire_bus();
   set_viewport(x, y, x, y);
   lcd7735_sendCmd(ST7735_RAMWR);
   lcd7735_sendData2(color);

   release_bus();
}


#endif /* GFX_USE_GDISP */
/** @} */


User avatar
Tectu
Posts: 1226
Joined: Thu May 10, 2012 9:50 am
Location: Switzerland
Contact:

Re: ST7735 driver

Postby Tectu » Sat Jun 15, 2013 11:42 am

Hello russian,

Thanks for sharing your new driver. New drivers always add value to ChibiOS/RT and ChibiOS/GFX.

Your driver does currently not meet the architecture of ChibiOS/GFX. Every access which gdisp_lld.c has to make to the hardware needs to be routed through the gdisp_lld_board.h file. You can observe this behavior at any of the other drivers you may find in the repository. The drivers/ginput/touch/ADS7843 driver shows how to handle SPI in such situations. Together with the information you may gather from the drivers/gdisp/SSD1289 you should be able to get things right. If you don't mind doing this changes, the driver could be included into the official repository.


~ Tectu

User avatar
russian
Posts: 284
Joined: Mon Oct 29, 2012 3:17 am
Location: Jersey City, USA
Has thanked: 2 times
Been thanked: 2 times

Re: ST7735 driver

Postby russian » Fri Jun 21, 2013 12:15 am

I'm sorry it took me so long to respond, here is a version with some changes and better separation of board level from logic level:

gdisp_lld_board.h

Code: Select all

/*
 * gdisp_lld_board.h
 *
 */

#ifndef GDISP_LLD_BOARD_H_
#define GDISP_LLD_BOARD_H_

// hardware reset pin
#define    LCD_RESET_PIN       14
#define      LCD_RESET_PORT      GPIOB

// chip select
#define      LCD_CS_PIN         10
#define      LCD_CS_PORT         GPIOB

// CMD/DATA mode line
#define      LCD_CMD_DATA_PIN   12
#define      LCD_CMD_DATA_PORT   GPIOB

#define    LCD_SPI_GPIO      GPIOB

#define      LCD_SDA_PIN         15
#define      LCD_SCK_PIN         13

#define      LCD_SPI            &SPID2
#define      LCD_SPI_AF         5 /*GPIO_AF_SPI2*/

static SPIConfig spicfg = { NULL, LCD_CS_PORT, LCD_CS_PIN, 0 /* SPI_CR1_BR_1 | SPI_CR1_BR_0 */
};

/**
 * @brief   Initialise the board.
 */
static inline void init_board(void) {
   spiStart(LCD_SPI, &spicfg);

   // SPI clock pin configuration
   palSetPadMode(LCD_SPI_GPIO, LCD_SCK_PIN, PAL_MODE_ALTERNATE(LCD_SPI_AF));

   // SPI data pin configuration
   palSetPadMode(LCD_SPI_GPIO, LCD_SDA_PIN, PAL_MODE_ALTERNATE(LCD_SPI_AF));

   palSetPadMode(LCD_RESET_PORT, LCD_RESET_PIN, PAL_STM32_MODE_OUTPUT);
   palSetPadMode(LCD_CMD_DATA_PORT, LCD_CMD_DATA_PIN, PAL_STM32_MODE_OUTPUT);
   palSetPadMode(LCD_CS_PORT, LCD_CS_PIN, PAL_STM32_MODE_OUTPUT);
}

/**
 * @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) {
   (void) state;
   if (state)
      palClearPad(LCD_RESET_PORT, LCD_RESET_PIN);
   else
      palSetPad(LCD_RESET_PORT, LCD_RESET_PIN);
}

// chip select line
static inline void acquire_bus(void) {
   palClearPad(LCD_CS_PORT, LCD_CS_PIN);
}

static inline void release_bus(void) {
   palSetPad(LCD_CS_PORT, LCD_CS_PIN);
}

// send a byte to display
void lcd7735_sendData(unsigned char data) {
   spiSend(LCD_SPI, 1, &data);
}

// send a command to display
void lcd7735_sendCmd(unsigned char cmd) {
   palClearPad(LCD_CMD_DATA_PORT, LCD_CMD_DATA_PIN);
   lcd7735_sendData(cmd);
   palSetPad(LCD_CMD_DATA_PORT, LCD_CMD_DATA_PIN);
}

static void lcd7735_sendData2(int value) {
   lcd7735_sendData((unsigned char) ((value & 0xFF00) >> 8));
   lcd7735_sendData((unsigned char) (value & 0x00FF));
}

#endif /* GDISP_LLD_BOARD_H_ */


gdisp_lld_config.h:

Code: Select all

/**
 * @file    drivers/gdisp/ST7735/gdisp_lld_config.h
 * @brief   GDISP Graphic Driver subsystem low level driver header for the ST7735 display.
 *
 * @addtogroup GDISP
 * @{
 */

#ifndef _GDISP_LLD_CONFIG_H
#define _GDISP_LLD_CONFIG_H

#if GFX_USE_GDISP

/*===========================================================================*/
/* Driver hardware support.                                                  */
/*===========================================================================*/

#define GDISP_DRIVER_NAME            "ST7735"

#define GDISP_HARDWARE_CLEARS         FALSE
#define GDISP_HARDWARE_FILLS         FALSE
#define GDISP_HARDWARE_BITFILLS         FALSE
#define GDISP_HARDWARE_SCROLL         FALSE
#define GDISP_HARDWARE_PIXELREAD      FALSE
#define GDISP_HARDWARE_CONTROL         FALSE

#define GDISP_PIXELFORMAT            GDISP_PIXELFORMAT_RGB565

#endif   /* GFX_USE_GDISP */

#endif   /* _GDISP_LLD_CONFIG_H */
/** @} */


gdisp_lld.c:

Code: Select all

/**
 * @file    drivers/gdisp/ST7735/gdisp_lld.c
 * @brief   GDISP Graphics Driver subsystem low level driver source for the SSD1289 display.
 *
 * @addtogroup GDISP
 * @{
 */

#include "ch.h"
#include "hal.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"

#include "gdisp_lld_board.h"

/*===========================================================================*/
/* Driver local definitions.                                                 */
/*===========================================================================*/

#ifndef GDISP_SCREEN_HEIGHT
   #define GDISP_SCREEN_HEIGHT      160
#endif
#ifndef GDISP_SCREEN_WIDTH
   #define GDISP_SCREEN_WIDTH      128
#endif

#define ST7735_SLEEP_OUT 0x11

#define ST7735_DISPLAY_ON 0x29
#define ST7735_CASET 0x2A
#define ST7735_RASET 0x2B
#define ST7735_RAMWR 0x2C

#define ST7735_MADCTL 0x36
#define ST7735_COLOR_MODE 0x3A

/*===========================================================================*/
/* Driver local functions.                                                   */
/*===========================================================================*/

#if defined(GDISP_USE_CUSTOM_BOARD) && GDISP_USE_CUSTOM_BOARD
   /* Include the user supplied board definitions */
   #include "gdisp_lld_board.h"
#endif

// Some common routines and macros
#define delayms(ms)               chThdSleepMilliseconds(ms)

static void lcd7735_init_lcd() {
   acquire_bus();

   // hardware display reset
   setpin_reset(TRUE);
   delayms(120);
   setpin_reset(FALSE);
   delayms(120);

   // actual LCD initialization
   lcd7735_sendCmd(ST7735_SLEEP_OUT); // wake up

   delayms(120);

   lcd7735_sendCmd(ST7735_COLOR_MODE);
   lcd7735_sendData(0x05); //     16 bit

   lcd7735_sendCmd(ST7735_MADCTL); // orientation & format
//#ifdef RGB
   lcd7735_sendData(0x1C);// RGB
//#else
//   lcd7735_sendData(0x14); // BGR
//#endif

   lcd7735_sendCmd(ST7735_DISPLAY_ON);

   release_bus();
}

static void set_viewport(coord_t startX, coord_t startY, coord_t stopX,
      coord_t stopY) {
   lcd7735_sendCmd(ST7735_CASET);
   lcd7735_sendData(0x00);
   lcd7735_sendData(startX);
   lcd7735_sendData(0x00);
   lcd7735_sendData(stopX);

   lcd7735_sendCmd(ST7735_RASET);
   lcd7735_sendData(0x00);
   lcd7735_sendData(startY);
   lcd7735_sendData(0x00);
   lcd7735_sendData(stopY);
}

/*===========================================================================*/
/* Driver exported functions.                                                */
/*===========================================================================*/

/* ---- Required Routines ---- */
/*
   The following 2 routines are required.
   All other routines are optional.
*/
/**
 * @brief   Low level GDISP driver initialization.
 *
 * @notapi
 */
bool_t gdisp_lld_init(void) {

   init_board();
   lcd7735_init_lcd();

   /* Initialise the GDISP structure */
   GDISP.Width = GDISP_SCREEN_WIDTH;
   GDISP.Height = GDISP_SCREEN_HEIGHT;
   GDISP.Orientation = GDISP_ROTATE_0;
   GDISP.Powermode = powerOn;
//   GDISP.Backlight = GDISP_INITIAL_BACKLIGHT;
//   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
   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
   
   acquire_bus();
   set_viewport(x, y, x, y);
   lcd7735_sendCmd(ST7735_RAMWR);
   lcd7735_sendData2(color);

   release_bus();
}
#endif /* GFX_USE_GDISP */
/** @} */

makerswamp
Posts: 1
Joined: Fri Jul 19, 2013 3:27 am

Re: ST7735 driver

Postby makerswamp » Fri Jul 19, 2013 3:28 am

Hey Guys,

Any updates on the ST7735 driver? Was the latest code more compliant?

User avatar
Tectu
Posts: 1226
Joined: Thu May 10, 2012 9:50 am
Location: Switzerland
Contact:

Re: ST7735 driver

Postby Tectu » Fri Jul 19, 2013 10:50 am

Are you open to test the new driver when I include it into the repository?


~ Tectu

tucow
Posts: 1
Joined: Fri Jul 19, 2013 11:47 pm
Location: Düsseldorf, Germany
Contact:

Re: ST7735 driver

Postby tucow » Fri Jul 19, 2013 11:52 pm

Hey Tectu,

I would be open to give it a try.

User avatar
Tectu
Posts: 1226
Joined: Thu May 10, 2012 9:50 am
Location: Switzerland
Contact:

Re: ST7735 driver

Postby Tectu » Sat Jul 20, 2013 10:22 am

Moin tucow,

I was just about to add it to the repository. However, it looks like russian forgot to add a file containing some register definitions he's using. Could you please add these, russian?


~ Tectu

User avatar
russian
Posts: 284
Joined: Mon Oct 29, 2012 3:17 am
Location: Jersey City, USA
Has thanked: 2 times
Been thanked: 2 times

Re: ST7735 driver

Postby russian » Sat Jul 20, 2013 1:17 pm

Techu, what exactly seems to be missing? The command constants are defined in gdisp_lld.c

User avatar
Tectu
Posts: 1226
Joined: Thu May 10, 2012 9:50 am
Location: Switzerland
Contact:

Re: ST7735 driver

Postby Tectu » Mon Jul 22, 2013 12:07 am

Ah, that was a copy-paste fault of mine - I'm sorry.

I will implement the driver on monday. I am currently very busy - more information tomorrow.


~ Tectu


Last bumped by Tectu on Mon Jul 22, 2013 12:07 am.


Return to “LCD Driver and Graphic Framework”

Who is online

Users browsing this forum: No registered users and 1 guest