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>
35 files changed:
1  2 
.gitignore
INSTALL
Makefile.am
aoload/aoload.c
aoview/Makefile.am
ccload/ccload.c
ccmanual/ccmanual.c
configure.ac
lib/cc-bitbang.c
lib/cc-usb.c
lib/ccdbg-command.c
lib/ccdbg-flash.c
lib/ccdbg-hex.c
lib/ccdbg-memory.c
lib/ccdbg-rom.c
lib/ccdbg.h
lib/cp-usb-async.c
lib/cp-usb.c
s51/commands
s51/s51-command.c
s51/s51-main.c
s51/s51-parse.c
s51/s51.1
target/adc-serial/adc_serial.c
target/adc/adc.c
target/beep-timer/beep_timer.c
target/dma/dma.c
target/ee/ee.c
target/isr.c
target/radio/init.c
target/radio/recv.c
target/serial/serial.c
target/timer/cc1111.h
tests/debug_mode
tests/get_status

diff --combined .gitignore
index 190ba2fd4c3b3a9c001d36c9a6d2a7b3de4ece72,93d05b7f1bd33d995b3a587f2a11bf4183db1823..71b0a61465d5582ccaffe1b0337e5142346567d6
@@@ -1,32 -1,20 +1,44 @@@
 -*.o
+ *.a
 +*.adb
 +*.asm
- *.lst
- *.ihx
- *.rel
- *.sym
- *.rst
 +*.cdb
++*.ihx
 +*.lnk
++*.lst
 +*.map
 +*.mem
- telemetrum
- teleterra
- tidongle
- teledongle
++*.o
++*.rel
++*.rst
++*.sym
+ .deps
 -tags
 -Makefile
 -Makefile.in
+ 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 --combined INSTALL
index c9fd2c0c3a1c835153ba46dfec89fbda38b6fb36,d3c5b40a94091285c27361905f591af64c1f7b21..200806c586303f2258464fa4c13299aa420af941
+++ b/INSTALL
@@@ -2,15 -2,15 +2,15 @@@ Installation Instruction
  *************************
  
  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 +73,9 @@@ The simplest way to compile this packag
  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 +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 +100,10 @@@ architecture at a time in the source co
  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 +126,7 @@@ option `--program-prefix=PREFIX' or `--
  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 +138,14 @@@ find the X include and library files au
  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 +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 +182,7 @@@ A warning: not all `configure' scripts 
  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 +201,11 @@@ an Autoconf bug.  Until the bug is fixe
  `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'
       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.
 -
diff --combined Makefile.am
index e5c0c1e83777991dc3f48d4cf4cc379ff86d62f6,86f2fad550b556dfc24db150bc8bb8b9ac0e9776..b0d059ea0968b8e49be6217cfc3c8382116abf15
@@@ -1,1 -1,1 +1,1 @@@
- SUBDIRS=src aoview
 -SUBDIRS=lib ccload s51 ccmanual ccdump aoload
++SUBDIRS=src aoview lib ccload s51 ccmanual ccdump aoload
diff --combined aoload/aoload.c
index 0000000000000000000000000000000000000000,a36ad375e6c8a8fd006b25ecd78f1352a3f5c666..b84a88a68f25c9b07530d6bb5e7d5b99385174ef
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,231 +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);
+ }
diff --combined aoview/Makefile.am
index 9f67ac40225d1b0e82d287ea47970817a914e1f3,0000000000000000000000000000000000000000..be3fbacf8c85a4a297f12a9e9f1f8a4eeb85ac36
mode 100644,000000..100644
--- /dev/null
@@@ -1,28 -1,0 +1,28 @@@
- AM_CFLAGS=$(AOVIEW_CFLAGS) -I$(top_srcdir)/src -DAOVIEW_VERSION=\"$(VERSION)\"
 +VERSION=$(shell git describe)
- aoview_LDADD=$(AOVIEW_LIBS)
++AM_CFLAGS=$(GNOME_CFLAGS) -I$(top_srcdir)/src -DAOVIEW_VERSION=\"$(VERSION)\"
 +
 +bin_PROGRAMS=aoview
 +
++aoview_LDADD=$(GNOME_LIBS)
 +
 +aoview_SOURCES = \
 +      aoview_main.c \
 +      aoview_dev.c \
 +      aoview_dev_dialog.c \
 +      aoview_serial.c \
 +      aoview_monitor.c \
 +      aoview_state.c \
 +      aoview_convert.c \
 +      aoview_log.c \
 +      aoview_table.c \
 +      aoview_util.c \
 +      aoview_file.c \
 +      aoview_eeprom.c \
 +      aoview.h
 +
 +BUILT_SOURCES = aoview_glade.h
 +
 +CLEANFILES = aoview_glade.h
 +
 +aoview_glade.h: aoview.glade
 +      sed -e 's/"/\\"/g' -e 's/^/"/' -e 's/$$/"/' $< > $@
diff --combined ccload/ccload.c
index 0000000000000000000000000000000000000000,3e220914080341e71cde1511a46de0bd6e9907b2..5f7708fd2f8c93ac4b1d8da40fefc0baaa71b2ca
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,80 +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 --combined ccmanual/ccmanual.c
index 0000000000000000000000000000000000000000,402d9b1333d99e4c3dca8e0d0bef6ced23d189c1..7090c9a364dbca0f35bf7f5370537464cefb5839
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,33 +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);
+ }
diff --combined configure.ac
index 0419489aee2cc3209a5732e2ec69c8a6ce67e372,6c8963c4f7c86437e5fdeb0092305c732df3147c..99511a6e0a19b9b2915b1b72cd3b8c14caaf7cd1
@@@ -1,25 -1,25 +1,25 @@@
 -dnl 
 -dnl  Copyright Â© 2008 Keith Packard <keithp@keithp.com>
 -dnl 
 +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
  dnl  the Free Software Foundation; either version 2 of the License, or
  dnl  (at your option) any later version.
 -dnl 
 +dnl
  dnl  This program is distributed in the hope that it will be useful, but
  dnl  WITHOUT ANY WARRANTY; without even the implied warranty of
  dnl  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  dnl  General Public License for more details.
 -dnl 
 +dnl
  dnl  You should have received a copy of the GNU General Public License along
  dnl  with this program; if not, write to the Free Software Foundation, Inc.,
  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(cctools, 0.1)
++AM_INIT_AUTOMAKE(altos, 0.1)
  AM_MAINTAINER_MODE
  
  dnl ==========================================================================
@@@ -43,16 -43,61 +43,17 @@@ if test "x$GCC" = "xyes"; the
  fi
  AC_SUBST(WARN_CFLAGS)
  
--dnl ==========================================================================
--
--AM_CONDITIONAL(CROSS_COMPILING, test $cross_compiling = yes)
--
--dnl ==========================================================================
--
 -# Setup for compiling build tools (fc-glyphname, etc)
 -AC_MSG_CHECKING([for a C compiler for build tools])
 -if test $cross_compiling = yes; then
 -  AC_CHECK_PROGS(CC_FOR_BUILD, gcc cc)
 -else
 -  CC_FOR_BUILD=$CC
 -fi
 -AC_MSG_RESULT([$CC_FOR_BUILD])
 -AC_SUBST(CC_FOR_BUILD)
++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_MSG_CHECKING([for suffix of executable build tools])
 -if test $cross_compiling = yes; then
 -  cat >conftest.c <<\_______EOF
 -int
 -main ()
 -{
 -  exit (0);
 -}
 -_______EOF
 -  for i in .exe ""; do
 -    compile="$CC_FOR_BUILD conftest.c -o conftest$i"
 -    if AC_TRY_EVAL(compile); then
 -      if (./conftest) 2>&AC_FD_CC; then
 -      EXEEXT_FOR_BUILD=$i
 -      break
 -      fi
 -    fi
 -  done
 -  rm -f conftest*
 -  if test "${EXEEXT_FOR_BUILD+set}" != set; then
 -    AC_MSG_ERROR([Cannot determine suffix of executable build tools])
 -  fi
 -else
 -  EXEEXT_FOR_BUILD=$EXEEXT
 -fi
 -AC_MSG_RESULT([$EXEEXT_FOR_BUILD])
 -AC_SUBST(EXEEXT_FOR_BUILD)
 -
 -USB_LIBS="-lusb"
 -AC_SUBST(USB_LIBS)
 -
  AC_OUTPUT([
 -Makefile 
 +Makefile
 +aoview/Makefile
+ lib/Makefile
+ ccload/Makefile
+ s51/Makefile
+ ccmanual/Makefile
+ ccdump/Makefile
+ aoload/Makefile
  ])
diff --combined lib/cc-bitbang.c
index 0000000000000000000000000000000000000000,a5d2d369e139db6226a44a47dc4ad552ec3ebd33..1d3ba47664af4bf19cac9a29452eca02e49133c8
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,270 +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 --combined lib/cc-usb.c
index 0000000000000000000000000000000000000000,2efe572ed701043340b8030b94cd4190085bd7ce..dc764c24e99f79fd326226cbb8f795063ab58340
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,360 +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;
 -              while (in_pos < cc->in_count && 
++
+       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 --combined lib/ccdbg-command.c
index 0000000000000000000000000000000000000000,7d1ae067556ee2dd2343566e7454a540409760c3..a1002879f815b178630face7a11ff8e365440350
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,177 +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 --combined lib/ccdbg-flash.c
index 0000000000000000000000000000000000000000,8a586a21ccb4fc076da2886881d9830662736925..3e6729851502ff8895a6e2088836284035f7702c
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,356 +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 --combined lib/ccdbg-hex.c
index 0000000000000000000000000000000000000000,86478da07b8c5f262c6adfb675cccf6aa11f2528..dfea915601a74e6258d8c6427b885eaf300870c5
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,330 +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;
 -                      newhex = realloc(hex, 
++
+                       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 --combined lib/ccdbg-memory.c
index 0000000000000000000000000000000000000000,878c5f97b9199a715164845a31dd479914f81a4c..554ac637c6911491e61005ba76ca7932d8d06686
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,179 +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 --combined lib/ccdbg-rom.c
index 0000000000000000000000000000000000000000,4559b4e7bd0d3476133b39cb70c9a1a3d79816e2..71bed2200478b2f9b56a199f2a8e7a8ee87d523f
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,63 +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 --combined lib/ccdbg.h
index 0000000000000000000000000000000000000000,fe0ea3a0192cf4721f7a741c32232bb499556afb..4a2e3b9f00c9222118f93386024a206d06ab5ffd
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,341 +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 --combined lib/cp-usb-async.c
index 0000000000000000000000000000000000000000,1fe09aad82f486f76a2a588eb3ed7c5b67ea377d..6539394b541a95ec4c2761d75d7a9c739e253048
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,188 +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 --combined lib/cp-usb.c
index 0000000000000000000000000000000000000000,d227b78c90922c848fb11260086ff5cf90c62410..530848db1cd50bbad8c014bab9019100d56c7f8d
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,157 +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 --combined s51/commands
index 0000000000000000000000000000000000000000,77a9849330158042e2184fdac72b9e19e500691a..aba65cd0f5b3de8ecd56c5ada56e7a68db5a843e
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,61 +1,60 @@@
 -      run <start> <stop>      - set temporary bp at <stop> 
+ 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 --combined s51/s51-command.c
index 0000000000000000000000000000000000000000,02ecdddd3dd714935eebd2c18aa1481147559f90..4f803060dbc801c17e68685ed9903762daa06ac2
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,655 +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 --combined s51/s51-main.c
index 0000000000000000000000000000000000000000,46b97b0c8ca7039c25867f9caa297cc0d72f121f..4dbd4c6036ebd72e0182aba47ca6fd81e466e191
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,240 +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);
 -              return 1; 
++
+                       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 --combined s51/s51-parse.c
index 0000000000000000000000000000000000000000,aba454859b94394e8711b60d76a2b6fc8dc6c687..170c979dbed599a1f99d643ce0fda2dd31f66351
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,242 +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 --combined s51/s51.1
index 0000000000000000000000000000000000000000,c283950e9b4e69993788c2f585d6426286292abc..f2f59a5286a6709fb96f4a66c5984cc381f3e680
mode 000000,100644..100644
--- /dev/null
+++ b/s51/s51.1
@@@ -1,0 -1,211 +1,211 @@@
 -.PP 
+ .\"
+ .\" 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"
 -\'s51\' command itself should connect to the device without trouble. 
++.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
index 0000000000000000000000000000000000000000,eba587440684b807e7b7c0e3303c30c0b1bd67ae..1f7b6880b1ffcb4133811cc7ad7ed8b9ce3781c7
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,578 +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 --combined target/adc/adc.c
index 0000000000000000000000000000000000000000,bdc6c6149aa27f0503911c5742bf77b3d1bf42ea..3a63a2c6c191a2f20626fffa959faafcda73246f
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,470 +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]);
+       }
+ }
index 0000000000000000000000000000000000000000,53b95495a657d607bc6cb87417b0f1b2dc57ad6a..b3fa8754206cf350f0c8e6680c67bc0bb27fc35e
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,204 +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 --combined target/dma/dma.c
index 0000000000000000000000000000000000000000,c35c39f6eefff930171fe33e583527270a5e2434..1762b65851f9041c357cc6438f7ea188c699d849
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,361 +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 --combined target/ee/ee.c
index 0000000000000000000000000000000000000000,7cc47120394a68ec54112826231fa5f58f588559..9ea22cdcc41fe74081e0a94c9ea0c10c22afe1df
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,407 +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 --combined target/isr.c
index 0000000000000000000000000000000000000000,43aedc298838b4a8b2afd578c24ae9330d076627..ae4d04c5802f8eaf395f065d16b7f286638674e5
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,90 +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 --combined target/radio/init.c
index 0000000000000000000000000000000000000000,c9b3d1861d2c53045fe6dfb8e8ec6615a75fc744..ea7c984c1b17cf3d24e8fa706f34b4a198122784
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,207 +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 --combined target/radio/recv.c
index 0000000000000000000000000000000000000000,1f50d8a95721ca3eb6832a6384136db183ead36a..c50c32055e35b164756d570da52f69d86fdecf72
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,68 +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 --combined target/serial/serial.c
index 0000000000000000000000000000000000000000,2939042635ca84d48e0ea586d9fa6d518ea9d1cd..63f6c6de0c32ec477249f2cfb5db3c0995f509a6
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,270 +1,270 @@@
 -      
+ /*
+  * 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 UART1
+  */
+ 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 MOSI  P1_5
+ #define MISO  P1_4
+ #define SCK   P1_3
+ #define CS    P1_2
+ #define DEBUG P1_1
+ #define USART 1
+ #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();
+ }
+ /*
+  * This version uses the USART in SPI 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);
+ }
+ uint8_t
+ usart_in_byte(void)
+ {
+       uint8_t b;
+       while ((U1CSR & UxCSR_RX_BYTE) == 0)
+               ;
+       b = U1DBUF;
+       U1CSR &= ~UxCSR_RX_BYTE;
+       return b;
+ }
+ void
+ debug_byte(uint8_t byte)
+ {
+       uint8_t s;
+       for (s = 0; s < 8; s++) {
+               DEBUG = byte & 1;
+               delay(5);
+               byte >>= 1;
+       }
+ }
+ main ()
+ {
+       P1DIR |= 2;
+       CLKCON = 0;
+       while (!(SLEEP & SLEEP_XOSC_STB))
+               ;
 -      
++
+       usart_init();
+       for (;;) {
+               usart_out_string("hello world\r\n");
+               debug_byte(usart_in_byte());
+       }
++
+ }
diff --combined target/timer/cc1111.h
index 0000000000000000000000000000000000000000,7a531cc0a04e3ef080c00875079d7b96f36520a7..76c95c2747a18351160a19b7cb1721f072c193d2
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,294 +1,294 @@@
 -  
+ /*-------------------------------------------------------------------------
+    Register Declarations for the ChipCon CC1111 Processor Range
+    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.
+    Adapted from the Cygnal C8051F12x config file which is:
 -sfr at 0xE1 RFST     ;  /*                                               */ 
 -sfr at 0xE2 T1CNTL   ;  /*                                               */ 
 -sfr at 0xE3 T1CNTH   ;  /*                                               */ 
 -sfr at 0xE4 T1CTL    ;  /*                                               */ 
 -sfr at 0xE5 T1CCTL0  ;  /*                                               */ 
 -sfr at 0xE6 T1CCTL1  ;  /*                                               */ 
 -sfr at 0xE7 T1CCTL2  ;  /*                                               */ 
 -sfr at 0xE8 IRCON2   ;  /*                                               */ 
 -sfr at 0xE9 RFIF     ;  /*                                               */ 
 -sfr at 0xEA T4CNT    ;  /*                                               */ 
 -sfr at 0xEB T4CTL    ;  /*                                               */ 
 -sfr at 0xEC T4CCTL0  ;  /*                                               */ 
 -sfr at 0xED T4CC0    ;  /*                                               */ 
 -sfr at 0xEE T4CCTL1  ;  /*                                               */ 
 -sfr at 0xEF T4CC1    ;  /*                                               */ 
 -sfr at 0xF0 B        ;  /*                                               */ 
 -sfr at 0xF1 PERCFG   ;  /*                                               */ 
 -sfr at 0xF2 ADCCFG   ;  /*                                               */ 
 -sfr at 0xF3 P0SEL    ;  /*                                               */ 
 -sfr at 0xF4 P1SEL    ;  /*                                               */ 
 -sfr at 0xF5 P2SEL    ;  /*                                               */ 
 -sfr at 0xF6 P1INP    ;  /*                                               */ 
 -sfr at 0xF7 P2INP    ;  /*                                               */ 
 -sfr at 0xF8 U1CSR    ;  /*                                               */ 
 -sfr at 0xF9 U1DBUF   ;  /*                                               */ 
 -sfr at 0xFA U1BAUD   ;  /*                                               */ 
 -sfr at 0xFB U1UCR    ;  /*                                               */ 
 -sfr at 0xFC U1GCR    ;  /*                                               */ 
 -sfr at 0xFD P0DIR    ;  /*                                               */ 
 -sfr at 0xFE P1DIR    ;  /*                                               */ 
 -sfr at 0xFF P2DIR    ;  /*                                               */ 
++
+    Copyright (C) 2003 - Maarten Brock, sourceforge.brock@dse.nl
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ -------------------------------------------------------------------------*/
+ #ifndef _CC1111_H_
+ #define _CC1111_H_
+ /*  BYTE Registers  */
+ sfr at 0x80 P0       ;  /* PORT 0                                        */
+ sfr at 0x81 SP       ;  /* STACK POINTER                                 */
+ sfr at 0x82 DPL      ;  /* DATA POINTER - LOW BYTE                       */
+ sfr at 0x83 DPH      ;  /* DATA POINTER - HIGH BYTE                      */
+ sfr at 0x84 DPL1     ;  /* DATA POINTER 1 - LOW BYTE                     */
+ sfr at 0x85 DPH1     ;  /* DATA POINTER 1 - HIGH BYTE                    */
+ sfr at 0x86 U0CSR    ;  /* USART 0 Control and status                    */
+ sfr at 0x87 PCON     ;  /* POWER CONTROL                                 */
+ sfr at 0x88 TCON     ;  /* TIMER CONTROL                                 */
+ sfr at 0x89 P0IFG    ;  /* TIMER MODE                                    */
+ sfr at 0x8A P1IFG    ;  /* TIMER 0 - LOW BYTE                            */
+ sfr at 0x8B P2IFG    ;  /* TIMER 1 - LOW BYTE                            */
+ sfr at 0x8C PICTL    ;  /* TIMER 0 - HIGH BYTE                           */
+ sfr at 0x8D P1IEN    ;  /* TIMER 1 - HIGH BYTE                           */
+ sfr at 0x8F P0INP    ;  /* FLASH WRITE/ERASE CONTROL                     */
+ sfr at 0x90 P1       ;  /* PORT 1                                        */
+ sfr at 0x91 RFIM     ;  /* UART 0 STATUS                                 */
+ sfr at 0x92 DPS      ;  /* */
+ sfr at 0x93 MPAGE    ;  /* */
+ sfr at 0x94 _SFR94_  ;  /* */
+ sfr at 0x95 ENDIAN   ;  /* */
+ sfr at 0x96 _SFR96_  ;  /* */
+ sfr at 0x97 _SFR97_  ;  /* */
+ sfr at 0x98 S0CON    ;  /* UART 0 CONTROL                                */
+ sfr at 0x99 _SFR99_  ;  /* UART 0 BUFFER                                 */
+ sfr at 0x9A IEN2     ;  /* SPI 0 CONFIGURATION                           */
+ sfr at 0x9B S1CON    ;  /* SPI 0 DATA                                    */
+ sfr at 0x9C T2CT     ;  /* SPI 0 DATA                                    */
+ sfr at 0x9D T2PR     ;  /* SPI 0 CLOCK RATE CONTROL                      */
+ sfr at 0x9E T2CTL    ;  /* SPI 0 CLOCK RATE CONTROL                      */
+ sfr at 0x9F _SFR9F_  ;  /* SPI 0 CLOCK RATE CONTROL                      */
+ sfr at 0xA0 P2       ;  /* PORT 2                                        */
+ sfr at 0xA1 WORIRQ   ;  /* EMIF TIMING CONTROL                           */
+ sfr at 0xA2 WORCTRL  ;  /* EMIF CONTROL                                  */
+ sfr at 0xA3 WOREVT0  ;  /* EMIF CONFIGURATION                            */
+ sfr at 0xA4 WOREVT1  ;  /* EMIF CONFIGURATION                            */
+ sfr at 0xA5 WORTIME0 ;  /* EMIF CONFIGURATION                            */
+ sfr at 0xA6 WORTIME1 ;  /* EMIF CONFIGURATION                            */
+ sfr at 0xA7 _SFRA7_  ;  /* EMIF CONFIGURATION                            */
+ sfr at 0xA8 IEN0     ;  /* INTERRUPT ENABLE                              */
+ sfr at 0xA9 IP0      ;  /* UART 0 SLAVE ADDRESS                          */
+ sfr at 0xAA _SFRAA_  ;  /*                                               */
+ sfr at 0xAB FWT      ;  /*                                               */
+ sfr at 0xAC FADDRL   ;  /*                                               */
+ sfr at 0xAD FADDRH   ;  /*                                               */
+ sfr at 0xAE FCTL     ;  /*                                               */
+ sfr at 0xAF FWDATA   ;  /*                                               */
+ sfr at 0xB0 _SFRB0_  ;  /*                                               */
+ sfr at 0xB1 ENCDI    ;  /* FLASH BANK SELECT                             */
+ sfr at 0xB2 ENCDO    ;  /*                                               */
+ sfr at 0xB3 ENCCS    ;  /*                                               */
+ sfr at 0xB4 ADCCON1  ;  /*                                               */
+ sfr at 0xB5 ADCCON2  ;  /*                                               */
+ sfr at 0xB6 ADCCON3  ;  /*                                               */
+ sfr at 0xB8 IEN1     ;  /* INTERRUPT PRIORITY                            */
+ sfr at 0xB9 IP1      ;  /*                                               */
+ sfr at 0xBA ADCL     ;  /*                                               */
+ sfr at 0xBB ADCH     ;  /*                                               */
+ sfr at 0xBC RNDL     ;  /*                                               */
+ sfr at 0xBD RNDH     ;  /*                                               */
+ sfr at 0xBE SLEEP    ;  /*                                               */
+ sfr at 0xC0 IRCON    ;  /*                                               */
+ sfr at 0xC1 U0DBUF   ;  /*                                               */
+ sfr at 0xC2 U0BAUD   ;  /*                                               */
+ sfr at 0xC4 U0UCR    ;  /*                                               */
+ sfr at 0xC5 U0GCR    ;  /*                                               */
+ sfr at 0xC6 CLKCON   ;  /*                                               */
+ sfr at 0xC7 MEMCTR   ;  /*                                               */
+ sfr at 0xC9 WDCTL    ;  /*                                               */
+ sfr at 0xCA T3CNT    ;  /*                                               */
+ sfr at 0xCB T3CTL    ;  /*                                               */
+ sfr at 0xCC T3CCTL0  ;  /*                                               */
+ sfr at 0xCD T3CC0    ;  /*                                               */
+ sfr at 0xCE T3CCTL1  ;  /*                                               */
+ sfr at 0xCF T3CC1    ;  /*                                               */
+ sfr at 0xD0 PSW      ;  /*                                               */
+ sfr at 0xD1 DMAIRQ   ;  /*                                               */
+ sfr at 0xD2 DMA1CFGL ;  /*                                               */
+ sfr at 0xD3 DMA1CFGH ;  /*                                               */
+ sfr at 0xD4 DMA0CFGL ;  /*                                               */
+ sfr at 0xD5 DMA0CFGH ;  /*                                               */
+ sfr at 0xD6 DMAARM   ;  /*                                               */
+ sfr at 0xD7 DMAREQ   ;  /*                                               */
+ sfr at 0xD8 TIMIF    ;  /*                                               */
+ sfr at 0xD9 RFD      ;  /*                                               */
+ sfr at 0xDA T1CC0L   ;  /*                                               */
+ sfr at 0xDB T1CC0H   ;  /*                                               */
+ sfr at 0xDC T1CC1L   ;  /*                                               */
+ sfr at 0xDD T1CC1H   ;  /*                                               */
+ sfr at 0xDE T1CC2L   ;  /*                                               */
+ sfr at 0xDF T1CC2H   ;  /*                                               */
+ sfr at 0xE0 ACC      ;  /* ACCUMULATOR                                   */
++sfr at 0xE1 RFST     ;  /*                                               */
++sfr at 0xE2 T1CNTL   ;  /*                                               */
++sfr at 0xE3 T1CNTH   ;  /*                                               */
++sfr at 0xE4 T1CTL    ;  /*                                               */
++sfr at 0xE5 T1CCTL0  ;  /*                                               */
++sfr at 0xE6 T1CCTL1  ;  /*                                               */
++sfr at 0xE7 T1CCTL2  ;  /*                                               */
++sfr at 0xE8 IRCON2   ;  /*                                               */
++sfr at 0xE9 RFIF     ;  /*                                               */
++sfr at 0xEA T4CNT    ;  /*                                               */
++sfr at 0xEB T4CTL    ;  /*                                               */
++sfr at 0xEC T4CCTL0  ;  /*                                               */
++sfr at 0xED T4CC0    ;  /*                                               */
++sfr at 0xEE T4CCTL1  ;  /*                                               */
++sfr at 0xEF T4CC1    ;  /*                                               */
++sfr at 0xF0 B        ;  /*                                               */
++sfr at 0xF1 PERCFG   ;  /*                                               */
++sfr at 0xF2 ADCCFG   ;  /*                                               */
++sfr at 0xF3 P0SEL    ;  /*                                               */
++sfr at 0xF4 P1SEL    ;  /*                                               */
++sfr at 0xF5 P2SEL    ;  /*                                               */
++sfr at 0xF6 P1INP    ;  /*                                               */
++sfr at 0xF7 P2INP    ;  /*                                               */
++sfr at 0xF8 U1CSR    ;  /*                                               */
++sfr at 0xF9 U1DBUF   ;  /*                                               */
++sfr at 0xFA U1BAUD   ;  /*                                               */
++sfr at 0xFB U1UCR    ;  /*                                               */
++sfr at 0xFC U1GCR    ;  /*                                               */
++sfr at 0xFD P0DIR    ;  /*                                               */
++sfr at 0xFE P1DIR    ;  /*                                               */
++sfr at 0xFF P2DIR    ;  /*                                               */
+ /*  BIT Registers  */
+ /*  P0  0x80 */
+ sbit at 0x80 P0_0    ;
+ sbit at 0x81 P0_1    ;
+ sbit at 0x82 P0_2    ;
+ sbit at 0x83 P0_3    ;
+ sbit at 0x84 P0_4    ;
+ sbit at 0x85 P0_5    ;
+ sbit at 0x86 P0_6    ;
+ sbit at 0x87 P0_7    ;
+ /*  TCON  0x88 */
+ sbit at 0x89 RFTXRXIF;  /*                                               */
+ sbit at 0x8B URX0IF  ;  /*                                               */
+ sbit at 0x8D ADCIF   ;  /*                                               */
+ sbit at 0x8F URX1IF  ;  /*                                               */
+ sbit at 0x8F I2SRXIF ;  /*                                               */
+ /*  SCON0  0x98 */
+ sbit at 0x98 ENCIF_0 ;  /* UART 0 RX INTERRUPT FLAG                      */
+ sbit at 0x99 ENCIF_1 ;  /* UART 0 RX INTERRUPT FLAG                      */
+ /*  IEN0  0xA8 */
+ sbit at 0xA8 RFTXRXIE;  /* RF TX/RX done interrupt enable                */
+ sbit at 0xA9 ADCIE   ;  /* ADC interrupt enable                          */
+ sbit at 0xAA URX0IE  ;  /* USART0 RX interrupt enable                    */
+ sbit at 0xAB URX1IE  ;  /* USART1 RX interrupt enable                    */
+ sbit at 0xAB I2SRXIE ;  /* I2S RX interrupt enable                       */
+ sbit at 0xAC ENCIE   ;  /* AES interrupt enable                          */
+ sbit at 0xAD STIE    ;  /* Sleep Timer interrupt enable                  */
+ sbit at 0xAF EA      ;  /* GLOBAL INTERRUPT ENABLE                       */
+ /*  IEN1  0xB8 */
+ sbit at 0xB8 DMAIE   ;  /* DMA transfer interrupt enable                 */
+ sbit at 0xB9 T1IE    ;  /* Timer 1 interrupt enable                      */
+ sbit at 0xBA T2IE    ;  /* Timer 2 interrupt enable                      */
+ sbit at 0xBB T3IE    ;  /* Timer 3 interrupt enable                      */
+ sbit at 0xBC T4IE    ;  /* Timer 4 interrupt enable                      */
+ sbit at 0xBD P0IE    ;  /* Port 0 interrupt enable                       */
+ /* IRCON 0xC0 */
+ sbit at 0xC0 DMAIF   ;  /*                                             */
+ sbit at 0xC1 T1IF    ;  /*                                             */
+ sbit at 0xC2 T2IF    ;  /*                                             */
+ sbit at 0xC3 T3IF    ;  /*                                             */
+ sbit at 0xC4 T4IF    ;  /*                                             */
+ sbit at 0xC5 P0IF    ;  /*                                             */
+ sbit at 0xC7 STIF    ;  /*                                             */
+ /*  PSW  0xD0 */
+ sbit at 0xD0 P       ;  /* ACCUMULATOR PARITY FLAG                       */
+ sbit at 0xD1 F1      ;  /* USER FLAG 1                                   */
+ sbit at 0xD2 OV      ;  /* OVERFLOW FLAG                                 */
+ sbit at 0xD3 RS0     ;  /* REGISTER BANK SELECT 0                        */
+ sbit at 0xD4 RS1     ;  /* REGISTER BANK SELECT 1                        */
+ sbit at 0xD5 F0      ;  /* USER FLAG 0                                   */
+ sbit at 0xD6 AC      ;  /* AUXILIARY CARRY FLAG                          */
+ sbit at 0xD7 CY      ;  /* CARRY FLAG                                    */
+ /* TIMIF D8H */
+ sbit at 0xD8 T3OVFIF ;  /*                                               */
+ sbit at 0xD9 T3CH0IF ;  /*                                               */
+ sbit at 0xDA T3CH1IF ;  /*                                               */
+ sbit at 0xDB T4OVFIF ;  /*                                               */
+ sbit at 0xDC T4CH0IF ;  /*                                               */
+ sbit at 0xDD T4CH1IF ;  /*                                               */
+ sbit at 0xDE OVFIM   ;  /*                                               */
+ /* IRCON2  E8H */
+ sbit at 0xE8 P2IF    ;  /*                                                     */
+ sbit at 0xE8 USBIF   ;  /*                                                     */
+ sbit at 0xE9 UTX0IF  ;  /*                                                     */
+ sbit at 0xEA UTX1IF  ;  /*                                                     */
+ sbit at 0xEA I2STXIF ;  /*                                                     */
+ sbit at 0xEB P1IF    ;  /*                                                     */
+ sbit at 0xEC WDTIF   ;  /*                                                     */
+ /* U1CSR F8H */
+ sbit at 0xF8 U1_ACTIVE  ;  /*                                               */
+ sbit at 0xF9 U1_TX_BYTE ;  /*                                               */
+ sbit at 0xFA U1_RX_BYTE ;  /*                                               */
+ sbit at 0xFB U1_ERR     ;  /*                                               */
+ sbit at 0xFC U1_FE      ;  /*                                               */
+ sbit at 0xFD U1_SLAVE   ;  /*                                               */
+ sbit at 0xFE U1_RE      ;  /*                                               */
+ sbit at 0xFF U1_MODE    ;  /*                                               */
+ #define T1CTL_MODE_SUSPENDED  (0 << 0)
+ #define T1CTL_MODE_FREE               (1 << 0)
+ #define T1CTL_MODE_MODULO     (2 << 0)
+ #define T1CTL_MODE_UP_DOWN    (3 << 0)
+ #define T1CTL_MODE_MASK               (3 << 0)
+ #define T1CTL_DIV_1           (0 << 2)
+ #define T1CTL_DIV_8           (1 << 2)
+ #define T1CTL_DIV_32          (2 << 2)
+ #define T1CTL_DIV_128         (3 << 2)
+ #define T1CTL_DIV_MASK                (3 << 2)
+ #define T1CTL_OVFIF           (1 << 4)
+ #define T1CTL_CH0IF           (1 << 5)
+ #define T1CTL_CH1IF           (1 << 6)
+ #define T1CTL_CH2IF           (1 << 7)
+ #define T1CCTL_NO_CAPTURE     (0 << 0)
+ #define T1CCTL_CAPTURE_RISING (1 << 0)
+ #define T1CCTL_CAPTURE_FALLING        (2 << 0)
+ #define T1CCTL_CAPTURE_BOTH   (3 << 0)
+ #define T1CCTL_CAPTURE_MASK   (3 << 0)
+ #define T1CCTL_MODE_CAPTURE   (0 << 2)
+ #define T1CCTL_MODE_COMPARE   (1 << 2)
+ #define T1CTL_CMP_SET         (0 << 3)
+ #define T1CTL_CMP_CLEAR               (1 << 3)
+ #define T1CTL_CMP_TOGGLE      (2 << 3)
+ #define T1CTL_CMP_SET_CLEAR   (3 << 3)
+ #define T1CTL_CMP_CLEAR_SET   (4 << 3)
+ #define T1CTL_IM_DISABLED     (0 << 6)
+ #define T1CTL_IM_ENABLED      (1 << 6)
+ #define T1CTL_CPSEL_NORMAL    (0 << 7)
+ #define T1CTL_CPSEL_RF                (1 << 7)
+ #endif
diff --combined tests/debug_mode
index 0000000000000000000000000000000000000000,fe25bfef77d4b36a23a19615bd30ca981396fb85..2b5ec02047bb2484bceb167f8ff7bc32d35a3244
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,11 +1,10 @@@
 -
+ #
+ # Debug mode - drive RESET_N low for two clock cycles
+ #
+ C D R
+ . D .
+ C D .
+ . D .
+ C D .
+ . D R
diff --combined tests/get_status
index 0000000000000000000000000000000000000000,1d4ff03d3a3f0ac210338bf1cedb24a767672ac8..3e67a2e0d5b586239332eb517059d6e243670ab7
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,329 +1,328 @@@
 -
+ #
+ # Debug mode - drive RESET_N low for two clock cycles
+ #
+ C D R
+ . D .
+ C D .
+ . D .
+ C D .
+ . D R
+ #
+ # Halt 0x44
+ #
+ C . R 0
+ . . R
+ C D R 1
+ . D R
+ C . R 0
+ . . R
+ C . R 0
+ . . R
+ C . R 0
+ . . R
+ C D R 1
+ . D R
+ C . R 0
+ . . R
+ C . R 0
+ . . R
+ # status byte
+ C D R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ # Resume 0x4c
+ #
+ C . R 0
+ . . R
+ C D R 1
+ . D R
+ C . R 0
+ . . R
+ C . R 0
+ . . R
+ C D R 1
+ . D R
+ C D R 1
+ . D R
+ C . R 0
+ . . R
+ C . R 0
+ . . R
+ # status byte
+ C D R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ #
+ # READ_STATUS
+ #
+ C . R 0
+ . . R
+ C . R 0
+ . . R
+ C D R 1
+ . D R
+ C D R 1
+ . D R
+ C . R 0
+ . . R
+ C D R 1
+ . D R
+ C . R 0
+ . . R
+ C . R 0
+ . . R
+ #
+ # status
+ #
+ C D R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ #
+ # READ_STATUS
+ #
+ C . R 0
+ . . R
+ C . R 0
+ . . R
+ C D R 1
+ . D R
+ C D R 1
+ . D R
+ C . R 0
+ . . R
+ C D R 1
+ . D R
+ C . R 0
+ . . R
+ C . R 0
+ . . R
+ #
+ # status
+ #
+ C D R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ #
+ # READ_STATUS
+ #
+ C . R 0
+ . . R
+ C . R 0
+ . . R
+ C D R 1
+ . D R
+ C D R 1
+ . D R
+ C . R 0
+ . . R
+ C D R 1
+ . D R
+ C . R 0
+ . . R
+ C . R 0
+ . . R
+ #
+ # status
+ #
+ C D R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ #
+ # Halt 0x44
+ #
+ C . R 0
+ . . R
+ C D R 1
+ . D R
+ C . R 0
+ . . R
+ C . R 0
+ . . R
+ C . R 0
+ . . R
+ C D R 1
+ . D R
+ C . R 0
+ . . R
+ C . R 0
+ . . R
+ # status byte
+ C D R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ #
+ # READ_STATUS
+ #
+ C . R 0
+ . . R
+ C . R 0
+ . . R
+ C D R 1
+ . D R
+ C D R 1
+ . D R
+ C . R 0
+ . . R
+ C D R 1
+ . D R
+ C . R 0
+ . . R
+ C . R 0
+ . . R
+ #
+ # status
+ #
+ C D R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R
+ C - R
+ . - R