Оптимизированы функции полттера добавлены функции для рисования стрелок
Плоттер - функция для отрисовки интерфейса плоттера - функция для отрисовки самого графика (кривой) - функции для отрисовки float, int, uint8_t, uint16_t - добавлены сдвиги осей Стрелки - функция для рисования ортогональных стрелок (вправо, влево, вверх, вниз) - функция для рисования стрелок в любом направлении
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
#include "math.h"
|
#include "math.h"
|
||||||
int menu_white_theme = 0;
|
int menu_white_theme = 0;
|
||||||
|
|
||||||
|
//#define ROTATING_ARROW_EXAMPLE
|
||||||
#define SINE_EXAMPLE
|
#define SINE_EXAMPLE
|
||||||
//#define ECG_EXAMPLE
|
//#define ECG_EXAMPLE
|
||||||
//#define PLAYER_EXAMPLE
|
//#define PLAYER_EXAMPLE
|
||||||
@@ -63,7 +64,7 @@ float ecg_data[ECG_SIZE] = {1.05893, 0.999357, 0.933132, 0.744792, 0.664672, 0.3
|
|||||||
void GFX_Draw_LoopIcon(uint8_t *Buffer_Frame, uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t pxColor);
|
void GFX_Draw_LoopIcon(uint8_t *Buffer_Frame, uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t pxColor);
|
||||||
|
|
||||||
GFXIconsTypeDef icons;
|
GFXIconsTypeDef icons;
|
||||||
GFX_PlotterFloatHandleTypeDef plotter;
|
GFX_PlotterHandleTypeDef plotter;
|
||||||
|
|
||||||
void Example_GFX_Init(void)
|
void Example_GFX_Init(void)
|
||||||
{
|
{
|
||||||
@@ -84,18 +85,26 @@ void Example_OLED_GFX_Update(PlayerTypeDef *player)
|
|||||||
oled_refresh();
|
oled_refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
float sine2plot;
|
uint8_t sine2plot;
|
||||||
float sine_cnt_step = 0.01;
|
float sine_cnt_step = 0.5;
|
||||||
float sine_cnt = 1;
|
float sine_cnt = 1;
|
||||||
|
float sine_scale = 255;
|
||||||
|
float ecg_step = 2.5;
|
||||||
|
float ecg_scale = 1.1;
|
||||||
void Example_GFX_CreateFrame(PlayerTypeDef *player)
|
void Example_GFX_CreateFrame(PlayerTypeDef *player)
|
||||||
{
|
{
|
||||||
#if defined(SINE_EXAMPLE)
|
#if defined(ROTATING_ARROW_EXAMPLE)
|
||||||
sine2plot = sinf(sine_cnt);
|
GFX_Clean_Buffer_Frame(oled_buf);
|
||||||
GFX_FloatPlotter(oled_buf, &plotter, &sine2plot);
|
__GFX_Draw_Arrow(oled_buf, 64, 16, 5, sine_cnt, 1);
|
||||||
|
sine_cnt+=ecg_step;
|
||||||
|
|
||||||
|
#elif defined(SINE_EXAMPLE)
|
||||||
|
sine2plot = (sinf(sine_cnt)+1)*128;
|
||||||
|
GFX_Plotter_uint8_t(oled_buf, &plotter, &sine2plot, 0, 0, sine_scale);
|
||||||
sine_cnt += sine_cnt_step;
|
sine_cnt += sine_cnt_step;
|
||||||
|
|
||||||
#elif defined(ECG_EXAMPLE)
|
#elif defined(ECG_EXAMPLE)
|
||||||
GFX_FloatPlotter(oled_buf, &plotter, NULL);
|
GFX_Plotter_float(oled_buf, &plotter, ecg_data, ECG_SIZE, ecg_step, ecg_scale);
|
||||||
|
|
||||||
#elif defined(PLAYER_EXAMPLE)
|
#elif defined(PLAYER_EXAMPLE)
|
||||||
GFX_Clean_Buffer_Frame(oled_buf);
|
GFX_Clean_Buffer_Frame(oled_buf);
|
||||||
@@ -198,25 +207,23 @@ void GFX_Draw_LoopIcon(uint8_t *Buffer_Frame, uint8_t x, uint8_t y, uint8_t widt
|
|||||||
|
|
||||||
void Example_GFX_PlotterInit(void)
|
void Example_GFX_PlotterInit(void)
|
||||||
{
|
{
|
||||||
|
#if defined(SINE_EXAMPLE)
|
||||||
|
plotter.xPos = 0;
|
||||||
|
plotter.yPos = 0;
|
||||||
|
plotter.plotWidth = 128;
|
||||||
|
plotter.plotHeight = 30;
|
||||||
|
plotter.plotYShift = 64;
|
||||||
|
plotter.f.plotXAxis = 1;
|
||||||
|
plotter.f.plotYAxis = 1;
|
||||||
|
#elif defined(ECG_EXAMPLE)
|
||||||
plotter.xPos = 2;
|
plotter.xPos = 2;
|
||||||
plotter.yPos = 0;
|
plotter.yPos = 0;
|
||||||
plotter.plotWidth = 120;
|
plotter.plotWidth = 128-plotter.xPos;
|
||||||
plotter.plotHeight = 32;
|
plotter.plotHeight = 32;
|
||||||
plotter.plotXAxis = 1;
|
plotter.f.plotXAxis = 1;
|
||||||
plotter.plotYAxis = 1;
|
plotter.f.plotYAxis = 1;
|
||||||
|
plotter.f.plotFrame = 1;
|
||||||
#if defined(SINE_EXAMPLE)
|
|
||||||
plotter.dataMax = 1.1;
|
|
||||||
plotter.signedData = 1;
|
|
||||||
#elif defined(ECG_EXAMPLE)
|
|
||||||
|
|
||||||
plotter.pDataPtr = ecg_data;
|
|
||||||
plotter.dataMax = 1.1;
|
|
||||||
plotter.dataSize = 550;
|
|
||||||
plotter.plotShift = 0;
|
|
||||||
plotter.plotSpeed = 2.5;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
void Example_GFX_IconInit(void)
|
void Example_GFX_IconInit(void)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -10,9 +10,9 @@
|
|||||||
*/
|
*/
|
||||||
#include "gfx_lib.h"
|
#include "gfx_lib.h"
|
||||||
#include "font_tahoma_8_prop.h"
|
#include "font_tahoma_8_prop.h"
|
||||||
|
|
||||||
#include "math.h"
|
#include "math.h"
|
||||||
|
|
||||||
|
#define PI 3.1415926535
|
||||||
/* переменные */
|
/* переменные */
|
||||||
uint8_t chSpacing = 0; //межсимвольный интервал в px
|
uint8_t chSpacing = 0; //межсимвольный интервал в px
|
||||||
|
|
||||||
@@ -405,9 +405,13 @@ void GFX_Draw_Arrow(uint8_t *Buffer_Frame, GFX_ArrowHandleTypeDef *hArrow)
|
|||||||
uint8_t xPos = hArrow->xPos;
|
uint8_t xPos = hArrow->xPos;
|
||||||
uint8_t yPos = hArrow->yPos;
|
uint8_t yPos = hArrow->yPos;
|
||||||
uint8_t size = hArrow->size;
|
uint8_t size = hArrow->size;
|
||||||
uint16_t angle = hArrow->angle;
|
uint16_t angle = hArrow->angle % 360;
|
||||||
uint8_t pxColor = hArrow->pxColor;
|
uint8_t pxColor = hArrow->pxColor;
|
||||||
|
|
||||||
|
|
||||||
|
if((angle == 0) || (angle == 90) || (angle == 180) || (angle == 270))
|
||||||
|
__GFX_Draw_Arrow_Ortho(Buffer_Frame, xPos, yPos, size, angle, pxColor);
|
||||||
|
else
|
||||||
__GFX_Draw_Arrow(Buffer_Frame, xPos, yPos, size, angle, pxColor);
|
__GFX_Draw_Arrow(Buffer_Frame, xPos, yPos, size, angle, pxColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -435,8 +439,9 @@ void GFX_Draw_Arc(uint8_t *Buffer_Frame, GFX_ArcHandleTypeDef *hArc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Функция вывода графика */
|
|
||||||
void GFX_FloatPlotter(uint8_t *Buffer_Frame, GFX_PlotterFloatHandleTypeDef *hPlot, float *numb2plot)
|
/* Функция для отрисовки графика uint8_t массива */
|
||||||
|
void GFX_Plotter_uint8_t(uint8_t *Buffer_Frame, GFX_PlotterHandleTypeDef *hPlot, uint8_t *data, uint32_t data_size, float data_step, uint8_t data_max)
|
||||||
{
|
{
|
||||||
if((Buffer_Frame == NULL) || (hPlot == NULL))
|
if((Buffer_Frame == NULL) || (hPlot == NULL))
|
||||||
return;
|
return;
|
||||||
@@ -444,112 +449,157 @@ void GFX_FloatPlotter(uint8_t *Buffer_Frame, GFX_PlotterFloatHandleTypeDef *hPlo
|
|||||||
return;
|
return;
|
||||||
if((hPlot->yPos + hPlot->plotHeight == NULL) || (hPlot->xPos + hPlot->plotWidth == NULL))
|
if((hPlot->yPos + hPlot->plotHeight == NULL) || (hPlot->xPos + hPlot->plotWidth == NULL))
|
||||||
return;
|
return;
|
||||||
if((numb2plot == NULL) && (hPlot->pDataPtr == NULL))
|
if(data == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(hPlot->__initialized == 0)
|
|
||||||
{
|
|
||||||
hPlot->__initialized = 1;
|
|
||||||
hPlot->plotInd = 0;
|
|
||||||
GFX_Clean_Buffer_Frame(Buffer_Frame);
|
|
||||||
if(hPlot->plotXAxis)
|
|
||||||
{
|
|
||||||
__GFX_Draw_Line(Buffer_Frame, hPlot->xPos, hPlot->yPos+hPlot->plotHeight/2, hPlot->xPos+hPlot->plotWidth-1, hPlot->yPos+hPlot->plotHeight/2, 1);
|
|
||||||
__GFX_Draw_Arrow(Buffer_Frame, hPlot->xPos+hPlot->plotWidth-1, hPlot->yPos+hPlot->plotHeight/2, 2, 0, 1);
|
|
||||||
|
|
||||||
}
|
/* Расчет позиции пикселя */
|
||||||
if(hPlot->plotYAxis)
|
uint8_t pix_y_uint8t;
|
||||||
|
if(data_size == 0)
|
||||||
|
pix_y_uint8t = *data;
|
||||||
|
else
|
||||||
|
pix_y_uint8t = data[(int)hPlot->dataInd];
|
||||||
|
// масштабирование под размеры графика
|
||||||
|
hPlot->dataY = (pix_y_uint8t*hPlot->plotHeight)/data_max;
|
||||||
|
|
||||||
|
hPlot->f.dataSigned = 0;
|
||||||
|
/* Вывод пикселя */
|
||||||
|
__GFX_Draw_Plotter_Value(Buffer_Frame, hPlot);
|
||||||
|
|
||||||
|
/* Смещение графика далее */
|
||||||
|
hPlot->dataX++;
|
||||||
|
hPlot->dataPrevY = hPlot->dataY;
|
||||||
|
// Если используется массив плота
|
||||||
|
if(data == NULL)
|
||||||
{
|
{
|
||||||
__GFX_Draw_Line(Buffer_Frame, hPlot->xPos, hPlot->yPos, hPlot->xPos, hPlot->yPos+hPlot->plotHeight-1, 1);
|
hPlot->dataInd += data_step;
|
||||||
__GFX_Draw_Arrow(Buffer_Frame, hPlot->xPos, hPlot->yPos, 2, 90, 1);
|
if(hPlot->dataInd >= data_size)
|
||||||
}
|
hPlot->dataInd -= data_size;
|
||||||
if(hPlot->plotFrame)
|
|
||||||
{
|
if(hPlot->dataInd < 0)
|
||||||
__GFX_Draw_Rectangle(Buffer_Frame, hPlot->xPos, hPlot->yPos, hPlot->plotWidth-1, hPlot->plotHeight-1, 1);
|
hPlot->dataInd += data_size;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
/* Функция для отрисовки графика uint16_t массива */
|
||||||
|
void GFX_Plotter_uint16_t(uint8_t *Buffer_Frame, GFX_PlotterHandleTypeDef *hPlot, uint16_t *data, uint32_t data_size, float data_step, uint16_t data_max)
|
||||||
|
{
|
||||||
|
if((Buffer_Frame == NULL) || (hPlot == NULL))
|
||||||
|
return;
|
||||||
|
if((hPlot->plotHeight == NULL) || (hPlot->plotWidth == NULL))
|
||||||
|
return;
|
||||||
|
if((hPlot->yPos + hPlot->plotHeight == NULL) || (hPlot->xPos + hPlot->plotWidth == NULL))
|
||||||
|
return;
|
||||||
|
if(data == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
/* Подготовка к выводу графика */
|
/* Расчет позиции пикселя */
|
||||||
if((hPlot->pixX < hPlot->xPos) || (hPlot->pixX >= hPlot->plotWidth))
|
uint16_t pix_y_uint16t;
|
||||||
{
|
if(data_size == 0)
|
||||||
hPlot->pixX = hPlot->xPos;
|
pix_y_uint16t = *data;
|
||||||
GFX_Clean_Area(Buffer_Frame, hPlot->xPos, hPlot->yPos, hPlot->plotWidth, hPlot->plotHeight);
|
else
|
||||||
|
pix_y_uint16t = data[(int)hPlot->dataInd];
|
||||||
|
// масштабирование под размеры графика
|
||||||
|
hPlot->dataY = (pix_y_uint16t*hPlot->plotHeight)/data_max;
|
||||||
|
|
||||||
if(hPlot->plotXAxis)
|
hPlot->f.dataSigned = 0;
|
||||||
{
|
/* Вывод пикселя */
|
||||||
__GFX_Draw_Line(Buffer_Frame, hPlot->xPos, hPlot->yPos+hPlot->plotHeight/2, hPlot->xPos+hPlot->plotWidth-1, hPlot->yPos+hPlot->plotHeight/2, 1);
|
__GFX_Draw_Plotter_Value(Buffer_Frame, hPlot);
|
||||||
__GFX_Draw_Arrow(Buffer_Frame, hPlot->xPos+hPlot->plotWidth-1, hPlot->yPos+hPlot->plotHeight/2, 2, 0, 1);
|
|
||||||
|
|
||||||
}
|
/* Смещение графика далее */
|
||||||
if(hPlot->plotYAxis)
|
hPlot->dataX++;
|
||||||
|
hPlot->dataPrevY = hPlot->dataY;
|
||||||
|
// Если используется массив плота
|
||||||
|
if(data == NULL)
|
||||||
{
|
{
|
||||||
__GFX_Draw_Line(Buffer_Frame, hPlot->xPos, hPlot->yPos, hPlot->xPos, hPlot->yPos+hPlot->plotHeight-1, 1);
|
hPlot->dataInd += data_step;
|
||||||
__GFX_Draw_Arrow(Buffer_Frame, hPlot->xPos, hPlot->yPos, 2, 90, 1);
|
if(hPlot->dataInd >= data_size)
|
||||||
|
hPlot->dataInd -= data_size;
|
||||||
|
|
||||||
|
if(hPlot->dataInd < 0)
|
||||||
|
hPlot->dataInd += data_size;
|
||||||
}
|
}
|
||||||
if(hPlot->plotFrame)
|
}
|
||||||
|
/* Функция для отрисовки графика int массива */
|
||||||
|
void GFX_Plotter_int(uint8_t *Buffer_Frame, GFX_PlotterHandleTypeDef *hPlot, int *data, uint32_t data_size, float data_step, int data_max)
|
||||||
|
{
|
||||||
|
if((Buffer_Frame == NULL) || (hPlot == NULL))
|
||||||
|
return;
|
||||||
|
if((hPlot->plotHeight == NULL) || (hPlot->plotWidth == NULL))
|
||||||
|
return;
|
||||||
|
if((hPlot->yPos + hPlot->plotHeight == NULL) || (hPlot->xPos + hPlot->plotWidth == NULL))
|
||||||
|
return;
|
||||||
|
if(data == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
/* Расчет позиции пикселя */
|
||||||
|
uint8_t pix_y_int;
|
||||||
|
if(data_size == 0)
|
||||||
|
pix_y_int = *data;
|
||||||
|
else
|
||||||
|
pix_y_int = data[(int)hPlot->dataInd];
|
||||||
|
// масштабирование под размеры графика
|
||||||
|
hPlot->dataY = (pix_y_int*hPlot->plotHeight)/data_max;
|
||||||
|
|
||||||
|
hPlot->f.dataSigned = 1;
|
||||||
|
/* Вывод пикселя */
|
||||||
|
__GFX_Draw_Plotter_Value(Buffer_Frame, hPlot);
|
||||||
|
|
||||||
|
/* Смещение графика далее */
|
||||||
|
hPlot->dataX++;
|
||||||
|
hPlot->dataPrevY = hPlot->dataY;
|
||||||
|
// Если используется массив плота
|
||||||
|
if(data == NULL)
|
||||||
{
|
{
|
||||||
__GFX_Draw_Rectangle(Buffer_Frame, hPlot->xPos, hPlot->yPos, hPlot->plotWidth-1, hPlot->plotHeight-1, 1);
|
hPlot->dataInd += data_step;
|
||||||
}
|
if(hPlot->dataInd >= data_size)
|
||||||
|
hPlot->dataInd -= data_size;
|
||||||
|
|
||||||
|
if(hPlot->dataInd < 0)
|
||||||
|
hPlot->dataInd += data_size;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Функция для отрисовки графика float массива */
|
||||||
|
void GFX_Plotter_float(uint8_t *Buffer_Frame, GFX_PlotterHandleTypeDef *hPlot, float *data, uint32_t data_size, float data_step, float data_max)
|
||||||
|
{
|
||||||
|
if((Buffer_Frame == NULL) || (hPlot == NULL))
|
||||||
|
return;
|
||||||
|
if((hPlot->plotHeight == NULL) || (hPlot->plotWidth == NULL))
|
||||||
|
return;
|
||||||
|
if((hPlot->yPos + hPlot->plotHeight == NULL) || (hPlot->xPos + hPlot->plotWidth == NULL))
|
||||||
|
return;
|
||||||
|
if((data == NULL) || (data_size == 0))
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
/* Расчет позиции пикселя */
|
/* Расчет позиции пикселя */
|
||||||
float pix_y_float;
|
float pix_y_float;
|
||||||
if(numb2plot != NULL)
|
if(data_size == 0)
|
||||||
pix_y_float = *numb2plot;
|
pix_y_float = *data;
|
||||||
else
|
else
|
||||||
pix_y_float = (hPlot->pDataPtr[(int)hPlot->plotInd]);
|
pix_y_float = data[(int)hPlot->dataInd];
|
||||||
|
|
||||||
|
hPlot->f.dataSigned = 1;
|
||||||
// масштабирование под размеры графика
|
// масштабирование под размеры графика
|
||||||
hPlot->pixY = (pix_y_float/hPlot->dataMax)*(hPlot->plotHeight);
|
hPlot->dataY = (pix_y_float/data_max)*(hPlot->plotHeight);
|
||||||
// если график должен быть знаковым, то уменьшаем машстаб еще в два раза
|
|
||||||
if(hPlot->signedData)
|
|
||||||
hPlot->pixY = (hPlot->pixY + hPlot->plotHeight)/2;
|
|
||||||
// инвертирование y потому что он считается сверху вниз
|
|
||||||
uint8_t plot_y_down = hPlot->yPos + hPlot->plotHeight;
|
|
||||||
hPlot->pixY = plot_y_down - hPlot->pixY;
|
|
||||||
// Сдвиг графика
|
|
||||||
hPlot->pixY += hPlot->plotShift;
|
|
||||||
|
|
||||||
|
/* Вывод пикселя */
|
||||||
/* Вывод пикселя позиции пикселя */
|
__GFX_Draw_Plotter_Value(Buffer_Frame, hPlot);
|
||||||
// Передний фронт
|
|
||||||
if(hPlot->pixY - hPlot->prevPixY > 0)
|
|
||||||
{
|
|
||||||
/* Цикл для заполнения пикселей по вертикали, когда фронт очень резкий */
|
|
||||||
for(int y = hPlot->prevPixY+1; y <= hPlot->pixY; y++)
|
|
||||||
{
|
|
||||||
if((y<=hPlot->yPos+hPlot->plotHeight) && (y>=hPlot->yPos))
|
|
||||||
GFX_Draw_Pixel(Buffer_Frame, hPlot->pixX, y, 1);
|
|
||||||
}
|
|
||||||
}// Задний фронт
|
|
||||||
else if (hPlot->pixY - hPlot->prevPixY < 0)
|
|
||||||
{
|
|
||||||
/* Цикл для заполнения пикселей по вертикали, когда фронт очень резкий */
|
|
||||||
for(int y = hPlot->prevPixY-1; y >= hPlot->pixY; y--)
|
|
||||||
{
|
|
||||||
if((y<=hPlot->yPos+hPlot->plotHeight) && (y>=hPlot->yPos))
|
|
||||||
GFX_Draw_Pixel(Buffer_Frame, hPlot->pixX, y, 1);
|
|
||||||
}
|
|
||||||
}// Плато
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if((hPlot->pixY<=hPlot->yPos+hPlot->plotHeight) && (hPlot->pixY>=hPlot->yPos))
|
|
||||||
GFX_Draw_Pixel(Buffer_Frame, hPlot->pixX, hPlot->pixY, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Смещение графика далее */
|
/* Смещение графика далее */
|
||||||
hPlot->pixX++;
|
hPlot->dataX++;
|
||||||
hPlot->prevPixY = hPlot->pixY;
|
hPlot->dataPrevY = hPlot->dataY;
|
||||||
// Если используется массив плота
|
// Если используется массив плота
|
||||||
if(numb2plot == NULL)
|
if(data_size != 0)
|
||||||
{
|
{
|
||||||
hPlot->plotInd += hPlot->plotSpeed;
|
hPlot->dataInd += data_step;
|
||||||
if(hPlot->plotInd >= hPlot->dataSize)
|
if(hPlot->dataInd >= data_size)
|
||||||
hPlot->plotInd -= hPlot->dataSize;
|
hPlot->dataInd -= data_size;
|
||||||
|
|
||||||
if(hPlot->plotInd < 0)
|
if(hPlot->dataInd < 0)
|
||||||
hPlot->plotInd += hPlot->dataSize;
|
hPlot->dataInd += data_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -695,8 +745,41 @@ void __GFX_Draw_Triangle(uint8_t *Buffer_Frame, uint8_t xPos1, uint8_t yPos1, ui
|
|||||||
__GFX_Draw_Line(Buffer_Frame, xPos3, yPos3, xPos1, yPos1, pxColor);
|
__GFX_Draw_Line(Buffer_Frame, xPos3, yPos3, xPos1, yPos1, pxColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* функция рисования стрелки */
|
|
||||||
|
float roundUp(float num) {
|
||||||
|
if (num > 0) {
|
||||||
|
return ceilf(num); // Для положительных чисел используем ceil
|
||||||
|
} else {
|
||||||
|
return floorf(num); // Для отрицательных чисел используем floor
|
||||||
|
}
|
||||||
|
}
|
||||||
void __GFX_Draw_Arrow(uint8_t *Buffer_Frame, uint8_t xPos, uint8_t yPos, uint8_t size, uint16_t angle, uint8_t pxColor)
|
void __GFX_Draw_Arrow(uint8_t *Buffer_Frame, uint8_t xPos, uint8_t yPos, uint8_t size, uint16_t angle, uint8_t pxColor)
|
||||||
|
{
|
||||||
|
float rad = (angle-90) * PI / 180.0; // Переводим угол в радианы
|
||||||
|
|
||||||
|
// Кончик стрелки (самая острая точка)
|
||||||
|
int16_t x1 = xPos;
|
||||||
|
int16_t y1 = yPos;
|
||||||
|
|
||||||
|
// Два боковых конца (формируют треугольник стрелки)
|
||||||
|
int16_t x2 = xPos + roundUp(size * sinf(rad + PI / 4));
|
||||||
|
int16_t y2 = yPos + roundUp(size * cosf(rad + PI / 4));
|
||||||
|
|
||||||
|
int16_t x3 = xPos + roundUp(size * sinf(rad - PI / 4));
|
||||||
|
int16_t y3 = yPos + roundUp(size * cosf(rad - PI / 4));
|
||||||
|
|
||||||
|
// Ограничение от выхода за границы (если нужно)
|
||||||
|
if (x2 < 0) x2 = 0;
|
||||||
|
if (x3 < 0) x3 = 0;
|
||||||
|
if (y2 < 0) y2 = 0;
|
||||||
|
if (y3 < 0) y3 = 0;
|
||||||
|
|
||||||
|
// Рисуем стрелку как две линии
|
||||||
|
__GFX_Draw_Line(Buffer_Frame, x1, y1, x2, y2, pxColor);
|
||||||
|
__GFX_Draw_Line(Buffer_Frame, x1, y1, x3, y3, pxColor);
|
||||||
|
}
|
||||||
|
/* функция рисования стрелки под прямым углом */
|
||||||
|
void __GFX_Draw_Arrow_Ortho(uint8_t *Buffer_Frame, uint8_t xPos, uint8_t yPos, uint8_t size, uint16_t angle, uint8_t pxColor)
|
||||||
{
|
{
|
||||||
int16_t x1, y1, x2, y2, x3, y3;
|
int16_t x1, y1, x2, y2, x3, y3;
|
||||||
|
|
||||||
@@ -738,6 +821,8 @@ void __GFX_Draw_Arrow(uint8_t *Buffer_Frame, uint8_t xPos, uint8_t yPos, uint8_t
|
|||||||
y3 = yPos + size;
|
y3 = yPos + size;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
|
||||||
if(x1 < 0)
|
if(x1 < 0)
|
||||||
x1 = 0;
|
x1 = 0;
|
||||||
@@ -768,3 +853,101 @@ void __GFX_Draw_Arc(uint8_t *Buffer_Frame, uint8_t xPos, uint8_t yPos, uint8_t r
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Функция для отрисовки осей и рамки графика */
|
||||||
|
HAL_StatusTypeDef __GFX_StartPlot(uint8_t *Buffer_Frame, GFX_PlotterHandleTypeDef *hPlot)
|
||||||
|
{
|
||||||
|
if((hPlot->dataX < hPlot->xPos) || (hPlot->dataX >= hPlot->plotWidth))
|
||||||
|
{
|
||||||
|
hPlot->dataX = hPlot->xPos;
|
||||||
|
GFX_Clean_Area(Buffer_Frame, hPlot->xPos, hPlot->yPos, hPlot->plotWidth, hPlot->plotHeight);
|
||||||
|
|
||||||
|
if(hPlot->f.plotXAxis)
|
||||||
|
{
|
||||||
|
uint8_t xaxis_x_start = hPlot->xPos;
|
||||||
|
uint8_t xaxis_x_end = hPlot->xPos+hPlot->plotWidth-1;
|
||||||
|
uint8_t xaxis_y = hPlot->yPos-hPlot->plotXShift;
|
||||||
|
if(hPlot->f.dataSigned)
|
||||||
|
xaxis_y += hPlot->plotHeight/2;
|
||||||
|
else
|
||||||
|
xaxis_y += hPlot->plotHeight-1;
|
||||||
|
|
||||||
|
__GFX_Draw_Line(Buffer_Frame, xaxis_x_start, xaxis_y, xaxis_x_end, xaxis_y, 1);
|
||||||
|
__GFX_Draw_Arrow_Ortho(Buffer_Frame, xaxis_x_end, xaxis_y, 2, 0, 1);
|
||||||
|
|
||||||
|
}
|
||||||
|
if(hPlot->f.plotYAxis)
|
||||||
|
{
|
||||||
|
uint8_t yaxis_y_start = hPlot->yPos;
|
||||||
|
uint8_t yaxis_y_end = hPlot->yPos+hPlot->plotHeight-1;
|
||||||
|
uint8_t yaxis_x = hPlot->xPos+hPlot->plotYShift;
|
||||||
|
|
||||||
|
__GFX_Draw_Line(Buffer_Frame, yaxis_x, yaxis_y_start, yaxis_x, yaxis_y_end, 1);
|
||||||
|
__GFX_Draw_Arrow_Ortho(Buffer_Frame, yaxis_x, yaxis_y_start, 2, 90, 1);
|
||||||
|
}
|
||||||
|
if(hPlot->f.plotFrame)
|
||||||
|
{
|
||||||
|
__GFX_Draw_Rectangle(Buffer_Frame, hPlot->xPos, hPlot->yPos, hPlot->plotWidth-1, hPlot->plotHeight-1, 1);
|
||||||
|
}
|
||||||
|
return HAL_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return HAL_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Функция для отрисовки выбранной точки графика*/
|
||||||
|
void __GFX_Draw_Plotter_Value(uint8_t *Buffer_Frame, GFX_PlotterHandleTypeDef *hPlot)
|
||||||
|
{
|
||||||
|
/* Первичная инициализация плоттера */
|
||||||
|
if(hPlot->f.initialized == 0)
|
||||||
|
{
|
||||||
|
hPlot->f.initialized = 1;
|
||||||
|
GFX_Clean_Buffer_Frame(Buffer_Frame);
|
||||||
|
hPlot->dataX = -1;
|
||||||
|
if(__GFX_StartPlot(Buffer_Frame, hPlot) != HAL_OK)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Очищение графика после полного заполнения */
|
||||||
|
if((hPlot->dataX < hPlot->xPos) || (hPlot->dataX >= hPlot->plotWidth))
|
||||||
|
{
|
||||||
|
__GFX_StartPlot(Buffer_Frame, hPlot);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Расчет позиции на графике */
|
||||||
|
// если график должен быть знаковым, то уменьшаем машстаб еще в два раза
|
||||||
|
if(hPlot->f.dataSigned)
|
||||||
|
hPlot->dataY = (hPlot->dataY + hPlot->plotHeight)/2;
|
||||||
|
// инвертирование y потому что он считается сверху вниз
|
||||||
|
uint8_t plot_y_down = hPlot->yPos + hPlot->plotHeight-1;
|
||||||
|
hPlot->dataY = plot_y_down - hPlot->dataY;
|
||||||
|
// Сдвиг графика
|
||||||
|
hPlot->dataY += hPlot->plotXShift;
|
||||||
|
|
||||||
|
/* Вывод пикселя позиции пикселя */
|
||||||
|
// Передний фронт
|
||||||
|
if(hPlot->dataY - hPlot->dataPrevY > 0)
|
||||||
|
{
|
||||||
|
/* Цикл для заполнения пикселей по вертикали, когда фронт очень резкий */
|
||||||
|
for(int y = hPlot->dataPrevY+1; y <= hPlot->dataY; y++)
|
||||||
|
{
|
||||||
|
if((y<hPlot->yPos+hPlot->plotHeight) && (y>=hPlot->yPos))
|
||||||
|
GFX_Draw_Pixel(Buffer_Frame, hPlot->dataX, y, 1);
|
||||||
|
}
|
||||||
|
}// Задний фронт
|
||||||
|
else if (hPlot->dataY - hPlot->dataPrevY < 0)
|
||||||
|
{
|
||||||
|
/* Цикл для заполнения пикселей по вертикали, когда фронт очень резкий */
|
||||||
|
for(int y = hPlot->dataPrevY-1; y >= hPlot->dataY; y--)
|
||||||
|
{
|
||||||
|
if((y<hPlot->yPos+hPlot->plotHeight) && (y>=hPlot->yPos))
|
||||||
|
GFX_Draw_Pixel(Buffer_Frame, hPlot->dataX, y, 1);
|
||||||
|
}
|
||||||
|
}// Плато
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if((hPlot->dataY<hPlot->yPos+hPlot->plotHeight) && (hPlot->dataY>=hPlot->yPos))
|
||||||
|
GFX_Draw_Pixel(Buffer_Frame, hPlot->dataX, hPlot->dataY, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "stdio.h"
|
#include "stdio.h"
|
||||||
#include "oled.h"
|
|
||||||
|
|
||||||
#define GFX_BufferWidth 128 //ширина дисплея в пикселях
|
#define GFX_BufferWidth 128 //ширина дисплея в пикселях
|
||||||
#define GFX_BufferHeight 32 //высота дисплея в пикселях
|
#define GFX_BufferHeight 32 //высота дисплея в пикселях
|
||||||
@@ -89,23 +88,23 @@ typedef struct
|
|||||||
uint8_t plotHeight;
|
uint8_t plotHeight;
|
||||||
uint8_t plotWidth;
|
uint8_t plotWidth;
|
||||||
|
|
||||||
float *pDataPtr;
|
int16_t dataX;
|
||||||
uint32_t dataSize;
|
int32_t dataY;
|
||||||
float dataMax;
|
float dataInd;
|
||||||
|
int32_t dataPrevY;
|
||||||
|
|
||||||
float plotSpeed;
|
int16_t plotXShift;
|
||||||
float plotInd;
|
int16_t plotYShift;
|
||||||
uint8_t plotShift;
|
|
||||||
uint8_t pixX;
|
|
||||||
int32_t pixY;
|
|
||||||
uint8_t prevPixY;
|
|
||||||
|
|
||||||
unsigned signedData:1;
|
struct
|
||||||
|
{
|
||||||
|
unsigned dataSigned:1;
|
||||||
unsigned plotFrame:1;
|
unsigned plotFrame:1;
|
||||||
unsigned plotXAxis:1;
|
unsigned plotXAxis:1;
|
||||||
unsigned plotYAxis:1;
|
unsigned plotYAxis:1;
|
||||||
unsigned __initialized:1;
|
unsigned initialized:1;
|
||||||
}GFX_PlotterFloatHandleTypeDef;
|
}f;
|
||||||
|
}GFX_PlotterHandleTypeDef;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -126,7 +125,10 @@ void GFX_Draw_Circle(uint8_t *Buffer_Frame, GFX_CircleHandleTypeDef *hCircle);
|
|||||||
void GFX_Draw_Triangle(uint8_t *Buffer_Frame, GFX_TriangleHandleTypeDef *hTriangle);
|
void GFX_Draw_Triangle(uint8_t *Buffer_Frame, GFX_TriangleHandleTypeDef *hTriangle);
|
||||||
void GFX_Draw_Arrow(uint8_t *Buffer_Frame, GFX_ArrowHandleTypeDef *hArrow);
|
void GFX_Draw_Arrow(uint8_t *Buffer_Frame, GFX_ArrowHandleTypeDef *hArrow);
|
||||||
void GFX_Draw_Arc(uint8_t *Buffer_Frame, GFX_ArcHandleTypeDef *hArc);
|
void GFX_Draw_Arc(uint8_t *Buffer_Frame, GFX_ArcHandleTypeDef *hArc);
|
||||||
void GFX_FloatPlotter(uint8_t *Buffer_Frame, GFX_PlotterFloatHandleTypeDef *hPlot, float *numb2plot);
|
void GFX_Plotter_uint8_t(uint8_t *Buffer_Frame, GFX_PlotterHandleTypeDef *hPlot, uint8_t *data, uint32_t data_size, float data_step, uint8_t data_max);
|
||||||
|
void GFX_Plotter_uint16_t(uint8_t *Buffer_Frame, GFX_PlotterHandleTypeDef *hPlot, uint16_t *data, uint32_t data_size, float data_step, uint16_t data_max);
|
||||||
|
void GFX_Plotter_int(uint8_t *Buffer_Frame, GFX_PlotterHandleTypeDef *hPlot, int *data, uint32_t data_size, float data_step, int data_max);
|
||||||
|
void GFX_Plotter_float(uint8_t *Buffer_Frame, GFX_PlotterHandleTypeDef *hPlot, float *data, uint32_t data_size, float data_step, float data_max);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -141,5 +143,8 @@ void __GFX_Draw_Triangle(uint8_t *Buffer_Frame,
|
|||||||
uint8_t xPos3, uint8_t yPos3,
|
uint8_t xPos3, uint8_t yPos3,
|
||||||
uint8_t pxColor);
|
uint8_t pxColor);
|
||||||
void __GFX_Draw_Arrow(uint8_t *Buffer_Frame, uint8_t xPos, uint8_t yPos, uint8_t size, uint16_t angle, uint8_t pxColor);
|
void __GFX_Draw_Arrow(uint8_t *Buffer_Frame, uint8_t xPos, uint8_t yPos, uint8_t size, uint16_t angle, uint8_t pxColor);
|
||||||
|
void __GFX_Draw_Arrow_Ortho(uint8_t *Buffer_Frame, uint8_t xPos, uint8_t yPos, uint8_t size, uint16_t angle, uint8_t pxColor);
|
||||||
void __GFX_Draw_Arc(uint8_t *Buffer_Frame, uint8_t xPos, uint8_t yPos, uint8_t radius, uint16_t startAngle, uint16_t endAngle, uint8_t pxColor);
|
void __GFX_Draw_Arc(uint8_t *Buffer_Frame, uint8_t xPos, uint8_t yPos, uint8_t radius, uint16_t startAngle, uint16_t endAngle, uint8_t pxColor);
|
||||||
|
HAL_StatusTypeDef __GFX_StartPlot(uint8_t *Buffer_Frame, GFX_PlotterHandleTypeDef *hPlot);
|
||||||
|
void __GFX_Draw_Plotter_Value(uint8_t *Buffer_Frame, GFX_PlotterHandleTypeDef *hPlot);
|
||||||
#endif /* INC_PIXEL_GRAPHICS_H_ */
|
#endif /* INC_PIXEL_GRAPHICS_H_ */
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -148,24 +148,7 @@
|
|||||||
<Name>-U-O142 -O2254 -SF10000 -C0 -A0 -I0 -HNlocalhost -HP7184 -P1 -N00("ARM CoreSight SW-DP (ARM Core") -D00(1BA01477) -L00(0) -TO131090 -TC10000000 -TT10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC800 -FN1 -FF0STM32F10x_128.FLM -FS08000000 -FL010000 -FP0($$Device:STM32F103C8$Flash\STM32F10x_128.FLM) -WA0 -WE0 -WVCE4 -WS2710 -WM0 -WP2</Name>
|
<Name>-U-O142 -O2254 -SF10000 -C0 -A0 -I0 -HNlocalhost -HP7184 -P1 -N00("ARM CoreSight SW-DP (ARM Core") -D00(1BA01477) -L00(0) -TO131090 -TC10000000 -TT10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC800 -FN1 -FF0STM32F10x_128.FLM -FS08000000 -FL010000 -FP0($$Device:STM32F103C8$Flash\STM32F10x_128.FLM) -WA0 -WE0 -WVCE4 -WS2710 -WM0 -WP2</Name>
|
||||||
</SetRegEntry>
|
</SetRegEntry>
|
||||||
</TargetDriverDllRegistry>
|
</TargetDriverDllRegistry>
|
||||||
<Breakpoint>
|
<Breakpoint/>
|
||||||
<Bp>
|
|
||||||
<Number>0</Number>
|
|
||||||
<Type>0</Type>
|
|
||||||
<LineNumber>441</LineNumber>
|
|
||||||
<EnabledFlag>1</EnabledFlag>
|
|
||||||
<Address>134220274</Address>
|
|
||||||
<ByteObject>0</ByteObject>
|
|
||||||
<HtxType>0</HtxType>
|
|
||||||
<ManyObjects>0</ManyObjects>
|
|
||||||
<SizeOfObject>0</SizeOfObject>
|
|
||||||
<BreakByAccess>0</BreakByAccess>
|
|
||||||
<BreakIfRCount>1</BreakIfRCount>
|
|
||||||
<Filename>..\Core\GFX_Lib\gfx_lib.c</Filename>
|
|
||||||
<ExecCommand></ExecCommand>
|
|
||||||
<Expression>\\gfx_lcd\../Core/GFX_Lib/gfx_lib.c\441</Expression>
|
|
||||||
</Bp>
|
|
||||||
</Breakpoint>
|
|
||||||
<WatchWindow1>
|
<WatchWindow1>
|
||||||
<Ww>
|
<Ww>
|
||||||
<count>0</count>
|
<count>0</count>
|
||||||
@@ -237,6 +220,41 @@
|
|||||||
<WinNumber>1</WinNumber>
|
<WinNumber>1</WinNumber>
|
||||||
<ItemText>y,0x0A</ItemText>
|
<ItemText>y,0x0A</ItemText>
|
||||||
</Ww>
|
</Ww>
|
||||||
|
<Ww>
|
||||||
|
<count>14</count>
|
||||||
|
<WinNumber>1</WinNumber>
|
||||||
|
<ItemText>sine_cnt_step</ItemText>
|
||||||
|
</Ww>
|
||||||
|
<Ww>
|
||||||
|
<count>15</count>
|
||||||
|
<WinNumber>1</WinNumber>
|
||||||
|
<ItemText>sine2plot,0x0A</ItemText>
|
||||||
|
</Ww>
|
||||||
|
<Ww>
|
||||||
|
<count>16</count>
|
||||||
|
<WinNumber>1</WinNumber>
|
||||||
|
<ItemText>sine_scale</ItemText>
|
||||||
|
</Ww>
|
||||||
|
<Ww>
|
||||||
|
<count>17</count>
|
||||||
|
<WinNumber>1</WinNumber>
|
||||||
|
<ItemText>pix_y_float</ItemText>
|
||||||
|
</Ww>
|
||||||
|
<Ww>
|
||||||
|
<count>18</count>
|
||||||
|
<WinNumber>1</WinNumber>
|
||||||
|
<ItemText>ecg_scale</ItemText>
|
||||||
|
</Ww>
|
||||||
|
<Ww>
|
||||||
|
<count>19</count>
|
||||||
|
<WinNumber>1</WinNumber>
|
||||||
|
<ItemText>sine_cnt</ItemText>
|
||||||
|
</Ww>
|
||||||
|
<Ww>
|
||||||
|
<count>20</count>
|
||||||
|
<WinNumber>1</WinNumber>
|
||||||
|
<ItemText>sine_cnt_step</ItemText>
|
||||||
|
</Ww>
|
||||||
</WatchWindow1>
|
</WatchWindow1>
|
||||||
<Tracepoint>
|
<Tracepoint>
|
||||||
<THDelay>0</THDelay>
|
<THDelay>0</THDelay>
|
||||||
|
|||||||
Reference in New Issue
Block a user