mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2026-01-29 22:00:54 +03:00
Complete display + add JPEG
This commit is contained in:
@@ -165,6 +165,25 @@ static void IRAM_ATTR DrawPixel1Fast( struct GDS_Device* Device, int X, int Y, i
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ClearWindow( struct GDS_Device* Device, int x1, int y1, int x2, int y2, int Color ) {
|
||||||
|
uint8_t _Color = Color == GDS_COLOR_BLACK ? 0: 0xff;
|
||||||
|
uint8_t Width = Device->Width >> 3;
|
||||||
|
uint8_t *optr = Device->Framebuffer;
|
||||||
|
|
||||||
|
for (int r = y1; r <= y2; r++) {
|
||||||
|
int c = x1;
|
||||||
|
// for a row that is not on a boundary, not column opt can be done, so handle all columns on that line
|
||||||
|
while (c & 0x07 && c <= x2) DrawPixel1Fast( Device, c++, r, Color );
|
||||||
|
// at this point we are aligned on column boundary
|
||||||
|
int chunk = (x2 - c + 1) >> 3;
|
||||||
|
memset(optr + Width * r + (c >> 3), _Color, chunk );
|
||||||
|
c += chunk * 8;
|
||||||
|
while (c <= x2) DrawPixel1Fast( Device, c++, r, Color );
|
||||||
|
}
|
||||||
|
|
||||||
|
Device->Dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
static void DrawBitmapCBR(struct GDS_Device* Device, uint8_t *Data, int Width, int Height, int Color ) {
|
static void DrawBitmapCBR(struct GDS_Device* Device, uint8_t *Data, int Width, int Height, int Color ) {
|
||||||
uint8_t *optr = Device->Framebuffer;
|
uint8_t *optr = Device->Framebuffer;
|
||||||
|
|
||||||
@@ -312,6 +331,7 @@ struct GDS_Device* SSD132x_Detect(char *Driver, struct GDS_Device* Device) {
|
|||||||
Device->Update = Update1;
|
Device->Update = Update1;
|
||||||
Device->DrawPixelFast = DrawPixel1Fast;
|
Device->DrawPixelFast = DrawPixel1Fast;
|
||||||
Device->DrawBitmapCBR = DrawBitmapCBR;
|
Device->DrawBitmapCBR = DrawBitmapCBR;
|
||||||
|
Device->ClearWindow = ClearWindow;
|
||||||
} else {
|
} else {
|
||||||
Device->Depth = 4;
|
Device->Depth = 4;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,21 +69,22 @@ void GDS_ClearWindow( struct GDS_Device* Device, int x1, int y1, int x2, int y2,
|
|||||||
memset( Device->Framebuffer, Color == GDS_COLOR_BLACK ? 0 : 0xff, Device->FramebufferSize );
|
memset( Device->Framebuffer, Color == GDS_COLOR_BLACK ? 0 : 0xff, Device->FramebufferSize );
|
||||||
} else {
|
} else {
|
||||||
uint8_t _Color = Color == GDS_COLOR_BLACK ? 0: 0xff;
|
uint8_t _Color = Color == GDS_COLOR_BLACK ? 0: 0xff;
|
||||||
uint8_t Width = Device->Width;
|
uint8_t Width = Device->Width >> 3;
|
||||||
|
uint8_t *optr = Device->Framebuffer;
|
||||||
// try to do byte processing as much as possible
|
// try to do byte processing as much as possible
|
||||||
for (int r = y1; r <= y2;) {
|
for (int r = y1; r <= y2;) {
|
||||||
int c = x1;
|
int c = x1;
|
||||||
// for a row that is not on a boundary, no optimization possible
|
// for a row that is not on a boundary, no optimization possible
|
||||||
while (r & 0x07 && r <= y2) {
|
while (r & 0x07 && r <= y2) {
|
||||||
for (c = x1; c <= x2; c++) GDS_DrawPixelFast( Device, c, r, Color);
|
for (c = x1; c <= x2; c++) GDS_DrawPixelFast( Device, c, r, Color );
|
||||||
r++;
|
r++;
|
||||||
}
|
}
|
||||||
// go fast if we have more than 8 lines to write
|
// go fast if we have more than 8 lines to write
|
||||||
if (r + 8 < y2) {
|
if (r + 8 <= y2) {
|
||||||
memset(Device->Framebuffer + Width * r / 8 + x1, _Color, x2 - x1 + 1);
|
memset(optr + Width * r + x1, _Color, x2 - x1 + 1);
|
||||||
r += 8;
|
r += 8;
|
||||||
} else while (r <= y2) {
|
} else while (r <= y2) {
|
||||||
for (c = x1; c <= x2; c++) GDS_DrawPixelFast( Device, c, r, Color);
|
for (c = x1; c <= x2; c++) GDS_DrawPixelFast( Device, c, r, Color );
|
||||||
r++;
|
r++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -95,12 +96,13 @@ void GDS_ClearWindow( struct GDS_Device* Device, int x1, int y1, int x2, int y2,
|
|||||||
} else {
|
} else {
|
||||||
uint8_t _Color = Color | (Color << 4);
|
uint8_t _Color = Color | (Color << 4);
|
||||||
uint8_t Width = Device->Width;
|
uint8_t Width = Device->Width;
|
||||||
|
uint8_t *optr = Device->Framebuffer;
|
||||||
// try to do byte processing as much as possible
|
// try to do byte processing as much as possible
|
||||||
for (int r = y1; r <= y2; r++) {
|
for (int r = y1; r <= y2; r++) {
|
||||||
int c = x1;
|
int c = x1;
|
||||||
if (c & 0x01) GDS_DrawPixelFast( Device, c++, r, Color);
|
if (c & 0x01) GDS_DrawPixelFast( Device, c++, r, Color);
|
||||||
int chunk = (x2 - c + 1) >> 1;
|
int chunk = (x2 - c + 1) >> 1;
|
||||||
memset(Device->Framebuffer + ((r * Width + c) >> 1), _Color, chunk);
|
memset(optr + ((r * Width + c) >> 1), _Color, chunk);
|
||||||
if (c + chunk <= x2) GDS_DrawPixelFast( Device, x2, r, Color);
|
if (c + chunk <= x2) GDS_DrawPixelFast( Device, x2, r, Color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ extern "C" {
|
|||||||
|
|
||||||
struct GDS_Device;
|
struct GDS_Device;
|
||||||
|
|
||||||
bool GDS_I2CInit( int PortNumber, int SDA, int SCL );
|
bool GDS_I2CInit( int PortNumber, int SDA, int SCL, int speed );
|
||||||
bool GDS_I2CAttachDevice( struct GDS_Device* Device, int Width, int Height, int I2CAddress, int RSTPin );
|
bool GDS_I2CAttachDevice( struct GDS_Device* Device, int Width, int Height, int I2CAddress, int RSTPin );
|
||||||
|
|
||||||
bool GDS_SPIInit( int SPI, int DC );
|
bool GDS_SPIInit( int SPI, int DC );
|
||||||
|
|||||||
225
components/display/core/gds_image.c
Normal file
225
components/display/core/gds_image.c
Normal file
@@ -0,0 +1,225 @@
|
|||||||
|
#include <string.h>
|
||||||
|
#include "math.h"
|
||||||
|
#include "esp32/rom/tjpgd.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
|
||||||
|
#include "gds.h"
|
||||||
|
#include "gds_private.h"
|
||||||
|
#include "gds_image.h"
|
||||||
|
|
||||||
|
const char TAG[] = "ImageDec";
|
||||||
|
|
||||||
|
#define SCRATCH_SIZE 3100
|
||||||
|
|
||||||
|
//Data that is passed from the decoder function to the infunc/outfunc functions.
|
||||||
|
typedef struct {
|
||||||
|
const unsigned char *InData; // Pointer to jpeg data
|
||||||
|
int InPos; // Current position in jpeg data
|
||||||
|
int Width, Height;
|
||||||
|
union {
|
||||||
|
uint16_t *OutData; // Decompress
|
||||||
|
struct { // DirectDraw
|
||||||
|
struct GDS_Device * Device;
|
||||||
|
int XOfs, YOfs;
|
||||||
|
int Depth;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} JpegCtx;
|
||||||
|
|
||||||
|
static unsigned InHandler(JDEC *Decoder, uint8_t *Buf, unsigned Len) {
|
||||||
|
JpegCtx *Context = (JpegCtx*) Decoder->device;
|
||||||
|
if (Buf) memcpy(Buf, Context->InData + Context->InPos, Len);
|
||||||
|
Context->InPos += Len;
|
||||||
|
return Len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned OutHandler(JDEC *Decoder, void *Bitmap, JRECT *Frame) {
|
||||||
|
JpegCtx *Context = (JpegCtx*) Decoder->device;
|
||||||
|
uint8_t *Pixels = (uint8_t*) Bitmap;
|
||||||
|
|
||||||
|
for (int y = Frame->top; y <= Frame->bottom; y++) {
|
||||||
|
if (y < Context->YOfs) continue;
|
||||||
|
for (int x = Frame->left; x <= Frame->right; x++) {
|
||||||
|
if (x < Context->XOfs) continue;
|
||||||
|
// Convert the 888 to RGB565
|
||||||
|
uint16_t Value = (*Pixels++ & ~0x07) << 8;
|
||||||
|
Value |= (*Pixels++ & ~0x03) << 3;
|
||||||
|
Value |= *Pixels++ >> 3;
|
||||||
|
Context->OutData[Context->Width * y + x] = Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned OutHandlerDirect(JDEC *Decoder, void *Bitmap, JRECT *Frame) {
|
||||||
|
JpegCtx *Context = (JpegCtx*) Decoder->device;
|
||||||
|
uint8_t *Pixels = (uint8_t*) Bitmap;
|
||||||
|
int Shift = 8 - Context->Depth;
|
||||||
|
|
||||||
|
for (int y = Frame->top; y <= Frame->bottom; y++) {
|
||||||
|
for (int x = Frame->left; x <= Frame->right; x++) {
|
||||||
|
// Convert the 888 to RGB565
|
||||||
|
int Value = ((Pixels[0]*11 + Pixels[1]*59 + Pixels[2]*30) / 100) >> Shift;
|
||||||
|
Pixels += 3;
|
||||||
|
// used DrawPixel and not "fast" version as X,Y may be beyond screen
|
||||||
|
GDS_DrawPixel( Context->Device, Context->XOfs + x, Context->YOfs + y, Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Decode the embedded image into pixel lines that can be used with the rest of the logic.
|
||||||
|
static uint16_t* DecodeJPEG(uint8_t *Source, int *Width, int *Height, float Scale, bool SizeOnly) {
|
||||||
|
JDEC Decoder;
|
||||||
|
JpegCtx Context;
|
||||||
|
char *Scratch = calloc(SCRATCH_SIZE, 1);
|
||||||
|
|
||||||
|
if (!Scratch) {
|
||||||
|
ESP_LOGE(TAG, "Cannot allocate workspace");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Context.OutData = NULL;
|
||||||
|
Context.InData = Source;
|
||||||
|
Context.InPos = 0;
|
||||||
|
|
||||||
|
//Prepare and decode the jpeg.
|
||||||
|
int Res = jd_prepare(&Decoder, InHandler, Scratch, SCRATCH_SIZE, (void*) &Context);
|
||||||
|
if (Width) *Width = Decoder.width;
|
||||||
|
if (Height) *Height = Decoder.height;
|
||||||
|
Decoder.scale = Scale;
|
||||||
|
|
||||||
|
if (Res == JDR_OK && !SizeOnly) {
|
||||||
|
// ready to decode
|
||||||
|
Context.OutData = malloc(Decoder.width * Decoder.height * sizeof(uint16_t));
|
||||||
|
uint8_t N = 0, iScale = 1.0 / Scale;
|
||||||
|
while (iScale >>= 1) N++;
|
||||||
|
if (Context.OutData) {
|
||||||
|
Context.Width = Decoder.width / (1 << N);
|
||||||
|
Context.Height = Decoder.height / (1 << N);
|
||||||
|
if (Width) *Width = Context.Width;
|
||||||
|
if (Height) *Height = Context.Height;
|
||||||
|
Res = jd_decomp(&Decoder, OutHandler, N > 3 ? 3 : N);
|
||||||
|
if (Res != JDR_OK) {
|
||||||
|
ESP_LOGE(TAG, "Image decoder: jd_decode failed (%d)", Res);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ESP_LOGE(TAG, "Can't allocate bitmap %dx%d", Decoder.width, Decoder.height);
|
||||||
|
}
|
||||||
|
} else if (!SizeOnly) {
|
||||||
|
ESP_LOGE(TAG, "Image decoder: jd_prepare failed (%d)", Res);
|
||||||
|
}
|
||||||
|
|
||||||
|
// free scratch area
|
||||||
|
if (Scratch) free(Scratch);
|
||||||
|
return Context.OutData;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t* GDS_DecodeJPEG(uint8_t *Source, int *Width, int *Height, float Scale) {
|
||||||
|
return DecodeJPEG(Source, Width, Height, Scale, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GDS_GetJPEGSize(uint8_t *Source, int *Width, int *Height) {
|
||||||
|
DecodeJPEG(Source, Width, Height, 1, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************************
|
||||||
|
* Simply draw a RGB565 image
|
||||||
|
* monoschrome (0.2125 * color.r) + (0.7154 * color.g) + (0.0721 * color.b)
|
||||||
|
* grayscale (0.3 * R) + (0.59 * G) + (0.11 * B) )
|
||||||
|
*/
|
||||||
|
void GDS_DrawRGB16( struct GDS_Device* Device, uint16_t *Image, int x, int y, int Width, int Height, int RGB_Mode ) {
|
||||||
|
if (Device->DrawRGB16) {
|
||||||
|
Device->DrawRGB16( Device, x, y, Width, Height, RGB_Mode, Image );
|
||||||
|
} else {
|
||||||
|
int Scale = Device->Depth < 5 ? 5 - Device->Depth : 0;
|
||||||
|
switch(RGB_Mode) {
|
||||||
|
case GDS_RGB565:
|
||||||
|
for (int c = 0; c < Width; c++) {
|
||||||
|
for (int r = 0; r < Height; r++) {
|
||||||
|
int pixel = Image[Width*r + c];
|
||||||
|
pixel = ((pixel & 0x1f) * 11 + ((((pixel >> 5) & 0x3f) * 59) >> 1) + (pixel >> 11) * 30) / 100;
|
||||||
|
GDS_DrawPixel( Device, c + x, r + y, pixel >> Scale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GDS_RGB555:
|
||||||
|
for (int c = 0; c < Width; c++) {
|
||||||
|
for (int r = 0; r < Height; r++) {
|
||||||
|
int pixel = Image[Width*r + c];
|
||||||
|
pixel = ((pixel & 0x1f) * 11 + ((pixel >> 5) & 0x1f) * 59 + (pixel >> 10) * 30) / 100;
|
||||||
|
GDS_DrawPixel( Device, c + x, r + y, pixel >> Scale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GDS_RGB444:
|
||||||
|
for (int c = 0; c < Width; c++) {
|
||||||
|
for (int r = 0; r < Height; r++) {
|
||||||
|
int pixel = Image[Width*r + c];
|
||||||
|
pixel = (pixel & 0x0f) * 11 + ((pixel >> 4) & 0x0f) * 59 + (pixel >> 8) * 30;
|
||||||
|
GDS_DrawPixel( Device, c + x, r + y, pixel >> (Scale - 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Decode the embedded image into pixel lines that can be used with the rest of the logic.
|
||||||
|
bool GDS_DrawJPEG( struct GDS_Device* Device, uint8_t *Source, int x, int y, int Fit) {
|
||||||
|
JDEC Decoder;
|
||||||
|
JpegCtx Context;
|
||||||
|
bool Ret = false;
|
||||||
|
char *Scratch = calloc(SCRATCH_SIZE, 1);
|
||||||
|
|
||||||
|
if (!Scratch) {
|
||||||
|
ESP_LOGE(TAG, "Cannot allocate workspace");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Populate fields of the JpegCtx struct.
|
||||||
|
Context.InData = Source;
|
||||||
|
Context.InPos = 0;
|
||||||
|
Context.XOfs = x;
|
||||||
|
Context.YOfs = y;
|
||||||
|
Context.Device = Device;
|
||||||
|
Context.Depth = Device->Depth;
|
||||||
|
|
||||||
|
//Prepare and decode the jpeg.
|
||||||
|
int Res = jd_prepare(&Decoder, InHandler, Scratch, SCRATCH_SIZE, (void*) &Context);
|
||||||
|
Context.Width = Decoder.width;
|
||||||
|
Context.Height = Decoder.height;
|
||||||
|
|
||||||
|
if (Res == JDR_OK) {
|
||||||
|
uint8_t N = 0;
|
||||||
|
|
||||||
|
// do we need to fit the image
|
||||||
|
if (Fit & GDS_IMAGE_FIT) {
|
||||||
|
float XRatio = (Device->Width - x) / (float) Decoder.width, YRatio = (Device->Height - y) / (float) Decoder.height;
|
||||||
|
uint8_t Ratio = XRatio < YRatio ? ceil(1/XRatio) : ceil(1/YRatio);
|
||||||
|
Ratio--; Ratio |= Ratio >> 1; Ratio |= Ratio >> 2; Ratio++;
|
||||||
|
while (Ratio >>= 1) N++;
|
||||||
|
Context.Width /= 1 << N;
|
||||||
|
Context.Height /= 1 << N;
|
||||||
|
}
|
||||||
|
|
||||||
|
// then place it
|
||||||
|
if (Fit & GDS_IMAGE_CENTER_X) Context.XOfs = x + ((Device->Width - x) - Context.Width) / 2;
|
||||||
|
if (Fit & GDS_IMAGE_CENTER_Y) Context.YOfs = y + ((Device->Height - y) - Context.Height) / 2;
|
||||||
|
|
||||||
|
// do decompress & draw
|
||||||
|
Res = jd_decomp(&Decoder, OutHandlerDirect, N > 3 ? 3 : N);
|
||||||
|
if (Res == JDR_OK) {
|
||||||
|
Ret = true;
|
||||||
|
} else {
|
||||||
|
ESP_LOGE(TAG, "Image decoder: jd_decode failed (%d)", Res);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ESP_LOGE(TAG, "Image decoder: jd_prepare failed (%d)", Res);
|
||||||
|
}
|
||||||
|
|
||||||
|
// free scratch area
|
||||||
|
if (Scratch) free(Scratch);
|
||||||
|
return Ret;
|
||||||
|
}
|
||||||
|
|
||||||
23
components/display/core/gds_image.h
Normal file
23
components/display/core/gds_image.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "esp_err.h"
|
||||||
|
|
||||||
|
// no progressive JPEG handling
|
||||||
|
|
||||||
|
struct GDS_Device;
|
||||||
|
|
||||||
|
enum { GDS_RGB565, GDS_RGB555, GDS_RGB444 };
|
||||||
|
|
||||||
|
#define GDS_IMAGE_TOP 0x00
|
||||||
|
#define GDS_IMAGE_CENTER_X 0x01
|
||||||
|
#define GDS_IMAGE_CENTER_Y 0x02
|
||||||
|
#define GDS_IMAGE_CENTER (GDS_IMAGE_CENTER_X | GDS_IMAGE_CENTER_Y)
|
||||||
|
#define GDS_IMAGE_FIT 0x10
|
||||||
|
|
||||||
|
// Width and Height can be NULL if you already know them (actual scaling is closest ^2)
|
||||||
|
uint16_t* GDS_DecodeJPEG(uint8_t *Source, int *Width, int *Height, float Scale);
|
||||||
|
void GDS_GetJPEGSize(uint8_t *Source, int *Width, int *Height);
|
||||||
|
void GDS_DrawRGB16( struct GDS_Device* Device, uint16_t *Image, int x, int y, int Width, int Height, int RGB_Mode );
|
||||||
|
// set DisplayWidth and DisplayHeight to non-zero if you want autoscale to closest factor ^2 from 0..3
|
||||||
|
bool GDS_DrawJPEG( struct GDS_Device* Device, uint8_t *Source, int x, int y, int Fit);
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
#include "gds_default_if.h"
|
#include "gds_default_if.h"
|
||||||
|
|
||||||
static int I2CPortNumber;
|
static int I2CPortNumber;
|
||||||
|
static int I2CWait;
|
||||||
|
|
||||||
static const int GDS_I2C_COMMAND_MODE = 0x80;
|
static const int GDS_I2C_COMMAND_MODE = 0x80;
|
||||||
static const int GDS_I2C_DATA_MODE = 0x40;
|
static const int GDS_I2C_DATA_MODE = 0x40;
|
||||||
@@ -31,9 +32,11 @@ static bool I2CDefaultWriteData( struct GDS_Device* Device, const uint8_t* Data,
|
|||||||
*
|
*
|
||||||
* Returns true on successful init of the i2c bus.
|
* Returns true on successful init of the i2c bus.
|
||||||
*/
|
*/
|
||||||
bool GDS_I2CInit( int PortNumber, int SDA, int SCL ) {
|
bool GDS_I2CInit( int PortNumber, int SDA, int SCL, int Speed ) {
|
||||||
I2CPortNumber = PortNumber;
|
I2CPortNumber = PortNumber;
|
||||||
|
|
||||||
|
I2CWait = pdMS_TO_TICKS( Speed ? Speed / 4000 : 100 );
|
||||||
|
|
||||||
if (SDA != -1 && SCL != -1) {
|
if (SDA != -1 && SCL != -1) {
|
||||||
i2c_config_t Config = { 0 };
|
i2c_config_t Config = { 0 };
|
||||||
|
|
||||||
@@ -42,7 +45,7 @@ bool GDS_I2CInit( int PortNumber, int SDA, int SCL ) {
|
|||||||
Config.sda_pullup_en = GPIO_PULLUP_ENABLE;
|
Config.sda_pullup_en = GPIO_PULLUP_ENABLE;
|
||||||
Config.scl_io_num = SCL;
|
Config.scl_io_num = SCL;
|
||||||
Config.scl_pullup_en = GPIO_PULLUP_ENABLE;
|
Config.scl_pullup_en = GPIO_PULLUP_ENABLE;
|
||||||
Config.master.clk_speed = 250000;
|
Config.master.clk_speed = Speed ? Speed : 400000;
|
||||||
|
|
||||||
ESP_ERROR_CHECK_NONFATAL( i2c_param_config( I2CPortNumber, &Config ), return false );
|
ESP_ERROR_CHECK_NONFATAL( i2c_param_config( I2CPortNumber, &Config ), return false );
|
||||||
ESP_ERROR_CHECK_NONFATAL( i2c_driver_install( I2CPortNumber, Config.mode, 0, 0, 0 ), return false );
|
ESP_ERROR_CHECK_NONFATAL( i2c_driver_install( I2CPortNumber, Config.mode, 0, 0, 0 ), return false );
|
||||||
@@ -98,7 +101,7 @@ static bool I2CDefaultWriteBytes( int Address, bool IsCommand, const uint8_t* Da
|
|||||||
ESP_ERROR_CHECK_NONFATAL( i2c_master_write( CommandHandle, ( uint8_t* ) Data, DataLength, true ), goto error );
|
ESP_ERROR_CHECK_NONFATAL( i2c_master_write( CommandHandle, ( uint8_t* ) Data, DataLength, true ), goto error );
|
||||||
ESP_ERROR_CHECK_NONFATAL( i2c_master_stop( CommandHandle ), goto error );
|
ESP_ERROR_CHECK_NONFATAL( i2c_master_stop( CommandHandle ), goto error );
|
||||||
|
|
||||||
ESP_ERROR_CHECK_NONFATAL( i2c_master_cmd_begin( I2CPortNumber, CommandHandle, pdMS_TO_TICKS( 1000 ) ), goto error );
|
ESP_ERROR_CHECK_NONFATAL( i2c_master_cmd_begin( I2CPortNumber, CommandHandle, I2CWait ), goto error );
|
||||||
i2c_cmd_link_delete( CommandHandle );
|
i2c_cmd_link_delete( CommandHandle );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -89,11 +89,12 @@ void display_init(char *welcome) {
|
|||||||
// Detect driver interface
|
// Detect driver interface
|
||||||
if (strstr(config, "I2C") && i2c_system_port != -1) {
|
if (strstr(config, "I2C") && i2c_system_port != -1) {
|
||||||
int address = 0x3C;
|
int address = 0x3C;
|
||||||
|
int speed = 0;
|
||||||
|
|
||||||
if ((p = strcasestr(config, "address")) != NULL) address = atoi(strchr(p, '=') + 1);
|
if ((p = strcasestr(config, "address")) != NULL) address = atoi(strchr(p, '=') + 1);
|
||||||
|
|
||||||
init = true;
|
init = true;
|
||||||
GDS_I2CInit( i2c_system_port, -1, -1 ) ;
|
GDS_I2CInit( i2c_system_port, -1, -1, i2c_system_speed ) ;
|
||||||
GDS_I2CAttachDevice( display, width, height, address, -1 );
|
GDS_I2CAttachDevice( display, width, height, address, -1 );
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Display is I2C on port %u", address);
|
ESP_LOGI(TAG, "Display is I2C on port %u", address);
|
||||||
|
|||||||
@@ -45,9 +45,11 @@ const i2c_config_t * config_i2c_get(int * i2c_port) {
|
|||||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||||
.scl_io_num = -1,
|
.scl_io_num = -1,
|
||||||
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||||
.master.clk_speed = 400000,
|
.master.clk_speed = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
i2c.master.clk_speed = i2c_system_speed;
|
||||||
|
|
||||||
nvs_item = config_alloc_get(NVS_TYPE_STR, "i2c_config");
|
nvs_item = config_alloc_get(NVS_TYPE_STR, "i2c_config");
|
||||||
if (nvs_item) {
|
if (nvs_item) {
|
||||||
if ((p = strcasestr(nvs_item, "scl")) != NULL) i2c.scl_io_num = atoi(strchr(p, '=') + 1);
|
if ((p = strcasestr(nvs_item, "scl")) != NULL) i2c.scl_io_num = atoi(strchr(p, '=') + 1);
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#define SPI_SYSTEM_HOST SPI2_HOST
|
#define SPI_SYSTEM_HOST SPI2_HOST
|
||||||
|
|
||||||
extern int i2c_system_port;
|
extern int i2c_system_port;
|
||||||
|
extern int i2c_system_speed;
|
||||||
extern int spi_system_host;
|
extern int spi_system_host;
|
||||||
extern int spi_system_dc_gpio;
|
extern int spi_system_dc_gpio;
|
||||||
extern bool gpio36_39_used;
|
extern bool gpio36_39_used;
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ extern void monitor_svc_init(void);
|
|||||||
extern void led_svc_init(void);
|
extern void led_svc_init(void);
|
||||||
|
|
||||||
int i2c_system_port = I2C_SYSTEM_PORT;
|
int i2c_system_port = I2C_SYSTEM_PORT;
|
||||||
|
int i2c_system_speed = 400000;
|
||||||
int spi_system_host = SPI_SYSTEM_HOST;
|
int spi_system_host = SPI_SYSTEM_HOST;
|
||||||
int spi_system_dc_gpio = -1;
|
int spi_system_dc_gpio = -1;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user