* Raspberry Pi Pico 用の LCD 1.3 Waveshare のためのページ
-(by [[K]], 2024.08.20)
** (0)
-2024年7月下旬に https://www.amazon.co.jp/dp/B0982BMST9/ を買いました(1700円でした)。これで遊んでみます。
-https://www.waveshare.com/wiki/Pico-LCD-1.3 に情報があるようです。
** (1)
-https://www.waveshare.com/wiki/Pico-LCD-1.3 の Resource の Examples の Example demo をダウンロードして、アーカイブを解凍すると、 c / uf2 / LCD_1in3.uf2 があるので、これをpicoに入れてやると、デモが動く。動作テストができる。
- c / examples にコードはあるけど、setup()やloop()は見当たらない。
-なるほどー。Arduino IDEのC言語では static void func(int a) { ... } みたいに、関数にstatic属性を付けるとうまくコンパイルできないことがあるんだなー。
--これがわからなくて30分くらい悩んでしまった(笑)。
-書き方変更。
--[1]コンパイル済みのサンプルコードは動いた。
--[2]サンプルをソースからビルドする環境が用意できなかったので、初期化ルーチンを見よう見まねで作ってみた。
--[3]苦労したら、とりあえずコンパイルエラーが出ない程度にはなった。
--[4]さあ実行だ!・・・まあ当然だけど、見事にぶっ壊れて、picoに書き込むたびにArduino-IDEの再起動と、picoのBOTSEL押しながら再接続が必要になった。つらい。
--[5]なるほど、スタックを食いつぶしたせいでpicoがおかしくなっていたようだ。そのほか、picoをおかしくする重度のバグを直したら、IDEの再起動をしなくても平気になった。これではかどる!
--[6]しかしそれにしても画面には何も出ない。なんか出ないと前進しているのかどうかよくわからない。
--[7]お!ついになんか出たぞ!これはありがたい。・・・でも期待しているのとは違う・・・。
--[8]もしかしてエンディアンか?picoはビッグエンディアンじゃないのか??
--[9]エンディアンに依存しないように書き直したら・・・おお変わった!・・・うーん、まだおかしい。なんでそんな色になるんだよう。
--[10]な、なるほど・・・RGBではなく、BGRになっているっぽいな・・・。設定を直せば直るのだろうか。
--[11]適当にいじったら、RGBになった・・・かも?(オリジナルのソースコードのコメントの逆にしたらうまくいった!)
--[12]色については不満なし!しかし今度は座標系がおかしい。そういえばさっき、座標系のことが書いてあったな・・・。
--[13]座標系も直ったー。よっしゃー。
#define LCD_RST_PIN 12
#define LCD_DC_PIN 8
#define LCD_BL_PIN 13
#define LCD_CS_PIN 9
#define LCD_CLK_PIN 10
#define LCD_MOSI_PIN 11
#define LCD_SCL_PIN 7
#define LCD_SDA_PIN 6
void GPIO_Init()
{
pinMode(LCD_RST_PIN, OUTPUT);
pinMode(LCD_DC_PIN, OUTPUT);
pinMode(LCD_CS_PIN, OUTPUT);
pinMode(LCD_BL_PIN, OUTPUT);
digitalWrite(LCD_CS_PIN, 1);
digitalWrite(LCD_DC_PIN, 0);
digitalWrite(LCD_BL_PIN, 1);
}
int slice_num;
void Module_Init()
{
_spi_init(spi1, 10000 * 1000);
gpio_set_function(LCD_CLK_PIN, GPIO_FUNC_SPI);
gpio_set_function(LCD_MOSI_PIN, GPIO_FUNC_SPI);
// GPIO Config
GPIO_Init();
// PWM Config
gpio_set_function(LCD_BL_PIN, GPIO_FUNC_PWM);
slice_num = pwm_gpio_to_slice_num(LCD_BL_PIN);
pwm_set_wrap(slice_num, 100);
pwm_set_chan_level(slice_num, PWM_CHAN_B, 1); // setPwm(1);
pwm_set_clkdiv(slice_num,50);
pwm_set_enabled(slice_num, true);
//I2C Config
_i2c_init(i2c1,300*1000);
gpio_set_function(LCD_SDA_PIN,GPIO_FUNC_I2C);
gpio_set_function(LCD_SCL_PIN,GPIO_FUNC_I2C);
gpio_pull_up(LCD_SDA_PIN);
gpio_pull_up(LCD_SCL_PIN);
}
void LCD_1IN3_Reset()
{
digitalWrite(LCD_RST_PIN, 1);
delay(100);
digitalWrite(LCD_RST_PIN, 0);
delay(100);
digitalWrite(LCD_RST_PIN, 1);
delay(100);
}
void LCD_1IN3_SendCommand(uint8_t dat)
{
digitalWrite(LCD_DC_PIN, 0);
digitalWrite(LCD_CS_PIN, 0);
spi_write_blocking(spi1, &dat, 1);
digitalWrite(LCD_CS_PIN, 1);
}
void LCD_1IN3_SendData_8Bit(int dat)
{
uint8_t a[1];
a[0] = dat & 0xff;
digitalWrite(LCD_DC_PIN, 1);
digitalWrite(LCD_CS_PIN, 0);
spi_write_blocking(spi1, a, 1);
digitalWrite(LCD_CS_PIN, 1);
}
void LCD_1IN3_SentData_16Bit(int dat)
{
digitalWrite(LCD_DC_PIN, 1);
digitalWrite(LCD_CS_PIN, 0);
uint8_t a[2];
a[0] = (dat >> 8) & 0xff;
a[1] = dat & 0xff;
spi_write_blocking(spi1, a, 2);
digitalWrite(LCD_CS_PIN, 1);
}
void LCD_1IN3_InitReg()
{
LCD_1IN3_SendCommand(0x3A);
LCD_1IN3_SendData_8Bit(0x05);
LCD_1IN3_SendCommand(0xB2);
LCD_1IN3_SendData_8Bit(0x0C);
LCD_1IN3_SendData_8Bit(0x0C);
LCD_1IN3_SendData_8Bit(0x00);
LCD_1IN3_SendData_8Bit(0x33);
LCD_1IN3_SendData_8Bit(0x33);
LCD_1IN3_SendCommand(0xB7); //Gate Control
LCD_1IN3_SendData_8Bit(0x35);
LCD_1IN3_SendCommand(0xBB); //VCOM Setting
LCD_1IN3_SendData_8Bit(0x19);
LCD_1IN3_SendCommand(0xC0); //LCM Control
LCD_1IN3_SendData_8Bit(0x2C);
LCD_1IN3_SendCommand(0xC2); //VDV and VRH Command Enable
LCD_1IN3_SendData_8Bit(0x01);
LCD_1IN3_SendCommand(0xC3); //VRH Set
LCD_1IN3_SendData_8Bit(0x12);
LCD_1IN3_SendCommand(0xC4); //VDV Set
LCD_1IN3_SendData_8Bit(0x20);
LCD_1IN3_SendCommand(0xC6); //Frame Rate Control in Normal Mode
LCD_1IN3_SendData_8Bit(0x0F);
LCD_1IN3_SendCommand(0xD0); // Power Control 1
LCD_1IN3_SendData_8Bit(0xA4);
LCD_1IN3_SendData_8Bit(0xA1);
LCD_1IN3_SendCommand(0xE0); //Positive Voltage Gamma Control
LCD_1IN3_SendData_8Bit(0xD0);
LCD_1IN3_SendData_8Bit(0x04);
LCD_1IN3_SendData_8Bit(0x0D);
LCD_1IN3_SendData_8Bit(0x11);
LCD_1IN3_SendData_8Bit(0x13);
LCD_1IN3_SendData_8Bit(0x2B);
LCD_1IN3_SendData_8Bit(0x3F);
LCD_1IN3_SendData_8Bit(0x54);
LCD_1IN3_SendData_8Bit(0x4C);
LCD_1IN3_SendData_8Bit(0x18);
LCD_1IN3_SendData_8Bit(0x0D);
LCD_1IN3_SendData_8Bit(0x0B);
LCD_1IN3_SendData_8Bit(0x1F);
LCD_1IN3_SendData_8Bit(0x23);
LCD_1IN3_SendCommand(0xE1); //Negative Voltage Gamma Control
LCD_1IN3_SendData_8Bit(0xD0);
LCD_1IN3_SendData_8Bit(0x04);
LCD_1IN3_SendData_8Bit(0x0C);
LCD_1IN3_SendData_8Bit(0x11);
LCD_1IN3_SendData_8Bit(0x13);
LCD_1IN3_SendData_8Bit(0x2C);
LCD_1IN3_SendData_8Bit(0x3F);
LCD_1IN3_SendData_8Bit(0x44);
LCD_1IN3_SendData_8Bit(0x51);
LCD_1IN3_SendData_8Bit(0x2F);
LCD_1IN3_SendData_8Bit(0x1F);
LCD_1IN3_SendData_8Bit(0x1F);
LCD_1IN3_SendData_8Bit(0x20);
LCD_1IN3_SendData_8Bit(0x23);
LCD_1IN3_SendCommand(0x21); //Display Inversion On
LCD_1IN3_SendCommand(0x11); //Sleep Out
LCD_1IN3_SendCommand(0x29); //Display On
}
void LCD_1IN3_Init()
{
pwm_set_chan_level(slice_num, PWM_CHAN_B, 90); // setPwm(90);
//Hardware reset
LCD_1IN3_Reset();
//Set the resolution and scanning method of the screen
LCD_1IN3_SendCommand(0x36); //MX, MY, RGB mode
LCD_1IN3_SendData_8Bit(0x70); //0x08 set RGB
//Set the initialization register
LCD_1IN3_InitReg();
}
uint16_t col(int r, int g, int b)
// r5:g6:b5 形式を計算してエンディアンをひっくり返す.
{
return (b << 8 | g << 13 | g >> 3 | r << 3) & 0xffff;
}
void bitblt(int sx, int sy, int x0, int y0, uint16_t *buf, int xBufSiz)
{
LCD_1IN3_SendCommand(0x2A);
LCD_1IN3_SendData_8Bit(0x00);
LCD_1IN3_SendData_8Bit(x0);
LCD_1IN3_SendData_8Bit(0x00);
LCD_1IN3_SendData_8Bit(x0 + sx - 1);
//set the Y coordinates
LCD_1IN3_SendCommand(0x2B);
LCD_1IN3_SendData_8Bit(0x00);
LCD_1IN3_SendData_8Bit(y0);
LCD_1IN3_SendData_8Bit(0x00);
LCD_1IN3_SendData_8Bit(y0 + sy - 1);
LCD_1IN3_SendCommand(0X2C);
digitalWrite(LCD_DC_PIN, 1);
digitalWrite(LCD_CS_PIN, 0);
int i, j;
for (i = 0; i < sy; i++) {
spi_write_blocking(spi1, (uint8_t *) buf, sx * 2);
buf += xBufSiz;
}
digitalWrite(LCD_CS_PIN, 1);
LCD_1IN3_SendCommand(0X29);
}
// グラデーション表示.
void setup()
{
delay(100);
Module_Init();
pwm_set_chan_level(slice_num, PWM_CHAN_B, 50); // setPwm(50);
LCD_1IN3_Init();
uint16_t *buf = (uint16_t *) malloc(240 * 240 * 2);
int x, y, i = 0;
for (y = 0; y < 240; y++) {
for (x = 0; x < 240; x++) {
buf[i++] = buf[i++] = col((y + 144) / 12, (x + 144) / 6, 0);
}
}
bitblt(240, 240, 0, 0, buf, 240);
}
void loop() {
// put your main code here, to run repeatedly:
delay(1000);
}
** (2)
-回転キューブとボタン入力のテスト。ソースは上記のbitblt()までは共通。
// 回転キューブとボタン入力のテスト.
#define KeyA_Pin 15
uint16_t *gbuf;
int sqr[24] = { 7,6,2,3, 6,4,0,2, 1,0,4,5, 7,3,1,5, 3,2,0,1, 7,5,4,6 };
int vertx[8] = { -50, -50, -50, -50, +50, +50, +50, +50 };
int verty[8] = { -50, -50, +50, +50, -50, -50, +50, +50 };
int vertz[8] = { -50, +50, -50, +50, -50, +50, -50, +50 };
int thx = 0, thy = 0, thz = 0;
uint16_t colTbl[6];
int *buf0, *buf1;
void setup()
{
delay(100);
Module_Init();
pwm_set_chan_level(slice_num, PWM_CHAN_B, 50); // setPwm(50);
LCD_1IN3_Init();
pinMode(KeyA_Pin, INPUT_PULLUP);
gbuf = (uint16_t *) malloc(240 * 240 * 2);
int i;
for (i = 0; i < 240 * 240; i++) {
gbuf[i] = 0x0000;
}
bitblt(240, 240, 0, 0, gbuf, 240);
colTbl[0] = col(0x00 >> 3, 0x00 >> 2, 0xff >> 3);
colTbl[1] = col(0x00 >> 3, 0xff >> 2, 0x00 >> 3);
colTbl[2] = col(0x00 >> 3, 0xff >> 2, 0xff >> 3);
colTbl[3] = col(0xff >> 3, 0x00 >> 2, 0x00 >> 3);
colTbl[4] = col(0xff >> 3, 0x00 >> 2, 0xff >> 3);
colTbl[5] = col(0xff >> 3, 0xff >> 2, 0x00 >> 3);
buf0 = (int *) malloc(160 * 4);
buf1 = (int *) malloc(160 * 4);
}
int32_t aFf16Sin(int x) { return (int32_t) (sin(x * (2 * 3.14159265358979323 / 65536)) * 65536); }
int32_t aFf16Cos(int x) { return (int32_t) (cos(x * (2 * 3.14159265358979323 / 65536)) * 65536); }
int32_t aFf16Sqrt(int x) { return (int32_t) (sqrt(x * (1.0 / 65536)) * 65536); }
int32_t aMul64Shr(int i, int j, int k) { return ((int64_t) i) * ((int64_t) j) >> k; }
void aFillRect(int sx, int sy, int x0, int y0, uint16_t c)
{
uint16_t *p = gbuf + y0 * 240 + x0;
int i, j;
for (j = 0; j < sy; j++) {
for (i = 0; i < sx; i++) {
p[i] = c;
}
p += 240;
}
}
void loop()
{
if (digitalRead(KeyA_Pin) == 0) { thx = thy = thz = 0; } // Aボタンを押すと初期状態に戻る.
thx = (thx + 182) & 0xffff;
thy = (thy + 273) & 0xffff;
thz = (thz + 364) & 0xffff;
int xp = aFf16Cos(thx), xa = aFf16Sin(thx);
int yp = aFf16Cos(thy), ya = aFf16Sin(thy);
int zp = aFf16Cos(thz), za = aFf16Sin(thz);
int i, t, l, vx[8], vy[8], vz[8], scx[8], scy[8], centerz[7];
for (i = 0; i < 240 * 240; i++) {
gbuf[i] = 0x0000;
}
for (i = 0; i < 8; i++) {
int zt = vertz[i] * xp + verty[i] * xa;
int yt = verty[i] * xp - vertz[i] * xa;
int xt = vertx[i] * yp + aMul64Shr(zt, ya, 16);
vz[i] = aMul64Shr(zt, yp, 16) - vertx[i] * ya;
vx[i] = aMul64Shr(xt, zp, 16) - aMul64Shr(yt, za, 16); // z軸の周りに回す.
vy[i] = aMul64Shr(yt, zp, 16) + aMul64Shr(xt, za, 16);
t = 4915200 / ((vz[i] + 13107200) >> 16);
scx[i] = aMul64Shr(vx[i], t, 31) + 80;
scy[i] = aMul64Shr(vy[i], t, 31) + 80;
}
for (l = 0; l < 6 * 4; l = l + 4) {
centerz[l / 4] = vz[sqr[l]] + vz[sqr[l+1]] + vz[sqr[l+2]] + vz[sqr[l+3]] + 0x70000000;
}
centerz[6] = 0;
for (;; centerz[i] = 0) {
t = centerz[0]; i = 0;
for (l = 1; l < 7; l++) {
if (t <= centerz[l]) { t = centerz[l]; i = l; }
}
if (i >= 6) break;
l = i * 4; int l1 = l + 4, j = sqr[l + 3], p0x = scx[j], p0y = scy[j];
int ymin = 99999, ymax = 0, c = colTbl[i];
int *buf, dx, x, y, y0, y1, p1x, p1y;
for (; l < l1; l++) {
j = sqr[l]; int p1x = scx[j], p1y = scy[j];
if (ymin > p1y) { ymin = p1y; }
if (ymax < p1y) { ymax = p1y; }
if (p0y != p1y) {
if (p0y < p1y) {
buf = buf0; y0 = p0y; y1 = p1y; dx = p1x - p0x; x = p0x;
} else {
buf = buf1; y0 = p1y; y1 = p0y; dx = p0x - p1x; x = p1x;
}
dx = dx * 65536 / (y1 - y0);
x = x * 65536 + 0x8000;
if (dx < 0) { x = x - 0x10000; }
for (y = y0; y <= y1; y++) {
buf[y] = x >> 16;
x = x + dx;
}
}
p0x = p1x; p0y = p1y;
}
for (y = ymin; y <= ymax; y++) {
p0x = buf0[y];
p1x = buf1[y];
if (p0x <= p1x) {
aFillRect(p1x - p0x + 1, 1, p0x, y, c);
} else {
aFillRect(p0x - p1x + 1, 1, p1x, y, c);
}
}
}
bitblt(160, 160, 40, 40, gbuf, 240);
}