diff --git a/OncillaMotordriver.X/nbproject/configurations.xml b/OncillaMotordriver.X/nbproject/configurations.xml
index d0b98bc..23f587f 100644
--- a/OncillaMotordriver.X/nbproject/configurations.xml
+++ b/OncillaMotordriver.X/nbproject/configurations.xml
@@ -1,224 +1,230 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <configurationDescriptor version="62">
   <logicalFolder name="root" displayName="root" projectFiles="true">
     <logicalFolder name="HeaderFiles"
                    displayName="Header Files"
                    projectFiles="true">
       <itemPath>../src/config.h</itemPath>
       <itemPath>../src/magnetic_encoder.h</itemPath>
       <itemPath>../src/mdv_control_modes.h</itemPath>
       <itemPath>../src/mdv_internal.h</itemPath>
       <itemPath>../src/mdv_speed_pid.h</itemPath>
       <itemPath>../src/misc_math.h</itemPath>
       <itemPath>../src/motordriver.h</itemPath>
       <itemPath>../src/pindefs.h</itemPath>
       <itemPath>../src/pwm.h</itemPath>
       <itemPath>../src/sbcp_mdv.h</itemPath>
       <itemPath>../src/timer.h</itemPath>
       <itemPath>../src/load_cell.h</itemPath>
+      <itemPath>../src/cos_table.h</itemPath>
+      <itemPath>../src/ring-buffer.h</itemPath>
     </logicalFolder>
     <logicalFolder name="LinkerScript"
                    displayName="Linker Files"
                    projectFiles="true">
     </logicalFolder>
     <logicalFolder name="SourceFiles"
                    displayName="Source Files"
                    projectFiles="true">
       <itemPath>../src/magnetic_encoder.c</itemPath>
       <itemPath>../src/main.c</itemPath>
       <itemPath>../src/mdv_control_modes.c</itemPath>
       <itemPath>../src/mdv_internal.c</itemPath>
       <itemPath>../src/mdv_speed_pid.c</itemPath>
       <itemPath>../src/motordriver.c</itemPath>
       <itemPath>../src/pindefs.c</itemPath>
       <itemPath>../src/pwm.c</itemPath>
       <itemPath>../src/sbcp_mdv.c</itemPath>
       <itemPath>../src/timer.c</itemPath>
       <itemPath>../src/load_cell.c</itemPath>
+      <itemPath>../src/cos_table.c</itemPath>
+      <itemPath>../src/ring-buffer.c</itemPath>
     </logicalFolder>
     <logicalFolder name="ExternalFiles"
                    displayName="Important Files"
                    projectFiles="false">
       <itemPath>Makefile</itemPath>
     </logicalFolder>
   </logicalFolder>
   <sourceRootList>
     <Elem>../src</Elem>
   </sourceRootList>
   <projectmakefile>Makefile</projectmakefile>
   <confs>
     <conf name="default" type="2">
       <toolsSet>
         <developmentServer>localhost</developmentServer>
         <targetDevice>dsPIC33FJ128MC804</targetDevice>
         <targetHeader></targetHeader>
         <targetPluginBoard></targetPluginBoard>
         <platformTool>PICkit3PlatformTool</platformTool>
         <languageToolchain>XC16</languageToolchain>
         <languageToolchainVersion>1.11</languageToolchainVersion>
         <platform>2</platform>
       </toolsSet>
       <compileType>
         <linkerTool>
           <linkerLibItems>
-            <linkerLibFileItem>../../sbcp-uc/libsbcp-uc.X/dist/128MC804_MDV/production/libsbcp-uc.X.a</linkerLibFileItem>
+            <linkerLibFileItem>../../../sbcp-uc/libsbcp-uc.X/dist/128MC804_MDV/production/libsbcp-uc.X.a</linkerLibFileItem>
           </linkerLibItems>
         </linkerTool>
         <loading>
           <useAlternateLoadableFile>false</useAlternateLoadableFile>
           <alternateLoadableFile></alternateLoadableFile>
         </loading>
       </compileType>
       <makeCustomizationType>
         <makeCustomizationPreStepEnabled>false</makeCustomizationPreStepEnabled>
         <makeCustomizationPreStep></makeCustomizationPreStep>
         <makeCustomizationPostStepEnabled>false</makeCustomizationPostStepEnabled>
         <makeCustomizationPostStep></makeCustomizationPostStep>
         <makeCustomizationPutChecksumInUserID>false</makeCustomizationPutChecksumInUserID>
         <makeCustomizationEnableLongLines>false</makeCustomizationEnableLongLines>
         <makeCustomizationNormalizeHexFile>false</makeCustomizationNormalizeHexFile>
       </makeCustomizationType>
       <C30>
         <property key="code-model" value="default"/>
         <property key="const-model" value="default"/>
         <property key="data-model" value="default"/>
         <property key="enable-all-warnings" value="true"/>
         <property key="enable-ansi-std" value="false"/>
         <property key="enable-ansi-warnings" value="false"/>
         <property key="enable-fatal-warnings" value="true"/>
         <property key="enable-large-arrays" value="false"/>
         <property key="enable-omit-frame-pointer" value="false"/>
         <property key="enable-procedural-abstraction" value="false"/>
         <property key="enable-short-double" value="false"/>
         <property key="enable-symbols" value="true"/>
         <property key="enable-unroll-loops" value="false"/>
-        <property key="extra-include-directories" value="../../sbcp-uc/include"/>
+        <property key="extra-include-directories" value="../../../sbcp-uc/include"/>
         <property key="isolate-each-function" value="false"/>
+        <property key="keep-inline" value="false"/>
         <property key="oXC16gcc-align-arr" value="false"/>
         <property key="oXC16gcc-cnsts-mauxflash" value="false"/>
         <property key="oXC16gcc-data-sects" value="false"/>
         <property key="oXC16gcc-errata" value=""/>
         <property key="oXC16gcc-fillupper" value=""/>
         <property key="oXC16gcc-large-aggregate" value="false"/>
         <property key="oXC16gcc-mauxflash" value="false"/>
         <property key="oXC16gcc-mpa-lvl" value=""/>
         <property key="oXC16gcc-name-text-sec" value=""/>
         <property key="oXC16gcc-near-chars" value="false"/>
         <property key="oXC16gcc-no-isr-warn" value="false"/>
         <property key="oXC16gcc-sfr-warn" value="true"/>
         <property key="oXC16gcc-smar-io-lvl" value="1"/>
         <property key="oXC16gcc-smart-io-fmt" value=""/>
         <property key="optimization-level" value="0"/>
         <property key="post-instruction-scheduling" value="default"/>
         <property key="pre-instruction-scheduling" value="default"/>
         <property key="preprocessor-macros"
                   value="SBCP_INST_TABLE_SIZE=8;SBCP_REG_TABLE_SIZE=128;SBCP_LOW_LATENCY_IN_SIZE=2;SBCP_LOW_LATENCY_OUT_SIZE=10"/>
         <property key="scalar-model" value="default"/>
+        <property key="use-cci" value="false"/>
       </C30>
       <C30-AS>
         <property key="assembler-symbols" value=""/>
         <property key="expand-macros" value="false"/>
         <property key="extra-include-directories-for-assembler" value=""/>
         <property key="extra-include-directories-for-preprocessor" value=""/>
         <property key="false-conditionals" value="false"/>
         <property key="keep-locals" value="false"/>
         <property key="list-assembly" value="false"/>
         <property key="list-file" value=""/>
         <property key="list-section-info" value="false"/>
         <property key="list-source" value="false"/>
         <property key="list-symbols" value="false"/>
         <property key="omit-debug-dirs" value="false"/>
         <property key="omit-forms" value="false"/>
         <property key="preprocessor-macros" value=""/>
         <property key="relax" value="false"/>
         <property key="warning-level" value="emit-warnings"/>
       </C30-AS>
       <C30-LD>
         <property key="boot-eeprom" value="no_eeprom"/>
         <property key="boot-flash" value="no_flash"/>
         <property key="boot-ram" value="no_ram"/>
         <property key="boot-write-protect" value="no_write_protect"/>
         <property key="enable-check-sections" value="false"/>
         <property key="enable-data-init" value="true"/>
         <property key="enable-default-isr" value="true"/>
         <property key="enable-handles" value="true"/>
         <property key="enable-pack-data" value="true"/>
         <property key="extra-lib-directories" value=""/>
         <property key="general-code-protect" value="no_code_protect"/>
         <property key="general-write-protect" value="no_write_protect"/>
         <property key="generate-cross-reference-file" value="false"/>
         <property key="heap-size" value=""/>
         <property key="input-libraries" value=""/>
         <property key="linker-symbols" value=""/>
         <property key="map-file" value=""/>
         <property key="preprocessor-macros" value=""/>
         <property key="remove-unused-sections" value="false"/>
         <property key="report-memory-usage" value="false"/>
         <property key="secure-eeprom" value="no_eeprom"/>
         <property key="secure-flash" value="no_flash"/>
         <property key="secure-ram" value="no_ram"/>
         <property key="secure-write-protect" value="no_write_protect"/>
         <property key="stack-size" value=""/>
         <property key="symbol-stripping" value=""/>
         <property key="trace-symbols" value=""/>
         <property key="warn-section-align" value="false"/>
       </C30-LD>
       <C30Global>
         <property key="fast-math" value="false"/>
         <property key="legacy-libc" value="false"/>
         <property key="output-file-format" value="elf"/>
       </C30Global>
       <PICkit3PlatformTool>
         <property key="ADC 1" value="true"/>
         <property key="AutoSelectMemRanges" value="auto"/>
         <property key="CRC" value="true"/>
         <property key="DUAL COMPARATOR" value="true"/>
         <property key="Freeze All Other Peripherals" value="true"/>
         <property key="I2C1" value="true"/>
         <property key="INPUT CAPTURE 1" value="true"/>
         <property key="INPUT CAPTURE 2" value="true"/>
         <property key="INPUT CAPTURE 7" value="true"/>
         <property key="INPUT CAPTURE 8" value="true"/>
         <property key="OUTPUT COMPARE 1" value="true"/>
         <property key="OUTPUT COMPARE 2" value="true"/>
         <property key="OUTPUT COMPARE 3" value="true"/>
         <property key="OUTPUT COMPARE 8" value="true"/>
         <property key="PARALLEL MASTER/SLAVE PORT" value="true"/>
         <property key="REAL TIME CLOCK AND CALENDAR" value="true"/>
         <property key="SPI 1" value="true"/>
         <property key="SPI 2" value="true"/>
         <property key="SecureSegment.SegmentProgramming" value="FullChipProgramming"/>
         <property key="TIMER1" value="true"/>
         <property key="TIMER2" value="true"/>
         <property key="TIMER3" value="true"/>
         <property key="TIMER4" value="true"/>
         <property key="TIMER5" value="true"/>
         <property key="ToolFirmwareFilePath"
                   value="Press to browse for a specific firmware version"/>
         <property key="ToolFirmwareOption.UseLatestFirmware" value="true"/>
         <property key="UART 1" value="true"/>
         <property key="UART 2" value="true"/>
         <property key="hwtoolclock.frcindebug" value="false"/>
         <property key="memories.aux" value="false"/>
         <property key="memories.eeprom" value="false"/>
         <property key="memories.flashdata" value="true"/>
         <property key="memories.id" value="false"/>
         <property key="memories.programmemory" value="true"/>
         <property key="memories.programmemory.end" value="0x157ff"/>
         <property key="memories.programmemory.start" value="0x0"/>
         <property key="poweroptions.powerenable" value="false"/>
         <property key="programmertogo.imagename" value=""/>
         <property key="programoptions.eraseb4program" value="true"/>
         <property key="programoptions.pgmspeed" value="2"/>
         <property key="programoptions.preserveeeprom" value="false"/>
         <property key="programoptions.preserveprogramrange" value="false"/>
         <property key="programoptions.preserveprogramrange.end" value="0xff"/>
         <property key="programoptions.preserveprogramrange.start" value="0x0"/>
         <property key="programoptions.preserveuserid" value="false"/>
         <property key="programoptions.usehighvoltageonmclr" value="false"/>
         <property key="programoptions.uselvpprogramming" value="false"/>
         <property key="voltagevalue" value="3.25"/>
       </PICkit3PlatformTool>
     </conf>
   </confs>
 </configurationDescriptor>
diff --git a/OncillaMotordriver.X/nbproject/project.xml b/OncillaMotordriver.X/nbproject/project.xml
index a844272..0a264e9 100644
--- a/OncillaMotordriver.X/nbproject/project.xml
+++ b/OncillaMotordriver.X/nbproject/project.xml
@@ -1,16 +1,16 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project xmlns="http://www.netbeans.org/ns/project/1">
     <type>com.microchip.mplab.nbide.embedded.makeproject</type>
     <configuration>
         <data xmlns="http://www.netbeans.org/ns/make-project/1">
-            <name>OncillaMotordriver</name>
+            <name>OncillaMotordriver_lc</name>
             <creation-uuid>0d773020-2f2f-4b98-89ff-c9a31e70eff1</creation-uuid>
             <make-project-type>0</make-project-type>
             <c-extensions>c</c-extensions>
             <cpp-extensions/>
             <header-extensions>h</header-extensions>
             <sourceEncoding>UTF-8</sourceEncoding>
             <make-dep-projects/>
         </data>
     </configuration>
 </project>
diff --git a/src/config.h b/src/config.h
index 53676f3..15f7223 100644
--- a/src/config.h
+++ b/src/config.h
@@ -1,29 +1,27 @@
 #ifndef __CONFIG_H__
 #define __CONFIG_H__
 
 // instruction cycle speed
-#define FCY_FOR_BAUDRATE	40000000UL
-#define FCY 			40000000UL
+#define FCY_FOR_BAUDRATE 40000000UL
+#define FCY              40000000UL
 
 // PWM frequency
-#define FPWM			60000UL
+#define FPWM                    60000UL
 // T1 interrupt frequency (Hz)
-#define FT1		        1000UL
-#define FSYST			1000UL
-
-
+#define FT1                     1000UL
+#define FSYST                   1000UL
 #define FSPI_ME_READING_LATENCY 1000000
 // uart time out value (us) SHOULD NOT BE USED
 //#define TIME_OUT		100
 
 
 #define SBCP_MDV_BAUDRATE 3310000UL
 #define SBCP_MDV_TIMEOUT  2000
 
 
-#define SBCP_MDV_CLASS 0xea
-#define SBCP_MDV_THIS_DEVICE_INITIAL_ID 0x01
+#define SBCP_MDV_CLASS                  0xea
+#define SBCP_MDV_THIS_DEVICE_INITIAL_ID 0x42
 
-#define SBCP_MDV_FIRMWARE_VERSION 0x01
+#define SBCP_MDV_FIRMWARE_VERSION       0x01
 
 #endif // __CONFIG_H__
diff --git a/src/load_cell.c b/src/load_cell.c
index 6523e9e..5ea699f 100644
--- a/src/load_cell.c
+++ b/src/load_cell.c
@@ -1,350 +1,421 @@
 #include "load_cell.h"
 
 #include "sbcp_mdv.h"
+#include <pps.h>
+#include <string.h>
+#include "timer.h"
+#include "pindefs.h"
+#include <libpic30.h>
+
+
 
 struct load_cell {
 	int torque;
 	lc_error_flags flags;
 };
 
 load_cell lcs[3];
 
 load_cell * lc1 = &(lcs[0]);
 load_cell * lc2 = &(lcs[1]);
 load_cell * lc3 = &(lcs[2]);
 
 
-
 /**
  * Th state machine states for Magnetic encoders reception
  */
-typedef enum DMA_SPI_LC_rx_state {
+typedef enum DMA_SPI_LC_state {
     DMA_SPI_LC_IDLE, ///< No reading is beeing performed.
-    DMA_SPI_LC_WAITING_FOR_DEVICES, ///< Reading is started, we send the start order to device, we putting a latency for them to read their data.
+    DMA_SPI_LC_WRITING_RESET,
+    DMA_SPI_LC_WAITING_500us,
+    DMA_SPI_LC_WAITING_TO_WRITE_SETTINGS,
+    DMA_SPI_LC_WRITING_SETTINGS,
+    DMA_SPI_LC_WRITING_INSTRUCTION_2,
+    DMA_SPI_LC_WRITING_INSTRUCTION_3,
+    DMA_SPI_LC_WAITING_FOR_READOUT,
     DMA_SPI_LC_READING_DEVICES, ///< We are actually reading the data from the devices
     DMA_SPI_LC_DATA_READY_TO_BE_PROCESSED ///< We have finish to read the data, and we need to process it to extract atual data in the spi_main function
-}DMA_SPI_LC_rx_state;
+}DMA_SPI_LC_state;
 
 
 struct DMA_SPI_LC_data {
-	gpio spi_cs;
-	DMA_SPI_LC_rx_state state;
+    gpio spi_cs;
+    gpio spi_sync;
+    gpio spi_mosi;
+    gpio spi_miso;
+    gpio spi_clk;
+    DMA_SPI_LC_state state;
 };
 
-struct DMA_SPI_LC_data dma_spi_lc;
-
-typedef union DMA_SPI_LC_rx_buffer{
-    struct{
-        //First word definition little endian representation
-        unsigned Q1_LIN : 1;           ///< their is a linearity read alarm, data invalid
-        unsigned Q1_COF : 1;           ///< their is CORDIC Overflow, data invalid
-        unsigned Q1_OCF : 1;           ///< Algorithm is finished. If zero, data invalid
-        unsigned Q1_ENC_DATA_LOW : 8;  ///< first 8 bits of data
-        unsigned Q1_ENC_DATA_HIGH : 4; ///< last 4 bits of data
-        unsigned Q1_DUMMY_BIT : 1;     ///< unimplemented
-        //------ 1 word size
-        //second word definition, little endian representation
-        unsigned Q2_ENC_DATA_LOW : 8;  ///< first 8 bits of data
-        unsigned Q2_ENC_DATA_HIGH : 4; ///< last 4 bits of data
-        unsigned Q2_DUMMY_BIT : 1;     ///< unimplemented
-
-        unsigned Q1_EVEN_PAR : 1;         ///< even parity bit
-        unsigned Q1_MAG_DEC : 1;          ///< Maginute amplitude decreased.
-        unsigned Q1_MAG_INC : 1;          ///< Maginute amplitude increased.
-        //------ 1 word size
-        //third word little endian representation
-        unsigned Q3_ENC_DATA_MID : 5;  ///<central 5 bits of data
-        unsigned Q3_ENC_DATA_HIGH : 4; ///< last 4 bits of data
-        unsigned Q3_DUMMY_BIT : 1;     ///< unimplemented
-        //19 bits for the first knee encoder.
-        unsigned Q2_EVEN_PAR : 1; ///< even parity bit
-        unsigned Q2_MAG_DEC : 1;  ///< Maginute amplitude decreased.
-        unsigned Q2_MAG_INC : 1;  ///< Maginute amplitude increased.
-        unsigned Q2_LIN : 1;      ///< their is a linearity read alarm, data invalid
-        unsigned Q2_COF : 1;      ///< their is CORDIC Overflow, data invalid
-        unsigned Q2_OCF : 1;      ///< Algorithm is finished. If zero, data invalid
-        //------ 1word size
-
-        // 4th and last word, little endian representation
-        //trailing 7 bits that should be ignored
-        unsigned DUMMY_BITS : 7; ///< unimplemented
-        //19 bits for the 2nd knee encoder.
-        unsigned Q3_EVEN_PAR : 1;     ///< even parity bit
-        unsigned Q3_MAG_DEC : 1;      ///< Maginute amplitude decreased.
-        unsigned Q3_MAG_INC : 1;      ///< Maginute amplitude increased.
-        unsigned Q3_LIN : 1;          ///< their is a linearity read alarm, data invalid
-        unsigned Q3_COF : 1;          ///< their is CORDIC Overflow, data invalid
-        unsigned Q3_OCF : 1;          ///< Algorithm is finished. If zero, data invalid
-        unsigned Q3_ENC_DATA_LOW : 3; ///< first 3 bits of data
-        //------ 1word size
-    } b; ///< bits representation
-    unsigned char B[8];///<byte representation
-    unsigned int  w[4];///<word representation
-} DMA_SPI_LC_rx_buffer;
-
-
-DMA_SPI_LC_rx_buffer dma_spi_lc_rx_buffer __attribute__((space(dma)));
-
-typedef union DMA_SPI_LC_tx_buffer{
-    struct{
-        //little endian representation
-        unsigned WEN : 1;
-        unsigned RW : 1;
-        unsigned RS2 : 1;
-        unsigned RS1 : 1;
-        unsigned RS0 : 1;
-        unsigned CREAD : 1;
-        unsigned DUMMY : 2;
-    } communication_bits; ///< bits rep
-
-    struct{
-        //little endian representation
-        unsigned RDY : 1;
-        unsigned ERR : 1;
-        unsigned NOREF : 1;
-        unsigned PARITY : 1;
-        unsigned CHD3 : 4;
-    } status_bits; ///< bits rep
-    
-    unsigned char byte;
-    unsigned char  w[1];///<word representation
-} DMA_SPI_LC_tx_buffer;
+volatile struct DMA_SPI_LC_data dma_spi_lc;
+
+typedef struct DMA_SPI_LC_read_value{
+    unsigned char DATA[3];
+    unsigned char STATUS;
+} DMA_SPI_LC_read_value;
+
+#define CIRCULAR_BUFFER_SIZE 3
+volatile unsigned char circular_buffer_ready = 0;
+volatile unsigned char circular_buffer_index = 0;
+volatile DMA_SPI_LC_read_value circular_buffer[CIRCULAR_BUFFER_SIZE];
+
+unsigned char dma_spi_lc_tx_buffer[16] __attribute__((space(dma)));
+
+volatile unsigned char dma_spi_lc_rx_buffer[16] __attribute__((space(dma)));
 
-DMA_SPI_LC_tx_buffer dma_spi_lc_tx_buffer __attribute__((space(dma)));
 
 #define dma_spi_lc_start() do{\
-	/*gpio_clear(dma_spi_lc.spi_cs);*/\
+	gpio_clear(dma_spi_lc.spi_cs);\
 }while(0)
 
 
 #define dma_spi_lc_stop() do{\
 	gpio_set(dma_spi_lc.spi_cs);\
 }while(0)
 
-#define dma_spi_lc_write(byte_val) do{\
-        dma_spi_lc_tx_buffer.byte = byte_val;\
-        DMA4REQbits.FORCE = 1;\
+#define dma_spi_lc_write() do{\
         dma_spi_lc_stop();\
-        /*SPI2BUF = byte_val;*/ /*force the transfer of dma channel */\
-        dma_spi_lc.state = DMA_SPI_LC_WAITING_FOR_DEVICES;\
-}while(0)
-
-#define dma_spi_lc_start_actual_reading() do{\
-	/*SPI2BUF = 0x0000; force the transfer of dma channel \
-	dma_spi_lc.state = DMA_SPI_LC_READING_DEVICES;*/\
+        dma_spi_lc_start();\
+        DMA4CONbits.CHEN  = 1;\
+        DMA3CONbits.CHEN  = 1;\
+        DMA4REQbits.FORCE = 1;\
 }while(0)
 
-
-
 void init_load_cell(load_cell * e){
 	e->torque = 0;
 	e->flags = LC_F_ONBOARD_PROCESSING_UNFINISHED;
 }
 
 
-void init_load_cells(gpio spi_cs){
-	dma_spi_lc.spi_cs = spi_cs;
-	dma_spi_lc_stop();
-	dma_spi_lc.state  = DMA_SPI_LC_IDLE;
+void init_load_cells(){
+
+    //Peripheral Pin Select
+
+    PPSUnLock;
+    PPSOutput(0, OUT_PIN_PPS_RP25); // no output on rp5
+    IN_FN_PPS_SDI2 = 0;// no input on rp2
+    IN_FN_PPS_SCK2 = 0;// no input on rp5
+    IN_FN_PPS_SS2 = 0;// no input on rp23
+    OUT_PIN_PPS_RP2 = 0;
+    OUT_PIN_PPS_RP5 = 0;
+    OUT_PIN_PPS_RP23 = 0;
+    OUT_PIN_PPS_RP24 = 0;
+    OUT_PIN_PPS_RP25 = 0;
+    PPSOutput(OUT_FN_PPS_SDO2, OUT_PIN_PPS_RP23); // MOSI to rp23
+    PPSOutput(OUT_FN_PPS_SS2, OUT_PIN_PPS_RP2); // chip select to rp2
+    PPSOutput(OUT_FN_PPS_SCK2, OUT_PIN_PPS_RP5); // clock out to rp5
+    PPSInput(PPS_SDI2, PPS_RP25);// MISO to rp25
+    //PPSLock;
+    
+    dma_spi_lc.spi_mosi = gpio_create(GPIO_PORT_C,GPIO_PIN_7,GPIO_OUTPUT);
+    gpio_clear(dma_spi_lc.spi_mosi);
 
-        SPI2STATbits.SPIEN  = 0;     //Disable SPI 2 module during configuration
-	//SPI 1 is for magentic encoders :
-	IEC2bits.SPI2IE     = 0; //disable interrupt. This is needed because we use DMA
-	IFS2bits.SPI2IF     = 0; //clear the interrupt flag.
-        IPC8bits.SPI2IP     = 0b111;
+    dma_spi_lc.spi_miso = gpio_create(GPIO_PORT_C,GPIO_PIN_9,GPIO_INPUT);
+    gpio_set(dma_spi_lc.spi_miso);
 
-        SPI2STATbits.SPIROV = 0;
-	SPI2CON1bits.DISSCK = 0; //Use the clock
-	SPI2CON1bits.DISSDO = 0; //Disable data output. This is not needed by the application, no pin are routed
-	SPI2CON1bits.MODE16 = 0; //Transmit bytes. Rx buffer is in byte, but we don't care because we are transmitting an even number of byte
-	
-	SPI2CON1bits.CKE    = 0; //data valid on rising edge
-	SPI2CON1bits.CKP    = 1; //clock idle state is at high level
-	SPI2CON1bits.MSTEN  = 1; //enable master mode
-        SPI2CON1bits.SMP    = 1; //data is sampled at middle of clock time
+    dma_spi_lc.spi_clk = gpio_create(GPIO_PORT_B,GPIO_PIN_5,GPIO_OUTPUT);
+    gpio_set(dma_spi_lc.spi_clk);
 
-        SPI2CON1bits.SSEN   = 0; //enable chip select bit
-        SPI2CON2bits.FRMEN  = 0;     //Frame support
+    dma_spi_lc.spi_sync = gpio_create(GPIO_PORT_C,GPIO_PIN_8,GPIO_OUTPUT);
+    gpio_set(dma_spi_lc.spi_sync);
 
-	//Choose a clock frequency of 625 kHz, max accepted by AS5045 is 1Mhz
-	SPI2CON1bits.SPRE   = 0b000; //Select a secondary prescaler of 1:1
-	SPI2CON1bits.PPRE   = 0b00 ; //select a primary prescaler of 64:1
+    dma_spi_lc.spi_cs = gpio_create(GPIO_PORT_B,GPIO_PIN_2,GPIO_OUTPUT);
+    gpio_set(dma_spi_lc.spi_cs);
 
-	
-	SPI2STATbits.SPIEN  = 1;     //Enable SPI 2 module
+    dma_spi_lc.state  = DMA_SPI_LC_IDLE;
 
-	DMA3CONbits.CHEN  = 0;
-	DMA3CONbits.SIZE  = 0;
-	DMA3CONbits.DIR   = 0;
-	DMA3CONbits.HALF  = 0;
+    /************************************
+     SPI2-MODULE
+     ************************************/
 
-	DMA3CONbits.NULLW = 1;
+    SPI2STATbits.SPIEN  = 0;     //Disable SPI 2 module during configuration
+    //SPI 1 is for magentic encoders :
+    IEC2bits.SPI2IE     = 0; //disable interrupt. This is needed because we use DMA
+    IFS2bits.SPI2IF     = 0; //clear the interrupt flag.
+    IPC8bits.SPI2IP     = 0b000;
+    SPI2CON1bits.MSTEN  = 1; //enable master mode
+    SPI2STATbits.SPIROV = 0; // clear overflow flag
 
-	DMA3CONbits.AMODE = 0b00;// Register indirect with posincrement
-	DMA3CONbits.MODE  = 0b01;// One - shot, No Ping Pong
+    SPI2CON1bits.DISSCK = 0; //Use the clock
+    SPI2CON1bits.DISSDO = 0; //Disable data output. This is not needed by the application, no pin are routed
+    SPI2CON1bits.MODE16 = 0; //Transmit bytes. Rx buffer is in byte, but we don't care because we are transmitting an even number of byte
 
-        DMA3STA = __builtin_dmaoffset(dma_spi_lc_rx_buffer.w);
+    SPI2CON1bits.CKE    = 0; //data valid on rising edge
+    SPI2CON1bits.CKP    = 1; //clock idle state is at high level
+    SPI2CON1bits.SMP    = 0; //0=data is sampled at middle of clock time
 
-        DMA3PAD = (volatile unsigned int) & SPI2BUF;
+    SPI2CON1bits.SSEN   = 0; //disable chip select bit (we do this ourselves)
+    SPI2CON2bits.FRMEN  = 0;     //Frame support
 
-	DMA3REQ = 0;//0x000A;
-	DMA3CNT = 3;
+    //Choose a clock frequency of 625 kHz, max accepted by AS5045 is 1Mhz
+    //TODO: set frequency
+    SPI2CON1bits.SPRE   = 0b000; //Select a secondary prescaler of 1:1
+    SPI2CON1bits.PPRE   = 0b10 ; //select a primary prescaler of 64:1
 
-        IFS2bits.DMA3IF = 0;
-	IEC2bits.DMA3IE = 0;
+    IEC2bits.SPI2IE     = 0;    //enable interrupt.
+    SPI2STATbits.SPIEN  = 1;     //Enable SPI 2 module
 
+    /************************************
+     DMA3-MODULE
+     ************************************/
 
-        IFS2bits.DMA4IF = 0;
-	IEC2bits.DMA4IE = 0;
-        IPC11bits.DMA4IP = 0b111; //maximum priority
+    IEC2bits.DMA3IE = 0;
+    IFS2bits.DMA3IF = 0;
 
-        DMA4CONbits.CHEN  = 0;
-	DMA4CONbits.SIZE  = 1; //send per byte
-	DMA4CONbits.DIR   = 1; //send, don't read
-	DMA4CONbits.HALF  = 0;
+    IPC9bits.DMA3IP = 0b001; //low priority, but needs to be higher than DMA4IP
 
-	DMA4CONbits.NULLW = 0;
 
-	DMA4CONbits.AMODE = 0b00;// Register indirect with post-increment
-	DMA4CONbits.MODE  = 0b01;// One - shot, No Ping Pong
+    DMA3CONbits.CHEN  = 0;
+    DMA3CONbits.SIZE  = 1;
+    DMA3CONbits.DIR   = 0;//read, don't send
+    DMA3CONbits.HALF  = 0;
 
-        dma_spi_lc_tx_buffer.byte = 0xAA;
-        DMA4STA = __builtin_dmaoffset(dma_spi_lc_tx_buffer.w); //transmission buffer
-        DMA4PAD = (volatile unsigned int) & SPI2BUF;
+    DMA3CONbits.NULLW = 0;
 
-	DMA4REQ = 0b00100001;
-	//DMA4REQ = 0x00A;
-        DMA4CNT = 2; //number of bytes to send
-        
-        IFS2bits.DMA4IF = 0;
-	IEC2bits.DMA4IE = 1; //we don't need this interrupt
-        DMA4CONbits.CHEN  = 1;
-                
-        init_load_cell(&(lcs[0]));
-	init_load_cell(&(lcs[1]));
-	init_load_cell(&(lcs[2]));
-}
+    DMA3CONbits.AMODE = 0b00;// Register indirect with posincrement
+    DMA3CONbits.MODE  = 0b00;// continuous, No Ping Pong
 
-#define fill_status(lc,ocf_bit,cof_bit,lin_bit,amp_incr_bit,amp_decr_bit) do{ \
-	lc.flags = LC_F_OK; \
-	if(!(ocf_bit)){ \
-		lc.flags |= LC_F_ONBOARD_PROCESSING_UNFINISHED; \
-	} \
-	if(cof_bit){ \
-		lc.flags |= LC_F_CORDIC_OVERFLOW; \
-	} \
-	if(lin_bit){ \
-		lc.flags |= LC_F_LINEARITY_READ_ALARM; \
-	} \
-	if( (amp_incr_bit) && (amp_decr_bit) ) { \
-		lc.flags |= LC_F_LOAD_CELL_AMPLITUDE_ERROR; \
-	} \
-}while(0)
+    DMA3STA = __builtin_dmaoffset(dma_spi_lc_rx_buffer);
 
+    DMA3PAD = (volatile unsigned int) & SPI2BUF;
 
-void load_cell_start_reading(){
-	if(dma_spi_lc.state == DMA_SPI_LC_IDLE){
-		dma_spi_lc.state = DMA_SPI_LC_WAITING_FOR_DEVICES;
-		//dma_spi_lc_start();
-		dma_spi_lc_write(0xAA);//0x5c
-                //dma_spi_lc_start_actual_reading();
-		return;
-	}
+    DMA3REQbits.IRQSEL = 0b0100001; //SPI2
+    DMA3CNT = 0;
+
+    IEC2bits.DMA3IE = 1;
+
+    /************************************
+     DMA4-MODULE
+     ************************************/
+
+    IEC2bits.DMA4IE = 0;
+    IFS2bits.DMA4IF = 0;
+    IPC11bits.DMA4IP = 0b000; //low priority
+
+    DMA4CONbits.CHEN  = 0;
+    DMA4CONbits.SIZE  = 1; //send per byte
+    DMA4CONbits.DIR   = 1; //send, don't read
+    DMA4CONbits.HALF  = 0; //only one buffer
+
+    DMA4CONbits.NULLW = 0;
+
+    DMA4CONbits.AMODE = 0b00;// Register indirect with post-increment
+    DMA4CONbits.MODE  = 0b01;// 0b01 One - shot, No Ping Pong
+
+    DMA4REQbits.IRQSEL = 0b0100001; //SPI2
+    DMA4CNT = 0; //number of bytes to send
+
+    DMA4STA = __builtin_dmaoffset(dma_spi_lc_tx_buffer); //transmission buffer
+    DMA4PAD = (volatile unsigned int) & SPI2BUF;
+
+    IEC2bits.DMA4IE = 0; //we don't need this interrupt, we use the interupt when everything is received
+
+    /************************************
+     CN19-MODULE
+     ************************************/
+
+    CNEN2bits.CN19IE = 1;
+    CNPU2bits.CN19PUE = 0;
+    IFS1bits.CNIF = 0;
+    IEC1bits.CNIE = 0; //don't enable it yet
+
+    init_load_cell(&(lcs[0]));
+    init_load_cell(&(lcs[1]));
+    init_load_cell(&(lcs[2]));
+
+    load_cell_reset();
 }
 
+inline void set_lc_torque(load_cell lc, int value, int adr) {
+    lc.flags = LC_F_OK;
+    lc.torque = value;
+    sbcp_me_reg(adr,LCX_TORQUE).u = value;
+    sbcp_mark_new_low_latency_data_available();
+}
 
-#define set_lc_torque(lc,value,adr) do{	  \
-	if((lc).flags == LC_F_OK){ \
-		(lc).torque = (long) ((value)); \
-		(lc).torque &= 0x3fff; \
-	} \
-	sbcp_lc_reg(adr,LCX_TORQUE).u = (lc).torque; \
-	if((lc).flags & (LC_F_LINEARITY_READ_ALARM | LC_F_CORDIC_OVERFLOW | LC_F_ONBOARD_PROCESSING_UNFINISHED)) { \
-		sbcp_lc_reg(adr,LCX_TORQUE).u |= 1 << 15; \
-	} \
-	if((lc).flags & LC_F_LOAD_CELL_AMPLITUDE_ERROR){ \
-		sbcp_lc_reg(adr,LCX_TORQUE).u |= 1 << 14; \
-	} \
+#define NUMARGS(...)  (sizeof((char[]){__VA_ARGS__})/sizeof(char))
+#define spi_write_bytes(...) do{\
+    memcpy(dma_spi_lc_tx_buffer, (char [NUMARGS(__VA_ARGS__)]) {__VA_ARGS__}, NUMARGS(__VA_ARGS__)*sizeof(char));\
+    DMA3CNT = NUMARGS(__VA_ARGS__)-1;\
+    DMA4CNT = NUMARGS(__VA_ARGS__)-1;\
+    dma_spi_lc_write();\
 }while(0)
 
+#define spi_led_on() spi_write_bytes(0x28,0x31)
+#define spi_led_off() spi_write_bytes(0x28,0x30)
+#define spi_led_blink() spi_write_bytes(0x28,0x30|BLINK)
+#define spi_settings 0b00001000,0b00011000,0b00101000,0b00000001,0b00010000,0b00000000,0b00000111,0b11010000,
+
+
+int lc_error_count=0;
+
+int reset_counter;
+volatile short start_reading = 0;
 
 void load_cell_process(){
-	if(dma_spi_lc.state == DMA_SPI_LC_DATA_READY_TO_BE_PROCESSED){
-
-		//we assume that the parity is always correct.
-		/// \todo : check the parity of the data, buts it's rather complicated.
-
-		//first we check the status
-		fill_status(lcs[0],
-		            dma_spi_lc_rx_buffer.b.Q1_OCF,
-		            dma_spi_lc_rx_buffer.b.Q1_COF,
-		            dma_spi_lc_rx_buffer.b.Q1_LIN,
-		            dma_spi_lc_rx_buffer.b.Q1_MAG_INC,
-		            dma_spi_lc_rx_buffer.b.Q1_MAG_DEC);
-
-		fill_status(lcs[1],
-		            dma_spi_lc_rx_buffer.b.Q2_OCF,
-		            dma_spi_lc_rx_buffer.b.Q2_COF,
-		            dma_spi_lc_rx_buffer.b.Q2_LIN,
-		            dma_spi_lc_rx_buffer.b.Q2_MAG_INC,
-		            dma_spi_lc_rx_buffer.b.Q2_MAG_DEC);
-
-		fill_status(lcs[2],
-		            dma_spi_lc_rx_buffer.b.Q3_OCF,
-		            dma_spi_lc_rx_buffer.b.Q3_COF,
-		            dma_spi_lc_rx_buffer.b.Q3_LIN,
-		            dma_spi_lc_rx_buffer.b.Q3_MAG_INC,
-		            dma_spi_lc_rx_buffer.b.Q3_MAG_DEC);
-
-
-		set_lc_torque(lcs[0], (dma_spi_lc_rx_buffer.b.Q1_ENC_DATA_HIGH << 8 ) + dma_spi_lc_rx_buffer.b.Q1_ENC_DATA_LOW , MDV_LC_AXIS_1);
-		set_lc_torque(lcs[1], (dma_spi_lc_rx_buffer.b.Q2_ENC_DATA_HIGH << 8 ) + dma_spi_lc_rx_buffer.b.Q2_ENC_DATA_LOW , MDV_LC_AXIS_2);
-		set_lc_torque(lcs[2], (dma_spi_lc_rx_buffer.b.Q3_ENC_DATA_HIGH << 8 ) + ( dma_spi_lc_rx_buffer.b.Q3_ENC_DATA_MID << 3 ) + dma_spi_lc_rx_buffer.b.Q3_ENC_DATA_LOW , MDV_LC_AXIS_3);
-
-		//mark that new data is available in the table.
-		sbcp_mark_new_low_latency_data_available();
-		//we have readen the data, nothing more to do
-		dma_spi_lc.state = DMA_SPI_LC_IDLE;
-
-	}
+    int v;
+    int index;
+    DMA_SPI_LC_read_value value;
+    unsigned short p;
+    if(start_reading){
+        start_reading=0;
+        dma_spi_lc.state = DMA_SPI_LC_READING_DEVICES;
+        spi_write_bytes(0x58,0x00,0x00,0x00,0x00); // read 4 bytes
+    }
+    if(circular_buffer_ready){
+        for(index = 0; index<CIRCULAR_BUFFER_SIZE; index++){
+
+            IEC2bits.DMA3IE = 0;//disable writing to circular buffer while reading from it, without losing interrupts.
+            value = circular_buffer[index]; //copy to remove race conditions with interupt
+            IEC2bits.DMA3IE = 1;
+            // step 1: check parity
+            v = value.DATA[0] ^ value.DATA[1] ^ value.DATA[2];
+            v = (v ^ v>>4) & 0x0f;
+            p = (0x6996 >> v) & 1; //Look-up table
+            if(value.DATA[0] == 0 && value.DATA[1] == 0 && value.DATA[2] == 0 && value.STATUS == 0){//while strictly speaking, this is a correct packet, it is more likely something is going wrong
+                lc_error_count++;
+            }
+            if(p != (value.STATUS & 0b00010000)>>4){
+                lc_error_count++;
+            }else if(value.STATUS & 0b11100000){ //RDY, ERR, NOREF
+                lc_error_count++;
+            }else {
+                switch(value.STATUS & 0b00001111){
+                    case 0:
+                        set_lc_torque(lcs[0], ((unsigned long) value.DATA[0])<<8 | ((unsigned long) value.DATA[1]),MDV_LC_AXIS_1);
+                        break;
+                    case 1:
+                        set_lc_torque(lcs[1], ((unsigned long) value.DATA[0])<<8 | ((unsigned long) value.DATA[1]),MDV_LC_AXIS_2);
+                        break;
+                    case 2:
+                        set_lc_torque(lcs[2], ((unsigned long) value.DATA[0])<<8 | ((unsigned long) value.DATA[1]),MDV_LC_AXIS_3);
+                        break;
+                    default:
+                        lc_error_count++;
+                }
+            }
+        }
+        if(lc_error_count>100){
+            if(dma_spi_lc.state == DMA_SPI_LC_WAITING_FOR_READOUT
+            || dma_spi_lc.state == DMA_SPI_LC_READING_DEVICES){
+                lc_error_count=0;
+                load_cell_reset();
+            }
+        }
+    }
+}
+
+void load_cell_reset(){
+    IEC1bits.CNIE = 0;
+    circular_buffer_ready = 0;
+    reset_counter = 0;
+    start_reading=0;
+    dma_spi_lc.state = DMA_SPI_LC_WRITING_RESET;
+    spi_write_bytes(0xff,0xff,0xff,0xff,0xff);
+}
+
+void load_cell_start_reading(){
+    if(dma_spi_lc.state == DMA_SPI_LC_IDLE){
+        //start reading
+        dma_spi_lc.state = DMA_SPI_LC_WAITING_FOR_READOUT;
+        IEC1bits.CNIE = 1;
+    }
+    if(dma_spi_lc.state == DMA_SPI_LC_WAITING_TO_WRITE_SETTINGS){
+        if(reset_counter == 0){ //you need to wait at least 500us to start writing the settings. We wait for an additional 1ms so we are sure we waited long enough.
+            reset_counter++;
+        }else{
+            dma_spi_lc.state = DMA_SPI_LC_WRITING_SETTINGS;
+            spi_write_bytes(spi_settings);
+        }
+    }
 }
 
 
 /*******************************************************************************
  *
- * Interruption
+ * Interrupt
  *
  ******************************************************************************/
 
 /**
- * Interruption when the SPI 2 finished its reading
+ * Interrupt when the DMA finished reading all the bytes
  */
 void __attribute__((__interrupt__ , no_auto_psv)) _DMA3Interrupt(){
-	dma_spi_lc.state = DMA_SPI_LC_DATA_READY_TO_BE_PROCESSED;
-	//dma_spi_lc_stop();
-	//clear the interruption flag
-	IFS2bits.DMA3IF = 0;
+
+    switch(dma_spi_lc.state){
+        case DMA_SPI_LC_WRITING_RESET:
+            dma_spi_lc.state = DMA_SPI_LC_WAITING_TO_WRITE_SETTINGS;
+            break;
+        case DMA_SPI_LC_WRITING_SETTINGS:
+            spi_led_on();
+            dma_spi_lc.state = DMA_SPI_LC_WRITING_INSTRUCTION_2; //todo,
+            break;
+        case DMA_SPI_LC_WRITING_INSTRUCTION_2:
+            dma_spi_lc.state = DMA_SPI_LC_IDLE; //todo,
+            break;
+        case DMA_SPI_LC_WRITING_INSTRUCTION_3:
+            dma_spi_lc.state = DMA_SPI_LC_IDLE; //todo,
+            break;
+        case DMA_SPI_LC_READING_DEVICES:
+            dma_spi_lc.state = DMA_SPI_LC_WAITING_FOR_READOUT;
+            circular_buffer[circular_buffer_index].DATA[0] = dma_spi_lc_rx_buffer[1];
+            circular_buffer[circular_buffer_index].DATA[1] = dma_spi_lc_rx_buffer[2];
+            circular_buffer[circular_buffer_index].DATA[2] = dma_spi_lc_rx_buffer[3];
+            circular_buffer[circular_buffer_index].STATUS  = dma_spi_lc_rx_buffer[4];
+            circular_buffer_index++;
+            if(circular_buffer_index >= CIRCULAR_BUFFER_SIZE){
+                circular_buffer_index = 0;
+                circular_buffer_ready = 1;
+            }
+            IEC1bits.CNIE = 1;// re-enable the read interrupt after communication is done
+            break;
+        default:
+            dma_spi_lc.state = DMA_SPI_LC_IDLE; //todo,
+            break;
+    }
+    //gpio_set(dma_spi_lc.spi_mosi);//Idle high
+    IFS2bits.DMA3IF = 0;//clear the interrupt flag
 }
 
+/**
+ * Interrupt when the DMA finished its writing of all the bytes
+*/
+void __attribute__((__interrupt__ , no_auto_psv)) _DMA4Interrupt(){
+    //clear the interruption flag
+    //DMA4CONbits.CHEN  = 0;
+    //dma_spi_lc.state = DMA_SPI_LC_IDLE;
+    //dma_spi_lc_stop();
+    IFS2bits.DMA4IF = 0;
+}
 
 /**
- * Interruption when the SPI 2 finished its writing
+ * Interrupt when the SPI 2 finished writing and reading a byte
+*/
+void __attribute__((__interrupt__, no_auto_psv)) _SPI2Interrupt(void)
+{
+    //SPI2STATbits.SPIROV = 0;
+    IFS2bits.SPI2IF = 0; // Clear the SPI1 Interrupt Flag
+    //SPI1BUF=0;      // send next byte, not necassary if NULLW set
+}
 
-void __attribute__((__interrupt__ , no_auto_psv)) _DMA4Interrupt(){
-	//clear the interruption flag
-    	//DMA4CONbits.CHEN  = 0;
-	IFS2bits.DMA4IF = 0;
-}*/
+void __attribute__((__interrupt__ , no_auto_psv)) _CNInterrupt(){
+    if(dma_spi_lc.state == DMA_SPI_LC_WAITING_FOR_READOUT){
+        if(gpio_read(dma_spi_lc.spi_miso) == 0){
+            IEC1bits.CNIE = 0;// disable this interrupt during communication
+            start_reading = 1;
+        }
+    }
+    IFS1bits.CNIF = 0;
+}
 
 int lc_get_torque(load_cell * e){
 	return e->torque;
 }
 
 lc_error_flags lc_get_error(load_cell * e){
 	return e->flags;
 }
 
-
 void lc_load_persistent_sbcp_settings(){
 	
 }
diff --git a/src/load_cell.h b/src/load_cell.h
index 1df07e1..0b1bbe2 100644
--- a/src/load_cell.h
+++ b/src/load_cell.h
@@ -1,44 +1,41 @@
 /* 
  * File:   load_cell.h
  * Author: jonas
  *
  * Created on March 26, 2013, 11:07 AM
  */
 
 #ifndef LOAD_CELL_H
 #define	LOAD_CELL_H
 
 #include <gpio.h>
+#include <libpic30.h>
+
 
 struct load_cell;
 
 typedef struct load_cell load_cell;
 
 
 
 
-void init_load_cells(gpio spi_cs);
-
+void init_load_cells();
+void load_cell_reset();
 void load_cell_process();
 void load_cell_start_reading();
 
 void lc_load_persistent_sbcp_settings();
 
-enum lc_error_flags {
+typedef enum lc_error_flags {
 	LC_F_OK                            = 0 ,
-	LC_F_LINEARITY_READ_ALARM          = 1 << 0,
-	LC_F_CORDIC_OVERFLOW               = 1 << 1,
-	LC_F_ONBOARD_PROCESSING_UNFINISHED = 1 << 2,
-	LC_F_LOAD_CELL_AMPLITUDE_ERROR      = 1 << 3
-};
-
-typedef enum lc_error_flags lc_error_flags;
+	LC_F_ONBOARD_PROCESSING_UNFINISHED = 1
+} lc_error_flags;
 
 int lc_get_torque(load_cell * e);
 
 lc_error_flags lc_get_error(load_cell * e);
 
 extern load_cell * lc1,* lc2,* lc3;
 
 #endif	/* LOAD_CELL_H */
 
diff --git a/src/magnetic_encoder.c b/src/magnetic_encoder.c
index f25fd9f..1d184b7 100644
--- a/src/magnetic_encoder.c
+++ b/src/magnetic_encoder.c
@@ -1,336 +1,342 @@
 #include "magnetic_encoder.h"
 
 #include "sbcp_mdv.h"
+#include "misc_math.h"
 
 
 #define timer_2_start() do { T2CONbits.TON = 1; }while(0)
 
 #define timer_2_stop()  do { T2CONbits.TON = 0; }while(0)
 
-#define timer_2_stop_and_clear() do{ \
-	timer_2_stop(); \
-	TMR2 = 0x00; \
-}while(0)
+#define timer_2_stop_and_clear() do{	  \
+		timer_2_stop(); \
+		TMR2 = 0x00; \
+	}while(0)
 
 
 
 
 struct magnetic_encoder {
 	int position;
 	me_error_flags flags;
 	int mult;
 	int div;
 };
 
 magnetic_encoder mes[3];
 
 magnetic_encoder * me1 = &(mes[0]);
 magnetic_encoder * me2 = &(mes[1]);
 magnetic_encoder * me3 = &(mes[2]);
 
 
 
 /**
  * Th state machine states for Magnetic encoders reception
  */
 typedef enum DMA_SPI_ME_rx_state {
-    DMA_SPI_ME_IDLE, ///< No reading is beeing performed.
-    DMA_SPI_ME_WAITING_FOR_DEVICES, ///< Reading is started, we send the start order to device, we putting a latency for them to read their data.
-    DMA_SPI_ME_READING_DEVICES, ///< We are actually reading the data from teh devices
-    DMA_SPI_ME_DATA_READY_TO_BE_PROCESSED ///< We have finish to read the data, and we need to process it to extract atual data in the spi_main function
+	DMA_SPI_ME_IDLE, ///< No reading is beeing performed.
+	DMA_SPI_ME_WAITING_FOR_DEVICES, ///< Reading is started, we send the start order to device, we putting a latency for them to read their data.
+	DMA_SPI_ME_READING_DEVICES, ///< We are actually reading the data from teh devices
+	DMA_SPI_ME_DATA_READY_TO_BE_PROCESSED ///< We have finish to read the data, and we need to process it to extract atual data in the spi_main function
 }DMA_SPI_ME_rx_state;
 
 
 struct DMA_SPI_ME_data {
 	gpio spi_cs;
 	DMA_SPI_ME_rx_state state;
 };
 
 struct DMA_SPI_ME_data dma_spi_me;
 
 typedef union DMA_SPI_ME_rx_buffer{
-    struct{
-        //First word definition little endian representation
-        unsigned Q1_LIN : 1;           ///< their is a linearity read alarm, data invalid
-        unsigned Q1_COF : 1;           ///< their is CORDIC Overflow, data invalid
-        unsigned Q1_OCF : 1;           ///< Algorithm is finished. If zero, data invalid
-        unsigned Q1_ENC_DATA_LOW : 8;  ///< first 8 bits of data
-        unsigned Q1_ENC_DATA_HIGH : 4; ///< last 4 bits of data
-        unsigned Q1_DUMMY_BIT : 1;     ///< unimplemented
-        //------ 1 word size
-        //second word definition, little endian representation
-        unsigned Q2_ENC_DATA_LOW : 8;  ///< first 8 bits of data
-        unsigned Q2_ENC_DATA_HIGH : 4; ///< last 4 bits of data
-        unsigned Q2_DUMMY_BIT : 1;     ///< unimplemented
-
-        unsigned Q1_EVEN_PAR : 1;         ///< even parity bit
-        unsigned Q1_MAG_DEC : 1;          ///< Maginute amplitude decreased.
-        unsigned Q1_MAG_INC : 1;          ///< Maginute amplitude increased.
-        //------ 1 word size
-        //third word little endian representation
-        unsigned Q3_ENC_DATA_MID : 5;  ///<central 5 bits of data
-        unsigned Q3_ENC_DATA_HIGH : 4; ///< last 4 bits of data
-        unsigned Q3_DUMMY_BIT : 1;     ///< unimplemented
-        //19 bits for the first knee encoder.
-        unsigned Q2_EVEN_PAR : 1; ///< even parity bit
-        unsigned Q2_MAG_DEC : 1;  ///< Maginute amplitude decreased.
-        unsigned Q2_MAG_INC : 1;  ///< Maginute amplitude increased.
-        unsigned Q2_LIN : 1;      ///< their is a linearity read alarm, data invalid
-        unsigned Q2_COF : 1;      ///< their is CORDIC Overflow, data invalid
-        unsigned Q2_OCF : 1;      ///< Algorithm is finished. If zero, data invalid
-        //------ 1word size
-
-        // 4th and last word, little endian representation
-        //trailing 7 bits that should be ignored
-        unsigned DUMMY_BITS : 7; ///< unimplemented
-        //19 bits for the 2nd knee encoder.
-        unsigned Q3_EVEN_PAR : 1;     ///< even parity bit
-        unsigned Q3_MAG_DEC : 1;      ///< Maginute amplitude decreased.
-        unsigned Q3_MAG_INC : 1;      ///< Maginute amplitude increased.
-        unsigned Q3_LIN : 1;          ///< their is a linearity read alarm, data invalid
-        unsigned Q3_COF : 1;          ///< their is CORDIC Overflow, data invalid
-        unsigned Q3_OCF : 1;          ///< Algorithm is finished. If zero, data invalid
-        unsigned Q3_ENC_DATA_LOW : 3; ///< first 3 bits of data
-        //------ 1word size
-    } b; ///< bits representation
-    unsigned char B[8];///<byte representation
-    unsigned int  w[4];///<word representation
+	struct{
+		//First word definition little endian representation
+		unsigned Q1_LIN : 1;           ///< their is a linearity read alarm, data invalid
+		unsigned Q1_COF : 1;           ///< their is CORDIC Overflow, data invalid
+		unsigned Q1_OCF : 1;           ///< Algorithm is finished. If zero, data invalid
+		unsigned Q1_ENC_DATA_LOW : 8;  ///< first 8 bits of data
+		unsigned Q1_ENC_DATA_HIGH : 4; ///< last 4 bits of data
+		unsigned Q1_DUMMY_BIT : 1;     ///< unimplemented
+		//------ 1 word size
+		//second word definition, little endian representation
+		unsigned Q2_ENC_DATA_LOW : 8;  ///< first 8 bits of data
+		unsigned Q2_ENC_DATA_HIGH : 4; ///< last 4 bits of data
+		unsigned Q2_DUMMY_BIT : 1;     ///< unimplemented
+
+		unsigned Q1_EVEN_PAR : 1;         ///< even parity bit
+		unsigned Q1_MAG_DEC : 1;          ///< Maginute amplitude decreased.
+		unsigned Q1_MAG_INC : 1;          ///< Maginute amplitude increased.
+		//------ 1 word size
+		//third word little endian representation
+		unsigned Q3_ENC_DATA_MID : 5;  ///<central 5 bits of data
+		unsigned Q3_ENC_DATA_HIGH : 4; ///< last 4 bits of data
+		unsigned Q3_DUMMY_BIT : 1;     ///< unimplemented
+		//19 bits for the first knee encoder.
+		unsigned Q2_EVEN_PAR : 1; ///< even parity bit
+		unsigned Q2_MAG_DEC : 1;  ///< Maginute amplitude decreased.
+		unsigned Q2_MAG_INC : 1;  ///< Maginute amplitude increased.
+		unsigned Q2_LIN : 1;      ///< their is a linearity read alarm, data invalid
+		unsigned Q2_COF : 1;      ///< their is CORDIC Overflow, data invalid
+		unsigned Q2_OCF : 1;      ///< Algorithm is finished. If zero, data invalid
+		//------ 1word size
+
+		// 4th and last word, little endian representation
+		//trailing 7 bits that should be ignored
+		unsigned DUMMY_BITS : 7; ///< unimplemented
+		//19 bits for the 2nd knee encoder.
+		unsigned Q3_EVEN_PAR : 1;     ///< even parity bit
+		unsigned Q3_MAG_DEC : 1;      ///< Maginute amplitude decreased.
+		unsigned Q3_MAG_INC : 1;      ///< Maginute amplitude increased.
+		unsigned Q3_LIN : 1;          ///< their is a linearity read alarm, data invalid
+		unsigned Q3_COF : 1;          ///< their is CORDIC Overflow, data invalid
+		unsigned Q3_OCF : 1;          ///< Algorithm is finished. If zero, data invalid
+		unsigned Q3_ENC_DATA_LOW : 3; ///< first 3 bits of data
+		//------ 1word size
+	} b; ///< bits representation
+	unsigned char B[8];///<byte representation
+	unsigned int  w[4];///<word representation
 } DMA_SPI_ME_rx_buffer;
 
 DMA_SPI_ME_rx_buffer dma_spi_me_rx_buffer __attribute__((space(dma)));
 
 
-#define dma_spi_me_start() do{\
-	gpio_clear(dma_spi_me.spi_cs);\
-}while(0)
+#define dma_spi_me_start() do{	  \
+		gpio_clear(dma_spi_me.spi_cs); \
+	}while(0)
 
 
-#define dma_spi_me_stop() do{\
-	gpio_set(dma_spi_me.spi_cs);\
-}while(0)
+#define dma_spi_me_stop() do{	  \
+		gpio_set(dma_spi_me.spi_cs); \
+	}while(0)
 
 
-#define dma_spi_me_start_actual_reading() do{\
-	SPI1BUF = 0x0000; /*force the transfer of dma channel */\
-	dma_spi_me.state = DMA_SPI_ME_READING_DEVICES;\
-}while(0)
+#define dma_spi_me_start_actual_reading() do{	  \
+		SPI1BUF = 0x0000; /*force the transfer of dma channel */ \
+		dma_spi_me.state = DMA_SPI_ME_READING_DEVICES; \
+	}while(0)
 
 
 
 void init_magnetic_encoder(magnetic_encoder * e){
 	e->position = 0;
 	e->flags = ME_F_ONBOARD_PROCESSING_UNFINISHED;
 	e->mult = 1;
 	e->div  = 1;
 }
 
 
 void init_magnetic_encoders(gpio spi_cs){
 	dma_spi_me.spi_cs = spi_cs;
 	dma_spi_me_stop();
 	dma_spi_me.state  = DMA_SPI_ME_IDLE;
 
 	//SPI 1 is for magentic encoders :
 	IEC0bits.SPI1IE     = 0; //disable interrupt. This is needed because we use DMA
 	IFS0bits.SPI1IF     = 0; //clear the interrupt flag.
 
 	SPI1CON1bits.DISSCK = 0; //Us the clock
 	SPI1CON1bits.DISSDO = 1; //Disable data output. This is not needed by the application, no pin are routed
 	SPI1CON1bits.MODE16 = 1; //Transmit word. Rx buffer is in byte, but we don't care because we are transmitting an even number of byte
 	SPI1CON1bits.SMP    = 0; //data is sampled at middle of clock time
 
 	SPI1CON1bits.CKE    = 1; //clock cycle start when going from active to idle clock state.
 	SPI1CON1bits.CKP    = 1; //clock idle state is at high level
 	SPI1CON1bits.MSTEN  = 1; //enable master mode
 
 	//Choose a clock frequency of 625 kHz, max accepted by AS5045 is 1Mhz
 	SPI1CON1bits.SPRE   = 0b111; //Select a secondary prescaler of 1:1
 	SPI1CON1bits.PPRE   = 0b00 ; //select a primary prescaler of 64:1
 
 	SPI1CON2bits.FRMEN  = 0;     //No frame support
 
 	SPI1STATbits.SPIEN  = 1;     //Enable SPI 1 module
 
+
 	DMA2CONbits.CHEN  = 0;
 	DMA2CONbits.SIZE  = 0;
 	DMA2CONbits.DIR   = 0;
 	DMA2CONbits.HALF  = 0;
 
 	DMA2CONbits.NULLW = 1;
 
 	DMA2CONbits.AMODE = 0b00;// Register indirect with posincrement
 	DMA2CONbits.MODE  = 0b01;// One - shot, No Ping Pong
 
 
 	DMA2STA = __builtin_dmaoffset(dma_spi_me_rx_buffer.w);
 
 	DMA2PAD = (volatile unsigned int) & SPI1BUF;
 
 	DMA2REQ = 0x000A;
 	DMA2CNT = 3;
 
 	IFS1bits.DMA2IF = 0;
 	IEC1bits.DMA2IE = 1;
 
 	init_magnetic_encoder(&(mes[0]));
 	init_magnetic_encoder(&(mes[1]));
 	init_magnetic_encoder(&(mes[2]));
 }
 
 #define fill_status(me,ocf_bit,cof_bit,lin_bit,amp_incr_bit,amp_decr_bit) do{ \
-	me.flags = ME_F_OK; \
-	if(!(ocf_bit)){ \
-		me.flags |= ME_F_ONBOARD_PROCESSING_UNFINISHED; \
-	} \
-	if(cof_bit){ \
-		me.flags |=  ME_F_CORDIC_OVERFLOW; \
-	} \
-	if(lin_bit){ \
-		me.flags |= ME_F_LINEARITY_READ_ALARM; \
-	} \
-	if( (amp_incr_bit) && (amp_decr_bit) ) { \
-		me.flags |= ME_F_MAGNETIC_AMPLITUDE_ERROR; \
-	} \
-}while(0)
+		me.flags = ME_F_OK; \
+		if(!(ocf_bit)){ \
+			me.flags |= ME_F_ONBOARD_PROCESSING_UNFINISHED; \
+		} \
+		if(cof_bit){ \
+			me.flags |=  ME_F_CORDIC_OVERFLOW; \
+		} \
+		if(lin_bit){ \
+			me.flags |= ME_F_LINEARITY_READ_ALARM; \
+		} \
+		if( (amp_incr_bit) && (amp_decr_bit) ) { \
+			me.flags |= ME_F_MAGNETIC_AMPLITUDE_ERROR; \
+		} \
+	}while(0)
 
 
 void magnetic_encoders_start_reading(){
 	if(dma_spi_me.state == DMA_SPI_ME_IDLE){
 		dma_spi_me.state = DMA_SPI_ME_WAITING_FOR_DEVICES;
 		DMA2CONbits.CHEN  = 1;
 		dma_spi_me_start();
 		timer_2_start();
 		return;
 	}
 }
 
 
 #define set_me_value(me,value,adr) do{	  \
-	if((me).flags == ME_F_OK){ \
-		(me).position = (long) ((value)) * (me).mult / (me).div; \
-		(me).position &= 0x3fff; \
-	} \
-	sbcp_me_reg(adr,MEX_POSITION).u = (me).position; \
-	if((me).flags & (ME_F_LINEARITY_READ_ALARM | ME_F_CORDIC_OVERFLOW | ME_F_ONBOARD_PROCESSING_UNFINISHED)) { \
-		sbcp_me_reg(adr,MEX_POSITION).u |= 1 << 15; \
-	} \
-	if((me).flags & ME_F_MAGNETIC_AMPLITUDE_ERROR){ \
-		sbcp_me_reg(adr,MEX_POSITION).u |= 1 << 14; \
-	} \
-}while(0)
+		if((me).flags == ME_F_OK){ \
+			unsigned int _TMP_val = value; \
+			if((me).mult < 0){ \
+				_TMP_val = 4096 - _TMP_val; \
+			} \
+			(me).position = (long) _TMP_val * abs((me).mult) / (me).div; \
+			(me).position &= 0x3fff; \
+		} \
+		sbcp_me_reg(adr,MEX_POSITION).u = (me).position; \
+		if((me).flags & (ME_F_LINEARITY_READ_ALARM | ME_F_CORDIC_OVERFLOW | ME_F_ONBOARD_PROCESSING_UNFINISHED)) { \
+			sbcp_me_reg(adr,MEX_POSITION).u |= 1 << 15; \
+		} \
+		if((me).flags & ME_F_MAGNETIC_AMPLITUDE_ERROR){ \
+			sbcp_me_reg(adr,MEX_POSITION).u |= 1 << 14; \
+		} \
+	}while(0)
 
 
 void magnetic_encoders_process(){
 
 
 	if(dma_spi_me.state == DMA_SPI_ME_DATA_READY_TO_BE_PROCESSED){
 
 		//we assume that the parity is always correct.
 		/// \todo : check the parity of the data, buts it's rather complicated.
 
 		//first we check the status
 		fill_status(mes[0],
 		            dma_spi_me_rx_buffer.b.Q1_OCF,
 		            dma_spi_me_rx_buffer.b.Q1_COF,
 		            dma_spi_me_rx_buffer.b.Q1_LIN,
 		            dma_spi_me_rx_buffer.b.Q1_MAG_INC,
 		            dma_spi_me_rx_buffer.b.Q1_MAG_DEC);
 
 		fill_status(mes[1],
 		            dma_spi_me_rx_buffer.b.Q2_OCF,
 		            dma_spi_me_rx_buffer.b.Q2_COF,
 		            dma_spi_me_rx_buffer.b.Q2_LIN,
 		            dma_spi_me_rx_buffer.b.Q2_MAG_INC,
 		            dma_spi_me_rx_buffer.b.Q2_MAG_DEC);
 
 
 		fill_status(mes[2],
 		            dma_spi_me_rx_buffer.b.Q3_OCF,
 		            dma_spi_me_rx_buffer.b.Q3_COF,
 		            dma_spi_me_rx_buffer.b.Q3_LIN,
 		            dma_spi_me_rx_buffer.b.Q3_MAG_INC,
 		            dma_spi_me_rx_buffer.b.Q3_MAG_DEC);
 
 
 		set_me_value(mes[0], (dma_spi_me_rx_buffer.b.Q1_ENC_DATA_HIGH << 8 ) + dma_spi_me_rx_buffer.b.Q1_ENC_DATA_LOW , MDV_ME_Q1);
 		set_me_value(mes[1], (dma_spi_me_rx_buffer.b.Q2_ENC_DATA_HIGH << 8 ) + dma_spi_me_rx_buffer.b.Q2_ENC_DATA_LOW , MDV_ME_Q2);
 		set_me_value(mes[2], (dma_spi_me_rx_buffer.b.Q3_ENC_DATA_HIGH << 8 ) + ( dma_spi_me_rx_buffer.b.Q3_ENC_DATA_MID << 3 ) + dma_spi_me_rx_buffer.b.Q3_ENC_DATA_LOW , MDV_ME_Q3);
 
 
 
 
 		//mark that new data is available in the table.
 		sbcp_mark_new_low_latency_data_available();
 		//we have readen the data, nothing more to do
 		dma_spi_me.state = DMA_SPI_ME_IDLE;
 
 	}
 }
 
 
 /*******************************************************************************
  *
  * Interruption
  *
  ******************************************************************************/
 
 /**
  * Interruption when the SPI 1 finished its reading
  */
 void __attribute__((__interrupt__ , no_auto_psv)) _DMA2Interrupt(){
 	dma_spi_me.state = DMA_SPI_ME_DATA_READY_TO_BE_PROCESSED;
 	dma_spi_me_stop();
 	//clear the interruption flag
 	IFS1bits.DMA2IF = 0;
 }
 
 
 /* Timer 2 is used to create the delay to communicate over the SPI1 bus */
 void __attribute__((__interrupt__, no_auto_psv)) _T2Interrupt(void){
 	/* Interrupt Service Routine code goes here */
 	timer_2_stop_and_clear();
 	dma_spi_me_start_actual_reading();
 	IFS0bits.T2IF = 0; 		// Clear Timer 2 Interrupt Flag
 }
 
 
 
 void me_set_gear_ratio(magnetic_encoder * e, int mult, int div){
 	if(div == 0) {
 		div = 1;
 	}
 	e->mult = mult;
 	e->div = div;
 }
 
 
 int me_get_gear_mult(magnetic_encoder * e){
 	return e->mult;
 }
 int me_get_gear_div(magnetic_encoder * e){
 	return e->div;
 }
 
 int me_get_value(magnetic_encoder * e){
 	return e->position;
 }
 
 me_error_flags me_get_error(magnetic_encoder * e){
 	return e->flags;
 }
 
 
 void me_load_persistent_sbcp_settings(){
 	me_set_gear_ratio(me1,
 	                  sbcp_me_reg(MDV_ME_Q1,MEX_GEAR_MULT).i,
 	                  sbcp_me_reg(MDV_ME_Q1,MEX_GEAR_DIV).i);
 
 	me_set_gear_ratio(me2,
 	                  sbcp_me_reg(MDV_ME_Q2,MEX_GEAR_MULT).i,
 	                  sbcp_me_reg(MDV_ME_Q2,MEX_GEAR_DIV).i);
 
 	me_set_gear_ratio(me3,
 	                  sbcp_me_reg(MDV_ME_Q3,MEX_GEAR_MULT).i,
 	                  sbcp_me_reg(MDV_ME_Q3,MEX_GEAR_DIV).i);
 
 }
diff --git a/src/magnetic_encoder.h b/src/magnetic_encoder.h
index 4dc2447..332ef5c 100644
--- a/src/magnetic_encoder.h
+++ b/src/magnetic_encoder.h
@@ -1,44 +1,50 @@
 #ifndef MAGNETIC_ENCODER_H_
 #define MAGNETIC_ENCODER_H_
 
 #include <gpio.h>
 
 struct magnetic_encoder;
 
 typedef struct magnetic_encoder magnetic_encoder;
 
 
 
 
 void init_magnetic_encoders(gpio spi_cs);
 
 void magnetic_encoders_process();
 void magnetic_encoders_start_reading();
 
 void me_load_persistent_sbcp_settings();
 
 enum me_error_flags {
 	ME_F_OK                            = 0 ,
 	ME_F_LINEARITY_READ_ALARM          = 1 << 0,
 	ME_F_CORDIC_OVERFLOW               = 1 << 1,
 	ME_F_ONBOARD_PROCESSING_UNFINISHED = 1 << 2,
 	ME_F_MAGNETIC_AMPLITUDE_ERROR      = 1 << 3
 };
 
 typedef enum me_error_flags me_error_flags;
 
 
 void me_set_gear_ratio(magnetic_encoder * e, int mult, int div);
 
 
 int me_get_gear_mult(magnetic_encoder * e);
 int me_get_gear_div(magnetic_encoder * e);
 
 int me_get_value(magnetic_encoder * e);
 
 me_error_flags me_get_error(magnetic_encoder * e);
 
+
+
 extern magnetic_encoder * me1,* me2,* me3;
 
 
+
+
+
+
 #endif //MAGNETIC_ENCODER_H_
diff --git a/src/main.c b/src/main.c
index c1de3bd..0cd8c71 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,286 +1,285 @@
-#include "config.h"
+ #include "config.h"
 #include <libpic30.h>
 #include "pindefs.h"
 #include "motordriver.h"
 
 #include "timer.h"
 #include "sbcp_mdv.h"
 #include "magnetic_encoder.h"
 #include "load_cell.h"
 
 
 
 
 
 /** C O N F I G ****************************************************/
 // See "p33fj128mc804.h" for all config settings.
 // Code Protect off, Write protect disabled
 _FGS(GSS_OFF & GWRP_OFF);
 // Prim. Osc (XT, HS, EC) w/ PLL, Two speed osc off, Temp protect off
 _FOSCSEL(FNOSC_PRIPLL);
 // Clock Switch & Clock Monitor off, OSC2 is IO, external clock generation
-_FOSC(FCKSM_CSDCMD & OSCIOFNC_ON & POSCMD_EC);
+_FOSC(FCKSM_CSDCMD & OSCIOFNC_ON & POSCMD_EC & IOL1WAY_OFF );
 // Watchdog Timer Disabled
 _FWDT(FWDTEN_OFF);
 // No PWM off delay, PWM controlled by port configuration at device reset
 _FPOR(FPWRT_PWR1);
 // No JTAG, debugging on PGD1 pins
 _FICD(JTAGEN_OFF & ICS_PGD1);
 
 
 extern unsigned int volatile systime;
 unsigned int prev_systime;
 
 void clock_init() {
 	// Configure PLL prescaler, PLL postscaler and PLL divisor
 	// 8MHz oscillator
 	// frequency = Fin * M / (N1 * N2)
 	// Maximum frequency is 80MHz = 40MIPS
 	// => 8*40/(2*2)
 
 	PLLFBD = 38; 				// M = 40
 	CLKDIVbits.PLLPOST=0; 		// N2 = 2
 	CLKDIVbits.PLLPRE=0; 		// N1 = 2
 }
 
 /*void pwm_init() {
 
 // initialize PWM channels
 // ***************** PWM section *****************
 // P1TCON, P2TCON
 // -> pwm enabled, pwm stops in idle mode, postscale 1:1, prescale 1:1, free run mode
 P1TCON = 0x00; // PTEN (1), DC (1), PTSIDL (1), DC (5), PTOPS (4), PTCKPS (2), PTMOD (2)
 P2TCON = 0x00; // PTEN (1), DC (1), PTSIDL (1), DC (5), PTOPS (4), PTCKPS (2), PTMOD (2)
 P1TCONbits.PTEN = 1;
 P2TCONbits.PTEN = 1;
 
 
 // PWM1CON1, PWM2CON1
 // -> only high side pwm channel is used
 PWM1CON1 = 0b0000011101110000; // DC (5), independent mode (3), DC (1), enable PWM1Hx (3), DC (1), PWM1Lx is IO-pin (3)
 PWM2CON1 = 0b0000000100010000; // DC (7), independent mode (1), DC (3), enable PWM2Hx (1), DC (3), PWM2Lx is IO-pin (1)
 
 // P1TPER, P2TPER
 // see p.14-25 ref manual motorcontrol dspic33f
 P1TPER = MAX_PWM;
 P2TPER = MAX_PWM;
 
 // initialize as 0 voltage
 P1DC1 = 0;
 P1DC2 = 0;
 P1DC3 = 0;
 P2DC1 = 0;
 //	PWM_TRQ1 = 0;
 //	M1_SET_PWM(0);
 //	PWM_TRQ2 = 0;
 //	M2_SET_PWM(0);
 }*/
 
 void qei_init() {
 	// Enable pullup on B8-B11 (encoder inputs)
 	//	__builtin_write_OSCCONL(0b10000000);//unlock peripheral pinsettings (p.168 manual)
 	_QEA1R = 20;
 	_QEB1R = 21;
 	_QEA2R = 6;
 	_QEB2R = 7;
 	//	__builtin_write_OSCCONL(0b11000000);//lock pereriphal pinsettings
 
 	// ***************** QEI section *****************
 	QEI1CON  = 0b0000011100000000; // CNTERR(1), unused(1), QEISIDL(1), INDEX(1), UPDN(1), QEIM(3), SWPAB(1), PCDOUT(1), TQGATE(1), POSRES(2) (prescale), POSRES(1), TQCS(1), UPDN_SRC(1)
 	DFLT1CON = 0b0000000110100000; // unused(5), IMV(2), CEID(1), QEOUT(1), QECK(3), unused(4) -> digital filter 1:4
 	MAX1CNT  = 0xffff;//maxcount for qei position.
 	QEI2CON  = 0b0000011100000000;
 	DFLT2CON = 0b0000000110100000;
 	MAX2CNT  = 0xffff;//maxcount for qei position.
 
 	mdv_reset_count(mdv1);
 	mdv_reset_count(mdv2);
 
 }
 
 void delay_ms(unsigned int t) {
 	uint16_t i;
 	for (i=0; i<t; i++) {
 		__delay_ms(1);
 	}
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 
 int main (void) {
 
 
 	// wait a little bit
 	delay_ms(100);
 
 	clock_init();
 	pin_init();
 
 
 
 	// enable motordrivers reset
 	mdv_master_reset_enable();
 
 	mdv_pin pins[2] =
 		{
 			{
 				gpio_create(GPIO_PORT_A,GPIO_PIN_3,GPIO_OUTPUT), //brake
 				gpio_create(GPIO_PORT_A,GPIO_PIN_4,GPIO_OUTPUT), //coast
 				gpio_create(GPIO_PORT_B,GPIO_PIN_11,GPIO_OUTPUT), //dir
 				gpio_create(GPIO_PORT_C,GPIO_PIN_3,GPIO_OUTPUT), //mode
 			},
 			{
 				gpio_create(GPIO_PORT_A,GPIO_PIN_10,GPIO_OUTPUT), //brake
 				gpio_create(GPIO_PORT_A,GPIO_PIN_8,GPIO_OUTPUT), //coast
 				gpio_create(GPIO_PORT_A,GPIO_PIN_7,GPIO_OUTPUT), //dir
 				gpio_create(GPIO_PORT_A,GPIO_PIN_9,GPIO_OUTPUT), //mode
 			}
 		};
 
 	pwm_init(&(pins[0].torque),PWM_1_1);
 	pwm_set_cycle(pins[0].torque, MAX_PWM);
 	pwm_set_value(pins[0].torque, 0);
 
 	pwm_init(&(pins[0].speed),PWM_1_3);
 	pwm_set_cycle(pins[0].speed, MAX_PWM);
 	pwm_set_value(pins[0].speed, 0);
 
 	pwm_init(&(pins[1].torque),PWM_2_1);
 	pwm_set_cycle(pins[1].torque, MAX_PWM);
 	pwm_set_value(pins[1].torque, 0);
 
 	pwm_init(&(pins[1].speed),PWM_1_2);
 	pwm_set_cycle(pins[1].speed, MAX_PWM);
 	pwm_set_value(pins[1].speed, 0);
 
 	qei_init();
 
 	init_motordrivers(&(pins[0]),&(pins[1]));
 
 
 	//now set the right default value for motor
 
 	mdv_get_parameters(mdv1)->p_gain = 400;
 	mdv_get_parameters(mdv1)->i_gain = 20;
 	mdv_get_parameters(mdv1)->d_gain = 200;
 
 	mdv_get_parameters(mdv1)->preload   = MAX_DUTY;
 	mdv_get_parameters(mdv1)->stiffness = 0;
 	mdv_get_parameters(mdv1)->damping   = 0;
 
-	mdv_set_maximal_torque(mdv1 , 10/256 * MAX_DUTY);
-	mdv_set_maximal_acceleration(mdv1 , 1000);
-	mdv_set_maximal_speed(mdv1 , 10000);
+        mdv_set_gear_ratio(mdv1,675,8);
+
+
+	mdv_set_maximal_torque(mdv1 , (long) 100 * (long)MAX_DUTY / (long)256);
+	mdv_set_maximal_acceleration(mdv1 , 32767);
+	mdv_set_maximal_speed(mdv1 , 32767);
 
 	//limit position set by calibration !!!
 
-        mdv_set_gear_ratio(mdv1,675,8);
 
 
 
 	mdv_get_parameters(mdv2)->p_gain = 400;
 	mdv_get_parameters(mdv2)->i_gain = 20;
 	mdv_get_parameters(mdv2)->d_gain = 200;
 
 	mdv_get_parameters(mdv2)->preload   = MAX_DUTY;
 	mdv_get_parameters(mdv2)->stiffness = 0;
 	mdv_get_parameters(mdv2)->damping   = 0;
 
-	mdv_set_maximal_torque(mdv2 , 10/256 * MAX_DUTY);
-	mdv_set_maximal_acceleration(mdv2 , 1000);
-	mdv_set_maximal_speed(mdv2 , 10000);
-
-
+        mdv_set_gear_ratio(mdv2,225,4);
 
+	mdv_set_maximal_torque(mdv2 , (long)100 * (long)MAX_DUTY / (long)256);
+	mdv_set_maximal_acceleration(mdv2 , 32767);
+	mdv_set_maximal_speed(mdv2 , 32767);
 
 
-        mdv_set_gear_ratio(mdv2,225,4);
-
 	// RS485 communication init
 	timer_init();
 
 
 	init_magnetic_encoders(gpio_create(GPIO_PORT_B,GPIO_PIN_4,GPIO_OUTPUT));
 
-        me_set_gear_ratio(me1,25,12);
+        me_set_gear_ratio(me1,12,25);
         me_set_gear_ratio(me2,1,1);
         me_set_gear_ratio(me3,1,1);
 
-        init_load_cells(gpio_create(GPIO_PORT_B,GPIO_PIN_5,GPIO_OUTPUT));
-
+        init_load_cells();
+        
 
 	sbcp_settings s;
 	gpio send_enable = gpio_create(GPIO_PORT_C,GPIO_PIN_2,GPIO_OUTPUT);
 
 
 	//we init with receive_disable == send_enable since there is only one pin.
 	sbcp_init_settings(&s,
 	                   SBCP_MDV_CLASS,
 	                   SBCP_MDV_THIS_DEVICE_INITIAL_ID,
 	                   SBCP_MDV_FIRMWARE_VERSION,send_enable,send_enable);
 
 	s.baudrate = SBCP_MDV_BAUDRATE;
 	s.clock_frequency = FCY_FOR_BAUDRATE;
 	s.uart = UART_1;
 	s.timeout_frequency = SBCP_MDV_TIMEOUT;
 
 	s.init_register = &init_sbcp_mdv_registers;
 	s.init_instruction = &init_sbcp_mdv_instructions;
 
 
         map_pin_to_periph_output(17,RP_U1TX);
         uart_map_rx_input(UART_1,16);
 
 	sbcp_init(&s);
 
 
 	//now set again the persistent parameters !!!
 	mdv_load_persistent_sbcp_settings();
 	me_load_persistent_sbcp_settings();
         lc_load_persistent_sbcp_settings();
 
 
 	prev_systime = 0;
 
 	// disable motordrivers reset, we are running boys!!
         mdv_master_reset_disable();
 
 
 	while (1) {
 		// run indefinetly
 
 		// check if system time has changed
-		if (systime != prev_systime) {
+		if (systime != prev_systime) { // every 1ms
 			prev_systime = systime;
 			// order of processes determines priority
 			// motor control process is most sensitive to timing
 			mdv_process(mdv1);
 			mdv_process(mdv2);
 
 
-			//sensor reading process, just meke one reading each 1ms
+			//sensor reading process, just make one reading each 1ms
 			//            cpg_main(&cpg);
 			//			sine_main(&sine);
                         magnetic_encoders_start_reading();
                         load_cell_start_reading();
 
-                        if(PORTBbits.RB13){
+                        if(BLINK){
                             LED_ENABLE;
                         } else {
                             LED_DISABLE;
                         }
 		}
 
 		// put here processes which do not depend on the system timer
 		//no need to fucking check prev_systime == systime, if this is not the
 		//case it means that the critical part last more than one loop
 		//increment,so we are fubar
 
 
 		magnetic_encoders_process();
                 load_cell_process();
 
 		sbcp_process();
 
 	}
 }
diff --git a/src/mdv_control_modes.c b/src/mdv_control_modes.c
index bbc3123..4955d20 100644
--- a/src/mdv_control_modes.c
+++ b/src/mdv_control_modes.c
@@ -1,229 +1,317 @@
 #include "mdv_control_modes.h"
 
 #include "mdv_speed_pid.h"
 
 #include "misc_math.h"
 
+#include "cos_table.h"
+
+#include "sbcp_mdv.h"
 
 
 void mdv_coast_init(motordriver * mdv){
 	gpio_set(mdv->pins.brake);
 	gpio_clear(mdv->pins.coast);
 }
 
 void mdv_brake_init(motordriver * mdv){
 	gpio_set(mdv->pins.coast);
 	gpio_clear(mdv->pins.brake);
 
 }
 
 void mdv_position_process(motordriver * mdv){
 	if(mdv_flag(mdv,MDV_F_NEW_POSITION_AVAILABLE)){
-		int abs_speed = abs(mdv->goal_speed > 0);
+                mdv->goal_pos = mdv_e2i_position(mdv,mdv->user_goal_pos);
+
+                mdv->goal_pos = clamp(mdv->goal_pos,0,mdv->pos_limit);
+                mdv->goal_speed = clamp_absolute(mdv_lo2hi_res_speed(mdv->goal_pos - mdv->moving_pos) / mdv->params.smooth_interval ,mdv->max_speed );
+
+                int abs_speed = abs(mdv->goal_speed);
 
+                //mdv->goal_pos = mdv->moving_pos + (mdv->goal_pos - mdv->moving_pos)*(long)(SMOOTH_POSITION_OVERSHOOT + 1 );
+                
 		//disable moving during play with parameter
 		mdv_clear_flag(mdv,MDV_F_MOVING_ENABLE);
 		//checks that the set speed is correct !!!!!! users could be morrons
 		// and move motor if needed
-		if(mdv->goal_pos != mdv-> moving_pos ){
+		if(mdv->goal_pos != mdv-> moving_pos ) {
 			if (mdv->goal_pos > mdv-> moving_pos) {
 				mdv->goal_speed = abs_speed;
 			} else {
 				mdv->goal_speed = -abs_speed;
 			}
 			mdv_set_flag(mdv,MDV_F_MOVING_ENABLE);
 		}
 		mdv_clear_flag(mdv,MDV_F_NEW_POSITION_AVAILABLE);
 	}
 	//now process normally
 	mdv_speed_pid_with_compliance_process(mdv);
 }
 
 void mdv_position_init(motordriver * mdv){
 	gpio_set(mdv->pins.coast);
 	gpio_set(mdv->pins.brake);
 
 }
 
 void mdv_velocity_process(motordriver * mdv){
 	if(mdv_flag(mdv,MDV_F_NEW_SPEED_AVAILABLE)){
 
 		mdv_clear_flag(mdv,MDV_F_MOVING_ENABLE);
 		//set flag if needed, and set the right goal position if user
 		// modify it
 		if(mdv->goal_speed > 0){
 			mdv->goal_pos = mdv->pos_limit;
 			if(mdv->moving_pos < mdv->goal_pos ){
 				mdv_set_flag(mdv,MDV_F_MOVING_ENABLE);
 			}
 		} else if (mdv->goal_speed < 0){
 			mdv->goal_pos = 0;
 			if(mdv->moving_pos > 0 ){
 				mdv_set_flag(mdv,MDV_F_MOVING_ENABLE);
 			}
 		}
 
 		mdv_clear_flag(mdv, MDV_F_NEW_SPEED_AVAILABLE);
 	}
 
 	mdv_speed_pid_with_compliance_process(mdv);
 }
 
 void mdv_velocity_init(motordriver * mdv){
 	gpio_set(mdv->pins.coast);
 	gpio_set(mdv->pins.brake);
 }
 
 
-
 void mdv_smooth_position_process(motordriver * mdv){
 	/// \todo implement safety where if no data is available for an
 	///       amount of time, we switch to COAST mode
-	if(mdv_flag(mdv,MDV_F_NEW_POSITION_AVAILABLE)){
-		// compute new desired speed, clamp within the range of integers
 
+        if(mdv_flag(mdv,MDV_F_NEW_POSITION_AVAILABLE))
+        {
+            pushIntoBuffer(&mdv->commandsBuffer, mdv->user_goal_pos);
+        }
 
-                int new_speed = clamp_absolute(mdv_lo2hi_res_speed(mdv->goal_pos - mdv->moving_pos) / mdv->params.smooth_interval ,
-		                               mdv->max_speed );
+        // starts the logging of commands whend half the capacity is reached.
+        // can be changed to 3/4 or any other fraction of the capacity.
+        // this fraction can also be precomputed for more efficiency
+        if(!mdv->startSendOrders && mdv->commandsBuffer.numVals >= BUFFER_CAPACITY/2)
+        {
+            mdv->startSendOrders = 1;
+        }
 
-		mdv_clear_flag(mdv,MDV_F_MOVING_ENABLE);
-		mdv->goal_speed = new_speed;
+	if(!mdv->startSendOrders)
+        {
+            mdv_speed_pid_with_compliance_process(mdv);
+            return;
+        }
+
+        if(mdv->timeCounter < mdv->params.smooth_interval)
+        {
+            ++(mdv->timeCounter);
+            mdv_speed_pid_with_compliance_process(mdv);
+            return;
+        }
 
-		mdv->goal_pos = mdv->moving_pos + (mdv->goal_pos - mdv->moving_pos)*(long)(SMOOTH_POSITION_OVERSHOOT + 1 );
+        //actually sends the orders  if the buffer is not empty.
+        if(mdv->commandsBuffer.numVals > 0)
+        {
+            //gets the goal position from the buffer.
+            mdv->goal_pos = mdv_e2i_position(mdv,popFromBuffer(&mdv->commandsBuffer));
 
-		// limit position
-		mdv->goal_pos = clamp(mdv->goal_pos,0,mdv->pos_limit);
+            // compute new desired speed, clamp within the range of integers
+            long new_speed = clamp_absolute(mdv_lo2hi_res_speed(mdv->goal_pos - mdv->moving_pos) / mdv->params.smooth_interval ,
+                                           mdv->max_speed );
 
-		// update goal position
-		if (mdv->goal_pos != mdv->moving_pos) {
-			// enable new movement
-			mdv_set_flag(mdv, MDV_F_MOVING_ENABLE);
-		}
+            mdv_clear_flag(mdv,MDV_F_MOVING_ENABLE);
+            mdv->goal_speed = new_speed;
 
-		mdv_clear_flag(mdv,MDV_F_NEW_POSITION_AVAILABLE);
-	}
+            mdv->goal_pos = mdv->moving_pos + (mdv->goal_pos - mdv->moving_pos)*(long)(SMOOTH_POSITION_OVERSHOOT + 1 );
 
-	mdv_speed_pid_with_compliance_process(mdv);
-}
+            // limit position
+            mdv->goal_pos = clamp(mdv->goal_pos,0,mdv->pos_limit);
 
+            // update goal position
+            if (mdv->goal_pos != mdv->moving_pos) {
+                    // enable new movement
+                    mdv_set_flag(mdv, MDV_F_MOVING_ENABLE);
+            }
+
+            mdv_clear_flag(mdv,MDV_F_NEW_POSITION_AVAILABLE);
+        }
+        mdv->timeCounter = 0;
+        mdv_speed_pid_with_compliance_process(mdv);
+}
 
 
 void mdv_smooth_position_init(motordriver * mdv){
 	gpio_set(mdv->pins.coast);
 	gpio_set(mdv->pins.brake);
+
+        initBuffer(&mdv->commandsBuffer);
+        mdv->timeCounter = 0;
+        mdv->startSendOrders = 0;
 }
 
 
 #define MDV_RUNTIME_CALIBRATION_SUCCESSFUL 0xffff
 
 
 #define mdv_rc_in_calibration_region(min,max,pos) ( (min) < (max) ? ( ( (min) <= (pos) ) && ( (pos) <= (max) ) ) : ( ( (pos)  <= (max)  ) || ( (min) <= (pos) ) ) )
 
 /**
  * returns 0xffff if calibration is over, otherwise a 12 bits unsigned
  * int being the real position.
  */
 
 int mdv_rc_check_and_calibrate(motordriver * mdv){
 
 	/* readout the real position */
 	int pos = (*(mdv->calib.pos_evaluator))();
 
 
 	if(mdv_rc_in_calibration_region(mdv->calib.min_region,mdv->calib.max_region,pos)){
 
 		//we check how much far away we are from the min position, in increments, and we map it to
 		//the 0 position, and add the offset.
-
-		long actual_position = mdv_e2i_position(mdv, pos - mdv->calib.min_region) + mdv->calib.offset;
+		long actual_position = (long)pos - (long)mdv->calib.min_region + (long)mdv->calib.offset;
+		if(actual_position < 0 ){
+			actual_position += mdv->calib.pos_evaluator_max_value;
+		}
+		actual_position = mdv_e2i_position(mdv,actual_position);
 
 		mdv->pos_limit = mdv_e2i_position(mdv,mdv->calib.pos_limit);
 
 		mdv_set_pos_count(mdv,actual_position);
 
 		return MDV_RUNTIME_CALIBRATION_SUCCESSFUL;
 	}
 
 	return pos;
 
 }
 
 void mdv_runtime_calibration_init(motordriver * mdv){
 	gpio_set(mdv->pins.brake);
-	gpio_set(mdv->pins.coast);
+	gpio_clear(mdv->pins.coast);
 
-        //this sets an update of 10 ms, and make sure that the next process will
-        //compute an update.
+	//this sets an update of 10 ms, and make sure that the next process will
+	//compute an update.
 	mdv->calib.update_period = 10;
 	mdv->calib.ellapsed_ts = 10;
 }
 
 
 void mdv_runtime_calibration_process(motordriver * mdv){
 
 	//first we check if we can calibrate
 	int pos = mdv_rc_check_and_calibrate(mdv);
 
 	if (pos == MDV_RUNTIME_CALIBRATION_SUCCESSFUL ){
 		//yes, and calibrated , so go back to COAST
-		mdv_set_control_mode(mdv,MDV_M_COAST);
+		mdv->sc.status |= MDV_RUNTIME_CALIBRATED;
+		mdv_set_control_mode_private(mdv,MDV_M_COAST);
 		return;
 	}
 
 	//now check if we need an update of the target (every mdv->calib.update_period)
 	if( (++(mdv->calib.ellapsed_ts)) <= mdv->calib.update_period ) {
 		//no update needed, just process PID and return
 		mdv_speed_pid_with_compliance_process(mdv);
 		return;
 	}
 
 	//we need to compute a new update update.
 
 	mdv->calib.ellapsed_ts = 0;
 
-	unsigned int mini = mdv->calib.min_region;
-	unsigned int maxi = mdv->calib.max_region;
+	int mini = mdv->calib.min_region;
+	int maxi = mdv->calib.max_region;
 
 	long target_position;
 
 	/* first put the actual absolute error in target position */
-        // the boundary are clean
+	// the boundary are clean
 	if (mini < maxi){
 		target_position = (mini + maxi) / 2 - pos ;
 	} else { //max has an overshoot, we should take it into account
 		target_position = (mini + maxi + mdv->calib.pos_evaluator_max_value + 1) / 2 - pos;
 	}
 
-        //check for the shortest path !!!
-        if(abs(target_position) > ANGULAR_RESOLUTION / 2){
-            //we should make more than half a turn, so we go in the other direction !!!
-            //case target > 0 remove ANGULAR_RESOLUTION
-            //case target < 0 add ANGULAR_RESOLUTION
-            target_position += ANGULAR_RESOLUTION * ((target_position > 0) ? -1 : 1);
-        }
+	//check for the shortest path !!!
+	if(abs(target_position) > ANGULAR_RESOLUTION / 2){
+		//we should make more than half a turn, so we go in the other direction !!!
+		//case target > 0 remove ANGULAR_RESOLUTION
+		//case target < 0 add ANGULAR_RESOLUTION
+		target_position += ANGULAR_RESOLUTION * ((target_position > 0) ? -1 : 1);
+	}
 
-        //don't forget to put this in the right dimension
+	//don't forget to put this in the right dimension
 	target_position = mdv_e2i_position(mdv,target_position);
 
 	//IGNORE POSITION_LIMIT !!!!!
 
 	//we now now our next target
 	mdv->goal_pos   =  target_position + mdv->pos_cnt ;
 
-	if(mdv->goal_pos != mdv->moving_pos){
+	if(mdv->goal_pos != mdv->pos_cnt){
 		mdv_set_flag(mdv,MDV_F_MOVING_ENABLE);
 	} else {
 		mdv_clear_flag(mdv,MDV_F_MOVING_ENABLE);
 	}
 
 
-	mdv->goal_speed =  mdv_lo2hi_res_speed((mdv->goal_pos - mdv->moving_pos) / mdv->calib.update_period);
+	mdv->goal_speed =  mdv_lo2hi_res_speed((mdv->goal_pos - mdv->pos_cnt) / mdv->calib.update_period);
+
+	//prevent the speed to exceed 2 turn per minute of the effector i.e. ANGULAR_RESOLUTION / 30.
+	long max_speed = mdv_e2i_speed(mdv, ANGULAR_RESOLUTION / 30);
+	mdv->goal_speed = clamp_absolute(mdv->goal_speed,max_speed);
 
-        //prevent the speed to exceed 2 turn per minute of the effector i.e. ANGULAR_RESOLUTION / 30.
-	mdv->goal_speed = clamp_absolute(mdv->goal_speed,
-                                         mdv_e2i_speed(mdv,ANGULAR_RESOLUTION / 30));
 
 	//now process the speed pid
 	mdv_speed_pid_with_compliance_process(mdv);
+	//activate move now
+	gpio_set(mdv->pins.coast);
+
+}
 
+void mdv_sine_generator_init(motordriver * mdv){
+	mdv->sine.t = COS_TABLE_SIZE / 4 - 1;
+	mdv->sine.t_residue = 0;
+	mdv->sine.iter = 4;
+	mdv_set_smooth_interval(mdv,5);
+	mdv_smooth_position_init(mdv);
+}
+
+
+void mdv_sine_generator_process(motordriver * mdv){
+	sbcp_reg_address r = mdv == mdv1 ? MDV_SINE_1 : MDV_SINE_2;
+	int16_t frequency = sbcp_reg_table[r + SINE_FREQUENCY].i;
+	mdv->sine.t += frequency / 100;
+	mdv->sine.t_residue += frequency % 100;
+	if(mdv->sine.t_residue > 100){
+		mdv->sine.t += 1;
+		mdv->sine.t_residue -= 100;
+	}
+
+	if(mdv->sine.t > COS_TABLE_SIZE){
+		mdv->sine.t -= COS_TABLE_SIZE;
+	}
+
+	mdv->sine.iter += 1;
+
+        //seems strange but we clear the flag, only us could move the motor
+        //if we need.
+        mdv_clear_flag(mdv,MDV_F_NEW_POSITION_AVAILABLE);
+
+	if(mdv->sine.iter % 5 == 0){
+		mdv->sine.iter = 0;
+		int16_t amp = sbcp_reg_table[r + SINE_AMPLITUDE].i;
+		int16_t offset = sbcp_reg_table[r + SINE_OFFSET].i;
+                long pos = (long)amp * (long)cos_table[mdv->sine.t] / (long)2048 + (long)offset ;
+		mdv_set_goal_position(mdv, pos & 0xffff);
+	}
+	mdv_smooth_position_process(mdv);
 }
diff --git a/src/mdv_control_modes.h b/src/mdv_control_modes.h
index ac851c7..a0388c5 100644
--- a/src/mdv_control_modes.h
+++ b/src/mdv_control_modes.h
@@ -1,33 +1,35 @@
 #ifndef MDV_CONTROL_MODES_H_
 #define MDV_CONTROL_MODES_H_
 
 
 #include "mdv_internal.h"
 
 /**
  * A mdv_ctrl_process_fptr function that does nothing.
  */
 void mdv_null_process(motordriver * mdv);
 
 void mdv_coast_init(motordriver * mdv);
 //Null process for coast mode
 
 void mdv_brake_init(motordriver * mdv);
 //Null process for brake mode
 
 void mdv_position_init(motordriver * mdv);
 void mdv_position_process(motordriver * mdv);
 
 void mdv_velocity_init(motordriver * mdv);
 void mdv_velocity_process(motordriver * mdv);
 
 void mdv_smooth_position_init(motordriver * mdv);
 void mdv_smooth_position_process(motordriver * mdv);
 
 
 void mdv_runtime_calibration_init(motordriver * mdv);
 
 void mdv_runtime_calibration_process(motordriver * mdv);
 
+void mdv_sine_generator_init(motordriver * mdv);
+void mdv_sine_generator_process(motordriver * mdv);
 
 #endif //MDV_CONTROL_MODES_H_
diff --git a/src/mdv_internal.c b/src/mdv_internal.c
index 2bb967b..bb9eaa6 100644
--- a/src/mdv_internal.c
+++ b/src/mdv_internal.c
@@ -1,46 +1,54 @@
 #include "mdv_internal.h"
 #include "mdv_control_modes.h"
 
 
 mdv_ctrl_fptr mdv_ctrl[MDV_NUMBER_OF_CONTROL_MODE] = {
-    {&mdv_null_process,&mdv_coast_init},
-    {&mdv_null_process,&mdv_brake_init},
-    {&mdv_position_process,&mdv_position_init},
-    {&mdv_velocity_process,&mdv_velocity_init},
-    {&mdv_smooth_position_process,&mdv_smooth_position_init},
-    {&mdv_null_process,&mdv_coast_init},
-    {&mdv_runtime_calibration_init, &mdv_runtime_calibration_process}
+	{&mdv_null_process,&mdv_coast_init},
+	{&mdv_null_process,&mdv_brake_init},
+	{&mdv_position_process,&mdv_position_init},
+	{&mdv_velocity_process,&mdv_velocity_init},
+	{&mdv_smooth_position_process,&mdv_smooth_position_init},
+	{&mdv_null_process,&mdv_coast_init},
+	{&mdv_runtime_calibration_process, &mdv_runtime_calibration_init},
+        {&mdv_sine_generator_process,&mdv_sine_generator_init}
 };
 
 
 void mdv_null_process(motordriver * mdv){
 	pwm_set_value(mdv->pins.speed,MAX_PWM / 2);
 	pwm_set_value(mdv->pins.torque,MAX_PWM / 2);
 }
 
 void mdv_cleanup(motordriver * mdv) {
-    mdv->goal_pos     = mdv->pos_cnt;
-    mdv->moving_pos   = mdv->pos_cnt;
-    mdv->goal_speed   = 0;
-    mdv->moving_speed = 0;
-    mdv->output_trq   = 0;
-    mdv->prev_p_error = 0;
-    mdv->i_error      = 0;
-    mdv_clear_flag(mdv,MDV_F_MOVING_ENABLE |
-                       MDV_F_UPDATE_I_ERROR |
-                       MDV_F_NEW_POSITION_AVAILABLE |
-                       MDV_F_NEW_SPEED_AVAILABLE);
+	mdv->goal_pos     = mdv->pos_cnt;
+	mdv->moving_pos   = mdv->pos_cnt;
+	mdv->goal_speed   = 0;
+	mdv->moving_speed = 0;
+	mdv->output_trq   = 0;
+	mdv->prev_p_error = 0;
+	mdv->i_error      = 0;
+	mdv_clear_flag(mdv,MDV_F_MOVING_ENABLE |
+	               MDV_F_UPDATE_I_ERROR |
+	               MDV_F_NEW_POSITION_AVAILABLE |
+	               MDV_F_NEW_SPEED_AVAILABLE);
 }
 
 
 void mdv_set_pos_count(motordriver * mdv, long pos){
 
 	IEC0bits.T1IE = 0;
 
 	mdv->previous_cnt   = pos;
 	mdv->pos_cnt        = pos;
-        *(mdv->pos_counter) = pos;
+	*(mdv->pos_counter) = pos;
 
 	IEC0bits.T1IE = 1;
 
 }
+
+
+void mdv_set_control_mode_private(motordriver * mdv , mdv_control_mode c){
+	mdv_cleanup(mdv);
+	mdv->sc.mode = c;
+	(*(mdv_ctrl[c].init))(mdv);
+}
diff --git a/src/mdv_internal.h b/src/mdv_internal.h
index d32658d..bdcdd79 100644
--- a/src/mdv_internal.h
+++ b/src/mdv_internal.h
@@ -1,276 +1,287 @@
 #ifndef MDV_INTERNAL_H_
 #define MDV_INTERNAL_H_
 
 #include "motordriver.h"
 
 #include "config.h"
 
+#include "ring-buffer.h"
+
 //==============================================================================
 // DEFINES
 //==============================================================================
 
 //nb increment of QEI encoder
 #define QEI_RES 512UL
 
 #define QEI_CNT_PER_TURN (QEI_RES * 4)
 
 
 //compute the gear coeff, not done automatically !!!
 
 // GEAR_MULT_COEFF     512 * 4     1
 //----------------- = --------- = ---
 // GEAR_DIV_COEFF        4096      2
 
 #define GEAR_MULT_COEFF 1
 #define GEAR_DIV_COEFF  2
 
 #define HALL_RES 12UL
 
 //max speed of the motor in RPM
 #define MAX_SPEED_RPM 16200UL
 
 
 //==============================================================================
 // CONTROL DATA FOR MOTORDRIVER
 //==============================================================================
 
 
 enum mdv_flags {
-    MDV_F_NO_FLAGS = 0,
-    MDV_F_MOVING_ENABLE          = 1 << 0,
-    MDV_F_UPDATE_I_ERROR         = 1 << 1,
-    MDV_F_NEW_POSITION_AVAILABLE = 1 << 2,
-    MDV_F_NEW_SPEED_AVAILABLE    = 1 << 3
+	MDV_F_NO_FLAGS = 0,
+	MDV_F_MOVING_ENABLE          = 1 << 0,
+	MDV_F_UPDATE_I_ERROR         = 1 << 1,
+	MDV_F_NEW_POSITION_AVAILABLE = 1 << 2,
+	MDV_F_NEW_SPEED_AVAILABLE    = 1 << 3
 };
 
 typedef enum mdv_flags mdv_flags;
 
 #define mdv_set_flag(m,f) do{ (m)->flags |= (f); }while(0)
 
 #define mdv_clear_flag(m,f) do { (m)->flags &= ~(f); }while(0)
 
 #define mdv_flag(m,f) ( (m->flags) & f )
 
-#define mdv_set_fast_decay(mdv) do{\
-	gpio_clear(mdv->pins.mode); /*fast decay when low */ \
-}while(0)
+#define mdv_set_fast_decay(mdv) \
+	do{ \
+		gpio_clear(mdv->pins.mode); /*fast decay when low */ \
+	}while(0)
 
-#define mdv_set_slow_decay(mdv) do{\
-	gpio_set(mdv->pins.mode); /* slow decay when high */ \
-}while(0)
+#define mdv_set_slow_decay(mdv) \
+	do{ \
+		gpio_set(mdv->pins.mode); /* slow decay when high */ \
+	}while(0)
 
 #define mdv_in_fast_decay_mode(mdv) (! gpio_read(mdv->pins.mode))
 
 #define mdv_in_slow_decay_mode(mdv) ( gpio_read(mdv->pins.mode))
 
 
 struct mdv_calibration_parameters {
 	unsigned int       pos_limit;
 	unsigned int       min_region;
 	unsigned int       max_region;
 	int                offset;
 	pos_evaluator_fptr pos_evaluator;
 	unsigned int       update_period;
 	unsigned int       ellapsed_ts;
 	unsigned int       pos_evaluator_max_value;
 };
 
 struct motordriver {
-    mdv_pin pins;
-    mdv_parameters params;
+	mdv_pin pins;
+	mdv_parameters params;
 
 	struct mdv_calibration_parameters calib;
 
-    mdv_status_and_control sc;
+	mdv_status_and_control sc;
 
-    mdv_flags flags;
+	mdv_flags flags;
 
 	sbcp_reg_address address_start;
-        volatile unsigned int * pos_counter;
+	volatile unsigned int * pos_counter;
 	/**
 	 *  \name qei position parameters
 	 */
 	///@{
 	/**
 	 * previous (relative) position counter of quadrature
 	 * input. dimension QEI increments
 	 */
-    volatile int previous_cnt;
+	volatile int previous_cnt;
 	/**
 	 * relative present position counter of quadrature
 	 * input. dimension QEI increments
 	 */
-    volatile long pos_cnt;
+	volatile long pos_cnt;
 	/**
 	 * current speed of quadrature input. dimension QEI increments per
 	 * 1/FT1
 	 */
-    volatile int current_speed;
+	volatile int current_speed;
 	/**
 	 * current acceleration of quadrature input. dimension QEI
 	 * increments per (1/FT1) ^2
 	 */
-    volatile int current_accel;
+	volatile int current_accel;
 	///@}
 
 
-     // move controlling parameters
-    long goal_pos;              // goal position
-    long goal_speed;              // desired speed of the motor during the motion
-                                // QEI incremet / ts (1ms)
-
+	// move controlling parameters
+        int  user_goal_pos;         //buffer goal position
+	long goal_pos;              // goal position
+	long goal_speed;              // desired speed of the motor during the motion
+	// QEI incremet / ts (1ms)
 
+        //commands buffer to avoid jitter
+        RingBuffer commandsBuffer; //the ring buffer containing the commands
+        int startSendOrders; //boolean to start sending the orders when half the capacity is reached
+        int timeCounter; //a counter to log commands only every 5ms.
 
-
-    // internally controlled variables
-    long moving_pos;            // current "desired" position during move
-    long moving_speed;           // current "desired" moving speed of the motor
+	// internally controlled variables
+	long moving_pos;            // current "desired" position during move
+	long moving_speed;           // current "desired" moving speed of the motor
 	// 1
-    int resolution_error;       // compensates for rounding errors
+	int resolution_error;       // compensates for rounding errors
+
 
+	long i_error;               // speed integral error
+	long prev_p_error;           // previous proportional error, used to compute the derivative error
 
-    long i_error;               // speed integral error
-    long prev_p_error;           // previous proportional error, used to compute the derivative error
+	int max_trq;       // maximum torque setting
 
-    int max_trq;       // maximum torque setting
+	// control output parameters
+	long output_trq;            // current torque request
 
-    // control output parameters
-    long output_trq;            // current torque request
+	// motor limits
+	long pos_limit;          // maximum positive limit
+	long max_speed;              // maximum speed the motor may reach
+	int  max_accel;     // 1 / 2 ^
 
-    // motor limits
-    long pos_limit;          // maximum positive limit
-    long max_speed;              // maximum speed the motor may reach
-    int  max_accel;     // 1 / 2 ^
 
+	int gear_mult;
+	int gear_div;
 
-    int gear_mult;
-    int gear_div;
 
+	struct {
+		int t;
+		int t_residue;
+		int iter;
+	} sine;
 };
 
 /**
  * \name conversion macro
  * Thes macro convert dimension for several value
  */
 
 ///@{
 /**
  * Transforms 1/4096 of turn in QEI increments
  * \params mdv the motordriver
  * \params pos the position to transform
  */
 #define mdv_e2i_position(mdv,pos) ((long) ( (mdv)->gear_mult * ((long) (pos)) / (mdv)->gear_div ))
 
 /**
  * Transforms QEI increments per (1/FT1) to 1 / 2 ^ SPEED_BINARY_PRECISION
  * QEI increments per per (1/FT1)
  * \params speed the speed to transform
  */
 #define mdv_lo2hi_res_speed(spd)  ( (spd)  * (1 << SPEED_BINARY_PRECISION) )
 
 /**
  * Transforms 1/4096 of turn per second to 1/ 2 ^
  * SPEED_BINARY_PRECISION QEI increments per (1/FT1) (with higher
  * precision)
  * \param mdv the motordriver
  * \param speed the speed
  */
 #define mdv_e2i_speed(mdv,spd)    (mdv_lo2hi_res_speed(mdv_e2i_position(mdv,spd)) / FT1)
 
 /**
  * Transforms 1/4096 of turn pers second^2 to 1 / 2 ^
  * SPEED_BINARY_PRECISION QEI per (1/ FT1)^2
  * \param mdv the motordriver
  * \param a the acceleration
  */
-#define mdv_e2i_accel(mdv,a)      (mdv_e2i_speed(mdv, a ) / FT1 )
+#define mdv_e2i_accel(mdv,a)      (mdv_e2i_speed(mdv, a ) * 128 / FT1 )
 
 
 /**
  *
  */
 #define mdv_e2i_torque(mdv,trq) (trq)
 
 
-
-
-
 /**
  * Transforms QEI increments in 1/4096 of turn.
  * \params mdv the motordriver
  * \params pos the position to transform
  */
 
 #define mdv_i2e_position(mdv,pos) ((long) ( (mdv)->gear_div * ((long) (pos)) / (mdv)->gear_mult ))
 
 /**
  * Transforms 1 / 2 ^ SPEED_BINARY_PRECISION QEI increments per (1/FT1) in QEI
  * increments per (1/FT1).
  * \params speed the speed to transform
  */
 #define mdv_hi2lo_res_speed(spd)  ( (spd) / ( 1 << SPEED_BINARY_PRECISION ) )
 
 /**
  * Transforms 1/ 2 ^ SPEED_BINARY_PRECISION QEI increments per (1/FT1) in
  * 1/4096 of turn per second.
  * \param mdv the motordriver
  * \param speed the speed
  */
 #define mdv_i2e_speed(mdv,speed)  ( FT1 * mdv_i2e_position(mdv,mdv_hi2lo_res_speed(speed)) )
 
 /**
  * Transforms 1 / 2 ^ SPEED_BINARY_PRECISION QEI per (1/FT1)^2 in 1/4096 of
  * turn pers second^2.
  * \param mdv the motordriver
  * \param a the acceleration
  */
-#define mdv_i2e_accel(mdv,a)      ( mdv_i2e_speed(mdv,a) * FT1 )
+#define mdv_i2e_accel(mdv,a)      ( mdv_i2e_speed(mdv,a) / 128 * FT1)
 
 
 /**
  *
  */
 #define mdv_i2e_torque(mdv,trq) (trq)
 
 ///@}
 
 
 
 
 //==============================================================================
 // CONTROL MODE SWITCHING
 //==============================================================================
 
 /**
  * Process function for a control mode.
  */
 typedef void (*mdv_ctrl_process_fptr)(motordriver *);
 
 /**
  * Init function for a control mode.
  */
 typedef void (*mdv_ctrl_init_fptr)(motordriver *);
 
 typedef struct mdv_ctrl_fptr {
-    mdv_ctrl_process_fptr process;
-    mdv_ctrl_init_fptr    init;
+	mdv_ctrl_process_fptr process;
+	mdv_ctrl_init_fptr    init;
 } mdv_ctrl_fptr;
 
 /**
  * General cleanup function. It resets a mode so all PID is clean and
  * unintegrated.
  */
 void mdv_cleanup(motordriver * mdv);
 
 /**
  * A mdv_ctrl_process_fptr function that does nothing.
  */
 void mdv_null_process(motordriver * mdv);
 
 
 void mdv_set_pos_count(motordriver * mdv, long pos);
 
 extern mdv_ctrl_fptr mdv_ctrl[MDV_NUMBER_OF_CONTROL_MODE];
 
+void mdv_set_control_mode_private(motordriver * mdv , mdv_control_mode c);
 
 #endif
diff --git a/src/mdv_speed_pid.c b/src/mdv_speed_pid.c
index 0040056..9adf6ff 100644
--- a/src/mdv_speed_pid.c
+++ b/src/mdv_speed_pid.c
@@ -1,253 +1,250 @@
 #include "mdv_speed_pid.h"
 #include "mdv_internal.h"
-
 #include "config.h"
-
 #include "misc_math.h"
 
 
 
 #define SMALLEST_HIGH_RES_SPEED mdv_lo2hi_res_speed(1L)
 
 unsigned int mdv_trq_to_pwm(motordriver * mdv, long desired_trq, uint8_t force_fast_decay);
 
 void mdv_update_position(motordriver * mdv){
 	int max_accel;
 
-    // The desired position moves according to the speed and acceleration settings...
+	// The desired position moves according to the speed and acceleration settings...
 
-    //if not moving, we skip :P
+	//if not moving, we skip :P
 	if (!mdv_flag(mdv,MDV_F_MOVING_ENABLE)) {
-        return;
+		return;
 	}
 
 	// if no acceleration curve is used, then moving_speed is just the set_speed
 	//		M->moving_speed = M->set_speed;
 
 	// => Acceleration curve computation
 	// compute when to switch off the set-speed in order to start descelerating such that zero speed is reached at the goal position
 	// maximum acceleration must not exceed the current moving speed (for correctly computing the speed auto-switch-off position)
 	max_accel = min(abs(mdv->moving_speed), (int)mdv->max_accel);
 
-	// auto-switching off the set_speed should only be done if the current speed has the same direction as the set_speed
-
-    if(   (mdv->moving_speed > 0 && mdv->goal_speed > 0)
-       || (mdv->moving_speed < 0 && mdv->goal_speed < 0)){
-
-	    ///\todo : find what these two mean
-	    long first_operand = abs(mdv->moving_pos - mdv->goal_pos) * (long) max_accel;
-	    long second_operand = mdv_hi2lo_res_speed(  (long) abs(mdv->moving_speed)
-	                                              * (  (long) abs(mdv->moving_speed)
-	                                                   + (long) max_accel -1          )) / 2 ;
-	    if (first_operand < second_operand )  {
-            // we don't set the desired speed to zero, but to the minimum acceleration setting in order to guarantee convergence
-            if (mdv->goal_speed > 0){
-                mdv->goal_speed =   min((int)mdv->max_accel, mdv->goal_speed);
-            } else {
-                mdv->goal_speed = - min((int)mdv->max_accel, - mdv->goal_speed);
-            }
-         }
-    }
-
-    // compute new speed according to the acceleration parameter
-    if (mdv->moving_speed != mdv->goal_speed) {
-
-	    if (mdv->moving_speed < mdv->goal_speed) {
-		    mdv->moving_speed += (int)mdv->max_accel;
-		    if (mdv->moving_speed > mdv->goal_speed) {
-			    mdv->moving_speed = mdv->goal_speed;
-		    }
-	    } else {
-		    mdv->moving_speed -= (int)mdv->max_accel;
-		    if (mdv->moving_speed < mdv->goal_speed) {
-			    mdv->moving_speed = mdv->goal_speed;
-		    }
-	    }
-    }
-
-
-    // compute new desired position for the current step
-    mdv->moving_pos += mdv_hi2lo_res_speed(mdv->moving_speed);
-
-    // compensate for the bit errors due to the shifting action
-    mdv->resolution_error += mdv->moving_speed - mdv_lo2hi_res_speed(mdv_hi2lo_res_speed(mdv->moving_speed)) ;
-    if (mdv->resolution_error > SMALLEST_HIGH_RES_SPEED ) {
-	    mdv->resolution_error -= SMALLEST_HIGH_RES_SPEED;
-	    mdv->moving_pos += 1;
-    } else if( mdv->resolution_error < - SMALLEST_HIGH_RES_SPEED) {
-	    mdv->resolution_error += SMALLEST_HIGH_RES_SPEED;
-	    mdv->moving_pos -= 1;
-    }
-
-    // check if the goal position is reached
-    if (((mdv->goal_speed > 0) && (mdv->moving_pos >= mdv->goal_pos)) || ((mdv->goal_speed < 0) && (mdv->moving_pos <= mdv->goal_pos)) ) {
-	    mdv->moving_pos   = mdv->goal_pos;
-	    mdv->moving_speed = 0;
-	    mdv_clear_flag(mdv,MDV_F_MOVING_ENABLE);
-    }
+	// auto-switching of the set_speed should only be done if the current speed has the same direction as the set_speed
+
+	if(   (mdv->moving_speed > 0 && mdv->goal_speed > 0)
+	   || (mdv->moving_speed < 0 && mdv->goal_speed < 0)){
+
+		///\todo : find what these two means
+		long first_operand = abs(mdv->moving_pos - mdv->goal_pos) * (long) max_accel;
+		long second_operand = mdv_hi2lo_res_speed(  (long) abs(mdv->moving_speed)
+		                                          * (  (long) abs(mdv->moving_speed)
+		                                             + (long) max_accel - 1         )) / 2 ;
+		if (first_operand < second_operand )  {
+			// we don't set the desired speed to zero, but to the minimum acceleration setting in order to guarantee convergence
+			if (mdv->goal_speed > 0){
+				mdv->goal_speed =   min((int)mdv->max_accel, mdv->goal_speed);
+			} else {
+				mdv->goal_speed = - min((int)mdv->max_accel, - mdv->goal_speed);
+			}
+		}
+	}
+
+	// compute new speed according to the acceleration parameter
+	if (mdv->moving_speed != mdv->goal_speed) {
+
+		if (mdv->moving_speed < mdv->goal_speed) {
+			mdv->moving_speed += (int)mdv->max_accel;
+			if (mdv->moving_speed > mdv->goal_speed) {
+				mdv->moving_speed = mdv->goal_speed;
+			}
+		} else {
+			mdv->moving_speed -= (int)mdv->max_accel;
+			if (mdv->moving_speed < mdv->goal_speed) {
+				mdv->moving_speed = mdv->goal_speed;
+			}
+		}
+	}
+
+
+	// compute new desired position for the current step
+	mdv->moving_pos += mdv_hi2lo_res_speed(mdv->moving_speed);
+
+	// compensate for the bit errors due to the shifting action
+	mdv->resolution_error += mdv->moving_speed - mdv_lo2hi_res_speed(mdv_hi2lo_res_speed(mdv->moving_speed)) ;
+	if (mdv->resolution_error > SMALLEST_HIGH_RES_SPEED ) {
+		mdv->resolution_error -= SMALLEST_HIGH_RES_SPEED;
+		mdv->moving_pos += 1;
+	} else if( mdv->resolution_error < - SMALLEST_HIGH_RES_SPEED) {
+		mdv->resolution_error += SMALLEST_HIGH_RES_SPEED;
+		mdv->moving_pos -= 1;
+	}
+
+	// check if the goal position is reached
+	if (((mdv->goal_speed > 0) && (mdv->moving_pos >= mdv->goal_pos)) || ((mdv->goal_speed < 0) && (mdv->moving_pos <= mdv->goal_pos)) ) {
+		mdv->moving_pos   = mdv->goal_pos;
+		mdv->moving_speed = 0;
+		mdv_clear_flag(mdv,MDV_F_MOVING_ENABLE);
+	}
 
 }
 
 void mdv_compute_and_apply_output(motordriver * mdv){
 	long desired_speed;
 	long p_error, d_error;
 	long pid_output;
 	unsigned int speed_output;
 	unsigned int scaled_speed_output;
 	long i_max;
 	long required_trq;
 
 	// ***************** Speed control section: velocity error *****************
 
 	desired_speed = mdv->moving_pos - mdv->pos_cnt;
 
 	// compute new PID output
 	p_error = (long)mdv->current_speed - desired_speed;
 
-	// only integrate action when not in complinat mode
+	// only integrate action when not in compliant mode
 	if (mdv_flag(mdv,MDV_F_UPDATE_I_ERROR)){
 		mdv->i_error += p_error;
 	}
 
 	d_error = p_error - mdv->prev_p_error;
-//	if (M1.update_i_error) d_error = p_error - M1.prev_p_error; else d_error = 0;
+	//	if (M1.update_i_error) d_error = p_error - M1.prev_p_error; else d_error = 0;
 	pid_output = ((p_error*(long) (mdv->params.p_gain)) + (mdv->i_error*(long)mdv->params.i_gain) + (d_error*(long)mdv->params.d_gain))/(long)1024;
 	mdv->prev_p_error = p_error;
 
 
 
 	// anti-windupif
-        if(mdv->params.i_gain != 0){
-            i_max = ((long)(MAX_PWM-1)*(long)1024)/(mdv->params.i_gain*2);
-            mdv->i_error = clamp_absolute(mdv->i_error,i_max);
-        }
+	if(mdv->params.i_gain != 0){
+		i_max = ((long)(MAX_PWM-1)*(long)1024)/(mdv->params.i_gain*2);
+		mdv->i_error = clamp_absolute(mdv->i_error,i_max);
+	}
 
 	// clamp output
 	speed_output = min(abs(pid_output),(long)(MAX_PWM-1));
-        if(mdv_in_fast_decay_mode(mdv)){
-            speed_output += MAX_DUTY / 2;
-        } else {
-            speed_output *= 2;
-        }
+	if(mdv_in_fast_decay_mode(mdv)){
+		speed_output += MAX_DUTY / 2;
+	} else {
+		speed_output *= 2;
+	}
 	// set pwm output
 
 	//(MODE1==FAST_DECAY) ? (_PWM) + MAX_DUTY/2 : (_PWM)*2);
 	pwm_set_value(mdv->pins.speed,speed_output);
 
 	// ***************** Output torque control section *****************
 
 	// torque as feeled by the leg = spring force - spring damping + rotor inertia compensation
 	long output_spring = (((desired_speed)*(long)mdv->params.stiffness)/512) ;
 	long output_damping = - (((long)(mdv->current_speed - mdv_hi2lo_res_speed(mdv->moving_speed)) * (long)mdv->params.damping)/64);
 	mdv->output_trq = output_spring + output_damping;
 
 	// Add the spring preload term
 	if (desired_speed > 0){
 		mdv->output_trq += mdv->params.preload;
 	} else {
 		mdv->output_trq -= mdv->params.preload;
 	}
 
 	// required torque on the motor is the requested torque + a compensation term for the rotor inertia
 	///\todo remove hardcoded 64.
 	required_trq = mdv->output_trq + (long)mdv->current_accel* (long) MDV_INERTIA_COMP/64;
 
 	// scale speed to torque dimensions
 	scaled_speed_output = (long)((long)speed_output*MAX_DUTY)/(long)MAX_PWM;
 
 	// Set direction of torque, depending on which factor is smallest
-//	if ((long)_ABS(required_trq) < (long)(speed_output*MAX_DUTY)/MAX_PWM) {
+	//	if ((long)_ABS(required_trq) < (long)(speed_output*MAX_DUTY)/MAX_PWM) {
 	if ((unsigned int)abs(mdv->params.preload) < scaled_speed_output) {
 		mdv_clear_flag(mdv, MDV_F_UPDATE_I_ERROR);
 		if (required_trq>0) {
 			gpio_clear(mdv->pins.dir);
 		} else {
 			gpio_set(mdv->pins.dir);
 		}
 		///\todo remove this hardcoded value
 		if (mdv->params.stiffness > 500) { // problematic switching between fast and slow decay for very stiff spring settings
 			pwm_set_value(mdv->pins.torque,  mdv_trq_to_pwm(mdv,abs(required_trq), 1));
 		} else {
 			pwm_set_value(mdv->pins.torque, mdv_trq_to_pwm(mdv,abs(required_trq), 0));
 			//		LED_TX_ENABLE;
 		}
 	}
 	else {
 		mdv_set_flag(mdv,MDV_F_UPDATE_I_ERROR);
-//		if (speed_output > 2)
+		//		if (speed_output > 2)
 		if (pid_output<0) {
 			gpio_clear(mdv->pins.dir);
 		} else {
 			gpio_set(mdv->pins.dir);
 		}
 		// force fast decay mode
 
-//		if (scaled_speed_output*4 < (unsigned int)_ABS(M1.compliance_preload))
-//			PWM_TRQ1 = M1_trq_to_pwm((long)scaled_speed_output*4, TRUE);//   (_ABS(required_trq)*(long)speed_output)/50, TRUE);
-//		else
-//			PWM_TRQ1 = M1_trq_to_pwm((long)scaled_speed_output, TRUE);
+		//		if (scaled_speed_output*4 < (unsigned int)_ABS(M1.compliance_preload))
+		//			PWM_TRQ1 = M1_trq_to_pwm((long)scaled_speed_output*4, TRUE);//   (_ABS(required_trq)*(long)speed_output)/50, TRUE);
+		//		else
+		//			PWM_TRQ1 = M1_trq_to_pwm((long)scaled_speed_output, TRUE);
 		pwm_set_value(mdv->pins.torque, mdv_trq_to_pwm(mdv,abs(required_trq), 1));
-//		LED_TX_DISABLE;
+		//		LED_TX_DISABLE;
 	}
-
 }
 
 
 unsigned int mdv_trq_to_pwm(motordriver * mdv, long desired_trq, uint8_t force_fast_decay) {
 	unsigned int pwm_out;
 
 	desired_trq = (desired_trq*4096)/MAX_DUTY;
 
 	// clamp desired_trq within safe range
 	if (desired_trq > 8192) {
 		desired_trq = 8192;
 	}
 
 	// desired torque is a 12-bit value
 	// translate to 12-bit pwm-output using a piece-wise linear function
 	// this function compensates for the non-linear pwm to torque relation
 	if      (desired_trq <  2) 	pwm_out = ((unsigned int)desired_trq)*215;
 	else if (desired_trq < 40) 	pwm_out = ((unsigned int)desired_trq - 2)*7/2 + 430;
 	else if (desired_trq < 86)	pwm_out = ((unsigned int)desired_trq -40)*3/2 + 563;
 	else						pwm_out = ((unsigned int)desired_trq -86)*7/8 + 632;
 
 	// full pwm scale is now 12-bit, convert to pwm-range
 	pwm_out = (unsigned int)(((unsigned long)pwm_out*(unsigned long)MAX_DUTY)/TORQUE_RESOLUTION);
 
 	// saturate at maximum torque
 	if ((mdv->max_trq > ((MAX_DUTY * MDV_SLOWFAST_THRES)/256)) && (!force_fast_decay)) {
 		if (pwm_out > mdv->max_trq + MDV_SLOWFAST_COMP) pwm_out = mdv->max_trq + MDV_SLOWFAST_COMP;
 	}
 	else { // motor remains in the fast decay regime
 		if (pwm_out > mdv->max_trq) pwm_out = mdv->max_trq;
 	}
 
 	if (force_fast_decay) {
 		mdv_set_fast_decay(mdv);
-//		LED_TX_DISABLE;
+		//		LED_TX_DISABLE;
 	}
 	else {
 		// choose appropriate decay mode
 		if (pwm_out > (unsigned int)((MAX_DUTY*MDV_SLOWFAST_THRES)/256)) {
 			mdv_set_slow_decay(mdv);
-//			LED_TX_ENABLE;
+			//			LED_TX_ENABLE;
 		}
 		else if (pwm_out < (unsigned int)((MAX_DUTY*(MDV_SLOWFAST_THRES-10))/256)) { // small hysteresis
 			mdv_set_fast_decay(mdv);
-//			LED_TX_DISABLE;
+			//			LED_TX_DISABLE;
 		}
 	}
 
 	// compensate for the slightly higher efficiency of the slow decay mode
 	if ( mdv_in_slow_decay_mode(mdv) ) {
 		pwm_out -= (unsigned int)MDV_SLOWFAST_COMP;
 	}
 	return pwm_out;
 }
 
 
 void mdv_speed_pid_with_compliance_process(motordriver * mdv){
-    mdv_update_position(mdv);
-    mdv_compute_and_apply_output(mdv);
+	mdv_update_position(mdv);
+	mdv_compute_and_apply_output(mdv);
 }
 
diff --git a/src/motordriver.c b/src/motordriver.c
index 3da24f6..dccfbef 100644
--- a/src/motordriver.c
+++ b/src/motordriver.c
@@ -1,311 +1,319 @@
 #include "motordriver.h"
 
 #include "mdv_internal.h"
 #include "mdv_control_modes.h"
 
 #include "timer.h"
 #include "config.h"
 
 #include "sbcp_mdv.h"
 
 #include "misc_math.h"
 
 
 
 motordriver _NEAR MDV_1;
 motordriver _NEAR MDV_2;
 
 motordriver * mdv1 = &(MDV_1);
 motordriver * mdv2 = &(MDV_2);
 
 
 gpio mdv_master_reset;
 
 
 
 void init_motordrivers(mdv_pin* mdv1_pin, mdv_pin* mdv2_pin){
 	init_motordriver(mdv1,mdv1_pin, MDV_M1, &POS1CNT);
 	init_motordriver(mdv2,mdv2_pin, MDV_M2, &POS2CNT);
 }
 
 
 void init_motordriver(motordriver * mdv,
-        mdv_pin * pins,
-        sbcp_reg_address address_start,
-        volatile unsigned int * pos_counter ){
-    mdv->pins = *pins;
-    /*set coast mode as default and init it*/
-    mdv->sc.status = MDV_IDLE;
-    mdv->sc.mode = MDV_M_COAST;
-    mdv->address_start = address_start;
-    mdv->pos_counter = pos_counter;
-    mdv_coast_init(mdv);
+                      mdv_pin * pins,
+                      sbcp_reg_address address_start,
+                      volatile unsigned int * pos_counter ){
+	mdv->pins = *pins;
+	/*set coast mode as default and init it*/
+	mdv->sc.status = MDV_IDLE;
+	mdv->sc.mode = MDV_M_COAST;
+	mdv->address_start = address_start;
+	mdv->pos_counter = pos_counter;
+	mdv_coast_init(mdv);
 
 
-    mdv->previous_cnt = 0;
-    mdv->pos_cnt      = 0;
-    mdv->goal_pos     = 0;
-    mdv->goal_speed   = 0;
-    mdv_clear_flag(mdv,MDV_F_MOVING_ENABLE | MDV_F_UPDATE_I_ERROR);
+	mdv->previous_cnt = 0;
+	mdv->pos_cnt      = 0;
+	mdv->goal_pos     = 0;
+	mdv->goal_speed   = 0;
+	mdv_clear_flag(mdv,MDV_F_MOVING_ENABLE | MDV_F_UPDATE_I_ERROR);
 
-    mdv->params.p_gain = 0;
-    mdv->params.i_gain = 0;
-    mdv->params.d_gain = 0;
+	mdv->params.p_gain = 0;
+	mdv->params.i_gain = 0;
+	mdv->params.d_gain = 0;
 
-    mdv->i_error      = 0;
-    mdv->prev_p_error = 0;
+	mdv->i_error      = 0;
+	mdv->prev_p_error = 0;
 
-    mdv->params.stiffness = 0;
-    mdv->params.damping   = 0;
-    mdv->params.preload   = 0;
+	mdv->params.stiffness = 0;
+	mdv->params.damping   = 0;
+	mdv->params.preload   = 0;
 
-    mdv->max_trq          = 0;
-    mdv->output_trq       = 0;
-    mdv->pos_limit        = 0;
+	mdv->max_trq          = 0;
+	mdv->output_trq       = 0;
+	mdv->pos_limit        = 0;
 
-    mdv->max_speed        = 0;
-    mdv->max_accel        = 0;
+	mdv->max_speed        = 0;
+	mdv->max_accel        = 0;
 
 }
 
 
 void mdv_reset_count(motordriver * mdv){
 	mdv_set_pos_count(mdv,0);
 }
 
 
-
-
-
 void mdv_update_sbcp_register(motordriver * mdv){
 
 	if(mdv_flag(mdv,MDV_F_MOVING_ENABLE)){
 		mdv->sc.status |= MDV_MOVING;
 	} else {
 		mdv->sc.status &= ~(MDV_MOVING);
 	}
 
-	sbcp_mdv_reg(mdv,MX_STATUS_AND_CONTROL_MODE) = mdv->sc.reg_val;
+	sbcp_mdv_reg(mdv ,MX_STATUS_AND_CONTROL_MODE) = mdv->sc.reg_val;
 
-	sbcp_mdv_reg(mdv, MX_TARGETED_POSITION).i = mdv_i2e_position(mdv,mdv->moving_pos);
-	sbcp_mdv_reg(mdv , MX_PRESENT_POSITION).i = mdv_i2e_position(mdv, mdv->pos_cnt);
+	sbcp_mdv_reg(mdv , MX_TARGETED_POSITION).i = mdv_i2e_position(mdv,mdv->moving_pos);
+	sbcp_mdv_reg(mdv , MX_PRESENT_POSITION).i  = mdv_i2e_position(mdv, mdv->pos_cnt);
 
-	sbcp_mdv_reg(mdv , MX_TARGETED_SPEED).i   = mdv_i2e_speed(mdv, mdv->moving_speed);
-	sbcp_mdv_reg(mdv , MX_PRESENT_SPEED).i    = mdv_i2e_speed(mdv,mdv_lo2hi_res_speed(mdv->current_speed));
+	sbcp_mdv_reg(mdv , MX_TARGETED_SPEED).i    = mdv_i2e_speed(mdv, mdv->moving_speed);
+	sbcp_mdv_reg(mdv , MX_PRESENT_SPEED).i     = mdv_i2e_speed(mdv,mdv_lo2hi_res_speed(mdv->current_speed));
 
-	sbcp_mdv_reg(mdv , MX_TARGETED_TORQUE).i  = mdv_i2e_torque(mdv, mdv->output_trq);
+	sbcp_mdv_reg(mdv , MX_TARGETED_TORQUE).i   = mdv_i2e_torque(mdv, mdv->output_trq);
 
-    sbcp_mark_new_low_latency_data_available();
+	sbcp_mark_new_low_latency_data_available();
 };
 
 
 void mdv_process(motordriver * mdv){
-    (*(mdv_ctrl[mdv->sc.mode].process))(mdv);
-    mdv_update_sbcp_register(mdv);
+	(*(mdv_ctrl[mdv->sc.mode].process))(mdv);
+	mdv_update_sbcp_register(mdv);
 }
 
 
-void mdv_set_control_mode_private(motordriver * mdv , mdv_control_mode c){
-	mdv_cleanup(mdv);
-	mdv->sc.mode = c;
-	(*(mdv_ctrl[c].init))(mdv);
-}
 
 mdv_error mdv_set_control_mode(motordriver * mdv, int c){
 	c = abs(c);
 	if(c >= MDV_NUMBER_OF_CONTROL_MODE){
 		return MDV_ERR_UNKNOWN_CONTROL_MODE;
 	}
 	if( c == MDV_M_RUNTIME_CALIBRATION ){
 		return MDV_ERR_RESERVED_CONTROL_MODE;
 	}
 
 	if( mdv->sc.mode == MDV_M_RUNTIME_CALIBRATION) {
 		return MDV_ERR_IN_CALIBRATION;
 	}
 
+	if( ! (mdv->sc.status & MDV_RUNTIME_CALIBRATED) ){
+		return MDV_ERR_MOTOR_NOT_RUNTIME_CALIBRATED;
+	}
+
 	if(c == mdv->sc.mode) {
 		return MDV_ERR_NO_ERROR;
 	}
 
 	mdv_set_control_mode_private(mdv,c);
 	return MDV_ERR_NO_ERROR;
 }
 
 
 int mdv_get_control_mode(motordriver * mdv){
 	return mdv->sc.mode;
 }
 
-#define mdv_update_position_and_speed(mdv,pos_counter) do{\
-int _MC_tmp_speed  =  pos_counter - mdv->previous_cnt;\
-mdv->current_accel = _MC_tmp_speed - mdv->current_speed;\
-mdv->current_speed = _MC_tmp_speed;\
-mdv->previous_cnt  = pos_counter;\
-mdv->pos_cnt      += mdv->current_speed;\
-}while(0)
+#define mdv_update_position_and_speed(mdv,pos_counter) do{	  \
+		int _MC_tmp_speed  =  pos_counter - mdv->previous_cnt; \
+		mdv->current_accel = _MC_tmp_speed - mdv->current_speed; \
+		mdv->current_speed = _MC_tmp_speed; \
+		mdv->previous_cnt  = pos_counter; \
+		mdv->pos_cnt      += mdv->current_speed; \
+	}while(0)
 
 
 /* Timer 1 is used as system timer */
 void __attribute__((__interrupt__, no_auto_psv)) _T1Interrupt(void) {
 	systime ++;
 
 	// timing critical part of motor control
 	mdv_update_position_and_speed(mdv1,POS1CNT);
 	mdv_update_position_and_speed(mdv2,POS2CNT);
 
 
 	IFS0bits.T1IF = 0; // Clear Timer 1 Interrupt Flag
 }
 
 
 
 
 int mdv_get_status_and_control_mode(motordriver * mdv) {
 	return mdv->sc.reg_val.i;
 }
 
 mdv_error mdv_set_goal_position(motordriver * mdv, int position){
-	mdv->goal_pos = mdv_e2i_position(mdv,position);
+	mdv->user_goal_pos = position;
 	mdv_set_flag(mdv,MDV_F_NEW_POSITION_AVAILABLE);
-        return MDV_ERR_NO_ERROR;
+	return MDV_ERR_NO_ERROR;
 }
 
 mdv_error mdv_set_goal_speed(motordriver * mdv , int speed){
 	mdv->goal_speed = mdv_e2i_speed(mdv,speed);
 	mdv_set_flag(mdv,MDV_F_NEW_SPEED_AVAILABLE);
-        return MDV_ERR_NO_ERROR;
+	return MDV_ERR_NO_ERROR;
 }
 //mdv_error mdv_set_goal_torque(motordriver * mdv, mdv_torque_t torque);
 
 int mdv_get_goal_position(motordriver * mdv){
 	return mdv_i2e_position(mdv,mdv->goal_pos);
 }
 int mdv_get_goal_speed(motordriver * mdv){
 	return mdv_i2e_speed(mdv,mdv->goal_speed);
 }
 //mdv_torque_t   mdv_get_goal_torque(motordriver * mdv);
 
 int mdv_get_position(motordriver * mdv){
 	return mdv_i2e_position(mdv,mdv->pos_cnt);
 }
 int    mdv_get_speed(motordriver * mdv){
 	return mdv_i2e_speed(mdv,mdv_lo2hi_res_speed(mdv->current_speed));
 }
 int   mdv_get_targeted_torque(motordriver * mdv){
 	return mdv_i2e_torque(mdv,mdv->output_trq);
 }
 int  mdv_get_current(motordriver * mdv){
 	return 0;
 }
 
 int mdv_get_virtual_goal_position(motordriver * mdv){
 	return mdv_i2e_position(mdv,mdv->moving_pos);
 }
 int mdv_get_virtual_goal_speed(motordriver * mdv){
 	return mdv_i2e_speed(mdv,mdv->moving_speed);
 }
 
 mdv_parameters * mdv_get_parameters(motordriver * mdv){
 	return &(mdv->params);
 }
 
 
 int mdv_get_maximal_acceleration(motordriver * mdv){
 	return mdv_i2e_accel(mdv,mdv->max_accel);
 }
 int mdv_get_maximal_speed(motordriver * mdv){
 	return mdv_i2e_speed(mdv,mdv->max_speed);
 }
 int mdv_get_maximal_torque(motordriver * mdv){
 	return mdv_i2e_torque(mdv,mdv->max_trq);
 }
 
 mdv_error mdv_set_maximal_acceleration(motordriver * mdv, int value){
 	mdv->max_accel = mdv_e2i_accel(mdv,max(0,value));
-        return MDV_ERR_NO_ERROR;
+	return MDV_ERR_NO_ERROR;
 }
 mdv_error mdv_set_maximal_speed(motordriver * mdv, int value){
-	mdv->max_speed = mdv_e2i_speed(mdv,max(0,value));
-        return MDV_ERR_NO_ERROR;
+	mdv->max_speed = mdv_e2i_speed(mdv,max((int)0,value));
+	return MDV_ERR_NO_ERROR;
 }
 mdv_error mdv_set_maximal_torque(motordriver * mdv, int value){
-	mdv->max_trq = mdv_e2i_torque(mdv,max(0,value));
-        return MDV_ERR_NO_ERROR;
+	mdv->max_trq = mdv_e2i_torque(mdv,max((int)0,value));
+	return MDV_ERR_NO_ERROR;
 }
 
 mdv_error mdv_set_gear_ratio(motordriver * mdv, int gear_mult, int gear_div){
 	mdv->gear_mult = GEAR_MULT_COEFF * gear_mult;
 	mdv->gear_div  = GEAR_DIV_COEFF * gear_div;
-        return MDV_ERR_NO_ERROR;
+	return MDV_ERR_NO_ERROR;
 }
 
 int mdv_get_gear_mult(motordriver * mdv){
 	return mdv->gear_mult / GEAR_MULT_COEFF;
 }
 
 int mdv_get_gear_div(motordriver * mdv){
 	return mdv->gear_div / GEAR_DIV_COEFF;
 }
 
 int mdv_get_limit_position(motordriver * mdv){
 	return mdv_i2e_position(mdv,mdv->pos_limit);
 }
 
 
 mdv_error mdv_calibrate_motor(motordriver * mdv,
                               unsigned int limit_pos,
                               unsigned int min_calibration_region,
                               unsigned int max_calibration_region,
                               int          calibration_offset,
                               pos_evaluator_fptr position_evaluator,
                               unsigned int       pos_evaluator_max_value,
                               uint8_t statically_calibrated){
 
 	/* only calibrate once */
 	if(mdv->sc.status & MDV_RUNTIME_CALIBRATED){
 		return MDV_ERR_ALREADY_RUNTIME_CALIBRATED;
 	}
 
 
 	if(! statically_calibrated){
-		mdv->pos_limit = mdv_e2i_position(mdv,limit_pos);
-                mdv_set_pos_count(mdv,mdv->pos_limit / 2);
-		mdv_set_control_mode(mdv, MDV_M_COAST);
-
-
-		return MDV_ERR_NO_ERROR;
+		return MDV_ERR_MOTOR_NOT_MANUFACTURER_CALIBRATED;
 	}
 
 
 	if(position_evaluator == 0x00){
 		return MDV_ERR_BAD_PARAM;
 	}
 
 
 	mdv->calib.pos_limit     = limit_pos;
 	mdv->calib.min_region    = clamp(min_calibration_region , 0 , ANGULAR_RESOLUTION);
 	mdv->calib.max_region    = clamp(max_calibration_region , 0 , ANGULAR_RESOLUTION);
 	mdv->calib.offset        = clamp_absolute(calibration_offset,
 	                                          mdv_e2i_position(mdv,ANGULAR_RESOLUTION));
 
 	mdv->calib.pos_evaluator = position_evaluator;
 	mdv->calib.pos_evaluator_max_value = pos_evaluator_max_value;
 
 
 	mdv_set_control_mode_private(mdv,MDV_M_RUNTIME_CALIBRATION);
 
-        return MDV_ERR_NO_ERROR;
+	return MDV_ERR_NO_ERROR;
 }
 
 
 void mdv_load_persistent_sbcp_settings(){
 	mdv_set_gear_ratio(mdv1,
 	                   sbcp_reg_table[MDV_M1 + MX_GEAR_MULT].i,
 	                   sbcp_reg_table[MDV_M1 + MX_GEAR_DIV].i);
 
 	mdv_set_gear_ratio(mdv2,
 	                   sbcp_reg_table[MDV_M2 + MX_GEAR_MULT].i,
 	                   sbcp_reg_table[MDV_M2 + MX_GEAR_DIV].i);
 
 }
+
+
+
+void mdv_uncalibrate_motor(motordriver * mdv){
+
+	mdv->sc.status &= ~(MDV_RUNTIME_CALIBRATED);
+	mdv->pos_limit = 0;
+	mdv_set_pos_count(mdv,0);
+	mdv_set_control_mode_private(mdv,MDV_M_COAST);
+
+}
+
+
+mdv_error mdv_set_smooth_interval(motordriver* mdv, int ts){
+    mdv->params.smooth_interval = ts;
+    return MDV_ERR_NO_ERROR;
+}
\ No newline at end of file
diff --git a/src/motordriver.h b/src/motordriver.h
index 62fc96a..f1e3481 100644
--- a/src/motordriver.h
+++ b/src/motordriver.h
@@ -1,228 +1,234 @@
 /*
  * File:   motordriver.h
  * Author: tuleu
  *
  * Created on August 22, 2012, 3:43 PM
  */
 
 #ifndef MOTORDRIVER_H_
 #define	MOTORDRIVER_H_
 
 #include <gpio.h>
 #include <register.h>
 
 #include "pwm.h"
 
 // number of counts per rotation
 #define ANGULAR_RESOLUTION 4096
 // maximum torque output value
 #define TORQUE_RESOLUTION 4096
 
 // spring force scaling: for a given SPRING_FORCE, maximum torque output is reached after TORQUE_PER_ROTATION_SCALING/SPRING_FORCE rotations
 #define TORQUE_PER_ROTATION_SCALING 16
 
 
 // since we have really low resolution speed
 // in order to improve movement resolution, we multiply by a multiple of two
 // the speed. this is the power of the multiplication. aim is to improve the precision
 #define SPEED_BINARY_PRECISION 4
 
 
 
 // common constants and macro's
 #define MAX_PID_RANGE	32767
 
 // communication protocol parameters
 
 // Maximum counter value of HW PWM counter
 #define MAX_PWM			(FCY/FPWM-1)
 #define MAX_DUTY		(2*FCY/FPWM-1)
 
 ///\todo these macro as parameters
 #define MDV_INERTIA_COMP   300
 #define MDV_SLOWFAST_COMP  200
 #define MDV_SLOWFAST_THRES 220
 
 
 #define SMOOTH_POSITION_OVERSHOOT 0
 
 
 
 
 enum mdv_status {
-    MDV_IDLE               = 0,
-    MDV_MOVING             = 1 << 0,
-    MDV_RUNTIME_CALIBRATED = 1 << 1,
-    MDV_ERROR              = 1 << 2
+	MDV_IDLE               = 0,
+	MDV_MOVING             = 1 << 0,
+	MDV_RUNTIME_CALIBRATED = 1 << 1,
+	MDV_ERROR              = 1 << 2
 };
 
 typedef enum mdv_status mdv_status;
 
 typedef enum mdv_control_mode {
-    MDV_M_COAST                    = 0,
-    MDV_M_BRAKE                    = 1,
-    MDV_M_POSITION_CONTROL         = 2,
-    MDV_M_VELOCITY_CONTROL         = 3,
-    MDV_M_SMOOTH_POSITION_CONTROL  = 4,
-    MDV_M_TORQUE_CONTROL           = 5,
-    MDV_M_RUNTIME_CALIBRATION      = 6,
-
-    MDV_NUMBER_OF_CONTROL_MODE
+	MDV_M_COAST                    = 0,
+	MDV_M_BRAKE                    = 1,
+	MDV_M_POSITION_CONTROL         = 2,
+	MDV_M_VELOCITY_CONTROL         = 3,
+	MDV_M_SMOOTH_POSITION_CONTROL  = 4,
+	MDV_M_TORQUE_CONTROL           = 5,
+	MDV_M_RUNTIME_CALIBRATION      = 6,
+	MDV_M_SINE_GENERATOR           = 7,
+	MDV_NUMBER_OF_CONTROL_MODE
 } mdv_control_mode;
 
 
 
 union mdv_status_and_control{
-    struct {
-        mdv_control_mode mode;
-        mdv_status       status;
-    };
-    unsigned int         uint;
-    sbcp_reg_val         reg_val;
+	struct {
+		uint8_t mode;
+		uint8_t status;
+	};
+	unsigned int         uint;
+	sbcp_reg_val         reg_val;
 };
 
 typedef union mdv_status_and_control mdv_status_and_control;
 
 
 typedef unsigned int mdv_pid_t;
 typedef unsigned int mdv_stiffness_t;
 typedef unsigned int mdv_damping_t;
 typedef unsigned int mdv_timestep_t;
 typedef          int mdv_torque_t;
 
 
 
 struct mdv_parameters {
 
 	mdv_pid_t p_gain;
 	mdv_pid_t i_gain;
 	mdv_pid_t d_gain;
 
 
 	mdv_stiffness_t stiffness;
 	mdv_damping_t   damping;
 	mdv_torque_t    preload;
 
 
 	mdv_timestep_t smooth_interval;
 };
 
 typedef struct mdv_parameters mdv_parameters;
 
 struct mdv_pin {
-    gpio brake;
-    gpio coast;
-    gpio dir;
-    gpio mode;
-    pwm_t torque;
-    pwm_t speed;
+	gpio brake;
+	gpio coast;
+	gpio dir;
+	gpio mode;
+	pwm_t torque;
+	pwm_t speed;
 };
 
 typedef struct mdv_pin mdv_pin;
 
 enum mdv_error {
-    MDV_ERR_NO_ERROR                   = 0,
-    MDV_ERR_UNKNOWN_CONTROL_MODE       = 1,
-    MDV_ERR_BAD_PARAM                  = 2,
-    MDV_ERR_ALREADY_RUNTIME_CALIBRATED = 3,
-    MDV_ERR_RESERVED_CONTROL_MODE      = 4,
-    MDV_ERR_IN_CALIBRATION             = 5,
-    MDV_ERR_NB_ERRORS                  = 6
+	MDV_ERR_NO_ERROR                          = 0,
+	MDV_ERR_UNKNOWN_CONTROL_MODE              = 1,
+	MDV_ERR_BAD_PARAM                         = 2,
+	MDV_ERR_ALREADY_RUNTIME_CALIBRATED        = 3,
+	MDV_ERR_RESERVED_CONTROL_MODE             = 4,
+	MDV_ERR_IN_CALIBRATION                    = 5,
+	MDV_ERR_MOTOR_NOT_MANUFACTURER_CALIBRATED = 6,
+	MDV_ERR_MOTOR_NOT_RUNTIME_CALIBRATED      = 7,
+	MDV_ERR_NB_ERRORS                         = 8
 };
 
 typedef enum mdv_error mdv_error;
 
 struct motordriver;
 typedef struct motordriver motordriver;
 
 
 // motordrivers reset output
 
 extern gpio mdv_master_reset;
 
 #define mdv_master_reset_enable() do{ gpio_clear(mdv_master_reset);}while(0)
 
 #define mdv_master_reset_disable() do{ gpio_set(mdv_master_reset);} while(0)
 
 
 
 void init_motordrivers(mdv_pin * mdv1_pin, mdv_pin * mdv2_pin);
 
 void init_motordriver(motordriver * mdv,
-        mdv_pin * pin,
-        sbcp_reg_address address_start,
-        volatile unsigned int * pos_counter);
+                      mdv_pin * pin,
+                      sbcp_reg_address address_start,
+                      volatile unsigned int * pos_counter);
 
 
 void mdv_reset_count(motordriver *m);
 
 void mdv_process(motordriver * mdv);
 
 
 int mdv_get_status_and_control_mode(motordriver *m);
 
 #define mdv_get_status(m) (mdv_get_status_and_control_mode(m).status)
 
 int mdv_get_control_mode(motordriver * mdv);
 
 mdv_error mdv_set_control_mode(motordriver * mdv, int ctrl);
 
 mdv_error mdv_runtime_calibrate(motordriver * mdv, int actual_position);
 
 mdv_error mdv_set_smooth_interval(motordriver * mdv, int ts);
 int mdv_get_smooth_interval(motordriver * mdv);
 
 
 mdv_error mdv_set_goal_position(motordriver * mdv, int position);
 mdv_error mdv_set_goal_speed(motordriver * mdv , int speed);
 //mdv_error mdv_set_goal_torque(motordriver * mdv, mdv_torque_t torque);
 
 int mdv_get_goal_position(motordriver * mdv);
 int    mdv_get_goal_speed(motordriver * mdv);
 //mdv_torque_t   mdv_get_goal_torque(motordriver * mdv);
 
 int mdv_get_position(motordriver * mdv);
 int    mdv_get_speed(motordriver * mdv);
 int   mdv_get_targeted_torque(motordriver * mdv);
 int  mdv_get_current(motordriver * mdv);
 
 int mdv_get_virtual_goal_position(motordriver *m);
 int mdv_get_virtual_goal_speed(motordriver *m);
 
 mdv_parameters * mdv_get_parameters(motordriver * m);
 
 
 int mdv_get_maximal_acceleration(motordriver * m);
 int mdv_get_maximal_speed(motordriver * m);
 int mdv_get_maximal_torque(motordriver * m);
 
 mdv_error mdv_set_maximal_acceleration(motordriver * m, int value);
 mdv_error mdv_set_maximal_speed(motordriver * m, int value);
 mdv_error mdv_set_maximal_torque(motordriver * m, int value);
 
 
 mdv_error mdv_set_gear_ratio(motordriver * m, int gear_mult, int gear_div);
 
 int mdv_get_gear_mult(motordriver * m);
 int mdv_get_gear_div(motordriver * m);
 
 int mdv_get_limit_position(motordriver * m);
 
 void mdv_load_persistent_sbcp_settings();
 
 
 typedef int ( * pos_evaluator_fptr )( );
 
 mdv_error mdv_calibrate_motor(motordriver * mdv,
                               unsigned int limit_pos,
                               unsigned int min_calibration_region,
                               unsigned int max_calibration_region,
                               int calibration_offset,
                               pos_evaluator_fptr pos_evaluator,
                               unsigned int pos_evaluator_max_value,
                               uint8_t statically_calibrated);
 
+
+/* never fails */
+void mdv_uncalibrate_motor(motordriver * mdv);
+
 extern motordriver * mdv1, * mdv2;
 
 #endif	/* MOTORDRIVER_H */
 
diff --git a/src/pindefs.c b/src/pindefs.c
index 5f9b5be..71997db 100644
--- a/src/pindefs.c
+++ b/src/pindefs.c
@@ -1,85 +1,85 @@
 #include "p33FJ128MC804.h"
 
 #include "pindefs.h"
 
 #include "motordriver.h"
 
 void pin_init()
 {
 	// pin default configuration
 	ADPCFG = 0xffff; 		// Set all Analog ports as Digital I/O
-//	TRISA = 0xffff;			// Everything is input
-//	TRISB = 0xffff;			// Everything is input
-        mdv_master_reset = gpio_create(GPIO_PORT_B,GPIO_PIN_15,GPIO_OUTPUT);
+	//	TRISA = 0xffff;			// Everything is input
+	//	TRISB = 0xffff;			// Everything is input
+	mdv_master_reset = gpio_create(GPIO_PORT_B,GPIO_PIN_15,GPIO_OUTPUT);
 
 	// set motor 1 control pins to output
-//	TRISCbits.TRISC3 = 0;	// MODE1 is output
-//	TRISBbits.TRISB11 = 0;	// DIR1 is output
+	//	TRISCbits.TRISC3 = 0;	// MODE1 is output
+	//	TRISBbits.TRISB11 = 0;	// DIR1 is output
 	TRISBbits.TRISB14 = 0;	// TRQ1 is output
 	TRISBbits.TRISB10 = 0;	// SPD1 is output
-//	TRISAbits.TRISA4 = 0;	// COAST1 is output
-//	TRISAbits.TRISA3 = 0;	// BREAK1 is output
-//	TRISAbits.TRISA0 = 1;	// CSOUT1 is input (analog input)
-//
-//	// set motor 2 control pins to output
-//	TRISAbits.TRISA9 = 0;	// MODE2 is output
-//	TRISAbits.TRISA7 = 0;	// DIR2 is output
+	//	TRISAbits.TRISA4 = 0;	// COAST1 is output
+	//	TRISAbits.TRISA3 = 0;	// BREAK1 is output
+	//	TRISAbits.TRISA0 = 1;	// CSOUT1 is input (analog input)
+	//
+	//	// set motor 2 control pins to output
+	//	TRISAbits.TRISA9 = 0;	// MODE2 is output
+	//	TRISAbits.TRISA7 = 0;	// DIR2 is output
 	TRISCbits.TRISC6 = 0;	// TRQ2 is output
 	TRISBbits.TRISB12 = 0;	// SPD2 is output
-//	TRISAbits.TRISA8 = 0;	// COAST2 is output
-//	TRISAbits.TRISA10 = 0;	// BREAK2 is output
-//	TRISAbits.TRISA1 = 1;	// CSOUT2 is input (analog input)
+	//	TRISAbits.TRISA8 = 0;	// COAST2 is output
+	//	TRISAbits.TRISA10 = 0;	// BREAK2 is output
+	//	TRISAbits.TRISA1 = 1;	// CSOUT2 is input (analog input)
 
 	// set motors reset pin to output
 	mdv_master_reset_enable();			// set the motor drivers in reset-state
 
 	// set motors error feedback pin to input
 	TRISBbits.TRISB13 = 1;	// FF2 is input
 
 	// quadrature encoder inputs
 	TRISCbits.TRISC4 = 1;	// QEI1_A is input
 	TRISCbits.TRISC5 = 1;	// QEI1_B is input
 	TRISBbits.TRISB6 = 1;	// QEI2_A is input
 	TRISBbits.TRISB7 = 1;	// QEI2_B is input
 
 	// RC servo pins
 	TRISBbits.TRISB0 = 0;	// SERVO1 is output
 	TRISBbits.TRISB1 = 0;	// SERVO2 is output
 
 	// SPI 1 interface: absolute magnetic encoders
 	TRISBbits.TRISB8 = 0; 	// SPI1_CLK is output
 	TRISBbits.TRISB4 = 0;	// SPI1_CS is output
 	TRISBbits.TRISB9 = 1;	// SPI1_DI is input
 
 	// SPI 2 interface: force/torque sensors
-	TRISCbits.TRISC7 = 0;	// SPI2_CLK is output
-	TRISBbits.TRISB5 = 0;	// SPI2_CS is output
-	TRISCbits.TRISC8 = 1;	// SPI2_DI is input
-	TRISCbits.TRISC9 = 0;	// SPI2_DO is output
-	TRISBbits.TRISB2 = 0;	// SPI2_SYNC is output
+	TRISBbits.TRISB5 = 0;	// SPI2_CLK is output
+	TRISBbits.TRISB2 = 0;	// SPI2_CS is output
+	TRISCbits.TRISC9 = 1;	// SPI2_DI is input
+	TRISCbits.TRISC7 = 0;	// SPI2_DO is output
+	TRISCbits.TRISC8 = 0;	// SPI2_SYNC is output
 
 	// General Purpose led
 	TRISBbits.TRISB3 = 0;	// LED is output
 
 	// RS485 interface pins
-//	TRISCbits.TRISC2 = 0;	// RS485 enable pin is output
-//	TRISCbits.TRISC1 = 0;	// RS485 transmit pin is output
-//	TRISCbits.TRISC0 = 1;	// RS485 receive pin is input
-//        PORT_RS485_RECEIVER_DISABLE;
+	//	TRISCbits.TRISC2 = 0;	// RS485 enable pin is output
+	//	TRISCbits.TRISC1 = 0;	// RS485 transmit pin is output
+	//	TRISCbits.TRISC0 = 1;	// RS485 receive pin is input
+	//        PORT_RS485_RECEIVER_DISABLE;
 
-        //UART1 connects to RS485
+	//UART1 connects to RS485
 
-//	RPINR18  = 0b0001111100000000;		//tie U1CTS to Vss, tie UART1RX to RP0
-//	RPOR0    = 0b0000001100000000;		//tie UART1TX to RP1
+	//	RPINR18  = 0b0001111100000000;		//tie U1CTS to Vss, tie UART1RX to RP0
+	//	RPOR0    = 0b0000001100000000;		//tie UART1TX to RP1
 
 
-        //SPI 1 configuration. It may already be configured, but better to repeat
+	//SPI 1 configuration. It may already be configured, but better to repeat
 	_SDI1R = 9; // Map SPI 1 DI to RP 9
 	_RP8R = 8; // Map RP8 to SPI 1 Clock Output
 
 	//SPI 2 configuration, it may already be configured, but better to repeat
-	_SDI2R = 24; //Map SPI 2 DI to RP24
+	/*_SDI2R = 24; //Map SPI 2 DI to RP24
 	_RP23R = 11; //Map RP23 to SPI 2 Clock Output
-	_RP25R = 10; //Map RP25 to SPI2 DO
+	_RP25R = 10; //Map RP25 to SPI2 DO*/
 }
 
diff --git a/src/pindefs.h b/src/pindefs.h
index 84e1102..b6294fd 100644
--- a/src/pindefs.h
+++ b/src/pindefs.h
@@ -1,34 +1,40 @@
 #ifndef PINDEFS_H
 #define PINDEFS_H
 
 #include <gpio.h>
 
 
 
 
 
 
 // SPI 2 interface: force/torque sensors
 //#define SPI2_CLK				LATCbits.LATC7
 //#define SPI2_CS					LATBbits.LATB5
 //#define SPI2_DI					LATCbits.LATC8
 //#define SPI2_DO					LATCbits.LATC9
 //#define SPI2_SYNC				LATBbits.LATB2
 
 // General Purpose led
+#define BLINK ((systime>>8)&0x01)
 #define LED						LATBbits.LATB3
 #define LED_ENABLE (LED = 1)
 #define LED_DISABLE (LED = 0)
 #define LED_TOGGLE (LED = !LED)
 
+#define led_disable() do{ LED = 0; }while(0)
 
-// debug led
-#define LED_TX					LATCbits.LATC1
-#define LED_TX_ENABLE (LED_TX = 0)
-#define LED_TX_DISABLE (LED_TX = 1)
-#define LED_TX_TOGGLE (LED_TX = !LED_TX)
+#define led_toggle() do{ LED = !LED; }while(0)
+
+
+// tx led
+#define LED_TX (LATCbits.LATC1)
+#define led_tx_enable() do{ LED_TX = 0; }while(0)
+
+#define led_tx_disable() do  { LED_TX = 1; } while(0)
+#define led_tx_toggle() do { LED_TX = !LED_TX; } while(0)
 
 void pin_init();
 
 #endif // PINDEFS_H
 
diff --git a/src/pwm.c b/src/pwm.c
index c779f8c..d55c2dd 100644
--- a/src/pwm.c
+++ b/src/pwm.c
@@ -1,49 +1,49 @@
 #include "pwm.h"
 
 #include <gpio.h>
 
 
 void pwm_init(pwm_t * pwm, pwm_device_t device){
-    switch(device){
-        case PWM_1_1 :
-            pwm->DC        = &(P1DC1);
-            pwm->TPER      = &(P1TPER);
-            pwm->TCON      = &(P1TCON);
-            pwm->CON1      = &(PWM1CON1);
-            pwm->pin       = 0;
-            break;
-        case PWM_1_2 :
-            pwm->DC        = &(P1DC2);
-            pwm->TPER      = &(P1TPER);
-            pwm->TCON      = &(P1TCON);
-            pwm->CON1      = &(PWM1CON1);
-            pwm->pin       = 1;
-            break;
-        case PWM_1_3 :
-            pwm->DC        = &(P1DC3);
-            pwm->TPER      = &(P1TPER);
-            pwm->TCON      = &(P1TCON);
-            pwm->CON1      = &(PWM1CON1);
-            pwm->pin       = 2;
-            break;
-        case PWM_2_1 :
-            pwm->DC        = &(P2DC1);
-            pwm->TPER      = &(P2TPER);
-            pwm->TCON      = &(P2TCON);
-            pwm->CON1      = &(PWM2CON1);
-            pwm->pin       = 0;
-            break;
-        default :
-            pwm->DC       = 0;
-            pwm->TCON     = 0;
-            pwm->CON1     = 0;
-            pwm->TPER     = 0;
-            pwm->pin      = 0;
-            break;
-    }
-    //enable the channel globally
-    atomic_or(pwm->TCON , 1 << 15);
-    //initialize the pin as an output !!!
-    atomic_or(pwm->CON1, ( 1 << (pwm->pin + 4)) | (1 << (pwm->pin + 8)));
+	switch(device){
+	case PWM_1_1 :
+		pwm->DC        = &(P1DC1);
+		pwm->TPER      = &(P1TPER);
+		pwm->TCON      = &(P1TCON);
+		pwm->CON1      = &(PWM1CON1);
+		pwm->pin       = 0;
+		break;
+	case PWM_1_2 :
+		pwm->DC        = &(P1DC2);
+		pwm->TPER      = &(P1TPER);
+		pwm->TCON      = &(P1TCON);
+		pwm->CON1      = &(PWM1CON1);
+		pwm->pin       = 1;
+		break;
+	case PWM_1_3 :
+		pwm->DC        = &(P1DC3);
+		pwm->TPER      = &(P1TPER);
+		pwm->TCON      = &(P1TCON);
+		pwm->CON1      = &(PWM1CON1);
+		pwm->pin       = 2;
+		break;
+	case PWM_2_1 :
+		pwm->DC        = &(P2DC1);
+		pwm->TPER      = &(P2TPER);
+		pwm->TCON      = &(P2TCON);
+		pwm->CON1      = &(PWM2CON1);
+		pwm->pin       = 0;
+		break;
+	default :
+		pwm->DC       = 0;
+		pwm->TCON     = 0;
+		pwm->CON1     = 0;
+		pwm->TPER     = 0;
+		pwm->pin      = 0;
+		break;
+	}
+	//enable the channel globally
+	atomic_or(pwm->TCON , 1 << 15);
+	//initialize the pin as an output !!!
+	atomic_or(pwm->CON1, ( 1 << (pwm->pin + 4)) | (1 << (pwm->pin + 8)));
 
 }
diff --git a/src/pwm.h b/src/pwm.h
index 288c020..efadf4e 100644
--- a/src/pwm.h
+++ b/src/pwm.h
@@ -1,51 +1,53 @@
 /*
  * File:   pwm.h
  * Author: tuleu
  *
  * Created on September 13, 2012, 2:24 PM
  */
 
 #ifndef PWM_H
 #define	PWM_H
 
 #include <p33Fxxxx.h>
 
 enum pwm_device_t {
-    PWM_1_1,
-    PWM_1_2,
-    PWM_1_3,
-    PWM_2_1
+	PWM_1_1,
+	PWM_1_2,
+	PWM_1_3,
+	PWM_2_1
 };
 
 typedef enum pwm_device_t pwm_device_t;
 
 
 struct pwm_t {
-    volatile unsigned int  * DC;
-    volatile unsigned int  * TCON;
-    volatile unsigned int  * CON1;
-    volatile unsigned int  * TPER;
-    unsigned char            pin;
+	volatile unsigned int  * DC;
+	volatile unsigned int  * TCON;
+	volatile unsigned int  * CON1;
+	volatile unsigned int  * TPER;
+	unsigned char            pin;
 };
 
 typedef struct pwm_t pwm_t;
 
 
 void pwm_init(pwm_t * pwm, pwm_device_t device);
 
 
-#define pwm_set_cycle(pwm,value) do{\
-*(pwm.TPER) = value;\
-}while(0)
+#define pwm_set_cycle(pwm,value) \
+	do{ \
+		*(pwm.TPER) = value; \
+	}while(0)
 
-#define pwm_set_value(pwm,value) do{\
-*(pwm.DC) = value;\
-}while(0)
+#define pwm_set_value(pwm,value) \
+	do{ \
+		*(pwm.DC) = value; \
+	}while(0)
 
 
 
 
 
 
 #endif	/* PWM_H */
 
diff --git a/src/sbcp_mdv.c b/src/sbcp_mdv.c
index 2aec0de..c6c4ca5 100644
--- a/src/sbcp_mdv.c
+++ b/src/sbcp_mdv.c
@@ -1,392 +1,419 @@
 #include "sbcp_mdv.h"
 #include "motordriver.h"
 #include "magnetic_encoder.h"
 #include "load_cell.h"
 #include <packet.h>
+#include "misc_math.h"
 
 /*******************************************************************************
  * C A L L B A C K S
  *******************************************************************************/
 
 
 typedef mdv_error (*set_param_fptr)(motordriver * mdv, int value);
 typedef int (*get_param_fptr)(motordriver * mdv);
 
 
 struct sbcp_mdv_setter_and_getter {
 	set_param_fptr  setter;
 	get_param_fptr  getter;
 };
 
 
 struct sbcp_mdv_setter_and_getter mdv_gAs[MX_REGISTER_SIZE];
 
 #ifndef NDEBUG
 enum sbcp_mdv_communication_error{
 	SBCP_MDV_CERR_NOT_A_MDV_REGISTER = MDV_ERR_NB_ERRORS, //6
 	SBCP_MDV_CERR_GETTER_UNSET, //7
 	SBCP_MDV_CERR_SETTER_UNSET  // 8
 };
 #endif
 
 
 sbcp_error sbcp_mdv_generic_clbk(sbcp_reg_address address, sbcp_reg_val * value){
 
 #ifndef NDEBUG
 
 	if(address < MDV_M1 || address > MDV_M2 + MX_REGISTER_SIZE){
 		return SBCP_MDV_CERR_NOT_A_MDV_REGISTER;
 	}
 #endif
 
 	enum sbcp_mdv_mX_register reg = address < MDV_M2 ? address - MDV_M1 : address - MDV_M2;
 	motordriver * mdv = address < MDV_M2 ? mdv1 : mdv2;
 	struct sbcp_mdv_setter_and_getter gAs = mdv_gAs[reg];
 
 #ifndef NDEBUG
 	if(gAs.setter == 0x00){
 		return SBCP_MDV_CERR_SETTER_UNSET;
 	}
 	if(gAs.getter == 0x00){
 		return SBCP_MDV_CERR_GETTER_UNSET;
 	}
 #endif
 
 	sbcp_error err = (*(gAs.setter))(mdv,value->i);
 
 	value->i = (*(gAs.getter))(mdv);
 
 	return err;
 }
 
 
 sbcp_error sbcp_mdv_generic_param_clbk(sbcp_reg_address address, sbcp_reg_val * value){
 	///\todo add min max value
 	mdv_parameters * params = (address < MDV_M2) ? mdv_get_parameters(mdv1) : mdv_get_parameters(mdv2);
 
 	switch( address < MDV_M2 ? address - MDV_M1 : address - MDV_M2){
 	case MX_PID_PGAIN :
 		params->p_gain = value->u;
 		break;
 	case MX_PID_IGAIN :
 		params->i_gain = value->u;
 		break;
 	case MX_PID_DGAIN :
 		params->d_gain = value->u;
 		break;
 	case MX_COMPLIANCE_PRELOAD :
 		params->preload = value->i;
 		break;
 	case MX_COMPLIANCE_STIFFNESS :
 		params->stiffness = value->u;
 		break;
 	case MX_COMPLIANCE_DAMPING :
 		params->damping = value->u;
 		break;
 	case MX_SMOOTH_POSITION_UPDATE :
 		params->smooth_interval = value->u;
 		break;
 	default :
 		return 42;
 	}
 
 	return SBCP_NO_ERROR;
 }
 
 
 sbcp_error sbcp_mdv_gear_clbk(sbcp_reg_address address, sbcp_reg_val * value){
 	motordriver * mdv = address < MDV_M2 ? mdv1 : mdv2;
 
 	enum sbcp_mdv_mX_register reg = address < MDV_M2 ? address - MDV_M1 : address - MDV_M2;
 
 	//get the gear either from the table, or the new value if this the one being set
 	int gear_mult = reg == MX_GEAR_MULT ? value->i : sbcp_reg_int(address);
 	int gear_div  = reg == MX_GEAR_DIV ? value->i : sbcp_reg_int(address);
 
 	return mdv_set_gear_ratio(mdv,gear_mult,gear_div);
 }
 
 
 void init_sbcp_register_for_mdv(motordriver * mdv , sbcp_reg_address address_start){
 
 #ifndef NDEBUG
 	unsigned int i;
 	for(i = 0; i < MX_REGISTER_SIZE; ++i){
 		mdv_gAs[i].setter = (set_param_fptr) 0x00;
 		mdv_gAs[i].getter = (get_param_fptr) 0x00;
 	}
 #endif
-        mdv_gAs[MX_STATUS_AND_CONTROL_MODE].setter = & mdv_set_control_mode;
-        mdv_gAs[MX_STATUS_AND_CONTROL_MODE].getter = & mdv_get_control_mode;
+	mdv_gAs[MX_STATUS_AND_CONTROL_MODE].setter = & mdv_set_control_mode;
+	mdv_gAs[MX_STATUS_AND_CONTROL_MODE].getter = & mdv_get_control_mode;
 
 
 	mdv_gAs[MX_GOAL_POSITION].setter    = &mdv_set_goal_position;
 	mdv_gAs[MX_GOAL_POSITION].getter    = &mdv_get_goal_position;
 
 	mdv_gAs[MX_GOAL_SPEED].setter       = &mdv_set_goal_speed;
 	mdv_gAs[MX_GOAL_SPEED].getter       = &mdv_get_goal_speed;
 
 	mdv_gAs[MX_MAX_ACCELERATION].setter = &mdv_set_maximal_acceleration;
 	mdv_gAs[MX_MAX_ACCELERATION].getter = &mdv_get_maximal_acceleration;
 
 	mdv_gAs[MX_MAX_SPEED].setter        = &mdv_set_maximal_speed;
 	mdv_gAs[MX_MAX_SPEED].getter        = &mdv_get_maximal_speed;
 
 	mdv_gAs[MX_MAX_TORQUE].setter       = &mdv_set_maximal_torque;
 	mdv_gAs[MX_MAX_TORQUE].getter       = &mdv_get_maximal_torque;
 
 
 	sbcp_add_register(address_start + MX_STATUS_AND_CONTROL_MODE,
 	                  mdv_get_status_and_control_mode(mdv),
 	                  SBCP_REG_READABLE | SBCP_REG_WRITABLE,
 	                  &sbcp_mdv_generic_clbk);
 
 	sbcp_add_register(address_start + MX_GOAL_POSITION,
 	                  mdv_get_goal_position(mdv),
 	                  SBCP_REG_READABLE | SBCP_REG_WRITABLE,
 	                  &sbcp_mdv_generic_clbk);
 
 	sbcp_add_register(address_start + MX_TARGETED_POSITION,
 	                  mdv_get_virtual_goal_position(mdv),
 	                  SBCP_REG_READABLE ,
 	                  SBCP_REG_NO_CALLBACK);
 
 	sbcp_add_register(address_start + MX_PRESENT_POSITION,
 	                  mdv_get_position(mdv),
 	                  SBCP_REG_READABLE ,
 	                  SBCP_REG_NO_CALLBACK);
 
 	sbcp_add_register(address_start + MX_GOAL_SPEED,
 	                  mdv_get_goal_speed(mdv),
 	                  SBCP_REG_READABLE | SBCP_REG_WRITABLE,
 	                  &sbcp_mdv_generic_clbk);
 
 	sbcp_add_register(address_start + MX_TARGETED_SPEED,
 	                  mdv_get_virtual_goal_speed(mdv),
 	                  SBCP_REG_READABLE ,
 	                  SBCP_REG_NO_CALLBACK);
 
 	sbcp_add_register(address_start + MX_PRESENT_SPEED,
 	                  mdv_get_speed(mdv),
 	                  SBCP_REG_READABLE ,
 	                  SBCP_REG_NO_CALLBACK);
 
 
 	sbcp_add_register(address_start + MX_TARGETED_TORQUE,
 	                  mdv_get_targeted_torque(mdv),
 	                  SBCP_REG_READABLE ,
 	                  SBCP_REG_NO_CALLBACK);
 
 
 	sbcp_add_register(address_start + MX_PID_PGAIN,
 	                  mdv_get_parameters(mdv)->p_gain,
 	                  SBCP_REG_READABLE | SBCP_REG_WRITABLE,
 	                  &sbcp_mdv_generic_param_clbk);
 
 	sbcp_add_register(address_start + MX_PID_IGAIN,
 	                  mdv_get_parameters(mdv)->i_gain,
 	                  SBCP_REG_READABLE | SBCP_REG_WRITABLE,
 	                  &sbcp_mdv_generic_param_clbk);
 
 	sbcp_add_register(address_start + MX_PID_DGAIN,
 	                  mdv_get_parameters(mdv)->d_gain,
 	                  SBCP_REG_READABLE | SBCP_REG_WRITABLE,
 	                  &sbcp_mdv_generic_param_clbk);
 
-        sbcp_add_register(address_start + MX_COMPLIANCE_PRELOAD,
+	sbcp_add_register(address_start + MX_COMPLIANCE_PRELOAD,
 	                  mdv_get_parameters(mdv)->preload,
 	                  SBCP_REG_READABLE | SBCP_REG_WRITABLE,
 	                  &sbcp_mdv_generic_param_clbk);
 
 	sbcp_add_register(address_start + MX_COMPLIANCE_STIFFNESS,
 	                  mdv_get_parameters(mdv)->stiffness,
 	                  SBCP_REG_READABLE | SBCP_REG_WRITABLE,
 	                  &sbcp_mdv_generic_param_clbk);
 
 	sbcp_add_register(address_start + MX_COMPLIANCE_DAMPING,
 	                  mdv_get_parameters(mdv)->damping,
 	                  SBCP_REG_READABLE | SBCP_REG_WRITABLE,
 	                  &sbcp_mdv_generic_param_clbk);
 
 
 	sbcp_add_register(address_start + MX_MAX_ACCELERATION,
 	                  mdv_get_maximal_acceleration(mdv),
 	                  SBCP_REG_READABLE | SBCP_REG_WRITABLE,
 	                  &sbcp_mdv_generic_clbk);
 
 	sbcp_add_register(address_start + MX_MAX_SPEED,
 	                  mdv_get_maximal_speed(mdv),
 	                  SBCP_REG_READABLE | SBCP_REG_WRITABLE,
 	                  &sbcp_mdv_generic_clbk);
 
 	sbcp_add_register(address_start + MX_MAX_TORQUE,
 	                  mdv_get_maximal_torque(mdv),
 	                  SBCP_REG_READABLE | SBCP_REG_WRITABLE,
 	                  &sbcp_mdv_generic_clbk);
 
 
 	sbcp_add_register(address_start + MX_GEAR_MULT,
 	                  mdv_get_gear_mult(mdv),
 	                  SBCP_REG_READABLE | SBCP_REG_WRITABLE | SBCP_REG_PERSISTENT,
 	                  &sbcp_mdv_gear_clbk);
 
 	sbcp_add_register(address_start + MX_GEAR_DIV,
 	                  mdv_get_gear_div(mdv),
 	                  SBCP_REG_READABLE | SBCP_REG_WRITABLE | SBCP_REG_PERSISTENT,
 	                  &sbcp_mdv_gear_clbk);
 
 	sbcp_add_register(address_start + MX_LIMIT_POS_CW,
 	                  ANGULAR_RESOLUTION - 1,
 	                  SBCP_REG_READABLE | SBCP_REG_WRITABLE | SBCP_REG_PERSISTENT,
 	                  SBCP_REG_NO_CALLBACK);
 
 	sbcp_add_register(address_start + MX_CALIBRATION_REGION_MIN,
 	                  0,
 	                  SBCP_REG_READABLE | SBCP_REG_WRITABLE | SBCP_REG_PERSISTENT,
 	                  SBCP_REG_NO_CALLBACK);
 
 	sbcp_add_register(address_start + MX_CALIBRATION_REGION_MAX,
 	                  ANGULAR_RESOLUTION - 1,
 	                  SBCP_REG_READABLE | SBCP_REG_WRITABLE | SBCP_REG_PERSISTENT,
 	                  SBCP_REG_NO_CALLBACK);
 
 
 	sbcp_add_register(address_start + MX_CALIBRATION_OFFSET,
 	                  0,
 	                  SBCP_REG_READABLE | SBCP_REG_WRITABLE | SBCP_REG_PERSISTENT,
 	                  SBCP_REG_NO_CALLBACK);
 
 	sbcp_add_register(address_start + MX_SMOOTH_POSITION_UPDATE,
 	                  mdv_get_parameters(mdv)->smooth_interval,
 	                  SBCP_REG_READABLE | SBCP_REG_WRITABLE,
 	                  &sbcp_mdv_generic_param_clbk);
 
 
 }
 
 sbcp_error magnetic_encoder_gear_clbk(sbcp_reg_address addr, sbcp_reg_val * value){
 	magnetic_encoder * q = 0;
 	if(addr >= MDV_ME_Q1 && addr < MDV_ME_Q2){
 		q = me1;
 		addr -= MDV_ME_Q1;
 	} else if ( addr < MDV_ME_Q3) {
 		q = me2;
 		addr -= MDV_ME_Q2;
 	} else if ( addr < MDV_ME_Q3 + MEX_REGISTER_SIZE){
 		q = me3;
 		addr -= MDV_ME_Q3;
 	} else {
 		/** \todo replace this 42 */
 		return 42;
 	}
 
 	int gear_mult =  addr == MEX_GEAR_MULT ? value->i : me_get_gear_mult(q);
 	int gear_div  =  addr == MEX_GEAR_DIV  ? value->i : me_get_gear_div(q);
 
 	me_set_gear_ratio(q,gear_mult,gear_div);
 
 
 	return SBCP_NO_ERROR;
 }
 
 
 void init_sbcp_register_for_magnetic_encoder(magnetic_encoder * q, sbcp_reg_address start){
 	sbcp_add_register(start + MEX_POSITION,
 	                  me_get_value(q),
 	                  SBCP_REG_READABLE,
 	                  SBCP_REG_NO_CALLBACK);
 
 	sbcp_add_register(start + MEX_GEAR_MULT,
 	                  me_get_gear_mult(q),
 	                  SBCP_REG_READABLE | SBCP_REG_WRITABLE | SBCP_REG_PERSISTENT,
 	                  &magnetic_encoder_gear_clbk);
 
 	sbcp_add_register(start + MEX_GEAR_DIV,
 	                  me_get_gear_div(q),
 	                  SBCP_REG_READABLE | SBCP_REG_WRITABLE | SBCP_REG_PERSISTENT,
 	                  & magnetic_encoder_gear_clbk);
+
+
 }
 
+void init_sbcp_register_for_sine(sbcp_reg_address start, int defaultAmplitude,
+                                 int defaultOffset,
+                                 int defaultFrequency){
+	sbcp_add_register_no_callback(start + SINE_FREQUENCY, defaultFrequency, SBCP_REG_READABLE | SBCP_REG_WRITABLE);
+	sbcp_add_register_no_callback(start + SINE_OFFSET, defaultOffset, SBCP_REG_READABLE | SBCP_REG_WRITABLE);
+	sbcp_add_register_no_callback(start + SINE_AMPLITUDE, defaultAmplitude, SBCP_REG_READABLE | SBCP_REG_WRITABLE);
+}
 
 void init_sbcp_register_for_load_cell(load_cell * q, sbcp_reg_address start){
 	sbcp_add_register(start + LCX_TORQUE,
 	                  lc_get_torque(q),
 	                  SBCP_REG_READABLE,
 	                  SBCP_REG_NO_CALLBACK);
 }
 
 void init_sbcp_mdv_registers(){
 	init_sbcp_register_for_magnetic_encoder(me1,MDV_ME_Q1);
 	init_sbcp_register_for_magnetic_encoder(me2,MDV_ME_Q2);
 	init_sbcp_register_for_magnetic_encoder(me3,MDV_ME_Q3);
         init_sbcp_register_for_load_cell(lc1,MDV_LC_AXIS_1);
         init_sbcp_register_for_load_cell(lc2,MDV_LC_AXIS_2);
         init_sbcp_register_for_load_cell(lc3,MDV_LC_AXIS_3);
 	
 	init_sbcp_register_for_mdv(mdv1,MDV_M1);
 	init_sbcp_register_for_mdv(mdv2,MDV_M2);
 
 	sbcp_append_low_latency_in_register(MDV_M1 + MX_GOAL_POSITION);
 	sbcp_append_low_latency_in_register(MDV_M2 + MX_GOAL_POSITION);
 
-	sbcp_append_low_latency_out_register(MDV_M1 + MX_PRESENT_POSITION);
-	sbcp_append_low_latency_out_register(MDV_M1 + MX_TARGETED_TORQUE);
+        sbcp_append_low_latency_out_register(MDV_M1 + MX_GOAL_SPEED);
+	sbcp_append_low_latency_out_register(MDV_M2 + MX_GOAL_SPEED);
 
+	sbcp_append_low_latency_out_register(MDV_M1 + MX_PRESENT_POSITION);
 	sbcp_append_low_latency_out_register(MDV_M2 + MX_PRESENT_POSITION);
+
+	sbcp_append_low_latency_out_register(MDV_M1 + MX_PRESENT_SPEED);
+	sbcp_append_low_latency_out_register(MDV_M2 + MX_PRESENT_SPEED);
+
+	sbcp_append_low_latency_out_register(MDV_M1 + MX_TARGETED_TORQUE);
 	sbcp_append_low_latency_out_register(MDV_M2 + MX_TARGETED_TORQUE);
 
-	sbcp_append_low_latency_out_register(MDV_ME_Q1 + MEX_POSITION);
+        sbcp_append_low_latency_out_register(MDV_ME_Q1 + MEX_POSITION);
 	sbcp_append_low_latency_out_register(MDV_ME_Q2 + MEX_POSITION);
 	sbcp_append_low_latency_out_register(MDV_ME_Q3 + MEX_POSITION);
 
 	sbcp_append_low_latency_out_register(MDV_LC_AXIS_1 + LCX_TORQUE);
 	sbcp_append_low_latency_out_register(MDV_LC_AXIS_2 + LCX_TORQUE);
 	sbcp_append_low_latency_out_register(MDV_LC_AXIS_3 + LCX_TORQUE);
 
 }
 
 
 int get_me1(){
 	return me_get_value(me1);
 }
 
 
 int get_me2(){
-	return me_get_value(me1);
+	return me_get_value(me2);
 }
 
-void sbcp_calibrate_motor(unsigned int * b){
+void sbcp_calibrate_motors(unsigned int * b){
 	sbcp_error err ;
 	err = mdv_calibrate_motor(mdv1,
 	                          sbcp_reg_table[MDV_M1 + MX_LIMIT_POS_CW].u & 0x7fff,
 	                          sbcp_reg_table[MDV_M1 + MX_CALIBRATION_REGION_MIN].u,
 	                          sbcp_reg_table[MDV_M1 + MX_CALIBRATION_REGION_MAX].u,
 	                          sbcp_reg_table[MDV_M1 + MX_CALIBRATION_OFFSET].i,
 	                          &get_me1,
-	                          me_get_gear_mult(me1)* (ANGULAR_RESOLUTION - 1) / me_get_gear_div(me1),
+	                          abs((long)me_get_gear_mult(me1)* ((long)ANGULAR_RESOLUTION ) / (long)me_get_gear_div(me1)),
 	                          (sbcp_reg_table[MDV_M1 + MX_LIMIT_POS_CW].u & 0x8000) >> 15);
 
 	if(err != MDV_ERR_NO_ERROR){
 		sbcp_prepare_r_packet(0,err);
 		sbcp_mark_r_packet_ready();
 		return;
 	}
 
 	err = mdv_calibrate_motor(mdv2,
 	                          sbcp_reg_table[MDV_M2 + MX_LIMIT_POS_CW].u & 0x0fff,
 	                          sbcp_reg_table[MDV_M2 + MX_CALIBRATION_REGION_MIN].u,
 	                          sbcp_reg_table[MDV_M2 + MX_CALIBRATION_REGION_MAX].u,
 	                          sbcp_reg_table[MDV_M2 + MX_CALIBRATION_OFFSET].i,
 	                          &get_me2,
-	                          me_get_gear_mult(me2)* (ANGULAR_RESOLUTION - 1) / me_get_gear_div(me2),
+	                          abs((long)me_get_gear_mult(me2)* ((long)ANGULAR_RESOLUTION) / (long)me_get_gear_div(me2)),
 	                          (sbcp_reg_table[MDV_M2 + MX_LIMIT_POS_CW].u & 0x8000) >> 15);
 
 	sbcp_prepare_r_packet(0,err);
 	sbcp_mark_r_packet_ready();
 
 }
 
+void sbcp_uncalibrate_motors(){
+	mdv_uncalibrate_motor(mdv1);
+	mdv_uncalibrate_motor(mdv2);
+
+	sbcp_prepare_r_packet(0,SBCP_NO_ERROR);
+	sbcp_mark_r_packet_ready();
+}
+
 void init_sbcp_mdv_instructions(){
 	sbcp_add_instruction(SBCP_MDV_CALIBRATE_MOTORS,
-	                     &sbcp_calibrate_motor);
+	                     &sbcp_calibrate_motors);
+
+	sbcp_add_instruction(SBCP_MDV_UNCALIBRATE_MOTORS,
+	                     &sbcp_uncalibrate_motors);
 }
diff --git a/src/sbcp_mdv.h b/src/sbcp_mdv.h
index aaf8bbd..48bacfe 100644
--- a/src/sbcp_mdv.h
+++ b/src/sbcp_mdv.h
@@ -1,101 +1,114 @@
 /*
  * File:   sbcp_mdv.h
  * Author: tuleu
  *
  * Created on September 12, 2012, 6:09 PM
  */
 
 #ifndef SBCP_MDV_H_
 #define	SBCP_MDV_H_
 
 #include <sbcp.h>
 
 enum sbcp_mdv_mX_register {
 	MX_STATUS_AND_CONTROL_MODE = 0,
 
-	MX_GOAL_POSITION =1,
-	MX_TARGETED_POSITION = 2,
-	MX_PRESENT_POSITION = 3,
+	MX_GOAL_POSITION           = 1,
+	MX_TARGETED_POSITION       = 2,
+	MX_PRESENT_POSITION        = 3,
 
-	MX_GOAL_SPEED = 4,
-	MX_TARGETED_SPEED = 5,
-	MX_PRESENT_SPEED = 6,
+	MX_GOAL_SPEED              = 4,
+	MX_TARGETED_SPEED          = 5,
+	MX_PRESENT_SPEED           = 6,
 
-	MX_TARGETED_TORQUE = 7,
+	MX_TARGETED_TORQUE         = 7,
 
-	MX_PID_PGAIN = 8,
-	MX_PID_IGAIN = 9,
-	MX_PID_DGAIN = 10,
+	MX_PID_PGAIN               = 8,
+	MX_PID_IGAIN               = 9,
+	MX_PID_DGAIN               = 10,
 
-	MX_COMPLIANCE_PRELOAD = 11,
-	MX_COMPLIANCE_STIFFNESS = 12,
-	MX_COMPLIANCE_DAMPING = 13,
-	MX_MAX_ACCELERATION = 14,
-	MX_MAX_SPEED = 15,
-	MX_MAX_TORQUE = 16,
+	MX_COMPLIANCE_PRELOAD      = 11,
+	MX_COMPLIANCE_STIFFNESS    = 12,
+	MX_COMPLIANCE_DAMPING      = 13,
+	MX_MAX_ACCELERATION        = 14,
 
+	MX_MAX_SPEED               = 15,
+	MX_MAX_TORQUE              = 16,
 
-	MX_GEAR_MULT = 17,
-	MX_GEAR_DIV = 18,
 
-	MX_LIMIT_POS_CW = 19,
-	MX_CALIBRATION_REGION_MIN = 20,
-	MX_CALIBRATION_REGION_MAX = 21,
-	MX_CALIBRATION_OFFSET = 22,
+	MX_GEAR_MULT               = 17,
+	MX_GEAR_DIV                = 18,
 
-	MX_SMOOTH_POSITION_UPDATE = 23,
+	MX_LIMIT_POS_CW            = 19,
+	MX_CALIBRATION_REGION_MIN  = 20,
+	MX_CALIBRATION_REGION_MAX  = 21,
+	MX_CALIBRATION_OFFSET      = 22,
 
+	MX_SMOOTH_POSITION_UPDATE  = 23,
 
-	MX_REGISTER_SIZE = 24
+
+	MX_REGISTER_SIZE           = 24
 };
 
 typedef enum sbcp_mdv_mx_register sbcp_mdv_mX_register;
 
 
 enum sbcp_mdv_meX_register {
-	MEX_POSITION  = 0,
-	MEX_GEAR_MULT = 1,
-	MEX_GEAR_DIV  = 2,
+	MEX_POSITION      = 0,
+	MEX_GEAR_MULT     = 1,
+	MEX_GEAR_DIV      = 2,
 	MEX_REGISTER_SIZE = 3
 };
 
 enum sbcp_mdv_lcX_register {
 	LCX_TORQUE  = 0,
 	LCX_REGISTER_SIZE = 1
 };
 
+enum sbcp_mdv_Sine_register {
+	SINE_FREQUENCY = 0,
+	SINE_AMPLITUDE = 1,
+	SINE_OFFSET    = 2,
+	SINE_REGISTER_SIZE
+};
+
 enum sbcp_mdv_register {
-	MDV_ME_Q1     = SBCP_SPECIFIC_REG_START, //3
+	MDV_ME_Q1     = SBCP_SPECIFIC_REG_START,           // 3
 
-	MDV_ME_Q2     = MDV_ME_Q1     + MEX_REGISTER_SIZE, //6
+	MDV_ME_Q2     = MDV_ME_Q1     + MEX_REGISTER_SIZE, // 6
 
-	MDV_ME_Q3     = MDV_ME_Q2     + MEX_REGISTER_SIZE, //9
+	MDV_ME_Q3     = MDV_ME_Q2     + MEX_REGISTER_SIZE, // 9
 
 	MDV_LC_AXIS_1 = MDV_ME_Q3     + MEX_REGISTER_SIZE, //12
 	MDV_LC_AXIS_2 = MDV_LC_AXIS_1 + LCX_REGISTER_SIZE, // 13
 	MDV_LC_AXIS_3 = MDV_LC_AXIS_2 + LCX_REGISTER_SIZE, // 14
 
-	MDV_M1        = MDV_LC_AXIS_3 + LCX_REGISTER_SIZE, //15
-	MDV_M2        = MDV_M1        + MX_REGISTER_SIZE   //39
-
+	MDV_M1        = MDV_LC_AXIS_3 + LCX_REGISTER_SIZE, // 15
+	MDV_M2        = MDV_M1        + MX_REGISTER_SIZE,  // 39
+	MDV_SINE_1    = MDV_M2        + MX_REGISTER_SIZE,  // 63
+	MDV_SINE_2    = MDV_SINE_1    + SINE_REGISTER_SIZE // 66
 };
 
 typedef enum sbcp_mdv_register sbcp_mdv_register;
 
 
 enum sbcp_mdv_instruction {
-	SBCP_MDV_CALIBRATE_MOTORS = SBCP_INST_DEVICE_SPECIFIC_START
+	SBCP_MDV_CALIBRATE_MOTORS   = SBCP_INST_DEVICE_SPECIFIC_START,
+	SBCP_MDV_UNCALIBRATE_MOTORS = SBCP_INST_DEVICE_SPECIFIC_START + 1
 };
 
+
+
+
 #define sbcp_mdv_reg(mdv,reg) (sbcp_reg_table[mdv->address_start + reg])
 
 #define sbcp_me_reg(me,reg) (sbcp_reg_table[me + reg])
 
 #define sbcp_lc_reg(lc,reg) (sbcp_reg_table[lc + reg])
 
 void init_sbcp_mdv_registers();
 
 void init_sbcp_mdv_instructions();
 
 #endif	/* SBCP_MDV_H */
 
diff --git a/src/timer.c b/src/timer.c
index b8477df..5a905d8 100644
--- a/src/timer.c
+++ b/src/timer.c
@@ -1,72 +1,71 @@
-
 #include "timer.h"
 
 #include "p33FJ128MC804.h"
 #include "config.h"
 
 
 #define NTOTPULSE		(FCY/FSYST -1)
 #define NTOTPULSE_SBCP	(FCY/FSBCPT -1)
 #define NTOTPULSE_SPI_ME_READING_LATENCY (FCY/FSPI_ME_READING_LATENCY - 1)
 
 volatile unsigned int systime;
 
 
 
 void timer_init()
 {
 	// Timer 1 is currently implemented in motorcontrol.c
 
 	/* Set timer 1 as main clock */
 	T1CONbits.TON = 0; 		// Disable Timer
 	T1CONbits.TCS = 0; 		// Select internal instruction cycle clock
 	T1CONbits.TGATE = 0; 	// Disable Gated Timer mode
 
 #if NTOTPULSE < 65535
 	/* 1x prescaler */
 	PR1 = NTOTPULSE;
 	T1CONbits.TCKPS = 0b00; // Select 1:1 Prescaler
 #elif NTOTPULSE < (8*65535)
 	/* 8x prescaler */
 	PR1 = NTOTPULSE/8;
 	T1CONbits.TCKPS = 0b01; // Select 1:8 Prescaler
 #else
 #error "FSYST - Check the values and maybe use a greater prescaler value"
 #endif
 
 	TMR1 = 0x00; 			// Clear timer register
 	IPC0bits.T1IP = 0x06; 		// Set Timer1 Interrupt Priority Level to 6 = very high priority
 	IFS0bits.T1IF = 0; 		// Clear Timer1 Interrupt Flag
 	IEC0bits.T1IE = 1; 		// Enable Timer1 interrupt
 	T1CONbits.TON = 1; 		// Start Timer
 
 	systime = 0;
 
-//		T2CONbits.T32 = 0;		// Select 16 bit mode
+	//		T2CONbits.T32 = 0;		// Select 16 bit mode
 
 	/* Set timer 2 for SBCP timeout */
 	T2CONbits.TON = 0; 			// Disable Timer
 	T2CONbits.TCS = 0; 		// Select internal instruction cycle clock
 	T2CONbits.TGATE = 0; 	// Disable Gated Timer mode
 
 #if NTOTPULSE_SPI_ME_READING_LATENCY < 65535
 	/* 1x prescaler */
 	PR2 = NTOTPULSE_SPI_ME_READING_LATENCY;
 	T2CONbits.TCKPS = 0b00; // Select 1:1 Prescaler
 #elif NTOTPULSE_SPI_ME_READING_LATENCY < (8*65535)
 	/* 8x prescaler */
 	PR2 = NTOTPULSE_SPI_ME_READING_LATENCY/8;
 	T2CONbits.TCKPS = 0b01; // Select 1:8 Prescaler
 #else
 #error "F_SPI_ME_REQADING_LATENCY - Check the values and maybe use a greater prescaler value"
 #endif
 
 	TMR2 = 0x00; 			// Clear timer register
 	IPC1bits.T2IP = 0x01; 	// Set Timer2 Interrupt Priority Level to 1 = low priority
 	IFS0bits.T2IF = 0; 		// Clear Timer2 Interrupt Flag
 	IEC0bits.T2IE = 1; 		// Enable Timer2 interrupt
 	// We do not activate timer 2 but keep it stopped until it is needed
 
 
 
 }