Merge ccdbg and altos sources into one giant repository
authorKeith Packard <keithp@keithp.com>
Thu, 4 Jun 2009 18:13:15 +0000 (11:13 -0700)
committerKeith Packard <keithp@keithp.com>
Thu, 4 Jun 2009 18:13:15 +0000 (11:13 -0700)
Keeping these separate isn't making things any easier.

Signed-off-by: Keith Packard <keithp@keithp.com>
86 files changed:
.gitignore
AUTHORS
INSTALL
Makefile.am
aoload/Makefile.am [new file with mode: 0644]
aoload/aoload.c [new file with mode: 0644]
aoview/Makefile.am
ccdump/Makefile.am [new file with mode: 0644]
ccdump/ccdump.c [new file with mode: 0644]
ccload/.gitignore [new file with mode: 0644]
ccload/Makefile.am [new file with mode: 0644]
ccload/ccload.c [new file with mode: 0644]
ccmanual/Makefile.am [new file with mode: 0644]
ccmanual/ccmanual.c [new file with mode: 0644]
configure.ac
lib/Makefile.am [new file with mode: 0644]
lib/cc-bitbang.c [new file with mode: 0644]
lib/cc-bitbang.h [new file with mode: 0644]
lib/cc-usb.c [new file with mode: 0644]
lib/cc-usb.h [new file with mode: 0644]
lib/cccp.c [new file with mode: 0644]
lib/cccp.h [new file with mode: 0644]
lib/ccdbg-command.c [new file with mode: 0644]
lib/ccdbg-debug.c [new file with mode: 0644]
lib/ccdbg-debug.h [new file with mode: 0644]
lib/ccdbg-flash.c [new file with mode: 0644]
lib/ccdbg-hex.c [new file with mode: 0644]
lib/ccdbg-io.c [new file with mode: 0644]
lib/ccdbg-manual.c [new file with mode: 0644]
lib/ccdbg-memory.c [new file with mode: 0644]
lib/ccdbg-rom.c [new file with mode: 0644]
lib/ccdbg-state.c [new file with mode: 0644]
lib/ccdbg.h [new file with mode: 0644]
lib/cp-usb-async.c [new file with mode: 0644]
lib/cp-usb-async.h [new file with mode: 0644]
lib/cp-usb.c [new file with mode: 0644]
lib/cp-usb.h [new file with mode: 0644]
s51/.gitignore [new file with mode: 0644]
s51/Makefile.am [new file with mode: 0644]
s51/commands [new file with mode: 0644]
s51/s51-command.c [new file with mode: 0644]
s51/s51-main.c [new file with mode: 0644]
s51/s51-parse.c [new file with mode: 0644]
s51/s51.1 [new file with mode: 0644]
s51/s51.h [new file with mode: 0644]
target/adc-serial/Makefile [new file with mode: 0644]
target/adc-serial/adc_serial.c [new file with mode: 0644]
target/adc/Makefile [new file with mode: 0644]
target/adc/adc.c [new file with mode: 0644]
target/beep-timer/Makefile [new file with mode: 0644]
target/beep-timer/beep_timer.c [new file with mode: 0644]
target/beep/Makefile [new file with mode: 0644]
target/beep/beep.c [new file with mode: 0644]
target/blink/.gitignore [new file with mode: 0644]
target/blink/Makefile [new file with mode: 0644]
target/blink/blink.c [new file with mode: 0644]
target/dma/Makefile [new file with mode: 0644]
target/dma/dma.c [new file with mode: 0644]
target/ee/Makefile [new file with mode: 0644]
target/ee/ee.c [new file with mode: 0644]
target/isr.c [new file with mode: 0644]
target/radio/Makefile [new file with mode: 0644]
target/radio/init.c [new file with mode: 0644]
target/radio/radio.h [new file with mode: 0644]
target/radio/recv.c [new file with mode: 0644]
target/radio/xmit.c [new file with mode: 0644]
target/serial/Makefile [new file with mode: 0644]
target/serial/serial.c [new file with mode: 0644]
target/simple/Makefile [new file with mode: 0644]
target/simple/simple.c [new file with mode: 0644]
target/timer/Makefile [new file with mode: 0644]
target/timer/cc1111.h [new file with mode: 0644]
target/timer/timer.c [new file with mode: 0644]
tests/blink-tiny [new file with mode: 0644]
tests/blink-tiny-ram [new file with mode: 0644]
tests/chip_id [new file with mode: 0644]
tests/debug_mode [new file with mode: 0644]
tests/get_pc [new file with mode: 0644]
tests/get_status [new file with mode: 0644]
tests/half_phase [new file with mode: 0644]
tests/in [new file with mode: 0644]
tests/p1_1 [new file with mode: 0644]
tests/rd_config [new file with mode: 0644]
tests/read_status [new file with mode: 0644]
tests/reset [new file with mode: 0644]
tests/wr_config [new file with mode: 0644]

index 190ba2f..71b0a61 100644 (file)
@@ -1,32 +1,44 @@
+*.a
 *.adb
 *.asm
-*.lst
-*.ihx
-*.rel
-*.sym
-*.rst
 *.cdb
+*.ihx
 *.lnk
+*.lst
 *.map
 *.mem
-telemetrum
-teleterra
-tidongle
-teledongle
+*.o
+*.rel
+*.rst
+*.sym
+.deps
+aclocal.m4
 ao_flight_test
+ao-teledongle.h
 ao-telemetrum.h
 ao-teleterra.h
-ao-teledongle.h
 ao-tidongle.h
-Makefile.in
-aclocal.m4
-.deps
+aoload/aoload
+ccdump/ccdump
+ccmanual/ccmanual
+aoview/Makefile
+aoview/aoview
 autom4te.cache
 config.*
+config.h
+config.h.in
+config.h.in~
+config.log
+config.status
+configure
 depcomp
 install-sh
+Makefile
+Makefile.in
 missing
 stamp-h1
-configure
-Makefile
-aoview/Makefile
+tags
+teledongle
+telemetrum
+teleterra
+tidongle
diff --git a/AUTHORS b/AUTHORS
index 9cee037..a5b6500 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -1 +1,2 @@
-Keith Packard <keithp@keithp.com>
+Keith Packard  <keithp@keithp.com>
+Bdale Garbee   <bdale@gag.com>
diff --git a/INSTALL b/INSTALL
index c9fd2c0..200806c 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -2,15 +2,15 @@ Installation Instructions
 *************************
 
 Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
-2006, 2007, 2008 Free Software Foundation, Inc.
+2006, 2007 Free Software Foundation, Inc.
 
-   This file is free documentation; the Free Software Foundation gives
+This file is free documentation; the Free Software Foundation gives
 unlimited permission to copy, distribute and modify it.
 
 Basic Installation
 ==================
 
-   Briefly, the shell commands `./configure; make; make install' should
+Briefly, the shell commands `./configure; make; make install' should
 configure, build, and install this package.  The following
 more-detailed instructions are generic; see the `README' file for
 instructions specific to this package.
@@ -73,9 +73,9 @@ The simplest way to compile this package is:
 Compilers and Options
 =====================
 
-   Some systems require unusual options for compilation or linking that
-the `configure' script does not know about.  Run `./configure --help'
-for details on some of the pertinent environment variables.
+Some systems require unusual options for compilation or linking that the
+`configure' script does not know about.  Run `./configure --help' for
+details on some of the pertinent environment variables.
 
    You can give `configure' initial values for configuration parameters
 by setting variables in the command line or in the environment.  Here
@@ -88,7 +88,7 @@ is an example:
 Compiling For Multiple Architectures
 ====================================
 
-   You can compile the package for more than one kind of computer at the
+You can compile the package for more than one kind of computer at the
 same time, by placing the object files for each architecture in their
 own directory.  To do this, you can use GNU `make'.  `cd' to the
 directory where you want the object files and executables to go and run
@@ -100,24 +100,10 @@ architecture at a time in the source code directory.  After you have
 installed the package for one architecture, use `make distclean' before
 reconfiguring for another architecture.
 
-   On MacOS X 10.5 and later systems, you can create libraries and
-executables that work on multiple system types--known as "fat" or
-"universal" binaries--by specifying multiple `-arch' options to the
-compiler but only a single `-arch' option to the preprocessor.  Like
-this:
-
-     ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
-                 CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
-                 CPP="gcc -E" CXXCPP="g++ -E"
-
-   This is not guaranteed to produce working output in all cases, you
-may have to build one architecture at a time and combine the results
-using the `lipo' tool if you have problems.
-
 Installation Names
 ==================
 
-   By default, `make install' installs the package's commands under
+By default, `make install' installs the package's commands under
 `/usr/local/bin', include files under `/usr/local/include', etc.  You
 can specify an installation prefix other than `/usr/local' by giving
 `configure' the option `--prefix=PREFIX'.
@@ -140,7 +126,7 @@ option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
 Optional Features
 =================
 
-   Some packages pay attention to `--enable-FEATURE' options to
+Some packages pay attention to `--enable-FEATURE' options to
 `configure', where FEATURE indicates an optional part of the package.
 They may also pay attention to `--with-PACKAGE' options, where PACKAGE
 is something like `gnu-as' or `x' (for the X Window System).  The
@@ -152,36 +138,14 @@ find the X include and library files automatically, but if it doesn't,
 you can use the `configure' options `--x-includes=DIR' and
 `--x-libraries=DIR' to specify their locations.
 
-Particular systems
-==================
-
-   On HP-UX, the default C compiler is not ANSI C compatible.  If GNU
-CC is not installed, it is recommended to use the following options in
-order to use an ANSI C compiler:
-
-     ./configure CC="cc -Ae"
-
-and if that doesn't work, install pre-built binaries of GCC for HP-UX.
-
-   On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
-parse its `<wchar.h>' header file.  The option `-nodtk' can be used as
-a workaround.  If GNU CC is not installed, it is therefore recommended
-to try
-
-     ./configure CC="cc"
-
-and if that doesn't work, try
-
-     ./configure CC="cc -nodtk"
-
 Specifying the System Type
 ==========================
 
-   There may be some features `configure' cannot figure out
-automatically, but needs to determine by the type of machine the package
-will run on.  Usually, assuming the package is built to be run on the
-_same_ architectures, `configure' can figure that out, but if it prints
-message saying it cannot guess the machine type, give it the
+There may be some features `configure' cannot figure out automatically,
+but needs to determine by the type of machine the package will run on.
+Usually, assuming the package is built to be run on the _same_
+architectures, `configure' can figure that out, but if it prints a
+message saying it cannot guess the machine type, give it the
 `--build=TYPE' option.  TYPE can either be a short name for the system
 type, such as `sun4', or a canonical name which has the form:
 
@@ -207,9 +171,9 @@ eventually be run) with `--host=TYPE'.
 Sharing Defaults
 ================
 
-   If you want to set default values for `configure' scripts to share,
-you can create a site shell script called `config.site' that gives
-default values for variables like `CC', `cache_file', and `prefix'.
+If you want to set default values for `configure' scripts to share, you
+can create a site shell script called `config.site' that gives default
+values for variables like `CC', `cache_file', and `prefix'.
 `configure' looks for `PREFIX/share/config.site' if it exists, then
 `PREFIX/etc/config.site' if it exists.  Or, you can set the
 `CONFIG_SITE' environment variable to the location of the site script.
@@ -218,7 +182,7 @@ A warning: not all `configure' scripts look for a site script.
 Defining Variables
 ==================
 
-   Variables not defined in a site shell script can be set in the
+Variables not defined in a site shell script can be set in the
 environment passed to `configure'.  However, some packages may run
 configure again during the build, and the customized values of these
 variables may be lost.  In order to avoid this problem, you should set
@@ -237,19 +201,11 @@ an Autoconf bug.  Until the bug is fixed you can use this workaround:
 `configure' Invocation
 ======================
 
-   `configure' recognizes the following options to control how it
-operates.
+`configure' recognizes the following options to control how it operates.
 
 `--help'
 `-h'
-     Print a summary of all of the options to `configure', and exit.
-
-`--help=short'
-`--help=recursive'
-     Print a summary of the options unique to this package's
-     `configure', and exit.  The `short' variant lists options used
-     only in the top level, while the `recursive' variant lists options
-     also present in any nested packages.
+     Print a summary of the options to `configure', and exit.
 
 `--version'
 `-V'
@@ -276,15 +232,5 @@ operates.
      Look for the package's source code in directory DIR.  Usually
      `configure' can determine that directory automatically.
 
-`--prefix=DIR'
-     Use DIR as the installation prefix.  *Note Installation Names::
-     for more details, including other options available for fine-tuning
-     the installation locations.
-
-`--no-create'
-`-n'
-     Run the configure checks, but stop before creating any output
-     files.
-
 `configure' also accepts some other, not widely useful, options.  Run
 `configure --help' for more details.
index e5c0c1e..b0d059e 100644 (file)
@@ -1 +1 @@
-SUBDIRS=src aoview
+SUBDIRS=src aoview lib ccload s51 ccmanual ccdump aoload
diff --git a/aoload/Makefile.am b/aoload/Makefile.am
new file mode 100644 (file)
index 0000000..2e32c0b
--- /dev/null
@@ -0,0 +1,10 @@
+bin_PROGRAMS=aoload
+
+AM_CFLAGS=-I$(top_srcdir)/lib $(LIBUSB_CFLAGS)
+AOLOAD_LIBS=../lib/libcc.a
+
+aoload_DEPENDENCIES = $(AOLOAD_LIBS)
+
+aoload_LDADD=$(AOLOAD_LIBS) $(LIBUSB_LIBS)
+
+aoload_SOURCES = aoload.c
diff --git a/aoload/aoload.c b/aoload/aoload.c
new file mode 100644 (file)
index 0000000..b84a88a
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * 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 <stdlib.h>
+#include <limits.h>
+#include <stdint.h>
+#include "ccdbg.h"
+
+#define AO_USB_DESC_STRING             3
+
+void
+usage(char *program)
+{
+       fprintf(stderr, "usage: %s <filename.ihx> <serial>\n", program);
+       exit(1);
+}
+
+struct sym {
+       unsigned        addr;
+       char            *name;
+} serial_symbols[] = {
+       { 0,    "_ao_serial_number" },
+#define AO_SERIAL_NUMBER       (serial_symbols[0].addr)
+       { 0,    "_ao_usb_descriptors" },
+#define AO_USB_DESCRIPTORS     (serial_symbols[1].addr)
+};
+
+#define NUM_SERIAL_SYMBOLS     (sizeof(serial_symbols)/sizeof(serial_symbols[0]))
+
+static int
+find_symbols(FILE *map)
+{
+       char    line[2048];
+       char    *addr, *addr_end;
+       char    *name;
+       char    *save;
+       char    *colon;
+       unsigned long   a;
+       int     s;
+       int     found = 0;
+
+       while (fgets(line, sizeof(line), map) != NULL) {
+               line[sizeof(line)-1] = '\0';
+               addr = strtok_r(line, " \t\n", &save);
+               if (!addr)
+                       continue;
+               name = strtok_r(NULL, " \t\n", &save);
+               if (!name)
+                       continue;
+               colon = strchr (addr, ':');
+               if (!colon)
+                       continue;
+               a = strtoul(colon+1, &addr_end, 16);
+               if (a == ULONG_MAX || addr_end == addr)
+                       continue;
+               for (s = 0; s < NUM_SERIAL_SYMBOLS; s++)
+                       if (!strcmp(serial_symbols[s].name, name)) {
+                               serial_symbols[s].addr = (unsigned) a;
+                               ++found;
+                               break;
+                       }
+       }
+       return found == NUM_SERIAL_SYMBOLS;
+}
+
+static int
+rewrite(struct hex_image *image, unsigned addr, char *data, int len)
+{
+       int i;
+       if (addr < image->address || image->address + image->length < addr + len)
+               return 0;
+       printf("rewrite %04x:", addr);
+       for (i = 0; i < len; i++)
+               printf (" %02x", image->data[addr - image->address + i]);
+       printf(" ->");
+       for (i = 0; i < len; i++)
+               printf (" %02x", data[i]);
+       printf("\n");
+       memcpy(image->data + addr - image->address, data, len);
+}
+
+int
+main (int argc, char **argv)
+{
+       struct ccdbg    *dbg;
+       uint8_t         status;
+       uint16_t        pc;
+       struct hex_file *hex;
+       struct hex_image *image;
+       char *filename;
+       FILE *file;
+       FILE *map;
+       char *serial_string;
+       unsigned int serial;
+       char *mapname, *dot;
+       char            *serial_ucs2;
+       int             serial_ucs2_len;
+       char            serial_int[2];
+       unsigned int    s;
+       int             i;
+       unsigned        usb_descriptors;
+       int             string_num;
+
+       filename = argv[1];
+       if (filename == NULL)
+               usage(argv[0]);
+       mapname = strdup(filename);
+       dot = strrchr(mapname, '.');
+       if (!dot || strcmp(dot, ".ihx") != 0)
+               usage(argv[0]);
+       strcpy(dot, ".map");
+
+       serial_string = argv[2];
+       if (serial_string == NULL)
+               usage(argv[0]);
+
+       file = fopen(filename, "r");
+       if (!file) {
+               perror(filename);
+               exit(1);
+       }
+       map = fopen(mapname, "r");
+       if (!map) {
+               perror(mapname);
+               exit(1);
+       }
+       if (!find_symbols(map)) {
+               fprintf(stderr, "Cannot find symbols in \"%s\"\n", mapname);
+               exit(1);
+       }
+       fclose(map);
+
+       hex = ccdbg_hex_file_read(file, filename);
+       fclose(file);
+       if (!hex) {
+               perror(filename);
+               exit (1);
+       }
+       image = ccdbg_hex_image_create(hex);
+       if (!image) {
+               fprintf(stderr, "image create failed\n");
+               exit (1);
+       }
+       ccdbg_hex_file_free(hex);
+
+       serial = strtoul(serial_string, NULL, 0);
+       if (!serial)
+               usage(argv[0]);
+
+       serial_int[0] = serial & 0xff;
+       serial_int[1] = (serial >> 8) & 0xff;
+
+       if (!rewrite(image, AO_SERIAL_NUMBER, serial_int, sizeof (serial_int))) {
+               fprintf(stderr, "Cannot rewrite serial integer at %04x\n",
+                       AO_SERIAL_NUMBER);
+               exit(1);
+       }
+
+       usb_descriptors = AO_USB_DESCRIPTORS - image->address;
+       string_num = 0;
+       while (image->data[usb_descriptors] != 0 && usb_descriptors < image->length) {
+               if (image->data[usb_descriptors+1] == AO_USB_DESC_STRING) {
+                       ++string_num;
+                       if (string_num == 4)
+                               break;
+               }
+               usb_descriptors += image->data[usb_descriptors];
+       }
+       if (usb_descriptors >= image->length || image->data[usb_descriptors] == 0 ) {
+               fprintf(stderr, "Cannot rewrite serial string at %04x\n", AO_USB_DESCRIPTORS);
+               exit(1);
+       }
+
+       serial_ucs2_len = image->data[usb_descriptors] - 2;
+       serial_ucs2 = malloc(serial_ucs2_len);
+       if (!serial_ucs2) {
+               fprintf(stderr, "Malloc(%d) failed\n", serial_ucs2_len);
+               exit(1);
+       }
+       s = serial;
+       for (i = serial_ucs2_len / 2; i; i--) {
+               serial_ucs2[i * 2 - 1] = 0;
+               serial_ucs2[i * 2 - 2] = (s % 10) + '0';
+               s /= 10;
+       }
+       if (!rewrite(image, usb_descriptors + 2 + image->address, serial_ucs2, serial_ucs2_len))
+               usage(argv[0]);
+
+       dbg = ccdbg_open();
+       if (!dbg)
+               exit (1);
+
+       ccdbg_add_debug(CC_DEBUG_FLASH);
+
+       ccdbg_debug_mode(dbg);
+       ccdbg_halt(dbg);
+       if (image->address == 0xf000) {
+               printf("Loading %d bytes to execute from RAM\n",
+                      image->length);
+               ccdbg_write_hex_image(dbg, image, 0);
+       } else if (image->address == 0x0000) {
+               printf("Loading %d bytes to execute from FLASH\n",
+                      image->length);
+               ccdbg_flash_hex_image(dbg, image);
+       } else {
+               printf("Cannot load code to 0x%04x\n",
+                      image->address);
+               ccdbg_hex_image_free(image);
+               ccdbg_close(dbg);
+               exit(1);
+       }
+       ccdbg_set_pc(dbg, image->address);
+       ccdbg_resume(dbg);
+       ccdbg_close(dbg);
+       exit (0);
+}
index 9f67ac4..be3fbac 100644 (file)
@@ -1,9 +1,9 @@
 VERSION=$(shell git describe)
-AM_CFLAGS=$(AOVIEW_CFLAGS) -I$(top_srcdir)/src -DAOVIEW_VERSION=\"$(VERSION)\"
+AM_CFLAGS=$(GNOME_CFLAGS) -I$(top_srcdir)/src -DAOVIEW_VERSION=\"$(VERSION)\"
 
 bin_PROGRAMS=aoview
 
-aoview_LDADD=$(AOVIEW_LIBS)
+aoview_LDADD=$(GNOME_LIBS)
 
 aoview_SOURCES = \
        aoview_main.c \
diff --git a/ccdump/Makefile.am b/ccdump/Makefile.am
new file mode 100644 (file)
index 0000000..976383f
--- /dev/null
@@ -0,0 +1,10 @@
+bin_PROGRAMS=ccdump
+
+AM_CFLAGS=-I$(top_srcdir)/lib $(LIBUSB_CFLAGS)
+CCLOAD_LIBS=../lib/libcc.a
+
+ccdump_DEPENDENCIES = $(CCLOAD_LIBS)
+
+ccdump_LDADD=$(CCLOAD_LIBS) $(LIBUSB_LIBS)
+
+ccdump_SOURCES = ccdump.c
diff --git a/ccdump/ccdump.c b/ccdump/ccdump.c
new file mode 100644 (file)
index 0000000..399732d
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright © 2009 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 <stdlib.h>
+#include "cc-usb.h"
+
+#define NUM_BLOCK      512
+
+int
+main (int argc, char **argv)
+{
+       struct cc_usb   *cc;
+       int             block;
+       uint8_t         bytes[32 * (2 + 8)];
+       uint8_t         *b;
+       int             i, j;
+       uint32_t        addr;
+       char            *tty;
+
+       tty = getenv("CCDBG_TTY");
+       cc = cc_usb_open(tty);
+       for (block = 0; block < NUM_BLOCK; block++) {
+               cc_queue_read(cc, bytes, sizeof (bytes));
+               cc_usb_printf(cc, "e %x\n", block);
+               cc_usb_sync(cc);
+               for (i = 0; i < 32; i++) {
+                       b = bytes + (i * 10);
+                       addr = block * 256 + i * 8;
+                       printf ("%06x", addr);
+                       for (j = 0; j < 8; j++) {
+                               printf (" %02x", b[j+2]);
+                       }
+                       printf ("\n");
+               }
+       }
+       cc_usb_close(cc);
+       exit (0);
+}
diff --git a/ccload/.gitignore b/ccload/.gitignore
new file mode 100644 (file)
index 0000000..3899747
--- /dev/null
@@ -0,0 +1 @@
+ccload
diff --git a/ccload/Makefile.am b/ccload/Makefile.am
new file mode 100644 (file)
index 0000000..3a754b2
--- /dev/null
@@ -0,0 +1,10 @@
+bin_PROGRAMS=ccload
+
+AM_CFLAGS=-I$(top_srcdir)/lib $(LIBUSB_CFLAGS)
+CCLOAD_LIBS=../lib/libcc.a
+
+ccload_DEPENDENCIES = $(CCLOAD_LIBS)
+
+ccload_LDADD=$(CCLOAD_LIBS) $(LIBUSB_LIBS)
+
+ccload_SOURCES = ccload.c
diff --git a/ccload/ccload.c b/ccload/ccload.c
new file mode 100644 (file)
index 0000000..5f7708f
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * 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 "ccdbg.h"
+
+int
+main (int argc, char **argv)
+{
+       struct ccdbg    *dbg;
+       uint8_t         status;
+       uint16_t        pc;
+       struct hex_file *hex;
+       struct hex_image *image;
+       char *filename;
+       FILE *file;
+
+       filename = argv[1];
+       if (filename == NULL) {
+               fprintf(stderr, "usage: %s <filename.ihx>\n", argv[0]);
+               exit(1);
+       }
+       file = fopen(filename, "r");
+       if (!file) {
+               perror(filename);
+               exit(1);
+       }
+       hex = ccdbg_hex_file_read(file, filename);
+       fclose(file);
+       if (!hex)
+               exit (1);
+       image = ccdbg_hex_image_create(hex);
+       if (!image) {
+               fprintf(stderr, "image create failed\n");
+               exit (1);
+       }
+
+       ccdbg_hex_file_free(hex);
+       dbg = ccdbg_open();
+       if (!dbg)
+               exit (1);
+
+       ccdbg_add_debug(CC_DEBUG_FLASH);
+
+       ccdbg_debug_mode(dbg);
+       ccdbg_halt(dbg);
+       if (image->address == 0xf000) {
+               printf("Loading %d bytes to execute from RAM\n",
+                      image->length);
+               ccdbg_write_hex_image(dbg, image, 0);
+       } else if (image->address == 0x0000) {
+               printf("Loading %d bytes to execute from FLASH\n",
+                      image->length);
+               ccdbg_flash_hex_image(dbg, image);
+       } else {
+               printf("Cannot load code to 0x%04x\n",
+                      image->address);
+               ccdbg_hex_image_free(image);
+               ccdbg_close(dbg);
+               exit(1);
+       }
+       ccdbg_set_pc(dbg, image->address);
+       ccdbg_resume(dbg);
+       ccdbg_close(dbg);
+       exit (0);
+}
diff --git a/ccmanual/Makefile.am b/ccmanual/Makefile.am
new file mode 100644 (file)
index 0000000..4477ef8
--- /dev/null
@@ -0,0 +1,10 @@
+bin_PROGRAMS=ccmanual
+
+AM_CFLAGS=-I$(top_srcdir)/lib $(LIBUSB_CFLAGS)
+CCMANUAL_LIBS=../lib/libcc.a
+
+ccmanual_DEPENDENCIES = $(CCMANUAL_LIBS)
+
+ccmanual_LDADD=$(CCMANUAL_LIBS) $(LIBUSB_LIBS)
+
+ccmanual_SOURCES = ccmanual.c
diff --git a/ccmanual/ccmanual.c b/ccmanual/ccmanual.c
new file mode 100644 (file)
index 0000000..7090c9a
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright © 2009 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 "ccdbg.h"
+
+int
+main (int argc, char **argv)
+{
+       struct ccdbg    *dbg;
+
+       dbg = ccdbg_open();
+       if (!dbg)
+               exit (1);
+
+       ccdbg_add_debug(CC_DEBUG_BITBANG);
+
+       ccdbg_manual(dbg, stdin);
+}
index 0419489..99511a6 100644 (file)
@@ -1,5 +1,5 @@
 dnl
-dnl  Copyright © 2008 Keith Packard <keithp@keithp.com>
+dnl  Copyright © 2008,2009 Keith Packard <keithp@keithp.com>
 dnl
 dnl  This program is free software; you can redistribute it and/or modify
 dnl  it under the terms of the GNU General Public License as published by
@@ -17,9 +17,9 @@ dnl  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
 dnl
 dnl Process this file with autoconf to create configure.
 
-AC_INIT(aoview)
+AC_INIT(COPYING)
 
-AM_INIT_AUTOMAKE(aoview, 0.1)
+AM_INIT_AUTOMAKE(altos, 0.1)
 AM_MAINTAINER_MODE
 
 dnl ==========================================================================
@@ -43,16 +43,17 @@ if test "x$GCC" = "xyes"; then
 fi
 AC_SUBST(WARN_CFLAGS)
 
-dnl ==========================================================================
-
-AM_CONDITIONAL(CROSS_COMPILING, test $cross_compiling = yes)
-
-dnl ==========================================================================
-
+PKG_CHECK_MODULES([GNOME], [gtk+-2.0 libglade-2.0 gconf-2.0])
 
-PKG_CHECK_MODULES([AOVIEW], [gtk+-2.0 libglade-2.0 gconf-2.0])
+PKG_CHECK_MODULES([LIBUSB], [libusb-1.0])
 
 AC_OUTPUT([
 Makefile
 aoview/Makefile
+lib/Makefile
+ccload/Makefile
+s51/Makefile
+ccmanual/Makefile
+ccdump/Makefile
+aoload/Makefile
 ])
diff --git a/lib/Makefile.am b/lib/Makefile.am
new file mode 100644 (file)
index 0000000..4d9ded3
--- /dev/null
@@ -0,0 +1,21 @@
+noinst_LIBRARIES = libcc.a
+
+AM_CFLAGS=$(WARN_CFLAGS) $(LIBUSB_CFLAGS)
+
+libcc_a_SOURCES = \
+       ccdbg-command.c \
+       ccdbg-debug.c \
+       ccdbg-flash.c \
+       ccdbg.h \
+       ccdbg-hex.c \
+       ccdbg-io.c \
+       ccdbg-manual.c \
+       ccdbg-memory.c \
+       ccdbg-rom.c \
+       ccdbg-state.c \
+       cc-usb.c \
+       cc-usb.h \
+       cc-bitbang.c \
+       cc-bitbang.h \
+       cp-usb.c \
+       cp-usb-async.c
diff --git a/lib/cc-bitbang.c b/lib/cc-bitbang.c
new file mode 100644 (file)
index 0000000..1d3ba47
--- /dev/null
@@ -0,0 +1,269 @@
+/*
+ * Copyright © 2009 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 <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "ccdbg-debug.h"
+#include "cc-bitbang.h"
+
+#define CP_USB_ASYNC
+
+#ifdef CP_USB_ASYNC
+#include "cp-usb-async.h"
+#else
+#include "cp-usb.h"
+#endif
+
+struct cc_bitbang {
+#ifdef CP_USB_ASYNC
+       struct cp_usb_async *cp_async;
+#else
+       struct cp_usb *cp;
+#endif
+};
+
+static uint32_t        cc_clock_us = CC_CLOCK_US;
+static uint32_t        cc_reset_us = CC_RESET_US;
+
+void
+cc_bitbang_set_clock(uint32_t us)
+{
+       cc_clock_us = us;
+}
+
+void
+cc_bitbang_half_clock(struct cc_bitbang *bb)
+{
+       struct timespec req, rem;
+       req.tv_sec = (cc_clock_us / 2) / 1000000;
+       req.tv_nsec = ((cc_clock_us / 2) % 1000000) * 1000;
+       nanosleep(&req, &rem);
+}
+
+void
+cc_bitbang_wait_reset(struct cc_bitbang *bb)
+{
+       struct timespec req, rem;
+
+       cc_bitbang_sync(bb);
+       req.tv_sec = (cc_reset_us) / 1000000;
+       req.tv_nsec = ((cc_reset_us) % 1000000) * 1000;
+       nanosleep(&req, &rem);
+}
+
+struct cc_bitbang *
+cc_bitbang_open(void)
+{
+       struct cc_bitbang *bb;
+
+       bb = calloc(sizeof (struct cc_bitbang), 1);
+       if (!bb) {
+               perror("calloc");
+               return NULL;
+       }
+#ifdef CP_USB_ASYNC
+       bb->cp_async = cp_usb_async_open();
+       if (!bb->cp_async) {
+               free (bb);
+               return NULL;
+       }
+#else
+       bb->cp = cp_usb_open ();
+       if (!bb->cp) {
+               free (bb);
+               return NULL;
+       }
+#endif
+       return bb;
+}
+
+void
+cc_bitbang_close(struct cc_bitbang *bb)
+{
+#ifdef CP_USB_ASYNC
+       cp_usb_async_close(bb->cp_async);
+#else
+       cp_usb_close(bb->cp);
+#endif
+       free (bb);
+}
+
+void
+cc_bitbang_debug_mode(struct cc_bitbang *bb)
+{
+       /* force two rising clocks while holding RESET_N low */
+       ccdbg_debug(CC_DEBUG_COMMAND, "#\n");
+       ccdbg_debug(CC_DEBUG_COMMAND, "# Debug mode\n");
+       ccdbg_debug(CC_DEBUG_COMMAND, "#\n");
+       cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA|CC_RESET_N);
+       cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N,          CC_DATA           );
+       cc_bitbang_wait_reset(bb);
+       cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA           );
+       cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N,          CC_DATA           );
+       cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA           );
+       cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N,          CC_DATA|CC_RESET_N);
+       cc_bitbang_wait_reset(bb);
+}
+
+void
+cc_bitbang_reset(struct cc_bitbang *bb)
+{
+       ccdbg_debug(CC_DEBUG_COMMAND, "#\n");
+       ccdbg_debug(CC_DEBUG_COMMAND, "# Reset\n");
+       ccdbg_debug(CC_DEBUG_COMMAND, "#\n");
+       cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA|CC_RESET_N);
+       cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA           );
+       cc_bitbang_wait_reset(bb);
+       cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA           );
+       cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA           );
+       cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA           );
+       cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA|CC_RESET_N);
+       cc_bitbang_wait_reset(bb);
+}
+
+int
+cc_bitbang_write(struct cc_bitbang *bb, uint8_t mask, uint8_t value)
+{
+#ifdef CP_USB_ASYNC
+       cp_usb_async_write(bb->cp_async, mask, value);
+#else
+       cp_usb_write(bb->cp, mask, value);
+#endif
+       return 0;
+}
+
+void
+cc_bitbang_read(struct cc_bitbang *bb, uint8_t *valuep)
+{
+#ifdef CP_USB_ASYNC
+       cp_usb_async_read(bb->cp_async, valuep);
+#else
+       *valuep = cp_usb_read(bb->cp);
+#endif
+}
+
+void
+cc_bitbang_sync(struct cc_bitbang *bb)
+{
+#ifdef CP_USB_ASYNC
+       cp_usb_async_sync(bb->cp_async);
+#endif
+}
+
+static char
+is_bit(uint8_t get, uint8_t mask, char on, uint8_t bit)
+{
+       if (mask&bit) {
+               if (get&bit)
+                       return on;
+               else
+                       return '.';
+       } else
+               return '-';
+}
+
+void
+cc_bitbang_print(char *format, uint8_t mask, uint8_t set)
+{
+       ccdbg_debug (CC_DEBUG_BITBANG, format,
+                    is_bit(set, mask, 'C', CC_CLOCK),
+                    is_bit(set, mask, 'D', CC_DATA),
+                    is_bit(set, mask, 'R', CC_RESET_N));
+}
+
+void
+cc_bitbang_send(struct cc_bitbang *bb, uint8_t mask, uint8_t set)
+{
+       cc_bitbang_write(bb, mask, set);
+       cc_bitbang_print("%c %c %c\n", mask, set);
+       cc_bitbang_half_clock(bb);
+}
+
+void
+cc_bitbang_send_bit(struct cc_bitbang *bb, uint8_t bit)
+{
+       if (bit) bit = CC_DATA;
+       cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|bit|CC_RESET_N);
+       cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N,          bit|CC_RESET_N);
+}
+
+void
+cc_bitbang_send_byte(struct cc_bitbang *bb, uint8_t byte)
+{
+       int bit;
+       ccdbg_debug(CC_DEBUG_BITBANG, "#\n# Send Byte 0x%02x\n#\n", byte);
+       for (bit = 7; bit >= 0; bit--) {
+               cc_bitbang_send_bit(bb, (byte >> bit) & 1);
+               if (bit == 3)
+                       ccdbg_debug(CC_DEBUG_BITBANG, "\n");
+       }
+       cc_bitbang_sync(bb);
+}
+
+void
+cc_bitbang_send_bytes(struct cc_bitbang *bb, uint8_t *bytes, int nbytes)
+{
+       while (nbytes--)
+               cc_bitbang_send_byte(bb, *bytes++);
+}
+
+void
+cc_bitbang_recv_bit(struct cc_bitbang *bb, int first, uint8_t *bit)
+{
+       uint8_t mask = first ? CC_DATA : 0;
+
+       cc_bitbang_send(bb, CC_CLOCK|mask|CC_RESET_N, CC_CLOCK|CC_DATA|CC_RESET_N);
+       cc_bitbang_read(bb, bit);
+       cc_bitbang_send(bb, CC_CLOCK|     CC_RESET_N,                  CC_RESET_N);
+}
+
+void
+cc_bitbang_recv_byte(struct cc_bitbang *bb, 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++) {
+               cc_bitbang_recv_bit(bb, first, &bits[bit]);
+               first = 0;
+       }
+       cc_bitbang_sync(bb);
+       for (bit = 0; bit < 8; bit++) {
+               byte = byte << 1;
+               byte |= (bits[bit] & CC_DATA) ? 1 : 0;
+               cc_bitbang_print("#\t%c %c %c\n", CC_DATA, bits[bit]);
+               if (bit == 3)
+                       ccdbg_debug(CC_DEBUG_BITBANG, "\n");
+       }
+       ccdbg_debug(CC_DEBUG_BITBANG, "#\n# Recv 0x%02x\n#\n", byte);
+       *bytep = byte;
+}
+
+void
+cc_bitbang_recv_bytes(struct cc_bitbang *bb, uint8_t *bytes, int nbytes)
+{
+       int i;
+       int first = 1;
+       for (i = 0; i < nbytes; i++) {
+               cc_bitbang_recv_byte(bb, first, &bytes[i]);
+               first = 0;
+       }
+}
diff --git a/lib/cc-bitbang.h b/lib/cc-bitbang.h
new file mode 100644 (file)
index 0000000..54b20e2
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright © 2009 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 _CC_BITBANG_H_
+#define _CC_BITBANG_H_
+
+#include <stdint.h>
+
+#define CC_CLOCK       0x1
+#define CC_DATA                0x2
+#define CC_RESET_N     0x4
+#define CC_CLOCK_US    (2)
+
+/* Telemetrum has a 10k pull-up to 3.3v, a 0.001uF cap to ground
+ * and a 2.7k resistor to the reset line. This takes about 6us
+ * to settle, so we'll wait longer than that after changing the reset line
+ */
+#define CC_RESET_US    (12)
+
+struct cc_bitbang;
+
+void
+cc_bitbang_set_clock(uint32_t us);
+
+void
+cc_bitbang_half_clock(struct cc_bitbang *bb);
+
+void
+cc_bitbang_wait_reset(struct cc_bitbang *bb);
+
+struct cc_bitbang *
+cc_bitbang_open(void);
+
+void
+cc_bitbang_close(struct cc_bitbang *bb);
+
+void
+cc_bitbang_debug_mode(struct cc_bitbang *bb);
+
+void
+cc_bitbang_reset(struct cc_bitbang *bb);
+
+int
+cc_bitbang_write(struct cc_bitbang *bb, uint8_t mask, uint8_t value);
+
+void
+cc_bitbang_read(struct cc_bitbang *bb, uint8_t *valuep);
+
+void
+cc_bitbang_sync(struct cc_bitbang *bb);
+
+void
+cc_bitbang_print(char *format, uint8_t mask, uint8_t set);
+
+void
+cc_bitbang_print(char *format, uint8_t mask, uint8_t set);
+
+void
+cc_bitbang_send(struct cc_bitbang *bb, uint8_t mask, uint8_t set);
+
+void
+cc_bitbang_send_bit(struct cc_bitbang *bb, uint8_t bit);
+
+void
+cc_bitbang_send_byte(struct cc_bitbang *bb, uint8_t byte);
+
+void
+cc_bitbang_send_bytes(struct cc_bitbang *bb, uint8_t *bytes, int nbytes);
+
+void
+cc_bitbang_recv_bit(struct cc_bitbang *bb, int first, uint8_t *bit);
+
+void
+cc_bitbang_recv_byte(struct cc_bitbang *bb, int first, uint8_t *bytep);
+
+void
+cc_bitbang_recv_bytes(struct cc_bitbang *bb, uint8_t *bytes, int nbytes);
+
+#endif /* _CC_BITBANG_H_ */
diff --git a/lib/cc-usb.c b/lib/cc-usb.c
new file mode 100644 (file)
index 0000000..dc764c2
--- /dev/null
@@ -0,0 +1,359 @@
+/*
+ * Copyright © 2009 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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <poll.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <termios.h>
+#include "ccdbg-debug.h"
+#include "cc-usb.h"
+
+
+#define CC_NUM_READ            16
+/*
+ * AltOS has different buffer sizes for in/out packets
+ */
+#define CC_IN_BUF              256
+#define CC_OUT_BUF             64
+#define DEFAULT_TTY            "/dev/ttyACM0"
+
+struct cc_read {
+       uint8_t *buf;
+       int     len;
+};
+
+struct cc_usb {
+       int             fd;
+       uint8_t         in_buf[CC_IN_BUF];
+       int             in_count;
+       uint8_t         out_buf[CC_OUT_BUF];
+       int             out_count;
+       struct cc_read  read_buf[CC_NUM_READ];
+       int             read_count;
+};
+
+#define NOT_HEX        0xff
+
+static uint8_t
+cc_hex_nibble(uint8_t c)
+{
+       if ('0' <= c && c <= '9')
+               return c - '0';
+       if ('a' <= c && c <= 'f')
+               return c - 'a' + 10;
+       if ('A' <= c && c <= 'F')
+               return c - 'A' + 10;
+       return NOT_HEX;
+}
+
+/*
+ * Take raw input bytes, parse them as hex
+ * and write them to the waiting buffer
+ */
+static void
+cc_handle_in(struct cc_usb *cc)
+{
+       uint8_t h, l;
+       int     in_pos;
+       int     read_pos;
+
+       in_pos = 0;
+       read_pos = 0;
+       while (read_pos < cc->read_count && in_pos < cc->in_count) {
+               /*
+                * Skip to next hex character
+                */
+               while (in_pos < cc->in_count &&
+                      cc_hex_nibble(cc->in_buf[in_pos]) == NOT_HEX)
+                       in_pos++;
+               /*
+                * Make sure we have two characters left
+                */
+               if (cc->in_count - in_pos < 2)
+                       break;
+               /*
+                * Parse hex number
+                */
+               h = cc_hex_nibble(cc->in_buf[in_pos]);
+               l = cc_hex_nibble(cc->in_buf[in_pos+1]);
+               if (h == NOT_HEX || l == NOT_HEX) {
+                       fprintf(stderr, "hex read error\n");
+                       break;
+               }
+               in_pos += 2;
+               /*
+                * Store hex number
+                */
+               *cc->read_buf[read_pos].buf++ = (h << 4) | l;
+               if (--cc->read_buf[read_pos].len <= 0)
+                       read_pos++;
+       }
+
+       /* Move remaining bytes to the start of the input buffer */
+       if (in_pos) {
+               memmove(cc->in_buf, cc->in_buf + in_pos,
+                       cc->in_count - in_pos);
+               cc->in_count -= in_pos;
+       }
+
+       /* Move pending reads to the start of the array */
+       if (read_pos) {
+               memmove(cc->read_buf, cc->read_buf + read_pos,
+                       (cc->read_count - read_pos) * sizeof (cc->read_buf[0]));
+               cc->read_count -= read_pos;
+       }
+
+       /* Once we're done reading, flush any pending input */
+       if (cc->read_count == 0)
+               cc->in_count = 0;
+}
+
+static void
+cc_usb_dbg(int indent, uint8_t *bytes, int len)
+{
+       int     eol = 1;
+       int     i;
+       uint8_t c;
+       while (len--) {
+               c = *bytes++;
+               if (eol) {
+                       for (i = 0; i < indent; i++)
+                               ccdbg_debug(CC_DEBUG_BITBANG, " ");
+                       eol = 0;
+               }
+               switch (c) {
+               case '\r':
+                       ccdbg_debug(CC_DEBUG_BITBANG, "^M");
+                       break;
+               case '\n':
+                       eol = 1;
+               default:
+                       ccdbg_debug(CC_DEBUG_BITBANG, "%c", c);
+               }
+       }
+}
+
+/*
+ * Flush pending writes, fill pending reads
+ */
+void
+cc_usb_sync(struct cc_usb *cc)
+{
+       int             ret;
+       struct pollfd   fds;
+       int             timeout;
+
+       fds.fd = cc->fd;
+       for (;;) {
+               if (cc->read_count || cc->out_count)
+                       timeout = -1;
+               else
+                       timeout = 0;
+               fds.events = 0;
+               if (cc->in_count < CC_IN_BUF)
+                       fds.events |= POLLIN;
+               if (cc->out_count)
+                       fds.events |= POLLOUT;
+               ret = poll(&fds, 1, timeout);
+               if (ret == 0)
+                       break;
+               if (ret < 0) {
+                       perror("poll");
+                       break;
+               }
+               if (fds.revents & POLLIN) {
+                       ret = read(cc->fd, cc->in_buf + cc->in_count,
+                                  CC_IN_BUF - cc->in_count);
+                       if (ret > 0) {
+                               cc_usb_dbg(24, cc->in_buf + cc->in_count, ret);
+                               cc->in_count += ret;
+                               cc_handle_in(cc);
+                       } else if (ret < 0)
+                               perror("read");
+               }
+               if (fds.revents & POLLOUT) {
+                       ret = write(cc->fd, cc->out_buf,
+                                   cc->out_count);
+                       if (ret > 0) {
+                               cc_usb_dbg(0, cc->out_buf, ret);
+                               memmove(cc->out_buf,
+                                       cc->out_buf + ret,
+                                       cc->out_count - ret);
+                               cc->out_count -= ret;
+                       } else if (ret < 0)
+                               perror("write");
+               }
+       }
+}
+
+void
+cc_usb_printf(struct cc_usb *cc, char *format, ...)
+{
+       char    buf[1024], *b;
+       va_list ap;
+       int     ret, this_time;
+
+       /* sprintf to a local buffer */
+       va_start(ap, format);
+       ret = vsnprintf(buf, sizeof(buf), format, ap);
+       va_end(ap);
+       if (ret > sizeof(buf)) {
+               fprintf(stderr, "printf overflow for format %s\n",
+                       format);
+       }
+
+       /* flush local buffer to the wire */
+       b = buf;
+       while (ret > 0) {
+               this_time = ret;
+               if (this_time > CC_OUT_BUF - cc->out_count)
+                       this_time = CC_OUT_BUF - cc->out_count;
+               memcpy(cc->out_buf + cc->out_count, b, this_time);
+               cc->out_count += this_time;
+               ret -= this_time;
+               b += this_time;
+               while (cc->out_count >= CC_OUT_BUF)
+                       cc_usb_sync(cc);
+       }
+}
+
+int
+cc_usb_send_bytes(struct cc_usb *cc, uint8_t *bytes, int len)
+{
+       int     this_len;
+       int     ret = len;
+
+       while (len) {
+               this_len = len;
+               if (this_len > 8)
+                       this_len = 8;
+               len -= this_len;
+               cc_usb_printf(cc, "P");
+               while (this_len--)
+                       cc_usb_printf (cc, " %02x", (*bytes++) & 0xff);
+               cc_usb_printf(cc, "\n");
+       }
+       return ret;
+}
+
+void
+cc_queue_read(struct cc_usb *cc, uint8_t *buf, int len)
+{
+       struct cc_read  *read_buf;
+       while (cc->read_count >= CC_NUM_READ)
+               cc_usb_sync(cc);
+       read_buf = &cc->read_buf[cc->read_count++];
+       read_buf->buf = buf;
+       read_buf->len = len;
+}
+
+int
+cc_usb_recv_bytes(struct cc_usb *cc, uint8_t *buf, int len)
+{
+       cc_queue_read(cc, buf, len);
+       cc_usb_printf(cc, "G %x\n", len);
+       return len;
+}
+
+int
+cc_usb_write_memory(struct cc_usb *cc, uint16_t addr, uint8_t *bytes, int len)
+{
+       cc_usb_printf(cc, "O %x %x\n", len, addr);
+       while (len--)
+               cc_usb_printf(cc, "%02x", *bytes++);
+       return 0;
+}
+
+int
+cc_usb_read_memory(struct cc_usb *cc, uint16_t addr, uint8_t *bytes, int len)
+{
+       int     i;
+       cc_queue_read(cc, bytes, len);
+       cc_usb_printf(cc, "I %x %x\n", len, addr);
+       cc_usb_sync(cc);
+       for (i = 0; i < len; i++) {
+               if ((i & 15) == 0) {
+                       if (i)
+                               ccdbg_debug(CC_DEBUG_MEMORY, "\n");
+                       ccdbg_debug(CC_DEBUG_MEMORY, "\t%04x", addr + i);
+               }
+               ccdbg_debug(CC_DEBUG_MEMORY, " %02x", bytes[i]);
+       }
+       ccdbg_debug(CC_DEBUG_MEMORY, "\n");
+       return 0;
+}
+
+int
+cc_usb_debug_mode(struct cc_usb *cc)
+{
+       cc_usb_sync(cc);
+       cc_usb_printf(cc, "D\n");
+       return 1;
+}
+
+int
+cc_usb_reset(struct cc_usb *cc)
+{
+       cc_usb_sync(cc);
+       cc_usb_printf(cc, "R\n");
+       return 1;
+}
+
+static struct termios  save_termios;
+
+struct cc_usb *
+cc_usb_open(char *tty)
+{
+       struct cc_usb   *cc;
+       struct termios  termios;
+
+       if (!tty)
+               tty = DEFAULT_TTY;
+       cc = calloc (sizeof (struct cc_usb), 1);
+       if (!cc)
+               return NULL;
+       cc->fd = open(tty, O_RDWR | O_NONBLOCK);
+       if (cc->fd < 0) {
+               perror(tty);
+               free (cc);
+               return NULL;
+       }
+       tcgetattr(cc->fd, &termios);
+       save_termios = termios;
+       cfmakeraw(&termios);
+       tcsetattr(cc->fd, TCSAFLUSH, &termios);
+       cc_usb_printf(cc, "E 0\n");
+       cc_usb_sync(cc);
+       sleep(1);
+       cc_usb_sync(cc);
+       return cc;
+}
+
+void
+cc_usb_close(struct cc_usb *cc)
+{
+       tcsetattr(cc->fd, TCSAFLUSH, &save_termios);
+       close (cc->fd);
+       free (cc);
+}
diff --git a/lib/cc-usb.h b/lib/cc-usb.h
new file mode 100644 (file)
index 0000000..d7acfbd
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright © 2009 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 _CC_USB_H_
+#define _CC_USB_H_
+
+#include <stdint.h>
+
+struct cc_usb;
+
+struct cc_usb *
+cc_usb_open(char *tty);
+
+void
+cc_usb_close(struct cc_usb *cc);
+
+int
+cc_usb_send_bytes(struct cc_usb *cc, uint8_t *bytes, int len);
+
+int
+cc_usb_recv_bytes(struct cc_usb *cc, uint8_t *bytes, int len);
+
+int
+cc_usb_write_memory(struct cc_usb *cc, uint16_t addr, uint8_t *bytes, int len);
+
+int
+cc_usb_read_memory(struct cc_usb *cc, uint16_t addr, uint8_t *bytes, int len);
+
+int
+cc_usb_debug_mode(struct cc_usb *cc);
+
+int
+cc_usb_reset(struct cc_usb *cc);
+
+void
+cc_usb_sync(struct cc_usb *cc);
+
+void
+cc_queue_read(struct cc_usb *cc, uint8_t *buf, int len);
+
+void
+cc_usb_printf(struct cc_usb *cc, char *format, ...);
+
+#endif /* _CC_USB_H_ */
diff --git a/lib/cccp.c b/lib/cccp.c
new file mode 100644 (file)
index 0000000..34e866e
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * 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 "ccdbg.h"
+
+static void
+say(char *name, uint8_t bits)
+{
+       printf("%s: ", name);
+       if (bits & CC_RESET_N)
+               printf ("R ");
+       else
+               printf (". ");
+       if (bits & CC_CLOCK)
+               printf ("C ");
+       else
+               printf (". ");
+       if (bits & CC_DATA)
+               printf ("D\n");
+       else
+               printf (".\n");
+}
+
+static void
+_cccp_write(struct ccdbg *dbg, uint8_t mask, uint8_t value)
+{
+       uint16_t        set;
+       int             ret;
+
+       set = (mask) | (value << 8);
+       dbg->debug_data = (dbg->debug_data & ~mask) | (value & mask);
+       ret = ioctl(dbg->fd, CP2101_IOCTL_GPIOSET, &set);
+       if (ret < 0)
+               perror("CP2101_IOCTL_GPIOSET");
+}
+
+void
+cccp_write(struct ccdbg *dbg, uint8_t mask, uint8_t value)
+{
+       _cccp_write(dbg, mask, value);
+//     say("w", dbg->debug_data);
+}
+
+uint8_t
+cccp_read_all(struct ccdbg *dbg)
+{
+       int ret;
+       uint8_t get;
+       ret = ioctl(dbg->fd, CP2101_IOCTL_GPIOGET, &get);
+       if (ret < 0) {
+               perror("CP2101_IOCTL_GPIOGET");
+               get = 0;
+       }
+       return get;
+}
+
+uint8_t
+cccp_read(struct ccdbg *dbg, uint8_t mask)
+{
+       uint8_t         pull_up;
+       uint8_t         get;
+
+       /* tri-state the bits of interest */
+       pull_up = (~dbg->debug_data) & mask;
+       if (pull_up)
+               _cccp_write(dbg, pull_up, pull_up);
+       get = cccp_read_all(dbg);
+       say("\t\tr", get);
+       return get & mask;
+}
+
+void
+cccp_init(struct ccdbg *dbg)
+{
+       /* set all of the GPIOs to a known state */
+       cccp_write(dbg, 0xf, 0xf);
+}
+
+void
+cccp_fini(struct ccdbg *dbg)
+{
+       /* set all of the GPIOs to a known state */
+       cccp_write(dbg, 0xf, 0xf);
+       dbg->clock = 1;
+}
+
+cccp_open()
+{
+       dbg->fd = open("/dev/ttyUSB0", 2);
+       if (dbg->fd < 0) {
+               perror(file);
+               free(dbg);
+               return NULL;
+       }
+       cccp_init(dbg);
+       cccp_write(dbg, CC_CLOCK, CC_CLOCK);
+}
diff --git a/lib/cccp.h b/lib/cccp.h
new file mode 100644 (file)
index 0000000..eecdbb4
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+/*
+ * Interface for using a CP2103 to talk to a CC1111
+ */
+
+#ifndef _CCCP_H_
+#define _CCCP_H_
+
+void
+cccp_write(struct ccdbg *dbg, uint8_t mask, uint8_t value);
+
+uint8_t
+cccp_read_all(struct ccdbg *dbg);
+
+uint8_t
+cccp_read(struct ccdbg *dbg, uint8_t mask);
+
+void
+cccp_init(struct ccdbg *dbg);
+
+void
+cccp_fini(struct ccdbg *dbg);
+
+#endif /* _CCCP_H_ */
diff --git a/lib/ccdbg-command.c b/lib/ccdbg-command.c
new file mode 100644 (file)
index 0000000..a100287
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * 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 "ccdbg.h"
+
+uint8_t
+ccdbg_chip_erase(struct ccdbg *dbg)
+{
+       return ccdbg_cmd_write_read8(dbg, CC_CHIP_ERASE, NULL, 0);
+}
+
+uint8_t
+ccdbg_wr_config(struct ccdbg *dbg, uint8_t config)
+{
+       return ccdbg_cmd_write_read8(dbg, CC_WR_CONFIG, &config, 1);
+}
+
+uint8_t
+ccdbg_rd_config(struct ccdbg *dbg)
+{
+       return ccdbg_cmd_write_read8(dbg, CC_RD_CONFIG, NULL, 0);
+}
+
+uint16_t
+ccdbg_get_pc(struct ccdbg *dbg)
+{
+       uint16_t        pc1, pc2;
+
+       pc1 = ccdbg_cmd_write_read16(dbg, CC_GET_PC, NULL, 0);
+       pc2 = ccdbg_cmd_write_read16(dbg, CC_GET_PC, NULL, 0);
+       if (pc1 != pc2)
+               fprintf (stderr, "Invalid pc %04x != %04x\n",
+                        pc1, pc2);
+       return pc2;
+}
+
+uint8_t
+ccdbg_read_status(struct ccdbg *dbg)
+{
+       return ccdbg_cmd_write_read8(dbg, CC_READ_STATUS, NULL, 0);
+}
+
+uint8_t
+ccdbg_set_hw_brkpnt(struct ccdbg *dbg, uint8_t number, uint8_t enable, uint16_t addr)
+{
+       uint8_t data[3];
+
+       data[0] = (number << 3) | (enable << 2);
+       data[1] = (addr >> 8);
+       data[2] = addr;
+       return ccdbg_cmd_write_read8(dbg, CC_SET_HW_BRKPNT, data, 3);
+}
+
+uint8_t
+ccdbg_halt(struct ccdbg *dbg)
+{
+       return ccdbg_cmd_write_read8(dbg, CC_HALT, NULL, 0);
+}
+
+uint8_t
+ccdbg_resume(struct ccdbg *dbg)
+{
+       return ccdbg_cmd_write_read8(dbg, CC_RESUME, NULL, 0);
+}
+
+uint8_t
+ccdbg_debug_instr(struct ccdbg *dbg, uint8_t *instr, int nbytes)
+{
+       return ccdbg_cmd_write_read8(dbg, CC_DEBUG_INSTR(nbytes), instr, nbytes);
+}
+
+void
+ccdbg_debug_instr_discard(struct ccdbg *dbg, uint8_t *instr, int nbytes)
+{
+       static uint8_t  discard;
+       ccdbg_cmd_write_queue8(dbg, CC_DEBUG_INSTR(nbytes),
+                              instr, nbytes, &discard);
+}
+
+void
+ccdbg_debug_instr_queue(struct ccdbg *dbg, uint8_t *instr, int nbytes,
+                       uint8_t *reply)
+{
+       return ccdbg_cmd_write_queue8(dbg, CC_DEBUG_INSTR(nbytes),
+                                     instr, nbytes, reply);
+}
+
+uint8_t
+ccdbg_step_instr(struct ccdbg *dbg)
+{
+       return ccdbg_cmd_write_read8(dbg, CC_STEP_INSTR, NULL, 0);
+}
+
+uint8_t
+ccdbg_step_replace(struct ccdbg *dbg, uint8_t *instr, int nbytes)
+{
+       return ccdbg_cmd_write_read8(dbg, CC_STEP_REPLACE(nbytes), instr, nbytes);
+}
+
+uint16_t
+ccdbg_get_chip_id(struct ccdbg *dbg)
+{
+       return ccdbg_cmd_write_read16(dbg, CC_GET_CHIP_ID, NULL, 0);
+}
+
+/*
+ * Execute a sequence of instructions
+ */
+uint8_t
+ccdbg_execute(struct ccdbg *dbg, uint8_t *inst)
+{
+       uint8_t status = 0;
+       while(inst[0] != 0) {
+               uint8_t len = inst[0];
+               int i;
+               ccdbg_debug(CC_DEBUG_INSTRUCTIONS, "\t%02x", inst[1]);
+               for (i = 0; i < len - 1; i++)
+                       ccdbg_debug(CC_DEBUG_INSTRUCTIONS, " %02x", inst[i+2]);
+               ccdbg_debug_instr_queue(dbg, inst+1, len, &status);
+               for (; i < 3; i++)
+                       ccdbg_debug(CC_DEBUG_INSTRUCTIONS, "   ");
+               ccdbg_debug(CC_DEBUG_INSTRUCTIONS, " -> %02x\n", status);
+               inst += len + 1;
+       }
+       ccdbg_sync(dbg);
+       return status;
+}
+
+static uint8_t jump_mem[] = {
+       3, LJMP, 0xf0, 0x00,
+#define PC_HIGH        2
+#define PC_LOW 3
+       0
+};
+
+uint8_t
+ccdbg_set_pc(struct ccdbg *dbg, uint16_t pc)
+{
+       jump_mem[PC_HIGH] = pc >> 8;
+       jump_mem[PC_LOW] = pc & 0xff;
+       return ccdbg_execute(dbg, jump_mem);
+}
+
+uint8_t
+ccdbg_execute_hex_image(struct ccdbg *dbg, struct hex_image *image)
+{
+       uint16_t pc;
+       uint8_t status;
+
+       if (image->address < 0xf000) {
+               fprintf(stderr, "Cannot execute program starting at 0x%04x\n", image->address);
+               return -1;
+       }
+       ccdbg_write_hex_image(dbg, image, 0);
+       ccdbg_set_pc(dbg, image->address);
+       pc = ccdbg_get_pc(dbg);
+       ccdbg_debug(CC_DEBUG_EXECUTE, "pc starts at 0x%04x\n", pc);
+       status = ccdbg_resume(dbg);
+       ccdbg_debug(CC_DEBUG_EXECUTE, "resume status: 0x%02x\n", status);
+       return 0;
+}
diff --git a/lib/ccdbg-debug.c b/lib/ccdbg-debug.c
new file mode 100644 (file)
index 0000000..6eb4e0c
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * 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 "ccdbg.h"
+#include <stdarg.h>
+
+int
+ccdbg_level = 0;
+
+void
+ccdbg_add_debug(int level)
+{
+       ccdbg_level |= level;
+}
+
+void
+ccdbg_clear_debug(int level)
+{
+       ccdbg_level &= ~level;
+}
+
+static int initialized;
+
+void
+ccdbg_debug(int level, char *format, ...)
+{
+       va_list ap;
+
+       if (!initialized) {
+               char *level;
+               initialized = 1;
+               level = getenv("CCDEBUG");
+               if (level)
+                       ccdbg_level |= strtoul(level, NULL, 0);
+       }
+       if (ccdbg_level & level) {
+               va_start(ap, format);
+               vprintf(format, ap);
+               va_end(ap);
+       }
+}
+
+void
+ccdbg_flush(int level)
+{
+       if (ccdbg_level & level)
+               fflush(stdout);
+}
diff --git a/lib/ccdbg-debug.h b/lib/ccdbg-debug.h
new file mode 100644 (file)
index 0000000..0b5b44c
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * 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(int level);
+
+#endif /* _CCDBG_DEBUG_H_ */
diff --git a/lib/ccdbg-flash.c b/lib/ccdbg-flash.c
new file mode 100644 (file)
index 0000000..3e67298
--- /dev/null
@@ -0,0 +1,356 @@
+/*
+ * 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 "ccdbg.h"
+
+/* From SWRA124 section 3.1.6 */
+
+static uint8_t flash_page[] = {
+
+       MOV_direct_data, P1DIR, 0x02,
+       MOV_direct_data, P1,    0xFF,
+
+       MOV_direct_data, FADDRH, 0,
+#define FLASH_ADDR_HIGH        8
+
+       MOV_direct_data, FADDRL, 0,
+#define FLASH_ADDR_LOW 11
+
+       MOV_DPTR_data16, 0, 0,
+#define RAM_ADDR_HIGH  13
+#define RAM_ADDR_LOW   14
+
+       MOV_Rn_data(7), 0,
+#define FLASH_WORDS_HIGH       16
+
+       MOV_Rn_data(6), 0,
+#define FLASH_WORDS_LOW                18
+
+       MOV_direct_data, FWT, 0x20,
+#define FLASH_TIMING           21
+
+       MOV_direct_data, FCTL, FCTL_ERASE,
+/* eraseWaitLoop: */
+               MOV_A_direct,           FCTL,
+       JB, ACC(FCTL_BUSY_BIT), 0xfb,
+
+       MOV_direct_data, P1, 0xfd,
+
+       MOV_direct_data, FCTL, FCTL_WRITE,
+/* writeLoop: */
+               MOV_Rn_data(5), 2,
+/* writeWordLoop: */
+                       MOVX_A_atDPTR,
+                       INC_DPTR,
+                       MOV_direct_A, FWDATA,
+               DJNZ_Rn_rel(5), 0xfa,           /* writeWordLoop */
+/* writeWaitLoop: */
+                       MOV_A_direct, FCTL,
+               JB, ACC(FCTL_SWBSY_BIT), 0xfb,          /* writeWaitLoop */
+       DJNZ_Rn_rel(6), 0xf1,                   /* writeLoop */
+       DJNZ_Rn_rel(7), 0xef,                   /* writeLoop */
+
+       MOV_direct_data, P1DIR, 0x00,
+       MOV_direct_data, P1,    0xFF,
+       TRAP,
+};
+
+#define FLASH_RAM      0xf000
+
+#if 0
+static uint8_t flash_erase_page[] = {
+       3,      MOV_direct_data, FADDRH, 0,
+#define ERASE_PAGE_HIGH        3
+
+       3,      MOV_direct_data, FADDRL, 0,
+#define ERASE_PAGE_LOW 7
+
+       3,      MOV_direct_data, FWT, 0x2A,
+       3,      MOV_direct_data, FCTL, FCTL_ERASE,
+       0
+};
+
+static uint8_t flash_read_control[] = {
+       2,      MOV_A_direct,   FCTL,
+       0
+};
+#endif
+
+#if 0
+static uint8_t flash_control_clear[] = {
+       3,      MOV_direct_data,        FCTL, 0,
+       2,      MOV_A_direct,           FCTL,
+       0
+};
+#endif
+
+#if 0
+static uint8_t
+ccdbg_flash_erase_page(struct ccdbg *dbg, uint16_t addr)
+{
+       uint16_t        page_addr = addr >> 1;
+       uint8_t         status;
+       uint8_t         old[0x10], new[0x10];
+       int             i;
+
+       ccdbg_read_memory(dbg, addr, old, 0x10);
+       flash_erase_page[ERASE_PAGE_HIGH] = page_addr >> 8;
+       flash_erase_page[ERASE_PAGE_LOW] = page_addr & 0xff;
+       status = ccdbg_execute(dbg, flash_erase_page);
+       ccdbg_debug(CC_DEBUG_FLASH, "erase status 0x%02x\n", status);
+       do {
+               status = ccdbg_execute(dbg, flash_read_control);
+               ccdbg_debug(CC_DEBUG_FLASH, "fctl 0x%02x\n", status);
+       } while (status & FCTL_BUSY);
+       ccdbg_read_memory(dbg, addr, new, 0x10);
+       for (i = 0; i < 0x10; i++)
+               ccdbg_debug(CC_DEBUG_FLASH, "0x%02x -> 0x%02x\n", old[i], new[i]);
+       status = ccdbg_execute(dbg, flash_control_clear);
+       ccdbg_debug(CC_DEBUG_FLASH, "clear fctl 0x%02x\n", status);
+       return 0;
+}
+#endif
+
+#if 0
+static uint8_t flash_write[] = {
+       MOV_direct_data, P1DIR, 0x02,
+       MOV_direct_data, P1,    0xFD,
+
+       MOV_A_direct, FCTL,
+       JB,     ACC(FCTL_BUSY_BIT), 0xf1,
+
+       MOV_direct_data, FCTL, 0x20,
+
+       MOV_direct_data, FADDRH, 0,
+#define WRITE_PAGE_HIGH        16
+
+       MOV_direct_data, FADDRL, 0,
+#define WRITE_PAGE_LOW 19
+
+       MOV_direct_data, FCTL, FCTL_WRITE,
+       MOV_direct_data, FWDATA, 0,
+#define WRITE_BYTE_0   25
+       MOV_direct_data, FWDATA, 0,
+#define WRITE_BYTE_1   28
+       MOV_A_direct, FCTL,
+       JB,     ACC(FCTL_SWBSY_BIT), 0xf1,
+
+       MOV_direct_data, P1,    0xFF,
+       TRAP,
+};
+#endif
+
+static uint8_t
+ccdbg_clock_init(struct ccdbg *dbg)
+{
+       static uint8_t set_clkcon_fast[] = {
+               3,      MOV_direct_data,        CLKCON, 0x00,
+               0
+       };
+
+       static uint8_t get_sleep[] = {
+               2,      MOV_A_direct, SLEEP,
+               0
+       };
+
+       uint8_t status;
+
+       ccdbg_execute(dbg, set_clkcon_fast);
+       do {
+               status = ccdbg_execute(dbg, get_sleep);
+       } while (!(status & 0x40));
+       return 0;
+}
+
+#if 0
+static uint8_t
+ccdbg_flash_write_word(struct ccdbg *dbg, uint16_t addr, uint8_t data[2])
+{
+       uint16_t page_addr = addr >> 1;
+       uint8_t check[2];
+       uint8_t status;
+       int i;
+
+       flash_write[WRITE_PAGE_HIGH] = page_addr >> 8;
+       flash_write[WRITE_PAGE_LOW] = page_addr & 0xff;
+       flash_write[WRITE_BYTE_0] = data[0];
+       flash_write[WRITE_BYTE_1] = data[1];
+       ccdbg_debug(CC_DEBUG_FLASH, "upload flash write\n");
+       ccdbg_write_memory(dbg, 0xf000, flash_write, sizeof(flash_write));
+       ccdbg_set_pc(dbg, 0xf000);
+       ccdbg_resume(dbg);
+       for (;;) {
+               status = ccdbg_read_status(dbg);
+               ccdbg_debug(CC_DEBUG_FLASH, "waiting for write 0x%02x\n", status);
+               if ((status & CC_STATUS_CPU_HALTED) != 0)
+                       break;
+               sleep (1);
+       }
+       status = ccdbg_execute(dbg, flash_control_clear);
+       ccdbg_debug(CC_DEBUG_FLASH, "clear fctl 0x%02x\n", status);
+       ccdbg_read_memory(dbg, addr, check, 2);
+       for (i = 0; i < 2; i++)
+               ccdbg_debug(CC_DEBUG_FLASH, "0x%02x : 0x%02x\n", data[i], check[i]);
+       return 0;
+}
+#endif
+
+#define TIMERS_OFF             0x08
+#define DMA_PAUSE              0x04
+#define TIMER_SUSPEND          0x02
+#define SEL_FLASH_INFO_PAGE    0x01
+
+#if 0
+static uint8_t
+ccdbg_flash_lock(struct ccdbg *dbg, uint8_t lock)
+{
+       uint8_t config;
+       uint8_t bytes[2];
+       uint8_t old[1], new[1];
+
+       config = ccdbg_rd_config(dbg);
+       ccdbg_wr_config(dbg, config|SEL_FLASH_INFO_PAGE);
+       bytes[0] = lock;
+       bytes[1] = 0;
+       ccdbg_flash_erase_page(dbg, 0);
+       ccdbg_read_memory(dbg, 0, old, 1);
+       ccdbg_flash_write_word(dbg, 0, bytes);
+       ccdbg_read_memory(dbg, 0, new, 1);
+       ccdbg_debug(CC_DEBUG_FLASH, "flash lock 0x%02x -> 0x%02x\n", old[0], new[0]);
+       ccdbg_wr_config(dbg, config & ~SEL_FLASH_INFO_PAGE);
+       return 0;
+}
+#endif
+
+uint8_t
+ccdbg_flash_hex_image(struct ccdbg *dbg, struct hex_image *image)
+{
+       uint16_t offset;
+       uint16_t flash_prog;
+       uint16_t flash_len;
+       uint8_t fwt;
+       uint16_t flash_addr;
+       uint16_t flash_word_addr;
+       uint16_t flash_words;
+       uint8_t flash_words_high, flash_words_low;
+       uint16_t ram_addr;
+       uint16_t pc;
+       uint8_t status;
+       uint16_t remain, this_time, start;
+       uint8_t verify[0x400];
+       int times;
+
+       ccdbg_clock_init(dbg);
+       if (image->address + image->length > 0x8000) {
+               fprintf(stderr, "cannot flash image from 0x%04x to 0x%04x\n",
+                       image->address, image->address + image->length);
+               return 1;
+       }
+       if (image->address & 0x3ff) {
+               fprintf(stderr, "flash image must start on page boundary\n");
+               return 1;
+       }
+       ram_addr = 0xf000;
+
+
+       flash_prog = 0xf400;
+
+       fwt = 0x20;
+
+       flash_page[FLASH_TIMING] = fwt;
+       ccdbg_debug(CC_DEBUG_FLASH, "Upload %d flash program bytes to 0x%04x\n",
+              sizeof (flash_page), flash_prog);
+       ccdbg_write_memory(dbg, flash_prog, flash_page, sizeof(flash_page));
+
+       remain = image->length;
+       start = 0;
+       while (remain) {
+               this_time = remain;
+               if (this_time > 0x400)
+                       this_time = 0x400;
+
+               offset = ram_addr - (image->address + start);
+
+               ccdbg_debug(CC_DEBUG_FLASH, "Upload %d bytes at 0x%04x\n", this_time, ram_addr);
+               ccdbg_write_memory(dbg, ram_addr, image->data + start, this_time);
+#if 0
+               ccdbg_debug(CC_DEBUG_FLASH, "Verify %d bytes in ram\n", this_time);
+               ccdbg_read_memory(dbg, ram_addr, verify, this_time);
+               if (memcmp (image->data + start, verify, this_time) != 0) {
+                       fprintf(stderr, "ram verify failed\n");
+                       return 1;
+               }
+#endif
+
+               flash_addr = image->address + start;
+               flash_word_addr = flash_addr >> 1;
+               flash_len = this_time + (this_time & 1);
+               flash_words = flash_len >> 1;
+
+               flash_words_low = flash_words & 0xff;
+               flash_words_high = flash_words >> 8;
+
+               /* The flash code above is lame */
+               if (flash_words_low)
+                       flash_words_high++;
+
+               ccdbg_write_uint8(dbg, flash_prog + FLASH_ADDR_HIGH, flash_word_addr >> 8);
+               ccdbg_write_uint8(dbg, flash_prog + FLASH_ADDR_LOW, flash_word_addr & 0xff);
+
+               ccdbg_write_uint8(dbg, flash_prog + RAM_ADDR_HIGH, ram_addr >> 8);
+               ccdbg_write_uint8(dbg, flash_prog + RAM_ADDR_LOW, ram_addr & 0xff);
+
+               ccdbg_write_uint8(dbg, flash_prog + FLASH_WORDS_HIGH, flash_words_high);
+               ccdbg_write_uint8(dbg, flash_prog + FLASH_WORDS_LOW, flash_words_low);
+
+               ccdbg_set_pc(dbg, flash_prog);
+               pc = ccdbg_get_pc(dbg);
+               ccdbg_debug(CC_DEBUG_FLASH, "Flashing %d bytes at 0x%04x\n",
+                           this_time, flash_addr);
+               status = ccdbg_resume(dbg);
+               for (times = 0; times < 10; times++) {
+                       status = ccdbg_read_status(dbg);
+                       ccdbg_debug(CC_DEBUG_FLASH, ".");
+                       ccdbg_flush(CC_DEBUG_FLASH);
+                       if ((status & CC_STATUS_CPU_HALTED) != 0)
+                               break;
+                       usleep(10000);
+               }
+               ccdbg_debug(CC_DEBUG_FLASH, "\n");
+               if (times == 10) {
+                       fprintf(stderr, "flash page timed out\n");
+                       return 1;
+               }
+
+               ccdbg_debug(CC_DEBUG_FLASH, "Verify %d bytes in flash\n", this_time);
+               ccdbg_read_memory(dbg, flash_addr, verify, this_time);
+               if (memcmp (image->data + start, verify, this_time) != 0) {
+                       int i;
+                       fprintf(stderr, "flash verify failed\n");
+                       for (i = 0; i < this_time; i++) {
+                               if (image->data[start + i] != verify[i])
+                                       fprintf(stderr, "0x%04x: 0x%02x != 0x%02x\n",
+                                               start + i, image->data[start+i], verify[i]);
+                       }
+                       return 1;
+               }
+               remain -= this_time;
+               start += this_time;
+       }
+       return 0;
+}
diff --git a/lib/ccdbg-hex.c b/lib/ccdbg-hex.c
new file mode 100644 (file)
index 0000000..dfea915
--- /dev/null
@@ -0,0 +1,330 @@
+/*
+ * 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 "ccdbg.h"
+#include <stdarg.h>
+#include <ctype.h>
+
+struct hex_input {
+       FILE    *file;
+       int     line;
+       char    *name;
+};
+
+enum hex_read_state {
+       read_marker,
+       read_length,
+       read_address,
+       read_type,
+       read_data,
+       read_checksum,
+       read_newline,
+       read_white,
+       read_done,
+};
+
+
+static void
+ccdbg_hex_error(struct hex_input *input, char *format, ...)
+{
+       va_list ap;
+
+       va_start(ap, format);
+       fprintf(stderr, "Hex error %s:%d: ", input->name, input->line);
+       vfprintf(stderr, format, ap);
+       fprintf(stderr, "\n");
+       va_end(ap);
+}
+
+static void
+ccdbg_hex_free(struct hex_record *record)
+{
+       if (!record) return;
+       free(record);
+}
+
+static struct hex_record *
+ccdbg_hex_alloc(uint8_t length)
+{
+       struct hex_record *record;
+
+       record = calloc(1, sizeof(struct hex_record) + length);
+       record->length = length;
+       return record;
+}
+
+static int
+ishex(char c)
+{
+       return isdigit(c) || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F');
+}
+
+static int
+fromhex(char c)
+{
+       if (isdigit(c))
+               return c - '0';
+       if ('a' <= c && c <= 'f')
+               return c - 'a' + 10;
+       if ('A' <= c && c <= 'F')
+               return c - 'A' + 10;
+       abort();
+       return 0;
+}
+
+static uint8_t
+ccdbg_hex_checksum(struct hex_record *record)
+{
+       uint8_t checksum = 0;
+       int i;
+
+       checksum += record->length;
+       checksum += record->address >> 8;
+       checksum += record->address & 0xff;
+       checksum += record->type;
+       for (i = 0; i < record->length; i++)
+               checksum += record->data[i];
+       return -checksum;
+}
+
+static struct hex_record *
+ccdbg_hex_read_record(struct hex_input *input)
+{
+       struct hex_record *record = NULL;
+       enum hex_read_state state = read_marker;
+       char c;
+       int nhexbytes;
+       uint32_t hex;
+       uint32_t ndata;
+       uint8_t checksum;
+
+       while (state != read_done) {
+               c = getc(input->file);
+               if (c == EOF && state != read_white) {
+                       ccdbg_hex_error(input, "Unexpected EOF");
+                       goto bail;
+               }
+               if (c == ' ')
+                       continue;
+               if (c == '\n')
+                       input->line++;
+               switch (state) {
+               case read_marker:
+                       if (c != ':') {
+                               ccdbg_hex_error(input, "Missing ':'");
+                               goto bail;
+                       }
+                       state = read_length;
+                       nhexbytes = 2;
+                       hex = 0;
+                       break;
+               case read_length:
+               case read_address:
+               case read_type:
+               case read_data:
+               case read_checksum:
+                       if (!ishex(c)) {
+                               ccdbg_hex_error(input, "Non-hex char '%c'",
+                                               c);
+                               goto bail;
+                       }
+                       hex = hex << 4 | fromhex(c);
+                       --nhexbytes;
+                       if (nhexbytes != 0)
+                               break;
+
+                       switch (state) {
+                       case read_length:
+                               record = ccdbg_hex_alloc(hex);
+                               if (!record) {
+                                       ccdbg_hex_error(input, "Out of memory");
+                                       goto bail;
+                               }
+                               state = read_address;
+                               nhexbytes = 4;
+                               break;
+                       case read_address:
+                               record->address = hex;
+                               state = read_type;
+                               nhexbytes = 2;
+                               break;
+                       case read_type:
+                               record->type = hex;
+                               state = read_data;
+                               nhexbytes = 2;
+                               ndata = 0;
+                               break;
+                       case read_data:
+                               record->data[ndata] = hex;
+                               ndata++;
+                               nhexbytes = 2;
+                               break;
+                       case read_checksum:
+                               record->checksum = hex;
+                               state = read_newline;
+                               break;
+                       default:
+                               break;
+                       }
+                       if (state == read_data)
+                               if (ndata == record->length) {
+                                       nhexbytes = 2;
+                                       state = read_checksum;
+                               }
+                       hex = 0;
+                       break;
+               case read_newline:
+                       if (c != '\n' && c != '\r') {
+                               ccdbg_hex_error(input, "Missing newline");
+                               goto bail;
+                       }
+                       state = read_white;
+                       break;
+               case read_white:
+                       if (!isspace(c)) {
+                               if (c == '\n')
+                                       input->line--;
+                               if (c != EOF)
+                                       ungetc(c, input->file);
+                               state = read_done;
+                       }
+                       break;
+               case read_done:
+                       break;
+               }
+       }
+       checksum = ccdbg_hex_checksum(record);
+       if (checksum != record->checksum) {
+               ccdbg_hex_error(input, "Invalid checksum (read 0x%02x computed 0x%02x)\n",
+                               record->checksum, checksum);
+               goto bail;
+       }
+       return record;
+
+bail:
+       ccdbg_hex_free(record);
+       return NULL;
+}
+
+void
+ccdbg_hex_file_free(struct hex_file *hex)
+{
+       int     i;
+
+       if (!hex)
+               return;
+       for (i = 0; i < hex->nrecord; i++)
+               ccdbg_hex_free(hex->records[i]);
+       free(hex);
+}
+
+static int
+ccdbg_hex_record_compar(const void *av, const void *bv)
+{
+       const struct hex_record *a = *(struct hex_record **) av;
+       const struct hex_record *b = *(struct hex_record **) bv;
+
+       return (int) a->address - (int) b->address;
+}
+
+struct hex_file *
+ccdbg_hex_file_read(FILE *file, char *name)
+{
+       struct hex_input input;
+       struct hex_file *hex = NULL, *newhex;
+       struct hex_record *record;
+       int srecord = 1;
+       int done = 0;
+
+       hex = calloc(sizeof (struct hex_file) + sizeof (struct hex_record *), 1);
+       input.name = name;
+       input.line = 1;
+       input.file = file;
+       while (!done) {
+               record = ccdbg_hex_read_record(&input);
+               if (!record)
+                       goto bail;
+               if (hex->nrecord == srecord) {
+                       srecord *= 2;
+                       newhex = realloc(hex,
+                                        sizeof (struct hex_file) +
+                                        srecord * sizeof (struct hex_record *));
+                       if (!newhex)
+                               goto bail;
+                       hex = newhex;
+               }
+               hex->records[hex->nrecord++] = record;
+               if (record->type == HEX_RECORD_EOF)
+                       done = 1;
+       }
+       /*
+        * Sort them into increasing addresses, except for EOF
+        */
+       qsort(hex->records, hex->nrecord - 1, sizeof (struct hex_record *),
+             ccdbg_hex_record_compar);
+       return hex;
+
+bail:
+       ccdbg_hex_file_free(hex);
+       return NULL;
+}
+
+struct hex_image *
+ccdbg_hex_image_create(struct hex_file *hex)
+{
+       struct hex_image *image;
+       struct hex_record *first, *last, *record;
+       int i;
+       uint32_t base, bound;
+       uint32_t offset;
+       int length;
+
+       first = hex->records[0];
+       last = hex->records[hex->nrecord - 2];  /* skip EOF */
+       base = (uint32_t) first->address;
+       bound = (uint32_t) last->address + (uint32_t) last->length;
+       length = bound - base;
+       image = calloc(sizeof(struct hex_image) + length, 1);
+       if (!image)
+               return NULL;
+       image->address = base;
+       image->length = length;
+       memset(image->data, 0xff, length);
+       for (i = 0; i < hex->nrecord - 1; i++) {
+               record = hex->records[i];
+               offset = record->address - base;
+               memcpy(image->data + offset, record->data, record->length);
+       }
+       return image;
+}
+
+void
+ccdbg_hex_image_free(struct hex_image *image)
+{
+       free(image);
+}
+
+int
+ccdbg_hex_image_equal(struct hex_image *a, struct hex_image *b)
+{
+       if (a->length != b->length)
+               return 0;
+       if (memcmp(a->data, b->data, a->length) != 0)
+               return 0;
+       return 1;
+}
diff --git a/lib/ccdbg-io.c b/lib/ccdbg-io.c
new file mode 100644 (file)
index 0000000..9c6693c
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * 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 "ccdbg.h"
+#include <time.h>
+#include "cc-usb.h"
+#include "cc-bitbang.h"
+
+struct ccdbg *
+ccdbg_open(void)
+{
+       struct ccdbg *dbg;
+       char *tty;
+
+       dbg = calloc(sizeof (struct ccdbg), 1);
+       if (!dbg) {
+               perror("calloc");
+               return NULL;
+       }
+       tty = getenv("CCDBG_TTY");
+       if (!tty || tty[0] == '/')
+               dbg->usb = cc_usb_open(tty);
+       if (!dbg->usb) {
+               dbg->bb = cc_bitbang_open();
+               if (!dbg->bb) {
+                       free(dbg);
+                       return NULL;
+               }
+       }
+       return dbg;
+}
+
+void
+ccdbg_close(struct ccdbg *dbg)
+{
+       if (dbg->usb)
+               cc_usb_close(dbg->usb);
+       if (dbg->bb)
+               cc_bitbang_close(dbg->bb);
+       free (dbg);
+}
+
+void
+ccdbg_debug_mode(struct ccdbg *dbg)
+{
+       if (dbg->usb)
+               cc_usb_debug_mode(dbg->usb);
+       else if (dbg->bb)
+               cc_bitbang_debug_mode(dbg->bb);
+}
+
+void
+ccdbg_reset(struct ccdbg *dbg)
+{
+       if (dbg->usb)
+               cc_usb_reset(dbg->usb);
+       else if (dbg->bb)
+               cc_bitbang_reset(dbg->bb);
+}
+
+void
+ccdbg_send_bytes(struct ccdbg *dbg, uint8_t *bytes, int nbytes)
+{
+       if (dbg->usb)
+               cc_usb_send_bytes(dbg->usb, bytes, nbytes);
+       else if (dbg->bb)
+               cc_bitbang_send_bytes(dbg->bb, bytes, nbytes);
+}
+
+void
+ccdbg_recv_bytes(struct ccdbg *dbg, uint8_t *bytes, int nbytes)
+{
+       if (dbg->usb)
+               cc_usb_recv_bytes(dbg->usb, bytes, nbytes);
+       else if (dbg->bb)
+               cc_bitbang_recv_bytes(dbg->bb, bytes, nbytes);
+}
+
+void
+ccdbg_sync(struct ccdbg *dbg)
+{
+       if (dbg->usb)
+               cc_usb_sync(dbg->usb);
+       else if (dbg->bb)
+               cc_bitbang_sync(dbg->bb);
+}
+
+void
+ccdbg_cmd_write(struct ccdbg *dbg, uint8_t cmd, uint8_t *data, int len)
+{
+       ccdbg_send_bytes(dbg, &cmd, 1);
+       ccdbg_send_bytes(dbg, data, len);
+}
+
+uint8_t
+ccdbg_cmd_write_read8(struct ccdbg *dbg, uint8_t cmd, uint8_t *data, int len)
+{
+       uint8_t byte[1];
+       ccdbg_cmd_write(dbg, cmd, data, len);
+       ccdbg_recv_bytes(dbg, byte, 1);
+       ccdbg_sync(dbg);
+       return byte[0];
+}
+
+uint16_t
+ccdbg_cmd_write_read16(struct ccdbg *dbg, uint8_t cmd, uint8_t *data, int len)
+{
+       uint8_t byte[2];
+       ccdbg_cmd_write(dbg, cmd, data, len);
+       ccdbg_recv_bytes(dbg, byte, 2);
+       ccdbg_sync(dbg);
+       return (byte[0] << 8) | byte[1];
+}
+
+void
+ccdbg_cmd_write_queue8(struct ccdbg *dbg, uint8_t cmd,
+                      uint8_t *data, int len,
+                      uint8_t *reply)
+{
+       ccdbg_cmd_write(dbg, cmd, data, len);
+       ccdbg_recv_bytes(dbg, reply, 1);
+}
diff --git a/lib/ccdbg-manual.c b/lib/ccdbg-manual.c
new file mode 100644 (file)
index 0000000..0e811b7
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * 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 "ccdbg.h"
+#include "cc-bitbang.h"
+
+/*
+ * Manual bit-banging to debug the low level protocol
+ */
+
+static void
+get_bit(char *line, int i, char on, uint8_t bit, uint8_t *bits, uint8_t *masks)
+{
+       if (line[i] == on) {
+               *bits |= bit;
+               *masks |= bit;
+               return;
+       }
+       if (line[i] == '.') {
+               *masks |= bit;
+               return;
+       }
+       if (line[i] == '-') {
+               return;
+       }
+       fprintf(stderr, "bad line %s\n", line);
+       exit (1);
+}
+
+void
+ccdbg_manual(struct ccdbg *dbg, FILE *input)
+{
+       char    line[80];
+       uint8_t set, mask;
+
+       if (dbg->bb == NULL) {
+               fprintf(stderr, "Must use bitbang API for manual mode\n");
+               return;
+       }
+       while (fgets(line, sizeof line, input)) {
+               if (line[0] == '#' || line[0] == '\n') {
+                       printf ("%s", line);
+                       continue;
+               }
+               set = 0;
+               mask = 0;
+               get_bit(line, 0, 'C', CC_CLOCK, &set, &mask);
+               get_bit(line, 2, 'D', CC_DATA, &set, &mask);
+               get_bit(line, 4, 'R', CC_RESET_N, &set, &mask);
+               if (mask != (CC_CLOCK|CC_DATA|CC_RESET_N)) {
+                       uint8_t read;
+                       cc_bitbang_read(dbg->bb, &read);
+                       cc_bitbang_sync(dbg->bb);
+                       cc_bitbang_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);
+                       printf ("\n");
+               }
+               cc_bitbang_send(dbg->bb, mask, set);
+               cc_bitbang_sync(dbg->bb);
+       }
+}
diff --git a/lib/ccdbg-memory.c b/lib/ccdbg-memory.c
new file mode 100644 (file)
index 0000000..554ac63
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * 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 "ccdbg.h"
+
+/*
+ * Read and write arbitrary memory through the debug port
+ */
+
+static uint8_t memory_init[] = {
+       3,      MOV_DPTR_data16,        0,      0,
+#define HIGH_START     2
+#define LOW_START      3
+       0,
+};
+
+
+static uint8_t write8[] = {
+       2,      MOV_A_data,     0,
+#define DATA_BYTE      2
+       1,      MOVX_atDPTR_A,
+       1,      INC_DPTR,
+       0
+};
+
+static uint8_t read8[] = {
+       1,      MOVX_A_atDPTR,
+       1,      INC_DPTR,
+       0,
+};
+
+uint8_t
+ccdbg_write_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes)
+{
+       int i, nl = 0;
+       struct ccstate state;
+
+       if (dbg->usb)
+               return cc_usb_write_memory(dbg->usb, addr, bytes, nbytes);
+       ccdbg_state_save(dbg, &state, CC_STATE_ACC | CC_STATE_PSW | CC_STATE_DP);
+       memory_init[HIGH_START] = addr >> 8;
+       memory_init[LOW_START] = addr;
+       (void) ccdbg_execute(dbg, memory_init);
+       for (i = 0; i < nbytes; i++) {
+               write8[DATA_BYTE] = *bytes++;
+               ccdbg_execute(dbg, write8);
+               if ((i & 0xf) == 0xf) {
+                       ccdbg_debug(CC_DEBUG_MEMORY, ".");
+                       ccdbg_flush(CC_DEBUG_MEMORY);
+                       nl = 1;
+               }
+               if ((i & 0xff) == 0xff) {
+                       ccdbg_debug(CC_DEBUG_MEMORY, "\n");
+                       nl = 0;
+               }
+       }
+       ccdbg_state_restore(dbg, &state);
+       if (nl)
+               ccdbg_debug(CC_DEBUG_MEMORY, "\n");
+       return 0;
+}
+
+uint8_t
+ccdbg_read_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes)
+{
+       int i, nl = 0;
+       struct ccstate state;
+
+       if (ccdbg_rom_contains(dbg, addr, nbytes)) {
+               ccdbg_rom_replace_xmem(dbg, addr, bytes, nbytes);
+               return 0;
+       }
+       if (dbg->usb)
+               return cc_usb_read_memory(dbg->usb, addr, bytes, nbytes);
+       ccdbg_state_save(dbg, &state, CC_STATE_ACC | CC_STATE_PSW | CC_STATE_DP);
+       memory_init[HIGH_START] = addr >> 8;
+       memory_init[LOW_START] = addr;
+       (void) ccdbg_execute(dbg, memory_init);
+       for (i = 0; i < nbytes; i++) {
+               *bytes++ = ccdbg_execute(dbg, read8);
+               if ((i & 0xf) == 0xf) {
+                       ccdbg_debug(CC_DEBUG_MEMORY, ".");
+                       ccdbg_flush(CC_DEBUG_MEMORY);
+                       nl = 1;
+               }
+               if ((i & 0xff) == 0xff) {
+                       ccdbg_debug(CC_DEBUG_MEMORY, "\n");
+                       nl = 0;
+               }
+       }
+       ccdbg_state_replace_xmem(dbg, &state, addr, bytes, nbytes);
+       ccdbg_state_restore(dbg, &state);
+       if (nl)
+               ccdbg_debug(CC_DEBUG_MEMORY, "\n");
+       return 0;
+}
+
+uint8_t
+ccdbg_write_uint8(struct ccdbg *dbg, uint16_t addr, uint8_t byte)
+{
+       return ccdbg_write_memory(dbg, addr, &byte, 1);
+}
+
+uint8_t
+ccdbg_write_hex_image(struct ccdbg *dbg, struct hex_image *image, uint16_t offset)
+{
+       ccdbg_write_memory(dbg, image->address + offset, image->data, image->length);
+       return 0;
+}
+
+struct hex_image *
+ccdbg_read_hex_image(struct ccdbg *dbg, uint16_t address, uint16_t length)
+{
+       struct hex_image *image;
+
+       image = calloc(sizeof(struct hex_image) + length, 1);
+       image->address = address;
+       image->length = length;
+       memset(image->data, 0xff, length);
+       ccdbg_read_memory(dbg, address, image->data, length);
+       return image;
+}
+
+static uint8_t sfr_read[] = {
+       2,      MOV_A_direct,           0,
+#define SFR_READ_ADDR  2
+       0,
+};
+
+static uint8_t sfr_write[] = {
+       3,      MOV_direct_data,        0,      0,
+#define SFR_WRITE_ADDR 2
+#define SFR_WRITE_DATA 3
+       0,
+};
+
+uint8_t
+ccdbg_read_sfr(struct ccdbg *dbg, uint8_t addr, uint8_t *bytes, int nbytes)
+{
+       int     i;
+       struct ccstate state;
+
+       ccdbg_state_save(dbg, &state, CC_STATE_ACC);
+       for (i = 0; i < nbytes; i++) {
+               sfr_read[SFR_READ_ADDR] = addr + i;
+               *bytes++ = ccdbg_execute(dbg, sfr_read);
+       }
+       ccdbg_state_replace_sfr(dbg, &state, addr, bytes, nbytes);
+       ccdbg_state_restore(dbg, &state);
+       return 0;
+}
+
+uint8_t
+ccdbg_write_sfr(struct ccdbg *dbg, uint8_t addr, uint8_t *bytes, int nbytes)
+{
+       int     i;
+
+       for (i = 0; i < nbytes; i++) {
+               sfr_write[SFR_WRITE_ADDR] = addr + i;
+               sfr_write[SFR_WRITE_DATA] = *bytes++;
+               ccdbg_execute(dbg, sfr_write);
+       }
+       return 0;
+}
diff --git a/lib/ccdbg-rom.c b/lib/ccdbg-rom.c
new file mode 100644 (file)
index 0000000..71bed22
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * 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 "ccdbg.h"
+
+uint8_t
+ccdbg_set_rom(struct ccdbg *dbg, struct hex_image *rom)
+{
+       if (dbg->rom)
+               ccdbg_hex_image_free(dbg->rom);
+       dbg->rom = rom;
+       return 0;
+}
+
+uint8_t
+ccdbg_rom_contains(struct ccdbg *dbg, uint16_t addr, int nbytes)
+{
+       struct hex_image *rom = dbg->rom;
+       if (!rom)
+               return 0;
+       if (addr < rom->address || rom->address + rom->length < addr + nbytes)
+               return 0;
+       return 1;
+}
+
+uint8_t
+ccdbg_rom_replace_xmem(struct ccdbg *dbg,
+                      uint16_t addr, uint8_t *bytes, int nbytes)
+{
+       struct hex_image *rom = dbg->rom;
+       if (!rom)
+               return 0;
+
+       if (rom->address < addr + nbytes && addr < rom->address + rom->length) {
+               int     start, stop;
+
+               start = addr;
+               if (addr < rom->address)
+                       start = rom->address;
+               stop = addr + nbytes;
+               if (rom->address + rom->length < stop)
+                       stop = rom->address + rom->length;
+               memcpy(bytes + start - addr, rom->data + start - rom->address,
+                      stop - start);
+               return 1;
+       }
+       return 0;
+}
diff --git a/lib/ccdbg-state.c b/lib/ccdbg-state.c
new file mode 100644 (file)
index 0000000..9aca8d2
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * 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 "ccdbg.h"
+
+static uint8_t save_acc[] = {
+       1,      NOP,
+       0
+};
+
+static uint8_t save_sfr[] = {
+       2,      MOV_A_direct,   0,
+#define SAVE_SFR_ADDR  2
+       0,
+};
+
+struct sfr_state {
+       uint8_t         address;
+       uint16_t        mask;
+       char            *name;
+};
+
+static struct sfr_state        sfrs[CC_STATE_NSFR] = {
+       { SFR_DPL0,     CC_STATE_DP,    "dpl0" },
+       { SFR_DPH0,     CC_STATE_DP,    "dph0" },
+       { SFR_DPL1,     CC_STATE_DP,    "dpl1" },
+       { SFR_DPH1,     CC_STATE_DP,    "dph1" },
+       { PSW(0),       CC_STATE_PSW,   "psw"  },
+};
+
+uint8_t
+ccdbg_state_save(struct ccdbg *dbg, struct ccstate *state, unsigned int mask)
+{
+       int     i;
+
+       mask |= CC_STATE_ACC;
+       if (mask & CC_STATE_ACC)
+               state->acc = ccdbg_execute(dbg, save_acc);
+       for (i = 0; i < CC_STATE_NSFR; i++) {
+               if (sfrs[i].mask & mask) {
+                       save_sfr[SAVE_SFR_ADDR] = sfrs[i].address;
+                       state->sfr[i] = ccdbg_execute(dbg, save_sfr);
+               }
+       }
+       state->mask = mask;
+       return 0;
+}
+
+static uint8_t restore_sfr[] = {
+       3,      MOV_direct_data,        0,      0,
+#define RESTORE_SFR_ADDR       2
+#define RESTORE_SFR_DATA       3
+       0
+};
+
+static uint8_t restore_acc[] = {
+       2,      MOV_A_data,     0,
+#define RESTORE_ACC_DATA       2
+       0
+};
+
+uint8_t
+ccdbg_state_restore(struct ccdbg *dbg, struct ccstate *state)
+{
+       int i;
+       for (i = CC_STATE_NSFR - 1; i >= 0; i--) {
+               if (sfrs[i].mask & state->mask) {
+                       restore_sfr[RESTORE_SFR_ADDR] = sfrs[i].address;
+                       restore_sfr[RESTORE_SFR_DATA] = state->sfr[i];
+                       ccdbg_execute(dbg, restore_sfr);
+               }
+       }
+       if (state->mask & CC_STATE_ACC) {
+               restore_acc[RESTORE_ACC_DATA] = state->acc;
+               ccdbg_execute(dbg, restore_acc);
+       }
+       state->mask = 0;
+       return 0;
+}
+
+static void
+ccdbg_state_replace(uint16_t sfr_addr, uint8_t sfr, char *name,
+                   uint16_t addr, uint8_t *bytes, int nbytes)
+{
+       sfr_addr += 0xdf00;
+
+       if (addr <= sfr_addr && sfr_addr < addr + nbytes) {
+               fprintf(stderr, "replacing %s at 0x%04x - read 0x%02x saved 0x%02x\n",
+                       name, sfr_addr, bytes[sfr_addr - addr], sfr);
+               bytes[sfr_addr - addr] = sfr;
+       }
+}
+
+void
+ccdbg_state_replace_xmem(struct ccdbg *dbg, struct ccstate *state,
+                        uint16_t addr, uint8_t *bytes, int nbytes)
+{
+       int i;
+       if (state->mask & CC_STATE_ACC)
+               ccdbg_state_replace(ACC(0), state->acc, "acc",
+                                   addr, bytes, nbytes);
+       for (i = 0; i < CC_STATE_NSFR; i++)
+               if (state->mask & sfrs[i].mask)
+                       ccdbg_state_replace(sfrs[i].address, state->sfr[i],
+                                           sfrs[i].name, addr, bytes, nbytes);
+}
+
+void
+ccdbg_state_replace_sfr(struct ccdbg *dbg, struct ccstate *state,
+                       uint8_t addr, uint8_t *bytes, int nbytes)
+{
+       ccdbg_state_replace_xmem(dbg, state, (uint16_t) addr + 0xdf00, bytes, nbytes);
+}
diff --git a/lib/ccdbg.h b/lib/ccdbg.h
new file mode 100644 (file)
index 0000000..4a2e3b9
--- /dev/null
@@ -0,0 +1,341 @@
+/*
+ * 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_H_
+#define _CCDBG_H_
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include "ccdbg-debug.h"
+#include "cc-bitbang.h"
+#include "cc-usb.h"
+
+/* 8051 instructions
+ */
+#define NOP                    0x00
+#define MOV_direct_data                0x75
+#define LJMP                   0x02
+#define MOV_Rn_data(n)         (0x78 | (n))
+#define DJNZ_Rn_rel(n)         (0xd8 | (n))
+#define MOV_A_direct           0xe5
+#define MOV_direct1_direct2    0x85
+#define MOV_direct_A           0xf5
+#define MOV_DPTR_data16                0x90
+#define MOV_A_data             0x74
+#define MOVX_atDPTR_A          0xf0
+#define MOVX_A_atDPTR          0xe0
+#define INC_DPTR               0xa3
+#define TRAP                   0xa5
+#define SJMP                   0x80
+#define JB                     0x20
+
+/* 8051 special function registers
+ */
+
+#define SFR_P0                 0x80
+#define SFR_SP                 0x81
+#define SFR_DPL0               0x82
+#define SFR_DPH0               0x83
+#define SFR_DPL1               0x84
+#define SFR_DPH1               0x85
+
+/* flash controller */
+#define FWT                    0xAB
+#define FADDRL                 0xAC
+#define FADDRH                 0xAD
+#define FCTL                   0xAE
+# define FCTL_BUSY             0x80
+# define FCTL_BUSY_BIT         7
+# define FCTL_SWBSY            0x40
+# define FCTL_SWBSY_BIT                6
+# define FCTL_CONTRD           0x10
+# define FCTL_WRITE            0x02
+# define FCTL_ERASE            0x01
+#define FWDATA                 0xAF
+
+#define SLEEP                  0xBE
+
+/* clock controller */
+#define CLKCON                 0xC6
+#define  CLKCON_OSC32K         0x80
+#define  CLKCON_OSC            0x40
+#define  CLKCON_TICKSPD                0x38
+#define  CLKCON_CLKSPD         0x07
+
+/* I/O pins */
+#define P0                     0x80
+#define P1                     0x90
+#define P2                     0xA0
+#define P0DIR                  0xFD
+#define P1DIR                  0xFE
+#define P2DIR                  0xFF
+
+/* Bit-addressable accumulator */
+#define ACC(bit)               (0xE0 | (bit))
+
+/* Bit-addressable status word */
+#define PSW(bit)               (0xD0 | (bit))
+
+struct ccdbg {
+       struct cc_bitbang       *bb;
+       struct cc_usb           *usb;
+       struct hex_image        *rom;
+};
+
+/* Intel hex file format data
+ */
+struct hex_record {
+       uint8_t length;
+       uint16_t address;
+       uint8_t type;
+       uint8_t checksum;
+       uint8_t data[0];
+};
+
+struct hex_file {
+       int                     nrecord;
+       struct hex_record       *records[0];
+};
+
+struct hex_image {
+       uint16_t        address;
+       uint16_t        length;
+       uint8_t         data[0];
+};
+
+#define CC_STATE_ACC   0x1
+#define CC_STATE_PSW   0x2
+#define CC_STATE_DP    0x4
+
+#define CC_STATE_NSFR  5
+
+struct ccstate {
+       uint16_t        mask;
+       uint8_t         acc;
+       uint8_t         sfr[CC_STATE_NSFR];
+};
+
+#define HEX_RECORD_NORMAL              0x00
+#define HEX_RECORD_EOF                 0x01
+#define HEX_RECORD_EXTENDED_ADDRESS    0x02
+
+/* CC1111 debug port commands
+ */
+#define CC_CHIP_ERASE          0x14
+
+#define CC_WR_CONFIG           0x1d
+#define CC_RD_CONFIG           0x24
+# define CC_CONFIG_TIMERS_OFF          (1 << 3)
+# define CC_CONFIG_DMA_PAUSE           (1 << 2)
+# define CC_CONFIG_TIMER_SUSPEND       (1 << 1)
+# define CC_SET_FLASH_INFO_PAGE                (1 << 0)
+
+#define CC_GET_PC              0x28
+#define CC_READ_STATUS         0x34
+# define CC_STATUS_CHIP_ERASE_DONE     (1 << 7)
+# define CC_STATUS_PCON_IDLE           (1 << 6)
+# define CC_STATUS_CPU_HALTED          (1 << 5)
+# define CC_STATUS_POWER_MODE_0                (1 << 4)
+# define CC_STATUS_HALT_STATUS         (1 << 3)
+# define CC_STATUS_DEBUG_LOCKED                (1 << 2)
+# define CC_STATUS_OSCILLATOR_STABLE   (1 << 1)
+# define CC_STATUS_STACK_OVERFLOW      (1 << 0)
+
+#define CC_SET_HW_BRKPNT       0x3b
+# define CC_HW_BRKPNT_N(n)     ((n) << 3)
+# define CC_HW_BRKPNT_N_MASK   (0x3 << 3)
+# define CC_HW_BRKPNT_ENABLE   (1 << 2)
+
+#define CC_HALT                        0x44
+#define CC_RESUME              0x4c
+#define CC_DEBUG_INSTR(n)      (0x54|(n))
+#define CC_STEP_INSTR          0x5c
+#define CC_STEP_REPLACE(n)     (0x64|(n))
+#define CC_GET_CHIP_ID         0x68
+
+/* ccdbg-command.c */
+void
+ccdbg_debug_mode(struct ccdbg *dbg);
+
+void
+ccdbg_reset(struct ccdbg *dbg);
+
+uint8_t
+ccdbg_chip_erase(struct ccdbg *dbg);
+
+uint8_t
+ccdbg_wr_config(struct ccdbg *dbg, uint8_t config);
+
+uint8_t
+ccdbg_rd_config(struct ccdbg *dbg);
+
+uint16_t
+ccdbg_get_pc(struct ccdbg *dbg);
+
+uint8_t
+ccdbg_read_status(struct ccdbg *dbg);
+
+uint8_t
+ccdbg_set_hw_brkpnt(struct ccdbg *dbg, uint8_t number, uint8_t enable, uint16_t addr);
+
+uint8_t
+ccdbg_halt(struct ccdbg *dbg);
+
+uint8_t
+ccdbg_resume(struct ccdbg *dbg);
+
+uint8_t
+ccdbg_debug_instr(struct ccdbg *dbg, uint8_t *instr, int nbytes);
+
+void
+ccdbg_debug_instr_discard(struct ccdbg *dbg, uint8_t *instr, int nbytes);
+
+void
+ccdbg_debug_instr_queue(struct ccdbg *dbg, uint8_t *instr, int nbytes,
+                       uint8_t *reply);
+
+uint8_t
+ccdbg_step_instr(struct ccdbg *dbg);
+
+uint8_t
+ccdbg_step_replace(struct ccdbg *dbg, uint8_t *instr, int nbytes);
+
+uint16_t
+ccdbg_get_chip_id(struct ccdbg *dbg);
+
+uint8_t
+ccdbg_execute(struct ccdbg *dbg, uint8_t *inst);
+
+uint8_t
+ccdbg_set_pc(struct ccdbg *dbg, uint16_t pc);
+
+uint8_t
+ccdbg_execute_hex_image(struct ccdbg *dbg, struct hex_image *image);
+
+/* ccdbg-flash.c */
+uint8_t
+ccdbg_flash_hex_image(struct ccdbg *dbg, struct hex_image *image);
+
+/* ccdbg-hex.c */
+struct hex_file *
+ccdbg_hex_file_read(FILE *file, char *name);
+
+void
+ccdbg_hex_file_free(struct hex_file *hex);
+
+struct hex_image *
+ccdbg_hex_image_create(struct hex_file *hex);
+
+void
+ccdbg_hex_image_free(struct hex_image *image);
+
+int
+ccdbg_hex_image_equal(struct hex_image *a, struct hex_image *b);
+
+/* ccdbg-io.c */
+struct ccdbg *
+ccdbg_open(void);
+
+void
+ccdbg_close(struct ccdbg *dbg);
+
+void
+ccdbg_cmd_write(struct ccdbg *dbg, uint8_t cmd, uint8_t *data, int len);
+
+uint8_t
+ccdbg_cmd_write_read8(struct ccdbg *dbg, uint8_t cmd, uint8_t *data, int len);
+
+void
+ccdbg_cmd_write_queue8(struct ccdbg *dbg, uint8_t cmd,
+                      uint8_t *data, int len, uint8_t *reply);
+
+uint16_t
+ccdbg_cmd_write_read16(struct ccdbg *dbg, uint8_t cmd, uint8_t *data, int len);
+
+void
+ccdbg_send_bytes(struct ccdbg *dbg, uint8_t *bytes, int nbytes);
+
+void
+ccdbg_recv_bytes(struct ccdbg *dbg, uint8_t *bytes, int nbytes);
+
+void
+ccdbg_sync(struct ccdbg *dbg);
+
+/* ccdbg-manual.c */
+
+void
+ccdbg_manual(struct ccdbg *dbg, FILE *input);
+
+/* ccdbg-memory.c */
+uint8_t
+ccdbg_write_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes);
+
+uint8_t
+ccdbg_read_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes);
+
+uint8_t
+ccdbg_write_uint8(struct ccdbg *dbg, uint16_t addr, uint8_t byte);
+
+uint8_t
+ccdbg_write_hex_image(struct ccdbg *dbg, struct hex_image *image, uint16_t offset);
+
+struct hex_image *
+ccdbg_read_hex_image(struct ccdbg *dbg, uint16_t address, uint16_t length);
+
+uint8_t
+ccdbg_read_sfr(struct ccdbg *dbg, uint8_t addr, uint8_t *bytes, int nbytes);
+
+uint8_t
+ccdbg_write_sfr(struct ccdbg *dbg, uint8_t addr, uint8_t *bytes, int nbytes);
+
+/* ccdbg-rom.c */
+uint8_t
+ccdbg_set_rom(struct ccdbg *dbg, struct hex_image *rom);
+
+uint8_t
+ccdbg_rom_contains(struct ccdbg *dbg, uint16_t addr, int nbytes);
+
+uint8_t
+ccdbg_rom_replace_xmem(struct ccdbg *dbg,
+                      uint16_t addrp, uint8_t *bytesp, int nbytes);
+
+/* ccdbg-state.c */
+uint8_t
+ccdbg_state_save(struct ccdbg *dbg, struct ccstate *state, unsigned int mask);
+
+uint8_t
+ccdbg_state_restore(struct ccdbg *dbg, struct ccstate *state);
+
+void
+ccdbg_state_replace_xmem(struct ccdbg *dbg, struct ccstate *state,
+                        uint16_t addr, uint8_t *bytes, int nbytes);
+
+void
+ccdbg_state_replace_sfr(struct ccdbg *dbg, struct ccstate *state,
+                       uint8_t addr, uint8_t *bytes, int nbytes);
+
+#endif /* _CCDBG_H_ */
diff --git a/lib/cp-usb-async.c b/lib/cp-usb-async.c
new file mode 100644 (file)
index 0000000..6539394
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * 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;
+       uint8_t                 value;
+       uint8_t                 set;
+};
+
+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);
+       cp->ack = -1;
+       if (!cp->handle) {
+               libusb_exit(cp->ctx);
+               free(cp);
+               return NULL;
+       }
+       cp->value = 0;
+       cp->set = 0;
+       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;
+       int     ret;
+
+       if (cp->set) {
+               value = (cp->value & ~mask) | (value & mask);
+               mask = value ^ cp->value;
+       }
+       cp->set = 1;
+       cp->value = value;
+       gpio_set = ((uint16_t) value << 8) | mask;
+       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 = -1;
+}
diff --git a/lib/cp-usb-async.h b/lib/cp-usb-async.h
new file mode 100644 (file)
index 0000000..976a320
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * 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
diff --git a/lib/cp-usb.c b/lib/cp-usb.c
new file mode 100644 (file)
index 0000000..530848d
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * 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.
+ */
+
+/*
+ * libusb interface to the GPIO pins on a CP2103.
+ *
+ * Various magic constants came from the cp210x driver published by silabs.
+ */
+
+#include "cp-usb.h"
+#include <stdio.h>
+#include <errno.h>
+#include <libusb.h>
+
+struct cp_usb {
+       usb_dev_handle *usb_dev;
+       uint8_t gpio;
+};
+
+#define CP2101_UART    0x00
+#define UART_ENABLE    0x0001
+#define UART_DISABLE   0x0000
+#define REQTYPE_HOST_TO_DEVICE  0x41
+#define REQTYPE_DEVICE_TO_HOST  0xc1
+
+static int
+cp_usb_gpio_get(struct cp_usb *cp, uint8_t *gpio_get)
+{
+       return usb_control_msg(cp->usb_dev,             /* dev */
+                              0xc0,                    /* request */
+                              0xff,                    /* requesttype */
+                              0x00c2,                  /* value */
+                              0,                       /* index */
+                              (char *) gpio_get,       /* bytes */
+                              1,                       /* size */
+                              300);                    /* timeout */
+}
+
+static int
+cp_usb_gpio_set(struct cp_usb *cp, uint8_t mask, uint8_t value)
+{
+       uint16_t gpio_set = ((uint16_t) value << 8) | mask;
+
+       return usb_control_msg(cp->usb_dev,             /* dev */
+                              0x40,                    /* request */
+                              0xff,                    /* requesttype */
+                              0x37e1,                  /* value */
+                              gpio_set,                /* index */
+                              NULL,                    /* bytes */
+                              0,                       /* size */
+                              300);                    /* timeout */
+}
+
+static int
+cp_usb_uart_enable_disable(struct cp_usb *cp, uint16_t enable)
+{
+       return usb_control_msg(cp->usb_dev,
+                              CP2101_UART,
+                              REQTYPE_HOST_TO_DEVICE,
+                              enable,
+                              0,
+                              NULL,
+                              0,
+                              300);
+}
+
+struct cp_usb *
+cp_usb_open(void)
+{
+       struct cp_usb *cp;
+       usb_dev_handle *dev_handle;
+       struct usb_device *dev = NULL;
+       struct usb_bus *bus, *busses;
+       int interface;
+       int ret;
+       uint8_t gpio;
+
+       usb_init();
+       usb_find_busses();
+       usb_find_devices();
+
+       busses = usb_get_busses();
+       for (bus = busses; bus; bus = bus->next) {
+               for (dev = bus->devices; dev; dev = dev->next) {
+                       if (dev->descriptor.idVendor == 0x10c4 &&
+                           dev->descriptor.idProduct == 0xea60)
+                               break;
+               }
+               if (dev)
+                       break;
+       }
+       if (!dev){
+               perror("No CP2103 found");
+               return NULL;
+       }
+       cp = calloc(sizeof(struct cp_usb), 1);
+       interface = 0;
+       dev_handle = usb_open(dev);
+       usb_detach_kernel_driver_np(dev_handle, interface);
+       usb_claim_interface(dev_handle, interface);
+       cp->usb_dev = dev_handle;
+       ret = cp_usb_uart_enable_disable(cp, UART_DISABLE);
+       cp->gpio = 0xf;
+       ret = cp_usb_gpio_set(cp, 0xf, cp->gpio);
+       ret = cp_usb_gpio_get(cp, &gpio);
+       return cp;
+}
+
+void
+cp_usb_close(struct cp_usb *cp)
+{
+       cp_usb_uart_enable_disable(cp, UART_DISABLE);
+       usb_close(cp->usb_dev);
+       free(cp);
+}
+
+void
+cp_usb_write(struct cp_usb *cp, uint8_t mask, uint8_t value)
+{
+       uint8_t new_gpio;
+       int ret;
+
+       new_gpio = (cp->gpio & ~mask) | (value & mask);
+       if (new_gpio != cp->gpio) {
+               ret = cp_usb_gpio_set(cp, new_gpio ^ cp->gpio, new_gpio);
+               if (ret < 0)
+                       perror("gpio_set");
+               cp->gpio = new_gpio;
+       }
+}
+
+uint8_t
+cp_usb_read(struct cp_usb *cp)
+{
+       int ret;
+       uint8_t gpio;
+
+       ret = cp_usb_gpio_get(cp, &gpio);
+       if (ret < 0)
+               perror("gpio_get");
+       return gpio;
+}
diff --git a/lib/cp-usb.h b/lib/cp-usb.h
new file mode 100644 (file)
index 0000000..3e5f25f
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * 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_H_
+#define _CP_USB_H_
+#include <usb.h>
+
+struct cp_usb *
+cp_usb_open(void);
+
+void
+cp_usb_close(struct cp_usb *cp);
+
+void
+cp_usb_write(struct cp_usb *cp, uint8_t mask, uint8_t value);
+
+uint8_t
+cp_usb_read(struct cp_usb *cp);
+
+
+#endif
diff --git a/s51/.gitignore b/s51/.gitignore
new file mode 100644 (file)
index 0000000..cb909cf
--- /dev/null
@@ -0,0 +1 @@
+s51
diff --git a/s51/Makefile.am b/s51/Makefile.am
new file mode 100644 (file)
index 0000000..4778d66
--- /dev/null
@@ -0,0 +1,12 @@
+bin_PROGRAMS=s51
+
+AM_CFLAGS=-I$(top_srcdir)/lib $(LIBUSB_CFLAGS)
+S51_LIBS=../lib/libcc.a -lreadline
+
+man_MANS = s51.1
+
+s51_DEPENDENCIES = $(S51_LIBS)
+
+s51_LDADD=$(S51_LIBS) $(LIBUSB_LIBS)
+
+s51_SOURCES = s51-parse.c s51-command.c s51-main.c
diff --git a/s51/commands b/s51/commands
new file mode 100644 (file)
index 0000000..aba65cd
--- /dev/null
@@ -0,0 +1,60 @@
+Listens on port 9756 for a command stream.
+
+Dump commands:
+       di <start> <end>        - dump imem
+       ds <start> <end>        - dump sprs
+       dx <start> <end>        - dump xaddr
+
+       Returns a string of hex pairs, each preceded by a space,
+       with 8 pairs per line
+
+Memory access commands:
+       set mem <prefix> <start> <end>
+       dump <prefix> <start> <end>
+
+       <prefix> is one of:
+
+               xram    - external ram or external stack
+               rom     - code space
+               iram    - internal ram or stack
+               sfr     - special function register
+
+
+       dump <addr>
+       set bit <addr>
+
+               bit addressable space
+
+Set PC:
+
+       pc <addr>
+
+       Sets PC to specified address
+
+       pc
+
+       Returns current PC
+
+Breakpoints
+
+       break <addr>
+       clear <addr>
+
+Load a file
+
+       file "<filename>"
+
+Execution control:
+
+       run <start>             - run starting at <start>
+       run <start> <stop>      - set temporary bp at <stop>
+       run                     - continue
+       next                    - step over calls(?)
+       step                    - step one instruction
+
+       reset                   - reset the simulator
+       res                     - synonym?
+
+Error messages:
+
+       start with "Error:"
diff --git a/s51/s51-command.c b/s51/s51-command.c
new file mode 100644 (file)
index 0000000..4f80306
--- /dev/null
@@ -0,0 +1,654 @@
+/*
+ * 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 "s51.h"
+
+static uint16_t start_address;
+
+static enum command_result
+parse_int(char *value, int *result)
+{
+       char *endptr;
+
+       *result = strtol(value, &endptr, 0);
+       if (endptr == value)
+               return command_syntax;
+       return command_success;
+}
+
+static enum command_result
+parse_uint16(char *value, uint16_t *uint16)
+{
+       int     v;
+       enum command_result result;
+
+       result = parse_int(value, &v);
+       if (result != command_success)
+               return command_error;
+       if (v < 0 || v > 0xffff)
+               return command_error;
+       *uint16 = v;
+       return command_success;
+}
+
+static enum command_result
+parse_uint8(char *value, uint8_t *uint8)
+{
+       int     v;
+       enum command_result result;
+
+       result = parse_int(value, &v);
+       if (result != command_success)
+               return command_error;
+       if (v < 0 || v > 0xff)
+               return command_error;
+       *uint8 = v;
+       return command_success;
+}
+
+enum command_result
+command_quit (int argc, char **argv)
+{
+       ccdbg_reset(s51_dbg);
+       exit(0);
+       return command_error;
+}
+
+static void
+dump_bytes(uint8_t *memory, int length, uint16_t start, char *format)
+{
+       int group, i;
+
+       for (group = 0; group < length; group += 8) {
+               s51_printf(format, start + group);
+               for (i = group; i < length && i < group + 8; i++)
+                       s51_printf("%02x ", memory[i]);
+               for (; i < group + 8; i++)
+                       s51_printf("   ");
+               for (i = group; i < length && i < group + 8; i++) {
+                       if (isascii(memory[i]) && isprint(memory[i]))
+                               s51_printf("%c", memory[i]);
+                       else
+                               s51_printf(".");
+               }
+               s51_printf("\n");
+       }
+}
+
+enum command_result
+command_di (int argc, char **argv)
+{
+       uint16_t start, end;
+       uint8_t memory[65536];
+       uint8_t status;
+       int length;
+
+       if (argc != 3)
+               return command_error;
+       if (parse_uint16(argv[1], &start) != command_success)
+               return command_error;
+       if (parse_uint16(argv[2], &end) != command_success)
+               return command_error;
+       length = (int) end - (int) start + 1;
+       status = ccdbg_read_memory(s51_dbg, start + 0xff00, memory, length);
+       dump_bytes(memory, length, start, "0x%02x ");
+       return command_success;
+}
+
+enum command_result
+command_ds (int argc, char **argv)
+{
+       uint8_t start, end;
+       uint8_t memory[0x100];
+       uint8_t status;
+       int length;
+
+       if (argc != 3)
+               return command_error;
+       if (parse_uint8(argv[1], &start) != command_success)
+               return command_error;
+       if (parse_uint8(argv[2], &end) != command_success)
+               return command_error;
+       length = (int) end - (int) start + 1;
+       status = ccdbg_read_sfr(s51_dbg, start, memory, length);
+       dump_bytes(memory, length, start, "0x%02x ");
+       return command_success;
+}
+
+enum command_result
+command_dx (int argc, char **argv)
+{
+       uint16_t start, end;
+       uint8_t memory[65536];
+       uint8_t status;
+       int length;
+
+       if (argc != 3)
+               return command_error;
+       if (parse_uint16(argv[1], &start) != command_success)
+               return command_error;
+       if (parse_uint16(argv[2], &end) != command_success)
+               return command_error;
+       length = (int) end - (int) start + 1;
+       status = ccdbg_read_memory(s51_dbg, start, memory, length);
+       dump_bytes(memory, length, start, "0x%04x ");
+       return command_success;
+}
+
+enum command_result
+command_set (int argc, char **argv)
+{
+       uint16_t address;
+       uint8_t *data;
+       int len = argc - 3;
+       int i;
+       enum command_result ret = command_success;
+
+       if (len < 0)
+               return command_error;
+       if (parse_uint16(argv[2], &address) != command_success)
+               return command_error;
+       if (len == 0)
+               return command_success;
+       data = malloc(len);
+       if (!data)
+               return command_error;
+       for (i = 0; i < len; i++)
+               if (parse_uint8(argv[i+3], &data[i]) != command_success)
+                       return command_error;
+
+       if (strcmp(argv[1], "xram") == 0) {
+               ccdbg_write_memory(s51_dbg, address, data, len);
+       } else if (strcmp(argv[1], "iram") == 0) {
+               ccdbg_write_memory(s51_dbg, address + 0xff00, data, len);
+       } else if (strcmp(argv[1], "sfr") == 0) {
+               ccdbg_write_sfr(s51_dbg, (uint8_t) address, data, len);
+       } else
+               ret = command_error;
+       free(data);
+       return ret;
+}
+
+enum command_result
+command_dump (int argc, char **argv)
+{
+       if (argv[1]) {
+               if (strcmp(argv[1], "rom") == 0 ||
+                   strcmp(argv[1], "xram") == 0)
+                       return command_dx(argc-1, argv+1);
+               if (strcmp(argv[1], "iram") == 0)
+                       return command_di(argc-1, argv+1);
+               if (strcmp(argv[1], "sfr") == 0)
+                       return command_ds(argc-1, argv+1);
+       }
+       return command_error;
+}
+
+enum command_result
+command_file (int argc, char **argv)
+{
+       struct hex_file *hex;
+       struct hex_image *image;
+       FILE *file;
+
+       if (argc != 2)
+               return command_error;
+       file = fopen (argv[1], "r");
+       if (!file)
+               return command_error;
+       hex = ccdbg_hex_file_read(file, argv[1]);
+       fclose(file);
+       if (!hex)
+               return command_error;
+       if (hex->nrecord == 0) {
+               ccdbg_hex_file_free(hex);
+               return command_error;
+       }
+       image = ccdbg_hex_image_create(hex);
+       ccdbg_hex_file_free(hex);
+       start_address = image->address;
+       ccdbg_set_rom(s51_dbg, image);
+       return command_success;
+}
+
+enum command_result
+command_pc (int argc, char **argv)
+{
+       uint16_t        pc;
+       if (argv[1]) {
+               enum command_result result;
+               result = parse_uint16(argv[1], &pc);
+               if (result != command_success)
+                       return result;
+               ccdbg_set_pc(s51_dbg, pc);
+       } else {
+               pc = ccdbg_get_pc(s51_dbg);
+               s51_printf("   0x%04x 00\n", pc);
+       }
+       return command_success;
+}
+
+struct cc_break {
+       int             enabled;
+       int             temporary;
+       uint16_t        address;
+};
+
+#define CC_NUM_BREAKPOINTS 4
+
+static struct cc_break breakpoints[CC_NUM_BREAKPOINTS];
+
+static void
+disable_breakpoint(int b)
+{
+       uint8_t status;
+
+       status = ccdbg_set_hw_brkpnt(s51_dbg, b, 0, breakpoints[b].address);
+       if (status != 0x00 && status != 0xff)
+               s51_printf("disable_breakpoint status 0x%02x\n", status);
+}
+
+static void
+enable_breakpoint(int b)
+{
+       uint8_t status;
+
+       status = ccdbg_set_hw_brkpnt(s51_dbg, b, 1, breakpoints[b].address);
+       if (status != 0xff)
+               s51_printf("enable_breakpoint status 0x%02x\n", status);
+}
+
+static void
+enable_breakpoints(void)
+{
+       int b;
+       for (b = 0; b < CC_NUM_BREAKPOINTS; b++)
+               if (breakpoints[b].enabled)
+                       enable_breakpoint(b);
+}
+
+enum command_result
+set_breakpoint(uint16_t address, int temporary)
+{
+       int b;
+       uint8_t status;
+       for (b = 0; b < CC_NUM_BREAKPOINTS; b++) {
+               if (breakpoints[b].enabled == 0)
+                       break;
+               if (breakpoints[b].address == address)
+                       break;
+       }
+       if (b == CC_NUM_BREAKPOINTS) {
+               s51_printf("Error: too many breakpoints requested\n");
+               return command_success;
+       }
+       if (breakpoints[b].enabled == 0) {
+               breakpoints[b].address = address;
+               enable_breakpoint(b);
+       }
+       ++breakpoints[b].enabled;
+       s51_printf("Breakpoint %d at 0x%04x\n", b, address);
+       breakpoints[b].temporary += temporary;
+       return command_success;
+}
+
+enum command_result
+clear_breakpoint(uint16_t address, int temporary)
+{
+       int b;
+       uint8_t status;
+
+       for (b = 0; b < CC_NUM_BREAKPOINTS; b++) {
+               if (breakpoints[b].enabled != 0 &&
+                   ((breakpoints[b].temporary != 0) == (temporary != 0)) &&
+                   breakpoints[b].address == address)
+                       break;
+       }
+       if (b == CC_NUM_BREAKPOINTS) {
+               s51_printf("Error: no matching breakpoint found\n");
+               return command_success;
+       }
+       --breakpoints[b].enabled;
+       breakpoints[b].temporary -= temporary;
+       if (breakpoints[b].enabled == 0) {
+               disable_breakpoint(b);
+               breakpoints[b].address = -1;
+       }
+       return command_success;
+}
+
+
+int
+find_breakpoint(uint16_t address)
+{
+       int b;
+
+       for (b = 0; b < CC_NUM_BREAKPOINTS; b++)
+               if (breakpoints[b].enabled && breakpoints[b].address == address)
+                       break;
+       if (b == CC_NUM_BREAKPOINTS)
+               return -1;
+       return b;
+}
+
+enum command_result
+command_break (int argc, char **argv)
+{
+       int b;
+       uint16_t address;
+       enum command_result result;
+
+       if (argc == 1) {
+               for (b = 0; b < CC_NUM_BREAKPOINTS; b++)
+                       if (breakpoints[b].enabled)
+                               s51_printf("Breakpoint %d 0x%04x\n",
+                                       b, breakpoints[b].address);
+               return command_success;
+       }
+       if (argc != 2)
+               return command_error;
+       result = parse_uint16(argv[1], &address);
+       if (result != command_success)
+               return result;
+
+       return set_breakpoint(address, 0);
+}
+
+enum command_result
+command_clear (int argc, char **argv)
+{
+       int b;
+       uint16_t address;
+       enum command_result result;
+
+       if (argc != 2)
+               return command_error;
+       result = parse_uint16(argv[1], &address);
+       if (result != command_success)
+               return result;
+       return clear_breakpoint(address, 0);
+}
+
+void
+cc_stopped(uint8_t status)
+{
+       uint16_t pc;
+       int b;
+       int code;
+       char *reason;
+
+       pc = ccdbg_get_pc(s51_dbg);
+       if (status & CC_STATUS_CPU_HALTED) {
+               if ((status & CC_STATUS_HALT_STATUS) != 0) {
+                       pc = pc - 1;
+                       code = 104;
+                       reason = "Breakpoint";
+                       b = find_breakpoint(pc);
+                       if (b != -1 && breakpoints[b].temporary)
+                               clear_breakpoint(pc, 1);
+                       ccdbg_set_pc(s51_dbg, pc);
+               } else {
+                       code = 105;
+                       reason = "Interrupt";
+               }
+               s51_printf("Stop at 0x%04x: (%d) %s\n",
+                       pc, code, reason);
+       }
+}
+
+uint8_t
+cc_step(uint16_t pc)
+{
+       int b;
+       uint8_t status;
+
+       b = find_breakpoint(pc);
+       if (b != -1)
+               disable_breakpoint(b);
+       status = ccdbg_step_instr(s51_dbg);
+       if (b != -1)
+               enable_breakpoint(b);
+       return status;
+}
+
+enum command_result
+command_run (int argc, char **argv)
+{
+       uint16_t start, end;
+       enum command_result result;
+       uint16_t pc;
+       uint8_t status;
+       int b;
+
+       if (argv[1]) {
+               result = parse_uint16(argv[1], &start);
+               if (result != command_success)
+                       return result;
+               if (argv[2]) {
+                       result = parse_uint16(argv[2], &end);
+                       if (result != command_success)
+                               return result;
+               }
+               if (start_address && start == 0) {
+                       start = start_address;
+                       s51_printf("Starting at 0x%04x\n", start);
+               }
+               ccdbg_set_pc(s51_dbg, start);
+       }
+       else
+               start = ccdbg_get_pc(s51_dbg);
+       s51_printf("Resume at 0x%04x\n", start);
+       pc = start;
+       b = find_breakpoint(pc);
+       if (b != -1) {
+               cc_step(pc);
+               pc = ccdbg_get_pc(s51_dbg);
+               if (find_breakpoint(pc) != -1) {
+                       status = ccdbg_read_status(s51_dbg);
+                       cc_stopped(status);
+                       return command_success;
+               }
+       }
+       ccdbg_resume(s51_dbg);
+       result = cc_wait();
+       return result;
+}
+
+enum command_result
+command_next (int argc, char **argv)
+{
+       return command_step(argc, argv);
+}
+
+enum command_result
+command_step (int argc, char **argv)
+{
+       uint16_t pc;
+       uint8_t opcode;
+       uint8_t a;
+
+       a = cc_step(ccdbg_get_pc(s51_dbg));
+       s51_printf(" ACC= 0x%02x\n", a);
+       pc = ccdbg_get_pc(s51_dbg);
+       ccdbg_read_memory(s51_dbg, pc, &opcode, 1);
+       s51_printf(" ? 0x%04x %02x\n", pc, opcode);
+       return command_success;
+}
+
+enum command_result
+command_load (int argc, char **argv)
+{
+       char *filename = argv[1];
+       FILE *file;
+       struct hex_file *hex;
+       struct hex_image *image;
+
+       if (!filename)
+               return command_error;
+       file = fopen(filename, "r");
+       if (!file) {
+               perror(filename);
+               return command_error;
+       }
+       hex = ccdbg_hex_file_read(file, filename);
+       fclose(file);
+       if (!hex) {
+               return command_error;
+       }
+       image = ccdbg_hex_image_create(hex);
+       ccdbg_hex_file_free(hex);
+       if (!image) {
+               fprintf(stderr, "image create failed\n");
+               return command_error;
+       }
+       if (image->address >= 0xf000) {
+               printf("Loading %d bytes to RAM at 0x%04x\n",
+                      image->length, image->address);
+               ccdbg_write_hex_image(s51_dbg, image, 0);
+       } else {
+               fprintf(stderr, "Can only load to RAM\n");
+       }
+       ccdbg_hex_image_free(image);
+       return command_success;
+}
+
+enum command_result
+command_halt (int argc, char **argv)
+{
+       uint16_t        pc;
+       ccdbg_halt(s51_dbg);
+       pc = ccdbg_get_pc(s51_dbg);
+       s51_printf("Halted at 0x%04x\n", pc);
+       return command_success;
+}
+
+enum command_result
+command_stop (int argc, char **argv)
+{
+       return command_success;
+}
+
+enum command_result
+command_reset (int argc, char **argv)
+{
+       ccdbg_debug_mode(s51_dbg);
+       ccdbg_halt(s51_dbg);
+       enable_breakpoints();
+       return command_success;
+}
+
+enum command_result
+command_status(int argc, char **argv)
+{
+       uint8_t status;
+
+       status = ccdbg_read_status(s51_dbg);
+       if ((status & CC_STATUS_CHIP_ERASE_DONE) == 0)
+               s51_printf("\tChip erase in progress\n");
+       if (status & CC_STATUS_PCON_IDLE)
+               s51_printf("\tCPU is idle (clock gated)\n");
+       if (status & CC_STATUS_CPU_HALTED)
+               s51_printf("\tCPU halted\n");
+       else
+               s51_printf("\tCPU running\n");
+       if ((status & CC_STATUS_POWER_MODE_0) == 0)
+               s51_printf("\tPower Mode 1-3 selected\n");
+       if (status & CC_STATUS_HALT_STATUS)
+               s51_printf("\tHalted by software or hw breakpoint\n");
+       else
+               s51_printf("\tHalted by debug command\n");
+       if (status & CC_STATUS_DEBUG_LOCKED)
+               s51_printf("\tDebug interface is locked\n");
+       if ((status & CC_STATUS_OSCILLATOR_STABLE) == 0)
+               s51_printf("\tOscillators are not stable\n");
+       if (status & CC_STATUS_STACK_OVERFLOW)
+               s51_printf("\tStack overflow\n");
+       return command_success;
+}
+
+static enum command_result
+info_breakpoints(int argc, char **argv)
+{
+       int b;
+       uint16_t address;
+       enum command_result result;
+
+       if (argc == 1) {
+               s51_printf("Num Type       Disp Hit   Cnt   Address  What\n");
+               for (b = 0; b < CC_NUM_BREAKPOINTS; b++)
+                       if (breakpoints[b].enabled) {
+                               s51_printf("%-3d fetch      %s 1     1     0x%04x   uc::disass() unimplemented\n",
+                                          b,
+                                          breakpoints[b].temporary ? "del " : "keep",
+                                          breakpoints[b].address);
+                       }
+               return command_success;
+       }
+
+}
+
+static enum command_result
+info_help(int argc, char **argv);
+
+static struct command_function infos[] = {
+       { "breakpoints", "b", info_breakpoints, "[b]reakpoints",
+               "List current breakpoints\n" },
+       { "help",   "?",  info_help,    "help",
+               "Print this list\n" },
+
+       { NULL, NULL, NULL, NULL, NULL },
+};
+
+static enum command_result
+info_help(int argc, char **argv)
+{
+       return command_function_help(infos, argc, argv);
+}
+
+enum command_result
+command_info(int argc, char **argv)
+{
+       struct command_function *func;
+
+       if (argc < 2)
+               return command_error;
+       func = command_string_to_function(infos, argv[1]);
+       if (!func)
+               return command_syntax;
+       return (*func->func)(argc-1, argv+1);
+}
+
+enum command_result
+cc_wait(void)
+{
+       for(;;) {
+               uint8_t status;
+               status = ccdbg_read_status(s51_dbg);
+               if (status & CC_STATUS_CPU_HALTED) {
+                       cc_stopped(status);
+                       return command_success;
+               }
+               if (s51_interrupted || s51_check_input()) {
+
+                       ccdbg_halt(s51_dbg);
+                       status = ccdbg_read_status(s51_dbg);
+                       cc_stopped(status);
+                       return command_interrupt;
+               }
+       }
+}
diff --git a/s51/s51-main.c b/s51/s51-main.c
new file mode 100644 (file)
index 0000000..4dbd4c6
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+ * 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 "s51.h"
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <poll.h>
+
+static int s51_port = 0;
+static char *cpu = "8051";
+static double freq = 11059200;
+char *s51_prompt = "> ";
+struct ccdbg *s51_dbg;
+int s51_interrupted = 0;
+int s51_monitor = 0;
+
+static FILE *s51_input;
+static FILE *s51_output;
+
+static void
+usage(void)
+{
+       fprintf(stderr, "You're doing it wrong.\n");
+       exit(1);
+}
+
+void s51_sigint()
+{
+       s51_interrupted = 1;
+}
+
+int
+main(int argc, char **argv)
+{
+       int flags, opt;
+       char *endptr;
+       struct sigvec vec, ovec;
+
+       while ((opt = getopt(argc, argv, "PVvHhmt:X:c:r:Z:s:S:p:")) != -1) {
+               switch (opt) {
+               case 't':
+                       cpu = optarg;
+                       break;
+               case 'X':
+                       freq = strtod(optarg, &endptr);
+                       if (endptr == optarg)
+                               usage();
+                       if (endptr[0] != '\0') {
+                               if (!strcmp(endptr, "k"))
+                                       freq *= 1000;
+                               else if (!strcmp(endptr, "M") )
+                                       freq *= 1000000;
+                               else
+                                       usage ();
+                       }
+                       break;
+               case 'c':
+                       break;
+               case 'r':
+               case 'Z':
+                       s51_port = strtol(optarg, &endptr, 0);
+                       if (endptr == optarg || strlen(endptr) != 0)
+                               usage();
+                       break;
+               case 's':
+                       break;
+               case 'S':
+                       break;
+               case 'p':
+                       s51_prompt = optarg;
+                       break;
+               case 'P':
+                       s51_prompt = NULL;
+                       break;
+               case 'V':
+                       break;
+               case 'v':
+                       break;
+               case 'H':
+                       exit (0);
+                       break;
+               case 'h':
+                       usage ();
+                       break;
+               case 'm':
+                       s51_monitor = 1;
+                       break;
+               }
+       }
+       if (s51_port) {
+               int l, r, one = 1;
+               int s;
+               struct sockaddr_in in;
+
+               l = socket(AF_INET, SOCK_STREAM, 0);
+               if (l < 0) {
+                       perror ("socket");
+                       exit(1);
+               }
+               r = setsockopt(l, SOL_SOCKET, SO_REUSEADDR, &one, sizeof (int));
+               if (r) {
+                       perror("setsockopt");
+                       exit(1);
+               }
+               in.sin_family = AF_INET;
+               in.sin_port = htons(s51_port);
+               in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+               r = bind(l, (struct sockaddr *) &in, sizeof (in));
+               if (r) {
+                       perror("bind");
+                       exit(1);
+               }
+               r = listen(l, 5);
+               if (r) {
+                       perror("listen");
+                       exit(1);
+               }
+               for (;;) {
+                       struct sockaddr_in client_addr;
+                       socklen_t client_len = sizeof (struct sockaddr_in);
+
+                       s = accept(l, (struct sockaddr *)
+                                  &client_addr, &client_len);
+                       if (s < 0) {
+                               perror("accept");
+                               exit(1);
+                       }
+                       s51_input = fdopen(s, "r");
+                       s51_output = fdopen(s, "w");
+                       if (!s51_input || !s51_output) {
+                               perror("fdopen");
+                               exit(1);
+                       }
+                       vec.sv_handler = SIG_IGN;
+                       vec.sv_mask = 0;
+                       vec.sv_flags = 0;
+                       sigvec(SIGINT, &vec, &ovec);
+                       command_read();
+                       sigvec(SIGINT, &ovec, NULL);
+                       fclose(s51_input);
+                       fclose(s51_output);
+               }
+       } else {
+               s51_input = stdin;
+               s51_output = stdout;
+               vec.sv_handler = s51_sigint;
+               vec.sv_mask = 0;
+               vec.sv_flags = 0;
+               sigvec(SIGINT, &vec, &ovec);
+               command_read();
+       }
+       exit(0);
+}
+
+void
+s51_printf(char *format, ...)
+{
+       va_list ap;
+
+       va_start(ap, format);
+       vfprintf(s51_output, format, ap);
+       if (s51_monitor)
+               vfprintf(stdout, format, ap);
+       va_end(ap);
+}
+
+void
+s51_putc(int c)
+{
+       putc(c, s51_output);
+}
+
+#include <readline/readline.h>
+#include <readline/history.h>
+
+int
+s51_read_line(char *line, int len)
+{
+       int ret;
+       if (s51_output == stdout && s51_input == stdin && s51_prompt) {
+               char *r;
+
+               r = readline(s51_prompt);
+               if (r == NULL)
+                       return 0;
+               strncpy (line, r, len);
+               line[len-1] = '\0';
+               add_history(r);
+               return 1;
+       } else {
+               if (s51_prompt)
+                       s51_printf("%s", s51_prompt);
+               else
+                       s51_putc('\0');
+               fflush(s51_output);
+               ret = fgets(line, len, s51_input) != NULL;
+               if (s51_monitor)
+                       printf("> %s", line);
+               fflush(stdout);
+       }
+       return ret;
+}
+
+int
+s51_check_input(void)
+{
+       struct pollfd   input;
+       int r;
+       int c;
+
+       input.fd = fileno(s51_input);
+       input.events = POLLIN;
+       r = poll(&input, 1, 0);
+       if (r > 0) {
+               char line[256];
+               (void) s51_read_line(line, sizeof (line));
+               return 1;
+       }
+       return 0;
+}
diff --git a/s51/s51-parse.c b/s51/s51-parse.c
new file mode 100644 (file)
index 0000000..170c979
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * 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 "s51.h"
+
+static struct command_function functions[] = {
+       { "help",   "?",  command_help, "help",         "Print this list\n" },
+       { "quit",   "q",  command_quit, "[q]uit",       "Quit\n" },
+       { "di",     "di", command_di,   "di <start> <end>",
+               "Dump imem\n" },
+       { "ds",     "ds", command_ds,   "ds <start> <end>",
+               "Dump sprs\n" },
+       { "dx",     "dx", command_dx,   "dx <start> <end>",
+               "Dump xaddr\n" },
+       { "set",    "t",  command_set,  "se[t] mem <prefix> <address> <data> ...",
+               "Set mem {xram|rom|iram|sfr}\n"
+               "set bit <addr>\n" },
+       { "dump",   "d",  command_dump, "[d]ump <prefix> <start> <end>",
+               "Dump {xram|rom|iram|sfr} <start> <end>\n" },
+       { "file", "file", command_file, "file <filename>",
+               "Pretend to load executable from <filename>\n" },
+       { "pc",     "p",  command_pc, "[p]c [addr]",
+               "Get or set pc value\n" },
+       { "break",  "b",  command_break,"[b]reak <addr>",
+               "Set break point\n" },
+       { "clear",  "c",  command_clear,"[c]lear <addr>",
+               "Clear break point\n" },
+       { "run",    "r",  command_run, "[r]un [start] [stop]",
+               "Run with optional start and temp breakpoint addresses\n" },
+       { "go",     "g",  command_run, "[g]o [start] [stop]",
+               "Run with optional start and temp breakpoint addresses\n" },
+       { "next",   "n",  command_next, "[n]ext",
+               "Step over one instruction, past any call\n" },
+       { "step",   "s",  command_step, "[s]tep",
+               "Single step\n" },
+       { "load",   "l",  command_load, "[l]oad <file>",
+               "Load a hex file into memory or flash" },
+       { "halt",   "h",  command_halt, "[h]alt",
+               "Halt the processor\n" },
+       { "reset","res",command_reset,  "[res]et",
+               "Reset the CPU\n" },
+       { "status","status",command_status, "status",
+               "Display CC1111 debug status\n" },
+       { "info",   "i",  command_info, "[i]info",
+               "Get information\n" },
+       { "stop",  "stop", command_stop, "stop",
+               "Ignored\n" },
+       { NULL, NULL, NULL, NULL, NULL },
+};
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE 1
+#endif
+
+static int
+string_to_int(char *s, int *v)
+{
+       char *endptr;
+
+       if (isdigit(s[0]) || s[0] == '-' || s[0] == '+') {
+               *v = strtol(s, &endptr, 0);
+               if (endptr == s)
+                       return FALSE;
+       } else if (*s == '\'') {
+               s++;
+               if (*s == '\\') {
+                       s++;
+                       switch (*s) {
+                       case 'n':
+                               *v = '\n';
+                               break;
+                       case 't':
+                               *v = '\t';
+                               break;
+                       default:
+                               *v = (int) *s;
+                               break;
+                       }
+               } else
+                       *v = (int) *s;
+               s++;
+               if (*s != '\'')
+                       return FALSE;
+       }
+       else
+               return FALSE;
+    return TRUE;
+}
+
+struct command_function *
+command_string_to_function(struct command_function *functions, char *name)
+{
+       int i;
+       for (i = 0; functions[i].name; i++)
+               if (!strcmp(name, functions[i].name) ||
+                   !strcmp(name, functions[i].alias))
+                       return &functions[i];
+       return NULL;
+}
+
+enum command_result
+command_function_help(struct command_function *functions, int argc, char **argv)
+{
+       int i;
+       struct command_function *func;
+
+       if (argc == 1) {
+               for (i = 0; functions[i].name; i++)
+                       s51_printf("%-10s%s\n", functions[i].name,
+                              functions[i].usage);
+       } else {
+               for (i = 1; i < argc; i++) {
+                       func = command_string_to_function(functions, argv[i]);
+                       if (!func) {
+                               s51_printf("%-10s unknown command\n", argv[i]);
+                               return command_syntax;
+                       }
+                       s51_printf("%-10s %s\n%s", func->name,
+                              func->usage, func->help);
+               }
+       }
+       return command_debug;
+}
+
+static int
+command_split_into_words(char *line, char **argv)
+{
+       char quotechar;
+       int argc;
+
+       argc = 0;
+       while (*line) {
+               while (isspace(*line))
+                       line++;
+               if (!*line)
+                       break;
+               if (*line == '"') {
+                       quotechar = *line++;
+                       *argv++ = line;
+                       argc++;
+                       while (*line && *line != quotechar)
+                               line++;
+                       if (*line)
+                               *line++ = '\0';
+               } else {
+                       *argv++ = line;
+                       argc++;
+                       while (*line && !isspace(*line))
+                               line++;
+                       if (*line)
+                               *line++ = '\0';
+               }
+       }
+       *argv = 0;
+       return argc;
+}
+
+enum command_result
+command_help(int argc, char **argv)
+{
+       return command_function_help(functions, argc, argv);
+}
+
+void
+command_syntax_error(int argc, char **argv)
+{
+       s51_printf("Syntax error in:");
+       while (*argv)
+               s51_printf(" %s", *argv++);
+       s51_printf("\n");
+}
+
+void
+command_read (void)
+{
+       int argc;
+       char line[1024];
+       char *argv[20];
+       enum command_result result;
+       struct command_function *func;
+
+       s51_dbg = ccdbg_open ();
+       if (!s51_dbg) {
+               perror("ccdbg_open");
+               exit(1);
+       }
+       ccdbg_debug_mode(s51_dbg);
+       ccdbg_halt(s51_dbg);
+       s51_printf("Welcome to the non-simulated processor\n");
+       for (;;) {
+               if (s51_read_line (line, sizeof line) == 0)
+                       break;
+               s51_interrupted = 0;
+               argc = command_split_into_words(line, argv);
+               if (argc > 0) {
+                       func = command_string_to_function(functions, argv[0]);
+                       if (!func)
+                               command_syntax_error(argc, argv);
+                       else
+                       {
+                               result = (*func->func)(argc, argv);
+                               if (s51_interrupted)
+                                       result = command_interrupt;
+                               switch (result) {
+                               case command_syntax:
+                                       command_syntax_error(argc, argv);
+                                       break;
+                               case command_error:
+                                       s51_printf("Error\n");
+                                       break;
+                               case command_success:
+                                       break;
+                               case command_interrupt:
+                                       ccdbg_halt(s51_dbg);
+                                       s51_printf("Interrupted\n");
+                                       break;
+                               default:
+                                       break;
+                               }
+                       }
+               }
+       }
+       ccdbg_close(s51_dbg);
+       s51_printf("...\n");
+}
diff --git a/s51/s51.1 b/s51/s51.1
new file mode 100644 (file)
index 0000000..f2f59a5
--- /dev/null
+++ b/s51/s51.1
@@ -0,0 +1,211 @@
+.\"
+.\" Copyright © 2009 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.
+.\"
+.\"
+.TH S51 1 "s51" ""
+.SH NAME
+s51 \- hex debugger for cc1111 processors
+.SH SYNOPSIS
+.B "s51"
+[\-t \fIcpu-type\fP]
+[\-X \fIfrequency\fP]
+[\-c]
+[\-r \fIlisten-port\fP]
+[\-Z \fIlisten-port\fP]
+[\-s]
+[\-S]
+[\-p \fIprompt\fP]
+[\-V]
+[\-v]
+[\-H]
+[\-h]
+[\-m]
+.SH DESCRIPTION
+.I s51
+connects to a cc1111 processor through a cp1203-based USB-to-serial
+converter board, using the GPIO pins available on that chip. It provides an
+interface compatible with the 8051 emulator of the same name (s51), but
+communicating with the real chip instead of an emulation. Using a modified
+version of the SDCC debugger (sdcdb), you can control program execution
+on the target machine at source-level.
+
+.SH OPTIONS
+The command line options are designed to be compatible with the 8051
+emulator so that it can be used with sdcdb. As such, they're all one letter
+long.
+.IP "\-t \fIcpu-type\fP"
+The 8051 emulator can operate as one of several different chips. Oddly, the
+real hardware cannot, so this option is ignored.
+.IP "\-X \fIfrequency\fP"
+Similarly, the emulator can pretend to run at an arbitrary frequency
+which the real hardware cannot do. Ignored.
+.IP "\-c"
+.IP "\-s"
+.IP "\-S"
+.IP "\-v"
+.IP "\-V"
+All ignored.
+.IP "\-r \fIlisten-port\fP, -Z \fIlisten-port\fP"
+The emulator and sdcdb communicate through a network socket. This option
+switches the debugger from communicating through stdin/stdout to listening
+on a specific network port instead. Once a connection is made, the debugger
+continues on, using that network port for command input and output. The
+debugger uses port 9756, and attempts to connect before launching s51, so if
+s51 is listening on this port before sdcdb is started, sdcdb will end up
+talking to the existing s51 instance. That's often useful for debugging s51
+itself.
+.IP "\-p \fIprompt\fP"
+This sets the command prompt to the specified string.
+.IP "\-P"
+This sets the command prompt to a single NUL character. This is for use by
+sdcdb.
+.IP "\-h"
+This should print a usage message, but does nothing useful currently.
+.IP "\-m"
+This option is not present in the original 8051 emulator, and causes s51 to
+dump all commands and replies that are received from and sent to sdcdb.
+.SH COMMANDS
+Once started, s51 connects to the cc1111 via the CP2103 using libusb2 and
+then reads and executes commands, either from stdin, or the nework
+connection to sdcdb.
+.PP
+Unlike the command line, s51 contains built-in help for each of these
+commands, via the 'help' command. Most of the commands are available in a
+long form and a single character short form. Below, the short form follows
+the long form after a comma.
+.IP "help, ? {command}"
+Without arguments, prints a list of available commands. With an argument
+prints more detail about the specific command
+.IP "quit, q"
+Terminates the application, without changing the state of the target
+processor.
+.IP "di [start] [end]"
+Dumps imem (256 bytes of "internal" memory) from start to end (inclusive).
+.IP "ds [start] [end]"
+Dumps sprs from start to end (inclusive). Note that while most sprs are
+visible in the global address space, some are not, so use this command
+instead of "dx" to read them.
+.IP "dx [start] [end]"
+Dump external (global) memory from start to end (inclusive).
+.IP "set, t <prefix> [start] {data ...}"
+Store to the memory space specified by prefix where prefix is one of "xram",
+"rom", "iram", or "sfr". Store bytes starting at start.
+.IP "dump, d <prefix> [start] [end]"
+Dump from the memory space specified by prefix, where prefix is one of
+"xram", "rom", "iram" or "sfr". Dumps from start to end (inclusive).
+.IP "file [filename]"
+Specifies an intel-format hex file (ihx) that contains the contents of the
+rom area loaded into the cc1111. This is used to respond to requests to dump
+rom memory contents without getting them from the cc1111 (which is slow).
+.IP "pc, p {address}"
+If the address argument is given, this sets the program counter to the
+specified value. Otherwise, the current program counter value is displayed.
+.IP "break, b [address]"
+Sets a breakpoint at the specified address. This uses the built-in hardware
+breakpoint support in the cc1111. As a result, it supports no more than four
+breakpoints at once. You must therefore use a modified version of sdcdb which
+changes how program execution is controlled to work within this limit.
+.IP "clear, c [address]"
+Clear a breakpoint from the specified address.
+.IP "run, r, go, g {start} {stop}"
+Resumes execution of the program. If the start argument is present, then it
+begins at that address, otherwise it continues running at the current pc. If
+a stop argument is present, then a temporary breakpoint is set at that
+address. This temporary breakpoint will be removed when execution hits it.
+.IP "next, n"
+Step one instruction. In the original s51 program this would ignore
+subroutines, but as sdcdb doesn't require this functionality, it's not
+available here.
+.IP "step, s"
+Step one instruction.
+.IP "load, l [filename]"
+This is not implemented, but it is supposed to load a hex file into flash.
+Use the ccload program instead.
+.IP "halt, h"
+Halt the processor. This is the only command which can be sent while the
+program is running. It is ignored at other times.
+.IP "reset, res"
+Reset the processor. This pulls the reset pin low and re-enables debug mode.
+Check the cc1111 documentation to see precisely what this does.
+.IP "status"
+This dumps the cc1111 debug status register.
+.IP "info, i breakpoints, b"
+List the current breakpoints.
+.IP "info, i help, ?"
+List the things you can get info on.
+.IP "stop"
+This doesn't do anything and is present only to retain compatibility with
+the original 8051 emulator.
+.SH "BOARD BRINGUP DEBUGGING"
+.PP
+While the original purpose for this program was to connect the source
+debugger with the hardware, it can also be used as a low-level hex debugger
+all on its own. In particular, all of the cc1111 peripherals can be
+manipulated directly from the s51 command line.
+.IP "Starting s51"
+If the CP2103 is plugged in, and the CC1111 is connected correctly, the
+\'s51\' command itself should connect to the device without trouble.
+Note that the CP2103 must have the GPIO pins configured correctly as well.
+.IP
+$ s51
+.br
+Welcome to the non-simulated processor
+.br
+> status
+.br
+       CPU halted
+.br
+       Halted by debug command
+.br
+>
+.IP "Turning on LEDs"
+Two of the cc1111 GPIO pins, P1_0 and P1_1 are capable of driving external
+LEDs. To control these, set the Port 1 direction bits to make these output
+pins and then change the Port 1 data to set them high or low:
+.IP
+> set sfr 0xfe 0x02    # set P1DIR to 0x2
+.br
+> set sfr 0x90 0x02    # set P1_1 to high
+.br
+> set sfr 0x90 0x00    # set P1_1 to low
+.IP "Reading the A/D converters"
+The six A/D converter inputs can each be connected to any of the P0 pins,
+ground, the A/D voltage refernece, an internal temperature sensor or VDD/3.
+To read one of these values, select an A/D converter to use then start the
+conversion process. The cc1111 manual has the table for selecting the input
+on page 144.
+.IP
+To configure one of the P0 pins for use by the A/D unit, we program the
+ADCCFG register, setting the bits in that which match the pins desired:
+.IP
+> set sfr 0xf2 0x3f    # enable all 6 A/D inputs
+.IP
+To trigger a single conversion, we ask the A/D unit to perform an 'extra'
+conversion, which means to do a single conversion not a whole sequence of
+conversions. This is controlled by the ADCCON3 register at 0xB6:
+.IP
+> set sfr 0xb6 0xb2    # sample P0_2 using 12 bits of precision
+.br
+> ds 0xba 0xbb         # dump the ADC data low and high regs
+.br
+> set sfr 0xb6 0xbe    # sample internal temperature sensor
+.br
+> ds 0xba 0xbb         # dump the ADC data low and high regs
+.SH "SEE ALSO"
+sdcdb(1), ccload(1)
+.SH AUTHOR
+Keith Packard
diff --git a/s51/s51.h b/s51/s51.h
new file mode 100644 (file)
index 0000000..f4dcce6
--- /dev/null
+++ b/s51/s51.h
@@ -0,0 +1,123 @@
+/*
+ * 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 <ccdbg.h>
+
+extern char *s51_prompt;
+extern struct ccdbg *s51_dbg;
+extern int s51_interrupted;
+extern int s51_monitor;
+
+enum command_result {
+       command_success, command_debug, command_syntax, command_interrupt, command_error,
+};
+
+struct command_function {
+       char                    *name;
+       char                    *alias;
+       enum command_result     (*func)(int argc, char **argv);
+       char                    *usage;
+       char                    *help;
+};
+
+struct command_function *
+command_string_to_function(struct command_function *functions, char *name);
+
+enum command_result
+command_function_help(struct command_function *functions, int argc, char **argv);
+
+void
+command_syntax_error(int argc, char **argv);
+
+enum command_result
+command_quit (int argc, char **argv);
+
+enum command_result
+command_help (int argc, char **argv);
+
+enum command_result
+command_stop (int argc, char **argv);
+
+enum command_result
+command_di (int argc, char **argv);
+
+enum command_result
+command_ds (int argc, char **argv);
+
+enum command_result
+command_dx (int argc, char **argv);
+
+enum command_result
+command_set (int argc, char **argv);
+
+enum command_result
+command_dump (int argc, char **argv);
+
+enum command_result
+command_file (int argc, char **argv);
+
+enum command_result
+command_pc (int argc, char **argv);
+
+enum command_result
+command_break (int argc, char **argv);
+
+enum command_result
+command_clear (int argc, char **argv);
+
+enum command_result
+command_run (int argc, char **argv);
+
+enum command_result
+command_next (int argc, char **argv);
+
+enum command_result
+command_step (int argc, char **argv);
+
+enum command_result
+command_load (int argc, char **argv);
+
+enum command_result
+command_halt (int argc, char **argv);
+
+enum command_result
+command_reset (int argc, char **argv);
+
+enum command_result
+command_status (int argc, char **argv);
+
+enum command_result
+command_info (int argc, char **argv);
+
+enum command_result
+cc_wait(void);
+
+void
+command_read (void);
+
+void
+s51_printf(char *format, ...);
+
+void
+s51_putc(int c);
+
+int
+s51_check_input(void);
+
+int
+s51_read_line(char *line, int len);
diff --git a/target/adc-serial/Makefile b/target/adc-serial/Makefile
new file mode 100644 (file)
index 0000000..9a8bf5c
--- /dev/null
@@ -0,0 +1,47 @@
+PROG=adc_serial
+CC=sdcc
+NO_OPT=--nogcse --noinvariant --noinduction --nojtbound --noloopreverse \
+       --nolabelopt --nooverlay --peep-asm
+DEBUG=--debug
+
+CFLAGS=--model-large $(DEBUG) --stack-auto --less-pedantic \
+       --no-peep --int-long-reent --float-reent \
+       --data-loc 0x30
+
+LDFLAGS=--out-fmt-ihx
+LDFLAGS_RAM=$(LDFLAGS) --code-loc 0xf000 --xram-loc 0xf800 --xram-size 1024
+
+LDFLAGS_FLASH=$(LDFLAGS) --code-loc 0x0000 --xram-loc 0xf000 --xram-size 1024
+
+SRC=$(PROG).c
+ADB=$(SRC:.c=.adb)
+ASM=$(SRC:.c=.asm)
+LNK=$(SRC:.c=.lnk)
+LST=$(SRC:.c=.lst)
+REL=$(SRC:.c=.rel)
+RST=$(SRC:.c=.rst)
+SYM=$(SRC:.c=.sym)
+
+PROGS=$(PROG)-flash.ihx $(PROG)-ram.ihx
+PCDB=$(PROGS:.ihx=.cdb)
+PLNK=$(PROGS:.ihx=.lnk)
+PMAP=$(PROGS:.ihx=.map)
+PMEM=$(PROGS:.ihx=.mem)
+PAOM=$(PROGS:.ihx=)
+
+%.rel : %.c
+       $(CC) -c $(CFLAGS) -o$*.rel $<
+
+all: $(PROGS)
+
+$(PROG)-ram.ihx: $(REL) Makefile
+       $(CC) $(LDFLAGS_RAM) $(CFLAGS) -o $(PROG)-ram.ihx $(REL)
+       $(CC) $(LDFLAGS_FLASH) $(CFLAGS) -o $(PROG)-flash.ihx $(REL)
+
+$(PROG)-flash.ihx: $(PROG)-ram.ihx
+
+clean:
+       rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM)
+       rm -f $(PROGS) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM)
+
+install:
diff --git a/target/adc-serial/adc_serial.c b/target/adc-serial/adc_serial.c
new file mode 100644 (file)
index 0000000..1f7b688
--- /dev/null
@@ -0,0 +1,578 @@
+/*
+ * 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 <stdint.h>
+
+/*
+ * Test ADC in DMA mode
+ */
+
+sfr at 0x80 P0;
+sfr at 0x90 P1;
+sfr at 0xA0 P2;
+sfr at 0xC6 CLKCON;
+sfr at 0xbe SLEEP;
+
+# define SLEEP_USB_EN          (1 << 7)
+# define SLEEP_XOSC_STB                (1 << 6)
+
+sfr at 0xF1 PERCFG;
+#define PERCFG_T1CFG_ALT_1     (0 << 6)
+#define PERCFG_T1CFG_ALT_2     (1 << 6)
+
+#define PERCFG_T3CFG_ALT_1     (0 << 5)
+#define PERCFG_T3CFG_ALT_2     (1 << 5)
+
+#define PERCFG_T4CFG_ALT_1     (0 << 4)
+#define PERCFG_T4CFG_ALT_2     (1 << 4)
+
+#define PERCFG_U1CFG_ALT_1     (0 << 1)
+#define PERCFG_U1CFG_ALT_2     (1 << 1)
+
+#define PERCFG_U0CFG_ALT_1     (0 << 0)
+#define PERCFG_U0CFG_ALT_2     (1 << 0)
+
+sfr at 0xF2 ADCCFG;
+sfr at 0xF3 P0SEL;
+sfr at 0xF4 P1SEL;
+sfr at 0xF5 P2SEL;
+
+sfr at 0xFD P0DIR;
+sfr at 0xFE P1DIR;
+sfr at 0xFF P2DIR;
+sfr at 0x8F P0INP;
+sfr at 0xF6 P1INP;
+sfr at 0xF7 P2INP;
+
+sfr at 0x89 P0IFG;
+sfr at 0x8A P1IFG;
+sfr at 0x8B P2IFG;
+
+sbit at 0x90 P1_0;
+sbit at 0x91 P1_1;
+sbit at 0x92 P1_2;
+sbit at 0x93 P1_3;
+sbit at 0x94 P1_4;
+sbit at 0x95 P1_5;
+sbit at 0x96 P1_6;
+sbit at 0x97 P1_7;
+
+/*
+ * UART registers
+ */
+
+sfr at 0x86 U0CSR;
+sfr at 0xF8 U1CSR;
+
+/*
+ * IRCON2
+ */
+sfr at 0xE8 IRCON2;    /* CPU Interrupt Flag 5 */
+
+sbit at 0xE8 USBIF;    /* USB interrupt flag (shared with Port2) */
+sbit at 0xE8 P2IF;     /* Port2 interrupt flag (shared with USB) */
+sbit at 0xE9 UTX0IF;   /* USART0 TX interrupt flag */
+sbit at 0xEA UTX1IF;   /* USART1 TX interrupt flag (shared with I2S TX) */
+sbit at 0xEA I2STXIF;  /* I2S TX interrupt flag (shared with USART1 TX) */
+sbit at 0xEB P1IF;     /* Port1 interrupt flag */
+sbit at 0xEC WDTIF;    /* Watchdog timer interrupt flag */
+
+# define UxCSR_MODE_UART               (1 << 7)
+# define UxCSR_MODE_SPI                        (0 << 7)
+# define UxCSR_RE                      (1 << 6)
+# define UxCSR_SLAVE                   (1 << 5)
+# define UxCSR_MASTER                  (0 << 5)
+# define UxCSR_FE                      (1 << 4)
+# define UxCSR_ERR                     (1 << 3)
+# define UxCSR_RX_BYTE                 (1 << 2)
+# define UxCSR_TX_BYTE                 (1 << 1)
+# define UxCSR_ACTIVE                  (1 << 0)
+
+sfr at 0xc4 U0UCR;
+sfr at 0xfb U1UCR;
+
+# define UxUCR_FLUSH                   (1 << 7)
+# define UxUCR_FLOW_DISABLE            (0 << 6)
+# define UxUCR_FLOW_ENABLE             (1 << 6)
+# define UxUCR_D9_EVEN_PARITY          (0 << 5)
+# define UxUCR_D9_ODD_PARITY           (1 << 5)
+# define UxUCR_BIT9_8_BITS             (0 << 4)
+# define UxUCR_BIT9_9_BITS             (1 << 4)
+# define UxUCR_PARITY_DISABLE          (0 << 3)
+# define UxUCR_PARITY_ENABLE           (1 << 3)
+# define UxUCR_SPB_1_STOP_BIT          (0 << 2)
+# define UxUCR_SPB_2_STOP_BITS         (1 << 2)
+# define UxUCR_STOP_LOW                        (0 << 1)
+# define UxUCR_STOP_HIGH               (1 << 1)
+# define UxUCR_START_LOW               (0 << 0)
+# define UxUCR_START_HIGH              (1 << 0)
+
+sfr at 0xc5 U0GCR;
+sfr at 0xfc U1GCR;
+
+# define UxGCR_CPOL_NEGATIVE           (0 << 7)
+# define UxGCR_CPOL_POSITIVE           (1 << 7)
+# define UxGCR_CPHA_FIRST_EDGE         (0 << 6)
+# define UxGCR_CPHA_SECOND_EDGE                (1 << 6)
+# define UxGCR_ORDER_LSB               (0 << 5)
+# define UxGCR_ORDER_MSB               (1 << 5)
+# define UxGCR_BAUD_E_MASK             (0x1f)
+# define UxGCR_BAUD_E_SHIFT            0
+
+sfr at 0xc1 U0DBUF;
+sfr at 0xf9 U1DBUF;
+sfr at 0xc2 U0BAUD;
+sfr at 0xfa U1BAUD;
+
+#define DEBUG  P1_1
+
+
+# define DMA_LEN_HIGH_VLEN_MASK                (7 << 5)
+# define DMA_LEN_HIGH_VLEN_LEN         (0 << 5)
+# define DMA_LEN_HIGH_VLEN_PLUS_1      (1 << 5)
+# define DMA_LEN_HIGH_VLEN             (2 << 5)
+# define DMA_LEN_HIGH_VLEN_PLUS_2      (3 << 5)
+# define DMA_LEN_HIGH_VLEN_PLUS_3      (4 << 5)
+# define DMA_LEN_HIGH_MASK             (0x1f)
+
+# define DMA_CFG0_WORDSIZE_8           (0 << 7)
+# define DMA_CFG0_WORDSIZE_16          (1 << 7)
+# define DMA_CFG0_TMODE_MASK           (3 << 5)
+# define DMA_CFG0_TMODE_SINGLE         (0 << 5)
+# define DMA_CFG0_TMODE_BLOCK          (1 << 5)
+# define DMA_CFG0_TMODE_REPEATED_SINGLE        (2 << 5)
+# define DMA_CFG0_TMODE_REPEATED_BLOCK (3 << 5)
+
+/*
+ * DMA triggers
+ */
+# define DMA_CFG0_TRIGGER_NONE         0
+# define DMA_CFG0_TRIGGER_PREV         1
+# define DMA_CFG0_TRIGGER_T1_CH0       2
+# define DMA_CFG0_TRIGGER_T1_CH1       3
+# define DMA_CFG0_TRIGGER_T1_CH2       4
+# define DMA_CFG0_TRIGGER_T2_OVFL      6
+# define DMA_CFG0_TRIGGER_T3_CH0       7
+# define DMA_CFG0_TRIGGER_T3_CH1       8
+# define DMA_CFG0_TRIGGER_T4_CH0       9
+# define DMA_CFG0_TRIGGER_T4_CH1       10
+# define DMA_CFG0_TRIGGER_IOC_0                12
+# define DMA_CFG0_TRIGGER_IOC_1                13
+# define DMA_CFG0_TRIGGER_URX0         14
+# define DMA_CFG0_TRIGGER_UTX0         15
+# define DMA_CFG0_TRIGGER_URX1         16
+# define DMA_CFG0_TRIGGER_UTX1         17
+# define DMA_CFG0_TRIGGER_FLASH                18
+# define DMA_CFG0_TRIGGER_RADIO                19
+# define DMA_CFG0_TRIGGER_ADC_CHALL    20
+# define DMA_CFG0_TRIGGER_ADC_CH0      21
+# define DMA_CFG0_TRIGGER_ADC_CH1      22
+# define DMA_CFG0_TRIGGER_ADC_CH2      23
+# define DMA_CFG0_TRIGGER_ADC_CH3      24
+# define DMA_CFG0_TRIGGER_ADC_CH4      25
+# define DMA_CFG0_TRIGGER_ADC_CH5      26
+# define DMA_CFG0_TRIGGER_ADC_CH6      27
+# define DMA_CFG0_TRIGGER_I2SRX                27
+# define DMA_CFG0_TRIGGER_ADC_CH7      28
+# define DMA_CFG0_TRIGGER_I2STX                28
+# define DMA_CFG0_TRIGGER_ENC_DW       29
+# define DMA_CFG0_TRIGGER_DNC_UP       30
+
+# define DMA_CFG1_SRCINC_MASK          (3 << 6)
+# define DMA_CFG1_SRCINC_0             (0 << 6)
+# define DMA_CFG1_SRCINC_1             (1 << 6)
+# define DMA_CFG1_SRCINC_2             (2 << 6)
+# define DMA_CFG1_SRCINC_MINUS_1       (3 << 6)
+
+# define DMA_CFG1_DESTINC_MASK         (3 << 4)
+# define DMA_CFG1_DESTINC_0            (0 << 4)
+# define DMA_CFG1_DESTINC_1            (1 << 4)
+# define DMA_CFG1_DESTINC_2            (2 << 4)
+# define DMA_CFG1_DESTINC_MINUS_1      (3 << 4)
+
+# define DMA_CFG1_IRQMASK              (1 << 3)
+# define DMA_CFG1_M8                   (1 << 2)
+
+# define DMA_CFG1_PRIORITY_MASK                (3 << 0)
+# define DMA_CFG1_PRIORITY_LOW         (0 << 0)
+# define DMA_CFG1_PRIORITY_NORMAL      (1 << 0)
+# define DMA_CFG1_PRIORITY_HIGH                (2 << 0)
+
+/*
+ * DMAARM - DMA Channel Arm
+ */
+
+sfr at 0xD6 DMAARM;
+
+# define DMAARM_ABORT                  (1 << 7)
+# define DMAARM_DMAARM4                        (1 << 4)
+# define DMAARM_DMAARM3                        (1 << 3)
+# define DMAARM_DMAARM2                        (1 << 2)
+# define DMAARM_DMAARM1                        (1 << 1)
+# define DMAARM_DMAARM0                        (1 << 0)
+
+/*
+ * DMAREQ - DMA Channel Start Request and Status
+ */
+
+sfr at 0xD7 DMAREQ;
+
+# define DMAREQ_DMAREQ4                        (1 << 4)
+# define DMAREQ_DMAREQ3                        (1 << 3)
+# define DMAREQ_DMAREQ2                        (1 << 2)
+# define DMAREQ_DMAREQ1                        (1 << 1)
+# define DMAREQ_DMAREQ0                        (1 << 0)
+
+/*
+ * DMA configuration 0 address
+ */
+
+sfr at 0xD5 DMA0CFGH;
+sfr at 0xD4 DMA0CFGL;
+
+/*
+ * DMA configuration 1-4 address
+ */
+
+sfr at 0xD3 DMA1CFGH;
+sfr at 0xD2 DMA1CFGL;
+
+/*
+ * DMAIRQ - DMA Interrupt Flag
+ */
+
+sfr at 0xD1 DMAIRQ;
+
+# define DMAIRQ_DMAIF4                 (1 << 4)
+# define DMAIRQ_DMAIF3                 (1 << 3)
+# define DMAIRQ_DMAIF2                 (1 << 2)
+# define DMAIRQ_DMAIF1                 (1 << 1)
+# define DMAIRQ_DMAIF0                 (1 << 0)
+
+struct cc_dma_channel {
+       uint8_t src_high;
+       uint8_t src_low;
+       uint8_t dst_high;
+       uint8_t dst_low;
+       uint8_t len_high;
+       uint8_t len_low;
+       uint8_t cfg0;
+       uint8_t cfg1;
+};
+
+/*
+ * ADC Data register, low and high
+ */
+sfr at 0xBA ADCL;
+sfr at 0xBB ADCH;
+__xdata __at (0xDFBA) volatile uint16_t ADCXDATA;
+
+/*
+ * ADC Control Register 1
+ */
+sfr at 0xB4 ADCCON1;
+
+# define ADCCON1_EOC           (1 << 7)        /* conversion complete */
+# define ADCCON1_ST            (1 << 6)        /* start conversion */
+
+# define ADCCON1_STSEL_MASK    (3 << 4)        /* start select */
+# define ADCCON1_STSEL_EXTERNAL        (0 << 4)        /* P2_0 pin triggers */
+# define ADCCON1_STSEL_FULLSPEED (1 << 4)      /* full speed, no waiting */
+# define ADCCON1_STSEL_TIMER1  (2 << 4)        /* timer 1 channel 0 */
+# define ADCCON1_STSEL_START   (3 << 4)        /* set start bit */
+
+# define ADCCON1_RCTRL_MASK    (3 << 2)        /* random number control */
+# define ADCCON1_RCTRL_COMPLETE        (0 << 2)        /* operation completed */
+# define ADCCON1_RCTRL_CLOCK_LFSR (1 << 2)     /* Clock the LFSR once */
+
+/*
+ * ADC Control Register 2
+ */
+sfr at 0xB5 ADCCON2;
+
+# define ADCCON2_SREF_MASK     (3 << 6)        /* reference voltage */
+# define ADCCON2_SREF_1_25V    (0 << 6)        /* internal 1.25V */
+# define ADCCON2_SREF_EXTERNAL (1 << 6)        /* external on AIN7 cc1110 */
+# define ADCCON2_SREF_VDD      (2 << 6)        /* VDD on the AVDD pin */
+# define ADCCON2_SREF_EXTERNAL_DIFF (3 << 6)   /* external on AIN6-7 cc1110 */
+
+# define ADCCON2_SDIV_MASK     (3 << 4)        /* decimation rate */
+# define ADCCON2_SDIV_64       (0 << 4)        /* 7 bits */
+# define ADCCON2_SDIV_128      (1 << 4)        /* 9 bits */
+# define ADCCON2_SDIV_256      (2 << 4)        /* 10 bits */
+# define ADCCON2_SDIV_512      (3 << 4)        /* 12 bits */
+
+# define ADCCON2_SCH_MASK      (0xf << 0)      /* Sequence channel select */
+# define ADCCON2_SCH_SHIFT     0
+# define ADCCON2_SCH_AIN0      (0 << 0)
+# define ADCCON2_SCH_AIN1      (1 << 0)
+# define ADCCON2_SCH_AIN2      (2 << 0)
+# define ADCCON2_SCH_AIN3      (3 << 0)
+# define ADCCON2_SCH_AIN4      (4 << 0)
+# define ADCCON2_SCH_AIN5      (5 << 0)
+# define ADCCON2_SCH_AIN6      (6 << 0)
+# define ADCCON2_SCH_AIN7      (7 << 0)
+# define ADCCON2_SCH_AIN0_AIN1 (8 << 0)
+# define ADCCON2_SCH_AIN2_AIN3 (9 << 0)
+# define ADCCON2_SCH_AIN4_AIN5 (0xa << 0)
+# define ADCCON2_SCH_AIN6_AIN7 (0xb << 0)
+# define ADCCON2_SCH_GND       (0xc << 0)
+# define ADCCON2_SCH_VREF      (0xd << 0)
+# define ADCCON2_SCH_TEMP      (0xe << 0)
+# define ADCCON2_SCH_VDD_3     (0xf << 0)
+
+
+/*
+ * ADC Control Register 3
+ */
+
+sfr at 0xB6 ADCCON3;
+
+# define ADCCON3_EREF_MASK     (3 << 6)        /* extra conversion reference */
+# define ADCCON3_EREF_1_25     (0 << 6)        /* internal 1.25V */
+# define ADCCON3_EREF_EXTERNAL (1 << 6)        /* external AIN7 cc1110 */
+# define ADCCON3_EREF_VDD      (2 << 6)        /* VDD on the AVDD pin */
+# define ADCCON3_EREF_EXTERNAL_DIFF (3 << 6)   /* external AIN6-7 cc1110 */
+# define ADCCON2_EDIV_MASK     (3 << 4)        /* extral decimation */
+# define ADCCON2_EDIV_64       (0 << 4)        /* 7 bits */
+# define ADCCON2_EDIV_128      (1 << 4)        /* 9 bits */
+# define ADCCON2_EDIV_256      (2 << 4)        /* 10 bits */
+# define ADCCON2_EDIV_512      (3 << 4)        /* 12 bits */
+# define ADCCON3_ECH_MASK      (0xf << 0)      /* Sequence channel select */
+# define ADCCON3_ECH_SHIFT     0
+# define ADCCON3_ECH_AIN0      (0 << 0)
+# define ADCCON3_ECH_AIN1      (1 << 0)
+# define ADCCON3_ECH_AIN2      (2 << 0)
+# define ADCCON3_ECH_AIN3      (3 << 0)
+# define ADCCON3_ECH_AIN4      (4 << 0)
+# define ADCCON3_ECH_AIN5      (5 << 0)
+# define ADCCON3_ECH_AIN6      (6 << 0)
+# define ADCCON3_ECH_AIN7      (7 << 0)
+# define ADCCON3_ECH_AIN0_AIN1 (8 << 0)
+# define ADCCON3_ECH_AIN2_AIN3 (9 << 0)
+# define ADCCON3_ECH_AIN4_AIN5 (0xa << 0)
+# define ADCCON3_ECH_AIN6_AIN7 (0xb << 0)
+# define ADCCON3_ECH_GND       (0xc << 0)
+# define ADCCON3_ECH_VREF      (0xd << 0)
+# define ADCCON3_ECH_TEMP      (0xe << 0)
+# define ADCCON3_ECH_VDD_3     (0xf << 0)
+
+sfr at 0xF2 ADCCFG;
+
+#define nop()  _asm nop _endasm;
+
+void
+delay (unsigned char n)
+{
+       unsigned char i = 0;
+       unsigned char j = 0;
+
+       n++;
+       while (--n != 0)
+               while (--i != 0)
+                       while (--j != 0)
+                               nop();
+}
+
+void
+debug_byte(uint8_t byte)
+{
+       uint8_t s;
+
+       for (s = 0; s < 8; s++) {
+               DEBUG = byte & 1;
+               delay(5);
+               byte >>= 1;
+       }
+}
+
+struct cc_dma_channel __xdata dma_config;
+
+#define ADC_LEN        6
+
+/* The DMA engine writes to XDATA in MSB order */
+struct dma_xdata16 {
+       uint8_t high;
+       uint8_t low;
+};
+
+struct dma_xdata16 adc_output[ADC_LEN];
+
+#define DMA_XDATA16(a,n)       ((uint16_t) ((a)[n].high << 8) | (uint16_t) (a[n].low))
+
+#define ADDRH(a)       (((uint16_t) (a)) >> 8)
+#define ADDRL(a)       (((uint16_t) (a)))
+
+void
+adc_init(void)
+{
+       dma_config.cfg0 = (DMA_CFG0_WORDSIZE_16 |
+                          DMA_CFG0_TMODE_REPEATED_SINGLE |
+                          DMA_CFG0_TRIGGER_ADC_CHALL);
+       dma_config.cfg1 = (DMA_CFG1_SRCINC_0 |
+                          DMA_CFG1_DESTINC_1 |
+                          DMA_CFG1_PRIORITY_NORMAL);
+
+       dma_config.src_high = ADDRH(&ADCXDATA);
+       dma_config.src_low = ADDRL(&ADCXDATA);
+       dma_config.dst_high = ADDRH(adc_output);
+       dma_config.dst_low = ADDRL(adc_output);
+       dma_config.len_high = 0;
+       dma_config.len_low = ADC_LEN;
+       DMA0CFGH = ADDRH(&dma_config);
+       DMA0CFGL = ADDRL(&dma_config);
+       ADCCFG = ((1 << 0) |    /* acceleration */
+                 (1 << 1) |    /* pressure */
+                 (1 << 2) |    /* temperature */
+                 (1 << 3) |    /* battery voltage */
+                 (1 << 4) |    /* drogue sense */
+                 (1 << 5));    /* main sense */
+
+       ADCCON1 = (ADCCON1_STSEL_START);        /* ST bit triggers */
+       ADCCON2 = (ADCCON2_SREF_VDD |           /* reference voltage is VDD */
+                  ADCCON2_SDIV_512 |           /* 12 bit ADC results */
+                  ADCCON2_SCH_AIN5);           /* sample all 6 inputs */
+}
+
+void
+adc_run(void)
+{
+       DMAIRQ &= ~1;
+       DMAARM |= 1;
+       ADCCON1 |= ADCCON1_ST;
+       while ((DMAIRQ & 1) == 0)
+               ;
+}
+
+/*
+ * This version uses the USART in UART mode
+ */
+void
+usart_init(void)
+{
+       P1DIR |= (1 << 2);
+       /*
+        * Configure the peripheral pin choices
+        * for both of the serial ports
+        *
+        * Note that telemetrum will use U1CFG_ALT_2
+        * but that overlaps with SPI ALT_2, so until
+        * we can test that this works, we'll set this
+        * to ALT_1
+        */
+       PERCFG = (PERCFG_U1CFG_ALT_2 |
+                 PERCFG_U0CFG_ALT_1);
+
+       /*
+        * Make the UART pins controlled by the UART
+        * hardware
+        */
+       P1SEL |= ((1 << 6) | (1 << 7));
+
+       /*
+        * UART mode with the receiver enabled
+        */
+       U1CSR = (UxCSR_MODE_UART |
+                UxCSR_RE);
+       /*
+        * Pick a 38.4kbaud rate
+        */
+       U1BAUD = 163;
+       U1GCR = 10 << UxGCR_BAUD_E_SHIFT;       /* 38400 */
+//     U1GCR = 3 << UxGCR_BAUD_E_SHIFT;        /* 300 */
+       /*
+        * Reasonable serial parameters
+        */
+       U1UCR = (UxUCR_FLUSH |
+                UxUCR_FLOW_DISABLE |
+                UxUCR_D9_ODD_PARITY |
+                UxUCR_BIT9_8_BITS |
+                UxUCR_PARITY_DISABLE |
+                UxUCR_SPB_2_STOP_BITS |
+                UxUCR_STOP_HIGH |
+                UxUCR_START_LOW);
+}
+
+void
+usart_out_byte(uint8_t byte)
+{
+       U1DBUF = byte;
+       while (!UTX1IF)
+               ;
+       UTX1IF = 0;
+}
+
+void
+usart_out_string(uint8_t *string)
+{
+       uint8_t b;
+
+       while (b = *string++)
+               usart_out_byte(b);
+}
+
+#define NUM_LEN 6
+
+uint8_t __xdata        num_buffer[NUM_LEN];
+uint8_t __xdata * __xdata num_ptr;
+
+void
+usart_out_number(uint16_t v)
+{
+
+       num_ptr = num_buffer + NUM_LEN;
+       *--num_ptr = '\0';
+       do {
+               *--num_ptr = '0' + v % 10;
+               v /= 10;
+       } while (v);
+       while (num_ptr != num_buffer)
+               *--num_ptr = ' ';
+       usart_out_string(num_buffer);
+}
+
+#define ADC(n) DMA_XDATA16(adc_output,n)
+
+main ()
+{
+       P1DIR = 3;
+       CLKCON = 0;
+       while (!(SLEEP & SLEEP_XOSC_STB))
+               ;
+
+       adc_init();
+       P1_0 = 1;
+       usart_init();
+       for (;;) {
+               adc_run();
+               usart_out_string("accel: ");
+               usart_out_number(ADC(0));
+               usart_out_string(" pres: ");
+               usart_out_number(ADC(1));
+               usart_out_string(" temp: ");
+               usart_out_number(ADC(2));
+               usart_out_string(" batt: ");
+               usart_out_number(ADC(3));
+               usart_out_string(" drogue: ");
+               usart_out_number(ADC(4));
+               usart_out_string(" main: ");
+               usart_out_number(ADC(5));
+               usart_out_string("\r\n");
+               delay(10);
+       }
+}
diff --git a/target/adc/Makefile b/target/adc/Makefile
new file mode 100644 (file)
index 0000000..54c1211
--- /dev/null
@@ -0,0 +1,47 @@
+PROG=adc
+CC=sdcc
+NO_OPT=--nogcse --noinvariant --noinduction --nojtbound --noloopreverse \
+       --nolabelopt --nooverlay --peep-asm
+DEBUG=--debug
+
+CFLAGS=--model-large $(DEBUG) --less-pedantic \
+       --no-peep --int-long-reent --float-reent \
+       --data-loc 0x30
+
+LDFLAGS=--out-fmt-ihx
+LDFLAGS_RAM=$(LDFLAGS) --code-loc 0xf000 --xram-loc 0xf800 --xram-size 1024
+
+LDFLAGS_FLASH=$(LDFLAGS) --code-loc 0x0000 --xram-loc 0xf000 --xram-size 1024
+
+SRC=$(PROG).c
+ADB=$(SRC:.c=.adb)
+ASM=$(SRC:.c=.asm)
+LNK=$(SRC:.c=.lnk)
+LST=$(SRC:.c=.lst)
+REL=$(SRC:.c=.rel)
+RST=$(SRC:.c=.rst)
+SYM=$(SRC:.c=.sym)
+
+PROGS=$(PROG)-flash.ihx $(PROG)-ram.ihx
+PCDB=$(PROGS:.ihx=.cdb)
+PLNK=$(PROGS:.ihx=.lnk)
+PMAP=$(PROGS:.ihx=.map)
+PMEM=$(PROGS:.ihx=.mem)
+PAOM=$(PROGS:.ihx=)
+
+%.rel : %.c
+       $(CC) -c $(CFLAGS) -o$*.rel $<
+
+all: $(PROGS)
+
+$(PROG)-ram.ihx: $(REL) Makefile
+       $(CC) $(LDFLAGS_RAM) $(CFLAGS) -o $(PROG)-ram.ihx $(REL)
+       $(CC) $(LDFLAGS_FLASH) $(CFLAGS) -o $(PROG)-flash.ihx $(REL)
+
+$(PROG)-flash.ihx: $(PROG)-ram.ihx
+
+clean:
+       rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM)
+       rm -f $(PROGS) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM)
+
+install:
diff --git a/target/adc/adc.c b/target/adc/adc.c
new file mode 100644 (file)
index 0000000..3a63a2c
--- /dev/null
@@ -0,0 +1,470 @@
+/*
+ * 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 <stdint.h>
+
+/*
+ * Test ADC in DMA mode
+ */
+
+sfr at 0x80 P0;
+sfr at 0x90 P1;
+sfr at 0xA0 P2;
+sfr at 0xC6 CLKCON;
+sfr at 0xbe SLEEP;
+
+# define SLEEP_USB_EN          (1 << 7)
+# define SLEEP_XOSC_STB                (1 << 6)
+
+sfr at 0xF1 PERCFG;
+#define PERCFG_T1CFG_ALT_1     (0 << 6)
+#define PERCFG_T1CFG_ALT_2     (1 << 6)
+
+#define PERCFG_T3CFG_ALT_1     (0 << 5)
+#define PERCFG_T3CFG_ALT_2     (1 << 5)
+
+#define PERCFG_T4CFG_ALT_1     (0 << 4)
+#define PERCFG_T4CFG_ALT_2     (1 << 4)
+
+#define PERCFG_U1CFG_ALT_1     (0 << 1)
+#define PERCFG_U1CFG_ALT_2     (1 << 1)
+
+#define PERCFG_U0CFG_ALT_1     (0 << 0)
+#define PERCFG_U0CFG_ALT_2     (1 << 0)
+
+sfr at 0xF2 ADCCFG;
+sfr at 0xF3 P0SEL;
+sfr at 0xF4 P1SEL;
+sfr at 0xF5 P2SEL;
+
+sfr at 0xFD P0DIR;
+sfr at 0xFE P1DIR;
+sfr at 0xFF P2DIR;
+sfr at 0x8F P0INP;
+sfr at 0xF6 P1INP;
+sfr at 0xF7 P2INP;
+
+sfr at 0x89 P0IFG;
+sfr at 0x8A P1IFG;
+sfr at 0x8B P2IFG;
+
+sbit at 0x90 P1_0;
+sbit at 0x91 P1_1;
+sbit at 0x92 P1_2;
+sbit at 0x93 P1_3;
+sbit at 0x94 P1_4;
+sbit at 0x95 P1_5;
+sbit at 0x96 P1_6;
+sbit at 0x97 P1_7;
+
+/*
+ * UART registers
+ */
+
+sfr at 0x86 U0CSR;
+sfr at 0xF8 U1CSR;
+
+/*
+ * IRCON2
+ */
+sfr at 0xE8 IRCON2;    /* CPU Interrupt Flag 5 */
+
+sbit at 0xE8 USBIF;    /* USB interrupt flag (shared with Port2) */
+sbit at 0xE8 P2IF;     /* Port2 interrupt flag (shared with USB) */
+sbit at 0xE9 UTX0IF;   /* USART0 TX interrupt flag */
+sbit at 0xEA UTX1IF;   /* USART1 TX interrupt flag (shared with I2S TX) */
+sbit at 0xEA I2STXIF;  /* I2S TX interrupt flag (shared with USART1 TX) */
+sbit at 0xEB P1IF;     /* Port1 interrupt flag */
+sbit at 0xEC WDTIF;    /* Watchdog timer interrupt flag */
+
+# define UxCSR_MODE_UART               (1 << 7)
+# define UxCSR_MODE_SPI                        (0 << 7)
+# define UxCSR_RE                      (1 << 6)
+# define UxCSR_SLAVE                   (1 << 5)
+# define UxCSR_MASTER                  (0 << 5)
+# define UxCSR_FE                      (1 << 4)
+# define UxCSR_ERR                     (1 << 3)
+# define UxCSR_RX_BYTE                 (1 << 2)
+# define UxCSR_TX_BYTE                 (1 << 1)
+# define UxCSR_ACTIVE                  (1 << 0)
+
+sfr at 0xc4 U0UCR;
+sfr at 0xfb U1UCR;
+
+# define UxUCR_FLUSH                   (1 << 7)
+# define UxUCR_FLOW_DISABLE            (0 << 6)
+# define UxUCR_FLOW_ENABLE             (1 << 6)
+# define UxUCR_D9_EVEN_PARITY          (0 << 5)
+# define UxUCR_D9_ODD_PARITY           (1 << 5)
+# define UxUCR_BIT9_8_BITS             (0 << 4)
+# define UxUCR_BIT9_9_BITS             (1 << 4)
+# define UxUCR_PARITY_DISABLE          (0 << 3)
+# define UxUCR_PARITY_ENABLE           (1 << 3)
+# define UxUCR_SPB_1_STOP_BIT          (0 << 2)
+# define UxUCR_SPB_2_STOP_BITS         (1 << 2)
+# define UxUCR_STOP_LOW                        (0 << 1)
+# define UxUCR_STOP_HIGH               (1 << 1)
+# define UxUCR_START_LOW               (0 << 0)
+# define UxUCR_START_HIGH              (1 << 0)
+
+sfr at 0xc5 U0GCR;
+sfr at 0xfc U1GCR;
+
+# define UxGCR_CPOL_NEGATIVE           (0 << 7)
+# define UxGCR_CPOL_POSITIVE           (1 << 7)
+# define UxGCR_CPHA_FIRST_EDGE         (0 << 6)
+# define UxGCR_CPHA_SECOND_EDGE                (1 << 6)
+# define UxGCR_ORDER_LSB               (0 << 5)
+# define UxGCR_ORDER_MSB               (1 << 5)
+# define UxGCR_BAUD_E_MASK             (0x1f)
+# define UxGCR_BAUD_E_SHIFT            0
+
+sfr at 0xc1 U0DBUF;
+sfr at 0xf9 U1DBUF;
+sfr at 0xc2 U0BAUD;
+sfr at 0xfa U1BAUD;
+
+#define DEBUG  P1_1
+
+
+# define DMA_LEN_HIGH_VLEN_MASK                (7 << 5)
+# define DMA_LEN_HIGH_VLEN_LEN         (0 << 5)
+# define DMA_LEN_HIGH_VLEN_PLUS_1      (1 << 5)
+# define DMA_LEN_HIGH_VLEN             (2 << 5)
+# define DMA_LEN_HIGH_VLEN_PLUS_2      (3 << 5)
+# define DMA_LEN_HIGH_VLEN_PLUS_3      (4 << 5)
+# define DMA_LEN_HIGH_MASK             (0x1f)
+
+# define DMA_CFG0_WORDSIZE_8           (0 << 7)
+# define DMA_CFG0_WORDSIZE_16          (1 << 7)
+# define DMA_CFG0_TMODE_MASK           (3 << 5)
+# define DMA_CFG0_TMODE_SINGLE         (0 << 5)
+# define DMA_CFG0_TMODE_BLOCK          (1 << 5)
+# define DMA_CFG0_TMODE_REPEATED_SINGLE        (2 << 5)
+# define DMA_CFG0_TMODE_REPEATED_BLOCK (3 << 5)
+
+/*
+ * DMA triggers
+ */
+# define DMA_CFG0_TRIGGER_NONE         0
+# define DMA_CFG0_TRIGGER_PREV         1
+# define DMA_CFG0_TRIGGER_T1_CH0       2
+# define DMA_CFG0_TRIGGER_T1_CH1       3
+# define DMA_CFG0_TRIGGER_T1_CH2       4
+# define DMA_CFG0_TRIGGER_T2_OVFL      6
+# define DMA_CFG0_TRIGGER_T3_CH0       7
+# define DMA_CFG0_TRIGGER_T3_CH1       8
+# define DMA_CFG0_TRIGGER_T4_CH0       9
+# define DMA_CFG0_TRIGGER_T4_CH1       10
+# define DMA_CFG0_TRIGGER_IOC_0                12
+# define DMA_CFG0_TRIGGER_IOC_1                13
+# define DMA_CFG0_TRIGGER_URX0         14
+# define DMA_CFG0_TRIGGER_UTX0         15
+# define DMA_CFG0_TRIGGER_URX1         16
+# define DMA_CFG0_TRIGGER_UTX1         17
+# define DMA_CFG0_TRIGGER_FLASH                18
+# define DMA_CFG0_TRIGGER_RADIO                19
+# define DMA_CFG0_TRIGGER_ADC_CHALL    20
+# define DMA_CFG0_TRIGGER_ADC_CH0      21
+# define DMA_CFG0_TRIGGER_ADC_CH1      22
+# define DMA_CFG0_TRIGGER_ADC_CH2      23
+# define DMA_CFG0_TRIGGER_ADC_CH3      24
+# define DMA_CFG0_TRIGGER_ADC_CH4      25
+# define DMA_CFG0_TRIGGER_ADC_CH5      26
+# define DMA_CFG0_TRIGGER_ADC_CH6      27
+# define DMA_CFG0_TRIGGER_I2SRX                27
+# define DMA_CFG0_TRIGGER_ADC_CH7      28
+# define DMA_CFG0_TRIGGER_I2STX                28
+# define DMA_CFG0_TRIGGER_ENC_DW       29
+# define DMA_CFG0_TRIGGER_DNC_UP       30
+
+# define DMA_CFG1_SRCINC_MASK          (3 << 6)
+# define DMA_CFG1_SRCINC_0             (0 << 6)
+# define DMA_CFG1_SRCINC_1             (1 << 6)
+# define DMA_CFG1_SRCINC_2             (2 << 6)
+# define DMA_CFG1_SRCINC_MINUS_1       (3 << 6)
+
+# define DMA_CFG1_DESTINC_MASK         (3 << 4)
+# define DMA_CFG1_DESTINC_0            (0 << 4)
+# define DMA_CFG1_DESTINC_1            (1 << 4)
+# define DMA_CFG1_DESTINC_2            (2 << 4)
+# define DMA_CFG1_DESTINC_MINUS_1      (3 << 4)
+
+# define DMA_CFG1_IRQMASK              (1 << 3)
+# define DMA_CFG1_M8                   (1 << 2)
+
+# define DMA_CFG1_PRIORITY_MASK                (3 << 0)
+# define DMA_CFG1_PRIORITY_LOW         (0 << 0)
+# define DMA_CFG1_PRIORITY_NORMAL      (1 << 0)
+# define DMA_CFG1_PRIORITY_HIGH                (2 << 0)
+
+/*
+ * DMAARM - DMA Channel Arm
+ */
+
+sfr at 0xD6 DMAARM;
+
+# define DMAARM_ABORT                  (1 << 7)
+# define DMAARM_DMAARM4                        (1 << 4)
+# define DMAARM_DMAARM3                        (1 << 3)
+# define DMAARM_DMAARM2                        (1 << 2)
+# define DMAARM_DMAARM1                        (1 << 1)
+# define DMAARM_DMAARM0                        (1 << 0)
+
+/*
+ * DMAREQ - DMA Channel Start Request and Status
+ */
+
+sfr at 0xD7 DMAREQ;
+
+# define DMAREQ_DMAREQ4                        (1 << 4)
+# define DMAREQ_DMAREQ3                        (1 << 3)
+# define DMAREQ_DMAREQ2                        (1 << 2)
+# define DMAREQ_DMAREQ1                        (1 << 1)
+# define DMAREQ_DMAREQ0                        (1 << 0)
+
+/*
+ * DMA configuration 0 address
+ */
+
+sfr at 0xD5 DMA0CFGH;
+sfr at 0xD4 DMA0CFGL;
+
+/*
+ * DMA configuration 1-4 address
+ */
+
+sfr at 0xD3 DMA1CFGH;
+sfr at 0xD2 DMA1CFGL;
+
+/*
+ * DMAIRQ - DMA Interrupt Flag
+ */
+
+sfr at 0xD1 DMAIRQ;
+
+# define DMAIRQ_DMAIF4                 (1 << 4)
+# define DMAIRQ_DMAIF3                 (1 << 3)
+# define DMAIRQ_DMAIF2                 (1 << 2)
+# define DMAIRQ_DMAIF1                 (1 << 1)
+# define DMAIRQ_DMAIF0                 (1 << 0)
+
+struct cc_dma_channel {
+       uint8_t src_high;
+       uint8_t src_low;
+       uint8_t dst_high;
+       uint8_t dst_low;
+       uint8_t len_high;
+       uint8_t len_low;
+       uint8_t cfg0;
+       uint8_t cfg1;
+};
+
+/*
+ * ADC Data register, low and high
+ */
+sfr at 0xBA ADCL;
+sfr at 0xBB ADCH;
+__xdata __at (0xDFBA) volatile uint16_t ADCXDATA;
+
+/*
+ * ADC Control Register 1
+ */
+sfr at 0xB4 ADCCON1;
+
+# define ADCCON1_EOC           (1 << 7)        /* conversion complete */
+# define ADCCON1_ST            (1 << 6)        /* start conversion */
+
+# define ADCCON1_STSEL_MASK    (3 << 4)        /* start select */
+# define ADCCON1_STSEL_EXTERNAL        (0 << 4)        /* P2_0 pin triggers */
+# define ADCCON1_STSEL_FULLSPEED (1 << 4)      /* full speed, no waiting */
+# define ADCCON1_STSEL_TIMER1  (2 << 4)        /* timer 1 channel 0 */
+# define ADCCON1_STSEL_START   (3 << 4)        /* set start bit */
+
+# define ADCCON1_RCTRL_MASK    (3 << 2)        /* random number control */
+# define ADCCON1_RCTRL_COMPLETE        (0 << 2)        /* operation completed */
+# define ADCCON1_RCTRL_CLOCK_LFSR (1 << 2)     /* Clock the LFSR once */
+
+/*
+ * ADC Control Register 2
+ */
+sfr at 0xB5 ADCCON2;
+
+# define ADCCON2_SREF_MASK     (3 << 6)        /* reference voltage */
+# define ADCCON2_SREF_1_25V    (0 << 6)        /* internal 1.25V */
+# define ADCCON2_SREF_EXTERNAL (1 << 6)        /* external on AIN7 cc1110 */
+# define ADCCON2_SREF_VDD      (2 << 6)        /* VDD on the AVDD pin */
+# define ADCCON2_SREF_EXTERNAL_DIFF (3 << 6)   /* external on AIN6-7 cc1110 */
+
+# define ADCCON2_SDIV_MASK     (3 << 4)        /* decimation rate */
+# define ADCCON2_SDIV_64       (0 << 4)        /* 7 bits */
+# define ADCCON2_SDIV_128      (1 << 4)        /* 9 bits */
+# define ADCCON2_SDIV_256      (2 << 4)        /* 10 bits */
+# define ADCCON2_SDIV_512      (3 << 4)        /* 12 bits */
+
+# define ADCCON2_SCH_MASK      (0xf << 0)      /* Sequence channel select */
+# define ADCCON2_SCH_SHIFT     0
+# define ADCCON2_SCH_AIN0      (0 << 0)
+# define ADCCON2_SCH_AIN1      (1 << 0)
+# define ADCCON2_SCH_AIN2      (2 << 0)
+# define ADCCON2_SCH_AIN3      (3 << 0)
+# define ADCCON2_SCH_AIN4      (4 << 0)
+# define ADCCON2_SCH_AIN5      (5 << 0)
+# define ADCCON2_SCH_AIN6      (6 << 0)
+# define ADCCON2_SCH_AIN7      (7 << 0)
+# define ADCCON2_SCH_AIN0_AIN1 (8 << 0)
+# define ADCCON2_SCH_AIN2_AIN3 (9 << 0)
+# define ADCCON2_SCH_AIN4_AIN5 (0xa << 0)
+# define ADCCON2_SCH_AIN6_AIN7 (0xb << 0)
+# define ADCCON2_SCH_GND       (0xc << 0)
+# define ADCCON2_SCH_VREF      (0xd << 0)
+# define ADCCON2_SCH_TEMP      (0xe << 0)
+# define ADCCON2_SCH_VDD_3     (0xf << 0)
+
+
+/*
+ * ADC Control Register 3
+ */
+
+sfr at 0xB6 ADCCON3;
+
+# define ADCCON3_EREF_MASK     (3 << 6)        /* extra conversion reference */
+# define ADCCON3_EREF_1_25     (0 << 6)        /* internal 1.25V */
+# define ADCCON3_EREF_EXTERNAL (1 << 6)        /* external AIN7 cc1110 */
+# define ADCCON3_EREF_VDD      (2 << 6)        /* VDD on the AVDD pin */
+# define ADCCON3_EREF_EXTERNAL_DIFF (3 << 6)   /* external AIN6-7 cc1110 */
+# define ADCCON2_EDIV_MASK     (3 << 4)        /* extral decimation */
+# define ADCCON2_EDIV_64       (0 << 4)        /* 7 bits */
+# define ADCCON2_EDIV_128      (1 << 4)        /* 9 bits */
+# define ADCCON2_EDIV_256      (2 << 4)        /* 10 bits */
+# define ADCCON2_EDIV_512      (3 << 4)        /* 12 bits */
+# define ADCCON3_ECH_MASK      (0xf << 0)      /* Sequence channel select */
+# define ADCCON3_ECH_SHIFT     0
+# define ADCCON3_ECH_AIN0      (0 << 0)
+# define ADCCON3_ECH_AIN1      (1 << 0)
+# define ADCCON3_ECH_AIN2      (2 << 0)
+# define ADCCON3_ECH_AIN3      (3 << 0)
+# define ADCCON3_ECH_AIN4      (4 << 0)
+# define ADCCON3_ECH_AIN5      (5 << 0)
+# define ADCCON3_ECH_AIN6      (6 << 0)
+# define ADCCON3_ECH_AIN7      (7 << 0)
+# define ADCCON3_ECH_AIN0_AIN1 (8 << 0)
+# define ADCCON3_ECH_AIN2_AIN3 (9 << 0)
+# define ADCCON3_ECH_AIN4_AIN5 (0xa << 0)
+# define ADCCON3_ECH_AIN6_AIN7 (0xb << 0)
+# define ADCCON3_ECH_GND       (0xc << 0)
+# define ADCCON3_ECH_VREF      (0xd << 0)
+# define ADCCON3_ECH_TEMP      (0xe << 0)
+# define ADCCON3_ECH_VDD_3     (0xf << 0)
+
+sfr at 0xF2 ADCCFG;
+
+#define nop()  _asm nop _endasm;
+
+void
+delay (unsigned char n)
+{
+       unsigned char i = 0;
+       unsigned char j = 0;
+
+       n++;
+       while (--n != 0)
+               while (--i != 0)
+                       while (--j != 0)
+                               nop();
+}
+
+void
+debug_byte(uint8_t byte)
+{
+       uint8_t s;
+
+       for (s = 0; s < 8; s++) {
+               DEBUG = byte & 1;
+               delay(5);
+               byte >>= 1;
+       }
+}
+
+struct cc_dma_channel __xdata dma_config;
+
+#define ADC_LEN        6
+
+uint16_t __xdata adc_output[ADC_LEN];
+
+#define ADDRH(a)       (((uint16_t) (a)) >> 8)
+#define ADDRL(a)       (((uint16_t) (a)))
+
+void
+adc_init(void)
+{
+       dma_config.cfg0 = (DMA_CFG0_WORDSIZE_16 |
+                          DMA_CFG0_TMODE_REPEATED_SINGLE |
+                          DMA_CFG0_TRIGGER_ADC_CHALL);
+       dma_config.cfg1 = (DMA_CFG1_SRCINC_0 |
+                          DMA_CFG1_DESTINC_1 |
+                          DMA_CFG1_PRIORITY_NORMAL);
+
+       dma_config.src_high = ADDRH(&ADCXDATA);
+       dma_config.src_low = ADDRL(&ADCXDATA);
+       dma_config.dst_high = ADDRH(adc_output);
+       dma_config.dst_low = ADDRL(adc_output);
+       dma_config.len_high = 0;
+       dma_config.len_low = ADC_LEN;
+       DMA0CFGH = ADDRH(&dma_config);
+       DMA0CFGL = ADDRL(&dma_config);
+       ADCCFG = ((1 << 0) |    /* acceleration */
+                 (1 << 1) |    /* pressure */
+                 (1 << 2) |    /* temperature */
+                 (1 << 3) |    /* battery voltage */
+                 (1 << 4) |    /* drogue sense */
+                 (1 << 5));    /* main sense */
+
+       ADCCON1 = (ADCCON1_STSEL_START);        /* ST bit triggers */
+       ADCCON2 = (ADCCON2_SREF_VDD |           /* reference voltage is VDD */
+                  ADCCON2_SDIV_512 |           /* 12 bit ADC results */
+                  ADCCON2_SCH_AIN5);           /* sample all 6 inputs */
+}
+
+void
+adc_run(void)
+{
+       DMAIRQ &= ~1;
+       DMAARM |= 1;
+       ADCCON1 |= ADCCON1_ST;
+       while ((DMAIRQ & 1) == 0)
+               ;
+}
+
+main ()
+{
+       int i;
+       P1DIR |= 2;
+       CLKCON = 0;
+       while (!(SLEEP & SLEEP_XOSC_STB))
+               ;
+       while (P1 & 0x4)
+               ;
+
+       adc_init();
+       for (;;) {
+               adc_run();
+               for (i = 0; i < ADC_LEN; i++)
+                       debug_byte(adc_output[i]);
+       }
+}
diff --git a/target/beep-timer/Makefile b/target/beep-timer/Makefile
new file mode 100644 (file)
index 0000000..008adbd
--- /dev/null
@@ -0,0 +1,47 @@
+PROG=beep_timer
+CC=sdcc
+NO_OPT=--nogcse --noinvariant --noinduction --nojtbound --noloopreverse \
+       --nolabelopt --nooverlay --peep-asm
+DEBUG=--debug
+
+CFLAGS=--model-large $(DEBUG) --less-pedantic \
+       --no-peep --int-long-reent --float-reent \
+       --data-loc 0x30
+
+LDFLAGS=--out-fmt-ihx
+LDFLAGS_RAM=$(LDFLAGS) --code-loc 0xf000 --xram-loc 0xf400 --xram-size 1024
+
+LDFLAGS_FLASH=$(LDFLAGS) --code-loc 0x0000 --xram-loc 0xf000 --xram-size 1024
+
+SRC=$(PROG).c
+ADB=$(SRC:.c=.adb)
+ASM=$(SRC:.c=.asm)
+LNK=$(SRC:.c=.lnk)
+LST=$(SRC:.c=.lst)
+REL=$(SRC:.c=.rel)
+RST=$(SRC:.c=.rst)
+SYM=$(SRC:.c=.sym)
+
+PROGS=$(PROG)-flash.ihx $(PROG)-ram.ihx
+PCDB=$(PROGS:.ihx=.cdb)
+PLNK=$(PROGS:.ihx=.lnk)
+PMAP=$(PROGS:.ihx=.map)
+PMEM=$(PROGS:.ihx=.mem)
+PAOM=$(PROGS:.ihx=)
+
+%.rel : %.c
+       $(CC) -c $(CFLAGS) -o$*.rel $<
+
+all: $(PROGS)
+
+$(PROG)-ram.ihx: $(REL) Makefile
+       $(CC) $(LDFLAGS_RAM) $(CFLAGS) -o $(PROG)-ram.ihx $(REL)
+       $(CC) $(LDFLAGS_FLASH) $(CFLAGS) -o $(PROG)-flash.ihx $(REL)
+
+$(PROG)-flash.ihx: $(PROG)-ram.ihx
+
+clean:
+       rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM)
+       rm -f $(PROGS) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM)
+
+install:
diff --git a/target/beep-timer/beep_timer.c b/target/beep-timer/beep_timer.c
new file mode 100644 (file)
index 0000000..b3fa875
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * 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.
+ */
+
+sfr at 0x80 P0;
+sfr at 0x90 P1;
+sfr at 0xA0 P2;
+sfr at 0xC6 CLKCON;
+sfr at 0xbe SLEEP;
+
+# define SLEEP_USB_EN          (1 << 7)
+# define SLEEP_XOSC_STB                (1 << 6)
+
+sbit at 0x90 P1_0;
+sbit at 0x91 P1_1;
+sbit at 0x92 P1_2;
+sbit at 0x93 P1_3;
+sbit at 0x94 P1_4;
+sbit at 0x95 P1_5;
+sbit at 0x96 P1_6;
+sbit at 0x97 P1_7;
+
+sfr at 0xF1 PERCFG;
+sfr at 0xF2 ADCCFG;
+sfr at 0xF3 P0SEL;
+sfr at 0xF4 P1SEL;
+sfr at 0xF5 P2SEL;
+
+#define P2SEL_PRI3P1_USART0            (0 << 6)
+#define P2SEL_PRI3P1_USART1            (1 << 6)
+#define P2SEL_PRI2P1_USART1            (0 << 5)
+#define P2SEL_PRI2P1_TIMER3            (1 << 5)
+#define P2SEL_PRI1P1_TIMER1            (0 << 4)
+#define P2SEL_PRI1P1_TIMER4            (1 << 4)
+#define P2SEL_PRI0P1_USART0            (0 << 3)
+#define P2SEL_PRI0P1_TIMER1            (1 << 3)
+#define P2SEL_SELP2_4_GPIO             (0 << 2)
+#define P2SEL_SELP2_4_PERIPHERAL       (1 << 2)
+#define P2SEL_SELP2_3_GPIO             (0 << 1)
+#define P2SEL_SELP2_3_PERIPHERAL       (1 << 1)
+#define P2SEL_SELP2_0_GPIO             (0 << 0)
+#define P2SEL_SELP2_0_PERIPHERAL       (1 << 0)
+
+sfr at 0xFD P0DIR;
+sfr at 0xFE P1DIR;
+sfr at 0xFF P2DIR;
+sfr at 0x8F P0INP;
+sfr at 0xF6 P1INP;
+sfr at 0xF7 P2INP;
+
+sfr at 0x89 P0IFG;
+sfr at 0x8A P1IFG;
+sfr at 0x8B P2IFG;
+
+sfr at 0xF1 PERCFG;
+#define PERCFG_T1CFG_ALT_1     (0 << 6)
+#define PERCFG_T1CFG_ALT_2     (1 << 6)
+
+#define PERCFG_T3CFG_ALT_1     (0 << 5)
+#define PERCFG_T3CFG_ALT_2     (1 << 5)
+
+#define PERCFG_T4CFG_ALT_1     (0 << 4)
+#define PERCFG_T4CFG_ALT_2     (1 << 4)
+
+#define PERCFG_U1CFG_ALT_1     (0 << 1)
+#define PERCFG_U1CFG_ALT_2     (1 << 1)
+
+#define PERCFG_U0CFG_ALT_1     (0 << 0)
+#define PERCFG_U0CFG_ALT_2     (1 << 0)
+
+/* Timer count */
+sfr at 0xCA T3CNT;
+sfr at 0xEA T4CNT;
+
+/* Timer control */
+
+sfr at 0xCB T3CTL;
+sfr at 0xEB T4CTL;
+
+#define TxCTL_DIV_1            (0 << 5)
+#define TxCTL_DIV_2            (1 << 5)
+#define TxCTL_DIV_4            (2 << 5)
+#define TxCTL_DIV_8            (3 << 5)
+#define TxCTL_DIV_16           (4 << 5)
+#define TxCTL_DIV_32           (5 << 5)
+#define TxCTL_DIV_64           (6 << 5)
+#define TxCTL_DIV_128          (7 << 5)
+#define TxCTL_START            (1 << 4)
+#define TxCTL_OVFIM            (1 << 3)
+#define TxCTL_CLR              (1 << 2)
+#define TxCTL_MODE_FREE                (0 << 0)
+#define TxCTL_MODE_DOWN                (1 << 0)
+#define TxCTL_MODE_MODULO      (2 << 0)
+#define TxCTL_MODE_UP_DOWN     (3 << 0)
+
+/* Timer 4 channel 0 compare control */
+
+sfr at 0xCC T3CCTL0;
+sfr at 0xCE T3CCTL1;
+sfr at 0xEC T4CCTL0;
+sfr at 0xEE T4CCTL1;
+
+#define TxCCTLy_IM                     (1 << 6)
+#define TxCCTLy_CMP_SET                        (0 << 3)
+#define TxCCTLy_CMP_CLEAR              (1 << 3)
+#define TxCCTLy_CMP_TOGGLE             (2 << 3)
+#define TxCCTLy_CMP_SET_UP_CLEAR_DOWN  (3 << 3)
+#define TxCCTLy_CMP_CLEAR_UP_SET_DOWN  (4 << 3)
+#define TxCCTLy_CMP_SET_CLEAR_FF       (5 << 3)
+#define TxCCTLy_CMP_CLEAR_SET_00       (6 << 3)
+#define TxCCTLy_CMP_MODE_ENABLE                (1 << 2)
+
+/* Timer compare value */
+sfr at 0xCD T3CC0;
+sfr at 0xCF T3CC1;
+sfr at 0xED T4CC0;
+sfr at 0xEF T4CC1;
+
+#define nop()  _asm nop _endasm;
+
+void
+delay (unsigned char n)
+{
+       unsigned char i = 0, j = 0;
+
+       n <<= 1;
+       while (--n != 0)
+               while (--j != 0)
+                       while (--i != 0)
+                               nop();
+}
+
+void
+dit() {
+       T4CTL |= TxCTL_START;
+       delay(1);
+       T4CTL &= ~TxCTL_START;
+       delay(1);
+}
+
+void
+dah () {
+       T4CTL |= TxCTL_START;
+       delay(3);
+       T4CTL &= ~TxCTL_START;
+       delay(1);
+}
+
+void
+charspace () {
+       delay(2);
+}
+
+void
+wordspace () {
+       delay(8);
+}
+
+#define _ dit();
+#define ___ dah();
+#define C charspace();
+#define W wordspace();
+
+main ()
+{
+       CLKCON = 0;
+       while (!(SLEEP & SLEEP_XOSC_STB))
+               ;
+
+       /* Use timer 4 alternate config 2 */
+       PERCFG = PERCFG_T4CFG_ALT_2;
+       /* Use P2_4 for timer 4 output */
+       P2SEL = P2SEL_SELP2_0_PERIPHERAL;
+
+       T4CCTL0 = TxCCTLy_CMP_TOGGLE|TxCCTLy_CMP_MODE_ENABLE;
+       T4CC0 = 125;
+       T4CTL = TxCTL_DIV_32 | TxCTL_MODE_MODULO;
+
+       for (;;) {
+               ___ _ ___ _ C ___ ___ _ ___ W   /* cq */
+               ___ _ _ C _ W                   /* de */
+               ___ _ ___ C ___ _ _ C           /* kd */
+               ___ ___ _ _ _ C _ _ _ C         /* 7s */
+               ___ ___ _ ___ C ___ ___ _ W     /* qg */
+               if (T4CC0 == 94)
+                       T4CC0 = 125;
+               else
+                       T4CC0 = 94;
+       }
+}
diff --git a/target/beep/Makefile b/target/beep/Makefile
new file mode 100644 (file)
index 0000000..8f600b4
--- /dev/null
@@ -0,0 +1,46 @@
+CC=sdcc
+NO_OPT=--nogcse --noinvariant --noinduction --nojtbound --noloopreverse \
+       --nolabelopt --nooverlay --peep-asm
+DEBUG=--debug
+
+CFLAGS=--model-large $(DEBUG) --less-pedantic \
+       --no-peep --int-long-reent --float-reent \
+       --data-loc 0x30
+
+LDFLAGS=--out-fmt-ihx
+LDFLAGS_RAM=$(LDFLAGS) --code-loc 0xf000 --xram-loc 0xf400 --xram-size 1024
+
+LDFLAGS_FLASH=$(LDFLAGS) --code-loc 0x0000 --xram-loc 0xf000 --xram-size 1024
+
+SRC=beep.c
+ADB=$(SRC:.c=.adb)
+ASM=$(SRC:.c=.asm)
+LNK=$(SRC:.c=.lnk)
+LST=$(SRC:.c=.lst)
+REL=$(SRC:.c=.rel)
+RST=$(SRC:.c=.rst)
+SYM=$(SRC:.c=.sym)
+
+PROGS=beep-flash.ihx beep-ram.ihx
+PCDB=$(PROGS:.ihx=.cdb)
+PLNK=$(PROGS:.ihx=.lnk)
+PMAP=$(PROGS:.ihx=.map)
+PMEM=$(PROGS:.ihx=.mem)
+PAOM=$(PROGS:.ihx=)
+
+%.rel : %.c
+       $(CC) -c $(CFLAGS) -o$*.rel $<
+
+all: $(PROGS)
+
+beep-ram.ihx: $(REL) Makefile
+       $(CC) $(LDFLAGS_RAM) $(CFLAGS) -o beep-ram.ihx $(REL)
+       $(CC) $(LDFLAGS_FLASH) $(CFLAGS) -o beep-flash.ihx $(REL)
+
+beep-flash.ihx: beep-ram.ihx
+
+clean:
+       rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM)
+       rm -f $(PROGS) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM)
+
+install:
diff --git a/target/beep/beep.c b/target/beep/beep.c
new file mode 100644 (file)
index 0000000..09c915b
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+
+sfr at 0x80 P0;
+sfr at 0x90 P1;
+sfr at 0xA0 P2;
+sfr at 0xC6 CLKCON;
+
+sfr at 0xF1 PERCFG;
+sfr at 0xF2 ADCCFG;
+sfr at 0xF3 P0SEL;
+sfr at 0xF4 P1SEL;
+sfr at 0xF5 P2SEL;
+
+sfr at 0xFD P0DIR;
+sfr at 0xFE P1DIR;
+sfr at 0xFF P2DIR;
+sfr at 0x8F P0INP;
+sfr at 0xF6 P1INP;
+sfr at 0xF7 P2INP;
+
+sfr at 0x89 P0IFG;
+sfr at 0x8A P1IFG;
+sfr at 0x8B P2IFG;
+
+#define nop()  _asm nop _endasm;
+
+void
+delay (unsigned char n)
+{
+       unsigned char i = 0;
+
+       n <<= 1;
+       while (--n != 0) {
+               i = 211;
+               while (--i != 0)
+                       nop();
+       }
+}
+
+void
+tone (unsigned char n, unsigned char m)
+{
+       unsigned char   i = 0;
+       while (--m != 0) {
+               while (--i != 0) {
+                       P2 = 0xff;
+                       delay(n);
+                       P2 = 0xfe;
+                       delay(n);
+               }
+       }
+}
+
+void
+high() {
+       tone(1, 2);
+}
+
+void
+low() {
+       tone(2, 1);
+}
+
+main ()
+{
+       CLKCON = 0;
+       /* Set P2_0 to output */
+       P2DIR = 0x01;
+       P1INP = 0x00;
+       P2INP = 0x00;
+       for (;;) {
+               high();
+/*             low();          */
+       }
+}
diff --git a/target/blink/.gitignore b/target/blink/.gitignore
new file mode 100644 (file)
index 0000000..40f72de
--- /dev/null
@@ -0,0 +1,13 @@
+*.ihx
+*.adb
+*.asm
+*.cdb
+*.lnk
+*.lst
+*.map
+*.mem
+*.rel
+*.rst
+*.sym
+blink-flash
+blink-ram
diff --git a/target/blink/Makefile b/target/blink/Makefile
new file mode 100644 (file)
index 0000000..d0112e6
--- /dev/null
@@ -0,0 +1,46 @@
+CC=sdcc
+NO_OPT=--nogcse --noinvariant --noinduction --nojtbound --noloopreverse \
+       --nolabelopt --nooverlay --peep-asm
+DEBUG=--debug
+
+CFLAGS=--model-large $(DEBUG) --less-pedantic \
+       --no-peep --int-long-reent --float-reent \
+       --data-loc 0x30
+
+LDFLAGS=--out-fmt-ihx
+LDFLAGS_RAM=$(LDFLAGS) --code-loc 0xf000 --xram-loc 0xf400 --xram-size 1024
+
+LDFLAGS_FLASH=$(LDFLAGS) --code-loc 0x0000 --xram-loc 0xf000 --xram-size 1024
+
+SRC=blink.c
+ADB=$(SRC:.c=.adb)
+ASM=$(SRC:.c=.asm)
+LNK=$(SRC:.c=.lnk)
+LST=$(SRC:.c=.lst)
+REL=$(SRC:.c=.rel)
+RST=$(SRC:.c=.rst)
+SYM=$(SRC:.c=.sym)
+
+PROGS=blink-flash.ihx blink-ram.ihx
+PCDB=$(PROGS:.ihx=.cdb)
+PLNK=$(PROGS:.ihx=.lnk)
+PMAP=$(PROGS:.ihx=.map)
+PMEM=$(PROGS:.ihx=.mem)
+PAOM=$(PROGS:.ihx=)
+
+%.rel : %.c
+       $(CC) -c $(CFLAGS) -o$*.rel $<
+
+all: $(PROGS)
+
+blink-ram.ihx: $(REL) Makefile
+       $(CC) $(LDFLAGS_RAM) $(CFLAGS) -o blink-ram.ihx $(REL)
+       $(CC) $(LDFLAGS_FLASH) $(CFLAGS) -o blink-flash.ihx $(REL)
+
+blink-flash.ihx: blink-ram.ihx
+
+clean:
+       rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM)
+       rm -f $(PROGS) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM)
+
+install:
diff --git a/target/blink/blink.c b/target/blink/blink.c
new file mode 100644 (file)
index 0000000..907c82b
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * 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.
+ */
+
+sfr at 0x80 P0;
+sfr at 0x90 P1;
+sfr at 0xA0 P2;
+sfr at 0xC6 CLKCON;
+
+sfr at 0xF1 PERCFG;
+sfr at 0xF2 ADCCFG;
+sfr at 0xF3 P0SEL;
+sfr at 0xF4 P1SEL;
+sfr at 0xF5 P2SEL;
+
+sfr at 0xFD P0DIR;
+sfr at 0xFE P1DIR;
+sfr at 0xFF P2DIR;
+sfr at 0x8F P0INP;
+sfr at 0xF6 P1INP;
+sfr at 0xF7 P2INP;
+
+sfr at 0x89 P0IFG;
+sfr at 0x8A P1IFG;
+sfr at 0x8B P2IFG;
+
+#define nop()  _asm nop _endasm;
+
+void
+delay (unsigned char n)
+{
+       unsigned char i = 0, j = 0;
+
+       n <<= 1;
+       while (--n != 0)
+               while (--j != 0)
+                       while (--i != 0)
+                               nop();
+}
+
+void
+dit() {
+       P1 = 0xff;
+       delay(1);
+       P1 = 0xfd;
+       delay(1);
+}
+
+void
+dah () {
+       P1 = 0xff;
+       delay(3);
+       P1 = 0xfd;
+       delay(1);
+}
+
+void
+charspace () {
+       delay(2);
+}
+
+void
+wordspace () {
+       delay(8);
+}
+
+#define _ dit();
+#define ___ dah();
+#define C charspace();
+#define W wordspace();
+
+main ()
+{
+       CLKCON = 0;
+       /* Set p1_1 to output */
+       P1DIR = 0x02;
+       P1INP = 0x00;
+       P2INP = 0x00;
+       for (;;) {
+               ___ _ ___ _ C ___ ___ _ ___ W   /* cq */
+               ___ _ _ C _ W                   /* de */
+               ___ _ ___ C ___ _ _ C           /* kd */
+               ___ ___ _ _ _ C _ _ _ C         /* 7s */
+               ___ ___ _ ___ C ___ ___ _ W     /* qg */
+       }
+}
diff --git a/target/dma/Makefile b/target/dma/Makefile
new file mode 100644 (file)
index 0000000..9cb3e32
--- /dev/null
@@ -0,0 +1,46 @@
+CC=sdcc
+NO_OPT=--nogcse --noinvariant --noinduction --nojtbound --noloopreverse \
+       --nolabelopt --nooverlay --peep-asm
+DEBUG=--debug
+
+CFLAGS=--model-large $(DEBUG) --less-pedantic \
+       --no-peep --int-long-reent --float-reent \
+       --data-loc 0x30
+
+LDFLAGS=--out-fmt-ihx
+LDFLAGS_RAM=$(LDFLAGS) --code-loc 0xf000 --xram-loc 0xf800 --xram-size 1024
+
+LDFLAGS_FLASH=$(LDFLAGS) --code-loc 0x0000 --xram-loc 0xf000 --xram-size 1024
+
+SRC=dma.c
+ADB=$(SRC:.c=.adb)
+ASM=$(SRC:.c=.asm)
+LNK=$(SRC:.c=.lnk)
+LST=$(SRC:.c=.lst)
+REL=$(SRC:.c=.rel)
+RST=$(SRC:.c=.rst)
+SYM=$(SRC:.c=.sym)
+
+PROGS=dma-flash.ihx dma-ram.ihx
+PCDB=$(PROGS:.ihx=.cdb)
+PLNK=$(PROGS:.ihx=.lnk)
+PMAP=$(PROGS:.ihx=.map)
+PMEM=$(PROGS:.ihx=.mem)
+PAOM=$(PROGS:.ihx=)
+
+%.rel : %.c
+       $(CC) -c $(CFLAGS) -o$*.rel $<
+
+all: $(PROGS)
+
+dma-ram.ihx: $(REL) Makefile
+       $(CC) $(LDFLAGS_RAM) $(CFLAGS) -o dma-ram.ihx $(REL)
+       $(CC) $(LDFLAGS_FLASH) $(CFLAGS) -o dma-flash.ihx $(REL)
+
+dma-flash.ihx: dma-ram.ihx
+
+clean:
+       rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM)
+       rm -f $(PROGS) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM)
+
+install:
diff --git a/target/dma/dma.c b/target/dma/dma.c
new file mode 100644 (file)
index 0000000..1762b65
--- /dev/null
@@ -0,0 +1,361 @@
+/*
+ * 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 <stdint.h>
+
+/*
+ * Test DMA
+ */
+
+sfr at 0x80 P0;
+sfr at 0x90 P1;
+sfr at 0xA0 P2;
+sfr at 0xC6 CLKCON;
+sfr at 0xbe SLEEP;
+
+# define SLEEP_USB_EN          (1 << 7)
+# define SLEEP_XOSC_STB                (1 << 6)
+
+sfr at 0xF1 PERCFG;
+#define PERCFG_T1CFG_ALT_1     (0 << 6)
+#define PERCFG_T1CFG_ALT_2     (1 << 6)
+
+#define PERCFG_T3CFG_ALT_1     (0 << 5)
+#define PERCFG_T3CFG_ALT_2     (1 << 5)
+
+#define PERCFG_T4CFG_ALT_1     (0 << 4)
+#define PERCFG_T4CFG_ALT_2     (1 << 4)
+
+#define PERCFG_U1CFG_ALT_1     (0 << 1)
+#define PERCFG_U1CFG_ALT_2     (1 << 1)
+
+#define PERCFG_U0CFG_ALT_1     (0 << 0)
+#define PERCFG_U0CFG_ALT_2     (1 << 0)
+
+sfr at 0xF2 ADCCFG;
+sfr at 0xF3 P0SEL;
+sfr at 0xF4 P1SEL;
+sfr at 0xF5 P2SEL;
+
+sfr at 0xFD P0DIR;
+sfr at 0xFE P1DIR;
+sfr at 0xFF P2DIR;
+sfr at 0x8F P0INP;
+sfr at 0xF6 P1INP;
+sfr at 0xF7 P2INP;
+
+sfr at 0x89 P0IFG;
+sfr at 0x8A P1IFG;
+sfr at 0x8B P2IFG;
+
+sbit at 0x90 P1_0;
+sbit at 0x91 P1_1;
+sbit at 0x92 P1_2;
+sbit at 0x93 P1_3;
+sbit at 0x94 P1_4;
+sbit at 0x95 P1_5;
+sbit at 0x96 P1_6;
+sbit at 0x97 P1_7;
+
+/*
+ * UART registers
+ */
+
+sfr at 0x86 U0CSR;
+sfr at 0xF8 U1CSR;
+
+/*
+ * IRCON2
+ */
+sfr at 0xE8 IRCON2;    /* CPU Interrupt Flag 5 */
+
+sbit at 0xE8 USBIF;    /* USB interrupt flag (shared with Port2) */
+sbit at 0xE8 P2IF;     /* Port2 interrupt flag (shared with USB) */
+sbit at 0xE9 UTX0IF;   /* USART0 TX interrupt flag */
+sbit at 0xEA UTX1IF;   /* USART1 TX interrupt flag (shared with I2S TX) */
+sbit at 0xEA I2STXIF;  /* I2S TX interrupt flag (shared with USART1 TX) */
+sbit at 0xEB P1IF;     /* Port1 interrupt flag */
+sbit at 0xEC WDTIF;    /* Watchdog timer interrupt flag */
+
+# define UxCSR_MODE_UART               (1 << 7)
+# define UxCSR_MODE_SPI                        (0 << 7)
+# define UxCSR_RE                      (1 << 6)
+# define UxCSR_SLAVE                   (1 << 5)
+# define UxCSR_MASTER                  (0 << 5)
+# define UxCSR_FE                      (1 << 4)
+# define UxCSR_ERR                     (1 << 3)
+# define UxCSR_RX_BYTE                 (1 << 2)
+# define UxCSR_TX_BYTE                 (1 << 1)
+# define UxCSR_ACTIVE                  (1 << 0)
+
+sfr at 0xc4 U0UCR;
+sfr at 0xfb U1UCR;
+
+# define UxUCR_FLUSH                   (1 << 7)
+# define UxUCR_FLOW_DISABLE            (0 << 6)
+# define UxUCR_FLOW_ENABLE             (1 << 6)
+# define UxUCR_D9_EVEN_PARITY          (0 << 5)
+# define UxUCR_D9_ODD_PARITY           (1 << 5)
+# define UxUCR_BIT9_8_BITS             (0 << 4)
+# define UxUCR_BIT9_9_BITS             (1 << 4)
+# define UxUCR_PARITY_DISABLE          (0 << 3)
+# define UxUCR_PARITY_ENABLE           (1 << 3)
+# define UxUCR_SPB_1_STOP_BIT          (0 << 2)
+# define UxUCR_SPB_2_STOP_BITS         (1 << 2)
+# define UxUCR_STOP_LOW                        (0 << 1)
+# define UxUCR_STOP_HIGH               (1 << 1)
+# define UxUCR_START_LOW               (0 << 0)
+# define UxUCR_START_HIGH              (1 << 0)
+
+sfr at 0xc5 U0GCR;
+sfr at 0xfc U1GCR;
+
+# define UxGCR_CPOL_NEGATIVE           (0 << 7)
+# define UxGCR_CPOL_POSITIVE           (1 << 7)
+# define UxGCR_CPHA_FIRST_EDGE         (0 << 6)
+# define UxGCR_CPHA_SECOND_EDGE                (1 << 6)
+# define UxGCR_ORDER_LSB               (0 << 5)
+# define UxGCR_ORDER_MSB               (1 << 5)
+# define UxGCR_BAUD_E_MASK             (0x1f)
+# define UxGCR_BAUD_E_SHIFT            0
+
+sfr at 0xc1 U0DBUF;
+sfr at 0xf9 U1DBUF;
+sfr at 0xc2 U0BAUD;
+sfr at 0xfa U1BAUD;
+
+#define DEBUG  P1_1
+
+
+# define DMA_LEN_HIGH_VLEN_MASK                (7 << 5)
+# define DMA_LEN_HIGH_VLEN_LEN         (0 << 5)
+# define DMA_LEN_HIGH_VLEN_PLUS_1      (1 << 5)
+# define DMA_LEN_HIGH_VLEN             (2 << 5)
+# define DMA_LEN_HIGH_VLEN_PLUS_2      (3 << 5)
+# define DMA_LEN_HIGH_VLEN_PLUS_3      (4 << 5)
+# define DMA_LEN_HIGH_MASK             (0x1f)
+
+# define DMA_CFG0_WORDSIZE_8           (0 << 7)
+# define DMA_CFG0_WORDSIZE_16          (1 << 7)
+# define DMA_CFG0_TMODE_MASK           (3 << 5)
+# define DMA_CFG0_TMODE_SINGLE         (0 << 5)
+# define DMA_CFG0_TMODE_BLOCK          (1 << 5)
+# define DMA_CFG0_TMODE_REPEATED_SINGLE        (2 << 5)
+# define DMA_CFG0_TMODE_REPEATED_BLOCK (3 << 5)
+
+/*
+ * DMA triggers
+ */
+# define DMA_CFG0_TRIGGER_NONE         0
+# define DMA_CFG0_TRIGGER_PREV         1
+# define DMA_CFG0_TRIGGER_T1_CH0       2
+# define DMA_CFG0_TRIGGER_T1_CH1       3
+# define DMA_CFG0_TRIGGER_T1_CH2       4
+# define DMA_CFG0_TRIGGER_T2_OVFL      6
+# define DMA_CFG0_TRIGGER_T3_CH0       7
+# define DMA_CFG0_TRIGGER_T3_CH1       8
+# define DMA_CFG0_TRIGGER_T4_CH0       9
+# define DMA_CFG0_TRIGGER_T4_CH1       10
+# define DMA_CFG0_TRIGGER_IOC_0                12
+# define DMA_CFG0_TRIGGER_IOC_1                13
+# define DMA_CFG0_TRIGGER_URX0         14
+# define DMA_CFG0_TRIGGER_UTX0         15
+# define DMA_CFG0_TRIGGER_URX1         16
+# define DMA_CFG0_TRIGGER_UTX1         17
+# define DMA_CFG0_TRIGGER_FLASH                18
+# define DMA_CFG0_TRIGGER_RADIO                19
+# define DMA_CFG0_TRIGGER_ADC_CHALL    20
+# define DMA_CFG0_TRIGGER_ADC_CH0      21
+# define DMA_CFG0_TRIGGER_ADC_CH1      22
+# define DMA_CFG0_TRIGGER_ADC_CH2      23
+# define DMA_CFG0_TRIGGER_ADC_CH3      24
+# define DMA_CFG0_TRIGGER_ADC_CH4      25
+# define DMA_CFG0_TRIGGER_ADC_CH5      26
+# define DMA_CFG0_TRIGGER_ADC_CH6      27
+# define DMA_CFG0_TRIGGER_I2SRX                27
+# define DMA_CFG0_TRIGGER_ADC_CH7      28
+# define DMA_CFG0_TRIGGER_I2STX                28
+# define DMA_CFG0_TRIGGER_ENC_DW       29
+# define DMA_CFG0_TRIGGER_DNC_UP       30
+
+# define DMA_CFG1_SRCINC_MASK          (3 << 6)
+# define DMA_CFG1_SRCINC_0             (0 << 6)
+# define DMA_CFG1_SRCINC_1             (1 << 6)
+# define DMA_CFG1_SRCINC_2             (2 << 6)
+# define DMA_CFG1_SRCINC_MINUS_1       (3 << 6)
+
+# define DMA_CFG1_DESTINC_MASK         (3 << 4)
+# define DMA_CFG1_DESTINC_0            (0 << 4)
+# define DMA_CFG1_DESTINC_1            (1 << 4)
+# define DMA_CFG1_DESTINC_2            (2 << 4)
+# define DMA_CFG1_DESTINC_MINUS_1      (3 << 4)
+
+# define DMA_CFG1_IRQMASK              (1 << 3)
+# define DMA_CFG1_M8                   (1 << 2)
+
+# define DMA_CFG1_PRIORITY_MASK                (3 << 0)
+# define DMA_CFG1_PRIORITY_LOW         (0 << 0)
+# define DMA_CFG1_PRIORITY_NORMAL      (1 << 0)
+# define DMA_CFG1_PRIORITY_HIGH                (2 << 0)
+
+/*
+ * DMAARM - DMA Channel Arm
+ */
+
+sfr at 0xD6 DMAARM;
+
+# define DMAARM_ABORT                  (1 << 7)
+# define DMAARM_DMAARM4                        (1 << 4)
+# define DMAARM_DMAARM3                        (1 << 3)
+# define DMAARM_DMAARM2                        (1 << 2)
+# define DMAARM_DMAARM1                        (1 << 1)
+# define DMAARM_DMAARM0                        (1 << 0)
+
+/*
+ * DMAREQ - DMA Channel Start Request and Status
+ */
+
+sfr at 0xD7 DMAREQ;
+
+# define DMAREQ_DMAREQ4                        (1 << 4)
+# define DMAREQ_DMAREQ3                        (1 << 3)
+# define DMAREQ_DMAREQ2                        (1 << 2)
+# define DMAREQ_DMAREQ1                        (1 << 1)
+# define DMAREQ_DMAREQ0                        (1 << 0)
+
+/*
+ * DMA configuration 0 address
+ */
+
+sfr at 0xD5 DMA0CFGH;
+sfr at 0xD4 DMA0CFGL;
+
+/*
+ * DMA configuration 1-4 address
+ */
+
+sfr at 0xD3 DMA1CFGH;
+sfr at 0xD2 DMA1CFGL;
+
+/*
+ * DMAIRQ - DMA Interrupt Flag
+ */
+
+sfr at 0xD1 DMAIRQ;
+
+# define DMAIRQ_DMAIF4                 (1 << 4)
+# define DMAIRQ_DMAIF3                 (1 << 3)
+# define DMAIRQ_DMAIF2                 (1 << 2)
+# define DMAIRQ_DMAIF1                 (1 << 1)
+# define DMAIRQ_DMAIF0                 (1 << 0)
+
+struct cc_dma_channel {
+       uint8_t src_high;
+       uint8_t src_low;
+       uint8_t dst_high;
+       uint8_t dst_low;
+       uint8_t len_high;
+       uint8_t len_low;
+       uint8_t cfg0;
+       uint8_t cfg1;
+};
+
+#define nop()  _asm nop _endasm;
+
+void
+delay (unsigned char n)
+{
+       unsigned char i = 0;
+       unsigned char j = 0;
+
+       n++;
+       while (--n != 0)
+               while (--i != 0)
+                       while (--j != 0)
+                               nop();
+}
+
+void
+debug_byte(uint8_t byte)
+{
+       uint8_t s;
+
+       for (s = 0; s < 8; s++) {
+               DEBUG = byte & 1;
+               delay(5);
+               byte >>= 1;
+       }
+}
+
+struct cc_dma_channel __xdata config;
+
+#define DMA_LEN        8
+
+uint8_t __xdata dma_input[DMA_LEN];
+uint8_t __xdata dma_output[DMA_LEN];
+
+#define ADDRH(a)       (((uint16_t) (a)) >> 8)
+#define ADDRL(a)       (((uint16_t) (a)))
+
+void
+dma_init(void)
+{
+       int i;
+       config.cfg0 = (DMA_CFG0_WORDSIZE_8 |
+                      DMA_CFG0_TMODE_BLOCK |
+                      DMA_CFG0_TRIGGER_NONE);
+       config.cfg1 = (DMA_CFG1_SRCINC_1 |
+                      DMA_CFG1_DESTINC_1 |
+                      DMA_CFG1_PRIORITY_NORMAL);
+
+       config.src_high = ADDRH(dma_input);
+       config.src_low = ADDRL(dma_input);
+       config.dst_high = ADDRH(dma_output);
+       config.dst_low = ADDRL(dma_output);
+       config.len_high = 0;
+       config.len_low = DMA_LEN;
+       DMA0CFGH = ADDRH(&config);
+       DMA0CFGL = ADDRL(&config);
+       for (i = 0; i < DMA_LEN; i++)
+               dma_input[i] = i + 1;
+}
+
+void
+dma_run(void)
+{
+       DMAREQ |= 1;
+       DMAARM |= 1;
+       while (DMAARM & 1)
+               ;
+}
+
+main ()
+{
+       int i;
+       P1DIR |= 2;
+       CLKCON = 0;
+       while (!(SLEEP & SLEEP_XOSC_STB))
+               ;
+
+       dma_init();
+       dma_run();
+       for (;;) {
+               for (i = 0; i < DMA_LEN; i++)
+                       debug_byte(dma_output[i]);
+       }
+}
diff --git a/target/ee/Makefile b/target/ee/Makefile
new file mode 100644 (file)
index 0000000..4c9abd1
--- /dev/null
@@ -0,0 +1,46 @@
+CC=sdcc
+NO_OPT=--nogcse --noinvariant --noinduction --nojtbound --noloopreverse \
+       --nolabelopt --nooverlay --peep-asm
+DEBUG=--debug
+
+CFLAGS=--model-large $(DEBUG) --less-pedantic \
+       --no-peep --int-long-reent --float-reent \
+       --data-loc 0x30
+
+LDFLAGS=--out-fmt-ihx
+LDFLAGS_RAM=$(LDFLAGS) --code-loc 0xf000 --xram-loc 0xf800 --xram-size 1024
+
+LDFLAGS_FLASH=$(LDFLAGS) --code-loc 0x0000 --xram-loc 0xf000 --xram-size 1024
+
+SRC=ee.c
+ADB=$(SRC:.c=.adb)
+ASM=$(SRC:.c=.asm)
+LNK=$(SRC:.c=.lnk)
+LST=$(SRC:.c=.lst)
+REL=$(SRC:.c=.rel)
+RST=$(SRC:.c=.rst)
+SYM=$(SRC:.c=.sym)
+
+PROGS=ee-flash.ihx ee-ram.ihx
+PCDB=$(PROGS:.ihx=.cdb)
+PLNK=$(PROGS:.ihx=.lnk)
+PMAP=$(PROGS:.ihx=.map)
+PMEM=$(PROGS:.ihx=.mem)
+PAOM=$(PROGS:.ihx=)
+
+%.rel : %.c
+       $(CC) -c $(CFLAGS) -o$*.rel $<
+
+all: $(PROGS)
+
+ee-ram.ihx: $(REL) Makefile
+       $(CC) $(LDFLAGS_RAM) $(CFLAGS) -o ee-ram.ihx $(REL)
+       $(CC) $(LDFLAGS_FLASH) $(CFLAGS) -o ee-flash.ihx $(REL)
+
+ee-flash.ihx: ee-ram.ihx
+
+clean:
+       rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM)
+       rm -f $(PROGS) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM)
+
+install:
diff --git a/target/ee/ee.c b/target/ee/ee.c
new file mode 100644 (file)
index 0000000..9ea22cd
--- /dev/null
@@ -0,0 +1,407 @@
+/*
+ * 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 <stdint.h>
+
+/*
+ * Validate the SPI-connected EEPROM
+ */
+
+sfr at 0x80 P0;
+sfr at 0x90 P1;
+sfr at 0xA0 P2;
+sfr at 0xC6 CLKCON;
+sfr at 0xbe SLEEP;
+
+# define SLEEP_USB_EN          (1 << 7)
+# define SLEEP_XOSC_STB                (1 << 6)
+
+sfr at 0xF1 PERCFG;
+#define PERCFG_T1CFG_ALT_1     (0 << 6)
+#define PERCFG_T1CFG_ALT_2     (1 << 6)
+
+#define PERCFG_T3CFG_ALT_1     (0 << 5)
+#define PERCFG_T3CFG_ALT_2     (1 << 5)
+
+#define PERCFG_T4CFG_ALT_1     (0 << 4)
+#define PERCFG_T4CFG_ALT_2     (1 << 4)
+
+#define PERCFG_U1CFG_ALT_1     (0 << 1)
+#define PERCFG_U1CFG_ALT_2     (1 << 1)
+
+#define PERCFG_U0CFG_ALT_1     (0 << 0)
+#define PERCFG_U0CFG_ALT_2     (1 << 0)
+
+sfr at 0xF2 ADCCFG;
+sfr at 0xF3 P0SEL;
+sfr at 0xF4 P1SEL;
+sfr at 0xF5 P2SEL;
+
+sfr at 0xFD P0DIR;
+sfr at 0xFE P1DIR;
+sfr at 0xFF P2DIR;
+sfr at 0x8F P0INP;
+sfr at 0xF6 P1INP;
+sfr at 0xF7 P2INP;
+
+sfr at 0x89 P0IFG;
+sfr at 0x8A P1IFG;
+sfr at 0x8B P2IFG;
+
+sbit at 0x90 P1_0;
+sbit at 0x91 P1_1;
+sbit at 0x92 P1_2;
+sbit at 0x93 P1_3;
+sbit at 0x94 P1_4;
+sbit at 0x95 P1_5;
+sbit at 0x96 P1_6;
+sbit at 0x97 P1_7;
+
+/*
+ * UART registers
+ */
+
+sfr at 0x86 U0CSR;
+sfr at 0xF8 U1CSR;
+
+# define UxCSR_MODE_UART               (1 << 7)
+# define UxCSR_MODE_SPI                        (0 << 7)
+# define UxCSR_RE                      (1 << 6)
+# define UxCSR_SLAVE                   (1 << 5)
+# define UxCSR_MASTER                  (0 << 5)
+# define UxCSR_FE                      (1 << 4)
+# define UxCSR_ERR                     (1 << 3)
+# define UxCSR_RX_BYTE                 (1 << 2)
+# define UxCSR_TX_BYTE                 (1 << 1)
+# define UxCSR_ACTIVE                  (1 << 0)
+
+sfr at 0xc4 U0UCR;
+sfr at 0xfb U1UCR;
+
+sfr at 0xc5 U0GCR;
+sfr at 0xfc U1GCR;
+
+# define UxGCR_CPOL_NEGATIVE           (0 << 7)
+# define UxGCR_CPOL_POSITIVE           (1 << 7)
+# define UxGCR_CPHA_FIRST_EDGE         (0 << 6)
+# define UxGCR_CPHA_SECOND_EDGE                (1 << 6)
+# define UxGCR_ORDER_LSB               (0 << 5)
+# define UxGCR_ORDER_MSB               (1 << 5)
+# define UxGCR_BAUD_E_MASK             (0x1f)
+# define UxGCR_BAUD_E_SHIFT            0
+
+sfr at 0xc1 U0DBUF;
+sfr at 0xf9 U1DBUF;
+sfr at 0xc2 U0BAUD;
+sfr at 0xfa U1BAUD;
+
+#define MOSI   P1_5
+#define MISO   P1_4
+#define SCK    P1_3
+#define CS     P1_2
+
+#define DEBUG  P1_1
+
+#define BITBANG        0
+#define USART  1
+
+#define nop()  _asm nop _endasm;
+
+void
+delay (unsigned char n)
+{
+       unsigned char i = 0;
+       unsigned char j = 0;
+
+       while (--n != 0)
+               while (--i != 0)
+                       while (--j != 0)
+                               nop();
+}
+
+#if BITBANG
+
+/*
+ * This version directly manipulates the GPIOs to synthesize SPI
+ */
+
+void
+bitbang_cs(uint8_t b)
+{
+       SCK = 0;
+       CS = b;
+       delay(1);
+}
+
+void
+bitbang_out_bit(uint8_t b)
+{
+       MOSI = b;
+       delay(1);
+       SCK = 1;
+       delay(1);
+       SCK = 0;
+}
+
+void
+bitbang_out_byte(uint8_t byte)
+{
+       uint8_t s;
+
+       for (s = 0; s < 8; s++) {
+               uint8_t b = (byte & 0x80) ? 1 : 0;
+               bitbang_out_bit(b);
+               byte <<= 1;
+       }
+}
+
+uint8_t
+bitbang_in_bit(void)
+{
+       uint8_t b;
+
+       delay(1);
+       SCK = 1;
+       delay(1);
+       b = MISO;
+       SCK = 0;
+       return b;
+}
+
+uint8_t
+bitbang_in_byte(void)
+{
+       uint8_t byte = 0;
+       uint8_t s;
+       uint8_t b;
+
+       for (s = 0; s < 8; s++) {
+               b = bitbang_in_bit();
+               byte = byte << 1;
+               byte |= b;
+       }
+       return byte;
+}
+
+void
+bit_bang_init(void)
+{
+       CS = 1;
+       SCK = 0;
+       P1DIR = ((1 << 5) |
+                (0 << 4) |
+                (1 << 3) |
+                (1 << 2) |
+                (1 << 1));
+}
+
+#define spi_init()     bitbang_init()
+#define spi_out_byte(b)        bitbang_out_byte(b)
+#define spi_in_byte()  bitbang_in_byte()
+#define spi_cs(b)      bitbang_cs(b)
+#endif
+
+#if USART
+
+/*
+ * This version uses the USART in SPI mode
+ */
+void
+usart_init(void)
+{
+       /*
+        * Configure our chip select line
+        */
+       CS = 1;
+       P1DIR |= (1 << 2);
+       /*
+        * Configure the peripheral pin choices
+        * for both of the serial ports
+        *
+        * Note that telemetrum will use U1CFG_ALT_2
+        * but that overlaps with SPI ALT_2, so until
+        * we can test that this works, we'll set this
+        * to ALT_1
+        */
+       PERCFG = (PERCFG_U1CFG_ALT_1 |
+                 PERCFG_U0CFG_ALT_2);
+
+       /*
+        * Make the SPI pins controlled by the SPI
+        * hardware
+        */
+       P1SEL |= ((1 << 5) | (1 << 4) | (1 << 3));
+
+       /*
+        * SPI in master mode
+        */
+       U0CSR = (UxCSR_MODE_SPI |
+                UxCSR_MASTER);
+
+       /*
+        * The cc1111 is limited to a 24/8 MHz SPI clock,
+        * while the 25LC1024 is limited to 20MHz. So,
+        * use the 3MHz clock (BAUD_E 17, BAUD_M 0)
+        */
+       U0BAUD = 0;
+       U0GCR = (UxGCR_CPOL_NEGATIVE |
+                UxGCR_CPHA_FIRST_EDGE |
+                UxGCR_ORDER_MSB |
+                (17 << UxGCR_BAUD_E_SHIFT));
+}
+
+void
+usart_cs(uint8_t b)
+{
+       CS = b;
+}
+
+uint8_t
+usart_in_out(uint8_t byte)
+{
+       U0DBUF = byte;
+       while ((U0CSR & UxCSR_TX_BYTE) == 0)
+               ;
+       U0CSR &= ~UxCSR_TX_BYTE;
+       return U0DBUF;
+}
+
+void
+usart_out_byte(uint8_t byte)
+{
+       (void) usart_in_out(byte);
+}
+
+uint8_t
+usart_in_byte(void)
+{
+       return usart_in_out(0xff);
+}
+
+#define spi_init()     usart_init()
+#define spi_out_byte(b)        usart_out_byte(b)
+#define spi_in_byte()  usart_in_byte()
+#define spi_cs(b)      usart_cs(b)
+
+#endif
+
+uint8_t
+rdsr(void)
+{
+       uint8_t status;
+       spi_cs(0);
+       spi_out_byte(0x05);
+       status = spi_in_byte();
+       spi_cs(1);
+       return status;
+}
+
+void
+wrsr(uint8_t status)
+{
+       spi_cs(0);
+       spi_out_byte(0x01);
+       spi_out_byte(status);
+       spi_cs(1);
+}
+
+void
+wren(void)
+{
+       spi_cs(0);
+       spi_out_byte(0x06);
+       spi_cs(1);
+}
+
+void
+write(uint32_t addr, uint8_t *bytes, uint16_t len)
+{
+       wren();
+       spi_cs(0);
+       spi_out_byte(0x02);
+       spi_out_byte(addr >> 16);
+       spi_out_byte(addr >> 8);
+       spi_out_byte(addr);
+       while (len-- > 0)
+               spi_out_byte(*bytes++);
+       spi_cs(1);
+       for (;;) {
+               uint8_t status = rdsr();
+               if ((status & (1 << 0)) == 0)
+                       break;
+       }
+}
+
+void
+read(uint32_t addr, uint8_t *bytes, uint16_t len)
+{
+       spi_cs(0);
+       spi_out_byte(0x03);
+       spi_out_byte(addr >> 16);
+       spi_out_byte(addr >> 8);
+       spi_out_byte(addr);
+       while (len-- > 0)
+               *bytes++ = spi_in_byte();
+       spi_cs(1);
+}
+
+void
+debug_byte(uint8_t byte)
+{
+       uint8_t s;
+
+       for (s = 0; s < 8; s++) {
+               DEBUG = byte & 1;
+               delay(5);
+               byte >>= 1;
+       }
+}
+
+#define STRING "\360\252"
+#define LENGTH 2
+
+main ()
+{
+       uint8_t status;
+       uint8_t buf[LENGTH];
+       int i;
+
+       P1DIR |= 2;
+       CLKCON = 0;
+       while (!(SLEEP & SLEEP_XOSC_STB))
+               ;
+
+       spi_init();
+
+       status = rdsr();
+       /*
+        * Turn off both block-protect bits
+        */
+       status &= ~((1 << 3) | (1 << 2));
+       /*
+        * Turn off write protect enable
+        */
+       status &= ~(1 << 7);
+       wrsr(status);
+       write(0x0, STRING, LENGTH);
+       for (;;) {
+               read(0x0, buf, LENGTH);
+               for (i = 0; i < LENGTH; i++)
+                       debug_byte(buf[i]);
+       }
+}
diff --git a/target/isr.c b/target/isr.c
new file mode 100644 (file)
index 0000000..ae4d04c
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+
+void rftxrx_isr (void) __interrupt(0) __using(1)
+{
+}
+
+void adc_isr (void) __interrupt(1) __using(1)
+{
+}
+
+void urx0_isr (void) __interrupt(2) __using(1)
+{
+}
+
+void urx1_isr (void) __interrupt(3) __using(1)
+{
+}
+
+void enc_isr (void) __interrupt(4) __using(1)
+{
+}
+
+void st_isr (void) __interrupt(5) __using(1)
+{
+}
+
+void usb_isr (void) __interrupt(6) __using(1)
+{
+}
+
+void utx0_isr (void) __interrupt(7) __using(1)
+{
+}
+
+void dma_isr (void) __interrupt(8) __using(1)
+{
+}
+
+void t1_isr (void) __interrupt(9) __using(1)
+{
+}
+
+void t2_isr (void) __interrupt(10) __using(1)
+{
+}
+
+void t3_isr (void) __interrupt(11) __using(1)
+{
+}
+
+void t4_isr (void) __interrupt(12) __using(1)
+{
+}
+
+void p0int_isr (void) __interrupt(13) __using(1)
+{
+}
+
+void utx1_isr (void) __interrupt(14) __using(1)
+{
+}
+
+void p1int_isr (void) __interrupt(15) __using(1)
+{
+}
+
+void rf_isr (void) __interrupt(16) __using(1)
+{
+}
+
+void wdt_isr (void) __interrupt(17) __using(1)
+{
+}
diff --git a/target/radio/Makefile b/target/radio/Makefile
new file mode 100644 (file)
index 0000000..97706fe
--- /dev/null
@@ -0,0 +1,52 @@
+CC=sdcc
+NO_OPT=--nogcse --noinvariant --noinduction --nojtbound --noloopreverse \
+       --nolabelopt --nooverlay --peep-asm
+DEBUG=--debug
+
+CFLAGS=--model-large $(DEBUG) --less-pedantic \
+       --no-peep --int-long-reent --float-reent \
+       --data-loc 0x30
+
+LDFLAGS=--out-fmt-ihx
+LDFLAGS_RAM=$(LDFLAGS) --code-loc 0xf000 --xram-loc 0xf400 --xram-size 1024
+
+LDFLAGS_FLASH=$(LDFLAGS) --code-loc 0x0000 --xram-loc 0xf000 --xram-size 1024
+
+SRC=xmit.c recv.c init.c
+ADB=$(SRC:.c=.adb)
+ASM=$(SRC:.c=.asm)
+LNK=$(SRC:.c=.lnk)
+LST=$(SRC:.c=.lst)
+REL=$(SRC:.c=.rel)
+RST=$(SRC:.c=.rst)
+SYM=$(SRC:.c=.sym)
+
+PROGS=xmit-flash.ihx xmit-ram.ihx recv-flash.ihx recv-ram.ihx
+PCDB=$(PROGS:.ihx=.cdb)
+PLNK=$(PROGS:.ihx=.lnk)
+PMAP=$(PROGS:.ihx=.map)
+PMEM=$(PROGS:.ihx=.mem)
+PAOM=$(PROGS:.ihx=)
+
+%.rel : %.c
+       $(CC) -c $(CFLAGS) -o$*.rel $<
+
+all: $(PROGS)
+
+xmit-ram.ihx: xmit.rel init.rel Makefile
+       $(CC) $(LDFLAGS_RAM) $(CFLAGS) -o xmit-ram.ihx xmit.rel init.rel
+       $(CC) $(LDFLAGS_FLASH) $(CFLAGS) -o xmit-flash.ihx xmit.rel init.rel
+
+xmit-flash.ihx: xmit-ram.ihx
+
+recv-ram.ihx: recv.rel init.rel Makefile
+       $(CC) $(LDFLAGS_RAM) $(CFLAGS) -o recv-ram.ihx recv.rel init.rel
+       $(CC) $(LDFLAGS_FLASH) $(CFLAGS) -o recv-flash.ihx recv.rel init.rel
+
+recv-flash.ihx: recv-ram.ihx
+
+clean:
+       rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM)
+       rm -f $(PROGS) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM)
+
+install:
diff --git a/target/radio/init.c b/target/radio/init.c
new file mode 100644 (file)
index 0000000..ea7c984
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ * Copyright © 2009 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; version 2 of the License.
+ *
+ * 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 "radio.h"
+
+/* Values from SmartRF® Studio for:
+ *
+ * Deviation:  20.507812 kHz
+ * Datarate:   38.360596 kBaud
+ * Modulation: GFSK
+ * RF Freq:    434.549927 MHz
+ * Channel:    99.975586 kHz
+ * Channel:    0
+ * RX filter:  93.75 kHz
+ */
+
+/*
+ * For 434.550MHz, the frequency value is:
+ *
+ * 434.550e6 / (24e6 / 2**16) = 1186611.2
+ */
+
+#define FREQ_CONTROL   1186611
+
+/*
+ * For IF freq of 140.62kHz, the IF value is:
+ *
+ * 140.62e3 / (24e6 / 2**10) = 6
+ */
+
+#define IF_FREQ_CONTROL        6
+
+/*
+ * For channel bandwidth of 93.75 kHz, the CHANBW_E and CHANBW_M values are
+ *
+ * BW = 24e6 / (8 * (4 + M) * 2 ** E)
+ *
+ * So, M = 0 and E = 3
+ */
+
+#define CHANBW_M       0
+#define CHANBW_E       3
+
+/*
+ * For a symbol rate of 38360kBaud, the DRATE_E and DRATE_M values are:
+ *
+ * R = (256 + M) * 2** E * 24e6 / 2**28
+ *
+ * So M is 163 and E is 10
+ */
+
+#define DRATE_E                10
+#define DRATE_M                163
+
+/*
+ * For a channel deviation of 20.5kHz, the DEVIATION_E and DEVIATION_M values are:
+ *
+ * F = 24e6/2**17 * (8 + DEVIATION_M) * 2**DEVIATION_E
+ *
+ * So M is 6 and E is 3
+ */
+
+#define DEVIATION_M    6
+#define DEVIATION_E    3
+
+#define PACKET_LEN     128
+
+/* This are from the table for 433MHz */
+
+#define RF_POWER_M30_DBM       0x12
+#define RF_POWER_M20_DBM       0x0e
+#define RF_POWER_M15_DBM       0x1d
+#define RF_POWER_M10_DBM       0x34
+#define RF_POWER_M5_DBM                0x2c
+#define RF_POWER_0_DBM         0x60
+#define RF_POWER_5_DBM         0x84
+#define RF_POWER_7_DBM         0xc8
+#define RF_POWER_10_DBM                0xc0
+
+#define RF_POWER               RF_POWER_0_DBM
+
+static __code uint8_t radio_setup[] = {
+       RF_PA_TABLE7_OFF,       RF_POWER,
+       RF_PA_TABLE6_OFF,       RF_POWER,
+       RF_PA_TABLE5_OFF,       RF_POWER,
+       RF_PA_TABLE4_OFF,       RF_POWER,
+       RF_PA_TABLE3_OFF,       RF_POWER,
+       RF_PA_TABLE2_OFF,       RF_POWER,
+       RF_PA_TABLE1_OFF,       RF_POWER,
+       RF_PA_TABLE0_OFF,       RF_POWER,
+
+       RF_FREQ2_OFF,           FREQ_CONTROL >> 16,
+       RF_FREQ1_OFF,           FREQ_CONTROL >> 8,
+       RF_FREQ0_OFF,           FREQ_CONTROL >> 0,
+
+       RF_FSCTRL1_OFF,         (IF_FREQ_CONTROL << RF_FSCTRL1_FREQ_IF_SHIFT),
+       RF_FSCTRL0_OFF,         (0 << RF_FSCTRL0_FREQOFF_SHIFT),
+
+       RF_MDMCFG4_OFF,         ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) |
+                                (CHANBW_M << RF_MDMCFG4_CHANBW_M_SHIFT) |
+                                (DRATE_E << RF_MDMCFG4_DRATE_E_SHIFT)),
+       RF_MDMCFG3_OFF,         (DRATE_M << RF_MDMCFG3_DRATE_M_SHIFT),
+       RF_MDMCFG2_OFF,         (RF_MDMCFG2_DEM_DCFILT_OFF |
+                                RF_MDMCFG2_MOD_FORMAT_GFSK |
+                                RF_MDMCFG2_SYNC_MODE_15_16_THRES),
+       RF_MDMCFG1_OFF,         (RF_MDMCFG1_FEC_EN |
+                                RF_MDMCFG1_NUM_PREAMBLE_4 |
+                                (2 << RF_MDMCFG1_CHANSPC_E_SHIFT)),
+       RF_MDMCFG0_OFF,         (17 << RF_MDMCFG0_CHANSPC_M_SHIFT),
+
+       RF_CHANNR_OFF,          0,
+
+       RF_DEVIATN_OFF,         ((DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) |
+                                (DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)),
+
+       /* SmartRF says set LODIV_BUF_CURRENT_TX to 0
+        * And, we're not using power ramping, so use PA_POWER 0
+        */
+       RF_FREND0_OFF,          ((1 << RF_FREND0_LODIV_BUF_CURRENT_TX_SHIFT) |
+                                (0 << RF_FREND0_PA_POWER_SHIFT)),
+
+       RF_FREND1_OFF,          ((1 << RF_FREND1_LNA_CURRENT_SHIFT) |
+                                (1 << RF_FREND1_LNA2MIX_CURRENT_SHIFT) |
+                                (1 << RF_FREND1_LODIV_BUF_CURRENT_RX_SHIFT) |
+                                (2 << RF_FREND1_MIX_CURRENT_SHIFT)),
+
+       RF_FSCAL3_OFF,          0xE9,
+       RF_FSCAL2_OFF,          0x0A,
+       RF_FSCAL1_OFF,          0x00,
+       RF_FSCAL0_OFF,          0x1F,
+
+       RF_TEST2_OFF,           0x88,
+       RF_TEST1_OFF,           0x31,
+       RF_TEST0_OFF,           0x09,
+
+       /* default sync values */
+       RF_SYNC1_OFF,           0xD3,
+       RF_SYNC0_OFF,           0x91,
+
+       /* max packet length */
+       RF_PKTLEN_OFF,          PACKET_LEN,
+
+       RF_PKTCTRL1_OFF,        ((1 << PKTCTRL1_PQT_SHIFT)|
+                                PKTCTRL1_APPEND_STATUS|
+                                PKTCTRL1_ADR_CHK_NONE),
+       RF_PKTCTRL0_OFF,        (RF_PKTCTRL0_WHITE_DATA|
+                                RF_PKTCTRL0_PKT_FORMAT_NORMAL|
+                                RF_PKTCTRL0_CRC_EN|
+                                RF_PKTCTRL0_LENGTH_CONFIG_FIXED),
+       RF_ADDR_OFF,            0x00,
+       RF_MCSM2_OFF,           (RF_MCSM2_RX_TIME_END_OF_PACKET),
+       RF_MCSM1_OFF,           (RF_MCSM1_CCA_MODE_RSSI_BELOW_UNLESS_RECEIVING|
+                                RF_MCSM1_RXOFF_MODE_IDLE|
+                                RF_MCSM1_TXOFF_MODE_IDLE),
+       RF_MCSM0_OFF,           (RF_MCSM0_FS_AUTOCAL_FROM_IDLE|
+                                RF_MCSM0_MAGIC_3|
+                                RF_MCSM0_CLOSE_IN_RX_18DB),
+       RF_FOCCFG_OFF,          (RF_FOCCFG_FOC_PRE_K_3K,
+                                RF_FOCCFG_FOC_POST_K_PRE_K,
+                                RF_FOCCFG_FOC_LIMIT_BW_OVER_4),
+       RF_BSCFG_OFF,           (RF_BSCFG_BS_PRE_K_2K|
+                                RF_BSCFG_BS_PRE_KP_3KP|
+                                RF_BSCFG_BS_POST_KI_PRE_KI|
+                                RF_BSCFG_BS_POST_KP_PRE_KP|
+                                RF_BSCFG_BS_LIMIT_0),
+       RF_AGCCTRL2_OFF,        0x43,
+       RF_AGCCTRL1_OFF,        0x40,
+       RF_AGCCTRL0_OFF,        0x91,
+
+       RF_IOCFG2_OFF,          0x00,
+       RF_IOCFG1_OFF,          0x00,
+       RF_IOCFG0_OFF,          0x00,
+};
+
+void
+radio_init(void) {
+       uint8_t i;
+       for (i = 0; i < sizeof (radio_setup); i += 2)
+               RF[radio_setup[i]] = radio_setup[i+1];
+}
+
+#define nop()  _asm nop _endasm;
+
+void
+delay (unsigned char n)
+{
+       unsigned char i = 0;
+
+       n <<= 1;
+       while (--n != 0)
+               while (--i != 0)
+                       nop();
+}
diff --git a/target/radio/radio.h b/target/radio/radio.h
new file mode 100644 (file)
index 0000000..f68001e
--- /dev/null
@@ -0,0 +1,435 @@
+/*
+ * 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 <stdint.h>
+
+sfr at 0x80 P0;
+sfr at 0x90 P1;
+sbit at 0x90 P1_0;
+sbit at 0x91 P1_1;
+sbit at 0x92 P1_2;
+sbit at 0x93 P1_3;
+sbit at 0x94 P1_4;
+sbit at 0x95 P1_5;
+sbit at 0x96 P1_6;
+sbit at 0x97 P1_7;
+
+sfr at 0xA0 P2;
+sfr at 0xC6 CLKCON;
+
+sfr at 0xF1 PERCFG;
+sfr at 0xF2 ADCCFG;
+sfr at 0xF3 P0SEL;
+sfr at 0xF4 P1SEL;
+sfr at 0xF5 P2SEL;
+
+sfr at 0xFD P0DIR;
+sfr at 0xFE P1DIR;
+sfr at 0xFF P2DIR;
+sfr at 0x8F P0INP;
+sfr at 0xF6 P1INP;
+sfr at 0xF7 P2INP;
+
+sfr at 0x89 P0IFG;
+sfr at 0x8A P1IFG;
+sfr at 0x8B P2IFG;
+
+sfr at 0xD9 RFD;
+sfr at 0xE9 RFIF;
+#define RFIF_IM_TXUNF  (1 << 7)
+#define RFIF_IM_RXOVF  (1 << 6)
+#define RFIF_IM_TIMEOUT        (1 << 5)
+#define RFIF_IM_DONE   (1 << 4)
+#define RFIF_IM_CS     (1 << 3)
+#define RFIF_IM_PQT    (1 << 2)
+#define RFIF_IM_CCA    (1 << 1)
+#define RFIF_IM_SFD    (1 << 0)
+
+sfr at 0xE1 RFST;
+
+sfr at 0x88 TCON;
+
+sfr at 0xbe SLEEP;
+
+# define SLEEP_USB_EN          (1 << 7)
+# define SLEEP_XOSC_STB                (1 << 6)
+
+sbit at 0x89 RFTXRXIF;
+
+#define TCON_RFTXRXIF  (1 << 1)
+
+#define RFST_SFSTXON   0x00
+#define RFST_SCAL      0x01
+#define RFST_SRX       0x02
+#define RFST_STX       0x03
+#define RFST_SIDLE     0x04
+
+__xdata __at (0xdf00) uint8_t RF[0x3c];
+
+__xdata __at (0xdf2f) uint8_t RF_IOCFG2;
+#define RF_IOCFG2_OFF  0x2f
+
+__xdata __at (0xdf30) uint8_t RF_IOCFG1;
+#define RF_IOCFG1_OFF  0x30
+
+__xdata __at (0xdf31) uint8_t RF_IOCFG0;
+#define RF_IOCFG0_OFF  0x31
+
+__xdata __at (0xdf00) uint8_t RF_SYNC1;
+#define RF_SYNC1_OFF   0x00
+
+__xdata __at (0xdf01) uint8_t RF_SYNC0;
+#define RF_SYNC0_OFF   0x01
+
+__xdata __at (0xdf02) uint8_t RF_PKTLEN;
+#define RF_PKTLEN_OFF  0x02
+
+__xdata __at (0xdf03) uint8_t RF_PKTCTRL1;
+#define RF_PKTCTRL1_OFF        0x03
+#define PKTCTRL1_PQT_MASK                      (0x7 << 5)
+#define PKTCTRL1_PQT_SHIFT                     5
+#define PKTCTRL1_APPEND_STATUS                 (1 << 2)
+#define PKTCTRL1_ADR_CHK_NONE                  (0 << 0)
+#define PKTCTRL1_ADR_CHK_NO_BROADCAST          (1 << 0)
+#define PKTCTRL1_ADR_CHK_00_BROADCAST          (2 << 0)
+#define PKTCTRL1_ADR_CHK_00_FF_BROADCAST       (3 << 0)
+
+/* If APPEND_STATUS is used, two bytes will be added to the packet data */
+#define PKT_APPEND_STATUS_0_RSSI_MASK          (0xff)
+#define PKT_APPEND_STATUS_0_RSSI_SHIFT         0
+#define PKT_APPEND_STATUS_1_CRC_OK             (1 << 7)
+#define PKT_APPEND_STATUS_1_LQI_MASK           (0x7f)
+#define PKT_APPEND_STATUS_1_LQI_SHIFT          0
+
+__xdata __at (0xdf04) uint8_t RF_PKTCTRL0;
+#define RF_PKTCTRL0_OFF        0x04
+#define RF_PKTCTRL0_WHITE_DATA                 (1 << 6)
+#define RF_PKTCTRL0_PKT_FORMAT_NORMAL          (0 << 4)
+#define RF_PKTCTRL0_PKT_FORMAT_RANDOM          (2 << 4)
+#define RF_PKTCTRL0_CRC_EN                     (1 << 2)
+#define RF_PKTCTRL0_LENGTH_CONFIG_FIXED                (0 << 0)
+#define RF_PKTCTRL0_LENGTH_CONFIG_VARIABLE     (1 << 0)
+
+__xdata __at (0xdf05) uint8_t RF_ADDR;
+#define RF_ADDR_OFF    0x05
+
+__xdata __at (0xdf06) uint8_t RF_CHANNR;
+#define RF_CHANNR_OFF  0x06
+
+__xdata __at (0xdf07) uint8_t RF_FSCTRL1;
+#define RF_FSCTRL1_OFF 0x07
+
+#define RF_FSCTRL1_FREQ_IF_SHIFT       (0)
+
+__xdata __at (0xdf08) uint8_t RF_FSCTRL0;
+#define RF_FSCTRL0_OFF 0x08
+
+#define RF_FSCTRL0_FREQOFF_SHIFT       (0)
+
+__xdata __at (0xdf09) uint8_t RF_FREQ2;
+#define RF_FREQ2_OFF   0x09
+
+__xdata __at (0xdf0a) uint8_t RF_FREQ1;
+#define RF_FREQ1_OFF   0x0a
+
+__xdata __at (0xdf0b) uint8_t RF_FREQ0;
+#define RF_FREQ0_OFF   0x0b
+
+__xdata __at (0xdf0c) uint8_t RF_MDMCFG4;
+#define RF_MDMCFG4_OFF 0x0c
+
+#define RF_MDMCFG4_CHANBW_E_SHIFT      6
+#define RF_MDMCFG4_CHANBW_M_SHIFT      4
+#define RF_MDMCFG4_DRATE_E_SHIFT       0
+
+__xdata __at (0xdf0d) uint8_t RF_MDMCFG3;
+#define RF_MDMCFG3_OFF 0x0d
+
+#define RF_MDMCFG3_DRATE_M_SHIFT       0
+
+__xdata __at (0xdf0e) uint8_t RF_MDMCFG2;
+#define RF_MDMCFG2_OFF 0x0e
+
+#define RF_MDMCFG2_DEM_DCFILT_OFF      (1 << 7)
+#define RF_MDMCFG2_DEM_DCFILT_ON       (0 << 7)
+
+#define RF_MDMCFG2_MOD_FORMAT_MASK     (7 << 4)
+#define RF_MDMCFG2_MOD_FORMAT_2_FSK    (0 << 4)
+#define RF_MDMCFG2_MOD_FORMAT_GFSK     (1 << 4)
+#define RF_MDMCFG2_MOD_FORMAT_ASK_OOK  (3 << 4)
+#define RF_MDMCFG2_MOD_FORMAT_MSK      (7 << 4)
+
+#define RF_MDMCFG2_MANCHESTER_EN       (1 << 3)
+
+#define RF_MDMCFG2_SYNC_MODE_MASK              (0x7 << 0)
+#define RF_MDMCFG2_SYNC_MODE_NONE              (0x0 << 0)
+#define RF_MDMCFG2_SYNC_MODE_15_16             (0x1 << 0)
+#define RF_MDMCFG2_SYNC_MODE_16_16             (0x2 << 0)
+#define RF_MDMCFG2_SYNC_MODE_30_32             (0x3 << 0)
+#define RF_MDMCFG2_SYNC_MODE_NONE_THRES                (0x4 << 0)
+#define RF_MDMCFG2_SYNC_MODE_15_16_THRES       (0x5 << 0)
+#define RF_MDMCFG2_SYNC_MODE_16_16_THRES       (0x6 << 0)
+#define RF_MDMCFG2_SYNC_MODE_30_32_THRES       (0x7 << 0)
+
+__xdata __at (0xdf0f) uint8_t RF_MDMCFG1;
+#define RF_MDMCFG1_OFF 0x0f
+
+#define RF_MDMCFG1_FEC_EN                      (1 << 7)
+#define RF_MDMCFG1_FEC_DIS                     (0 << 7)
+
+#define RF_MDMCFG1_NUM_PREAMBLE_MASK           (7 << 4)
+#define RF_MDMCFG1_NUM_PREAMBLE_2              (0 << 4)
+#define RF_MDMCFG1_NUM_PREAMBLE_3              (1 << 4)
+#define RF_MDMCFG1_NUM_PREAMBLE_4              (2 << 4)
+#define RF_MDMCFG1_NUM_PREAMBLE_6              (3 << 4)
+#define RF_MDMCFG1_NUM_PREAMBLE_8              (4 << 4)
+#define RF_MDMCFG1_NUM_PREAMBLE_12             (5 << 4)
+#define RF_MDMCFG1_NUM_PREAMBLE_16             (6 << 4)
+#define RF_MDMCFG1_NUM_PREAMBLE_24             (7 << 4)
+
+#define RF_MDMCFG1_CHANSPC_E_MASK              (3 << 0)
+#define RF_MDMCFG1_CHANSPC_E_SHIFT             (0)
+
+__xdata __at (0xdf10) uint8_t RF_MDMCFG0;
+#define RF_MDMCFG0_OFF 0x10
+
+#define RF_MDMCFG0_CHANSPC_M_SHIFT             (0)
+
+__xdata __at (0xdf11) uint8_t RF_DEVIATN;
+#define RF_DEVIATN_OFF 0x11
+
+#define RF_DEVIATN_DEVIATION_E_SHIFT           4
+#define RF_DEVIATN_DEVIATION_M_SHIFT           0
+
+__xdata __at (0xdf12) uint8_t RF_MCSM2;
+#define RF_MCSM2_OFF   0x12
+#define RF_MCSM2_RX_TIME_RSSI                  (1 << 4)
+#define RF_MCSM2_RX_TIME_QUAL                  (1 << 3)
+#define RF_MCSM2_RX_TIME_MASK                  (0x7)
+#define RF_MCSM2_RX_TIME_SHIFT                 0
+#define RF_MCSM2_RX_TIME_END_OF_PACKET         (7)
+
+__xdata __at (0xdf13) uint8_t RF_MCSM1;
+#define RF_MCSM1_OFF   0x13
+#define RF_MCSM1_CCA_MODE_ALWAYS                       (0 << 4)
+#define RF_MCSM1_CCA_MODE_RSSI_BELOW                   (1 << 4)
+#define RF_MCSM1_CCA_MODE_UNLESS_RECEIVING             (2 << 4)
+#define RF_MCSM1_CCA_MODE_RSSI_BELOW_UNLESS_RECEIVING  (3 << 4)
+#define RF_MCSM1_RXOFF_MODE_IDLE                       (0 << 2)
+#define RF_MCSM1_RXOFF_MODE_FSTXON                     (1 << 2)
+#define RF_MCSM1_RXOFF_MODE_TX                         (2 << 2)
+#define RF_MCSM1_RXOFF_MODE_RX                         (3 << 2)
+#define RF_MCSM1_TXOFF_MODE_IDLE                       (0 << 0)
+#define RF_MCSM1_TXOFF_MODE_FSTXON                     (1 << 0)
+#define RF_MCSM1_TXOFF_MODE_TX                         (2 << 0)
+#define RF_MCSM1_TXOFF_MODE_RX                         (3 << 0)
+
+__xdata __at (0xdf14) uint8_t RF_MCSM0;
+#define RF_MCSM0_OFF   0x14
+#define RF_MCSM0_FS_AUTOCAL_NEVER              (0 << 4)
+#define RF_MCSM0_FS_AUTOCAL_FROM_IDLE          (1 << 4)
+#define RF_MCSM0_FS_AUTOCAL_TO_IDLE            (2 << 4)
+#define RF_MCSM0_FS_AUTOCAL_TO_IDLE_EVERY_4    (3 << 4)
+#define RF_MCSM0_MAGIC_3                       (1 << 3)
+#define RF_MCSM0_MAGIC_2                       (1 << 2)
+#define RF_MCSM0_CLOSE_IN_RX_0DB               (0 << 0)
+#define RF_MCSM0_CLOSE_IN_RX_6DB               (1 << 0)
+#define RF_MCSM0_CLOSE_IN_RX_12DB              (2 << 0)
+#define RF_MCSM0_CLOSE_IN_RX_18DB              (3 << 0)
+
+__xdata __at (0xdf15) uint8_t RF_FOCCFG;
+#define RF_FOCCFG_OFF  0x15
+#define RF_FOCCFG_FOC_BS_CS_GATE               (1 << 5)
+#define RF_FOCCFG_FOC_PRE_K_1K                 (0 << 3)
+#define RF_FOCCFG_FOC_PRE_K_2K                 (1 << 3)
+#define RF_FOCCFG_FOC_PRE_K_3K                 (2 << 3)
+#define RF_FOCCFG_FOC_PRE_K_4K                 (3 << 3)
+#define RF_FOCCFG_FOC_POST_K_PRE_K             (0 << 2)
+#define RF_FOCCFG_FOC_POST_K_PRE_K_OVER_2      (1 << 2)
+#define RF_FOCCFG_FOC_LIMIT_0                  (0 << 0)
+#define RF_FOCCFG_FOC_LIMIT_BW_OVER_8          (1 << 0)
+#define RF_FOCCFG_FOC_LIMIT_BW_OVER_4          (2 << 0)
+#define RF_FOCCFG_FOC_LIMIT_BW_OVER_2          (3 << 0)
+
+__xdata __at (0xdf16) uint8_t RF_BSCFG;
+#define RF_BSCFG_OFF   0x16
+#define RF_BSCFG_BS_PRE_K_1K                   (0 << 6)
+#define RF_BSCFG_BS_PRE_K_2K                   (1 << 6)
+#define RF_BSCFG_BS_PRE_K_3K                   (2 << 6)
+#define RF_BSCFG_BS_PRE_K_4K                   (3 << 6)
+#define RF_BSCFG_BS_PRE_KP_1KP                 (0 << 4)
+#define RF_BSCFG_BS_PRE_KP_2KP                 (1 << 4)
+#define RF_BSCFG_BS_PRE_KP_3KP                 (2 << 4)
+#define RF_BSCFG_BS_PRE_KP_4KP                 (3 << 4)
+#define RF_BSCFG_BS_POST_KI_PRE_KI             (0 << 3)
+#define RF_BSCFG_BS_POST_KI_PRE_KI_OVER_2      (1 << 3)
+#define RF_BSCFG_BS_POST_KP_PRE_KP             (0 << 2)
+#define RF_BSCFG_BS_POST_KP_PRE_KP_OVER_2      (1 << 2)
+#define RF_BSCFG_BS_LIMIT_0                    (0 << 0)
+#define RF_BSCFG_BS_LIMIT_3_125                        (1 << 0)
+#define RF_BSCFG_BS_LIMIT_6_25                 (2 << 0)
+#define RF_BSCFG_BS_LIMIT_12_5                 (3 << 0)
+
+__xdata __at (0xdf17) uint8_t RF_AGCCTRL2;
+#define RF_AGCCTRL2_OFF        0x17
+
+__xdata __at (0xdf18) uint8_t RF_AGCCTRL1;
+#define RF_AGCCTRL1_OFF        0x18
+
+__xdata __at (0xdf19) uint8_t RF_AGCCTRL0;
+#define RF_AGCCTRL0_OFF        0x19
+
+__xdata __at (0xdf1a) uint8_t RF_FREND1;
+#define RF_FREND1_OFF  0x1a
+
+#define RF_FREND1_LNA_CURRENT_SHIFT            6
+#define RF_FREND1_LNA2MIX_CURRENT_SHIFT                4
+#define RF_FREND1_LODIV_BUF_CURRENT_RX_SHIFT   2
+#define RF_FREND1_MIX_CURRENT_SHIFT            0
+
+__xdata __at (0xdf1b) uint8_t RF_FREND0;
+#define RF_FREND0_OFF  0x1b
+
+#define RF_FREND0_LODIV_BUF_CURRENT_TX_MASK    (0x3 << 4)
+#define RF_FREND0_LODIV_BUF_CURRENT_TX_SHIFT   4
+#define RF_FREND0_PA_POWER_MASK                        (0x7)
+#define RF_FREND0_PA_POWER_SHIFT               0
+
+__xdata __at (0xdf1c) uint8_t RF_FSCAL3;
+#define RF_FSCAL3_OFF  0x1c
+
+__xdata __at (0xdf1d) uint8_t RF_FSCAL2;
+#define RF_FSCAL2_OFF  0x1d
+
+__xdata __at (0xdf1e) uint8_t RF_FSCAL1;
+#define RF_FSCAL1_OFF  0x1e
+
+__xdata __at (0xdf1f) uint8_t RF_FSCAL0;
+#define RF_FSCAL0_OFF  0x1f
+
+__xdata __at (0xdf23) uint8_t RF_TEST2;
+#define RF_TEST2_OFF   0x23
+
+#define RF_TEST2_NORMAL_MAGIC          0x88
+#define RF_TEST2_RX_LOW_DATA_RATE_MAGIC        0x81
+
+__xdata __at (0xdf24) uint8_t RF_TEST1;
+#define RF_TEST1_OFF   0x24
+
+#define RF_TEST1_TX_MAGIC              0x31
+#define RF_TEST1_RX_LOW_DATA_RATE_MAGIC        0x35
+
+__xdata __at (0xdf25) uint8_t RF_TEST0;
+#define RF_TEST0_OFF   0x25
+
+#define RF_TEST0_7_2_MASK              (0xfc)
+#define RF_TEST0_VCO_SEL_CAL_EN                (1 << 1)
+#define RF_TEST0_0_MASK                        (1)
+
+/* These are undocumented, and must be computed
+ * using the provided tool.
+ */
+__xdata __at (0xdf27) uint8_t RF_PA_TABLE7;
+#define RF_PA_TABLE7_OFF       0x27
+
+__xdata __at (0xdf28) uint8_t RF_PA_TABLE6;
+#define RF_PA_TABLE6_OFF       0x28
+
+__xdata __at (0xdf29) uint8_t RF_PA_TABLE5;
+#define RF_PA_TABLE5_OFF       0x29
+
+__xdata __at (0xdf2a) uint8_t RF_PA_TABLE4;
+#define RF_PA_TABLE4_OFF       0x2a
+
+__xdata __at (0xdf2b) uint8_t RF_PA_TABLE3;
+#define RF_PA_TABLE3_OFF       0x2b
+
+__xdata __at (0xdf2c) uint8_t RF_PA_TABLE2;
+#define RF_PA_TABLE2_OFF       0x2c
+
+__xdata __at (0xdf2d) uint8_t RF_PA_TABLE1;
+#define RF_PA_TABLE1_OFF       0x2d
+
+__xdata __at (0xdf2e) uint8_t RF_PA_TABLE0;
+#define RF_PA_TABLE0_OFF       0x2e
+
+__xdata __at (0xdf36) uint8_t RF_PARTNUM;
+#define RF_PARTNUM_OFF 0x36
+
+__xdata __at (0xdf37) uint8_t RF_VERSION;
+#define RF_VERSION_OFF 0x37
+
+__xdata __at (0xdf38) uint8_t RF_FREQEST;
+#define RF_FREQEST_OFF 0x38
+
+__xdata __at (0xdf39) uint8_t RF_LQI;
+#define RF_LQI_OFF     0x39
+
+#define RF_LQI_CRC_OK                  (1 << 7)
+#define RF_LQI_LQI_EST_MASK            (0x7f)
+
+__xdata __at (0xdf3a) uint8_t RF_RSSI;
+#define RF_RSSI_OFF    0x3a
+
+__xdata __at (0xdf3b) uint8_t RF_MARCSTATE;
+#define RF_MARCSTATE_OFF       0x3b
+
+#define RF_MARCSTATE_MASK              0x0f
+#define RF_MARCSTATE_SLEEP             0x00
+#define RF_MARCSTATE_IDLE              0x01
+#define RF_MARCSTATE_VCOON_MC          0x03
+#define RF_MARCSTATE_REGON_MC          0x04
+#define RF_MARCSTATE_MANCAL            0x05
+#define RF_MARCSTATE_VCOON             0x06
+#define RF_MARCSTATE_REGON             0x07
+#define RF_MARCSTATE_STARTCAL          0x08
+#define RF_MARCSTATE_BWBOOST           0x09
+#define RF_MARCSTATE_FS_LOCK           0x0a
+#define RF_MARCSTATE_IFADCON           0x0b
+#define RF_MARCSTATE_ENDCAL            0x0c
+#define RF_MARCSTATE_RX                        0x0d
+#define RF_MARCSTATE_RX_END            0x0e
+#define RF_MARCSTATE_RX_RST            0x0f
+#define RF_MARCSTATE_TXRX_SWITCH       0x10
+#define RF_MARCSTATE_RX_OVERFLOW       0x11
+#define RF_MARCSTATE_FSTXON            0x12
+#define RF_MARCSTATE_TX                        0x13
+#define RF_MARCSTATE_TX_END            0x14
+#define RF_MARCSTATE_RXTX_SWITCH       0x15
+#define RF_MARCSTATE_TX_UNDERFLOW      0x16
+
+
+__xdata __at (0xdf3c) uint8_t RF_PKTSTATUS;
+#define RF_PKTSTATUS_OFF       0x3c
+
+#define RF_PKTSTATUS_CRC_OK            (1 << 7)
+#define RF_PKTSTATUS_CS                        (1 << 6)
+#define RF_PKTSTATUS_PQT_REACHED       (1 << 5)
+#define RF_PKTSTATUS_CCA               (1 << 4)
+#define RF_PKTSTATUS_SFD               (1 << 3)
+
+__xdata __at (0xdf3d) uint8_t RF_VCO_VC_DAC;
+#define RF_VCO_VC_DAC_OFF      0x3d
+
+#define PACKET_LEN     128
+
+void
+radio_init(void);
+
+void
+delay (unsigned char n);
diff --git a/target/radio/recv.c b/target/radio/recv.c
new file mode 100644 (file)
index 0000000..c50c320
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * 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 "radio.h"
+
+main ()
+{
+       static uint8_t  packet[PACKET_LEN + 2];
+       CLKCON = 0;
+       while (!(SLEEP & SLEEP_XOSC_STB))
+               ;
+       /* Set P2_0 to output */
+       P1 = 0;
+       P1DIR = 0x02;
+       radio_init ();
+       delay(100);
+
+       for (;;) {
+               uint8_t i;
+               RFST = RFST_SIDLE;
+               RFIF = 0;
+               delay(100);
+               RFST = RFST_SRX;
+//             while (!(RFIF & RFIF_IM_CS));
+//             P1 = 2;
+               for (i = 0; i < PACKET_LEN + 2; i++) {
+                       while (!RFTXRXIF)
+                               ;
+                       P1=2;
+                       RFTXRXIF = 0;
+                       packet[i] = RFD;
+               }
+               P1 = 0;
+
+               /* check packet contents */
+               for (i = 0; i < PACKET_LEN; i++)
+                       if (packet[i] != i)
+                               break;
+
+               /* get excited if the packet came through correctly */
+               if (i == PACKET_LEN &&
+                   packet[PACKET_LEN+1] & PKT_APPEND_STATUS_1_CRC_OK)
+               {
+                       for (i = 0; i < 5; i++){
+                               P1 = 2;
+                               delay(100);
+                               P1 = 0;
+                               delay(100);
+                       }
+               }
+               delay(100);
+       }
+}
diff --git a/target/radio/xmit.c b/target/radio/xmit.c
new file mode 100644 (file)
index 0000000..e80a0f8
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright © 2009 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; version 2 of the License.
+ *
+ * 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 "radio.h"
+
+main ()
+{
+       int16_t j;
+       CLKCON = 0;
+       while (!(SLEEP & SLEEP_XOSC_STB))
+               ;
+       P1 = 0;
+       P1DIR = 3;
+       radio_init ();
+       delay(100);
+
+       for (;;) {
+               uint8_t i;
+
+               for (j = 0; j < 100; j++)
+                       delay(100);
+               P1 = 2;
+               RFST = RFST_SIDLE;
+               delay(1);
+               RFST = RFST_STX;
+               for (i = 0; i < PACKET_LEN; i++) {
+                       while (!RFTXRXIF);
+                       RFTXRXIF = 0;
+                       RFD = i;
+               }
+               P1 = 0;
+       }
+}
diff --git a/target/serial/Makefile b/target/serial/Makefile
new file mode 100644 (file)
index 0000000..3a1d81e
--- /dev/null
@@ -0,0 +1,46 @@
+CC=sdcc
+NO_OPT=--nogcse --noinvariant --noinduction --nojtbound --noloopreverse \
+