0,0 → 1,246 |
/* |
* 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: paddle.c,v 1.4 2004/03/03 07:37:11 dbh Exp $ |
*/ |
|
/* This file handles the interface to the EQ-6/Atlas hand paddle. |
* |
* This paddle generates a continuous serial stream containing information |
* about the state of the paddle. Unlike many simple paddles the EQ-6 has a |
* small microprocessor to handle the various functions (debouncing, switch |
* refersal, etc) |
* |
* See the file eq6-serial.txt for further information on the prototcol |
* used by the hand paddle. |
*/ |
#include <avr/io.h> |
#include <avr/interrupt.h> |
#include <inttypes.h> |
|
#include "paddle.h" |
#include "eq6.h" |
#include "combine.h" |
|
uint8_t paddleGuideRate = SPEED_1_X; |
|
/* paddleInit() initializes the serial port used for the EQ6/Atlas |
* hand paddle. The communication with this port is only in one |
* direction (from paddle to mount). |
* |
* Passed: |
* Nothing |
* |
* Returns: |
* Nothing. |
*/ |
void |
paddleInit(void) |
{ |
// The handpaddle is connected to UART port #0 (pin 10) |
|
// Set serial rate |
UBRR0H = (CLK_RATE / PADDLE_RATE / 16 - 1) >> 8; |
UBRR0L = (CLK_RATE / PADDLE_RATE / 16 - 1) & 0xff; |
|
/* Setup registers |
* 9 bits, RX enable |
*/ |
UCSR0B = 0; // Disable all interrupts |
UCSR0C = _BV(URSEL0) | _BV(UCSZ01) | _BV(UCSZ00); |
UCSR0B = _BV(RXCIE0) | _BV(UCSZ02) | _BV(RXEN0); |
} |
|
/* paddleInt() is called whenever a character is received on USART0. |
* These characters are send by the hand paddle |
* |
* Passed: |
* Nothing |
* |
* Returns: |
* Nothing |
* |
* Notes: |
* This function inplemented a state machine to properly |
* synchronize with the incoming character stream. |
* |
* Interrupts are disabled during processing |
*/ |
SIGNAL(SIG_USART0_RECV) |
{ |
uint8_t lowerByte; |
uint8_t b8; |
|
static void *pLabel = &&wait_for_sync; |
|
static uint8_t raDir = 0; |
static uint8_t raSpeed = 0; |
static uint8_t decDir = 0; |
|
static uint8_t oldRaDir = (uint8_t)-1; |
static uint8_t oldRaSpeed = (uint8_t)-1; |
static uint8_t oldDecDir = (uint8_t)-1; |
static uint8_t oldDecSpeed = (uint8_t)-1; |
|
/* Read the nine bits of transferred data. We don't do this |
* during initialization as the order is important! |
*/ |
b8 = UCSR0B & _BV(RXB80); |
lowerByte = UDR0; |
|
/* Jump to the code that handles the current reception system. Note that |
* this feature is GCC specific. |
*/ |
goto *pLabel; |
|
/* Wait for the RA sync byte |
*/ |
wait_for_sync: |
if ((b8 == 0) && (lowerByte == RA_SYNC)) |
pLabel = &&get_ra_direction; |
return; |
|
/* Get the RA direction - this will have b8 == 0 |
*/ |
get_ra_direction: |
if (b8 == 0) |
{ |
raDir = lowerByte & _BV(RA_DIR_BIT); |
pLabel = &&get_ra_speed; |
} |
else |
pLabel = &&wait_for_sync; |
return; |
|
/* Get the RA speed - this will have b8 == 0 |
*/ |
get_ra_speed: |
if (b8 == 0) |
{ |
raSpeed = lowerByte & RA_SPEED_MASK; |
pLabel = &&get_dec_sync; |
} |
else |
pLabel = &&wait_for_sync; |
return; |
|
/* Get the mystery fourth byte |
*/ |
get_dec_sync: |
if (b8 != 0) |
{ |
pLabel = &&get_dec_direction; |
} |
else |
pLabel = &&wait_for_sync; |
return; |
|
/* Get the DEC direction - this will have b8 != 0 |
*/ |
get_dec_direction: |
if (b8 != 0) |
{ |
decDir = lowerByte & _BV(DEC_DIR_BIT); |
pLabel = &&get_dec_speed; |
} |
else |
pLabel = &&wait_for_sync; |
return; |
|
/* Get the RA speed - this will have b8 == 0 |
*/ |
get_dec_speed: |
// We've got all the words - the next state will always be wait for sync |
pLabel = &&wait_for_sync; |
lowerByte &= DEC_SPEED_MASK; |
|
/* If the parity is correct and any of the bytes are different then |
* process them |
*/ |
if ( b8 != 0 |
&& ( (oldRaDir != raDir) |
|| (oldRaSpeed != raSpeed) |
|| (oldDecDir != decDir) |
|| (oldDecSpeed != lowerByte))) |
{ |
/* Update "old" indications */ |
oldRaDir = raDir; |
oldRaSpeed = raSpeed; |
oldDecDir = decDir; |
oldDecSpeed = lowerByte; |
|
/* Process the data from the paddle |
* - if the RA speed is one then setup the siderial speed |
* - convert the RA speed/direction into a device independent form |
* - convert the DEC speed/direction into a device independent form |
*/ |
if (raSpeed == RA_SPEED_0) |
{ |
rateInput.paddleRaRate = -paddleGuideRate; |
|
/* This is a little trick because the "direction" bit doesn't |
* work then the speed is zero. Do a pre-invert if the |
* siderial rate is for the northern hemisphere |
*/ |
if (rateInput.siderialRate == SPEED_SIDERIAL) |
rateInput.paddleRaRate = -rateInput.paddleRaRate; |
} |
else if (raSpeed == RA_SPEED_1) |
{ |
rateInput.paddleRaRate = SPEED_0_X; |
rateInput.siderialRate = raDir ? SPEED_SIDERIAL : -SPEED_SIDERIAL; |
} |
else if (raSpeed == RA_SPEED_2) |
rateInput.paddleRaRate = paddleGuideRate; |
else if (raSpeed == RA_SPEED_8) |
rateInput.paddleRaRate = SPEED_8_X; |
else if (raSpeed == RA_SPEED_16) |
rateInput.paddleRaRate = SPEED_16_X; |
|
#if 0 |
/* The direction of the RA keys is reversed when operating in |
* the southern hemisphere, so modify them back |
*/ |
if ((raDir == 0) ^ (rateInput.siderialRate == SPEED_SIDERIAL)) |
rateInput.paddleRaRate = -rateInput.paddleRaRate; |
#else |
/* Use the keys as returned by the paddle. These are reversed when |
* operating in the southern hemisphere. This ensures that the |
* "right" key always increases the RA angle |
*/ |
if (raDir == 0) |
rateInput.paddleRaRate = -rateInput.paddleRaRate; |
#endif |
|
if (lowerByte == DEC_SPEED_0) |
rateInput.paddleDecRate = SPEED_0_X; |
else if (lowerByte == DEC_SPEED_2) |
rateInput.paddleDecRate = paddleGuideRate; |
else if (lowerByte == DEC_SPEED_8) |
rateInput.paddleDecRate = SPEED_8_X; |
else if (lowerByte == DEC_SPEED_16) |
rateInput.paddleDecRate = SPEED_16_X; |
|
if (decDir != 0) |
rateInput.paddleDecRate = -rateInput.paddleDecRate; |
|
/* Ok, all parsed. Force an update of the combined speed |
*/ |
updateMountSpeed(); |
} |
} |