time to save again, looking good so far
This commit is contained in:
parent
1e6c74096e
commit
90ea2910aa
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
PROGRAM = mendel
|
||||
|
||||
SOURCES = $(PROGRAM).c ringbuffer.c serial.c dda.c gcode.c pinout.c
|
||||
SOURCES = $(PROGRAM).c ringbuffer.c serial.c dda.c gcode.c timer.c
|
||||
|
||||
##############################################################################
|
||||
# #
|
||||
|
|
@ -46,10 +46,10 @@ PROGBAUD = 19200
|
|||
|
||||
OBJ = $(patsubst %.c,%.o,${SOURCES})
|
||||
|
||||
.PHONY: all program clean
|
||||
.PHONY: all program clean size
|
||||
.PRECIOUS: %.o %.elf
|
||||
|
||||
all: $(PROGRAM).hex $(PROGRAM).lst
|
||||
all: $(PROGRAM).hex $(PROGRAM).lst size
|
||||
|
||||
program: $(PROGRAM).hex
|
||||
stty $(PROGBAUD) raw ignbrk hup < $(PROGPORT)
|
||||
|
|
@ -60,6 +60,9 @@ program: $(PROGRAM).hex
|
|||
clean:
|
||||
rm -rf *.o *.elf *.lst *.map *.sym *.lss *.eep *.srec *.bin *.hex *.al *.i *.s *~
|
||||
|
||||
size: $(PROGRAM).hex
|
||||
@objdump -h mendel.elf | perl -ne '/.(data|text)\s+([0-9a-f]+)/ && do { $$a += eval "0x$$2" }; END { printf "%d bytes (%d%% of %dkb)\n", $$a, $$a * 100 / 16384, 16 }'
|
||||
|
||||
%.o: %.c
|
||||
$(CC) -c $(CFLAGS) -Wa,-adhlns=$(<:.c=.al) -o $@ $^
|
||||
|
||||
|
|
|
|||
189
mendel/dda.c
189
mendel/dda.c
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include <string.h>
|
||||
|
||||
#include "timer.h"
|
||||
|
||||
extern struct {
|
||||
volatile int32_t X;
|
||||
volatile int32_t Y;
|
||||
|
|
@ -10,10 +12,53 @@ extern struct {
|
|||
volatile int32_t F;
|
||||
} current_position;
|
||||
|
||||
// courtesy of http://www.flipcode.com/archives/Fast_Approximate_Distance_Functions.shtml
|
||||
uint8_t mb_head = 0;
|
||||
uint8_t mb_tail = 0;
|
||||
DDA movebuffer[MOVEBUFFER_SIZE];
|
||||
|
||||
uint8_t queue_full() {
|
||||
if (mb_tail == 0)
|
||||
return mb_head == (MOVEBUFFER_SIZE - 1);
|
||||
else
|
||||
return mb_head == (mb_tail - 1);
|
||||
}
|
||||
|
||||
inline uint8_t queue_empty() {
|
||||
return (mb_tail == mb_head) && !movebuffer[tail].live;
|
||||
}
|
||||
|
||||
void enqueue(TARGET *t) {
|
||||
while (queue_full())
|
||||
delay(WAITING_DELAY);
|
||||
|
||||
uint8_t h = mb_head;
|
||||
h++;
|
||||
if (h == MOVEBUFFER_SIZE)
|
||||
h = 0;
|
||||
mb_head = h;
|
||||
dda_create(t, &movebuffer[h]);
|
||||
}
|
||||
|
||||
void next_move() {
|
||||
if ((mb_tail == mb_head) && (!movebuffer[mb_tail].live)) {
|
||||
// queue is empty
|
||||
disable_steppers();
|
||||
setTimer(DEFAULT_TICK);
|
||||
}
|
||||
else {
|
||||
uint8_t t = mb_tail;
|
||||
t++;
|
||||
if (t == MOVEBUFFER_SIZE)
|
||||
t = 0;
|
||||
mb_tail = t;
|
||||
dda_start(&movebuffer[t]);
|
||||
}
|
||||
}
|
||||
|
||||
// courtesy of http://www.oroboro.com/rafael/docserv.php/index/programming/article/distance
|
||||
uint32_t approx_distance( int32_t dx, int32_t dy )
|
||||
{
|
||||
uint32_t min, max;
|
||||
uint32_t min, max, approx;
|
||||
|
||||
if ( dx < 0 ) dx = -dx;
|
||||
if ( dy < 0 ) dy = -dy;
|
||||
|
|
@ -27,32 +72,80 @@ uint32_t approx_distance( int32_t dx, int32_t dy )
|
|||
max = dx;
|
||||
}
|
||||
|
||||
// coefficients equivalent to ( 123/128 * max ) and ( 51/128 * min )
|
||||
return ((( max << 8 ) + ( max << 3 ) - ( max << 4 ) - ( max << 1 ) +
|
||||
( min << 7 ) - ( min << 5 ) + ( min << 3 ) - ( min << 1 )) >> 8 );
|
||||
approx = ( max * 1007 ) + ( min * 441 );
|
||||
if ( max < ( min << 4 ))
|
||||
approx -= ( max * 40 );
|
||||
|
||||
// add 512 for proper rounding
|
||||
return (( approx + 512 ) >> 10 );
|
||||
}
|
||||
|
||||
// courtesy of http://www.oroboro.com/rafael/docserv.php/index/programming/article/distance
|
||||
uint32_t approx_distance_3( int32_t dx, int32_t dy, int32_t dz )
|
||||
{
|
||||
uint32_t min, med, max, approx;
|
||||
|
||||
if ( dx < 0 ) dx = -dx;
|
||||
if ( dy < 0 ) dy = -dy;
|
||||
if ( dz < 0 ) dz = -dz;
|
||||
|
||||
if ( dx < dy )
|
||||
{
|
||||
min = dy;
|
||||
med = dx;
|
||||
} else {
|
||||
min = dx;
|
||||
med = dy;
|
||||
}
|
||||
|
||||
if ( dz < (int32_t)min )
|
||||
{
|
||||
max = med;
|
||||
med = min;
|
||||
min = dz;
|
||||
} else if ( dz < (int32_t)med ) {
|
||||
max = med;
|
||||
med = dz;
|
||||
} else {
|
||||
max = dz;
|
||||
}
|
||||
|
||||
approx = ( max * 860 ) + ( med * 851 ) + ( min * 520 );
|
||||
if ( max < ( med << 1 )) approx -= ( max * 294 );
|
||||
if ( max < ( min << 2 )) approx -= ( max * 113 );
|
||||
if ( med < ( min << 2 )) approx -= ( med * 40 );
|
||||
|
||||
// add 512 for proper rounding
|
||||
return (( approx + 512 ) >> 10 );
|
||||
}
|
||||
|
||||
/*
|
||||
CREATE
|
||||
*/
|
||||
|
||||
void dda_create(GCODE_COMMAND *cmd, DDA *dda) {
|
||||
void dda_create(TARGET *target, DDA *dda) {
|
||||
static TARGET startpoint = { 0, 0, 0, 0, 0 };
|
||||
|
||||
// we start at the previous endpoint
|
||||
memcpy(&dda->currentpoint, &startpoint, sizeof(TARGET));
|
||||
// we end at the passed command's endpoint
|
||||
memcpy(&dda->endpoint, &cmd->target, sizeof(TARGET));
|
||||
memcpy(&dda->endpoint, target, sizeof(TARGET));
|
||||
|
||||
dda->x_delta = dda->endpoint.X - startpoint.X;
|
||||
dda->y_delta = dda->endpoint.Y - startpoint.Y;
|
||||
dda->z_delta = dda->endpoint.Z - startpoint.Z;
|
||||
// always relative
|
||||
dda->e_delta = dda->endpoint.E;
|
||||
// always absolute
|
||||
dda->f_delta = dda->endpoint.F - startpoint.F;
|
||||
|
||||
|
||||
dda->distance = approx_distance(dda->x_delta, dda->y_delta);
|
||||
// since it's unusual to combine X, Y and Z changes in a single move on reprap, check if we can use simpler approximations before trying the full 3d approximation.
|
||||
if (dda->z_delta == 0)
|
||||
dda->distance = approx_distance(dda->x_delta, dda->y_delta);
|
||||
else if (dda->x_delta == 0 && dda->y_delta == 0)
|
||||
dda->distance = dda->z_delta;
|
||||
else
|
||||
dda->distance = approx_distance_3(dda->x_delta, dda->y_delta, dda->z_delta);
|
||||
|
||||
if (dda->distance < 2)
|
||||
dda->distance = dda->e_delta;
|
||||
|
|
@ -62,6 +155,9 @@ void dda_create(GCODE_COMMAND *cmd, DDA *dda) {
|
|||
dda->total_steps = dda->x_delta;
|
||||
if (dda->y_delta > dda->total_steps)
|
||||
dda->total_steps = dda->y_delta;
|
||||
if (dda->z_delta > dda->total_steps)
|
||||
dda->total_steps = dda->z_delta;
|
||||
|
||||
if (dda->e_delta > dda->total_steps)
|
||||
dda->total_steps = dda->e_delta;
|
||||
if (dda->f_delta > dda->total_steps)
|
||||
|
|
@ -79,7 +175,6 @@ void dda_create(GCODE_COMMAND *cmd, DDA *dda) {
|
|||
// dda->endpoint.F = distance / total_steps;
|
||||
|
||||
if (dda->f_delta > dda->total_steps) {
|
||||
// TODO: rescale F
|
||||
dda->f_scale = dda->f_delta / dda->total_steps;
|
||||
if (dda->f_scale > 3) {
|
||||
dda->f_delta /= dda->f_scale;
|
||||
|
|
@ -92,14 +187,22 @@ void dda_create(GCODE_COMMAND *cmd, DDA *dda) {
|
|||
|
||||
dda->x_direction = (dda->endpoint.X > startpoint.X)?1:0;
|
||||
dda->y_direction = (dda->endpoint.Y > startpoint.Y)?1:0;
|
||||
dda->z_direction = (dda->endpoint.Z > startpoint.Z)?1:0;
|
||||
dda->e_direction = (dda->endpoint.E > startpoint.E)?1:0;
|
||||
dda->f_direction = (dda->endpoint.F > startpoint.F)?1:0;
|
||||
|
||||
dda->x_counter = dda->y_counter = dda->e_counter = dda->f_counter
|
||||
dda->x_counter = dda->y_counter = dda->z_counter = dda->e_counter = dda->f_counter
|
||||
= -(dda->total_steps >> 1);
|
||||
|
||||
// pre-calculate move speed in millimeter microseconds per step minute for less math in interrupt context
|
||||
// mm (distance) * 60000000 us/min / step (total_steps) = mm.us per step.min
|
||||
// mm.us per step.min / mm/min (F) = us per step
|
||||
dda->move_duration = dda->distance * 60000000 / dda->total_steps;
|
||||
|
||||
// next dda starts where we finish
|
||||
memcpy(&startpoint, &dda->endpoint, sizeof(TARGET));
|
||||
|
||||
dda->live = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -107,10 +210,17 @@ void dda_create(GCODE_COMMAND *cmd, DDA *dda) {
|
|||
*/
|
||||
|
||||
void dda_start(DDA *dda) {
|
||||
// called from interrupt context: keep it simple!
|
||||
if (dda->nullmove)
|
||||
return;
|
||||
|
||||
x_direction(dda->x_direction);
|
||||
y_direction(dda->y_direction);
|
||||
z_direction(dda->z_direction);
|
||||
e_direction(dda->e_direction);
|
||||
|
||||
enable_steppers();
|
||||
dda->live = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -147,16 +257,17 @@ void dda_step(DDA *dda) {
|
|||
step_option |= can_step(x_min(), x_max(), current_position.X, dda->endpoint.X, dda->x_direction) & X_CAN_STEP;
|
||||
step_option |= can_step(y_min(), y_max(), current_position.Y, dda->endpoint.Y, dda->y_direction) & Y_CAN_STEP;
|
||||
step_option |= can_step(z_min(), z_max(), current_position.Z, dda->endpoint.Z, dda->z_direction) & Z_CAN_STEP;
|
||||
step_option |= can_step(-1, -1, current_position.E, dda->endpoint.E, dda->e_direction) & E_CAN_STEP;
|
||||
step_option |= can_step(-1, -1, current_position.F, dda->endpoint.F, dda->f_direction) & F_CAN_STEP;
|
||||
step_option |= can_step(-1 , -1 , current_position.E, dda->endpoint.E, dda->e_direction) & E_CAN_STEP;
|
||||
step_option |= can_step(-1 , -1 , current_position.F, dda->endpoint.F, dda->f_direction) & F_CAN_STEP;
|
||||
|
||||
if (step_option & X_CAN_STEP) {
|
||||
dda->x_counter += dda->x_delta;
|
||||
if (dda->x_counter > 0) {
|
||||
dda->x_counter -= dda->x_delta;
|
||||
if (dda->x_counter < 0) {
|
||||
step_option |= REAL_MOVE;
|
||||
|
||||
// do X step
|
||||
dda->x_counter -= dda->total_steps;
|
||||
x_step();
|
||||
|
||||
dda->x_counter += dda->total_steps;
|
||||
|
||||
if (dda->x_direction)
|
||||
current_position.X++;
|
||||
|
|
@ -166,12 +277,13 @@ void dda_step(DDA *dda) {
|
|||
}
|
||||
|
||||
if (step_option & Y_CAN_STEP) {
|
||||
dda->y_counter += dda->y_delta;
|
||||
if (dda->y_counter > 0) {
|
||||
dda->y_counter -= dda->y_delta;
|
||||
if (dda->y_counter < 0) {
|
||||
step_option |= REAL_MOVE;
|
||||
|
||||
// do Y step
|
||||
dda->y_counter -= dda->total_steps;
|
||||
y_step();
|
||||
|
||||
dda->y_counter += dda->total_steps;
|
||||
|
||||
if (dda->y_direction)
|
||||
current_position.Y++;
|
||||
|
|
@ -181,12 +293,13 @@ void dda_step(DDA *dda) {
|
|||
}
|
||||
|
||||
if (step_option & Z_CAN_STEP) {
|
||||
dda->z_counter += dda->z_delta;
|
||||
if (dda->z_counter > 0) {
|
||||
dda->z_counter -= dda->z_delta;
|
||||
if (dda->z_counter < 0) {
|
||||
step_option |= REAL_MOVE;
|
||||
|
||||
// do Z step
|
||||
dda->z_counter -= dda->total_steps;
|
||||
z_step();
|
||||
|
||||
dda->z_counter += dda->total_steps;
|
||||
|
||||
if (dda->z_direction)
|
||||
current_position.Z++;
|
||||
|
|
@ -196,12 +309,13 @@ void dda_step(DDA *dda) {
|
|||
}
|
||||
|
||||
if (step_option & E_CAN_STEP) {
|
||||
dda->e_counter += dda->e_delta;
|
||||
if (dda->e_counter > 0) {
|
||||
dda->e_counter -= dda->e_delta;
|
||||
if (dda->e_counter < 0) {
|
||||
step_option |= REAL_MOVE;
|
||||
|
||||
// do E step
|
||||
dda->e_counter -= dda->total_steps;
|
||||
e_step();
|
||||
|
||||
dda->e_counter += dda->total_steps;
|
||||
|
||||
if (dda->e_direction)
|
||||
current_position.E++;
|
||||
|
|
@ -211,10 +325,10 @@ void dda_step(DDA *dda) {
|
|||
}
|
||||
|
||||
if (step_option & F_CAN_STEP) {
|
||||
dda->f_counter += dda->f_delta;
|
||||
if (dda->f_counter > 0) {
|
||||
// do F step
|
||||
dda->f_counter -= dda->total_steps;
|
||||
dda->f_counter -= dda->f_delta;
|
||||
if (dda->f_counter < 0) {
|
||||
|
||||
dda->f_counter += dda->total_steps;
|
||||
|
||||
if (dda->f_direction)
|
||||
current_position.F += dda->f_scale;
|
||||
|
|
@ -222,9 +336,14 @@ void dda_step(DDA *dda) {
|
|||
current_position.F -= dda->f_scale;
|
||||
}
|
||||
}
|
||||
} while (((step_option & REAL_MOVE) == 0) && (step_option & F_CAN_STEP));
|
||||
} while ( ((step_option & REAL_MOVE ) == 0) &&
|
||||
((step_option & F_CAN_STEP) != 0) );
|
||||
|
||||
unstep();
|
||||
|
||||
if (step_option & REAL_MOVE) {
|
||||
setTimer(dda->distance * (60000000 / current_position.F / dda->total_steps));
|
||||
setTimer(dda->move_duration / current_position.F);
|
||||
}
|
||||
|
||||
dda->live = (step_option & (X_CAN_STEP | Y_CAN_STEP | Z_CAN_STEP | E_CAN_STEP | F_CAN_STEP));
|
||||
}
|
||||
|
|
|
|||
19
mendel/dda.h
19
mendel/dda.h
|
|
@ -6,25 +6,25 @@
|
|||
#include "target.h"
|
||||
#include "pinout.h"
|
||||
#include "gcode.h"
|
||||
#include "machine.h"
|
||||
|
||||
typedef struct {
|
||||
TARGET currentpoint;
|
||||
TARGET endpoint;
|
||||
|
||||
uint8_t steep :1;
|
||||
uint8_t swap :1;
|
||||
uint8_t x_direction :1;
|
||||
uint8_t y_direction :1;
|
||||
uint8_t z_direction :1;
|
||||
uint8_t e_direction :1;
|
||||
uint8_t f_direction :1;
|
||||
uint8_t nullmove :1;
|
||||
uint8_t live :1;
|
||||
|
||||
int8_t x_delta;
|
||||
int8_t y_delta;
|
||||
int8_t z_delta;
|
||||
int8_t e_delta;
|
||||
int8_t f_delta;
|
||||
int16_t x_delta;
|
||||
int16_t y_delta;
|
||||
int16_t z_delta;
|
||||
int16_t e_delta;
|
||||
int16_t f_delta;
|
||||
|
||||
int32_t x_counter;
|
||||
int32_t y_counter;
|
||||
|
|
@ -36,8 +36,13 @@ typedef struct {
|
|||
|
||||
uint16_t f_scale;
|
||||
uint32_t distance;
|
||||
uint32_t move_duration;
|
||||
} DDA;
|
||||
|
||||
extern uint8_t mb_head;
|
||||
extern uint8_t mb_tail;
|
||||
extern DDA movebuffer[MOVEBUFFER_SIZE];
|
||||
|
||||
uint32_t approx_distance( int32_t dx, int32_t dy );
|
||||
|
||||
void dda_create(GCODE_COMMAND *cmd, DDA *dda);
|
||||
|
|
|
|||
|
|
@ -5,9 +5,6 @@
|
|||
#include "machine.h"
|
||||
#include "dda.h"
|
||||
|
||||
extern uint8_t mb_head;
|
||||
extern uint8_t mb_tail;
|
||||
extern DDA movebuffer[16];
|
||||
extern uint8_t option_bitfield;
|
||||
|
||||
#define PI 3.1415926535
|
||||
|
|
@ -135,7 +132,7 @@ void scan_char(uint8_t c) {
|
|||
else if ((c == '.') && ((exp & 0x7F) == 0))
|
||||
exp |= 1;
|
||||
else if (c >= '0' && c <= '9') {
|
||||
mantissa = (mantissa * 10) + (c - '0');
|
||||
mantissa = ((mantissa << 3) + (mantissa << 1)) + (c - '0');
|
||||
if (exp & 0x7F)
|
||||
exp++;
|
||||
}
|
||||
|
|
@ -189,6 +186,6 @@ void process_gcode_command(GCODE_COMMAND *gcmd) {
|
|||
}
|
||||
|
||||
if (do_move) {
|
||||
dda_create(gcmd, movebuffer);
|
||||
dda_create(&gcmd->target, movebuffer);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,9 +4,7 @@
|
|||
/*
|
||||
machine variables
|
||||
*/
|
||||
#define AXIS_COUNT 5
|
||||
#define AXIS_HOMING_COUNT 3
|
||||
|
||||
#define MOVEBUFFER_SIZE 8
|
||||
/*
|
||||
axis calculations, adjust as necessary
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -9,13 +9,10 @@
|
|||
|
||||
#include "dda.h"
|
||||
#include "gcode.h"
|
||||
#include "timer.h"
|
||||
|
||||
#include "machine.h"
|
||||
|
||||
uint8_t mb_head = 0;
|
||||
uint8_t mb_tail = 0;
|
||||
DDA movebuffer[16];
|
||||
|
||||
uint8_t option_bitfield;
|
||||
|
||||
struct {
|
||||
|
|
@ -31,6 +28,9 @@ int main (void)
|
|||
// set up serial
|
||||
serial_init();
|
||||
|
||||
// set up timers
|
||||
setupTimerInterrupt();
|
||||
|
||||
// enable interrupts
|
||||
sei();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,48 +0,0 @@
|
|||
#include "pinout.h"
|
||||
|
||||
void delayMicrosecondsInterruptible(uint16_t us)
|
||||
{
|
||||
// for a one-microsecond delay, simply return. the overhead
|
||||
// of the function call yields a delay of approximately 1 1/8 us.
|
||||
if (--us == 0)
|
||||
return;
|
||||
|
||||
// the following loop takes a quarter of a microsecond (4 cycles)
|
||||
// per iteration, so execute it four times for each microsecond of
|
||||
// delay requested.
|
||||
us <<= 2;
|
||||
|
||||
// account for the time taken in the preceeding commands.
|
||||
us -= 2;
|
||||
|
||||
// busy wait
|
||||
__asm__ __volatile__ ("1: sbiw %0,1" "\n\t" // 2 cycles
|
||||
"brne 1b" :
|
||||
"=w" (us) :
|
||||
"0" (us) // 2 cycles
|
||||
);
|
||||
}
|
||||
|
||||
void x_step() {
|
||||
WRITE(DIO0, 1);
|
||||
delayMicrosecondsInterruptible(5);
|
||||
WRITE(DIO0, 0);
|
||||
}
|
||||
|
||||
void y_step() {
|
||||
WRITE(DIO4, 1);
|
||||
delayMicrosecondsInterruptible(5);
|
||||
WRITE(DIO4, 0);
|
||||
}
|
||||
|
||||
void z_step() {
|
||||
WRITE(DIO8, 1);
|
||||
delayMicrosecondsInterruptible(5);
|
||||
WRITE(DIO8, 0);
|
||||
}
|
||||
|
||||
void e_step() {
|
||||
WRITE(DIO12, 1);
|
||||
delayMicrosecondsInterruptible(5);
|
||||
WRITE(DIO12, 0);
|
||||
}
|
||||
|
|
@ -7,74 +7,59 @@
|
|||
#define MASK(PIN) (1 << PIN)
|
||||
#endif
|
||||
|
||||
#define _PIN(P) #P
|
||||
|
||||
#define READ(IO) (RPORT_ ## IO & MASK(PIN_ ## IO))
|
||||
#define WRITE(IO, v) if (v) { WPORT_ ## IO |= MASK(PIN_ ## IO); } else { WPORT_ ## IO &= ~MASK(PIN_ ## IO); }
|
||||
|
||||
#define SET_INPUT(IO) (DDR_ ## IO |= MASK(PIN_ ## IO))
|
||||
#define SET_OUTPUT(IO) (DDR_ ## IO &= ~MASK(PIN ## IO))
|
||||
|
||||
// #define X_STEP_PIN DIO0
|
||||
// #define X_DIR_PIN DIO1
|
||||
// #define X_MIN_MIN DIO2
|
||||
// #define X_MAX_PIN DIO3
|
||||
// void x_step(void);
|
||||
// void y_step(void);
|
||||
// void z_step(void);
|
||||
// void e_step(void);
|
||||
|
||||
// #define Y_STEP_PIN DIO4
|
||||
// #define Y_DIR_PIN DIO5
|
||||
// #define Y_MIN_MIN DIO6
|
||||
// #define Y_MAX_PIN DIO7
|
||||
#define _x_step(st) WRITE(AIO0, st)
|
||||
#define x_step() _x_step(1);
|
||||
#define x_direction(dir) WRITE(AIO1, dir)
|
||||
#define x_min() READ(AIO2)
|
||||
#ifdef MAX_ENDSTOPS
|
||||
#define x_max() READ(AIO3)
|
||||
#else
|
||||
#define x_max() (0)
|
||||
#endif
|
||||
|
||||
// #define Z_STEP_PIN DIO8
|
||||
// #define Z_DIR_PIN DIO9
|
||||
// #define Z_MIN_MIN DIO10
|
||||
// #define Z_MAX_PIN DIO11
|
||||
#define _y_step(st) WRITE(DIO2, st)
|
||||
#define y_step() _y_step(1);
|
||||
#define y_direction(dir) WRITE(DIO3, dir)
|
||||
#define y_min() READ(DIO4)
|
||||
#ifdef MAX_ENDSTOPS
|
||||
#define y_max() READ(DIO5)
|
||||
#else
|
||||
#define y_max() (0)
|
||||
#endif
|
||||
|
||||
// #define E_STEP_PIN DIO12
|
||||
// #define E_DIR_PIN DIO13
|
||||
#define _z_step(st) WRITE(DIO6, st)
|
||||
#define z_step() _z_step(1);
|
||||
#define z_direction(dir) WRITE(DIO7, dir)
|
||||
#define z_min() READ(DIO8)
|
||||
#ifdef MAX_ENDSTOPS
|
||||
#define z_max() READ(DIO9)
|
||||
#else
|
||||
#define z_max() (0)
|
||||
#endif
|
||||
|
||||
void x_step(void);
|
||||
void y_step(void);
|
||||
void z_step(void);
|
||||
void e_step(void);
|
||||
#define _e_step(st) WRITE(AIO4, st)
|
||||
#define e_step() _e_step(1);
|
||||
#define e_direction(dir) WRITE(AIO5, dir)
|
||||
|
||||
inline void x_direction(uint8_t dir) {
|
||||
WRITE(DIO1, dir);
|
||||
}
|
||||
#define enable_steppers() WRITE(DIO10, 1)
|
||||
#define disable_steppers() WRITE(DIO10, 0)
|
||||
|
||||
inline uint8_t x_min(void) {
|
||||
return READ(DIO2);
|
||||
}
|
||||
|
||||
inline uint8_t x_max(void) {
|
||||
return READ(DIO3);
|
||||
}
|
||||
|
||||
inline void y_direction(uint8_t dir) {
|
||||
WRITE(DIO5, dir);
|
||||
}
|
||||
|
||||
inline uint8_t y_min(void) {
|
||||
return READ(DIO6);
|
||||
}
|
||||
|
||||
inline uint8_t y_max(void) {
|
||||
return READ(DIO7);
|
||||
}
|
||||
|
||||
inline void z_direction(uint8_t dir) {
|
||||
WRITE(DIO9, dir);
|
||||
}
|
||||
|
||||
inline uint8_t z_min(void) {
|
||||
return READ(DIO10);
|
||||
}
|
||||
|
||||
inline uint8_t z_max(void) {
|
||||
return READ(DIO11);
|
||||
}
|
||||
|
||||
inline void e_direction(uint8_t dir) {
|
||||
WRITE(DIO13, dir);
|
||||
inline void unstep(void) {
|
||||
_x_step(0);
|
||||
_y_step(0);
|
||||
_z_step(0);
|
||||
_e_step(0);
|
||||
}
|
||||
|
||||
#endif /* _PINOUT_H */
|
||||
|
|
|
|||
|
|
@ -0,0 +1,158 @@
|
|||
#include "timer.h"
|
||||
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
#include "pinout.h"
|
||||
#include "dda.h"
|
||||
|
||||
ISR(TIMER1_COMPA_vect) {
|
||||
// static interruptBlink = 0;
|
||||
//
|
||||
// interruptBlink++;
|
||||
// if (interruptBlink == 0x80) {
|
||||
// blink();
|
||||
// interruptBlink = 0;
|
||||
// }
|
||||
|
||||
if(movebuffer[mb_tail].live)
|
||||
dda_step(&movebuffer[mb_tail]);
|
||||
else
|
||||
next_move();
|
||||
}
|
||||
|
||||
void setupTimerInterrupt()
|
||||
{
|
||||
//clear the registers
|
||||
TCCR1A = 0;
|
||||
TCCR1B = 0;
|
||||
TCCR1C = 0;
|
||||
TIMSK1 = 0;
|
||||
|
||||
//waveform generation = 0100 = CTC
|
||||
TCCR1B &= ~(1<<WGM13);
|
||||
TCCR1B |= (1<<WGM12);
|
||||
TCCR1A &= ~(1<<WGM11);
|
||||
TCCR1A &= ~(1<<WGM10);
|
||||
|
||||
//output mode = 00 (disconnected)
|
||||
TCCR1A &= ~(1<<COM1A1);
|
||||
TCCR1A &= ~(1<<COM1A0);
|
||||
TCCR1A &= ~(1<<COM1B1);
|
||||
TCCR1A &= ~(1<<COM1B0);
|
||||
|
||||
//start off with a slow frequency.
|
||||
setTimerResolution(4);
|
||||
setTimerCeiling(65535);
|
||||
}
|
||||
|
||||
uint8_t getTimerResolution(const uint32_t delay)
|
||||
{
|
||||
// these also represent frequency: 1000000 / delay / 2 = frequency in hz.
|
||||
|
||||
// our slowest speed at our highest resolution ( (2^16-1) * 0.0625 usecs = 4095 usecs (4 millisecond max))
|
||||
// range: 8Mhz max - 122hz min
|
||||
if (delay <= 65535L)
|
||||
return 0;
|
||||
// our slowest speed at our next highest resolution ( (2^16-1) * 0.5 usecs = 32767 usecs (32 millisecond max))
|
||||
// range:1Mhz max - 15.26hz min
|
||||
else if (delay <= 524280L)
|
||||
return 1;
|
||||
// our slowest speed at our medium resolution ( (2^16-1) * 4 usecs = 262140 usecs (0.26 seconds max))
|
||||
// range: 125Khz max - 1.9hz min
|
||||
else if (delay <= 4194240L)
|
||||
return 2;
|
||||
// our slowest speed at our medium-low resolution ( (2^16-1) * 16 usecs = 1048560 usecs (1.04 seconds max))
|
||||
// range: 31.25Khz max - 0.475hz min
|
||||
else if (delay <= 16776960L)
|
||||
return 3;
|
||||
// our slowest speed at our lowest resolution ((2^16-1) * 64 usecs = 4194240 usecs (4.19 seconds max))
|
||||
// range: 7.812Khz max - 0.119hz min
|
||||
// else if (delay <= 67107840L)
|
||||
// return 4;
|
||||
//its really slow... hopefully we can just get by with super slow.
|
||||
// else
|
||||
return 4;
|
||||
}
|
||||
|
||||
void setTimerResolution(uint8_t r)
|
||||
{
|
||||
//here's how you figure out the tick size:
|
||||
// 1000000 / ((F_CPU / prescaler))
|
||||
// 1000000 = microseconds in 1 second
|
||||
// prescaler = your prescaler
|
||||
|
||||
// assuming CS10,CS11,CS12 are adjacent bits in platform endian order,
|
||||
TCCR1B = (TCCR1B & ~(MASK(CS10) | MASK(CS11) | MASK(CS12))) | ((r + 1) << CS10);
|
||||
}
|
||||
|
||||
uint16_t getTimerCeiling(const uint32_t delay)
|
||||
{
|
||||
// our slowest speed at our highest resolution ( (2^16-1) * 0.0625 usecs = 4095 usecs)
|
||||
if (delay <= 65535L)
|
||||
return (delay & 0xffff);
|
||||
// our slowest speed at our next highest resolution ( (2^16-1) * 0.5 usecs = 32767 usecs)
|
||||
else if (delay <= 524280L)
|
||||
return ((delay >> 3) & 0xffff);
|
||||
// our slowest speed at our medium resolution ( (2^16-1) * 4 usecs = 262140 usecs)
|
||||
else if (delay <= 4194240L)
|
||||
return ((delay >> 6) & 0xffff);
|
||||
// our slowest speed at our medium-low resolution ( (2^16-1) * 16 usecs = 1048560 usecs)
|
||||
else if (delay <= 16776960L)
|
||||
return ((delay >> 8) & 0xffff);
|
||||
// our slowest speed at our lowest resolution ((2^16-1) * 64 usecs = 4194240 usecs)
|
||||
else if (delay <= 67107840L)
|
||||
return ((delay >> 10) & 0xffff);
|
||||
//its really slow... hopefully we can just get by with super slow.
|
||||
else
|
||||
return 65535;
|
||||
}
|
||||
|
||||
|
||||
// Depending on how much work the interrupt function has to do, this is
|
||||
// pretty accurate between 10 us and 0.1 s. At fast speeds, the time
|
||||
// taken in the interrupt function becomes significant, of course.
|
||||
|
||||
// Note - it is up to the user to call enableTimerInterrupt() after a call
|
||||
// to this function.
|
||||
|
||||
void setTimer(uint32_t delay)
|
||||
{
|
||||
// delay is the delay between steps in microsecond ticks.
|
||||
//
|
||||
// we break it into 5 different resolutions based on the delay.
|
||||
// then we set the resolution based on the size of the delay.
|
||||
// we also then calculate the timer ceiling required. (ie what the counter counts to)
|
||||
// the result is the timer counts up to the appropriate time and then fires an interrupt.
|
||||
|
||||
// Actual ticks are 0.0625 us, so multiply delay by 16
|
||||
|
||||
// convert to ticks
|
||||
delay = delay US;
|
||||
|
||||
setTimerCeiling(getTimerCeiling(delay));
|
||||
setTimerResolution(getTimerResolution(delay));
|
||||
}
|
||||
|
||||
// from reprap project 5D firmware
|
||||
void delayMicrosecondsInterruptible(uint16_t us)
|
||||
{
|
||||
// for a one-microsecond delay, simply return. the overhead
|
||||
// of the function call yields a delay of approximately 1 1/8 us.
|
||||
if (--us == 0)
|
||||
return;
|
||||
|
||||
// the following loop takes a quarter of a microsecond (4 cycles)
|
||||
// per iteration, so execute it four times for each microsecond of
|
||||
// delay requested.
|
||||
us <<= 2;
|
||||
|
||||
// account for the time taken in the preceeding commands.
|
||||
us -= 2;
|
||||
|
||||
// busy wait
|
||||
__asm__ __volatile__ ("1: sbiw %0,1" "\n\t" // 2 cycles
|
||||
"brne 1b" :
|
||||
"=w" (us) :
|
||||
"0" (us) // 2 cycles
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
#ifndef _TIMER_H
|
||||
#define _TIMER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <avr/io.h>
|
||||
|
||||
// time-related constants
|
||||
#define US * (F_CPU / 1000000)
|
||||
#define MS * (F_CPU / 1000)
|
||||
|
||||
#define DEFAULT_TICK (100 US)
|
||||
|
||||
void setupTimerInterrupt(void);
|
||||
uint8_t getTimerResolution(const uint32_t delay);
|
||||
void setTimerResolution(uint8_t r);
|
||||
uint16_t getTimerCeiling(const uint32_t delay);
|
||||
|
||||
void setTimer(uint32_t delay);
|
||||
|
||||
void delayMicrosecondsInterruptible(unsigned int us);
|
||||
|
||||
inline void enableTimerInterrupt(void)
|
||||
{
|
||||
TIMSK1 |= (1<<OCIE1A);
|
||||
}
|
||||
|
||||
inline void disableTimerInterrupt(void)
|
||||
{
|
||||
TIMSK1 &= ~(1<<OCIE1A);
|
||||
}
|
||||
|
||||
inline void setTimerCeiling(uint16_t c)
|
||||
{
|
||||
OCR1A = c;
|
||||
}
|
||||
|
||||
#endif /* _TIMER_H */
|
||||
Loading…
Reference in New Issue