From d0801b36b47d8f3da610597160fde92059fd7e62 Mon Sep 17 00:00:00 2001
From: Nao Pross <naopross@thearcway.org>
Date: Mon, 7 Aug 2017 19:27:05 +0200
Subject: implementation for avr programmer

the programmer will receive the binary in blocks of defined size
by a program under sw/programmer/linux (moved from sw/linux).
---
 sw/linux/config.h                     |  26 ----
 sw/linux/configure.ac                 |  23 ----
 sw/linux/makefile.am                  |   2 -
 sw/linux/reading_links.txt            |   4 -
 sw/linux/src/main.c                   |  13 --
 sw/linux/src/makefile.am              |   7 --
 sw/linux/src/serial.c                 |  42 -------
 sw/linux/src/serial.h                 |  17 ---
 sw/linux/src/ui.c                     |  90 --------------
 sw/linux/src/ui.h                     |  17 ---
 sw/linux/src/z80prog                  | Bin 34688 -> 0 bytes
 sw/linux/src/z80prog.ui               | 222 ----------------------------------
 sw/programmer/avr/fileinfo.h          |  13 ++
 sw/programmer/avr/main.c              | 109 +++++++++++++++++
 sw/programmer/avr/makefile            |  31 +++++
 sw/programmer/avr/usart.c             | 107 ++++++++++++++++
 sw/programmer/avr/usart.h             |  96 +++++++++++++++
 sw/programmer/linux/config.h          |  26 ++++
 sw/programmer/linux/configure.ac      |  23 ++++
 sw/programmer/linux/makefile.am       |   2 +
 sw/programmer/linux/reading_links.txt |   4 +
 sw/programmer/linux/src/main.c        |  13 ++
 sw/programmer/linux/src/makefile.am   |   7 ++
 sw/programmer/linux/src/serial.c      |  42 +++++++
 sw/programmer/linux/src/serial.h      |  17 +++
 sw/programmer/linux/src/ui.c          |  90 ++++++++++++++
 sw/programmer/linux/src/ui.h          |  17 +++
 sw/programmer/linux/src/z80prog       | Bin 0 -> 34688 bytes
 sw/programmer/linux/src/z80prog.ui    | 222 ++++++++++++++++++++++++++++++++++
 29 files changed, 819 insertions(+), 463 deletions(-)
 delete mode 100644 sw/linux/config.h
 delete mode 100644 sw/linux/configure.ac
 delete mode 100644 sw/linux/makefile.am
 delete mode 100644 sw/linux/reading_links.txt
 delete mode 100644 sw/linux/src/main.c
 delete mode 100644 sw/linux/src/makefile.am
 delete mode 100644 sw/linux/src/serial.c
 delete mode 100644 sw/linux/src/serial.h
 delete mode 100644 sw/linux/src/ui.c
 delete mode 100644 sw/linux/src/ui.h
 delete mode 100755 sw/linux/src/z80prog
 delete mode 100644 sw/linux/src/z80prog.ui
 create mode 100644 sw/programmer/avr/fileinfo.h
 create mode 100644 sw/programmer/avr/main.c
 create mode 100644 sw/programmer/avr/makefile
 create mode 100644 sw/programmer/avr/usart.c
 create mode 100644 sw/programmer/avr/usart.h
 create mode 100644 sw/programmer/linux/config.h
 create mode 100644 sw/programmer/linux/configure.ac
 create mode 100644 sw/programmer/linux/makefile.am
 create mode 100644 sw/programmer/linux/reading_links.txt
 create mode 100644 sw/programmer/linux/src/main.c
 create mode 100644 sw/programmer/linux/src/makefile.am
 create mode 100644 sw/programmer/linux/src/serial.c
 create mode 100644 sw/programmer/linux/src/serial.h
 create mode 100644 sw/programmer/linux/src/ui.c
 create mode 100644 sw/programmer/linux/src/ui.h
 create mode 100755 sw/programmer/linux/src/z80prog
 create mode 100644 sw/programmer/linux/src/z80prog.ui

(limited to 'sw')

diff --git a/sw/linux/config.h b/sw/linux/config.h
deleted file mode 100644
index d319f43..0000000
--- a/sw/linux/config.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* config.h.  Generated from config.h.in by configure.  */
-/* config.h.in.  Generated from configure.ac by autoheader.  */
-
-/* Name of package */
-#define PACKAGE "z80prog"
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT "naopross@tharcway.org"
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME "z80prog"
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "z80prog 0.1"
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "z80prog"
-
-/* Define to the home page for this package. */
-#define PACKAGE_URL ""
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION "0.1"
-
-/* Version number of package */
-#define VERSION "0.1"
diff --git a/sw/linux/configure.ac b/sw/linux/configure.ac
deleted file mode 100644
index a5c4b3b..0000000
--- a/sw/linux/configure.ac
+++ /dev/null
@@ -1,23 +0,0 @@
-AC_CONFIG_SRCDIR([src])
-AC_CONFIG_HEADERS([config.h])
-AC_CONFIG_MACRO_DIR([m4])
-AC_CONFIG_AUX_DIR([build-aux])
-
-AC_INIT([z80prog], [0.1], [naopross@tharcway.org])
-AM_INIT_AUTOMAKE([-Wall -Werror foreign])
-
-AC_PROG_CC
-
-####
-# Check for required packages / libraries
-#
-LIBGTK_REQUIRED=2.91
-
-PKG_CHECK_MODULES(gtk3, [gtk+-3.0 >= $LIBGTK_REQUIRED])
-
-AC_CONFIG_FILES([
-    makefile
-    src/makefile
-])
-
-AC_OUTPUT
diff --git a/sw/linux/makefile.am b/sw/linux/makefile.am
deleted file mode 100644
index 4d27cea..0000000
--- a/sw/linux/makefile.am
+++ /dev/null
@@ -1,2 +0,0 @@
-SUBDIRS = src
-CLEANFILES  = *~
diff --git a/sw/linux/reading_links.txt b/sw/linux/reading_links.txt
deleted file mode 100644
index 83c62f4..0000000
--- a/sw/linux/reading_links.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-https://developer.gnome.org/gtk3/stable/ch01s04.html#id-1.2.3.12.5
-https://developer.gnome.org/gio/unstable/GApplication.html
-https://git.gnome.org/browse/gnome-hello/tree/src/app.c
-
diff --git a/sw/linux/src/main.c b/sw/linux/src/main.c
deleted file mode 100644
index 769992a..0000000
--- a/sw/linux/src/main.c
+++ /dev/null
@@ -1,13 +0,0 @@
-#include "config.h"
-#include "ui.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdbool.h>
-
-int main(int argc, char *argv[])
-{
-    ui_init(&argc, &argv);
-    return 0;
-}
-
diff --git a/sw/linux/src/makefile.am b/sw/linux/src/makefile.am
deleted file mode 100644
index 492c3ec..0000000
--- a/sw/linux/src/makefile.am
+++ /dev/null
@@ -1,7 +0,0 @@
-bin_PROGRAMS = z80prog
-z80prog_SOURCES = main.c ui.c serial.c
-
-z80prog_CFLAGS = -Wall -Werror -g $(gtk3_CFLAGS)
-z80prog_LDADD = $(gtk3_LIBS)
-
-CLEANFILES = *~
diff --git a/sw/linux/src/serial.c b/sw/linux/src/serial.c
deleted file mode 100644
index 564676b..0000000
--- a/sw/linux/src/serial.c
+++ /dev/null
@@ -1,42 +0,0 @@
-#include "serial.h"
-
-int serial_connect(const char *devpath, long baudrate)
-{
-    int fd;
-    struct termios tty;
-    // struct termios tty_old;
-    
-    // open device
-    if ((fd = open(devpath, O_RDWR | O_NOCTTY)) < 0) {
-        return -1;
-    }
-
-    // set parameters
-    if (tcgetattr(fd, &tty) != 0) {
-        return -1;
-    }
-
-    // TODO: update UI or add support for custom baudrate
-    // cfsetospeed(&tty, 
-    // cfsetispeed(&tty, 
-
-    tty.c_cflag &= ~PARENB;  // no parity
-    tty.c_cflag &= ~CSTOPB;  // no stop bit
-    tty.c_cflag |= CS8;      // 8 bit data
-    tty.c_cflag &= ~CRTSCTS; // no flow control
-
-    tty.c_lflag     =  0;  // no signaling chars, no echo, no canonical processing
-    tty.c_oflag     =  0;  // no remapping, no delays
-    tty.c_cc[VMIN]  =  0;  // no block read
-    tty.c_cc[VTIME] = .5;  // .5 seconds read timeout
-
-    tty.c_cflag |= CREAD | CLOCAL;      // turn on read and ignore ctrl lines
-    tty.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl
-    tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // make raw
-    tty.c_oflag &= ~OPOST; // make raw
-
-    tcflush(fd , TCIFLUSH);
-    // if (tcsetaddr(
-
-    return fd;
-}
diff --git a/sw/linux/src/serial.h b/sw/linux/src/serial.h
deleted file mode 100644
index 6123e42..0000000
--- a/sw/linux/src/serial.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef __Z80PROG_SERIAL_H__
-#define __Z80PROG_SERIAL_H__
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <termios.h>
-
-int serial_connect(const char *devpath, long baudrate);
-void serial_close(int fd);
-
-void serial_program(const char *rompath);
-void serial_read_rom(const char *rom);
-
-#endif
diff --git a/sw/linux/src/ui.c b/sw/linux/src/ui.c
deleted file mode 100644
index b33aa04..0000000
--- a/sw/linux/src/ui.c
+++ /dev/null
@@ -1,90 +0,0 @@
-#include "ui.h"
-
-static bool ui_connected, ui_fileset;
-static GtkTextBuffer *ui_logbuf;
-static GtkBuilder *ui_builder;
-
-void ui_init(int *argc, char **argv[])
-{
-    GtkWindow *window;
-    GtkTextView *logview;
-    GtkFileChooserButton *filechoosebtn;
-    GtkButton *connectbtn, *flashbtn;
-
-    /* set ui global variables */
-    ui_connected = ui_fileset = false;
-
-    /* start gtk */
-    gtk_init(argc, argv);
-
-    /* load glade gtk ui */
-    ui_builder = gtk_builder_new();
-    gtk_builder_add_from_file(ui_builder, "gbprog.ui", NULL);
-
-    /* connect logger buffer (extern variable) */
-    ui_logbuf = gtk_text_buffer_new(NULL);
-    logview = GTK_TEXT_VIEW(gtk_builder_get_object(ui_builder, "logview"));
-
-    gtk_text_view_set_buffer(logview, ui_logbuf);
-
-    /* connect objects to function calls */
-    // window
-    window = GTK_WINDOW(gtk_builder_get_object(ui_builder, "window"));
-    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
-
-    // connectbtn 
-    connectbtn = GTK_BUTTON(gtk_builder_get_object(ui_builder, "flashbtn"));
-    g_signal_connect(connectbtn, "clicked", 
-                        G_CALLBACK(ui_connect_clicked), NULL);
-
-    // flashbtn
-    flashbtn = GTK_BUTTON(gtk_builder_get_object(ui_builder, "flashbtn"));
-    g_signal_connect(flashbtn, "clicked", G_CALLBACK(ui_flash_clicked), NULL);
-
-    // file chooser
-    filechoosebtn = GTK_FILE_CHOOSER_BUTTON(
-            gtk_builder_get_object(ui_builder, "filechoosebtn"));
-    g_signal_connect(filechoosebtn, "file-set", G_CALLBACK(ui_file_set), NULL);
-
-    /* start gtk window */
-    gtk_main();
-}
-
-void ui_log(const char *msg, char type) 
-{
-    GtkTextIter end;
-    gchar typech[4] = "[ ] ";
-
-    switch (type) {
-        case 'm': typech[1] = '@'; break; // message
-        case 'w': typech[1] = '#'; break; // warning
-        case 'e': typech[1] = '!'; break; // error
-    }
-
-    gtk_text_buffer_get_end_iter(ui_logbuf, &end);
-    gtk_text_buffer_insert(ui_logbuf, &end, typech, 4);
-    gtk_text_buffer_get_end_iter(ui_logbuf, &end);
-    gtk_text_buffer_insert(ui_logbuf, &end, (const gchar *) msg, strlen(msg));
-}
-
-void ui_file_set(GtkFileChooserButton *btn, gpointer user_data)
-{
-    GtkEntry *filepath = 
-            GTK_ENTRY(gtk_builder_get_object(ui_builder, "filepath"));
-
-    gtk_entry_set_text(filepath, 
-            gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(btn)));
-
-    ui_log("File set\n", 'm');
-    ui_fileset = true;
-}
-
-void ui_connect_clicked(void) 
-{
-
-}
-
-void ui_flash_clicked(void)
-{
-
-}
diff --git a/sw/linux/src/ui.h b/sw/linux/src/ui.h
deleted file mode 100644
index 44314d6..0000000
--- a/sw/linux/src/ui.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef __Z80PROG_UI_H__
-#define __Z80PROG_UI_H_
-
-#include <stdbool.h>
-#include <string.h>
-
-#include <gtk/gtk.h>
-
-void ui_init(int *argc, char **argv[]);
-void ui_log(const char *msg, char type);
-
-void ui_file_set(GtkFileChooserButton *btn, gpointer user_data);
-
-void ui_connect_clicked(void);
-void ui_flash_clicked(void);
-
-#endif
diff --git a/sw/linux/src/z80prog b/sw/linux/src/z80prog
deleted file mode 100755
index 878683b..0000000
Binary files a/sw/linux/src/z80prog and /dev/null differ
diff --git a/sw/linux/src/z80prog.ui b/sw/linux/src/z80prog.ui
deleted file mode 100644
index 3735efa..0000000
--- a/sw/linux/src/z80prog.ui
+++ /dev/null
@@ -1,222 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.20.0 -->
-<interface>
-  <requires lib="gtk+" version="3.12"/>
-  <object class="GtkAdjustment" id="baudrateadjust">
-    <property name="upper">1000000</property>
-    <property name="value">9600</property>
-    <property name="step_increment">1</property>
-    <property name="page_increment">10</property>
-  </object>
-  <object class="GtkFileFilter" id="gbbinfilter">
-    <patterns>
-      <pattern>*.bin</pattern>
-      <pattern>*.gb</pattern>
-      <pattern>*.gba</pattern>
-      <pattern>*.gbc</pattern>
-      <pattern>*.hex</pattern>
-    </patterns>
-  </object>
-  <object class="GtkWindow" id="window">
-    <property name="width_request">450</property>
-    <property name="height_request">250</property>
-    <property name="visible">True</property>
-    <property name="can_focus">False</property>
-    <property name="title" translatable="yes">Z80 ROM Programmer</property>
-    <property name="default_width">450</property>
-    <property name="default_height">200</property>
-    <child>
-      <object class="GtkBox" id="mainbox">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="margin_left">10</property>
-        <property name="margin_right">10</property>
-        <property name="margin_top">10</property>
-        <property name="margin_bottom">10</property>
-        <property name="orientation">vertical</property>
-        <property name="spacing">10</property>
-        <child>
-          <object class="GtkBox" id="devbox">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="spacing">10</property>
-            <child>
-              <object class="GtkEntry" id="devpath">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="placeholder_text" translatable="yes">Enter path</property>
-              </object>
-              <packing>
-                <property name="expand">True</property>
-                <property name="fill">True</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkSpinButton" id="devbaudrate">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="width_chars">0</property>
-                <property name="max_width_chars">7</property>
-                <property name="overwrite_mode">True</property>
-                <property name="placeholder_text" translatable="yes">9600</property>
-                <property name="input_purpose">number</property>
-                <property name="adjustment">baudrateadjust</property>
-                <property name="climb_rate">10</property>
-                <property name="snap_to_ticks">True</property>
-                <property name="numeric">True</property>
-                <property name="update_policy">if-valid</property>
-                <property name="value">9600</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkButton" id="connectbtn">
-                <property name="label">gtk-connect</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="use_stock">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">2</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">True</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkBox" id="filebox">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="spacing">10</property>
-            <child>
-              <object class="GtkEntry" id="filepath">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="placeholder_text" translatable="yes">Binary Path</property>
-              </object>
-              <packing>
-                <property name="expand">True</property>
-                <property name="fill">True</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkFileChooserButton" id="filechoosebtn">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="filter">gbbinfilter</property>
-                <property name="title" translatable="yes"/>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">True</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkBox" id="flashbox">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="orientation">vertical</property>
-            <property name="spacing">10</property>
-            <child>
-              <object class="GtkProgressBar" id="flashbar">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="show_text">True</property>
-                <property name="ellipsize">start</property>
-              </object>
-              <packing>
-                <property name="expand">True</property>
-                <property name="fill">True</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkButton" id="flashbtn">
-                <property name="label" translatable="yes">Flash</property>
-                <property name="visible">True</property>
-                <property name="sensitive">False</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">True</property>
-            <property name="position">2</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkScrolledWindow" id="logscrolled">
-            <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="shadow_type">in</property>
-            <child>
-              <object class="GtkViewport" id="logviewport">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <child>
-                  <object class="GtkExpander" id="logexpander">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="expanded">True</property>
-                    <property name="label_fill">True</property>
-                    <property name="resize_toplevel">True</property>
-                    <child>
-                      <object class="GtkTextView" id="logview">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="hexpand">True</property>
-                        <property name="vexpand">True</property>
-                        <property name="editable">False</property>
-                        <property name="monospace">True</property>
-                      </object>
-                    </child>
-                    <child type="label">
-                      <object class="GtkLabel" id="loglabel">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="label" translatable="yes">Logs</property>
-                      </object>
-                    </child>
-                  </object>
-                </child>
-              </object>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">True</property>
-            <property name="fill">True</property>
-            <property name="position">4</property>
-          </packing>
-        </child>
-      </object>
-    </child>
-  </object>
-</interface>
diff --git a/sw/programmer/avr/fileinfo.h b/sw/programmer/avr/fileinfo.h
new file mode 100644
index 0000000..6c831ed
--- /dev/null
+++ b/sw/programmer/avr/fileinfo.h
@@ -0,0 +1,13 @@
+#ifndef __FILEINFO_H__
+#define __FILEINFO_H__
+
+#include <stdio.h>
+
+struct file_info
+{
+    size_t size;
+    size_t blklen;
+    uint16_t start_addr;
+};
+
+#endif 
diff --git a/sw/programmer/avr/main.c b/sw/programmer/avr/main.c
new file mode 100644
index 0000000..90d05fa
--- /dev/null
+++ b/sw/programmer/avr/main.c
@@ -0,0 +1,109 @@
+#include "fileinfo.h"
+#include "usart.h"
+#include <util/delay.h>
+
+#define EEPROM_TICK_MS  10
+
+#define ADDRCR      PORTB
+#define EEPROMCR    PORTC
+#define EEPROMDR    PORTD
+
+#define ADDR_BIT    0
+#define ADDR_EL     3
+#define ADDR_EH     4
+#define ADDR_DL     5
+#define ADDR_DH     6
+
+#define EEPROM_WR   0
+#define EEPROM_RD   1
+#define EEPROM_CLK  2
+
+
+void eeprom_write(uint16_t addr, uint8_t byte);
+void eeprom_tick();
+
+int main(void)
+{
+    uint8_t *buffer, i;
+    uint16_t addr;
+    size_t read;
+
+    struct file_info *finfo =  malloc(sizeof(struct file_info));
+
+    DDRB = 0x7F;
+    DDRC = 0x83;
+    DDRD = 0xFC;
+
+    /* get configuration */
+    usart_init(1200); 
+
+    usart_print("EEPROM Programmer\n\r");
+
+    do {
+        usart_print("Waiting for configuration\n\r");
+        read = usart_read((uint8_t *) finfo, sizeof(struct file_info));
+    } while (read != sizeof(struct file_info));
+
+    usart_print("Programmer Ready\n<waiting for binary>\n\r");
+
+    buffer = malloc(finfo->blklen);
+    addr = finfo->start_addr;
+
+    /* read file */
+    while ((read = usart_read(buffer, finfo->blklen))) {
+        for (i = 0; i < read; i++) {
+            eeprom_write(addr + i, *(buffer++));
+        }
+
+        addr += finfo->blklen;
+    }
+
+    return 0;
+}
+
+
+void eeprom_write(uint16_t addr, uint8_t byte)
+{
+    int bit;
+
+    /* set address */
+    for (bit = 0; bit < 8; bit++) {
+        // clear bit
+        ADDRCR &= ~0x07;
+        // select the bit
+        ADDRCR |= bit;
+
+        // write bit for lower byte
+        if (addr & _BV(bit))
+            ADDRCR |= _BV(ADDR_DL);
+        else
+            ADDRCR &= ~_BV(ADDR_DL);
+
+        // write bit for higher byte
+        if ((addr>>8) & _BV(bit))
+            ADDRCR |= _BV(ADDR_DH);
+        else
+            ADDRCR &= ~_BV(ADDR_DH);
+    }
+
+    /* set data */
+    EEPROMDR = byte;
+    EEPROMCR &= ~(_BV(ADDR_EH) | _BV(ADDR_EL));
+
+    /* write eeprom */
+    EEPROMCR &= ~_BV(EEPROM_WR);
+    eeprom_tick();
+
+    EEPROMCR |= _BV(EEPROM_WR);
+    EEPROMCR |= _BV(ADDR_EH) | _BV(ADDR_EL);
+}
+
+/* pulse the clock line for the eeprom */
+void eeprom_tick()
+{
+    EEPROMCR |= _BV(EEPROM_CLK);
+    _delay_ms(EEPROM_TICK_MS);         
+    EEPROMCR &= ~_BV(EEPROM_CLK);
+    _delay_ms(EEPROM_TICK_MS);         
+}
+
diff --git a/sw/programmer/avr/makefile b/sw/programmer/avr/makefile
new file mode 100644
index 0000000..95fb5fe
--- /dev/null
+++ b/sw/programmer/avr/makefile
@@ -0,0 +1,31 @@
+###
+# Project settings
+#
+TARGET := programmer
+SOURCES := $(wildcard *.c)
+
+###
+# Compiler settings
+#
+CC   := avr-gcc
+PORT := /dev/ttyUSB0
+MCU  := atmega328p
+
+CFLAGS  := -g -Wall -mcall-prologues -mmcu=$(MCU) -Os -I . \
+			-DF_CPU=1000000UL
+LDFLAGS := -Wl,-gc-sections -Wl,-relax
+
+.PHONY: all clean program
+all: $(TARGET).hex
+
+clean:
+	rm -f *.o *.hex *.obj *.bin
+
+$(TARGET).hex: $(TARGET).bin
+	avr-objcopy -R .eeprom -O ihex $(TARGET).bin $@
+
+$(TARGET).bin: $(SOURCES)
+	$(CC) $(CFLAGS) $(SOURCES) -o $@ $(LDFLAGS)
+
+program: $(TARGET).hex
+	avrdude -p $(MCU) -c usbasp -P usb -U flash:w:$(TARGET).hex
diff --git a/sw/programmer/avr/usart.c b/sw/programmer/avr/usart.c
new file mode 100644
index 0000000..8c2eb38
--- /dev/null
+++ b/sw/programmer/avr/usart.c
@@ -0,0 +1,107 @@
+#include "usart.h"
+
+static uint16_t usart_baudrate;
+static uint16_t usart_baud_prescale;
+
+void usart_init(uint16_t baudrate)
+{
+    // enable RX and TX
+    UCSR0B |= _BV(RXEN0) | _BV(TXEN0);
+    
+    // set 8 bit size char
+    UCSR0C |= _BV(UCSZ01) | _BV(UCSZ00);
+
+    // set baudrate 
+    usart_baudrate = baudrate;
+    usart_baud_prescale = (F_CPU / (usart_baudrate * 16)) -1;
+    
+    UBRR0L = usart_baud_prescale;
+    UBRR0H = usart_baud_prescale >> 8;
+}
+
+void usart_send_byte(uint8_t data)
+{
+    while (!(UCSR0A & _BV(UDRE0)));
+    UDR0 = data;
+}
+
+void usart_send(uint8_t *data, size_t len)
+{
+    uint8_t *p = data;
+
+    while (len--) {
+        usart_send_byte(*(p++));
+    }
+}
+
+void usart_print(char *str)
+{
+    char *p = str;
+    size_t len = 0;
+
+    while (*p++ != '\0') {
+        len++;
+    }
+
+    usart_send((uint8_t *) str, len);
+}
+
+int usart_read_byte(uint8_t *byte)
+{
+    uint16_t timeout = USART_TIMEOUT;
+
+    do {
+        if (UCSR0A & _BV(RXC0)) {
+            *byte = UDR0;
+            return 0;
+        }
+    } while (timeout--);
+
+    return -1;
+}
+
+uint8_t usart_read_byte_nt(void)
+{
+    while ((UCSR0A & _BV(RXC0)) == 0);
+    return UDR0;
+}
+
+
+size_t usart_read(uint8_t *buffer, size_t len)
+{
+    size_t read = 0;
+    uint8_t *p = buffer;
+
+    while (len--) {
+        if (usart_read_byte(p)  == 0) {
+            p++; 
+            read++;
+        }
+    }
+
+    return read;
+}
+
+int usart_read_line(uint8_t *buffer, size_t len)
+{
+    uint8_t ch;
+    uint8_t *p = buffer;
+    size_t read = 0;
+
+    while (len--) {
+        if (usart_read_byte(&ch) != 0)
+            continue;
+        else
+            read++;
+
+        if (ch == '\n')
+            break;
+        else
+            *(p++) = ch;
+    }
+
+    if (ch != '\n')
+        return -1;
+
+    return 0;
+}
diff --git a/sw/programmer/avr/usart.h b/sw/programmer/avr/usart.h
new file mode 100644
index 0000000..1bb6607
--- /dev/null
+++ b/sw/programmer/avr/usart.h
@@ -0,0 +1,96 @@
+#ifndef __USART_H__
+#define __USART_H__
+/*** 
+ * USART REGISTERS {{{
+ *
+ * UCSR: control and status regisers, composed from 3 registers:
+ *  +------------------------------------------------------------------------+
+ *  | UCSRA :| RXC   | TXC   | UDRE  | FE    | DOR   | PE    | U2X   | MPCM  | 
+ *  +------------------------------------------------------------------------+
+ *   UCSRA is a status register (read only)
+ *   Relevant bits:
+ *       - RXC : set to 1 if data is present on the receive buffer
+ *       - TXC : set to 1 when data is transferred to the transfer register 
+ *       - UDRE: set to 1 when trasmit buffer is empty (data sent)
+ *  +------------------------------------------------------------------------+
+ *  | UCSRB :| RXCIE | TXCIE | UDRIE | RXEN  | TXEN  | UCSZ2 | RXB8  | TXB8  | 
+ *  +------------------------------------------------------------------------+
+ *   UCSRB is used to setup hardware configuration
+ *   Relevant bits:
+ *       - RXCIE: RX complete interrupt enabled when set to 1
+ *       - TXCIE: TX complete interrupt enabled when set to 1
+ *       - UDRIE: data register empty interrupt enabled when set to 1
+ *       - RXEN : uart receiver enabled  when set to 1
+ *       - TXEN : uart transmitter enabled when set to 1
+ *  +------------------------------------------------------------------------+
+ *  | UCSRC :| URSEL | UMSEL | UPM1  | UPM0  | USBS  | UCSZ1 | UCSZ0 | UCPOL | 
+ *  +------------------------------------------------------------------------+
+ *   UCSRB is used to setup protocol configuration
+ *   Relevant bits:
+ *       - URSEL: register select (location is shared with UBRRH and UCSRC)
+ *       - UMSEL: mode select
+ *              1 -> synchronous
+ *              0 -> asynchronous
+ *       - UMP1 + UPM0: set parity
+ *              00 -> no parity
+ *              01 -> reserved
+ *              10 -> even
+ *              11 -> odd
+ *       - UCSZ2 + UCSZ1 + UCSZ0: set data frame (char size)
+ *              000 -> 5 bit
+ *              001 -> 6 bit
+ *              010 -> 7 bit
+ *              011 -> 8 bit
+ *              100 to 110 -> reserved
+ *              111 -> 9 bit
+ *
+ * UBRR: baudrate register
+ *  +------------------------------------------------------------------------+
+ *  | UBRRH :| URSEL |       |       |       | UBRR11| UBRR10| UBRR9 | UBRR8 | 
+ *  +------------------------------------------------------------------------+
+ *  | UBRRL :| UBRR7 | UBRR6 | UBRR5 | UBRR4 | UBRR3 | UBRR2 | UBRR1 | UBRR0 | 
+ *  +------------------------------------------------------------------------+
+ *    UBRR is composed of 2 8 bit registers to store a 12 bit baudrate value.
+ *    The value to be stored in this register is calculated with the following
+ *    formula (approximate to integer):
+ *       UBRR = ( XTAL_frequency ) / ( 16 * BAUDRATE ) -1
+ *
+ *    in C code corresponds to:
+ *       #define USART_BAUDRATE 9600
+ *       #define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
+ *
+ *    Relevant bits:
+ *       - URSEL: register select (location is share with UCSRC)
+ *
+ * UDR : data register
+ *   This register is shared between RX and TX
+ *
+ * }}}
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <avr/io.h>
+
+#define USART_TIMEOUT   5000
+
+// struct usart_conf
+// {
+//     uint16_t baudrate;
+// };
+
+void usart_init(uint16_t baudrate);
+// void usart_init_conf(struct usart_conf *conf);
+
+void usart_send_byte(uint8_t data);
+void usart_send(uint8_t *data, size_t len);
+
+void usart_print(char *str);
+
+int usart_read_byte(uint8_t *byte);
+uint8_t usart_read_byte_nt(void);
+size_t usart_read(uint8_t *buffer, size_t len);
+int uart_read_line(uint8_t *buffer, size_t len);
+
+#endif
diff --git a/sw/programmer/linux/config.h b/sw/programmer/linux/config.h
new file mode 100644
index 0000000..d319f43
--- /dev/null
+++ b/sw/programmer/linux/config.h
@@ -0,0 +1,26 @@
+/* config.h.  Generated from config.h.in by configure.  */
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Name of package */
+#define PACKAGE "z80prog"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "naopross@tharcway.org"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "z80prog"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "z80prog 0.1"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "z80prog"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "0.1"
+
+/* Version number of package */
+#define VERSION "0.1"
diff --git a/sw/programmer/linux/configure.ac b/sw/programmer/linux/configure.ac
new file mode 100644
index 0000000..a5c4b3b
--- /dev/null
+++ b/sw/programmer/linux/configure.ac
@@ -0,0 +1,23 @@
+AC_CONFIG_SRCDIR([src])
+AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_MACRO_DIR([m4])
+AC_CONFIG_AUX_DIR([build-aux])
+
+AC_INIT([z80prog], [0.1], [naopross@tharcway.org])
+AM_INIT_AUTOMAKE([-Wall -Werror foreign])
+
+AC_PROG_CC
+
+####
+# Check for required packages / libraries
+#
+LIBGTK_REQUIRED=2.91
+
+PKG_CHECK_MODULES(gtk3, [gtk+-3.0 >= $LIBGTK_REQUIRED])
+
+AC_CONFIG_FILES([
+    makefile
+    src/makefile
+])
+
+AC_OUTPUT
diff --git a/sw/programmer/linux/makefile.am b/sw/programmer/linux/makefile.am
new file mode 100644
index 0000000..4d27cea
--- /dev/null
+++ b/sw/programmer/linux/makefile.am
@@ -0,0 +1,2 @@
+SUBDIRS = src
+CLEANFILES  = *~
diff --git a/sw/programmer/linux/reading_links.txt b/sw/programmer/linux/reading_links.txt
new file mode 100644
index 0000000..83c62f4
--- /dev/null
+++ b/sw/programmer/linux/reading_links.txt
@@ -0,0 +1,4 @@
+https://developer.gnome.org/gtk3/stable/ch01s04.html#id-1.2.3.12.5
+https://developer.gnome.org/gio/unstable/GApplication.html
+https://git.gnome.org/browse/gnome-hello/tree/src/app.c
+
diff --git a/sw/programmer/linux/src/main.c b/sw/programmer/linux/src/main.c
new file mode 100644
index 0000000..769992a
--- /dev/null
+++ b/sw/programmer/linux/src/main.c
@@ -0,0 +1,13 @@
+#include "config.h"
+#include "ui.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+
+int main(int argc, char *argv[])
+{
+    ui_init(&argc, &argv);
+    return 0;
+}
+
diff --git a/sw/programmer/linux/src/makefile.am b/sw/programmer/linux/src/makefile.am
new file mode 100644
index 0000000..492c3ec
--- /dev/null
+++ b/sw/programmer/linux/src/makefile.am
@@ -0,0 +1,7 @@
+bin_PROGRAMS = z80prog
+z80prog_SOURCES = main.c ui.c serial.c
+
+z80prog_CFLAGS = -Wall -Werror -g $(gtk3_CFLAGS)
+z80prog_LDADD = $(gtk3_LIBS)
+
+CLEANFILES = *~
diff --git a/sw/programmer/linux/src/serial.c b/sw/programmer/linux/src/serial.c
new file mode 100644
index 0000000..564676b
--- /dev/null
+++ b/sw/programmer/linux/src/serial.c
@@ -0,0 +1,42 @@
+#include "serial.h"
+
+int serial_connect(const char *devpath, long baudrate)
+{
+    int fd;
+    struct termios tty;
+    // struct termios tty_old;
+    
+    // open device
+    if ((fd = open(devpath, O_RDWR | O_NOCTTY)) < 0) {
+        return -1;
+    }
+
+    // set parameters
+    if (tcgetattr(fd, &tty) != 0) {
+        return -1;
+    }
+
+    // TODO: update UI or add support for custom baudrate
+    // cfsetospeed(&tty, 
+    // cfsetispeed(&tty, 
+
+    tty.c_cflag &= ~PARENB;  // no parity
+    tty.c_cflag &= ~CSTOPB;  // no stop bit
+    tty.c_cflag |= CS8;      // 8 bit data
+    tty.c_cflag &= ~CRTSCTS; // no flow control
+
+    tty.c_lflag     =  0;  // no signaling chars, no echo, no canonical processing
+    tty.c_oflag     =  0;  // no remapping, no delays
+    tty.c_cc[VMIN]  =  0;  // no block read
+    tty.c_cc[VTIME] = .5;  // .5 seconds read timeout
+
+    tty.c_cflag |= CREAD | CLOCAL;      // turn on read and ignore ctrl lines
+    tty.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl
+    tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // make raw
+    tty.c_oflag &= ~OPOST; // make raw
+
+    tcflush(fd , TCIFLUSH);
+    // if (tcsetaddr(
+
+    return fd;
+}
diff --git a/sw/programmer/linux/src/serial.h b/sw/programmer/linux/src/serial.h
new file mode 100644
index 0000000..6123e42
--- /dev/null
+++ b/sw/programmer/linux/src/serial.h
@@ -0,0 +1,17 @@
+#ifndef __Z80PROG_SERIAL_H__
+#define __Z80PROG_SERIAL_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <termios.h>
+
+int serial_connect(const char *devpath, long baudrate);
+void serial_close(int fd);
+
+void serial_program(const char *rompath);
+void serial_read_rom(const char *rom);
+
+#endif
diff --git a/sw/programmer/linux/src/ui.c b/sw/programmer/linux/src/ui.c
new file mode 100644
index 0000000..b33aa04
--- /dev/null
+++ b/sw/programmer/linux/src/ui.c
@@ -0,0 +1,90 @@
+#include "ui.h"
+
+static bool ui_connected, ui_fileset;
+static GtkTextBuffer *ui_logbuf;
+static GtkBuilder *ui_builder;
+
+void ui_init(int *argc, char **argv[])
+{
+    GtkWindow *window;
+    GtkTextView *logview;
+    GtkFileChooserButton *filechoosebtn;
+    GtkButton *connectbtn, *flashbtn;
+
+    /* set ui global variables */
+    ui_connected = ui_fileset = false;
+
+    /* start gtk */
+    gtk_init(argc, argv);
+
+    /* load glade gtk ui */
+    ui_builder = gtk_builder_new();
+    gtk_builder_add_from_file(ui_builder, "gbprog.ui", NULL);
+
+    /* connect logger buffer (extern variable) */
+    ui_logbuf = gtk_text_buffer_new(NULL);
+    logview = GTK_TEXT_VIEW(gtk_builder_get_object(ui_builder, "logview"));
+
+    gtk_text_view_set_buffer(logview, ui_logbuf);
+
+    /* connect objects to function calls */
+    // window
+    window = GTK_WINDOW(gtk_builder_get_object(ui_builder, "window"));
+    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
+
+    // connectbtn 
+    connectbtn = GTK_BUTTON(gtk_builder_get_object(ui_builder, "flashbtn"));
+    g_signal_connect(connectbtn, "clicked", 
+                        G_CALLBACK(ui_connect_clicked), NULL);
+
+    // flashbtn
+    flashbtn = GTK_BUTTON(gtk_builder_get_object(ui_builder, "flashbtn"));
+    g_signal_connect(flashbtn, "clicked", G_CALLBACK(ui_flash_clicked), NULL);
+
+    // file chooser
+    filechoosebtn = GTK_FILE_CHOOSER_BUTTON(
+            gtk_builder_get_object(ui_builder, "filechoosebtn"));
+    g_signal_connect(filechoosebtn, "file-set", G_CALLBACK(ui_file_set), NULL);
+
+    /* start gtk window */
+    gtk_main();
+}
+
+void ui_log(const char *msg, char type) 
+{
+    GtkTextIter end;
+    gchar typech[4] = "[ ] ";
+
+    switch (type) {
+        case 'm': typech[1] = '@'; break; // message
+        case 'w': typech[1] = '#'; break; // warning
+        case 'e': typech[1] = '!'; break; // error
+    }
+
+    gtk_text_buffer_get_end_iter(ui_logbuf, &end);
+    gtk_text_buffer_insert(ui_logbuf, &end, typech, 4);
+    gtk_text_buffer_get_end_iter(ui_logbuf, &end);
+    gtk_text_buffer_insert(ui_logbuf, &end, (const gchar *) msg, strlen(msg));
+}
+
+void ui_file_set(GtkFileChooserButton *btn, gpointer user_data)
+{
+    GtkEntry *filepath = 
+            GTK_ENTRY(gtk_builder_get_object(ui_builder, "filepath"));
+
+    gtk_entry_set_text(filepath, 
+            gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(btn)));
+
+    ui_log("File set\n", 'm');
+    ui_fileset = true;
+}
+
+void ui_connect_clicked(void) 
+{
+
+}
+
+void ui_flash_clicked(void)
+{
+
+}
diff --git a/sw/programmer/linux/src/ui.h b/sw/programmer/linux/src/ui.h
new file mode 100644
index 0000000..44314d6
--- /dev/null
+++ b/sw/programmer/linux/src/ui.h
@@ -0,0 +1,17 @@
+#ifndef __Z80PROG_UI_H__
+#define __Z80PROG_UI_H_
+
+#include <stdbool.h>
+#include <string.h>
+
+#include <gtk/gtk.h>
+
+void ui_init(int *argc, char **argv[]);
+void ui_log(const char *msg, char type);
+
+void ui_file_set(GtkFileChooserButton *btn, gpointer user_data);
+
+void ui_connect_clicked(void);
+void ui_flash_clicked(void);
+
+#endif
diff --git a/sw/programmer/linux/src/z80prog b/sw/programmer/linux/src/z80prog
new file mode 100755
index 0000000..878683b
Binary files /dev/null and b/sw/programmer/linux/src/z80prog differ
diff --git a/sw/programmer/linux/src/z80prog.ui b/sw/programmer/linux/src/z80prog.ui
new file mode 100644
index 0000000..3735efa
--- /dev/null
+++ b/sw/programmer/linux/src/z80prog.ui
@@ -0,0 +1,222 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.20.0 -->
+<interface>
+  <requires lib="gtk+" version="3.12"/>
+  <object class="GtkAdjustment" id="baudrateadjust">
+    <property name="upper">1000000</property>
+    <property name="value">9600</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
+  <object class="GtkFileFilter" id="gbbinfilter">
+    <patterns>
+      <pattern>*.bin</pattern>
+      <pattern>*.gb</pattern>
+      <pattern>*.gba</pattern>
+      <pattern>*.gbc</pattern>
+      <pattern>*.hex</pattern>
+    </patterns>
+  </object>
+  <object class="GtkWindow" id="window">
+    <property name="width_request">450</property>
+    <property name="height_request">250</property>
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="title" translatable="yes">Z80 ROM Programmer</property>
+    <property name="default_width">450</property>
+    <property name="default_height">200</property>
+    <child>
+      <object class="GtkBox" id="mainbox">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="margin_left">10</property>
+        <property name="margin_right">10</property>
+        <property name="margin_top">10</property>
+        <property name="margin_bottom">10</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">10</property>
+        <child>
+          <object class="GtkBox" id="devbox">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="spacing">10</property>
+            <child>
+              <object class="GtkEntry" id="devpath">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="placeholder_text" translatable="yes">Enter path</property>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkSpinButton" id="devbaudrate">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="width_chars">0</property>
+                <property name="max_width_chars">7</property>
+                <property name="overwrite_mode">True</property>
+                <property name="placeholder_text" translatable="yes">9600</property>
+                <property name="input_purpose">number</property>
+                <property name="adjustment">baudrateadjust</property>
+                <property name="climb_rate">10</property>
+                <property name="snap_to_ticks">True</property>
+                <property name="numeric">True</property>
+                <property name="update_policy">if-valid</property>
+                <property name="value">9600</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="connectbtn">
+                <property name="label">gtk-connect</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkBox" id="filebox">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="spacing">10</property>
+            <child>
+              <object class="GtkEntry" id="filepath">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="placeholder_text" translatable="yes">Binary Path</property>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkFileChooserButton" id="filechoosebtn">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="filter">gbbinfilter</property>
+                <property name="title" translatable="yes"/>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkBox" id="flashbox">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="orientation">vertical</property>
+            <property name="spacing">10</property>
+            <child>
+              <object class="GtkProgressBar" id="flashbar">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="show_text">True</property>
+                <property name="ellipsize">start</property>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="flashbtn">
+                <property name="label" translatable="yes">Flash</property>
+                <property name="visible">True</property>
+                <property name="sensitive">False</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkScrolledWindow" id="logscrolled">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="shadow_type">in</property>
+            <child>
+              <object class="GtkViewport" id="logviewport">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <child>
+                  <object class="GtkExpander" id="logexpander">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="expanded">True</property>
+                    <property name="label_fill">True</property>
+                    <property name="resize_toplevel">True</property>
+                    <child>
+                      <object class="GtkTextView" id="logview">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="hexpand">True</property>
+                        <property name="vexpand">True</property>
+                        <property name="editable">False</property>
+                        <property name="monospace">True</property>
+                      </object>
+                    </child>
+                    <child type="label">
+                      <object class="GtkLabel" id="loglabel">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="label" translatable="yes">Logs</property>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">4</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>
-- 
cgit v1.2.1


From c7925cbb73f319a390507b33e4df44f106822683 Mon Sep 17 00:00:00 2001
From: Nao Pross <naopross@thearcway.org>
Date: Wed, 23 Aug 2017 16:43:56 +0200
Subject: new programmer interface for linux

there is a new program with GUI (gtk3) to send data to its avr
conterpart.

it needs to be tested, since there may be a few bugs in it;
building a GUI was a terrible idea.
---
 sw/programmer/avr/fileinfo.h        |  13 ----
 sw/programmer/avr/main.c            |  42 +++++++-----
 sw/programmer/avr/makefile          |   2 +-
 sw/programmer/linux/src/flash.c     |  59 +++++++++++++++++
 sw/programmer/linux/src/flash.h     |  22 +++++++
 sw/programmer/linux/src/makefile.am |   6 +-
 sw/programmer/linux/src/serial.c    |   3 +-
 sw/programmer/linux/src/serial.h    |   6 +-
 sw/programmer/linux/src/ui.c        | 126 +++++++++++++++++++++++++-----------
 sw/programmer/linux/src/ui.h        |  11 +++-
 sw/programmer/linux/src/z80prog     | Bin 34688 -> 48160 bytes
 sw/programmer/linux/src/z80prog.ui  |  43 ++++++------
 12 files changed, 234 insertions(+), 99 deletions(-)
 delete mode 100644 sw/programmer/avr/fileinfo.h
 create mode 100644 sw/programmer/linux/src/flash.c
 create mode 100644 sw/programmer/linux/src/flash.h

(limited to 'sw')

diff --git a/sw/programmer/avr/fileinfo.h b/sw/programmer/avr/fileinfo.h
deleted file mode 100644
index 6c831ed..0000000
--- a/sw/programmer/avr/fileinfo.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __FILEINFO_H__
-#define __FILEINFO_H__
-
-#include <stdio.h>
-
-struct file_info
-{
-    size_t size;
-    size_t blklen;
-    uint16_t start_addr;
-};
-
-#endif 
diff --git a/sw/programmer/avr/main.c b/sw/programmer/avr/main.c
index 90d05fa..9cdc35d 100644
--- a/sw/programmer/avr/main.c
+++ b/sw/programmer/avr/main.c
@@ -1,5 +1,6 @@
-#include "fileinfo.h"
 #include "usart.h"
+
+#include <stdio.h>
 #include <util/delay.h>
 
 #define EEPROM_TICK_MS  10
@@ -18,6 +19,11 @@
 #define EEPROM_RD   1
 #define EEPROM_CLK  2
 
+struct file_blk
+{
+    uint16_t addr;
+    uint16_t size;
+};
 
 void eeprom_write(uint16_t addr, uint8_t byte);
 void eeprom_tick();
@@ -25,10 +31,10 @@ void eeprom_tick();
 int main(void)
 {
     uint8_t *buffer, i;
-    uint16_t addr;
     size_t read;
+    char str[64];
 
-    struct file_info *finfo =  malloc(sizeof(struct file_info));
+    struct file_blk *blk = malloc(sizeof(struct file_blk));
 
     DDRB = 0x7F;
     DDRC = 0x83;
@@ -36,28 +42,32 @@ int main(void)
 
     /* get configuration */
     usart_init(1200); 
+    usart_print("programmer Ready\n<waiting for binary>\n\r");
 
-    usart_print("EEPROM Programmer\n\r");
-
-    do {
-        usart_print("Waiting for configuration\n\r");
-        read = usart_read((uint8_t *) finfo, sizeof(struct file_info));
-    } while (read != sizeof(struct file_info));
+    while (usart_read((uint8_t *) blk, sizeof(struct file_blk))) {
+        buffer = malloc(blk->size);
+        read = usart_read(buffer, blk->size);
 
-    usart_print("Programmer Ready\n<waiting for binary>\n\r");
+#ifdef DEBUG
+        sprintf(str, "info : reading block from addr %d of size %d\n\r", 
+                blk->addr, blk->size);
+        usart_print(str);
 
-    buffer = malloc(finfo->blklen);
-    addr = finfo->start_addr;
+        if (read != blk->size) {
+            sprintf(str, "error: expected %d but read %d\n\r", 
+                    blk->size, read);
+            usart_print(str);
+        }
+#endif
 
-    /* read file */
-    while ((read = usart_read(buffer, finfo->blklen))) {
         for (i = 0; i < read; i++) {
-            eeprom_write(addr + i, *(buffer++));
+            eeprom_write(blk->addr +i, buffer[i]);
         }
 
-        addr += finfo->blklen;
+        free(buffer);
     }
 
+    free(blk);
     return 0;
 }
 
diff --git a/sw/programmer/avr/makefile b/sw/programmer/avr/makefile
index 95fb5fe..ba2a709 100644
--- a/sw/programmer/avr/makefile
+++ b/sw/programmer/avr/makefile
@@ -12,7 +12,7 @@ PORT := /dev/ttyUSB0
 MCU  := atmega328p
 
 CFLAGS  := -g -Wall -mcall-prologues -mmcu=$(MCU) -Os -I . \
-			-DF_CPU=1000000UL
+			-DF_CPU=1000000UL -DDEBUG
 LDFLAGS := -Wl,-gc-sections -Wl,-relax
 
 .PHONY: all clean program
diff --git a/sw/programmer/linux/src/flash.c b/sw/programmer/linux/src/flash.c
new file mode 100644
index 0000000..48189da
--- /dev/null
+++ b/sw/programmer/linux/src/flash.c
@@ -0,0 +1,59 @@
+#include "flash.h"
+
+static int flash_serial_fd = -1;
+
+int flash_open(const char *path, unsigned long baudrate)
+{
+	flash_serial_fd = serial_open(path, baudrate);
+
+	if (flash_serial_fd < 0)
+		return -1;
+
+	return 0;
+}
+
+int flash_write(const char *romfile, void (*log)(const char *))
+{
+	int romfd;
+	ssize_t written;
+
+	struct stat romst;
+	struct flash_blk head;
+
+	uint8_t *buffer = malloc(FLASH_BLOCK_SIZE);
+
+	romfd = open(romfile, O_RDONLY);
+
+	if (fstat(romfd, &romst) != 0)
+		goto exit_romfd;
+
+	while ((head.size = read(romfd, buffer, FLASH_BLOCK_SIZE))) {
+		head.addr = (uint16_t) lseek(romfd, 0, SEEK_CUR);
+
+		written = write(flash_serial_fd, &head, sizeof(struct flash_blk));
+		if (written < 0) {
+			// error
+		}
+
+		written = write(flash_serial_fd, buffer, head.size);		
+		if (written < 0) {
+			// error
+		}
+
+		char logbuf[64];
+		sprintf(logbuf, "[@] Written %d bytes at address %d\n", head.size, head.addr);
+		log(logbuf);
+	}
+
+exit_romfd:
+	close(romfd);
+
+	free(buffer);
+	return 0;
+}
+
+void flash_close(void)
+{
+	if (flash_serial_fd >= 0) 
+		close(flash_serial_fd);
+}
\ No newline at end of file
diff --git a/sw/programmer/linux/src/flash.h b/sw/programmer/linux/src/flash.h
new file mode 100644
index 0000000..373ebf3
--- /dev/null
+++ b/sw/programmer/linux/src/flash.h
@@ -0,0 +1,22 @@
+#ifndef __FLASH_H__
+#define __FLASH_H__
+
+#include "serial.h"
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#define FLASH_BLOCK_SIZE 	512
+
+struct flash_blk
+{
+	uint16_t addr;
+	uint16_t size;
+};
+
+int flash_open(const char *devpath, unsigned long baudrate);
+int flash_write(const char *romfile, void (*log)(const char *));
+void flash_close(void);
+
+#endif
diff --git a/sw/programmer/linux/src/makefile.am b/sw/programmer/linux/src/makefile.am
index 492c3ec..33ae438 100644
--- a/sw/programmer/linux/src/makefile.am
+++ b/sw/programmer/linux/src/makefile.am
@@ -1,7 +1,7 @@
 bin_PROGRAMS = z80prog
-z80prog_SOURCES = main.c ui.c serial.c
+z80prog_SOURCES = main.c ui.c serial.c flash.c
 
-z80prog_CFLAGS = -Wall -Werror -g $(gtk3_CFLAGS)
-z80prog_LDADD = $(gtk3_LIBS)
+z80prog_CFLAGS = -Wall -g $(gtk3_CFLAGS) -pthread
+z80prog_LDADD = $(gtk3_LIBS) 
 
 CLEANFILES = *~
diff --git a/sw/programmer/linux/src/serial.c b/sw/programmer/linux/src/serial.c
index 564676b..e2544be 100644
--- a/sw/programmer/linux/src/serial.c
+++ b/sw/programmer/linux/src/serial.c
@@ -1,6 +1,6 @@
 #include "serial.h"
 
-int serial_connect(const char *devpath, long baudrate)
+int serial_open(const char *devpath, unsigned long baudrate)
 {
     int fd;
     struct termios tty;
@@ -40,3 +40,4 @@ int serial_connect(const char *devpath, long baudrate)
 
     return fd;
 }
+
diff --git a/sw/programmer/linux/src/serial.h b/sw/programmer/linux/src/serial.h
index 6123e42..fe21524 100644
--- a/sw/programmer/linux/src/serial.h
+++ b/sw/programmer/linux/src/serial.h
@@ -8,10 +8,6 @@
 #include <fcntl.h>
 #include <termios.h>
 
-int serial_connect(const char *devpath, long baudrate);
-void serial_close(int fd);
-
-void serial_program(const char *rompath);
-void serial_read_rom(const char *rom);
+int serial_open(const char *devpath, unsigned long baudrate);
 
 #endif
diff --git a/sw/programmer/linux/src/ui.c b/sw/programmer/linux/src/ui.c
index b33aa04..87dc0c7 100644
--- a/sw/programmer/linux/src/ui.c
+++ b/sw/programmer/linux/src/ui.c
@@ -1,90 +1,142 @@
 #include "ui.h"
 
 static bool ui_connected, ui_fileset;
-static GtkTextBuffer *ui_logbuf;
 static GtkBuilder *ui_builder;
 
 void ui_init(int *argc, char **argv[])
 {
     GtkWindow *window;
-    GtkTextView *logview;
     GtkFileChooserButton *filechoosebtn;
     GtkButton *connectbtn, *flashbtn;
 
-    /* set ui global variables */
     ui_connected = ui_fileset = false;
 
-    /* start gtk */
     gtk_init(argc, argv);
 
-    /* load glade gtk ui */
     ui_builder = gtk_builder_new();
-    gtk_builder_add_from_file(ui_builder, "gbprog.ui", NULL);
+    gtk_builder_add_from_file(ui_builder, "z80prog.ui", NULL);
 
-    /* connect logger buffer (extern variable) */
-    ui_logbuf = gtk_text_buffer_new(NULL);
-    logview = GTK_TEXT_VIEW(gtk_builder_get_object(ui_builder, "logview"));
-
-    gtk_text_view_set_buffer(logview, ui_logbuf);
-
-    /* connect objects to function calls */
-    // window
+    /* connect objects to callbacks */
     window = GTK_WINDOW(gtk_builder_get_object(ui_builder, "window"));
     g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
 
-    // connectbtn 
-    connectbtn = GTK_BUTTON(gtk_builder_get_object(ui_builder, "flashbtn"));
-    g_signal_connect(connectbtn, "clicked", 
-                        G_CALLBACK(ui_connect_clicked), NULL);
+    connectbtn = GTK_BUTTON(gtk_builder_get_object(ui_builder, "connectbtn"));
+    g_signal_connect(connectbtn, "clicked", G_CALLBACK(ui_connect_clicked), NULL);
 
-    // flashbtn
     flashbtn = GTK_BUTTON(gtk_builder_get_object(ui_builder, "flashbtn"));
     g_signal_connect(flashbtn, "clicked", G_CALLBACK(ui_flash_clicked), NULL);
 
-    // file chooser
-    filechoosebtn = GTK_FILE_CHOOSER_BUTTON(
-            gtk_builder_get_object(ui_builder, "filechoosebtn"));
+    filechoosebtn = GTK_FILE_CHOOSER_BUTTON(gtk_builder_get_object(ui_builder, "filechoosebtn"));
     g_signal_connect(filechoosebtn, "file-set", G_CALLBACK(ui_file_set), NULL);
 
     /* start gtk window */
     gtk_main();
 }
 
-void ui_log(const char *msg, char type) 
+void ui_log(const char *msg) 
 {
     GtkTextIter end;
-    gchar typech[4] = "[ ] ";
+    GtkTextView *ui_log;
+
+    static GtkTextBuffer *ui_logbuf = NULL; 
+
+    ui_log = GTK_TEXT_VIEW(gtk_builder_get_object(ui_builder, "logview"));
 
-    switch (type) {
-        case 'm': typech[1] = '@'; break; // message
-        case 'w': typech[1] = '#'; break; // warning
-        case 'e': typech[1] = '!'; break; // error
+    if (ui_logbuf == NULL) {
+        ui_logbuf = gtk_text_buffer_new(NULL);
+        gtk_text_view_set_buffer(ui_log, ui_logbuf);
     }
 
     gtk_text_buffer_get_end_iter(ui_logbuf, &end);
-    gtk_text_buffer_insert(ui_logbuf, &end, typech, 4);
-    gtk_text_buffer_get_end_iter(ui_logbuf, &end);
-    gtk_text_buffer_insert(ui_logbuf, &end, (const gchar *) msg, strlen(msg));
+    gtk_text_buffer_insert(ui_logbuf, &end, msg, -1);
+    gtk_text_view_scroll_to_iter(ui_log, &end, .0, TRUE, .0, .1);
 }
 
-void ui_file_set(GtkFileChooserButton *btn, gpointer user_data)
+void ui_check_enable_flashbtn(void)
 {
-    GtkEntry *filepath = 
-            GTK_ENTRY(gtk_builder_get_object(ui_builder, "filepath"));
+    GtkWidget *ui_flashbtn = GTK_WIDGET(gtk_builder_get_object(ui_builder, "flashbtn"));
 
-    gtk_entry_set_text(filepath, 
-            gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(btn)));
+    if (ui_connected && ui_fileset) 
+        gtk_widget_set_sensitive(ui_flashbtn, TRUE);
+    else
+        gtk_widget_set_sensitive(ui_flashbtn, FALSE); 
+}
 
-    ui_log("File set\n", 'm');
+void ui_file_set(GtkFileChooserButton *btn, gpointer user_data)
+{
+    GtkEntry *filepath = GTK_ENTRY(gtk_builder_get_object(ui_builder, "filepath"));
+
+    gtk_entry_set_text(filepath, gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(btn)));
+    ui_log(UI_LOG_MSG "file set\n");
     ui_fileset = true;
+
+    ui_check_enable_flashbtn();
 }
 
 void ui_connect_clicked(void) 
 {
+    GtkEntry *ui_devpath = GTK_ENTRY(gtk_builder_get_object(ui_builder, "devpath"));
+    GtkSpinButton *ui_baudrate = GTK_SPIN_BUTTON(gtk_builder_get_object(ui_builder, "devbaudrate"));
+    GtkButton *ui_connectbtn = GTK_BUTTON(gtk_builder_get_object(ui_builder, "connectbtn"));
+
+    unsigned long baudrate = gtk_spin_button_get_value_as_int(ui_baudrate);
+    const char *devpath = gtk_entry_get_text(ui_devpath);
+
+    if (flash_open(devpath, baudrate) != 0) {
+        ui_log(UI_LOG_ERR "failed to open serial device\n");
+    } else {
+        ui_connected = true;
+        ui_log(UI_LOG_MSG "connected to serial device ");
+        ui_log(devpath);
+        ui_log("\n");
+
+        g_signal_handlers_disconnect_by_func(ui_connectbtn, G_CALLBACK(ui_connect_clicked), NULL);
+        g_signal_connect(ui_connectbtn, "clicked", G_CALLBACK(ui_disconnect_clicked), NULL);
+
+        gtk_button_set_label(ui_connectbtn, "gtk-disconnect");
+        ui_check_enable_flashbtn();
+    }
+}
 
+void ui_disconnect_clicked(void)
+{
+    GtkButton *ui_connectbtn = GTK_BUTTON(gtk_builder_get_object(ui_builder, "connectbtn"));
+
+    flash_close();
+
+    ui_connected = false;
+    ui_log(UI_LOG_MSG "disconnected\n");
+
+    g_signal_handlers_disconnect_by_func(ui_connectbtn, G_CALLBACK(ui_disconnect_clicked), NULL);
+    g_signal_connect(ui_connectbtn, "clicked", G_CALLBACK(ui_connect_clicked), NULL);
+
+    gtk_button_set_label(ui_connectbtn, "gtk-connect");
+    ui_check_enable_flashbtn();
+}
+
+int ui_flash_write_start(void *ptr)
+{
+    const char *filepath = (const char *) ptr;
+
+    flash_write(filepath, ui_log);
+    ui_check_enable_flashbtn();
+
+    return 0;
 }
 
 void ui_flash_clicked(void)
 {
+    GtkWidget *ui_flashbtn = GTK_WIDGET(gtk_builder_get_object(ui_builder, "flashbtn"));
+    GtkEntry *ui_filepath = GTK_ENTRY(gtk_builder_get_object(ui_builder, "filepath"));
+
+    const char *filepath = gtk_entry_get_text(ui_filepath);
+
+    gdk_threads_add_idle_full(
+        G_PRIORITY_HIGH_IDLE,
+        ui_flash_write_start,
+        (void *) filepath,
+        NULL
+    );
 
+    gtk_widget_set_sensitive(ui_flashbtn, FALSE);
 }
diff --git a/sw/programmer/linux/src/ui.h b/sw/programmer/linux/src/ui.h
index 44314d6..510537a 100644
--- a/sw/programmer/linux/src/ui.h
+++ b/sw/programmer/linux/src/ui.h
@@ -1,17 +1,24 @@
 #ifndef __Z80PROG_UI_H__
 #define __Z80PROG_UI_H_
 
+#include "flash.h"
+
 #include <stdbool.h>
 #include <string.h>
 
 #include <gtk/gtk.h>
 
+#define UI_LOG_ERR	"[!] "
+#define UI_LOG_WARN	"[#] "
+#define UI_LOG_MSG	"[@] "
+
 void ui_init(int *argc, char **argv[]);
-void ui_log(const char *msg, char type);
+void ui_log(const char *msg);
+void ui_check_enable_flashbtn(void);
 
 void ui_file_set(GtkFileChooserButton *btn, gpointer user_data);
-
 void ui_connect_clicked(void);
+void ui_disconnect_clicked(void);
 void ui_flash_clicked(void);
 
 #endif
diff --git a/sw/programmer/linux/src/z80prog b/sw/programmer/linux/src/z80prog
index 878683b..2f0d230 100755
Binary files a/sw/programmer/linux/src/z80prog and b/sw/programmer/linux/src/z80prog differ
diff --git a/sw/programmer/linux/src/z80prog.ui b/sw/programmer/linux/src/z80prog.ui
index 3735efa..6c652ec 100644
--- a/sw/programmer/linux/src/z80prog.ui
+++ b/sw/programmer/linux/src/z80prog.ui
@@ -44,7 +44,8 @@
               <object class="GtkEntry" id="devpath">
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
-                <property name="placeholder_text" translatable="yes">Enter path</property>
+                <property name="text" translatable="yes">/dev/tty</property>
+                <property name="placeholder_text" translatable="yes">Enter device path</property>
               </object>
               <packing>
                 <property name="expand">True</property>
@@ -59,14 +60,14 @@
                 <property name="width_chars">0</property>
                 <property name="max_width_chars">7</property>
                 <property name="overwrite_mode">True</property>
-                <property name="placeholder_text" translatable="yes">9600</property>
+                <property name="placeholder_text" translatable="yes">1200</property>
                 <property name="input_purpose">number</property>
                 <property name="adjustment">baudrateadjust</property>
                 <property name="climb_rate">10</property>
                 <property name="snap_to_ticks">True</property>
                 <property name="numeric">True</property>
                 <property name="update_policy">if-valid</property>
-                <property name="value">9600</property>
+                <property name="value">1200</property>
               </object>
               <packing>
                 <property name="expand">False</property>
@@ -104,7 +105,7 @@
               <object class="GtkEntry" id="filepath">
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
-                <property name="placeholder_text" translatable="yes">Binary Path</property>
+                <property name="placeholder_text" translatable="yes">Enter binary path</property>
               </object>
               <packing>
                 <property name="expand">True</property>
@@ -173,21 +174,21 @@
           </packing>
         </child>
         <child>
-          <object class="GtkScrolledWindow" id="logscrolled">
+          <object class="GtkViewport" id="logviewport">
             <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="shadow_type">in</property>
+            <property name="can_focus">False</property>
             <child>
-              <object class="GtkViewport" id="logviewport">
+              <object class="GtkExpander" id="logexpander">
                 <property name="visible">True</property>
-                <property name="can_focus">False</property>
+                <property name="can_focus">True</property>
+                <property name="expanded">True</property>
+                <property name="label_fill">True</property>
+                <property name="resize_toplevel">True</property>
                 <child>
-                  <object class="GtkExpander" id="logexpander">
+                  <object class="GtkScrolledWindow" id="logscroller">
                     <property name="visible">True</property>
                     <property name="can_focus">True</property>
-                    <property name="expanded">True</property>
-                    <property name="label_fill">True</property>
-                    <property name="resize_toplevel">True</property>
+                    <property name="shadow_type">in</property>
                     <child>
                       <object class="GtkTextView" id="logview">
                         <property name="visible">True</property>
@@ -198,13 +199,13 @@
                         <property name="monospace">True</property>
                       </object>
                     </child>
-                    <child type="label">
-                      <object class="GtkLabel" id="loglabel">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="label" translatable="yes">Logs</property>
-                      </object>
-                    </child>
+                  </object>
+                </child>
+                <child type="label">
+                  <object class="GtkLabel" id="loglabel">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="label" translatable="yes">Logs</property>
                   </object>
                 </child>
               </object>
@@ -213,7 +214,7 @@
           <packing>
             <property name="expand">True</property>
             <property name="fill">True</property>
-            <property name="position">4</property>
+            <property name="position">3</property>
           </packing>
         </child>
       </object>
-- 
cgit v1.2.1