Refine the bresenham implementation

This commit is contained in:
Savanni D'Gerinel 2022-07-17 23:01:27 -04:00
parent c9e0775b4b
commit a81d8cec6b
5 changed files with 135 additions and 56 deletions

View File

@ -1,43 +1,82 @@
#include "animation.h" #include "animation.h"
#include <stdio.h>
line_t line_new(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1) { time_line_t time_line_new(int t0, int y0, int t1, int y1) {
uint8_t dx = x1 - x0; int dt = t1 - t0;
int8_t dy = y1 - y0; int dy = y1 - y0;
int8_t inc = dy > 0 ? 1 : dy == 0 ? 0 : -1; int de = 2 * dy;
int8_t m = 2 * dy;
int8_t error = 0; int inc = dy > 0 ? 1 : dy == 0 ? 0 : -1;
int error;
if (de > 0) {
error = de - dt;
} else {
error = de + dt;
}
return (time_line_t){ .y = y0, .dt = dt, .de = de, .error = error, .inc = inc, .dy = dy };
}
int time_line_next(time_line_t *self) {
int error = self->error + self->de;
if (self->de > 0) {
while (error >= 0) {
self->y += self->inc;
error -= 2 * self->dt;
}
} else {
while (error < 0) {
self->y -= self->inc;
error += 2 * self->dt;
}
}
self->error = error;
return self->y;
}
/*
time_line_t time_line_new(int t0, int y0, int t1, int y1) {
int dt = t1 - t0;
int dy = y1 - y0;
int inc = dy > 0 ? 1 : dy == 0 ? 0 : -1;
int m = 2 * dy;
int error = 0;
if (m > 0) { if (m > 0) {
error = m - dx; error = m - dt;
} else { } else {
error = m + dx; error = m + dt;
} }
return (line_t){ .y = y0, .m = m, .error = error, .inc = inc, .dx = dx }; return (time_line_t){ .y = y0, .m = m, .error = error, .inc = inc, .dt = dt };
} }
*/
uint8_t line_next(line_t *slope) { /*
int time_line_next(time_line_t *slope) {
slope->error += slope->m; slope->error += slope->m;
if (slope->m > 0) { if (slope->m > 0) {
if (slope->error >= 0) { if (slope->error >= 0) {
slope->y += slope->inc; slope->y += slope->inc;
slope->error -= 2 * slope->dx; slope->error -= 2 * slope->dt;
} }
} else { } else {
if (slope->error <= 0) { if (slope->error <= 0) {
slope->y += slope->inc; slope->y += slope->inc;
slope->error += 2 * slope->dx; slope->error += 2 * slope->dt;
} }
} }
return slope->y; return slope->y;
} }
/*
void line_print(line_t *line) {
printf("y: %d\tm: %d\terror: %d\tinc: %d\t:dx: %d\n", line->y, line->m, line->error, line->inc, line->dx);
}
*/ */
void time_line_print(time_line_t *self) {
printf("y: %d\tde: %d\terror: %d\tinc: %d\t:dt: %d\n", self->y, self->de, self->error, self->inc, self->dt);
}

View File

@ -1,25 +1,24 @@
#ifndef __ANIMATION_H__ #ifndef __ANIMATION_H__
#define __ANIMATION_H__ #define __ANIMATION_H__
#include <avr/io.h>
// line_t provides a simplified implementation of Bresenham's line drawing // line_t provides a simplified implementation of Bresenham's line drawing
// technique. At this time, it assumes a transition of x = 0 -> 60, and a dy // technique. At this time, it assumes a transition of x = 0 -> 60, and a dy
// between -59 and 59. I am not sure I understand Bresenham's algorithm yet, // between -59 and 59. I am not sure I understand Bresenham's algorithm yet,
// but I'll need to revisit all of this if I want to expand the boundaries. // but I'll need to revisit all of this if I want to expand the boundaries.
typedef struct line_s { typedef struct {
uint8_t y; int y;
int8_t m; int de;
int8_t error; int error;
int8_t inc; int inc;
uint8_t dx; int dt;
} line_t; int dy;
} time_line_t;
// Construct a new line object. x1 must be greater than x0, and dy must be less than dx. // Construct a new line object. x1 must be greater than x0, and dy must be less than dx.
line_t line_new(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1); time_line_t time_line_new(int, int, int, int);
// Calculate the next y value of the line. // Calculate the next y value of the line.
uint8_t line_next(line_t *line); int time_line_next(time_line_t *);
// Diagnostic printout of the current state of line_t. // Diagnostic printout of the current state of line_t.
// void line_print(line_t *line); // void line_print(line_t *line);

View File

@ -1,30 +1,30 @@
#include <stdlib.h> #include <stdlib.h>
void bresenham(int x1, int y1, int x2, int y2) { void bresenham_time(int t1, int y1, int t2, int y2) {
int dx = x2 - x1; int dt = t2 - t1;
int dy = y2 - y1; int dy = y2 - y1;
int m = 2 * dy; int m = 2 * dy;
int err = 0; int err = 0;
if (m > 0) { if (m > 0) {
err = m - dx; err = m - dt;
} else if (m < 0) { } else if (m < 0) {
err = m + dx; err = m + dt;
} }
for (int x = x1, y = y1; x <= x2; x++) { for (int t = t1, y = y1; t <= t2; t++) {
printf("(%d, %d) [%d]\n", x, y, err); printf("(%d, %d) [%d]\n", t, y, err);
err += m; err += m;
if (m > 0) { if (m > 0) {
if (err >= 0) { if (err >= 0) {
y++; y++;
err -= 2 * dx; err -= 2 * dt;
} }
} else if (m < 0) { } else if (m < 0) {
if (err <= 0) { if (err <= 0) {
y--; y--;
err += 2 * dx; err += 2 * dt;
} }
} }
} }

View File

@ -1,21 +1,36 @@
#include <stdlib.h> #include <stdlib.h>
#include <base.h> #include <stdio.h>
#include <rng.h> #include <animation.h>
typedef struct RGB_s {
uint8_t brightness;
uint8_t r;
uint8_t g;
uint8_t b;
} rgb_t;
int main (void) { int main (void) {
rng_t rng = rng_new(0); {
animation_t animation = animation_new(); time_line_t line = time_line_new(0, 0, 15, 10);
time_line_print(&line);
for (int i = 0; i < 15; i++) {
time_line_next(&line);
time_line_print(&line);
}
}
for (int i = 0; i < 120; i++) { printf("\n");
animation_step(&animation, &rng);
printf("[%d] %d %d %d\n", animation.frame, animation.lamp.r, animation.lamp.g, animation.lamp.b); {
time_line_t line = time_line_new(0, 0, 15, 25);
time_line_print(&line);
for (int i = 0; i < 15; i++) {
time_line_next(&line);
time_line_print(&line);
}
}
printf("\n");
{
time_line_t line = time_line_new(0, 0, 10, 255);
time_line_print(&line);
for (int i = 0; i < 10; i++) {
time_line_next(&line);
time_line_print(&line);
}
} }
} }

View File

@ -75,18 +75,18 @@
}; };
packages."x86_64-linux"."animation" = packages."x86_64-linux"."animation" =
{ mcu, chip_select, f_cpu }: # { gcc, mcu, chip_select, f_cpu }:
{ gcc }:
let let
pkgs = import nixpkgs { system = "x86_64-linux"; }; pkgs = import nixpkgs { system = "x86_64-linux"; };
avr = pkgs.pkgsCross.avr.buildPackages;
in pkgs.stdenv.mkDerivation rec { in pkgs.stdenv.mkDerivation rec {
name = "animation"; name = "animation";
src = ./.; src = ./.;
CFLAGS = cflags { inherit mcu chip_select f_cpu; }; # CFLAGS = cflags { inherit mcu chip_select f_cpu; };
buildPhase = '' buildPhase = ''
${avr.gcc}/bin/avr-gcc ${CFLAGS} -o animation.o -c ${src}/animation/animation.c ${gcc} -o animation.o -c ${src}/animation/animation.c
''; '';
installPhase = '' installPhase = ''
@ -95,6 +95,32 @@
''; '';
}; };
packages."x86_64-linux"."animation-test" =
let
pkgs = import nixpkgs { system = "x86_64-linux"; };
lib = pkgs.lib;
in pkgs.stdenv.mkDerivation rec {
name = "animation-test";
src = ./.;
buildInputs = [
(packages."x86_64-linux"."animation" { inherit gcc; })
];
INCLUDE_DIRS = lib.concatStringsSep " " (map (dir: "-I${dir}") buildInputs);
OBJECT_FILES = lib.concatStringsSep " " (map (dir: "${dir}/*.o") buildInputs);
gcc = "${pkgs.gcc}/bin/gcc";
buildPhase = ''
${gcc} ${INCLUDE_DIRS} -o main.o -c ${src}/animation/main.c
${gcc} ${INCLUDE_DIRS} -o animation-test main.o ${OBJECT_FILES}
'';
installPhase = ''
mkdir $out
cp animation-test $out
'';
};
packages."x86_64-linux"."sk9822" = packages."x86_64-linux"."sk9822" =
{ mcu, chip_select, f_cpu }: { mcu, chip_select, f_cpu }:
let let