diff --git a/boards/base/Olimex-SAM7EX256-GE12/board_Nokia6610GE12.h b/boards/base/Olimex-SAM7EX256-GE12/board_Nokia6610GE12.h index f6c73a14..f1c1c42f 100644 --- a/boards/base/Olimex-SAM7EX256-GE12/board_Nokia6610GE12.h +++ b/boards/base/Olimex-SAM7EX256-GE12/board_Nokia6610GE12.h @@ -100,9 +100,7 @@ static inline void init_board(GDisplay *g) { pPIOA->PIO_SODR = PIOA_LCD_RESET_MASK; // Set PA2 to HIGH pPIOA->PIO_OER = PIOA_LCD_RESET_MASK; // Configure PA2 as output - // CS pin - this seems to be ignored - // pPIOA->PIO_SODR = 1<<12; // Set PA2 to HIGH - // pPIOA->PIO_OER = 1<<12; // Configure PA2 as output + // CS pin - this is driven automatically by the SPI hardware itself // Init SPI0 // Disable the following pins from PIO control (will be used instead by the SPI0 peripheral) @@ -119,6 +117,7 @@ static inline void init_board(GDisplay *g) { // Fixed mode pSPI->SPI_CR = 0x81; //SPI Enable, Software reset + pSPI->SPI_CR = 0x81; //SPI Enable, Software reset - 2nd write as per errata pSPI->SPI_CR = 0x01; //SPI Enable pSPI->SPI_MR = 0xE0011; //Master mode, fixed select, disable decoder, PCS=1110 pSPI->SPI_CSR[0] = 0x01010311; //9bit, CPOL=1, ClockPhase=0, SCLK = 48Mhz/3 = 16MHz @@ -179,7 +178,7 @@ static inline void release_bus(GDisplay *g) { static inline void write_index(GDisplay *g, uint16_t index) { (void) g; // wait for the previous transfer to complete - while((pSPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0); + while(!(pSPI->SPI_SR & AT91C_SPI_TDRE)); // send the command pSPI->SPI_TDR = index & 0xFF; } @@ -187,7 +186,7 @@ static inline void write_index(GDisplay *g, uint16_t index) { static inline void write_data(GDisplay *g, uint16_t data) { (void) g; // wait for the previous transfer to complete - while((pSPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0); + while(!(pSPI->SPI_SR & AT91C_SPI_TDRE)); // send the data pSPI->SPI_TDR = data | 0x0100; } diff --git a/boards/base/Olimex-SAM7EX256-GE8/board_Nokia6610GE8.h b/boards/base/Olimex-SAM7EX256-GE8/board_Nokia6610GE8.h index aa907058..e74fe5b2 100644 --- a/boards/base/Olimex-SAM7EX256-GE8/board_Nokia6610GE8.h +++ b/boards/base/Olimex-SAM7EX256-GE8/board_Nokia6610GE8.h @@ -37,7 +37,6 @@ static volatile AT91PS_PIO pPIOA = AT91C_BASE_PIOA; static volatile AT91PS_PIO pPIOB = AT91C_BASE_PIOB; static volatile AT91PS_SPI pSPI = AT91C_BASE_SPI0; static volatile AT91PS_PMC pPMC = AT91C_BASE_PMC; -static volatile AT91PS_PDC pPDC = AT91C_BASE_PDC_SPI0; /* The PWM backlight control is non-linear on this board. * We pick values here that make it look a bit more linear. @@ -100,9 +99,7 @@ static inline void init_board(GDisplay *g) { pPIOA->PIO_SODR = PIOA_LCD_RESET_MASK; // Set PA2 to HIGH pPIOA->PIO_OER = PIOA_LCD_RESET_MASK; // Configure PA2 as output - // CS pin - this seems to be ignored - // pPIOA->PIO_SODR = 1<<12; // Set PA2 to HIGH - // pPIOA->PIO_OER = 1<<12; // Configure PA2 as output + // CS pin - this is driven automatically by the SPI hardware itself // Init SPI0 // Disable the following pins from PIO control (will be used instead by the SPI0 peripheral) @@ -112,16 +109,16 @@ static inline void init_board(GDisplay *g) { // BIT18 = PA18 -> SPI0_SPCK Serial Clock (to LCD slave) pPIOA->PIO_PDR = (1<<12) | (1<<16) | (1<<17) | (1<<18); pPIOA->PIO_ASR = (1<<12) | (1<<16) | (1<<17) | (1<<18); - pPIOA->PIO_BSR = 0; //enable the clock of SPI pPMC->PMC_PCER = 1 << AT91C_ID_SPI0; // Fixed mode pSPI->SPI_CR = 0x81; //SPI Enable, Software reset + pSPI->SPI_CR = 0x81; //SPI Enable, Software reset - 2nd write as per errata pSPI->SPI_CR = 0x01; //SPI Enable - pSPI->SPI_MR = 0xE0011; //Master mode, fixed select, disable decoder, PCS=1110 - pSPI->SPI_CSR[0] = 0x01010311; //9bit, CPOL=1, ClockPhase=0, SCLK = 48Mhz/3 = 16MHz + pSPI->SPI_MR = 0x000E0011; //Master mode, fixed select, disable decoder, PCS=1110 + pSPI->SPI_CSR[0] = 0x00000311; //9bit, CPOL=1, ClockPhase=0, SCLK = 48Mhz/3 = 16MHz /* Display backlight control at 100% */ pwmRunning = FALSE; @@ -178,16 +175,16 @@ static inline void release_bus(GDisplay *g) { static inline void write_index(GDisplay *g, uint16_t index) { (void) g; - // wait for the previous transfer to complete - while((pSPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0); + // wait for the previous transfer to start + while(!(pSPI->SPI_SR & AT91C_SPI_TDRE)); // send the command pSPI->SPI_TDR = index & 0xFF; } static inline void write_data(GDisplay *g, uint16_t data) { (void) g; - // wait for the previous transfer to complete - while((pSPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0); + // wait for the previous transfer to start + while(!(pSPI->SPI_SR & AT91C_SPI_TDRE)); // send the data pSPI->SPI_TDR = data | 0x0100; } diff --git a/boards/base/Olimex-SAM7EX256-GE8/board_TLS8204.h b/boards/base/Olimex-SAM7EX256-GE8/board_TLS8204.h index a548b832..0ec832aa 100644 --- a/boards/base/Olimex-SAM7EX256-GE8/board_TLS8204.h +++ b/boards/base/Olimex-SAM7EX256-GE8/board_TLS8204.h @@ -10,36 +10,142 @@ #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 -#define BIT_BASH TRUE // Native SPI is not working yet -#define DIRECT_IO TRUE // ChibiOS for the AT91SAM7 requires patch 7669 or higher if DIRECT_IO is FALSE -#if DIRECT_IO +#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) -#else +#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 BIT_BASH - // simple delays - void Delay(volatile unsigned long a) { while (a!=0) a--; } - void Delayc(volatile unsigned char a) { while (a!=0) a--; } -#else +#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(1000); + PinClear(UEXT_SPI_SCK_PORT, UEXT_SPI_SCK_PORTPIN); + spi_delay(1000); + 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, - 0x01010801 // For AT91SAM7: 8bit, CPOL=1, NCPHA = 0, ClockPhase=0, SCLK = 48Mhz/8 = 6MHz + 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) { @@ -49,15 +155,7 @@ static inline void init_board(GDisplay *g) { PinIsOutput (PORT_RESET, PIN_RESET); PinSet (PORT_RESET, PIN_RESET); - PinIsOutput (UEXT_SPI_CS_PORT, UEXT_SPI_CS_PORTPIN); - PinSet (UEXT_SPI_CS_PORT, UEXT_SPI_CS_PORTPIN); - - #if BIT_BASH - 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); - #endif + SPI_INIT(); } static inline void post_init_board(GDisplay *g) { @@ -82,77 +180,34 @@ static inline void set_backlight(GDisplay *g, uint8_t percent) { static inline void acquire_bus(GDisplay *g) { (void) g; - #if BIT_BASH - PinClear(UEXT_SPI_CS_PORT, UEXT_SPI_CS_PORTPIN); - #else - spiStart(UEXT_SPI, &spiconfig); - spiSelect(UEXT_SPI); - #endif + SPI_GETBUS(); } static inline void release_bus(GDisplay *g) { (void) g; - #if BIT_BASH - PinSet(UEXT_SPI_CS_PORT, UEXT_SPI_CS_PORTPIN); - #else - spiUnselect(UEXT_SPI); - spiStop(UEXT_SPI); - #endif + 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); - #if BIT_BASH - { - uint8_t bit; - - - for(bit = 0x80; bit; bit >>= 1) { - if(cmd & bit) - PinSet(UEXT_SPI_MOSI_PORT, UEXT_SPI_MOSI_PORTPIN); - else - PinClear(UEXT_SPI_MOSI_PORT, UEXT_SPI_MOSI_PORTPIN); - Delay(1); - PinClear(UEXT_SPI_SCK_PORT, UEXT_SPI_SCK_PORTPIN); - Delay(1); - PinSet(UEXT_SPI_SCK_PORT, UEXT_SPI_SCK_PORTPIN); - } - } - #else - spiStartSend(UEXT_SPI, 1, &cmd); - #endif + 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); - #if BIT_BASH - while(length--) { - 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); - Delay(1); - PinClear(UEXT_SPI_SCK_PORT, UEXT_SPI_SCK_PORTPIN); - Delay(1); - PinSet(UEXT_SPI_SCK_PORT, UEXT_SPI_SCK_PORTPIN); - } - data++; - } - #else - spiStartSend(UEXT_SPI, length, data); - #endif + SPI_WRITEBYTES(data, length); } #endif /* _GDISP_LLD_BOARD_H */