diff --git a/AstroEQ-ConfigUtility/AstroEQ.exe b/AstroEQ-ConfigUtility/AstroEQ.exe
index 18822d80397addb749862c90ea7657bdcb4b238b..58c73837b215561b2ff502779be15634bc23cb7d 100644
Binary files a/AstroEQ-ConfigUtility/AstroEQ.exe and b/AstroEQ-ConfigUtility/AstroEQ.exe differ
diff --git a/AstroEQ-ConfigUtility/hex/AstroEQATMega162Based(Legacy).hex b/AstroEQ-ConfigUtility/hex/AstroEQATMega162Based(Legacy).hex
index 8e3e4a442e71741e2c04d0576c0e8407f47d0f0d..7fa28b24ab58cd850a8eb34b2decda138b123c4c 100644
Binary files a/AstroEQ-ConfigUtility/hex/AstroEQATMega162Based(Legacy).hex and b/AstroEQ-ConfigUtility/hex/AstroEQATMega162Based(Legacy).hex differ
diff --git a/AstroEQ-ConfigUtility/hex/AstroEQATMega162Based(Legacy)EEPROMReader.hex b/AstroEQ-ConfigUtility/hex/AstroEQATMega162Based(Legacy)EEPROMReader.hex
index 2d94e3cd2a1167898aaf23cc4d4181297e9b1547..6dd7b0b4e29d3a6fe44600968b516ff0bbebb40c 100644
Binary files a/AstroEQ-ConfigUtility/hex/AstroEQATMega162Based(Legacy)EEPROMReader.hex and b/AstroEQ-ConfigUtility/hex/AstroEQATMega162Based(Legacy)EEPROMReader.hex differ
diff --git a/AstroEQ-ConfigUtility/hex/AstroEQArduinoMega1280(Legacy).hex b/AstroEQ-ConfigUtility/hex/AstroEQArduinoMega1280(Legacy).hex
index ac5041e30b76f3bc6b0933bbeb0cf9d9fe9b10eb..fc0da958c4035bb3a05a99a51330761cb7d8238b 100644
Binary files a/AstroEQ-ConfigUtility/hex/AstroEQArduinoMega1280(Legacy).hex and b/AstroEQ-ConfigUtility/hex/AstroEQArduinoMega1280(Legacy).hex differ
diff --git a/AstroEQ-ConfigUtility/hex/AstroEQArduinoMega1280(Legacy)EEPROMReader.hex b/AstroEQ-ConfigUtility/hex/AstroEQArduinoMega1280(Legacy)EEPROMReader.hex
index 09e86b9e1dd3eead312e3734e4c92967ab60bca5..d1ac8db29cc5329e3b59b41b522089bd65b84bab 100644
Binary files a/AstroEQ-ConfigUtility/hex/AstroEQArduinoMega1280(Legacy)EEPROMReader.hex and b/AstroEQ-ConfigUtility/hex/AstroEQArduinoMega1280(Legacy)EEPROMReader.hex differ
diff --git a/AstroEQ-ConfigUtility/hex/AstroEQArduinoMega2560(Legacy).hex b/AstroEQ-ConfigUtility/hex/AstroEQArduinoMega2560(Legacy).hex
index a5ff5fa743dbcbe699703ec28ef843dca0127e45..36e41c6fb8b0cf3c36dba5ee661cc804fc5d7af7 100644
Binary files a/AstroEQ-ConfigUtility/hex/AstroEQArduinoMega2560(Legacy).hex and b/AstroEQ-ConfigUtility/hex/AstroEQArduinoMega2560(Legacy).hex differ
diff --git a/AstroEQ-ConfigUtility/hex/AstroEQArduinoMega2560(Legacy)EEPROMReader.hex b/AstroEQ-ConfigUtility/hex/AstroEQArduinoMega2560(Legacy)EEPROMReader.hex
index 58aeea91b6fb7c34de7967d1e8aacfc52b3890ec..cb7c999472e09957e1fa6a8011b2b1a5fb99ee98 100644
Binary files a/AstroEQ-ConfigUtility/hex/AstroEQArduinoMega2560(Legacy)EEPROMReader.hex and b/AstroEQ-ConfigUtility/hex/AstroEQArduinoMega2560(Legacy)EEPROMReader.hex differ
diff --git a/AstroEQ-ConfigUtility/hex/AstroEQV4-DIYBoard(includingKits).hex b/AstroEQ-ConfigUtility/hex/AstroEQV4-DIYBoard(includingKits).hex
index c860869261ee1c87acd6c6a5533eeec01c26baef..a4e35176dc480867e17a103351422a0a1a628f87 100644
Binary files a/AstroEQ-ConfigUtility/hex/AstroEQV4-DIYBoard(includingKits).hex and b/AstroEQ-ConfigUtility/hex/AstroEQV4-DIYBoard(includingKits).hex differ
diff --git a/AstroEQ-ConfigUtility/hex/AstroEQV4-DIYBoard(includingKits)EEPROMReader.hex b/AstroEQ-ConfigUtility/hex/AstroEQV4-DIYBoard(includingKits)EEPROMReader.hex
index 48128f2a0b1b848d0a6a963b1c3ffac239dcfa51..c268a6cb9f6d710ae94282a52de072d3a864d406 100644
Binary files a/AstroEQ-ConfigUtility/hex/AstroEQV4-DIYBoard(includingKits)EEPROMReader.hex and b/AstroEQ-ConfigUtility/hex/AstroEQV4-DIYBoard(includingKits)EEPROMReader.hex differ
diff --git a/AstroEQ-ConfigUtility/hex/AstroEQV4-EQ5Board.hex b/AstroEQ-ConfigUtility/hex/AstroEQV4-EQ5Board.hex
index c860869261ee1c87acd6c6a5533eeec01c26baef..a4e35176dc480867e17a103351422a0a1a628f87 100644
Binary files a/AstroEQ-ConfigUtility/hex/AstroEQV4-EQ5Board.hex and b/AstroEQ-ConfigUtility/hex/AstroEQV4-EQ5Board.hex differ
diff --git a/AstroEQ-ConfigUtility/hex/AstroEQV4-EQ5BoardEEPROMReader.hex b/AstroEQ-ConfigUtility/hex/AstroEQV4-EQ5BoardEEPROMReader.hex
index 9632d1cab8b8b26c108479859a6f161893a747ae..c268a6cb9f6d710ae94282a52de072d3a864d406 100644
Binary files a/AstroEQ-ConfigUtility/hex/AstroEQV4-EQ5BoardEEPROMReader.hex and b/AstroEQ-ConfigUtility/hex/AstroEQV4-EQ5BoardEEPROMReader.hex differ
diff --git a/AstroEQ-Firmware/AstroEQ6.ino b/AstroEQ-Firmware/AstroEQ6.ino
index 3b81c3ddeae8b276bb60f8b0b0e2423c866ef6b7..d03ae24cccbad9bc3cff47fcd8fd21b5073a95ed 100644
--- a/AstroEQ-Firmware/AstroEQ6.ino
+++ b/AstroEQ-Firmware/AstroEQ6.ino
@@ -9,7 +9,7 @@
  
   Works with EQ5, HEQ5, and EQ6 mounts (Not EQ3-2, they have a different gear ratio)
  
-  Current Verison: 6
+  Current Verison: 6.1
 */
 
 //Only works with ATmega162, and Arduino Mega boards (1280 and 2560)
@@ -34,6 +34,7 @@ Synta synta = Synta::getInstance(1281); //create a mount instance, specify versi
 unsigned int normalGotoSpeed[2];
 unsigned int gotoFactor;
 unsigned int minSpeed[2];
+unsigned int stopSpeed[2];
 
 unsigned long gotoPosn[2] = {0UL,0UL}; //where to slew to
 
@@ -61,6 +62,7 @@ const byte errorPin[2] = {errorPin_0_Define,errorPin_1_Define};
 const byte dirPin[2] = {dirPin_0_Define,dirPin_1_Define};
 const byte enablePin[2] = {enablePin_0_Define,enablePin_1_Define};
 const byte stepPin[2] = {stepPin_0_Define,stepPin_1_Define};
+const byte st4Pin[2][2] = {{ST4AddPin_0_Define,ST4SubPin_0_Define},{ST4AddPin_1_Define,ST4SubPin_1_Define}};
 
 #ifdef LEGACY_MODE
 const byte modePins[2][2] = {{modePins0_0_Define,modePins2_0_Define},{modePins0_1_Define,modePins2_1_Define}};
@@ -124,6 +126,11 @@ void systemInitialiser(){
   minSpeed[RA] = synta.cmd.siderealIVal[RA] + ((unsigned int)synta.cmd.stepIncrement[RA] << 2);
   minSpeed[DC] = synta.cmd.siderealIVal[DC] + ((unsigned int)synta.cmd.stepIncrement[DC] << 2);
   
+  highSpeed[RA] = !EEPROM.readByte(Microstep_Address);
+  highSpeed[DC] = highSpeed[RA];
+  distributionWidth[RA] = highSpeed[RA] ? HighspeedDistnWidth : NormalDistnWidth;
+  distributionWidth[DC] = highSpeed[DC] ? HighspeedDistnWidth : NormalDistnWidth;
+  
 #ifdef DEBUG
   Serial1.println();
   Serial1.println(minSpeed[RA]);
@@ -167,20 +174,23 @@ void setup()
     pinMode(modePins[i][0],OUTPUT); //enable the mode pins
     pinMode(modePins[i][1],OUTPUT); //enable the mode pins
     for( byte j = 0; j < 2; j++){
-      digitalWrite(modePins[i][j],modeState[0][j]);
+      digitalWrite(modePins[i][j],modeState[highSpeed[i]][j]);
     }
 #else
     pinMode(modePins[i][0],OUTPUT); //enable the mode pins
     pinMode(modePins[i][1],OUTPUT); //enable the mode pins
     pinMode(modePins[i][2],OUTPUT); //enable the mode pins
     for( byte j = 0; j < 3; j++){
-      digitalWrite(modePins[i][j],modeState[0][j]);
+      digitalWrite(modePins[i][j],modeState[highSpeed[i]][j]);
     }
 #endif
     pinMode(resetPin[i],OUTPUT); //enable the reset pin
     digitalWrite(resetPin[i],LOW); //active low reset
     delay(1); //allow ic to reset
     digitalWrite(resetPin[i],HIGH); //complete reset
+    
+    pinMode(st4Pin[i][0],INPUT_PULLUP);
+    pinMode(st4Pin[i][1],INPUT_PULLUP);
   }
     
   // start Serial port:
@@ -189,8 +199,18 @@ void setup()
     Serial.read(); //Clear the buffer
   }
   
-  
   configureTimer(); //setup the motor pulse timers.
+  
+  //setup interrupt for ST4 connection
+#if defined(__AVR_ATmega162__)
+  PCMSK0 = 0xF0; //PCINT[4..7]
+#define PCICR GICR
+#else
+  PCMSK0 = 0x0F; //PCINT[0..3]
+  PCICR &= ~_BV(PCIE2); //disable PCInt[16..23] vector
+#endif
+  PCICR &= ~_BV(PCIE1); //disable PCInt[8..15] vector
+  PCICR |= _BV(PCIE0); //enable PCInt[0..7] vector
 }
 
 void loop(){
@@ -239,6 +259,7 @@ void decodeCommand(char command, char* packetIn){ //each command is axis specifi
   byte axis = synta.axis();
   unsigned int correction;
   //byte scalar = synta.scalar[axis]+1;
+  uint8_t oldSREG;
   switch(command){
     case 'e': //readonly, return the eVal (version number)
         responseData = synta.cmd.eVal[axis]; //response to the e command is stored in the eVal function for that axis.
@@ -261,7 +282,10 @@ void decodeCommand(char command, char* packetIn){ //each command is axis specifi
         responseData = synta.cmd.fVal(axis); //response to the f command is stored in the fVal function for that axis.
         break;
     case 'j': //readonly, return the jVal (current position)
+        oldSREG = SREG; 
+        cli();  //The next bit needs to be atomic, just in case the motors are running
         responseData = synta.cmd.jVal[axis]; //response to the j command is stored in the jVal function for that axis.
+        SREG = oldSREG;
         break;
     case 'K': //stop the motor, return empty response
         motorStop(axis,0); //normal ISR based decelleration trigger.
@@ -285,16 +309,14 @@ void decodeCommand(char command, char* packetIn){ //each command is axis specifi
         if (responseData > minSpeed[axis]){
           responseData = minSpeed[axis]; //minimum speed
         }
-        synta.cmd.setIVal(axis, responseData); //set the speed container (convert string to long first)
-        
-        //This will be different if you use a different motor code
-        calculateRate(axis); //Used to convert speed into the number of 0.5usecs per step. Result is stored in TimerOVF
-  
-  
+        synta.cmd.setIVal(axis, responseData); //set the speed container (convert string to long first) 
         responseData = 0;
         break;
     case 'E': //set the current position, return empty response
+        oldSREG = SREG; 
+        cli();  //The next bit needs to be atomic, just in case the motors are running
         synta.cmd.setjVal(axis, synta.hexToLong(packetIn)); //set the current position (used to sync to what EQMOD thinks is the current position at startup
+        SREG = oldSREG;
         break;
     case 'F': //Enable the motor driver, return empty response
         motorEnable(axis); //This enables the motors - gives the motor driver board power
@@ -336,12 +358,13 @@ void calculateRate(byte motor){
   unsigned long remainder;
   float floatRemainder;
   unsigned long divisor = synta.cmd.bVal[motor];
-  byte GVal = synta.cmd.GVal[motor];
-  if((GVal == 2)||(GVal == 1)){ //Normal Speed
-    highSpeed[motor] = false;
+ // byte GVal = synta.cmd.GVal[motor];
+  //if((GVal == 2)||(GVal == 1)){ //Normal Speed}
+  if(!highSpeed[motor]){ //Normal Speed
+  //  highSpeed[motor] = false;
     distributionWidth[motor] = NormalDistnWidth;
   } else { //High Speed
-    highSpeed[motor] = true;
+  //  highSpeed[motor] = true;
     distributionWidth[motor] = HighspeedDistnWidth; //There are 8 times fewer steps over which to distribute extra clock cycles
   }
   
@@ -396,6 +419,7 @@ void calculateRate(byte motor){
 void motorEnable(byte axis){
   digitalWrite(enablePin[axis],LOW);
   synta.cmd.setFVal(axis,1);
+  calculateRate(axis); //Initialise the interrupt speed table. This now only has to be done once at the beginning.
 }
 
 void motorDisable(byte axis){
@@ -432,52 +456,30 @@ void gotoMode(byte axis){
   Serial1.println(decelerationLength);
   Serial1.println(synta.cmd.jVal[axis]);
 #endif
-    gotoPosn[axis] = synta.cmd.jVal[axis] + (synta.cmd.stepDir[axis] * (synta.cmd.HVal[axis] - (unsigned long)decelerationLength)); //current position + relative change - decelleration region
+  gotoPosn[axis] = synta.cmd.jVal[axis] + (synta.cmd.stepDir[axis] * (synta.cmd.HVal[axis] - (unsigned long)decelerationLength)); //current position + relative change - decelleration region
     
 #ifdef DEBUG
   Serial1.println(gotoPosn[axis]);
   Serial1.println();
 #endif
-    synta.cmd.setIVal(axis, gotoSpeed);
-    calculateRate(axis);
-    motorStart(axis,decelerationLength/*decellerateStepsFactor[axis]*/); //Begin PWM
-    synta.cmd.setGotoEn(axis,1);
-  //}
+  synta.cmd.setIVal(axis, gotoSpeed);
+  //calculateRate(axis);
+  motorStart(axis,decelerationLength/*decellerateStepsFactor[axis]*/); //Begin PWM
+  synta.cmd.setGotoEn(axis,1);
 }
-/*
-void normalTorqueTimerEnable(byte motor) {
-//  if(motor){
-//    TCCR1B &= ~((1<<CS12) | (1<<CS11));//00x
-//    TCCR1B |= (1<<CS10);//xx1
-//  } else {
-//    TCCR3B &= ~((1<<CS32) | (1<<CS31));//00x
-//    TCCR3B |= (1<<CS30);//xx1
-//  }
-  //set normal speed mode
-  synta.cmd.setStepLength(motor, 1);
-#ifdef LEGACY_MODE
-  for( byte j = 0; j < 2; j++){
-    digitalWrite(modePins[motor][j],modeState[0][j]);
-  }
-#else
-  for( byte j = 0; j < 3; j++){
-    digitalWrite(modePins[motor][j],modeState[0][j]);
-  }
-#endif
-}*/
 
 void timerEnable(byte motor, byte mode) {
-  if (mode){
+  //if (mode){
     //FCPU/8
-    timerPrescalarRegister(motor) &= ~((1<<CSn2) | (1<<CSn0)); //0x0
-    timerPrescalarRegister(motor) |= (1<<CSn1);//x1x
-  } else {
+  //  timerPrescalarRegister(motor) &= ~((1<<CSn2) | (1<<CSn0)); //0x0
+  //  timerPrescalarRegister(motor) |= (1<<CSn1);//x1x
+  //} else {
     //FCPU/1
-    timerPrescalarRegister(motor) &= ~((1<<CSn2) | (1<<CSn1));//00x
-    timerPrescalarRegister(motor) |= (1<<CSn0);//xx1
-  }
-  synta.cmd.setStepLength(motor, (mode ? synta.cmd.gVal[motor] : 1));
-#ifdef LEGACY_MODE
+  timerPrescalarRegister(motor) &= ~((1<<CSn2) | (1<<CSn1));//00x
+  timerPrescalarRegister(motor) |= (1<<CSn0);//xx1
+  //}
+  synta.cmd.setStepLength(motor, 1);//(mode ? synta.cmd.gVal[motor] : 1));
+/*#ifdef LEGACY_MODE
   for( byte j = 0; j < 2; j++){
     digitalWrite(modePins[motor][j],modeState[mode][j]);
   }
@@ -485,25 +487,7 @@ void timerEnable(byte motor, byte mode) {
   for( byte j = 0; j < 3; j++){
     digitalWrite(modePins[motor][j],modeState[mode][j]);
   }
-#endif
-//  if(motor){
-//    TCCR1B &= ~((1<<CS12) | (1<<CS10)); //0x0
-//    TCCR1B |= (1<<CS11);//x1x
-//  } else {
-//    TCCR3B &= ~((1<<CS32) | (1<<CS30)); //0x0
-//    TCCR3B |= (1<<CS31);//x1x
-//  }
-  //Enable Highspeed mode
-//  synta.cmd.setStepLength(motor, synta.cmd.gVal[motor]);
-//#ifdef LEGACY_MODE
-//  for( byte j = 0; j < 2; j++){
-//    digitalWrite(modePins[motor][j],modeState[1][j]);
-//  }
-//#else
-//  for( byte j = 0; j < 3; j++){
-//    digitalWrite(modePins[motor][j],modeState[1][j]);
-//  }
-//#endif
+#endif*/
 }
 
 inline void timerDisable(byte motor) {
@@ -516,78 +500,44 @@ void motorStart(byte motor, byte gotoDeceleration){
   synta.cmd.setStopped(motor, 0);
   
 #ifdef DEBUG
-  Serial1.println();
+  Serial1.println(F("IVal:"));
   Serial1.println(synta.cmd.IVal[motor]);
   Serial1.println();
 #endif
   
-//  if(!highSpeed[motor]){ //Normal Speed
-//    normalTorqueTimerEnable(motor);
-//  } else {
-//    highTorqueTimerEnable(motor);
-//  }
+  unsigned int startSpeed = minSpeed[motor];
+  if (synta.cmd.IVal[motor] > minSpeed[motor]){
+    startSpeed = synta.cmd.IVal[motor]; //This is only the case with ST4 on the DEC axis.
+  } else if ((startSpeed > 650) && (synta.cmd.IVal[motor] <= 650)){
+    startSpeed = 650; //if possible start closer to the target speed to avoid *very* long accelleration times. 
+  }
+  stopSpeed[motor] = startSpeed;
+#ifdef DEBUG
+  Serial1.println(F("StartSpeed:"));
+  Serial1.println(startSpeed);
+  Serial1.println();
+#endif
   
   interruptCount(motor) = 1;
-  currentMotorSpeed(motor) = minSpeed[motor];
+  currentMotorSpeed(motor) = startSpeed;//minSpeed[motor];
   distributionSegment(motor) = 0;
   decelerationSteps(motor) = -gotoDeceleration;
   timerCountRegister(motor) = 0;
   interruptControlRegister(motor) |= interruptControlBitMask(motor);
   interruptOVFCount(motor) = timerOVF[motor][0];
   timerEnable(motor,highSpeed[motor]);
-//  if(motor == DC){
-//    ICR1 = timerOVF[motor][0];
-//    interruptCount(DC) = 1;//synta.cmd.IVal[motor];
-//    currentMotorSpeed(DC) = 640;//synta.cmd.IVal[motor];
-//    TCNT1 = 0;
-//    distributionSegment(DC) = 0;
-//    decelerationSteps(DC) = -gotoDeceleration; //inform goto of how many decelleration steps to use (ignored if slew)
-//    TCCR1A |= (1<<COM1B1); //Set port operation to fast PWM
-//#if defined(__AVR_ATmega162__)
-//    TIMSK |= (1<<TICIE1); //Enable timer interrupt
-//#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
-//    TIMSK1 |= (1<<ICIE1); //Enable timer interrupt
-//#endif
-//  } else {
-//    ICR3 = timerOVF[motor][0];
-//    OCR1B = 1;//synta.cmd.IVal[motor];
-//    OCR3B = 640;//synta.cmd.IVal[motor];
-//    TCNT3 = 0;
-//    distributionSegment(RA) = 0;
-//    PORTC = -gotoDeceleration; //inform goto of how many decelleration steps to use (ignored if slew)
-//    TCCR3A |= (1<<COM3A1); //Set port operation to fast PWM
-//#if defined(__AVR_ATmega162__)
-//    ETIMSK |= (1<<TICIE3); //Enable timer interrupt
-//#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
-//    TIMSK3 |= (1<<ICIE3); //Enable timer interrupt
-//#endif
-//  }
 }
 
 void motorStop(byte motor, byte emergency){
   if (emergency) {
     //trigger instant shutdown of the motor in an emergency.
-    //interruptControlRegister(motor) &= ~interruptControlBitMask(motor);
-//    if(motor){
-//#if defined(__AVR_ATmega162__)
-//      TIMSK &= ~(1<<TICIE1); //Disable timer interrupt
-//#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
-//      TIMSK1 &= ~(1<<ICIE1); //Disable timer interrupt
-//#endif
-//    } else {
-//#if defined(__AVR_ATmega162__)
-//      ETIMSK &= ~(1<<TICIE3); //Disable timer interrupt
-//#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
-//      TIMSK3 &= ~(1<<ICIE3); //Disable timer interrupt
-//#endif
-//    }
     synta.cmd.setGotoEn(motor,0); //Not in goto mode.
     synta.cmd.setStopped(motor,1); //mark as stopped
     timerDisable(motor);
     
   } else if (!synta.cmd.stopped[motor]){  //Only stop if not already stopped - for some reason EQMOD stops both axis when slewing, even if one isn't currently moving?
     //trigger ISR based decelleration
-    synta.cmd.IVal[motor] = minSpeed[motor] + synta.cmd.stepIncrement[motor]; 
+    synta.cmd.IVal[motor] = stopSpeed[motor] + synta.cmd.stepIncrement[motor]; 
   }
 }
 
@@ -599,17 +549,6 @@ void configureTimer(){
 #else
   interruptControlRegister(RA) = 0;
 #endif
-//#if defined(__AVR_ATmega162__)
-//  TIMSK &= ~(1<<TOIE1); //disable timer so it can be configured
-//  ETIMSK &= ~(1<<TOIE3); //disable timer so it can be configured
-//  TIMSK &= ~((1<<OCIE1A) | (1<<OCIE1B));
-//  ETIMSK &= ~((1<<OCIE3A) | (1<<OCIE3B));
-//#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
-//  TIMSK1 &= ~(1<<TOIE1); //disable timer so it can be configured
-//  TIMSK3 &= ~(1<<TOIE3); //disable timer so it can be configured
-//  TIMSK1 &= ~((1<<OCIE1A) | (1<<OCIE1B) | (1<<OCIE1C));
-//  TIMSK3 &= ~((1<<OCIE3A) | (1<<OCIE3B) | (1<<OCIE3C));
-//#endif
   //set to ctc mode (0100)
   TCCR1A = 0;//~((1<<WGM11) | (1<<WGM10));
   TCCR1B = ((1<<WGM12) | (1<<WGM13));
@@ -618,6 +557,112 @@ void configureTimer(){
 }
 
 
+unsigned int divu3b(unsigned int n) { //accurate for  n < 0x7FFF
+  unsigned long b = n+1;
+  n = ((b * 0x5555) >> 16);
+  return n;
+}
+unsigned int divu5b(unsigned int n) { //accurate for n < 0x7FFF
+  unsigned long b = n+1;
+  n = ((b * 0x3333) >> 16);
+  return n = b >> 16;
+}
+
+ISR(PCINT0_vect) {
+  //ST4 Pin Change Interrupt Handler.
+  byte stopped;
+  if(!synta.cmd.gotoEn[RA]){
+    //Only allow when not it goto mode.
+    stopped = synta.cmd.stopped[RA];
+    unsigned int newSpeed = synta.cmd.siderealIVal[RA];
+    if (synta.cmd.dir[RA] && !stopped) {
+      goto ignoreRAST4; //if travelling in the wrong direction, then ignore.
+    }
+    byte multiplier;
+    if (!(*digitalPinToPinReg(st4Pin[RA][1]) & _BV(digitalPinToBit(st4Pin[RA][1])))) {
+      //RA-
+      multiplier = 0x55; //------------ 0.75x sidereal rate
+      goto setRASpeed;
+    } else if (!(*digitalPinToPinReg(st4Pin[RA][0]) & _BV(digitalPinToBit(st4Pin[RA][0])))) {
+      //RA+
+      multiplier = 0x33; //------------ 1.25x sidereal rate
+setRASpeed:
+      unsigned long working = multiplier;
+      newSpeed = newSpeed << 2;
+      asm volatile( //This is a division by 5, or by 3. Which depends on multiplier (0x55 = /3, 0x33 = /5)
+        "subi r18, 0xFF \n\t"  //n++
+        "sbci r19, 0xFF \n\t"
+        "mul  %A0, %A2  \n\t"  //A * X
+        "mov  %B2,  r1  \n\t"
+        
+        "add  %B2,  r0  \n\t"  //A* X'
+        "adc  %C2,  r1  \n\t"
+        
+        "mul  %B0, %A1  \n\t"
+        "add  %B2,  r0  \n\t"  //A* X'
+        "adc  %C2,  r1  \n\t"
+        "adc  %D2, %D2  \n\t"  //D0 is known 0, we need to grab the carry
+        
+        "add  %C2,  r0  \n\t"  //A* X'
+        "adc  %D2,  r1  \n\t"
+        
+        "eor   r1,  r1  \n\t"
+        
+        "movw %A0, %C2  \n\t"  // >> 16
+        
+        : "=r" (newSpeed)
+        : "0" (newSpeed), "r" (working)
+        : "r1", "r0"
+      );
+      synta.cmd.IVal[RA] = newSpeed;
+      if (stopped) {
+        synta.cmd.dir[RA] = 0; //set direction
+        register byte one asm("r22");
+        asm volatile(
+          "ldi %0,0x01  \n\t"
+          : "=r" (one)
+          : "0" (one)
+          :
+        );
+        synta.cmd.stepDir[RA] = one; //set step direction
+        synta.cmd.GVal[RA] = one; //slew mode
+        //calculateRate(RA);
+        motorStart(RA,one);
+      } else {
+        if (stopSpeed[RA] < synta.cmd.IVal[RA]) {
+          stopSpeed[RA] = synta.cmd.IVal[RA]; //ensure that RA doesn't stop.
+        }
+      }
+    } else {
+ignoreRAST4:
+      synta.cmd.IVal[RA] = newSpeed;
+    }
+  }
+  if(!synta.cmd.gotoEn[DC]){
+    //Only allow when not it goto mode.
+    byte dir;
+    byte stepDir;
+    if (!(*digitalPinToPinReg(st4Pin[DC][1]) & _BV(digitalPinToBit(st4Pin[DC][1])))) {
+      //DEC-
+      dir = 1;
+      stepDir = -1;
+      goto setDECSpeed;
+    } else if (!(*digitalPinToPinReg(st4Pin[DC][0]) & _BV(digitalPinToBit(st4Pin[DC][0])))) {
+      //DEC+
+      dir = 0;
+      stepDir = 1;
+setDECSpeed:
+      synta.cmd.stepDir[DC] = stepDir; //set step direction
+      synta.cmd.dir[DC] = dir; //set direction
+      synta.cmd.IVal[DC] = (synta.cmd.siderealIVal[RA] << 2); //move at 0.25x sidereal rate
+      synta.cmd.GVal[DC] = 1; //slew mode
+      //calculateRate(DC);
+      motorStart(DC,1);
+    } else {
+      synta.cmd.IVal[DC] = stopSpeed[DC] + synta.cmd.stepIncrement[DC];
+    }
+  }
+}
 
 /*Timer Interrupt Vector*/
 ISR(TIMER3_CAPT_vect) {
@@ -671,13 +716,13 @@ ISR(TIMER3_CAPT_vect) {
             );
             //-----------------------------------------------------------------------------------------
             decelerationSteps(DC) = 0; //say we are stopping
-            synta.cmd.IVal[DC] = minSpeed[DC]; //decellerate to min speed. This is possible in at most 80 steps.
+            synta.cmd.IVal[DC] = stopSpeed[DC]; //decellerate to min speed. This is possible in at most 80 steps.
           } else {
             goto stopMotorISR3;
           }
         }
       } 
-      if (currentMotorSpeed(DC) > minSpeed[DC]) {
+      if (currentMotorSpeed(DC) > stopSpeed[DC]) {
 stopMotorISR3:
         synta.cmd.gotoEn[DC] = 0; //Not in goto mode.
         synta.cmd.stopped[DC] = 1; //mark as stopped
@@ -779,13 +824,13 @@ ISR(TIMER1_CAPT_vect) {
               :
             );
             decelerationSteps(RA) = 0; //say we are stopping
-            synta.cmd.IVal[RA] = minSpeed[RA]; //decellerate to min speed. This is possible in at most 80 steps.
+            synta.cmd.IVal[RA] = stopSpeed[RA]; //decellerate to min speed. This is possible in at most 80 steps.
           } else {
             goto stopMotorISR1;
           }
         }
       } 
-      if (currentMotorSpeed(RA) > minSpeed[RA]) {
+      if (currentMotorSpeed(RA) > stopSpeed[RA]) {
 stopMotorISR1:
         //interruptControlRegister(RA) &= ~interruptControlBitMask(RA);
         synta.cmd.gotoEn[RA] = 0; //Not in goto mode.
diff --git a/AstroEQ-Firmware/EEPROMAddresses.h b/AstroEQ-Firmware/EEPROMAddresses.h
index dccbeb835a2277a9e2bcd8fba247119eb1dcf5e1..80db5ee970ad156b8a6e2b24541123d2273f8261 100644
--- a/AstroEQ-Firmware/EEPROMAddresses.h
+++ b/AstroEQ-Firmware/EEPROMAddresses.h
@@ -1,7 +1,7 @@
 
 #define EEPROMStart_Address (                      0 )
 #define AstroEQID_Address   (EEPROMStart_Address + 0 )
-//#define AstroEQVer_Address  (EEPROMStart_Address + 8 )
+#define Microstep_Address   (EEPROMStart_Address + 8) //whether to use microstepping.
 #define RAReverse_Address   (EEPROMStart_Address + 9 )
 #define DECReverse_Address  (EEPROMStart_Address + 10)
 #define Driver_Address      (EEPROMStart_Address + 11)
diff --git a/AstroEQ-Firmware/EEPROMReader.h b/AstroEQ-Firmware/EEPROMReader.h
index 4d64c7febff794b6820360aa05001f86707111a7..9dbaaa7202324d3ddfc67141f0b946b77b43ba81 100644
--- a/AstroEQ-Firmware/EEPROMReader.h
+++ b/AstroEQ-Firmware/EEPROMReader.h
@@ -2,18 +2,7 @@
 #define EEPROM_h
 
 #include "Arduino.h"
-#include <inttypes.h>
-
-typedef union {
-  uint16_t integer;
-  uint8_t array[2];
-} TwoBytes;
-
-typedef union {
-  uint32_t integer;
-  uint16_t array[2];
-  uint8_t bytes[4];
-} FourBytes;
+#include "UnionHelpers.h"
 
 class EEPROMReader
 {
diff --git a/AstroEQ-Firmware/PinMappings.h b/AstroEQ-Firmware/PinMappings.h
index d3f61beffe79693f0bcc206349689b667224f8b4..57f25427d0213a22021cb83537a1dcb59a459cb1 100644
--- a/AstroEQ-Firmware/PinMappings.h
+++ b/AstroEQ-Firmware/PinMappings.h
@@ -23,6 +23,11 @@
 #define stepPin_0_Define 5
 #define stepPin_1_Define 30
 
+#define ST4AddPin_0_Define 34
+#define ST4AddPin_1_Define 33
+#define ST4SubPin_0_Define 31
+#define ST4SubPin_1_Define 32
+
 #ifdef LEGACY_MODE
 #define modePins0_0_Define 16
 #define modePins2_0_Define 17
@@ -59,6 +64,11 @@
 #define stepPin_0_Define 5
 #define stepPin_1_Define 12
 
+#define ST4AddPin_0_Define 50
+#define ST4AddPin_1_Define 51
+#define ST4SubPin_0_Define 53
+#define ST4SubPin_1_Define 52
+
 #define modePins0_0_Define 16
 #define modePins2_0_Define 17
 #define modePins0_1_Define 19
@@ -110,6 +120,12 @@
 ((((P) >= 20 && (P) <= 27)) ? &PORTC : \
 ((((P) <= 7)) ? &PORTD :  &PORTE ))))
 
+#define digitalPinToPinReg(P) \
+((((P) >= 14 && (P) <= 17) || ((P) >= 31 && (P) <= 34)) ? &PINA : \
+((((P) >= 8 && (P) <= 13) || ((P) >= 18 && (P) <= 19)) ? &PINB : \
+((((P) >= 20 && (P) <= 27)) ? &PINC : \
+((((P) <= 7)) ? &PIND :  &PINE ))))
+
 #define digitalPinToBit(P) \
 (((P) >=  0 && (P) <=  3) ? (P)      : \
 (((P) >= 10 && (P) <= 13) ? (P) - 6  : \
@@ -141,6 +157,18 @@
 (((P) == 14 || (P) == 15) ? &PORTJ : \
 (((P) >= 62 && (P) <= 69) ? &PORTK : &PORTL))))))))))
 
+#define digitalPinToPinReg(P) \
+(((P) >= 22 && (P) <= 29) ? &PINA : \
+((((P) >= 10 && (P) <= 13) || ((P) >= 50 && (P) <= 53)) ? &PINB : \
+(((P) >= 30 && (P) <= 37) ? &PINC : \
+((((P) >= 18 && (P) <= 21) || (P) == 38) ? &PIND : \
+((((P) >= 0 && (P) <= 3) || (P) == 5) ? &PINE : \
+(((P) >= 54 && (P) <= 61) ? &PINF : \
+((((P) >= 39 && (P) <= 41) || (P) == 4) ? &PING : \
+((((P) >= 6 && (P) <= 9) || (P) == 16 || (P) == 17) ? &PINH : \
+(((P) == 14 || (P) == 15) ? &PINJ : \
+(((P) >= 62 && (P) <= 69) ? &PINK : &PINL))))))))))
+
 #define digitalPinToBit(P) \
 (((P) >=  7 && (P) <=  9) ? (P) - 3 : \
 (((P) >= 10 && (P) <= 13) ? (P) - 6 : \
diff --git a/AstroEQ-Firmware/UnionHelpers.h b/AstroEQ-Firmware/UnionHelpers.h
new file mode 100644
index 0000000000000000000000000000000000000000..2cdd11ac921cfc5b52f29c2de7b863d8fcb6761d
--- /dev/null
+++ b/AstroEQ-Firmware/UnionHelpers.h
@@ -0,0 +1,63 @@
+
+#ifndef UnionHelpers_h
+#define UnionHelpers_h
+
+typedef union {
+  uint16_t integer;
+  uint8_t array[2];
+} TwoBytes;
+
+typedef union {
+  uint32_t integer;
+  uint16_t array[2];
+  uint8_t bytes[4];
+} FourBytes;
+
+typedef union{
+  byte integer;
+  struct {
+    byte low:4;
+    byte high:4;
+  };
+} Nibbler;
+
+typedef union{
+  unsigned int integer;
+  struct {
+    byte low;
+    byte high;
+  };
+  struct {
+    Nibbler lowNibbler;
+    Nibbler highNibbler;
+  };
+} Byter;
+
+typedef union InterMaker{
+  unsigned long integer;
+  struct {
+    byte low;
+    byte mid;
+    byte high;
+    byte top;
+  };
+  struct {
+    Byter lowByter;
+    Byter highByter;
+  };
+  InterMaker(unsigned long _integer){
+    integer = _integer;
+  }
+} Inter;
+
+typedef union{
+  unsigned int integer;
+  struct {
+    unsigned int low:4;
+    unsigned int mid:4;
+    unsigned int high:4;
+    unsigned int:4;
+  };
+} DoubleNibbler;
+
+#endif
diff --git a/AstroEQ-Firmware/commands.cpp b/AstroEQ-Firmware/commands.cpp
index a78f4651a4e13e336f2e60f11446cae0f7013495..4fe6d0092b507ae089168e1d51ed9ada13304764 100644
--- a/AstroEQ-Firmware/commands.cpp
+++ b/AstroEQ-Firmware/commands.cpp
@@ -99,7 +99,7 @@ void Commands::setDir(byte target, byte _dir){ //Set Method
   } else {//if (dir == 0){}
     stepDir[target] = 1; //set step direction
   }
-  dir[target] = _dir & 1; //set direction
+  dir[target] = _dir; //set direction
 }
 
 void Commands::setStopped(byte target, byte _stopped){ //Set Method
diff --git a/AstroEQ-Firmware/synta.cpp b/AstroEQ-Firmware/synta.cpp
index 33b510665be3937a6ac54838ca03b90f5b62bb25..c7cec63807e64531d94f41ca9ef75c06b4eb857f 100644
--- a/AstroEQ-Firmware/synta.cpp
+++ b/AstroEQ-Firmware/synta.cpp
@@ -1,5 +1,6 @@
 
 #include "synta.h"
+#include "UnionHelpers.h"
 
 void Synta::initialise(unsigned long eVal){
   validPacket = 0;
@@ -26,36 +27,46 @@ void Synta::clearBuffer(char* buf, byte len){
   strncpy(buf,"",len);
 }
 
-void Synta::success(char* buf, char data[], byte dataLen){
-  strcpy(buf + 1,data);
-  buf[0] = startOutChar;
-  buf[dataLen] = endChar;
-  buf[dataLen + 1] = 0;
-}
+//void Synta::success(char* buf, char data[], byte dataLen){
+//  strcpy(buf + 1,data);
+//  buf[0] = startOutChar;
+//  buf[dataLen] = endChar;
+//  buf[dataLen + 1] = 0;
+//}
 
 void Synta::assembleResponse(char* dataPacket, char commandOrError, unsigned long responseData){
   char replyLength = cmd.getLength(commandOrError,0); //get the number of data bytes for response
   
-  char tempStr[11];
+  //char tempStr[11];
+  if (replyLength == -1) {
+    dataPacket[0] = errorChar;  
+  } else {
+    dataPacket[0] = startOutChar;
+  }
+  dataPacket++;
   
   switch (replyLength){
     case -1:
-        error(dataPacket); //In otherwords, invalid command, so send error
-        return;
-    case 0:
-        clearBuffer(tempStr,sizeof(tempStr)); //empty temporary string
+        //error(dataPacket); //In otherwords, invalid command, so send error
+        //return;
+        break;
+    case 0:  
+        //clearBuffer(dataPacket+1,sizeof(tempStr)); //empty temporary string
         break;
     case 2:
-        byteToHex(tempStr,responseData);
+        byteToHex(dataPacket,responseData);
         break;
     case 3:
-        intToHex(tempStr,responseData);
+        intToHex(dataPacket,responseData);
         break;
     case 6:
-        longToHex(tempStr,responseData);
+        longToHex(dataPacket,responseData);
         break;
-  }        
-  success(dataPacket,tempStr,replyLength + 1); //compile response
+  }
+  
+  dataPacket[(byte)replyLength] = endChar;
+  dataPacket[(byte)replyLength + 1] = 0;  
+  //success(dataPacket,tempStr,replyLength + 1); //compile response
   return;
 }
 
@@ -111,32 +122,73 @@ error:
   return -1;
 }
 
+byte hexToNibbler(char hex) {
+  if (hex > '9'){
+    hex -= (('A'-'0')-0xA); //even if hex is lower case (e.g. 'a'), the lower nibble will have the correct value as (('a'-'A')&0x0F) = 0.
+  }
+  return (hex - '0'); //as we are keeping the lower nibble, the -'0' gets optimised away.
+}
+void hexToByte(char* hex, Nibbler &nibble){
+  nibble.low = hexToNibbler(hex[1]);
+  nibble.high = hexToNibbler(hex[0]);
+}
 unsigned long Synta::hexToLong(char* hex){
-  char *boo; //waste point for strtol
-  char str[7]; //Destination of rearranged hex
-  strncpy(str,&hex[4],2); //Lower Byte
-  strncpy(str+2,&hex[2],2); //Middle Byte
-  strncpy(str+4,hex,2); //Upper Byte
-  str[6] = 0;
-  return strtol(str,&boo,16); //convert hex to long integer
+//  char *boo; //waste point for strtol
+//  char str[7]; //Destination of rearranged hex
+//  strncpy(str,&hex[4],2); //Lower Byte
+//  strncpy(str+2,&hex[2],2); //Middle Byte
+//  strncpy(str+4,hex,2); //Upper Byte
+//  str[6] = 0;
+//  return strtol(str,&boo,16); //convert hex to long integer
+
+  Inter inter = Inter(0); //create a blank inter 
+  hexToByte(hex+4,inter.highByter.lowNibbler);
+  hexToByte(hex+2,inter.lowByter.highNibbler);
+  hexToByte(hex,inter.lowByter.lowNibbler);
+  return inter.integer;
+}
+
+const char hexLookup[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
+void nibbleToHex(char* hex, byte offset, byte nibble) {
+//  char hexChar;
+//  asm volatile(
+//    "movw   Y, %1  \n\t"
+//    "add  r28, %2  \n\t"
+//    "adc  r29, r1  \n\t"
+//    "ld    %0, Y   \n\t"
+//    : "=r" (hexChar) //goto selects r18:r21. This adds sts commands for all 4 bytes
+//    : "e" (hexLookup),"r" (nibble)       //stepDir is in r19 to match second byte of goto.
+//    : "r28","r29"
+//  );
+//  hex[offset] = hexChar;
+  char hexChar = hexLookup[nibble];
+  hex[offset] = hexChar;
+}
+void private_byteToHex(char* hex, Nibbler nibbler){
+  nibbleToHex(hex,1, nibbler.low);
+  nibbleToHex(hex,0, nibbler.high);
 }
 
-void Synta::longToHex(char* hex, unsigned long data){
-  byte bytes[3];
-  bytes[0] = (data >> 16) & 0xFF;
-  bytes[1] = (data >> 8) & 0xFF;
-  bytes[2] = (data) & 0xFF;
-  sprintf(hex,"%02X%02X%02X",bytes[2],bytes[1],bytes[0]);
+void Synta::longToHex(char* hex, unsigned long data){  
+  Inter inter = Inter(data);
+  private_byteToHex(hex+4,inter.highByter.lowNibbler);
+  private_byteToHex(hex+2,inter.lowByter.highNibbler);
+  private_byteToHex(hex,inter.lowByter.lowNibbler);
+  hex[6] = 0;
 }
 
 void Synta::intToHex(char* hex, unsigned int data){
-  data &= 0xFFF;
-  sprintf(hex,"%03X",data);
+  DoubleNibbler nibble = {data};
+  hex[3] = 0;
+  nibbleToHex(hex,2, nibble.low);
+  nibbleToHex(hex,1, nibble.mid);
+  nibbleToHex(hex,0, nibble.high);
 }
 
 void Synta::byteToHex(char* hex, byte data){
-  data &= 0xFF;
-  sprintf(hex,"%02X",data);
+  Nibbler nibble = {data};
+  hex[2] = 0;
+  private_byteToHex(hex,nibble);
 }
 
 char Synta::command(){
diff --git a/AstroEQ-Firmware/synta.h b/AstroEQ-Firmware/synta.h
index d4ff08ad1a670bb00c0c85670e1df805cbbdda7e..b45d85d8d578f9f8040aa3cff53c12af7e75c4fe 100644
--- a/AstroEQ-Firmware/synta.h
+++ b/AstroEQ-Firmware/synta.h
@@ -42,7 +42,7 @@
       
       
       void clearBuffer(char* buf, byte len);
-      void success(char* buf, char data[], byte dataLen);
+//      void success(char* buf, char data[], byte dataLen);
       void error(char* buf);
       boolean validateCommand(byte len);
       
diff --git a/Downloads/AstroEQ6-ConfigUtility.zip b/Downloads/AstroEQ6-ConfigUtility.zip
index 7ec7f851dba1ea4590fcf52c5347b280f1fcc92f..36a2f46e055dd4afc84f18ac44df7dfac4f2dfab 100644
Binary files a/Downloads/AstroEQ6-ConfigUtility.zip and b/Downloads/AstroEQ6-ConfigUtility.zip differ
diff --git a/Downloads/AstroEQ6-Firmware.zip b/Downloads/AstroEQ6-Firmware.zip
index dab868141eedc7bc5f39d4de8835d3fa3ed26b1d..f3a4d7bc891f33974f0d382318ae2472c513f78f 100644
Binary files a/Downloads/AstroEQ6-Firmware.zip and b/Downloads/AstroEQ6-Firmware.zip differ