Raspberry Pi Picoでも動かすことの出来そうなタッチディスプレイをスイッチサイエンスさんで買いました。
Waveshare 3.5型静電容量式タッチスクリーンディスプレイ(320 x 480、SPI/I2C接続)
製造メーカーのWikiはこちらです。
3.5inch Capacitive Touch LCD Wiki
C++サンプルコード
時代の流れなのか、RaspberryPiだからなのか、WikiのPicoのサンプルコードはMicroPythonだけでした。
そこで、Pico C/C++ SDKでビルド可能な同等機能のC++コードを書いてみました。ついでに余っているCPUコアでLチカする機能も加えました。
冒頭画像はこちらのコードで動いている様子です。
CMakeLists.txtでは次のソースファイルとライブラリーを加えて下さい。
add_executable(プロジェクト名 main.cpp LocalTouchLcd.cpp )
target_link_libraries(プロジェクト名 pico_stdlib pico_multicore hardware_spi hardware_gpio hardware_i2c)
作成したC++のソースコードとヘッダーファイルを以下に記します。
main.cpp
#include <stdio.h>
#include "pico/stdlib.h"
#include "pico/multicore.h"
#include "LocalTouchLcd.h"
void Core1Main(void);
int main()
{
multicore_launch_core1(Core1Main);
//----------------
CLocalLcd *LLP = new CLocalLcd;
(LLP->Init)();
CLocalTouch *LTP = new CLocalTouch;
(LTP->Init)();
stdio_init_all();
//----------------
(LLP->LcdFill)(0xf800);
sleep_ms(1000);
(LLP->LcdFill)(0x07e0);
sleep_ms(1000);
(LLP->LcdFill)(0x001f);
sleep_ms(1000);
(LLP->LcdFill)(0xa33f);
//----------------
int nCnt = 0;
while(1) {
int nRet, nPosX, nPosY;
nRet = (LTP->GetTouchXy)(&nPosX, &nPosY);
if(nRet==0) {
nCnt ++;
(LLP->DrawSquare)(nPosX, nPosY, 4, 0xff00);
printf("point x=%03d y=%03d %d\n", nPosX, nPosY, nCnt);
}
}
//----------------
delete LTP;
delete LLP;
return(0);
}
void Core1Main(void)
{
gpio_init(PICO_DEFAULT_LED_PIN);
gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT);
while(1) {
gpio_put(PICO_DEFAULT_LED_PIN, 1);
sleep_ms(500);
gpio_put(PICO_DEFAULT_LED_PIN, 0);
sleep_ms(500);
}
}
LocalTouchLcd.cpp
#include <stdio.h>
#include <string.h>
#include "pico/stdlib.h"
#include "hardware/spi.h"
#include "hardware/i2c.h"
#include "LocalTouchLcd.h"
#define LDEF_LCD_WIDTH 320
#define LDEF_LCD_HEIGHT 480
//==============================================================================
// LCD class
//==============================================================================
#define LDEF_SPI_PORT spi1
#define LDEF_SPI_SCK 10
#define LDEF_SPI_MOSI 11
#define LDEF_SPI_MISO 12
#define LDEF_LCD_RST 13
#define LDEF_LCD_BL 15
#define LDEF_LCD_DC 14
#define LDEF_LCD_CS 9
CLocalLcd::CLocalLcd()
{
}
CLocalLcd::~CLocalLcd()
{
}
void CLocalLcd::Init(void)
{
InitRpp();
InitLcd();
}
void CLocalLcd::LcdFill(int nColor)
{
int nLoop;
unsigned char *bpArray = new unsigned char [2 * LDEF_LCD_WIDTH];
unsigned char bUpper = (unsigned char)((nColor>>8) & 0xff);
unsigned char bLower = (unsigned char)(nColor & 0xff);
for(nLoop=0; nLoop<LDEF_LCD_WIDTH; nLoop++) {
(bpArray[2*nLoop]) = bUpper;
(bpArray[(2*nLoop)+1]) = bLower;
}
SetWindows(0, 0, LDEF_LCD_WIDTH, LDEF_LCD_HEIGHT);
gpio_put(LDEF_LCD_DC, 1);
gpio_put(LDEF_LCD_CS, 0);
for(nLoop=0; nLoop<LDEF_LCD_HEIGHT; nLoop++) {
SpiWriteBase(bpArray, (2 * LDEF_LCD_WIDTH));
}
gpio_put(LDEF_LCD_CS, 1);
delete [] bpArray;
}
void CLocalLcd::DrawSquare(int nPosX, int nPosY, int nSize, int nColor)
{
int nXstart = nPosX;
int nYstart = nPosY;
int nXend = nXstart + nSize;
int nYend = nYstart + nSize;
unsigned char sArray[] = {(unsigned char)(nColor>>8), (unsigned char)(nColor&0xff)};
SetWindows(nXstart, nYstart, nXend, nYend);
gpio_put(LDEF_LCD_DC, 1);
gpio_put(LDEF_LCD_CS, 0);
int nPixelAll = (nSize+1) * (nSize+1);
for(int nLoop=0; nLoop<nPixelAll; nLoop++) {
SpiWriteBase(sArray, sizeof(sArray));
}
gpio_put(LDEF_LCD_CS, 1);
}
void CLocalLcd::InitRpp(void)
{
gpio_init(LDEF_LCD_CS);
gpio_set_dir(LDEF_LCD_CS, GPIO_OUT);
gpio_init(LDEF_LCD_RST);
gpio_set_dir(LDEF_LCD_RST, GPIO_OUT);
gpio_init(LDEF_LCD_BL);
gpio_set_dir(LDEF_LCD_BL, GPIO_OUT);
gpio_put(LDEF_LCD_BL, 1);
gpio_put(LDEF_LCD_CS, 1);
spi_init(LDEF_SPI_PORT, (10*1000*1000));
gpio_set_function(LDEF_SPI_MISO, GPIO_FUNC_SPI);
gpio_set_function(LDEF_SPI_SCK, GPIO_FUNC_SPI);
gpio_set_function(LDEF_SPI_MOSI, GPIO_FUNC_SPI);
gpio_init(LDEF_LCD_DC);
gpio_set_dir(LDEF_LCD_DC, GPIO_OUT);
gpio_put(LDEF_LCD_DC, 1);
}
void CLocalLcd::InitLcd(void)
{
gpio_put(LDEF_LCD_RST, 0);
busy_wait_us(100*1000);
gpio_put(LDEF_LCD_RST, 1);
busy_wait_us(10*1000);
SpiWriteCmd(0x11);
busy_wait_us(120*1000);
SpiWriteCmd(0x36);
SpiWriteData(0x08);
SpiWriteCmd(0x3A);
SpiWriteData(0x05);
SpiWriteCmd(0xF0);
SpiWriteData(0xC3);
SpiWriteCmd(0xF0);
SpiWriteData(0x96);
SpiWriteCmd(0xB4);
SpiWriteData(0x01);
SpiWriteCmd(0xB7);
SpiWriteData(0xC6);
SpiWriteCmd(0xC0);
SpiWriteData(0x80);
SpiWriteData(0x45);
SpiWriteCmd(0xC1);
SpiWriteData(0x13);
SpiWriteCmd(0xC2);
SpiWriteData(0xA7);
SpiWriteCmd(0xC5);
SpiWriteData(0x0A);
SpiWriteCmd(0xE8);
SpiWriteData(0x40);
SpiWriteData(0x8A);
SpiWriteData(0x00);
SpiWriteData(0x00);
SpiWriteData(0x29);
SpiWriteData(0x19);
SpiWriteData(0xA5);
SpiWriteData(0x33);
SpiWriteCmd(0xE0);
SpiWriteData(0xD0);
SpiWriteData(0x08);
SpiWriteData(0x0F);
SpiWriteData(0x06);
SpiWriteData(0x06);
SpiWriteData(0x33);
SpiWriteData(0x30);
SpiWriteData(0x33);
SpiWriteData(0x47);
SpiWriteData(0x17);
SpiWriteData(0x13);
SpiWriteData(0x13);
SpiWriteData(0x2B);
SpiWriteData(0x31);
SpiWriteCmd(0xE1);
SpiWriteData(0xD0);
SpiWriteData(0x0A);
SpiWriteData(0x11);
SpiWriteData(0x0B);
SpiWriteData(0x09);
SpiWriteData(0x07);
SpiWriteData(0x2F);
SpiWriteData(0x33);
SpiWriteData(0x47);
SpiWriteData(0x38);
SpiWriteData(0x15);
SpiWriteData(0x16);
SpiWriteData(0x2C);
SpiWriteData(0x32);
SpiWriteCmd(0xF0);
SpiWriteData(0x3C);
SpiWriteCmd(0xF0);
SpiWriteData(0x69);
busy_wait_us(120*1000);
SpiWriteCmd(0x21);
SpiWriteCmd(0x29);
}
void CLocalLcd::SetWindows(int nXstart, int nYstart, int nXend, int nYend)
{
unsigned char bData;
SpiWriteCmd(0x2A);
bData = (unsigned char)((nXstart >> 8) & 0xff);
SpiWriteData(bData);
bData = (unsigned char)(nXstart & 0xff);
SpiWriteData(bData);
bData = (unsigned char)((nXend >> 8) & 0xff);
SpiWriteData(bData);
bData = (unsigned char)(nXend & 0xff);
SpiWriteData(bData);
SpiWriteCmd(0x2B);
bData = (unsigned char)((nYstart >> 8) & 0xff);
SpiWriteData(bData);
bData = (unsigned char)(nYstart & 0xff);
SpiWriteData(bData);
bData = (unsigned char)((nYend >> 8) & 0xff);
SpiWriteData(bData);
bData = (unsigned char)(nYend & 0xff);
SpiWriteData(bData);
SpiWriteCmd(0x2C);
}
void CLocalLcd::SpiWriteBase(unsigned char *bpTxBuf, int nLen)
{
spi_write_blocking (LDEF_SPI_PORT, bpTxBuf, nLen);
}
void CLocalLcd::SpiWriteCmd(unsigned char bCmd)
{
gpio_put(LDEF_LCD_DC, 0);
gpio_put(LDEF_LCD_CS, 0);
SpiWriteBase(&bCmd, 1);
}
void CLocalLcd::SpiWriteData(unsigned char bData)
{
gpio_put(LDEF_LCD_DC, 1);
gpio_put(LDEF_LCD_CS, 0);
SpiWriteBase(&bData, 1);
gpio_put(LDEF_LCD_CS, 1);
}
//==============================================================================
// Touch class
//==============================================================================
#define LDEF_I2C_PORT i2c1
#define LDEF_I2C_ADDRESS 0x38
#define LDEF_I2C_SDA 6
#define LDEF_I2C_SCL 7
#define LDEF_I2C_IRQ 8
#define LDEF_I2C_RST 5
#define LDEF_I2C_REG_NUM 0X02
#define LDEF_I2C_REG_XY 0X03
static CLocalTouch *sctp;
CLocalTouch::CLocalTouch()
{
CP = new tagClassParameter;
memset(CP, 0, sizeof(tagClassParameter));
sctp = this;
}
CLocalTouch::~CLocalTouch()
{
delete CP;
}
void CLocalTouch::Init(void)
{
i2c_init(LDEF_I2C_PORT, 400 * 1000);
gpio_set_function(LDEF_I2C_SDA, GPIO_FUNC_I2C);
gpio_set_function(LDEF_I2C_SCL, GPIO_FUNC_I2C);
gpio_pull_up(LDEF_I2C_SDA);
gpio_pull_up(LDEF_I2C_SCL);
gpio_init(LDEF_I2C_IRQ);
gpio_set_dir(LDEF_I2C_IRQ, GPIO_IN);
gpio_pull_up(LDEF_I2C_IRQ);
gpio_init(LDEF_I2C_RST);
gpio_set_dir(LDEF_I2C_RST, GPIO_OUT);
gpio_put(LDEF_I2C_RST, 1);
sleep_ms(200);
gpio_put(LDEF_I2C_RST, 0);
sleep_ms(200);
gpio_put(LDEF_I2C_RST, 1);
sleep_ms(200);
gpio_set_irq_enabled_with_callback(LDEF_I2C_IRQ, GPIO_IRQ_EDGE_FALL, true, CLocalTouch::IrqHandler);
}
int CLocalTouch::GetTouchXy(int *npOutX, int *npOutY)
{
if((CP->nPointCount)==0) {
return(-1);
}
(CP->nPointCount) = 0;
(*npOutX) = (CP->nPosX);
(*npOutY) = (CP->nPosY);
return(0);
}
void CLocalTouch::IrqHandler(uint gpio, uint32_t events)
{
unsigned char bCmd;
unsigned char sRxBuf[64];
int nRet, nLen, nLocalPC;
//--------
bCmd = LDEF_I2C_REG_NUM;
i2c_write_blocking(LDEF_I2C_PORT, LDEF_I2C_ADDRESS, &bCmd, 1, false);
nRet = i2c_read_blocking(LDEF_I2C_PORT, LDEF_I2C_ADDRESS, sRxBuf, 1, false);
if(nRet==0) {
return;
}
nLocalPC = (int)(sRxBuf[0]);
nLen = (int)(sRxBuf[0]) * 6;
//--------
bCmd = LDEF_I2C_REG_XY;
i2c_write_blocking(LDEF_I2C_PORT, LDEF_I2C_ADDRESS, &bCmd, 1, false);
nRet = i2c_read_blocking(LDEF_I2C_PORT, LDEF_I2C_ADDRESS, sRxBuf, nLen, false);
if(nRet==0) {
return;
}
//--------
(sctp->CP->nPosX) = LDEF_LCD_WIDTH - (((int)((sRxBuf[0])&0x0f) << 8) + (int)(sRxBuf[1]));
(sctp->CP->nPosY) = ((int)((sRxBuf[2])&0x0f) << 8) + (int)(sRxBuf[3]);
(sctp->CP->nPointCount) = nLocalPC;
//printf("tpirq x=%03d y=%03d\n", (sctp->CP->nPosX), (sctp->CP->nPosY));
}
LocalTouchLcd.h
class CLocalLcd {
public:
CLocalLcd();
virtual ~CLocalLcd();
void Init(void);
void LcdFill(int nColor);
void DrawSquare(int nPosX, int nPosY, int nSize, int nColor);
private:
void InitRpp(void);
void InitLcd(void);
void SetWindows(int nXstart, int nYstart, int nXend, int nYend);
void SpiWriteBase(unsigned char *bpTxBuf, int nLen);
void SpiWriteCmd(unsigned char bCmd);
void SpiWriteData(unsigned char bData);
};
class CLocalTouch {
public:
CLocalTouch();
virtual ~CLocalTouch();
void Init(void);
int GetTouchXy(int *npOutX, int *npOutY);
typedef struct {
int nPointCount;
int nPosX;
int nPosY;
} tagClassParameter;
tagClassParameter *CP;
private:
static void IrqHandler(uint gpio, uint32_t events);
};
続きもご覧下さい。
Raspberry Pi Pico C/C++ SDK で LVGL
