#include "boot.h"
#include "sp_driver.h"
+#include "lcd.h"
#include <util/delay.h>
#include <util/crc16.h>
}
+void lcd_splash(uint8_t addr) {
+ lcd_init(addr);
+ lcd_goto(addr, 1, 1);
+ lcd_pgmstr(addr, "Controller booting");
+ lcd_goto(addr, 3, 2);
+ lcd_pgmstr(addr, "Please wait...");
+}
+
+
bool uart_has_char() {return UART_DEVICE.STATUS & USART_RXCIF_bm;}
uint8_t uart_recv_char() {return UART_DEVICE.DATA;}
}
-int main() {
- // Init
- clock_init();
- uart_init();
- watchdog_init();
-
- // Check for trigger
- bool in_bootloader = false;
- uint16_t j = INITIAL_WAIT;
- while (!in_bootloader && 0 < j--) {
- if (uart_has_char()) in_bootloader = uart_recv_char() == CMD_SYNC;
- watchdog_reset();
- _delay_ms(1);
- }
-
- // Main bootloader
+void bootloader() {
uint32_t address = 0;
uint16_t i = 0;
- while (in_bootloader) {
+ while (true) {
uint8_t val = get_char();
watchdog_reset();
break;
case CMD_EXIT_BOOTLOADER:
- in_bootloader = false;
send_char(REPLY_ACK);
+ return;
break;
case CMD_PROGRAMMER_TYPE: send_char('S'); break; // serial
// Wait for any lingering SPM instructions to finish
nvm_wait();
}
+}
+
+
+int main() {
+ // Init
+ clock_init();
+ uart_init();
+ watchdog_init();
+
+ // Check for trigger
+ uint16_t j = INITIAL_WAIT;
+ while (0 < j--) {
+ if (uart_has_char() && uart_recv_char() == CMD_SYNC) {
+ bootloader();
+ break;
+ }
+
+ watchdog_reset();
+ _delay_ms(1);
+ }
// Deinit
uart_deinit();
// Disable further self programming until next reset
SP_LockSPM();
+ lcd_splash(0x27);
+ lcd_splash(0x3f);
+
// Jump to application code
asm("jmp 0");
}
--- /dev/null
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2017 Buildbotics LLC
+ Copyright (c) 2010 Alex Forencich <alex@alexforencich.com>
+ 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 <http://www.gnu.org/licenses/>.
+
+ 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
+ <http://www.gnu.org/licenses/>.
+
+ For information regarding this software email:
+ "Joseph Coffland" <joseph@buildbotics.com>
+
+\******************************************************************************/
+
+#include "lcd.h"
+
+#include <avr/io.h>
+#include <util/delay.h>
+
+#include <stdbool.h>
+
+
+void lcd_init(uint8_t addr) {
+ // Enable I2C master
+ TWIC.MASTER.BAUD = 0x9b; // 100 KHz with 32MHz clock
+ TWIC.MASTER.CTRLA = TWI_MASTER_ENABLE_bm;
+ TWIC.MASTER.CTRLB = TWI_MASTER_TIMEOUT_DISABLED_gc;
+ TWIC.MASTER.STATUS |= 1; // Force idle
+
+ _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 _write_i2c(uint8_t addr, uint8_t data) {
+ data |= BACKLIGHT_BIT;
+
+ TWIC.MASTER.ADDR = addr << 1;
+ while (!(TWIC.MASTER.STATUS & TWI_MASTER_WIF_bm)) continue;
+
+ TWIC.MASTER.DATA = data;
+ while (!(TWIC.MASTER.STATUS & TWI_MASTER_WIF_bm)) continue;
+
+ 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 (*s) lcd_putchar(addr, *s++);
+}
--- /dev/null
+/******************************************************************************\
+
+ This file is part of the Buildbotics firmware.
+
+ Copyright (c) 2015 - 2017 Buildbotics LLC
+ Copyright (c) 2010 Alex Forencich <alex@alexforencich.com>
+ 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 <http://www.gnu.org/licenses/>.
+
+ 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
+ <http://www.gnu.org/licenses/>.
+
+ For information regarding this software email:
+ "Joseph Coffland" <joseph@buildbotics.com>
+
+\******************************************************************************/
+
+#pragma once
+
+#include <avr/pgmspace.h>
+
+#include <stdint.h>
+
+
+// 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);
self.current_page = 0
self.screen = self.new_screen()
- self.set_message('Loading')
-
# Redraw screen every 5 seconds
self.redraw_timer = tornado.ioloop.PeriodicCallback(self._redraw, 5000,
self.ctrl.ioloop)
self.redraw_timer.stop()
self.redraw_timer = None
- if self.lcd is not None: self.set_message('Goodbye')
+ if self.lcd is not None: self.set_message('')