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