From 42d34fd421db06cb3388edd72cb7ca8d0f29feb0 Mon Sep 17 00:00:00 2001 From: inmarket Date: Sat, 9 May 2015 23:39:52 +1000 Subject: More comments for the UEXT SSD1306 SPI board file --- boards/base/Olimex-SAM7EX256-GE8/board_SSD1306.h | 212 ------------------- .../base/Olimex-SAM7EX256-GE8/board_SSD1306_i2c.h | 146 +++++++++++++ .../base/Olimex-SAM7EX256-GE8/board_SSD1306_spi.h | 226 +++++++++++++++++++++ 3 files changed, 372 insertions(+), 212 deletions(-) delete mode 100644 boards/base/Olimex-SAM7EX256-GE8/board_SSD1306.h create mode 100644 boards/base/Olimex-SAM7EX256-GE8/board_SSD1306_i2c.h create mode 100644 boards/base/Olimex-SAM7EX256-GE8/board_SSD1306_spi.h (limited to 'boards') diff --git a/boards/base/Olimex-SAM7EX256-GE8/board_SSD1306.h b/boards/base/Olimex-SAM7EX256-GE8/board_SSD1306.h deleted file mode 100644 index 137808da..00000000 --- a/boards/base/Olimex-SAM7EX256-GE8/board_SSD1306.h +++ /dev/null @@ -1,212 +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 - -#include "board_uext.h" - -// The various methods of driving the SPI interface -#define SPI_METHOD_PIO 1 -#define SPI_METHOD_AT91 2 -#define SPI_METHOD_CHIBIOS 3 // ChibiOS SPI for AT91SAM7 requires patch 7675 or higher to work correctly - -// The various methods of driving the PIO interface -#define PIO_METHOD_AT91 1 -#define PIO_METHOD_CHIBIOS 2 // ChibiOS PIO for the AT91SAM7 requires patch 7669 or higher to work correctly - -// What methods are we using in this file -#define SPI_METHOD SPI_METHOD_AT91 -#define PIO_METHOD PIO_METHOD_AT91 - -// If using SPI_METHOD_CHIBIOS or SPI_METHOD_AT91 then this must be defined for your CPU -#define SPI_CONFIG_REGISTER 0x00000801 // For AT91SAM7: 8bit, CPOL=1, NCPHA = 0, ClockPhase=0, SCLK = 48Mhz/8 = 6MHz - -//--------------------------------------------------------------------- - -#define PORT_RESET UEXT_PORT_PIN5 -#define PIN_RESET UEXT_PORTPIN_PIN5 -#define PORT_DC UEXT_PORT_PIN6 -#define PIN_DC UEXT_PORTPIN_PIN6 - -#if PIO_METHOD == PIO_METHOD_AT91 - #define PinIsOutput(port,pin) ((port)->PIO_OER = 1 << (pin), (port)->PIO_PER = 1 << (pin), (port)->PIO_MDDR = 1 << (pin), (port)->PIO_PPUDR = 1 << (pin)) - #define PinSet(port,pin) (port)->PIO_SODR = 1 << (pin) - #define PinClear(port,pin) (port)->PIO_CODR = 1 << (pin) -#elif PIO_METHOD == PIO_METHOD_CHIBIOS - #define PinIsOutput(port,pin) palSetPadMode((port), (pin), PAL_MODE_OUTPUT_PUSHPULL) - #define PinSet(port,pin) palSetPad((port), (pin)) - #define PinClear(port,pin) palClearPad((port), (pin)) -#else - #error "TLS8204 board file: Unsupported PIO method" -#endif - -#if SPI_METHOD == SPI_METHOD_PIO - - static void spi_delay(volatile unsigned long a) { while (a!=0) a--; } - - static void spi_write(uint8_t data) { - uint8_t bit; - - for(bit = 0x80; bit; bit >>= 1) { - if(data & bit) - PinSet(UEXT_SPI_MOSI_PORT, UEXT_SPI_MOSI_PORTPIN); - else - PinClear(UEXT_SPI_MOSI_PORT, UEXT_SPI_MOSI_PORTPIN); - spi_delay(1); - PinClear(UEXT_SPI_SCK_PORT, UEXT_SPI_SCK_PORTPIN); - spi_delay(1); - PinSet(UEXT_SPI_SCK_PORT, UEXT_SPI_SCK_PORTPIN); - } - } - - #define SPI_INIT() { \ - PinIsOutput (UEXT_SPI_MOSI_PORT, UEXT_SPI_MOSI_PORTPIN); \ - PinSet (UEXT_SPI_MOSI_PORT, UEXT_SPI_MOSI_PORTPIN); \ - PinIsOutput (UEXT_SPI_SCK_PORT, UEXT_SPI_SCK_PORTPIN); \ - PinSet (UEXT_SPI_SCK_PORT, UEXT_SPI_SCK_PORTPIN); \ - PinIsOutput (UEXT_SPI_CS_PORT, UEXT_SPI_CS_PORTPIN); \ - PinSet (UEXT_SPI_CS_PORT, UEXT_SPI_CS_PORTPIN); \ - } - - #define SPI_GETBUS() PinClear(UEXT_SPI_CS_PORT, UEXT_SPI_CS_PORTPIN) - #define SPI_RELEASEBUS() PinSet(UEXT_SPI_CS_PORT, UEXT_SPI_CS_PORTPIN) - #define SPI_WAITCOMPLETE() - #define SPI_WRITEBYTE(data) spi_write(data) - #define SPI_WRITEBYTES(pdata, len) while(len--) spi_write(*pdata++) - -#elif SPI_METHOD == SPI_METHOD_AT91 - - #if UEXT_SPI_SCK_PORTPIN == 22 - // Assume it is on SPI1 - #define UEXT_SPI_DEV AT91C_BASE_SPI1 - #define UEXT_SPI_ID AT91C_ID_SPI1 - #define UEXT_SPI_PORT AT91C_BASE_PIOA - #define UEXT_SPI_PERIPH PIO_BSR - #else - // Assume it is on SPI0 - #define UEXT_SPI_DEV AT91C_BASE_SPI0 - #define UEXT_SPI_ID AT91C_ID_SPI0 - #define UEXT_SPI_PORT AT91C_BASE_PIOA - #define UEXT_SPI_PERIPH PIO_ASR - #endif - - #define SPI_INIT() { \ - UEXT_SPI_PORT->PIO_MDDR = (1<PIO_PPUER = 1<PIO_PDR = (1<UEXT_SPI_PERIPH = (1<PMC_PCER = 1 << UEXT_SPI_ID; \ - UEXT_SPI_DEV->SPI_CR = 0x81; \ - UEXT_SPI_DEV->SPI_CR = 0x81; \ - UEXT_SPI_DEV->SPI_CR = 0x01; \ - UEXT_SPI_DEV->SPI_MR = 0x000E0011; \ - UEXT_SPI_DEV->SPI_CSR[0] = SPI_CONFIG_REGISTER; \ - } - - #define SPI_WAITCOMPLETE() while(!(UEXT_SPI_DEV->SPI_SR & AT91C_SPI_TXEMPTY)) - #define SPI_GETBUS() - #define SPI_RELEASEBUS() - #define SPI_WRITEBYTE(data) { \ - while(!(UEXT_SPI_DEV->SPI_SR & AT91C_SPI_TDRE)); \ - UEXT_SPI_DEV->SPI_TDR = data; \ - } - #define SPI_WRITEBYTES(pdata, len) while(len--) SPI_WRITEBYTE(*pdata++) - -#elif SPI_METHOD == SPI_METHOD_CHIBIOS - - static const SPIConfig spiconfig = { - 0, - /* HW dependent part.*/ - UEXT_SPI_CS_PORT, - UEXT_SPI_CS_PORTPIN, - SPI_CONFIG_REGISTER - }; - - #define SPI_INIT() - - #define SPI_GETBUS() { \ - spiStart(UEXT_SPI, &spiconfig); \ - spiSelect(UEXT_SPI); \ - } - - #define SPI_RELEASEBUS() { \ - spiUnselect(UEXT_SPI); \ - spiStop(UEXT_SPI); \ - } - - #define SPI_WAITCOMPLETE() - #define SPI_WRITEBYTE(data) spiSend(UEXT_SPI, 1, &data) - #define SPI_WRITEBYTES(pdata, len) spiSend(UEXT_SPI, len, pdata) - -#else - #error "TLS8204 board file: Unsupported SPI method" -#endif - -static inline void init_board(GDisplay *g) { - (void) g; - - PinIsOutput (PORT_DC, PIN_DC); - PinIsOutput (PORT_RESET, PIN_RESET); - PinSet (PORT_RESET, PIN_RESET); - - SPI_INIT(); -} - -static inline void post_init_board(GDisplay *g) { - (void) g; -} - -static inline void setpin_reset(GDisplay *g, bool_t state) { - (void) g; - (void) state; - - if (state) - PinClear(PORT_RESET, PIN_RESET); - else - PinSet(PORT_RESET, PIN_RESET); -} - -static inline void set_backlight(GDisplay *g, uint8_t percent) { - (void) g; - (void) percent; -} - -static inline void acquire_bus(GDisplay *g) { - (void) g; - - SPI_GETBUS(); -} - -static inline void release_bus(GDisplay *g) { - (void) g; - - SPI_WAITCOMPLETE(); - SPI_RELEASEBUS(); -} - -static inline void write_cmd(GDisplay *g, uint8_t cmd) { - (void) g; - - // Command mode please - SPI_WAITCOMPLETE(); - PinClear(PORT_DC, PIN_DC); - - SPI_WRITEBYTE(cmd); -} - -static inline void write_data(GDisplay *g, uint8_t* data, uint16_t length) { - (void) g; - - // Data mode please - SPI_WAITCOMPLETE(); - PinSet(PORT_DC, PIN_DC); - - SPI_WRITEBYTES(data, length); -} - -#endif /* _GDISP_LLD_BOARD_H */ diff --git a/boards/base/Olimex-SAM7EX256-GE8/board_SSD1306_i2c.h b/boards/base/Olimex-SAM7EX256-GE8/board_SSD1306_i2c.h new file mode 100644 index 00000000..0818c3a5 --- /dev/null +++ b/boards/base/Olimex-SAM7EX256-GE8/board_SSD1306_i2c.h @@ -0,0 +1,146 @@ +/* + * 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 "board_uext.h" + +/* + * NOTE: This board file is for an SSD1306 running in I2C mode + * You will need to use a different board file for an SSD1306 running in SPI mode + */ + +#define I2C_ADDRESS (0x78/2) // SSD1306 supports either 0x78 or 0x7A (including the write bit) +#define I2C_RATE 400000 // 400kHz is I2C FAST mode + +// The various methods of driving the I2C interface +#define I2C_METHOD_CHIBIOS 3 + +// The various supported CPU's +#define CPU_AT91 1 + +// What methods are we using in this file +#define I2C_METHOD I2C_METHOD_CHIBIOS +#define CPU_METHOD CPU_AT91 + +// If using SPI_METHOD_CHIBIOS the CPU specific i2cconfig structure must be defined for your CPU +#if CPU_METHOD == CPU_AT91 + #define I2C_CONFIG_REGISTER ((((MCK/I2C_RATE/2 - 3)>>8)<<16)|(((MCK/I2C_RATE/2 - 3)&0xFF)<<8)|(((MCK/I2C_RATE/2 - 3)&0xFF)<<0)) // For AT91SAM7: 8bit, CPOL=1, NCPHA = 0, ClockPhase=0, SCLK = 48Mhz/8 = 6MHz + #if I2C_METHOD == I2C_METHOD_CHIBIOS + // ChibiOS - Yuck! This structure is different on each platform. + // This is the one for the AT91 + static const I2CConfig i2cconfig = { + I2C_CONFIG_REGISTER + }; + #endif +#else + #error "SSD1306: Unsupported CPU" +#endif + + + +//--------------------------------------------------------------------- + +/* + * Pin connection for the display to the UEXT connector: + * + * DISPLAY VCC UEXT PIN 1 (3.3V) + * DISPLAY GND UEXT PIN 2 (GND) + * DISPLAY SCL UEXT PIN 5 (SCL) + * DISPLAY SDA UEXT PIN 6 (SDA) + */ + +#if I2C_METHOD == I2C_METHOD_CHIBIOS + + /* ChibiOS can't send a separate data prefix byte in the same transaction as the real data. + * Nor does it support an address prefix to the data (such as an EEPROM would use). + * Instead we tell the driver to put it into the RAM buffer at the beginning of each page (Yuck!). + * + * Prefix bytes: + * 0x40 means all following bytes in this transaction go into the GDRAM. + * 0x00 means the following byte (singular) is a command byte. + */ + #define SSD1306_PAGE_PREFIX 0x40 + + #define I2C_INIT() + + #define I2C_GETBUS() { \ + i2cAcquireBus(UEXT_I2C); \ + i2cStart(UEXT_I2C, &i2cconfig); \ + } + + #define I2C_RELEASEBUS() { \ + i2cStop(UEXT_I2C); \ + i2cReleaseBus(UEXT_I2C); \ + } + + #define I2C_WAITCOMPLETE() + #define I2C_WRITECMDBYTE(cmd) { \ + uint8_t data[2]; \ + data[0] = 0; \ + data[1] = cmd; \ + i2cMasterTransmitTimeout (UEXT_I2C, I2C_ADDRESS, data, 2, 0, 0, TIME_INFINITE); \ + } + #define I2C_WRITEBYTES(pdata, len) i2cMasterTransmitTimeout (UEXT_I2C, I2C_ADDRESS, pdata, length, 0, 0, TIME_INFINITE) + +#else + #error "SSD1306 board file: Unsupported I2C method" +#endif + +static inline void init_board(GDisplay *g) { + (void) g; + + I2C_INIT(); +} + +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 set_backlight(GDisplay *g, uint8_t percent) { + (void) g; + (void) percent; +} + +static inline void acquire_bus(GDisplay *g) { + (void) g; + + I2C_GETBUS(); +} + +static inline void release_bus(GDisplay *g) { + (void) g; + + I2C_WAITCOMPLETE(); + I2C_RELEASEBUS(); +} + +static inline void write_cmd(GDisplay *g, uint8_t cmd) { + (void) g; + + I2C_WAITCOMPLETE(); + + // Command mode please + I2C_WRITECMDBYTE(cmd); +} + +static inline void write_data(GDisplay *g, uint8_t* data, uint16_t length) { + (void) g; + + I2C_WAITCOMPLETE(); + + // Data mode please + I2C_WRITEBYTES(data, length); +} + +#endif /* _GDISP_LLD_BOARD_H */ diff --git a/boards/base/Olimex-SAM7EX256-GE8/board_SSD1306_spi.h b/boards/base/Olimex-SAM7EX256-GE8/board_SSD1306_spi.h new file mode 100644 index 00000000..3585d287 --- /dev/null +++ b/boards/base/Olimex-SAM7EX256-GE8/board_SSD1306_spi.h @@ -0,0 +1,226 @@ +/* + * 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 "board_uext.h" + +/* + * NOTE: This board file is for an SSD1306 running in SPI mode + * You will need to use a different board file for an SSD1306 running in I2C mode + */ +// The various methods of driving the SPI interface +#define SPI_METHOD_PIO 1 +#define SPI_METHOD_AT91 2 +#define SPI_METHOD_CHIBIOS 3 // ChibiOS SPI for AT91SAM7 requires patch 7675 or higher to work correctly + +// The various methods of driving the PIO interface +#define PIO_METHOD_AT91 1 +#define PIO_METHOD_CHIBIOS 2 // ChibiOS PIO for the AT91SAM7 requires patch 7669 or higher to work correctly + +// What methods are we using in this file +#define SPI_METHOD SPI_METHOD_AT91 +#define PIO_METHOD PIO_METHOD_AT91 + +// If using SPI_METHOD_CHIBIOS or SPI_METHOD_AT91 then this must be defined for your CPU +#define SPI_CONFIG_REGISTER 0x00000801 // For AT91SAM7: 8bit, CPOL=1, NCPHA = 0, ClockPhase=0, SCLK = 48Mhz/8 = 6MHz + +//--------------------------------------------------------------------- + +/* + * Pin connection for the display to the UEXT connector: + * + * DISPLAY VCC UEXT PIN 1 (3.3V) + * DISPLAY GND UEXT PIN 2 (GND) + * DISPLAY SCL UEXT PIN 9 (SCK) + * DISPLAY SDA UEXT PIN 8 (MOSI) + * DISPLAY RST UEXT PIN 5 (SCL) + * DISPLAY D/C UEXT PIN 6 (SDA) + */ +#define PORT_RESET UEXT_PORT_PIN5 +#define PIN_RESET UEXT_PORTPIN_PIN5 +#define PORT_DC UEXT_PORT_PIN6 +#define PIN_DC UEXT_PORTPIN_PIN6 + +#if PIO_METHOD == PIO_METHOD_AT91 + #define PinIsOutput(port,pin) ((port)->PIO_OER = 1 << (pin), (port)->PIO_PER = 1 << (pin), (port)->PIO_MDDR = 1 << (pin), (port)->PIO_PPUDR = 1 << (pin)) + #define PinSet(port,pin) (port)->PIO_SODR = 1 << (pin) + #define PinClear(port,pin) (port)->PIO_CODR = 1 << (pin) +#elif PIO_METHOD == PIO_METHOD_CHIBIOS + #define PinIsOutput(port,pin) palSetPadMode((port), (pin), PAL_MODE_OUTPUT_PUSHPULL) + #define PinSet(port,pin) palSetPad((port), (pin)) + #define PinClear(port,pin) palClearPad((port), (pin)) +#else + #error "SSD1306 board file: Unsupported PIO method" +#endif + +#if SPI_METHOD == SPI_METHOD_PIO + + static void spi_delay(volatile unsigned long a) { while (a!=0) a--; } + + static void spi_write(uint8_t data) { + uint8_t bit; + + for(bit = 0x80; bit; bit >>= 1) { + if(data & bit) + PinSet(UEXT_SPI_MOSI_PORT, UEXT_SPI_MOSI_PORTPIN); + else + PinClear(UEXT_SPI_MOSI_PORT, UEXT_SPI_MOSI_PORTPIN); + spi_delay(1); + PinClear(UEXT_SPI_SCK_PORT, UEXT_SPI_SCK_PORTPIN); + spi_delay(1); + PinSet(UEXT_SPI_SCK_PORT, UEXT_SPI_SCK_PORTPIN); + } + } + + #define SPI_INIT() { \ + PinIsOutput (UEXT_SPI_MOSI_PORT, UEXT_SPI_MOSI_PORTPIN); \ + PinSet (UEXT_SPI_MOSI_PORT, UEXT_SPI_MOSI_PORTPIN); \ + PinIsOutput (UEXT_SPI_SCK_PORT, UEXT_SPI_SCK_PORTPIN); \ + PinSet (UEXT_SPI_SCK_PORT, UEXT_SPI_SCK_PORTPIN); \ + PinIsOutput (UEXT_SPI_CS_PORT, UEXT_SPI_CS_PORTPIN); \ + PinSet (UEXT_SPI_CS_PORT, UEXT_SPI_CS_PORTPIN); \ + } + + #define SPI_GETBUS() PinClear(UEXT_SPI_CS_PORT, UEXT_SPI_CS_PORTPIN) + #define SPI_RELEASEBUS() PinSet(UEXT_SPI_CS_PORT, UEXT_SPI_CS_PORTPIN) + #define SPI_WAITCOMPLETE() + #define SPI_WRITEBYTE(data) spi_write(data) + #define SPI_WRITEBYTES(pdata, len) while(len--) spi_write(*pdata++) + +#elif SPI_METHOD == SPI_METHOD_AT91 + + #if UEXT_SPI_SCK_PORTPIN == 22 + // Assume it is on SPI1 + #define UEXT_SPI_DEV AT91C_BASE_SPI1 + #define UEXT_SPI_ID AT91C_ID_SPI1 + #define UEXT_SPI_PORT AT91C_BASE_PIOA + #define UEXT_SPI_PERIPH PIO_BSR + #else + // Assume it is on SPI0 + #define UEXT_SPI_DEV AT91C_BASE_SPI0 + #define UEXT_SPI_ID AT91C_ID_SPI0 + #define UEXT_SPI_PORT AT91C_BASE_PIOA + #define UEXT_SPI_PERIPH PIO_ASR + #endif + + #define SPI_INIT() { \ + UEXT_SPI_PORT->PIO_MDDR = (1<PIO_PPUER = 1<PIO_PDR = (1<UEXT_SPI_PERIPH = (1<PMC_PCER = 1 << UEXT_SPI_ID; \ + UEXT_SPI_DEV->SPI_CR = 0x81; \ + UEXT_SPI_DEV->SPI_CR = 0x81; \ + UEXT_SPI_DEV->SPI_CR = 0x01; \ + UEXT_SPI_DEV->SPI_MR = 0x000E0011; \ + UEXT_SPI_DEV->SPI_CSR[0] = SPI_CONFIG_REGISTER; \ + } + + #define SPI_WAITCOMPLETE() while(!(UEXT_SPI_DEV->SPI_SR & AT91C_SPI_TXEMPTY)) + #define SPI_GETBUS() + #define SPI_RELEASEBUS() + #define SPI_WRITEBYTE(data) { \ + while(!(UEXT_SPI_DEV->SPI_SR & AT91C_SPI_TDRE)); \ + UEXT_SPI_DEV->SPI_TDR = data; \ + } + #define SPI_WRITEBYTES(pdata, len) while(len--) SPI_WRITEBYTE(*pdata++) + +#elif SPI_METHOD == SPI_METHOD_CHIBIOS + + static const SPIConfig spiconfig = { + 0, + /* HW dependent part.*/ + UEXT_SPI_CS_PORT, + UEXT_SPI_CS_PORTPIN, + SPI_CONFIG_REGISTER + }; + + #define SPI_INIT() + + #define SPI_GETBUS() { \ + spiStart(UEXT_SPI, &spiconfig); \ + spiSelect(UEXT_SPI); \ + } + + #define SPI_RELEASEBUS() { \ + spiUnselect(UEXT_SPI); \ + spiStop(UEXT_SPI); \ + } + + #define SPI_WAITCOMPLETE() + #define SPI_WRITEBYTE(data) spiSend(UEXT_SPI, 1, &data) + #define SPI_WRITEBYTES(pdata, len) spiSend(UEXT_SPI, len, pdata) + +#else + #error "SSD1306 board file: Unsupported SPI method" +#endif + +static inline void init_board(GDisplay *g) { + (void) g; + + PinIsOutput (PORT_DC, PIN_DC); + PinIsOutput (PORT_RESET, PIN_RESET); + PinSet (PORT_RESET, PIN_RESET); + + SPI_INIT(); +} + +static inline void post_init_board(GDisplay *g) { + (void) g; +} + +static inline void setpin_reset(GDisplay *g, bool_t state) { + (void) g; + (void) state; + + if (state) + PinClear(PORT_RESET, PIN_RESET); + else + PinSet(PORT_RESET, PIN_RESET); +} + +static inline void set_backlight(GDisplay *g, uint8_t percent) { + (void) g; + (void) percent; +} + +static inline void acquire_bus(GDisplay *g) { + (void) g; + + SPI_GETBUS(); +} + +static inline void release_bus(GDisplay *g) { + (void) g; + + SPI_WAITCOMPLETE(); + SPI_RELEASEBUS(); +} + +static inline void write_cmd(GDisplay *g, uint8_t cmd) { + (void) g; + + // Command mode please + SPI_WAITCOMPLETE(); + PinClear(PORT_DC, PIN_DC); + + SPI_WRITEBYTE(cmd); +} + +static inline void write_data(GDisplay *g, uint8_t* data, uint16_t length) { + (void) g; + + // Data mode please + SPI_WAITCOMPLETE(); + PinSet(PORT_DC, PIN_DC); + + SPI_WRITEBYTES(data, length); +} + +#endif /* _GDISP_LLD_BOARD_H */ -- cgit v1.2.3