From e63b29435c7ab7440d5cf3870eb650851b04e8d5 Mon Sep 17 00:00:00 2001 From: Edward Emelianov Date: Thu, 11 May 2023 23:16:56 +0300 Subject: [PATCH] Add font scaling, fix trouble with sprites, fix trouble with blocking SPI read (DMA read non-fixing without reset SPI) --- F3:F303/NitrogenFlooding/font14.h | 60 +++++++++++++------------- F3:F303/NitrogenFlooding/ili9341.c | 6 +-- F3:F303/NitrogenFlooding/nitrogen.bin | Bin 31440 -> 31916 bytes F3:F303/NitrogenFlooding/proto.c | 11 ++++- F3:F303/NitrogenFlooding/screen.c | 31 +++++++------ F3:F303/NitrogenFlooding/screen.h | 4 ++ F3:F303/NitrogenFlooding/spi.c | 20 ++++----- F3:F303/NitrogenFlooding/version.inc | 2 +- 8 files changed, 70 insertions(+), 64 deletions(-) diff --git a/F3:F303/NitrogenFlooding/font14.h b/F3:F303/NitrogenFlooding/font14.h index a31229e..3a65ad8 100644 --- a/F3:F303/NitrogenFlooding/font14.h +++ b/F3:F303/NitrogenFlooding/font14.h @@ -590,6 +590,7 @@ const uint8_t font14_table[] = { ________,________, ________,________, ________,________, + ________,________, XX______,________, XX______,________, ________,________, @@ -600,8 +601,7 @@ const uint8_t font14_table[] = { XX______,________, _X______,________, _X______,________, - X_______,________, - ________,________ + X_______,________ // 0x3C , 9, @@ -1516,21 +1516,21 @@ const uint8_t font14_table[] = { ________,________ // 0x6C , - 3, + 5, ________,________, ________,________, - XX______,________, - XX______,________, - XX______,________, - XX______,________, - XX______,________, - XX______,________, - XX______,________, - XX______,________, - XX______,________, - XX______,________, - XX______,________, - XX______,________, + XXX_____,________, + _XX_____,________, + _XX_____,________, + _XX_____,________, + _XX_____,________, + _XX_____,________, + _XX_____,________, + _XX_____,________, + _XX_____,________, + _XX_____,________, + _XX_____,________, + __XX____,________, ________,________, ________,________ // 0x6D @@ -1820,22 +1820,22 @@ const uint8_t font14_table[] = { ________,________ // 0x7C , - 3, + 4, ________,________, - XX______,________, - XX______,________, - XX______,________, - XX______,________, - XX______,________, - XX______,________, - XX______,________, - XX______,________, - XX______,________, - XX______,________, - XX______,________, - XX______,________, - XX______,________, - XX______,________, + _XX_____,________, + _XX_____,________, + _XX_____,________, + _XX_____,________, + _XX_____,________, + _XX_____,________, + _XX_____,________, + _XX_____,________, + _XX_____,________, + _XX_____,________, + _XX_____,________, + _XX_____,________, + _XX_____,________, + _XX_____,________, ________,________ // 0x7D , diff --git a/F3:F303/NitrogenFlooding/ili9341.c b/F3:F303/NitrogenFlooding/ili9341.c index 399cd99..beaac7a 100644 --- a/F3:F303/NitrogenFlooding/ili9341.c +++ b/F3:F303/NitrogenFlooding/ili9341.c @@ -219,12 +219,8 @@ int ili9341_readregdma(uint8_t reg, uint8_t *data, uint32_t N){ do{ if(!spi_write(®, 1)) break; if(!spi_waitbsy()) break; - SCRN_Data(); - if(!dmardwr(data, data, N)) break; - r = 1; + r = dmardwr(data, data, N); }while(0); - SCRN_Command(); - SCRN_RST_set(1); return r; } diff --git a/F3:F303/NitrogenFlooding/nitrogen.bin b/F3:F303/NitrogenFlooding/nitrogen.bin index 32c58c2e330b300056477fd2bede6526f5dbc792..805c2d59f99a22e65ea5dffeb61c3f7202257223 100755 GIT binary patch delta 19507 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 diff --git a/F3:F303/NitrogenFlooding/proto.c b/F3:F303/NitrogenFlooding/proto.c index add0765..9bb7975 100644 --- a/F3:F303/NitrogenFlooding/proto.c +++ b/F3:F303/NitrogenFlooding/proto.c @@ -241,7 +241,7 @@ static int scrnrdwr4(const char *cmd, int parno, const char *c, int32_t i){ static int scrnrdn(const char *cmd, int parno, const char *c, int32_t i){ if(parno < 0 || parno > 255) return RET_WRONGPARNO; if(!c || i < 1 || i > COLORBUFSZ*2) return RET_WRONGARG; - if(!ili9341_readregdma(parno, (uint8_t*)colorbuf, i)) return RET_BAD; + if(!(i = ili9341_readregdma(parno, (uint8_t*)colorbuf, i))) return RET_BAD; sendkey(cmd, parno, i); hexdump(USB_sendstr, (uint8_t*)colorbuf, i); return RET_GOOD; @@ -346,7 +346,8 @@ static int sputstr(const char _U_ *cmd, int parno, const char *c, int32_t _U_ i) if(parno < 0) parno = 0; if(parno > SCRNH-1) parno = SCRNH-1; PutStringAt(0, parno, c); - UpdateScreen(parno - 14, parno+2); + int fs = SetFontScale(0); // get font scale + UpdateScreen(parno-13*fs, parno+3*fs); USB_sendstr("put string: '"); USB_sendstr(c); USB_sendstr("'\n"); return RET_GOOD; } @@ -375,6 +376,11 @@ static int sstate(const char _U_ *cmd, int _U_ parno, const char _U_ *c, int32_t USB_sendstr("ScreenState="); USB_sendstr(s); newline(); return RET_GOOD; } +static int sfscale(const char *cmd, int _U_ parno, const char _U_ *c, int32_t i){ + sendkeyu(cmd, -1, SetFontScale((uint8_t)i)); + return RET_GOOD; +} + typedef struct{ int (*fn)(const char*, int, const char*, int32_t); @@ -418,6 +424,7 @@ commands cmdlist[] = { {scolor, "Scolor", "seg color fg=bg"}, {sputstr, "Sstr", "put string y=string"}, {sstate, "Sstate", "current screen state"}, + {sfscale, "Sfscale", "set/get =font scale"}, {NULL, "ADC commands", NULL}, {adcval, "ADC", "get ADCx value (without x - for all)"}, {adcvoltage, "ADCv", "get ADCx voltage (without x - for all)"}, diff --git a/F3:F303/NitrogenFlooding/screen.c b/F3:F303/NitrogenFlooding/screen.c index 451e5fe..c1ff253 100644 --- a/F3:F303/NitrogenFlooding/screen.c +++ b/F3:F303/NitrogenFlooding/screen.c @@ -56,6 +56,8 @@ static int uy0, uy1; static int updidx = 0; // ==-1 to initialize update // next data portion size (in bytes!), total amount of bytes in update buffer static int portionsz = 0, updbuffsz; +// font scale +static uint8_t fontscale = 1; static uint16_t fgColor = 0xff, bgColor = 0; // foreground and background colors void setBGcolor(uint16_t c){bgColor = c;} @@ -84,14 +86,11 @@ void UpdateScreen(int y0, int y1){ */ void ClearScreen(){ memset(screenbuf, 0, SCREENBUF_SZ); - int i; - for(i = 0; i < SPRITE_SZ; ++i){ + for(int i = 0; i < SPRITE_SZ; ++i){ foreground[i] = fgColor; background[i] = bgColor; } - USB_sendstr("total spsz="); USB_sendstr(i2str(i)); newline(); - foreground[SPRITE_SZ-5] = 0x1234; - foreground[SPRITE_SZ-21] = 0x4321; + for(int i = SPRITE_SZ-40; i < SPRITE_SZ; ++i) foreground[i] = i; UpdateScreen(0, SCRNH-1); } @@ -103,7 +102,7 @@ void ClearScreen(){ void DrawPix(int X, int Y, uint8_t pix){ if(X < 0 || X > SCRNW-1 || Y < 0 || Y > SCRNH-1) return; // outside of screen // now calculate coordinate of pixel - int16_t spritex = X/SPRITEWD, spriteidx = spritex + SCRNSPRITEW * Y / SPRITEHT; + int16_t spritex = X/SPRITEWD, spriteidx = spritex + SCRNSPRITEW * (Y / SPRITEHT); uint8_t *ptr = &screenbuf[Y*SCRNSPRITEW + spritex]; // pointer to byte with 8 pixels if(pix) *ptr |= 1 << (7 - (X%8)); else *ptr &= ~(1 << (7 - (X%8))); @@ -135,6 +134,11 @@ void invertSpriteColor(int xmin, int xmax, int ymin, int ymax){ } } +uint8_t SetFontScale(uint8_t scale){ + if(scale > 0 && scale <= FONTSCALEMAX) fontscale = scale; + return fontscale; +} + // TODO in case of low speed: draw at once full line? /** * @brief DrawCharAt - draws character @ position X,Y (this point is left baseline corner of char!) @@ -147,18 +151,20 @@ uint8_t DrawCharAt(int X, int Y, uint8_t Char){ const uint8_t *curchar = font_char(Char); if(!curchar) return 0; // now change Y coordinate to left upper corner of font - Y += curfont->baseline - curfont->height + 1; + Y += fontscale*(curfont->baseline - curfont->height + 1); // height and width of letter in pixels uint8_t h = curfont->height, w = *curchar++; // now curchar is pointer to bits array uint8_t lw = curfont->bytes / h; // width of letter in bytes for(uint8_t row = 0; row < h; ++row){ - int Y1 = Y + row; + int Y1 = Y + fontscale * row; for(uint8_t col = 0; col < w; ++col){ register uint8_t pix = curchar[row*lw + (col/8)] & (1 << (7 - (col%8))); - DrawPix(X + col, Y1, pix); + int xx = X + fontscale * col; + for(int y = 0; y < fontscale; ++y) for(int x = 0; x < fontscale; ++x) + DrawPix(xx + x, Y1 + y, pix); } } - return w; + return w * fontscale; } /** @@ -215,11 +221,8 @@ static int convbuf(){ uint16_t *fg = foreground + spidx, *bg = background + spidx; for(int X = 0; X < SCRNSPRITEW; ++X, ++fg, ++bg, ++i){ // prepare colors for SPI transfer - uint16_t f = __builtin_bswap16(*fg++), b = __builtin_bswap16(*bg++); + uint16_t f = __builtin_bswap16(*fg), b = __builtin_bswap16(*bg); uint8_t pix = *i; - if(Y==239){ - USB_sendstr("X="); USB_sendstr(i2str(X)); newline(); - USB_sendstr("f="); USB_sendstr(uhex2str(f)); newline();} for(int idx = 0; idx < SPRITEWD; ++idx){ // now check bits in pixels mask *o++ = (pix & 0x80) ? f : b; pix <<= 1; diff --git a/F3:F303/NitrogenFlooding/screen.h b/F3:F303/NitrogenFlooding/screen.h index 0095847..a912f7f 100644 --- a/F3:F303/NitrogenFlooding/screen.h +++ b/F3:F303/NitrogenFlooding/screen.h @@ -39,6 +39,9 @@ typedef enum{ // screen states #define SPRITEWD (8) #define SPRITEHT (8) +// maximal font scale +#define FONTSCALEMAX (10) + screen_state getScreenState(); void ClearScreen(); void UpdateScreen(int y0, int y1); @@ -46,6 +49,7 @@ void setBGcolor(uint16_t c); void setFGcolor(uint16_t c); void invertSpriteColor(int xmin, int xmax, int ymin, int ymax); void DrawPix(int X, int Y, uint8_t pix); +uint8_t SetFontScale(uint8_t scale); uint8_t DrawCharAt(int X, int Y, uint8_t Char); int PutStringAt(int X, int Y, const char *str); int CenterStringAt(int Y, const char *str); diff --git a/F3:F303/NitrogenFlooding/spi.c b/F3:F303/NitrogenFlooding/spi.c index 045b243..0d13b16 100644 --- a/F3:F303/NitrogenFlooding/spi.c +++ b/F3:F303/NitrogenFlooding/spi.c @@ -24,7 +24,7 @@ #include "strfunc.h" #endif -#define SPIDR *((uint8_t*)&SPI2->DR) +#define SPIDR *((volatile uint8_t*)&SPI2->DR) spiStatus spi_status = SPI_NOTREADY; volatile uint32_t wctr; @@ -40,11 +40,12 @@ static uint32_t rxbuflen = 0; // Channel 5 - SPI2 Tx void spi_setup(){ SPI2->CR1 = 0; // clear EN - //RCC->APB1RSTR = RCC_APB1RSTR_SPI2RST; // reset SPI + RCC->APB1RSTR = RCC_APB1RSTR_SPI2RST; // reset SPI + RCC->APB1RSTR = 0; // clear reset RCC->APB1ENR |= RCC_APB1ENR_SPI2EN; RCC->AHBENR |= RCC_AHBENR_DMA1EN; - // Baudrate = 0b011 - fpclk/16 = 2MHz; software slave management (without hardware NSS pin) - SPI2->CR1 = SPI_CR1_MSTR | SPI_CR1_BR_0 | SPI_CR1_BR_1 | SPI_CR1_SSM | SPI_CR1_SSI; + // Baudrate = 0b011 - fpclk/4 = 8MHz; software slave management (without hardware NSS pin) + SPI2->CR1 = SPI_CR1_MSTR | /*SPI_CR1_BR_0 |*/ SPI_CR1_SSM | SPI_CR1_SSI; // 8bit; RXNE generates after 8bit of data in FIFO SPI2->CR2 = SPI_CR2_FRXTH | SPI_CR2_DS_2|SPI_CR2_DS_1|SPI_CR2_DS_0 | SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN; // setup SPI2 DMA @@ -94,14 +95,10 @@ int spi_write(const uint8_t *data, uint32_t n){ */ int spi_write_dma(const uint8_t *data, uint8_t *rxbuf, uint32_t n){ if(spi_status != SPI_READY) return 0; + if(!spi_waitbsy()) return 0; rxbufptr = rxbuf; rxbuflen = n; - if(!spi_waitbsy()) return 0; - // clear SPI Rx FIFO - (void) SPI2->DR; - while(SPI2->SR & SPI_SR_RXNE) (void) SPI2->DR; - //DMA1_Channel4->CCR &= ~DMA_CCR_EN; // turn off to reconfigure - //DMA1_Channel5->CCR &= ~DMA_CCR_EN; + // spi_setup(); - only so we can clear Rx FIFO! DMA1_Channel5->CMAR = (uint32_t) data; DMA1_Channel5->CNDTR = n; // check if user want to receive data @@ -130,8 +127,7 @@ int spi_read(uint8_t *data, uint32_t n){ } if(!spi_waitbsy()) return 0; // clear SPI Rx FIFO - (void) SPI2->DR; - while(SPI2->SR & SPI_SR_RXNE) (void) SPI2->DR; + for(int i = 0; i < 4; ++i) (void) SPI2->DR; for(uint32_t x = 0; x < n; ++x){ WAITX(!(SPI2->SR & SPI_SR_TXE)); SPIDR = 0; diff --git a/F3:F303/NitrogenFlooding/version.inc b/F3:F303/NitrogenFlooding/version.inc index cccedd9..3a1d7b1 100644 --- a/F3:F303/NitrogenFlooding/version.inc +++ b/F3:F303/NitrogenFlooding/version.inc @@ -1,2 +1,2 @@ -#define BUILD_NUMBER "217" +#define BUILD_NUMBER "242" #define BUILD_DATE "2023-05-11"