Skip to content

Commit

Permalink
Added support for working with arrays and improved boundary checking
Browse files Browse the repository at this point in the history
  • Loading branch information
Bexin3 authored Jan 12, 2024
1 parent 201fac6 commit 4a8ed89
Show file tree
Hide file tree
Showing 5 changed files with 301 additions and 20 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# SpeeduinoGL
A work in progress library with basic graphical functions optimised for arm cortex m7. Tested on GIGA R1, with rasterization writing to registers between two lines, and basic shapes (triangles, circles and quadrilaterals).Support for processing arrays instead of pixels one by one is in progress.
A work in progress library with graphical functions optimised for arm cortex m7. Tested on GIGA R1, with rasterization writing to registers between two lines, and basic shapes (triangles, circles and quadrilaterals), but also transfer of one image to another with zoom shift and rotate transformations. Support for better examples, documentation, a whole display function fill and small changes to drawing function are in progress. The camera trasnfer takes about 30ms at 5x zoom, and while its slower at lower zoomes than each display pixel reading a camera ones, it progressively gets faster.
76 changes: 76 additions & 0 deletions examples/CameraToDisplaySquares/CameraToDisplaySquares.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#include <algorithm>
#include "SpeeduinoGL.h"
#include "arducam_dvp.h"
#include "Arduino_H7_Video.h"
#include "dsi.h"
#include "SDRAM.h"


float ShiftH = -100;
float ShiftV = -400;
float zoom = 5;
float rotationRad = 0.3;




Rectangle sq1 = {
{ 0, 0 },
{ 0, 480 },
{ 800, 0 },
{ 800, 480 }
};

uint16_t* DisplayFrameBuffer = (uint16_t*)SDRAM_START_ADDRESS;
FrameBuffer fb(1613300736);

#include "OV7670/ov767x.h"
// OV7670 ov767x;
OV7675 ov767x;
Camera cam(ov767x);
#define IMAGE_MODE CAMERA_RGB565

Arduino_H7_Video Display(800, 480, GigaDisplayShield);



void setup() {
// put your setup code here, to run once:

if (!cam.begin(CAMERA_R320x240, IMAGE_MODE, 30)) {
}
SDRAM.begin();
Display.begin();



dsi_lcdClear(0);
dsi_drawCurrentFrameBuffer();
dsi_lcdClear(0);
dsi_drawCurrentFrameBuffer();


FillRectangle(sq1, 0xFF00);


}

void loop() {
// put your main code here, to run repeatedly:

cam.grabFrame(fb, 3000);

long t1 = micros();

TransferSquares(ShiftH, ShiftV, zoom, rotationRad);


Serial.println(micros() - t1);

dsi_lcdDrawImage((void *)DisplayFrameBuffer, (void *)dsi_getCurrentFrameBuffer(), 480, 800, DMA2D_INPUT_RGB565);
dsi_drawCurrentFrameBuffer();

}



2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=SpeeduinoGL
version=0.0.2
version=0.0.4
author=Benjamin Gombala
maintainer=Benjamin Gombala [email protected] Bexin
sentence=A library with basic graphical functions optimised for arm cortex m7.
Expand Down
225 changes: 209 additions & 16 deletions src/SpeeduinoGL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,23 @@ uint32_t ImageAddress = 0x60000000;
uint32_t ResV = 480;
uint32_t ResH = 800;

uint16_t InputSizeH = 240;
uint16_t InputSizeV = 320;
uint32_t CameraAddress = 1613300736;


void ConfigBuffer(uint32_t Address, uint32_t ResolutionV, uint32_t ResolutionH) {
ResV = ResolutionV;
ImageAddress = Address;
ResH = ResolutionH;
}

void ConfigInput(uint32_t Address, uint32_t ResolutionV, uint32_t ResolutionH ) {
InputSizeV = ResolutionV;
CameraAddress = Address;
InputSizeH = ResolutionH;
}

void FillTriangle(Triangle triangle, uint16_t Colour) {
// Sort points based on x-coordinates
std::sort(&triangle.A, &triangle.C + 1,
Expand Down Expand Up @@ -75,6 +85,7 @@ uint32_t ResH = 800;
rectangle.A.h + gradAD * (ceil(rectangle.A.w) - rectangle.A.w),
rectangle.A.h + gradAB * (ceil(rectangle.A.w) - rectangle.A.w),
gradAB, gradAD, Colour, Polarized);


if (switched) {
PolarizedTwoLineRasterizer(ceil(rectangle.B.w), ceil(rectangle.C.w),
Expand All @@ -99,42 +110,90 @@ uint32_t ResH = 800;
}
}

void PolarizedTwoLineRasterizer(int32_t CellStartX, int32_t CellEndX, float PointerCoordinateH, float PointerEndH, float Gradient1, float Gradient2, uint16_t Colour, bool Polarity) {
DoubleFloat PolarizedTwoLineRasterizer(int32_t CellStartX, int32_t CellEndX, float PointerCoordinateH, float PointerEndH, float Gradient1, float Gradient2, uint16_t Colour, bool Polarity) {
if (Polarity) {
TwoLineRasterizer(CellStartX, CellEndX, PointerCoordinateH, PointerEndH, Gradient1, Gradient2, Colour);
return(TwoLineRasterizer(CellStartX, CellEndX, PointerCoordinateH, PointerEndH, Gradient1, Gradient2, Colour));
} else {
TwoLineRasterizer(CellStartX, CellEndX, PointerEndH, PointerCoordinateH, Gradient2, Gradient1, Colour);
return(TwoLineRasterizer(CellStartX, CellEndX, PointerEndH, PointerCoordinateH, Gradient2, Gradient1, Colour));
}
}


void TwoLineRasterizer(int32_t CellStartX, int32_t CellEndX, float PointerCoordinateH, float PointerEndH, float Gradient1, float Gradient2, uint16_t Colour) {
uint16_t* ImageBuffer = (uint16_t*)ImageAddress;
DoubleFloat TwoLineRasterizer(int32_t CellStartX, int32_t CellEndX, float PointerCoordinateH, float PointerEndH, float Gradient1, float Gradient2, uint16_t Colour) {



uint16_t* ImageBuffer = (uint16_t*)ImageAddress;


if (CellStartX < 0) {
PointerCoordinateH -= Gradient2 * CellStartX;
PointerEndH -= Gradient1 * CellStartX;
}

if (CellEndX < 0) {
PointerCoordinateH -= Gradient2 * (CellStartX-CellEndX);
PointerEndH -= Gradient1 * (CellStartX-CellEndX);
goto returnpoint;
} else {
PointerCoordinateH -= Gradient2 * CellStartX;
PointerEndH -= Gradient1 * CellStartX;
CellStartX = 0;
};
};







if (CellEndX > ResH) {
CellEndX = ResH;
}
};


for (uint32_t CurrentW = CellStartX; CellEndX > CurrentW; CurrentW++) {
uint32_t PointerCoorInt = ceil(PointerCoordinateH);
uint32_t PointerEndInt = ceil(PointerEndH);
int32_t PointerCoorInt = ceil(PointerCoordinateH);
int32_t PointerEndInt = ceil(PointerEndH);



if (PointerEndInt < 0) {
PointerEndInt = 0;
};

if (PointerCoorInt < 0) {
PointerCoorInt = 0;
};



if (PointerEndInt > ResV) {
PointerEndInt = ResV;
}
};

if (PointerCoorInt > ResV) {
PointerCoorInt = ResV;
};


for (int32_t CurrentH = PointerCoorInt; PointerEndInt > CurrentH; CurrentH++) {
for (uint32_t CurrentH = PointerCoorInt; PointerEndInt > CurrentH; CurrentH++) {
ImageBuffer[ResV * (CurrentW) + (CurrentH)] = Colour;
}
};

PointerCoordinateH += Gradient2;
PointerEndH += Gradient1;
}
};



returnpoint:

DoubleFloat Retruner = {PointerCoordinateH, PointerEndH};

return(Retruner);





}

void FillCircle(float Radius, uint16_t Colour, Point Centre) {
Expand Down Expand Up @@ -174,3 +233,137 @@ uint32_t ResH = 800;
}
}


void TransferSquares(float ShiftH, float ShiftV, float zoom, float rotationRad) {

uint16_t* InputBuffer = (uint16_t*)CameraAddress;

float gradient1 = cos(rotationRad);
float gradient2 = sin(rotationRad);


float HShift = zoom * gradient2;
float VShift = zoom * gradient1;

gradient1 = abs(gradient1);
gradient2 = abs(gradient2);

float grad1;
float grad2;



bool Polarized = 0;

if (sin(2 * rotationRad) <= 0) {
std::swap(gradient1, gradient2);
};

if (sin(4 * rotationRad) <= 0) {
Polarized = 1;
grad1 = gradient2 / gradient1;
grad2 = -gradient1 / gradient2;
} else {
grad1 = -gradient1 / gradient2;
grad2 = gradient2 / gradient1;
};




float CellPointerH = ShiftH;
float CellPointerV = ShiftV;

const float BoundStartH = 0 - zoom - abs(VShift);
const float BoundStartV = 0 - zoom - abs(HShift);
const float BoundEndH = ResH + zoom + abs(VShift);
const float BoundEndV = ResV + zoom + abs(HShift);


for (int16_t PosH = 0; PosH < InputSizeH; PosH++) {


float CellPointerHU = CellPointerH + VShift;
float CellPointerVU = CellPointerV + HShift;

float EOCPTRH = CellPointerHU;
float EOCPTRV = CellPointerVU;

float CellPointerH2 = CellPointerH - HShift;
float CellPointerV2 = CellPointerV + VShift;
float CellPointerHU2 = CellPointerHU - HShift;
float CellPointerVU2 = CellPointerVU + VShift;



for (int16_t PosV = 0; PosV < InputSizeV; PosV++) {

if (CellPointerH <= BoundEndH && CellPointerV <= BoundEndV && CellPointerH >= BoundStartH && CellPointerV >= BoundStartV) {



Rectangle square = {
{ CellPointerH, CellPointerV },
{ CellPointerHU, CellPointerVU },
{ CellPointerH2, CellPointerV2 },
{ CellPointerHU2, CellPointerVU2 }
};




uint16_t Colour = InputBuffer[InputSizeV * PosH + PosV];
Colour = (((Colour >> 8) & 0x00FF) | ((Colour << 8) & 0xFF00));



std::sort(&square.A, &square.C + 1,
[](const Point &a, const Point &b) {
return a.w < b.w;
});

if (square.A.w == square.B.w && square.A.h != square.D.h) {
std::swap(square.D.h, square.C.h);
};




DoubleFloat WouldWork =
PolarizedTwoLineRasterizer(ceil(square.A.w), ceil(square.B.w),
square.A.h + grad2 * (ceil(square.A.w) - square.A.w),
square.A.h + grad1 * (ceil(square.A.w) - square.A.w),
grad1, grad2, Colour, Polarized);

if (Polarized) { std::swap(WouldWork.Float1, WouldWork.Float2); };
WouldWork =
PolarizedTwoLineRasterizer(ceil(square.B.w), ceil(square.D.w),
WouldWork.Float2,
square.B.h + grad2 * (ceil(square.B.w) - square.B.w),
grad2, grad2, Colour, Polarized);

if (Polarized) { std::swap(WouldWork.Float1, WouldWork.Float2); };
WouldWork =
PolarizedTwoLineRasterizer(ceil(square.D.w), ceil(square.C.w),
square.D.h + grad1 * (ceil(square.D.w) - square.D.w),
WouldWork.Float1,
grad2, grad1, Colour, Polarized);
};

CellPointerH = CellPointerH2;
CellPointerV = CellPointerV2;

CellPointerHU = CellPointerHU2;
CellPointerVU = CellPointerVU2;

CellPointerH2 -= HShift;
CellPointerV2 += VShift;

CellPointerHU2 -= HShift;
CellPointerVU2 += VShift;
};

CellPointerH = EOCPTRH;
CellPointerV = EOCPTRV;
};
}
16 changes: 14 additions & 2 deletions src/SpeeduinoGL.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@
float h;
};


struct DoubleFloat {
float Float1;
float Float2;
};

struct Triangle {
Point A;
Point B;
Expand All @@ -21,12 +27,18 @@
Point C;
};




void ConfigBuffer(uint32_t address = 0x60000000, uint32_t ResolutionV = 480, uint32_t ResolutionH = 800);
void ConfigInput(uint32_t address = 1613300736, uint32_t ResolutionV = 320, uint32_t ResolutionH = 240);
void FillTriangle(Triangle triangle, uint16_t Colour);
void FillRectangle(Rectangle rectangle, uint16_t Colour);

void PolarizedTwoLineRasterizer(int32_t CellStartX, int32_t CellEndX, float PointerCoordinateH, float PointerEndH, float Gradient1, float Gradient2, uint16_t Colour, bool Polarity);
void TwoLineRasterizer(int32_t CellStartX, int32_t CellEndX, float PointerCoordinateH, float PointerEndH, float Gradient1, float Gradient2, uint16_t Colour);
DoubleFloat PolarizedTwoLineRasterizer(int32_t CellStartX, int32_t CellEndX, float PointerCoordinateH, float PointerEndH, float Gradient1, float Gradient2, uint16_t Colour, bool Polarity);
DoubleFloat TwoLineRasterizer(int32_t CellStartX, int32_t CellEndX, float PointerCoordinateH, float PointerEndH, float Gradient1, float Gradient2, uint16_t Colour);
void FillCircle(float Radius, uint16_t Colour, Point Centre);

void TransferSquares(float ShiftH, float ShiftV, float zoom, float rotationRad);

#endif

0 comments on commit 4a8ed89

Please sign in to comment.