TARGET = $(PROJECT).elf
# Compile flags
-CC = avr-gcc
+CC = avr-g++
COMMON = -mmcu=$(MCU) -flto -fwhole-program
CFLAGS += $(COMMON)
CFLAGS += -Wall -Werror
CFLAGS += -Wno-error=strict-aliasing # for _invsqrt
-CFLAGS += -std=gnu99 -DF_CPU=$(CLOCK)UL -O3
+CFLAGS += -std=gnu++98 -DF_CPU=$(CLOCK)UL -O3
CFLAGS += -funsigned-bitfields -fpack-struct -fshort-enums -funsigned-char
CFLAGS += -MD -MP -MT $@ -MF build/dep/$(@F).d
+CFLAGS += -D__STDC_LIMIT_MACROS
CFLAGS += -Isrc
# Linker flags
// Define command callbacks
#define CMD(CODE, NAME, SYNC, ...) \
- stat_t command_##NAME(); \
+ stat_t command_##NAME(char *); \
IF(SYNC)(unsigned command_##NAME##_size();) \
IF(SYNC)(void command_##NAME##_exec(void *);)
#include "command.def"
void command_print_json() {
bool first = true;
static const char fmt[] PROGMEM =
- "\"%c\":{\"name\":\"%"PRPSTR"\",\"help\":\"%"PRPSTR"\"}";
+ "\"%c\":{\"name\":\"%" PRPSTR "\",\"help\":\"%" PRPSTR "\"}";
#define CMD(CODE, NAME, SYNC, HELP) \
if (first) first = false; else putchar(','); \
unsigned command_dwell_size() {return sizeof(float);}
-void command_dwell_exec(float *seconds) {
- st_prep_dwell(*seconds);
+void command_dwell_exec(void *seconds) {
+ st_prep_dwell(*(float *)seconds);
exec_set_cb(_dwell_exec); // Necessary evil
}
typedef struct {
+ uint8_t cs_pin;
+ switch_id_t stall_sw;
+
uint8_t status;
uint16_t flags;
bool stalled;
uint8_t mode; // microstepping mode
stall_callback_t stall_cb;
-
- uint8_t cs_pin;
- switch_id_t stall_sw;
} drv8711_driver_t;
static stat_t _get_reason() {
- return eeprom_read_word(&estop_reason_eeprom);
+ return (stat_t)eeprom_read_word(&estop_reason_eeprom);
}
// TODO implement overrides
// Set callback for limit switches
- for (switch_id_t sw = SW_MIN_X; sw <= SW_MAX_A; sw++)
- switch_set_callback(sw, _limit_switch_cb);
+ for (int sw = SW_MIN_X; sw <= SW_MAX_A; sw++)
+ switch_set_callback((switch_id_t)sw, _limit_switch_cb);
}
if (*cmd) return STAT_INVALID_ARGUMENTS;
// Update command
- command_set_axis_position(axis, position);
+ command_set_axis_position((uint8_t)axis, position);
// Queue
- set_axis_t set_axis = {axis, position};
+ set_axis_t set_axis = {(uint8_t)axis, position};
command_push(COMMAND_set_axis, &set_axis);
return STAT_OK;
} else result = analog_get(active_cmd.port);
// TODO find a better way to send this
- printf("{\"result\": %f}\n", result);
+ printf("{\"result\": %f}\n", (double)result);
active_cmd.port = -1;
}
}
// Mode
if (!isdigit(*cmd)) return STAT_INVALID_ARGUMENTS;
- input_cmd.mode = *cmd - '0';
+ input_cmd.mode = (input_mode_t)(*cmd - '0');
if (INPUT_LOW < input_cmd.mode) return STAT_INVALID_ARGUMENTS;
cmd++;
static struct {
- line_t line;
-
+ float current_time;
int section;
bool stop_section;
- float current_time;
float offset_time;
int seg;
+ line_t line;
+
float iD; // Initial section distance
float iV; // Initial section velocity
float iA; // Initial section acceleration
void _print_vector(const char *name, float v[4]) {
- printf("%s %f %f %f %f\n", name, v[0], v[1], v[2], v[3]);
+ printf("%s %f %f %f %f\n",
+ name, (double)v[0], (double)v[1], (double)v[2], (double)v[3]);
}
typedef struct {
// Config
uint8_t axis; // map motor to axis
+ uint8_t step_pin;
+ uint8_t dir_pin;
+ TC0_t *timer;
+ DMA_CH_t *dma;
+ uint8_t dma_trigger;
bool slave;
uint16_t microsteps; // microsteps per full step
bool reverse;
float min_soft_limit;
float max_soft_limit;
bool homed;
- uint8_t step_pin;
- uint8_t dir_pin;
- TC0_t *timer;
- DMA_CH_t *dma;
- uint8_t dma_trigger;
// Computed
float steps_per_unit;
for (int m = motor; m < MOTORS; m++)
if (motors[m].axis == motors[motor].axis)
motors[m].power_mode =
- value <= MOTOR_POWERED_ONLY_WHEN_MOVING ? value : MOTOR_DISABLED;
+ value <= MOTOR_POWERED_ONLY_WHEN_MOVING ?
+ (motor_power_mode_t)value : MOTOR_DISABLED;
}
// Var callbacks
-uint8_t get_output_state(uint8_t id) {
+uint8_t get_output_state(int id) {
return OUTS <= id ? OUT_TRI : outputs[id].state;
}
-bool get_output_active(uint8_t id) {
+bool get_output_active(int id) {
return OUTS <= id ? false : outputs[id].active;
}
-void set_output_active(uint8_t id, bool active) {
+void set_output_active(int id, bool active) {
if (OUTS <= id) return;
outputs[id].active = active;
_update_state(&outputs[id]);
}
-uint8_t get_output_mode(uint8_t id) {
+uint8_t get_output_mode(int id) {
return OUTS <= id ? OUT_DISABLED : outputs[id].mode;
}
-void set_output_mode(uint8_t id, uint8_t mode) {
+void set_output_mode(int id, uint8_t mode) {
if (OUTS <= id) return;
- outputs[id].mode = mode;
+ outputs[id].mode = (output_mode_t)mode;
_update_state(&outputs[id]);
}
} seek_t;
-static seek_t seek = {false, -1, 0};
+static seek_t seek = {false, SW_INVALID, 0};
-switch_id_t seek_get_switch() {return seek.active ? seek.sw : -1;}
+switch_id_t seek_get_switch() {return seek.active ? seek.sw : SW_INVALID;}
bool seek_switch_found() {
// Command callbacks
stat_t command_seek(char *cmd) {
- int8_t sw = decode_hex_nibble(cmd[1]);
+ switch_id_t sw = (switch_id_t)decode_hex_nibble(cmd[1]);
if (sw <= 0) return STAT_INVALID_ARGUMENTS; // Don't allow seek to ESTOP
if (!switch_is_enabled(sw)) return STAT_SEEK_NOT_ENABLED;
- int8_t flags = decode_hex_nibble(cmd[2]);
+ uint8_t flags = decode_hex_nibble(cmd[2]);
if (flags & 0xfc) return STAT_INVALID_ARGUMENTS;
seek_t seek = {true, sw, flags};
case SPINDLE_TYPE_HUANYANG: hy_deinit(); break;
}
- spindle.type = value;
+ spindle.type = (spindle_type_t)value;
switch (spindle.type) {
case SPINDLE_TYPE_DISABLED: break;
static struct {
- state_t state;
- hold_reason_t hold_reason;
-
+ bool flushing;
+ bool resuming;
bool stop_requested;
bool pause_requested;
bool optional_pause_requested;
bool unpause_requested;
- bool flushing;
- bool resuming;
+ state_t state;
+ hold_reason_t hold_reason;
} s = {
.flushing = true, // Start out flushing
};
const char *status_to_pgmstr(stat_t code) {
- return pgm_read_ptr(&stat_msg[code]);
+ return (const char *)pgm_read_ptr(&stat_msg[code]);
}
va_list args;
// Type
- printf_P(PSTR("\n{\"level\":\"%"PRPSTR"\",\"msg\":\""),
+ printf_P(PSTR("\n{\"level\":\"%" PRPSTR "\",\"msg\":\""),
status_level_pgmstr(level));
// Message
if (code) printf_P(PSTR(",\"code\":%d"), code);
// Location
- if (location) printf_P(PSTR(",\"where\":\"%"PRPSTR"\""), location);
+ if (location) printf_P(PSTR(",\"where\":\"%" PRPSTR "\""), location);
putchar('}');
putchar('\n');
s->state = state;
s->debounce = 0;
s->initialized = true;
- if (s->cb) s->cb(i, switch_is_active(i));
+ if (s->cb) s->cb((switch_id_t)i, switch_is_active((switch_id_t)i));
}
}
}
void set_min_sw_mode(int index, uint8_t value) {
- switch_set_type(MIN_SWITCH(index), value);
+ switch_set_type(MIN_SWITCH(index), (switch_type_t)value);
}
void set_max_sw_mode(int index, uint8_t value) {
- switch_set_type(MAX_SWITCH(index), value);
+ switch_set_type(MAX_SWITCH(index), (switch_type_t)value);
}
uint8_t get_estop_mode() {return switch_get_type(SW_ESTOP);}
-void set_estop_mode(uint8_t value) {switch_set_type(SW_ESTOP, value);}
+
+
+void set_estop_mode(uint8_t value) {
+ switch_set_type(SW_ESTOP, (switch_type_t)value);
+}
+
+
uint8_t get_probe_mode() {return switch_get_type(SW_PROBE);}
-void set_probe_mode(uint8_t value) {switch_set_type(SW_PROBE, value);}
+
+
+void set_probe_mode(uint8_t value) {
+ switch_set_type(SW_PROBE, (switch_type_t)value);
+}
static uint8_t _get_state(int index) {
- if (!switch_is_enabled(index)) return 2; // Disabled
+ if (!switch_is_enabled((switch_id_t)index)) return 2; // Disabled
return switches[index].state;
}
// macros for finding the index into the switch table give the axis number
-#define MIN_SWITCH(axis) (2 + axis * 2)
-#define MAX_SWITCH(axis) (2 + axis * 2 + 1)
+#define MIN_SWITCH(axis) ((switch_id_t)(2 + axis * 2))
+#define MAX_SWITCH(axis) ((switch_id_t)(2 + axis * 2 + 1))
typedef enum {
/// Switch IDs
typedef enum {
+ SW_INVALID = -1,
SW_ESTOP, SW_PROBE,
SW_MIN_X, SW_MAX_X,
SW_MIN_Y, SW_MAX_Y,
// Program string
bool type_eq_pstr(pstr a, pstr b) {return a == b;}
-void type_print_pstr(pstr s) {printf_P(PSTR("\"%"PRPSTR"\""), s);}
+void type_print_pstr(pstr s) {printf_P(PSTR("\"%" PRPSTR "\""), s);}
const char *type_parse_pstr(const char *value) {return value;}
float type_pstr_to_float(pstr s) {return 0;}
// bool
-bool type_eq_bool(bool a, bool b) {return a == b;}
-float type_bool_to_float(bool x) {return x;}
-void type_print_bool(bool x) {printf_P(x ? PSTR("true") : PSTR("false"));}
+bool type_eq_b8(bool a, bool b) {return a == b;}
+float type_b8_to_float(bool x) {return x;}
+void type_print_b8(bool x) {printf_P(x ? PSTR("true") : PSTR("false"));}
-bool type_parse_bool(const char *value) {
+bool type_parse_b8(const char *value) {
return !strcasecmp(value, "true") || type_parse_f32(value);
}
// s8
bool type_eq_s8(s8 a, s8 b) {return a == b;}
float type_s8_to_float(s8 x) {return x;}
-void type_print_s8(s8 x) {printf_P(PSTR("%"PRIi8), x);}
+void type_print_s8(s8 x) {printf_P(PSTR("%" PRIi8), x);}
s8 type_parse_s8(const char *value) {return strtol(value, 0, 0);}
// u8
bool type_eq_u8(u8 a, u8 b) {return a == b;}
float type_u8_to_float(u8 x) {return x;}
-void type_print_u8(u8 x) {printf_P(PSTR("%"PRIu8), x);}
+void type_print_u8(u8 x) {printf_P(PSTR("%" PRIu8), x);}
u8 type_parse_u8(const char *value) {return strtol(value, 0, 0);}
// u16
bool type_eq_u16(u16 a, u16 b) {return a == b;}
float type_u16_to_float(u16 x) {return x;}
-void type_print_u16(u16 x) {printf_P(PSTR("%"PRIu16), x);}
+void type_print_u16(u16 x) {printf_P(PSTR("%" PRIu16), x);}
u16 type_parse_u16(const char *value) {return strtoul(value, 0, 0);}
// s32
bool type_eq_s32(s32 a, s32 b) {return a == b;}
float type_s32_to_float(s32 x) {return x;}
-void type_print_s32(s32 x) {printf_P(PSTR("%"PRIi32), x);}
+void type_print_s32(s32 x) {printf_P(PSTR("%" PRIi32), x);}
s32 type_parse_s32(const char *value) {return strtol(value, 0, 0);}
// u32
bool type_eq_u32(u32 a, u32 b) {return a == b;}
float type_u32_to_float(u32 x) {return x;}
-void type_print_u32(u32 x) {printf_P(PSTR("%"PRIu32), x);}
+void type_print_u32(u32 x) {printf_P(PSTR("%" PRIu32), x);}
u32 type_parse_u32(const char *value) {return strtol(value, 0, 0);}
\******************************************************************************/
-#ifdef bool
-#undef bool
-#endif
-
// TYPE DEF
TYPEDEF(flags, uint16_t)
TYPEDEF(str, const char *)
TYPEDEF(u16, uint16_t)
TYPEDEF(s32, int32_t)
TYPEDEF(u32, uint32_t)
-TYPEDEF(bool, _Bool)
+TYPEDEF(b8, bool)
#include "pgmspace.h"
#include <stdint.h>
+#include <stdbool.h>
// Define types
#include <stdio.h>
#include <stdbool.h>
+#include <string.h>
+
// Ring buffers
#define RING_BUF_NAME tx_buf
}
-static FILE _stdout = FDEV_SETUP_STREAM(_usart_putchar, 0, _FDEV_SETUP_WRITE);
-
-
void usart_init(void) {
// Setup ring buffer
tx_buf_init();
PMIC.CTRL |= PMIC_HILVLEN_bm; // Interrupt level on
// Connect IO
+ static FILE _stdout;
+ memset(&_stdout, 0, sizeof(FILE));
+ _stdout.put = _usart_putchar;
+ _stdout.flags = _FDEV_SETUP_WRITE;
+
stdout = &_stdout;
stderr = &_stdout;
void vars_print_json() {
bool first = true;
static const char fmt[] PROGMEM =
- "\"%s\":{\"name\":\"%"PRPSTR"\",\"type\":\"%"PRPSTR"\","
- "\"help\":\"%"PRPSTR"\"";
+ "\"%s\":{\"name\":\"%" PRPSTR "\",\"type\":\"%" PRPSTR "\","
+ "\"help\":\"%" PRPSTR "\"";
static const char index_fmt[] PROGMEM = ",\"index\":\"%s\"";
#define VAR(NAME, CODE, TYPE, INDEX, ...) \
unsigned command_sync_var_size() {return sizeof(var_cmd_t);}
-void command_sync_var_exec(char *data) {
+void command_sync_var_exec(void *data) {
var_cmd_t *cmd = (var_cmd_t *)data;
_set(cmd->type, cmd->index, cmd->set, cmd->value);
}
VAR(drive_current, dc, f32, MOTORS, 1, 1, "Max motor drive current")
VAR(idle_current, ic, f32, MOTORS, 1, 1, "Motor idle current")
-VAR(reverse, rv, u8, MOTORS, 1, 1, "Reverse motor polarity")
+VAR(reverse, rv, b8, MOTORS, 1, 1, "Reverse motor polarity")
VAR(microstep, mi, u16, MOTORS, 1, 1, "Microsteps per full step")
VAR(velocity_max, vm, f32, MOTORS, 1, 1, "Maxium vel in mm/min")
VAR(accel_max, am, f32, MOTORS, 1, 1, "Maxium accel in mm/min^2")
VAR(min_soft_limit, tn, f32, MOTORS, 1, 1, "Min soft limit")
VAR(max_soft_limit, tm, f32, MOTORS, 1, 1, "Max soft limit")
-VAR(homed, h, bool, MOTORS, 1, 1, "Motor homed status")
+VAR(homed, h, b8, MOTORS, 1, 1, "Motor homed status")
VAR(active_current, ac, f32, MOTORS, 0, 1, "Motor current now")
VAR(driver_flags, df, u16, MOTORS, 0, 1, "Motor driver flags")
VAR(status_strings, ds, flags, MOTORS, 0, 1, "Motor driver status")
-VAR(driver_stalled, sl, bool, MOTORS, 0, 1, "Motor driver status")
+VAR(driver_stalled, sl, b8, MOTORS, 0, 1, "Motor driver status")
VAR(encoder, en, s32, MOTORS, 0, 0, "Motor encoder")
VAR(error, ee, s32, MOTORS, 0, 0, "Motor position error")
-VAR(motor_fault, fa, bool, 0, 0, 1, "Motor fault status")
+VAR(motor_fault, fa, b8, 0, 0, 1, "Motor fault status")
// Switches
VAR(min_sw_mode, ls, u8, MOTORS, 1, 1, "Minimum switch mode")
VAR(axis_position, p, f32, AXES, 0, 1, "Axis position")
// Outputs
-VAR(output_active, oa, bool, OUTS, 1, 1, "Output pin active")
+VAR(output_active, oa, b8, OUTS, 1, 1, "Output pin active")
VAR(output_state, os, u8, OUTS, 0, 1, "Output pin state")
VAR(output_mode, om, u8, OUTS, 1, 1, "Output pin mode")
// Spindle
VAR(spindle_type, st, u8, 0, 1, 1, "DISABLED=0, PWM=1 or HUANYANG=2")
-VAR(spin_reversed, sr, bool, 0, 1, 1, "Reverse spin")
+VAR(spin_reversed, sr, b8, 0, 1, 1, "Reverse spin")
VAR(max_spin, sx, f32, 0, 1, 1, "Maximum spindle speed")
VAR(min_spin, sm, f32, 0, 1, 1, "Minimum spindle speed")
VAR(pwm_min_duty, nd, f32, 0, 1, 1, "Minimum PWM duty cycle")
VAR(pwm_freq, sf, u16, 0, 1, 1, "Spindle PWM frequency in Hz")
// PWM spindle
-VAR(pwm_invert, pi, bool, 0, 1, 1, "Inverted spindle PWM")
+VAR(pwm_invert, pi, b8, 0, 1, 1, "Inverted spindle PWM")
// Huanyang spindle
VAR(hy_id, hi, u8, 0, 1, 1, "Huanyang ID")
VAR(hy_min_freq, hm, f32, 0, 0, 1, "Huanyang min freq")
VAR(hy_rated_rpm, hq, u16, 0, 0, 1, "Huanyang rated RPM")
VAR(hy_status, hs, u8, 0, 0, 1, "Huanyang status flags")
-VAR(hy_debug, hb, bool, 0, 1, 1, "Huanyang debugging")
-VAR(hy_connected, he, bool, 0, 0, 1, "Huanyang connected")
+VAR(hy_debug, hb, b8, 0, 1, 1, "Huanyang debugging")
+VAR(hy_connected, he, b8, 0, 0, 1, "Huanyang connected")
// Machine state
VAR(id, id, u32, 0, 1, 1, "Last executed command ID")
VAR(speed, s, f32, 0, 1, 1, "Current spindle speed")
VAR(feed_override, fo, f32, 0, 1, 1, "Feed rate override")
VAR(speed_override, so, f32, 0, 1, 1, "Spindle speed override")
-VAR(optional_pause, op, bool, 0, 1, 1, "Optional pause state")
+VAR(optional_pause, op, b8, 0, 1, 1, "Optional pause state")
// System
VAR(velocity, v, f32, 0, 0, 1, "Current velocity")
VAR(acceleration, ax, f32, 0, 0, 1, "Current acceleration")
VAR(jerk, j, f32, 0, 0, 1, "Current jerk")
VAR(hw_id, hid, str, 0, 0, 1, "Hardware ID")
-VAR(estop, es, bool, 0, 1, 1, "Emergency stop")
+VAR(estop, es, b8, 0, 1, 1, "Emergency stop")
VAR(estop_reason, er, pstr, 0, 0, 1, "Emergency stop reason")
VAR(state, xx, pstr, 0, 0, 1, "Machine state")
VAR(hold_reason, pr, pstr, 0, 0, 1, "Machine pause reason")