diff --git a/CHANGELOG.md b/CHANGELOG.md index f175d55d..f5cb81af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ Buildbotics CNC Controller Firmware Changelog ============================================= +## v1.0.2 + - Remappable IO + ## v1.0.1 - Handle case correctly when assigning named GCode variables. - Increased gamepad deadband to 15% but with rescaling to improve precision. @@ -11,6 +14,7 @@ Buildbotics CNC Controller Firmware Changelog - Correction for voltage measurements. - Removed load current and faults for newer hardware from indicators and LCD. - Added DB15 breakout box to indicators page. + - Send stop command to VFD on estop. ## v1.0.0 - Added online GCode editor. diff --git a/jshint.json b/jshint.json index 93298410..42cb1f9e 100644 --- a/jshint.json +++ b/jshint.json @@ -3,6 +3,7 @@ "browser": true, "devel": true, "strict": "global", + "esversion": 6, "globals": { "$": false, "require": false, @@ -11,6 +12,8 @@ "SockJS": false, "Gauge": false, "Clusterize": false, - "CodeMirror": false + "CodeMirror": false, + "Chart": false, + "THREE": false } } diff --git a/scripts/avr109-flash b/scripts/avr109-flash index 2fec9366..f7ca79d5 100755 --- a/scripts/avr109-flash +++ b/scripts/avr109-flash @@ -1,15 +1,14 @@ #!/usr/bin/env python3 import sys +import os import time import serial import binascii +import argparse -dev = '/dev/ttyAMA0' -baud = 921600 boot_id = 'bbctrl ' -verbose = False def crc16(data): @@ -70,41 +69,57 @@ def read_intel_hex(f): def send(data): - if verbose: print('Sending:', data) + if args.verbose: print('Sending:', data) sp.write(bytes(data, 'utf8')) def send_int(x, size): - if verbose: print('Sending: %d', x) + if args.verbose: print('Sending: %d', x) sp.write((x).to_bytes(size, byteorder = 'big')) def recv(count): data = sp.read(count).decode('utf8') - if count and verbose: print('Received:', data) + if count and args.verbose: print('Received:', data) return data def recv_int(size): x = int.from_bytes(sp.read(size), byteorder = 'big') - if verbose: print('Received:', x) + if args.verbose: print('Received:', x) return x +# Parse arguments +parser = argparse.ArgumentParser(description = 'Program AVR over serial port ' + 'using the AVR109 bootloader protocol.') +parser.add_argument('-b', '--baud', default = 921600, type = int, + help = 'Set baud rate.') +parser.add_argument('-t', '--timeout', default = 10, type = int, + help = 'Timeout in seconds.') +parser.add_argument('-d', '--device', default = '/dev/ttyAMA0', + help = 'Serial device.') +parser.add_argument('-r', '--reset', default = 27, type = int, + help = 'Reset line GPIO.') +parser.add_argument('-v', '--verbose', help = 'Enable verbose logging', + action = 'count', default = 0) +parser.add_argument('file', help = 'The Intel hex file to program.') +args = parser.parse_args() # Read firmware hex file -data = list(read_intel_hex(open(sys.argv[1], 'r'))) +data = list(read_intel_hex(open(args.file, 'r'))) # Open serial port -sp = serial.Serial(dev, baud, timeout = 10) +sp = serial.Serial(args.device, args.baud, timeout = args.timeout) # Reset AVR -import RPi.GPIO as gpio -gpio.setwarnings(False) -gpio.setmode(gpio.BCM) -gpio.setup(27, gpio.OUT) -gpio.output(27, 0) -gpio.output(27, 1) -gpio.setup(27, gpio.IN, pull_up_down = gpio.PUD_UP) +reset_gpio_path = '/sys/class/gpio/gpio%s' % args.reset +if not os.path.exists(reset_gpio_path): + with open('/sys/class/gpio/export', 'w') as f: + f.write(str(args.reset)) + +with open(reset_gpio_path + '/direction', 'w') as f: f.write('out') +with open(reset_gpio_path + '/value', 'w') as f: f.write('0') +with open(reset_gpio_path + '/value', 'w') as f: f.write('1') time.sleep(0.1) # Sync diff --git a/scripts/install.sh b/scripts/install.sh index 9a86d4f2..47c95fe6 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -14,7 +14,21 @@ while [ $# -gt 0 ]; do shift 1 done -service bbctrl stop +if [ -e /etc/systemd/system/bbctrl.service ]; then + service bbctrl stop +fi + +# Find devices +if [ -e /dev/ttyAMA0 ]; then + AVR_DEV=/dev/ttyAMA0 + AVR_RESET=27 +elif [ -e /dev/ttyS2 ]; then + AVR_DEV=/dev/ttyS2 + AVR_RESET=117 +else + >&2 echo "Cannot find AVR serial device." + UPDATE_AVR=false +fi if $UPDATE_PY; then # Update service @@ -26,7 +40,8 @@ if $UPDATE_PY; then fi if $UPDATE_AVR; then - ./scripts/avr109-flash src/avr/bbctrl-avr-firmware.hex + ./scripts/avr109-flash -d $AVR_DEV -r $AVR_RESET \ + src/avr/bbctrl-avr-firmware.hex fi # Update config.txt diff --git a/src/avr/src/config.h b/src/avr/src/config.h index 5ef516c0..03da59c4 100644 --- a/src/avr/src/config.h +++ b/src/avr/src/config.h @@ -94,8 +94,9 @@ enum { #define AXES 6 // number of axes #define MOTORS 4 // number of motors on the board +#define INS 6 // number of supported pin outputs #define OUTS 10 // number of supported pin outputs -#define ANALOGS 4 // number of supported analog inputs +#define ANALOGS 2 // number of supported analog inputs #define DIGITALS 4 // number of supported digital inputs #define VFDREG 32 // number of supported VFD modbus registers #define IO_PINS 17 // number of supported i/o pins diff --git a/src/avr/src/drv8711.c b/src/avr/src/drv8711.c index 2e0c9ed1..301e6500 100644 --- a/src/avr/src/drv8711.c +++ b/src/avr/src/drv8711.c @@ -174,6 +174,7 @@ static uint8_t _driver_get_torque(drv8711_driver_t *drv) { } } + static uint16_t _driver_get_torque_reg(drv8711_driver_t *drv) { uint16_t reg; diff --git a/src/avr/src/io.c b/src/avr/src/io.c index 270de293..0649980f 100644 --- a/src/avr/src/io.c +++ b/src/avr/src/io.c @@ -32,11 +32,7 @@ #include -#define IO_MIN_INDEX 'a' -#define IO_MAX_INDEX 'q' - -#define IF_INVALID_INDEX_RETURN \ - if (index < IO_MIN_INDEX || IO_MAX_INDEX < index) return +#define IO_MAX_INDEX 17 // macros for finding io function given the axis number #define MIN_INPUT(axis) ((io_function_t)(INPUT_MOTOR_0_MIN + axis)) @@ -65,6 +61,7 @@ typedef struct { typedef struct { uint8_t pin; + uint8_t types; uint8_t adc_ch; uint8_t adc_mux; io_function_t function; @@ -80,31 +77,32 @@ typedef struct { static io_pin_t _pins[] = { - {IO_01_PIN, IO_INVALID}, - {IO_02_PIN, IO_INVALID}, - {IO_03_PIN, 1, ADC_CH_MUXPOS_PIN0_gc}, - {IO_04_PIN, 1, ADC_CH_MUXPOS_PIN1_gc}, - {IO_05_PIN, 1, ADC_CH_MUXPOS_PIN4_gc}, - {IO_08_PIN, 1, ADC_CH_MUXPOS_PIN5_gc}, - {IO_09_PIN, 1, ADC_CH_MUXPOS_PIN6_gc}, - {IO_10_PIN, 1, ADC_CH_MUXPOS_PIN7_gc}, - {IO_11_PIN, 1, ADC_CH_MUXPOS_PIN2_gc}, - {IO_12_PIN, 1, ADC_CH_MUXPOS_PIN3_gc}, - {IO_15_PIN, 0, ADC_CH_MUXPOS_PIN5_gc}, - {IO_16_PIN, 0, ADC_CH_MUXPOS_PIN4_gc}, - {IO_18_PIN, 0, ADC_CH_MUXPOS_PIN7_gc}, - {IO_21_PIN, IO_INVALID}, - {IO_22_PIN, IO_INVALID}, - {IO_23_PIN, IO_INVALID}, - {IO_24_PIN, 0, ADC_CH_MUXPOS_PIN6_gc}, + // Remapable pins + {IO_01_PIN, IO_TYPE_OUTPUT}, + {IO_02_PIN, IO_TYPE_OUTPUT}, + {IO_03_PIN, IO_TYPE_INPUT}, + {IO_04_PIN, IO_TYPE_INPUT}, + {IO_05_PIN, IO_TYPE_INPUT}, + {IO_08_PIN, IO_TYPE_INPUT}, + {IO_09_PIN, IO_TYPE_INPUT}, + {IO_10_PIN, IO_TYPE_INPUT}, + {IO_11_PIN, IO_TYPE_INPUT}, + {IO_12_PIN, IO_TYPE_INPUT}, + {IO_15_PIN, IO_TYPE_OUTPUT}, + {IO_16_PIN, IO_TYPE_OUTPUT}, + {IO_18_PIN, IO_TYPE_ANALOG, 0, ADC_CH_MUXPOS_PIN7_gc}, + {IO_21_PIN, IO_TYPE_OUTPUT}, + {IO_22_PIN, IO_TYPE_INPUT}, + {IO_23_PIN, IO_TYPE_INPUT}, + {IO_24_PIN, IO_TYPE_ANALOG, 0, ADC_CH_MUXPOS_PIN6_gc}, // Hard wired pins - {STALL_0_PIN, IO_INVALID, 0, INPUT_STALL_0}, - {STALL_1_PIN, IO_INVALID, 0, INPUT_STALL_1}, - {STALL_2_PIN, IO_INVALID, 0, INPUT_STALL_2}, - {STALL_3_PIN, IO_INVALID, 0, INPUT_STALL_3}, - {MOTOR_FAULT_PIN, IO_INVALID, 0, INPUT_MOTOR_FAULT}, - {TEST_PIN, IO_INVALID, 0, OUTPUT_TEST}, + {STALL_0_PIN, IO_TYPE_INPUT, 0, 0, INPUT_STALL_0, HI_LO}, + {STALL_1_PIN, IO_TYPE_INPUT, 0, 0, INPUT_STALL_1, HI_LO}, + {STALL_2_PIN, IO_TYPE_INPUT, 0, 0, INPUT_STALL_2, HI_LO}, + {STALL_3_PIN, IO_TYPE_INPUT, 0, 0, INPUT_STALL_3, HI_LO}, + {MOTOR_FAULT_PIN, IO_TYPE_INPUT, 0, 0, INPUT_MOTOR_FAULT, HI_LO}, + {TEST_PIN, IO_TYPE_OUTPUT, 0, 0, OUTPUT_TEST}, {0}, // Sentinal }; @@ -115,16 +113,29 @@ static float _analog_ports[ANALOGS]; static io_function_t _output_to_function(int id) { switch (id) { - case 0: return OUTPUT_0; - case 1: return OUTPUT_1; - case 2: return OUTPUT_2; - case 3: return OUTPUT_3; - case 4: return OUTPUT_MIST; - case 5: return OUTPUT_FLOOD; - case 6: return OUTPUT_FAULT; - case 7: return OUTPUT_TOOL_DIRECTION; - case 8: return OUTPUT_TOOL_ENABLE; - case 9: return OUTPUT_TEST; + case 0: return OUTPUT_0; + case 1: return OUTPUT_1; + case 2: return OUTPUT_2; + case 3: return OUTPUT_3; + case 4: return OUTPUT_MIST; + case 5: return OUTPUT_FLOOD; + case 6: return OUTPUT_FAULT; + case 7: return OUTPUT_TOOL_ENABLE; + case 8: return OUTPUT_TOOL_DIRECTION; + case 9: return OUTPUT_TEST; + default: return IO_DISABLED; + } +} + + +static io_function_t _input_to_function(int id) { + switch (id) { + case 0: return INPUT_0; + case 1: return INPUT_1; + case 2: return INPUT_2; + case 3: return INPUT_3; + case 4: return INPUT_ESTOP; + case 5: return INPUT_PROBE; default: return IO_DISABLED; } } @@ -135,7 +146,14 @@ static uint8_t _function_to_analog_port(io_function_t function) { } +static bool _is_valid(io_function_t function, io_type_t type) { + return io_get_type(function) == type; +} + + static void _state_set_active(io_function_t function, bool active) { + if (!_is_valid(function, IO_TYPE_INPUT)) return; + io_func_state_t *state = &_func_state[function]; if (active) { @@ -149,23 +167,6 @@ static void _state_set_active(io_function_t function, bool active) { } -static bool _is_valid(io_function_t function, io_type_t type) { - return io_get_type(function) == type; -} - - -static bool _is_input_active(io_pin_t *pin) { - if (!_is_valid(pin->function, IO_TYPE_INPUT) || !pin->input.initialized) - return false; - - switch (pin->mode) { - case HI_LO: return !pin->input.state; - case LO_HI: return pin->input.state; - default: return false; - } -} - - static uint8_t _mode_state(io_mode_t mode, bool active) { switch (mode) { case LO_HI: return active ? IO_HI : IO_LO; @@ -179,13 +180,39 @@ static uint8_t _mode_state(io_mode_t mode, bool active) { } +static uint8_t _get_pin_output_mode(io_pin_t *pin) { + if (!DIR_PIN(pin->pin)) return IO_TRI; + return OUT_PIN(pin->pin) ? IO_HI : IO_LO; +} + + +static bool _is_active(io_pin_t *pin) { + switch (io_get_type(pin->function)) { + case IO_TYPE_INPUT: + if (!pin->input.initialized) return false; + + switch (pin->mode) { + case HI_LO: return !pin->input.state; + case LO_HI: return pin->input.state; + default: return false; + } + break; + + case IO_TYPE_OUTPUT: + return _get_pin_output_mode(pin) == _mode_state(pin->mode, true); + + default: return false; + } +} + + static void _set_output(io_pin_t *pin, bool active) { uint8_t state = _mode_state(pin->mode, active); switch (state) { - case 0: OUTCLR_PIN(pin->pin); DIRSET_PIN(pin->pin); break; - case 1: OUTSET_PIN(pin->pin); DIRSET_PIN(pin->pin); break; - default: DIRCLR_PIN(pin->pin); break; + case IO_LO: OUTCLR_PIN(pin->pin); DIRSET_PIN(pin->pin); break; + case IO_HI: OUTSET_PIN(pin->pin); DIRSET_PIN(pin->pin); break; + default: DIRCLR_PIN(pin->pin); break; } } @@ -196,7 +223,7 @@ static void _set_function(io_pin_t *pin, io_function_t function) { switch (oldType) { case IO_TYPE_INPUT: // Release active input - if (_is_input_active(pin)) _state_set_active(pin->function, false); + if (_is_active(pin)) _state_set_active(pin->function, false); memset(&pin->input, 0, sizeof(pin->input)); // Reset input state break; @@ -208,8 +235,10 @@ static void _set_function(io_pin_t *pin, io_function_t function) { } pin->function = function; + io_type_t newType = io_get_type(function); + if (!(pin->types & newType)) newType = IO_TYPE_DISABLED; - switch (io_get_type(function)) { + switch (newType) { case IO_TYPE_INPUT: PINCTRL_PIN(pin->pin) = PORT_OPC_PULLUP_gc; // Pull up DIRCLR_PIN(pin->pin); // Input @@ -221,13 +250,9 @@ static void _set_function(io_pin_t *pin, io_function_t function) { case IO_TYPE_ANALOG: _analog_ports[_function_to_analog_port(function)] = 0; - - if (pin->adc_ch == IO_INVALID) pin->function = IO_DISABLED; - else { - PINCTRL_PIN(pin->pin) = 0; // Disable pull up - DIRCLR_PIN(pin->pin); // Input - break; - } + PINCTRL_PIN(pin->pin) = 0; // Disable pull up + DIRCLR_PIN(pin->pin); // Input + break; // Fall through if analog disabled @@ -408,12 +433,15 @@ void io_rtc_callback() { bool state = IN_PIN(pin->pin); if (state == input->state && input->initialized) input->debounce = 0; else if (++input->debounce == _io.debounce) { + bool first = !input->initialized; + input->state = state; input->debounce = 0; input->initialized = true; input->lockout = _io.lockout; - _state_set_active(pin->function, _is_input_active(pin)); + if (!first || _is_active(pin)) + _state_set_active(pin->function, _is_active(pin)); } } } @@ -438,46 +466,48 @@ static uint8_t _get_state(io_function_t function) { if (!_is_valid(function, IO_TYPE_INPUT) || !io_is_enabled(function)) return IO_INVALID; - return _func_state[function].active; + return !!_func_state[function].active; } // Var callbacks uint8_t get_io_function(int index) { - IF_INVALID_INDEX_RETURN IO_DISABLED; - return _pins[index].function; + return IO_MAX_INDEX <= index ? IO_DISABLED : _pins[index].function; } void set_io_function(int index, uint8_t function) { - IF_INVALID_INDEX_RETURN; - if (IO_FUNCTION_COUNT <= function || _pins[index].function == function) - return; + if (IO_MAX_INDEX <= index || IO_FUNCTION_COUNT <= function || + _pins[index].function == function) return; _set_function(&_pins[index], (io_function_t)function); } uint8_t get_io_mode(int index) { - IF_INVALID_INDEX_RETURN 0; - return _pins[index].mode; + return IO_MAX_INDEX <= index ? 0 : _pins[index].mode; } void set_io_mode(int index, uint8_t mode) { - IF_INVALID_INDEX_RETURN; - if (LO_TRI < mode) return; + if (IO_MAX_INDEX <= index || LO_TRI < mode) return; - // Changing the mode may change the input state io_pin_t *pin = &_pins[index]; - bool wasActive = _is_input_active(pin); + bool wasActive = _is_active(pin); pin->mode = (io_mode_t)mode; - bool isActive = _is_input_active(pin); - if (wasActive != isActive) _state_set_active(pin->function, isActive); + bool isActive = _is_active(pin); + + // Changing the mode may change the pin state + if (wasActive != isActive) + switch (io_get_type(pin->function)) { + case IO_TYPE_OUTPUT: _set_output(pin, wasActive); break; + case IO_TYPE_INPUT: _state_set_active(pin->function, isActive); break; + default: break; + } } -uint8_t get_io_state(int pin) {return _is_input_active(&_pins[pin]);} +uint8_t get_io_state(int pin) {return _is_active(&_pins[pin]);} void set_input_debounce(uint16_t debounce) { @@ -494,26 +524,21 @@ void set_input_lockout(uint16_t lockout) { uint16_t get_input_lockout() {return _io.lockout;} - - uint8_t get_min_input(int axis) {return _get_state(MIN_INPUT(axis));} uint8_t get_max_input(int axis) {return _get_state(MAX_INPUT(axis));} -uint8_t get_estop_input() {return _get_state(INPUT_ESTOP);} -uint8_t get_probe_input() {return _get_state(INPUT_PROBE);} +uint8_t get_input(int index) {return _get_state(_input_to_function(index));} -bool get_output_active(int id) { - return _func_state[_output_to_function(id)].active; +uint8_t get_output_active(int index) { + return _func_state[_output_to_function(index)].active; } -void set_output_active(int id, bool active) { - io_function_t f = _output_to_function(id); - if (f != IO_DISABLED) _func_state[f].active = active; +void set_output_active(int index, uint8_t active) { + io_set_output(_output_to_function(index), active); } float get_analog_input(int port) { - return io_get_analog(io_get_port_function(false, port)); } diff --git a/src/avr/src/io.h b/src/avr/src/io.h index 4a731836..39a18f04 100644 --- a/src/avr/src/io.h +++ b/src/avr/src/io.h @@ -33,6 +33,8 @@ // Must be kept in synch with resources/config-template.json typedef enum { IO_DISABLED, + + // Mappable functions INPUT_MOTOR_0_MAX, INPUT_MOTOR_1_MAX, INPUT_MOTOR_2_MAX, INPUT_MOTOR_3_MAX, INPUT_MOTOR_0_MIN, INPUT_MOTOR_1_MIN, INPUT_MOTOR_2_MIN, INPUT_MOTOR_3_MIN, INPUT_0, INPUT_1, INPUT_2, INPUT_3, INPUT_ESTOP, INPUT_PROBE, @@ -54,7 +56,10 @@ typedef enum {LO_HI, HI_LO, TRI_LO, TRI_HI, LO_TRI, HI_TRI} io_mode_t; typedef enum { - IO_TYPE_DISABLED, IO_TYPE_INPUT, IO_TYPE_OUTPUT, IO_TYPE_ANALOG + IO_TYPE_DISABLED = 0, + IO_TYPE_INPUT = 1 << 0, + IO_TYPE_OUTPUT = 1 << 1, + IO_TYPE_ANALOG = 1 << 2, } io_type_t; diff --git a/src/avr/src/pins.h b/src/avr/src/pins.h index 43252e25..c52211c0 100644 --- a/src/avr/src/pins.h +++ b/src/avr/src/pins.h @@ -43,6 +43,7 @@ extern PORT_t *pin_ports[]; #define DIRSET_PIN(PIN) PIN_PORT(PIN)->DIRSET = PIN_BM(PIN) #define DIRCLR_PIN(PIN) PIN_PORT(PIN)->DIRCLR = PIN_BM(PIN) +#define DIR_PIN(PIN) (!!(PIN_PORT(PIN)->DIR & PIN_BM(PIN))) #define OUTCLR_PIN(PIN) PIN_PORT(PIN)->OUTCLR = PIN_BM(PIN) #define OUTSET_PIN(PIN) PIN_PORT(PIN)->OUTSET = PIN_BM(PIN) #define OUTTGL_PIN(PIN) PIN_PORT(PIN)->OUTTGL = PIN_BM(PIN) diff --git a/src/avr/src/usart.c b/src/avr/src/usart.c index d5345af6..19811dd7 100644 --- a/src/avr/src/usart.c +++ b/src/avr/src/usart.c @@ -51,6 +51,8 @@ #include "ringbuf.def" static bool _flush = false; +static uint16_t rx_max_fill = 0; +static uint16_t cts_thresh = SERIAL_CTS_THRESH; static void _set_dre_interrupt(bool enable) { @@ -61,7 +63,7 @@ static void _set_dre_interrupt(bool enable) { static void _set_rxc_interrupt(bool enable) { if (enable) { - if (SERIAL_CTS_THRESH <= rx_buf_space()) + if (cts_thresh <= rx_buf_space()) OUTCLR_PIN(SERIAL_CTS_PIN); // CTS Lo (enable) SERIAL_PORT.CTRLA |= USART_RXCINTLVL_HI_gc; @@ -84,9 +86,14 @@ ISR(SERIAL_DRE_vect) { // Data received interrupt vector ISR(SERIAL_RXC_vect) { if (rx_buf_full()) _set_rxc_interrupt(false); // Disable interrupt - else rx_buf_push(SERIAL_PORT.DATA); + else { + rx_buf_push(SERIAL_PORT.DATA); + + uint16_t fill = rx_buf_fill(); + if (rx_max_fill < fill) rx_max_fill = fill; + } - if (rx_buf_space() < SERIAL_CTS_THRESH) + if (rx_buf_space() < cts_thresh) OUTSET_PIN(SERIAL_CTS_PIN); // CTS Hi (disable) } @@ -279,6 +286,12 @@ void usart_flush() { void usart_rx_flush() {rx_buf_init();} int16_t usart_rx_space() {return rx_buf_space();} -int16_t usart_rx_fill() {return rx_buf_fill();} +int16_t usart_rx_fill() {return rx_buf_fill();} int16_t usart_tx_space() {return tx_buf_space();} -int16_t usart_tx_fill() {return tx_buf_fill();} +int16_t usart_tx_fill() {return tx_buf_fill();} + + +// Variable callbacks +uint16_t get_rx_max_fill() {return rx_max_fill;} +void set_cts_thresh(uint16_t x) {cts_thresh = x;} +uint16_t get_cts_thresh() {return cts_thresh;} diff --git a/src/avr/src/vars.def b/src/avr/src/vars.def index a97d33f8..f825e5b3 100644 --- a/src/avr/src/vars.def +++ b/src/avr/src/vars.def @@ -25,11 +25,12 @@ \******************************************************************************/ -#define AXES_LABEL "xyzabc" -#define MOTORS_LABEL "0123" -#define OUTS_LABEL "0123MFfdet" +#define AXES_LABEL "xyzabc" +#define MOTORS_LABEL "0123" +#define OUTS_LABEL "0123MFfedt" +#define INS_LABEL "0123ep" #define ANALOGS_LABEL "0123" -#define VFDREG_LABEL "0123456789abcdefghijklmnopqrstuv" +#define VFDREG_LABEL "0123456789abcdefghijklmnopqrstuv" #define IO_PINS_LABEL "abcdefghijklmnopq" // VAR(name, code, type, index, settable, report) @@ -78,9 +79,8 @@ VAR(input_debounce, sd, u16, 0, 1, 1) // Input debounce time in ms VAR(input_lockout, sc, u16, 0, 1, 1) // Input lockout time in ms VAR(min_input, lw, u8, MOTORS, 0, 1) // Minimum switch input state VAR(max_input, xw, u8, MOTORS, 0, 1) // Maximum switch input state -VAR(estop_input, ew, u8, 0, 0, 1) // Estop input state -VAR(probe_input, pw, u8, 0, 0, 1) // Probe input state -VAR(output_active, oa, b8, OUTS, 1, 1) // Digital output active +VAR(input, w, u8, INS, 0, 1) // Digital input state +VAR(output_active, oa, u8, OUTS, 1, 1) // Digital output active VAR(analog_input, ai, f32, ANALOGS, 0, 0) // Analog input state // Spindle @@ -143,3 +143,5 @@ VAR(state_count, xc, u16, 0, 0, 1) // Machine state change count VAR(hold_reason, pr, pstr, 0, 0, 1) // Machine pause reason VAR(underrun, un, u32, 0, 0, 1) // Stepper buffer underrun count VAR(dwell_time, dt, f32, 0, 0, 1) // Dwell timer +VAR(rx_max_fill, rf, u16, 0, 0, 1) // UART receive buffer max fill +VAR(cts_thresh, ct, u16, 0, 1, 1) // UART receive buffer max fill diff --git a/src/avr/src/vfd_spindle.c b/src/avr/src/vfd_spindle.c index 4976e1fc..5cd392c0 100644 --- a/src/avr/src/vfd_spindle.c +++ b/src/avr/src/vfd_spindle.c @@ -87,69 +87,75 @@ const vfd_reg_t ac_tech_regs[] PROGMEM = { {REG_REV_WRITE, 1, 64}, // Reverse {REG_REV_WRITE, 1, 8}, // Start drive {REG_FREQ_ACTECH_READ, 24, 0}, // Actual freq + {REG_DISCONNECT_WRITE, 1, 4}, // Stop on disconnect {REG_DISCONNECT_WRITE, 1, 2}, // Lock controls and parameters {REG_DISABLED}, }; const vfd_reg_t nowforever_regs[] PROGMEM = { - {REG_MAX_FREQ_READ, 7, 0}, // Max frequency - {REG_FREQ_SET, 2305, 0}, // Frequency - {REG_STOP_WRITE, 2304, 0}, // Stop drive - {REG_FWD_WRITE, 2304, 1}, // Forward - {REG_REV_WRITE, 2304, 3}, // Reverse - {REG_FREQ_READ, 1282, 0}, // Output freq - {REG_STATUS_READ, 768, 0}, // Status + {REG_MAX_FREQ_READ, 0x007, 0}, // Max frequency + {REG_FREQ_SET, 0x901, 0}, // Frequency + {REG_STOP_WRITE, 0x900, 0}, // Stop drive + {REG_FWD_WRITE, 0x900, 1}, // Forward + {REG_REV_WRITE, 0x900, 3}, // Reverse + {REG_FREQ_READ, 0x502, 0}, // Output freq + {REG_STATUS_READ, 0x300, 0}, // Status + {REG_DISCONNECT_WRITE, 0x900, 0}, // Stop on disconnect {REG_DISABLED}, }; const vfd_reg_t delta_vfd015m21a_regs[] PROGMEM = { - {REG_CONNECT_WRITE, 0x2002, 2}, // Reset fault - {REG_MAX_FREQ_READ, 3, 0}, // Max frequency - {REG_FREQ_SET, 0x2001, 0}, // Frequency - {REG_STOP_WRITE, 0x2000, 1}, // Stop drive - {REG_FWD_WRITE, 0x2000, 18}, // Forward - {REG_REV_WRITE, 0x2000, 34}, // Reverse - {REG_FREQ_READ, 0x2103, 0}, // Output freq - {REG_STATUS_READ, 0x2100, 0}, // Status + {REG_CONNECT_WRITE, 0x2002, 2}, // Reset fault + {REG_MAX_FREQ_READ, 3, 0}, // Max frequency + {REG_FREQ_SET, 0x2001, 0}, // Frequency + {REG_STOP_WRITE, 0x2000, 1}, // Stop drive + {REG_FWD_WRITE, 0x2000, 18}, // Forward + {REG_REV_WRITE, 0x2000, 34}, // Reverse + {REG_FREQ_READ, 0x2103, 0}, // Output freq + {REG_STATUS_READ, 0x2100, 0}, // Status + {REG_DISCONNECT_WRITE, 0x2000, 1}, // Stop on disconnect {REG_DISABLED}, }; const vfd_reg_t yl600_regs[] PROGMEM = { - {REG_CONNECT_WRITE, 0x2000, 128}, // Reset all errors - {REG_MAX_FREQ_READ, 0x0004, 0}, // Max frequency - {REG_FREQ_SET, 0x2001, 0}, // Frequency - {REG_STOP_WRITE, 0x2000, 1}, // Stop drive - {REG_FWD_WRITE, 0x2000, 18}, // Forward - {REG_REV_WRITE, 0x2000, 34}, // Reverse - {REG_FREQ_READ, 0x200b, 0}, // Output freq - {REG_STATUS_READ, 0x2008, 0}, // Status + {REG_CONNECT_WRITE, 0x2000, 128}, // Reset all errors + {REG_MAX_FREQ_READ, 0x0004, 0}, // Max frequency + {REG_FREQ_SET, 0x2001, 0}, // Frequency + {REG_STOP_WRITE, 0x2000, 1}, // Stop drive + {REG_FWD_WRITE, 0x2000, 18}, // Forward + {REG_REV_WRITE, 0x2000, 34}, // Reverse + {REG_FREQ_READ, 0x200b, 0}, // Output freq + {REG_STATUS_READ, 0x2008, 0}, // Status + {REG_DISCONNECT_WRITE, 0x2000, 1}, // Stop on disconnect {REG_DISABLED}, }; const vfd_reg_t fr_d700_regs[] PROGMEM = { - {REG_MAX_FREQ_READ, 1000, 0}, // Max frequency - {REG_FREQ_SET, 13, 0}, // Frequency - {REG_STOP_WRITE, 8, 1}, // Stop drive - {REG_FWD_WRITE, 8, 2}, // Forward - {REG_REV_WRITE, 8, 4}, // Reverse - {REG_FREQ_READ, 200, 0}, // Output freq + {REG_MAX_FREQ_READ, 1000, 0}, // Max frequency + {REG_FREQ_SET, 13, 0}, // Frequency + {REG_STOP_WRITE, 8, 1}, // Stop drive + {REG_FWD_WRITE, 8, 2}, // Forward + {REG_REV_WRITE, 8, 4}, // Reverse + {REG_FREQ_READ, 200, 0}, // Output freq + {REG_DISCONNECT_WRITE, 8, 1}, // Stop on disconnect {REG_DISABLED}, }; const vfd_reg_t sunfar_e300_regs[] PROGMEM = { - {REG_CONNECT_WRITE, 0x1001, 32}, // Reset all errors - {REG_MAX_FREQ_READ, 0xf004, 0}, // Max frequency F0.4 - {REG_FREQ_SET, 0x1002, 0}, // Frequency - {REG_STOP_WRITE, 0x1001, 3}, // Stop drive - {REG_FWD_WRITE, 0x1001, 1}, // Forward - {REG_REV_WRITE, 0x1001, 2}, // Reverse - {REG_FREQ_READ, 0xd000, 0}, // Output freq d.0 - {REG_STATUS_READ, 0x2000, 0}, // Status + {REG_CONNECT_WRITE, 0x1001, 32}, // Reset all errors + {REG_MAX_FREQ_READ, 0xf004, 0}, // Max frequency F0.4 + {REG_FREQ_SET, 0x1002, 0}, // Frequency + {REG_STOP_WRITE, 0x1001, 3}, // Stop drive + {REG_FWD_WRITE, 0x1001, 1}, // Forward + {REG_REV_WRITE, 0x1001, 2}, // Reverse + {REG_FREQ_READ, 0xd000, 0}, // Output freq d.0 + {REG_STATUS_READ, 0x2000, 0}, // Status + {REG_DISCONNECT_WRITE, 0x1001, 3}, // Stop on disconnect {REG_DISABLED}, }; @@ -170,35 +176,38 @@ const vfd_reg_t omron_mx2_regs[] PROGMEM = { const vfd_reg_t v70_regs[] PROGMEM = { - {REG_MAX_FREQ_READ, 0x0005, 0}, // Maximum operating frequency - {REG_FREQ_SET, 0x0201, 0}, // Set frequency in 0.1Hz - {REG_STOP_WRITE, 0x0200, 0}, // Stop - {REG_FWD_WRITE, 0x0200, 1}, // Run forward - {REG_REV_WRITE, 0x0200, 5}, // Run reverse - {REG_FREQ_READ, 0x0220, 0}, // Read operating frequency - {REG_STATUS_READ, 0x0210, 0}, // Read status + {REG_MAX_FREQ_READ, 0x0005, 0}, // Maximum operating frequency + {REG_FREQ_SET, 0x0201, 0}, // Set frequency in 0.1Hz + {REG_STOP_WRITE, 0x0200, 0}, // Stop + {REG_FWD_WRITE, 0x0200, 1}, // Run forward + {REG_REV_WRITE, 0x0200, 5}, // Run reverse + {REG_FREQ_READ, 0x0220, 0}, // Read operating frequency + {REG_STATUS_READ, 0x0210, 0}, // Read status + {REG_DISCONNECT_WRITE, 0x0200, 0}, // Stop on disconnect {REG_DISABLED}, }; const vfd_reg_t dmm_dyn4_regs[] PROGMEM = { - {REG_MAX_FREQ_FIXED, 0x00, 6000}, // Maximum operating frequency - {REG_FREQ_SIGN_SET, 0x0e, 0}, // Set frequency in 0.1Hz - {REG_STOP_WRITE, 0x0e, 0}, // Stop - {REG_FREQ_SIGN_READ, 0x14, 0}, // Read operating frequency - {REG_STATUS_READ, 0x02, 0}, // Read status + {REG_MAX_FREQ_FIXED, 0x00, 6000}, // Maximum operating frequency + {REG_FREQ_SIGN_SET, 0x0e, 0}, // Set frequency in 0.1Hz + {REG_STOP_WRITE, 0x0e, 0}, // Stop + {REG_FREQ_SIGN_READ, 0x14, 0}, // Read operating frequency + {REG_STATUS_READ, 0x02, 0}, // Read status + {REG_DISCONNECT_WRITE, 0x0e, 0}, // Stop on disconnect {REG_DISABLED}, }; const vfd_reg_t galt_g200_regs[] PROGMEM = { - {REG_MAX_FREQ_READ, 0x0003, 0}, // Read maximum operating frequency in 0.01Hz - {REG_FREQ_SET, 0x2001, 0}, // Set frequency in 0.01Hz - {REG_FREQ_READ, 0x3000, 0}, // Read frequency with 0.01Hz - {REG_FWD_WRITE, 0x2000, 1}, // Run forward - {REG_REV_WRITE, 0x2000, 2}, // Run reverse - {REG_STOP_WRITE, 0x2000, 5}, // Stop - {REG_STATUS_READ, 0x2100, 0}, // Read status + {REG_MAX_FREQ_READ, 0x0003, 0}, // Read max operating frequency in 0.01Hz + {REG_FREQ_SET, 0x2001, 0}, // Set frequency in 0.01Hz + {REG_FREQ_READ, 0x3000, 0}, // Read frequency with 0.01Hz + {REG_FWD_WRITE, 0x2000, 1}, // Run forward + {REG_REV_WRITE, 0x2000, 2}, // Run reverse + {REG_STOP_WRITE, 0x2000, 5}, // Stop + {REG_STATUS_READ, 0x2100, 0}, // Read status + {REG_DISCONNECT_WRITE, 0x2000, 5}, // Stop on disconnect {REG_DISABLED}, }; diff --git a/src/js/app.js b/src/js/app.js index 37ea5904..fadc77bb 100644 --- a/src/js/app.js +++ b/src/js/app.js @@ -136,9 +136,13 @@ module.exports = new Vue({ events: { route: function (path) { + let oldView = this.currentView; + if (typeof this.$options.components['view-' + path[0]] == 'undefined') return location.hash = 'control'; else this.currentView = path[0]; + + if (oldView != this.currentView) $('#main').scrollTop(0) }, diff --git a/src/js/breakout.js b/src/js/breakout.js new file mode 100644 index 00000000..274c9ecd --- /dev/null +++ b/src/js/breakout.js @@ -0,0 +1,110 @@ +/******************************************************************************\ + + This file is part of the Buildbotics firmware. + + Copyright (c) 2015 - 2021, Buildbotics LLC, All rights reserved. + + This Source describes Open Hardware and is licensed under the + CERN-OHL-S v2. + + You may redistribute and modify this Source and make products + using it under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). + This Source is distributed WITHOUT ANY EXPRESS OR IMPLIED + WARRANTY, INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS + FOR A PARTICULAR PURPOSE. Please see the CERN-OHL-S v2 for applicable + conditions. + + Source location: https://github.com/buildbotics + + As per CERN-OHL-S v2 section 4, should You produce hardware based on + these sources, You must maintain the Source Location clearly visible on + the external case of the CNC Controller or other product you make using + this Source. + + For more information, email info@buildbotics.com + +\******************************************************************************/ + +'use strict' + + +function make_tmpl(name, data) { + return { + props: ['state', 'template'], + template: '#' + name + '-template', + data() {return data || {}} + } +} + + +module.exports = { + template: '#breakout-template', + props: ['name', 'state', 'template'], + + data() {return {active_pin: undefined}}, + + + components: { + 'db15-breakout': {'template': '#db15-breakout-template'}, + 'db25-breakout': {'template': '#db25-breakout-template'}, + 'db15-pin-1': {'template': '#db15-fault-template'}, + 'db15-pin-2': make_tmpl('db15-step', {ch: 0}), + 'db15-pin-3': make_tmpl('db15-step', {ch: 1}), + 'db15-pin-4': make_tmpl('db15-step', {ch: 2}), + 'db15-pin-5': make_tmpl('db15-step', {ch: 3}), + 'db15-pin-6': make_tmpl('breakout-5v'), + 'db15-pin-7': make_tmpl('breakout-reserved'), + 'db15-pin-8': make_tmpl('breakout-reserved'), + 'db15-pin-9': make_tmpl('db15-enable'), + 'db15-pin-10': make_tmpl('db15-dir', {ch: 0}), + 'db15-pin-11': make_tmpl('db15-dir', {ch: 1}), + 'db15-pin-12': make_tmpl('db15-dir', {ch: 2}), + 'db15-pin-13': make_tmpl('db15-dir', {ch: 3}), + 'db15-pin-14': make_tmpl('breakout-ground'), + 'db15-pin-15': make_tmpl('breakout-ground'), + 'db15-pin-gnd': make_tmpl('breakout-ground'), + 'db25-pin-1': make_tmpl('db25-io', {pin: 1}), + 'db25-pin-2': make_tmpl('db25-io', {pin: 2}), + 'db25-pin-3': make_tmpl('db25-io', {pin: 3}), + 'db25-pin-4': make_tmpl('db25-io', {pin: 4}), + 'db25-pin-5': make_tmpl('db25-io', {pin: 5}), + 'db25-pin-6': make_tmpl('db25-0to10'), + 'db25-pin-7': make_tmpl('breakout-ground'), + 'db25-pin-8': make_tmpl('db25-io', {pin: 8}), + 'db25-pin-9': make_tmpl('db25-io', {pin: 9}), + 'db25-pin-10': make_tmpl('db25-io', {pin: 10}), + 'db25-pin-11': make_tmpl('db25-io', {pin: 11}), + 'db25-pin-12': make_tmpl('db25-io', {pin: 12}), + 'db25-pin-13': make_tmpl('db25-rs485', {ch: 'A'}), + 'db25-pin-14': make_tmpl('db25-rs485', {ch: 'B'}), + 'db25-pin-15': make_tmpl('db25-io', {pin: 15}), + 'db25-pin-16': make_tmpl('db25-io', {pin: 16}), + 'db25-pin-17': make_tmpl('db25-pwm'), + 'db25-pin-18': make_tmpl('db25-io', {pin: 18}), + 'db25-pin-19': make_tmpl('breakout-ground'), + 'db25-pin-20': make_tmpl('breakout-5v'), + 'db25-pin-21': make_tmpl('db25-io', {pin: 21}), + 'db25-pin-22': make_tmpl('db25-io', {pin: 22}), + 'db25-pin-23': make_tmpl('db25-io', {pin: 23}), + 'db25-pin-24': make_tmpl('db25-io', {pin: 24}), + 'db25-pin-25': make_tmpl('breakout-ground'), + 'db25-pin-gnd': make_tmpl('breakout-ground') + }, + + + ready() { + $(this.$refs.breakout.$el).find('.pin').mouseover((e) => { + let classes = e.currentTarget.classList + + for (let i = 0; i < classes.length; i++) + if (classes[i].startsWith('pin-')) { + this.active_pin = classes[i].substr(4) + + if (this.active != undefined) + this.active.classList.remove('selected-pin') + this.active = e.currentTarget + classes.add('selected-pin') + } + }) + } +} diff --git a/src/js/indicators.js b/src/js/indicators.js index 36d64311..82b0f8a3 100644 --- a/src/js/indicators.js +++ b/src/js/indicators.js @@ -27,88 +27,8 @@ 'use strict' -var modbus = require('./modbus.js'); - module.exports = { template: '#indicators-template', - props: ['state'], - - - computed: { - watts: function () { - var I = parseFloat(this.state.motor) - var V = parseFloat(this.state.vout) - return I * V - }, - - - modbus_status: function () {return modbus.status_to_string(this.state.mx)}, - - - sense_error: function () { - var error = ''; - - if (this.state.motor_voltage_sense_error) error += 'Motor voltage\n'; - if (this.state.motor_current_sense_error) error += 'Motor current\n'; - if (this.state.load1_sense_error) error += 'Load 1\n'; - if (this.state.load2_sense_error) error += 'Load 2\n'; - if (this.state.vdd_current_sense_error) error += 'Vdd current\n'; - - return error; - } - }, - - - methods: { - is_motor_enabled: function (motor) { - return typeof this.state[motor + 'me'] != 'undefined' && - this.state[motor + 'me']; - }, - - - get_min_pin: function (motor) { - switch (motor) { - case 0: return 3; - case 1: return 5; - case 2: return 9; - case 3: return 11; - } - }, - - - get_max_pin: function (motor) { - switch (motor) { - case 0: return 4; - case 1: return 8; - case 2: return 10; - case 3: return 12; - } - }, - - - motor_fault_class: function (motor, bit) { - if (typeof motor == 'undefined') { - var status = this.state['fa']; - if (typeof status == 'undefined') return 'fa-question'; - return 'fa-thumbs-' + (status ? 'down error' : 'up success') - } - - var flags = this.state[motor + 'df']; - if (typeof flags == 'undefined') return 'fa-question'; - return (flags & (1 << bit)) ? 'fa-thumbs-down error' : - 'fa-thumbs-up success'; - }, - - - motor_reset: function (motor) { - if (typeof motor == 'undefined') { - var cmd = ''; - for (var i = 0; i < 4; i++) - cmd += '\\$' + i + 'df=0\n'; - this.$dispatch('send', cmd); - - } else this.$dispatch('send', '\\$' + motor + 'df=0'); - } - } + props: ['state', 'template'] } diff --git a/src/js/io-functions.js b/src/js/io-functions.js new file mode 100644 index 00000000..34a35155 --- /dev/null +++ b/src/js/io-functions.js @@ -0,0 +1,89 @@ +/******************************************************************************\ + + This file is part of the Buildbotics firmware. + + Copyright (c) 2015 - 2021, Buildbotics LLC, All rights reserved. + + This Source describes Open Hardware and is licensed under the + CERN-OHL-S v2. + + You may redistribute and modify this Source and make products + using it under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). + This Source is distributed WITHOUT ANY EXPRESS OR IMPLIED + WARRANTY, INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS + FOR A PARTICULAR PURPOSE. Please see the CERN-OHL-S v2 for applicable + conditions. + + Source location: https://github.com/buildbotics + + As per CERN-OHL-S v2 section 4, should You produce hardware based on + these sources, You must maintain the Source Location clearly visible on + the external case of the CNC Controller or other product you make using + this Source. + + For more information, email info@buildbotics.com + +\******************************************************************************/ + +'use strict' + + +module.exports = { + template: "#io-functions-template", + props: ['template', 'state'], + + + components: { + 'io-functions-row': { + template: "#io-functions-row-template", + props: ['func'], + replace: true + } + }, + + + computed: { + columns: () => ['function', 'state', 'pins', '', + 'function', 'state', 'pins'], + + + rows: function () {return Math.ceil(this.functions.length / 2.0)}, + + + functions: function () { + let l = [] + let io_map = this.template['io-map'] + let pins = io_map.pins + let tmpl = io_map.template.function + let funcs = tmpl.values + let codes = tmpl.codes + let title = '' + + for (let i = 1; i < funcs.length; i++) { + let p = [] + + for (let j = 0; j < pins.length; j++) { + let code = String.fromCharCode(97 + j) + 'io' + if (i == this.state[code]) p.push(pins[j].id) + } + + let state = this.state[codes[i]] + let type = funcs[i].split('-')[0] + if (!p.length) { + type = 'disabled' + title = 'Function not mapped to any pins.' + } + + l.push({ + name: funcs[i], + state, + pins: p, + type, + title + }) + } + + return l + } + } +} diff --git a/src/js/io-indicator.js b/src/js/io-indicator.js index a115f360..7c1bffa9 100644 --- a/src/js/io-indicator.js +++ b/src/js/io-indicator.js @@ -30,148 +30,53 @@ module.exports = { template: "#io-indicator-template", - props: ['name', 'state'], + props: { + state: {type: Number}, + mode: String, + type: String + }, computed: { klass: function () { - if (this.name == 'min-switch-0') return this.get_motor_min_class(0); - if (this.name == 'min-switch-1') return this.get_motor_min_class(1); - if (this.name == 'min-switch-2') return this.get_motor_min_class(2); - if (this.name == 'min-switch-3') return this.get_motor_min_class(3); - if (this.name == 'max-switch-0') return this.get_motor_max_class(0); - if (this.name == 'max-switch-1') return this.get_motor_max_class(1); - if (this.name == 'max-switch-2') return this.get_motor_max_class(2); - if (this.name == 'max-switch-3') return this.get_motor_max_class(3); - if (this.name == 'estop') return this.get_input_class('ew', 'et'); - if (this.name == 'probe') return this.get_input_class('pw', 'pt'); - if (this.name == 'load-1') return this.get_output_class('1'); - if (this.name == 'load-2') return this.get_output_class('2'); - if (this.name == 'fault') return this.get_output_class('f'); - if (this.name == 'tool-enable-mode') return this.get_output_class('e'); - if (this.name == 'tool-direction-mode') return this.get_output_class('d'); - }, - - - tooltip: function () { - if (this.name == 'min-switch-0') return this.get_motor_min_tooltip(0); - if (this.name == 'min-switch-1') return this.get_motor_min_tooltip(1); - if (this.name == 'min-switch-2') return this.get_motor_min_tooltip(2); - if (this.name == 'min-switch-3') return this.get_motor_min_tooltip(3); - if (this.name == 'max-switch-0') return this.get_motor_max_tooltip(0); - if (this.name == 'max-switch-1') return this.get_motor_max_tooltip(1); - if (this.name == 'max-switch-2') return this.get_motor_max_tooltip(2); - if (this.name == 'max-switch-3') return this.get_motor_max_tooltip(3); - if (this.name == 'estop') return this.get_input_tooltip('ew', 'et'); - if (this.name == 'probe') return this.get_input_tooltip('pw', 'pt'); - if (this.name == 'load-1') return this.get_output_tooltip('1'); - if (this.name == 'load-2') return this.get_output_tooltip('2'); - if (this.name == 'fault') return this.get_output_tooltip('f'); - if (this.name == 'tool-direction-mode') - return this.get_output_tooltip('d'); - if (this.name == 'tool-enable-mode') - return this.get_output_tooltip('e'); - } - }, - - - methods: { - get_io_state_class: function (active, state) { - if (typeof active == 'undefined' || typeof state == 'undefined') - return 'fa-exclamation-triangle warn'; - - if (state == 2) return 'fa-circle-o'; - - return (state ? 'fa-plus-circle' : 'fa-minus-circle') + ' ' + - (active ? 'active' : 'inactive'); - }, - - - get_input_active: function (stateCode, typeCode) { - var type = this.state[typeCode]; - var state = this.state[stateCode]; - - if (type == 1) return !state; // Normally open - else if (type == 2) return state; // Normally closed - - return false - }, - - - get_input_class: function (stateCode, typeCode) { - return this.get_io_state_class(this.get_input_active(stateCode, typeCode), - this.state[stateCode]); - }, - - - get_output_class: function (output) { - return this.get_io_state_class(this.state[output + 'oa'], - this.state[output + 'os']); - }, - + let klass = '' - get_motor_min_class: function (motor) { - return this.get_input_class(motor + 'lw', motor + 'ls'); - }, + if (this.type == 'disabled') return 'fa-ban' + if (this.type == 'analog') return 'fa-circle-o' + if (this.state == 0) klass = 'inactive' + if (this.state == 1) klass = 'active' - get_motor_max_class: function (motor) { - return this.get_input_class(motor + 'xw', motor + 'xs'); - }, + if (this.mode) { + let parts = this.mode.split('-') + let state = 'tri' + if (this.state == 0) state = parts[0] + if (this.state == 1) state = parts[1] - get_tooltip: function (mode, active, state) { - if (typeof mode == 'undefined' || typeof active == 'undefined' || - typeof state == 'undefined') return 'Invalid'; + if (state == 'lo') return klass + ' fa-minus-circle' + if (state == 'hi') return klass + ' fa-plus-circle' + if (state == 'tri') return klass + ' fa-circle-o' - if (state == 0) state = 'Lo/Gnd'; - else if (state == 1) state = 'Hi/+3.3v'; - else if (state == 2) state = 'Tristated'; - else return 'Invalid'; + } else { + if (this.state == 0) return klass + ' fa-circle' + if (this.state == 1) return klass + ' fa-circle' + if (this.state == 0xff) return klass + ' fa-ban' + } - return 'Mode: ' + mode + '\nActive: ' + (active ? 'True' : 'False') + - '\nLevel: ' + state; + return 'fa-exclamation-triangle warn' }, - get_input_tooltip: function (stateCode, typeCode) { - var type = this.state[typeCode]; - if (type == 0) return 'Disabled'; - else if (type == 1) type = 'Normally open'; - else if (type == 2) type = 'Normally closed'; - - var active = this.get_input_active(stateCode, typeCode); - var state = this.state[stateCode]; - - return this.get_tooltip(type, active, state); - }, - - - get_output_tooltip: function (output) { - var mode = this.state[output + 'om']; - if (mode == 0) return 'Disabled'; - else if (mode == 1) mode = 'Lo/Hi'; - else if (mode == 2) mode = 'Hi/Lo'; - else if (mode == 3) mode = 'Tri/Lo'; - else if (mode == 4) mode = 'Tri/Hi'; - else if (mode == 5) mode = 'Lo/Tri'; - else if (mode == 6) mode = 'Hi/Tri'; - else mode = undefined; - - var active = this.state[output + 'oa']; - var state = this.state[output + 'os']; - - return this.get_tooltip(mode, active, state); - }, - - - get_motor_min_tooltip: function (motor) { - return this.get_input_tooltip(motor + 'lw', motor + 'ls'); - }, + tooltip: function () { + let parts = [] + if (this.type) parts.push('Type: ' + this.type) + if (this.mode) parts.push('Mode: ' + this.mode) + if (this.type != 'analog') + parts.push('Active: ' + (this.state == 1 ? 'True' : 'False')) - get_motor_max_tooltip: function (motor) { - return this.get_input_tooltip(motor + 'xw', motor + 'xs'); + return parts.join('\n') } } } diff --git a/src/js/io-pins.js b/src/js/io-pins.js new file mode 100644 index 00000000..17abe3fa --- /dev/null +++ b/src/js/io-pins.js @@ -0,0 +1,72 @@ +/******************************************************************************\ + + This file is part of the Buildbotics firmware. + + Copyright (c) 2015 - 2021, Buildbotics LLC, All rights reserved. + + This Source describes Open Hardware and is licensed under the + CERN-OHL-S v2. + + You may redistribute and modify this Source and make products + using it under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). + This Source is distributed WITHOUT ANY EXPRESS OR IMPLIED + WARRANTY, INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS + FOR A PARTICULAR PURPOSE. Please see the CERN-OHL-S v2 for applicable + conditions. + + Source location: https://github.com/buildbotics + + As per CERN-OHL-S v2 section 4, should You produce hardware based on + these sources, You must maintain the Source Location clearly visible on + the external case of the CNC Controller or other product you make using + this Source. + + For more information, email info@buildbotics.com + +\******************************************************************************/ + +'use strict' + + +module.exports = { + template: "#io-pins-template", + props: ['template', 'state'], + + + components: { + 'io-pins-row': { + template: "#io-pins-row-template", + props: ['pin'], + replace: true + } + }, + + + computed: { + columns: () => ['pin', 'state', 'mode', 'function', '', + 'pin', 'state', 'mode', 'function'], + + + rows: function () {return Math.ceil(this.io_pins.length / 2.0)}, + + + io_pins: function () { + let l = [] + let io_map = this.template['io-map'] + let pins = io_map.pins + let modes = io_map.template.mode.values + let functions = io_map.template.function.values + + for (let i = 0; i < pins.length; i++) { + let c = String.fromCharCode(97 + i) + let state = this.state[c + 'is'] + let mode = modes[this.state[c + 'im']] + let func = functions[this.state[c + 'io']] + + l.push({id: pins[i].id, state, mode, func}) + } + + return l + } + } +} diff --git a/src/js/main.js b/src/js/main.js index 43b405a8..49c2d5d5 100644 --- a/src/js/main.js +++ b/src/js/main.js @@ -2,7 +2,7 @@ This file is part of the Buildbotics firmware. - Copyright (c) 2015 - 2021, Buildbotics LLC, All rights reserved. + Copyright (c) 2015 - 2022, Buildbotics LLC, All rights reserved. This Source describes Open Hardware and is licensed under the CERN-OHL-S v2. @@ -25,65 +25,71 @@ \******************************************************************************/ -'use strict'; +'use strict' -var cookie = require('./cookie'); -var util = require('./util'); -var api = require('./api'); +var cookie = require('./cookie') +var util = require('./util') +var api = require('./api') function menu_ui() { - var layout = document.getElementById('layout'); - var menuLink = document.getElementById('menuLink'); + var layout = document.getElementById('layout') + var menuLink = document.getElementById('menuLink') var collapse = function () { - layout.classList.remove('active'); - window.removeEventListener('click', collapse); + layout.classList.remove('active') + window.removeEventListener('click', collapse) } menuLink.onclick = function (e) { - e.preventDefault(); - e.stopPropagation(); - layout.classList.toggle('active'); - window.addEventListener('click', collapse); + e.preventDefault() + e.stopPropagation() + layout.classList.toggle('active') + window.addEventListener('click', collapse) } } $(function() { - menu_ui(); + menu_ui() if (typeof cookie.get('client-id') == 'undefined') - cookie.set('client-id', util.uuid()); + cookie.set('client-id', util.uuid()) // Vue debugging - Vue.config.debug = true; + Vue.config.debug = true // Init global modules - require('./cm-gcode'); - require('./keyboard'); + require('./cm-gcode') + require('./keyboard') // Register global components - Vue.component('templated-input', require('./templated-input')); - Vue.component('message', require('./message')); - Vue.component('loading-message', require('./loading-message')); - Vue.component('dialog', require('./dialog')); - Vue.component('indicators', require('./indicators')); - Vue.component('io-indicator', require('./io-indicator')); - Vue.component('console', require('./console')); - Vue.component('unit-value', require('./unit-value')); - Vue.component('files', require('./files')); - Vue.component('file-dialog', require('./file-dialog')); - Vue.component('upload-dialog', require('./upload-dialog')); - Vue.component('nav-menu', require('./nav-menu')); - Vue.component('nav-item', require('./nav-item')); - Vue.component('video', require('./video')); - Vue.component('color-picker', require('./color-picker')); - Vue.component('dragbar', require('./dragbar')); - - require('./filters')(); + Vue.component('templated-input', require('./templated-input')) + Vue.component('templated-select', require('./templated-select')) + Vue.component('message', require('./message')) + Vue.component('loading-message', require('./loading-message')) + Vue.component('dialog', require('./dialog')) + Vue.component('power', require('./power')) + Vue.component('indicators', require('./indicators')) + Vue.component('io-functions', require('./io-functions')) + Vue.component('io-pins', require('./io-pins')) + Vue.component('io-indicator', require('./io-indicator')) + Vue.component('breakout', require('./breakout')) + Vue.component('console', require('./console')) + Vue.component('unit-value', require('./unit-value')) + Vue.component('files', require('./files')) + Vue.component('file-dialog', require('./file-dialog')) + Vue.component('upload-dialog', require('./upload-dialog')) + Vue.component('nav-menu', require('./nav-menu')) + Vue.component('nav-item', require('./nav-item')) + Vue.component('video', require('./video')) + Vue.component('color-picker', require('./color-picker')) + Vue.component('dragbar', require('./dragbar')) + Vue.component('mapped-io', require('./mapped-io')) + + require('./filters')() // Vue app - require('./app'); -}); + require('./app') +}) diff --git a/src/js/mapped-io.js b/src/js/mapped-io.js new file mode 100644 index 00000000..794b7dd1 --- /dev/null +++ b/src/js/mapped-io.js @@ -0,0 +1,70 @@ +/******************************************************************************\ + + This file is part of the Buildbotics firmware. + + Copyright (c) 2015 - 2022, Buildbotics LLC, All rights reserved. + + This Source describes Open Hardware and is licensed under the + CERN-OHL-S v2. + + You may redistribute and modify this Source and make products + using it under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). + This Source is distributed WITHOUT ANY EXPRESS OR IMPLIED + WARRANTY, INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS + FOR A PARTICULAR PURPOSE. Please see the CERN-OHL-S v2 for applicable + conditions. + + Source location: https://github.com/buildbotics + + As per CERN-OHL-S v2 section 4, should You produce hardware based on + these sources, You must maintain the Source Location clearly visible on + the external case of the CNC Controller or other product you make using + this Source. + + For more information, email info@buildbotics.com + +\******************************************************************************/ + +'use strict' + + +module.exports = { + template: '#mapped-io-template', + props: ['pin', 'state', 'template'], + + + computed: { + index() { + let io_map = this.template['io-map'] + let code = '' + + for (let i = 0; i < io_map.pins.length; i++) { + let pin = io_map.pins[i] + if (pin.id == this.pin) return i + } + + return undefined + }, + + + code() {return this.template['io-map'].index[this.index]}, + type() {return this.template['io-map'].pins[this.index].type}, + + + func() { + let funcID = this.state[this.code + 'io'] + return this.template['io-map'].template.function.values[funcID] + }, + + + mode() { + let modeID = this.state[this.code + 'im'] + return this.template['io-map'].template.mode.values[modeID] + } + }, + + + methods: { + capitalize(s) {return s.charAt(0).toUpperCase() + s.slice(1)} + } +} diff --git a/src/js/power.js b/src/js/power.js new file mode 100644 index 00000000..8c993388 --- /dev/null +++ b/src/js/power.js @@ -0,0 +1,82 @@ +/******************************************************************************\ + + This file is part of the Buildbotics firmware. + + Copyright (c) 2015 - 2021, Buildbotics LLC, All rights reserved. + + This Source describes Open Hardware and is licensed under the + CERN-OHL-S v2. + + You may redistribute and modify this Source and make products + using it under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). + This Source is distributed WITHOUT ANY EXPRESS OR IMPLIED + WARRANTY, INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS + FOR A PARTICULAR PURPOSE. Please see the CERN-OHL-S v2 for applicable + conditions. + + Source location: https://github.com/buildbotics + + As per CERN-OHL-S v2 section 4, should You produce hardware based on + these sources, You must maintain the Source Location clearly visible on + the external case of the CNC Controller or other product you make using + this Source. + + For more information, email info@buildbotics.com + +\******************************************************************************/ + +'use strict' + + +module.exports = { + template: '#power-template', + props: ['state', 'template'], + + computed: { + watts: function () { + var I = parseFloat(this.state.motor) + var V = parseFloat(this.state.vout) + return I * V + }, + + + sense_error: function () { + var error = ''; + + if (this.state.motor_voltage_sense_error) error += 'Motor voltage\n'; + if (this.state.motor_current_sense_error) error += 'Motor current\n'; + if (this.state.load1_sense_error) error += 'Load 1\n'; + if (this.state.load2_sense_error) error += 'Load 2\n'; + if (this.state.vdd_current_sense_error) error += 'Vdd current\n'; + + return error; + } + }, + + + methods: { + motor_fault_class: function (motor, bit) { + if (motor == undefined) { + var status = this.state.fa; + if (status == undefined) return 'fa-question'; + return 'fa-thumbs-' + (status ? 'down error' : 'up success') + } + + var flags = this.state[motor + 'df']; + if (typeof flags == 'undefined') return 'fa-question'; + return (flags & (1 << bit)) ? 'fa-thumbs-down error' : + 'fa-thumbs-up success'; + }, + + + motor_reset: function (motor) { + if (typeof motor == 'undefined') { + var cmd = ''; + for (var i = 0; i < 4; i++) + cmd += '\\$' + i + 'df=0\n'; + this.$dispatch('send', cmd); + + } else this.$dispatch('send', '\\$' + motor + 'df=0'); + } + } +} diff --git a/src/js/settings-io.js b/src/js/settings-io.js index bdb8e40c..09e5bd0e 100644 --- a/src/js/settings-io.js +++ b/src/js/settings-io.js @@ -30,5 +30,32 @@ module.exports = { template: '#settings-io-template', - props: ['config', 'template', 'state'] + props: ['config', 'template', 'state'], + + computed: { + io() { + let io = [] + let config = this.config['io-map'] + let template = this.template['io-map'] + let indices = template.index; + let functions = template.template.function.values; + let modes = template.template.mode.values; + + for (let i = 0; i < indices.length; i++) { + let type = template.pins[i].type + let funcs = functions.filter(name => name.startsWith(type)) + funcs.unshift('disabled') + + io.push({ + id: template.pins[i].id, + type, + config: config[i], + functions: funcs, + modes: type == 'output' ? modes : [] + }) + } + + return io + } + } } diff --git a/src/js/settings-motor.js b/src/js/settings-motor.js index 37861b14..f73c89b7 100644 --- a/src/js/settings-motor.js +++ b/src/js/settings-motor.js @@ -55,12 +55,12 @@ module.exports = { maxMaxVelocity: function () { - return 1 * (15 * this.umPerStep / this.motor['microsteps']).toFixed(3); + return 1 * (15 * this.umPerStep / this.motor.microsteps).toFixed(3); }, ustepPerSec: function () { - return this.rpm * this.stepsPerRev * this.motor['microsteps'] / 60; + return this.rpm * this.stepsPerRev * this.motor.microsteps / 60; }, diff --git a/src/js/templated-select.js b/src/js/templated-select.js new file mode 100644 index 00000000..3a232c51 --- /dev/null +++ b/src/js/templated-select.js @@ -0,0 +1,40 @@ +/******************************************************************************\ + + This file is part of the Buildbotics firmware. + + Copyright (c) 2015 - 2021, Buildbotics LLC, All rights reserved. + + This Source describes Open Hardware and is licensed under the + CERN-OHL-S v2. + + You may redistribute and modify this Source and make products + using it under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). + This Source is distributed WITHOUT ANY EXPRESS OR IMPLIED + WARRANTY, INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS + FOR A PARTICULAR PURPOSE. Please see the CERN-OHL-S v2 for applicable + conditions. + + Source location: https://github.com/buildbotics + + As per CERN-OHL-S v2 section 4, should You produce hardware based on + these sources, You must maintain the Source Location clearly visible on + the external case of the CNC Controller or other product you make using + this Source. + + For more information, email info@buildbotics.com + +\******************************************************************************/ + +'use strict' + + +module.exports = { + replace: true, + template: '#templated-select-template', + props: ['model', 'values'], + + + methods: { + change: function () {this.$dispatch('input-changed')} + } +} diff --git a/src/pug/templates/breakout.pug b/src/pug/templates/breakout.pug new file mode 100644 index 00000000..d67b38ba --- /dev/null +++ b/src/pug/templates/breakout.pug @@ -0,0 +1,55 @@ +//-///////////////////////////////////////////////////////////////////////////// +//- // +//- This file is part of the Buildbotics firmware. // +//- // +//- Copyright (c) 2015 - 2021, Buildbotics LLC, All rights reserved. // +//- // +//- This Source describes Open Hardware and is licensed under the // +//- CERN-OHL-S v2. // +//- // +//- You may redistribute and modify this Source and make products // +//- using it under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). // +//- This Source is distributed WITHOUT ANY EXPRESS OR IMPLIED // +//- WARRANTY, INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS // +//- FOR A PARTICULAR PURPOSE. Please see the CERN-OHL-S v2 for applicable // +//- conditions. // +//- // +//- Source location: https://github.com/buildbotics // +//- // +//- As per CERN-OHL-S v2 section 4, should You produce hardware based on // +//- these sources, You must maintain the Source Location clearly visible on // +//- the external case of the CNC Controller or other product you make using // +//- this Source. // +//- // +//- For more information, email info@buildbotics.com // +//- // +//-///////////////////////////////////////////////////////////////////////////// + +script#breakout-template(type="text/x-template") + .breakout + h2 {{name.toUpperCase()}} breakout box + .breakout-body + div(:is="name + '-breakout'", v-ref:breakout) + .breakout-pin + div(v-if="active_pin") + h3 Pin {{active_pin}} + div(:is="name + '-pin-' + active_pin", :state="state", + :template="template") + + +script#breakout-ground-template(type="text/x-template") + .pin + h4 Ground + div This pin is connected to ground. + + +script#breakout-5v-template(type="text/x-template") + .pin + h4 5v + div This pin is connected to 5 volts. It can supply a maximum of 3A. + + +script#breakout-reserved-template(type="text/x-template") + .pin + h4 Reserved + div This is a reserved pin. Do not connect. diff --git a/src/pug/templates/db15-breakout.pug b/src/pug/templates/db15-breakout.pug new file mode 100644 index 00000000..803dfc2e --- /dev/null +++ b/src/pug/templates/db15-breakout.pug @@ -0,0 +1,57 @@ +//-///////////////////////////////////////////////////////////////////////////// +//- // +//- This file is part of the Buildbotics firmware. // +//- // +//- Copyright (c) 2015 - 2021, Buildbotics LLC, All rights reserved. // +//- // +//- This Source describes Open Hardware and is licensed under the // +//- CERN-OHL-S v2. // +//- // +//- You may redistribute and modify this Source and make products // +//- using it under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). // +//- This Source is distributed WITHOUT ANY EXPRESS OR IMPLIED // +//- WARRANTY, INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS // +//- FOR A PARTICULAR PURPOSE. Please see the CERN-OHL-S v2 for applicable // +//- conditions. // +//- // +//- Source location: https://github.com/buildbotics // +//- // +//- As per CERN-OHL-S v2 section 4, should You produce hardware based on // +//- these sources, You must maintain the Source Location clearly visible on // +//- the external case of the CNC Controller or other product you make using // +//- this Source. // +//- // +//- For more information, email info@buildbotics.com // +//- // +//-///////////////////////////////////////////////////////////////////////////// + +script#db15-breakout-template(type="text/x-template") + include http/images/db15_breakout.svg + + +script#db15-fault-template(type="text/x-template") + .pin + h4 Motor fault output + div. + This pin will be pulled to ground when a motor fault is detected. + + +script#db15-enable-template(type="text/x-template") + .pin + h4 Motor enable output + div. + This pin will be pulled high when the motor drivers are enabled. + + +script#db15-step-template(type="text/x-template") + .pin + h4 Motor channel {{ch}} step + div. + The channel {{ch}} step signal is present on this pin. + + +script#db15-dir-template(type="text/x-template") + .pin + h4 Motor channel {{ch}} direction + div. + The channel {{ch}} direction signal is present on this pin. diff --git a/src/pug/templates/db25-breakout.pug b/src/pug/templates/db25-breakout.pug new file mode 100644 index 00000000..9250aa56 --- /dev/null +++ b/src/pug/templates/db25-breakout.pug @@ -0,0 +1,58 @@ +//-///////////////////////////////////////////////////////////////////////////// +//- // +//- This file is part of the Buildbotics firmware. // +//- // +//- Copyright (c) 2015 - 2021, Buildbotics LLC, All rights reserved. // +//- // +//- This Source describes Open Hardware and is licensed under the // +//- CERN-OHL-S v2. // +//- // +//- You may redistribute and modify this Source and make products // +//- using it under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). // +//- This Source is distributed WITHOUT ANY EXPRESS OR IMPLIED // +//- WARRANTY, INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS // +//- FOR A PARTICULAR PURPOSE. Please see the CERN-OHL-S v2 for applicable // +//- conditions. // +//- // +//- Source location: https://github.com/buildbotics // +//- // +//- As per CERN-OHL-S v2 section 4, should You produce hardware based on // +//- these sources, You must maintain the Source Location clearly visible on // +//- the external case of the CNC Controller or other product you make using // +//- this Source. // +//- // +//- For more information, email info@buildbotics.com // +//- // +//-///////////////////////////////////////////////////////////////////////////// + +script#db25-breakout-template(type="text/x-template") + include http/images/db25_breakout.svg + + +script#db25-io-template(type="text/x-template") + .pin + h4 Mappable IO {{pin}} + mapped-io(:pin="pin", :state="state", :template="template") + + +script#db25-rs485-template(type="text/x-template") + .pin + h4 RS485 channel {{ch}} + div. + RS485 communication is used to talk to VFDs using the Modbus protocol. + + +script#db25-pwm-template(type="text/x-template") + .pin + h4 Tool PWM output + div. + This pin outputs a Pulse Width Modulated signal which can be used to + control spindle speed or LASER intensity. + + +script#db25-0to10-template(type="text/x-template") + .pin + h4 0 to 10v output + div. + This pin outputs a voltage between 0 and 10 which can be used to + control spindle speed or LASER intensity. diff --git a/src/pug/templates/indicators.pug b/src/pug/templates/indicators.pug index 5b6048a7..0d5b3c2b 100644 --- a/src/pug/templates/indicators.pug +++ b/src/pug/templates/indicators.pug @@ -27,241 +27,38 @@ script#indicators-template(type="text/x-template") .indicators - table.legend - tr - th.header(colspan=100) Legend - - tr - td - .fa.fa-plus-circle.io - th Hi/+3.3v - tr - td - .fa.fa-minus-circle.io - th Lo/Gnd - tr - td - .fa.fa-circle.io.active - th Active - tr - td - .fa.fa-circle.io.inactive - th Inactive - tr - td - .fa.fa-circle-o.io - th Tristated/Disabled - - table.inputs - tr - th.header(colspan=7) Inputs + div + io-pins(:state="state", :template="template") - tr - th State - th Pin - th Name - th.separator - th State - th Pin - th Name + table.legend + tr + th.header(colspan=100) Legend - each motor in '0123' tr - td: io-indicator(name=`min-switch-${motor}`, :state="state") - td {{get_min_pin(#{motor})}} - th Motor #{motor} Min + td + .fa.fa-circle.io.active + th Active th.separator - td: io-indicator(name=`max-switch-${motor}`, :state="state") - td {{get_max_pin(#{motor})}} - th Motor #{motor} Max - - tr - td: io-indicator(name="estop", :state="state") - td 23 - th EStop - th.separator - td: io-indicator(name="probe", :state="state") - td 22 - th Probe - - tr(v-if="false") - td {{state['1ai'] | percent 0}} - td 24 - th Analog 1 - th.separator - td {{state['2ai'] | percent 0}} - td 18 - th Analog 2 - - table.outputs - tr - th.header(colspan=7) Outputs - - tr - th State - th Pin - th Name - th.separator - th State - th Pin - th Name - - tr - td: io-indicator(name="tool-enable-mode", :state="state") - td 15 - th Tool Enable - th.separator - td: io-indicator(name="load-1", :state="state") - td 2 - th Load 1 - - tr - td: io-indicator(name="tool-direction-mode", :state="state") - td 16 - th Tool Direction - th.separator - td: io-indicator(name="load-2", :state="state") - td 1 - th Load 2 - - tr - td {{state.pd | percent 0}} - td 17 - th Tool PWM - th.separator - td: io-indicator(name="fault", :state="state") - td 21 - th Fault - - table.pwr_fault - tr - th.header(colspan=5). - Power Faults - #[span(v-if="state.pwr_version") (Version {{state.pwr_version}})] - tr - th(:class="{error: state.under_voltage}") Under voltage - td(:class="{error: state.under_voltage}") - | {{state.under_voltage ? 'True' : 'False'}} - th.separator - th(:class="{error: state.over_voltage}") Over voltage - td(:class="{error: state.over_voltage}") - | {{state.over_voltage ? 'True' : 'False'}} - tr - th(:class="{error: state.over_current}") Over current - td(:class="{error: state.over_current}") - | {{state.over_current ? 'True' : 'False'}} - th.separator - th(:class="{error: state.sense_error}", :title="sense_error") - | Sense error - td(:class="{error: state.sense_error}") - | {{state.sense_error ? 'True' : 'False'}} - tr - th(:class="{error: state.shunt_overload}") Shunt overload - td(:class="{error: state.shunt_overload}") - | {{state.shunt_overload ? 'True' : 'False'}} - th.separator - th(:class="{error: state.shunt_error}") Shunt error - td(:class="{error: state.shunt_error}") - | {{state.shunt_error ? 'True' : 'False'}} - tr(v-if="state.pwr_version_int < 0x100") - th(:class="{error: state.load1_shutdown}") Load 1 shutdown - td(:class="{error: state.load1_shutdown}") - | {{state.load1_shutdown ? 'True' : 'False'}} - th.separator - th(:class="{error: state.load2_shutdown}") Load 2 shutdown - td(:class="{error: state.load2_shutdown}") - | {{state.load2_shutdown ? 'True' : 'False'}} - tr - th(:class="{error: state.motor_under_voltage}") Motor under volt - td(:class="{error: state.motor_under_voltage}") - | {{state.motor_under_voltage ? 'True' : 'False'}} - th.separator - th(:class="{error: state.motor_overload}") Motor overload - td(:class="{error: state.motor_overload}") - | {{state.motor_overload ? 'True' : 'False'}} - - tr - th(:class="{error: state.power_shutdown}") Power shutdown - td(:class="{error: state.power_shutdown}") - | {{state.power_shutdown ? 'True' : 'False'}} - th.separator - th(:class="{error: state.gate_error}") Gate error - td(:class="{error: state.gate_error}") - | {{state.gate_error ? 'True' : 'False'}} - - table.motor_fault - tr - th.header(colspan=99) - | Motor Faults - .fa(:class="motor_fault_class()", title="General motor driver fault") - - tr - th Motor - th(title="Overtemperature fault"): .fa.fa-thermometer-full - th(title="Overcurrent motor channel A") A #[.fa.fa-bolt] - th(title="Predriver fault motor channel A") - | A #[.fa.fa-exclamation-triangle] - th(title="Overcurrent motor channel B") B #[.fa.fa-bolt] - th(title="Predriver fault motor channel B") - | B #[.fa.fa-exclamation-triangle] - th(title="Driver communication failure"): .fa.fa-handshake-o - th(title="Reset all motor flags") - .fa.fa-eraser(@click="motor_reset()") - - tr(v-for="motor in [0, 1, 2, 3]") - td {{motor}} - td: .fa(:class="motor_fault_class(motor, 0)", - title="Overtemperature fault") - td: .fa(:class="motor_fault_class(motor, 1)", - title="Overcurrent motor channel A") - td: .fa(:class="motor_fault_class(motor, 3)", - title="Predriver fault motor channel A") - td: .fa(:class="motor_fault_class(motor, 2)", - title="Overcurrent motor channel B") - td: .fa(:class="motor_fault_class(motor, 4)", - title="Predriver fault motor channel B") - td: .fa(:class="motor_fault_class(motor, 8)", - title="Driver communication failure") - td(:title="'Reset motor ' + motor + ' flags'") - .fa.fa-eraser(@click="motor_reset(motor)") - - table.measurements - tr - th.header(colspan=5) Measurements - - tr - td {{state.vin | fixed 1}} V - th Input Voltage - th.separator - td {{watts | fixed 2}} W - th Motor Power - - tr - td {{state.vout | fixed 1}} V - th Motor Voltage - th.separator - td {{state.motor | fixed 2}} A - th Motor Current - - tr(v-if="state.pwr_version_int < 0x100") - td {{state.load1 | fixed 2}} A - th Load 1 - th.separator - td {{state.load2 | fixed 2}} A - th Load 2 - - tr - td {{state.temp | fixed 0}} ℃ - th Board Temp - th.separator - td(:class="{'error': 80 <= state.rpi_temp}") - | {{state.rpi_temp | fixed 0}} ℃ - th RPi Temp - - div - h2 DB25 breakout box - img(src="images/DB25_breakout_box.png") + td + .fa.fa-circle.io.inactive + th Inactive + tr + td + .fa.fa-plus-circle.io + th Hi + th.separator + td + .fa.fa-minus-circle.io + th Lo + tr + td + .fa.fa-circle-o.io + th Tristated + th.separator + td + .fa.fa-ban.io + th Disabled + div: io-functions(:state="state", :template="template") - div - h2 DB15 breakout box - img(src="images/DB15_breakout_box.png") + breakout(name="db25", :state="state", :template="template") + breakout(name="db15", :state="state", :template="template") diff --git a/src/pug/templates/io-functions.pug b/src/pug/templates/io-functions.pug new file mode 100644 index 00000000..eaa95a93 --- /dev/null +++ b/src/pug/templates/io-functions.pug @@ -0,0 +1,46 @@ +//-///////////////////////////////////////////////////////////////////////////// +//- // +//- This file is part of the Buildbotics firmware. // +//- // +//- Copyright (c) 2015 - 2021, Buildbotics LLC, All rights reserved. // +//- // +//- This Source describes Open Hardware and is licensed under the // +//- CERN-OHL-S v2. // +//- // +//- You may redistribute and modify this Source and make products // +//- using it under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). // +//- This Source is distributed WITHOUT ANY EXPRESS OR IMPLIED // +//- WARRANTY, INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS // +//- FOR A PARTICULAR PURPOSE. Please see the CERN-OHL-S v2 for applicable // +//- conditions. // +//- // +//- Source location: https://github.com/buildbotics // +//- // +//- As per CERN-OHL-S v2 section 4, should You produce hardware based on // +//- these sources, You must maintain the Source Location clearly visible on // +//- the external case of the CNC Controller or other product you make using // +//- this Source. // +//- // +//- For more information, email info@buildbotics.com // +//- // +//-///////////////////////////////////////////////////////////////////////////// + +script#io-functions-template(type="text/x-template") + table.functions + tr: th.header(colspan=100) I/O Functions + + tr + th(v-for="name in columns", track-by="$index", + :class="name || 'separator'") {{name}} + + tr(v-for="i in rows") + td(is="io-functions-row", :func="functions[i * 2 + 0]") + th.separator + td(is="io-functions-row", :func="functions[i * 2 + 1]", + v-if="functions[i * 2 + 1]") + + +script#io-functions-row-template(type="text/x-template") + td.function(:class="func.type", :title="func.title") {{func.name}} + td.state: io-indicator(:state="func.state", :type="func.type") + td.pins {{func.pins.join(' ')}} diff --git a/src/pug/templates/io-pins.pug b/src/pug/templates/io-pins.pug new file mode 100644 index 00000000..199b7cc2 --- /dev/null +++ b/src/pug/templates/io-pins.pug @@ -0,0 +1,46 @@ +//-///////////////////////////////////////////////////////////////////////////// +//- // +//- This file is part of the Buildbotics firmware. // +//- // +//- Copyright (c) 2015 - 2021, Buildbotics LLC, All rights reserved. // +//- // +//- This Source describes Open Hardware and is licensed under the // +//- CERN-OHL-S v2. // +//- // +//- You may redistribute and modify this Source and make products // +//- using it under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). // +//- This Source is distributed WITHOUT ANY EXPRESS OR IMPLIED // +//- WARRANTY, INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS // +//- FOR A PARTICULAR PURPOSE. Please see the CERN-OHL-S v2 for applicable // +//- conditions. // +//- // +//- Source location: https://github.com/buildbotics // +//- // +//- As per CERN-OHL-S v2 section 4, should You produce hardware based on // +//- these sources, You must maintain the Source Location clearly visible on // +//- the external case of the CNC Controller or other product you make using // +//- this Source. // +//- // +//- For more information, email info@buildbotics.com // +//- // +//-///////////////////////////////////////////////////////////////////////////// + +script#io-pins-template(type="text/x-template") + table.io-pins + tr: th.header(colspan=100) Mappable I/O Pins + + tr + th(v-for="name in columns", track-by="$index", + :class="name || 'separator'") {{name}} + + tr(v-for="i in rows") + td(is="io-pins-row", :pin="io_pins[i * 2 + 0]") + th.separator + td(is="io-pins-row", :pin="io_pins[i * 2 + 1]", v-if="io_pins[i * 2 + 1]") + + +script#io-pins-row-template(type="text/x-template") + td.pin {{pin.id}} + td.state: io-indicator(:state="pin.state", :mode="pin.mode") + td.mode {{pin.mode}} + td.function {{pin.func}} diff --git a/src/pug/templates/mapped-io.pug b/src/pug/templates/mapped-io.pug new file mode 100644 index 00000000..412d9c3a --- /dev/null +++ b/src/pug/templates/mapped-io.pug @@ -0,0 +1,32 @@ +//-///////////////////////////////////////////////////////////////////////////// +//- // +//- This file is part of the Buildbotics firmware. // +//- // +//- Copyright (c) 2015 - 2021, Buildbotics LLC, All rights reserved. // +//- // +//- This Source describes Open Hardware and is licensed under the // +//- CERN-OHL-S v2. // +//- // +//- You may redistribute and modify this Source and make products // +//- using it under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). // +//- This Source is distributed WITHOUT ANY EXPRESS OR IMPLIED // +//- WARRANTY, INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS // +//- FOR A PARTICULAR PURPOSE. Please see the CERN-OHL-S v2 for applicable // +//- conditions. // +//- // +//- Source location: https://github.com/buildbotics // +//- // +//- As per CERN-OHL-S v2 section 4, should You produce hardware based on // +//- these sources, You must maintain the Source Location clearly visible on // +//- the external case of the CNC Controller or other product you make using // +//- this Source. // +//- // +//- For more information, email info@buildbotics.com // +//- // +//-///////////////////////////////////////////////////////////////////////////// + +script#mapped-io-template(type="text/x-template") + .mapped-io + div. + {{capitalize(type)}} pin currently mapped to function #[tt {{func}}]. + #[span(v-if="type == 'output'") Output mode set to #[tt {{mode}}].] diff --git a/src/pug/templates/power.pug b/src/pug/templates/power.pug new file mode 100644 index 00000000..fe12479a --- /dev/null +++ b/src/pug/templates/power.pug @@ -0,0 +1,153 @@ +//-///////////////////////////////////////////////////////////////////////////// +//- // +//- This file is part of the Buildbotics firmware. // +//- // +//- Copyright (c) 2015 - 2021, Buildbotics LLC, All rights reserved. // +//- // +//- This Source describes Open Hardware and is licensed under the // +//- CERN-OHL-S v2. // +//- // +//- You may redistribute and modify this Source and make products // +//- using it under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). // +//- This Source is distributed WITHOUT ANY EXPRESS OR IMPLIED // +//- WARRANTY, INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS // +//- FOR A PARTICULAR PURPOSE. Please see the CERN-OHL-S v2 for applicable // +//- conditions. // +//- // +//- Source location: https://github.com/buildbotics // +//- // +//- As per CERN-OHL-S v2 section 4, should You produce hardware based on // +//- these sources, You must maintain the Source Location clearly visible on // +//- the external case of the CNC Controller or other product you make using // +//- this Source. // +//- // +//- For more information, email info@buildbotics.com // +//- // +//-///////////////////////////////////////////////////////////////////////////// + +script#power-template(type="text/x-template") + .power + table.pwr_fault + tr + th.header(colspan=5). + Power Faults + #[span(v-if="state.pwr_version") (Version {{state.pwr_version}})] + tr + th(:class="{error: state.under_voltage}") Under voltage + td(:class="{error: state.under_voltage}") + | {{state.under_voltage ? 'True' : 'False'}} + th.separator + th(:class="{error: state.over_voltage}") Over voltage + td(:class="{error: state.over_voltage}") + | {{state.over_voltage ? 'True' : 'False'}} + tr + th(:class="{error: state.over_current}") Over current + td(:class="{error: state.over_current}") + | {{state.over_current ? 'True' : 'False'}} + th.separator + th(:class="{error: state.sense_error}", :title="sense_error") + | Sense error + td(:class="{error: state.sense_error}") + | {{state.sense_error ? 'True' : 'False'}} + tr + th(:class="{error: state.shunt_overload}") Shunt overload + td(:class="{error: state.shunt_overload}") + | {{state.shunt_overload ? 'True' : 'False'}} + th.separator + th(:class="{error: state.shunt_error}") Shunt error + td(:class="{error: state.shunt_error}") + | {{state.shunt_error ? 'True' : 'False'}} + tr(v-if="state.pwr_version_int < 0x100") + th(:class="{error: state.load1_shutdown}") Load 1 shutdown + td(:class="{error: state.load1_shutdown}") + | {{state.load1_shutdown ? 'True' : 'False'}} + th.separator + th(:class="{error: state.load2_shutdown}") Load 2 shutdown + td(:class="{error: state.load2_shutdown}") + | {{state.load2_shutdown ? 'True' : 'False'}} + tr + th(:class="{error: state.motor_under_voltage}") Motor under volt + td(:class="{error: state.motor_under_voltage}") + | {{state.motor_under_voltage ? 'True' : 'False'}} + th.separator + th(:class="{error: state.motor_overload}") Motor overload + td(:class="{error: state.motor_overload}") + | {{state.motor_overload ? 'True' : 'False'}} + + tr + th(:class="{error: state.power_shutdown}") Power shutdown + td(:class="{error: state.power_shutdown}") + | {{state.power_shutdown ? 'True' : 'False'}} + th.separator + th(:class="{error: state.gate_error}") Gate error + td(:class="{error: state.gate_error}") + | {{state.gate_error ? 'True' : 'False'}} + + table.motor_fault + tr + th.header(colspan=99) + | Motor Faults + .fa(:class="motor_fault_class()", title="General motor driver fault") + + tr + th Motor + th(title="Overtemperature fault"): .fa.fa-thermometer-full + th(title="Overcurrent motor channel A") A #[.fa.fa-bolt] + th(title="Predriver fault motor channel A") + | A #[.fa.fa-exclamation-triangle] + th(title="Overcurrent motor channel B") B #[.fa.fa-bolt] + th(title="Predriver fault motor channel B") + | B #[.fa.fa-exclamation-triangle] + th(title="Driver communication failure"): .fa.fa-handshake-o + th(title="Reset all motor flags") + .fa.fa-eraser(@click="motor_reset()") + + tr(v-for="motor in [0, 1, 2, 3]") + td {{motor}} + td: .fa(:class="motor_fault_class(motor, 0)", + title="Overtemperature fault") + td: .fa(:class="motor_fault_class(motor, 1)", + title="Overcurrent motor channel A") + td: .fa(:class="motor_fault_class(motor, 3)", + title="Predriver fault motor channel A") + td: .fa(:class="motor_fault_class(motor, 2)", + title="Overcurrent motor channel B") + td: .fa(:class="motor_fault_class(motor, 4)", + title="Predriver fault motor channel B") + td: .fa(:class="motor_fault_class(motor, 8)", + title="Driver communication failure") + td(:title="'Reset motor ' + motor + ' flags'") + .fa.fa-eraser(@click="motor_reset(motor)") + + table.measurements + tr + th.header(colspan=5) Measurements + + tr + td {{state.vin | fixed 1}} V + th Input Voltage + th.separator + td {{watts | fixed 2}} W + th Motor Power + + tr + td {{state.vout | fixed 1}} V + th Motor Voltage + th.separator + td {{state.motor | fixed 2}} A + th Motor Current + + tr(v-if="state.pwr_version_int < 0x100") + td {{state.load1 | fixed 2}} A + th Load 1 + th.separator + td {{state.load2 | fixed 2}} A + th Load 2 + + tr + td {{state.temp | fixed 0}} ℃ + th Board Temp + th.separator + td(:class="{'error': 80 <= state.rpi_temp}") + | {{state.rpi_temp | fixed 0}} ℃ + th RPi Temp diff --git a/src/pug/templates/settings-admin.pug b/src/pug/templates/settings-admin.pug index 4153bacf..15399d90 100644 --- a/src/pug/templates/settings-admin.pug +++ b/src/pug/templates/settings-admin.pug @@ -35,7 +35,6 @@ script#settings-admin-template(type="text/x-template") @change="change_enable_keyboard") label   Enable automatic virtual keyboard on local screen. - h2 Configuration button.pure-button.pure-button-primary(@click="backup") Backup button.pure-button.pure-button-primary(@click="restore_config") Restore diff --git a/src/pug/templates/settings-io.pug b/src/pug/templates/settings-io.pug index 576c860a..4480f125 100644 --- a/src/pug/templates/settings-io.pug +++ b/src/pug/templates/settings-io.pug @@ -26,24 +26,31 @@ //-///////////////////////////////////////////////////////////////////////////// script#settings-io-template(type="text/x-template") - #io + #settings-io h1 I/O Configuration - .pure-form.pure-form-aligned - fieldset - h2 Switches - templated-input(v-for="templ in template.switches", :name="$key", - :model.sync="config.switches[$key]", :template="templ") + h2 Remapable Pins + table.pure-table.pure-table-striped + thead + tr + th Pin + th Type + th Function + th Mode - label.extra(slot="extra", v-if="templ.pin") - | Pin {{templ.pin}} - io-indicator(:name="$key", :state="state") + tbody + tr(v-for="pin in io") + td {{pin.id}} + td {{pin.type}} + td + templated-select.function(:model.sync="pin.config.function", + :values="pin.functions") + td + templated-select.mode(v-if="pin.modes.length", + :model.sync="pin.config.mode", :values="pin.modes") + h2 Input + .pure-form.pure-form-aligned fieldset - h2 Outputs - templated-input(v-for="templ in template.outputs", :name="$key", - :model.sync="config.outputs[$key]", :template="templ") - - label.extra(slot="extra") - | Pin {{templ.pin}} - io-indicator(:name="$key", :state="state") + templated-input(v-for="templ in template.input", :name="$key", + :model.sync="config.input[$key]", :template="templ") diff --git a/src/pug/templates/settings-tool.pug b/src/pug/templates/settings-tool.pug index b967ab0f..46226a66 100644 --- a/src/pug/templates/settings-tool.pug +++ b/src/pug/templates/settings-tool.pug @@ -194,6 +194,13 @@ script#settings-tool-template(type="text/x-template") td.reg-value 0 td 1 start, 8 data, no parity, 1 stop td Must match #[tt parity] above + p + | Other settings according to the + | + a(href="https://buildbotics.com/upload/vfd/nowforever-e100.pdf", + target="_blank") Nowforever VFD manual + | + | and spindle type. .notes(v-if="tool_type.startsWith('DELTA VFD015M21A')") h2 Notes diff --git a/src/pug/templates/templated-select.pug b/src/pug/templates/templated-select.pug new file mode 100644 index 00000000..b22f7f01 --- /dev/null +++ b/src/pug/templates/templated-select.pug @@ -0,0 +1,30 @@ +//-///////////////////////////////////////////////////////////////////////////// +//- // +//- This file is part of the Buildbotics firmware. // +//- // +//- Copyright (c) 2015 - 2021, Buildbotics LLC, All rights reserved. // +//- // +//- This Source describes Open Hardware and is licensed under the // +//- CERN-OHL-S v2. // +//- // +//- You may redistribute and modify this Source and make products // +//- using it under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl). // +//- This Source is distributed WITHOUT ANY EXPRESS OR IMPLIED // +//- WARRANTY, INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS // +//- FOR A PARTICULAR PURPOSE. Please see the CERN-OHL-S v2 for applicable // +//- conditions. // +//- // +//- Source location: https://github.com/buildbotics // +//- // +//- As per CERN-OHL-S v2 section 4, should You produce hardware based on // +//- these sources, You must maintain the Source Location clearly visible on // +//- the external case of the CNC Controller or other product you make using // +//- this Source. // +//- // +//- For more information, email info@buildbotics.com // +//- // +//-///////////////////////////////////////////////////////////////////////////// + +script#templated-select-template(type="text/x-template") + select(v-model="model", @change="change") + option(v-for="opt in values", :value="opt") {{opt}} diff --git a/src/pug/templates/view-control.pug b/src/pug/templates/view-control.pug index 0f6e1bb7..a1dd778f 100644 --- a/src/pug/templates/view-control.pug +++ b/src/pug/templates/view-control.pug @@ -164,15 +164,6 @@ script#view-control-template(type="text/x-template") span(v-if="!isNaN(state.s)")  ({{state.s | fixed 0}}) = ' RPM' - tr(title="Load switch states.") - th Loads - td - span(:class="state['1oa'] ? 'load-on' : ''") - | 1:{{state['1oa'] ? 'On' : 'Off'}} - |   - span(:class="state['2oa'] ? 'load-on' : ''") - | 2:{{state['2oa'] ? 'On' : 'Off'}} - table.info tr th Remaining @@ -222,6 +213,9 @@ script#view-control-template(type="text/x-template") input#tab5(type="radio", name="tabs", @click="tab = 'indicators'") label(for="tab5") Indicators + input#tab6(type="radio", name="tabs", @click="tab = 'power'") + label(for="tab6") Power + section#content1.tab-content.pure-form .toolbar.pure-control-group button.pure-button(:class="{'attention': is_holding}", @@ -324,3 +318,6 @@ script#view-control-template(type="text/x-template") section#content5.tab-content indicators(:state="state", :template="template") + + section#content6.tab-content + power(:state="state", :template="template") diff --git a/src/pwr2/main.c b/src/pwr2/main.c index 9bc0161d..4039a4f1 100644 --- a/src/pwr2/main.c +++ b/src/pwr2/main.c @@ -330,10 +330,6 @@ ISR(TWI0_TWIS_vect) { static uint16_t reg; static uint8_t pec = 0; - // Stretch clock longer to work around RPi bug - // See https://github.com/raspberrypi/linux/issues/254 - //_delay_us(100); // Must use software delay while in interrupt - uint8_t status = TWI0.SSTATUS; if (status & TWI_DIF_bm) { diff --git a/src/py/bbctrl/Comm.py b/src/py/bbctrl/Comm.py index c709138f..5bc14bb9 100644 --- a/src/py/bbctrl/Comm.py +++ b/src/py/bbctrl/Comm.py @@ -250,6 +250,7 @@ def connect(self): try: # Resume once current queue of GCode commands has flushed self.queue_command(Cmd.RESUME) + self.queue_command(Cmd.set('ct', 128)) self.queue_command(Cmd.HELP) # Load AVR commands and variables except Exception as e: diff --git a/src/py/bbctrl/Preplanner.py b/src/py/bbctrl/Preplanner.py index 3dff300e..ab9c0a1c 100644 --- a/src/py/bbctrl/Preplanner.py +++ b/src/py/bbctrl/Preplanner.py @@ -32,6 +32,7 @@ import glob import tempfile import signal +import shutil from concurrent.futures import Future from tornado import gen, process, iostream import bbctrl @@ -162,9 +163,9 @@ def _exec(self): proc.stdout.close() if not self.cancel: - os.rename(tmpdir + '/meta.json', self.files[0]) - os.rename(tmpdir + '/positions.gz', self.files[1]) - os.rename(tmpdir + '/speeds.gz', self.files[2]) + shutil.move(tmpdir + '/meta.json', self.files[0]) + shutil.move(tmpdir + '/positions.gz', self.files[1]) + shutil.move(tmpdir + '/speeds.gz', self.files[2]) self.preplanner.clean() os.sync() diff --git a/src/py/bbctrl/State.py b/src/py/bbctrl/State.py index 9d3e663a..c3d979d9 100644 --- a/src/py/bbctrl/State.py +++ b/src/py/bbctrl/State.py @@ -94,7 +94,7 @@ def init(self): def reset(self): # Unhome all motors - for i in range(4): self.set('%dhomed' % i, False) + for i in range(4): self.set('%dhomed' % i, 0) # Zero offsets and positions for axis in 'xyzabc': @@ -261,7 +261,7 @@ def find_motor(self, axis): return motor - def is_axis_homed(self, axis): return self.get('%s_homed' % axis, False) + def is_axis_homed(self, axis): return self.get('%s_homed' % axis, 0) def is_axis_enabled(self, axis): diff --git a/src/py/bbctrl/Web.py b/src/py/bbctrl/Web.py index 2d46edd5..7abe3f6a 100644 --- a/src/py/bbctrl/Web.py +++ b/src/py/bbctrl/Web.py @@ -577,51 +577,52 @@ def __init__(self, args, ioloop): self.monitor = bbctrl.MonitorTemp(self) handlers = [ - (r'/websocket', WSConnection), - (r'/api/state(/.*)?', StateHandler), - (r'/api/log', LogHandler), - (r'/api/message/(\d+)/ack', MessageAckHandler), - (r'/api/bugreport', BugReportHandler), - (r'/api/reboot', RebootHandler), - (r'/api/hostname', HostnameHandler), - (r'/api/wifi', WifiHandler), - (r'/api/remote/username', UsernameHandler), - (r'/api/remote/password', PasswordHandler), - (r'/api/config/load', ConfigLoadHandler), - (r'/api/config/download', ConfigDownloadHandler), - (r'/api/config/save', ConfigSaveHandler), - (r'/api/config/reset', ConfigResetHandler), - (r'/api/firmware/update', FirmwareUpdateHandler), - (r'/api/upgrade', UpgradeHandler), - (r'/api/queue/(.*)', QueueHandler), - (r'/api/usb/update', USBUpdateHandler), - (r'/api/usb/eject/(.*)', USBEjectHandler), - (r'/api/fs/(.*)', bbctrl.FileSystemHandler), - (r'/api/macro/(\d+)', MacroHandler), - (r'/api/(path)/(.*)', PathHandler), - (r'/api/(positions)/(.*)', PathHandler), - (r'/api/(speeds)/(.*)', PathHandler), + (r'/websocket', WSConnection), + (r'/api/state(/.*)?', StateHandler), + (r'/api/log', LogHandler), + (r'/api/message/(\d+)/ack', MessageAckHandler), + (r'/api/bugreport', BugReportHandler), + (r'/api/reboot', RebootHandler), + (r'/api/hostname', HostnameHandler), + (r'/api/wifi', WifiHandler), + (r'/api/remote/username', UsernameHandler), + (r'/api/remote/password', PasswordHandler), + (r'/api/config/load', ConfigLoadHandler), + (r'/api/config/download', ConfigDownloadHandler), + (r'/api/config/save', ConfigSaveHandler), + (r'/api/config/reset', ConfigResetHandler), + (r'/api/firmware/update', FirmwareUpdateHandler), + (r'/api/upgrade', UpgradeHandler), + (r'/api/queue/(.*)', QueueHandler), + (r'/api/usb/update', USBUpdateHandler), + (r'/api/usb/eject/(.*)', USBEjectHandler), + (r'/api/fs/(.*)', bbctrl.FileSystemHandler), + (r'/api/macro/(\d+)', MacroHandler), + (r'/api/(path)/(.*)', PathHandler), + (r'/api/(positions)/(.*)', PathHandler), + (r'/api/(speeds)/(.*)', PathHandler), (r'/api/home(/[xyzabcXYZABC]((/set)|(/clear))?)?', HomeHandler), - (r'/api/start', StartHandler), - (r'/api/estop', EStopHandler), - (r'/api/clear', ClearHandler), - (r'/api/stop', StopHandler), - (r'/api/pause', PauseHandler), - (r'/api/unpause', UnpauseHandler), - (r'/api/pause/optional', OptionalPauseHandler), - (r'/api/step', StepHandler), + (r'/api/start', StartHandler), + (r'/api/estop', EStopHandler), + (r'/api/clear', ClearHandler), + (r'/api/stop', StopHandler), + (r'/api/pause', PauseHandler), + (r'/api/unpause', UnpauseHandler), + (r'/api/pause/optional', OptionalPauseHandler), + (r'/api/step', StepHandler), (r'/api/position/([xyzabcXYZABC])', PositionHandler), - (r'/api/override/feed/([\d.]+)', OverrideFeedHandler), - (r'/api/override/speed/([\d.]+)', OverrideSpeedHandler), - (r'/api/modbus/read', ModbusReadHandler), - (r'/api/modbus/write', ModbusWriteHandler), - (r'/api/jog', JogHandler), - (r'/api/video', bbctrl.VideoHandler), - (r'/api/keyboard/((show)|(hide))', KeyboardHandler), - (r'/(.*)', StaticFileHandler, - {'path': bbctrl.get_resource('http/'), - 'default_filename': 'index.html'}), - ] + (r'/api/override/feed/([\d.]+)', OverrideFeedHandler), + (r'/api/override/speed/([\d.]+)', OverrideSpeedHandler), + (r'/api/modbus/read', ModbusReadHandler), + (r'/api/modbus/write', ModbusWriteHandler), + (r'/api/jog', JogHandler), + (r'/api/video', bbctrl.VideoHandler), + (r'/api/keyboard/((show)|(hide))', KeyboardHandler), + (r'/(.*)', StaticFileHandler, { + 'path': bbctrl.get_resource('http/'), + 'default_filename': 'index.html' + }), + ] router = sockjs.tornado.SockJSRouter(SockJSConnection, '/sockjs') router.app = self diff --git a/src/resources/config-template.json b/src/resources/config-template.json index 9482353e..66a5a55d 100644 --- a/src/resources/config-template.json +++ b/src/resources/config-template.json @@ -374,9 +374,28 @@ "io-map": { "type": "list", "index": "abcdefghijklmnopq", + "pins": [ + {"id": 1, "type": "output"}, + {"id": 2, "type": "output"}, + {"id": 3, "type": "input"}, + {"id": 4, "type": "input"}, + {"id": 5, "type": "input"}, + {"id": 8, "type": "input"}, + {"id": 9, "type": "input"}, + {"id": 10, "type": "input"}, + {"id": 11, "type": "input"}, + {"id": 12, "type": "input"}, + {"id": 15, "type": "output"}, + {"id": 16, "type": "output"}, + {"id": 18, "type": "analog"}, + {"id": 21, "type": "output"}, + {"id": 22, "type": "input"}, + {"id": 23, "type": "input"}, + {"id": 24, "type": "analog"} + ], "default": [ - {"function": "output-flood"}, - {"function": "output-mist"}, + {"function": "output-flood", "mode": "lo-hi"}, + {"function": "output-mist", "mode": "lo-hi"}, {"function": "input-motor-0-min"}, {"function": "input-motor-0-max"}, {"function": "input-motor-1-min"}, @@ -385,10 +404,10 @@ {"function": "input-motor-2-max"}, {"function": "input-motor-3-min"}, {"function": "input-motor-3-max"}, - {"function": "output-tool-enable"}, - {"function": "output-tool-direction"}, + {"function": "output-tool-enable", "mode": "lo-hi"}, + {"function": "output-tool-direction", "mode": "lo-hi"}, {"function": "analog-1"}, - {"function": "output-fault"}, + {"function": "output-fault", "mode": "lo-hi"}, {"function": "input-probe"}, {"function": "input-estop"}, {"function": "analog-0"} @@ -408,12 +427,17 @@ "output-tool-enable", "output-tool-direction", "analog-0", "analog-1", "analog-2", "analog-3" ], + "codes": [ + null, "0xw", "1xw", "2xw", "3xw", "0lw", "1lw", "2lw", "3lw", + "0w", "1w", "2w", "3w", "ew", "pw", "0oa", "1oa", "2oa", "3oa", + "Moa", "Foa", "foa", "eoa", "doa", "0ai", "1ai", "2ai", "3ai" + ], "code": "io" }, "mode": { "type": "enum", "values": ["lo-hi", "hi-lo", "tri-lo", "tri-hi", "lo-tri", "hi-tri"], - "default": "lo-hi", + "default": "hi-lo", "code": "im" } } diff --git a/src/resources/images/DB15_breakout_box.png b/src/resources/images/DB15_breakout_box.png deleted file mode 100644 index 5a5e4fb8..00000000 Binary files a/src/resources/images/DB15_breakout_box.png and /dev/null differ diff --git a/src/resources/images/DB25_breakout_box.png b/src/resources/images/DB25_breakout_box.png deleted file mode 100644 index 406eb3ff..00000000 Binary files a/src/resources/images/DB25_breakout_box.png and /dev/null differ diff --git a/src/resources/images/db15_breakout.svg b/src/resources/images/db15_breakout.svg new file mode 100644 index 00000000..73067bdd --- /dev/null +++ b/src/resources/images/db15_breakout.svg @@ -0,0 +1,1519 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 9 + + + + + + enable + + + 10 + + + + + + dir 0 + + + 11 + + + + + + dir 1 + + + 12 + + + + + + dir 2 + + + 13 + + + + + + dir 3 + + + 14 + + + + + + gnd + + + 15 + + + + + + gnd + + + GND + + + + + + gnd + + + 8 + + + + + + n/c + + + 7 + + + + + + n/c + + + 6 + + + + + + 5v + + + 5 + + + + + + step 0 + + + 4 + + + + + + step 1 + + + 3 + + + + + + step 2 + + + 2 + + + + + + step 3 + + + 1 + + + + + + fault + + + diff --git a/src/resources/images/db25_breakout.svg b/src/resources/images/db25_breakout.svg new file mode 100644 index 00000000..5bb055cf --- /dev/null +++ b/src/resources/images/db25_breakout.svg @@ -0,0 +1,3593 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + io + - + + + + + + + 1 + + + + 2 + io + - + + + + + + + 2 + + + + 3 + io + - + + + + + + + 3 + + + + 4 + io + - + + + + + + + 4 + + + + 5 + io + - + + + + + + + 5 + + + + 6 + 0-10v + - + + + + + + + 6 + + + + 7 + gnd + - + + + + + + + 7 + + + + 8 + io + - + + + + + + + 8 + + + + 9 + io + - + + + + + + + 9 + + + + 10 + io + - + + + + + + + 10 + + + + 11 + io + - + + + + + + + 11 + + + + 12 + io + - + + + + + + + 12 + + + + 13 + rs485 a + - + + + + + + + 13 + + + + 14 + rs485 b + - + + + + + + + 14 + + + + 15 + io + - + + + + + + + 15 + + + + 16 + io + - + + + + + + + 16 + + + + 17 + pwm + - + + + + + + + 17 + + + + 18 + io + - + + + + + + + 18 + + + + 19 + gnd + - + + + + + + + 19 + + + + 20 + 5v + - + + + + + + + 20 + + + + 21 + io + - + + + + + + + 21 + + + + 22 + io + - + + + + + + + 22 + + + + 23 + io + - + + + + + + + 23 + + + + 24 + io + - + + + + + + + 24 + + + + 25 + gnd + - + + + + + + + 25 + + + + gnd + shield + - + + + + + + + GND + + + + diff --git a/src/stylus/indicators.styl b/src/stylus/indicators.styl index 523129d2..ed94beb2 100644 --- a/src/stylus/indicators.styl +++ b/src/stylus/indicators.styl @@ -25,17 +25,18 @@ \******************************************************************************/ -.indicators +.indicators, .power padding 1em 0 text-align center display grid grid-template-columns 1fr 1fr + > * + border 2px solid #bbb + table - height 100% - vertical-align top + width 100% empty-cells show - border 2px solid #bbb border-collapse separate td, th @@ -51,10 +52,6 @@ td text-align right - &.inputs, &.outputs - td:nth-child(1), td:nth-child(5) - text-align center - th.header height 2.5em border-bottom 3px solid #ccc @@ -65,6 +62,23 @@ border 1px solid #ccc padding 0 + + &.legend + border-top 2px solid #bbb + + &.functions, &.io-pins + th + text-transform capitalize + + .function, .mode + text-align left + + .disabled + text-decoration line-through + + .state + text-align center + &.motor_fault td, th text-align center @@ -80,8 +94,37 @@ td width 8em + .breakout + h3 + margin 0 + + .pin + cursor pointer + + .selected-pin + filter grayscale(100%) brightness(60%) sepia(100%) hue-rotate(-30deg) \ + saturate(600%) contrast(0.8) + + text + fill #fff !important + + .breakout-body + display flex + flex-direction row + + .breakout + margin 0.5em + + .breakout-pin + flex 1 + text-align left + padding 0 1em @media only screen and (max-width 1000px) + .power + grid-template-columns 1fr + +@media only screen and (max-width 1300px) .indicators grid-template-columns 1fr diff --git a/src/stylus/view-settings.styl b/src/stylus/view-settings.styl index 9066d8ce..f9961f1c 100644 --- a/src/stylus/view-settings.styl +++ b/src/stylus/view-settings.styl @@ -42,3 +42,10 @@ #settings-admin a text-decoration none + +#settings-io .pure-table + td, th + padding 0.25em 0.5em + + select.function + width 14em