Refine the bresenham implementation

i2c
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 <stdio.h>
line_t line_new(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1) {
uint8_t dx = x1 - x0;
int8_t dy = y1 - y0;
int8_t inc = dy > 0 ? 1 : dy == 0 ? 0 : -1;
int8_t m = 2 * dy;
int8_t error = 0;
time_line_t time_line_new(int t0, int y0, int t1, int y1) {
int dt = t1 - t0;
int dy = y1 - y0;
int de = 2 * dy;
if (m > 0) {
error = m - dx;
int inc = dy > 0 ? 1 : dy == 0 ? 0 : -1;
int error;
if (de > 0) {
error = de - dt;
} else {
error = m + dx;
error = de + dt;
}
return (line_t){ .y = y0, .m = m, .error = error, .inc = inc, .dx = dx };
return (time_line_t){ .y = y0, .dt = dt, .de = de, .error = error, .inc = inc, .dy = dy };
}
uint8_t line_next(line_t *slope) {
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) {
error = m - dt;
} else {
error = m + dt;
}
return (time_line_t){ .y = y0, .m = m, .error = error, .inc = inc, .dt = dt };
}
*/
/*
int time_line_next(time_line_t *slope) {
slope->error += slope->m;
if (slope->m > 0) {
if (slope->error >= 0) {
slope->y += slope->inc;
slope->error -= 2 * slope->dx;
slope->error -= 2 * slope->dt;
}
} else {
if (slope->error <= 0) {
slope->y += slope->inc;
slope->error += 2 * slope->dx;
slope->error += 2 * slope->dt;
}
}
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__
#define __ANIMATION_H__
#include <avr/io.h>
// 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
// 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.
typedef struct line_s {
uint8_t y;
int8_t m;
int8_t error;
int8_t inc;
uint8_t dx;
} line_t;
typedef struct {
int y;
int de;
int error;
int inc;
int dt;
int dy;
} time_line_t;
// 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.
uint8_t line_next(line_t *line);
int time_line_next(time_line_t *);
// Diagnostic printout of the current state of line_t.
// void line_print(line_t *line);

View File

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

View File

@ -1,21 +1,36 @@
#include <stdlib.h>
#include <base.h>
#include <rng.h>
typedef struct RGB_s {
uint8_t brightness;
uint8_t r;
uint8_t g;
uint8_t b;
} rgb_t;
#include <stdio.h>
#include <animation.h>
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++) {
animation_step(&animation, &rng);
printf("[%d] %d %d %d\n", animation.frame, animation.lamp.r, animation.lamp.g, animation.lamp.b);
printf("\n");
{
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" =
{ mcu, chip_select, f_cpu }:
# { gcc, mcu, chip_select, f_cpu }:
{ gcc }:
let
pkgs = import nixpkgs { system = "x86_64-linux"; };
avr = pkgs.pkgsCross.avr.buildPackages;
in pkgs.stdenv.mkDerivation rec {
name = "animation";
src = ./.;
CFLAGS = cflags { inherit mcu chip_select f_cpu; };
# CFLAGS = cflags { inherit mcu chip_select f_cpu; };
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 = ''
@ -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" =
{ mcu, chip_select, f_cpu }:
let