Attempting to get SSD1963 working with a Nucleo-F767ZI (144)

Working libraries, libraries being ported and related hardware
RGarrett93
Posts: 8
Joined: Thu Jan 28, 2021 3:36 pm
Answers: 1

Attempting to get SSD1963 working with a Nucleo-F767ZI (144)

Post by RGarrett93 »

I've created a pull request on github for modifying the GxTFT IO class for Nucleo_144.
https://github.com/RGarrett93/GxTFT/pull/1

Using ZinggJM library GxTFT on a F4 using FSMC, I managed to run LVGL with a 7" SSD1963 display.
https://github.com/ZinggJM/GxTFT

I now want to attempt to getting the display working with STM32F767 due to its flash memory and SRAM, my current program fits on the F407 but is now at 90% capacity and will only get bigger.

Am I calling the correct pins in the registers?
For instance setting PA5 as an output would be GPIOA->BSRR = 0b0000000000100000

I have attempted using the same pinouts on the nucleo 144 as the F4 that works with bitbashing, removed the SB5 & SB6 so I can use pin PD8 & PD9 and then used the library that works with the F4 but it is just a blank screen, so I am wondering whether it could be a timing issue.

With the below code I am wiring the tft as follows

Code: Select all


  // TFT connector to Nucleo 144 pins
  // D0   D1   D2   D3   D4   D5   D6  D7   D8   D9  D10  D11 D12 D13 D14 D15
  // PG9 PG14 PF15 PE13 PF14 PE11 PE9 PF13 PF12 PD15 PD14 PA7 PA6 PA5 PB9 PB8


Any help/ direction would be appreciated; once the code is neaten up I will post my configuration for getting LVGL on the F4 board and hopefully with the Nucleo 144.

Image


Code: Select all

//Using ZinggJM/GxTFT library and adding GxIO for STM32 Nucleo 144
//The below doesn't work, currently experimenting with a Nucleo 144 & SSD1963 Display
//For now currently attempting to use the exposed pins on the board CN10 for Data and CN9 for Ctrl 

#include "Nucleo_144.h"


#define PA_USED_BITS 0x00E8
#define PB_USED_BITS 0x0300
#define PC_USED_BITS 0x0008
#define PD_USED_BITS 0xC000
#define PE_USED_BITS 0x2A00
#define PF_USED_BITS 0xF428
#define PG_USED_BITS 0x4200

#define PA_DATA_BITS 0x00E8
#define PB_DATA_BITS 0x0300
#define PC_DATA_BITS 0x0008
#define PD_DATA_BITS 0xC000
#define PE_DATA_BITS 0x2A00
#define PF_DATA_BITS 0xF428
#define PG_DATA_BITS 0x4200

#define PA_MODE_MASK 0x0000FCC0 // all used bits
#define PA_MODE_BITS 0x00005440 // 01 : general purpose output mode
#define PB_MODE_MASK 0x000F0000 // all used bits
#define PB_MODE_BITS 0x00050000 // 01 : general purpose output mode
#define PC_MODE_MASK 0x000000C3 // all used bits
#define PC_MODE_BITS 0x00000041 // 01 : general purpose output mode
#define PD_MODE_MASK 0xF0000000 // all used bits
#define PD_MODE_BITS 0x50000000 // 01 : general purpose output mode
#define PE_MODE_MASK 0x0CCC0000 // all used bits
#define PE_MODE_BITS 0x04440000 // 01 : general purpose output mode
#define PF_MODE_MASK 0xFF300CC0 // all used bits
#define PF_MODE_BITS 0x55100440 // 01 : general purpose output mode
#define PG_MODE_MASK 0x300C0000 // all used bits
#define PG_MODE_BITS 0x10040000 // 01 : general purpose output mode

#define PA_MODE_DATA 0x0000FC00 // all data bits
#define PA_MODE_OUTP 0x00005400 // 01 : general purpose output mode
#define PA_MODE_INP  0x00000000 // 00 : input floating mode
#define PB_MODE_DATA 0x000F0000 // all data bits
#define PB_MODE_OUTP 0x00050000 // 01 : general purpose output mode
#define PB_MODE_INP  0x00000000 // 00 : input floating mode
#define PD_MODE_DATA 0xF0000000 // all data bits
#define PD_MODE_OUTP 0x50000000 // 01 : general purpose output mode
#define PD_MODE_INP  0x00000000 // 00 : input floating mode
#define PE_MODE_DATA 0x0CCC0000 // all data bits
#define PE_MODE_OUTP 0x04440000 // 01 : general purpose output mode
#define PE_MODE_INP  0x00000000 // 00 : input floating mode
#define PF_MODE_DATA 0xFF000000 // all data bits
#define PF_MODE_OUTP 0x55000000 // 01 : general purpose output mode
#define PF_MODE_INP  0x00000000 // 00 : input floating mode
#define PG_MODE_DATA 0x300C0000 // all data bits
#define PG_MODE_OUTP 0x10040000 // 01 : general purpose output mode
#define PG_MODE_INP  0x00000000 // 00 : input floating mode

Nucleo_144::Nucleo_144(bool bl_active_high)
{
  _cs   = PA3;
  _rs   = PF3;
  _rst  = 0; // not available, driven from NRST
  _wr   = PC3;
  _rd   = PC0;
  _bl   = PB1;
  _bl_active_high = bl_active_high;
}

void Nucleo_144::reset()
{
  // _rst pin not available
}

void Nucleo_144::init()
{
  RCC->AHB1ENR |= 0x0000007F; // enable A, B, C, D, E, F, G clock speed
  READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOAEN); // delay after an RCC peripheral clock enabling
  READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOBEN); // delay after an RCC peripheral clock enabling
  READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN); // delay after an RCC peripheral clock enabling
  READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIODEN); // delay after an RCC peripheral clock enabling
  READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOEEN); // delay after an RCC peripheral clock enabling
  READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOFEN); // delay after an RCC peripheral clock enabling
  READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOGEN); // delay after an RCC peripheral clock enabling

  GPIOA->BSRR |= PA_USED_BITS; // preset all output high
  GPIOA->MODER &= ~PA_MODE_MASK;
  GPIOA->MODER |= PA_MODE_BITS;
  GPIOA->OTYPER &= ~PA_USED_BITS; // 0 : output push-pull //PA_USED_BITS
  GPIOA->OSPEEDR &= ~0x00; // 0 : low speed //PA_MODE_MASK
  GPIOA->PUPDR &= ~PA_MODE_MASK; // 0 : no pull-up, no pull-down //PA_MODE_MASK

  GPIOB->BSRR |= PB_USED_BITS; // preset all output high
  GPIOB->MODER &= ~PB_MODE_MASK;
  GPIOB->MODER |= PB_MODE_BITS;
  GPIOB->OTYPER &= ~PB_USED_BITS; // 0 : output push-pull
  GPIOB->OSPEEDR &= ~0x00; // 0 : low speed
  GPIOB->PUPDR &= ~PB_MODE_MASK; // 0 : no pull-up, no pull-down

  GPIOC->BSRR |= PC_USED_BITS; // preset all output high
  GPIOC->MODER &= ~PC_MODE_MASK;
  GPIOC->MODER |= PC_MODE_BITS;
  GPIOC->OTYPER &= ~PC_USED_BITS; // 0 : output push-pull
  GPIOC->OSPEEDR &= ~0x00; // 0 : low speed
  GPIOC->PUPDR &= ~PC_MODE_MASK; // 0 : no pull-up, no pull-down

  GPIOD->BSRR |= PD_USED_BITS; // preset all output high
  GPIOD->MODER &= ~PD_MODE_MASK;
  GPIOD->MODER |= PD_MODE_BITS;
  GPIOD->OTYPER &= ~PD_USED_BITS; // 0 : output push-pull
  GPIOD->OSPEEDR &= ~0x00; // 0 : low speed
  GPIOD->PUPDR &= ~PD_MODE_MASK; // 0 : no pull-up, no pull-down

  GPIOE->BSRR |= PE_USED_BITS; // preset all output high
  GPIOE->MODER &= ~PE_MODE_MASK;
  GPIOE->MODER |= PE_MODE_BITS;
  GPIOE->OTYPER &= ~PE_USED_BITS; // 0 : output push-pull
  GPIOE->OSPEEDR &= ~0x00; // 0 : low speed
  GPIOE->PUPDR &= ~PE_MODE_MASK; // 0 : no pull-up, no pull-down

  GPIOF->BSRR |= PF_USED_BITS; // preset all output high
  GPIOF->MODER &= ~PF_MODE_MASK;
  GPIOF->MODER |= PF_MODE_BITS;
  GPIOF->OTYPER &= ~PF_USED_BITS; // 0 : output push-pull
  GPIOF->OSPEEDR &= ~0x00; // 0 : low speed
  GPIOF->PUPDR &= ~PF_MODE_MASK; // 0 : no pull-up, no pull-down

  GPIOG->BSRR |= PG_USED_BITS; // preset all output high
  GPIOG->MODER &= ~PG_MODE_MASK;
  GPIOG->MODER |= PG_MODE_BITS;
  GPIOG->OTYPER &= ~PG_USED_BITS; // 0 : output push-pull
  GPIOG->OSPEEDR &= ~0x00; // 0 : low speed
  GPIOG->PUPDR &= ~PG_MODE_MASK; // 0 : no pull-up, no pull-down

  
  pinMode(_cs, OUTPUT);
  digitalWrite(_cs, HIGH);
  pinMode(_rs, OUTPUT);
  digitalWrite(_rs, HIGH);
  pinMode(_bl, OUTPUT);
  digitalWrite(_bl, LOW);
  reset();
}

uint8_t Nucleo_144::readDataTransaction()
{
  return readData16Transaction();
}

uint16_t Nucleo_144::readData16Transaction()
{
  GPIOA->BSRR = (0x1 << (3 + 16));  // PA3 CS low
  uint16_t rv = readData16();
  GPIOA->BSRR = (0x1 << 3);  // PA3 CS high
  return rv;
}

uint8_t Nucleo_144::readData()
{
  return readData16();
}

uint16_t Nucleo_144::readData16()
{
  // Set direction input
  GPIOA->MODER &= ~PD_MODE_DATA;
  GPIOB->MODER &= ~PD_MODE_DATA;
  GPIOD->MODER &= ~PD_MODE_DATA;
  GPIOE->MODER &= ~PD_MODE_DATA;
  GPIOF->MODER &= ~PE_MODE_DATA;
  GPIOG->MODER &= ~PD_MODE_DATA;
//  GPIOD->BSRR = (0x1 << (4 + 16));  // PC0 RD low pulse
//  GPIOD->BSRR = (0x1 << 4); // PC0 RD high
  GPIOC->BSRR = (0x1 << (0 + 16));  // PC0 RD low read
  GPIOC->BSRR = (0x1 << (0 + 16));  // PC0 RD low read
  GPIOC->BSRR = (0x1 << (0 + 16));  // PC0 RD low read
  GPIOC->BSRR = (0x1 << (0 + 16));  // PC0 RD low read
  GPIOC->BSRR = (0x1 << (0 + 16));  // PC0 RD low read
  GPIOC->BSRR = (0x1 << (0 + 16));  // PC0 RD low read
  GPIOC->BSRR = (0x1 << (0 + 16));  // PC0 RD low read
  GPIOC->BSRR = (0x1 << (0 + 16));  // PC0 RD low read
/*GPIOC->BSRR = 0b0000000000000001 << 16;
GPIOC->BSRR = 0b0000000000000001 << 16;
GPIOC->BSRR = 0b0000000000000001 << 16;
GPIOC->BSRR = 0b0000000000000001 << 16;
GPIOC->BSRR = 0b0000000000000001 << 16;
GPIOC->BSRR = 0b0000000000000001 << 16;
GPIOC->BSRR = 0b0000000000000001 << 16;*/
  uint16_t rv = 0;
  // The compiler efficiently codes this  so it is quite quick.
  rv |= (GPIOB->IDR & (0x1 << 8)) << (15 - 8); // PB8
  rv |= (GPIOB->IDR & (0x1 << 9)) << (14 - 9); // PB9
  rv |= (GPIOA->IDR & (0x1 << 5)) << (13 - 5); // PA5
  rv |= (GPIOA->IDR & (0x1 << 6)) << (12 - 6); // PA6
  rv |= (GPIOA->IDR & (0x1 << 7)) << (11 - 7); // PA7
  rv |= (GPIOD->IDR & (0x1 << 14)) >> -(10 - 14); // PD14
  rv |= (GPIOD->IDR & (0x1 << 15)) >> -(9 - 15); // PD15
  rv |= (GPIOF->IDR & (0x1 << 12)) >> -(8 - 12); // PF12
  rv |= (GPIOF->IDR & (0x1 << 13)) >> -(7 - 13); // PF13
  rv |= (GPIOE->IDR & (0x1 << 9)) >> -(6 - 9); // PE9
  rv |= (GPIOE->IDR & (0x1 << 11)) >> -(5 - 11); // PE11
  rv |= (GPIOF->IDR & (0x1 << 14)) >> -(4 - 14); // PF14
  rv |= (GPIOE->IDR & (0x1 << 13)) >> -(3 - 13); // PE13
  rv |= (GPIOF->IDR & (0x1 << 15)) >> -(2 - 15); // PF15
  rv |= (GPIOG->IDR & (0x1 << 14)) >> -(1 - 14); // PG14
  rv |= (GPIOG->IDR & (0x1 << 9)) >> -(0 - 9); // PG9
  GPIOC->BSRR = (0x1 << 0); // PC0 RD high
  // Set direction output again
  GPIOA->MODER &= ~PA_MODE_DATA;
  GPIOA->MODER |= PA_MODE_OUTP;
  GPIOB->MODER &= ~PB_MODE_DATA;
  GPIOB->MODER |= PB_MODE_OUTP;
  GPIOD->MODER &= ~PD_MODE_DATA;
  GPIOD->MODER |= PD_MODE_OUTP;
  GPIOE->MODER &= ~PE_MODE_DATA;
  GPIOE->MODER |= PE_MODE_OUTP;
  GPIOF->MODER &= ~PF_MODE_DATA;
  GPIOF->MODER |= PF_MODE_OUTP;
  GPIOG->MODER &= ~PG_MODE_DATA;
  GPIOG->MODER |= PG_MODE_OUTP;
  return rv;
}
/*
uint32_t Nucleo_144::readRawData32(uint8_t part)
{
  // Set direction input
  GPIOD->MODER &= ~PD_MODE_DATA;
  GPIOE->MODER &= ~PE_MODE_DATA;
  GPIOC->BSRR = (0x1 << (0 + 16));  // PC0 RD low pulse
  GPIOC->BSRR = (0x1 << 0); // PC0 RD high
  GPIOC->BSRR = (0x1 << (0 + 16));  // PC0 RD low read
  uint32_t rv = 0;
  if (part == 0) rv = GPIOD->IDR & PD_DATA_BITS;
  if (part == 1) rv = GPIOE->IDR & PE_DATA_BITS;
  GPIOD->BSRR = (0x1 << 4); // PC0 RD high
  // Set direction output again
  GPIOD->MODER &= ~PD_MODE_DATA;
  GPIOD->MODER |= PD_MODE_OUTP;
  GPIOE->MODER &= ~PD_MODE_DATA;
  GPIOE->MODER |= PE_MODE_OUTP;
  return rv;
}
*/
void Nucleo_144::writeCommandTransaction(uint8_t c)
{
  GPIOA->BSRR = (0x1 << (3 + 16));  // PA3 CS low
  GPIOF->BSRR = (0x1 << (3 + 16));  // PF3 RS low
  writeData16(c);
  GPIOF->BSRR = (0x1 << 3);  // PF3 RS high
  GPIOA->BSRR = (0x1 << 3);  // PA3 CS high
}

void Nucleo_144::writeCommand16Transaction(uint16_t c)
{
  GPIOA->BSRR = (0x1 << (3 + 16));  // PA3 CS low
  GPIOF->BSRR = (0x1 << (3 + 16));  // PF3 RS low
  writeData16(c);
  GPIOF->BSRR = (0x1 << 3);  // PF3 RS high
  GPIOA->BSRR = (0x1 << 3);  // PA3 CS high
}

void Nucleo_144::writeDataTransaction(uint8_t d)
{
  GPIOA->BSRR = (0x1 << (3 + 16));  // PA3 CS low
  writeData16(d);
  GPIOA->BSRR = (0x1 << 3);  // PA3 CS high
}

void Nucleo_144::writeData16Transaction(uint16_t d, uint32_t num)
{
 // GPIOA->BSRR = (0x1 << (3 + 16));  // PA3 CS low
 digitalWrite(PA3, LOW);
  writeData16(d, num);
  digitalWrite(PA3, HIGH); 
  //GPIOA->BSRR = (0x1 << 3);  // PA3 CS high
}

void Nucleo_144::writeCommand(uint8_t c)
{
  GPIOF->BSRR = (0x1 << (3 + 16));  // PF3 RS low
  writeData16(c);
  GPIOF->BSRR = (0x1 << 3);  // PF3 RS high
}

void Nucleo_144::writeCommand16(uint16_t c)
{
  GPIOF->BSRR = (0x1 << (3 + 16));  // PF3 RS low
  writeData16(c);
  GPIOF->BSRR = (0x1 << 3);  // PF3 RS high
}

void Nucleo_144::writeData(uint8_t d)
{
  writeData16(d);
}

void Nucleo_144::writeData(uint8_t* d, uint32_t num)
{
  while (num > 0)
  {
    writeData16(*d);
    d++;
    num--;
  }
}

void Nucleo_144::writeData16(uint16_t d, uint32_t num)
{
  GPIOA->BSRR = PA_DATA_BITS << 16; // clear bits
  GPIOB->BSRR = PB_DATA_BITS << 16; // clear bits
  //GPIOC->BSRR = PC_DATA_BITS << 16; // clear bits
  GPIOD->BSRR = PD_DATA_BITS << 16; // clear bits
  GPIOE->BSRR = PE_DATA_BITS << 16; // clear bits
  GPIOF->BSRR = PF_DATA_BITS << 16; // clear bits
  GPIOG->BSRR = PG_DATA_BITS << 16; // clear bits

  // TFT connector to Nucleo 144 pins
  // D0   D1   D2   D3   D4   D5   D6  D7   D8   D9  D10  D11 D12 D13 D14 D15
  // PG9 PG14 PF15 PE13 PF14 PE11 PE9 PF13 PF12 PD15 PD14 PA7 PA6 PA5 PB9 PB8

  // The compiler efficiently codes this  so it is quite quick.
 
  if (d & 0x8000) GPIOB->BSRR = 0x1 << 8; // PB8
  if (d & 0x4000) GPIOB->BSRR = 0x1 << 9; // PB9
  if (d & 0x2000) GPIOA->BSRR = 0x1 << 5; // PA5
  if (d & 0x1000) GPIOA->BSRR = 0x1 << 6; // PA6
  if (d & 0x0800) GPIOA->BSRR = 0x1 << 7; // PA7
  if (d & 0x0400) GPIOD->BSRR = 0x1 << 14; // PD14
  if (d & 0x0200) GPIOD->BSRR = 0x1 << 15; // PD15
  if (d & 0x0100) GPIOF->BSRR = 0x1 << 12; // PF12

  if (d & 0x0080) GPIOF->BSRR = 0x1 << 13; // PF13
  if (d & 0x0040) GPIOE->BSRR = 0x1 << 9; // PE9
  if (d & 0x0020) GPIOE->BSRR = 0x1 << 11; // PE11
  if (d & 0x0010) GPIOF->BSRR = 0x1 << 14; // PF14
  if (d & 0x0008) GPIOE->BSRR = 0x1 << 13; // PE13
  if (d & 0x0004) GPIOF->BSRR = 0x1 << 15; // PF15
  if (d & 0x0002) GPIOG->BSRR = 0x1 << 14; // PG14
  if (d & 0x0001) GPIOG->BSRR = 0x1 << 9; // PG9
///////////////////////////////////////////////////////////
/*
  if (d & 0x8000) GPIOG->BSRR = 0x1 << 9; // PB8
  if (d & 0x4000) GPIOG->BSRR = 0x1 << 14; // PB9
  if (d & 0x2000) GPIOF->BSRR = 0x1 << 15;// PA5
  if (d & 0x1000) GPIOE->BSRR = 0x1 << 13;// PA6
  if (d & 0x0800) GPIOF->BSRR = 0x1 << 14; // PA7
  if (d & 0x0400) GPIOE->BSRR = 0x1 << 11; // PD14
  if (d & 0x0200) GPIOE->BSRR = 0x1 << 9; // PD15
  if (d & 0x0100) GPIOF->BSRR = 0x1 << 13; // PF12

  if (d & 0x0080) GPIOF->BSRR = 0x1 << 12; // PF13
  if (d & 0x0040) GPIOD->BSRR = 0x1 << 15; // PE9
  if (d & 0x0020) GPIOD->BSRR = 0x1 << 14; // PE11
  if (d & 0x0010) GPIOA->BSRR = 0x1 << 7; // PF14
  if (d & 0x0008) GPIOA->BSRR = 0x1 << 6; // PE13
  if (d & 0x0004) GPIOA->BSRR = 0x1 << 5; // PF15
  if (d & 0x0002) GPIOB->BSRR = 0x1 << 9; // PG14
  if (d & 0x0001) GPIOB->BSRR = 0x1 << 8; // PG9
*/
  while (num)
  {
    /*
    GPIOC->BSRR = (0x1 << (3 + 16));  // PC3 WR low
    GPIOC->BSRR = (0x1 << (3 + 16));  // PC3 WR low
    GPIOC->BSRR = (0x1 << (3 + 16));  // PC3 WR low
    GPIOC->BSRR = (0x1 << (3 + 16));  // PC3 WR low
    GPIOC->BSRR = (0x1 << 3); // PC3 WR high
    */
    digitalWrite(_wr, LOW);
    digitalWrite(_wr, LOW);
    digitalWrite(_wr, LOW);
    digitalWrite(_wr, LOW);
    digitalWrite(_wr, HIGH);
    num--;
  }
}

void Nucleo_144::writeAddrMSBfirst(uint16_t d)
{
  writeData16(d >> 8);
  writeData16(d & 0xFF);
}

void Nucleo_144::startTransaction()
{
  GPIOA->BSRR = (0x1 << (3 + 16));  // PA3 CS low
}

void Nucleo_144::endTransaction()
{
  GPIOA->BSRR = (0x1 << 3);  // PA3 CS high
}

void Nucleo_144::selectRegister(bool rs_low)
{
  digitalWrite(_rs, (rs_low ? LOW : HIGH));
}

void Nucleo_144::setBackLight(bool lit)
{
  digitalWrite(_bl, (lit == _bl_active_high));
}

by RGarrett93 » Fri Feb 19, 2021 8:17 am
Hi all,

Jean-Marc the author of the library for GxTFT has been very helpful and corrected the timing and managed to get FMC to work with the Nucleo 144, including changing the FMC address region to bypass DCache

GxTFT discussion

Version 2.1.3 of library GxTFT is available.

- added FSMC/FMC support for my Nucleo-144 proto board with FSMC/FMC TFT connector
- supported by class GxIO_STM32Nucleo144_FSMC using FMC for F767ZI and F746ZG
- tested with 3.2" ILI9341 on F767ZI

The performance is great with minimal screen tearing, I was really impressed with how much ICache & DCache optimises it all

I've attached a video of the Nucleo 144 in action with a SSD1963 7" Display running LVGL demo widget
Nucleo 144 FMC LVGL Demo Widget
Go to full post
User avatar
fpiSTM
Posts: 1723
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 91
Location: Le Mans
Contact:

Re: Attempting to get SSD1963 working with a Nucleo-F767ZI (144)

Post by fpiSTM »

As a first test, I would disable the Dcache and Icache.
They are enabled by default:

Code: Select all

#if (__CORTEX_M == 0x07U)
  // Defined in CMSIS core_cm7.h
#ifndef I_CACHE_DISABLED
  SCB_EnableICache();
#endif
#ifndef D_CACHE_DISABLED
  SCB_EnableDCache();
#endif
#endif
Define the D_CACHE_DISABLED and I_CACHE_DISABLED in a build_opt.h file:
https://github.com/stm32duino/wiki/wiki ... ld-options
RGarrett93
Posts: 8
Joined: Thu Jan 28, 2021 3:36 pm
Answers: 1

Re: Attempting to get SSD1963 working with a Nucleo-F767ZI (144)

Post by RGarrett93 »

Thanks, how would I go about implementing that with PlatformIO IDE.

I created build_opt.h as per
https://github.com/stm32duino/wiki/wiki ... ld-options
and placed it in in the root of src but it doesn't look like it is disabling Dcache and Icache in (core_cm7.h)

I am not sure whether build_opt.h is being detected when compiled.

@file build_opt.h

Code: Select all

/**
 * @file build_opt.h
 *
 */
/*
Read command-line options from file. The options read are inserted in place of the original @file option.
If file does not exist, or cannot be read, then the option will be treated literally, and not removed.

Options in file are separated by whitespace. A whitespace character may be included in an option
by surrounding the entire option in either single or double quotes. Any character (including a backslash)
may be included by prefixing the character to be included with a backslash. The file may itself contain
additional @file options; any such options will be processed recursively.
*/

#define I_CACHE_DISABLED
#define D_CACHE_DISABLED

User avatar
fpiSTM
Posts: 1723
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 91
Location: Le Mans
Contact:

Re: Attempting to get SSD1963 working with a Nucleo-F767ZI (144)

Post by fpiSTM »

The build_opt.h file format is not liek an header file. It is inline defintion:

Code: Select all

-DI_CACHE_DISABLED -DD_CACHE_DISABLED
Anyway with PIO I don't know how this feature is handled. Maybe simply define those definition in your json.
RGarrett93
Posts: 8
Joined: Thu Jan 28, 2021 3:36 pm
Answers: 1

Re: Attempting to get SSD1963 working with a Nucleo-F767ZI (144)

Post by RGarrett93 »

Oh sorry, misunderstood the build_opt.h.

I will give it a go with the JSON as noticed "HAL_UART_MODULE_ENABLED" is defined in there.

Thanks for your help.
RGarrett93
Posts: 8
Joined: Thu Jan 28, 2021 3:36 pm
Answers: 1

Re: Attempting to get SSD1963 working with a Nucleo-F767ZI (144)

Post by RGarrett93 »

Okay, it doesn't seem to have made a difference with disabling the DCache & ICache - assuming that I have managed to disable them.

I believe it is disabling them in the json as I put a made up definition to see whether PIO would throw a message and it did moan whereas it did not complain when I put
"I_CACHE_DISABLED",
"D_CACHE_DISABLED",

I've wired it up as I would on the F407 (working) with the same pinouts and tested the library but still showing a blank screen, also tested my modified code with specified pinouts and again just a blank screen.

Out of interest, why would disabling the DCache & ICache possibly help?
RGarrett93
Posts: 8
Joined: Thu Jan 28, 2021 3:36 pm
Answers: 1

Re: Attempting to get SSD1963 working with a Nucleo-F767ZI (144)

Post by RGarrett93 »

I think I was slightly doing the cache disabling wrong on PlatformIO.

In the configuration file (platformio.ini) you set 'build_flags'

Code: Select all

build_flags = 
	-DI_CACHE_DISABLED
	-DD_CACHE_DISABLED
this then automatically updates the defines in c_cpp_properties.json

Code: Select all

            "defines": [
                "PLATFORMIO=50004",
                "STM32F767xx",
                "I_CACHE_DISABLED",
                "D_CACHE_DISABLED",
                "STM32F7xx",
                "ARDUINO=10808",
                "ARDUINO_ARCH_STM32",
                "ARDUINO_NUCLEO_F767ZI",
                "BOARD_NAME=\"NUCLEO_F767ZI\"",
                "HAL_UART_MODULE_ENABLED",
                ""
            ],
Anyway tested the above and doesn't seem to have helped, I don't see any reference in the compiler for disabling the cache.
Where about is the below located in the core?

Code: Select all

#if (__CORTEX_M == 0x07U)
  // Defined in CMSIS core_cm7.h
#ifndef I_CACHE_DISABLED
  SCB_EnableICache();
#endif
#ifndef D_CACHE_DISABLED
  SCB_EnableDCache();
#endif
#endif 
Going back to trying to get the library working with the Nucleo 144, I am testing the F4 working code on the Nucleo with the same pinouts, two of the pins used PD8 & PD9 is used for the virtual Serial on the STlink top board, they are physically disconnected from the board via SB5 & SB6 but I was wondering whether I need to set any build_flags to prevent enabling Serial on those pins as default?


This is the code that works well with the STM32F407 board

Code: Select all

// TFT connector uses FSMC pins
// D0   D1   D2  D3  D4  D5  D6  D7   D8   D9   D10  D11  D12  D13 D14 D15
// PD14 PD15 PD0 PD1 PE7 PE8 PE9 PE10 PE11 PE12 PE13 PE14 PE15 PD8 PD9 PD10

// connector pins
// 01  02  03  04  05  06  07  08  09  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31  32
// GND RST D15 D14 D13 D12 D11 D10 D9  D8  D7  D6  D5  D4  D3  D2  D1  D0  RD  WR  RS  CS  SCK SCS SI  SO  INT BLK SET GND 3.3 GND
//         D10 D9  D8  E15 E14 E13 E12 E11 E10 E9  E8  E7  D1  D0  D15 D14 D4  D5  D13 D7                      B1

// D used : 15,14,13,..,..,10, 9, 8, 7,.., 5, 4,..,.., 1, 0, // 11
// D data : 15,14,..,..,..,10, 9, 8,..,..,..,..,..,.., 1, 0, // 7
//         |           |           |           |           |
// E used : 15,14,13,12,11,10, 9, 8, 7,..,..,..,..,..,..,.., // 9
// E data : 15,14,13,12,11,10, 9, 8, 7,..,..,..,..,..,..,.., // 9

#define PD_USED_BITS 0xE7B3
#define PD_DATA_BITS 0xC703

#define PE_USED_BITS 0xFF80
#define PE_DATA_BITS 0xFF80

#define PD_MODE_MASK 0xFC3FCF0F // all used bits
#define PD_MODE_BITS 0x54154505 // 01 : general purpose output mode
#define PE_MODE_MASK 0xFFFFC000 // all used bits
#define PE_MODE_BITS 0x55554000 // 01 : general purpose output mode

#define PD_MODE_DATA 0xF03F000F // all data bits
#define PD_MODE_OUTP 0x50150005 // 01 : general purpose output mode
#define PD_MODE_INP  0x00000000 // 00 : input floating mode
#define PE_MODE_DATA 0xFFFFC000 // all data bits
#define PE_MODE_OUTP 0x55554000 // 01 : general purpose output mode
#define PE_MODE_INP  0x00000000 // 00 : input floating mode

GxIO_STM32F407V_P16::GxIO_STM32F407V_P16(bool bl_active_high)
{
  _cs   = PD7;
  _rs   = PD13;
  _rst  = 0; // not available, driven from NRST
  _wr   = PD5;
  _rd   = PD4;
  _bl   = PB1;
  _bl_active_high = bl_active_high;
}

void GxIO_STM32F407V_P16::reset()
{
  // _rst pin not available
}

void GxIO_STM32F407V_P16::init()
{
  RCC->AHB1ENR |= 0x00000078; // enable GPIOD, GPIOE, GPIOF and GPIOG interface clock
  READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIODEN); // delay after an RCC peripheral clock enabling
  GPIOD->BSRR |= PD_USED_BITS; // preset all output high
  GPIOD->MODER &= ~PD_MODE_MASK;
  GPIOD->MODER |= PD_MODE_BITS;
  GPIOD->OTYPER &= ~PD_USED_BITS; // 0 : output push-pull
  GPIOD->OSPEEDR &= ~PD_MODE_MASK; // 0 : low speed
  GPIOD->PUPDR &= ~PD_MODE_MASK; // 0 : no pull-up, no pull-down

  GPIOE->BSRR |= PE_USED_BITS; // preset all output high
  GPIOE->MODER &= ~PE_MODE_MASK;
  GPIOE->MODER |= PE_MODE_BITS;
  GPIOE->OTYPER &= ~PE_USED_BITS; // 0 : output push-pull
  GPIOE->OSPEEDR &= ~PE_MODE_MASK; // 0 : low speed
  GPIOE->PUPDR &= ~PE_MODE_MASK; // 0 : no pull-up, no pull-down

  digitalWrite(_bl, LOW);
  pinMode(_bl, OUTPUT);

  reset();
}

uint8_t GxIO_STM32F407V_P16::readDataTransaction()
{
  return readData16Transaction();
}

uint16_t GxIO_STM32F407V_P16::readData16Transaction()
{
  GPIOD->BSRR = (0x1 << (7 + 16));  // PD7 CS low
  uint16_t rv = readData16();
  GPIOD->BSRR = (0x1 << 7);  // PD7 CS high
  return rv;
}

uint8_t GxIO_STM32F407V_P16::readData()
{
  return readData16();
}

uint16_t GxIO_STM32F407V_P16::readData16()
{
  // Set direction input
  GPIOD->MODER &= ~PD_MODE_DATA;
  GPIOE->MODER &= ~PE_MODE_DATA;
//  GPIOD->BSRR = (0x1 << (4 + 16));  // PD4 RD low pulse
//  GPIOD->BSRR = (0x1 << 4); // PD4 RD high
  GPIOD->BSRR = (0x1 << (4 + 16));  // PD4 RD low read
  GPIOD->BSRR = (0x1 << (4 + 16));  // PD4 RD low read
  GPIOD->BSRR = (0x1 << (4 + 16));  // PD4 RD low read
  GPIOD->BSRR = (0x1 << (4 + 16));  // PD4 RD low read
  uint16_t rv = 0;
  // The compiler efficiently codes this  so it is quite quick.
  rv |= (GPIOD->IDR & (0x1 << 10)) << (15 - 10); // PD10
  rv |= (GPIOD->IDR & (0x1 << 9)) << (14 - 9); // PD9
  rv |= (GPIOD->IDR & (0x1 << 8)) << (13 - 8); // PD8
  rv |= (GPIOE->IDR & (0x1 << 15)) >> -(12 - 15); // PE15
  rv |= (GPIOE->IDR & (0x1 << 14)) >> -(11 - 14); // PE14
  rv |= (GPIOE->IDR & (0x1 << 13)) >> -(10 - 13); // PE13
  rv |= (GPIOE->IDR & (0x1 << 12)) >> -(9 - 12); // PE12
  rv |= (GPIOE->IDR & (0x1 << 11)) >> -(8 - 11); // PE11
  rv |= (GPIOE->IDR & (0x1 << 10)) >> -(7 - 10); // PE10
  rv |= (GPIOE->IDR & (0x1 << 9)) >> -(6 - 9); // PE9
  rv |= (GPIOE->IDR & (0x1 << 8)) >> -(5 - 8); // PE8
  rv |= (GPIOE->IDR & (0x1 << 7)) >> -(4 - 7); // PE7
  rv |= (GPIOD->IDR & (0x1 << 1)) << (3 - 1); // PD1
  rv |= (GPIOD->IDR & (0x1 << 0)) << (2 - 0); // PD0
  rv |= (GPIOD->IDR & (0x1 << 15)) >> -(1 - 15); // PD15
  rv |= (GPIOD->IDR & (0x1 << 14)) >> -(0 - 14); // PD14
  GPIOD->BSRR = (0x1 << 4); // PD4 RD high
  // Set direction output again
  GPIOD->MODER &= ~PD_MODE_DATA;
  GPIOD->MODER |= PD_MODE_OUTP;
  GPIOE->MODER &= ~PD_MODE_DATA;
  GPIOE->MODER |= PE_MODE_OUTP;
  return rv;
}

uint32_t GxIO_STM32F407V_P16::readRawData32(uint8_t part)
{
  // Set direction input
  GPIOD->MODER &= ~PD_MODE_DATA;
  GPIOE->MODER &= ~PE_MODE_DATA;
  GPIOD->BSRR = (0x1 << (4 + 16));  // PD4 RD low pulse
  GPIOD->BSRR = (0x1 << 4); // PD4 RD high
  GPIOD->BSRR = (0x1 << (4 + 16));  // PD4 RD low read
  uint32_t rv = 0;
  if (part == 0) rv = GPIOD->IDR & PD_DATA_BITS;
  if (part == 1) rv = GPIOE->IDR & PE_DATA_BITS;
  GPIOD->BSRR = (0x1 << 4); // PD4 RD high
  // Set direction output again
  GPIOD->MODER &= ~PD_MODE_DATA;
  GPIOD->MODER |= PD_MODE_OUTP;
  GPIOE->MODER &= ~PD_MODE_DATA;
  GPIOE->MODER |= PE_MODE_OUTP;
  return rv;
}

void GxIO_STM32F407V_P16::writeCommandTransaction(uint8_t c)
{
  GPIOD->BSRR = (0x1 << (7 + 16));  // PD7 CS low
  GPIOD->BSRR = (0x1 << (13 + 16));  // PD13 RS low
  writeData16(c);
  GPIOD->BSRR = (0x1 << 13);  // PD13 RS high
  GPIOD->BSRR = (0x1 << 7);  // PD7 CS high
}

void GxIO_STM32F407V_P16::writeCommand16Transaction(uint16_t c)
{
  GPIOD->BSRR = (0x1 << (7 + 16));  // PD7 CS low
  GPIOD->BSRR = (0x1 << (13 + 16));  // PD13 RS low
  writeData16(c);
  GPIOD->BSRR = (0x1 << 13);  // PD13 RS high
  GPIOD->BSRR = (0x1 << 7);  // PD7 CS high
}

void GxIO_STM32F407V_P16::writeDataTransaction(uint8_t d)
{
  GPIOD->BSRR = (0x1 << (7 + 16));  // PD7 CS low
  writeData16(d);
  GPIOD->BSRR = (0x1 << 7);  // PD7 CS high
}

void GxIO_STM32F407V_P16::writeData16Transaction(uint16_t d, uint32_t num)
{
  GPIOD->BSRR = (0x1 << (7 + 16));  // PD7 CS low
  writeData16(d, num);
  GPIOD->BSRR = (0x1 << 7);  // PD7 CS high
}

void GxIO_STM32F407V_P16::writeCommand(uint8_t c)
{
  GPIOD->BSRR = (0x1 << (13 + 16));  // PD13 RS low
  writeData16(c);
  GPIOD->BSRR = (0x1 << 13);  // PD13 RS high
}

void GxIO_STM32F407V_P16::writeCommand16(uint16_t c)
{
  GPIOD->BSRR = (0x1 << (13 + 16));  // PD13 RS low
  writeData16(c);
  GPIOD->BSRR = (0x1 << 13);  // PD13 RS high
}

void GxIO_STM32F407V_P16::writeData(uint8_t d)
{
  writeData16(d);
}

void GxIO_STM32F407V_P16::writeData(uint8_t* d, uint32_t num)
{
  while (num > 0)
  {
    writeData16(*d);
    d++;
    num--;
  }
}

void GxIO_STM32F407V_P16::writeData16(uint16_t d, uint32_t num)
{
  GPIOD->BSRR = PD_DATA_BITS << 16; // clear bits
  GPIOE->BSRR = PE_DATA_BITS << 16; // clear bits

  // TFT connector uses FSMC pins
  // D0   D1   D2  D3  D4  D5  D6  D7   D8   D9   D10  D11  D12  D13 D14 D15
  // PD14 PD15 PD0 PD1 PE7 PE8 PE9 PE10 PE11 PE12 PE13 PE14 PE15 PD8 PD9 PD10

  // The compiler efficiently codes this  so it is quite quick.
  if (d & 0x8000) GPIOD->BSRR = 0x1 << 10; // PD10
  if (d & 0x4000) GPIOD->BSRR = 0x1 << 9; // PD9
  if (d & 0x2000) GPIOD->BSRR = 0x1 << 8; // PD8
  if (d & 0x1000) GPIOE->BSRR = 0x1 << 15; // PE15
  if (d & 0x0800) GPIOE->BSRR = 0x1 << 14; // PE14
  if (d & 0x0400) GPIOE->BSRR = 0x1 << 13; // PE13
  if (d & 0x0200) GPIOE->BSRR = 0x1 << 12; // PE12
  if (d & 0x0100) GPIOE->BSRR = 0x1 << 11; // PE11

  if (d & 0x0080) GPIOE->BSRR = 0x1 << 10; // PE10
  if (d & 0x0040) GPIOE->BSRR = 0x1 << 9; // PE9
  if (d & 0x0020) GPIOE->BSRR = 0x1 << 8; // PE8
  if (d & 0x0010) GPIOE->BSRR = 0x1 << 7; // PE7
  if (d & 0x0008) GPIOD->BSRR = 0x1 << 1; // PD1
  if (d & 0x0004) GPIOD->BSRR = 0x1 << 0; // PD0
  if (d & 0x0002) GPIOD->BSRR = 0x1 << 15; // PD15
  if (d & 0x0001) GPIOD->BSRR = 0x1 << 14; // PD14
  while (num)
  {
    GPIOD->BSRR = (0x1 << (5 + 16));  // PD5 WR low
    GPIOD->BSRR = (0x1 << (5 + 16));  // PD5 WR low
    GPIOD->BSRR = (0x1 << (5 + 16));  // PD5 WR low
    GPIOD->BSRR = (0x1 << (5 + 16));  // PD5 WR low
    GPIOD->BSRR = (0x1 << 5); // PD5 WR high
    //digitalWrite(_wr, LOW);
    //digitalWrite(_wr, HIGH);
    num--;
  }
}

void GxIO_STM32F407V_P16::writeAddrMSBfirst(uint16_t d)
{
  writeData16(d >> 8);
  writeData16(d & 0xFF);
}

void GxIO_STM32F407V_P16::startTransaction()
{
  GPIOD->BSRR = (0x1 << (7 + 16));  // PD7 CS low
}

void GxIO_STM32F407V_P16::endTransaction()
{
  GPIOD->BSRR = (0x1 << 7);  // PD7 CS high
}

void GxIO_STM32F407V_P16::selectRegister(bool rs_low)
{
  digitalWrite(_rs, (rs_low ? LOW : HIGH));
}

void GxIO_STM32F407V_P16::setBackLight(bool lit)
{
  digitalWrite(_bl, (lit == _bl_active_high));
}
RGarrett93
Posts: 8
Joined: Thu Jan 28, 2021 3:36 pm
Answers: 1

Re: Attempting to get SSD1963 working with a Nucleo-F767ZI (144)

Post by RGarrett93 »

@fpiSTM

I managed to test bitbashing with using just pinMode on the Nucleo-F767ZI but I had to use the Zio Connectors (uno equivalent pins) and get something to display.
The performance was poor so next I will have to work on the registers and make sure the timing is correct to spec to speed things up.

Ultimately I want to use FMC so to start off with those pins, I noticed that one of the GPIO pin (PD10) is not assigned on the core for pinMode, digitalWrite etc... ? Is there any particular reason why that pin can not be used?

Image

Code: Select all

//R.Garrett
//Using ZinggJM/GxTFT library and adding GxIO for STM32 Nucleo 144
//This should in theory work with any board if you redefine the below pins
//This is purely to test on a new MCU prior to writing the registers - so this will be slow!

#include "GxTFT_MCU_Tester.h"


// Pin define here

#define CS  PA3 
#define RS  PF3
#define RST 0 
#define WR  PC3 
#define RD  PC0 
#define BL  PB1 

  // TFT connector to Nucleo 144 pins
  // D0   D1   D2   D3   D4   D5   D6  D7   D8   D9  D10  D11 D12 D13 D14 D15
  // PG9 PG14 PF15 PE13 PF14 PE11 PE9 PF13 PF12 PD15 PD14 PA7 PA6 PA5 PB9 PB8

#define _D15  PB8 
#define _D14  PB9 
#define _D13  PA5 
#define _D12  PA6 
#define _D11  PA7 
#define _D10  PD14 
#define _D9   PD15
#define _D8   PF12 
#define _D7   PF13
#define _D6   PE9
#define _D5   PE11
#define _D4   PF14 
#define _D3   PE13
#define _D2   PF15
#define _D1   PG14
#define _D0   PG9 


MCU_Tester::MCU_Tester(bool bl_active_high)
{
  _cs   = CS;
  _rs   = RS;
  _rst  = 0; // not available, driven from NRST
  _wr   = WR;
  _rd   = RD;
  _bl   = BL;
  _bl_active_high = bl_active_high;
}

void MCU_Tester::reset()
{
  // _rst pin not available
}

void MCU_Tester::init()
{
 
pinMode(_D15, OUTPUT);  //15
pinMode(_D14, OUTPUT);  //14
pinMode(_D13, OUTPUT);  //13
pinMode(_D12, OUTPUT);  //12
pinMode(_D11, OUTPUT);  //11
pinMode(_D10, OUTPUT); //10
pinMode(_D9, OUTPUT); //9
pinMode(_D8, OUTPUT); //8
pinMode(_D7, OUTPUT); //7
pinMode(_D6, OUTPUT);  //6
pinMode(_D5, OUTPUT); //5
pinMode(_D4, OUTPUT); //4
pinMode(_D3, OUTPUT); //3
pinMode(_D2, OUTPUT); //2
pinMode(_D1, OUTPUT); //1
pinMode(_D0, OUTPUT);  //0

digitalWrite(_D15, HIGH);  //15
digitalWrite(_D14, HIGH);  //14
digitalWrite(_D13, HIGH);  //13
digitalWrite(_D12, HIGH);  //12
digitalWrite(_D11, HIGH);  //11
digitalWrite(_D10, HIGH); //10
digitalWrite(_D9, HIGH); //9
digitalWrite(_D8, HIGH); //8
digitalWrite(_D7, HIGH); //7
digitalWrite(_D6, HIGH);  //6
digitalWrite(_D5, HIGH); //5
digitalWrite(_D4, HIGH); //4
digitalWrite(_D3, HIGH); //3
digitalWrite(_D2, HIGH); //2
digitalWrite(_D1, HIGH); //1
digitalWrite(_D0, HIGH);  //0
  

  pinMode(_wr, OUTPUT);
  digitalWrite(_wr, HIGH);
  pinMode(_rd, OUTPUT);
  digitalWrite(_rd, HIGH);
  pinMode(_cs, OUTPUT);
  digitalWrite(_cs, HIGH);
  pinMode(_rs, OUTPUT);
  digitalWrite(_rs, HIGH);
  pinMode(_bl, OUTPUT);
  digitalWrite(_bl, LOW);
  reset();
}

uint8_t MCU_Tester::readDataTransaction()
{
  return readData16Transaction();
}

uint16_t MCU_Tester::readData16Transaction()
{
  digitalWrite(_cs, LOW);
  uint16_t rv = readData16();
  digitalWrite(_cs, HIGH);
  return rv;
}

uint8_t MCU_Tester::readData()
{
  return readData16();
}

uint16_t MCU_Tester::readData16()
{
  // Set direction to input
pinMode(_D15, INPUT);  //15
pinMode(_D14, INPUT);  //14
pinMode(_D13, INPUT);  //13
pinMode(_D12, INPUT);  //12
pinMode(_D11, INPUT);  //11
pinMode(_D10, INPUT); //10
pinMode(_D9, INPUT); //9
pinMode(_D8, INPUT); //8
pinMode(_D7, INPUT); //7
pinMode(_D6, INPUT);  //6
pinMode(_D5, INPUT); //5
pinMode(_D4, INPUT); //4
pinMode(_D3, INPUT); //3
pinMode(_D2, INPUT); //2
pinMode(_D1, INPUT); //1
pinMode(_D0, INPUT);  //0

digitalWrite(_rd, LOW);
digitalWrite(_rd, LOW);
digitalWrite(_rd, LOW);
digitalWrite(_rd, LOW);
digitalWrite(_rd, LOW);
digitalWrite(_rd, LOW);
digitalWrite(_rd, LOW);
digitalWrite(_rd, LOW);
digitalWrite(_rd, LOW);


  uint16_t rv = 0;

  rv |= digitalRead(_D15) ? 0x8000 : 0x0000; //15
  rv |= digitalRead(_D14) ? 0x4000 : 0x0000; // 14
  rv |= digitalRead(_D13) ? 0x2000 : 0x0000; // 13
  rv |= digitalRead(_D12) ? 0x1000 : 0x0000; // 12
  rv |= digitalRead(_D11) ? 0x0800 : 0x0000; // 11
  rv |= digitalRead(_D10) ? 0x0400 : 0x0000; // 10
  rv |= digitalRead(_D9) ? 0x0200 : 0x0000;  // 9
  rv |= digitalRead(_D8) ? 0x0100 : 0x0000;  // 8

  rv |= digitalRead(_D7) ? 0x0080 : 0x0000;  // 7
  rv |= digitalRead(_D6) ? 0x0040 : 0x0000;  // 6
  rv |= digitalRead(_D5) ? 0x0020 : 0x0000;  // 5
  rv |= digitalRead(_D4) ? 0x0010 : 0x0000;  // 4
  rv |= digitalRead(_D3) ? 0x0008 : 0x0000;  // 3
  rv |= digitalRead(_D2) ? 0x0004 : 0x0000;  // 2
  rv |= digitalRead(_D1) ? 0x0002 : 0x0000;  // 1
  rv |= digitalRead(_D0) ? 0x0001 : 0x0000;  // 0

 digitalWrite(_rd, HIGH);
  
  // Set direction output again
pinMode(_D15, OUTPUT);  //15
pinMode(_D14, OUTPUT);  //14
pinMode(_D13, OUTPUT);  //13
pinMode(_D12, OUTPUT);  //12
pinMode(_D11, OUTPUT);  //11
pinMode(_D10, OUTPUT); //10
pinMode(_D9, OUTPUT); //9
pinMode(_D8, OUTPUT); //8
pinMode(_D7, OUTPUT); //7
pinMode(_D6, OUTPUT);  //6
pinMode(_D5, OUTPUT); //5
pinMode(_D4, OUTPUT); //4
pinMode(_D3, OUTPUT); //3
pinMode(_D2, OUTPUT); //2
pinMode(_D1, OUTPUT); //1
pinMode(_D0, OUTPUT);  //0

digitalWrite(_D15, HIGH);  //15
digitalWrite(_D14, HIGH);  //14
digitalWrite(_D13, HIGH);  //13
digitalWrite(_D12, HIGH);  //12
digitalWrite(_D11, HIGH);  //11
digitalWrite(_D10, HIGH); //10
digitalWrite(_D9, HIGH); //9
digitalWrite(_D8, HIGH); //8
digitalWrite(_D7, HIGH); //7
digitalWrite(_D6, HIGH);  //6
digitalWrite(_D5, HIGH); //5
digitalWrite(_D4, HIGH); //4
digitalWrite(_D3, HIGH); //3
digitalWrite(_D2, HIGH); //2
digitalWrite(_D1, HIGH); //1
digitalWrite(_D0, HIGH);  //0

  return rv;
}

void MCU_Tester::writeCommandTransaction(uint8_t c)
{

 digitalWrite(_cs, LOW);
 digitalWrite(_rs, LOW);
  writeData16(c);
 digitalWrite(_cs, HIGH);
 digitalWrite(_rs, HIGH);

}

void MCU_Tester::writeCommand16Transaction(uint16_t c)
{

digitalWrite(_cs, LOW);
digitalWrite(_rs, LOW);
  writeData16(c);
digitalWrite(_cs, HIGH);
digitalWrite(_rs, HIGH);

}

void MCU_Tester::writeDataTransaction(uint8_t d)
{
digitalWrite(_cs, LOW);
writeData16(d);
digitalWrite(_cs, HIGH);

}

void MCU_Tester::writeData16Transaction(uint16_t d, uint32_t num)
{
digitalWrite(_cs, LOW);
writeData16(d, num);
digitalWrite(_cs, HIGH); 
}

void MCU_Tester::writeCommand(uint8_t c)
{
digitalWrite(_rs, LOW);
writeData16(c);
digitalWrite(_rs, HIGH);
}

void MCU_Tester::writeCommand16(uint16_t c)
{
digitalWrite(_rs, LOW);
writeData16(c);
digitalWrite(_rs, HIGH);
}

void MCU_Tester::writeData(uint8_t d)
{
  writeData16(d);
}

void MCU_Tester::writeData(uint8_t* d, uint32_t num)
{
  while (num > 0)
  {
    writeData16(*d);
    d++;
    num--;
  }
}

void MCU_Tester::writeData16(uint16_t d, uint32_t num)
{

digitalWrite(_D15, LOW);  //15
digitalWrite(_D14, LOW);  //14
digitalWrite(_D13, LOW);  //13
digitalWrite(_D12, LOW);  //12
digitalWrite(_D11, LOW);  //11
digitalWrite(_D10, LOW); //10
digitalWrite(_D9, LOW); //9
digitalWrite(_D8, LOW); //8
digitalWrite(_D7, LOW); //7
digitalWrite(_D6, LOW);  //6
digitalWrite(_D5, LOW); //5
digitalWrite(_D4, LOW); //4
digitalWrite(_D3, LOW); //3
digitalWrite(_D2, LOW); //2
digitalWrite(_D1, LOW); //1
digitalWrite(_D0, LOW);  //0

  (d & 0x8000) ? digitalWrite(_D15, HIGH) : digitalWrite(_D15, LOW); //15
  (d & 0x4000) ? digitalWrite(_D14, HIGH) : digitalWrite(_D14, LOW); //14
  (d & 0x2000) ? digitalWrite(_D13, HIGH) : digitalWrite(_D13, LOW); //13
  (d & 0x1000) ? digitalWrite(_D12, HIGH): digitalWrite(_D12, LOW); //12
  (d & 0x0800) ? digitalWrite(_D11, HIGH) : digitalWrite(_D11, LOW); //11
  (d & 0x0400) ? digitalWrite(_D10, HIGH) : digitalWrite(_D10, LOW); //10
  (d & 0x0200) ? digitalWrite(_D9, HIGH) : digitalWrite(_D9, LOW);//9
  (d & 0x0100) ? digitalWrite(_D8, HIGH) : digitalWrite(_D8, LOW);//8

  (d & 0x0080) ? digitalWrite(_D7, HIGH) : digitalWrite(_D7, LOW);//7
  (d & 0x0040) ? digitalWrite(_D6, HIGH) : digitalWrite(_D6, LOW);//6
  (d & 0x0020) ? digitalWrite(_D5, HIGH) : digitalWrite(_D5, LOW);//5
  (d & 0x0010) ? digitalWrite(_D4, HIGH) : digitalWrite(_D4, LOW);//4
  (d & 0x0008) ? digitalWrite(_D3, HIGH) : digitalWrite(_D3, LOW);//3
  (d & 0x0004) ? digitalWrite(_D2, HIGH) : digitalWrite(_D2, LOW);//2
  (d & 0x0002) ? digitalWrite(_D1, HIGH) : digitalWrite(_D1, LOW);//1
  (d & 0x0001) ? digitalWrite(_D0, HIGH) : digitalWrite(_D0, LOW); //0

  while (num)
  {
    digitalWrite(_wr, LOW);
    digitalWrite(_wr, LOW);
    digitalWrite(_wr, LOW);
    digitalWrite(_wr, LOW);
    digitalWrite(_wr, HIGH);
    num--;
  }
}

void MCU_Tester::writeAddrMSBfirst(uint16_t d)
{
  writeData16(d >> 8);
  writeData16(d & 0xFF);
}

void MCU_Tester::startTransaction()
{
  digitalWrite(_cs, LOW);
}

void MCU_Tester::endTransaction()
{
  digitalWrite(_cs, HIGH);
}

void MCU_Tester::selectRegister(bool rs_low)
{
  digitalWrite(_rs, (rs_low ? LOW : HIGH));
}

void MCU_Tester::setBackLight(bool lit)
{
  digitalWrite(_bl, (lit == _bl_active_high));
}
User avatar
fpiSTM
Posts: 1723
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 91
Location: Le Mans
Contact:

Re: Attempting to get SSD1963 working with a Nucleo-F767ZI (144)

Post by fpiSTM »

RGarrett93 wrote: Fri Feb 12, 2021 10:03 am Ultimately I want to use FMC so to start off with those pins, I noticed that one of the GPIO pin (PD10) is not assigned on the core for pinMode, digitalWrite etc... ? Is there any particular reason why that pin can not be used?
No particular reason. It simply was not defined when the variant has been created. The variant will be reworked soon for the 2.0.0 and all pins will be defined.
RGarrett93
Posts: 8
Joined: Thu Jan 28, 2021 3:36 pm
Answers: 1

Re: Attempting to get SSD1963 working with a Nucleo-F767ZI (144)

Post by RGarrett93 »

@fpiSTM

Okay that's great, I'm going to be using the registers anyway but just wanted to double check.

I have physically disconnected the STlink serial from the board via solder bridge SB5 & SB6 on the Nucleo board but I was wondering whether I need to set any build_flags to prevent enabling Serial UART3 on those pins as default? This is in relation to GPIO PD8 & PD9 for FMC
Post Reply

Return to “Libraries & Hardware”