From: Michel Pollet Date: Sat, 19 May 2012 13:33:12 +0000 (+0100) Subject: reprap: Added opengl renderer X-Git-Tag: v1.0~125 X-Git-Url: https://git.htl-mechatronik.at/public/?a=commitdiff_plain;h=022f8dcc8d9744189519f563b2d585db3a640c14;p=sx%2Fsimavr.git reprap: Added opengl renderer The small red cross moves as the nozzle. Very primitive still Rotate with the mouse, sorta. Signed-off-by: Michel Pollet --- diff --git a/examples/board_reprap/Makefile b/examples/board_reprap/Makefile index 83b84ed..7a6ceb1 100644 --- a/examples/board_reprap/Makefile +++ b/examples/board_reprap/Makefile @@ -29,13 +29,28 @@ IPATH += ${simavr}/include IPATH += ${simavr}/simavr/sim VPATH = src +VPATH += src/c3 VPATH += ../parts VPATH += ../shared # for the Open Motion Controller board CFLAGS += -DMOTHERBOARD=91 +CFLAGS += ${shell pkg-config --cflags pangocairo} +ifneq (${shell uname}, Darwin) +LDFLAGS += -lGL -lglut -lGLU +else +LDFLAGS += -framework GLUT -framework OpenGL +endif +LDFLAGS += ${shell pkg-config --libs pangocairo} LDFLAGS += -lpthread -lutil -ldl +LDFLAGS += -lm + +C3SRC = ${wildcard src/c3/*.c} +C3OBJ = ${patsubst src/c3%,${OBJ}%,${C3SRC:.c=.o}} + +CFLAGS += ${patsubst %,-I%,${subst :, ,${IPATH}}} + all: obj ${firmware} ${target} @@ -43,16 +58,20 @@ include ${simavr}/Makefile.common board = ${OBJ}/${target}.elf +${board} : ${C3OBJ} ${board} : ${OBJ}/mongoose.o ${board} : ${OBJ}/button.o ${board} : ${OBJ}/uart_pty.o ${board} : ${OBJ}/thermistor.o ${board} : ${OBJ}/heatpot.o ${board} : ${OBJ}/stepper.o +${board} : ${OBJ}/c_utils.o ${board} : ${OBJ}/${target}.o +${board} : ${OBJ}/${target}_gl.o ${target}: ${board} @echo $@ done clean: clean-${OBJ} rm -rf *.a *.axf ${target} *.vcd + diff --git a/examples/board_reprap/src/reprap.c b/examples/board_reprap/src/reprap.c index d8f8ce0..19f6ad9 100644 --- a/examples/board_reprap/src/reprap.c +++ b/examples/board_reprap/src/reprap.c @@ -33,16 +33,13 @@ #include "sim_elf.h" #include "sim_hex.h" #include "sim_gdb.h" -#include "sim_vcd_file.h" #include "mongoose.h" +#include "reprap_gl.h" + #include "button.h" -#include "uart_pty.h" -#include "thermistor.h" -#include "thermistor.h" -#include "heatpot.h" -#include "stepper.h" +#include "reprap.h" #define __AVR_ATmega644__ #include "marlin/pins.h" @@ -60,17 +57,9 @@ enum { TALLY_HOTEND_FAN, }; -thermistor_t therm_hotend; -thermistor_t therm_hotbed; -thermistor_t therm_spare; -heatpot_t hotend; -heatpot_t hotbed; - -stepper_t step_x, step_y, step_z, step_e; +reprap_t reprap; -uart_pty_t uart_pty; avr_t * avr = NULL; -avr_vcd_t vcd_file; typedef struct ardupin_t { uint32_t port : 7, pin : 3, analog : 1, adc : 3, pwm : 1, ardupin; @@ -143,13 +132,18 @@ get_ardu_irq( * called when the AVR change any of the pins on port B * so lets update our buffer */ -void hotbed_change_hook(struct avr_irq_t * irq, uint32_t value, void * param) +void +hotbed_change_hook( + struct avr_irq_t * irq, + uint32_t value, + void * param) { printf("%s %d\n", __func__, value); // pin_state = (pin_state & ~(1 << irq->irq)) | (value << irq->irq); } + char avr_flash_path[1024]; int avr_flash_fd = 0; @@ -185,7 +179,7 @@ void avr_special_deinit( avr_t* avr) perror(avr_flash_path); } close(avr_flash_fd); - uart_pty_stop(&uart_pty); + uart_pty_stop(&reprap.uart_pty); } static void * @@ -215,9 +209,89 @@ reprap_relief_callback( void * param) { // printf("%s write %x\n", __func__, addr); - usleep(1000); + static uint16_t tick = 0; + if (!(tick++ & 0xf)) + usleep(100); } +static void * +avr_run_thread( + void * ignore) +{ + while (1) { + avr_run(avr); + } + return NULL; +} + +void +reprap_init( + avr_t * avr, + reprap_p r) +{ + r->avr = avr; + uart_pty_init(avr, &r->uart_pty); + uart_pty_connect(&r->uart_pty, '0'); + + thermistor_init(avr, &r->therm_hotend, 0, + (short*)TERMISTOR_TABLE(TEMP_SENSOR_0), + sizeof(TERMISTOR_TABLE(TEMP_SENSOR_0)) / sizeof(short) / 2, + OVERSAMPLENR, 25.0f); + thermistor_init(avr, &r->therm_hotbed, 2, + (short*)TERMISTOR_TABLE(TEMP_SENSOR_BED), + sizeof(TERMISTOR_TABLE(TEMP_SENSOR_BED)) / sizeof(short) / 2, + OVERSAMPLENR, 30.0f); + thermistor_init(avr, &r->therm_spare, 1, + (short*)temptable_5, sizeof(temptable_5) / sizeof(short) / 2, + OVERSAMPLENR, 10.0f); + + heatpot_init(avr, &r->hotend, "hotend", 28.0f); + heatpot_init(avr, &r->hotbed, "hotbed", 25.0f); + + /* connect heatpot temp output to thermistors */ + avr_connect_irq(r->hotend.irq + IRQ_HEATPOT_TEMP_OUT, + r->therm_hotend.irq + IRQ_TERM_TEMP_VALUE_IN); + avr_connect_irq(r->hotbed.irq + IRQ_HEATPOT_TEMP_OUT, + r->therm_hotbed.irq + IRQ_TERM_TEMP_VALUE_IN); + + float axis_pp_per_mm[4] = DEFAULT_AXIS_STEPS_PER_UNIT; // from Marlin! + { + avr_irq_t * e = get_ardu_irq(avr, X_ENABLE_PIN, arduidiot_644); + avr_irq_t * s = get_ardu_irq(avr, X_STEP_PIN, arduidiot_644); + avr_irq_t * d = get_ardu_irq(avr, X_DIR_PIN, arduidiot_644); + avr_irq_t * m = get_ardu_irq(avr, X_MIN_PIN, arduidiot_644); + + stepper_init(avr, &r->step_x, "X", axis_pp_per_mm[0], 100, 220, 0); + stepper_connect(&r->step_x, s, d, e, m, stepper_endstop_inverted); + } + { + avr_irq_t * e = get_ardu_irq(avr, Y_ENABLE_PIN, arduidiot_644); + avr_irq_t * s = get_ardu_irq(avr, Y_STEP_PIN, arduidiot_644); + avr_irq_t * d = get_ardu_irq(avr, Y_DIR_PIN, arduidiot_644); + avr_irq_t * m = get_ardu_irq(avr, Y_MIN_PIN, arduidiot_644); + + stepper_init(avr, &r->step_y, "Y", axis_pp_per_mm[1], 100, 220, 0); + stepper_connect(&r->step_y, s, d, e, m, stepper_endstop_inverted); + } + { + avr_irq_t * e = get_ardu_irq(avr, Z_ENABLE_PIN, arduidiot_644); + avr_irq_t * s = get_ardu_irq(avr, Z_STEP_PIN, arduidiot_644); + avr_irq_t * d = get_ardu_irq(avr, Z_DIR_PIN, arduidiot_644); + avr_irq_t * m = get_ardu_irq(avr, Z_MIN_PIN, arduidiot_644); + + stepper_init(avr, &r->step_z, "Z", axis_pp_per_mm[2], 20, 110, 0); + stepper_connect(&r->step_z, s, d, e, m, stepper_endstop_inverted); + } + { + avr_irq_t * e = get_ardu_irq(avr, E0_ENABLE_PIN, arduidiot_644); + avr_irq_t * s = get_ardu_irq(avr, E0_STEP_PIN, arduidiot_644); + avr_irq_t * d = get_ardu_irq(avr, E0_DIR_PIN, arduidiot_644); + + stepper_init(avr, &r->step_e, "E", axis_pp_per_mm[3], 0, 0, 0); + stepper_connect(&r->step_e, s, d, e, NULL, 0); + } + +} int main(int argc, char *argv[]) { @@ -279,74 +353,18 @@ int main(int argc, char *argv[]) // I changed Marlin to do a spurious write to the GPIOR0 register so we can trap it avr_register_io_write(avr, MEGA644_GPIOR0, reprap_relief_callback, NULL); - uart_pty_init(avr, &uart_pty); - uart_pty_connect(&uart_pty, '0'); - - thermistor_init(avr, &therm_hotend, 0, - (short*)TERMISTOR_TABLE(TEMP_SENSOR_0), - sizeof(TERMISTOR_TABLE(TEMP_SENSOR_0)) / sizeof(short) / 2, - OVERSAMPLENR, 25.0f); - thermistor_init(avr, &therm_hotbed, 2, - (short*)TERMISTOR_TABLE(TEMP_SENSOR_BED), - sizeof(TERMISTOR_TABLE(TEMP_SENSOR_BED)) / sizeof(short) / 2, - OVERSAMPLENR, 30.0f); - thermistor_init(avr, &therm_spare, 1, - (short*)temptable_5, sizeof(temptable_5) / sizeof(short) / 2, - OVERSAMPLENR, 10.0f); - - heatpot_init(avr, &hotend, "hotend", 28.0f); - heatpot_init(avr, &hotbed, "hotbed", 25.0f); - - /* connect heatpot temp output to thermistors */ - avr_connect_irq(hotend.irq + IRQ_HEATPOT_TEMP_OUT, therm_hotend.irq + IRQ_TERM_TEMP_VALUE_IN); - avr_connect_irq(hotbed.irq + IRQ_HEATPOT_TEMP_OUT, therm_hotbed.irq + IRQ_TERM_TEMP_VALUE_IN); - - float axis_pp_per_mm[4] = DEFAULT_AXIS_STEPS_PER_UNIT; // from Marlin! - { - avr_irq_t * e = get_ardu_irq(avr, X_ENABLE_PIN, arduidiot_644); - avr_irq_t * s = get_ardu_irq(avr, X_STEP_PIN, arduidiot_644); - avr_irq_t * d = get_ardu_irq(avr, X_DIR_PIN, arduidiot_644); - avr_irq_t * m = get_ardu_irq(avr, X_MIN_PIN, arduidiot_644); - - stepper_init(avr, &step_x, "X", axis_pp_per_mm[0], 100, 220, 0); - stepper_connect(&step_x, s, d, e, m, stepper_endstop_inverted); - } - { - avr_irq_t * e = get_ardu_irq(avr, Y_ENABLE_PIN, arduidiot_644); - avr_irq_t * s = get_ardu_irq(avr, Y_STEP_PIN, arduidiot_644); - avr_irq_t * d = get_ardu_irq(avr, Y_DIR_PIN, arduidiot_644); - avr_irq_t * m = get_ardu_irq(avr, Y_MIN_PIN, arduidiot_644); - - stepper_init(avr, &step_y, "Y", axis_pp_per_mm[1], 100, 220, 0); - stepper_connect(&step_y, s, d, e, m, stepper_endstop_inverted); - } - { - avr_irq_t * e = get_ardu_irq(avr, Z_ENABLE_PIN, arduidiot_644); - avr_irq_t * s = get_ardu_irq(avr, Z_STEP_PIN, arduidiot_644); - avr_irq_t * d = get_ardu_irq(avr, Z_DIR_PIN, arduidiot_644); - avr_irq_t * m = get_ardu_irq(avr, Z_MIN_PIN, arduidiot_644); - - stepper_init(avr, &step_z, "Z", axis_pp_per_mm[2], 20, 110, 0); - stepper_connect(&step_z, s, d, e, m, stepper_endstop_inverted); - } - { - avr_irq_t * e = get_ardu_irq(avr, E0_ENABLE_PIN, arduidiot_644); - avr_irq_t * s = get_ardu_irq(avr, E0_STEP_PIN, arduidiot_644); - avr_irq_t * d = get_ardu_irq(avr, E0_DIR_PIN, arduidiot_644); - - stepper_init(avr, &step_e, "E", axis_pp_per_mm[3], 0, 0, 0); - stepper_connect(&step_e, s, d, e, NULL, 0); - } + reprap_init(avr, &reprap); const char *options[] = {"listening_ports", "9090", NULL}; struct mg_context *ctx = mg_start(&mongoose_callback, NULL, options); printf("mongoose %p\n", ctx); - while (1) { - int state = avr_run(avr); - if ( state == cpu_Done || state == cpu_Crashed) - break; - } + gl_init(argc, argv); + pthread_t run; + pthread_create(&run, NULL, avr_run_thread, NULL); + + gl_runloop(); + mg_stop(ctx); } diff --git a/examples/board_reprap/src/reprap.h b/examples/board_reprap/src/reprap.h new file mode 100644 index 0000000..567c493 --- /dev/null +++ b/examples/board_reprap/src/reprap.h @@ -0,0 +1,47 @@ +/* + reprap.h + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + + +#ifndef __REPRAP_H___ +#define __REPRAP_H___ + +#include "sim_avr.h" +#include "thermistor.h" +#include "heatpot.h" +#include "stepper.h" +#include "uart_pty.h" +#include "sim_vcd_file.h" + +typedef struct reprap_t { + struct avr_t * avr; + thermistor_t therm_hotend; + thermistor_t therm_hotbed; + thermistor_t therm_spare; + heatpot_t hotend; + heatpot_t hotbed; + + stepper_t step_x, step_y, step_z, step_e; + + uart_pty_t uart_pty; + avr_vcd_t vcd_file; +} reprap_t, *reprap_p; + +#endif /* __REPRAP_H___ */ diff --git a/examples/board_reprap/src/reprap_gl.c b/examples/board_reprap/src/reprap_gl.c new file mode 100644 index 0000000..e2afe54 --- /dev/null +++ b/examples/board_reprap/src/reprap_gl.c @@ -0,0 +1,276 @@ +/* + reprap_gl.c + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + +#if __APPLE__ +#include +#else +#include +#endif + +#include + +#include "reprap.h" +#include "reprap_gl.h" + +#include "c3/c3.h" +#include "c3/c3camera.h" +#include "c3/c3arcball.h" + +int _w = 800, _h = 600; +c3cam cam; +c3arcball arcball; +c3object_p root; +c3object_p head; +c3geometry_array_t geo_sorted = C_ARRAY_NULL; + +extern reprap_t reprap; + +static void +_gl_key_cb( + unsigned char key, + int x, + int y) /* called on key press */ +{ + switch (key) { + case 'q': + // avr_vcd_stop(&vcd_file); + exit(0); + break; + case 'r': + printf("Starting VCD trace; press 's' to stop\n"); + // avr_vcd_start(&vcd_file); + break; + case 's': + printf("Stopping VCD trace\n"); + // avr_vcd_stop(&vcd_file); + break; + } +} + + +static void +_gl_display_cb(void) /* function called whenever redisplay needed */ +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // Set up projection matrix + glMatrixMode(GL_PROJECTION); // Select projection matrix + glLoadIdentity(); // Start with an identity matrix + + gluPerspective(45, _w / _h, 0, 10000); + +// glEnable(GL_TEXTURE_2D); + glShadeModel(GL_SMOOTH); + + glClearColor(0.8f, 0.8f, 0.8f, 1.0f); + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); // Enable Blending + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Type Of Blending To Use + + glMatrixMode( GL_MODELVIEW ); + glLoadIdentity(); + // glMultMatrixf(arcball.rot.n); + glMultMatrixf(cam.mtx.n); + glTranslatef( -cam.eye.n[VX], -cam.eye.n[VY], -cam.eye.n[VZ] ); + // glMultMatrixf(arcball.rot.n); + + c3vec3 headp = c3vec3f( + stepper_get_position_mm(&reprap.step_x), + stepper_get_position_mm(&reprap.step_y), + stepper_get_position_mm(&reprap.step_z)); + c3mat4 headmove = translation3D(headp); + c3transform_set(head->transform.e[0], &headmove); + + if (root->dirty) { + printf("reproject\n"); + c3mat4 m = identity3D(); + c3object_project(root, &m); + c3geometry_array_clear(&geo_sorted); + c3object_get_geometry(root, &geo_sorted); + } + + for (int gi = 0; gi < geo_sorted.count; gi++) { + c3geometry_p g = geo_sorted.e[gi]; + glColor4fv(g->mat.color.n); + glVertexPointer(3, GL_FLOAT, 0, g->projected.count ? g->projected.e : g->vertice.e); + glEnableClientState(GL_VERTEX_ARRAY); + + glDrawArrays(g->type, 0, g->vertice.count); + + glDisableClientState(GL_VERTEX_ARRAY); + + } + + glMatrixMode(GL_PROJECTION); // Select projection matrix + glLoadIdentity(); // Start with an identity matrix + glOrtho(0, _w, 0, _h, 0, 10); + glScalef(1,-1,1); + glTranslatef(0, -1 * _h, 0); + + glMatrixMode(GL_MODELVIEW); // Select modelview matrix + + #if 0 + glPushMatrix(); + glLoadIdentity(); // Start with an identity matrix + glScalef(3, 3, 1); + hd44780_gl_draw( + &hd44780, + colors[color][0], /* background */ + colors[color][1], /* character background */ + colors[color][2], /* text */ + colors[color][3] /* shadow */ ); + glPopMatrix(); +#endif + glutSwapBuffers(); +} + +int button; +c3vec2 move; +c3cam startcam; + +static +void _gl_button_cb( + int b, + int s, + int x, + int y) +{ + button = s == GLUT_DOWN ? b : 0; + startcam = cam; + move = c3vec2f(x, y); + if (s == GLUT_DOWN) + c3arcball_mouse_down(&arcball, x, y); + else + c3arcball_mouse_up(&arcball); +} + +void +_gl_motion_cb( + int x, + int y) +{ + c3vec2 m = c3vec2f(x, y); + c3vec2 delta = c3vec2_sub(move, m); + +// printf("%s b%d click %.1f,%.1f now %d,%d\n", +// __func__, button, move.n[0], move.n[1], x, y); + + switch (button) { + case GLUT_LEFT_BUTTON: { + + // c3cam_eye_yaw(&cam, delta.n[0] / 4); + // c3cam_eye_pitch(&cam, delta.n[1] / 4); + + c3mat4 rotx = rotation3D(c3vec3f(1.0, 0, 0), delta.n[1] / 4); + c3mat4 roty = rotation3D(c3vec3f(0.0, 0.0, 1.0), delta.n[0] / 4); + rotx = c3mat4_mul(&rotx, &roty); + c3cam_rot_about_lookat(&cam, &rotx); + + c3cam_update_matrix(&cam); +// c3arcball_mouse_motion(&arcball, x, y, 0,0,0); + } break; + case GLUT_RIGHT_BUTTON: { + + } break; + } + move = m; +} + +// gl timer. if the lcd is dirty, refresh display +static void +_gl_timer_cb( + int i) +{ + //static int oldstate = -1; + // restart timer + c3arcball_idle(&arcball); + glutTimerFunc(1000 / 24, _gl_timer_cb, 0); + glutPostRedisplay(); +} + +int +gl_init( + int argc, + char *argv[] ) +{ + glutInit(&argc, argv); /* initialize GLUT system */ + + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); + glutInitWindowSize(_w, _h); /* width=400pixels height=500pixels */ + /*window =*/ glutCreateWindow("Press 'q' to quit"); /* create window */ + + glutDisplayFunc(_gl_display_cb); /* set window's display callback */ + glutKeyboardFunc(_gl_key_cb); /* set window's key callback */ + glutTimerFunc(1000 / 24, _gl_timer_cb, 0); + + glutMouseFunc(_gl_button_cb); + glutMotionFunc(_gl_motion_cb); + + glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + glEnable(GL_LINE_SMOOTH); + cam = c3cam_new(); + cam.lookat = c3vec3f(100.0, 100.0, 0.0); + cam.eye = c3vec3f(100.0, -100.0, 100.0); + c3cam_update_matrix(&cam); + + c3arcball_init_center(&arcball, c3vec2f(_w/2, _h/2), 100); +// hd44780_gl_init(); + + root = c3object_new(NULL); + + c3object_p grid = c3object_new(root); + { + c3geometry_p g = c3geometry_new(GL_LINES, grid); + g->mat.color = c3vec4f(1.0, 1.0, 1.0, 1.0); + for (int x = 0; x < 20; x++) { + for (int y = 0; y < 20; y++) { + c3vec3 p[4] = { + c3vec3f(-1+x*10,y*10,0), c3vec3f(1+x*10,y*10,0), + c3vec3f(x*10,-1+y*10,0), c3vec3f(x*10,1+y*10,0), + }; + c3vertex_array_insert(&g->vertice, + g->vertice.count, p, 4); + } + } + } + head = c3object_new(root); + c3transform_new(head); + { + c3geometry_p g = c3geometry_new(GL_LINES, head); + g->mat.color = c3vec4f(1.0, 0.0, 0.0, 1.0); + c3vec3 p[4] = { + c3vec3f(-1, 0, 0), c3vec3f(1, 0, 0), + c3vec3f(0, -1, 0), c3vec3f(0, 1, 0), + }; + c3vertex_array_insert(&g->vertice, + g->vertice.count, p, 4); + } + return 1; +} + +int +gl_runloop() +{ + glutMainLoop(); + return 0; +} diff --git a/examples/board_reprap/src/reprap_gl.h b/examples/board_reprap/src/reprap_gl.h new file mode 100644 index 0000000..c0e85e8 --- /dev/null +++ b/examples/board_reprap/src/reprap_gl.h @@ -0,0 +1,34 @@ +/* + reprap_gl.h + + Copyright 2008-2012 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + + +#ifndef __REPRAP_GL_H___ +#define __REPRAP_GL_H___ + +int +gl_init( + int argc, + char *argv[] ); + +int +gl_runloop(); + +#endif /* __REPRAP_GL_H___ */ diff --git a/examples/board_reprap/src/stepper.c b/examples/board_reprap/src/stepper.c index d047288..23f6e7d 100644 --- a/examples/board_reprap/src/stepper.c +++ b/examples/board_reprap/src/stepper.c @@ -79,7 +79,7 @@ stepper_step_hook( return; if (value) return; - p->position += p->dir ? -1 : 1; + p->position += p->dir ? 1 : -1; if (p->position < 0) p->position = 0; if (p->endstop && p->position < p->endstop) @@ -141,3 +141,11 @@ stepper_connect( p->timer_period = avr_usec_to_cycles(p->avr, 100000 / 1000); // 1ms avr_cycle_timer_register(p->avr, p->timer_period, stepper_update_timer, p); } + +float +stepper_get_position_mm( + stepper_p p) +{ + return p->position / p->steps_per_mm; +} + diff --git a/examples/board_reprap/src/stepper.h b/examples/board_reprap/src/stepper.h index d8f8867..9f450ac 100644 --- a/examples/board_reprap/src/stepper.h +++ b/examples/board_reprap/src/stepper.h @@ -68,4 +68,8 @@ stepper_connect( avr_irq_t * endstop, uint16_t flags); +float +stepper_get_position_mm( + stepper_p p); + #endif /* __STEPPER_H___ */