Test code for proving multi-NCO implementation on Altera FPGA using DEO Nano development board

Dependencies:   MODSERIAL mbed-rtos mbed

Files at this revision

API Documentation at this revision

Comitter:
JonFreeman
Date:
Thu Apr 24 15:35:38 2014 +0000
Commit message:
For testing numerically controlled oscillators implemented in Altera FPGA fitted to DEO Nan0 development board

Changed in this revision

MODSERIAL.lib 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
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-rtos.lib Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MODSERIAL.lib	Thu Apr 24 15:35:38 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/Sissors/code/MODSERIAL/#f42def64c4ee
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cnc.h	Thu Apr 24 15:35:38 2014 +0000
@@ -0,0 +1,52 @@
+/**
+Programme   COPIED FROM "cnc__machine_driver_3"
+Author      Jon Freeman
+
+Designed to compile and run on:
+    Mbed LPC1768
+    Freescale KL25Z
+    Freescale KL46Z
+*/
+using namespace std;
+
+typedef float  fl_typ;  //  
+    
+//#define SPI_Enable
+#define I2C_Enable
+#define ESTOP   0x100   //  bits used in input reading KX3 limit and EStop switches
+#define XLIM    1
+#define YLIM    2
+#define ZLIM    4
+#define UNKN    8
+
+const   fl_typ  TWO_PI = 8.0 * atan(1.0);
+const   fl_typ  epsilon = 1e-5;
+struct  pirbufgrain {
+    fl_typ  x,
+            y,
+            z,
+            distance_code,
+            f_rate;
+    }   ;
+
+struct  singleGparam    {   //  Place to put all we know about 'x' or 'j' etc parameter from G Code line
+    fl_typ          flt;
+    unsigned long   ul;
+    int         i,  c;
+    bool            changed;      // Flagged true when new value for this axis found in Gcode line, false otherwise 
+}   ;
+
+struct  Gparams {  //  Where possibly messy G code line gets ordered and sorted into
+    struct  singleGparam   x, y, z, i, j, r, a, b, c, d;   //  After sorting, know where to find any X, Y etc values !
+}   ;
+
+const int NumofGParams = sizeof(struct Gparams) / sizeof(struct singleGparam);
+
+#define clken       XDi
+#define d_in_isr    XSt
+#define d_in_osr    YDi
+#define ld_osr      YSt
+#define ld_pir      ZDi
+#define sclk        ZSt
+#define sclr        ADi
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/command_interpreter.cpp	Thu Apr 24 15:35:38 2014 +0000
@@ -0,0 +1,264 @@
+#include "mbed.h"
+#include "rtos.h"
+#include "MODSERIAL.h"
+#include "cnc.h"
+#include <cctype>
+
+extern  MODSERIAL pc;
+extern  void    report_inputs   ()  ;
+
+#if defined I2C_Enable
+extern    I2CSlave slave;//(PTE0, PTE1); on KL25
+
+int i2c_checksumchecker (char * buf, int len)    {
+    int k, i = 0x01;
+    for (k = 0; k < len; k++)
+        i += buf[k];
+    i &= 0x0ff;
+    return  i;
+}
+
+int i2c_checksumchecker (char * buf)    {
+    return  i2c_checksumchecker (buf, strlen(buf));
+}
+
+char * add_csum (char * buf, int len)    {           //  Adds checksum to end of binary string of known length
+    int j;
+    char    cs = 0;
+    for (j = 0; j < len; j++) {
+        cs += buf[j];
+    }
+    buf[len] = 0xff - cs;
+    buf[len + 1] = 0;
+    return  buf;
+}
+
+char * add_csum (char * buf)    {           //  Adds checksum to end of null terminated string
+    return  add_csum    (buf, strlen(buf));
+}
+
+void    i2c_handler    (void const * name)
+{
+    const int i2buflen = 16;
+    int err = 0;
+    char    buf[i2buflen];
+    char msg[20] = "Message 2snd\0";
+    add_csum(msg);
+    slave.address(0xc0);
+    err = slave.write(msg, strlen(msg) + 1); // Includes null char    //  returns 0 on success, nz otherwise
+    while   (true)  {
+        int i = slave.receive();
+        switch (i) {
+            case I2CSlave::NoData:  //  Happens most of the time    NoData - the slave has not been addressed
+                osThreadYield();  //  Using RTOS on this project
+                break;
+            case I2CSlave::ReadAddressed:   //   - the master has requested a read from this slave
+                err = slave.write(msg, strlen(msg) + 1); // Includes null char    //  returns 0 on success, nz otherwise
+                pc.printf("RdAddr'd ");
+                break;
+            case I2CSlave::WriteGeneral:    //   - the master is writing to all slave
+                err = slave.read(buf, i2buflen);    //  returns 0 on success, nz otherwise
+                pc.printf("i=%d, - the master is writing to all slave %s\r\n", i, buf);
+                break;
+            case I2CSlave::WriteAddressed:  //   - the master is writing to this slave
+                err = slave.read(buf, i2buflen);    //  returns 0 on success, nz otherwise
+                pc.printf("M wr-> [%s]", buf);
+                for (int z = 0; z < strlen(buf); z++)
+                    pc.printf("%2x, ", buf[z]);
+                pc.printf("cs %2x\r\n", i2c_checksumchecker(buf));
+                break;
+            default:
+                pc.printf("Unknown I2C code %d\r\n");
+                break;
+        }   //  end of switch (i) upon result of slave.receive()
+        if  (err)   {
+            pc.printf("Err %d with i = %d\r\n", err, i);
+            err = 0;
+        }
+        memset  (buf, 0, i2buflen);    // Clear buffer
+    }   //  end of while (true)
+}       //  end of void    i2c_handler    (void const * name)
+
+#endif
+
+extern  char const *    target_str_addr (void)   ;
+void    target_cmd (struct singleGparam * a)   {
+    pc.printf("Computer is %s\r\n", target_str_addr());
+}
+
+//extern  void    FPGA_bit    (int whichbit, int hiorlo)    ;
+
+extern  void    setpir_cmd  (struct singleGparam * a)  ;
+extern  void    setcmd_cmd  (struct singleGparam * a)  ;
+extern  void    getdro_cmd  (struct singleGparam * a)  ;
+extern  void    getpir_cmd  (struct singleGparam * a)  ;
+extern  void    clrpir_cmd  (struct singleGparam * a)  ;
+extern  void    clrdro_cmd  (struct singleGparam * a)  ;
+extern  void    setdro_cmd  (struct singleGparam * a)  ;
+
+
+void    report_ins_cmd  (struct singleGparam * a)  {
+   report_inputs();
+}
+void    menucmd (struct singleGparam * a);
+struct kb_command  {
+    const char * cmd_word;         //  points to text e.g. "menu"
+    const char * explan;
+    void (*f)(struct singleGparam *);   //  points to function
+}  ;
+
+struct  kb_command const * command_list_ptr = NULL;   //  Pointer switched between 'input_syntax_check' and 'command_execute'
+
+struct  kb_command const  input_syntax_check  [] = {
+    {"menu", "Lists available commands, same as ls", menucmd},
+    {"ls", "Lists available commands, same as menu", menucmd}    
+    }   ;
+
+struct  kb_command const command_execute[] = {
+    {"menu", "Lists available commands, same as ls", menucmd},
+    {"ls", "Lists available commands, same as menu", menucmd},
+    {"inputs", "Report State of Input bits", report_ins_cmd},
+    {"pir", "Send number to FPGA pir", setpir_cmd},
+    {"cmd", "Send command to FPGA command reg", setcmd_cmd},
+    {"rddro", "Read DRO from FPGA", getdro_cmd},
+    {"rdpir", "Read PIR from FPGA", getpir_cmd},
+    {"clrpir", "Zero PIR", clrpir_cmd},
+    {"clrdro", "Zero DRO", clrdro_cmd},
+    {"setdro", "Set DRO", setdro_cmd},
+    {"target", "Identify computer device", target_cmd},
+};
+
+int numof_menu_items;
+void    menucmd (struct singleGparam * a)
+{
+    pc.printf("At menucmd function - listing commands:-\r\n");
+    for(int i = 0; i < numof_menu_items; i++)
+        pc.printf("[%s]\t\t%s\r\n", command_list_ptr[i].cmd_word, command_list_ptr[i].explan);
+    pc.printf("End of List of Commands\r\n");
+}
+
+extern  void    grain_clr   (struct singleGparam & g)  ;
+
+void    command_line_interpreter    (void const * name)
+{
+const int MAX_PARAMS = 10, MAX_CMD_LEN = 120;
+static  char    cmd_line[MAX_CMD_LEN + 4];
+static  struct  singleGparam   params[MAX_PARAMS + 1];
+static  int     cl_index = 0, lastalpha = 0;
+static  fl_typ  fracmul;
+    if  (true)  {
+        command_list_ptr = command_execute;
+        numof_menu_items = sizeof(command_execute) / sizeof(kb_command);
+    }
+    else    {
+        command_list_ptr = input_syntax_check;
+        numof_menu_items = sizeof(input_syntax_check) / sizeof(kb_command);
+    }
+    while   (true)  {
+        while  (pc.readable()) {
+            int     ch;
+            if  (cl_index > MAX_CMD_LEN)  {   //  trap out stupidly long command lines
+                pc.printf   ("Keyboard Error!! Killing stupidly long command line");
+                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
+                cmd_line[cl_index] = 0; //  null terminate command string
+                if(cl_index)    {   //  If have got some chars to lookup
+                    int i, wrdlen;
+                    for (i = 0; i < numof_menu_items; i++)   {   //  Look for input match in command list
+                        wrdlen = strlen(command_list_ptr[i].cmd_word);
+                        if(strncmp(command_list_ptr[i].cmd_word, cmd_line, wrdlen) == 0
+                            && !isalpha(cmd_line[wrdlen]))  {   //  If match found
+                            bool negflag = false;
+                            int state = 0, paramindex;
+    //                            pc.printf("Found match for word [%s]\r\n", kbc[i].wrd);
+                            for(paramindex = 0; paramindex < MAX_PARAMS; paramindex++) 
+                                grain_clr   (params[paramindex]);
+                            paramindex = 0;
+                            //  read any parameters from command line here
+                            //  Using parameters[0] as count of parameters to follow
+                            while   (wrdlen <= cl_index)  {
+                                ch = cmd_line[wrdlen++];
+                                if(isalpha(ch)) lastalpha = ch;
+                                if(ch == '-')   negflag = true;
+                                if(ch == '+')   negflag = false;
+                                switch  (state) {
+                                    case    0:  //  looking for start of a number string
+                                        if(isdigit(ch)) {   //  found first digit of a number string
+                                            paramindex++;
+                                            if(paramindex > MAX_PARAMS)    {
+                                                wrdlen = cl_index;  //  exit condition
+                                                pc.printf("WARNING - too many parameters, ignoring extra\r\n");
+                                            } else    {
+                                                params[paramindex].i = ch - '0';
+                                                params[paramindex].c = lastalpha;
+                                                state = 1;  //  Found first digit char of number string
+                                            }
+                                        }
+                                        break;
+                                    case    1:  //  looking for end of a number string
+                                        if(isdigit(ch)) {   //  accumulating integer from string
+                                            params[paramindex].i *= 10;
+                                            params[paramindex].i += ch - '0';
+                                        } else    { //  found non-digit terminating number
+                                            if  (ch == '.')  {
+                                                state = 2;
+                                                fracmul = 0.1;
+                                                params[paramindex].flt = (fl_typ)params[paramindex].i;
+                                            } else    {
+                                                params[0].i++;    //  count of validated parameters
+                                                state = 0;  //  Have read past last digit of number string
+                                                if(negflag) {
+                                                    params[paramindex].i = -params[paramindex].i;
+                                                    negflag = false;
+                                                }
+                                                params[paramindex].flt = (fl_typ)params[paramindex].i;
+                                            }
+                                        }
+                                        break;
+                                    case    2:  //  looking for fractional part of double
+                                        if(isdigit(ch)) {   //  accumulating fractional part from string
+                                            params[paramindex].flt += (fl_typ)((ch - '0') * fracmul);
+                                            fracmul /= 10.0;
+                                        } else    { //  found non-digit terminating double precision number
+                                            params[0].i++;    //  count of validated parameters
+                                            state = 0;  //  Have read past last digit of number string
+                                            if(negflag) {
+                                                params[paramindex].i = -params[paramindex].i;
+                                                params[paramindex].flt = -params[paramindex].flt;
+                                                negflag = false;
+                                            }
+                                        }
+                                        break;
+                                    default:
+                                        break;
+                                }   //  end of switch state
+                            }       //  end of while wrdlen < cl_index
+    //                            pc.printf("Found match to [%s] with %d parameters\r\n", command_list_ptr[i].wrd, paramindex);
+                            command_list_ptr[i].f(params);   //  execute command
+                            i = numof_menu_items + 1;    //  to exit for loop
+                        }
+                    }       // End of for numof_menu_items
+                    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())
+        osThreadYield();  //  Using RTOS on this project
+    }
+}
+
+////} cli;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Thu Apr 24 15:35:38 2014 +0000
@@ -0,0 +1,510 @@
+#include "mbed.h"
+#include "rtos.h"
+#include "MODSERIAL.h"
+#include "cnc.h"
+extern  void    i2c_handler    (void const *);
+extern  void    command_line_interpreter    (void const *) ;
+extern  fl_typ  feed_rate;      //  float type is 'float'
+extern  signed long spindle_rpm;
+
+const   int BAUD = 38400;
+MODSERIAL  pc(USBTX, USBRX);    //  tx, rx to pc via usb lead
+Ticker  msec;                   //  Ticker updating global millisecs counter
+
+bool    running         = false,
+        new_run_pending = false,
+        idle            = false,
+        move_ended      = false;
+
+unsigned long   millisecs = 0L;        //  32 bit
+
+#if defined (TARGET_KL25Z)
+    const char Target[] = "KL25Z";  //  Note need PTE0 (sda) and PTE1 (scl)
+    DigitalOut intled               (PTD7); //(PTE1);     //J2p19, was 20
+    DigitalOut charge_pumpD25pin1   (PTD6); //(PTE0);     //J2p17, was 18    
+    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
+#if defined I2C_Enable
+    I2CSlave slave(PTE0, PTE1); //  PTE0 sda, (yellow) PTE1 scl (blue)
+#endif
+#if defined SPI_Enable
+    SPI spi(PTD2, PTD3, PTD1, PTD0); // mosi, miso, sclk (uses p11, p12, p13 on mbed LPC1768)
+#endif
+    //                 J2p08,J2p10,J2p12, J2p06
+    #define STEPPER_PORT    PortC
+    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)
+    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
+#if defined I2C_Enable
+    I2CSlave slave(p9, p10);
+#endif
+#if defined SPI_Enable
+    SPI spi(PTA16, PTA17, PTA15, PTA14); // mosi, miso, sclk, ssel (uses p11, p12, p13, p? on mbed LPC)
+#endif
+    //                 J2p13, J2p15, J2p11, J2p09
+                // 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   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_pumpD25pin1      (p25);    //
+//    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
+#if defined I2C_Enable
+    I2CSlave slave(p9, p10);
+#endif
+//#if defined SPI_Enable
+    SPI spi(p5, p6, p7);
+//#endif
+                // Easy way to allocate port bits
+                // output of stepper motor Step and DIR sigs
+    #define STEPPER_PORT    Port0
+    /* 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  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
+                PortBitSSt  = 23,   //  Port bit num Spin Step
+                PortBitSDi  = 24;   //  Port bit num Spin Dir
+#endif
+
+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);
+//        direction_swappers = XDi | YDi | ZDi | SDi; //  include bit to swap direction
+
+    PortOut Steppers    (STEPPER_PORT, SM_MASK);
+
+int freq_to_n   (int freq)  {
+    const double factor = (1 << 25) / 390625.0;
+//    unsigned long long ll = ((1 << 31) * freq) / 50000000; 
+    double ll = factor * (double)freq;
+    return  (long) ll;
+}
+//  freq = (50E6 * 'n' / 2**BUS_WIDTH)
+//  'n' = freq * 2**BUS_WIDTH / 50000000
+//  'n' = freq * 2**31 / 25000000
+//  'n' = freq * 2**30 / 12500000
+//  'n' = freq * 2**29 / 6250000
+//  'n' = freq * 2**25 / 390625
+
+int pirs[8], dros[8];
+
+void    FPGA_bit    (int whichbit, int hiorlo)    {
+    int port = Steppers;
+    if  (hiorlo)    port |= whichbit;
+    else            port &= ~whichbit;
+    Steppers = port;
+}
+
+void    FPGA_setup  ()  {
+    int port = Steppers;
+    port |= sclr | clken;
+    Steppers = port;
+    port &= ~sclr;
+    port &= ~clken;
+    port &= ~ld_osr;
+    port &= ~ld_pir;
+    Steppers = port;
+    for (int i = 0; i < 8; i++)
+        pirs[i] = dros[i] = 0;
+}
+
+/*
+--    About Use of 16 bit Command Word
+--    bit 0   -   '1' causes zero reset of phase_inc_reg
+--    bit 1   -   '1' causes zero reset of dro_udcounter
+--    bit 2   -   '1' causes load of phase_inc_reg from input shift reg
+--    bit 3   -   '1' causes load of dro_udcounter from input shift reg 
+--    bit 4   -   '1' causes dro_udcounter --> shift reg ready to read dro value
+--    bit 5   -   '1' causes phase_inc_reg --> shift reg ready to read pir value
+--    bit 6   -   '1' causes reset everything to 0
+--
+--    bit 15  -   '1' causes reset of command_word to all 0 after one clock
+
+*/
+#define zero_pir            0x8001
+#define zero_dro            0x8002
+#define load_pir_from_sr    0x8004
+#define load_dro_from_sr    0x8008
+#define load_dro_into_sr    0x8010
+#define load_pir_into_sr    0x8020
+
+void    FPGA_cmd    (int command_word)  {
+    int port = Steppers;
+    int spirx[8], command_copy = command_word;
+//    pc.printf("At FPGA_cmd, sending %d\r\n", command_word);
+    port |= sclr;       //  cmdhi_datalo set to 1
+    Steppers = port;    //  
+    spirx[0] = spi.write(command_copy >> 8);
+    spirx[1] = spi.write(command_copy);
+    port &= ~sclr;       //  cmdhi_datalo set to 0
+    Steppers = port;    //  
+//    pc.printf("Read spi %x %x\r\n", spirx[0], spirx[1]);
+}
+
+void    setcmd_cmd  (struct singleGparam * a)  {
+    FPGA_cmd    (a[1].i);
+}
+
+//#define load_pir_from_sr    0x8004
+//#define load_dro_into_sr    0x8010
+
+//    DigitalIn   D25pin15_unkn   (p20);    //P1.31 use this to read osr
+int FPGA_rdandwr    (int tosend)  { //  send 32 bits to in_sr, read 32 bits from out_sr
+    int torecv = 0, port = Steppers, tmp;
+//    tosend = freq_to_n(tosend);
+    for (int j = 3; j >= 0; j--) {
+        torecv <<= 8;
+        tmp = tosend >> (j << 3);
+        torecv |= spi.write(tmp);
+    }
+    return  torecv;
+}
+
+const int   numof_ncos = 4;
+
+void    setdro_cmd  (struct singleGparam * a)  {
+    int recd[numof_ncos + 1];
+    pc.printf("At setdro with values ");
+    FPGA_cmd(load_dro_into_sr);
+    for (int k = 0; k < numof_ncos; k++)    {
+        recd[k] = FPGA_rdandwr    (a[k + 1].i);
+        pc.printf("%d, ", a[k + 1].i);
+    }
+    FPGA_cmd(load_dro_from_sr);
+    pc.printf("end\r\n");
+}
+
+void    setpir_cmd  (struct singleGparam * a)  {
+    int recd[numof_ncos + 1];
+    pc.printf("At setpir with values ");
+    FPGA_cmd(load_dro_into_sr);
+    for (int k = 0; k < numof_ncos; k++)    {
+        recd[k] = FPGA_rdandwr    (a[k + 1].i);
+        pc.printf("%d, ", a[k + 1].i);
+    }
+    FPGA_cmd(load_pir_from_sr);
+    pc.printf("end\r\n");
+}
+
+void    getdro_cmd  (struct singleGparam * a)  {
+    int read_dro[numof_ncos + 1];
+    pc.printf("At rddro, retrieved values ");
+    FPGA_cmd(load_dro_into_sr);
+    for (int k = 0; k < numof_ncos; k++)    {
+        read_dro[k] = FPGA_rdandwr (0);
+        pc.printf("%d, ", read_dro[k]);
+    }
+    pc.printf(" end\r\n");
+}
+
+void    getpir_cmd  (struct singleGparam * a)  {
+    int read_pir[numof_ncos + 1];
+    pc.printf("At rdpir, retrieved values ");
+    FPGA_cmd(load_pir_into_sr);
+    for (int k = 0; k < numof_ncos; k++)    {
+        read_pir[k] = FPGA_rdandwr (0);
+        pc.printf("%d, ", read_pir[k]);
+    }
+    pc.printf(" end\r\n");
+}
+
+void    clrpir_cmd  (struct singleGparam * a)  {
+    FPGA_cmd(zero_pir);
+    getpir_cmd(a);    
+}
+
+void    clrdro_cmd  (struct singleGparam * a)  {
+    FPGA_cmd(zero_dro);
+    getdro_cmd(a);    
+}
+
+
+char const * target_str_addr  ()  {
+    return  Target;
+}
+
+void    grain_clr   (struct singleGparam & g)  {
+    g.flt = 0.0;
+    g.ul = 0L;
+    g.i = g.c = 0;
+    g.changed = false;
+}
+void    Gparams_clr    (struct Gparams & p)   {
+    grain_clr   (p.x);    grain_clr   (p.y);    grain_clr   (p.z);    grain_clr   (p.i);    grain_clr   (p.j);
+    grain_clr   (p.r);    grain_clr   (p.a);    grain_clr   (p.b);    grain_clr   (p.c);    grain_clr   (p.d);
+}
+
+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)  {
+        if(!idle)  {
+            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 ;   //  single instance of class digital_readout_stuff
+
+void    millisec_update_ISR ()  {
+    millisecs++;
+}
+
+/*#define STEP_IDLE_HI    //  Choose IDLE_HI or LO to suit any power save function of stepper motor drive units
+//#define STEP_IDLE_LO
+void    Numerically_Controlled_Oscillators_ISR ()  {   // services Ticker 'NCO_gen' generated interrupts ***ISR***
+    static  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  signed  long     //  27 Feb 14 changed from unsigned
+#if defined Fourth_Axis
+        acc_a   = 0L,        pir_a   = 0L,
+#endif
+        acc_x       = 0L,   //  acc Accumuloators
+        pir_x       = 0L,   //  pir Phase Increment Registers
+        acc_y       = 0L,        pir_y   = 0L,
+        acc_z       = 0L,        pir_z   = 0L,
+        acc_spin    = 0L,  //  separate acc for spindle rotation NCO
+        inc_x       = 1L,   //  inc_x, y, z for updating DRO registers
+        inc_y       = 1L,        inc_z   = 1L,
+        dir_bits    = 0L,  //  direction flags for up to four axes
+        oldSteps    = 0L;  //  
+    long tmp, newSteps = 0L;
+
+    intled = 1;     //  LED on for duration of interrupt service - point for scope probing
+    ticks++;        //  count of interrupts serviced, vital to time end of movement
+    charge_pumpD25pin1 = ticks & 0x01;  //  Can use 0x01 or 0x02 here to alter charge pump freq
+    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
+    acc_spin += pir_spin;   //  Spindle NCO
+    if  (acc_spin < 0)  tmp |= SSt;
+    else                tmp &= ~SSt;
+    if  (!running)      Steppers = tmp ^ direction_swappers;    //  Axes not moving, spindle may be turning or not
+    else    {   //  running == true, Further manipulation of tmp follows, prior to rewriting to 'Steppers' IO Port
+//        newSteps = 0L;   //  Added 6th Feb 14
+#if defined Fourth_Axis
+        acc_a   += pir_a;
+        if  (acc_a < 0)    newSteps |= ASt;//  Added 6th Feb 14
+#endif
+        acc_x   += pir_x;     //  Update phase of signals in accumulators
+        if  (acc_x < 0)    newSteps |= XSt;//  Added 6th Feb 14
+        acc_y   += pir_y;
+        if  (acc_y < 0)    newSteps |= YSt;//  Added 6th Feb 14
+        acc_z   += pir_z;
+        if  (acc_z < 0)    newSteps |= ZSt;//  Added 6th Feb 14
+        //  newSteps has copy of all 4 'acc' MSBs shifted into port bit positions
+        oldSteps    ^= newSteps;  //  Any bit of stbits set to initiate a Step pulse
+        tmp         ^= oldSteps;
+        Steppers = tmp ^ direction_swappers; //  Output signals to stepper motor drivers, next update dros from 'clocked' bits CLOCK IDLES HIGH
+        if(oldSteps & XSt)  dro_out.x += inc_x;       //  got clk edge for axis X
+        if(oldSteps & YSt)  dro_out.y += inc_y;       //  got clk edge for axis Y
+        if(oldSteps & ZSt)  dro_out.z += inc_z;       //  got clk edge for axis Z
+        oldSteps    = newSteps;   //  Added 6th Feb 14
+        if  (tickrun <= ticks & !new_run_pending)   {   //  End of a machine movement detected, start next move here if possible
+                running = false;
+                move_ended = true;
+                pir_x = 0L; //  stop all stepper motors
+                pir_y = 0L;
+                pir_z = 0L;
+#if defined Fourth_Axis
+                pir_a = 0L;
+#endif
+    //          ticks = 0L; //  Simply to avoid having to think about overflow problems
+        }       //  end of if   (tickrun <= ticks)  {
+    }           //  end of else is   (running)   {
+    if  (!running & new_run_pending)  { //  Start axis movement
+        dir_bits= dir_bits_next;
+#if defined Fourth_Axis
+        pir_a   = pir_a_next;
+#endif
+        pir_x   = pir_x_next;
+        pir_y   = pir_y_next;
+        pir_z   = pir_z_next;
+        inc_x   = inc_x_next;
+        inc_y   = inc_y_next;
+        inc_z   = inc_z_next;
+        tmp     = Steppers ^ direction_swappers;  //  read output lines
+        tmp     &= ~dir_mask;
+        tmp     |= dir_bits;
+        Steppers = tmp ^ 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     else    {   //  Not running. Grab next data here when or if available
+    intled = 0;         //  LED off
+}           //  end of interrupt handler
+*/
+/*
+*   End of Interrupt Service Routine
+*/
+/*bool    spindle_running ()  {
+*/
+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);
+}
+
+int main() {
+    long    ins, ins_old, ins_changed = 0;
+    pc.baud(BAUD); //  comms to 'PuTTY' serial terminal via mbed usb
+    spi.format  (8,0);          //  use 8 bit format for compatibility with Freescale KLxxZ
+    spi.frequency(12000000);    //  12MHz, fast enough
+    dro_out.init    ();
+    FPGA_setup();
+    pc.printf("\r\n*\n*\nFound Computer %s\r\n", Target);
+
+    msec.attach_us(&millisec_update_ISR, 1001);
+
+    Thread comlin (command_line_interpreter,    (void *)"cli"); //  Read any instructions arriving via serial port and act upon them
+//#if defined I2C_Enable
+//    Thread i2cstuff (i2c_handler, (void *)"i2c thing");
+//#endif
+    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);
+        osThreadYield();                //
+    }   //  end of Round Robin loop
+}       //  end of int main()
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-rtos.lib	Thu Apr 24 15:35:38 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed-rtos/#4ef72665e2c8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Thu Apr 24 15:35:38 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/6473597d706e
\ No newline at end of file