mirror of
https://github.com/eddyem/stm32samples.git
synced 2026-02-28 11:54:30 +03:00
restructuring
This commit is contained in:
213
F1:F103/RGB_LED_Screen/screen.c
Normal file
213
F1:F103/RGB_LED_Screen/screen.c
Normal file
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* This file is part of the LED_screen project.
|
||||
* Copyright 2019 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <string.h> // memset, memcpy
|
||||
#include <stdio.h>
|
||||
#include "fonts.h"
|
||||
#include "hardware.h"
|
||||
#include "screen.h"
|
||||
//#include "usb.h"
|
||||
|
||||
|
||||
// !!!FOR LITTLE-ENDIAN!!!
|
||||
|
||||
// X coordinate - from left to right!
|
||||
// Y coordinate - from top to bottom!
|
||||
// (0,0) is top left corner
|
||||
|
||||
// all-screen buffer
|
||||
static uint8_t screenbuf[SCREENBUF_SZ];
|
||||
extern volatile uint32_t Tms; // time for FPS count
|
||||
static uint32_t FPS = 0, Tfps = 0; // approx FPS
|
||||
uint32_t getFPS(){return FPS;}
|
||||
|
||||
static uint8_t fgColor = 0xff, bgColor = 0; // foreground and background colors
|
||||
void setBGcolor(uint8_t c){bgColor = c;}
|
||||
void setFGcolor(uint8_t c){fgColor = c;}
|
||||
|
||||
/**
|
||||
* @brief FillScreen - fill screen buffer with current bgColor
|
||||
*/
|
||||
void ClearScreen(){
|
||||
for(int i = 0; i < SCREENBUF_SZ; ++i)
|
||||
screenbuf[i] = bgColor;
|
||||
/*for(int i = 0; i < 32; ++i){
|
||||
DrawPix(0,i,0b11111111);
|
||||
DrawPix(1,i,0b1001010);
|
||||
DrawPix(2,i,0b00100101);
|
||||
DrawPix(20,i,0b11100000);
|
||||
DrawPix(21,i,0b10000000);
|
||||
DrawPix(22,i,0b00100000);
|
||||
DrawPix(30,i,0b00011100);
|
||||
DrawPix(31,i,0b00010000);
|
||||
DrawPix(32,i,0b00000100);
|
||||
DrawPix(60,i,0b00000011);
|
||||
DrawPix(61,i,0b00000010);
|
||||
DrawPix(62,i,0b00000001);
|
||||
}*/
|
||||
// memset -> halt
|
||||
//memset(screenbuf, pattern, SCREENBUF_SZ);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DrawPix - set or clear pixel
|
||||
* @param X, Y - pixel coordinates (could be outside of screen)
|
||||
* @param pix - == pixel color (RRRGGGBB)
|
||||
*/
|
||||
void DrawPix(int16_t X, int16_t Y, uint8_t pix){
|
||||
if(X < 0 || X > SCREEN_WIDTH-1 || Y < 0 || Y > SCREEN_HEIGHT-1) return; // outside of screen
|
||||
// now calculate coordinate of pixel
|
||||
screenbuf[Y*SCREEN_WIDTH + X] = pix;
|
||||
}
|
||||
void InvertPix(int16_t X, int16_t Y){
|
||||
if(X < 0 || X > SCREEN_WIDTH-1 || Y < 0 || Y > SCREEN_HEIGHT-1) return; // outside of screen
|
||||
screenbuf[Y*SCREEN_WIDTH + X] = ~screenbuf[Y*SCREEN_WIDTH + X];
|
||||
}
|
||||
void XORPix(int16_t X, int16_t Y, uint8_t pix){
|
||||
if(X < 0 || X > SCREEN_WIDTH-1 || Y < 0 || Y > SCREEN_HEIGHT-1) return; // outside of screen
|
||||
screenbuf[Y*SCREEN_WIDTH + X] ^= pix;
|
||||
}
|
||||
uint8_t GetPix(int16_t X, int16_t Y){
|
||||
if(X < 0 || X > SCREEN_WIDTH-1 || Y < 0 || Y > SCREEN_HEIGHT-1) return 0;
|
||||
return screenbuf[Y*SCREEN_WIDTH + X];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DrawCharAt - draws character @ position X,Y (this point is left baseline corner of char!)
|
||||
* character will be drawn with current fg and bg colors
|
||||
* @param X, Y - started point
|
||||
* @param Char - char to draw
|
||||
* @return char width
|
||||
*/
|
||||
uint8_t DrawCharAt(int16_t X, int16_t 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 += 1 - curfont->height + curfont->baseline;
|
||||
// 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){
|
||||
for(uint8_t col = 0; col < w; ++col){
|
||||
if(curchar[row*lw + (col/8)] & (1 << (7 - (col%8))))
|
||||
DrawPix(X + col, Y + row, fgColor);
|
||||
else
|
||||
DrawPix(X + col, Y + row, bgColor);
|
||||
}
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief PutStringAt - draw text string @ screen
|
||||
* @param X, Y - base coordinates
|
||||
* @param str - string to draw
|
||||
* @return - text width in pixels
|
||||
*/
|
||||
uint8_t PutStringAt(int16_t X, int16_t Y, const char *str){
|
||||
if(!str) return 0;
|
||||
int16_t Xold = X;
|
||||
while(*str){
|
||||
X += DrawCharAt(X, Y, (uint8_t)*str++);
|
||||
}
|
||||
return X - Xold;
|
||||
}
|
||||
|
||||
uint8_t *getScreenBuf(){return screenbuf;}
|
||||
|
||||
static screen_state ScrnState = SCREEN_RELAX;
|
||||
screen_state getScreenState(){return ScrnState;}
|
||||
|
||||
static uint8_t currentB = 0; // current block number
|
||||
static uint8_t Ntick = 0; // tick number (0..7) for PWM color
|
||||
|
||||
/**
|
||||
* @brief process_screen - screen state machine processing
|
||||
*/
|
||||
void process_screen(){
|
||||
static uint32_t framecnt = 0;
|
||||
switch(ScrnState){
|
||||
case SCREEN_ACTIVE: // transmission active
|
||||
if(transfer_done){
|
||||
ScrnState = SCREEN_UPDATENXT;
|
||||
}else return;
|
||||
// fallthrough
|
||||
case SCREEN_UPDATENXT:
|
||||
ConvertScreenBuf(screenbuf, currentB, Ntick); // convert data
|
||||
TIM_DMA_transfer(currentB); // start transfer
|
||||
ScrnState = SCREEN_ACTIVE;
|
||||
if(++Ntick >= 7){
|
||||
Ntick = 0;
|
||||
if(++currentB >= NBLOCKS){
|
||||
currentB = 0; // start again
|
||||
++framecnt;
|
||||
if(Tms - Tfps > 999){
|
||||
FPS = framecnt;
|
||||
Tfps = Tms;
|
||||
framecnt = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief ShowScreen - turn on data transmission
|
||||
*/
|
||||
void ScreenON(){
|
||||
ScrnState = SCREEN_UPDATENXT;
|
||||
Tfps = Tms;
|
||||
process_screen();
|
||||
}
|
||||
|
||||
void ScreenOFF(){
|
||||
stopTIMDMA();
|
||||
SCRN_DISBL();
|
||||
ScrnState = SCREEN_RELAX;
|
||||
currentB = 0;
|
||||
Ntick = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief RGB2pack - convert RGB color to packed RRRGGGBB
|
||||
* @param RGB - color (each in range 0..8)
|
||||
* @return packed color
|
||||
*/
|
||||
uint8_t RGB2pack(const uint8_t *RGB){
|
||||
uint8_t b = RGB[2] & 7;
|
||||
if(b) b = (b - 1) >> 1;
|
||||
return ((RGB[0] & 7)<<5 | (RGB[1] & 7) << 2 | b);
|
||||
}
|
||||
/**
|
||||
* @brief pack2RGB - convert packed color to array of RGB (0..8)
|
||||
* @param pack - packed color
|
||||
* @return RGB array
|
||||
*/
|
||||
uint8_t *pack2RGB(uint8_t pack){
|
||||
static uint8_t RGB[3];
|
||||
RGB[0] = pack >> 5;
|
||||
RGB[1] = (pack & 0x1c) >> 2;
|
||||
pack &= 3;
|
||||
if(pack) RGB[2] = (pack<<1) + 1;
|
||||
else RGB[2] = 0;
|
||||
return RGB;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user