Last active
June 13, 2020 17:53
-
-
Save djmips/3597baf53c74dd1c71bc0e9445dd7466 to your computer and use it in GitHub Desktop.
Line Draw into SAM3x8e DMA buffer (Arduino DUE)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Assume there is a currX and currY global state which is the current x,y position | |
// Assume that currBuffer points to a valid properly sized buffer in RAM for DMA | |
// | |
// Buffer size can be calculated as n * 4 bytes where n is max(xdelta, ydelta) | |
// where xdelta and ydelta are the extents of the line to be drawn | |
// | |
// xd and yd is the destination point | |
// | |
// The output DACs are 12 bit but for speed this outputs in steps of 4 to cut the point generation by 4 times | |
// Effective resolution is 1024 points in X and Y | |
// | |
// The routine uses a SWAR (SIMD within a register) technique of operating on two 16 bit values within a 32 bit register | |
// | |
// So in summary the words are 16 bit and only the low 12 bits are used for the DAC. And then I'm only stepping in 10 bit resolution | |
// The extra OR with 0x10000000 is a hardware flag to use the other DAC | |
// y is in the low word and x is in the high word | |
#define DAC_PACK_COORD(_x, _y) (((0x0FFF & (_y)) << 2) | ((0x0FFF & (_x)) << 18) | 0x10000000) | |
void line(uint16_t xd, uint16_t yd) { | |
uint16_t x1 = currX; | |
uint16_t y1 = currY; | |
uint16_t x2 = xd; | |
uint16_t y2 = yd; | |
// updated the new currX and currY to be the end position | |
currX = x2; | |
currY = y2; | |
uint16_t dx; // abs(deltax) | |
uint16_t dy; // abs(deltay) | |
uint16_t hx; // counter used when moving predominatnly in the x direction | |
uint16_t hy; // counter used when moving predominantly in the y direction | |
uint16_t ddx; // accumulator to decide when to move in the | |
uint16_t ddy; // accumulator | |
// packs both x and y into a 32 bit word suitable for DMA to DAC on Arduino DUE | |
uint32_t coord = DAC_PACK_COORD(x1,y1); | |
if (x1 > x2) { | |
dx = x1-x2; | |
if (y1 > y2) { | |
dy = y1-y2; | |
if (dy > dx) { | |
hy = dy; | |
ddy = dy; | |
while(hy) | |
{ | |
ddy = ddy - dx; | |
if (ddy < 0) { | |
coord = coord - (1 << 18); // Occasionally stepping by 1 in X (16 to shift to upper word and 2 more for increments of 4) | |
ddy = ddy + dy; | |
} | |
currBuffer[bufferCounter++] = coord; | |
coord = coord - (1<<2); // Always stepping by 1 in Y (increments of 4 because of 10 bit stepping) | |
hy = hy - 1; | |
} | |
} else { | |
hx = dx; | |
ddx = dx; | |
while(hx) | |
{ | |
ddx = ddx - dy; | |
if (ddx < 0) { | |
coord = coord - (1<<2); | |
ddx = ddx + dx; | |
} | |
currBuffer[bufferCounter++] = coord; | |
coord = coord - (1 << 18); | |
hx = hx - 1; | |
} | |
} | |
} else { | |
dy = y2-y1; | |
if (dy > dx) { | |
hy = dy; | |
ddy = dy; | |
while(hy) | |
{ | |
ddy = ddy - dx; | |
if (ddy < 0) { | |
coord = coord - (1<<18); | |
ddy = ddy + dy; | |
} | |
currBuffer[bufferCounter++] = coord; | |
coord = coord + (1<<2); | |
hy = hy - 1; | |
} | |
} else { | |
hx = dx; | |
ddx = dx; | |
while(hx) | |
{ | |
ddx = ddx - dy; | |
if (ddx < 0) { | |
coord = coord + (1<<2); | |
ddx = ddx + dx; | |
} | |
currBuffer[bufferCounter++] = coord; | |
coord = coord - (1<<18); | |
hx = hx - 1; | |
} | |
} | |
} | |
} else { | |
dx = x2-x1; | |
if (y1 > y2) { | |
dy = y1-y2; | |
if (dy > dx) { | |
hy = dy; | |
ddy = dy; | |
while(hy) | |
{ | |
ddy = ddy - dx; | |
if (ddy < 0) { | |
coord = coord + (1<<18); | |
ddy = ddy + dy; | |
} | |
currBuffer[bufferCounter++] = coord; | |
coord = coord - (1<<2); | |
hy = hy - 1; | |
} | |
} else { | |
hx = dx; | |
ddx = dx; | |
while(hx) | |
{ | |
ddx = ddx - dy; | |
if (ddx < 0) { | |
coord = coord - (1<<2); | |
ddx = ddx + dx; | |
} | |
currBuffer[bufferCounter++] = coord; | |
coord = coord + (1<<18); | |
hx = hx - 1; | |
} | |
} | |
} else { | |
dy = y2-y1; | |
if (dy > dx) { | |
hy = dy; | |
ddy = dy; | |
while(hy) | |
{ | |
ddy = ddy - dx; | |
if (ddy < 0) { | |
coord = coord + (1<<18); | |
ddy = ddy + dy; | |
} | |
currBuffer[bufferCounter++] = coord; | |
coord = coord + (1<<2); | |
hy = hy - 1; | |
} | |
} else { | |
hx = dx; | |
ddx = dx; | |
while(hx) | |
{ | |
ddx = ddx - dy; | |
if (ddx < 0) { | |
coord = coord + (1<<2); | |
ddx = ddx + dx; | |
} | |
currBuffer[bufferCounter++] = coord; | |
coord = coord + (1<<18); | |
hx = hx - 1; | |
} | |
} | |
} | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment