Code to drive a CNC machine via a PC LPT port lookalike 25 pin 'D', experiment in 'PC/Mach3' replacement. Designed to compile and run on mbed LPC1768, Freescale KL25Z and Freescale KL46Z. Proved on LPC1768 and KL25Z, problem with serial port on KL46Z. Reads subset of 'G Codes' through usb/serial port and drives 3 stepper/servo drives for X, Y and Z, also similar Step/Dir outputs for spindle motor control. Emulates PC LPT, outputs 'charge pump', proved driving Seig KX3 CNC mill

Dependencies:   MODSERIAL mbed

Files at this revision

API Documentation at this revision

Comitter:
JonFreeman
Date:
Thu Feb 20 09:27:18 2014 +0000
Parent:
1:66ee619f206b
Child:
3:7aaf0072cc22
Commit message:
As used to produce Lissajous patterns for EiM articles. XYZ axis good, Axis A not implemented, spindle 'S' working. Using MODSERIAL, therefore no longer compatible with KL46Z, good for KL25Z and Mbed LPC1768

Changed in this revision

MODSERIAL.lib Show annotated file Show diff for this revision Revisions of this file
arith.cpp Show annotated file Show diff for this revision Revisions of this file
cnc.h Show annotated file Show diff for this revision Revisions of this file
command_interpreter.cpp Show annotated file Show diff for this revision Revisions of this file
lissajous.cpp Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-rtos-marcusbirkin.lib Show annotated file Show diff for this revision Revisions of this file
mbed-rtos.lib Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MODSERIAL.lib	Thu Feb 20 09:27:18 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/Sissors/code/MODSERIAL/#f42def64c4ee
--- a/arith.cpp	Thu Feb 06 08:45:02 2014 +0000
+++ b/arith.cpp	Thu Feb 20 09:27:18 2014 +0000
@@ -4,18 +4,21 @@
 
 const   double  ball_screw_pitch_mm   =   4.0,    //  KX3 has 4mm ball screws
                 motor_step_per_rev  =   200.0,    //  KX3 has 200 step per rev steppers
-                micro_steps         =   20.0,      //  Arc Eurotrade choice 2,4,5,8,10,16,20,25,32,40,50,64,100,125,128
+                micro_steps         =   10.0,      //  Arc Eurotrade choice 2,4,5,8,10,16,20,25,32,40,50,64,100,125,128
                 pulses_per_mm       =   micro_steps * motor_step_per_rev / ball_screw_pitch_mm,
 
-                interrupt_period_us =   24.0, //16 is possible with Mbed LPC1768
+                interrupt_period_us =   32.0,//24.0, //16 is possible with Mbed LPC1768
                 interrupt_freq_Hz   =   1000000.0 / interrupt_period_us,  //  Serious limit when doing all in software, no real limit with FPGA
-                max_pulse_freq_Hz   =   interrupt_freq_Hz / 4.5,  //  strictly 4, but allow a good margin
+                max_pulse_freq_Hz   =   interrupt_freq_Hz / 3.25,  //  strictly 2.0, but allow a good margin
                 max_mm_per_min      =   60.0 * max_pulse_freq_Hz / pulses_per_mm,
-                n_for_onemmpermin   = pulses_per_mm * interrupt_period_us * pow(2.0,32) / 60000000.0, //  n pir to produce 1mm/min travel
+//                n_for_onemmpermin   = pulses_per_mm * interrupt_period_us * pow(2.0,32) / 60000000.0, //  n pir to produce 1mm/min travel
+                n_for_onemmpermin   = pulses_per_mm * interrupt_period_us * pow(2.0,31) / 60000000.0, //  n pir to produce 1mm/min travel
+                //  note power reduced from 32to 31 as interrupt handler now issued step pulse on both edges
                 feed_rate_max       = max_mm_per_min,
+                spindle_factor      = interrupt_period_us * 4280,
                 spindle_max         = 5000.0;
 //The output frequency F<sub>out</sub> = 'Kernel Speed (Hz)' * n / (2 to the power of 32)
-
+    
 struct  Gparams    last_position;
 void    grain_clr   (struct singleGparam & g)  {
     g.dbl = 0.0;
--- a/cnc.h	Thu Feb 06 08:45:02 2014 +0000
+++ b/cnc.h	Thu Feb 20 09:27:18 2014 +0000
@@ -1,3 +1,8 @@
+#define ESTOP   0x100   //  bits used in input reading
+#define XLIM    1
+#define YLIM    2
+#define ZLIM    4
+#define UNKN    8
 const   double  TWO_PI = 8.0 * atan(1.0);
 const   double  epsilon = 1e-5;
 struct  pirbufgrain {
@@ -19,11 +24,6 @@
     struct  singleGparam   x, y, z, i, j, r, a, b, c, d;   //  After sorting, know where to find any X, Y etc values !
 }   ;
 
-struct  digital_readouts    {   //  DROs keep count of 'Step' positive edges detected in interrupt handler
-    signed long x, y, z;    //  Could easily expand up to six or more dros
-    bool    dro_output;             //  To enabe / disable output to terminal
-}   ;
-
-extern  const double  n_for_onemmpermin, feed_rate_max, feed_rate_min, spindle_min, spindle_max;
+extern  const double  n_for_onemmpermin, feed_rate_max, feed_rate_min, spindle_min, spindle_max, spindle_factor;
 //extern  const   long  pulses_per_mm, max_mm_per_min, interrupt_period_us;
 extern  const   double  pulses_per_mm, max_mm_per_min, interrupt_period_us;
--- a/command_interpreter.cpp	Thu Feb 06 08:45:02 2014 +0000
+++ b/command_interpreter.cpp	Thu Feb 20 09:27:18 2014 +0000
@@ -1,17 +1,21 @@
 #include "mbed.h"
 #include "rtos.h"
+#include "MODSERIAL.h"
 #include "cnc.h"
 using namespace std;
 
-extern  Serial pc;
-extern  bool    liss_active;
-extern  unsigned long pir_s;
-extern  int spindlefwdrev;
+extern  MODSERIAL pc;
+//extern  Serial pc;
+//extern  bool    liss_active;
 extern  struct  Gparams    last_position;
-extern  int PutMoveOnList   (struct pirbufgrain & s)    ;
-extern  struct  digital_readouts    dro;    //
+extern  void    move_to_XYZ   (struct pirbufgrain & ins)   ;
+//extern  struct  digital_readouts    dro;    //
+//extern  void    scmd (struct singleGparam * a)   ;
+extern  void    flags_report_cmd (struct singleGparam * a)   ;
+extern  void    report_inputs   ()  ;
 
-double  feed_rate = 1.0;  //  global scope, mm per minute. DEFAULTS to 1.0mm per min, very slow.
+double  feed_rate = 1.0,  //  global scope, mm per minute. DEFAULTS to 1.0mm per min, very slow.
+        spindle_rpm = 0.0;  //  global scope
 
 bool    isdigit (int a)
 {
@@ -122,29 +126,6 @@
     }
 }
 
-const   double  duration_multiplier =   60000000.0 /  interrupt_period_us;
-
-void    mover   (struct pirbufgrain & ins)   {
-    struct  pirbufgrain outs;
-    double  distx   = ins.x - last_position.x.dbl,
-            disty   = ins.y - last_position.y.dbl,
-            distz   = ins.z - last_position.z.dbl,
-            distT   = sqrt ((distx * distx) + (disty * disty) + (distz * distz)), // 3D Pythag !
-            temp    = n_for_onemmpermin / distT;
-    if  (distT < 0.01)  {
-        pc.printf("Very small move %.4f, Ignoring!\r\n", distT);
-        return;
-    }
-    last_position.x.dbl   = ins.x;     //  Update global last_position record
-    last_position.y.dbl   = ins.y;
-    last_position.z.dbl   = ins.z;
-    outs.f_rate = ins.f_rate;
-    outs.c  = duration_multiplier * distT;   //  Duration ticks subject to feed rate compo
-    outs.x = temp * distx;
-    outs.y = temp * disty;
-    outs.z = temp * distz;  //  Have assembled data ready to put onto queue of move instructions
-    PutMoveOnList   (outs);
-}
 
 void    g2g3cmdcore (struct singleGparam * source_array, int twoorthree) {
     struct  Gparams tmp;
@@ -222,6 +203,8 @@
                 next_point.z += z_step; 
                 pc.printf("X %.3f, Y %.3f\r\n", next_point.x, next_point.y);
                 Thread::wait(300);
+                next_point.f_rate = feed_rate;
+                move_to_XYZ (next_point);
             }
         break;  //  end of case    2:  //  Centre format arc ** OFFSETS ARE RELATIVE ** Abs coordinates not catered for
         default:    //  Input error detected
@@ -232,8 +215,7 @@
 
 void    g0g1cmdcore (struct singleGparam * source_array, double f_rate)    //  Updates any / all of x, y, z NCOs
 {   //  Only get here when some G0 or G1 input has been read.  G0 or G1 determined by f_rate
-    struct  pirbufgrain ins, outs;
-    double  distx, disty, distz;//, outx, outy, outz, outtimefactor;
+    struct  pirbufgrain ins;//, outs;
     struct  Gparams tmp;
     get_codepositions   (source_array, tmp);  //  will overwrite with new where entered
     if  (!tmp.x.changed && !tmp.y.changed && !tmp.z.changed)    {
@@ -244,41 +226,7 @@
     ins.y  = tmp.y.dbl;
     ins.z  = tmp.z.dbl;
     ins.f_rate = f_rate;
-    distx  = ins.x - last_position.x.dbl;     //  All doubles
-    disty  = ins.y - last_position.y.dbl;
-    distz  = ins.z - last_position.z.dbl;
-    double  distT = sqrt ((distx * distx) + (disty * disty) + (distz * distz));
-    if  (distT < 0.01)  {
-        pc.printf("Very small move %.4f, Ignoring!\r\n", distT);
-        return;
-    }
-    if  (f_rate > feed_rate_max)   {
-        pc.printf("WARNING Stupid feed rate in G0/G1 of %f, setting to %f\r\n", f_rate, feed_rate_max);
-        f_rate = feed_rate_max;
-    }
-    if  (f_rate < 0.0)  {
-        pc.printf("Bonkers neg feed rate %f, setting to 0");
-        f_rate = 0.0;
-    }
-    double  temp    = n_for_onemmpermin / distT;
-//    pc.printf("\nG0--G1 Moving to  X %4.4f, Y %4.4f, Z%4.4f, distT %f\r\n", px, py, pz, distT);
-//    pc.printf("Moving From pos'n X %4.4f, Y %4.4f, Z%4.4f\r\n", last_position.x.dbl, last_position.y.dbl, last_position.z.dbl);
-//    pc.printf("Distances to move X %4.4f, Y %4.4f, Z%4.4f\r\n", distx, disty, distz);
-//    pc.printf("mm per sec req'd  X %4.4f, Y %4.4f, Z%4.4f\r\n", xmmps, ymmps, zmmps);
-    pc.printf("Total move distance %4.4f, at feed rate %.2f, run time SECs = %f\r\n", distT, f_rate, 60.0 * distT / f_rate);
-//    pc.printf("This time maps to %f interrupt ticks\r\n", run_secs * 1000000.0 / interrupt_period_us);
-    last_position.x.dbl   = ins.x;     //  Update global last_position record
-    last_position.y.dbl   = ins.y;
-    last_position.z.dbl   = ins.z;
-    outs.f_rate = ins.f_rate;
-    outs.c  = duration_multiplier * distT;   //  Duration ticks subject to feed rate compo
-    outs.x = temp * distx;
-    outs.y = temp * disty;
-    outs.z = temp * distz;
-//    pc.printf("Dists Scaled for angle, X%f, Y%f, Z%f\r\n", outs.x, outs.y, outs.z);
-//    pc.printf("Last position X%f, Y%f, Z%f\r\n", last_position.x.dbl, last_position.y.dbl, last_position.z.dbl);
-//    outs.a.dbl = 0.0;     // not used axis
-    PutMoveOnList (outs);
+    move_to_XYZ (ins);
 }
 
 void    g0cmd (struct singleGparam * a)    //  Updates any / all of x, y, z NCOs
@@ -291,36 +239,59 @@
     g0g1cmdcore (a, feed_rate);     //  Settable feed_rate
 }
 
+void    g2cmd (struct singleGparam * a)   { //  Clockwise arc
+    g2g3cmdcore (a, 2);
+}
+
+void    g3cmd (struct singleGparam * a)   { //  Counter clockwise arc
+    g2g3cmdcore (a, 3);
+}
+
 void    fcmd (struct singleGparam * a)   {  //  Set Feed Rate command
     if  (a[1].dbl < 0.0)    {
-        pc.printf("feed rate %f ? Setting to 0\r\n", a[1].dbl);
+        pc.printf("feed rate %.1f ? Setting to 0\r\n", a[1].dbl);
         a[1].dbl = 0.0;
     }
     if  (a[1].dbl > feed_rate_max)    {
-        pc.printf   ("Error, can't set feed rate to %f, max is %f, ", a[1].dbl, feed_rate_max);
+        pc.printf   ("Error, can't set feed rate to %.1f, max is %.1f, ", a[1].dbl, feed_rate_max);
         a[1].dbl = feed_rate_max;
     }
-    pc.printf   ("Setting feed_rate to %f\r\n", a[1].dbl);
+    pc.printf   ("Setting feed_rate to %.1f\r\n", a[1].dbl);
     feed_rate = a[1].dbl;
 }
+extern  void    spindle_control (double ss)  ;
+extern  bool    spindle_running ()  ;
 
-void    sfcmd (struct singleGparam * a)   {pc.printf("Spindle Fwd\r\n"); spindlefwdrev = 0;}
-void    srcmd (struct singleGparam * a)   {pc.printf("Spindle Rev\r\n"); spindlefwdrev = 4;}
-void    stopcmd (struct singleGparam * a)   {pc.printf("Stop ! er, not working yet\r\n");}
+void    M3cmd (struct singleGparam * a)   { spindle_control (spindle_rpm);  }
+void    M5cmd (struct singleGparam * a)   { spindle_control (0.0);  }
 
 void    scmd (struct singleGparam * a)   {
-    pc.printf("pir_s=0x%x\r\n", pir_s);
-    if  (a[1].dbl < 0.0 || a[1].dbl > spindle_max)    {
-        pc.printf   ("Errror setting spindle RPM, can't set to %f, ignoring request\r\n", a[1].dbl);
-//        return;
+    if  (fabs(a[1].dbl) > spindle_max)    {
+        pc.printf   ("Errror setting spindle RPM, can't set to %.0f, ignoring request\r\n", a[1].dbl);
+        return;
     }
-    pc.printf   ("Setting spindle RPM to %f\r\n", a[1].dbl);
-//    feed_rate = a[1].d;   //  ****TO DO****
-    pir_s = (unsigned long) (a[1].dbl * 4096);
-    pc.printf("pir_s=0x%x\r\n", pir_s);
+    pc.printf   ("Setting spindle RPM to %.0f Can set Pos or Neg for fwd/rev\r\n", a[1].dbl);
+    spindle_rpm = a[1].dbl;
+    if  (spindle_running())
+        spindle_control (spindle_rpm);
+/*
+
+    pir_spin = (signed long) (a[1].dbl * spindle_factor);
+    t = ticks;
+    while   (t == ticks)    {}  //  wait until just after next interrupt
+    p = mysteppers;
+    if  (pir_spin & 0x80000000)
+        p |= SDi;
+    else
+        p &= ~SDi;
+    mysteppers = p;
+*/
+
 }
 
-//void    stopcmd (struct grain * a)   {pc.printf("Stop !\r\n");}
+extern  void    target_cmd (struct singleGparam * a)   ;
+
+void    stopcmd (struct singleGparam * a)   {pc.printf("Stop ! er, not working yet\r\n");}
 void    m1cmd (struct singleGparam * a)   {pc.printf("m1 Optional Programme Stop\r\n");}
 void    m3cmd (struct singleGparam * a)   {pc.printf("m3 Rotate Spindle Clockwise\r\n");}
 void    m4cmd (struct singleGparam * a)   {pc.printf("m4 Rotate Spindle Counter Clockwise\r\n");}
@@ -341,16 +312,14 @@
 void    g53cmd (struct singleGparam * a)   {pc.printf("g53 Move in Absolute Coordinates\r\n");}
 void    g90cmd (struct singleGparam * a)   {pc.printf("g90 Absolute Distance Mode\r\n");}
 */
-void    g2cmd (struct singleGparam * a)   { //  Clockwise arc
-    g2g3cmdcore (a, 2);
-    }
-void    g3cmd (struct singleGparam * a)   { //  Counter clockwise arc
-    g2g3cmdcore (a, 3);
-    }
-void    g4cmd (struct singleGparam * a)   {pc.printf("g4 Dwell\r\n");}
-void    g91p1cmd (struct singleGparam * a)   {pc.printf("g91.1 \r\n");}
+//void    g4cmd (struct singleGparam * a)   {pc.printf("g4 Dwell\r\n");}
+//void    g91p1cmd (struct singleGparam * a)   {pc.printf("g91.1 \r\n");}
 
-void    tasktstone    (void const * name)
+//void    report_inputs   ()  {
+void    report_ins_cmd  (struct singleGparam * a)  {
+   report_inputs();
+}
+/*void    tasktstone    (void const * name)
 {
     static int i = 0;
     pc.printf("Arrived at tasktstone\r\n");
@@ -359,7 +328,7 @@
         Thread::wait(9500);
         osThreadYield();
     }
-}
+}*/
 
 /*void    tasktestcmd (struct singleGparam * a)   {
     pc.printf("At tasktestcmd\r\n");
@@ -367,16 +336,19 @@
     pc.printf("Leaving tasktestcmd\r\n");
 }
 */
+extern  void    lissajous   (double)  ;
+
 void    lisscmd (struct singleGparam * a)   {
-    if(liss_active) {
+    lissajous   (feed_rate);
+/*    if(liss_active) {
         pc.printf("Can not add Lissajous, already running.\r\n");
     }
     else    {
         pc.printf("Adding Lissajous task\r\n");
         liss_active = true;
-    }
+    }*/
 }
-
+/*
 void    drooncmd    (struct singleGparam * a)
 {
     dro.dro_output = true;     //  Enable continuous dro display update
@@ -385,9 +357,9 @@
 {
     dro.dro_output = false;    //  Disable continuous dro display update
 }
-
+*/
 
-void    g90p1cmd (struct singleGparam * a)
+/*void    g90p1cmd (struct singleGparam * a)
 {
     pc.printf   ("Arrived at function fredcmd with %d parameters\r\n", a[0].i);
     for (int i = 1; i <= a[0].i; i++)   {
@@ -397,7 +369,7 @@
     }
     pc.printf   (" endof param list\r\n");
 }
-
+*/
 void    menucmd (struct singleGparam * a);
 struct kb_command  {
     const char * cmd_word;         //  points to text e.g. "menu"
@@ -416,10 +388,10 @@
     {"menu", "Lists available commands, same as ls", menucmd},
     {"ls", "Lists available commands, same as menu", menucmd},
     {"stop", "To Stop the Machine !", stopcmd},
-    {"sf", "Spindle Clockwise", sfcmd},
-    {"sr", "Spindle Anticlockwise", srcmd},
     {"f ", "To set Feed Rate mm/min, e.g. f 25", fcmd},
     {"s ", "To set Spindle RPM, e.g. S 1250", scmd},
+    {"m3", "Start Spindle at last 'S'", M3cmd},
+    {"m5", "Stop Spindle", M5cmd},
     {"g0", "Rapid move", g0cmd},
     /*{"m30", "Not Implemented", m30cmd},
     {"m47", "Not Implemented", m47cmd},
@@ -444,10 +416,13 @@
     {"g1", "Linear Interpolation - move straight at current feed rate", g1cmd},
     {"g2", "Helical Interpolation CW (Arc, circle)", g2cmd},
     {"g3", "Helical Interpolation CCW (Arc, circle)", g3cmd},
-    {"liss", "Add Lissajous pattern generator", lisscmd},
+    {"liss", "Run Lissajous pattern generator", lisscmd},
+    {"flags", "Report System Flags", flags_report_cmd},
+    {"inputs", "Report State of Input bits", report_ins_cmd},
+    {"target", "Identify computer device", target_cmd},
 //    {"ttest", "Add a task to prove we can, or not", tasktestcmd},
-    {"dro on", "Turn dro readout on", drooncmd},
-    {"dro off", "Turn dro readout off", drooffcmd}
+//    {"dro on", "Turn dro readout on", drooncmd},
+//    {"dro off", "Turn dro readout off", drooffcmd}
 };
 //const    int numof_menu_items = sizeof(kbc2) / sizeof(kb_command);
 //const    int numof_menu_items_sc = sizeof(input_syntax_check) / sizeof(kb_command);
@@ -468,6 +443,40 @@
     return  false;
 }
 
+void    nudger  (int code)  {
+    //  Using <Ctrl>+ 'F', 'B' for Y, 'L', 'R' for X, 'U', 'D' for Z
+    //                 6    2          12   18         21   4
+//    struct  Gparams dest;
+    struct  pirbufgrain dest;
+    dest.x = last_position.x.dbl;
+    dest.y = last_position.y.dbl;
+    dest.z = last_position.z.dbl;
+    dest.f_rate = feed_rate;
+    switch  (code)  {
+        case    6:  //  'F' move -Y
+        dest.y -= 0.1;
+        break;
+        case    2:  //  'B' move +Y
+        dest.y += 0.1;
+        break;
+        case    12: //  'L' move +X
+        dest.x += 0.1;
+        break;
+        case    18: //  'R' move -X
+        dest.x -= 0.1;
+        break;
+        case    21: //  'U' move +Z
+        dest.z += 0.1;
+        break;
+        case    4:  //  'D' move -Z
+        dest.z -= 0.1;
+        default:
+        break;
+//            pc.printf("Nuffink to do in nudger\r\n");
+    }   //  end of switch
+    move_to_XYZ (dest);
+}
+
 ////class CLI {
 
 /*
@@ -481,7 +490,7 @@
 static  char    cmd_line[MAX_CMD_LEN + 4];
 static  struct  singleGparam   params[MAX_PARAMS + 1];
 static  int     cl_index = 0, lastalpha = 0;
-    pc.printf("Got to cli, Starting cli\r\n");
+//    pc.printf("Got to cli, Starting cli\r\n");
     if  (true)  {
         command_list_ptr = command_execute;
         numof_menu_items = sizeof(command_execute) / sizeof(kb_command);
@@ -498,6 +507,13 @@
                 cl_index = 0;
             }
             ch = tolower(pc.getc());
+            if  (ch == '\r' || ch >= ' ' && ch <= 'z')
+                pc.printf("%c", ch);
+            else    {                   //  Using <Ctrl>+ 'F', 'B' for Y, 'L', 'R' for X, 'U', 'D' for Z
+                cl_index = 0;           //                 6    2          12   18         21   4
+                pc.printf("[%d]", ch);
+                nudger  (ch);
+            }
             if(ch != '\r')  //  was this the 'Enter' key?
                 cmd_line[cl_index++] = ch;  //  added char to command being assembled
             else    {   //  key was CR, may or may not be command to lookup
@@ -587,6 +603,7 @@
                     if(i == numof_menu_items)
                         pc.printf("No Match Found for CMD [%s]\r\n", cmd_line);
                 }           //  End of If have got some chars to lookup
+                pc.printf("\r\n>");
                 cl_index = lastalpha = 0;
             }               // End of else key was CR, may or may not be command to lookup
         }                   //  End of while (pc.readable())
--- a/lissajous.cpp	Thu Feb 06 08:45:02 2014 +0000
+++ b/lissajous.cpp	Thu Feb 20 09:27:18 2014 +0000
@@ -1,8 +1,10 @@
 #include "mbed.h"
-#include "rtos.h"
+//#include "rtos.h"
+#include "MODSERIAL.h"
 #include "cnc.h"
-extern  Serial pc;
-extern  void    mover   (struct pirbufgrain & ins)   ;
+extern  MODSERIAL pc;
+//extern  Serial pc;
+extern  void    move_to_XYZ   (struct pirbufgrain & ins)   ;
 /*
 This file contains one function:
 void    lissajous   ()  ;
@@ -12,17 +14,16 @@
 
 Thus far we have proved only that both finish at the same point (give or take a few microns)
 */
-bool    liss_active = false;    //  global flag used to prevent running more than once at a time
+//bool    liss_active = false;    //  global flag used to prevent running more than once at a time
 
-void    lissajous   (void const * arg_string)  {
+void    lissajous   (double feed_rate)  {
     const double    PI          = 4.0 * atan(1.0),  //3.142ish but more accurate
                     Deg2Rad     = PI / 180.0, //  degrees to radian conversion factor
-                    MaxX            = 6.40,     // Plot size X to move +/- MaxX
-                    MaxY            = 6.4,   //3.20,     // Plot size Y to move +/- MaxY
+                    MaxX            = 40.0,     // Plot size X to move +/- MaxX
+                    MaxY            = 25.0,     // Plot size Y to move +/- MaxY
                     StartAngDegX    = 0.0,
-                    StartAngDegY    = 0.0,  //10.0,
-                    FreqRatio       = 1.0,  //0.254,
-                    FeedRate        = 500.0;    // In mm per minute
+                    StartAngDegY    = 10.0,
+                    FreqRatio       = 0.255;
     const int       StepsPerRevX    = 100,
                     NumofXCycles    = 16;
     const double    AngleStepX  = (2.0 * PI / StepsPerRevX),
@@ -33,17 +34,22 @@
     double  AngleX = StartAngDegX * Deg2Rad,
             AngleY = StartAngDegY * Deg2Rad;
             
-    pc.printf("In lissajous func, Loading Lissajous\r\n");
-    while   (1) {
-        while   (!liss_active)  //  Other code to activate
-            osThreadYield();
+//    pc.printf("In lissajous func, Loading Lissajous\r\n");
+//    while   (1) {
+//        while   (!liss_active)  //  Other code to activate
+//            osThreadYield();
     //    liss_active = true;   //  this hapens in activating code
         pc.printf("In lissajous func, Starting Lissajous, has been activated\r\n");
+        Coords.x = 0.0;
+        Coords.y = 0.0;
+        Coords.z = 12.7;
+        Coords.f_rate = feed_rate;
+        move_to_XYZ (Coords);
         Coords.x = MaxX * cos(AngleX);  //  Coordinates of start position
         Coords.y = MaxY * sin(AngleY);  //  assembled into packet for motion controller
+        move_to_XYZ (Coords);
         Coords.z = 0.0;
-        Coords.f_rate = FeedRate;
-        mover(Coords);
+        move_to_XYZ (Coords);
     
         for (int i = 0; i < NumofXCycles; i++)   {      // Outer loop 'NumofXCycles' times
             for (int j = 0; j < StepsPerRevX; j++)   {  // Inner loop 'StepsPerRevX' times
@@ -51,16 +57,22 @@
                 AngleY += AngleStepY;
                 Coords.x = MaxX * cos(AngleX);
                 Coords.y = MaxY * sin(AngleY);
-                mover(Coords);
-                osThreadYield();
+                move_to_XYZ (Coords);
+//                osThreadYield();
             }
+            pc.printf("liss cyc %d\r\n", i);
         }
+        Coords.z = 100.0;
+        move_to_XYZ (Coords);
+        Coords.x = 0.0;
+        Coords.y = 0.0;
+        move_to_XYZ (Coords);
         
         pc.printf("Lissajous finish point X%f, Y%f\r\n", Coords.x, Coords.y);
-        liss_active = false;
+//        liss_active = false;
         pc.printf("Leaving liss\r\n");
-        osThreadYield();    //  terminate would be better here
-    }   //  end of while(1)
+//        osThreadYield();    //  terminate would be better here
+//    }   //  end of while(1)
 }
 
 /*
--- a/main.cpp	Thu Feb 06 08:45:02 2014 +0000
+++ b/main.cpp	Thu Feb 20 09:27:18 2014 +0000
@@ -1,22 +1,24 @@
 #include "mbed.h"
 #include "rtos.h"
+#include "MODSERIAL.h"
 #include "cnc.h"
 using namespace std;
 extern  void    command_line_interpreter    (void const *) ;
-extern  void    lissajous   (void const *)  ;
-extern  double  feed_rate;
+//extern  void    lissajous   (void const *)  ;
+extern  double  feed_rate, spindle_rpm;
 extern  void    more_setup  ()  ;
+extern  struct  Gparams    last_position;
 
 const   int BAUD = 38400;
-Serial  pc(USBTX, USBRX);        //  tx, rx to pc
+MODSERIAL  pc(USBTX, USBRX);        //  tx, rx to pc
+//Serial  pc(USBTX, USBRX);        //  tx, rx to pc
 Ticker  NCO_gen;                 // Ticker generating interrupts at "Kernel Speed", NCO updating frequency (about 40kHz)
-struct  digital_readouts    dro;    //some signed int
 
 bool    running     = false,    new_run_pending = false,    idle = false,   move_ended = false;
 volatile unsigned long ticks    = 0L;  //  32 bit count of "interrupt_period_us" interrupts from time t=0
 unsigned long          tickrun  = 0L;  //  32 bit effectively stores time in future when current movement to stop
 unsigned long          ticks_next  = 0L;  //  32 bit effectively stores time in future when current movement to stop
-unsigned long   millisecs = 0L;        //  32 bit
+unsigned long          millisecs = 0L;        //  32 bit
 unsigned long   pir_a = 0L,         //  Phase Increment Registers
                 pir_x = 0L,
                 pir_y = 0L,
@@ -25,19 +27,20 @@
                 pir_x_next  = 0L,   //  during a move.
                 pir_y_next  = 0L,   //  This way, next move can start immediately
                 pir_z_next  = 0L,   //  on end of current move - minimised jerking
-                pir_s = 0L;     //  Referenced only in command_interpreter as spindle speed setting
+                pir_spin    = 0L;     //  Referenced only in command_interpreter as spindle speed setting
 
-int spindlefwdrev = 0;  //  Takes values of 0 or 4 only
 
 
 #if defined (TARGET_KL25Z)
-    DigitalOut intled       (PTE1);     //J2p20
-    DigitalOut charge_pump  (PTE0);     //J2p18    
-    DigitalIn   D25pin10    (PTD6);     //jp217
-    DigitalIn   D25pin11    (PTE31);    //j2p13
-    DigitalIn   D25pin12    (PTA17);    //j2p11
-    DigitalIn   D25pin13    (PTA16);    //j2p9
-    DigitalIn   D25pin15    (PTC17);    //j2p7
+    const char Target[] = "KL25Z";
+    DigitalOut intled               (PTE1);     //J2p20
+    DigitalOut charge_pumpD25pin1   (PTE0);     //J2p18    
+//    InterruptIn     D25pin10_EStop    (PTE20);    //j10p1   KL25 J10 is KL46 j4
+    DigitalIn     D25pin10_EStop    (PTE20);    //j10p1   KL25 J10 is KL46 j4
+    DigitalIn       D25pin11_XLim     (PTE21);    //j10p3
+    DigitalIn       D25pin12_YLim     (PTE22);    //j10p5
+    DigitalIn       D25pin13_ZLim     (PTE23);    //j10p7
+    DigitalIn       D25pin15_unkn     (PTE30);    //j10p11
     //SPISlave spidevice(PTD3, PTD2, PTD1, PTD0); // mosi, miso, sclk THIS TURNS LED ON BLUE ! (uses p11, p12, p13 on mbed LPC)
     SPISlave spidevice(PTD2, PTD3, PTD1, PTD0); // mosi, miso, sclk THIS TURNS LED ON BLUE ! (uses p11, p12, p13 on mbed LPC)
     //                 J2p08,J2p10,J2p12, J2p06
@@ -45,45 +48,58 @@
     //SPI spidevice(PTD3, PTD2, PTD1); // mosi, miso, sclk THIS TURNS LED ON BLUE ! (uses p11, p12, p13 on mbed LPC)
     //NOTE doubt possibly miso mosi in wrong order here, PTD3 and PTD2
     #define STEPPER_PORT    PortC
-    const   int PortBitXSt   = 3,    //  Port bit num X Step    J1P05
-                PortBitXDi   = 4,    //  Port bit num X Dir     J1P07
-                PortBitYSt   = 5,    //  Port bit num Y Step    J1P09
-                PortBitYDi   = 6,    //  Port bit num Y Dir     J1P11
-                PortBitZSt   = 10,    //  Port bit num Z Step   J1P13
-                PortBitZDi   = 11,    //  Port bit num Z Dir    J1P15
-                PortBitASt   = 12,    //  Port bit num A Step   J2P01
-                PortBitADi   = 13;    //  Port bit num A Dir    J2P03
+    const   int PortBitXSt   = 3,    //  Port bit num X Step    J1P05   D25pin 2
+                PortBitXDi   = 4,    //  Port bit num X Dir     J1P07   D25pin 3
+                PortBitYSt   = 5,    //  Port bit num Y Step    J1P09   D25pin 4
+                PortBitYDi   = 6,    //  Port bit num Y Dir     J1P11   D25pin 5
+                PortBitZSt   = 10,    //  Port bit num Z Step   J1P13   D25pin 6
+                PortBitZDi   = 11,    //  Port bit num Z Dir    J1P15   D25pin 7
+                PortBitASt   = 12,    //  Port bit num A Step   J2P01   D25pin 8
+                PortBitADi   = 13,    //  Port bit num A Dir    J2P03   D25pin 9
+                PortBitSSt   = 8,    //  Port bit num Spin Step   J1P14 D25pin 14
+                PortBitSDi   = 9;    //  Port bit num Spin Dir    J1P16 D25pin 16
 #endif
+
+
+
 #if defined (TARGET_KL46Z)
-    DigitalOut intled       (PTE1);    //J2p20
-    DigitalOut charge_pump  (PTE0);    //J2p18    
-    DigitalIn   D25pin10    (PTB9);//d6 on 25 jp217
-    DigitalIn   D25pin11    (PTA16);//e31 on 25 j2p13
-    DigitalIn   D25pin12    (PTA15);//a17 on 20 j2p11
-    DigitalIn   D25pin13    (PTA14);//a16 on 25 j2p9
-    DigitalIn   D25pin15    (PTA6);//c17 on 25 j2p7
+    const char Target[] = "KL46Z";
+    DigitalOut intled               (PTE1);    //J2p20 checked
+
+
+    DigitalOut charge_pumpD25pin1   (PTE0);    //J2p18 checked
+//    InterruptIn     D25pin10_EStop    (PTE20);  // j4p1  KL46 J4 is KL25 J10
+    DigitalIn     D25pin10_EStop    (PTE20);  // j4p1  KL46 J4 is KL25 J10 checked
+    DigitalIn       D25pin11_XLim     (PTE21);  // j4p3 checked
+    DigitalIn       D25pin12_YLim     (PTE22);  // j4p5 checked
+    DigitalIn       D25pin13_ZLim     (PTE23);  // j4p7 checked
+    DigitalIn       D25pin15_unkn     (PTE30);  // j4p11 checked
     SPISlave spidevice(PTA16, PTA17, PTA15, PTA14); // mosi, miso, sclk, ssel (uses p11, p12, p13, p? on mbed LPC)
     //                 J2p13, J2p15, J2p11, J2p09
-                // Easy way to allocate port bits for           ***  N O T  CHECKED for 46Z ***
+                // Easy way to allocate port bits for
                 // output of stepper motor Step and DIR sigs
     #define STEPPER_PORT    PortC
-    const   int PortBitXSt   = 0,    //  Port bit num X Step    J1P05
-                PortBitXDi   = 4,    //  Port bit num X Dir     J1P07
-                PortBitYSt   = 6,    //  Port bit num Y Step    J1P09
-                PortBitYDi   = 7,    //  Port bit num Y Dir     J1P11
-                PortBitZSt   = 10,    //  Port bit num Z Step   J1P13
-                PortBitZDi   = 11,    //  Port bit num Z Dir    J1P15
-                PortBitASt   = 13,    //  Port bit num A Step   J2P01
-                PortBitADi   = 16;    //  Port bit num A Dir    J2P03
+    const   int PortBitXSt   = 0,    //  Port bit num X Step    J1P05   D25pin 2 checked
+                PortBitXDi   = 4,    //  Port bit num X Dir     J1P07   D25pin 3 checked
+                PortBitYSt   = 6,    //  Port bit num Y Step    J1P09   D25pin 4 checked
+                PortBitYDi   = 7,    //  Port bit num Y Dir     J1P11   D25pin 5 checked
+                PortBitZSt   = 10,    //  Port bit num Z Step   J1P13   D25pin 6 checked
+                PortBitZDi   = 11,    //  Port bit num Z Dir    J1P15   D25pin 7 checked
+                PortBitASt   = 13,    //  Port bit num A Step   J2P01   D25pin 8 checked
+                PortBitADi   = 16,    //  Port bit num A Dir    J2P03   D25pin 9 checked
+                PortBitSSt   = 8,    //  Port bit num Spin Step J1P14   D25pin 14 checked
+                PortBitSDi   = 9;    //  Port bit num Spin Dir  J1P16   D25pin 16 checked
 #endif
 #if defined (TARGET_MBED_LPC1768)
+    const char Target[] = "MBED LPC1768";
     DigitalOut intled(LED2);                    //  Correct
-    DigitalOut charge_pump  (PTE0);    //J2p18    Following 5 inputs all wrong - TO DO sort which pins
-    DigitalIn   D25pin10    (PTD6);     //jp217
-    DigitalIn   D25pin11    (PTE31);    //j2p13
-    DigitalIn   D25pin12    (PTA17);    //j2p11
-    DigitalIn   D25pin13    (PTA16);    //j2p9
-    DigitalIn   D25pin15    (PTC17);    //j2p7
+    DigitalOut charge_pumpD25pin1      (p25);    //J2p18    Following 5 inputs all wrong - TO DO sort which pins
+//    InterruptIn D25pin10_EStop  (p26);    //P2.0
+    DigitalIn D25pin10_EStop  (p26);    //P2.0
+    DigitalIn   D25pin11_XLim   (p24);    //P2.2
+    DigitalIn   D25pin12_YLim   (p23);    //P2.3
+    DigitalIn   D25pin13_ZLim   (p19);    //P1.30
+    DigitalIn   D25pin15_unkn   (p20);    //P1.31
     SPISlave spidevice(p5, p6, p7, p8);
                 // Easy way to allocate port bits for           ***  N O T  CHECKED for MBED_LPC1768 ***
                 // output of stepper motor Step and DIR sigs
@@ -91,44 +107,104 @@
     /* Port 0 bits routed to DIP pins as follows:-
         P0.00   p09 Reserve SDA
         P0.01   p10 Reserve SCL
-        P0.04   p30 CAN rd  -   USE X Step
-        P0.05   p29 CAN td  -   USE X Dir
-        P0.10   p28 SDA     -   USE Y Step
-        P0.11   p27 SCL     -   USE Y Dir
-        P0.15   p13 Tx      -   USE Z Step
-        P0.16   p14 Rx      -   USE Z Dir
-        P0.17   p12 miso    -   USE A Step
-        P0.18   p11 mosi    -   Use A Dir
-        P0.23   p15 A In
-        P0.24   p16 A In
-        P0.25   p17 A In
+        P0.04   p30 CAN rd  -   USE X Step  D25pin 2
+        P0.05   p29 CAN td  -   USE X Dir   D25pin 3
+        P0.10   p28 SDA     -   USE Y Step  D25pin 4
+        P0.11   p27 SCL     -   USE Y Dir   D25pin 5
+        P0.15   p13 Tx      -   USE Z Step  D25pin 6
+        P0.16   p14 Rx      -   USE Z Dir   D25pin 7
+        P0.17   p12 miso    -   USE A Step  D25pin 8
+        P0.18   p11 mosi    -   Use A Dir   D25pin 9
+        P0.23   p15 A In    -   Use S Step  D25pin 14
+        P0.24   p16 A In    -   Use S Dir   D25pin 16
+        P0.25   p17 Reserve A In
         P0.26   p18 Reserve A Out
     */
-    const   int PortBitXSt   = 4,    //  Port bit num X Step
-                PortBitXDi   = 5,    //  Port bit num X Dir
-                PortBitYSt   = 10,    //  Port bit num Y Step
-                PortBitYDi   = 11,    //  Port bit num Y Dir
-                PortBitZSt   = 15,    //  Port bit num Z Step
-                PortBitZDi   = 16,    //  Port bit num Z Dir
-                PortBitASt   = 17,    //  Port bit num A Step
-                PortBitADi   = 18;    //  Port bit num A Dir
+    const   int PortBitXSt  = 4,    //  Port bit num X Step
+                PortBitXDi  = 5,    //  Port bit num X Dir
+                PortBitYSt  = 10,    //  Port bit num Y Step
+                PortBitYDi  = 11,    //  Port bit num Y Dir
+                PortBitZSt  = 15,    //  Port bit num Z Step
+                PortBitZDi  = 16,    //  Port bit num Z Dir
+                PortBitASt  = 17,    //  Port bit num A Step
+                PortBitADi  = 18,    //  Port bit num A Dir
+                PortBitSSt  = 23,   //  Port bit num Spin Step
+                PortBitSDi  = 24;   //  Port bit num Spin Dir
 #endif
 
-const   long
-            XSt1 =   1 << PortBitXSt, XSt0 = 0,
-            XDi1 =   1 << PortBitXDi, XDi0 = 0,
-            YSt1 =   1 << PortBitYSt, YSt0 = 0,
-            YDi1 =   1 << PortBitYDi, YDi0 = 0,
-            ZSt1 =   1 << PortBitZSt, ZSt0 = 0,
-            ZDi1 =   1 << PortBitZDi, ZDi0 = 0,
-            ASt1 =   1 << PortBitASt, ASt0 = 0,
-            ADi1 =   1 << PortBitADi, ADi0 = 0,
+const   long    //  Assemble mask bits from now known port bit positions
+            XSt =   1 << PortBitXSt,    //  X axis Step signal
+            XDi =   1 << PortBitXDi,    //  X axis Direction signal
+            YSt =   1 << PortBitYSt,    //  Y axis Step, etc
+            YDi =   1 << PortBitYDi,
+            ZSt =   1 << PortBitZSt,    //  Z axis
+            ZDi =   1 << PortBitZDi,
+            ASt =   1 << PortBitASt,    //  A axis, not implemented in full, for e.g. rotary axis
+            ADi =   1 << PortBitADi,
+            SDi =  1 << PortBitSDi,     //  Spindle, also driven by Step and Dir signals up to 5kHz
+            SSt =  1 << PortBitSSt,     //  for 5000 RPM
+
+            SM_MASK = (XSt | XDi | YSt | YDi | ZSt | ZDi | ASt | ADi | SDi | SSt);
 
-            SM_MASK = (XSt1 | XDi1 | YSt1 | YDi1 | ZSt1 | ZDi1 | ASt1 | ADi1);
+    PortOut Steppers    (STEPPER_PORT, SM_MASK);
+    const   long    direction_swappers = XDi | YDi | ZDi | SDi; //  include bit to swap direction
+/*
+    long    read    ()  {
+        return  mysteppers ^ direction_swappers;
+    }
+    void    write   (long val)  {
+        mysteppers  = val ^ direction_swappers;
+    }
+  */  
+class digital_readout_stuff  {   //  class does not need to be named here
+    private:
+    char *  readout (char * txt, long p)         //  p has running subtotal of all pulses issued to stepper driver
+    {
+        txt[0] = '+';               //  constructs string e.g. "+123.456"
+        txt[8] = 0;                 //  null terminated
+        if  (p < 0)    {
+            txt[0] = '-';
+            p = -p;
+        }
+        p *= 1000;
+        p /= pulses_per_mm;
+        if  (p > 999999)    {
+            sprintf(txt + 1, "OVRANGE");
+            return  txt;
+        }
+        for(int k = 7; k > 0; k--)  {
+            if  (k == 4)
+                txt[k] = '.';
+            else    {
+                txt[k] = '0' + (p % 10);
+                p /= 10;
+            }
+        }
+        return  txt;    //  Returns pointer unaltered for subsequent use by e.g. cout
+    }
+        public:
+    signed long x, y, z, a;    //  Could easily expand up to six or more dros
+    bool    dro_output;             //  To enabe / disable output to terminal
+    void    init    ()  {
+        x = y = z = a = 0;   //  These dro registers count pulses delivered to stepper motor driver
+        dro_output = true;
+    }
+    void    update  ()  {
+        static  long    t = 300;    //  Prevent display immediately upon startup
+        if  (millisecs < t)
+            return;
+        if(!idle && dro_output)  {
+            char    txt[12];
+            pc.printf("dros X %s,", readout(txt, x));    //  dro.n has running subtotal of all pulses issued to stepper driver.n
+            pc.printf(" Y %s, Z ", readout(txt, y));
+            pc.printf("%s, %s\r\n", readout(txt, z), running ? "R":"idle");
+            if(!running)    idle = true;    //  Purpose of idle flag is to stop dro updates JUST AFTER run completes.
+            t = millisecs + 350;    //  Schedule next update after this non-blocking delay
+        }
+    }
+}   dro_out ;
 
-PortOut mysteppers(STEPPER_PORT, SM_MASK);
-
-const int PIRBUFFSIZE = 10;
+const int PIRBUFFSIZE = 40; //  pirbufgrain are 40 bytes each
 class   circbuff    {
     private:
         pirbufgrain grain   [PIRBUFFSIZE + 1];
@@ -165,7 +241,8 @@
     bool    readable    ()  {return !buffempty; }
     bool    writeable   ()  {return !bufffull; }
     bool    read    (pirbufgrain & g)   {
-        if  (buffempty) return  false;
+//        if  (buffempty) return  false;    //  TO DO Fix problem with buffempty flag
+        if  (On_Q() == 0) return  false;
         bufffull = false;
         grain_copy  (grain[OffPtr++], g);
         if  (OffPtr >= PIRBUFFSIZE)
@@ -193,17 +270,44 @@
     return  0;
 }
 
+const   double  duration_multiplier =   60000000.0 /  interrupt_period_us;
 
+void    move_to_XYZ   (struct pirbufgrain & ins)   {
+    struct  pirbufgrain outs;
+    double  distx   = ins.x - last_position.x.dbl,
+            disty   = ins.y - last_position.y.dbl,
+            distz   = ins.z - last_position.z.dbl,
+            distT   = sqrt ((distx * distx) + (disty * disty) + (distz * distz)), // 3D Pythag !
+            temp    = n_for_onemmpermin / distT;
+    if  (distT < 0.01)  {
+        pc.printf("Very small move %.4f, Ignoring!\r\n", distT);
+        return;
+    }
+    last_position.x.dbl   = ins.x;     //  Update global last_position record
+    last_position.y.dbl   = ins.y;
+    last_position.z.dbl   = ins.z;
+    outs.f_rate = ins.f_rate;
+    outs.c  = duration_multiplier * distT;   //  Duration ticks subject to feed rate compo
+    outs.x = temp * distx;
+    outs.y = temp * disty;
+    outs.z = temp * distz;  //  Have assembled data ready to put onto queue of move instructions
+    PutMoveOnList   (outs);
+}
+
+void    target_cmd (struct singleGparam * a)   {
+    pc.printf("Computer is %s\r\n", Target);
+}
 /*
 *   Interrupt Service Routine
 */
+/*  **** UNBROKEN VERSION 6th Feb 2014 ******************
 void    Numerically_Controlled_Oscillators_ISR ()  {   // services Ticker 'NCO_gen' generated interrupts ***ISR***
     static  const   int millisec_countdown = 1000 / interrupt_period_us;
     const   long    bit_lutx[4] = {XSt0 | XDi0, XSt0 | XDi1, XSt1 | XDi1, XSt1 | XDi0},  //  Used to look-up 'clk' and 'dir' signals from accum MSBs
                     bit_luty[4] = {YSt0 | YDi0, YSt0 | YDi1, YSt1 | YDi1, YSt1 | YDi0},  //  Used to look-up 'clk' and 'dir' signals from accum MSBs
                     bit_lutz[4] = {ZSt0 | ZDi0, ZSt0 | ZDi1, ZSt1 | ZDi1, ZSt1 | ZDi0},  //  Used to look-up 'clk' and 'dir' signals from accum MSBs
                     bit_luta[4] = {ASt0 | ADi0, ASt0 | ADi1, ASt1 | ADi1, ASt1 | ADi0},  //  Used to look-up 'clk' and 'dir' signals from accum MSBs
-                    bits2shift = (sizeof (long) << 3) - 2;
+                    bits2shift  = (sizeof (long) << 3) - 2,
     static  unsigned long
 //        acc_s = 0L, //  For Spindle motor, probably not needed as may be pwm
         acc_a = 0L,
@@ -272,20 +376,202 @@
     charge_pump = ticks & 0x02;
     intled = 0;         //  LED off
 }           //  end of interrupt handler
-
+*/
 /*
 *   End of Interrupt Service Routine
 */
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*
+*   Interrupt Service Routine
+*/
+#define STEP_IDLE_HI
+//#define STEP_IDLE_LO
+void    Numerically_Controlled_Oscillators_ISR ()  {   // services Ticker 'NCO_gen' generated interrupts ***ISR***
+    static  const   int millisec_countdown = 1000 / interrupt_period_us;
+    const   long    step_mask   = ASt | XSt | YSt | ZSt,    //  Added 6th Feb 14 Mask Does NOT include spindle bits
+                    dir_mask    = ADi | XDi | YDi | ZDi;    //  Added 6th Feb 14 Mask Does NOT include spindle bits
+    static  unsigned long
+        acc_spin = 0L,
+        acc_a = 0L,
+        acc_x = 0L,
+        acc_y = 0L,
+        acc_z = 0L;
+    static  long    mscount = millisec_countdown;
+    static  long    dir_bits = 0L, oldSteps = 0L;   //  Added 6th Feb 14
+    long acts, tmp, newSteps, stbits;
+
+    intled = 1;     //  LED on for duration of interrupt service - point for scope probing
+    ticks++;        //  count of interrupts serviced
+    if(!--mscount)  {   //  Maintain global counter of elapsed milli seconds
+        mscount = millisec_countdown;
+        millisecs++;
+    }
+    acc_spin += pir_spin;
+    tmp = Steppers ^ direction_swappers;
+#if defined STEP_IDLE_LO
+    tmp &= ~step_mask;   //  Step bits prepared for idle lo
+#endif
+#if defined STEP_IDLE_HI
+    tmp |= step_mask;   //  Step bits prepared for idle hi
+#endif
+    if  (acc_spin & 0x80000000) {   tmp |= SSt;    }
+    else    {                       tmp &= ~SSt;   }
+//    mysteppers = tmp;
+    if  (running)   {
+        acc_x += pir_x;     //  Update phase of signals in accumulators
+        acc_y += pir_y;
+        acc_z += pir_z;
+        acc_a += pir_a;   //  not yet implemented
+        
+        newSteps = 0L;   //  Added 6th Feb 14
+        if  (acc_a & 0x80000000)    newSteps |= ASt;//  Added 6th Feb 14
+        if  (acc_x & 0x80000000)    newSteps |= XSt;//  Added 6th Feb 14
+        if  (acc_y & 0x80000000)    newSteps |= YSt;//  Added 6th Feb 14
+        if  (acc_z & 0x80000000)    newSteps |= ZSt;//  Added 6th Feb 14
+        stbits  = newSteps ^ oldSteps;  //  Any bit of stbits set to initiate a Step pulse
+        acts     = dir_bits | stbits; //
+        oldSteps    = newSteps;   //  Added 6th Feb 14
+//        tmp         = acts ^ step_mask;   //  Invert clock - Arc Euro stepp motor driver only goes into half current mode this way
+        tmp ^= stbits;
+        Steppers = tmp ^ direction_swappers; //  Output signals to stepper motor drivers, next update dros from 'clocked' bits CLOCK IDLES HIGH
+
+        if(acts & XSt)  {       //  got clk edge for axis X
+            if  (acts & XDi)
+                dro_out.x--;
+            else    dro_out.x++;
+        }
+        if(acts & YSt)  {       //  got clk edge for axis Y
+            if  (acts & YDi)
+                dro_out.y--;
+            else    dro_out.y++;
+        }
+        if(acts & ZSt)  {       //  got clk edge for axis Z
+            if  (acts & ZDi)
+                dro_out.z--;
+            else    dro_out.z++;
+        }
+        if  (tickrun <= ticks)   {   //  End of a machine movement detected, start next move here if possible
+            if  (new_run_pending)  {
+                pir_a   = pir_a_next;
+                pir_x   = pir_x_next;
+                pir_y   = pir_y_next;
+                pir_z   = pir_z_next;
+                dir_bits = 0;           //  Added 6th Feb 14
+                if  (pir_a & 0x80000000)    dir_bits |= ADi;//  Added 6th Feb 14 read sign bits
+                if  (pir_x & 0x80000000)    dir_bits |= XDi;//  Added 6th Feb 14
+                if  (pir_y & 0x80000000)    dir_bits |= YDi;//  Added 6th Feb 14
+                if  (pir_z & 0x80000000)    dir_bits |= ZDi;//  Added 6th Feb 14
+                acts = Steppers ^ direction_swappers;  //  read output lines
+                acts &= ~dir_mask;
+                acts |= dir_bits;
+                Steppers = acts ^ direction_swappers;
+                tickrun = ticks + ticks_next;
+                running = true;     //  Start the new run
+                new_run_pending = false;    //  Clear the flag which initiated this update
+                idle = false;
+            }           //  End of if   (new_run_pending)   {
+            else    {   //  End of machine movement AND no new_run_pending
+                running = false;
+                move_ended = true;
+                pir_x = 0L; //  stop all stepper motors
+                pir_y = 0L;
+                pir_z = 0L;
+                pir_a = 0L;
+    //          ticks = 0L; //  Simply to avoid having to think about overflow problems
+            }
+        }
+    }
+    else    {   //  Not running. Grab next data here when or if available
+        Steppers = tmp ^ direction_swappers;
+        if  (new_run_pending)  {        //  Pick up on flag set elsewhere
+            pir_a   = pir_a_next;
+            pir_x   = pir_x_next;
+            pir_y   = pir_y_next;
+            pir_z   = pir_z_next;
+            dir_bits = 0;           //  Added 6th Feb 14
+            if  (pir_a & 0x80000000)    dir_bits |= ADi;//  Added 6th Feb 14 read sign bits
+            if  (pir_x & 0x80000000)    dir_bits |= XDi;//  Added 6th Feb 14
+            if  (pir_y & 0x80000000)    dir_bits |= YDi;//  Added 6th Feb 14
+            if  (pir_z & 0x80000000)    dir_bits |= ZDi;//  Added 6th Feb 14
+            acts = Steppers ^ direction_swappers;  //  read output lines
+            acts &= ~dir_mask;
+            acts |= dir_bits;
+            Steppers = acts ^ direction_swappers;
+            tickrun = ticks + ticks_next;
+            running = true;     //  Start the new run
+            new_run_pending = false;    //  Clear the flag which initiated this update
+            idle = false;
+        }   //  end of if  (new_run_pending)  {        //  Pick up on flag set elsewhere
+    }       //  end of     else    {   //  Not running. Grab next data here when or if available
+    charge_pumpD25pin1 = ticks & 0x01;  //  Can use 0x01 or 0x02 here to alter charge pump freq
+    intled = 0;         //  LED off
+}           //  end of interrupt handler
+
+/*
+*   End of Interrupt Service Routine
+*/
+bool    spindle_running ()  {
+    return  pir_spin;
+}
+void    spindle_control (double ss)  {
+    long t, p;
+    pir_spin = (signed long) (ss * spindle_factor);
+    t = ticks;
+    while   (t == ticks)    {}  //  wait until just after next interrupt
+    p = Steppers ^ direction_swappers;
+    if  (pir_spin & 0x80000000)
+        p |= SDi;
+    else
+        p &= ~SDi;
+    Steppers = p ^ direction_swappers;
+    pc.printf("Done setting spindle speed %.0f, delay = %d\r\n", ss, ticks - t);
+}
+
+
+/*
+void    scmd (struct singleGparam * a)   {
+    long t, p;
+    if  (fabs(a[1].dbl) > spindle_max)    {
+        pc.printf   ("Errror setting spindle RPM, can't set to %.0f, ignoring request\r\n", a[1].dbl);
+        return;
+    }
+    pc.printf   ("Setting spindle RPM to %.0f Can set Pos or Neg for fwd/rev\r\n", a[1].dbl);
+    pir_spin = (signed long) (a[1].dbl * spindle_factor);
+    t = ticks;
+    while   (t == ticks)    {}  //  wait until just after next interrupt
+    p = mysteppers;
+    if  (pir_spin & 0x80000000)
+        p |= SDi;
+    else
+        p &= ~SDi;
+    mysteppers = p;
+    pc.printf("Done setting spindle, delay = %d", ticks - t);
+}
+*/
 void    newpir_updater (void const * name)   {
-    static  long    x, y, z, count = 0;
+    static  long    x, y, z;//, count = 0;
     struct pirbufgrain outs;
-    pc.printf("Arrived at newpir_updater\r\n");
+//    pc.printf("Arrived at newpir_updater\r\n");
     while   (true)  {
-        while   (!move_ended  || !CircBuff.readable())   {
+//        while   (!move_ended  || !CircBuff.readable())   { ** TO DO ** Solve problem with empty flag
+        while   (!move_ended  || CircBuff.On_Q() == 0)   {
             osThreadYield();
-        }
+        }   //  Proceed beyond here only when move_ended AND CircBuff.readable() both TRUE
         CircBuff.read(outs);
         x = (long)(outs.f_rate * outs.x);  //  These take much CPU time !!
         y = (long)(outs.f_rate * outs.y);
@@ -294,55 +580,23 @@
         pir_x_next = x;
         pir_y_next = y;
         pir_z_next = z;
-        move_ended = false;
+        move_ended = idle = false;
         new_run_pending = true; //  cleared and 'running' flag set in interrupt handler
-        idle = false;
-        count++;
+//        idle = false;
+//        count++;
 //        pc.printf("CircB tot %d\r\n", count);
     }
 }
 
 
-class digital_readout_stuff  {   //  class does not need to be named here
-    char *  readout (char * txt, long p)         //  p has running subtotal of all pulses issued to stepper driver
-    {
-        txt[0] = '+';               //  constructs string e.g. "+123.456"
-        txt[8] = 0;                 //  null terminated
-        if  (p < 0)    {
-            txt[0] = '-';
-            p = -p;
-        }
-        p *= 1000;
-        p /= pulses_per_mm;
-        if  (p > 999999)    {
-            sprintf(txt + 1, "OVRANGE");
-            return  txt;
-        }
-        for(int k = 7; k > 0; k--)  {
-            if  (k == 4)
-                txt[k] = '.';
-            else    {
-                txt[k] = '0' + (p % 10);
-                p /= 10;
-            }
-        }
-        return  txt;    //  Returns pointer unaltered for subsequent use by e.g. cout
-    }
-        public:
-    void    update  ()  {
-        static  long    t = 0;
-        if  (millisecs < t)
-            return;
-        if(!idle && dro.dro_output)  {
-            char    txt[12];
-            pc.printf("dros X %s,", readout(txt, dro.x));    //  dro.n has running subtotal of all pulses issued to stepper driver.n
-            pc.printf(" Y %s, Z ", readout(txt, dro.y));
-            pc.printf("%s, %s\r\n", readout(txt, dro.z), running ? "runn":"idle");
-            if(!running)    idle = true;    //  Purpose of idle flag is to stop dro after run completes.
-            t = millisecs + 350;    //  Schedule next update after this non-blocking delay
-        }
-    }
-}   dro_out ;
+void    flags_report_cmd (struct singleGparam * a)   {  //  Diagnostic helper function
+    pc.printf("Flags Report\r\nRunning %s\r\n", running ? "T":"F");
+    pc.printf("idle %s\r\n", idle ? "T":"F");
+    pc.printf("new_run_pending %s\r\n", new_run_pending ? "T":"F");
+    pc.printf("move_ended %s\r\n", move_ended ? "T":"F");
+    pc.printf("CircBuff.readable() %s\r\n", CircBuff.readable() ? "T":"F");
+    pc.printf("On CircBuff %d\r\n", CircBuff.On_Q());
+}
 
 /*void    taskone    (void const * name)
 {
@@ -370,39 +624,81 @@
         osThreadYield();
     }
 }*/
+/*
+#define ESTOP   0x100
+#define XLIM    1
+#define YLIM    2
+#define ZLIM    4
+#define UNKN    8
+*/
+class   inputsreaderstuff   {
+    private:
+    long    ins_now;//,    ins_old,    ins_changed;
+    public:
+        void    init    ()  {   ins_now = 0L;}//ins_old = ins_changed = 0L;   }
+        long    read    ()  {
+            ins_now = 0;
+            if  (D25pin10_EStop)    ins_now |= ESTOP;
+            if  (D25pin11_XLim)     ins_now |= XLIM;
+            if  (D25pin12_YLim)     ins_now |= YLIM;
+            if  (D25pin13_ZLim)     ins_now |= ZLIM;
+            if  (D25pin15_unkn)     ins_now |= UNKN;
+//            ins_changed = ins_now ^ ins_old;
+//            ins_old = ins_now;
+            return  ins_now;
+        }
+//        long    changed ()  {   return  ins_changed;    }
+    }   Inputs_From_Machine;
+
+void    report_inputs   ()  {
+    long    i = Inputs_From_Machine.read();
+    pc.printf("Inputs: EStop %d, XLim %d, YLim %d, ", i & ESTOP ? 1:0, i & XLIM ? 1:0, i & YLIM ? 1:0);
+    pc.printf("ZLim %d, unkn %d\r\n", i & ZLIM ? 1:0, i & UNKN ? 1:0);
+}
+
+//void    Emergency_Stop_Interrupt  ()  {
+//    pc.printf("Emergency Stop Activated !!\r\n");
+//    spindle_control (0.0);  //  Stop spindle rotation
+//}
 
 int main() {
     pc.baud(BAUD); //  comms to 'PuTTY' serial terminal via mbed usb
-    dro.x = dro.y = dro.z = 0;   //  These dro registers count pulses delivered to stepper motor driver
-    dro.dro_output = true;
+//    D25pin11_XLim.mode  (PullDown);   External resistors now fitted
+//    D25pin12_YLim.mode  (PullDown);
+//    D25pin13_ZLim.mode  (PullDown);
+//    D25pin15_unkn.mode  (PullDown);
+//    D25pin10_EStop.mode (PullDown);
+//    D25pin10_EStop.rise (& Emergency_Stop_Interrupt);
+//    D25pin10_EStop.fall (& Emergency_Stop_Interrupt);
+    
     more_setup  ()  ;   //  Zeros one 'pirs' structure 'last_position'
+    dro_out.init();
     CircBuff.init   ();
+    Inputs_From_Machine.init    ();
     spidevice.format(8, 0);    //  8 bits mode 0,  // p11 mosi, p12 miso, p13 sclk ** ONLY 8 BIT **
     spidevice.frequency(12000000);  //  12MHz bit rate
-    pc.printf("\r\n*\n*\n");
-#if defined (TARGET_KL25Z)
-    pc.printf   ("Found device Freescale KL25Z\r\n");
-#endif
-#if defined (TARGET_KL46Z)
-    pc.printf   ("Found device Freescale KL46Z\r\n");
-#endif
-#if defined (TARGET_MBED_LPC1768)
-    pc.printf   ("Found device MBED_LPC1768\r\n");
-#endif
+    pc.printf("\r\n*\n*\nFound Computer %s\r\n", Target);
     pc.printf("Welcome to the CNC tester\r\nStep pulses required to move 1.0mm = %9.0f\r\n", pulses_per_mm);
-    pc.printf("PIR 'n' for 1mm per min = %9.0f\r\ntop speed = %6.5f mm per min\r\n\n", n_for_onemmpermin, max_mm_per_min);
+    pc.printf("PIR 'n' for 1mm per min = %9.0f\r\ntop speed = %6.1f mm per min\r\n\n", n_for_onemmpermin, max_mm_per_min);
     NCO_gen.attach_us(&Numerically_Controlled_Oscillators_ISR, (long)interrupt_period_us);// Have setup timed interrupts, let other code deal
 //    Thread threadnametaskone   (taskone, (void *)"task one stuff");
 //    Thread t8   (tasktwo, (void *)"task two");
     Thread tsr2   (newpir_updater, (void *)"read from CircBuff and move");
 //    Thread tthree   (taskthree, (void *)"task three");
-    Thread patterngen (lissajous,   (void *)"Loading Lissajous")  ;
+//    Thread patterngen (lissajous,   (void *)"Loading Lissajous")  ;
     Thread comlin (command_line_interpreter,    (void *)"cli"); //  Read any instructions arriving via serial port and act upon them
-    pc.printf("Added cli thread\r\n");
+    long    ins, ins_old, ins_changed = 0;
+    ins = ins_old = Inputs_From_Machine.read    ();
     move_ended = true;  //  Needed to kickstart system
     
     while(1) {  //  Round Robin loop
         dro_out.update  ();             //  Update DRO readings if, and as often as needed
+        ins = Inputs_From_Machine.read    ();
+        ins_changed = ins ^ ins_old;
+        ins_old = ins;
+        if  (ins_changed)
+            pc.printf("Inputs Have Changed 0x%x, read 0x%x\r\n", ins_changed, ins);
+//        pc.printf(".");
         osThreadYield();                //
     }   //  end of Round Robin loop
 }       //  end of int main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-rtos-marcusbirkin.lib	Thu Feb 20 09:27:18 2014 +0000
@@ -0,0 +1,1 @@
+https://mbed.org/users/marcusbirkin/code/mbed-rtos/#98a14efb7882
--- a/mbed-rtos.lib	Thu Feb 06 08:45:02 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-http://mbed.org/users/mbed_official/code/mbed-rtos/#f88660a9bed1