minimacplus/components/tme-esp32/mipi_lcd.c

279 lines
7.9 KiB
C

/* SPI Master example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "driver/spi_master.h"
#include "soc/gpio_struct.h"
#include "driver/gpio.h"
#include "esp_heap_alloc_caps.h"
#include "mpumouse.h"
#include "mouse.h"
#include "mipi.h"
#include "mipi_dsi.h"
typedef struct {
uint8_t type;
uint8_t addr;
uint8_t len;
uint8_t data[16];
} DispPacket;
//Copied from the X163QLN01 appliation note.
DispPacket initPackets[]={
#if 0
{0x39, 0xF0, 5, {0x55, 0x55, 0x55, 0x55, 0x55}},
{0x39, 0xBD, 5, {0x01, 0x01, 0x01, 0x01, 0x01}},
{0x39, 0xBE, 5, {0x01, 0x01, 0x01, 0x01, 0x01}},
{0x39, 0xBF, 5, {0x01, 0x01, 0x01, 0x01, 0x01}},
{0x39, 0xBB, 3, {0x07, 0x07, 0x07}},
{0x39, 0xD0, 1, {0x00}},
{0x39, 0xD1, 3, {0x00, 0x00, 0x00}},
{0x39, 0xD2, 3, {0x00, 0x00, 0x00}},
{0x39, 0xD3, 3, {0x00, 0x00, 0x00}},
{0x39, 0xC7, 1, {0x40}},
{0x39, 0xF0, 5, {0x55, 0x55, 0x55, 0x55, 0x55}},
{0x15, 0xEB, 1, {0x02}},
{0x15, 0xF5, 1, {0x10}},
{0x39, 0xED, 8, {0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48}},
{0x39, 0xC7, 8, {0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F}},
{0x39, 0xFE, 2, {0x08, 0x08}},
{0x39, 0xC3, 3, {0xF2, 0xF2, 0xF2}},
{0x39, 0xE9, 3, {0x00, 0x00, 0x00}},
{0x15, 0xCA, 1, {0x04}},
{0x39, 0xF0, 5, {0x55, 0x55, 0x55, 0x55, 0x55}},
{0x39, 0xB0, 3, {0x00, 0x00, 0x00}},
{0x39, 0xB1, 3, {0x05, 0x05, 0x05}},
{0x39, 0xB2, 3, {0x01, 0x01, 0x01}},
{0x39, 0xB4, 3, {0x07, 0x07, 0x07}},
{0x39, 0xB5, 3, {0x03, 0x03, 0x03}},
{0x39, 0xB6, 3, {0x55, 0x55, 0x55}},
{0x39, 0xB7, 3, {0x35, 0x35, 0x35}},
{0x39, 0xB8, 3, {0x23, 0x23, 0x23}},
{0x39, 0xB9, 3, {0x03, 0x03, 0x03}},
{0x39, 0xBA, 3, {0x03, 0x03, 0x03}},
{0x39, 0xBE, 3, {0x32, 0x32, 0x32}},
{0x39, 0xC2, 12, {0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B}},
{0x39, 0xCF, 7, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}},
{0x15, 0x35, 1, {0x00}},
{0x15, 0x36, 1, {0x00}},
{0x15, 0xC0, 1, {0x28}},
{0x32, 0x00, 1, {0x00}},
{0x15, 0x51, 1, {0x00}},
{0x05, 0x11, 1, {0x00}},
{0x05, 0x29, 1, {0x00}},
#endif
#if 0
{0x39, 0xF0, 5, {0x55, 0x55, 0x55, 0x55, 0x55}},
{0x39, 0xBD, 5, {0x01, 0x01, 0x01, 0x01, 0x01}},
{0x39, 0xBE, 5, {0x01, 0x01, 0x01, 0x01, 0x01}},
{0x39, 0xBF, 5, {0x01, 0x01, 0x01, 0x01, 0x01}},
{0x39, 0xBB, 3, {0x07, 0x07, 0x07}},
{0x39, 0xD0, 1, {0x00}},
{0x39, 0xD1, 3, {0x00, 0x00, 0x00}},
{0x39, 0xD2, 3, {0x00, 0x00, 0x00}},
{0x39, 0xD3, 3, {0x00, 0x00, 0x00}},
{0x39, 0xC7, 1, {0x40}},
{0x39, 0xF0, 5, {0x55, 0x55, 0x55, 0x55, 0x55}},
{0x15, 0xEB, 1, {0x02}},
{0x15, 0xF5, 1, {0x10}},
{0x39, 0xED, 8, {0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48}},
{0x39, 0xC7, 8, {0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F}},
{0x39, 0xFE, 2, {0x08, 0x08}},
{0x39, 0xC3, 3, {0xF2, 0xF2, 0xF2}},
{0x39, 0xE9, 3, {0x00, 0x00, 0x00}},
{0x15, 0xCA, 1, {0x04}},
{0x39, 0xF0, 5, {0x55, 0x55, 0x55, 0x55, 0x55}},
{0x39, 0xB0, 3, {0x00, 0x00, 0x00}},
{0x39, 0xB1, 3, {0x05, 0x05, 0x05}},
{0x39, 0xB2, 3, {0x01, 0x01, 0x01}},
{0x39, 0xB4, 3, {0x07, 0x07, 0x07}},
{0x39, 0xB5, 3, {0x03, 0x03, 0x03}},
{0x39, 0xB6, 3, {0x55, 0x55, 0x55}},
{0x39, 0xB7, 3, {0x35, 0x35, 0x35}},
{0x39, 0xB8, 3, {0x23, 0x23, 0x23}},
{0x39, 0xB9, 3, {0x03, 0x03, 0x03}},
{0x39, 0xBA, 3, {0x03, 0x03, 0x03}},
{0x39, 0xBE, 3, {0x32, 0x32, 0x32}},
{0x39, 0xC2, 12, {0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B}},
{0x39, 0xCF, 7, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}},
{0x15, 0x35, 1, {0x00}},
{0x15, 0x36, 1, {0x00}},
{0x15, 0xC0, 1, {0x28}},
{0x32, 0x00, 1, {0x00}},
{0x15, 0x51, 1, {0x00}},
{0x05, 0x11, 1, {0x00}},
{0x05, 0x29, 1, {0x00}},
#endif
#if 1
{0x39, 0xF0, 5, {0x55, 0xAA, 0x52, 0x08, 0x00}},
{0x39, 0xBD, 5, {0x01, 0x90, 0x14, 0x14, 0x00}},
{0x39, 0xBE, 5, {0x01, 0x90, 0x14, 0x14, 0x01}},
{0x39, 0xBF, 5, {0x01, 0x90, 0x14, 0x14, 0x00}},
{0x39, 0xBB, 3, {0x07, 0x07, 0x07}},
{0x39, 0xC7, 1, {0x40}},
{0x39, 0xF0, 5, {0x55, 0xAA, 0x52, 0x80, 0x02}},
{0x39, 0xFE, 2, {0x08, 0x50}},
{0x39, 0xC3, 3, {0xF2, 0x95, 0x04}},
{0x15, 0xCA, 1, {0x04}},
{0x39, 0xF0, 5, {0x55, 0xAA, 0x52, 0x08, 0x01}},
{0x39, 0xB0, 3, {0x03, 0x03, 0x03}},
{0x39, 0xB1, 3, {0x05, 0x05, 0x05}},
{0x39, 0xB2, 3, {0x01, 0x01, 0x01}},
{0x39, 0xB4, 3, {0x07, 0x07, 0x07}},
{0x39, 0xB5, 3, {0x05, 0x05, 0x05}},
{0x39, 0xB6, 3, {0x53, 0x53, 0x53}},
{0x39, 0xB7, 3, {0x33, 0x33, 0x33}},
{0x39, 0xB8, 3, {0x23, 0x23, 0x23}},
{0x39, 0xB9, 3, {0x03, 0x03, 0x03}},
{0x39, 0xBA, 3, {0x13, 0x13, 0x13}},
{0x39, 0xBE, 3, {0x22, 0x30, 0x70}},
{0x39, 0xCF, 7, {0xFF, 0xD4, 0x95, 0xEF, 0x4F, 0x00, 0x04}},
{0x15, 0x35, 1, {0x01}}, //
{0x15, 0x36, 1, {0x00}}, //
{0x15, 0xC0, 1, {0x20}}, //
{0x39, 0xC2, 6, {0x17, 0x17, 0x17, 0x17, 0x17, 0x0B}},
{0x32, 0, 0, {0}},
{0x05, 0x11, 1, {0x00}}, //exit_sleep_mode
{0x05, 0x29, 1, {0x00}}, //turn display on
#endif
{0x15, 0x3A, 1, {0x55}}, //16-bit mode
// {0x29, 0x2B, 4, {0x00, 0x00, 0x00, 0xEF}},
{0,0,0,{0}}
};
//Returns 0-1024
int findMacVal(uint8_t *data, int x, int y) {
int a,b,c,d;
int v=0;
int rx=x/32;
int ry=y/32;
if (ry>=342) return 0;
a=data[ry*(512/8)+rx/8]&(1<<(7-(rx&7)));
rx++;
b=data[ry*(512/8)+rx/8]&(1<<(7-(rx&7)));
rx--; ry++;
if (ry<342) {
c=data[ry*(512/8)+rx/8]&(1<<(7-(rx&7)));
rx++;
d=data[ry*(512/8)+rx/8]&(1<<(7-(rx&7)));
} else {
c=1;
d=1;
}
if (!a) v+=(31-(x&31))*(31-(y&31));
if (!b) v+=(x&31)*(31-(y&31));
if (!c) v+=(31-(x&31))*(y&31);
if (!d) v+=(x&31)*(y&31);
return v;
}
// Even pixels: a
// RRBB
// GG
//
// Odd pixels: b
// GG
// RRBB
//
// Even lines start with an even pixel, odd lines with an odd pixel.
//
// Due to the weird buildup, a horizontal subpixel actually is 1/3rd real pixel wide!
int findPixelVal(uint8_t *data, int x, int y) {
int sx=(x*51); //32th is 512/320 -> scale 512 mac screen to 320 width
int sy=(y*51);
//sx and sy are now 27.5 fixed point values for the 'real' mac-like components
int r,g,b;
if (((x+y)&1)) {
//pixel a
r=findMacVal(data, sx, sy);
b=findMacVal(data, sx+(51/3)*2, sy);
g=findMacVal(data, sx+(51/3), sy+(51/2));
} else {
//pixel b
r=findMacVal(data, sx, sy+10);
b=findMacVal(data, sx+(51/3)*2, sy+(51/1));
g=findMacVal(data, sx+(51/3), sy);
}
return ((r>>5)<<0)|((g>>4)<<5)|((b>>5)<<11);
}
volatile static uint8_t *currFbPtr=NULL;
SemaphoreHandle_t dispSem = NULL;
void IRAM_ATTR displayTask(void *arg) {
mipiInit();
for (int i=0; initPackets[i].type!=0; i++) {
if (initPackets[i].type==0x39 || initPackets[i].type==0x29) {
uint8_t data[17];
data[0]=initPackets[i].addr;
memcpy(data+1, initPackets[i].data, 16);
mipiDsiSendLong(initPackets[i].type, data, initPackets[i].len+1);
} else {
uint8_t data[2]={initPackets[i].addr, initPackets[i].data[0]};
mipiDsiSendShort(initPackets[i].type, data, initPackets[i].len+1);
if (initPackets[i].type==5) vTaskDelay(300/portTICK_RATE_MS);
}
}
printf("Inited.\n");
uint8_t img[641];
while(1) {
xSemaphoreTake(dispSem, portMAX_DELAY);
uint8_t *myData=(uint8_t*)currFbPtr;
uint8_t img[641];
img[0]=0x2c;
for (int j=0; j<320; j++) {
uint8_t *p=&img[1];
for (int i=0; i<320; i++) {
int v=findPixelVal(myData, i, j);
*p++=(v&0xff);
*p++=(v>>8);
}
mipiDsiSendLong(0x39, img, sizeof(img)+4);
img[0]=0x3c;
}
}
}
void dispDraw(uint8_t *mem) {
int dx, dy, btn;
currFbPtr=mem;
xSemaphoreGive(dispSem);
// mpuMouseGetDxDyBtn(&dx, &dy, &btn);
// mouseMove(dx, dy, btn);
}
void dispInit() {
printf("spi_lcd_init()\n");
dispSem=xSemaphoreCreateBinary();
#if CONFIG_FREERTOS_UNICORE
xTaskCreatePinnedToCore(&displayTask, "display", 3000, NULL, 5, NULL, 0);
#else
xTaskCreatePinnedToCore(&displayTask, "display", 3000, NULL, 5, NULL, 1);
#endif
}