bin_PROGRAMS=ccload
-AM_CFLAGS=-I$(top_srcdir)/lib
+AM_CFLAGS=-I$(top_srcdir)/lib $(LIBUSB_CFLAGS)
CCLOAD_LIBS=../lib/libcc.a
ccload_DEPENDENCIES = $(CCLOAD_LIBS)
-ccload_LDADD=$(CCLOAD_LIBS) $(USB_LIBS)
+ccload_LDADD=$(CCLOAD_LIBS) $(LIBUSB_LIBS)
ccload_SOURCES = ccload.c
AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_RANLIB
+PKG_PROG_PKG_CONFIG
+CFLAGS="-g"
WARN_CFLAGS=""
if test "x$GCC" = "xyes"; then
WARN_CFLAGS="-Wall -Wpointer-arith -Wstrict-prototypes \
AC_MSG_RESULT([$CC_FOR_BUILD])
AC_SUBST(CC_FOR_BUILD)
+PKG_CHECK_MODULES([LIBUSB], [libusb-1.0])
+
AC_MSG_CHECKING([for suffix of executable build tools])
if test $cross_compiling = yes; then
cat >conftest.c <<\_______EOF
noinst_LIBRARIES = libcc.a
-AM_CFLAGS=$(WARN_CFLAGS)
+AM_CFLAGS=$(WARN_CFLAGS) $(LIBUSB_CFLAGS)
libcc_a_SOURCES = \
ccdbg-command.c \
ccdbg-io.c \
ccdbg-manual.c \
ccdbg-memory.c \
- cp-usb.c
+ cp-usb.c \
+ cp-usb-async.c
ccdbg_send(dbg, CC_CLOCK|CC_DATA|CC_RESET_N, CC_DATA );
ccdbg_send(dbg, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA );
ccdbg_send(dbg, CC_CLOCK|CC_DATA|CC_RESET_N, CC_DATA|CC_RESET_N);
+ ccdbg_sync_io(dbg);
}
void
ccdbg_send(dbg, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA );
ccdbg_send(dbg, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA );
ccdbg_send(dbg, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA|CC_RESET_N);
+ ccdbg_sync_io(dbg);
}
uint8_t
--- /dev/null
+/*
+ * Copyright © 2008 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _CCDBG_DEBUG_H_
+#define _CCDBG_DEBUG_H_
+/* Debug levels
+ */
+#define CC_DEBUG_BITBANG 0x00000001
+#define CC_DEBUG_COMMAND 0x00000002
+#define CC_DEBUG_INSTRUCTIONS 0x00000004
+#define CC_DEBUG_EXECUTE 0x00000008
+#define CC_DEBUG_FLASH 0x00000010
+#define CC_DEBUG_MEMORY 0x00000020
+#define CC_DEBUG_USB_ASYNC 0x00000040
+
+/* ccdbg-debug.c */
+void
+ccdbg_debug(int level, char *format, ...);
+
+void
+ccdbg_add_debug(int level);
+
+void
+ccdbg_clear_debug(int level);
+
+void
+ccdbg_flush(void);
+
+#endif /* _CCDBG_DEBUG_H_ */
#include "ccdbg.h"
#include <time.h>
+#ifdef CP_USB_ASYNC
+#include "cp-usb-async.h"
+#else
+#include "cp-usb.h"
+#endif
void
ccdbg_half_clock(struct ccdbg *dbg)
perror("calloc");
return NULL;
}
+#ifdef CP_USB_ASYNC
+ dbg->cp_async = cp_usb_async_open();
+ if (!dbg->cp_async) {
+ free (dbg);
+ return NULL;
+ }
+#else
dbg->cp = cp_usb_open ();
if (!dbg->cp) {
free (dbg);
return NULL;
}
+#endif
return dbg;
}
void
ccdbg_close(struct ccdbg *dbg)
{
+#ifdef CP_USB_ASYNC
+ cp_usb_async_close(dbg->cp_async);
+#else
cp_usb_close(dbg->cp);
+#endif
free (dbg);
}
int
ccdbg_write(struct ccdbg *dbg, uint8_t mask, uint8_t value)
{
+#ifdef CP_USB_ASYNC
+ cp_usb_async_write(dbg->cp_async, mask, value);
+#else
cp_usb_write(dbg->cp, mask, value);
+#endif
return 0;
}
-uint8_t
-ccdbg_read(struct ccdbg *dbg)
+void
+ccdbg_read(struct ccdbg *dbg, uint8_t *valuep)
+{
+#ifdef CP_USB_ASYNC
+ cp_usb_async_read(dbg->cp_async, valuep);
+#else
+ *valuep = cp_usb_read(dbg->cp);
+#endif
+}
+
+void
+ccdbg_sync_io(struct ccdbg *dbg)
{
- return cp_usb_read(dbg->cp);
+#ifdef CP_USB_ASYNC
+ cp_usb_async_sync(dbg->cp_async);
+#endif
}
static char
if (bit == 3)
ccdbg_debug(CC_DEBUG_BITBANG, "\n");
}
+ ccdbg_sync_io(dbg);
}
void
ccdbg_send_byte(dbg, *bytes++);
}
-uint8_t
-ccdbg_recv_bit(struct ccdbg *dbg, int first)
+void
+ccdbg_recv_bit(struct ccdbg *dbg, int first, uint8_t *bit)
{
uint8_t mask = first ? CC_DATA : 0;
- uint8_t read;
ccdbg_send(dbg, CC_CLOCK|mask|CC_RESET_N, CC_CLOCK|CC_DATA|CC_RESET_N);
- read = ccdbg_read(dbg);
- ccdbg_print("#\t%c %c %c\n", CC_DATA, read);
+ ccdbg_read(dbg, bit);
ccdbg_send(dbg, CC_CLOCK| CC_RESET_N, CC_RESET_N);
- return (read & CC_DATA) ? 1 : 0;
}
-uint8_t
-ccdbg_recv_byte(struct ccdbg *dbg, int first)
+void
+ccdbg_recv_byte(struct ccdbg *dbg, int first, uint8_t *bytep)
{
uint8_t byte = 0;
+ uint8_t bits[8];
int bit;
ccdbg_debug(CC_DEBUG_BITBANG, "#\n# Recv byte\n#\n");
+ for (bit = 0; bit < 8; bit++) {
+ ccdbg_recv_bit(dbg, first, &bits[bit]);
+ first = 0;
+ }
+ ccdbg_sync_io(dbg);
for (bit = 0; bit < 8; bit++) {
byte = byte << 1;
- byte |= ccdbg_recv_bit(dbg, first);
+ byte |= (bits[bit] & CC_DATA) ? 1 : 0;
+ ccdbg_print("#\t%c %c %c\n", CC_DATA, bits[bit]);
if (bit == 3)
ccdbg_debug(CC_DEBUG_BITBANG, "\n");
- first = 0;
}
ccdbg_debug(CC_DEBUG_BITBANG, "#\n# Recv 0x%02x\n#\n", byte);
- return byte;
+ *bytep = byte;
}
void
ccdbg_recv_bytes(struct ccdbg *dbg, uint8_t *bytes, int nbytes)
{
+ int i;
int first = 1;
- while (nbytes--) {
- *bytes++ = ccdbg_recv_byte(dbg, first);
+ for (i = 0; i < nbytes; i++) {
+ ccdbg_recv_byte(dbg, first, &bytes[i]);
first = 0;
}
}
get_bit(line, 4, 'R', CC_RESET_N, &set, &mask);
if (mask != (CC_CLOCK|CC_DATA|CC_RESET_N)) {
uint8_t read;
- read = ccdbg_read(dbg);
+ ccdbg_read(dbg, &read);
ccdbg_print("\t%c %c %c", CC_CLOCK|CC_DATA|CC_RESET_N, read);
if ((set & CC_CLOCK) == 0)
printf ("\t%d", (read&CC_DATA) ? 1 : 0);
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
-#include "cp-usb.h"
+#include "ccdbg-debug.h"
+
#define CC_CLOCK 0x1
#define CC_DATA 0x2
#define CC_RESET_N 0x4
-#define CC_CLOCK_US (40)
+#define CC_CLOCK_US (0)
/* 8051 instructions
*/
/* Bit-addressable accumulator */
#define ACC(bit) (0xE0 | (bit))
+#define CP_USB_ASYNC
+
struct ccdbg {
+#ifdef CP_USB_ASYNC
+ struct cp_usb_async *cp_async;
+#else
struct cp_usb *cp;
+#endif
};
/* Intel hex file format data
#define CC_STEP_REPLACE(n) (0x64|(n))
#define CC_GET_CHIP_ID 0x68
-/* Debug levels
- */
-#define CC_DEBUG_BITBANG 0x00000001
-#define CC_DEBUG_COMMAND 0x00000002
-#define CC_DEBUG_INSTRUCTIONS 0x00000004
-#define CC_DEBUG_EXECUTE 0x00000008
-#define CC_DEBUG_FLASH 0x00000010
-#define CC_DEBUG_MEMORY 0x00000020
-
/* ccdbg-command.c */
void
ccdbg_debug_mode(struct ccdbg *dbg);
uint8_t
ccdbg_execute_hex_image(struct ccdbg *dbg, struct hex_image *image);
-/* ccdbg-debug.c */
-void
-ccdbg_debug(int level, char *format, ...);
-
-void
-ccdbg_add_debug(int level);
-
-void
-ccdbg_clear_debug(int level);
-
-void
-ccdbg_flush(void);
-
/* ccdbg-flash.c */
uint8_t
ccdbg_flash_hex_image(struct ccdbg *dbg, struct hex_image *image);
int
ccdbg_write(struct ccdbg *dbg, uint8_t mask, uint8_t value);
-uint8_t
-ccdbg_read(struct ccdbg *dbg);
+void
+ccdbg_read(struct ccdbg *dbg, uint8_t *valuep);
struct ccdbg *
ccdbg_open(void);
void
ccdbg_send_bytes(struct ccdbg *dbg, uint8_t *bytes, int nbytes);
-uint8_t
-ccdbg_recv_bit(struct ccdbg *dbg, int first);
+void
+ccdbg_recv_bit(struct ccdbg *dbg, int first, uint8_t *bit);
-uint8_t
-ccdbg_recv_byte(struct ccdbg *dbg, int first);
+void
+ccdbg_recv_byte(struct ccdbg *dbg, int first, uint8_t *byte);
void
ccdbg_recv_bytes(struct ccdbg *dbg, uint8_t *bytes, int nbytes);
+void
+ccdbg_sync_io(struct ccdbg *dbg);
+
void
ccdbg_print(char *format, uint8_t mask, uint8_t set);
--- /dev/null
+/*
+ * Copyright © 2008 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "cp-usb-async.h"
+#include "ccdbg-debug.h"
+
+#define MAX_OUTSTANDING 256
+#define CP_TIMEOUT 1000 /* ms */
+
+struct cp_usb_packet {
+ struct libusb_transfer *transfer;
+ enum { packet_read, packet_write } direction;
+ unsigned char data[9];
+ uint8_t *valuep;
+};
+
+struct cp_usb_async {
+ libusb_context *ctx;
+ libusb_device_handle *handle;
+ struct cp_usb_packet packet[MAX_OUTSTANDING];
+ int p, ack;
+};
+
+struct cp_usb_async *
+cp_usb_async_open(void)
+{
+ struct cp_usb_async *cp;
+ int ret;
+
+ cp = calloc(sizeof (struct cp_usb_async), 1);
+ if (!cp)
+ return NULL;
+ ret = libusb_init(&cp->ctx);
+ if (ret) {
+ free(cp);
+ return NULL;
+ }
+ cp->handle = libusb_open_device_with_vid_pid(cp->ctx,
+ 0x10c4, 0xea60);
+ if (!cp->handle) {
+ libusb_exit(cp->ctx);
+ free(cp);
+ return NULL;
+ }
+ return cp;
+}
+
+void
+cp_usb_async_close(struct cp_usb_async *cp)
+{
+ libusb_close(cp->handle);
+ libusb_exit(cp->ctx);
+ free(cp);
+}
+
+static void
+cp_usb_async_transfer_callback(struct libusb_transfer *transfer)
+{
+ struct cp_usb_async *cp = transfer->user_data;
+ int p;
+
+ for (p = 0; p < cp->p; p++)
+ if (cp->packet[p].transfer == transfer)
+ break;
+ if (p == cp->p) {
+ fprintf(stderr, "unknown transfer\n");
+ return;
+ }
+ switch (cp->packet[p].direction) {
+ case packet_read:
+ ccdbg_debug(CC_DEBUG_USB_ASYNC, "ack read %d 0x%02x\n",
+ p, cp->packet[p].data[8]);
+ *cp->packet[p].valuep = cp->packet[p].data[8];
+ break;
+ case packet_write:
+ ccdbg_debug(CC_DEBUG_USB_ASYNC, "ack write %d\n", p);
+ break;
+ }
+ if (p > cp->ack)
+ cp->ack = p;
+}
+
+void
+cp_usb_async_write(struct cp_usb_async *cp, uint8_t mask, uint8_t value)
+{
+ int p;
+ uint16_t gpio_set = ((uint16_t) value << 8) | mask;
+ int ret;
+
+ if (cp->p == MAX_OUTSTANDING)
+ cp_usb_async_sync(cp);
+ p = cp->p;
+ if (!cp->packet[p].transfer)
+ cp->packet[p].transfer = libusb_alloc_transfer(0);
+ cp->packet[p].direction = packet_write;
+ libusb_fill_control_setup(cp->packet[p].data,
+ 0x40, /* request */
+ 0xff, /* request type */
+ 0x37e1, /* value */
+ gpio_set, /* index */
+ 0); /* length */
+
+ libusb_fill_control_transfer(cp->packet[p].transfer,
+ cp->handle,
+ cp->packet[p].data,
+ cp_usb_async_transfer_callback,
+ cp,
+ CP_TIMEOUT);
+ ccdbg_debug(CC_DEBUG_USB_ASYNC, "Write packet %d 0x%x 0x%x\n", p, mask, value);
+ ret = libusb_submit_transfer(cp->packet[p].transfer);
+ if (ret)
+ fprintf(stderr, "libusb_submit_transfer failed %d\n", ret);
+ cp->p++;
+}
+
+void
+cp_usb_async_read(struct cp_usb_async *cp, uint8_t *valuep)
+{
+ int p;
+ int ret;
+
+ if (cp->p == MAX_OUTSTANDING)
+ cp_usb_async_sync(cp);
+ p = cp->p;
+ if (!cp->packet[p].transfer)
+ cp->packet[p].transfer = libusb_alloc_transfer(0);
+ cp->packet[p].valuep = valuep;
+ cp->packet[p].direction = packet_read;
+ libusb_fill_control_setup(cp->packet[p].data,
+ 0xc0, /* request */
+ 0xff, /* request type */
+ 0x00c2, /* value */
+ 0, /* index */
+ 1); /* length */
+
+ libusb_fill_control_transfer(cp->packet[p].transfer,
+ cp->handle,
+ cp->packet[p].data,
+ cp_usb_async_transfer_callback,
+ cp,
+ CP_TIMEOUT);
+ ccdbg_debug(CC_DEBUG_USB_ASYNC, "Read packet %d\n", p);
+ ret = libusb_submit_transfer(cp->packet[p].transfer);
+ if (ret)
+ fprintf(stderr, "libusb_submit_transfer failed %d\n", ret);
+ cp->p++;
+}
+
+void
+cp_usb_async_sync(struct cp_usb_async *cp)
+{
+ while (cp->ack < cp->p - 1) {
+ libusb_handle_events(cp->ctx);
+ }
+ cp->p = 0;
+ cp->ack = 0;
+}
--- /dev/null
+/*
+ * Copyright © 2008 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _CP_USB_ASYNC_H_
+#define _CP_USB_ASYNC_H_
+#include <libusb.h>
+
+struct cp_usb_async *
+cp_usb_async_open(void);
+
+void
+cp_usb_async_close(struct cp_usb_async *cp);
+
+void
+cp_usb_async_write(struct cp_usb_async *cp, uint8_t mask, uint8_t value);
+
+void
+cp_usb_async_read(struct cp_usb_async *cp, uint8_t *valuep);
+
+void
+cp_usb_async_sync(struct cp_usb_async *cp);
+
+#endif
bin_PROGRAMS=s51
-AM_CFLAGS=-I$(top_srcdir)/lib
+AM_CFLAGS=-I$(top_srcdir)/lib $(LIBUSB_CFLAGS)
S51_LIBS=../lib/libcc.a
s51_DEPENDENCIES = $(S51_LIBS)
-s51_LDADD=$(S51_LIBS) $(USB_LIBS)
+s51_LDADD=$(S51_LIBS) $(LIBUSB_LIBS)
s51_SOURCES = s51-parse.c s51-command.c s51-main.c