TFT (plus Hardware SPI) for LPC (#19139)

This commit is contained in:
Victor Oliveira
2020-08-26 07:13:58 -03:00
committed by GitHub
parent 4955aa5b78
commit 1a4b82a5d6
11 changed files with 862 additions and 49 deletions

View File

@ -0,0 +1,153 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "../../../inc/MarlinConfig.h"
#if HAS_SPI_TFT
#include "tft_spi.h"
//TFT_SPI tft;
SPIClass TFT_SPI::SPIx(1);
#define TFT_CS_H WRITE(TFT_CS_PIN, HIGH)
#define TFT_CS_L WRITE(TFT_CS_PIN, LOW)
#define TFT_DC_H WRITE(TFT_DC_PIN, HIGH)
#define TFT_DC_L WRITE(TFT_DC_PIN, LOW)
#define TFT_RST_H WRITE(TFT_RESET_PIN, HIGH)
#define TFT_RST_L WRITE(TFT_RESET_PIN, LOW)
#define TFT_BLK_H WRITE(TFT_BACKLIGHT_PIN, HIGH)
#define TFT_BLK_L WRITE(TFT_BACKLIGHT_PIN, LOW)
void TFT_SPI::Init() {
#if PIN_EXISTS(TFT_RESET)
SET_OUTPUT(TFT_RESET_PIN);
TFT_RST_H;
delay(100);
#endif
#if PIN_EXISTS(TFT_BACKLIGHT)
SET_OUTPUT(TFT_BACKLIGHT_PIN);
TFT_BLK_H;
#endif
SET_OUTPUT(TFT_DC_PIN);
SET_OUTPUT(TFT_CS_PIN);
TFT_DC_H;
TFT_CS_H;
/**
* STM32F1 APB2 = 72MHz, APB1 = 36MHz, max SPI speed of this MCU if 18Mhz
* STM32F1 has 3 SPI ports, SPI1 in APB2, SPI2/SPI3 in APB1
* so the minimum prescale of SPI1 is DIV4, SPI2/SPI3 is DIV2
*/
#if 0
#if SPI_DEVICE == 1
#define SPI_CLOCK_MAX SPI_CLOCK_DIV4
#else
#define SPI_CLOCK_MAX SPI_CLOCK_DIV2
#endif
uint8_t clock;
uint8_t spiRate = SPI_FULL_SPEED;
switch (spiRate) {
case SPI_FULL_SPEED: clock = SPI_CLOCK_MAX ; break;
case SPI_HALF_SPEED: clock = SPI_CLOCK_DIV4 ; break;
case SPI_QUARTER_SPEED: clock = SPI_CLOCK_DIV8 ; break;
case SPI_EIGHTH_SPEED: clock = SPI_CLOCK_DIV16; break;
case SPI_SPEED_5: clock = SPI_CLOCK_DIV32; break;
case SPI_SPEED_6: clock = SPI_CLOCK_DIV64; break;
default: clock = SPI_CLOCK_DIV2; // Default from the SPI library
}
#endif
#if TFT_MISO_PIN == BOARD_SPI1_MISO_PIN
SPIx.setModule(1);
#elif TFT_MISO_PIN == BOARD_SPI2_MISO_PIN
SPIx.setModule(2);
#endif
SPIx.setClock(SPI_CLOCK_MAX);
SPIx.setBitOrder(MSBFIRST);
SPIx.setDataMode(SPI_MODE0);
}
void TFT_SPI::DataTransferBegin(uint16_t DataSize) {
SPIx.setDataSize(DataSize);
SPIx.begin();
TFT_CS_L;
}
uint32_t TFT_SPI::GetID() {
uint32_t id;
id = ReadID(LCD_READ_ID);
if ((id & 0xFFFF) == 0 || (id & 0xFFFF) == 0xFFFF)
id = ReadID(LCD_READ_ID4);
return id;
}
uint32_t TFT_SPI::ReadID(uint16_t Reg) {
uint32_t data = 0;
#if PIN_EXISTS(TFT_MISO)
uint8_t d = 0;
SPIx.setDataSize(DATASIZE_8BIT);
SPIx.setClock(SPI_CLOCK_DIV64);
SPIx.begin();
TFT_CS_L;
WriteReg(Reg);
LOOP_L_N(i, 4) {
SPIx.read((uint8_t*)&d, 1);
data = (data << 8) | d;
}
DataTransferEnd();
SPIx.setClock(SPI_CLOCK_MAX);
#endif
return data >> 7;
}
bool TFT_SPI::isBusy() {
return false;
}
void TFT_SPI::Abort() {
DataTransferEnd();
}
void TFT_SPI::Transmit(uint16_t Data) {
SPIx.transfer(Data);
}
void TFT_SPI::TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count) {
DataTransferBegin(DATASIZE_16BIT); //16
TFT_DC_H;
SPIx.dmaSend(Data, Count, MemoryIncrease);
DataTransferEnd();
}
#endif // HAS_SPI_TFT

View File

@ -0,0 +1,77 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#include "../../../inc/MarlinConfig.h"
#include <SPI.h>
#include <lpc17xx_ssp.h>
// #include <lpc17xx_gpdma.h>
#ifndef LCD_READ_ID
#define LCD_READ_ID 0x04 // Read display identification information (0xD3 on ILI9341)
#endif
#ifndef LCD_READ_ID4
#define LCD_READ_ID4 0xD3 // Read display identification information (0xD3 on ILI9341)
#endif
#define DATASIZE_8BIT SSP_DATABIT_8
#define DATASIZE_16BIT SSP_DATABIT_16
#define TFT_IO TFT_SPI
#define DMA_MINC_ENABLE 1
#define DMA_MINC_DISABLE 0
class TFT_SPI {
private:
static uint32_t ReadID(uint16_t Reg);
static void Transmit(uint16_t Data);
static void TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count);
public:
static SPIClass SPIx;
static void Init();
static uint32_t GetID();
static bool isBusy();
static void Abort();
static void DataTransferBegin(uint16_t DataWidth = DATASIZE_16BIT);
static void DataTransferEnd() { OUT_WRITE(TFT_CS_PIN, HIGH); SPIx.end(); };
static void DataTransferAbort();
static void WriteData(uint16_t Data) { Transmit(Data); }
static void WriteReg(uint16_t Reg) { OUT_WRITE(TFT_A0_PIN, LOW); Transmit(Reg); OUT_WRITE(TFT_A0_PIN, HIGH); }
static void WriteSequence(uint16_t *Data, uint16_t Count) { TransmitDMA(DMA_MINC_ENABLE, Data, Count); }
// static void WriteMultiple(uint16_t Color, uint16_t Count) { static uint16_t Data; Data = Color; TransmitDMA(DMA_MINC_DISABLE, &Data, Count); }
static void WriteMultiple(uint16_t Color, uint32_t Count) {
static uint16_t Data; Data = Color;
//LPC dma can only write 0xFFF bytes at once.
#define MAX_DMA_SIZE (0xFFF - 1)
while (Count > 0) {
TransmitDMA(DMA_MINC_DISABLE, &Data, Count > MAX_DMA_SIZE ? MAX_DMA_SIZE : Count);
Count = Count > MAX_DMA_SIZE ? Count - MAX_DMA_SIZE : 0;
}
#undef MAX_DMA_SIZE
}
};

View File

@ -0,0 +1,129 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "../../../inc/MarlinConfig.h"
#if HAS_TFT_XPT2046 || HAS_TOUCH_XPT2046
#include "xpt2046.h"
#include <SPI.h>
uint16_t delta(uint16_t a, uint16_t b) { return a > b ? a - b : b - a; }
#if ENABLED(TOUCH_BUTTONS_HW_SPI)
#include <SPI.h>
SPIClass XPT2046::SPIx(TOUCH_BUTTONS_HW_SPI_DEVICE);
static void touch_spi_init(uint8_t spiRate) {
XPT2046::SPIx.setModule(TOUCH_BUTTONS_HW_SPI_DEVICE);
XPT2046::SPIx.setClock(SPI_CLOCK_DIV128);
XPT2046::SPIx.setBitOrder(MSBFIRST);
XPT2046::SPIx.setDataMode(SPI_MODE0);
XPT2046::SPIx.setDataSize(DATA_SIZE_8BIT);
}
#endif
void XPT2046::Init() {
SET_INPUT(TOUCH_MISO_PIN);
SET_OUTPUT(TOUCH_MOSI_PIN);
SET_OUTPUT(TOUCH_SCK_PIN);
OUT_WRITE(TOUCH_CS_PIN, HIGH);
#if PIN_EXISTS(TOUCH_INT)
// Optional Pendrive interrupt pin
SET_INPUT(TOUCH_INT_PIN);
#endif
TERN_(TOUCH_BUTTONS_HW_SPI, touch_spi_init(SPI_SPEED_6));
// Read once to enable pendrive status pin
getRawData(XPT2046_X);
}
bool XPT2046::isTouched() {
return isBusy() ? false : (
#if PIN_EXISTS(TOUCH_INT)
READ(TOUCH_INT_PIN) != HIGH
#else
getRawData(XPT2046_Z1) >= XPT2046_Z1_THRESHOLD
#endif
);
}
bool XPT2046::getRawPoint(int16_t *x, int16_t *y) {
if (isBusy()) return false;
if (!isTouched()) return false;
*x = getRawData(XPT2046_X);
*y = getRawData(XPT2046_Y);
SERIAL_ECHOLNPAIR("X: ", *x, ", Y: ", *y);
return isTouched();
}
uint16_t XPT2046::getRawData(const XPTCoordinate coordinate) {
uint16_t data[3];
DataTransferBegin();
TERN_(TOUCH_BUTTONS_HW_SPI, SPIx.begin());
for (uint16_t i = 0; i < 3 ; i++) {
IO(coordinate);
data[i] = (IO() << 4) | (IO() >> 4);
}
TERN_(TOUCH_BUTTONS_HW_SPI, SPIx.end());
DataTransferEnd();
uint16_t delta01 = delta(data[0], data[1]),
delta02 = delta(data[0], data[2]),
delta12 = delta(data[1], data[2]);
if (delta01 > delta02 || delta01 > delta12)
data[delta02 > delta12 ? 0 : 1] = data[2];
return (data[0] + data[1]) >> 1;
}
uint16_t XPT2046::IO(uint16_t data) {
return TERN(TOUCH_BUTTONS_HW_SPI, HardwareIO, SoftwareIO)(data);
}
extern uint8_t spiTransfer(uint8_t b);
#if ENABLED(TOUCH_BUTTONS_HW_SPI)
uint16_t XPT2046::HardwareIO(uint16_t data) {
return SPIx.transfer(data & 0xFF);
}
#endif
uint16_t XPT2046::SoftwareIO(uint16_t data) {
uint16_t result = 0;
for (uint8_t j = 0x80; j; j >>= 1) {
WRITE(TOUCH_SCK_PIN, LOW);
WRITE(TOUCH_MOSI_PIN, data & j ? HIGH : LOW);
if (READ(TOUCH_MISO_PIN)) result |= j;
WRITE(TOUCH_SCK_PIN, HIGH);
}
WRITE(TOUCH_SCK_PIN, LOW);
return result;
}
#endif // HAS_TFT_XPT2046

View File

@ -0,0 +1,80 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#include "../../../inc/MarlinConfig.h"
#if ENABLED(TOUCH_BUTTONS_HW_SPI)
#include <SPI.h>
#endif
#ifndef TOUCH_MISO_PIN
#define TOUCH_MISO_PIN MISO_PIN
#endif
#ifndef TOUCH_MOSI_PIN
#define TOUCH_MOSI_PIN MOSI_PIN
#endif
#ifndef TOUCH_SCK_PIN
#define TOUCH_SCK_PIN SCK_PIN
#endif
#ifndef TOUCH_CS_PIN
#define TOUCH_CS_PIN CS_PIN
#endif
#ifndef TOUCH_INT_PIN
#define TOUCH_INT_PIN -1
#endif
#define XPT2046_DFR_MODE 0x00
#define XPT2046_SER_MODE 0x04
#define XPT2046_CONTROL 0x80
enum XPTCoordinate : uint8_t {
XPT2046_X = 0x10 | XPT2046_CONTROL | XPT2046_DFR_MODE,
XPT2046_Y = 0x50 | XPT2046_CONTROL | XPT2046_DFR_MODE,
XPT2046_Z1 = 0x30 | XPT2046_CONTROL | XPT2046_DFR_MODE,
XPT2046_Z2 = 0x40 | XPT2046_CONTROL | XPT2046_DFR_MODE,
};
#if !defined(XPT2046_Z1_THRESHOLD)
#define XPT2046_Z1_THRESHOLD 10
#endif
class XPT2046 {
private:
static bool isBusy() { return false; }
static uint16_t getRawData(const XPTCoordinate coordinate);
static bool isTouched();
static inline void DataTransferBegin() { WRITE(TOUCH_CS_PIN, LOW); };
static inline void DataTransferEnd() { WRITE(TOUCH_CS_PIN, HIGH); };
#if ENABLED(TOUCH_BUTTONS_HW_SPI)
static uint16_t HardwareIO(uint16_t data);
#endif
static uint16_t SoftwareIO(uint16_t data);
static uint16_t IO(uint16_t data = 0);
public:
#if ENABLED(TOUCH_BUTTONS_HW_SPI)
static SPIClass SPIx;
#endif
static void Init();
static bool getRawPoint(int16_t *x, int16_t *y);
};