diff --git a/package-lock.json b/package-lock.json index 20d79b6..8b6a115 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "bbctrl", - "version": "1.0.10b1", + "version": "1.0.10b2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "bbctrl", - "version": "1.0.10b1", + "version": "1.0.10b2", "license": "GPL-3.0+", "dependencies": { "browserify": "^17.0.0", diff --git a/package.json b/package.json index 9b82c1b..e7e8200 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bbctrl", - "version": "1.0.10b1", + "version": "1.0.10b2", "homepage": "https://onefinitycnc.com/", "repository": "https://github.com/OneFinityCNC/onefinity", "license": "GPL-3.0+", diff --git a/setup.py b/setup.py index e3bd034..8e7dbdf 100755 --- a/setup.py +++ b/setup.py @@ -19,7 +19,6 @@ setup( packages=[ 'bbctrl', 'inevent', - 'lcd', 'camotics', 'iw_parse' ], diff --git a/src/avr/src/lcd.c b/src/avr/src/lcd.c deleted file mode 100644 index 7802eb4..0000000 --- a/src/avr/src/lcd.c +++ /dev/null @@ -1,143 +0,0 @@ -/******************************************************************************\ - - This file is part of the Buildbotics firmware. - - Copyright (c) 2015 - 2018, Buildbotics LLC - All rights reserved. - - This file ("the software") is free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License, - version 2 as published by the Free Software Foundation. You should - have received a copy of the GNU General Public License, version 2 - along with the software. If not, see . - - The software is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the software. If not, see - . - - For information regarding this software email: - "Joseph Coffland" - -\******************************************************************************/ - -#include "lcd.h" -#include "rtc.h" -#include "hardware.h" -#include "command.h" - -#include -#include -#include - -#include - - -void lcd_init(uint8_t addr) { - // Enable I2C master - TWIC.MASTER.BAUD = F_CPU / 2 / 100000 - 5; // 100 KHz - TWIC.MASTER.CTRLA = TWI_MASTER_ENABLE_bm; - TWIC.MASTER.CTRLB = TWI_MASTER_TIMEOUT_DISABLED_gc; - TWIC.MASTER.STATUS = TWI_MASTER_BUSSTATE_IDLE_gc; - - _delay_ms(50); - lcd_nibble(addr, 3 << 4); // Home - _delay_ms(50); - lcd_nibble(addr, 3 << 4); // Home - _delay_ms(50); - lcd_nibble(addr, 3 << 4); // Home - lcd_nibble(addr, 2 << 4); // 4-bit - - lcd_write(addr, - LCD_FUNCTION_SET | LCD_2_LINE | LCD_5x8_DOTS | LCD_4_BIT_MODE, 0); - lcd_write(addr, LCD_DISPLAY_CONTROL | LCD_DISPLAY_ON, 0); - lcd_write(addr, LCD_ENTRY_MODE_SET | LCD_ENTRY_SHIFT_INC, 0); - - lcd_write(addr, LCD_CLEAR_DISPLAY, 0); - lcd_write(addr, LCD_RETURN_HOME, 0); -} - - -static void _master_wait() { -#ifdef __AVR__ - while (!(TWIC.MASTER.STATUS & TWI_MASTER_WIF_bm)) continue; -#endif -} - - -static void _write_i2c(uint8_t addr, uint8_t data) { - data |= BACKLIGHT_BIT; - - TWIC.MASTER.ADDR = addr << 1; - _master_wait(); - - TWIC.MASTER.DATA = data; - _master_wait(); - - TWIC.MASTER.CTRLC = TWI_MASTER_CMD_STOP_gc; - - _delay_us(100); -} - - -void lcd_nibble(uint8_t addr, uint8_t data) { - _write_i2c(addr, data); - _write_i2c(addr, data | ENABLE_BIT); - _delay_us(500); - _write_i2c(addr, data & ~ENABLE_BIT); - _delay_us(100); -} - - -void lcd_write(uint8_t addr, uint8_t cmd, uint8_t flags) { - lcd_nibble(addr, flags | (cmd & 0xf0)); - lcd_nibble(addr, flags | ((cmd << 4) & 0xf0)); -} - - -void lcd_goto(uint8_t addr, uint8_t x, uint8_t y) { - static uint8_t row[] = {0, 64, 20, 84}; - lcd_write(addr, LCD_SET_DDRAM_ADDR | (row[y] + x), 0); -} - - -void lcd_putchar(uint8_t addr, uint8_t c) { - lcd_write(addr, c, REG_SELECT_BIT); -} - - -void lcd_pgmstr(uint8_t addr, const char *s) { - while (true) { - char c = pgm_read_byte(s++); - if (!c) break; - lcd_putchar(addr, c); - } -} - - -void _splash(uint8_t addr) { - lcd_init(addr); - lcd_goto(addr, 1, 1); - lcd_pgmstr(addr, PSTR("Controller booting")); - lcd_goto(addr, 3, 2); - lcd_pgmstr(addr, PSTR("Please wait...")); -} - - -void lcd_splash() { - wdt_disable(); - _splash(0x27); - _splash(0x3f); - wdt_enable(WDTO_250MS); -} - - -void lcd_rtc_callback() { - // Display the splash if we haven't gotten any commands in 1sec since boot - if (!command_is_active() && rtc_get_time() == 1000) - lcd_splash(); -} diff --git a/src/avr/src/lcd.h b/src/avr/src/lcd.h deleted file mode 100644 index b7369f0..0000000 --- a/src/avr/src/lcd.h +++ /dev/null @@ -1,103 +0,0 @@ -/******************************************************************************\ - - This file is part of the Buildbotics firmware. - - Copyright (c) 2015 - 2018, Buildbotics LLC - All rights reserved. - - This file ("the software") is free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License, - version 2 as published by the Free Software Foundation. You should - have received a copy of the GNU General Public License, version 2 - along with the software. If not, see . - - The software is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the software. If not, see - . - - For information regarding this software email: - "Joseph Coffland" - -\******************************************************************************/ - -#pragma once - -#include "pgmspace.h" - -#include - - -// Control flags -enum { - REG_SELECT_BIT = 1 << 0, - READ_BIT = 1 << 1, - ENABLE_BIT = 1 << 2, - BACKLIGHT_BIT = 1 << 3, -}; - - -// Commands -enum { - LCD_CLEAR_DISPLAY = 1 << 0, - LCD_RETURN_HOME = 1 << 1, - LCD_ENTRY_MODE_SET = 1 << 2, - LCD_DISPLAY_CONTROL = 1 << 3, - LCD_CURSOR_SHIFT = 1 << 4, - LCD_FUNCTION_SET = 1 << 5, - LCD_SET_CGRAM_ADDR = 1 << 6, - LCD_SET_DDRAM_ADDR = 1 << 7, -}; - - -// Entry Mode Set flags -#define LCD_ENTRY_SHIFT_DISPLAY (1 << 0) -#define LCD_ENTRY_SHIFT_INC (1 << 1) -#define LCD_ENTRY_SHIFT_DEC (0 << 1) - - -// Display Control flags -#define LCD_BLINK_ON (1 << 0) -#define LCD_BLINK_OFF (0 << 0) -#define LCD_CURSOR_ON (1 << 1) -#define LCD_CURSOR_OFF (0 << 1) -#define LCD_DISPLAY_ON (1 << 2) -#define LCD_DISPLAY_OFF (0 << 2) - - -// Cursor Shift flags -#define LCD_SHIFT_RIGHT (1 << 2) -#define LCD_SHIFT_LEFT (0 << 2) -#define LCD_SHIFT_DISPLAY (1 << 3) -#define LCD_SHIFT_CURSOR (0 << 3) - - -// Function Set flags -#define LCD_5x11_DOTS (1 << 2) -#define LCD_5x8_DOTS (0 << 2) -#define LCD_2_LINE (1 << 3) -#define LCD_1_LINE (0 << 3) -#define LCD_8_BIT_MODE (1 << 4) -#define LCD_4_BIT_MODE (0 << 4) - - -// Text justification flags -enum { - JUSTIFY_LEFT = 0, - JUSTIFY_RIGHT = 1, - JUSTIFY_CENTER = 2, -}; - - -void lcd_init(uint8_t addr); -void lcd_nibble(uint8_t addr, uint8_t data); -void lcd_write(uint8_t addr, uint8_t cmd, uint8_t flags); -void lcd_goto(uint8_t addr, uint8_t x, uint8_t y); -void lcd_putchar(uint8_t addr, uint8_t c); -void lcd_pgmstr(uint8_t addr, const char *s); -void lcd_splash(); -void lcd_rtc_callback(); diff --git a/src/avr/src/rtc.c b/src/avr/src/rtc.c index 8020895..f52c4fc 100644 --- a/src/avr/src/rtc.c +++ b/src/avr/src/rtc.c @@ -30,7 +30,6 @@ #include "switch.h" #include "analog.h" #include "motor.h" -#include "lcd.h" #include "vfd_spindle.h" #include @@ -46,7 +45,6 @@ static uint32_t ticks; ISR(RTC_OVF_vect) { ticks++; - lcd_rtc_callback(); switch_rtc_callback(); analog_rtc_callback(); vfd_spindle_rtc_callback(); diff --git a/src/avr/step-test/Makefile b/src/avr/step-test/Makefile deleted file mode 100644 index 52f894a..0000000 --- a/src/avr/step-test/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Makefile for Bulidbotics step-test -PROJECT = step-test -MCU = atxmega192a3u -CLOCK = 32000000 - -# SRC -SRC = usart.c lcd.c pins.c hardware.c -SRC := $(wildcard *.c) $(patsubst %,../src/%,$(SRC)) - -include ../Makefile.common - -CFLAGS += -I../src -I. - -# Build -all: $(PROJECT).hex size - -$(PROJECT).elf: $(SRC) - $(CC) $(SRC) $(CFLAGS) $(LDFLAGS) $(LIBS) -o $@ - -.PHONY: all diff --git a/src/avr/step-test/plot_velocity.py b/src/avr/step-test/plot_velocity.py deleted file mode 100644 index 2006faf..0000000 --- a/src/avr/step-test/plot_velocity.py +++ /dev/null @@ -1,187 +0,0 @@ -#!/usr/bin/env python3 - -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -import sys, serial, argparse -import numpy as np -import math -import json -from time import sleep -from collections import deque -from datetime import datetime - -import matplotlib.pyplot as plt -import matplotlib.animation as animation - - -MM_PER_STEP = 5 * 1.8 / 360 / 32 -SAMPLES_PER_MIN = 6000 - - -class Plot: - def __init__(self, port, baud, max_len): - # Open serial port - self.sp = serial.Serial(port, baud) - - # Create data series - self.series = [] - for i in range(5): - self.series.append(deque([0.0] * max_len)) - - # Init vars - self.max_len = max_len - self.incoming = '' - self.last = [None] * 4 - - # Open velocity log - ts = datetime.now().strftime('%Y-%m-%d-%H:%M:%S') - self.log = open('velocity-%s.log' % ts, 'w') - - - # Add new series data - def add(self, i, value): - self.series[i].pop() - self.series[i].appendleft(value) - - - def update_text(self, text, vel, data): - text[4].set_text('V {0:8,.2f}'.format(vel)) - - for i in range(4): - text[i].set_text('{} {:11,}'.format('XYZA'[i], int(data[i]))) - - - def update(self, frame, axes, text): - # Read new data - try: - data = self.sp.read(self.sp.in_waiting) - self.incoming += data.decode('utf-8') - - except Exception as e: - print(e) - return - - while True: - # Parse lines - i = self.incoming.find('\n') - if i == -1: break - line = self.incoming[0:i] - self.incoming = self.incoming[i + 1:] - - # Handle reset - if line.find('RESET') != -1: - self.update_text(text, 0, [0] * 4) - self.log.write(line + '\n') - self.last = [None] * 4 - continue - - # Parse data - try: - data = [float(value) for value in line.split(',')] - except ValueError: continue - - if len(data) != 4: continue - - # Compute axis velocities - v = [] # Axis velocity - totalV = 0 # Tool velocity - - for i in range(4): - if self.last[i] is not None: - delta = self.last[i] - data[i] - v.append(delta * MM_PER_STEP * SAMPLES_PER_MIN) # mm/min - totalV += math.pow(v[i], 2) - - self.last[i] = data[i] - - # Compute tool velocity - totalV = math.sqrt(totalV) - - # Update position and velocity text - self.update_text(text, totalV, data) - - # Don't update plots when not moving - if totalV == 0: continue - - # Add new data - for i in range(4): self.add(i, v[i]) - self.add(4, totalV) - - # Update plots - for i in range(5): - axes[i].set_data(range(self.max_len), self.series[i]) - - self.log.write(line + '\n') - - - def close(self): - self.sp.flush() - self.sp.close() - - -if __name__ == '__main__': - # Parse command line arguments - description = "Plot velocity data in real-time" - parser = argparse.ArgumentParser(description = description) - parser.add_argument('-p', '--port', default = '/dev/ttyUSB0') - parser.add_argument('-b', '--baud', default = 115200, type = int) - parser.add_argument('-m', '--max-width', default = 2000, type = int) - args = parser.parse_args() - - # Create plot - plot = Plot(args.port, args.baud, args.max_width) - fig = plt.figure() - ax = plt.axes(xlim = (0, args.max_width), ylim = (-10000, 10000)) - axes = [] - axes_text = [] - - # Setup position and velocity text fields - font = dict(fontsize = 14, family = 'monospace') - - axes_text.append(plt.text(0, 11700, '', **font)) - axes_text.append(plt.text(800, 11700, '', **font)) - axes_text.append(plt.text(0, 10500, '', **font)) - axes_text.append(plt.text(800, 10500, '', **font)) - axes_text.append(plt.text(1500, 11700, '', **font)) - - # Create axes - for i in range(5): - axes.append(ax.plot([], [])[0]) - # Set text color to match axis color - axes_text[i].set_color(axes[i].get_color()) - - # Initial text views - plot.update_text(axes_text, 0, [0] * 4) - - # Set up animation - anim = animation.FuncAnimation(fig, plot.update, fargs = [axes, axes_text], - interval = 100) - - # Run - plt.show() - plot.close() diff --git a/src/avr/step-test/step-test.c b/src/avr/step-test/step-test.c deleted file mode 100644 index db267bf..0000000 --- a/src/avr/step-test/step-test.c +++ /dev/null @@ -1,230 +0,0 @@ -/******************************************************************************\ - - This file is part of the Buildbotics firmware. - - Copyright (c) 2015 - 2018, Buildbotics LLC - All rights reserved. - - This file ("the software") is free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License, - version 2 as published by the Free Software Foundation. You should - have received a copy of the GNU General Public License, version 2 - along with the software. If not, see . - - The software is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the software. If not, see - . - - For information regarding this software email: - "Joseph Coffland" - -\******************************************************************************/ - -#include "config.h" -#include "hardware.h" -#include "usart.h" -#include "lcd.h" - -#include - -#include -#include - - -#define RESET_PIN SPI_MOSI_PIN - - -void rtc_init() {} - - -static struct { - uint8_t step_pin; - uint8_t dir_pin; - TC0_t *timer; - volatile int16_t high; - volatile bool reading; - -} channel[4] = { - {STEP_X_PIN, DIR_X_PIN, &TCC0, 0}, - {STEP_Y_PIN, DIR_Y_PIN, &TCD0, 0}, - {STEP_Z_PIN, DIR_Z_PIN, &TCE0, 0}, - {STEP_A_PIN, DIR_A_PIN, &TCF0, 0}, -}; - - -static int reset = 0; - - -void channel_reset(int i) {channel[i].timer->CNT = channel[i].high = 0;} - - -#define EVSYS_CHMUX(CH) (&EVSYS_CH0MUX)[CH] -#define EVSYS_CHCTRL(CH) (&EVSYS_CH0CTRL)[CH] - - -void channel_overflow(int i) { - if (IN_PIN(channel[i].dir_pin)) channel[i].high--; - else channel[i].high++; - channel[i].reading = false; -} - - -ISR(TCC0_OVF_vect) {channel_overflow(0);} -ISR(TCD0_OVF_vect) {channel_overflow(1);} -ISR(TCE0_OVF_vect) {channel_overflow(2);} -ISR(TCF0_OVF_vect) {channel_overflow(3);} - - -void channel_update_dir(int i) { - if (IN_PIN(channel[i].dir_pin)) channel[i].timer->CTRLFSET = TC0_DIR_bm; - else channel[i].timer->CTRLFCLR = TC0_DIR_bm; -} - - -ISR(PORTE_INT0_vect) {for (int i = 0; i < 4; i++) channel_update_dir(i);} - - -int32_t __attribute__ ((noinline)) _channel_read(int i) { - return (int32_t)channel[i].high << 16 | channel[i].timer->CNT; -} - - -int32_t channel_read(int i) { - while (true) { - channel[i].reading = true; - - int32_t x = _channel_read(i); - int32_t y = _channel_read(i); - - if (x != y || !channel[i].reading) continue; - - channel[i].reading = false; - return x; - } -} - - -void channel_update_enable(int i) { - if (IN_PIN(MOTOR_ENABLE_PIN)) - channel[i].timer->CTRLA = TC_CLKSEL_EVCH0_gc + i; - else channel[i].timer->CTRLA = 0; -} - - -ISR(PORTF_INT0_vect) { - for (int i = 0; i < 4; i++) channel_update_enable(i); - if (!IN_PIN(MOTOR_ENABLE_PIN)) reset = 2; -} - - -ISR(PORTC_INT0_vect) {reset = 32;} - - -ISR(TCC1_OVF_vect) { - if (reset) reset--; - - // Report measured steps - static int32_t counts[4] = {0, 0, 0, 0}; - bool moving = false; - bool zero = true; - for (int i = 0; i < 4; i++) { - int32_t count = channel_read(i); - if (count != counts[i]) moving = true; - if (count) zero = false; - counts[i] = count; - } - - if (reset && !zero) { - for (int i = 0; i < 4; i++) channel_reset(i); - printf("RESET\n"); - return; - } - - if (moving) - printf("%ld,%ld,%ld,%ld\n", counts[0], counts[1], counts[2], counts[3]); -} - - -static void _splash(uint8_t addr) { - lcd_init(addr); - lcd_goto(addr, 5, 1); - lcd_pgmstr(addr, PSTR("Step Test")); -} - - -void channel_init(int i) { - uint8_t step_pin = channel[i].step_pin; - uint8_t dir_pin = channel[i].dir_pin; - - // Configure I/O - DIRCLR_PIN(step_pin); - DIRCLR_PIN(dir_pin); - PINCTRL_PIN(step_pin) = PORT_SRLEN_bm | PORT_ISC_RISING_gc; - PINCTRL_PIN(dir_pin) = PORT_SRLEN_bm | PORT_ISC_BOTHEDGES_gc; - - // Dir change interrupt - PIN_PORT(dir_pin)->INTCTRL |= PORT_INT0LVL_HI_gc; - PIN_PORT(dir_pin)->INT0MASK |= PIN_BM(dir_pin); - - // Events - EVSYS_CHMUX(i) = PIN_EVSYS_CHMUX(step_pin); - EVSYS_CHCTRL(i) = EVSYS_DIGFILT_8SAMPLES_gc; - - // Clock - channel_update_enable(i); - channel[i].timer->INTCTRLA = TC_OVFINTLVL_HI_gc; - - // Set initial clock direction - channel_update_dir(i); -} - - -static void init() { - cli(); - - hw_init(); - usart_init(); - - // Motor channels - for (int i = 0; i < 4; i++) channel_init(i); - - // Motor enable - DIRCLR_PIN(MOTOR_ENABLE_PIN); - PINCTRL_PIN(MOTOR_ENABLE_PIN) = - PORT_SRLEN_bm | PORT_ISC_BOTHEDGES_gc | PORT_OPC_PULLUP_gc; - PIN_PORT(MOTOR_ENABLE_PIN)->INTCTRL |= PORT_INT0LVL_HI_gc; - PIN_PORT(MOTOR_ENABLE_PIN)->INT0MASK |= PIN_BM(MOTOR_ENABLE_PIN); - - // Configure report clock - TCC1.INTCTRLA = TC_OVFINTLVL_LO_gc; - TCC1.PER = F_CPU / 256 * 0.01; // 10ms - TCC1.CTRLA = TC_CLKSEL_DIV256_gc; - - // Reset switch - DIRCLR_PIN(RESET_PIN); - PINCTRL_PIN(RESET_PIN) = - PORT_SRLEN_bm | PORT_ISC_RISING_gc | PORT_OPC_PULLUP_gc; - PIN_PORT(RESET_PIN)->INTCTRL |= PORT_INT0LVL_LO_gc; - PIN_PORT(RESET_PIN)->INT0MASK |= PIN_BM(RESET_PIN); - - printf("RESET\n"); - - sei(); -} - - -int main() { - init(); - - _splash(0x27); - _splash(0x3f); - - while (true) continue; - - return 0; -} diff --git a/src/py/bbctrl/Ctrl.py b/src/py/bbctrl/Ctrl.py index 43fa61f..fae382c 100644 --- a/src/py/bbctrl/Ctrl.py +++ b/src/py/bbctrl/Ctrl.py @@ -31,7 +31,6 @@ class Ctrl(object): self.avr = bbctrl.AVR(self) self.i2c = bbctrl.I2C(args.i2c_port, args.demo) - self.lcd = bbctrl.LCD(self) self.mach = bbctrl.Mach(self, self.avr) self.preplanner = bbctrl.Preplanner(self) if not args.demo: @@ -40,9 +39,6 @@ class Ctrl(object): self.mach.connect() - self.lcd.add_new_page(bbctrl.MainLCDPage(self)) - self.lcd.add_new_page(bbctrl.IPLCDPage(self.lcd)) - os.environ['GCODE_SCRIPT_PATH'] = self.get_upload() except Exception: diff --git a/src/py/bbctrl/IPLCDPage.py b/src/py/bbctrl/IPLCDPage.py deleted file mode 100644 index 4f5ee4e..0000000 --- a/src/py/bbctrl/IPLCDPage.py +++ /dev/null @@ -1,48 +0,0 @@ -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -import subprocess - -import bbctrl - - -class IPLCDPage(bbctrl.LCDPage): - # From bbctrl.LCDPage - def activate(self): - p = subprocess.Popen(['hostname', '-I'], stdout = subprocess.PIPE) - ips = p.communicate()[0].decode('utf-8').split() - - p = subprocess.Popen(['hostname'], stdout = subprocess.PIPE) - hostname = p.communicate()[0].decode('utf-8').strip() - - self.clear() - - self.text('Host: %s' % hostname[0:14], 0, 0) - - for i in range(min(3, len(ips))): - if len(ips[i]) <= 16: - self.text('IP: %s' % ips[i], 0, i + 1) diff --git a/src/py/bbctrl/Jog.py b/src/py/bbctrl/Jog.py index c4544e2..f198bdf 100644 --- a/src/py/bbctrl/Jog.py +++ b/src/py/bbctrl/Jog.py @@ -64,12 +64,6 @@ class Jog(inevent.JogHandler): self.processor = inevent.InEvent(ctrl.ioloop, self, types = ['js']) - def up(self): self.ctrl.lcd.page_up() - def down(self): self.ctrl.lcd.page_down() - def left(self): self.ctrl.lcd.page_left() - def right(self): self.ctrl.lcd.page_right() - - def callback(self): if self.v != self.lastV: self.lastV = self.v diff --git a/src/py/bbctrl/LCD.py b/src/py/bbctrl/LCD.py deleted file mode 100644 index 38f6adb..0000000 --- a/src/py/bbctrl/LCD.py +++ /dev/null @@ -1,207 +0,0 @@ -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -import lcd -import atexit - - -class LCDPage: - def __init__(self, lcd, text = None): - self.lcd = lcd - self.data = lcd.new_screen() - - if text is not None: - self.text(text, (lcd.width - len(text)) // 2, 1) - - - def activate(self): pass - def deactivate(self): pass - - - def put(self, c, x, y): - y += x // self.lcd.width - x %= self.lcd.width - y %= self.lcd.height - - if self.data[x][y] != c: - self.data[x][y] = c - if self == self.lcd.page: self.lcd.update() - - - def text(self, s, x, y): - for c in s: - self.put(c, x, y) - x += 1 - - - def clear(self): - self.data = self.lcd.new_screen() - self.lcd.redraw = True - - - def shift_left(self): pass - def shift_right(self): pass - def shift_up(self): pass - def shift_down(self): pass - - -class LCD: - def __init__(self, ctrl): - self.ctrl = ctrl - self.log = ctrl.log.get('LCD') - - self.addrs = self.ctrl.args.lcd_addr - self.addr = self.addrs[0] - self.addr_num = 0 - - self.width = 20 - self.height = 4 - self.lcd = None - self.timeout = None - self.reset = False - self.page = None - self.pages = [] - self.current_page = 0 - self.screen = self.new_screen() - self.set_message('Loading...') - - self._redraw(False) - if not ctrl.args.demo: atexit.register(self.goodbye) - - - def set_message(self, msg): - try: - self.load_page(LCDPage(self, msg)) - self._update() - except IOError as e: - self.log.warning('LCD communication failed: %s' % e) - - - def new_screen(self): - return [[' ' for y in range(self.height)] for x in range(self.width)] - - - def new_page(self): return LCDPage(self) - def add_page(self, page): self.pages.append(page) - - - def add_new_page(self, page = None): - if page is None: page = self.new_page() - page.id = len(self.pages) - self.add_page(page) - return page - - - def load_page(self, page): - if self.page != page: - if self.page is not None: self.page.deactivate() - page.activate() - self.page = page - self.redraw = True - self.update() - - - def set_current_page(self, current_page): - self.current_page = current_page % len(self.pages) - self.load_page(self.pages[self.current_page]) - - - def page_up(self): pass - def page_down(self): pass - def page_right(self): self.set_current_page(self.current_page + 1) - def page_left(self): self.set_current_page(self.current_page - 1) - - - def update(self): - if self.timeout is None: - self.timeout = self.ctrl.ioloop.call_later(0.25, self._update) - - - def _redraw(self, now = True): - if now: - self.redraw = True - self.update() - self.redraw_timer = self.ctrl.ioloop.call_later(5, self._redraw) - - - def _update(self): - self.timeout = None - - try: - if self.lcd is None: - self.lcd = lcd.LCD(self.ctrl.i2c, self.addr, self.height, - self.width) - - if self.reset: - self.lcd.reset() - self.redraw = True - self.reset = False - - cursorX, cursorY = -1, -1 - - for y in range(self.height): - for x in range(self.width): - c = self.page.data[x][y] - - if self.redraw or self.screen[x][y] != c: - if cursorX != x or cursorY != y: - self.lcd.goto(x, y) - cursorX, cursorY = x, y - - self.lcd.put_char(c) - cursorX += 1 - self.screen[x][y] = c - - self.redraw = False - - except IOError as e: - # Try next address - #self.addr_num += 1 - #if len(self.addrs) <= self.addr_num: self.addr_num = 0 - #self.addr = self.addrs[self.addr_num] - #self.lcd = None - - #self.log.warning('LCD communication failed, ' + - # 'retrying on address 0x%02x: %s' % (self.addr, e)) - - #self.log.warning('LCD not present.') - - #self.reset = True - self.reset = False - #self.timeout = self.ctrl.ioloop.call_later(1, self._update) - - - def goodbye(self, message = ''): - if self.timeout: - self.ctrl.ioloop.remove_timeout(self.timeout) - self.timeout = None - - if self.redraw_timer: - self.ctrl.ioloop.remove_timeout(self.redraw_timer) - self.redraw_timer = None - - if self.lcd is not None: self.set_message(message) diff --git a/src/py/bbctrl/MainLCDPage.py b/src/py/bbctrl/MainLCDPage.py deleted file mode 100644 index ba17391..0000000 --- a/src/py/bbctrl/MainLCDPage.py +++ /dev/null @@ -1,76 +0,0 @@ -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -import bbctrl - - -class MainLCDPage(bbctrl.LCDPage): - def __init__(self, ctrl): - bbctrl.LCDPage.__init__(self, ctrl.lcd) - - self.ctrl = ctrl - self.install = True - - ctrl.state.add_listener(self.update) - - - def update(self, update): - state = self.ctrl.state - - # Must be after machine vars have loaded - if self.install and hasattr(self, 'id'): - self.install = False - self.ctrl.lcd.set_current_page(self.id) - - self.text('%-9s' % state.get('xx', ''), 0, 0) - - metric = not state.get('imperial', False) - scale = 1 if metric else 25.4 - - # Show enabled axes - row = 0 - for axis in 'xyzabc': - if state.is_axis_faulted(axis): - self.text(' FAULT %s' % axis.upper(), 9, row) - row += 1 - - elif state.is_axis_enabled(axis): - position = state.get(axis + 'p', 0) - position += state.get('offset_' + axis, 0) - position /= scale - self.text('% 10.3f%s' % (position, axis.upper()), 9, row) - row += 1 - - while row < 4: - self.text(' ' * 11, 9, row) - row += 1 - - # Show tool, units, feed and speed - self.text('%2uT' % state.get('tool', 0), 6, 1) - self.text('%-6s' % 'MM' if metric else 'INCH', 0, 1) - self.text('%8uF' % (state.get('feed', 0) / scale), 0, 2) - self.text('%8dS' % state.get('speed', 0), 0, 3) diff --git a/src/py/bbctrl/Pwr.py b/src/py/bbctrl/Pwr.py index 9c4579a..32b46c6 100644 --- a/src/py/bbctrl/Pwr.py +++ b/src/py/bbctrl/Pwr.py @@ -68,7 +68,6 @@ class Pwr(): self.i2c_addr = ctrl.args.pwr_addr self.regs = [-1] * 9 - self.lcd_page = ctrl.lcd.add_new_page() self.failures = 0 self._update_cb(False) @@ -179,16 +178,6 @@ class Pwr(): self.failures = 0 return - self.lcd_page.text('%3dC Tmp' % self.regs[TEMP_REG], 0, 0) - self.lcd_page.text('%5.1fV In' % self.regs[VIN_REG], 0, 1) - self.lcd_page.text('%5.1fV Out' % self.regs[VOUT_REG], 0, 2) - self.lcd_page.text(' %04x Flg' % self.regs[FLAGS_REG], 0, 3) - - self.lcd_page.text('%5.1fA Mot' % self.regs[MOTOR_REG], 10, 0) - self.lcd_page.text('%5.1fA Ld1' % self.regs[LOAD1_REG], 10, 1) - self.lcd_page.text('%5.1fA Ld2' % self.regs[LOAD2_REG], 10, 2) - self.lcd_page.text('%5.1fA Vdd' % self.regs[VDD_REG], 10, 3) - if len(update): self.ctrl.state.update(update) self.failures = 0 diff --git a/src/py/bbctrl/Web.py b/src/py/bbctrl/Web.py index 148fcdd..1a96146 100644 --- a/src/py/bbctrl/Web.py +++ b/src/py/bbctrl/Web.py @@ -22,7 +22,6 @@ def call_get_output(cmd): class RebootHandler(bbctrl.APIHandler): def put_ok(self): - self.get_ctrl().lcd.goodbye('Rebooting...') subprocess.Popen('reboot') @@ -193,13 +192,11 @@ class FirmwareUpdateHandler(bbctrl.APIHandler): with open('firmware/update.tar.bz2', 'wb') as f: f.write(firmware['body']) - self.get_ctrl().lcd.goodbye('Upgrading firmware') subprocess.Popen(['/usr/local/bin/update-bbctrl']) class UpgradeHandler(bbctrl.APIHandler): def put_ok(self): - self.get_ctrl().lcd.goodbye('Upgrading firmware') subprocess.Popen(['/usr/local/bin/upgrade-bbctrl']) diff --git a/src/py/bbctrl/__init__.py b/src/py/bbctrl/__init__.py index b1a6452..c5cae69 100644 --- a/src/py/bbctrl/__init__.py +++ b/src/py/bbctrl/__init__.py @@ -40,7 +40,6 @@ from bbctrl.RequestHandler import RequestHandler from bbctrl.APIHandler import APIHandler from bbctrl.FileHandler import FileHandler from bbctrl.Config import Config -from bbctrl.LCD import LCD, LCDPage from bbctrl.Mach import Mach from bbctrl.Web import Web from bbctrl.Jog import Jog @@ -52,8 +51,6 @@ from bbctrl.Preplanner import Preplanner from bbctrl.State import State from bbctrl.Comm import Comm from bbctrl.CommandQueue import CommandQueue -from bbctrl.MainLCDPage import MainLCDPage -from bbctrl.IPLCDPage import IPLCDPage from bbctrl.Camera import Camera, VideoHandler from bbctrl.AVR import AVR from bbctrl.AVREmu import AVREmu @@ -132,8 +129,6 @@ def parse_args(): help = 'Serial baud rate') parser.add_argument('--i2c-port', default = 1, type = int, help = 'I2C port') - parser.add_argument('--lcd-addr', default = [0x27, 0x3f], type = int, - help = 'LCD I2C address') parser.add_argument('--avr-addr', default = 0x2b, type = int, help = 'AVR I2C address') parser.add_argument('--pwr-addr', default = 0x60, type = int, diff --git a/src/py/inevent/JogHandler.py b/src/py/inevent/JogHandler.py index f5fad5b..f03c5a8 100644 --- a/src/py/inevent/JogHandler.py +++ b/src/py/inevent/JogHandler.py @@ -72,12 +72,6 @@ class JogHandler: log.info(axes_to_string(self.axes) + ' x {:d}'.format(self.speed)) - def up(self): log.debug('up') - def down(self): log.debug('down') - def left(self): log.debug('left') - def right(self): log.debug('right') - - def reset(self): self.axes = [0.0, 0.0, 0.0, 0.0] self.speed = 3 @@ -105,17 +99,6 @@ class JogHandler: if event.type == EV_ABS and event.code in config['axes']: pass - elif event.type == EV_ABS and event.code in config['arrows']: - axis = config['arrows'].index(event.code) - - if event.value < 0: - if axis == 1: self.up() - else: self.left() - - elif 0 < event.value: - if axis == 1: self.down() - else: self.right() - elif event.type == EV_KEY and event.code in config['speed']: old_speed = self.speed self.speed = config['speed'].index(event.code) + 1 diff --git a/src/py/lcd/__init__.py b/src/py/lcd/__init__.py deleted file mode 100644 index 238a6e1..0000000 --- a/src/py/lcd/__init__.py +++ /dev/null @@ -1,236 +0,0 @@ -#!/usr/bin/env python3 - -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -import time -import logging - - -log = logging.getLogger('LCD') - - -# Control flags -REG_SELECT_BIT = 1 << 0 -READ_BIT = 1 << 1 -ENABLE_BIT = 1 << 2 -BACKLIGHT_BIT = 1 << 3 - -# Commands -LCD_CLEAR_DISPLAY = 1 << 0 -LCD_RETURN_HOME = 1 << 1 -LCD_ENTRY_MODE_SET = 1 << 2 -LCD_DISPLAY_CONTROL = 1 << 3 -LCD_CURSOR_SHIFT = 1 << 4 -LCD_FUNCTION_SET = 1 << 5 -LCD_SET_CGRAM_ADDR = 1 << 6 -LCD_SET_DDRAM_ADDR = 1 << 7 - -# Entry Mode Set flags -LCD_ENTRY_SHIFT_DISPLAY = 1 << 0 -LCD_ENTRY_SHIFT_INC = 1 << 1 -LCD_ENTRY_SHIFT_DEC = 0 << 1 - -# Display Control flags -LCD_BLINK_ON = 1 << 0 -LCD_BLINK_OFF = 0 << 0 -LCD_CURSOR_ON = 1 << 1 -LCD_CURSOR_OFF = 0 << 1 -LCD_DISPLAY_ON = 1 << 2 -LCD_DISPLAY_OFF = 0 << 2 - -# Cursor Shift flags -LCD_SHIFT_RIGHT = 1 << 2 -LCD_SHIFT_LEFT = 0 << 2 -LCD_SHIFT_DISPLAY = 1 << 3 -LCD_SHIFT_CURSOR = 0 << 3 - -# Function Set flags -LCD_5x11_DOTS = 1 << 2 -LCD_5x8_DOTS = 0 << 2 -LCD_2_LINE = 1 << 3 -LCD_1_LINE = 0 << 3 -LCD_8_BIT_MODE = 1 << 4 -LCD_4_BIT_MODE = 0 << 4 - -# Text justification flags -JUSTIFY_LEFT = 0 -JUSTIFY_RIGHT = 1 -JUSTIFY_CENTER = 2 - - - -class LCD: - def __init__(self, i2c, addr, height = 4, width = 20): - self.addr = addr - self.height = height - self.width = width - self.i2c = i2c - self.backlight = True - - self.reset() - - - def reset(self): - self.clear() - time.sleep(0.050) - self.write_nibble(3 << 4) # Home - time.sleep(0.050) - self.write_nibble(3 << 4) # Home - time.sleep(0.050) - self.write_nibble(3 << 4) # Home - self.write_nibble(2 << 4) # 4-bit - - self.write(LCD_FUNCTION_SET | LCD_2_LINE | LCD_5x8_DOTS | - LCD_4_BIT_MODE) - self.write(LCD_DISPLAY_CONTROL | LCD_DISPLAY_ON) - self.write(LCD_ENTRY_MODE_SET | LCD_ENTRY_SHIFT_INC) - - - def write_i2c(self, data): - if self.backlight: data |= BACKLIGHT_BIT - - self.i2c.write(self.addr, data) - time.sleep(0.0001) - - - # Write half of a command to LCD - def write_nibble(self, data): - self.write_i2c(data) - - # Strobe - self.write_i2c(data | ENABLE_BIT) - time.sleep(0.0005) - - self.write_i2c(data & ~ENABLE_BIT) - time.sleep(0.0001) - - - # Write an 8-bit command to LCD - def write(self, cmd, flags = 0): - self.write_nibble(flags | (cmd & 0xf0)) - self.write_nibble(flags | ((cmd << 4) & 0xf0)) - - - def set_cursor(self, on, blink): - data = LCD_DISPLAY_CONTROL - - if on: data |= LCD_CURSOR_ON - if blink: data |= LCD_BLINK_ON - - self.write(data) - - - def set_backlight(self, enable): - self.backlight = enable - self.write_i2c(0) - - - def program_char(self, addr, data): - if addr < 0 or 8 <= addr: return - - self.write(LCD_SET_CGRAM_ADDR | (addr << 3)) - for x in data: - self.write(x, REG_SELECT_BIT) - - - def goto(self, x, y): - if x < 0 or self.width <= x or y < 0 or self.height <= y: return - self.write(LCD_SET_DDRAM_ADDR | (0, 64, 20, 84)[y] + int(x)) - - - def put_char(self, c): - self.write(ord(c), REG_SELECT_BIT) - - - def text(self, msg, x = None, y = None): - if x is not None and y is not None: self.goto(x, y) - - for c in msg: self.put_char(c) - - - def display(self, line, msg, justify = JUSTIFY_LEFT): - if justify == JUSTIFY_RIGHT: x = self.width - len(msg) - elif justify == JUSTIFY_CENTER: x = (self.width - len(msg)) / 2 - else: x = 0 - - if x < 0: x = 0 - - self.text(msg, x, line) - - - def shift(self, count = 1, right = True, display = True): - cmd = LCD_CURSOR_SHIFT - if right: cmd |= LCD_SHIFT_RIGHT - if display: cmd |= LCD_SHIFT_DISPLAY - - for i in range(count): self.write(cmd) - - - # Clear LCD and move cursor home - def clear(self): - self.write(LCD_CLEAR_DISPLAY) - self.write(LCD_RETURN_HOME) - - - -if __name__ == "__main__": - lcd = LCD(1, 0x27) - - lcd.clear() - - lcd.program_char(0, (0b11011, - 0b11011, - 0b00000, - 0b01100, - 0b01100, - 0b00000, - 0b11011, - 0b11011)) - - lcd.program_char(1, (0b11000, - 0b01100, - 0b00110, - 0b00011, - 0b00011, - 0b00110, - 0b01100, - 0b11000)) - - lcd.program_char(2, (0b00011, - 0b00110, - 0b01100, - 0b11000, - 0b11000, - 0b01100, - 0b00110, - 0b00011)) - - lcd.display(0, '\0' * lcd.width) - lcd.display(1, 'Hello world!', JUSTIFY_CENTER) - lcd.display(2, '\1\2' * (lcd.width / 2)) - lcd.display(3, '12345678901234567890') diff --git a/src/py/lcd/splash.py b/src/py/lcd/splash.py deleted file mode 100644 index 203f60a..0000000 --- a/src/py/lcd/splash.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env python3 - -################################################################################ -# # -# This file is part of the Buildbotics firmware. # -# # -# Copyright (c) 2015 - 2018, Buildbotics LLC # -# All rights reserved. # -# # -# This file ("the software") is free software: you can redistribute it # -# and/or modify it under the terms of the GNU General Public License, # -# version 2 as published by the Free Software Foundation. You should # -# have received a copy of the GNU General Public License, version 2 # -# along with the software. If not, see . # -# # -# The software is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# Lesser General Public License for more details. # -# # -# You should have received a copy of the GNU Lesser General Public # -# License along with the software. If not, see # -# . # -# # -# For information regarding this software email: # -# "Joseph Coffland" # -# # -################################################################################ - -import lcd - -if __name__ == "__main__": - screen = lcd.LCD(1, 0x27) - - screen.clear() - screen.display(0, 'Buildbotics', lcd.JUSTIFY_CENTER) - screen.display(1, 'Controller', lcd.JUSTIFY_CENTER) - screen.display(3, 'Booting...', lcd.JUSTIFY_CENTER)