diff -Naur avrdude-cvs/avrdude.1 avrdude/avrdude.1
--- avrdude-cvs/avrdude.1	2004-02-09 16:20:51.000000000 -0800
+++ avrdude/avrdude.1	2004-06-16 08:49:13.000000000 -0700
@@ -432,6 +432,11 @@
 .It Ar fosc off
 Turn the master oscillator off.
 .Em Only supported on the STK500 programmer.
+.It Ar sck period
+Set the SCK clock period to
+.Ar period
+microseconds.
+.Em Only supported on the STK500 programmer.
 .It Ar parms
 Display the current voltage and master oscillator parameters.
 .Em Only supported on the STK500 programmer.
diff -Naur avrdude-cvs/doc/avrdude.texi avrdude/doc/avrdude.texi
--- avrdude-cvs/doc/avrdude.texi	2004-02-09 16:20:51.000000000 -0800
+++ avrdude/doc/avrdude.texi	2004-06-16 08:59:10.000000000 -0700
@@ -747,6 +747,9 @@
 @item fosc off
 Turn the master oscillator off.
 
+@item sck @var{period}
+Set the SCK clock period to @var{period} microseconds.
+
 @item parms
 Display the current voltage and master oscillator parameters.
 
diff -Naur avrdude-cvs/pgm.h avrdude/pgm.h
--- avrdude-cvs/pgm.h	2004-01-28 12:01:44.000000000 -0800
+++ avrdude/pgm.h	2004-06-16 08:30:44.000000000 -0700
@@ -76,6 +76,7 @@
   int  (*set_vtarget)    (struct programmer_t * pgm, double v);
   int  (*set_varef)      (struct programmer_t * pgm, double v);
   int  (*set_fosc)       (struct programmer_t * pgm, double v);
+  int  (*set_sck_period) (struct programmer_t * pgm, double v);
   char config_file[PATH_MAX]; /* config file where defined */
   int  lineno;                /* config file line number */
 } PROGRAMMER;
diff -Naur avrdude-cvs/stk500.c avrdude/stk500.c
--- avrdude-cvs/stk500.c	2004-05-19 16:00:38.000000000 -0700
+++ avrdude/stk500.c	2004-06-16 09:55:59.000000000 -0700
@@ -41,6 +41,7 @@
 #include "stk500_private.h"
 #include "serial.h"
 
+#define STK500_XTAL 7372800U
 
 extern int    verbose;
 extern char * progname;
@@ -889,7 +890,6 @@
 
 static int stk500_set_fosc(PROGRAMMER * pgm, double v)
 {
-#define fbase 7372800U
   unsigned prescale, cmatch, fosc;
   static unsigned ps[] = {
     1, 8, 32, 64, 128, 256, 1024
@@ -898,7 +898,7 @@
 
   prescale = cmatch = 0;
   if (v > 0.0) {
-    if (v > fbase / 2) {
+    if (v > STK500_XTAL / 2) {
       const char *unit;
       if (v > 1e6) {
         v /= 1e6;
@@ -910,22 +910,22 @@
         unit = "Hz";
       fprintf(stderr,
           "%s: stk500_set_fosc(): f = %.3f %s too high, using %.3f MHz\n",
-          progname, v, unit, fbase / 2e6);
-      fosc = fbase / 2;
+          progname, v, unit, STK500_XTAL / 2e6);
+      fosc = STK500_XTAL / 2;
     } else
       fosc = (unsigned)v;
     
     for (idx = 0; idx < sizeof(ps) / sizeof(ps[0]); idx++) {
-      if (fosc >= fbase / (256 * ps[idx] * 2)) {
+      if (fosc >= STK500_XTAL / (256 * ps[idx] * 2)) {
         /* this prescaler value can handle our frequency */
         prescale = idx + 1;
-        cmatch = (unsigned)(fbase / (2 * v * ps[idx]));
+        cmatch = (unsigned)(STK500_XTAL / (2 * v * ps[idx]));
         break;
       }
     }
     if (idx == sizeof(ps) / sizeof(ps[0])) {
       fprintf(stderr, "%s: stk500_set_fosc(): f = %u Hz too low, %u Hz min\n",
-          progname, fosc, fbase / (256 * 1024 * 2));
+          progname, fosc, STK500_XTAL / (256 * 1024 * 2));
       return -1;
     }
   }
@@ -938,6 +938,38 @@
 }
 
 
+/* This code assumes that each count of the SCK duration parameter
+   represents 8/f, where f is the clock frequency of the STK500 master
+   processors (not the target).  This number comes from Atmel
+   application note AVR061.  It appears that the STK500 bit bangs SCK.
+   For small duration values, the actual SCK width is larger than
+   expected.  As the duration value increases, the SCK width error
+   diminishes. */
+static int stk500_set_sck_period(PROGRAMMER * pgm, double v)
+{
+  int dur;
+  double min, max;
+
+  min = 8.0 / STK500_XTAL;
+  max = 255 * min;
+  dur = v / min + 0.5;
+  
+  if (v < min) {
+      dur = 1;
+      fprintf(stderr,
+	      "%s: stk500_set_sck_period(): p = %.1f us too small, using %.1f us\n",
+	      progname, v / 1e-6, dur * min / 1e-6);
+  } else if (v > max) {
+      dur = 255;
+      fprintf(stderr,
+	      "%s: stk500_set_sck_period(): p = %.1f us too large, using %.1f us\n",
+	      progname, v / 1e-6, dur * min / 1e-6);
+  }
+  
+  return stk500_setparm(pgm, Parm_STK_SCK_DURATION, dur);
+}
+
+
 static int stk500_getparm(PROGRAMMER * pgm, unsigned parm, unsigned * value)
 {
   unsigned char buf[16];
@@ -1081,12 +1113,13 @@
 
 static void stk500_print_parms1(PROGRAMMER * pgm, char * p)
 {
-  unsigned vtarget, vadjust, osc_pscale, osc_cmatch;
+  unsigned vtarget, vadjust, osc_pscale, osc_cmatch, sck_duration;
 
   stk500_getparm(pgm, Parm_STK_VTARGET, &vtarget);
   stk500_getparm(pgm, Parm_STK_VADJUST, &vadjust);
   stk500_getparm(pgm, Parm_STK_OSC_PSCALE, &osc_pscale);
   stk500_getparm(pgm, Parm_STK_OSC_CMATCH, &osc_cmatch);
+  stk500_getparm(pgm, Parm_STK_SCK_DURATION, &sck_duration);
 
   fprintf(stderr, "%sVtarget         : %.1f V\n", p, vtarget / 10.0);
   fprintf(stderr, "%sVaref           : %.1f V\n", p, vadjust / 10.0);
@@ -1095,7 +1128,7 @@
     fprintf(stderr, "Off\n");
   else {
     int prescale = 1;
-    double f = 3.6864e6;
+    double f = STK500_XTAL / 2;
     const char *unit;
 
     switch (osc_pscale) {
@@ -1118,6 +1151,8 @@
       unit = "Hz";
     fprintf(stderr, "%.3f %s\n", f, unit);
   }
+  fprintf(stderr, "%sSCK period      : %.1f us\n", p, 
+	  sck_duration * 8.0e6 / STK500_XTAL + 0.05);
 
   return;
 }
@@ -1155,5 +1190,6 @@
   pgm->set_vtarget    = stk500_set_vtarget;
   pgm->set_varef      = stk500_set_varef;
   pgm->set_fosc       = stk500_set_fosc;
+  pgm->set_sck_period = stk500_set_sck_period;
   pgm->page_size      = 256;
 }
diff -Naur avrdude-cvs/term.c avrdude/term.c
--- avrdude-cvs/term.c	2003-11-21 19:25:48.000000000 -0800
+++ avrdude/term.c	2004-06-16 08:44:10.000000000 -0700
@@ -76,6 +76,8 @@
 
 int cmd_fosc  (PROGRAMMER * pgm, struct avrpart * p, int argc, char *argv[]);
 
+int cmd_sck   (PROGRAMMER * pgm, struct avrpart * p, int argc, char *argv[]);
+
 
 struct command cmd[] = {
   { "dump",  cmd_dump,  "dump memory  : %s <memtype> <addr> <N-Bytes>" },
@@ -89,6 +91,7 @@
   { "vtarg", cmd_vtarg, "set <V[target]> (STK500 only)" },
   { "varef", cmd_varef, "set <V[aref]> (STK500 only)" },
   { "fosc",  cmd_fosc,  "set <oscillator frequency> (STK500 only)" },
+  { "sck",   cmd_sck,   "set <SCK period> (STK500 only)" },
   { "help",  cmd_help,  "help" },
   { "?",     cmd_help,  "help" },
   { "quit",  cmd_quit,  "quit" }
@@ -595,6 +598,38 @@
 }
 
 
+int cmd_sck(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[])
+{
+  int rc;
+  double v;
+  char *endp;
+
+  if (argc != 2) {
+    fprintf(stderr, "Usage: sck <value>\n");
+    return -1;
+  }
+  v = strtod(argv[1], &endp);
+  if (endp == argv[1]) {
+    fprintf(stderr, "%s (sck): can't parse period \"%s\"\n",
+	    progname, argv[1]);
+    return -1;
+  }
+  v *= 1e-6;			/* Convert from microseconds to seconds. */
+  if (pgm->set_sck_period == NULL) {
+    fprintf(stderr,
+	    "%s (sck): the %s programmer cannot set SCK period\n",
+	    progname, pgm->type);
+    return -2;
+  }
+  if ((rc = pgm->set_sck_period(pgm, v)) != 0) {
+    fprintf(stderr, "%s (sck): failed to set SCK period (rc = %d)\n",
+	    progname, rc);
+    return -3;
+  }
+  return 0;
+}
+
+
 int cmd_varef(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[])
 {
   int rc;
