Blame | Last modification | View Log | Download
/*
* 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();
}