From 2b924fa425632817ef934e06ecfde23f25ea1eba Mon Sep 17 00:00:00 2001 From: philippe44 Date: Tue, 3 Mar 2020 20:37:23 -0800 Subject: [PATCH] Validated 256 pixels SSD1326 --- components/display/SSD132x.c | 33 +++++++++++---- components/display/core/gds.c | 4 +- components/display/core/gds_draw.c | 4 +- components/raop/raop.c | 65 ++++++------------------------ components/squeezelite/display.c | 5 ++- 5 files changed, 45 insertions(+), 66 deletions(-) diff --git a/components/display/SSD132x.c b/components/display/SSD132x.c index 6088d187..f7ed2b3b 100644 --- a/components/display/SSD132x.c +++ b/components/display/SSD132x.c @@ -162,15 +162,15 @@ static void IRAM_ATTR DrawPixel1Fast( struct GDS_Device* Device, int X, int Y, i *FBOffset ^= BIT( 7 - XBit ); } else { // we might be able to save the 7-Xbit using BitRemap (A0 bit 2) - *FBOffset = ( Color == GDS_COLOR_BLACK ) ? *FBOffset & ~BIT( 7 - XBit ) : *FBOffset | BIT( 7 - XBit ); + *FBOffset = ( Color == GDS_COLOR_BLACK ) ? *FBOffset & ~BIT( XBit ) : *FBOffset | BIT( XBit ); } } 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; + int 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 @@ -184,13 +184,28 @@ static void ClearWindow( struct GDS_Device* Device, int x1, int y1, int x2, int } static void DrawBitmapCBR(struct GDS_Device* Device, uint8_t *Data, int Width, int Height, int Color ) { - uint8_t *optr = Device->Framebuffer; - if (!Height) Height = Device->Height; if (!Width) Width = Device->Width; + int DWidth = Device->Width >> 3; - // just do bitreverse and if BitRemap works, there will be even nothing to do - for (int i = Height * Width >> 3; --i >= 0;) *optr++ = BitReverseTable256[*Data++]; + // Two consecutive bits of source data are split over two different bytes of framebuffer + for (int c = 0; c < Width; c++) { + uint8_t shift = c & 0x07, bit = ~(1 << shift); + uint8_t *optr = Device->Framebuffer + (c >> 3); + + // we need to linearize code to let compiler better optimize + for (int r = Height >> 3; --r >= 0;) { + uint8_t Byte = BitReverseTable256[*Data++]; + *optr = (*optr & bit) | ((Byte & 0x01) << shift); optr += DWidth; Byte >>= 1; + *optr = (*optr & bit) | ((Byte & 0x01) << shift); optr += DWidth; Byte >>= 1; + *optr = (*optr & bit) | ((Byte & 0x01) << shift); optr += DWidth; Byte >>= 1; + *optr = (*optr & bit) | ((Byte & 0x01) << shift); optr += DWidth; Byte >>= 1; + *optr = (*optr & bit) | ((Byte & 0x01) << shift); optr += DWidth; Byte >>= 1; + *optr = (*optr & bit) | ((Byte & 0x01) << shift); optr += DWidth; Byte >>= 1; + *optr = (*optr & bit) | ((Byte & 0x01) << shift); optr += DWidth; Byte >>= 1; + *optr = (*optr & bit) | ((Byte & 0x01) << shift); optr += DWidth; + } + } } static void SetHFlip( struct GDS_Device* Device, bool On ) { @@ -294,6 +309,7 @@ static const struct GDS_Device SSD132x = { struct GDS_Device* SSD132x_Detect(char *Driver, struct GDS_Device* Device) { uint8_t Model; + int Depth; if (strcasestr(Driver, "SSD1326")) Model = SSD1326; else if (strcasestr(Driver, "SSD1327")) Model = SSD1327; @@ -304,7 +320,8 @@ struct GDS_Device* SSD132x_Detect(char *Driver, struct GDS_Device* Device) { *Device = SSD132x; ((struct PrivateSpace*) Device->Private)->Model = Model; - sscanf(Driver, "%*[^:]:%c", &Device->Depth); + sscanf(Driver, "%*[^:]:%u", &Depth); + Device->Depth = Depth; if (Model == SSD1326 && Device->Depth == 1) { Device->Update = Update1; diff --git a/components/display/core/gds.c b/components/display/core/gds.c index 499a931b..d315b027 100644 --- a/components/display/core/gds.c +++ b/components/display/core/gds.c @@ -95,7 +95,7 @@ void GDS_ClearWindow( struct GDS_Device* Device, int x1, int y1, int x2, int y2, memset( Device->Framebuffer, Color | (Color << 4), Device->FramebufferSize ); } else { uint8_t _Color = Color | (Color << 4); - uint8_t Width = Device->Width; + int Width = Device->Width; uint8_t *optr = Device->Framebuffer; // try to do byte processing as much as possible for (int r = y1; r <= y2; r++) { @@ -113,7 +113,7 @@ void GDS_ClearWindow( struct GDS_Device* Device, int x1, int y1, int x2, int y2, } } } - + // make sure diplay will do update Device->Dirty = true; } diff --git a/components/display/core/gds_draw.c b/components/display/core/gds_draw.c index 7e6995e0..c85d39e6 100644 --- a/components/display/core/gds_draw.c +++ b/components/display/core/gds_draw.c @@ -195,11 +195,11 @@ void GDS_DrawBox( struct GDS_Device* Device, int x1, int y1, int x2, int y2, int void GDS_DrawBitmapCBR(struct GDS_Device* Device, uint8_t *Data, int Width, int Height, int Color ) { if (!Height) Height = Device->Height; if (!Width) Width = Device->Width; - Height >>= 3; if (Device->DrawBitmapCBR) { Device->DrawBitmapCBR( Device, Data, Width, Height, Color ); } else if (Device->Depth == 1) { + Height >>= 3; // need to do row/col swap and bit-reverse for (int r = 0; r < Height; r++) { uint8_t *optr = Device->Framebuffer + r*Device->Width, *iptr = Data + r; @@ -211,6 +211,7 @@ void GDS_DrawBitmapCBR(struct GDS_Device* Device, uint8_t *Data, int Width, int } else if (Device->Depth == 4) { uint8_t *optr = Device->Framebuffer; int LineLen = Device->Width >> 1; + Height >>= 3; for (int i = Width * Height, r = 0, c = 0; --i >= 0;) { uint8_t Byte = BitReverseTable256[*Data++]; // we need to linearize code to let compiler better optimize @@ -237,6 +238,7 @@ void GDS_DrawBitmapCBR(struct GDS_Device* Device, uint8_t *Data, int Width, int if (++r == Height) { c++; r = 0; optr = Device->Framebuffer + (c >> 1); } } } else { + Height >>= 3; // don't know bitdepth, use brute-force solution for (int i = Width * Height, r = 0, c = 0; --i >= 0;) { uint8_t Byte = *Data++; diff --git a/components/raop/raop.c b/components/raop/raop.c index ffce9b46..ceed0aa0 100644 --- a/components/raop/raop.c +++ b/components/raop/raop.c @@ -44,7 +44,7 @@ #include "log_util.h" #define RTSP_STACK_SIZE (8*1024) -#define SEARCH_STACK_SIZE (2*1048) +#define SEARCH_STACK_SIZE (3*1048) typedef struct raop_ctx_s { #ifdef WIN32 @@ -86,7 +86,7 @@ typedef struct raop_ctx_s { struct mDNShandle_s *handle; pthread_t thread; #else - TaskHandle_t thread, joiner; + TaskHandle_t thread; StaticTask_t *xTaskBuffer; StackType_t xStack[SEARCH_STACK_SIZE] __attribute__ ((aligned (4)));; SemaphoreHandle_t destroy_mutex; @@ -100,7 +100,7 @@ extern log_level raop_loglevel; static log_level *loglevel = &raop_loglevel; static void* rtsp_thread(void *arg); -static void abort_rtsp(raop_ctx_t *ctx); +static void cleanup_rtsp(raop_ctx_t *ctx, bool abort); static bool handle_rtsp(raop_ctx_t *ctx, int sock); static char* rsa_apply(unsigned char *input, int inlen, int *outlen, int mode); @@ -248,18 +248,6 @@ void raop_delete(struct raop_ctx_s *ctx) { mdns_service_remove(ctx->svr, ctx->svc); mdnsd_stop(ctx->svr); #else - // first stop the search task if any - if (ctx->active_remote.running) { - ctx->active_remote.joiner = xTaskGetCurrentTaskHandle(); - ctx->active_remote.running = false; - - vTaskResume(ctx->active_remote.thread); - ulTaskNotifyTake(pdFALSE, portMAX_DELAY); - vTaskDelete(ctx->active_remote.thread); - - heap_caps_free(ctx->active_remote.xTaskBuffer); - } - // then the RTSP task ctx->joiner = xTaskGetCurrentTaskHandle(); ctx->running = false; @@ -268,10 +256,11 @@ void raop_delete(struct raop_ctx_s *ctx) { vTaskDelete(ctx->thread); heap_caps_free(ctx->xTaskBuffer); - rtp_end(ctx->rtp); - shutdown(ctx->sock, SHUT_RDWR); closesocket(ctx->sock); + + // cleanup all session-created items + cleanup_rtsp(ctx, true); mdns_service_remove("_raop", "_tcp"); #endif @@ -406,7 +395,7 @@ static void *rtsp_thread(void *arg) { if (n > 0) res = handle_rtsp(ctx, sock); if (n < 0 || !res || ctx->abort) { - abort_rtsp(ctx); + cleanup_rtsp(ctx, true); closesocket(sock); LOG_INFO("RTSP close %u", sock); sock = -1; @@ -581,37 +570,11 @@ static bool handle_rtsp(raop_ctx_t *ctx, int sock) if ((p = strcasestr(buf, "rtptime")) != NULL) sscanf(p, "%*[^=]=%u", &rtptime); // only send FLUSH if useful (discards frames above buffer head and top) - if (ctx->rtp && rtp_flush(ctx->rtp, seqno, rtptime)) - success = ctx->cmd_cb(RAOP_FLUSH); + if (ctx->rtp && rtp_flush(ctx->rtp, seqno, rtptime)) success = ctx->cmd_cb(RAOP_FLUSH); } else if (!strcmp(method, "TEARDOWN")) { - rtp_end(ctx->rtp); - - ctx->rtp = NULL; - - // need to make sure no search is on-going and reclaim pthread memory -#ifdef WIN32 - if (ctx->active_remote.handle) close_mDNS(ctx->active_remote.handle); - pthread_join(ctx->active_remote.thread, NULL); -#else - ctx->active_remote.joiner = xTaskGetCurrentTaskHandle(); - ctx->active_remote.running = false; - - xSemaphoreTake(ctx->active_remote.destroy_mutex, portMAX_DELAY); - vTaskDelete(ctx->active_remote.thread); - vSemaphoreDelete(ctx->active_remote.thread); - - heap_caps_free(ctx->active_remote.xTaskBuffer); - - LOG_INFO("[%p]: mDNS search task terminated", ctx); -#endif - - memset(&ctx->active_remote, 0, sizeof(ctx->active_remote)); - NFREE(ctx->rtsp.aeskey); - NFREE(ctx->rtsp.aesiv); - NFREE(ctx->rtsp.fmtp); - + cleanup_rtsp(ctx, false); success = ctx->cmd_cb(RAOP_STOP); } else if (!strcmp(method, "SET_PARAMETER")) { @@ -681,12 +644,12 @@ static bool handle_rtsp(raop_ctx_t *ctx, int sock) } /*----------------------------------------------------------------------------*/ -void abort_rtsp(raop_ctx_t *ctx) { +void cleanup_rtsp(raop_ctx_t *ctx, bool abort) { // first stop RTP process if (ctx->rtp) { rtp_end(ctx->rtp); ctx->rtp = NULL; - LOG_INFO("[%p]: RTP thread aborted", ctx); + if (abort) LOG_INFO("[%p]: RTP thread aborted", ctx); } if (ctx->active_remote.running) { @@ -695,9 +658,7 @@ void abort_rtsp(raop_ctx_t *ctx) { close_mDNS(ctx->active_remote.handle); #else // need to make sure no search is on-going and reclaim task memory - ctx->active_remote.joiner = xTaskGetCurrentTaskHandle(); ctx->active_remote.running = false; - xSemaphoreTake(ctx->active_remote.destroy_mutex, portMAX_DELAY); vTaskDelete(ctx->active_remote.thread); vSemaphoreDelete(ctx->active_remote.thread); @@ -705,8 +666,6 @@ void abort_rtsp(raop_ctx_t *ctx) { heap_caps_free(ctx->active_remote.xTaskBuffer); #endif memset(&ctx->active_remote, 0, sizeof(ctx->active_remote)); - - LOG_INFO("[%p]: Remote search thread aborted", ctx); } @@ -776,7 +735,7 @@ static void* search_remote(void *args) { LOG_INFO("found remote %s %s:%hu", r->instance_name, inet_ntoa(ctx->active_remote.host), ctx->active_remote.port); } } - + mdns_query_results_free(results); } diff --git a/components/squeezelite/display.c b/components/squeezelite/display.c index 91030330..3923467f 100644 --- a/components/squeezelite/display.c +++ b/components/squeezelite/display.c @@ -151,7 +151,7 @@ static EXT_RAM_ATTR struct { #define ANIM_SCREEN_2 0x08 static u8_t ANIC_resp = ANIM_NONE; -static u8_t SETD_width; +static uint16_t SETD_width; #define SCROLL_STACK_SIZE (3*1024) #define LINELEN 40 @@ -316,8 +316,9 @@ static void send_server(void) { pkt_header.id = 0xfe; // id 0xfe is width S:P:Squeezebox2 pkt_header.length = htonl(sizeof(pkt_header) + 2 - 8); + SETD_width = htons(SETD_width); send_packet((u8_t *)&pkt_header, sizeof(pkt_header)); - send_packet(&SETD_width, 2); + send_packet((uint8_t*) &SETD_width, 2); SETD_width = 0; }