kopia lustrzana https://github.com/piotr022/UV_K5_playground
286 wiersze
8.4 KiB
C++
286 wiersze
8.4 KiB
C++
#pragma once
|
|
#include <string.h>
|
|
#include <type_traits>
|
|
|
|
struct ILcd {
|
|
virtual void UpdateScreen() = 0;
|
|
};
|
|
|
|
template <unsigned short _SizeX, unsigned short _SizeY,
|
|
unsigned char _LineHeight>
|
|
struct IBitmap {
|
|
constexpr IBitmap(const unsigned char *_pBuffStart)
|
|
: pBuffStart(_pBuffStart){};
|
|
static constexpr auto SizeX = _SizeX;
|
|
static constexpr auto SizeY = _SizeY;
|
|
static constexpr auto LineHeight = _LineHeight;
|
|
static constexpr auto Lines = _SizeX / _LineHeight;
|
|
static constexpr unsigned short GetCoursorPosition(unsigned char u8Line,
|
|
unsigned char u8XPos) {
|
|
return (u8Line * SizeX) + u8XPos;
|
|
}
|
|
|
|
virtual bool GetPixel(unsigned char u8X, unsigned char u8Y) const = 0;
|
|
virtual void SetPixel(unsigned char u8X, unsigned char u8Y) const = 0;
|
|
virtual void *GetCoursorData(unsigned short u16CoursorPosition) const {
|
|
return nullptr;
|
|
}
|
|
virtual void ClearAll() = 0;
|
|
const unsigned char *pBuffStart;
|
|
};
|
|
|
|
struct IFont {
|
|
virtual bool GetPixel(char c8Character, unsigned char u8X,
|
|
unsigned char u8Y) const = 0;
|
|
virtual unsigned char *GetRaw(char c8Character) const = 0;
|
|
virtual unsigned char GetSizeX(char c8Character) const = 0;
|
|
virtual unsigned char GetSizeY(char c8Character) const = 0;
|
|
};
|
|
|
|
template <class BitmapType> class CDisplay {
|
|
public:
|
|
constexpr CDisplay(BitmapType &_Bitmap)
|
|
: Bitmap(_Bitmap), pCurrentFont(nullptr), u16CoursorPosition(0) {}
|
|
|
|
void SetCoursor(unsigned char u8Line, unsigned char u8X) const {
|
|
u16CoursorPosition = (u8Line * Bitmap.SizeX) + u8X;
|
|
}
|
|
|
|
void SetCoursorXY(unsigned char x, unsigned char y) const {
|
|
u16CoursorPosition = x + (y << 4);
|
|
}
|
|
|
|
void SetFont(const IFont *pFont) const { pCurrentFont = pFont; }
|
|
|
|
void DrawLine(int sx, int ex, int ny) {
|
|
for (int i = sx; i <= ex; i++) {
|
|
if (i < Bitmap.SizeX && ny < Bitmap.SizeY) {
|
|
Bitmap.SetPixel(i, ny);
|
|
}
|
|
}
|
|
}
|
|
|
|
void DrawHLine(int sy, int ey, int nx, bool bCropped = false) {
|
|
for (int i = sy; i <= ey; i++) {
|
|
if (i < Bitmap.SizeY && nx < Bitmap.SizeX && (!bCropped || i % 2)) {
|
|
Bitmap.SetPixel(nx, i);
|
|
}
|
|
}
|
|
}
|
|
|
|
void DrawCircle(unsigned char cx, unsigned char cy, unsigned int r,
|
|
bool bFilled = false) {
|
|
int x = 0;
|
|
int y = r;
|
|
int d = 3 - 2 * r;
|
|
if (!r)
|
|
return;
|
|
|
|
while (y >= x) {
|
|
// when bFilled is true, draw lines to fill the circle
|
|
if (bFilled) {
|
|
DrawLine(cx - x, cx + x, cy - y);
|
|
DrawLine(cx - y, cx + y, cy - x);
|
|
DrawLine(cx - x, cx + x, cy + y);
|
|
DrawLine(cx - y, cx + y, cy + x);
|
|
} else {
|
|
if (cx + x < Bitmap.SizeX && cy + y < Bitmap.SizeY)
|
|
Bitmap.SetPixel(cx + x, cy - y); // 1st quarter
|
|
if (cx + y < Bitmap.SizeX && cy + x < Bitmap.SizeY)
|
|
Bitmap.SetPixel(cx + y, cy - x); // 2nd quarter
|
|
if (cx - x >= 0 && cy + y < Bitmap.SizeY)
|
|
Bitmap.SetPixel(cx - x, cy - y); // 3rd quarter
|
|
if (cx - y >= 0 && cy + x < Bitmap.SizeY)
|
|
Bitmap.SetPixel(cx - y, cy - x); // 4th quarter
|
|
if (cx + x < Bitmap.SizeX && cy + y < Bitmap.SizeY)
|
|
Bitmap.SetPixel(cx + x, cy + y); // 5th quarter
|
|
if (cx + y < Bitmap.SizeX && cy - x >= 0)
|
|
Bitmap.SetPixel(cx + y, cy + x); // 6th quarter
|
|
if (cx - x >= 0 && cy - y >= 0)
|
|
Bitmap.SetPixel(cx - x, cy + y); // 7th quarter
|
|
if (cx - y >= 0 && cy - x >= 0)
|
|
Bitmap.SetPixel(cx - y, cy + x); // 8th quarter
|
|
}
|
|
x++;
|
|
if (d < 0)
|
|
d += 4 * x + 6;
|
|
else {
|
|
y--;
|
|
d += 4 * (x - y) + 10;
|
|
}
|
|
}
|
|
}
|
|
|
|
void DrawRectangle(unsigned char sx, unsigned char sy, unsigned char width,
|
|
unsigned char height, bool bFilled) {
|
|
unsigned char maxX =
|
|
(sx + width < Bitmap.SizeX) ? sx + width : Bitmap.SizeX;
|
|
unsigned char maxY =
|
|
(sy + height < Bitmap.SizeY) ? sy + height : Bitmap.SizeY;
|
|
|
|
// Draw vertical lines
|
|
for (unsigned char y = sy; y < maxY; y++) {
|
|
Bitmap.SetPixel(sx, y);
|
|
Bitmap.SetPixel(maxX - 1, y);
|
|
}
|
|
|
|
// Draw horizontal lines
|
|
for (unsigned char x = sx; x < maxX; x++) {
|
|
Bitmap.SetPixel(x, sy);
|
|
Bitmap.SetPixel(x, maxY - 1);
|
|
}
|
|
|
|
// If filled, draw horizontal lines within the rectangle
|
|
if (bFilled) {
|
|
for (unsigned char x = sx + 1; x < maxX - 1; x++) {
|
|
for (unsigned char y = sy + 1; y < maxY - 1; y++) {
|
|
Bitmap.SetPixel(x, y);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
unsigned char PrintCharacter(const char c8Character) const {
|
|
if (!pCurrentFont) {
|
|
return 0;
|
|
}
|
|
|
|
const auto *const pFontRawData = pCurrentFont->GetRaw(c8Character);
|
|
auto *pCoursorPosition = Bitmap.GetCoursorData(u16CoursorPosition);
|
|
auto const CopySize =
|
|
pCurrentFont->GetSizeY(c8Character) * (BitmapType::LineHeight / 8);
|
|
if (pCoursorPosition && !(BitmapType::LineHeight % 8)) {
|
|
if (pFontRawData)
|
|
memcpy(pCoursorPosition, pFontRawData, CopySize);
|
|
else
|
|
memset(pCoursorPosition, 0, CopySize);
|
|
}
|
|
|
|
u16CoursorPosition += pCurrentFont->GetSizeY(c8Character);
|
|
return 0;
|
|
}
|
|
|
|
void Print(const char *C8String) const {
|
|
for (unsigned char i = 0; i < strlen(C8String); i++) {
|
|
PrintCharacter(C8String[i]);
|
|
}
|
|
}
|
|
|
|
unsigned char PrintFixedDigtsNumer(int s32Number, unsigned char u8Digts) {
|
|
char U8NumBuff[32];
|
|
memset(U8NumBuff, 0, sizeof(U8NumBuff));
|
|
|
|
char *pString = U8NumBuff + u8Digts;
|
|
*pString = '\0';
|
|
|
|
if (s32Number < 0) {
|
|
U8NumBuff[0] = '-';
|
|
s32Number = -s32Number;
|
|
}
|
|
|
|
while (u8Digts--) {
|
|
*--pString = '0' + (s32Number % 10);
|
|
s32Number /= 10;
|
|
}
|
|
|
|
Print(U8NumBuff);
|
|
return u8Digts * pCurrentFont->GetSizeX('0');
|
|
}
|
|
|
|
static constexpr int powersOfTen[9] = {
|
|
1, // 10^0
|
|
10, // 10^1
|
|
100, // 10^2
|
|
1000, // 10^3
|
|
10000, // 10^4
|
|
100000, // 10^5
|
|
1000000, // 10^6
|
|
10000000, // 10^7
|
|
100000000 // 10^8
|
|
};
|
|
void PrintFixedDigitsNumber2(int s32Number, unsigned char u8DigsToCut = 2,
|
|
unsigned char u8FixedDigtsCnt = 0) {
|
|
char U8NumBuff[11] = {0}; // 9 digits, sign, and null terminator
|
|
int startIdx = 0;
|
|
bool isNegative = false;
|
|
|
|
if (s32Number < 0) {
|
|
PrintCharacter('-');
|
|
// U8NumBuff[0] = '-';
|
|
s32Number = -s32Number;
|
|
// isNegative = true;
|
|
}
|
|
|
|
for (int i = 8; i >= u8DigsToCut;
|
|
--i) // assuming powersOfTen is an array of powers of 10
|
|
{
|
|
int digit = 0;
|
|
while (s32Number >= powersOfTen[i]) {
|
|
s32Number -= powersOfTen[i];
|
|
++digit;
|
|
}
|
|
U8NumBuff[isNegative + (8 - i)] = '0' + digit;
|
|
|
|
// We found the first non-zero digit
|
|
if (digit != 0 && startIdx == (isNegative ? 1 : 0))
|
|
startIdx = isNegative + (8 - i);
|
|
}
|
|
|
|
// If the number was 0, we write a single 0.
|
|
if (startIdx == (isNegative ? 1 : 0))
|
|
U8NumBuff[isNegative] = '0';
|
|
|
|
// Print the string from the start index
|
|
if (u8FixedDigtsCnt) {
|
|
startIdx = 9 - u8DigsToCut - u8FixedDigtsCnt;
|
|
}
|
|
|
|
Print(U8NumBuff + startIdx);
|
|
}
|
|
void PrintFixedDigitsNumber3(int s32Number, unsigned char u8DigsToCut = 2,
|
|
unsigned char u8FixedDigtsCnt = 0,
|
|
unsigned char pointAt = 128) {
|
|
char U8NumBuff[11] = {0}; // 9 digits, sign, and null terminator
|
|
unsigned char startIdx = 0;
|
|
|
|
for (unsigned char i = 8; i >= u8DigsToCut; --i) {
|
|
int digit = 0;
|
|
while (s32Number >= powersOfTen[i]) {
|
|
s32Number -= powersOfTen[i];
|
|
++digit;
|
|
}
|
|
U8NumBuff[8 - i] = '0' + digit;
|
|
|
|
// We found the first non-zero digit
|
|
if (digit != 0 && startIdx == 0)
|
|
startIdx = 8 - i;
|
|
}
|
|
|
|
// If the number was 0, we write a single 0.
|
|
/* if (startIdx == 0)
|
|
U8NumBuff[0] = '0'; */
|
|
|
|
// Print the string from the start index
|
|
if (u8FixedDigtsCnt) {
|
|
startIdx = 9 - u8DigsToCut - u8FixedDigtsCnt;
|
|
}
|
|
|
|
const char *str = U8NumBuff + startIdx;
|
|
const char len = strlen(str);
|
|
const char dot[1] = {64};
|
|
for (unsigned char i = 0; i < len; i++) {
|
|
if (pointAt == len - i) {
|
|
auto *pCoursorPosition = Bitmap.GetCoursorData(u16CoursorPosition + 1);
|
|
memcpy(pCoursorPosition, dot, 1);
|
|
u16CoursorPosition += 2;
|
|
}
|
|
PrintCharacter(str[i]);
|
|
}
|
|
}
|
|
|
|
private:
|
|
const BitmapType &Bitmap;
|
|
mutable const IFont *pCurrentFont;
|
|
mutable unsigned short u16CoursorPosition;
|
|
};
|