diff options
author | leleraffa97@hotmail.it <leleraffa97@hotmail.it> | 2017-08-23 21:18:02 +0200 |
---|---|---|
committer | leleraffa97@hotmail.it <leleraffa97@hotmail.it> | 2017-08-23 21:18:02 +0200 |
commit | 3f92d0e29700fc2da45354a4cf3e3afe5c5245c2 (patch) | |
tree | cb6def68635ff2b4e4ab30c7e8fdbdf3e730bc05 /sw/programmer/linux/src | |
parent | Filesystem struct order (diff) | |
parent | new programmer interface for linux (diff) | |
download | z80uPC-3f92d0e29700fc2da45354a4cf3e3afe5c5245c2.tar.gz z80uPC-3f92d0e29700fc2da45354a4cf3e3afe5c5245c2.zip |
Merge remote-tracking branch 'origin/naopross' into atlas
Diffstat (limited to 'sw/programmer/linux/src')
-rw-r--r-- | sw/programmer/linux/src/flash.c | 59 | ||||
-rw-r--r-- | sw/programmer/linux/src/flash.h | 22 | ||||
-rw-r--r-- | sw/programmer/linux/src/main.c | 13 | ||||
-rw-r--r-- | sw/programmer/linux/src/makefile.am | 7 | ||||
-rw-r--r-- | sw/programmer/linux/src/serial.c | 43 | ||||
-rw-r--r-- | sw/programmer/linux/src/serial.h | 13 | ||||
-rw-r--r-- | sw/programmer/linux/src/ui.c | 142 | ||||
-rw-r--r-- | sw/programmer/linux/src/ui.h | 24 | ||||
-rwxr-xr-x | sw/programmer/linux/src/z80prog | bin | 0 -> 48160 bytes | |||
-rw-r--r-- | sw/programmer/linux/src/z80prog.ui | 223 |
10 files changed, 546 insertions, 0 deletions
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/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..33ae438 --- /dev/null +++ b/sw/programmer/linux/src/makefile.am @@ -0,0 +1,7 @@ +bin_PROGRAMS = z80prog +z80prog_SOURCES = main.c ui.c serial.c flash.c + +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 new file mode 100644 index 0000000..e2544be --- /dev/null +++ b/sw/programmer/linux/src/serial.c @@ -0,0 +1,43 @@ +#include "serial.h" + +int serial_open(const char *devpath, unsigned 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..fe21524 --- /dev/null +++ b/sw/programmer/linux/src/serial.h @@ -0,0 +1,13 @@ +#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_open(const char *devpath, unsigned long baudrate); + +#endif diff --git a/sw/programmer/linux/src/ui.c b/sw/programmer/linux/src/ui.c new file mode 100644 index 0000000..87dc0c7 --- /dev/null +++ b/sw/programmer/linux/src/ui.c @@ -0,0 +1,142 @@ +#include "ui.h" + +static bool ui_connected, ui_fileset; +static GtkBuilder *ui_builder; + +void ui_init(int *argc, char **argv[]) +{ + GtkWindow *window; + GtkFileChooserButton *filechoosebtn; + GtkButton *connectbtn, *flashbtn; + + ui_connected = ui_fileset = false; + + gtk_init(argc, argv); + + ui_builder = gtk_builder_new(); + gtk_builder_add_from_file(ui_builder, "z80prog.ui", NULL); + + /* 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 = GTK_BUTTON(gtk_builder_get_object(ui_builder, "connectbtn")); + g_signal_connect(connectbtn, "clicked", G_CALLBACK(ui_connect_clicked), NULL); + + flashbtn = GTK_BUTTON(gtk_builder_get_object(ui_builder, "flashbtn")); + g_signal_connect(flashbtn, "clicked", G_CALLBACK(ui_flash_clicked), NULL); + + 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) +{ + GtkTextIter end; + GtkTextView *ui_log; + + static GtkTextBuffer *ui_logbuf = NULL; + + ui_log = GTK_TEXT_VIEW(gtk_builder_get_object(ui_builder, "logview")); + + 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, msg, -1); + gtk_text_view_scroll_to_iter(ui_log, &end, .0, TRUE, .0, .1); +} + +void ui_check_enable_flashbtn(void) +{ + GtkWidget *ui_flashbtn = GTK_WIDGET(gtk_builder_get_object(ui_builder, "flashbtn")); + + if (ui_connected && ui_fileset) + gtk_widget_set_sensitive(ui_flashbtn, TRUE); + else + gtk_widget_set_sensitive(ui_flashbtn, FALSE); +} + +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 new file mode 100644 index 0000000..510537a --- /dev/null +++ b/sw/programmer/linux/src/ui.h @@ -0,0 +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); +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 Binary files differnew file mode 100755 index 0000000..2f0d230 --- /dev/null +++ b/sw/programmer/linux/src/z80prog diff --git a/sw/programmer/linux/src/z80prog.ui b/sw/programmer/linux/src/z80prog.ui new file mode 100644 index 0000000..6c652ec --- /dev/null +++ b/sw/programmer/linux/src/z80prog.ui @@ -0,0 +1,223 @@ +<?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="text" translatable="yes">/dev/tty</property> + <property name="placeholder_text" translatable="yes">Enter device 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">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">1200</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">Enter 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="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="GtkScrolledWindow" id="logscroller"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="shadow_type">in</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> + </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> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + </object> + </child> + </object> +</interface> |