Port manipulation - LCD 8bit parallel

Working libraries, libraries being ported and related hardware
wizarcl
Posts: 12
Joined: Tue Aug 04, 2015 4:06 pm

Port manipulation - LCD 8bit parallel

Postby wizarcl » Thu Aug 06, 2015 11:51 pm

Hi everyone.
I'm trying to port Adafruit_TFTLCD library (for 8bit parallel LCD) and inside in library, control lines is controlled by macros, using port manipulation, but STM32 has a different method to make this. Using AVR, library make control using DDRA and PORTA, for example, to control port direction and values. How can I make this manipulations? Using GPIOA_BASE.CRL, GPIOA_BASE.CRH, GPIOA_BASE.IDR and GPIOA_BASE.ODR?

Follow a piece of code in pin_magic.h:

Code: Select all

   #define write8inline(d) {                          \
   PORTD = (PORTD & B00000011) | ((d) & B11111100); \
   PORTB = (PORTB & B11111100) | ((d) & B00000011); \
   WR_STROBE; }
   #define read8inline(result) {                       \
   RD_ACTIVE;                                        \
   DELAY7;                                           \
   result = (PIND & B11111100) | (PINB & B00000011); \
   RD_IDLE; }
   #define setWriteDirInline() { DDRD |=  B11111100; DDRB |=  B00000011; }
   #define setReadDirInline()  { DDRD &= ~B11111100; DDRB &= ~B00000011; }


I need change this part to work with STM32.

User avatar
RogerClark
Posts: 5465
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: Port manipulation - LCD 8bit parallel

Postby RogerClark » Fri Aug 07, 2015 12:49 am

The hardware is not that hard to control

Each port has multiple registers, but I think the ones you are interested in is the Output Data Register (ODR) (Not there are also a separate high speed register to Set bits, Reset bits)

If you look in system/libmaple/include/libmaple/gpio.h there is a function to toggle a single bit

static inline void gpio_toggle_bit(gpio_dev *dev, uint8 pin) {
dev->regs->ODR = dev->regs->ODR ^ (1U << pin);
}


So if you do

dev->regs->ODR = 0x1234

it will set whichever port to 0x1234

Note the ports are 16 bits wide, so you will need to read / mask / write to just update just 8 bits, so thinking about it, it may actually be quicker to write to the BSSR register, e.g. something like

dev->regs->BSRR = (youNum & 0x0F) | ~(yourNum & 0x0F)<<16;

You'd need to double check this code, but I think you'll probably get the idea.

The device "dev->" have defines in the code already

GPIOA, GPIOB, GPIOC etc etc


Anyway, that should give you a head start ..

wizarcl
Posts: 12
Joined: Tue Aug 04, 2015 4:06 pm

Re: Port manipulation - LCD 8bit parallel

Postby wizarcl » Fri Aug 07, 2015 3:57 pm

RogerClark wrote:
Anyway, that should give you a head start ..


Yes. You give a direction. I was looking this files in core files and I need change port directions also but, thank you so much. I'll try to port this library, test and post here.

Sorry for my bad english.

zmemw16
Posts: 974
Joined: Wed Jul 08, 2015 2:09 pm
Location: St Annes, Lancs,UK

Re: Port manipulation - LCD 8bit parallel

Postby zmemw16 » Fri Aug 07, 2015 8:02 pm

RogerClark wrote:Note the ports are 16 bits wide, so you will need to read / mask / write to just update just 8 bits, so thinking about it, it may actually be quicker to write to the BSSR register, e.g. something like

dev->regs->BSRR = (youNum & 0x0F) | ~(yourNum & 0x0F)<<16;



my braincell is overloaded and it's been a long night/day, but where do the 0x0f masks and the << 16 come from?
0xff's and << 8 are what i'd expect?

stephen

User avatar
mrburnette
Posts: 1766
Joined: Mon Apr 27, 2015 12:50 pm
Location: Greater Atlanta
Contact:

Re: Port manipulation - LCD 8bit parallel

Postby mrburnette » Fri Aug 07, 2015 8:21 pm

zmemw16 wrote:<...>
my braincell is overloaded and it's been a long night/day, but where do the 0x0f masks and the << 16 come from?
0xff's and << 8 are what i'd expect?

stephen


32-bit word, upper 16 bits and lower 16-bits

madias
Posts: 812
Joined: Mon Apr 27, 2015 11:26 am
Location: Vienna, Austria

Re: Port manipulation - LCD 8bit parallel

Postby madias » Fri Aug 07, 2015 8:25 pm

Wizarcl please refer to my st7781 TFT library. Use the search function in this forum for my Google Drive url. I've done this for a similar maybe the same library you need

wizarcl
Posts: 12
Joined: Tue Aug 04, 2015 4:06 pm

Re: Port manipulation - LCD 8bit parallel

Postby wizarcl » Sun Aug 23, 2015 3:35 pm

Hi friends... I tried to port Adafruit TFT LCD library to work with STM32 but I can't control LCD. This library control 8 bit parallel LCD's. I'm including codes for you appreciate. Changes:
In pin_magic.h:

Code: Select all

#elif defined(__STM32F1__)
   
   // Data pins is PA4 PA5 PA6 PA7 - PB12 PB13 PB14 PB15
   #define write8inline(d) { \
      GPIOA->regs->ODR = ((GPIOA->regs->ODR & 0xFF0F) | ((d << 4) & 0x00F0)); \
      GPIOB->regs->ODR = ((GPIOB->regs->ODR & 0x0FFF) | ((d << 8) & 0xF000)); \
      WR_STROBE; }

   #define read8inline(result) { \
      RD_ACTIVE;   \
      delayMicroseconds(1);      \
      result = (((GPIOA->regs->IDR & 0x00F0) >> 4) | ((GPIOB->regs->IDR & 0xF000) >> 8)); \
      RD_IDLE;}

   #define setWriteDirInline() { \
        GPIOA->regs->CRL = ((GPIOA->regs->CRL &= 0xFFFF) | 0x33330000);   \
        GPIOB->regs->CRH = ((GPIOB->regs->CRH &= 0xFFFF) | 0x33330000);   \
      }
   
   #define setReadDirInline() { \
        GPIOA->regs->CRL = ((GPIOA->regs->CRL &= 0xFFFF) | 0x44440000);   \
        GPIOB->regs->CRH = ((GPIOB->regs->CRH &= 0xFFFF) | 0x44440000);   \
      }
      
   // When using the TFT breakout board, control pins are configurable.
   #define RD_ACTIVE   rdPort->regs->BRR  |= rdPinSet      //PIO_Clear(rdPort, rdPinSet)
   #define RD_IDLE      rdPort->regs->BSRR |= rdPinSet      //PIO_Set(rdPort, rdPinSet)   
   #define WR_ACTIVE   wrPort->regs->BRR  |= wrPinSet      //PIO_Clear(wrPort, wrPinSet)
   #define WR_IDLE      wrPort->regs->BSRR |= wrPinSet      //PIO_Set(wrPort, wrPinSet)
   #define CD_COMMAND   cdPort->regs->BRR  |= cdPinSet      //PIO_Clear(cdPort, cdPinSet)
   #define CD_DATA      cdPort->regs->BSRR |= cdPinSet      //PIO_Set(cdPort, cdPinSet)
   #define CS_ACTIVE   csPort->regs->BRR  |= csPinSet      //PIO_Clear(csPort, csPinSet)
   #define CS_IDLE      csPort->regs->BSRR |= csPinSet      //PIO_Set(csPort, csPinSet)

   
   // As part of the inline control, macros reference other macros...if any
   // of these are left undefined, an equivalent function version (non-inline)
   // is declared later.  The Uno has a moderate amount of program space, so
   // only write8() is inlined -- that one provides the most performance
   // benefit, but unfortunately also generates the most bloat.  This is
   // why only certain cases are inlined for each board.
   #define write8 write8inline
   
   
#else


In Adafruit-TFTLCD.h

Code: Select all

  #if defined(__STM32F1__)
    gpio_dev       *csPort    , *cdPort    , *wrPort    , *rdPort;
   uint32_t          csPinSet  ,  cdPinSet  ,  wrPinSet  ,  rdPinSet  ,
                 csPinUnset,  cdPinUnset,  wrPinUnset,  rdPinUnset,
                 _reset;
  #endif


In Adafruit-TFTLCD.cpp

Code: Select all

#if defined(__STM32F1__)
   #include <wirish_types.h>
   #define PROGMEM __FLASH__
    #define pgm_read_byte(addr) (*(const unsigned char *)(addr))
    #define pgm_read_word(addr) (*(const unsigned short *)(addr))   
#endif

Code: Select all

      #if defined(__STM32F1__)
         csPort     = digitalPinToPort(cs);
         cdPort     = digitalPinToPort(cd);
         wrPort     = digitalPinToPort(wr);
         rdPort     = digitalPinToPort(rd);
         csPort->regs->ODR  |=  csPinSet; // Set all control bits to HIGH (idle)
         cdPort->regs->ODR  |=  cdPinSet; // Signals are ACTIVE LOW
         wrPort->regs->ODR  |=  wrPinSet;
         rdPort->regs->ODR  |=  rdPinSet;         
      #endif   
      


Sketch:

Code: Select all

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_TFTLCD.h> // Hardware-specific library

#define LCD_CS PA0         // Chip Select
#define LCD_CD PA1         // Command/Data
#define LCD_WR PA2          // LCD Write
#define LCD_RD PA3          // LCD Read
#define LCD_RESET PC15               // Reset

// Assign human-readable names to some common 16-bit color values:
#define   BLACK   0x0000
#define   BLUE    0x001F
#define   RED     0xF800
#define   GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF

Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);

void setup(void) {
  Serial.begin(9600);
  Serial.println("TFT LCD test");
//  pinMode(PC13, OUTPUT); // I don't know why, but when I set PC13 to OUTPUT, LED is turned on (ok),  but micro-controller stop running.
  digitalWrite(PC13, HIGH);
  delay(1000);
  digitalWrite(PC13, LOW);
  delay(1000);
  digitalWrite(PC13, HIGH);
  delay(1000); 
 
#ifdef USE_ADAFRUIT_SHIELD_PINOUT
  Serial.println("Using Adafruit 2.8\" TFT Arduino Shield Pinout");
#else
  Serial.println("Using Adafruit 2.8\" TFT Breakout Board Pinout");
#endif
  digitalWrite(PC13, LOW);
  delay(1000);
  Serial.print("TFT size is "); Serial.print(tft.width()); Serial.print("x"); Serial.println(tft.height());

  tft.reset();
  digitalWrite(PC13, HIGH);
  delay(1000);
 
  digitalWrite(PC13, LOW);
  delay(1000);

  //tft.begin(identifier);
  tft.begin();

  Serial.println("Benchmark                Time (microseconds)");

  Serial.print("Screen fill              ");
  Serial.println(testFillScreen());
  delay(500);
}

void loop(void) {
  digitalWrite(PC13, HIGH);
  for(uint8_t rotation=0; rotation<4; rotation++) {
    tft.setRotation(rotation);
    testFillScreen();
    delay(2000);
  }
  digitalWrite(PC13, LOW);
  delay(1000);
}

unsigned long testFillScreen() {
  unsigned long start = micros();
  tft.fillScreen(BLACK);
  tft.fillScreen(RED);
  tft.fillScreen(GREEN);
  tft.fillScreen(BLUE);
  tft.fillScreen(BLACK);
  return micros() - start;
}

I don't know why, but when I set PC13 to OUTPUT, LED is turned on (ok), but micro-controller stop running.


Can anyone help me?
Attachments
Adafruit-TFTLCD-Modified.rar
(135.6 KiB) Downloaded 122 times
Adafruit-TFTLCD-Original.rar
(138.45 KiB) Downloaded 70 times

madias
Posts: 812
Joined: Mon Apr 27, 2015 11:26 am
Location: Vienna, Austria

Re: Port manipulation - LCD 8bit parallel

Postby madias » Sun Aug 23, 2015 7:53 pm

...and what is connected to PC13?
If it's the backlight than connect it to VCC, the STM32 cannot give enough power for driving the backlight for the LCD via a single pin without additional hardware.

wizarcl
Posts: 12
Joined: Tue Aug 04, 2015 4:06 pm

Re: Port manipulation - LCD 8bit parallel

Postby wizarcl » Sun Aug 23, 2015 9:36 pm

madias wrote:...and what is connected to PC13?
If it's the backlight than connect it to VCC, the STM32 cannot give enough power for driving the backlight for the LCD via a single pin without additional hardware.

PC13 is conected in LED on STM board, just to test. LCD power supply is provide USB 5V power, like STM.

User avatar
RogerClark
Posts: 5465
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: Port manipulation - LCD 8bit parallel

Postby RogerClark » Mon Aug 24, 2015 3:45 am

Do you mean you are powering the whole LCD from 5V, e.g. including the chips etc

This is likely to cause problems, because the STM32 is a 3.3V device not 5V device.

I recommend you power the LCD from 3.3V


Return to “Libraries & Hardware”

Who is online

Users browsing this forum: No registered users and 2 guests