smoothie port to mbed online compiler (smoothieware.org)

Dependencies:   mbed

For documentation, license, ..., please check http://smoothieware.org/

This version has been tested with a 3 axis machine

Files at this revision

API Documentation at this revision

Comitter:
scachat
Date:
Tue Jul 31 21:11:18 2012 +0000
Commit message:
smoothie port to mbed online compiler

Changed in this revision

libs/ADC/adc.cpp Show annotated file Show diff for this revision Revisions of this file
libs/ADC/adc.h Show annotated file Show diff for this revision Revisions of this file
libs/Adc.cpp Show annotated file Show diff for this revision Revisions of this file
libs/Adc.h Show annotated file Show diff for this revision Revisions of this file
libs/Config.cpp Show annotated file Show diff for this revision Revisions of this file
libs/Config.h Show annotated file Show diff for this revision Revisions of this file
libs/ConfigCache.h Show annotated file Show diff for this revision Revisions of this file
libs/ConfigSource.h Show annotated file Show diff for this revision Revisions of this file
libs/ConfigSources/FileConfigSource.cpp Show annotated file Show diff for this revision Revisions of this file
libs/ConfigSources/FileConfigSource.h Show annotated file Show diff for this revision Revisions of this file
libs/ConfigValue.h Show annotated file Show diff for this revision Revisions of this file
libs/Digipot.h Show annotated file Show diff for this revision Revisions of this file
libs/FPointer.h Show annotated file Show diff for this revision Revisions of this file
libs/Hook.cpp Show annotated file Show diff for this revision Revisions of this file
libs/Hook.h Show annotated file Show diff for this revision Revisions of this file
libs/Kernel.cpp Show annotated file Show diff for this revision Revisions of this file
libs/Kernel.h Show annotated file Show diff for this revision Revisions of this file
libs/Module.cpp Show annotated file Show diff for this revision Revisions of this file
libs/Module.h Show annotated file Show diff for this revision Revisions of this file
libs/Pauser.cpp Show annotated file Show diff for this revision Revisions of this file
libs/Pauser.h Show annotated file Show diff for this revision Revisions of this file
libs/Pin.h Show annotated file Show diff for this revision Revisions of this file
libs/RingBuffer.h Show annotated file Show diff for this revision Revisions of this file
libs/RingBuffer.o Show annotated file Show diff for this revision Revisions of this file
libs/SerialMessage.h Show annotated file Show diff for this revision Revisions of this file
libs/SlowTicker.cpp Show annotated file Show diff for this revision Revisions of this file
libs/SlowTicker.h Show annotated file Show diff for this revision Revisions of this file
libs/StepTicker.cpp Show annotated file Show diff for this revision Revisions of this file
libs/StepTicker.h Show annotated file Show diff for this revision Revisions of this file
libs/StreamOutput.h Show annotated file Show diff for this revision Revisions of this file
libs/nuts_bolts.h Show annotated file Show diff for this revision Revisions of this file
libs/utils.cpp Show annotated file Show diff for this revision Revisions of this file
libs/utils.h 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.bld Show annotated file Show diff for this revision Revisions of this file
modules/communication/GcodeDispatch.cpp Show annotated file Show diff for this revision Revisions of this file
modules/communication/GcodeDispatch.h Show annotated file Show diff for this revision Revisions of this file
modules/communication/SerialConsole.cpp Show annotated file Show diff for this revision Revisions of this file
modules/communication/SerialConsole.h Show annotated file Show diff for this revision Revisions of this file
modules/communication/utils/Gcode.cpp Show annotated file Show diff for this revision Revisions of this file
modules/communication/utils/Gcode.h Show annotated file Show diff for this revision Revisions of this file
modules/robot/Block.cpp Show annotated file Show diff for this revision Revisions of this file
modules/robot/Block.h Show annotated file Show diff for this revision Revisions of this file
modules/robot/Planner.cpp Show annotated file Show diff for this revision Revisions of this file
modules/robot/Planner.h Show annotated file Show diff for this revision Revisions of this file
modules/robot/Player.cpp Show annotated file Show diff for this revision Revisions of this file
modules/robot/Player.h Show annotated file Show diff for this revision Revisions of this file
modules/robot/Robot.cpp Show annotated file Show diff for this revision Revisions of this file
modules/robot/Robot.h Show annotated file Show diff for this revision Revisions of this file
modules/robot/Stepper.cpp Show annotated file Show diff for this revision Revisions of this file
modules/robot/Stepper.h Show annotated file Show diff for this revision Revisions of this file
modules/robot/arm_solutions/BaseSolution.cpp Show annotated file Show diff for this revision Revisions of this file
modules/robot/arm_solutions/BaseSolution.h Show annotated file Show diff for this revision Revisions of this file
modules/robot/arm_solutions/CartesianSolution.cpp Show annotated file Show diff for this revision Revisions of this file
modules/robot/arm_solutions/CartesianSolution.h Show annotated file Show diff for this revision Revisions of this file
modules/tools/extruder/Extruder.cpp Show annotated file Show diff for this revision Revisions of this file
modules/tools/extruder/Extruder.h Show annotated file Show diff for this revision Revisions of this file
modules/tools/laser/Laser.cpp Show annotated file Show diff for this revision Revisions of this file
modules/tools/laser/Laser.h Show annotated file Show diff for this revision Revisions of this file
modules/tools/spindle/Spindle.cpp Show annotated file Show diff for this revision Revisions of this file
modules/tools/spindle/Spindle.h Show annotated file Show diff for this revision Revisions of this file
modules/tools/temperaturecontrol/TemperatureControl.cpp Show annotated file Show diff for this revision Revisions of this file
modules/tools/temperaturecontrol/TemperatureControl.h Show annotated file Show diff for this revision Revisions of this file
modules/tools/temperaturecontrol/TemperatureControlPool.cpp Show annotated file Show diff for this revision Revisions of this file
modules/tools/temperaturecontrol/TemperatureControlPool.h Show annotated file Show diff for this revision Revisions of this file
modules/utils/configurator/Configurator.cpp Show annotated file Show diff for this revision Revisions of this file
modules/utils/configurator/Configurator.h Show annotated file Show diff for this revision Revisions of this file
modules/utils/currentcontrol/CurrentControl.cpp Show annotated file Show diff for this revision Revisions of this file
modules/utils/currentcontrol/CurrentControl.h Show annotated file Show diff for this revision Revisions of this file
modules/utils/pausebutton/PauseButton.cpp Show annotated file Show diff for this revision Revisions of this file
modules/utils/pausebutton/PauseButton.h Show annotated file Show diff for this revision Revisions of this file
modules/utils/simpleshell/SimpleShell.cpp Show annotated file Show diff for this revision Revisions of this file
modules/utils/simpleshell/SimpleShell.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 31e91bb0ef3c libs/ADC/adc.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/ADC/adc.cpp	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,439 @@
+/* mbed Library - ADC
+ * Copyright (c) 2010, sblandford
+ * released under MIT license http://mbed.org/licence/mit
+ */
+#include "mbed.h"
+#include "adc.h"
+
+
+ADC *ADC::instance;
+
+ADC::ADC(int sample_rate, int cclk_div)
+    {
+
+    int i, adc_clk_freq, pclk, clock_div, max_div=1;
+
+    //Work out CCLK
+    adc_clk_freq=CLKS_PER_SAMPLE*sample_rate;
+    int m = (LPC_SC->PLL0CFG & 0xFFFF) + 1;
+    int n = (LPC_SC->PLL0CFG >> 16) + 1;
+    int cclkdiv = LPC_SC->CCLKCFG + 1;
+    int Fcco = (2 * m * XTAL_FREQ) / n;
+    int cclk = Fcco / cclkdiv;
+
+    //Power up the ADC        
+    LPC_SC->PCONP |= (1 << 12);
+    //Set clock at cclk / 1.
+    LPC_SC->PCLKSEL0 &= ~(0x3 << 24);    
+    switch (cclk_div) {
+        case 1:
+            LPC_SC->PCLKSEL0 |= 0x1 << 24;
+            break;
+        case 2:
+            LPC_SC->PCLKSEL0 |= 0x2 << 24;
+            break;
+        case 4:
+            LPC_SC->PCLKSEL0 |= 0x0 << 24;
+            break;
+        case 8:
+            LPC_SC->PCLKSEL0 |= 0x3 << 24;
+            break;
+        default:
+            printf("Warning: ADC CCLK clock divider must be 1, 2, 4 or 8. %u supplied.\n",
+                cclk_div);
+            printf("Defaulting to 1.\n");
+            LPC_SC->PCLKSEL0 |= 0x1 << 24;
+            break;
+    }
+    pclk = cclk / cclk_div;
+    clock_div=pclk / adc_clk_freq;
+
+    if (clock_div > 0xFF) {
+        //printf("Warning: Clock division is %u which is above 255 limit. Re-Setting at limit.\n",
+        //    clock_div);
+        clock_div=0xFF;
+    }
+    if (clock_div == 0) {
+        printf("Warning: Clock division is 0. Re-Setting to 1.\n");
+        clock_div=1;
+    }
+
+    _adc_clk_freq=pclk / clock_div;
+    if (_adc_clk_freq > MAX_ADC_CLOCK) {
+        printf("Warning: Actual ADC sample rate of %u which is above %u limit\n",
+            _adc_clk_freq / CLKS_PER_SAMPLE, MAX_ADC_CLOCK / CLKS_PER_SAMPLE);
+        while ((pclk / max_div) > MAX_ADC_CLOCK) max_div++;
+        printf("Maximum recommended sample rate is %u\n", (pclk / max_div) / CLKS_PER_SAMPLE);
+    }
+
+    LPC_ADC->ADCR =
+        ((clock_div - 1 ) << 8 ) |    //Clkdiv
+        ( 1 << 21 );                  //A/D operational
+
+    //Default no channels enabled
+    LPC_ADC->ADCR &= ~0xFF;
+    //Default NULL global custom isr
+    _adc_g_isr = NULL;
+    //Initialize arrays
+    for (i=7; i>=0; i--) {
+        _adc_data[i] = 0;
+        _adc_isr[i] = NULL;
+    }
+
+
+    //* Attach IRQ
+    instance = this;
+    NVIC_SetVector(ADC_IRQn, (uint32_t)&_adcisr);
+
+    //Disable global interrupt
+    LPC_ADC->ADINTEN &= ~0x100;
+
+};
+
+void ADC::_adcisr(void)
+{
+    instance->adcisr();
+}
+
+
+void ADC::adcisr(void)  
+{
+    uint32_t stat;
+    int chan;
+
+    // Read status
+    stat = LPC_ADC->ADSTAT;
+    //Scan channels for over-run or done and update array
+    if (stat & 0x0101) _adc_data[0] = LPC_ADC->ADDR0;
+    if (stat & 0x0202) _adc_data[1] = LPC_ADC->ADDR1;
+    if (stat & 0x0404) _adc_data[2] = LPC_ADC->ADDR2;
+    if (stat & 0x0808) _adc_data[3] = LPC_ADC->ADDR3;
+    if (stat & 0x1010) _adc_data[4] = LPC_ADC->ADDR4;
+    if (stat & 0x2020) _adc_data[5] = LPC_ADC->ADDR5;
+    if (stat & 0x4040) _adc_data[6] = LPC_ADC->ADDR6;
+    if (stat & 0x8080) _adc_data[7] = LPC_ADC->ADDR7;
+
+    // Channel that triggered interrupt
+    chan = (LPC_ADC->ADGDR >> 24) & 0x07;
+    //User defined interrupt handlers
+    if (_adc_isr[chan] != NULL)
+        _adc_isr[chan](_adc_data[chan]);
+    if (_adc_g_isr != NULL)
+        _adc_g_isr(chan, _adc_data[chan]); 
+    return;
+}
+
+int ADC::_pin_to_channel(PinName pin) {
+    int chan;
+    switch (pin) {
+        case p15://=p0.23 of LPC1768
+        default:
+            chan=0;
+            break;
+        case p16://=p0.24 of LPC1768
+            chan=1;
+            break;
+        case p17://=p0.25 of LPC1768
+            chan=2;
+            break;
+        case p18://=p0.26 of LPC1768
+            chan=3;
+            break;
+        case p19://=p1.30 of LPC1768
+            chan=4;
+            break;
+        case p20://=p1.31 of LPC1768
+            chan=5;
+            break;
+    }
+    return(chan);
+}
+
+PinName ADC::channel_to_pin(int chan) {
+    const PinName pin[8]={p15, p16, p17, p18, p19, p20, p15, p15};
+    
+    if ((chan < 0) || (chan > 5))
+        fprintf(stderr, "ADC channel %u is outside range available to MBED pins.\n", chan);
+    return(pin[chan & 0x07]);
+} 
+
+
+int ADC::channel_to_pin_number(int chan) {
+    const int pin[8]={15, 16, 17, 18, 19, 20, 0, 0};
+    
+    if ((chan < 0) || (chan > 5))
+        fprintf(stderr, "ADC channel %u is outside range available to MBED pins.\n", chan);
+    return(pin[chan & 0x07]);
+} 
+
+
+uint32_t ADC::_data_of_pin(PinName pin) {
+    //If in burst mode and at least one interrupt enabled then
+    //take all values from _adc_data
+    if (burst() && (LPC_ADC->ADINTEN & 0x3F)) {
+        return(_adc_data[_pin_to_channel(pin)]);
+    } else {
+        //Return current register value or last value from interrupt
+        switch (pin) {
+            case p15://=p0.23 of LPC1768
+            default:
+                return(LPC_ADC->ADINTEN & 0x01?_adc_data[0]:LPC_ADC->ADDR0);
+            case p16://=p0.24 of LPC1768
+                return(LPC_ADC->ADINTEN & 0x02?_adc_data[1]:LPC_ADC->ADDR1);
+            case p17://=p0.25 of LPC1768
+                return(LPC_ADC->ADINTEN & 0x04?_adc_data[2]:LPC_ADC->ADDR2);
+            case p18://=p0.26 of LPC1768:
+                return(LPC_ADC->ADINTEN & 0x08?_adc_data[3]:LPC_ADC->ADDR3);
+            case p19://=p1.30 of LPC1768
+                return(LPC_ADC->ADINTEN & 0x10?_adc_data[4]:LPC_ADC->ADDR4);
+            case p20://=p1.31 of LPC1768
+                return(LPC_ADC->ADINTEN & 0x20?_adc_data[5]:LPC_ADC->ADDR5);
+        }
+    }
+}
+
+//Enable or disable an ADC pin
+void ADC::setup(PinName pin, int state) {
+    int chan;    
+    chan=_pin_to_channel(pin);
+    if ((state & 1) == 1) {
+        switch(pin) {
+            case p15://=p0.23 of LPC1768
+            default:
+                LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 14);
+                LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 14;
+                LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 14);
+                LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 14;
+                break;
+            case p16://=p0.24 of LPC1768
+                LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 16);
+                LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 16;
+                LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 16);
+                LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 16;
+                break;
+            case p17://=p0.25 of LPC1768
+                LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 18);
+                LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 18;
+                LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 18);
+                LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 18;
+                break;
+            case p18://=p0.26 of LPC1768:
+                LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 20);
+                LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 20;
+                LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 20);
+                LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 20;
+                break;
+            case p19://=p1.30 of LPC1768
+                LPC_PINCON->PINSEL3 &= ~((unsigned int)0x3 << 28);
+                LPC_PINCON->PINSEL3 |= (unsigned int)0x3 << 28;
+                LPC_PINCON->PINMODE3 &= ~((unsigned int)0x3 << 28);
+                LPC_PINCON->PINMODE3 |= (unsigned int)0x2 << 28;
+                break;
+            case p20://=p1.31 of LPC1768
+                LPC_PINCON->PINSEL3 &= ~((unsigned int)0x3 << 30);
+                LPC_PINCON->PINSEL3 |= (unsigned int)0x3 << 30;
+                LPC_PINCON->PINMODE3 &= ~((unsigned int)0x3 << 30);
+                LPC_PINCON->PINMODE3 |= (unsigned int)0x2 << 30;
+               break;
+        }
+        //Only one channel can be selected at a time if not in burst mode
+        if (!burst()) LPC_ADC->ADCR &= ~0xFF;
+        //Select channel
+        LPC_ADC->ADCR |= (1 << chan);
+    }
+    else {
+        switch(pin) {
+            case p15://=p0.23 of LPC1768
+            default:
+                LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 14);
+                LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 14);
+                break;
+            case p16://=p0.24 of LPC1768
+                LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 16);
+                LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 16);
+                break;
+            case p17://=p0.25 of LPC1768
+                LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 18);
+                LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 18);
+                break;
+            case p18://=p0.26 of LPC1768:
+                LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 20);
+                LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 20);
+                break;
+            case p19://=p1.30 of LPC1768
+                LPC_PINCON->PINSEL3 &= ~((unsigned int)0x3 << 28);
+                LPC_PINCON->PINMODE3 &= ~((unsigned int)0x3 << 28);
+                break;
+            case p20://=p1.31 of LPC1768
+                LPC_PINCON->PINSEL3 &= ~((unsigned int)0x3 << 30);
+                LPC_PINCON->PINMODE3 &= ~((unsigned int)0x3 << 30);
+                break;
+        }
+        LPC_ADC->ADCR &= ~(1 << chan);
+    }
+}
+//Return channel enabled/disabled state
+int ADC::setup(PinName pin) {
+    int chan;
+    
+    chan = _pin_to_channel(pin);
+    return((LPC_ADC->ADCR & (1 << chan)) >> chan);
+}
+
+//Select channel already setup
+void ADC::select(PinName pin) {
+    int chan;
+    
+    //Only one channel can be selected at a time if not in burst mode
+    if (!burst()) LPC_ADC->ADCR &= ~0xFF;
+    //Select channel
+    chan = _pin_to_channel(pin);
+    LPC_ADC->ADCR |= (1 << chan);
+}
+
+//Enable or disable burst mode
+void ADC::burst(int state) {
+    if ((state & 1) == 1) {
+        if (startmode(0) != 0)
+            fprintf(stderr, "Warning. startmode is %u. Must be 0 for burst mode.\n", startmode(0));
+        LPC_ADC->ADCR |= (1 << 16);
+    }
+    else 
+        LPC_ADC->ADCR &= ~(1 << 16);
+}
+//Return burst mode state
+int  ADC::burst(void) {
+    return((LPC_ADC->ADCR & (1 << 16)) >> 16);
+}
+
+//Set startmode and edge
+void ADC::startmode(int mode, int edge) {
+    int lpc_adc_temp;
+    
+    //Reset start mode and edge bit, 
+    lpc_adc_temp = LPC_ADC->ADCR & ~(0x0F << 24);
+    //Write with new values
+    lpc_adc_temp |= ((mode & 7) << 24) | ((edge & 1) << 27);
+    LPC_ADC->ADCR = lpc_adc_temp;
+}
+
+//Return startmode state according to mode_edge=0: mode and mode_edge=1: edge
+int ADC::startmode(int mode_edge){
+    switch (mode_edge) {
+        case 0:
+        default:
+            return((LPC_ADC->ADCR >> 24) & 0x07);
+        case 1:
+            return((LPC_ADC->ADCR >> 27) & 0x01);
+    }
+}
+
+//Start ADC conversion
+void ADC::start(void) {
+    startmode(1,0);
+}
+
+
+//Set interrupt enable/disable for pin to state
+void ADC::interrupt_state(PinName pin, int state) {
+    int chan;
+    
+    chan = _pin_to_channel(pin);
+    if (state == 1) {
+        LPC_ADC->ADINTEN &= ~0x100;
+        LPC_ADC->ADINTEN |= 1 << chan;
+        /* Enable the ADC Interrupt */
+        NVIC_EnableIRQ(ADC_IRQn);
+    } else {
+        LPC_ADC->ADINTEN &= ~( 1 << chan );
+        //Disable interrrupt if no active pins left
+        if ((LPC_ADC->ADINTEN & 0xFF) == 0)
+            NVIC_DisableIRQ(ADC_IRQn);
+    }
+}
+
+//Return enable/disable state of interrupt for pin
+int ADC::interrupt_state(PinName pin) {
+    int chan;
+        
+    chan = _pin_to_channel(pin);
+    return((LPC_ADC->ADINTEN >> chan) & 0x01);
+}
+
+
+//Attach custom interrupt handler replacing default
+void ADC::attach(void(*fptr)(void)) {
+    //* Attach IRQ
+    NVIC_SetVector(ADC_IRQn, (uint32_t)fptr);
+}
+
+//Restore default interrupt handler
+void ADC::detach(void) {
+    //* Attach IRQ
+    instance = this;
+    NVIC_SetVector(ADC_IRQn, (uint32_t)&_adcisr);
+}
+
+
+//Append interrupt handler for pin to function isr
+void ADC::append(PinName pin, void(*fptr)(uint32_t value)) {
+    int chan;
+        
+    chan = _pin_to_channel(pin);
+    _adc_isr[chan] = fptr;
+}
+
+//Append interrupt handler for pin to function isr
+void ADC::unappend(PinName pin) {
+    int chan;
+        
+    chan = _pin_to_channel(pin);
+    _adc_isr[chan] = NULL;
+}
+
+//Unappend global interrupt handler to function isr
+void ADC::append(void(*fptr)(int chan, uint32_t value)) {
+    _adc_g_isr = fptr;
+}
+
+//Detach global interrupt handler to function isr
+void ADC::unappend() {
+    _adc_g_isr = NULL;
+}
+
+//Set ADC offset
+void offset(int offset) {
+    LPC_ADC->ADTRM &= ~(0x07 << 4);
+    LPC_ADC->ADTRM |= (offset & 0x07) << 4;
+}
+
+//Return current ADC offset
+int offset(void) {
+    return((LPC_ADC->ADTRM >> 4) & 0x07);
+}
+
+//Return value of ADC on pin
+int ADC::read(PinName pin) {
+    //Reset DONE and OVERRUN flags of interrupt handled ADC data
+    _adc_data[_pin_to_channel(pin)] &= ~(((uint32_t)0x01 << 31) | ((uint32_t)0x01 << 30));
+    //Return value
+    return((_data_of_pin(pin) >> 4) & 0xFFF);
+}
+
+//Return DONE flag of ADC on pin
+int ADC::done(PinName pin) {
+    return((_data_of_pin(pin) >> 31) & 0x01);
+}
+
+//Return OVERRUN flag of ADC on pin
+int ADC::overrun(PinName pin) {
+    return((_data_of_pin(pin) >> 30) & 0x01);
+}
+
+int ADC::actual_adc_clock(void) {
+    return(_adc_clk_freq);
+}
+
+int ADC::actual_sample_rate(void) {
+    return(_adc_clk_freq / CLKS_PER_SAMPLE);
+}
diff -r 000000000000 -r 31e91bb0ef3c libs/ADC/adc.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/ADC/adc.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,131 @@
+/* mbed Library - ADC
+ * Copyright (c) 2010, sblandford
+ * released under MIT license http://mbed.org/licence/mit
+ */
+
+#ifndef MBED_ADC_H
+#define MBED_ADC_H
+ 
+#include "PinNames.h" // mbed.h lib
+#define XTAL_FREQ       12000000
+#define MAX_ADC_CLOCK   13000000
+#define CLKS_PER_SAMPLE 64
+
+class ADC {
+public:
+
+    //Initialize ADC with ADC maximum sample rate of
+    //sample_rate and system clock divider of cclk_div
+    //Maximum recommened sample rate is 184000
+    ADC(int sample_rate, int cclk_div);
+
+    //Enable/disable ADC on pin according to state
+    //and also select/de-select for next conversion
+    void setup(PinName pin, int state);
+
+    //Return enabled/disabled state of ADC on pin
+    int setup(PinName pin);
+
+    //Enable/disable burst mode according to state
+    void burst(int state);
+
+    //Select channel already setup
+    void select(PinName pin);
+
+    //Return burst mode enabled/disabled
+    int burst(void);
+
+    /*Set start condition and edge according to mode:
+    0 - No start (this value should be used when clearing PDN to 0).
+    1 - Start conversion now.
+    2 - Start conversion when the edge selected by bit 27 occurs on the P2.10 / EINT0 / NMI pin.
+    3 - Start conversion when the edge selected by bit 27 occurs on the P1.27 / CLKOUT /
+        USB_OVRCRn / CAP0.1 pin.
+    4 - Start conversion when the edge selected by bit 27 occurs on MAT0.1. Note that this does
+        not require that the MAT0.1 function appear on a device pin.
+    5 - Start conversion when the edge selected by bit 27 occurs on MAT0.3. Note that it is not
+        possible to cause the MAT0.3 function to appear on a device pin.
+    6 - Start conversion when the edge selected by bit 27 occurs on MAT1.0. Note that this does
+        not require that the MAT1.0 function appear on a device pin.
+    7 - Start conversion when the edge selected by bit 27 occurs on MAT1.1. Note that this does
+        not require that the MAT1.1 function appear on a device pin.
+    When mode >= 2, conversion is triggered by edge:
+    0 - Rising edge
+    1 - Falling edge
+    */
+    void startmode(int mode, int edge);
+    
+    //Return startmode state according to mode_edge=0: mode and mode_edge=1: edge
+    int startmode(int mode_edge);
+    
+    //Start ADC conversion
+    void start(void);
+
+    //Set interrupt enable/disable for pin to state
+    void interrupt_state(PinName pin, int state);
+    
+    //Return enable/disable state of interrupt for pin
+    int interrupt_state(PinName pin);
+
+    //Attach custom interrupt handler replacing default
+    void attach(void(*fptr)(void));
+
+    //Restore default interrupt handler
+    void detach(void);
+
+    //Append custom interrupt handler for pin
+    void append(PinName pin, void(*fptr)(uint32_t value));
+
+    //Unappend custom interrupt handler for pin
+    void unappend(PinName pin);
+
+    //Append custom global interrupt handler
+    void append(void(*fptr)(int chan, uint32_t value));
+
+    //Unappend custom global interrupt handler
+    void unappend(void);
+
+    //Set ADC offset to a value 0-7
+    void offset(int offset);
+    
+    //Return current ADC offset
+    int offset(void);
+
+    //Return value of ADC on pin
+    int read(PinName pin);
+
+    //Return DONE flag of ADC on pin
+    int done(PinName pin);
+    
+    //Return OVERRUN flag of ADC on pin
+    int overrun(PinName pin);
+
+    //Return actual ADC clock
+    int actual_adc_clock(void);
+    
+    //Return actual maximum sample rate
+    int actual_sample_rate(void);
+
+    //Return pin ID of ADC channel
+    PinName channel_to_pin(int chan);
+
+    //Return pin number of ADC channel
+    int channel_to_pin_number(int chan);
+
+
+private:
+    int _pin_to_channel(PinName pin);
+    uint32_t _data_of_pin(PinName pin);
+
+    int _adc_clk_freq;
+    void adcisr(void);
+    static void _adcisr(void);
+    static ADC *instance;
+    
+    uint32_t _adc_data[8];
+    void(*_adc_isr[8])(uint32_t value);
+    void(*_adc_g_isr)(int chan, uint32_t value);
+    void(*_adc_m_isr)(void);
+};
+
+#endif
diff -r 000000000000 -r 31e91bb0ef3c libs/Adc.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/Adc.cpp	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,51 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+using namespace std;
+#include <vector>
+#include "libs/nuts_bolts.h"
+#include "libs/Module.h"
+#include "libs/Kernel.h"
+#include "Adc.h"
+#include "libs/ADC/adc.h"
+#include "libs/Pin.h"
+
+Adc::Adc(){
+    this->adc = new ADC(1000, 1);
+}
+
+void Adc::enable_pin(Pin* pin){
+    PinName pin_name = this->_pin_to_pinname(pin);
+    this->adc->burst(1);
+    this->adc->setup(pin_name,1);
+    this->adc->interrupt_state(pin_name,1);
+}
+
+unsigned int Adc::read(Pin* pin){
+    return this->adc->read(this->_pin_to_pinname(pin));
+}
+
+PinName Adc::_pin_to_pinname(Pin* pin){
+    if( pin->port == LPC_GPIO0 && pin->pin == 23 ){ 
+        return p15;
+    }else if( pin->port == LPC_GPIO0 && pin->pin == 24 ){ 
+        return p16;
+    }else if( pin->port == LPC_GPIO0 && pin->pin == 25 ){ 
+        return p17;
+    }else if( pin->port == LPC_GPIO0 && pin->pin == 26 ){ 
+        return p18;
+    }else if( pin->port == LPC_GPIO1 && pin->pin == 30 ){ 
+        return p19;
+    }else if( pin->port == LPC_GPIO1 && pin->pin == 31 ){ 
+        return p20;
+    }else{
+        //TODO: Error
+        error("Bad adc pin");
+        
+    }
+}
+
diff -r 000000000000 -r 31e91bb0ef3c libs/Adc.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/Adc.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,34 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+
+
+#ifndef ADC_H
+#define ADC_H
+
+using namespace std;
+#include <vector>
+#include "libs/nuts_bolts.h"
+#include "libs/Module.h"
+#include "libs/Kernel.h"
+#include "PinNames.h" // mbed.h lib
+#include "libs/ADC/adc.h"
+#include "libs/Pin.h"
+
+class Adc : public Module{
+    public:
+        Adc();
+        void enable_pin(Pin* pin);
+        unsigned int read(Pin* pin);
+        PinName _pin_to_pinname(Pin* pin);
+
+        ADC* adc;
+};
+
+
+
+#endif
diff -r 000000000000 -r 31e91bb0ef3c libs/Config.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/Config.cpp	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,150 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+
+using namespace std;
+#include <vector>
+#include <string>
+
+#include "libs/Kernel.h"
+#include "Config.h"
+#include "ConfigValue.h"
+#include "ConfigSource.h"
+#include "ConfigCache.h"
+#include "libs/nuts_bolts.h"
+#include "libs/utils.h"
+#include "libs/SerialMessage.h"
+#include "libs/ConfigSources/FileConfigSource.h"
+
+
+Config::Config(){
+
+    this->config_cache_loaded = false;
+
+    // Config source for */config files
+    this->config_sources.push_back( new FileConfigSource("/local/config", LOCAL_CONFIGSOURCE_CHECKSUM) );
+    //this->config_sources.push_back( new FileConfigSource("/sd/config",    SD_CONFIGSOURCE_CHECKSUM   ) );
+
+    // Pre-load the config cache
+    this->config_cache_load();
+
+}
+
+void Config::on_module_loaded(){}
+
+void Config::on_console_line_received( void* argument ){}
+
+void Config::set_string( string setting, string value ){
+    ConfigValue* cv = new ConfigValue;
+    cv->found = true;
+    cv->check_sums = get_checksums(setting);
+    cv->value = value;
+
+    this->config_cache.replace_or_push_back(cv);
+
+    this->kernel->call_event(ON_CONFIG_RELOAD);
+}
+
+void Config::get_module_list(vector<uint16_t>* list, uint16_t family){ 
+    for( int i=1; i<this->config_cache.size(); i++){
+        ConfigValue* value = this->config_cache.at(i); 
+        if( value->check_sums.size() == 3 && value->check_sums.at(2) == 29545 && value->check_sums.at(0) == family ){
+            // We found a module enable for this family, add it's number 
+            list->push_back(value->check_sums.at(1));
+        } 
+    }
+}
+
+
+// Command to load config cache into buffer for multiple reads during init
+void Config::config_cache_load(){
+
+    this->config_cache_clear();
+
+    // First element is a special empty ConfigValue for values not found
+    ConfigValue* result = new ConfigValue;
+    this->config_cache.push_back(result);
+    // For each ConfigSource in our stack
+    for( unsigned int i = 0; i < this->config_sources.size(); i++ ){
+        ConfigSource* source = this->config_sources[i];
+        source->transfer_values_to_cache(&this->config_cache);
+    }
+
+    this->config_cache_loaded = true;
+}
+
+// Command to clear the config cache after init
+void Config::config_cache_clear(){
+    while( ! this->config_cache.empty() ){
+        delete this->config_cache.back();
+        this->config_cache.pop_back();
+    }
+    this->config_cache_loaded = false;
+}
+
+
+ConfigValue* Config::value(uint16_t check_sum_a, uint16_t check_sum_b, uint16_t check_sum_c ){
+    vector<uint16_t> check_sums;
+    check_sums.push_back(check_sum_a); 
+    check_sums.push_back(check_sum_b); 
+    check_sums.push_back(check_sum_c); 
+    return this->value(check_sums);
+}    
+
+ConfigValue* Config::value(uint16_t check_sum_a, uint16_t check_sum_b){
+    vector<uint16_t> check_sums;
+    check_sums.push_back(check_sum_a); 
+    check_sums.push_back(check_sum_b); 
+    return this->value(check_sums);
+}    
+
+ConfigValue* Config::value(uint16_t check_sum){
+    vector<uint16_t> check_sums;
+    check_sums.push_back(check_sum); 
+    return this->value(check_sums);
+}    
+    
+// Get a value from the configuration as a string
+// Because we don't like to waste space in Flash with lengthy config parameter names, we take a checksum instead so that the name does not have to be stored
+// See get_checksum
+ConfigValue* Config::value(vector<uint16_t> check_sums){
+    ConfigValue* result = this->config_cache[0];
+    //if( this->has_config_file() == false ){
+    //   return result;
+    //} 
+    // Check if the config is cached, and load it temporarily if it isn't
+    bool cache_preloaded = this->config_cache_loaded;
+    if( !cache_preloaded ){ this->config_cache_load(); }
+     
+    for( int i=1; i<this->config_cache.size(); i++){
+        // If this line matches the checksum 
+        bool match = true;
+        for( unsigned int j = 0; j < check_sums.size(); j++ ){
+            uint16_t checksum_node = check_sums[j];
+           
+            //printf("%u(%s) against %u\r\n", get_checksum(key_node), key_node.c_str(), checksum_node);
+            if(this->config_cache[i]->check_sums[j] != checksum_node ){
+                match = false;
+                break; 
+            }
+        } 
+        if( match == false ){ 
+            //printf("continue\r\n");
+            continue; 
+        }
+        result = this->config_cache[i];
+        break;
+    }
+    
+    if( !cache_preloaded ){
+        this->config_cache_clear();
+    }
+    return result;
+}
+
+
+
diff -r 000000000000 -r 31e91bb0ef3c libs/Config.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/Config.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,53 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+#include "libs/Kernel.h"
+#include "libs/utils.h"
+#include "libs/Pin.h"
+#include "ConfigValue.h"
+#include "ConfigCache.h"
+#include "ConfigSource.h"
+#include "libs/ConfigSources/FileConfigSource.h"
+
+#define error(...) (fprintf(stderr, __VA_ARGS__), exit(1))
+
+using namespace std;
+#include <vector>
+#include <string>
+#include <stdio.h>
+
+#define LOCAL_CONFIGSOURCE_CHECKSUM     13581
+#define SD_CONFIGSOURCE_CHECKSUM        19415
+
+
+class Config : public Module {
+    public:
+        Config();
+
+        virtual void on_module_loaded();
+        virtual void on_console_line_received( void* argument );
+        void config_cache_load();
+        void config_cache_clear();
+        void set_string( string setting , string value);
+
+        ConfigValue* value(uint16_t check_sum);
+        ConfigValue* value(uint16_t check_sum_a, uint16_t check_sum_b);
+        ConfigValue* value(uint16_t check_sum_a, uint16_t check_sum_b, uint16_t check_sum_c );
+        ConfigValue* value(vector<uint16_t> check_sums );
+
+        void get_module_list(vector<uint16_t>* list, uint16_t family);
+
+        bool   has_characters(uint16_t check_sum, string str );
+
+        ConfigCache config_cache;             // A cache in which ConfigValues are kept
+        vector<ConfigSource*> config_sources; // A list of all possible coniguration sources
+        bool   config_cache_loaded;           // Whether or not the cache is currently popluated
+};
+
+#endif
diff -r 000000000000 -r 31e91bb0ef3c libs/ConfigCache.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/ConfigCache.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,54 @@
+/*
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+#ifndef CONFIGCACHE_H
+#define CONFIGCACHE_H
+
+using namespace std;
+#include <vector>
+
+#include "ConfigValue.h"
+
+class ConfigCache : public std::vector<ConfigValue*> {
+    public:
+        ConfigCache(){}
+        
+        // If we find an existing value, replace it, otherwise, push it at the back of the list 
+        void replace_or_push_back(ConfigValue* new_value){
+       
+           bool value_exists = false; 
+            // For each already existing element 
+            for( int i=1; i<this->size(); i++){
+                // If this configvalue matches the checksum 
+                bool match = true;
+                for( unsigned int j = 0; j < new_value->check_sums.size(); j++ ){
+                    uint16_t checksum_node = new_value->check_sums[j];
+                    if(this->at(i)->check_sums[j] != checksum_node ){
+                        match = false;
+                        break; 
+                    }
+                } 
+                if( match == false ){ continue; }
+                value_exists = true;
+                // Replace with the provided value 
+                delete this->at(i);
+                this->at(i) = new_value;
+                break;
+            }
+
+            // Value does not already exists, add to the list
+            if( value_exists == false ){ 
+                this->push_back(new_value);
+            }
+
+        }
+
+};
+
+
+
+#endif
diff -r 000000000000 -r 31e91bb0ef3c libs/ConfigSource.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/ConfigSource.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,34 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+#ifndef CONFIGSOURCE_H
+#define CONFIGSOURCE_H
+
+using namespace std;
+#include <vector>
+#include <string>
+#include "ConfigValue.h"
+#include "ConfigCache.h"
+
+class ConfigValue;
+
+class ConfigSource {
+    public:
+        ConfigSource(){}
+
+        // Read each value, and append it as a ConfigValue to the config_cache we were passed
+        virtual void transfer_values_to_cache( ConfigCache* ){}
+        virtual bool is_named( uint16_t check_sum ){return false;}
+        virtual void write( string setting, string value ){}
+        virtual string read( vector<uint16_t> check_sums ){return "";}
+
+        uint16_t name_checksum;
+};
+
+
+
+#endif
diff -r 000000000000 -r 31e91bb0ef3c libs/ConfigSources/FileConfigSource.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/ConfigSources/FileConfigSource.cpp	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,177 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+#include "libs/Kernel.h"
+#include "ConfigValue.h"
+#include "FileConfigSource.h"
+#include "ConfigCache.h"
+using namespace std;
+#include <string>
+
+FileConfigSource::FileConfigSource(string config_file, uint16_t name_checksum){
+    this->name_checksum = name_checksum;
+    this->config_file = config_file;
+    this->config_file_found = false;
+}
+
+// Transfer all values found in the file to the passed cache
+void FileConfigSource::transfer_values_to_cache( ConfigCache* cache ){
+    // Default empty value
+    ConfigValue* result = new ConfigValue;
+    if( this->has_config_file() == false ){
+        return;
+    }
+    // Open the config file ( find it if we haven't already found it ) 
+    FILE *lp = fopen(this->get_config_file().c_str(), "r");
+    string buffer;
+    int c; 
+    // For each line 
+    do {
+        c = fgetc (lp);
+        if (c == '\n' || c == EOF){
+            // We have a new line
+            if( buffer[0] == '#' ){ buffer.clear(); continue; } // Ignore comments
+            if( buffer.length() < 3 ){ buffer.clear(); continue; } //Ignore empty lines
+            size_t begin_key = buffer.find_first_not_of(" ");
+            size_t begin_value = buffer.find_first_not_of(" ", buffer.find_first_of(" ", begin_key));
+            string key = buffer.substr(begin_key,  buffer.find_first_of(" ", begin_key) - begin_key).append(" ");
+            vector<uint16_t> check_sums = get_checksums(key);
+
+            result = new ConfigValue;
+            result->found = true;
+            result->check_sums = check_sums;
+            result->value = buffer.substr(begin_value, buffer.find_first_of("\r\n# ", begin_value+1)-begin_value);
+            
+            // Append the newly found value to the cache we were passed 
+            cache->replace_or_push_back(result);
+            
+            buffer.clear();
+        }else{
+            buffer += c;
+        }
+    } while (c != EOF);  
+    fclose(lp);
+
+}
+
+// Return true if the check_sums match
+bool FileConfigSource::is_named( uint16_t check_sum ){
+    return check_sum == this->name_checksum;
+}
+
+// Write a config setting to the file
+void FileConfigSource::write( string setting, string value ){
+/*
+    // Open the config file ( find it if we haven't already found it )
+    FILE *lp = fopen(this->get_config_file().c_str(), "r+");
+    string buffer;
+    int c;
+    // For each line
+    do {
+        c = fgetc (lp);
+        if (c == '\n' || c == EOF){
+            // We have a new line
+            if( buffer[0] == '#' ){ buffer.clear(); continue; } // Ignore comments
+            if( buffer.length() < 3 ){ buffer.clear(); continue; } //Ignore empty lines
+            size_t begin_key = buffer.find_first_not_of(" ");
+            size_t begin_value = buffer.find_first_not_of(" ", buffer.find_first_of(" ", begin_key));
+            // If this line matches the checksum
+            string candidate = buffer.substr(begin_key,  buffer.find_first_of(" ", begin_key) - begin_key);
+            if( candidate.compare(setting) != 0 ){ buffer.clear(); continue; }
+            int free_space = int(int(buffer.find_first_of("\r\n#", begin_value+1))-begin_value);
+            if( int(value.length()) >= free_space ){
+                //this->kernel->serial->printf("ERROR: Not enough room for value\r\n");
+                fclose(lp);
+                return;
+            }
+            // Update value
+            for( int i = value.length(); i < free_space; i++){ value += " "; }
+            fpos_t pos;
+            fgetpos( lp, &pos );
+            int start = pos - buffer.length() + begin_value - 1;
+            fseek(lp, start, SEEK_SET);
+            fputs(value.c_str(), lp);
+            fclose(lp);
+            return;
+        }else{
+            buffer += c;
+        }
+    } while (c != EOF);
+    fclose(lp);
+    //this->kernel->serial->printf("ERROR: configuration key not found\r\n");
+    */
+}
+
+// Return the value for a specific checksum
+string FileConfigSource::read( vector<uint16_t> check_sums ){
+
+    string value = "";
+
+    if( this->has_config_file() == false ){return value;}
+    // Open the config file ( find it if we haven't already found it ) 
+    FILE *lp = fopen(this->get_config_file().c_str(), "r");
+    string buffer;
+    int c; 
+    // For each line 
+    do {
+        c = fgetc (lp);
+        if (c == '\n' || c == EOF){
+            // We have a new line
+            if( buffer[0] == '#' ){ buffer.clear(); continue; } // Ignore comments
+            if( buffer.length() < 3 ){ buffer.clear(); continue; } //Ignore empty lines
+            size_t begin_key = buffer.find_first_not_of(" ");
+            size_t begin_value = buffer.find_first_not_of(" ", buffer.find_first_of(" ", begin_key));
+            string key = buffer.substr(begin_key,  buffer.find_first_of(" ", begin_key) - begin_key).append(" ");
+            vector<uint16_t> line_checksums = get_checksums(key);
+
+            if(check_sums == line_checksums){
+                value = buffer.substr(begin_value, buffer.find_first_of("\r\n# ", begin_value+1)-begin_value);
+                break;
+            }
+            
+            buffer.clear();
+        }else{
+            buffer += c;
+        }
+    } while (c != EOF);  
+    fclose(lp);
+
+    return value;
+}
+
+// Return wether or not we have a readable config file
+bool FileConfigSource::has_config_file(){
+    if( this->config_file_found ){ return true; }
+    this->try_config_file(this->config_file);
+    if( this->config_file_found ){
+        return true;
+    }else{
+        return false;
+    }
+
+}
+
+// Tool function for get_config_file
+inline void FileConfigSource::try_config_file(string candidate){
+    if(file_exists(candidate)){ 
+        this->config_file_found = true; 
+    }
+}
+
+// Get the filename for the config file
+string FileConfigSource::get_config_file(){
+    if( this->config_file_found ){ return this->config_file; }
+    if( this->has_config_file() ){
+        return this->config_file;
+    }else{
+        printf("ERROR: no config file found\r\n");
+    }
+}
+
+
+
+
diff -r 000000000000 -r 31e91bb0ef3c libs/ConfigSources/FileConfigSource.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/ConfigSources/FileConfigSource.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,39 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+#ifndef FILECONFIGSOURCE_H
+#define FILECONFIGSOURCE_H
+
+#include "ConfigValue.h"
+#include "ConfigSource.h"
+#include "ConfigCache.h"
+
+using namespace std;
+#include <string>
+
+#define FILE_CONFIGSOURCE_CHECKSUM    5281      // "file"
+
+class FileConfigSource : public ConfigSource {
+    public:
+        FileConfigSource(string config_file = "/sd/config", uint16_t name_checksum = FILE_CONFIGSOURCE_CHECKSUM);
+        virtual void transfer_values_to_cache( ConfigCache* cache );
+        virtual bool is_named( uint16_t check_sum );
+        virtual void write( string setting, string value );
+        virtual string read( vector<uint16_t> check_sums );
+        bool has_config_file();
+        void try_config_file(string candidate);
+        string get_config_file();
+
+        string config_file;         // Path to the config file
+        bool   config_file_found;   // Wether or not the config file's location is known
+
+
+};
+
+
+
+#endif
diff -r 000000000000 -r 31e91bb0ef3c libs/ConfigValue.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/ConfigValue.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,115 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+#ifndef CONFIGVALUE_H
+#define CONFIGVALUE_H
+
+#include "libs/Kernel.h"
+#include "libs/utils.h"
+#include "libs/Pin.h"
+
+
+#define error(...) (fprintf(stderr, __VA_ARGS__), exit(1))
+
+using namespace std;
+#include <vector>
+#include <string>
+#include <stdio.h>
+
+
+class ConfigValue{
+    public:
+        ConfigValue(){
+            this->found = false;
+            this->default_set = false; 
+        };
+
+        ConfigValue* required(){
+            if( this->found == true ){
+                return this;
+            }else{
+                error("could not find config setting with checksum %u, please see http://smoothieware.org/configuring-smoothie\r\n", this->check_sum );
+                return NULL;
+            }
+        }
+
+        double as_number(){
+            if( this->found == false && this->default_set == true ){
+                return this->default_double;
+            }else{
+                double result = atof(remove_non_number(this->value).c_str());
+                if( result == 0.0 && this->value.find_first_not_of("0.") != string::npos ){
+                    error("config setting with value '%s' is not a valid number, please see http://smoothieware.org/configuring-smoothie\r\n", this->value.c_str() );
+                }
+                return result; 
+            }
+           
+        }
+
+        std::string as_string(){
+            if( this->found == false && this->default_set == true ){
+                return this->default_string;
+            }else{
+                return this->value; 
+            }
+        }
+
+        bool as_bool(){
+            if( this->found == false && this->default_set == true ){
+                return this->default_double;
+            }else{
+                if( this->value.find_first_of("t1") != string::npos ){
+                    return true;
+                }else{
+                    return false;
+                } 
+            }
+        }
+
+        Pin* as_pin(){
+            Pin* pin = new Pin();
+            pin->from_string(this->as_string());
+            return pin;
+        }
+
+        ConfigValue* by_default(double val){
+            this->default_set = true;
+            this->default_double = val;
+            return this; 
+        }
+
+        ConfigValue* by_default(std::string val){
+            this->default_set = true;
+            this->default_string = val;
+            return this;
+        }
+
+        bool has_characters( string mask ){
+            if( this->value.find_first_of(mask) != string::npos ){ return true; }else{ return false; } 
+        }
+
+        bool is_inverted(){
+            return this->has_characters(string("!"));
+        }
+
+        string value;
+        vector<uint16_t> check_sums;
+        uint16_t check_sum; 
+        bool found;
+        bool default_set;
+        double default_double; 
+        string default_string;
+};
+
+
+
+
+
+
+
+
+#endif
diff -r 000000000000 -r 31e91bb0ef3c libs/Digipot.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/Digipot.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,47 @@
+#ifndef DIGIPOT_H
+#define DIGIPOT_H
+
+#include "libs/Kernel.h"
+#include "I2C.h" // mbed.h lib
+#include "libs/utils.h"
+#include <string>
+#include <math.h>
+
+class Digipot{
+    public:
+        Digipot(){ }
+      
+        char current_to_wiper( double current ){
+            return char(ceil(double((113.33*current)))); 
+        }
+
+        void i2c_send( char first, char second, char third ){
+            this->i2c->start();
+            this->i2c->write(first);
+            this->i2c->write(second);
+            this->i2c->write(third);
+            this->i2c->stop(); 
+        }
+
+        void set_current( int channel, double current ){ 
+
+            current = min( max( current, 0.0L ), 2.0L );
+
+            // I2C com 
+            this->i2c = new mbed::I2C(p9, p10); 
+           
+            // Initial setup 
+            this->i2c_send( 0x58, 0x40, 0xff );   
+            this->i2c_send( 0x58, 0xA0, 0xff );   
+
+            // Set actual wiper value
+            char adresses[4] = { 0x00, 0x10, 0x60, 0x70 };  
+            this->i2c_send( 0x58, adresses[channel], this->current_to_wiper(current) );   
+
+        } 
+
+        mbed::I2C* i2c;
+};
+
+
+#endif
diff -r 000000000000 -r 31e91bb0ef3c libs/FPointer.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/FPointer.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,162 @@
+/*
+Copyright (c) 2011 Andy Kirkham
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#ifndef AJK_FPOINTER_H
+#define AJK_FPOINTER_H
+#ifndef NULL
+#define NULL 0
+#endif
+namespace AjK {
+
+class FPointerDummy;
+
+/** FPointer - Adds callbacks that take and return a 32bit uint32_t data type.
+*
+* The Mbed library supplies a callback using the FunctionPointer object as
+* defined in FunctionPointer.h However, this callback system does not allow
+* the caller to pass a value to the callback. Likewise, the callback itself
+* cannot return a value.
+*
+* FPointer operates in the same way but allows the callback function to be
+* passed one arg, a uint32_t value. Additionally, the callback can return
+* a single uint32_t value. The reason for using uint32_t is that the Mbed
+* and the microcontroller (LPC1768) have a natural data size of 32bits and
+* this means we can use the uint32_t as a pointer. See example1.h for more
+* information. This example passes an "int" by passing a pointer to that
+* int as a 32bit value. Using this technique you can pass any value you like.
+* All you have to do is pass a pointer to your value cast to (uint32_t). Your
+* callback can the deference it to get the original value.
+*
+* example2.h shows how to do the same thing but demostrates how to specify
+* the callback into a class object/method.
+*
+* Finally, example3.h shows how to pass multiple values. In this example we
+* define a data structure and in the callback we pass a pointer to that
+* data structure thus allowing the callback to again get the values.
+*
+* Note, when passing pointers to variables to the callback, if the callback
+* function/method changes that variable's value then it will also change the
+* value the caller sees. If C pointers are new to you, you are strongly
+* advised to read up on the subject. It's pointers that often get beginners
+* into trouble when mis-used.
+*
+* @see example1.h
+* @see example2.h
+* @see example3.h
+* @see http://mbed.org/handbook/C-Data-Types
+* @see http://mbed.org/projects/libraries/svn/mbed/trunk/FunctionPointer.h
+*/
+class FPointer {
+
+protected:
+
+    //! C callback function pointer.
+    uint32_t (*c_callback)(uint32_t);
+    
+    //! C++ callback object/method pointer (the object part).
+    FPointerDummy *obj_callback;
+    
+    //! C++ callback object/method pointer (the method part).
+    uint32_t (FPointerDummy::*method_callback)(uint32_t);
+
+public:
+    
+    /** Constructor
+*/
+    FPointer() {
+        c_callback = NULL;
+        obj_callback = NULL;
+        method_callback = NULL;
+    }
+    
+    /** attach - Overloaded attachment function.
+*
+* Attach a C type function pointer as the callback.
+*
+* Note, the callback function prototype must be:-
+* @code
+* uint32_t myCallbackFunction(uint32_t);
+* @endcode
+* @param A C function pointer to call.
+*/
+    void attach(uint32_t (*function)(uint32_t) = 0) { c_callback = function; }
+    
+    /** attach - Overloaded attachment function.
+*
+* Attach a C++ type object/method pointer as the callback.
+*
+* Note, the callback method prototype must be:-
+* @code
+* public:
+* uint32_t myCallbackFunction(uint32_t);
+* @endcode
+* @param A C++ object pointer.
+* @param A C++ method within the object to call.
+*/
+    template<class T>
+    void attach(T* item, uint32_t (T::*method)(uint32_t)) {
+        obj_callback = (FPointerDummy *)item;
+        method_callback = (uint32_t (FPointerDummy::*)(uint32_t))method;
+    }
+
+    /** call - Overloaded callback initiator.
+*
+* call the callback function.
+*
+* @param uint32_t The value to pass to the callback.
+* @return uint32_t The value the callback returns.
+*/
+    uint32_t call(uint32_t arg) {
+        if (c_callback != NULL) {
+            return (*c_callback)(arg);
+        }
+        else {
+            if (obj_callback != NULL && method_callback != NULL) {
+                return (obj_callback->*method_callback)(arg);
+            }
+        }
+        return (uint32_t)NULL;
+    }
+    
+    /** call - Overloaded callback initiator.
+*
+* Call the callback function without passing an argument.
+* The callback itself is passed NULL. Note, the callback
+* prototype should still be <b>uint32_t callback(uint32_t)</b>.
+*
+* @return uint32_t The value the callback returns.
+*/
+    uint32_t call(void) {
+        if (c_callback != NULL) {
+            return (*c_callback)((uint32_t)NULL);
+        }
+        else {
+            if (obj_callback != NULL && method_callback != NULL) {
+                return (obj_callback->*method_callback)((uint32_t)NULL);
+            }
+        }
+        return (uint32_t)NULL;
+    }
+};
+
+}; // namespace AjK ends
+
+using namespace AjK;
+
+#endif
diff -r 000000000000 -r 31e91bb0ef3c libs/Hook.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/Hook.cpp	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,6 @@
+extern "C"{
+    #include <stdint.h>
+}
+#include "Hook.h"
+
+Hook::Hook(){}
diff -r 000000000000 -r 31e91bb0ef3c libs/Hook.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/Hook.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,12 @@
+#ifndef HOOK_H
+#define HOOK_H
+#include "libs/FPointer.h"
+
+class Hook : public FPointer {
+    public:
+        Hook();
+        double           frequency;
+        double           counter;
+};
+
+#endif
diff -r 000000000000 -r 31e91bb0ef3c libs/Kernel.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/Kernel.cpp	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,97 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+using namespace std;
+#include <vector>
+#include "libs/Kernel.h"
+#include "libs/Module.h"
+#include "libs/Config.h"
+#include "libs/nuts_bolts.h"
+#include "libs/SlowTicker.h"
+#include "libs/Adc.h"
+#include "libs/Digipot.h"
+#include "libs/Pauser.h"
+
+#include "modules/communication/SerialConsole.h"
+#include "modules/communication/GcodeDispatch.h"
+#include "modules/robot/Planner.h"
+#include "modules/robot/Robot.h"
+#include "modules/robot/Stepper.h"
+#include "modules/robot/Player.h"
+
+
+// List of callback functions, ordered as their corresponding events
+const ModuleCallback kernel_callback_functions[NUMBER_OF_DEFINED_EVENTS] = { 
+        &Module::on_main_loop, 
+        &Module::on_console_line_received,
+        &Module::on_gcode_received, 
+        &Module::on_stepper_wake_up,
+        &Module::on_gcode_execute,
+        &Module::on_speed_change,
+        &Module::on_block_begin,
+        &Module::on_block_end,
+        &Module::on_config_reload,
+        &Module::on_play,
+        &Module::on_pause,
+        &Module::on_idle
+};
+
+#define baud_rate_setting_checksum 10922
+#define uart0_checksum             16877
+
+// The kernel is the central point in Smoothie : it stores modules, and handles event calls
+Kernel::Kernel(){
+
+    // Config first, because we need the baud_rate setting before we start serial 
+    this->config         = new Config();
+
+    // Serial second, because the other modules might want to say something
+    this->serial         = new SerialConsole(USBTX, USBRX, this->config->value(uart0_checksum,baud_rate_setting_checksum)->by_default(9600)->as_number());
+
+    this->add_module( this->config );
+    this->add_module( this->serial );
+  
+    // HAL stuff 
+    this->slow_ticker          = new SlowTicker();
+    this->step_ticker          = new StepTicker();
+    this->adc                  = new Adc();
+    this->digipot              = new Digipot();
+
+    // LPC17xx-specific 
+    NVIC_SetPriority(TIMER0_IRQn, 1); 
+    NVIC_SetPriority(TIMER2_IRQn, 2); 
+
+    // Core modules 
+    this->add_module( this->gcode_dispatch = new GcodeDispatch() );
+    this->add_module( this->robot          = new Robot()         );
+    this->add_module( this->stepper        = new Stepper()       );
+    this->add_module( this->planner        = new Planner()       );
+    this->add_module( this->player         = new Player()        );
+    this->add_module( this->pauser         = new Pauser()        );
+}
+
+void Kernel::add_module(Module* module){
+    module->kernel = this;
+    module->on_module_loaded();
+    module->register_for_event(ON_CONFIG_RELOAD);
+}
+
+void Kernel::register_for_event(unsigned int id_event, Module* module){
+    this->hooks[id_event].push_back(module);
+}
+
+void Kernel::call_event(unsigned int id_event){
+    for(unsigned int i=0; i < this->hooks[id_event].size(); i++){
+        (this->hooks[id_event][i]->*kernel_callback_functions[id_event])(this);
+    }
+}
+
+void Kernel::call_event(unsigned int id_event, void * argument){
+    for(unsigned int i=0; i < this->hooks[id_event].size(); i++){
+        (this->hooks[id_event][i]->*kernel_callback_functions[id_event])(argument);
+    }
+}
diff -r 000000000000 -r 31e91bb0ef3c libs/Kernel.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/Kernel.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,77 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+#ifndef KERNEL_H
+#define KERNEL_H
+#include "libs/Module.h"
+#include "libs/Config.h"
+#include "libs/SlowTicker.h"
+#include "libs/StepTicker.h"
+#include "libs/Adc.h"
+#include "libs/Digipot.h"
+#include "libs/Pauser.h"
+#include "modules/communication/SerialConsole.h"
+#include "modules/communication/GcodeDispatch.h"
+#include "modules/robot/Planner.h"
+#include "modules/robot/Robot.h"
+#include "modules/robot/Stepper.h"
+
+// See : http://smoothieware.org/listofevents
+#define NUMBER_OF_DEFINED_EVENTS   12
+#define ON_MAIN_LOOP               0
+#define ON_CONSOLE_LINE_RECEIVED   1
+#define ON_GCODE_RECEIVED          2
+#define ON_STEPPER_WAKE_UP         3    //TODO : Remove the need for this event, then this event itself eg: have planner call stepper directly
+#define ON_GCODE_EXECUTE           4
+#define ON_SPEED_CHANGE            5
+#define ON_BLOCK_BEGIN             6
+#define ON_BLOCK_END               7
+#define ON_CONFIG_RELOAD           8
+#define ON_PLAY                    9
+#define ON_PAUSE                   10
+#define ON_IDLE                    11
+
+
+using namespace std;
+#include <vector>
+
+typedef void (Module::*ModuleCallback)(void * argument);
+
+//Module manager
+class Module;
+class Player;
+class SlowTicker;
+class Kernel {
+    public:
+        Kernel();
+        void add_module(Module* module);
+        void register_for_event(unsigned int id_event, Module* module);
+        void call_event(unsigned int id_event);
+        void call_event(unsigned int id_event, void * argument);
+
+        // These modules are aviable to all other modules
+        SerialConsole*    serial;
+        GcodeDispatch*    gcode_dispatch;
+        Robot*            robot;
+        Stepper*          stepper;
+        Planner*          planner;
+        Config*           config;
+        Player*           player;
+        Pauser*           pauser;
+
+        int debug;
+        SlowTicker*       slow_ticker;
+        StepTicker*       step_ticker;
+        Adc*              adc;
+        Digipot*          digipot;
+
+    private:
+        vector<Module*> hooks[NUMBER_OF_DEFINED_EVENTS]; // When a module asks to be called for a specific event ( a hook ), this is where that request is remembered
+
+};
+
+#endif
diff -r 000000000000 -r 31e91bb0ef3c libs/Module.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/Module.cpp	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,31 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+#include "libs/Module.h"
+#include "libs/Kernel.h"
+
+Module::Module(){ }
+
+void Module::on_module_loaded(){
+}
+
+void Module::register_for_event(int event_id){
+    this->kernel->register_for_event(event_id, this);
+}
+
+void Module::on_main_loop(             void * argument){}
+void Module::on_console_line_received( void * argument){}
+void Module::on_gcode_received(        void * argument){}
+void Module::on_stepper_wake_up(       void * argument){}
+void Module::on_gcode_execute(         void * argument){}
+void Module::on_speed_change(          void * argument){}
+void Module::on_block_begin(           void * argument){}
+void Module::on_block_end(             void * argument){}
+void Module::on_config_reload(         void * argument){}
+void Module::on_play(                  void * argument){}
+void Module::on_pause(                 void * argument){}
+void Module::on_idle(                  void * argument){}
diff -r 000000000000 -r 31e91bb0ef3c libs/Module.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/Module.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,37 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+#ifndef MODULE_H
+#define MODULE_H
+
+#include <string>
+using std::string;
+
+// Module base class
+// All modules must extend this class, see http://smoothieware.org/moduleexample 
+class Kernel;
+class Module {
+    public:
+        Module();
+        virtual void on_module_loaded();
+        virtual void register_for_event(int event_id);
+        virtual void on_main_loop(void * argument);
+        virtual void on_console_line_received(  void * argument);
+        virtual void on_gcode_received(         void * argument);
+        virtual void on_gcode_execute(          void * argument);
+        virtual void on_stepper_wake_up(        void * argument);
+        virtual void on_speed_change(           void * argument);
+        virtual void on_block_begin(            void * argument);
+        virtual void on_block_end(              void * argument);
+        virtual void on_config_reload(          void * argument);
+        virtual void on_play(                   void * argument);
+        virtual void on_pause(                  void * argument);
+        virtual void on_idle(                   void * argument);
+        Kernel * kernel;
+};
+
+#endif
diff -r 000000000000 -r 31e91bb0ef3c libs/Pauser.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/Pauser.cpp	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,26 @@
+#include "libs/Kernel.h"
+#include "Pauser.h"
+#include "libs/nuts_bolts.h"
+#include "libs/utils.h"
+#include <string>
+using namespace std;
+
+Pauser::Pauser(){}
+
+void Pauser::on_module_loaded(){
+    this->counter = 0;
+}
+
+void Pauser::take(){
+    this->counter++;
+    if( this->counter == 1 ){
+        this->kernel->call_event(ON_PAUSE, &this->counter);
+    }
+}
+
+void Pauser::release(){
+    this->counter--;
+    if( this->counter == 0 ){
+        this->kernel->call_event(ON_PLAY, &this->counter);
+    }
+}
diff -r 000000000000 -r 31e91bb0ef3c libs/Pauser.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/Pauser.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,18 @@
+#ifndef PAUSER_H
+#define PAUSER_H
+
+#include "libs/Kernel.h"
+#include "libs/nuts_bolts.h"
+#include "libs/utils.h"
+
+class Pauser : public Module {
+    public:
+        Pauser();
+        virtual void on_module_loaded();
+        void take();
+        void release();
+
+        unsigned short counter;
+};
+
+#endif
diff -r 000000000000 -r 31e91bb0ef3c libs/Pin.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/Pin.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,64 @@
+#ifndef PIN_H
+#define PIN_H
+
+#include <stdlib.h>
+#include "mbed.h" // smoothed mbed.h lib
+#include "libs/Kernel.h"
+#include "libs/utils.h"
+#include <string>
+
+class Pin{
+    public:
+        Pin(){ }
+
+        Pin* from_string(std::string value){
+            LPC_GPIO_TypeDef* gpios[5] ={LPC_GPIO0,LPC_GPIO1,LPC_GPIO2,LPC_GPIO3,LPC_GPIO4};
+            this->port_number =  atoi(value.substr(0,1).c_str());  
+            this->port = gpios[this->port_number]; 
+            this->inverting = ( value.find_first_of("!")!=string::npos ? true : false );
+            this->pin  = atoi( value.substr(2, value.size()-2-(this->inverting?1:0)).c_str() );
+            return this;
+        }
+
+        inline Pin*  as_output(){
+            this->port->FIODIR |= 1<<this->pin;
+            return this;
+        }  
+
+        inline Pin*  as_input(){
+            this->port->FIODIR &= ~(1<<this->pin);
+            return this;
+        }  
+
+        inline Pin* as_open_drain(){
+            if( this->port_number == 0 ){ LPC_PINCON->PINMODE_OD0 |= (1<<this->pin); }
+            if( this->port_number == 1 ){ LPC_PINCON->PINMODE_OD1 |= (1<<this->pin); }
+            if( this->port_number == 2 ){ LPC_PINCON->PINMODE_OD2 |= (1<<this->pin); }
+            if( this->port_number == 3 ){ LPC_PINCON->PINMODE_OD3 |= (1<<this->pin); }
+            if( this->port_number == 4 ){ LPC_PINCON->PINMODE_OD4 |= (1<<this->pin); }
+            return this;
+        }
+
+        inline bool get(){
+            return this->inverting ^ (( this->port->FIOPIN >> this->pin ) & 1);
+        }
+
+        inline void set(bool value){
+            value = this->inverting ^ value;
+            if( value ){
+                this->port->FIOSET = 1 << this->pin;
+            }else{
+                this->port->FIOCLR = 1 << this->pin;
+            }        
+        }
+
+        bool inverting; 
+        LPC_GPIO_TypeDef* port;
+        char port_number;
+        char pin; 
+};
+
+
+
+
+#endif
diff -r 000000000000 -r 31e91bb0ef3c libs/RingBuffer.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/RingBuffer.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,103 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+      
+      With chucks taken from http://en.wikipedia.org/wiki/Circular_buffer, see licence there also
+*/
+
+#ifndef RINGBUFFER_H
+#define RINGBUFFER_H
+
+
+template<class kind, int length> class RingBuffer {
+    public:
+        RingBuffer();
+        int          size();
+        int          capacity();
+        int          next_block_index(int index);
+        int          prev_block_index(int index);
+        void         push_back(kind object);
+        void         pop_front(kind &object);
+        void         get( int index, kind &object);
+        kind*        get_ref( int index);
+        void         delete_first();
+
+        kind         buffer[length];
+        int          head;
+        int          tail;
+};
+
+
+template<class kind, int length> RingBuffer<kind, length>::RingBuffer(){
+    this->head = this->tail = 0;
+}
+
+template<class kind, int length>  int RingBuffer<kind, length>::capacity(){
+    return length-1;
+}
+
+template<class kind, int length>  int RingBuffer<kind, length>::size(){
+return((this->head>this->tail)?length:0)+this->tail-head;
+}
+
+template<class kind, int length> int RingBuffer<kind, length>::next_block_index(int index){
+    index++;
+    if (index == length) { index = 0; }
+    return(index);
+}
+
+template<class kind, int length> int RingBuffer<kind, length>::prev_block_index(int index){
+    if (index == 0) { index = length; }
+    index--;
+    return(index);
+}
+
+template<class kind, int length> void RingBuffer<kind, length>::push_back(kind object){
+    this->buffer[this->tail] = object;
+    this->tail = (tail+1)&(length-1);
+}
+
+template<class kind, int length> void RingBuffer<kind, length>::get(int index, kind &object){
+    int j= 0;
+    int k= this->head;
+    while (k != this->tail){
+        if (j == index) break;
+        j++;
+        k= (k + 1) & (length - 1);
+    }
+    if (k == this->tail){
+        //return NULL; 
+    }
+    object = this->buffer[k];
+}
+
+
+template<class kind, int length> kind* RingBuffer<kind, length>::get_ref(int index){
+    int j= 0;
+    int k= this->head;
+    while (k != this->tail){
+        if (j == index) break;
+        j++;
+        k= (k + 1) & (length - 1);
+    }
+    if (k == this->tail){
+        return NULL;
+    }
+    return &(this->buffer[k]);
+}
+
+template<class kind, int length> void RingBuffer<kind, length>::pop_front(kind &object){
+    object = this->buffer[this->head]; 
+    this->head = (this->head+1)&(length-1);
+}
+
+template<class kind, int length> void RingBuffer<kind, length>::delete_first(){
+    //kind dummy;
+    //this->pop_front(dummy);
+    this->head = (this->head+1)&(length-1);
+}
+
+
+#endif
diff -r 000000000000 -r 31e91bb0ef3c libs/RingBuffer.o
Binary file libs/RingBuffer.o has changed
diff -r 000000000000 -r 31e91bb0ef3c libs/SerialMessage.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/SerialMessage.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,8 @@
+#ifndef SERIALMESSAGE_H
+#define SERIALMESSAGE_H
+#include "libs/StreamOutput.h"
+struct SerialMessage {
+        StreamOutput* stream;
+        std::string message;
+};
+#endif
diff -r 000000000000 -r 31e91bb0ef3c libs/SlowTicker.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/SlowTicker.cpp	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,53 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+using namespace std;
+#include <vector>
+#include "libs/nuts_bolts.h"
+#include "libs/Module.h"
+#include "libs/Kernel.h"
+#include "SlowTicker.h"
+#include "libs/Hook.h"
+#include "system_LPC17xx.h" // mbed.h lib
+
+
+SlowTicker* global_slow_ticker;
+
+SlowTicker::SlowTicker(){
+    this->max_frequency = 1;
+    global_slow_ticker = this;
+    LPC_SC->PCONP |= (1 << 22);     // Power Ticker ON
+    LPC_TIM2->MR0 = 10000;        // Initial dummy value for Match Register
+    LPC_TIM2->MCR = 3;              // Match on MR0, reset on MR0
+    LPC_TIM2->TCR = 1;              // Enable interrupt
+    NVIC_EnableIRQ(TIMER2_IRQn);    // Enable interrupt handler
+}
+
+void SlowTicker::set_frequency( int frequency ){
+    LPC_TIM2->MR0 = (SystemCoreClock/4)/frequency;  // SystemCoreClock/4 = Timer increments in a second
+    LPC_TIM2->TCR = 3;  // Reset
+    LPC_TIM2->TCR = 1;  // Reset
+}
+
+void SlowTicker::tick(){
+    for (int i=0; i<this->hooks.size(); i++){ 
+        Hook* hook = this->hooks.at(i);
+        hook->counter += ( hook->frequency / this->max_frequency );
+        if( hook->counter > 0 ){
+            hook->counter-=1;
+            hook->call();
+        } 
+    }
+}
+
+extern "C" void TIMER2_IRQHandler (void){
+    if((LPC_TIM2->IR >> 0) & 1){  // If interrupt register set for MR0
+        LPC_TIM2->IR |= 1 << 0;   // Reset it 
+        global_slow_ticker->tick(); 
+    }
+}
+
diff -r 000000000000 -r 31e91bb0ef3c libs/SlowTicker.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/SlowTicker.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,46 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+
+
+#ifndef SLOWTICKER_H
+#define SLOWTICKER_H
+
+using namespace std;
+#include <vector>
+#include "libs/nuts_bolts.h"
+#include "libs/Module.h"
+#include "libs/Kernel.h"
+#include "libs/Hook.h"
+
+class SlowTicker : public Module{
+    public:
+        SlowTicker();
+        void set_frequency( int frequency );
+        void tick();
+        // For some reason this can't go in the .cpp, see :  http://mbed.org/forum/mbed/topic/2774/?page=1#comment-14221
+        template<typename T> void attach( double frequency, T *optr, uint32_t ( T::*fptr )( uint32_t ) ){
+            Hook* hook = new Hook(); 
+            hook->frequency = frequency;
+            hook->attach(optr, fptr);
+            hook->counter = -2;
+            if( frequency > this->max_frequency ){ 
+                this->max_frequency = frequency; 
+            } 
+            this->set_frequency(this->max_frequency); 
+            this->hooks.push_back(hook);
+        }
+
+        vector<Hook*> hooks; 
+        double max_frequency;
+};
+
+
+
+
+
+#endif
diff -r 000000000000 -r 31e91bb0ef3c libs/StepTicker.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/StepTicker.cpp	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,65 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+
+
+using namespace std;
+#include <vector>
+#include "libs/nuts_bolts.h"
+#include "libs/Module.h"
+#include "libs/Kernel.h"
+#include "StepTicker.h"
+#include "system_LPC17xx.h" // mbed.h lib
+
+
+StepTicker* global_step_ticker;
+
+StepTicker::StepTicker(){
+    global_step_ticker = this;
+    LPC_TIM0->MR0 = 1000000;        // Initial dummy value for Match Register
+    LPC_TIM0->MCR = 11;              // Match on MR0, reset on MR0, match on MR1
+    LPC_TIM0->TCR = 1;              // Enable interrupt
+    NVIC_EnableIRQ(TIMER0_IRQn);    // Enable interrupt handler
+}
+
+void StepTicker::set_frequency( double frequency ){
+    this->frequency = frequency;
+    LPC_TIM0->MR0 = int(floor((SystemCoreClock/4)/frequency));  // SystemCoreClock/4 = Timer increments in a second
+    if( LPC_TIM0->TC > LPC_TIM0->MR0 ){
+        LPC_TIM0->TCR = 3;  // Reset
+        LPC_TIM0->TCR = 1;  // Reset
+    }
+}
+
+void StepTicker::set_reset_delay( double seconds ){
+    LPC_TIM0->MR1 = int(floor(double(SystemCoreClock/4)*( seconds )));  // SystemCoreClock/4 = Timer increments in a second
+}
+
+void StepTicker::tick(){
+    for (int i=0; i<this->hooks.size(); i++){ 
+        this->hooks.at(i)->call();
+    }
+}
+
+void StepTicker::reset_tick(){
+    for (int i=0; i<this->reset_hooks.size(); i++){ 
+        this->reset_hooks.at(i)->call();
+    }
+}
+
+extern "C" void TIMER0_IRQHandler (void){
+    if((LPC_TIM0->IR >> 0) & 1){  // If interrupt register set for MR0
+        LPC_TIM0->IR |= 1 << 0;   // Reset it 
+        global_step_ticker->tick(); 
+    }
+    if((LPC_TIM0->IR >> 1) & 1){  // If interrupt register set for MR1
+        LPC_TIM0->IR |= 1 << 1;   // Reset it
+        global_step_ticker->reset_tick();
+    }
+}
+
+
diff -r 000000000000 -r 31e91bb0ef3c libs/StepTicker.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/StepTicker.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,58 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+
+
+#ifndef STEPTICKER_H
+#define STEPTICKER_H
+
+using namespace std;
+#include <vector>
+#include "libs/nuts_bolts.h"
+#include "libs/Module.h"
+#include "libs/Kernel.h"
+
+
+class StepTicker{
+    public:
+        StepTicker();
+        void set_frequency( double frequency );
+        void tick();
+        void set_reset_delay( double seconds );
+        void reset_tick();
+
+        // For some reason this can't go in the .cpp, see :  http://mbed.org/forum/mbed/topic/2774/?page=1#comment-14221
+        template<typename T> void attach( T *optr, uint32_t ( T::*fptr )( uint32_t ) ){
+            FPointer* hook = new FPointer(); 
+            hook->attach(optr, fptr);
+            this->hooks.push_back(hook);
+        }
+
+        template<typename T> void reset_attach( T *optr, uint32_t ( T::*fptr )( uint32_t ) ){
+            FPointer* reset_hook = new FPointer(); 
+            reset_hook->attach(optr, fptr);
+            this->reset_hooks.push_back(reset_hook);
+        }
+
+
+        vector<FPointer*> hooks; 
+        vector<FPointer*> reset_hooks; 
+        double frequency;
+
+};
+
+
+
+
+
+
+
+
+
+
+
+#endif
diff -r 000000000000 -r 31e91bb0ef3c libs/StreamOutput.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/StreamOutput.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,22 @@
+#ifndef STREAMOUTPUT_H
+#define STREAMOUTPUT_H
+
+class StreamOutput {
+    public:
+       StreamOutput(){}
+       virtual int printf(const char* format, ...){return 0;}
+
+
+
+
+};
+
+
+
+
+
+
+
+
+
+#endif
diff -r 000000000000 -r 31e91bb0ef3c libs/nuts_bolts.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/nuts_bolts.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,43 @@
+/*
+nuts_bolts.h - cartesian robot controller.
+Part of Grbl
+
+Copyright (c) 2009-2011 Simen Svale Skogsrud
+
+Grbl is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Grbl is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Grbl. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef nuts_bolts_h
+#define nuts_bolts_h
+
+#include <string>
+using std::string;
+
+#define X_AXIS 0
+#define Y_AXIS 1
+#define Z_AXIS 2
+
+#define ALPHA_STEPPER 0
+#define BETA_STEPPER 1
+#define GAMMA_STEPPER 2
+
+#define clear_vector(a) memset(a, 0, sizeof(a))
+#define clear_vector_double(a) memset(a, 0.0, sizeof(a))
+#define max(a,b) (((a) > (b)) ? (a) : (b))
+
+#define dd(...) LPC_GPIO2->FIODIR = 0xffff; LPC_GPIO2->FIOCLR = 0xffff; LPC_GPIO2->FIOSET = __VA_ARGS__ 
+
+
+#endif
+
diff -r 000000000000 -r 31e91bb0ef3c libs/utils.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/utils.cpp	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,95 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+#include "libs/Kernel.h"
+#include "libs/utils.h"
+#include "system_LPC17xx.h"
+using namespace std;
+#include <string>
+using std::string;
+#include <cstring>
+
+
+uint16_t get_checksum(string to_check){
+   // From: http://en.wikipedia.org/wiki/Fletcher%27s_checksum 
+   uint16_t sum1 = 0;
+   uint16_t sum2 = 0;
+   for( int index = 0; index < to_check.length(); ++index ){
+      sum1 = (sum1 + to_check[index]) % 255;
+      sum2 = (sum2 + sum1) % 255;
+   }
+   return (sum2 << 8) | sum1;
+}
+
+vector<uint16_t> get_checksums(string key){
+    key = key.append(" ");
+    vector<uint16_t> check_sums;
+    size_t begin_key = 0;
+    while( begin_key < key.size()-1 ){
+        size_t end_key =  key.find_first_of(" .", begin_key);
+        string key_node = key.substr(begin_key, end_key - begin_key);
+        check_sums.push_back(get_checksum(key_node));
+        begin_key = end_key + 1;
+    }
+    return check_sums;
+}
+
+// Convert to lowercase
+string lc(string str){
+    for (int i=0;i<strlen(str.c_str());i++)
+        if (str[i] >= 0x41 && str[i] <= 0x5A)
+        str[i] = str[i] + 0x20;
+    return str;
+}
+
+// Remove non-number characters
+string remove_non_number( string str ){
+    string number_mask = "0123456789-.";
+    size_t found=str.find_first_not_of(number_mask);
+    while (found!=string::npos){
+        //str[found]='*';
+        str.replace(found,1,""); 
+        found=str.find_first_not_of(number_mask);
+    }
+    return str;
+}
+
+// Get the first parameter, and remove it from the original string
+string shift_parameter( string &parameters ){
+    size_t beginning = parameters.find_first_of(" ");
+    if( beginning == string::npos ){ string temp = parameters; parameters = ""; return temp; } 
+    string temp = parameters.substr( 0, beginning );
+    parameters = parameters.substr(beginning+1, parameters.size());
+    return temp;
+}
+
+// Separate command from arguments
+string get_arguments( string possible_command ){
+    size_t beginning = possible_command.find_first_of(" ");
+    if( beginning == string::npos ){ return ""; } 
+    return possible_command.substr( beginning+1, possible_command.size() - beginning);
+}
+
+// Returns true if the file exists
+bool file_exists( string file_name ){
+    bool exists = false;
+    FILE *lp = fopen(file_name.c_str(), "r");
+    if(lp){ exists = true; }
+    fclose(lp);
+    return exists;
+}
+
+// Prepares and executes a watchdog reset
+void system_reset( void ){
+    LPC_WDT->WDCLKSEL = 0x1;                // Set CLK src to PCLK
+    uint32_t clk = SystemCoreClock / 16;    // WD has a fixed /4 prescaler, PCLK default is /4
+    LPC_WDT->WDTC = 1 * (float)clk;         // Reset in 1 second
+    LPC_WDT->WDMOD = 0x3;                   // Enabled and Reset
+    LPC_WDT->WDFEED = 0xAA;                 // Kick the dog!
+    LPC_WDT->WDFEED = 0x55;
+}
+
diff -r 000000000000 -r 31e91bb0ef3c libs/utils.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libs/utils.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,29 @@
+#ifndef utils_h
+#define utils_h
+
+#include <stdint.h>
+using namespace std;
+#include <string>
+#include <vector>
+using std::string;
+
+string lc(string str);
+
+string remove_non_number( string str );
+
+uint16_t get_checksum(string to_check);
+
+vector<uint16_t> get_checksums(string key);
+
+string shift_parameter( string &parameters );
+
+string get_arguments( string possible_command );
+
+bool file_exists( string file_name );
+
+void system_reset( void );
+
+
+
+
+#endif
diff -r 000000000000 -r 31e91bb0ef3c main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,54 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+#include "libs/Kernel.h"
+#include "modules/tools/laser/Laser.h"
+#include "modules/tools/spindle/Spindle.h"
+#include "modules/tools/extruder/Extruder.h"
+#include "modules/tools/temperaturecontrol/TemperatureControlPool.h"
+#include "modules/robot/Player.h"
+#include "modules/utils/simpleshell/SimpleShell.h"
+#include "modules/utils/configurator/Configurator.h"
+#include "modules/utils/currentcontrol/CurrentControl.h"
+#include "modules/utils/pausebutton/PauseButton.h"
+//#include "libs/ChaNFSSD/SDFileSystem.h"
+#include "libs/Config.h"
+#include "libs/nuts_bolts.h"
+#include "libs/utils.h"
+
+//#include "libs/USBCDCMSC/USBCDCMSC.h"
+LocalFileSystem local("local");
+//SDFileSystem sd(p5, p6, p7, p8, "sd");  // LPC17xx specific : comment if you are not using a SD&#65533;card ( for example with a mBed ).
+//LocalFileSystem local("local");       // LPC17xx specific :&#65533;comment if you are not running a mBed
+//USBCDCMSC cdcmsc(&sd);                  // LPC17xx specific :&#65533;Composite serial + msc USB device
+
+int main() {
+
+    Kernel* kernel = new Kernel();
+
+    kernel->serial->printf("Smoothie ( grbl port ) version 0.6.1_mbed \r\n");
+
+
+
+    //kernel->add_module( new Laser(p21) );
+    //kernel->add_module( new Extruder() );
+    kernel->add_module( new Spindle() );
+    kernel->add_module( new SimpleShell() );
+    kernel->add_module( new Configurator() );
+    kernel->add_module( new CurrentControl() );
+    kernel->add_module( new TemperatureControlPool() );
+    kernel->add_module( new PauseButton() );   
+
+    //kernel->add_module( &cdcmsc );
+   
+    kernel->serial->printf("start\r\n");
+
+    while(1){
+        kernel->call_event(ON_MAIN_LOOP);
+        kernel->call_event(ON_IDLE);
+    }
+}
diff -r 000000000000 -r 31e91bb0ef3c mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/10b9abbe79a6
\ No newline at end of file
diff -r 000000000000 -r 31e91bb0ef3c modules/communication/GcodeDispatch.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/communication/GcodeDispatch.cpp	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,115 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+#include <string>
+using std::string;
+#include "libs/Module.h"
+#include "libs/Kernel.h"
+#include "utils/Gcode.h"
+#include "libs/nuts_bolts.h"
+#include "GcodeDispatch.h"
+#include "modules/robot/Player.h" 
+#include "libs/SerialMessage.h"
+#include "libs/StreamOutput.h"
+
+GcodeDispatch::GcodeDispatch(){}
+
+// Called when the module has just been loaded
+void GcodeDispatch::on_module_loaded() {
+    this->register_for_event(ON_CONSOLE_LINE_RECEIVED);
+    currentline = -1;
+}
+
+// When a command is received, if it is a Gcode, dispatch it as an object via an event
+void GcodeDispatch::on_console_line_received(void * line){
+    SerialMessage new_message = *static_cast<SerialMessage*>(line);
+    string possible_command = new_message.message;    
+
+    char first_char = possible_command[0];
+    int ln = 0;
+    int cs = 0;
+    if( first_char == 'G' || first_char == 'M' || first_char == 'T' || first_char == 'N' ){ 
+
+        //Get linenumber
+        if( first_char == 'N' ){ 
+            Gcode full_line = Gcode();
+            full_line.command = possible_command;
+            full_line.stream = new_message.stream;
+            ln = (int) full_line.get_value('N');
+            int chksum = (int) full_line.get_value('*');
+
+            //Catch message if it is M110: Set Current Line Number
+            if( full_line.has_letter('M') ){
+                if( ((int) full_line.get_value('M')) == 110 ){
+                    currentline = ln;
+                    new_message.stream->printf("ok\r\n");
+                    return;
+                }
+            }
+
+            //Strip checksum value from possible_command
+            size_t chkpos = possible_command.find_first_of("*");
+            possible_command = possible_command.substr(0, chkpos); 
+            //Calculate checksum
+            if( chkpos != string::npos ){ 
+                for(int i = 0; possible_command[i] != '*' && possible_command[i] != NULL; i++)
+                    cs = cs ^ possible_command[i];
+                cs &= 0xff;  // Defensive programming...
+                cs -= chksum;
+            }
+            //Strip line number value from possible_command
+            size_t lnsize = possible_command.find_first_of(" ") + 1;
+            possible_command = possible_command.substr(lnsize); 
+
+        }else{
+            //Assume checks succeeded
+            cs = 0x00;
+            ln = currentline + 1;
+        }
+
+        //Remove comments
+        size_t comment = possible_command.find_first_of(";");
+        if( comment != string::npos ){ possible_command = possible_command.substr(0, comment); }
+
+        //If checksum passes then process message, else request resend
+        int nextline = currentline + 1;
+        if( cs == 0x00 && ln == nextline ){
+            if( first_char == 'N' ) {
+                currentline = nextline;
+            }
+
+            while(possible_command.size() > 0) {
+                size_t nextcmd = possible_command.find_first_of("GMT", possible_command.find_first_of("GMT")+1);
+                string single_command;
+                if(nextcmd == string::npos) {
+                    single_command = possible_command;
+                    possible_command = "";
+                }
+                else {
+                    single_command = possible_command.substr(0,nextcmd);
+                    possible_command = possible_command.substr(nextcmd);
+                }
+                //Prepare gcode for dispatch
+                Gcode gcode = Gcode();
+                gcode.command = single_command;
+                gcode.stream = new_message.stream;
+
+                //Dispatch message!
+                this->kernel->call_event(ON_GCODE_RECEIVED, &gcode );
+                new_message.stream->printf("ok\r\n");
+            }
+        }else{
+            //Request resend
+            new_message.stream->printf("rs N%d\r\n", nextline);
+        }
+
+    // Ignore comments and blank lines
+    }else if( first_char == ';' || first_char == '(' || first_char == ' ' || first_char == '\n' || first_char == '\r' ){
+        new_message.stream->printf("ok\r\n");
+    }
+}
+
diff -r 000000000000 -r 31e91bb0ef3c modules/communication/GcodeDispatch.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/communication/GcodeDispatch.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,29 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+#ifndef GCODE_DISPATCH_H
+#define GCODE_DISPATCH_H
+
+#include <string>
+using std::string;
+#include "libs/Module.h"
+#include "libs/Kernel.h"
+#include "utils/Gcode.h"
+
+#include "libs/StreamOutput.h"
+
+class GcodeDispatch : public Module {
+    public:
+        GcodeDispatch();
+        
+        virtual void on_module_loaded();
+        virtual void on_console_line_received(void* line);
+    private:
+        int currentline;
+};
+
+#endif
diff -r 000000000000 -r 31e91bb0ef3c modules/communication/SerialConsole.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/communication/SerialConsole.cpp	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,88 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+#include <string>
+#include <stdarg.h>
+using std::string;
+#include "libs/Module.h"
+#include "libs/Kernel.h"
+#include "libs/nuts_bolts.h"
+#include "SerialConsole.h"
+#include "libs/RingBuffer.h"
+#include "libs/SerialMessage.h"
+#include "libs/StreamOutput.h"
+
+// Serial reading module
+// Treats every received line as a command and passes it ( via event call ) to the command dispatcher. 
+// The command dispatcher will then ask other modules if they can do something with it
+SerialConsole::SerialConsole( PinName rx_pin, PinName tx_pin, int baud_rate ){
+    this->serial = new mbed::Serial( rx_pin, tx_pin );
+    this->serial->printf("T1\n");
+    this->serial->baud(baud_rate);
+}  
+
+// Called when the module has just been loaded
+void SerialConsole::on_module_loaded() {
+    // We want to be called every time a new char is received
+    this->serial->attach(this, &SerialConsole::on_serial_char_received, mbed::Serial::RxIrq);
+
+    // We only call the command dispatcher in the main loop, nowhere else
+    this->register_for_event(ON_MAIN_LOOP);
+}
+        
+// Called on Serial::RxIrq interrupt, meaning we have received a char
+void SerialConsole::on_serial_char_received(){
+    while(this->serial->readable()){
+        char received = this->serial->getc();
+        // convert CR to NL (for host OSs that don't send NL)
+        if( received == '\r' ){ received = '\n'; }
+        this->buffer.push_back(received); 
+    }
+}
+        
+// Actual event calling must happen in the main loop because if it happens in the interrupt we will loose data
+void SerialConsole::on_main_loop(void * argument){
+    if( this->has_char('\n') ){
+        int index = 0;
+        string received;
+        while(1){
+           char c;
+           this->buffer.pop_front(c);
+           if( c == '\n' ){
+                struct SerialMessage message; 
+                message.message = received;
+                message.stream = this;
+                this->kernel->call_event(ON_CONSOLE_LINE_RECEIVED, &message ); 
+                return;
+            }else{
+                received += c;
+            }
+        }
+    }
+}
+
+
+int SerialConsole::printf(const char* format, ...){
+    va_list args;
+    int result=0; 
+    va_start (args, format);
+    this->serial->printf( format, args);
+    va_end (args);
+    return result;
+}
+
+
+bool SerialConsole::has_char(char letter){
+    int index = this->buffer.head;
+    while( index != this->buffer.tail ){
+        if( this->buffer.buffer[index] == letter ){
+            return true;
+        }
+        index = this->buffer.next_block_index(index);
+    }
+    return false;
+}
diff -r 000000000000 -r 31e91bb0ef3c modules/communication/SerialConsole.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/communication/SerialConsole.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,39 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+#ifndef SERIALCONSOLE_H
+#define SERIALCONSOLE_H
+
+#include "libs/Module.h"
+#include "mbed.h"
+#include "libs/Kernel.h"
+#include <vector>
+#include <string>
+using std::string;
+#include "libs/RingBuffer.h"
+#include "libs/StreamOutput.h"
+
+
+#define baud_rate_setting_checksum 10922
+
+class SerialConsole : public Module, public StreamOutput {
+    public:
+        SerialConsole( PinName rx_pin, PinName tx_pin, int baud_rate );
+        
+        virtual void on_module_loaded();
+        void on_serial_char_received();
+        virtual void on_main_loop(void * argument);
+        bool has_char(char letter);
+        virtual int printf(const char* format, ...);
+        
+        //string receive_buffer;                 // Received chars are stored here until a newline character is received
+        //vector<std::string> received_lines;    // Received lines are stored here until they are requested
+        RingBuffer<char,256> buffer;             // Receive buffer
+        mbed::Serial* serial;
+};
+
+#endif
diff -r 000000000000 -r 31e91bb0ef3c modules/communication/utils/Gcode.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/communication/utils/Gcode.cpp	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,53 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+
+#include <string>
+using std::string;
+#include "Gcode.h"
+#include "libs/StreamOutput.h"
+
+#include <stdlib.h>
+
+
+Gcode::Gcode(){}
+
+// Whether or not a Gcode has a letter
+bool Gcode::has_letter( char letter ){
+    //return ( this->command->find( letter ) != string::npos );
+    for (size_t i=0; i < this->command.length(); i++){
+        if( this->command.at(i) == letter ){
+            return true;
+        }
+    }
+    return false;
+}
+
+// Retrieve the value for a given letter
+// We don't use the high-level methods of std::string because they call malloc and it's very bad to do that inside of interrupts
+double Gcode::get_value( char letter ){
+    //__disable_irq();
+    for (size_t i=0; i <= this->command.length()-1; i++){
+         if( letter == this->command.at(i) ){
+            size_t beginning = i+1;
+            char buffer[20];
+            for(size_t j=beginning; j <= this->command.length(); j++){
+                char c;
+                if( j == this->command.length() ){ c = ';'; }else{ c = this->command.at(j); }
+                if( c != '.' && c != '-' && ( c < '0' || c > '9' ) ){
+                    buffer[j-beginning] = '\0';
+                    //__enable_irq();
+                    return atof(buffer); 
+                }else{
+                    buffer[j-beginning] = c;
+                }
+            }
+         }
+    }
+    //__enable_irq();
+    return 0; 
+}
\ No newline at end of file
diff -r 000000000000 -r 31e91bb0ef3c modules/communication/utils/Gcode.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/communication/utils/Gcode.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,30 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+
+#ifndef GCODE_H
+#define GCODE_H
+#include <string>
+using std::string;
+#include "libs/StreamOutput.h"
+// Object to represent a Gcode comman
+#include <stdlib.h>
+
+class Gcode {
+    public:
+        Gcode();
+        bool has_letter( char letter );
+        double get_value ( char letter );
+
+        string command;
+        double millimeters_of_travel;
+        bool call_on_gcode_execute_event_immediatly;
+        bool on_gcode_execute_event_called;
+
+        StreamOutput* stream;
+};
+#endif
\ No newline at end of file
diff -r 000000000000 -r 31e91bb0ef3c modules/robot/Block.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/robot/Block.cpp	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,221 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+#include "libs/Module.h"
+#include "libs/Kernel.h"
+#include "libs/nuts_bolts.h"
+#include <math.h>
+#include <string>
+#include "Block.h"
+#include "Planner.h"
+#include "Player.h"
+using std::string;
+#include <vector>
+#include "../communication/utils/Gcode.h"
+
+Block::Block(){
+    clear_vector(this->steps);
+    this->times_taken = 0;   // A block can be "taken" by any number of modules, and the next block is not moved to until all the modules have "released" it. This value serves as a tracker.
+    this->is_ready = false;
+    this->initial_rate = -1;
+    this->final_rate = -1;
+}
+
+void Block::debug(Kernel* kernel){
+    kernel->serial->printf("%p: steps:%4d|%4d|%4d(max:%4d) nominal:r%10d/s%6.1f mm:%9.6f rdelta:%8d acc:%5d dec:%5d rates:%10d>%10d taken:%d ready:%d \r\n", this, this->steps[0], this->steps[1], this->steps[2], this->steps_event_count, this->nominal_rate, this->nominal_speed, this->millimeters, this->rate_delta, this->accelerate_until, this->decelerate_after, this->initial_rate, this->final_rate, this->times_taken, this->is_ready );
+}
+
+
+// Calculate a braking factor to reach baseline speed which is max_jerk/2, e.g. the
+// speed under which you cannot exceed max_jerk no matter what you do.
+double Block::compute_factor_for_safe_speed(){
+    return( this->planner->max_jerk / this->nominal_speed ); 
+}
+
+
+// Calculates trapezoid parameters so that the entry- and exit-speed is compensated by the provided factors.
+// The factors represent a factor of braking and must be in the range 0.0-1.0.
+//                                +--------+ <- nominal_rate
+//                               /          \
+// nominal_rate*entry_factor -> +            \
+//                              |             + <- nominal_rate*exit_factor
+//                              +-------------+
+//                                  time -->
+void Block::calculate_trapezoid( double entryfactor, double exitfactor ){
+
+    this->initial_rate = ceil(this->nominal_rate * entryfactor);   // (step/min) 
+    this->final_rate   = ceil(this->nominal_rate * exitfactor);    // (step/min)
+    double acceleration_per_minute = this->rate_delta * this->planner->kernel->stepper->acceleration_ticks_per_second * 60.0; 
+    int accelerate_steps = ceil( this->estimate_acceleration_distance( this->initial_rate, this->nominal_rate, acceleration_per_minute ) );
+    int decelerate_steps = ceil( this->estimate_acceleration_distance( this->nominal_rate, this->final_rate,  -acceleration_per_minute ) );
+
+    // Calculate the size of Plateau of Nominal Rate.
+    int plateau_steps = this->steps_event_count-accelerate_steps-decelerate_steps;
+
+   // Is the Plateau of Nominal Rate smaller than nothing? That means no cruising, and we will
+   // have to use intersection_distance() to calculate when to abort acceleration and start braking
+   // in order to reach the final_rate exactly at the end of this block.
+   if (plateau_steps < 0) {
+       accelerate_steps = ceil(this->intersection_distance(this->initial_rate, this->final_rate, acceleration_per_minute, this->steps_event_count));
+       accelerate_steps = max( accelerate_steps, 0 ); // Check limits due to numerical round-off
+       accelerate_steps = min( accelerate_steps, int(this->steps_event_count) );
+       plateau_steps = 0;
+   }
+   
+   this->accelerate_until = accelerate_steps;
+   this->decelerate_after = accelerate_steps+plateau_steps; 
+
+   // TODO: FIX THIS: DIRTY HACK so that we don't end too early for blocks with 0 as final_rate. Doing the math right would be better. Probably fixed in latest grbl
+   if( this->final_rate < 0.01 ){
+        this->decelerate_after += ( this->nominal_rate / 60 / this->planner->kernel->stepper->acceleration_ticks_per_second ) * 3;
+    }
+
+}
+
+// Calculates the distance (not time) it takes to accelerate from initial_rate to target_rate using the
+// given acceleration:
+double Block::estimate_acceleration_distance(double initialrate, double targetrate, double acceleration) {
+      return( (targetrate*targetrate-initialrate*initialrate)/(2L*acceleration));
+}
+
+// This function gives you the point at which you must start braking (at the rate of -acceleration) if
+// you started at speed initial_rate and accelerated until this point and want to end at the final_rate after
+// a total travel of distance. This can be used to compute the intersection point between acceleration and
+// deceleration in the cases where the trapezoid has no plateau (i.e. never reaches maximum speed)
+//
+/*                          + <- some maximum rate we don't care about
+                           /|\
+                          / | \
+                         /  |  + <- final_rate
+                        /   |  |
+       initial_rate -> +----+--+
+                            ^ ^
+                            | |
+        intersection_distance distance */
+double Block::intersection_distance(double initialrate, double finalrate, double acceleration, double distance) {
+   return((2*acceleration*distance-initialrate*initialrate+finalrate*finalrate)/(4*acceleration));
+}
+
+// Calculates the maximum allowable speed at this point when you must be able to reach target_velocity using the
+// acceleration within the allotted distance.
+inline double max_allowable_speed(double acceleration, double target_velocity, double distance) {
+  return(
+    sqrt(target_velocity*target_velocity-2L*acceleration*60*60*distance)  //Was acceleration*60*60*distance, in case this breaks, but here we prefer to use seconds instead of minutes
+  );
+}
+
+
+// Called by Planner::recalculate() when scanning the plan from last to first entry.
+void Block::reverse_pass(Block* next, Block* previous){
+
+    if (next) {
+        // If entry speed is already at the maximum entry speed, no need to recheck. Block is cruising.
+        // If not, block in state of acceleration or deceleration. Reset entry speed to maximum and
+        // check for maximum allowable speed reductions to ensure maximum possible planned speed.
+        if (this->entry_speed != this->max_entry_speed) {
+
+            // If nominal length true, max junction speed is guaranteed to be reached. Only compute
+            // for max allowable speed if block is decelerating and nominal length is false.
+            if ((!this->nominal_length_flag) && (this->max_entry_speed > next->entry_speed)) {
+                this->entry_speed = min( this->max_entry_speed, max_allowable_speed(-this->planner->acceleration,next->entry_speed,this->millimeters));
+            } else {
+                this->entry_speed = this->max_entry_speed;
+            }
+            this->recalculate_flag = true;
+
+        }
+    } // Skip last block. Already initialized and set for recalculation.
+
+}
+
+
+// Called by Planner::recalculate() when scanning the plan from first to last entry.
+void Block::forward_pass(Block* previous, Block* next){
+
+    if(!previous) { return; } // Begin planning after buffer_tail
+
+    // If the previous block is an acceleration block, but it is not long enough to complete the
+    // full speed change within the block, we need to adjust the entry speed accordingly. Entry
+    // speeds have already been reset, maximized, and reverse planned by reverse planner.
+    // If nominal length is true, max junction speed is guaranteed to be reached. No need to recheck.
+    if (!previous->nominal_length_flag) {
+        if (previous->entry_speed < this->entry_speed) {
+          double entry_speed = min( this->entry_speed,
+            max_allowable_speed(-this->planner->acceleration,previous->entry_speed,previous->millimeters) );
+
+          // Check for junction speed change
+          if (this->entry_speed != entry_speed) {
+            this->entry_speed = entry_speed;
+            this->recalculate_flag = true;
+          }
+        }
+    }
+      
+}
+
+
+// Gcodes are attached to their respective blocks so that on_gcode_execute can be called with it
+void Block::append_gcode(Gcode* gcode){
+   __disable_irq();
+   this->gcodes.push_back(*gcode);
+   __enable_irq();
+}
+
+// The attached gcodes are then poped and the on_gcode_execute event is called with them as a parameter
+void Block::pop_and_execute_gcode(Kernel* &kernel){
+    Block* block = const_cast<Block*>(this);
+    for(unsigned short index=0; index<block->gcodes.size(); index++){
+        kernel->call_event(ON_GCODE_EXECUTE, &(block->gcodes[index]));
+    }
+}
+
+// Signal the player that this block is ready to be injected into the system
+void Block::ready(){
+    this->is_ready = true;
+    this->player->new_block_added();
+}
+
+// Mark the block as taken by one more module
+void Block::take(){
+    this->times_taken++;
+}
+
+// Mark the block as no longer taken by one module, go to next block if this free's it
+void Block::release(){
+    this->times_taken--;
+    if( this->times_taken < 1 ){
+        this->player->kernel->call_event(ON_BLOCK_END, this);
+        this->pop_and_execute_gcode(this->player->kernel);
+        Player* player = this->player;
+
+        if( player->queue.size() > 0 ){ 
+            player->queue.delete_first();
+        } 
+
+        if( player->looking_for_new_block == false ){
+            if( player->queue.size() > 0 ){
+                Block* candidate =  player->queue.get_ref(0);
+                if( candidate->is_ready ){
+                    player->current_block = candidate;
+                    player->kernel->call_event(ON_BLOCK_BEGIN, player->current_block);
+                    if( player->current_block->times_taken < 1 ){
+                        player->current_block->release();
+                    }
+                }else{
+
+                    player->current_block = NULL;
+
+                } 
+            }else{
+                player->current_block = NULL;
+            }
+        }
+    }
+}
+
+
+
diff -r 000000000000 -r 31e91bb0ef3c modules/robot/Block.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/robot/Block.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,81 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+#ifndef BLOCK_H
+#define BLOCK_H
+#include "libs/Module.h"
+#include "libs/Kernel.h"
+using namespace std;
+#include <string>
+#include <vector>
+
+#include "../communication/utils/Gcode.h"
+#include "Planner.h"
+class Planner;
+class Player;
+
+double max_allowable_speed( double acceleration, double target_velocity, double distance);
+
+class Block {
+    public:
+        Block();
+        double compute_factor_for_safe_speed();
+        void calculate_trapezoid( double entry_factor, double exit_factor );
+        double estimate_acceleration_distance( double initial_rate, double target_rate, double acceleration );
+        double intersection_distance(double initial_rate, double final_rate, double acceleration, double distance); 
+        void reverse_pass(Block* previous, Block* next);
+        void forward_pass(Block* previous, Block* next);
+        void debug(Kernel* kernel);
+        void append_gcode(Gcode* gcode);
+        void pop_and_execute_gcode(Kernel* &kernel);
+        double get_duration_left(unsigned int already_taken_steps);
+        void take();
+        void release();
+        void ready();
+
+        vector<std::string> commands;
+        vector<double> travel_distances;
+        vector<Gcode> gcodes;
+        
+        unsigned int   steps[3];           // Number of steps for each axis for this block
+        unsigned int   steps_event_count;  // Steps for the longest axis
+        unsigned int   nominal_rate;       // Nominal rate in steps per minute
+        float          nominal_speed;      // Nominal speed in mm per minute
+        float          millimeters;        // Distance for this move
+        double         entry_speed;
+        unsigned int   rate_delta;         // Nomber of steps to add to the speed for each acceleration tick
+        int   initial_rate;       // Initial speed in steps per minute
+        int   final_rate;         // Final speed in steps per minute
+        unsigned int   accelerate_until;   // Stop accelerating after this number of steps
+        unsigned int   decelerate_after;   // Start decelerating after this number of steps
+        unsigned int   direction_bits;     // Direction for each axis in bit form, relative to the direction port's mask
+
+
+        uint8_t recalculate_flag; // Planner flag to recalculate trapezoids on entry junction
+        uint8_t nominal_length_flag; // Planner flag for nominal speed always reached
+
+        double max_entry_speed;
+        Planner* planner;
+        Player*  player;
+        
+        bool is_ready;
+
+        short times_taken;    // A block can be "taken" by any number of modules, and the next block is not moved to until all the modules have "released" it. This value serves as a tracker.
+
+};
+
+
+
+
+
+
+
+
+
+
+
+#endif
diff -r 000000000000 -r 31e91bb0ef3c modules/robot/Planner.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/robot/Planner.cpp	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,264 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl) with additions from Sungeun K. Jeon (https://github.com/chamnit/grbl)
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+using namespace std;
+#include <vector>
+#include "libs/nuts_bolts.h"
+#include "libs/RingBuffer.h"
+#include "../communication/utils/Gcode.h"
+#include "libs/Module.h"
+#include "libs/Kernel.h"
+#include "Block.h"
+#include "Planner.h"
+#include "Player.h" 
+
+
+Planner::Planner(){
+    clear_vector(this->position);
+    clear_vector_double(this->previous_unit_vec);
+    this->previous_nominal_speed = 0.0;
+    this->has_deleted_block = false;
+}
+
+void Planner::on_module_loaded(){
+    this->on_config_reload(this);
+}
+
+void Planner::on_config_reload(void* argument){
+    this->acceleration =       this->kernel->config->value(acceleration_checksum       )->by_default(100 )->as_number();
+    this->max_jerk =           this->kernel->config->value(max_jerk_checksum           )->by_default(100 )->as_number();
+    this->junction_deviation = this->kernel->config->value(junction_deviation_checksum )->by_default(0.05)->as_number(); 
+}
+
+
+// Append a block to the queue, compute it's speed factors
+void Planner::append_block( int target[], double feed_rate, double distance, double deltas[] ){
+   
+    // Stall here if the queue is ful
+    this->kernel->player->wait_for_queue(2);
+
+    Block* block = this->kernel->player->new_block();
+    block->planner = this;   
+
+    // Direction bits
+    block->direction_bits = 0; 
+    for( int stepper=ALPHA_STEPPER; stepper<=GAMMA_STEPPER; stepper++){ 
+        if( target[stepper] < position[stepper] ){ block->direction_bits |= (1<<stepper); } 
+    }
+    
+    // Number of steps for each stepper
+    for( int stepper=ALPHA_STEPPER; stepper<=GAMMA_STEPPER; stepper++){ block->steps[stepper] = labs(target[stepper] - this->position[stepper]); } 
+    
+    // Max number of steps, for all axes
+    block->steps_event_count = max( block->steps[ALPHA_STEPPER], max( block->steps[BETA_STEPPER], block->steps[GAMMA_STEPPER] ) );
+    //if( block->steps_event_count == 0 ){ this->computing = false; return; }
+
+    block->millimeters = distance;
+    double inverse_millimeters = 0; 
+    if( distance > 0 ){ inverse_millimeters = 1.0/distance; }
+
+    // Calculate speed in mm/minute for each axis. No divide by zero due to previous checks.
+    // NOTE: Minimum stepper speed is limited by MINIMUM_STEPS_PER_MINUTE in stepper.c
+    double inverse_minute = feed_rate * inverse_millimeters;
+    if( distance > 0 ){ 
+        block->nominal_speed = block->millimeters * inverse_minute;           // (mm/min) Always > 0
+        block->nominal_rate = ceil(block->steps_event_count * inverse_minute); // (step/min) Always > 0
+    }else{
+        block->nominal_speed = 0;
+        block->nominal_rate = 0;
+    }
+
+    //this->kernel->serial->printf("nom_speed: %f nom_rate: %u step_event_count: %u block->steps_z: %u \r\n", block->nominal_speed, block->nominal_rate, block->steps_event_count, block->steps[2]  );
+    
+    // Compute the acceleration rate for the trapezoid generator. Depending on the slope of the line
+    // average travel per step event changes. For a line along one axis the travel per step event
+    // is equal to the travel/step in the particular axis. For a 45 degree line the steppers of both
+    // axes might step for every step event. Travel per step event is then sqrt(travel_x^2+travel_y^2).
+    // To generate trapezoids with contant acceleration between blocks the rate_delta must be computed
+    // specifically for each line to compensate for this phenomenon:
+    // Convert universal acceleration for direction-dependent stepper rate change parameter
+    block->rate_delta = ceil( block->steps_event_count*inverse_millimeters * this->acceleration*60.0 / this->kernel->stepper->acceleration_ticks_per_second ); // (step/min/acceleration_tick)
+
+    // Compute path unit vector
+    double unit_vec[3];
+    unit_vec[X_AXIS] = deltas[X_AXIS]*inverse_millimeters;
+    unit_vec[Y_AXIS] = deltas[Y_AXIS]*inverse_millimeters;
+    unit_vec[Z_AXIS] = deltas[Z_AXIS]*inverse_millimeters;
+  
+    // Compute maximum allowable entry speed at junction by centripetal acceleration approximation.
+    // Let a circle be tangent to both previous and current path line segments, where the junction
+    // deviation is defined as the distance from the junction to the closest edge of the circle,
+    // colinear with the circle center. The circular segment joining the two paths represents the
+    // path of centripetal acceleration. Solve for max velocity based on max acceleration about the
+    // radius of the circle, defined indirectly by junction deviation. This may be also viewed as
+    // path width or max_jerk in the previous grbl version. This approach does not actually deviate
+    // from path, but used as a robust way to compute cornering speeds, as it takes into account the
+    // nonlinearities of both the junction angle and junction velocity.
+    double vmax_junction = MINIMUM_PLANNER_SPEED; // Set default max junction speed
+
+    if (this->kernel->player->queue.size() > 1 && (this->previous_nominal_speed > 0.0)) {
+      // Compute cosine of angle between previous and current path. (prev_unit_vec is negative)
+      // NOTE: Max junction velocity is computed without sin() or acos() by trig half angle identity.
+      double cos_theta = - this->previous_unit_vec[X_AXIS] * unit_vec[X_AXIS]
+                         - this->previous_unit_vec[Y_AXIS] * unit_vec[Y_AXIS]
+                         - this->previous_unit_vec[Z_AXIS] * unit_vec[Z_AXIS] ;
+                           
+      // Skip and use default max junction speed for 0 degree acute junction.
+      if (cos_theta < 0.95) {
+        vmax_junction = min(this->previous_nominal_speed,block->nominal_speed);
+        // Skip and avoid divide by zero for straight junctions at 180 degrees. Limit to min() of nominal speeds.
+        if (cos_theta > -0.95) {
+          // Compute maximum junction velocity based on maximum acceleration and junction deviation
+          double sin_theta_d2 = sqrt(0.5*(1.0-cos_theta)); // Trig half angle identity. Always positive.
+          vmax_junction = min(vmax_junction,
+            sqrt(this->acceleration*60*60 * this->junction_deviation * sin_theta_d2/(1.0-sin_theta_d2)) ); 
+        }
+      }
+    }
+    block->max_entry_speed = vmax_junction;
+   
+    // Initialize block entry speed. Compute based on deceleration to user-defined MINIMUM_PLANNER_SPEED.
+    double v_allowable = this->max_allowable_speed(-this->acceleration,0.0,block->millimeters); //TODO: Get from config
+    block->entry_speed = min(vmax_junction, v_allowable);
+
+    // Initialize planner efficiency flags
+    // Set flag if block will always reach maximum junction speed regardless of entry/exit speeds.
+    // If a block can de/ac-celerate from nominal speed to zero within the length of the block, then
+    // the current block and next block junction speeds are guaranteed to always be at their maximum
+    // junction speeds in deceleration and acceleration, respectively. This is due to how the current
+    // block nominal speed limits both the current and next maximum junction speeds. Hence, in both
+    // the reverse and forward planners, the corresponding block junction speed will always be at the
+    // the maximum junction speed and may always be ignored for any speed reduction checks.
+    if (block->nominal_speed <= v_allowable) { block->nominal_length_flag = true; }
+    else { block->nominal_length_flag = false; }
+    block->recalculate_flag = true; // Always calculate trapezoid for new block
+ 
+    // Update previous path unit_vector and nominal speed
+    memcpy(this->previous_unit_vec, unit_vec, sizeof(unit_vec)); // previous_unit_vec[] = unit_vec[]
+    this->previous_nominal_speed = block->nominal_speed;
+    
+    // Update current position
+    memcpy(this->position, target, sizeof(int)*3);
+
+    // Math-heavy re-computing of the whole queue to take the new 
+    this->recalculate();
+    
+    // The block can now be used 
+    block->ready();
+
+}
+
+
+// Recalculates the motion plan according to the following algorithm:
+//
+// 1. Go over every block in reverse order and calculate a junction speed reduction (i.e. block_t.entry_factor)
+// so that:
+//   a. The junction jerk is within the set limit
+//   b. No speed reduction within one block requires faster deceleration than the one, true constant
+//      acceleration.
+// 2. Go over every block in chronological order and dial down junction speed reduction values if
+//   a. The speed increase within one block would require faster accelleration than the one, true
+//      constant acceleration.
+//
+// When these stages are complete all blocks have an entry_factor that will allow all speed changes to
+// be performed using only the one, true constant acceleration, and where no junction jerk is jerkier than
+// the set limit. Finally it will:
+//
+// 3. Recalculate trapezoids for all blocks.
+//
+void Planner::recalculate() {
+   //this->kernel->serial->printf("recalculate last: %p, queue size: %d \r\n", this->kernel->player->queue.get_ref( this->kernel->player->queue.size()-1  ), this->kernel->player->queue.size() );
+   this->reverse_pass();
+   this->forward_pass();
+   this->recalculate_trapezoids();
+}
+
+// Planner::recalculate() needs to go over the current plan twice. Once in reverse and once forward. This
+// implements the reverse pass.
+void Planner::reverse_pass(){
+    // For each block
+    int block_index = this->kernel->player->queue.tail;
+    Block* blocks[3] = {NULL,NULL,NULL};
+
+    while(block_index!=this->kernel->player->queue.head){
+        block_index = this->kernel->player->queue.prev_block_index( block_index );
+        blocks[2] = blocks[1];
+        blocks[1] = blocks[0];
+        blocks[0] = &this->kernel->player->queue.buffer[block_index];
+        if( blocks[1] == NULL ){ continue; }
+        blocks[1]->reverse_pass(blocks[2], blocks[0]);
+    }
+    
+}
+
+// Planner::recalculate() needs to go over the current plan twice. Once in reverse and once forward. This
+// implements the forward pass.
+void Planner::forward_pass() {
+    // For each block
+    int block_index = this->kernel->player->queue.head; 
+    Block* blocks[3] = {NULL,NULL,NULL};
+
+    while(block_index!=this->kernel->player->queue.tail){
+        blocks[0] = blocks[1];
+        blocks[1] = blocks[2];
+        blocks[2] = &this->kernel->player->queue.buffer[block_index];
+        if( blocks[0] == NULL ){ continue; }
+        blocks[1]->forward_pass(blocks[0],blocks[2]);
+        block_index = this->kernel->player->queue.next_block_index( block_index );
+    } 
+    blocks[2]->forward_pass(blocks[1],NULL);   
+
+}
+
+// Recalculates the trapezoid speed profiles for flagged blocks in the plan according to the
+// entry_speed for each junction and the entry_speed of the next junction. Must be called by
+// planner_recalculate() after updating the blocks. Any recalulate flagged junction will
+// compute the two adjacent trapezoids to the junction, since the junction speed corresponds
+// to exit speed and entry speed of one another.
+void Planner::recalculate_trapezoids() {
+    int block_index = this->kernel->player->queue.head;
+    Block* current;
+    Block* next = NULL;
+
+    while(block_index != this->kernel->player->queue.tail){
+        current = next;
+        next = &this->kernel->player->queue.buffer[block_index];
+        //this->kernel->serial->printf("index:%d current:%p next:%p \r\n", block_index, current, next );
+        if( current ){
+            // Recalculate if current block entry or exit junction speed has changed.
+            if( current->recalculate_flag || next->recalculate_flag ){
+                current->calculate_trapezoid( current->entry_speed/current->nominal_speed, next->entry_speed/current->nominal_speed );
+                current->recalculate_flag = false;
+            }
+        }
+        block_index = this->kernel->player->queue.next_block_index( block_index ); 
+    }
+
+    // Last/newest block in buffer. Exit speed is set with MINIMUM_PLANNER_SPEED. Always recalculated.
+    next->calculate_trapezoid( next->entry_speed/next->nominal_speed, MINIMUM_PLANNER_SPEED/next->nominal_speed); //TODO: Make configuration option
+    next->recalculate_flag = false;
+
+}
+
+// Debug function
+void Planner::dump_queue(){
+    for( int index = 0; index <= this->kernel->player->queue.size()-1; index++ ){
+       if( index > 10 && index < this->kernel->player->queue.size()-10 ){ continue; }
+       this->kernel->serial->printf("block %03d > ", index);
+       this->kernel->player->queue.get_ref(index)->debug(this->kernel); 
+    }
+}
+
+// Calculates the maximum allowable speed at this point when you must be able to reach target_velocity using the
+// acceleration within the allotted distance.
+double Planner::max_allowable_speed(double acceleration, double target_velocity, double distance) {
+  return(
+    sqrt(target_velocity*target_velocity-2L*acceleration*60*60*distance)  //Was acceleration*60*60*distance, in case this breaks, but here we prefer to use seconds instead of minutes
+  );
+}
+
+
diff -r 000000000000 -r 31e91bb0ef3c modules/robot/Planner.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/robot/Planner.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,54 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+#ifndef PLANNER_H
+#define PLANNER_H
+
+#include <vector>
+#include "libs/RingBuffer.h"
+#include "../communication/utils/Gcode.h"
+#include "Block.h"
+
+#define acceleration_checksum       25326  
+#define max_jerk_checksum           61012 
+#define junction_deviation_checksum 6035 
+
+// TODO: Get from config
+#define MINIMUM_PLANNER_SPEED 0.0
+using namespace std;
+
+
+class Planner : public Module {
+    public:
+        Planner();
+        void append_block( int target[], double feed_rate, double distance, double deltas[] );
+        double max_allowable_speed( double acceleration, double target_velocity, double distance);
+        void recalculate();
+        void reverse_pass();
+        void forward_pass();
+        void recalculate_trapezoids();
+        void dump_queue();
+        Block* get_current_block(); 
+        void cleanup_queue();
+        virtual void on_module_loaded();
+        virtual void on_config_reload(void* argument);
+
+        int position[3];              // Current position, in steps
+        double previous_unit_vec[3];
+        Block last_deleted_block;     // Item -1 in the queue, TODO: Grbl does not need this, but Smoothie won't work without it, we are probably doing something wrong
+        bool has_deleted_block;       // Flag for above value
+        float previous_nominal_speed;
+
+        double acceleration;          // Setting
+        double max_jerk;              // Setting
+        double junction_deviation;    // Setting
+
+};
+
+
+
+#endif
diff -r 000000000000 -r 31e91bb0ef3c modules/robot/Player.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/robot/Player.cpp	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,99 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl) with additions from Sungeun K. Jeon (https://github.com/chamnit/grbl)
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+using namespace std;
+#include <vector>
+#include "libs/nuts_bolts.h"
+#include "libs/RingBuffer.h"
+#include "../communication/utils/Gcode.h"
+#include "libs/Module.h"
+#include "libs/Kernel.h"
+#include "Timer.h" // mbed.h lib
+#include "wait_api.h" // mbed.h lib
+#include "Block.h"
+#include "Player.h"
+#include "Planner.h"
+
+Player::Player(){
+    this->current_block = NULL;
+    this->looking_for_new_block = false;
+}
+
+// Append a block to the list
+Block* Player::new_block(){
+
+    // Clean up the vector of commands in the block we are about to replace
+    // It is quite strange to do this here, we really should do it inside Block->pop_and_execute_gcode
+    // but that function is called inside an interrupt and thus can break everything if the interrupt was trigerred during a memory access
+    //Block* block = this->queue.get_ref( this->queue.size()-1 );
+    Block* block = this->queue.get_ref( this->queue.size() );
+    if( block->player == this ){
+        for(short index=0; index<block->gcodes.size(); index++){
+            block->gcodes.pop_back(); 
+        }     
+    }
+    
+    // Create a new virgin Block in the queue 
+    this->queue.push_back(Block());
+    block = this->queue.get_ref( this->queue.size()-1 );
+    block->is_ready = false;
+    block->initial_rate = -2;
+    block->final_rate = -2;
+    block->player = this;
+    
+    return block;
+}
+
+// Used by blocks to signal when they are ready to be used by the system
+void Player::new_block_added(){
+    if( this->current_block == NULL ){
+        this->pop_and_process_new_block(33);
+    }
+}
+
+// Process a new block in the queue
+void Player::pop_and_process_new_block(int debug){
+    if( this->looking_for_new_block ){ return; }
+    this->looking_for_new_block = true;
+
+    if( this->current_block != NULL ){ this->looking_for_new_block = false; return; }
+
+    // Return if queue is empty 
+    if( this->queue.size() == 0 ){
+        this->current_block = NULL; 
+        // TODO : ON_QUEUE_EMPTY event 
+        this->looking_for_new_block = false;
+        return; 
+    }
+    
+    // Get a new block
+    this->current_block = this->queue.get_ref(0);
+
+    // Tell all modules about it
+    this->kernel->call_event(ON_BLOCK_BEGIN, this->current_block);
+    
+    // In case the module was not taken
+    if( this->current_block->times_taken < 1 ){
+        this->looking_for_new_block = false;
+        this->current_block->release();
+    }
+
+    this->looking_for_new_block = false;
+
+}
+
+void Player::wait_for_queue(int free_blocks){
+    mbed::Timer t;
+    while( this->queue.size() >= this->queue.capacity()-free_blocks ){
+        t.reset();
+        t.start();
+        this->kernel->call_event(ON_IDLE);
+        t.stop();
+        if(t.read_us() < 500)
+            wait_us(500 - t.read_us());
+    }
+}
diff -r 000000000000 -r 31e91bb0ef3c modules/robot/Player.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/robot/Player.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,33 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+#ifndef PLAYER_H
+#define PLAYER_H
+#include "libs/Module.h"
+#include "libs/Kernel.h"
+using namespace std;
+#include <string>
+#include <vector>
+
+class Player : public Module {
+    public:
+        Player();
+
+        Block* new_block();
+        void new_block_added();
+        void pop_and_process_new_block(int debug);
+        void wait_for_queue(int free_blocks);
+
+        RingBuffer<Block,32> queue;  // Queue of Blocks
+        Block* current_block;
+        bool looking_for_new_block;
+
+};
+
+
+
+#endif
diff -r 000000000000 -r 31e91bb0ef3c modules/robot/Robot.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/robot/Robot.cpp	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,317 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl) with additions from Sungeun K. Jeon (https://github.com/chamnit/grbl)
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+#include "libs/Module.h"
+#include "libs/Kernel.h"
+#include <string>
+using std::string;
+#include <math.h>
+#include "Planner.h"
+#include "Player.h"
+#include "Robot.h"
+#include "libs/nuts_bolts.h"
+#include "../communication/utils/Gcode.h"
+#include "arm_solutions/BaseSolution.h"
+#include "arm_solutions/CartesianSolution.h"
+
+Robot::Robot(){
+    this->inch_mode = false;
+    this->absolute_mode = true;
+    this->motion_mode =  MOTION_MODE_SEEK; 
+    this->select_plane(X_AXIS, Y_AXIS, Z_AXIS);
+    clear_vector(this->current_position);
+    clear_vector(this->last_milestone); 
+}
+
+//Called when the module has just been loaded
+void Robot::on_module_loaded() {
+    this->arm_solution = new CartesianSolution(this->kernel->config);
+    this->register_for_event(ON_GCODE_RECEIVED);
+
+    // Configuration
+    this->on_config_reload(this);
+}
+
+void Robot::on_config_reload(void* argument){
+    this->feed_rate =           this->kernel->config->value(default_feed_rate_checksum  )->by_default(100)->as_number()/60; 
+    this->seek_rate =           this->kernel->config->value(default_seek_rate_checksum  )->by_default(100)->as_number()/60;
+    this->mm_per_line_segment = this->kernel->config->value(mm_per_line_segment_checksum)->by_default(0.1)->as_number();
+    this->mm_per_arc_segment  = this->kernel->config->value(mm_per_arc_segment_checksum )->by_default(10 )->as_number();
+    this->arc_correction      = this->kernel->config->value(arc_correction_checksum     )->by_default(5  )->as_number();
+    this->max_speeds[X_AXIS]  = this->kernel->config->value(x_axis_max_speed_checksum   )->by_default(0  )->as_number();
+    this->max_speeds[Y_AXIS]  = this->kernel->config->value(y_axis_max_speed_checksum   )->by_default(0  )->as_number();
+    this->max_speeds[Z_AXIS]  = this->kernel->config->value(z_axis_max_speed_checksum   )->by_default(0  )->as_number();
+}
+
+//A GCode has been received
+void Robot::on_gcode_received(void * argument){
+    Gcode* gcode = static_cast<Gcode*>(argument);
+    gcode->call_on_gcode_execute_event_immediatly = false; 
+    gcode->on_gcode_execute_event_called = false;
+    //If the queue is empty, execute immediatly, otherwise attach to the last added block
+    if( this->kernel->player->queue.size() == 0 ){
+        gcode->call_on_gcode_execute_event_immediatly = true;
+        this->execute_gcode(gcode);
+        if( gcode->on_gcode_execute_event_called == false ){
+            this->kernel->call_event(ON_GCODE_EXECUTE, gcode ); 
+        }
+    }else{
+        Block* block = this->kernel->player->queue.get_ref( this->kernel->player->queue.size() - 1 );
+        this->execute_gcode(gcode);
+        block->append_gcode(gcode);
+    }
+    
+}
+
+
+//See if the current Gcode line has some orders for us
+void Robot::execute_gcode(Gcode* gcode){
+    
+    //Temp variables, constant properties are stored in the object
+    uint8_t next_action = NEXT_ACTION_DEFAULT;
+    this->motion_mode = -1;
+
+   //G-letter Gcodes are mostly what the Robot module is interrested in, other modules also catch the gcode event and do stuff accordingly
+   if( gcode->has_letter('G')){
+       switch( (int) gcode->get_value('G') ){
+           case 0: this->motion_mode = MOTION_MODE_SEEK; break;
+           case 1: this->motion_mode = MOTION_MODE_LINEAR; break;
+           case 2: this->motion_mode = MOTION_MODE_CW_ARC; break;
+           case 3: this->motion_mode = MOTION_MODE_CCW_ARC; break;
+           case 17: this->select_plane(X_AXIS, Y_AXIS, Z_AXIS); break;
+           case 18: this->select_plane(X_AXIS, Z_AXIS, Y_AXIS); break;
+           case 19: this->select_plane(Y_AXIS, Z_AXIS, X_AXIS); break;
+           case 20:this->inch_mode = true; break;
+           case 21:this->inch_mode = false; break;
+           case 90:this->absolute_mode = true; break;
+           case 91:this->absolute_mode = false; break;
+       } 
+    }else{ return; }
+    
+   //Get parameters
+    double target[3], offset[3];
+    clear_vector(target); clear_vector(offset); 
+    
+    memcpy(target, this->current_position, sizeof(target));    //default to last target
+    
+    for(char letter = 'I'; letter <= 'K'; letter++){ if( gcode->has_letter(letter) ){ offset[letter-'I'] = this->to_millimeters(gcode->get_value(letter));                                                    } }     
+    for(char letter = 'X'; letter <= 'Z'; letter++){ if( gcode->has_letter(letter) ){ target[letter-'X'] = this->to_millimeters(gcode->get_value(letter)) + ( this->absolute_mode ? 0 : target[letter-'X']);  } }     
+    
+    if( gcode->has_letter('F') ){ if( this->motion_mode == MOTION_MODE_SEEK ){ this->seek_rate = this->to_millimeters( gcode->get_value('F') ) / 60; }else{ this->feed_rate = this->to_millimeters( gcode->get_value('F') ) / 60; } }
+   
+    //Perform any physical actions
+    switch( next_action ){
+        case NEXT_ACTION_DEFAULT:
+            switch(this->motion_mode){
+                case MOTION_MODE_CANCEL: break;
+                case MOTION_MODE_SEEK  : this->append_line(gcode, target, this->seek_rate ); break;
+                case MOTION_MODE_LINEAR: this->append_line(gcode, target, this->feed_rate ); break;
+                case MOTION_MODE_CW_ARC: case MOTION_MODE_CCW_ARC: this->compute_arc(gcode, offset, target ); break; 
+            }
+            break;
+    }
+
+    // As far as the parser is concerned, the position is now == target. In reality the
+    // motion control system might still be processing the action and the real tool position
+    // in any intermediate location.
+    memcpy(this->current_position, target, sizeof(double)*3); // this->position[] = target[]; 
+
+}
+
+// Convert target from millimeters to steps, and append this to the planner
+void Robot::append_milestone( double target[], double rate ){
+    int steps[3]; //Holds the result of the conversion
+    
+    this->arm_solution->millimeters_to_steps( target, steps );
+    
+    double deltas[3];
+    for(int axis=X_AXIS;axis<=Z_AXIS;axis++){deltas[axis]=target[axis]-this->last_milestone[axis];}
+
+    
+    double millimeters_of_travel = sqrt( pow( deltas[X_AXIS], 2 ) +  pow( deltas[Y_AXIS], 2 ) +  pow( deltas[Z_AXIS], 2 ) );      
+    
+    double duration = 0;
+    if( rate > 0 ){ duration = millimeters_of_travel / rate; }
+
+    for(int axis=X_AXIS;axis<=Z_AXIS;axis++){
+        if( this->max_speeds[axis] > 0 ){ 
+            double axis_speed = ( fabs(deltas[axis]) / ( millimeters_of_travel / rate )) * 60; 
+            if( axis_speed > this->max_speeds[axis] ){ 
+                rate = rate * ( this->max_speeds[axis] / axis_speed ); 
+            }
+        }
+    }
+
+    this->kernel->planner->append_block( steps, rate*60, millimeters_of_travel, deltas ); 
+
+    memcpy(this->last_milestone, target, sizeof(double)*3); // this->last_milestone[] = target[]; 
+
+}
+
+void Robot::append_line(Gcode* gcode, double target[], double rate ){
+
+
+    // We cut the line into smaller segments. This is not usefull in a cartesian robot, but necessary for robots with rotational axes. 
+    // In cartesian robot, a high "mm_per_line_segment" setting will prevent waste.
+    gcode->millimeters_of_travel = sqrt( pow( target[X_AXIS]-this->current_position[X_AXIS], 2 ) +  pow( target[Y_AXIS]-this->current_position[Y_AXIS], 2 ) +  pow( target[Z_AXIS]-this->current_position[Z_AXIS], 2 ) ); 
+
+    if( gcode->call_on_gcode_execute_event_immediatly == true ){
+            this->kernel->call_event(ON_GCODE_EXECUTE, gcode ); 
+            gcode->on_gcode_execute_event_called = true;
+    }
+
+    if (gcode->millimeters_of_travel == 0.0) { 
+        this->append_milestone(this->current_position, 0.0);
+        return; 
+    }
+
+    uint16_t segments = ceil( gcode->millimeters_of_travel/ this->mm_per_line_segment); 
+    // A vector to keep track of the endpoint of each segment
+    double temp_target[3];
+    //Initialize axes
+    memcpy( temp_target, this->current_position, sizeof(double)*3); // temp_target[] = this->current_position[];  
+
+    //For each segment
+    for( int i=0; i<segments-1; i++ ){
+        for(int axis=X_AXIS; axis <= Z_AXIS; axis++ ){ temp_target[axis] += ( target[axis]-this->current_position[axis] )/segments; }        
+        this->append_milestone(temp_target, rate); 
+    }
+    this->append_milestone(target, rate);
+}
+
+
+void Robot::append_arc(Gcode* gcode, double target[], double offset[], double radius, bool is_clockwise ){
+
+    double center_axis0 = this->current_position[this->plane_axis_0] + offset[this->plane_axis_0];
+    double center_axis1 = this->current_position[this->plane_axis_1] + offset[this->plane_axis_1];
+    double linear_travel = target[this->plane_axis_2] - this->current_position[this->plane_axis_2];
+    double r_axis0 = -offset[this->plane_axis_0]; // Radius vector from center to current location
+    double r_axis1 = -offset[this->plane_axis_1];
+    double rt_axis0 = target[this->plane_axis_0] - center_axis0;
+    double rt_axis1 = target[this->plane_axis_1] - center_axis1;
+
+    // CCW angle between position and target from circle center. Only one atan2() trig computation required.
+    double angular_travel = atan2(r_axis0*rt_axis1-r_axis1*rt_axis0, r_axis0*rt_axis0+r_axis1*rt_axis1);
+    if (angular_travel < 0) { angular_travel += 2*M_PI; }
+    if (is_clockwise) { angular_travel -= 2*M_PI; }
+
+    gcode->millimeters_of_travel = hypot(angular_travel*radius, fabs(linear_travel));
+
+    if( gcode->call_on_gcode_execute_event_immediatly == true ){
+            this->kernel->call_event(ON_GCODE_EXECUTE, gcode ); 
+            gcode->on_gcode_execute_event_called = true;
+    }
+
+    if (gcode->millimeters_of_travel == 0.0) { 
+        this->append_milestone(this->current_position, 0.0);
+        return; 
+    }
+ 
+    uint16_t segments = floor(gcode->millimeters_of_travel/this->mm_per_arc_segment);
+
+    double theta_per_segment = angular_travel/segments;
+    double linear_per_segment = linear_travel/segments;
+
+    /* Vector rotation by transformation matrix: r is the original vector, r_T is the rotated vector,
+    and phi is the angle of rotation. Based on the solution approach by Jens Geisler.
+    r_T = [cos(phi) -sin(phi);
+    sin(phi) cos(phi] * r ;
+    For arc generation, the center of the circle is the axis of rotation and the radius vector is
+    defined from the circle center to the initial position. Each line segment is formed by successive
+    vector rotations. This requires only two cos() and sin() computations to form the rotation
+    matrix for the duration of the entire arc. Error may accumulate from numerical round-off, since
+    all double numbers are single precision on the Arduino. (True double precision will not have
+    round off issues for CNC applications.) Single precision error can accumulate to be greater than
+    tool precision in some cases. Therefore, arc path correction is implemented.
+
+    Small angle approximation may be used to reduce computation overhead further. This approximation
+    holds for everything, but very small circles and large mm_per_arc_segment values. In other words,
+    theta_per_segment would need to be greater than 0.1 rad and N_ARC_CORRECTION would need to be large
+    to cause an appreciable drift error. N_ARC_CORRECTION~=25 is more than small enough to correct for
+    numerical drift error. N_ARC_CORRECTION may be on the order a hundred(s) before error becomes an
+    issue for CNC machines with the single precision Arduino calculations.
+    This approximation also allows mc_arc to immediately insert a line segment into the planner
+    without the initial overhead of computing cos() or sin(). By the time the arc needs to be applied
+    a correction, the planner should have caught up to the lag caused by the initial mc_arc overhead.
+    This is important when there are successive arc motions.
+    */
+    // Vector rotation matrix values
+    double cos_T = 1-0.5*theta_per_segment*theta_per_segment; // Small angle approximation
+    double sin_T = theta_per_segment;
+
+    double arc_target[3];
+    double sin_Ti;
+    double cos_Ti;
+    double r_axisi;
+    uint16_t i;
+    int8_t count = 0;
+
+    // Initialize the linear axis
+    arc_target[this->plane_axis_2] = this->current_position[this->plane_axis_2];
+
+    for (i = 1; i<segments; i++) { // Increment (segments-1)
+
+        if (count < this->arc_correction ) {
+          // Apply vector rotation matrix
+          r_axisi = r_axis0*sin_T + r_axis1*cos_T;
+          r_axis0 = r_axis0*cos_T - r_axis1*sin_T;
+          r_axis1 = r_axisi;
+          count++;
+        } else {
+          // Arc correction to radius vector. Computed only every N_ARC_CORRECTION increments.
+          // Compute exact location by applying transformation matrix from initial radius vector(=-offset).
+          cos_Ti = cos(i*theta_per_segment);
+          sin_Ti = sin(i*theta_per_segment);
+          r_axis0 = -offset[this->plane_axis_0]*cos_Ti + offset[this->plane_axis_1]*sin_Ti;
+          r_axis1 = -offset[this->plane_axis_0]*sin_Ti - offset[this->plane_axis_1]*cos_Ti;
+          count = 0;
+        }
+
+        // Update arc_target location
+        arc_target[this->plane_axis_0] = center_axis0 + r_axis0;
+        arc_target[this->plane_axis_1] = center_axis1 + r_axis1;
+        arc_target[this->plane_axis_2] += linear_per_segment;
+        this->append_milestone(arc_target, this->feed_rate);
+
+    }
+    // Ensure last segment arrives at target location.
+    this->append_milestone(target, this->feed_rate);
+}
+
+
+void Robot::compute_arc(Gcode* gcode, double offset[], double target[]){
+
+    // Find the radius
+    double radius = hypot(offset[this->plane_axis_0], offset[this->plane_axis_1]);
+
+    // Set clockwise/counter-clockwise sign for mc_arc computations
+    bool is_clockwise = false;
+    if( this->motion_mode == MOTION_MODE_CW_ARC ){ is_clockwise = true; } 
+
+    // Append arc
+    this->append_arc(gcode, target, offset,  radius, is_clockwise );
+
+}
+
+
+// Convert from inches to millimeters ( our internal storage unit ) if needed
+inline double Robot::to_millimeters( double value ){
+        return this->inch_mode ? value/25.4 : value; 
+}
+
+double Robot::theta(double x, double y){
+    double t = atan(x/fabs(y));
+    if (y>0) {return(t);} else {if (t>0){return(M_PI-t);} else {return(-M_PI-t);}}
+}
+
+void Robot::select_plane(uint8_t axis_0, uint8_t axis_1, uint8_t axis_2){
+    this->plane_axis_0 = axis_0;
+    this->plane_axis_1 = axis_1;
+    this->plane_axis_2 = axis_2;
+}
+
+
diff -r 000000000000 -r 31e91bb0ef3c modules/robot/Robot.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/robot/Robot.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,92 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+#ifndef ROBOT_H
+#define ROBOT_H
+
+#include <string>
+using std::string;
+#include "libs/Module.h"
+#include "libs/Kernel.h"
+#include "../communication/utils/Gcode.h"
+#include "arm_solutions/BaseSolution.h"
+#include "Planner.h"
+
+#define default_seek_rate_checksum             6633
+#define default_feed_rate_checksum             47357
+#define mm_per_line_segment_checksum           30176
+#define mm_per_arc_segment_checksum            15470
+#define arc_correction_checksum                5074
+#define x_axis_max_speed_checksum              64935
+#define y_axis_max_speed_checksum              3752
+#define z_axis_max_speed_checksum              7849
+
+#define NEXT_ACTION_DEFAULT 0
+#define NEXT_ACTION_DWELL 1
+#define NEXT_ACTION_GO_HOME 2
+
+#define MOTION_MODE_SEEK 0 // G0
+#define MOTION_MODE_LINEAR 1 // G1
+#define MOTION_MODE_CW_ARC 2 // G2
+#define MOTION_MODE_CCW_ARC 3 // G3
+#define MOTION_MODE_CANCEL 4 // G80
+
+#define PATH_CONTROL_MODE_EXACT_PATH 0
+#define PATH_CONTROL_MODE_EXACT_STOP 1
+#define PATH_CONTROL_MODE_CONTINOUS 2
+
+#define PROGRAM_FLOW_RUNNING 0
+#define PROGRAM_FLOW_PAUSED 1
+#define PROGRAM_FLOW_COMPLETED 2
+
+#define SPINDLE_DIRECTION_CW 0
+#define SPINDLE_DIRECTION_CCW 1
+
+#define M_PI 3.14159
+
+
+class Robot : public Module {
+    public:
+        Robot();
+        virtual void on_module_loaded();
+        virtual void on_config_reload(void* argument);
+        virtual void on_gcode_received(void* argument);
+        void execute_gcode(Gcode* gcode);
+        void append_milestone( double target[], double feed_rate);
+        void append_line( Gcode* gcode, double target[], double feed_rate);
+        //void append_arc(double theta_start, double angular_travel, double radius, double depth, double rate);
+        void append_arc( Gcode* gcode, double target[], double offset[], double radius, bool is_clockwise );
+
+
+        void compute_arc(Gcode* gcode, double offset[], double target[]);
+        double to_millimeters(double value);
+        double theta(double x, double y);
+        void select_plane(uint8_t axis_0, uint8_t axis_1, uint8_t axis_2);
+
+        double current_position[3];                           // Current position, in millimeters
+        double last_milestone[3];                             // Last position, in millimeters
+        bool inch_mode;                                       // true for inch mode, false for millimeter mode ( default )
+        bool absolute_mode;                                   // true for absolute mode ( default ), false for relative mode
+        int8_t motion_mode;                                  // Motion mode for the current received Gcode
+        double seek_rate;                                     // Current rate for seeking moves ( mm/s )
+        double feed_rate;                                     // Current rate for feeding moves ( mm/s )
+        uint8_t plane_axis_0, plane_axis_1, plane_axis_2;     // Current plane ( XY, XZ, YZ )
+        BaseSolution* arm_solution;                           // Selected Arm solution ( millimeters to step calculation )
+        double mm_per_line_segment;                           // Setting : Used to split lines into segments
+        double mm_per_arc_segment;                            // Setting : Used to split arcs into segmentrs
+        
+        // Number of arc generation iterations by small angle approximation before exact arc trajectory
+        // correction. This parameter maybe decreased if there are issues with the accuracy of the arc
+        // generations. In general, the default value is more than enough for the intended CNC applications
+        // of grbl, and should be on the order or greater than the size of the buffer to help with the
+        // computational efficiency of generating arcs.
+        int arc_correction;                                   // Setting : how often to rectify arc computation
+        double max_speeds[3];                                 // Setting : max allowable speed in mm/m for each axis
+
+};
+
+#endif
diff -r 000000000000 -r 31e91bb0ef3c modules/robot/Stepper.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/robot/Stepper.cpp	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,243 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl) with additions from Sungeun K. Jeon (https://github.com/chamnit/grbl)
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+#include "libs/Module.h"
+#include "libs/Kernel.h"
+#include "Stepper.h"
+#include "Planner.h"
+#include "Player.h"
+#include <vector>
+using namespace std;
+#include "libs/nuts_bolts.h"
+
+Stepper* stepper;
+
+Stepper::Stepper(){
+    this->current_block = NULL;
+    this->step_events_completed = 0; 
+    this->divider = 0;
+    this->paused = false;
+}
+
+//Called when the module has just been loaded
+void Stepper::on_module_loaded(){
+    stepper = this;
+    this->register_for_event(ON_BLOCK_BEGIN);
+    this->register_for_event(ON_BLOCK_END);
+    this->register_for_event(ON_GCODE_EXECUTE);
+    this->register_for_event(ON_PLAY);
+    this->register_for_event(ON_PAUSE);
+ 
+    // Get onfiguration
+    this->on_config_reload(this); 
+
+    // Acceleration ticker
+    //this->kernel->slow_ticker->set_frequency(this->acceleration_ticks_per_second/10);
+    this->kernel->slow_ticker->attach( this->acceleration_ticks_per_second, this, &Stepper::trapezoid_generator_tick );
+
+    // Initiate main_interrupt timer and step reset timer
+    this->kernel->step_ticker->attach( this, &Stepper::main_interrupt );   
+    this->kernel->step_ticker->reset_attach( this, &Stepper::reset_step_pins );
+
+}
+
+// Get configuration from the config file
+void Stepper::on_config_reload(void* argument){
+    
+    this->microseconds_per_step_pulse   =  this->kernel->config->value(microseconds_per_step_pulse_checksum  )->by_default(5     )->as_number();
+    this->acceleration_ticks_per_second =  this->kernel->config->value(acceleration_ticks_per_second_checksum)->by_default(100   )->as_number();
+    this->minimum_steps_per_minute      =  this->kernel->config->value(minimum_steps_per_minute_checksum     )->by_default(1200  )->as_number();
+    this->base_stepping_frequency       =  this->kernel->config->value(base_stepping_frequency_checksum      )->by_default(100000)->as_number();
+    this->alpha_step_pin                =  this->kernel->config->value(alpha_step_pin_checksum               )->by_default("1.21"     )->as_pin()->as_output();
+    this->beta_step_pin                 =  this->kernel->config->value(beta_step_pin_checksum                )->by_default("1.23"     )->as_pin()->as_output();
+    this->gamma_step_pin                =  this->kernel->config->value(gamma_step_pin_checksum               )->by_default("1.22!"    )->as_pin()->as_output();
+    this->alpha_dir_pin                 =  this->kernel->config->value(alpha_dir_pin_checksum                )->by_default("1.18"     )->as_pin()->as_output();
+    this->beta_dir_pin                  =  this->kernel->config->value(beta_dir_pin_checksum                 )->by_default("1.20"     )->as_pin()->as_output();
+    this->gamma_dir_pin                 =  this->kernel->config->value(gamma_dir_pin_checksum                )->by_default("1.19"     )->as_pin()->as_output();
+    this->alpha_en_pin                  =  this->kernel->config->value(alpha_en_pin_checksum                 )->by_default("0.4"      )->as_pin()->as_output()->as_open_drain();
+    this->beta_en_pin                   =  this->kernel->config->value(beta_en_pin_checksum                  )->by_default("0.10"     )->as_pin()->as_output()->as_open_drain();
+    this->gamma_en_pin                  =  this->kernel->config->value(gamma_en_pin_checksum                 )->by_default("0.19"     )->as_pin()->as_output()->as_open_drain();
+
+
+    // TODO : This is supposed to be done by gcodes
+    this->alpha_en_pin->set(0);
+    this->beta_en_pin->set(0);
+    this->gamma_en_pin->set(0);
+
+
+    // Set the Timer interval for Match Register 1, 
+    this->kernel->step_ticker->set_reset_delay( this->microseconds_per_step_pulse / 1000000 );
+    this->kernel->step_ticker->set_frequency( this->base_stepping_frequency );
+}
+
+// When the play/pause button is set to pause, or a module calls the ON_PAUSE event
+void Stepper::on_pause(void* argument){
+    this->paused = true;
+}
+
+// When the play/pause button is set to play, or a module calls the ON_PLAY event
+void Stepper::on_play(void* argument){
+    // TODO: Re-compute the whole queue for a cold-start
+    this->paused = false;
+}
+
+void Stepper::on_gcode_execute(void* argument){
+    Gcode* gcode = static_cast<Gcode*>(argument);
+
+    if( gcode->has_letter('M')){
+        int code = (int) gcode->get_value('M');
+        if( code == 84 ){
+            this->alpha_en_pin->set(0);
+            this->beta_en_pin->set(0);
+            this->gamma_en_pin->set(0);
+        }
+    }
+}
+
+// A new block is popped from the queue
+void Stepper::on_block_begin(void* argument){
+    Block* block  = static_cast<Block*>(argument);
+
+    // The stepper does not care about 0-blocks
+    if( block->millimeters == 0.0 ){ return; }
+    
+    // Mark the new block as of interrest to us
+    block->take();
+   
+    // Setup
+    for( int stpr=ALPHA_STEPPER; stpr<=GAMMA_STEPPER; stpr++){ this->counters[stpr] = 0; this->stepped[stpr] = 0; } 
+    this->step_events_completed = 0; 
+
+    this->current_block = block;
+    
+    // This is just to save computing power and not do it every step 
+    this->update_offsets();
+    
+    // Setup acceleration for this block 
+    this->trapezoid_generator_reset();
+
+}
+
+// Current block is discarded
+void Stepper::on_block_end(void* argument){
+    Block* block  = static_cast<Block*>(argument);
+    this->current_block = NULL; //stfu !
+}
+
+// "The Stepper Driver Interrupt" - This timer interrupt is the workhorse of Smoothie. It is executed at the rate set with
+// config_step_timer. It pops blocks from the block_buffer and executes them by pulsing the stepper pins appropriately.
+inline uint32_t Stepper::main_interrupt(uint32_t dummy){
+    if( this->paused ){ return 0; } 
+
+    // Step dir pins first, then step pinse, stepper drivers like to know the direction before the step signal comes in
+    this->alpha_dir_pin->set(  ( this->out_bits >> 0  ) & 1 );
+    this->beta_dir_pin->set(   ( this->out_bits >> 1  ) & 1 );
+    this->gamma_dir_pin->set(  ( this->out_bits >> 2  ) & 1 );
+    this->alpha_step_pin->set( ( this->out_bits >> 3  ) & 1 );
+    this->beta_step_pin->set(  ( this->out_bits >> 4  ) & 1 );
+    this->gamma_step_pin->set( ( this->out_bits >> 5  ) & 1 );
+
+    if( this->current_block != NULL ){
+        // Set bits for direction and steps 
+        this->out_bits = this->current_block->direction_bits;
+        for( int stpr=ALPHA_STEPPER; stpr<=GAMMA_STEPPER; stpr++){ 
+            this->counters[stpr] += this->counter_increment; 
+            if( this->counters[stpr] > this->offsets[stpr] && this->stepped[stpr] < this->current_block->steps[stpr] ){
+                this->counters[stpr] -= this->offsets[stpr] ;
+                this->stepped[stpr]++;
+                this->out_bits |= (1 << (stpr+3) );
+            } 
+        } 
+        // If current block is finished, reset pointer
+        this->step_events_completed += this->counter_increment;
+        if( this->step_events_completed >= this->current_block->steps_event_count<<16 ){ 
+            if( this->stepped[ALPHA_STEPPER] == this->current_block->steps[ALPHA_STEPPER] && this->stepped[BETA_STEPPER] == this->current_block->steps[BETA_STEPPER] && this->stepped[GAMMA_STEPPER] == this->current_block->steps[GAMMA_STEPPER] ){ 
+                if( this->current_block != NULL ){
+                    this->current_block->release(); 
+                }
+            }
+        }
+    }else{
+        this->out_bits = 0;
+    }
+
+}
+
+// We compute this here instead of each time in the interrupt
+void Stepper::update_offsets(){
+    for( int stpr=ALPHA_STEPPER; stpr<=GAMMA_STEPPER; stpr++){ 
+        this->offsets[stpr] = (int)floor((float)((float)(1<<16)*(float)((float)this->current_block->steps_event_count / (float)this->current_block->steps[stpr]))); 
+    }
+}
+
+// This is called ACCELERATION_TICKS_PER_SECOND times per second by the step_event
+// interrupt. It can be assumed that the trapezoid-generator-parameters and the
+// current_block stays untouched by outside handlers for the duration of this function call.
+uint32_t Stepper::trapezoid_generator_tick( uint32_t dummy ) {
+    if(this->current_block && !this->trapezoid_generator_busy && !this->paused ) {
+          if(this->step_events_completed < this->current_block->accelerate_until<<16) {
+              this->trapezoid_adjusted_rate += this->current_block->rate_delta;
+              if (this->trapezoid_adjusted_rate > this->current_block->nominal_rate ) {
+                  this->trapezoid_adjusted_rate = this->current_block->nominal_rate;
+              }
+              this->set_step_events_per_minute(this->trapezoid_adjusted_rate);
+          } else if (this->step_events_completed >= this->current_block->decelerate_after<<16) {
+              // NOTE: We will only reduce speed if the result will be > 0. This catches small
+              // rounding errors that might leave steps hanging after the last trapezoid tick.
+              if (this->trapezoid_adjusted_rate > double(this->current_block->rate_delta) * 1.5) {
+                  this->trapezoid_adjusted_rate -= this->current_block->rate_delta;
+              }else{
+                  this->trapezoid_adjusted_rate = double(this->current_block->rate_delta) * 1.5; 
+                  //this->trapezoid_adjusted_rate = floor(double(this->trapezoid_adjusted_rate / 2 ));
+                  //this->kernel->serial->printf("over!\r\n");
+              }
+              if (this->trapezoid_adjusted_rate < this->current_block->final_rate ) {
+                  this->trapezoid_adjusted_rate = this->current_block->final_rate;
+              }
+              this->set_step_events_per_minute(this->trapezoid_adjusted_rate);
+          } else {
+              // Make sure we cruise at exactly nominal rate
+              if (this->trapezoid_adjusted_rate != this->current_block->nominal_rate) {
+                  this->trapezoid_adjusted_rate = this->current_block->nominal_rate;
+                  this->set_step_events_per_minute(this->trapezoid_adjusted_rate);
+              }
+          }
+    }
+}
+
+// Initializes the trapezoid generator from the current block. Called whenever a new
+// block begins.
+void Stepper::trapezoid_generator_reset(){
+    this->trapezoid_adjusted_rate = this->current_block->initial_rate;
+    this->trapezoid_tick_cycle_counter = 0;
+    // Because this can be called directly from the main loop, it could be interrupted by the acceleration ticker, and that would be bad, so we use a flag
+    this->trapezoid_generator_busy = true;
+    this->set_step_events_per_minute(this->trapezoid_adjusted_rate); 
+    this->trapezoid_generator_busy = false;
+}
+
+void Stepper::set_step_events_per_minute( double steps_per_minute ){
+
+    // We do not step slower than this 
+    steps_per_minute = max(steps_per_minute, this->minimum_steps_per_minute);
+
+    // The speed factor is the factor by which we must multiply the minimal step frequency to reach the maximum step frequency
+    // The higher, the smoother the movement will be, but the closer the maximum and minimum frequencies are, the smaller the factor is
+    // speed_factor = base_stepping_frequency / steps_per_second
+    // counter_increment = 1 / speed_factor ( 1 is 1<<16 because we do fixed point )
+    this->counter_increment = int(floor(double(1<<16)/double(this->base_stepping_frequency / (steps_per_minute/60L))));
+
+    this->kernel->call_event(ON_SPEED_CHANGE, this);
+
+}
+
+uint32_t Stepper::reset_step_pins(uint32_t dummy){
+    this->alpha_step_pin->set(0);
+    this->beta_step_pin->set(0); 
+    this->gamma_step_pin->set(0);
+
+}
diff -r 000000000000 -r 31e91bb0ef3c modules/robot/Stepper.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/robot/Stepper.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,83 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+#ifndef STEPPER_H
+#define STEPPER_H
+#include "libs/Module.h"
+#include "libs/Kernel.h"
+#include "Planner.h"
+#include "Block.h"
+
+#define microseconds_per_step_pulse_checksum        42333
+#define acceleration_ticks_per_second_checksum      25075
+#define minimum_steps_per_minute_checksum           9003
+#define base_stepping_frequency_checksum            21918
+#define alpha_step_pin_checksum                     11468
+#define beta_step_pin_checksum                      22114
+#define gamma_step_pin_checksum                     1225
+#define alpha_dir_pin_checksum                      55887
+#define beta_dir_pin_checksum                       28644
+#define gamma_dir_pin_checksum                      46412
+#define alpha_en_pin_checksum                       35042  
+#define beta_en_pin_checksum                        34680 
+#define gamma_en_pin_checksum                       26335 
+
+
+class Stepper : public Module {
+    public:
+        Stepper();
+        virtual void on_module_loaded();
+        virtual void on_config_reload(void* argument);
+        virtual void on_block_begin(void* argument);
+        virtual void on_block_end(void* argument);
+        virtual void on_gcode_execute(void* argument);
+        virtual void on_play(void* argument);
+        virtual void on_pause(void* argument);
+        uint32_t main_interrupt(uint32_t dummy);
+        void trapezoid_generator_reset();
+        void set_step_events_per_minute(double steps_per_minute);
+        uint32_t trapezoid_generator_tick(uint32_t dummy);
+        uint32_t reset_step_pins(uint32_t dummy);
+        void update_offsets();
+        int config_step_timer( int cycles );
+
+        Block* current_block;
+        int counters[3];
+        int stepped[3]; 
+        int offsets[3]; 
+        float counter_alpha;
+        float counter_beta;
+        float counter_gamma;
+        int step_events_completed; 
+        unsigned int out_bits; 
+        double trapezoid_adjusted_rate;
+        int trapezoid_tick_cycle_counter;
+        int cycles_per_step_event; 
+        bool trapezoid_generator_busy;
+        int microseconds_per_step_pulse; 
+        int acceleration_ticks_per_second;
+        int divider;
+        int minimum_steps_per_minute;
+        int base_stepping_frequency;
+        Pin* alpha_step_pin;
+        Pin* beta_step_pin;
+        Pin* gamma_step_pin;
+        Pin* alpha_dir_pin;
+        Pin* beta_dir_pin;
+        Pin* gamma_dir_pin;
+        Pin* alpha_en_pin;
+        Pin* beta_en_pin;
+        Pin* gamma_en_pin;
+        unsigned short step_bits[3];
+        int counter_increment;
+        bool paused;
+};
+
+
+
+
+#endif
diff -r 000000000000 -r 31e91bb0ef3c modules/robot/arm_solutions/BaseSolution.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/robot/arm_solutions/BaseSolution.cpp	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,6 @@
+#include "BaseSolution.h"
+
+BaseSolution::BaseSolution(){}
+
+void BaseSolution::millimeters_to_steps( double millimeters[], int steps[] ){}
+void BaseSolution::steps_to_millimeters( int steps[], double millimeters[] ){} 
diff -r 000000000000 -r 31e91bb0ef3c modules/robot/arm_solutions/BaseSolution.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/robot/arm_solutions/BaseSolution.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,12 @@
+// Base class for an arm solution, only usefull for inheritence. http://en.wikipedia.org/wiki/Arm_solution
+#ifndef BASESOLUTION_H
+#define BASESOLUTION_H
+
+class BaseSolution {
+    public:
+        BaseSolution();
+        virtual void millimeters_to_steps( double millimeters[], int steps[] );
+        virtual void steps_to_millimeters( int steps[], double millimeters[] ); 
+};
+
+#endif
diff -r 000000000000 -r 31e91bb0ef3c modules/robot/arm_solutions/CartesianSolution.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/robot/arm_solutions/CartesianSolution.cpp	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,16 @@
+#include "CartesianSolution.h"
+#include <math.h>
+
+CartesianSolution::CartesianSolution(Config* passed_config) : config(passed_config){
+    this->alpha_steps_per_mm = this->config->value(alpha_steps_per_mm_checksum)->as_number();
+    this->beta_steps_per_mm  = this->config->value( beta_steps_per_mm_checksum)->as_number();
+    this->gamma_steps_per_mm = this->config->value(gamma_steps_per_mm_checksum)->as_number();
+}
+
+void CartesianSolution::millimeters_to_steps( double millimeters[], int steps[] ){
+    steps[ALPHA_STEPPER] = floor( millimeters[X_AXIS] * this->alpha_steps_per_mm +0.5);
+    steps[BETA_STEPPER ] = floor( millimeters[Y_AXIS] * this->beta_steps_per_mm +0.5);
+    steps[GAMMA_STEPPER] = floor( millimeters[Z_AXIS] * this->gamma_steps_per_mm +0.5);
+}
+
+void CartesianSolution::steps_to_millimeters( int steps[], double millimeters[] ){} 
diff -r 000000000000 -r 31e91bb0ef3c modules/robot/arm_solutions/CartesianSolution.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/robot/arm_solutions/CartesianSolution.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,31 @@
+#ifndef CARTESIANSOLUTION_H
+#define CARTESIANSOLUTION_H
+#include "libs/Module.h"
+#include "libs/Kernel.h"
+#include "BaseSolution.h"
+#include "libs/nuts_bolts.h"
+
+#include "libs/Config.h"
+
+#define alpha_steps_per_mm_checksum 46458
+#define beta_steps_per_mm_checksum  13840
+#define gamma_steps_per_mm_checksum 33143
+
+class CartesianSolution : public BaseSolution {
+    public:
+        CartesianSolution(Config* passed_config);
+        virtual void millimeters_to_steps( double millimeters[], int steps[] );
+        virtual void steps_to_millimeters( int steps[], double millimeters[] ); 
+
+        Config* config;
+        double alpha_steps_per_mm;
+        double beta_steps_per_mm;
+        double gamma_steps_per_mm;
+};
+
+
+
+
+
+
+#endif
diff -r 000000000000 -r 31e91bb0ef3c modules/tools/extruder/Extruder.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/tools/extruder/Extruder.cpp	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,285 @@
+/*
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+
+#include "libs/Module.h"
+#include "libs/Kernel.h"
+#include "modules/robot/Player.h"
+#include "modules/robot/Block.h"
+#include "modules/tools/extruder/Extruder.h"
+
+#define extruder_step_pin_checksum    40763
+#define extruder_dir_pin_checksum     57277
+#define extruder_en_pin_checksum      8017
+
+Extruder::Extruder() {
+    this->absolute_mode = true;
+    this->direction     = 1;
+    this->acceleration_lock = false;
+    this->step_counter = 0;
+    this->counter_increment = 0;
+    this->paused = false;
+}
+
+void Extruder::on_module_loaded() {
+
+    // Do not do anything if not enabledd
+    if( this->kernel->config->value( extruder_module_enable_checksum )->by_default(false)->as_bool() == false ){ return; }
+
+    // Settings
+    this->on_config_reload(this);
+
+    // We work on the same Block as Stepper, so we need to know when it gets a new one and drops one
+    this->register_for_event(ON_BLOCK_BEGIN);
+    this->register_for_event(ON_BLOCK_END);
+    this->register_for_event(ON_GCODE_EXECUTE);
+    this->register_for_event(ON_PLAY);
+    this->register_for_event(ON_PAUSE);
+
+    // Start values
+    this->start_position = 0;
+    this->target_position = 0;
+    this->current_position = 0;
+    this->current_block = NULL;
+    this->mode = OFF;
+
+    // Update speed every *acceleration_ticks_per_second*
+    // TODO: Make this an independent setting
+    this->kernel->slow_ticker->attach( this->kernel->stepper->acceleration_ticks_per_second , this, &Extruder::acceleration_tick );
+
+    // Initiate main_interrupt timer and step reset timer
+    this->kernel->step_ticker->attach( this, &Extruder::stepping_tick );
+    this->kernel->step_ticker->reset_attach( this, &Extruder::reset_step_pin );
+
+}
+
+// Get config
+void Extruder::on_config_reload(void* argument){
+    this->microseconds_per_step_pulse = this->kernel->config->value(microseconds_per_step_pulse_checksum)->by_default(5)->as_number();
+    this->steps_per_millimeter        = this->kernel->config->value(extruder_steps_per_mm_checksum       )->by_default(1)->as_number();
+    this->feed_rate                   = this->kernel->config->value(default_feed_rate_checksum          )->by_default(1)->as_number();
+    this->acceleration                = this->kernel->config->value(acceleration_checksum               )->by_default(1)->as_number();
+
+    this->step_pin                    = this->kernel->config->value(extruder_step_pin_checksum          )->by_default("1.22" )->as_pin()->as_output();
+    this->dir_pin                     = this->kernel->config->value(extruder_dir_pin_checksum           )->by_default("1.19" )->as_pin()->as_output();
+    this->en_pin                      = this->kernel->config->value(extruder_en_pin_checksum            )->by_default("0.19" )->as_pin()->as_output();
+}
+
+
+// When the play/pause button is set to pause, or a module calls the ON_PAUSE event
+void Extruder::on_pause(void* argument){
+    this->paused = true;
+}
+
+// When the play/pause button is set to play, or a module calls the ON_PLAY event
+void Extruder::on_play(void* argument){
+    this->paused = false;
+}
+
+
+
+// Compute extrusion speed based on parameters and gcode distance of travel
+void Extruder::on_gcode_execute(void* argument){
+    Gcode* gcode = static_cast<Gcode*>(argument);
+
+    // Absolute/relative mode
+    if( gcode->has_letter('M')){
+        int code = (int) gcode->get_value('M');
+        if( code == 82 ){ this->absolute_mode = true; }
+        if( code == 83 ){ this->absolute_mode = false; }
+        if( code == 84 ){ this->en_pin->set(0); }
+    }
+
+    // The mode is OFF by default, and SOLO or FOLLOW only if we need to extrude
+    this->mode = OFF;
+
+    if( gcode->has_letter('G') ){
+        // G92: Reset extruder position
+        if( gcode->get_value('G') == 92 ){
+            if( gcode->has_letter('E') ){
+                this->current_position = gcode->get_value('E');
+                this->target_position  = this->current_position;
+                this->start_position   = this->current_position;
+            }
+        }else{
+            // Extrusion length from 'G' Gcode
+            if( gcode->has_letter('E' )){
+                // Get relative extrusion distance depending on mode ( in absolute mode we must substract target_position )
+                double relative_extrusion_distance = gcode->get_value('E');
+                if( this->absolute_mode == true ){ relative_extrusion_distance = relative_extrusion_distance - this->target_position; }
+
+                // If the robot is moving, we follow it's movement, otherwise, we move alone
+                if( fabs(gcode->millimeters_of_travel) < 0.0001 ){  // With floating numbers, we can have 0 != 0 ... beeeh
+                    this->mode = SOLO;
+                    this->travel_distance = relative_extrusion_distance;
+                    if( gcode->has_letter('F') ){ this->feed_rate = gcode->get_value('F'); }
+                }else{
+                    this->mode = FOLLOW;
+                    // We move proportionally to the robot's movement
+                    this->travel_ratio = relative_extrusion_distance / gcode->millimeters_of_travel;
+                }
+
+                this->en_pin->set(1);
+            }
+        }
+    }
+
+}
+
+// When a new block begins, either follow the robot, or step by ourselves ( or stay back and do nothing )
+void Extruder::on_block_begin(void* argument){
+    Block* block = static_cast<Block*>(argument);
+    if( this->mode == SOLO ){
+        // In solo mode we take the block so we can move even if the stepper has nothing to do
+        block->take();
+        this->current_block = block;
+        this->start_position = this->target_position;
+        this->target_position = this->start_position + this->travel_distance ;
+        this->travel_ratio = 0.2;   // TODO : Make a real acceleration thing
+        if( this->target_position > this->current_position ){ this->direction = 1; }else if( this->target_position < this->current_position ){ this->direction = -1; }
+        this->set_speed(int(floor((this->feed_rate/60)*this->steps_per_millimeter)));//Speed in steps per second
+    }else if( this->mode == FOLLOW ){
+        // In non-solo mode, we just follow the stepper module
+        this->current_block = block;
+        this->start_position = this->target_position;
+        this->target_position =  this->start_position + ( this->current_block->millimeters * this->travel_ratio );
+        if( this->target_position > this->current_position ){ this->direction = 1; }else if( this->target_position < this->current_position ){ this->direction = -1; }
+        this->acceleration_tick(0);
+    }
+
+}
+
+// When a block ends, pause the stepping interrupt
+void Extruder::on_block_end(void* argument){
+    Block* block = static_cast<Block*>(argument);
+    this->current_block = NULL;
+}
+
+// Called periodically to change the speed to match acceleration or to match the speed of the robot
+uint32_t Extruder::acceleration_tick(uint32_t dummy){
+
+    // Avoid trying to work when we really shouldn't ( between blocks or re-entry )
+    if( this->current_block == NULL || this->acceleration_lock || this->paused ){ return 0; }
+    this->acceleration_lock = true;
+
+    // In solo mode, we mode independently from the robot
+    if( this->mode == SOLO ){
+        // TODO : Do real acceleration here
+        this->travel_ratio += 0.03;
+        if( this->travel_ratio > 1 ){ this->travel_ratio = 1; }
+        this->set_speed( int(floor(((this->feed_rate/60)*this->steps_per_millimeter)*this->travel_ratio)) );  // Speed in steps per second
+
+        // In follow mode we match the speed of the robot, + eventually advance
+    }else if( this->mode == FOLLOW ){
+        Stepper* stepper = this->kernel->stepper; // Just for convenience
+
+        // Strategy :
+        //   * Find where in the block will the stepper be at the next tick ( if the block will have ended then, don't change speed )
+        //   * Find what position this is for us
+        //   * Find what speed we must go at to be at that position for the next acceleration tick
+        // TODO : This works, but PLEASE PLEASE PLEASE if you know a better way to do it, do it better, I don't find this elegant at all, it's just the best I could think of
+        // UPDATE: Yes, this sucks, I have ideas on how to do it better. If this is really bugging you, open a ticket and I'll make it a priority
+
+        int ticks_forward = 3;
+        // We need to take those values here, and then use those instead of the live values, because using the live values inside the loop can break things ( infinite loops etc ... )
+        double next_stepper_rate = stepper->trapezoid_adjusted_rate;
+        double step_events_completed =   (double(double(stepper->step_events_completed)/double(1<<16)));
+        double position = ( this->current_position - this->start_position ) * this->direction ;
+        double length = fabs( this->start_position - this->target_position );
+        double last_ratio = -1;
+
+        // Do the startegy above, but if it does not work, look a bit further and try again, and again ...
+        while(1){
+
+            // Find the position where we should be at the next tick
+            double next_ratio = double( step_events_completed + ( next_stepper_rate / 60 / ((double(stepper->acceleration_ticks_per_second)/ticks_forward)) ) ) / double( this->current_block->steps_event_count );
+            double next_relative_position = ( length * next_ratio );
+
+            // Advance
+            // TODO: Proper advance configuration
+            double advance = double(next_stepper_rate) * ( 0.00001 * 0.15 ) * 0.4 ;
+            //double advance = 0;
+            next_relative_position += ( advance );
+
+            // TODO : all of those "if->return" is very hacky, we should do the math in a way where most of those don't happen, but that requires doing tons of drawing ...
+            if( last_ratio == next_ratio ){ this->acceleration_lock = false; return 0; }else{ last_ratio = next_ratio; }
+            if( next_ratio == 0 || next_ratio > 1 ){ this->acceleration_lock = false; return 0; }
+            if( ticks_forward > 1000 ){ this->acceleration_lock = false; return 0; } // This is very ugly
+
+            // Hack : We have not looked far enough, we compute how far ahead we must look to get a relevant value
+            if( position > next_relative_position ){
+                double far_back = position - next_relative_position;
+                double far_back_ratio = far_back / length;
+                double move_duration = double( this->current_block->steps_event_count ) / ( double(next_stepper_rate) / 60 ) ;
+                double ticks_in_a_move = floor( stepper->acceleration_ticks_per_second * move_duration +0.5);
+                double ratio_per_tick = 1 / ticks_in_a_move;
+                double ticks_to_equilibrium = ceil(far_back_ratio / ratio_per_tick) + 1;
+                ticks_forward += ticks_to_equilibrium;
+                // Because this is a loop, and we can be interrupted by the stepping interrupt, if that interrupt changes block, the new block may not be solo, and we may get trapped into an infinite loop
+                if( this->mode != FOLLOW ){ this->acceleration_lock = false; return 0; }
+                continue;
+            }
+
+            // Finally, compute the speed to get to that next position
+            double next_absolute_position = this->start_position + ( this->direction * next_relative_position );
+            double steps_to_next_tick = ( next_relative_position - position ) * this->steps_per_millimeter;
+            double speed_to_next_tick = steps_to_next_tick / ( 1 / double(double(this->kernel->stepper->acceleration_ticks_per_second) / ticks_forward) );
+
+            // Change stepping speed
+            this->set_speed( speed_to_next_tick );
+
+            this->acceleration_lock = false;
+            return 0;
+        }
+    }
+
+    this->acceleration_lock = false;
+    return 0;
+}
+
+// Convenience function to set stepping speed
+void Extruder::set_speed( int steps_per_second ){
+
+    if( steps_per_second < 10 ){ steps_per_second = 10; }
+
+    // TODO : Proper limit config value
+    if( steps_per_second > (this->feed_rate*double(this->steps_per_millimeter))/60 ){
+        steps_per_second = (this->feed_rate*double(this->steps_per_millimeter))/60;
+    }
+
+    this->counter_increment = int(floor(double(1<<16)/double(this->kernel->stepper->base_stepping_frequency / steps_per_second)));
+
+}
+
+inline uint32_t Extruder::stepping_tick(uint32_t dummy){
+    if( this->paused ){ return 0; }
+
+    this->step_counter += this->counter_increment;
+    if( this->step_counter > 1<<16 ){
+        this->step_counter -= 1<<16;
+
+        // If we still have steps to do
+        // TODO: Step using the same timer as the robot, and count steps instead of absolute float position
+        if( ( this->current_position < this->target_position && this->direction == 1 ) || ( this->current_position > this->target_position && this->direction == -1 ) ){
+            this->current_position += (double(double(1)/double(this->steps_per_millimeter)))*double(this->direction);
+            this->dir_pin->set((this->direction > 0) ? 1 : 0);
+            this->step_pin->set(1);
+        }else{
+            // Move finished
+            if( this->mode == SOLO && this->current_block != NULL ){
+                // In follow mode, the robot takes and releases the block, in solo mode we do
+                this->current_block->release();
+            }
+        }
+    }
+    return 0;
+}
+
+uint32_t Extruder::reset_step_pin(uint32_t dummy){
+    this->step_pin->set(0);
+    return 0;
+}
diff -r 000000000000 -r 31e91bb0ef3c modules/tools/extruder/Extruder.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/tools/extruder/Extruder.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,74 @@
+/*
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+
+
+#ifndef EXTURDER_MODULE_H
+#define EXTRUDER_MODULE_H
+
+#include "libs/Module.h"
+#include "libs/Kernel.h"
+#include "modules/robot/Block.h"
+
+#define microseconds_per_step_pulse_checksum 42333
+#define extruder_module_enable_checksum      6183
+#define extruder_steps_per_mm_checksum       58088
+#define default_feed_rate_checksum           53183
+#define acceleration_checksum                60356
+
+#define OFF 0
+#define SOLO 1
+#define FOLLOW 2
+
+class Extruder : public Module{
+    public:
+        Extruder();
+        virtual void on_module_loaded();
+        virtual void on_config_reload(void* argument);
+        virtual void on_gcode_execute(void* argument);
+        virtual void on_block_begin(void* argument);
+        virtual void on_block_end(void* argument);
+        virtual void on_play(void* argument);
+        virtual void on_pause(void* argument);
+        void set_speed(int steps_per_second);
+        uint32_t acceleration_tick(uint32_t dummy);
+        uint32_t stepping_tick(uint32_t dummy);
+        uint32_t reset_step_pin(uint32_t dummy);
+
+        Pin*            step_pin;                     // Step pin for the stepper driver
+        Pin*            dir_pin;                      // Dir pin for the stepper driver
+        Pin*            en_pin;
+
+        double          start_position;               // Start point ( in steps ) for the current move
+        double          target_position;              // End point ( in steps ) for the current move
+        double          current_position;             // Current point ( in steps ) for the current move, incremented every time a step is outputed
+        Block*          current_block;                // Current block we are stepping, same as Stepper's one
+        int             microseconds_per_step_pulse;  // Pulse duration for step pulses
+        double          steps_per_millimeter;         // Steps to travel one millimeter
+        double          feed_rate;                    //
+        double          acceleration;                 //
+
+        int             counter_increment;
+        int             step_counter;
+
+        bool            solo_mode;
+        double          travel_ratio;
+        double          travel_distance;
+        bool            absolute_mode;
+
+        int             direction;
+
+        bool            debug;
+        int debug_count;
+
+        char mode;
+        bool acceleration_lock;
+
+        bool paused;
+};
+
+#endif
diff -r 000000000000 -r 31e91bb0ef3c modules/tools/laser/Laser.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/tools/laser/Laser.cpp	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,73 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+#include "libs/Module.h"
+#include "libs/Kernel.h"
+#include "modules/communication/utils/Gcode.h"
+#include "modules/robot/Stepper.h"
+#include "Laser.h"
+#include "libs/nuts_bolts.h"
+
+Laser::Laser(PinName pin) : laser_pin(pin){
+    this->laser_pin.period_us(10);
+}
+
+void Laser::on_module_loaded() {
+    if( !this->kernel->config->value( laser_module_enable_checksum )->by_default(false)->as_bool() ){ return; } 
+    this->register_for_event(ON_GCODE_EXECUTE);
+    this->register_for_event(ON_SPEED_CHANGE);
+    this->register_for_event(ON_PLAY);
+    this->register_for_event(ON_PAUSE);
+    this->register_for_event(ON_BLOCK_BEGIN);
+    this->register_for_event(ON_BLOCK_END);
+}
+
+// Turn laser off laser at the end of a move
+void  Laser::on_block_end(void* argument){
+    this->laser_pin = 0;
+}
+
+// Set laser power at the beginning of a block
+void Laser::on_block_begin(void* argument){
+    this->set_proportional_power();
+}
+
+// When the play/pause button is set to pause, or a module calls the ON_PAUSE event
+void Laser::on_pause(void* argument){
+    this->laser_pin = 0;
+}
+
+// When the play/pause button is set to play, or a module calls the ON_PLAY event
+void Laser::on_play(void* argument){
+    this->set_proportional_power();
+}
+
+// Turn laser on/off depending on received GCodes
+void Laser::on_gcode_execute(void* argument){
+    Gcode* gcode = static_cast<Gcode*>(argument);
+    this->laser_on = false;
+    if( gcode->has_letter('G' )){
+        int code = gcode->get_value('G');
+        if( code == 0 ){                    // G0
+            this->laser_pin = 0;
+            this->laser_on =  false;
+        }else if( code >= 1 && code <= 3 ){ // G1, G2, G3
+            this->laser_on =  true;
+        }
+    }
+}
+
+// We follow the stepper module here, so speed must be proportional
+void Laser::on_speed_change(void* argument){
+    this->set_proportional_power();
+}
+
+void Laser::set_proportional_power(){
+    if( this->laser_on && this->kernel->stepper->current_block ){ 
+        this->laser_pin = double(this->kernel->stepper->trapezoid_adjusted_rate)/double(this->kernel->stepper->current_block->nominal_rate);
+    }
+}
diff -r 000000000000 -r 31e91bb0ef3c modules/tools/laser/Laser.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/tools/laser/Laser.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,51 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+#ifndef LASER_MODULE_H
+#define LASER_MODULE_H
+
+#include "libs/Module.h"
+#include "PwmOut.h" // mbed.h lib
+#include "libs/Kernel.h"
+#include "modules/communication/utils/Gcode.h"
+
+
+#define laser_module_enable_checksum 35529 
+
+class Laser : public Module{
+    public:
+        Laser(PinName pin);
+        virtual void on_module_loaded();
+        virtual void on_block_end(void* argument);
+        virtual void on_block_begin(void* argument);
+        virtual void on_play(void* argument);
+        virtual void on_pause(void* argument);
+        virtual void on_gcode_execute(void* argument);
+        virtual void on_speed_change(void* argument);
+        void set_proportional_power();
+
+        mbed::PwmOut laser_pin;    // PWM output to regulate the laser power
+        bool   laser_on;     // Laser status
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#endif
diff -r 000000000000 -r 31e91bb0ef3c modules/tools/spindle/Spindle.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/tools/spindle/Spindle.cpp	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,81 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+#include "libs/Module.h"
+#include "libs/Kernel.h"
+#include "modules/communication/utils/Gcode.h"
+#include "modules/robot/Stepper.h"
+#include "Spindle.h"
+#include "libs/nuts_bolts.h"
+
+Spindle::Spindle(){
+
+}
+
+void Spindle::on_module_loaded() {
+    if( !this->kernel->config->value( spindle_module_enable_checksum )->by_default(false)->as_bool() ){ return; } 
+
+    // Settings
+    this->on_config_reload(this);
+    
+    this->register_for_event(ON_GCODE_EXECUTE);
+    this->register_for_event(ON_PLAY);
+    this->register_for_event(ON_PAUSE);
+    this->register_for_event(ON_BLOCK_BEGIN);
+    this->register_for_event(ON_BLOCK_END);
+}
+
+
+// Get config
+void Spindle::on_config_reload(void* argument){
+    this->spindle_pin= this->kernel->config->value(spindle_pin_checksum)->by_default("0.4" )->as_pin()->as_output();
+}
+
+// Turn spindle off spindle at the end of a move
+void  Spindle::on_block_end(void* argument){
+    //this->spindle_pin->set(0);
+}
+
+// Set spindle power at the beginning of a block
+void Spindle::on_block_begin(void* argument){
+    //this->set_spindle();
+}
+
+// When the play/pause button is set to pause, or a module calls the ON_PAUSE event
+void Spindle::on_pause(void* argument){
+    this->spindle_pin->set(0);
+}
+
+// When the play/pause button is set to play, or a module calls the ON_PLAY event
+void Spindle::on_play(void* argument){
+    this->set_spindle();
+}
+
+// Turn spindle on/off depending on received GCodes
+void Spindle::on_gcode_execute(void* argument){
+    Gcode* gcode = static_cast<Gcode*>(argument);
+    this->spindle_on = false;
+    if( gcode->has_letter('G' )){
+        int code = gcode->get_value('G');
+        if( code == 0 ){                    // G0
+            this->kernel->serial->printf("off\r\n");
+            this->spindle_pin->set(0);
+            this->spindle_on =  false;
+        }else if( code >= 1 && code <= 3 ){ // G1, G2, G3
+            this->kernel->serial->printf("on\r\n");
+            this->spindle_pin->set(1);
+            this->spindle_on =  true;
+        }
+    }
+}
+
+
+void Spindle::set_spindle(){
+    if( this->spindle_on && this->kernel->stepper->current_block ){ 
+        this->spindle_pin->set(1);
+    }
+}
diff -r 000000000000 -r 31e91bb0ef3c modules/tools/spindle/Spindle.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/tools/spindle/Spindle.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,51 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+#ifndef SPINDLE_MODULE_H
+#define SPINDLE_MODULE_H
+
+#include "libs/Module.h"
+#include "mbed.h"
+#include "libs/Kernel.h"
+#include "modules/communication/utils/Gcode.h"
+ 
+#define spindle_module_enable_checksum 43962 
+#define spindle_pin_checksum      54937
+
+class Spindle : public Module{
+    public:
+        Spindle();
+        virtual void on_module_loaded();
+        virtual void on_config_reload(void* argument);
+        virtual void on_block_end(void* argument);
+        virtual void on_block_begin(void* argument);
+        virtual void on_play(void* argument);
+        virtual void on_pause(void* argument);
+        virtual void on_gcode_execute(void* argument);
+    private:
+        void set_spindle();
+        bool   spindle_on;     // Spindle status
+        Pin* spindle_pin;
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#endif
diff -r 000000000000 -r 31e91bb0ef3c modules/tools/temperaturecontrol/TemperatureControl.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/tools/temperaturecontrol/TemperatureControl.cpp	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,187 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+// TODO : THIS FILE IS LAME, MUST BE MADE MUCH BETTER
+
+#include "libs/Module.h"
+#include "libs/Kernel.h"
+#include <math.h>
+#include "TemperatureControl.h"
+#include "libs/Pin.h"
+
+TemperatureControl::TemperatureControl(){}
+
+TemperatureControl::TemperatureControl(uint16_t name){
+    this->name_checksum = name;
+    this->error_count = 0; 
+}
+
+void TemperatureControl::on_module_loaded(){
+    
+    // We start not desiring any temp
+    this->desired_adc_value = UNDEFINED;
+
+    // Settings
+    this->on_config_reload(this);
+
+    this->acceleration_factor = 10;
+
+    this->kernel->slow_ticker->attach( 20, this, &TemperatureControl::thermistor_read_tick );
+
+    // Register for events
+    this->register_for_event(ON_GCODE_EXECUTE); 
+    this->register_for_event(ON_MAIN_LOOP); 
+
+}
+
+void TemperatureControl::on_main_loop(void* argument){ }
+
+// Get configuration from the config file
+void TemperatureControl::on_config_reload(void* argument){
+
+    this->readings_per_second = this->kernel->config->value(temperature_control_checksum, this->name_checksum, readings_per_second_checksum)->by_default(5)->as_number();
+
+    // Values are here : http://reprap.org/wiki/Thermistor
+    this->r0   = 100000;
+    this->t0   = 25;
+    this->beta = 4066;
+    this->vadc = 3.3;
+    this->vcc  = 3.3;
+    this->r1   = 0;
+    this->r2   = 4700;
+
+    // Preset values for various common types of thermistors
+    ConfigValue* thermistor = this->kernel->config->value(temperature_control_checksum, this->name_checksum, thermistor_checksum);    
+    if(       thermistor->value.compare("EPCOS100K"    ) == 0 ){ // Default
+    }else if( thermistor->value.compare("RRRF100K"     ) == 0 ){ this->beta = 3960;
+    }else if( thermistor->value.compare("RRRF10K"      ) == 0 ){ this->beta = 3964; this->r0 = 10000; this->r1 = 680; this->r2 = 1600;
+    }else if( thermistor->value.compare("Honeywell100K") == 0 ){ this->beta = 3974;
+    }else if( thermistor->value.compare("Semitec"      ) == 0 ){ this->beta = 4267; }
+
+    // Preset values are overriden by specified values
+    this->r0 =                  this->kernel->config->value(temperature_control_checksum, this->name_checksum, r0_checksum  )->by_default(100000)->as_number();               // Stated resistance eg. 100K
+    this->t0 =                  this->kernel->config->value(temperature_control_checksum, this->name_checksum, t0_checksum  )->by_default(25    )->as_number() + 273.15;      // Temperature at stated resistance, eg. 25C
+    this->beta =                this->kernel->config->value(temperature_control_checksum, this->name_checksum, beta_checksum)->by_default(4066  )->as_number();               // Thermistor beta rating. See http://reprap.org/bin/view/Main/MeasuringThermistorBeta
+    this->vadc =                this->kernel->config->value(temperature_control_checksum, this->name_checksum, vadc_checksum)->by_default(3.3   )->as_number();               // ADC Reference
+    this->vcc  =                this->kernel->config->value(temperature_control_checksum, this->name_checksum, vcc_checksum )->by_default(3.3   )->as_number();               // Supply voltage to potential divider
+    this->r1 =                  this->kernel->config->value(temperature_control_checksum, this->name_checksum, r1_checksum  )->by_default(0     )->as_number();
+    this->r2 =                  this->kernel->config->value(temperature_control_checksum, this->name_checksum, r2_checksum  )->by_default(4700  )->as_number();
+    
+    // Thermistor math 
+    this->k = this->r0 * exp( -this->beta / this->t0 );
+    if( r1 > 0 ){ this->vs = r1 * this->vcc / ( r1 + r2 ); this->rs = r1 * r2 / ( r1 + r2 ); }else{ this->vs = this->vcc; this->rs = r2; } 
+
+    // Thermistor pin for ADC readings
+    this->thermistor_pin = this->kernel->config->value(temperature_control_checksum, this->name_checksum, thermistor_pin_checksum )->required()->as_pin();
+    this->kernel->adc->enable_pin(this->thermistor_pin);
+
+    // Heater pin
+    this->heater_pin     =  this->kernel->config->value(temperature_control_checksum, this->name_checksum, heater_pin_checksum)->required()->as_pin()->as_output();
+    this->heater_pin->set(0);
+
+}
+
+void TemperatureControl::on_gcode_execute(void* argument){
+    Gcode* gcode = static_cast<Gcode*>(argument);
+
+    // Set temperature without waiting
+    if( gcode->has_letter('M') && gcode->get_value('M') == 104 && gcode->has_letter('S') ){
+        this->set_desired_temperature(gcode->get_value('S')); 
+    } 
+
+    // Set temperature and wait
+    if( gcode->has_letter('M') && gcode->get_value('M') == 109 && gcode->has_letter('S') ){
+        this->set_desired_temperature(gcode->get_value('S'));
+        
+        // Pause 
+        this->kernel->pauser->take(); 
+        this->waiting = true; 
+    
+    } 
+
+    // Get temperature
+    if( gcode->has_letter('M') && gcode->get_value('M') == 105 ){
+        gcode->stream->printf("get temperature: %f current:%f target:%f \r\n", this->get_temperature(), this->new_thermistor_reading(), this->desired_adc_value );
+    } 
+}
+
+void TemperatureControl::set_desired_temperature(double desired_temperature){
+    this->desired_adc_value = this->temperature_to_adc_value(desired_temperature);
+}
+
+double TemperatureControl::get_temperature(){
+    double temp = this->new_thermistor_reading() ;
+    return this->adc_value_to_temperature( this->new_thermistor_reading() );
+}
+
+double TemperatureControl::adc_value_to_temperature(double adc_value){
+    double v = adc_value * this->vadc;            // Convert from 0-1 adc value to voltage
+    double r = this->rs * v / ( this->vs - v );   // Resistance of thermistor
+    return ( this->beta / log( r / this->k )) - 273.15;
+}
+
+double TemperatureControl::temperature_to_adc_value(double temperature){
+    double r = this->r0 * exp( this->beta * ( 1 / (temperature + 273.15) -1 / this->t0 ) ); // Resistance of the thermistor 
+    double v = this->vs * r / ( this->rs + r );                                             // Voltage at the potential divider
+    return v / this->vadc * 1.00000;                                               // The ADC reading
+}
+
+uint32_t TemperatureControl::thermistor_read_tick(uint32_t dummy){
+    if( this->desired_adc_value != UNDEFINED ){
+        if( this->new_thermistor_reading() > this->desired_adc_value ){
+            this->heater_pin->set(1); 
+        }else{
+            this->heater_pin->set(0); 
+            if( this->waiting ){ 
+                this->kernel->pauser->release();
+                this->waiting = false; 
+            }
+        }
+    }
+}
+
+double TemperatureControl::new_thermistor_reading(){
+   
+    double new_reading = double( double(this->kernel->adc->read(this->thermistor_pin) / double(1<<12) ) );
+
+    if( this->queue.size() < 15 ){
+        this->queue.push_back( new_reading );
+        return new_reading;
+    }else{
+        double current_temp = this->average_adc_reading();
+        double error = fabs(new_reading - current_temp); 
+        if( error < 0.1 ){
+            this->error_count = 0;
+            double test;
+            this->queue.pop_front(test); 
+            this->queue.push_back( new_reading );
+        }else{
+            this->error_count++;
+            if( this->error_count > 4 ){
+                double test;
+                this->queue.pop_front(test); 
+            }
+        } 
+        return current_temp;
+    }
+}
+
+
+double TemperatureControl::average_adc_reading(){
+    double total;
+    int j=0;
+    int reading_index = this->queue.head;
+    while( reading_index != this->queue.tail ){
+        j++;
+        total += this->queue.buffer[reading_index];
+        reading_index = this->queue.next_block_index( reading_index );
+    }
+    return total / j;
+}
+
+
+
diff -r 000000000000 -r 31e91bb0ef3c modules/tools/temperaturecontrol/TemperatureControl.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/tools/temperaturecontrol/TemperatureControl.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,77 @@
+/*  
+      this file is part of smoothie (http://smoothieware.org/). the motion control part is heavily based on grbl (https://github.com/simen/grbl).
+      smoothie is free software: you can redistribute it and/or modify it under the terms of the gnu general public license as published by the free software foundation, either version 3 of the license, or (at your option) any later version.
+      smoothie is distributed in the hope that it will be useful, but without any warranty; without even the implied warranty of merchantability or fitness for a particular purpose. see the gnu general public license for more details.
+      you should have received a copy of the gnu general public license along with smoothie. if not, see <http://www.gnu.org/licenses/>. 
+*/
+
+#ifndef temperaturecontrol_h
+#define temperaturecontrol_h
+
+#include "libs/Pin.h"
+#include <math.h>
+
+#define UNDEFINED -1
+
+#define thermistor_checksum                41045
+#define r0_checksum                        5538
+#define readings_per_second_checksum       18645 
+#define t0_checksum                        6564
+#define beta_checksum                      1181
+#define vadc_checksum                      10911
+#define vcc_checksum                       36157
+#define r1_checksum                        5795
+#define r2_checksum                        6052
+#define temperature_control_checksum       44054
+#define thermistor_pin_checksum            1788 
+#define heater_pin_checksum                35619 
+
+class TemperatureControl : public Module {
+    public:
+        TemperatureControl();
+        TemperatureControl(uint16_t name);
+        
+        virtual void on_module_loaded();
+        virtual void on_main_loop(void* argument);
+        virtual void on_gcode_execute(void* argument);
+        virtual void on_config_reload(void* argument);
+        void set_desired_temperature(double desired_temperature);
+        double get_temperature();
+        double adc_value_to_temperature(double adc_value);
+        double temperature_to_adc_value(double temperature);
+        uint32_t thermistor_read_tick(uint32_t dummy);
+        double new_thermistor_reading();
+        double average_adc_reading();
+        
+        double    desired_adc_value;
+        double    tail_adc_value;
+        double    head_adc_value;
+
+        // Thermistor computation settings
+        double r0;
+        double t0;
+        double r1;
+        double r2;
+        double beta;
+        double vadc;
+        double vcc;
+        double k;
+        double vs;
+        double rs;
+        
+        double acceleration_factor;
+        double readings_per_second;
+
+        RingBuffer<double,16> queue;  // Queue of Blocks
+        int error_count;
+
+        uint16_t name_checksum;
+
+        Pin* thermistor_pin;
+        Pin* heater_pin;
+    
+        bool waiting;
+
+};
+
+#endif
diff -r 000000000000 -r 31e91bb0ef3c modules/tools/temperaturecontrol/TemperatureControlPool.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/tools/temperaturecontrol/TemperatureControlPool.cpp	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,37 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+#include "libs/Module.h"
+#include "libs/Kernel.h"
+#include <math.h>
+using namespace std;
+#include <vector>
+#include "TemperatureControlPool.h"
+#include "TemperatureControl.h"
+
+TemperatureControlPool::TemperatureControlPool(){}
+
+void TemperatureControlPool::on_module_loaded(){
+
+    vector<uint16_t> modules;
+    this->kernel->config->get_module_list( &modules, temperature_control_checksum );
+
+    for( int i = 0; i < modules.size(); i++ ){
+        // If module is enabled
+        if( this->kernel->config->value(temperature_control_checksum, modules[i], enable_checksum )->as_bool() == true ){
+            TemperatureControl* controller = new TemperatureControl(modules[i]);
+            this->kernel->add_module(controller); 
+            this->controllers.push_back( controller );
+        }
+    }
+
+}
+
+
+
+
+
diff -r 000000000000 -r 31e91bb0ef3c modules/tools/temperaturecontrol/TemperatureControlPool.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/tools/temperaturecontrol/TemperatureControlPool.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,30 @@
+/*  
+      this file is part of smoothie (http://smoothieware.org/). the motion control part is heavily based on grbl (https://github.com/simen/grbl).
+      smoothie is free software: you can redistribute it and/or modify it under the terms of the gnu general public license as published by the free software foundation, either version 3 of the license, or (at your option) any later version.
+      smoothie is distributed in the hope that it will be useful, but without any warranty; without even the implied warranty of merchantability or fitness for a particular purpose. see the gnu general public license for more details.
+      you should have received a copy of the gnu general public license along with smoothie. if not, see <http://www.gnu.org/licenses/>. 
+*/
+
+#ifndef TEMPERATURECONTROLPOOL_H
+#define TEMPERATURECONTROLPOOL_H
+
+#include "TemperatureControl.h"
+#include <math.h>
+using namespace std;
+#include <vector>
+
+#define temperature_control_checksum 44054
+#define enable_checksum              29545
+
+class TemperatureControlPool : public Module {
+    public:
+        TemperatureControlPool();
+
+        virtual void on_module_loaded();
+
+        vector<TemperatureControl*> controllers;
+};
+
+
+
+#endif
diff -r 000000000000 -r 31e91bb0ef3c modules/utils/configurator/Configurator.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/utils/configurator/Configurator.cpp	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,128 @@
+/*
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+
+#include "libs/Kernel.h"
+#include "Configurator.h"
+#include "libs/nuts_bolts.h"
+#include "libs/utils.h"
+#include "libs/SerialMessage.h"
+#include "libs/StreamOutput.h"
+
+
+void Configurator::on_module_loaded(){
+    this->register_for_event(ON_CONSOLE_LINE_RECEIVED);
+//    this->register_for_event(ON_GCODE_EXECUTE);
+//    this->register_for_event(ON_MAIN_LOOP);
+}
+
+// When a new line is received, check if it is a command, and if it is, act upon it
+void Configurator::on_console_line_received( void* argument ){
+    SerialMessage new_message = *static_cast<SerialMessage*>(argument);
+    string possible_command = new_message.message;
+
+    // We don't compare to a string but to a checksum of that string, this saves some space in flash memory
+    uint16_t check_sum = get_checksum( possible_command.substr(0,possible_command.find_first_of(" \r\n")) );  // todo: put this method somewhere more convenient
+
+    // Act depending on command
+    switch( check_sum ){
+        case config_get_command_checksum: this->config_get_command(  get_arguments(possible_command), new_message.stream ); break;
+        case config_set_command_checksum: this->config_set_command(  get_arguments(possible_command), new_message.stream ); break;
+        case config_load_command_checksum: this->config_load_command(  get_arguments(possible_command), new_message.stream ); break;
+    }
+}
+
+// Process and respond to eeprom gcodes (M50x)
+void Configurator::on_gcode_execute(void* argument){
+    Gcode* gcode = static_cast<Gcode*>(argument);
+    if( gcode->has_letter('G') ){
+        int code = gcode->get_value('G');
+        switch( code ){
+        }
+    }
+    else if( gcode->has_letter('M') ){
+        int code = gcode->get_value('M');
+        switch( code ){
+        }
+    }
+}
+
+void Configurator::on_main_loop(void* argument){}
+
+// Output a ConfigValue from the specified ConfigSource to the stream
+void Configurator::config_get_command( string parameters, StreamOutput* stream ){
+    string source = shift_parameter(parameters);
+    string setting = shift_parameter(parameters);
+    if (setting == "") { // output live setting
+        setting = source;
+        source = "";
+        vector<uint16_t> setting_checksums = get_checksums( setting );
+        ConfigValue* cv = this->kernel->config->value(setting_checksums);
+        string value = "";
+        if(cv->found){ value = cv->as_string(); }
+        stream->printf( "live: %s is set to %s\r\n", setting.c_str(), value.c_str() );
+    } else { // output setting from specified source
+        uint16_t source_checksum = get_checksum( source );
+        vector<uint16_t> setting_checksums = get_checksums( setting );
+        for(int i=0; i < this->kernel->config->config_sources.size(); i++){
+            if( this->kernel->config->config_sources[i]->is_named(source_checksum) ){
+                string value = this->kernel->config->config_sources[i]->read(setting_checksums);
+                stream->printf( "%s: %s is set to %s\r\n", source.c_str(), setting.c_str(), value.c_str() );
+                break;
+            }
+        }
+    }
+}
+
+// Write the specified setting to the specified ConfigSource
+void Configurator::config_set_command( string parameters, StreamOutput* stream ){
+    string source = shift_parameter(parameters);
+    string setting = shift_parameter(parameters);
+    string value = shift_parameter(parameters);
+    if (value == "") {
+        value = setting;
+        setting = source;
+        source = "";
+        this->kernel->config->set_string(setting, value);
+        stream->printf( "live: %s has been set to %s\r\n", setting.c_str(), value.c_str() );
+    } else {
+        uint16_t source_checksum = get_checksum(source);
+        for(int i=0; i < this->kernel->config->config_sources.size(); i++){
+            if( this->kernel->config->config_sources[i]->is_named(source_checksum) ){
+                this->kernel->config->config_sources[i]->write(setting, value);
+                stream->printf( "%s: %s has been set to %s\r\n", source.c_str(), setting.c_str(), value.c_str() );
+                break;
+            }
+        }
+    }
+}
+
+// Reload config values from the specified ConfigSource
+void Configurator::config_load_command( string parameters, StreamOutput* stream ){
+    string source = shift_parameter(parameters);
+    if(source == ""){
+        this->kernel->config->config_cache_load();
+        this->kernel->call_event(ON_CONFIG_RELOAD);
+        stream->printf( "Reloaded settings\r\n" );
+    } else if(file_exists(source)){
+        FileConfigSource fcs(source);
+        fcs.transfer_values_to_cache(&this->kernel->config->config_cache);
+        this->kernel->call_event(ON_CONFIG_RELOAD);
+        stream->printf( "Loaded settings from %s\r\n", source.c_str() );
+    } else {
+        uint16_t source_checksum = get_checksum(source);
+        for(int i=0; i < this->kernel->config->config_sources.size(); i++){
+            if( this->kernel->config->config_sources[i]->is_named(source_checksum) ){
+                this->kernel->config->config_sources[i]->transfer_values_to_cache(&this->kernel->config->config_cache);
+                this->kernel->call_event(ON_CONFIG_RELOAD);
+                stream->printf( "Loaded settings from %s\r\n", source.c_str() );
+                break;
+            }
+        }
+    }
+}
+
diff -r 000000000000 -r 31e91bb0ef3c modules/utils/configurator/Configurator.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/utils/configurator/Configurator.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,42 @@
+/*
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+
+#ifndef configurator_h
+#define configurator_h
+
+#include "libs/Kernel.h"
+#include "libs/nuts_bolts.h"
+#include "libs/utils.h"
+#include "libs/StreamOutput.h"
+
+
+#define CONF_NONE       0
+#define CONF_ROM        1
+#define CONF_SD         2
+#define CONF_EEPROM     3
+
+#define config_get_command_checksum        46310    // "config-get"
+#define config_set_command_checksum        55538    // "config-set"
+#define config_load_command_checksum       3143     // "config-load"
+
+class Configurator : public Module {
+    public:
+        Configurator(){}
+
+        virtual void on_module_loaded();
+        virtual void on_console_line_received( void* argument );
+        virtual void on_gcode_execute( void* argument );
+        virtual void on_main_loop( void* argument );
+
+        void config_get_command( string parameters, StreamOutput* stream ); 
+        void config_set_command( string parameters, StreamOutput* stream ); 
+        void config_load_command(string parameters, StreamOutput* stream );
+};
+
+
+#endif // configurator_h
diff -r 000000000000 -r 31e91bb0ef3c modules/utils/currentcontrol/CurrentControl.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/utils/currentcontrol/CurrentControl.cpp	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,26 @@
+#include "libs/Kernel.h"
+#include "CurrentControl.h"
+#include "libs/nuts_bolts.h"
+#include "libs/utils.h"
+#include <string>
+using namespace std;
+
+CurrentControl::CurrentControl(){}
+
+void CurrentControl::on_module_loaded(){
+    if( !this->kernel->config->value( currentcontrol_module_enable_checksum )->by_default(false)->as_bool() ){ return; } 
+
+    // Get configuration
+    this->alpha_current =           this->kernel->config->value(alpha_current_checksum  )->by_default(0.8)->as_number(); 
+    this->beta_current  =           this->kernel->config->value(beta_current_checksum   )->by_default(0.8)->as_number(); 
+    this->gamma_current =           this->kernel->config->value(gamma_current_checksum  )->by_default(0.8)->as_number(); 
+    this->delta_current =           this->kernel->config->value(delta_current_checksum  )->by_default(0.8)->as_number();
+
+    this->kernel->digipot->set_current(0, this->alpha_current);
+    this->kernel->digipot->set_current(1, this->beta_current );
+    this->kernel->digipot->set_current(2, this->gamma_current);
+    this->kernel->digipot->set_current(3, this->delta_current);
+
+}
+
+
diff -r 000000000000 -r 31e91bb0ef3c modules/utils/currentcontrol/CurrentControl.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/utils/currentcontrol/CurrentControl.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,31 @@
+#ifndef CURRENTCONTROL_H
+#define CURRENTCONTROL_H
+
+#include "libs/Kernel.h"
+#include "libs/nuts_bolts.h"
+#include "libs/utils.h"
+#include "libs/Pin.h"
+
+#define alpha_current_checksum   22381 
+#define beta_current_checksum    60163 
+#define gamma_current_checksum   12906 
+#define delta_current_checksum   30321
+#define currentcontrol_module_enable_checksum 38842
+
+class CurrentControl : public Module {
+    public:
+        CurrentControl();
+       
+        virtual void on_module_loaded();
+       
+        double alpha_current;
+        double beta_current;
+        double gamma_current;
+        double delta_current; 
+};
+
+
+
+
+
+#endif
diff -r 000000000000 -r 31e91bb0ef3c modules/utils/pausebutton/PauseButton.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/utils/pausebutton/PauseButton.cpp	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,48 @@
+#include "libs/Kernel.h"
+#include "PauseButton.h"
+#include "libs/nuts_bolts.h"
+#include "libs/utils.h"
+#include <string>
+using namespace std;
+
+PauseButton::PauseButton(){}
+
+void PauseButton::on_module_loaded(){
+    this->button_state = true;
+    this->play_state   = true;
+    this->register_for_event(ON_PLAY);
+    this->register_for_event(ON_PAUSE);
+
+    this->button     =  this->kernel->config->value( pause_button_pin_checksum )->by_default("2.12")->as_pin()->as_input();
+    this->led        =  this->kernel->config->value( pause_led_pin_checksum    )->by_default("4.28")->as_pin()->as_output();
+
+    this->kernel->slow_ticker->attach( 100, this, &PauseButton::button_tick );
+}
+
+//TODO: Make this use InterruptIn
+//Check the state of the button and act accordingly
+uint32_t PauseButton::button_tick(uint32_t dummy){
+    // If button changed 
+    if(this->button_state != this->button->get()){ 
+        this->button_state = this->button->get();
+        // If button pressed 
+        if( this->button_state ){
+            if( this->play_state ){
+                this->play_state = false;
+                this->kernel->pauser->take(); 
+            }else{
+                this->play_state = true;
+                this->kernel->pauser->release(); 
+            } 
+        } 
+    }
+}
+
+void PauseButton::on_play( void* argument ){
+    this->led->set(0);
+}
+
+void PauseButton::on_pause( void* argument ){
+    this->led->set(1);
+}
+
diff -r 000000000000 -r 31e91bb0ef3c modules/utils/pausebutton/PauseButton.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/utils/pausebutton/PauseButton.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,37 @@
+#ifndef PAUSEBUTTON_H
+#define PAUSEBUTTON_H
+
+#include "libs/Kernel.h"
+#include "libs/nuts_bolts.h"
+#include "libs/utils.h"
+#include "libs/Pin.h"
+
+#define pause_button_pin_checksum 32709
+#define pause_led_pin_checksum    48477
+
+class PauseButton : public Module {
+    public:
+        PauseButton();
+       
+        virtual void on_module_loaded();
+        uint32_t button_tick(uint32_t dummy);
+        virtual void on_play( void* argument );
+        virtual void on_pause( void* argument );
+        
+        Pin*       button;
+        Pin*       led; 
+        bool       button_state;
+        bool       play_state;
+};
+
+
+
+
+
+
+
+
+
+
+
+#endif
diff -r 000000000000 -r 31e91bb0ef3c modules/utils/simpleshell/SimpleShell.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/utils/simpleshell/SimpleShell.cpp	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,162 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+
+#include "libs/Kernel.h"
+#include "SimpleShell.h"
+#include "libs/nuts_bolts.h"
+#include "libs/utils.h"
+#include "libs/SerialMessage.h"
+#include "libs/StreamOutput.h"
+#include "modules/robot/Player.h"
+
+
+void SimpleShell::on_module_loaded(){
+    this->current_path = "/";
+    this->playing_file = false;
+    this->register_for_event(ON_CONSOLE_LINE_RECEIVED);
+    this->register_for_event(ON_MAIN_LOOP);
+}
+
+// When a new line is received, check if it is a command, and if it is, act upon it
+void SimpleShell::on_console_line_received( void* argument ){
+    SerialMessage new_message = *static_cast<SerialMessage*>(argument);
+    string possible_command = new_message.message;
+
+    // We don't compare to a string but to a checksum of that string, this saves some space in flash memory
+    unsigned short check_sum = get_checksum( possible_command.substr(0,possible_command.find_first_of(" \r\n")) );  // todo: put this method somewhere more convenient
+
+    // Act depending on command
+    switch( check_sum ){
+        case ls_command_checksum      : this->ls_command(  get_arguments(possible_command), new_message.stream ); break;
+        case cd_command_checksum      : this->cd_command(  get_arguments(possible_command), new_message.stream ); break;
+        case pwd_command_checksum     : this->pwd_command( get_arguments(possible_command), new_message.stream ); break;
+        case cat_command_checksum     : this->cat_command( get_arguments(possible_command), new_message.stream ); break;
+        case play_command_checksum    : this->play_command(get_arguments(possible_command), new_message.stream ); break; 
+        case reset_command_checksum   : this->reset_command(get_arguments(possible_command),new_message.stream ); break;
+    }
+}
+
+// Convert a path indication ( absolute or relative ) into a path ( absolute )
+string SimpleShell::absolute_from_relative( string path ){
+    if( path[0] == '/' ){ return path; }
+    if( path[0] == '.' ){ return this->current_path; } 
+    return this->current_path + path;
+}
+
+// Act upon an ls command
+// Convert the first parameter into an absolute path, then list the files in that path
+void SimpleShell::ls_command( string parameters, StreamOutput* stream ){
+    string folder = this->absolute_from_relative( parameters );
+    DIR* d;
+    struct dirent* p;
+    d = opendir(folder.c_str());
+    if(d != NULL) {
+        while((p = readdir(d)) != NULL) { stream->printf("%s\r\n", lc(string(p->d_name)).c_str()); }
+    } else {
+        stream->printf("Could not open directory %s \r\n", folder.c_str());
+    }
+}
+
+// Change current absolute path to provided path
+void SimpleShell::cd_command( string parameters, StreamOutput* stream ){
+    string folder = this->absolute_from_relative( parameters );
+    if( folder[folder.length()-1] != '/' ){ folder += "/"; }
+    DIR *d;
+    struct dirent *p;
+    d = opendir(folder.c_str());
+    if(d == NULL) { 
+        stream->printf("Could not open directory %s \r\n", folder.c_str() ); 
+    }else{
+        this->current_path = folder;
+    }
+}
+
+// Responds with the present working directory
+void SimpleShell::pwd_command( string parameters, StreamOutput* stream ){
+    stream->printf("%s\r\n", this->current_path.c_str());
+}
+
+// Output the contents of a file, first parameter is the filename, second is the limit ( in number of lines to output )
+void SimpleShell::cat_command( string parameters, StreamOutput* stream ){
+    
+    // Get parameters ( filename and line limit ) 
+    string filename          = this->absolute_from_relative(shift_parameter( parameters ));
+    string limit_paramater   = shift_parameter( parameters );
+    int limit = -1;
+    if( limit_paramater != "" ){ limit = int(atof(limit_paramater.c_str())); }
+   
+    // Open file 
+    FILE *lp = fopen(filename.c_str(), "r");
+    if(lp == NULL) {
+        stream->printf("File not found: %s\r\n", filename.c_str());
+        return;
+    }
+    string buffer;
+    int c;
+    int newlines = 0; 
+    
+    // Print each line of the file
+    while ((c = fgetc (lp)) != EOF){
+        buffer.append((char *)&c, 1);
+        if( char(c) == '\n' ){
+            newlines++;
+            stream->printf("%s", buffer.c_str());
+            buffer.clear();
+        }
+        if( newlines == limit ){ break; }
+    }; 
+    fclose(lp);
+
+}
+
+// Play a gcode file by considering each line as if it was received on the serial console
+void SimpleShell::play_command( string parameters, StreamOutput* stream ){
+    // Get filename
+    string filename          = this->absolute_from_relative(shift_parameter( parameters ));
+    this->current_file_handler = fopen( filename.c_str(), "r");
+    if(this->current_file_handler == NULL)
+    {
+        stream->printf("File not found: %s\r\n", filename.c_str());
+        return;
+    }
+    this->playing_file = true;
+    this->current_stream = stream;
+}
+
+// Reset the system
+void SimpleShell::reset_command( string parameters, StreamOutput* stream){
+    stream->printf("Smoothie out. Peace.\r\n");
+    system_reset();
+}
+
+void SimpleShell::on_main_loop(void* argument){
+
+    if( this->playing_file ){ 
+        string buffer;
+        int c;
+        // Print each line of the file
+        while ((c = fgetc(this->current_file_handler)) != EOF){
+            if (c == '\n'){
+                this->current_stream->printf("%s\n", buffer.c_str());
+                struct SerialMessage message; 
+                message.message = buffer;
+                message.stream = this->current_stream;
+                // wait for the queue to have enough room that a serial message could still be received before sending
+                this->kernel->player->wait_for_queue(2);
+                this->kernel->call_event(ON_CONSOLE_LINE_RECEIVED, &message); 
+                buffer.clear();
+                return;
+            }else{
+                buffer += c;
+            }
+        }; 
+
+        fclose(this->current_file_handler);
+        this->playing_file = false;
+    }
+}
diff -r 000000000000 -r 31e91bb0ef3c modules/utils/simpleshell/SimpleShell.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/utils/simpleshell/SimpleShell.h	Tue Jul 31 21:11:18 2012 +0000
@@ -0,0 +1,47 @@
+/*  
+      This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
+      Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+      Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+      You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 
+*/
+
+
+#ifndef simpleshell_h
+#define simpleshell_h
+
+#include "libs/Kernel.h"
+#include "libs/nuts_bolts.h"
+#include "libs/utils.h"
+#include "libs/StreamOutput.h"
+
+
+#define ls_command_checksum      19679 
+#define cd_command_checksum      11207
+#define pwd_command_checksum     42060
+#define cat_command_checksum     24889
+#define play_command_checksum    17335
+#define reset_command_checksum   27429
+
+class SimpleShell : public Module {
+    public: 
+        SimpleShell(){}
+
+        virtual void on_module_loaded();
+        virtual void on_console_line_received( void* argument );
+        virtual void on_main_loop( void* argument ); 
+        string absolute_from_relative( string path );
+        void ls_command(   string parameters, StreamOutput* stream );
+        void cd_command(   string parameters, StreamOutput* stream );
+        void pwd_command(  string parameters, StreamOutput* stream );
+        void cat_command(  string parameters, StreamOutput* stream );
+        void play_command( string parameters, StreamOutput* stream );
+        void reset_command(string parameters, StreamOutput* stream );
+
+        string current_path;
+        bool playing_file;
+        StreamOutput* current_stream;
+        FILE* current_file_handler;
+};
+
+
+#endif