Jump to content

KS0108 driver review


JoVM

Recommended Posts

This is a rudimentary hardware driver for the KS0108 controller.


/*
* 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

#include "pal.h"

#define KS0108_PORT GPIOA

#define KS0108_RS GPIOA_PIN8
#define KS0108_RW GPIOA_PIN9
#define KS0108_EN GPIOA_PIN10

#define KS0108_CS1 GPIOA_CS1
#define KS0108_CS2 GPIOA_CS2
#define KS0108_CS3 GPIOA_CS3

#define KS0108_D0 0

#define DISPLAY_STATUS_BUSY 0x80

unsigned char screen_x;
unsigned char screen_y;

//#define KS0108_PAGE_PREFIX 0x40

//-------------------------------------------------------------------------------------------------
// Delay function /for 8MHz/
//-------------------------------------------------------------------------------------------------
static inline void GLCD_Delay(void)
{
asm("nop");asm("nop");asm("nop");asm("nop");
}
//-------------------------------------------------------------------------------------------------
// Enalbe Controller (0-2)
//-------------------------------------------------------------------------------------------------
static inline void GLCD_EnableController(unsigned char controller)
{
switch(controller){
case 0 : palClearPad(KS0108_PORT, KS0108_CS1); break;
case 1 : palClearPad(KS0108_PORT, KS0108_CS2); break;
case 2 : palClearPad(KS0108_PORT, KS0108_CS3); break;
}
}
//-------------------------------------------------------------------------------------------------
// Disable Controller (0-2)
//-------------------------------------------------------------------------------------------------
static inline void GLCD_DisableController(unsigned char controller)
{
switch(controller){
case 0 : palSetPad(KS0108_PORT, KS0108_CS1); break;
case 1 : palSetPad(KS0108_PORT, KS0108_CS2); break;
case 2 : palSetPad(KS0108_PORT, KS0108_CS3); break;
}
}

//-------------------------------------------------------------------------------------------------
// Read Status byte from specified controller (0-2)
//-------------------------------------------------------------------------------------------------
static inline uint8_t read_data(uint8_t controller)
{
uint8_t status;

palSetPadMode(KS0108_PORT, 0, PAL_MODE_INPUT_PULLUP);
palSetPadMode(KS0108_PORT, 1, PAL_MODE_INPUT_PULLUP);
palSetPadMode(KS0108_PORT, 2, PAL_MODE_INPUT_PULLUP);
palSetPadMode(KS0108_PORT, 3, PAL_MODE_INPUT_PULLUP);
palSetPadMode(KS0108_PORT, 4, PAL_MODE_INPUT_PULLUP);
palSetPadMode(KS0108_PORT, 5, PAL_MODE_INPUT_PULLUP);
palSetPadMode(KS0108_PORT, 6, PAL_MODE_INPUT_PULLUP);
palSetPadMode(KS0108_PORT, 7, PAL_MODE_INPUT_PULLUP);

palSetPad(KS0108_PORT, KS0108_RW);
palClearPad(KS0108_PORT, KS0108_RS);
GLCD_EnableController(controller);
GLCD_Delay();
palSetPad(KS0108_PORT, KS0108_EN);
GLCD_Delay();
status = ((palReadPort(KS0108_PORT) >> KS0108_D0) & 0xFF);
palClearPad(KS0108_PORT, KS0108_EN);
GLCD_DisableController(controller);
return status;
}

static inline void init_board(GDisplay *g) {
(void) g;
}

static inline void post_init_board(GDisplay *g) {
(void) g;
}

static inline void setpin_reset(GDisplay *g, bool_t state) {
(void) g;
(void) state;
}

static inline void acquire_bus(GDisplay *g) {
(void) g;
}

static inline void release_bus(GDisplay *g) {
(void) g;
}

static inline void write_cmd(GDisplay *g, uint8_t cmd, uint8_t controller) {
(void) g;
//(void) cmd;

while(read_data(controller)&DISPLAY_STATUS_BUSY);

palSetPadMode(KS0108_PORT, 0, PAL_MODE_OUTPUT_PUSHPULL);
palSetPadMode(KS0108_PORT, 1, PAL_MODE_OUTPUT_PUSHPULL);
palSetPadMode(KS0108_PORT, 2, PAL_MODE_OUTPUT_PUSHPULL);
palSetPadMode(KS0108_PORT, 3, PAL_MODE_OUTPUT_PUSHPULL);
palSetPadMode(KS0108_PORT, 4, PAL_MODE_OUTPUT_PUSHPULL);
palSetPadMode(KS0108_PORT, 5, PAL_MODE_OUTPUT_PUSHPULL);
palSetPadMode(KS0108_PORT, 6, PAL_MODE_OUTPUT_PUSHPULL);
palSetPadMode(KS0108_PORT, 7, PAL_MODE_OUTPUT_PUSHPULL);

palClearPad(KS0108_PORT, KS0108_RS | KS0108_RW);
GLCD_Delay();
GLCD_EnableController(controller);
GLCD_Delay();
palSetPad(KS0108_PORT, (cmd << KS0108_D0));
cmd ^= 0xFF;
palClearPad(KS0108_PORT, (cmd << KS0108_D0));
GLCD_Delay();
palSetPad(KS0108_PORT, KS0108_EN);
GLCD_Delay();
palClearPad(KS0108_PORT, KS0108_EN);
GLCD_Delay();
GLCD_DisableController(controller);

}

static inline void write_data(GDisplay *g, uint8_t* data, uint16_t length) {
(void) g;
(void) data;
(void) length;

while(read_data(screen_x / 64)&DISPLAY_STATUS_BUSY);

palSetPadMode(KS0108_PORT, 0, PAL_MODE_OUTPUT_PUSHPULL);
palSetPadMode(KS0108_PORT, 1, PAL_MODE_OUTPUT_PUSHPULL);
palSetPadMode(KS0108_PORT, 2, PAL_MODE_OUTPUT_PUSHPULL);
palSetPadMode(KS0108_PORT, 3, PAL_MODE_OUTPUT_PUSHPULL);
palSetPadMode(KS0108_PORT, 4, PAL_MODE_OUTPUT_PUSHPULL);
palSetPadMode(KS0108_PORT, 5, PAL_MODE_OUTPUT_PUSHPULL);
palSetPadMode(KS0108_PORT, 6, PAL_MODE_OUTPUT_PUSHPULL);
palSetPadMode(KS0108_PORT, 7, PAL_MODE_OUTPUT_PUSHPULL);

palClearPad(KS0108_PORT, KS0108_RW);
GLCD_Delay();
palSetPad(KS0108_PORT, KS0108_RS);
GLCD_Delay();
palSetPad(KS0108_PORT, (*data << KS0108_D0));
*data ^= 0xFF;
palClearPad(KS0108_PORT, (*data << KS0108_D0));
GLCD_Delay();
GLCD_EnableController(screen_x / 64);
GLCD_Delay();
palSetPad(KS0108_PORT, KS0108_EN);
GLCD_Delay();
palClearPad(KS0108_PORT, KS0108_EN);
GLCD_Delay();
GLCD_DisableController(screen_x / 64);
screen_x++;

}

#endif /* _GDISP_LLD_BOARD_H */

I do a HARDWARE_FLUSH on the data pins. read_status and enable- disablecontroller() needs to go in driver code. Please your review.

Link to comment
Share on other sites

board config file:


/*
* 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_CONFIG_H
#define _GDISP_LLD_CONFIG_H

#if GFX_USE_GDISP

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

#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_HARDWARE_FILLS TRUE

#define GDISP_LLD_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 */

Link to comment
Share on other sites

This parts can be optimized:

palSetPadMode(KS0108_PORT, 0, PAL_MODE_INPUT_PULLUP);
palSetPadMode(KS0108_PORT, 1, PAL_MODE_INPUT_PULLUP);
palSetPadMode(KS0108_PORT, 2, PAL_MODE_INPUT_PULLUP);
palSetPadMode(KS0108_PORT, 3, PAL_MODE_INPUT_PULLUP);
palSetPadMode(KS0108_PORT, 4, PAL_MODE_INPUT_PULLUP);
palSetPadMode(KS0108_PORT, 5, PAL_MODE_INPUT_PULLUP);
palSetPadMode(KS0108_PORT, 6, PAL_MODE_INPUT_PULLUP);
palSetPadMode(KS0108_PORT, 7, PAL_MODE_INPUT_PULLUP);

palSetPadMode(KS0108_PORT, 0, PAL_MODE_OUTPUT_PUSHPULL);
palSetPadMode(KS0108_PORT, 1, PAL_MODE_OUTPUT_PUSHPULL);
palSetPadMode(KS0108_PORT, 2, PAL_MODE_OUTPUT_PUSHPULL);
palSetPadMode(KS0108_PORT, 3, PAL_MODE_OUTPUT_PUSHPULL);
palSetPadMode(KS0108_PORT, 4, PAL_MODE_OUTPUT_PUSHPULL);
palSetPadMode(KS0108_PORT, 5, PAL_MODE_OUTPUT_PUSHPULL);
palSetPadMode(KS0108_PORT, 6, PAL_MODE_OUTPUT_PUSHPULL);
palSetPadMode(KS0108_PORT, 7, PAL_MODE_OUTPUT_PUSHPULL);

with:

IOBus Databus = { KS0108_PORT, (1 << 0) | (1 << 1) | (1 <<2) | (1 <<3) |        \ 
(1 << 4) | (1 << 5) | (1 << 6) | (1 << 7), 0 };
/*respectively*/
palSetBusMode(&Databus , PAL_MODE_INPUT_PULLUP);
palSetBusMode(&Databus , PAL_MODE_OUTPUT_PUSHPULL);

Link to comment
Share on other sites

Hello JoVM,

I took a look at your files and things don't seem quite right. In order to use the uGFX library you need to write a GDISP driver. The GDISP driver knows how to talk to the KS0108 controller.

The next thing you need is the board file. The board file is what your driver uses to actually talk to the display controller through the microcontroller's peripheral interface. This is what you posted in your first post.

Please have a look at some of the existing GDISP drivers. You can find them under /drivers/gdisp/. Furthermore, this article contains a few informations about the different GDISP driver models.

Don't hesitate to ask when you have some questions. We are happy to help where we can. Just have a look at the existing drivers first :)

~ Tectu

Link to comment
Share on other sites

Hi guys,

This part:

//-------------------------------------------------------------------------------------------------
// Delay function /for 8MHz/
//-------------------------------------------------------------------------------------------------
static inline void GLCD_Delay(void)
{
asm("nop");asm("nop");asm("nop");asm("nop");
}

is ofcourse obselete. This is for an AVR at 8MHz.

For the STM32F4 you could use gfxSleepMilliseconds() but I prefer to set up a gpt and use gptPolledDelay() for short delays.

Link to comment
Share on other sites

Hello JoVM,

I am very sorry for my previous stupid forum post. I was sitting in the waiting hall in the airport and I wanted to look at your drivers before I take off and loose the internet for couple of days. One should not review any code when there are only five minutes left. Please ignore it, your driver obviously uses the other GDISp driver model.

We will take a look at this and let you know.

~ Tectu

Link to comment
Share on other sites

My GLCD is broken so can't get live test. grt!

Whoops... I am happy to test it with my GLCD when I find some time. I hope that mine will work. I bought it like 5 years ago and never tested it.

I looked at the zip that you attached to your previous post and everything looks good on first glance. However, what happened in KS0108.h? :P

~ Tectu

Link to comment
Share on other sites

It would be nice if you could test the driver if you find the time. The datasheet states min 2.0V at the logic pins except RTS. I hooked my display on a BIGPIC5 board to test it but nothing shows only BL is on. At his maiden I reversed polarised the displays +5V supply. Could be it is damaged. :shock:

Me no, I'm going to order a 128x64 SPI or I2C based controller.

The KS0108.h is very minimalistic. :o:D

#define KS0108_SCREEN_WIDTH		128
#define KS0108_SCREEN_HEIGHT 64


#define DISPLAY_SET_Y 0x40
#define DISPLAY_SET_X 0xB8
#define DISPLAY_START_LINE 0xC0
#define DISPLAY_ON_CMD 0x3E
#define ON 0x01
#define OFF 0x00
#define DISPLAY_STATUS_BUSY 0x80

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...