0,0 → 1,416 |
/* |
* Copyright (C) 2004 Darren Hutchinson (dbh@gbdt.com.au) |
* |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU Library General Public License as published by |
* the Free Software Foundation; either version 2 of the License, or (at your |
* option) any later version. |
* |
* This program is distributed in the hope that it will be useful, but |
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public |
* License for more details. |
* |
* You should have received a copy of the GNU Library General Public License |
* along with this program; see the file COPYING. If not, write to |
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, |
* MA 02111-1307, USA. |
* |
* $Id: serial.c,v 1.10 2004/04/04 10:32:50 dbh Exp $ |
*/ |
|
#include <inttypes.h> |
#include <avr/io.h> |
|
#include "eq6.h" |
#include "serial.h" |
#include "combine.h" |
#include "stepper.h" |
#include "paddle.h" |
#include "sr.h" |
|
/* This file accepts serial data from a serial guider and performs the |
* requested guiding operation. |
* |
* This interface is also is designed to support future mount management |
* operations via the same serial interface |
* |
* The current protocol is: |
* |
* [0-9] Add the number to the "accumulator" |
* - Denote accumulator as negative |
* # Clear the accumulator and flag |
* < Clear the flag |
* > Set the flag |
* U Copy flag state to the DEC UP key |
* D Copy flag state to the DEC DOWN key |
* L Copy flag state to the RA left key |
* R Copy flag state to the RA right key |
* C Release all keys |
* |
* B Set DEC backlash to accum |
* M Set DEC backlash mode (+ = finish pos, 0 = none, - = finish neg) |
* b Set RA backlash to accum |
* m Set RA backlash mode (see DEC backlash) |
* |
* G Set 2X paddle to guiding speed (0.3x) if flag set, 1X if clear |
* |
* t Use halfStep for slow step if flag set, microStep if clear (TEST) |
* |
* T Set the tracking rate as-per the accumulator |
* -1 = No tracking (Terrestial) |
* 0 = Sidereal |
* 1 = Solar / Planetary |
* 2 = Lunar |
* |
* g Set transmission (gearbox) ratio |
* |
* The '#' and accumulator support future value-based entries |
* |
* A subset of LX200 commands are supported for compatibility |
* with various autoguiding programs. |
* |
* :Me# :Mw# :Ms# :Mn# Start slewing East(right), West(left), |
* North (up), South (down) |
* :Qe# :Qw# :Qs# :Qn# :Q# Halt selected or all slews |
* :RG# :RC# :RM# :RS# Set guiding rate for LX200 motions |
* G = 0.3x |
* C = 1x |
* M = 8x |
* S = 16x |
* |
* ACK Returns alignment mode (always 'P' polar) |
*/ |
#include <avr/interrupt.h> |
#include <inttypes.h> |
|
#include "paddle.h" |
#include "eq6.h" |
#include "combine.h" |
|
/* serialInit() initializes the serial port used for the |
* serial guider input. |
* |
* Passed: |
* Nothing |
* |
* Returns: |
* Nothing. |
*/ |
void |
serialInit(void) |
{ |
// The serial guider is attached to USART1 |
|
// Set serial rate |
UBRR1H = (CLK_RATE / GUIDE_BAUD / 16 - 1) >> 8; |
UBRR1L = (CLK_RATE / GUIDE_BAUD / 16 - 1) & 0xff; |
|
/* Setup registers |
* 8 bits, no parity, RX enable, TX enable. Only the Rx interrupts are |
* enabled at this point. |
*/ |
UCSR1B = 0; // Disable all interrupts |
UCSR1C = _BV(URSEL1) | _BV(UCSZ11) | _BV(UCSZ10); |
UCSR1B = _BV(RXCIE1) | _BV(RXEN1) | _BV(TXEN1); |
} |
|
/* serialInt() is called whenever a character is received on USART1. |
* These characters are send by the serial guider |
* |
* Passed: |
* Nothing |
* |
* Returns: |
* Nothing |
* |
* Notes: |
* Interrupts are disabled during processing |
*/ |
SIGNAL(SIG_USART1_RECV) |
{ |
/* Variables for flags/accumulator */ |
static uint8_t flag = 0; |
static uint16_t accum = 0; |
static uint8_t sign = 0; |
|
/* Variable holding current guiding rate */ |
static int8_t guideRate = SPEED_0_33_X; |
|
/* Flags holding current requested slewing directions */ |
static uint8_t upFlag; |
static uint8_t downFlag; |
static uint8_t leftFlag; |
static uint8_t rightFlag; |
|
/* LX200 command state */ |
#define LX200_CMD_LEN 8 |
static char lxCmd[LX200_CMD_LEN]; |
static uint8_t lxPos; |
|
uint8_t ch; |
uint8_t dirChg; |
|
static uint8_t lxMode; |
|
|
/* Get the character from the port. This will dismiss the interrupt |
*/ |
dirChg = 0; |
ch = UDR1; |
/* UDR1 = ch; /* Echo for debugging */ |
|
/* This code processes commands when a LX200 command is not currently |
* being processed. |
*/ |
if (lxMode == 0) |
{ |
switch(ch) |
{ |
case '0' ... '9': |
/* Add it to the accumulator */ |
accum = (accum * 10) + ch - '0'; |
break; |
|
case '#': |
/* Clear the accumulator */ |
accum = 0; |
sign = 0; |
break; |
|
case '-': |
/* Set the sign of the accumulator to negative */ |
sign = 1; |
break; |
|
case '<': |
/* Clear the flag */ |
flag = 0; |
break; |
|
case '>': |
/* Set the flag */ |
flag = 1; |
break; |
|
case 'U': |
/* Guide UP (DEC) */ |
upFlag = flag; |
dirChg = 1; |
break; |
|
case 'D': |
/* Guide DOWN (DEC) */ |
downFlag = flag; |
dirChg = 1; |
break; |
|
case 'R': |
/* Guide RIGHT (RA) */ |
rightFlag = flag; |
dirChg = 1; |
break; |
|
case 'L': |
/* Guide LEFT (RA) */ |
leftFlag = flag; |
dirChg = 1; |
break; |
|
case 'C': |
/* Clear all keys */ |
upFlag = downFlag = leftFlag = rightFlag = 0; |
dirChg = 1; |
break; |
|
case 'b': |
/* Set RA backlash steps */ |
raState.backlash = accum; |
doSave = 1; |
break; |
|
case 'B': |
/* Set DEC backlash steps */ |
decState.backlash = accum; |
doSave = 1; |
break; |
|
case 'm': |
/* Set RA backlash mode */ |
raState.finNeg = raState.finPos = 0; |
if (accum != 0) |
{ |
if (sign) |
raState.finNeg = 1; |
else |
raState.finPos = 1; |
} |
doSave = 1; |
break; |
|
case 'M': |
/* Set DEC backlash mode */ |
decState.finNeg = decState.finPos = 0; |
if (accum != 0) |
{ |
if (sign) |
decState.finNeg = 1; |
else |
decState.finPos = 1; |
} |
doSave = 1; |
break; |
|
case 'G': |
/* Set the speed for the 2x paddle button. This has |
* no effect on the rate used for serial commands |
*/ |
paddleGuideRate = flag ? SPEED_0_33_X : SPEED_1_X; |
doSave = 1; |
break; |
|
case 'T': |
/* Set the tracking speed */ |
setTrackRate(sign ? -accum : accum); |
doSave = 1; |
break; |
|
case 'g': /* Set transmission (gearbox) ratio */ |
transRatio = accum; |
doSave = 1; |
break; |
|
case 't': |
/* *TEST* Allow half step table to be specified instead of |
* the microstep table |
*/ |
doHalfStep = flag; |
break; |
|
case '\006': /* LX200: ACK */ |
UDR1 = 'P'; |
break; |
|
case ':': /* LX200: Start command */ |
/* This indicates the start of a LX200 command */ |
lxMode = 1; |
lxPos = 0; |
break; |
|
default: |
/* OK, now we're confused .... */ |
UDR1 = '?'; |
break; |
} |
} |
else |
{ |
/* This section of code supports the LX200 commands. They |
* have a fundimentally different syntax to the existing |
* commands, so they are implemented in this code seperately |
* for clarity. |
*/ |
if (ch != '#') |
{ |
/* Add this to the command characters so far */ |
lxCmd[lxPos++] = ch; |
if (lxPos == LX200_CMD_LEN) |
{ |
/* Too much data for any command */ |
UDR1 = '?'; |
lxMode = 0; |
} |
} |
else |
{ |
/* We are going back to native mode after this */ |
lxMode = 0; |
|
if (lxPos >= 1) |
{ |
/* We have a complete LX200 command (without the delimiters). |
* Do what it asks |
*/ |
switch(lxCmd[0]) |
{ |
case 'M': // Start guiding in specified direction |
if (lxPos == 2) |
{ |
// We have the right number of chars */ |
switch (lxCmd[1]) |
{ |
case 'n': upFlag = 1; break; |
case 's': downFlag = 1; break; |
case 'e': rightFlag = 1; break; |
case 'w': leftFlag = 1; break; |
default: UDR1 = '?'; break; |
} |
|
dirChg = 1; |
} |
break; |
|
case 'Q': // Stop guiding in specified direction |
if (lxPos == 1) |
{ |
// Stop slewing |
upFlag = downFlag = leftFlag = rightFlag = 0; |
dirChg = 1; |
} |
else if (lxPos == 2) |
{ |
// Stop slewing is specified direction |
switch (lxCmd[1]) |
{ |
case 'n': upFlag = 0; break; |
case 's': downFlag = 0; break; |
case 'e': rightFlag = 0; break; |
case 'w': leftFlag = 0; break; |
default: UDR1 = '?'; break; |
} |
|
dirChg = 1; |
} else |
UDR1 = '?'; |
break; |
|
case 'R': // Set guiding speed |
if (lxPos == 2) |
{ |
switch (lxCmd[1]) |
{ |
case 'G': guideRate = SPEED_0_33_X; break; |
case 'C': guideRate = SPEED_1_X; break; |
case 'M': guideRate = SPEED_8_X; break; |
case 'S': guideRate = SPEED_16_X; break; |
default: UDR1 = '?'; break; |
} |
dirChg = 1; |
} |
break; |
default: |
UDR1 = '?'; |
} |
} |
} |
} |
|
/* Update the serial guiding rate data if it has changed */ |
if (dirChg) |
{ |
if (upFlag) |
rateInput.serialDecRate = guideRate; |
else if (downFlag) |
rateInput.serialDecRate = -guideRate; |
else |
rateInput.serialDecRate = SPEED_0_X; |
|
if (rightFlag) |
rateInput.serialRaRate = guideRate; |
else if (leftFlag) |
rateInput.serialRaRate = -guideRate; |
else |
rateInput.serialRaRate = SPEED_0_X; |
} |
updateMountSpeed(); |
} |