Subversion Repositories svnkaklik

Rev

Details | Last modification | View Log

Rev Author Line No. Line
508 kaklik 1
/* 
2
 * Copyright (C) 2004 Darren Hutchinson (dbh@gbdt.com.au)
3
 * 
4
 * This program is free software; you can redistribute it and/or modify
5
 * it under the terms of the GNU Library General Public License as published by
6
 * the Free Software Foundation; either version 2 of the License, or (at your
7
 * option) any later version.
8
 *
9
 * This program is distributed in the hope that it will be useful, but
10
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
12
 * License for more details.
13
 * 
14
 * You should have received a copy of the GNU Library General Public License
15
 * along with this program; see the file COPYING.  If not, write to
16
 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
17
 * MA 02111-1307, USA. 
18
 *
19
 * $Id: serial.c,v 1.10 2004/04/04 10:32:50 dbh Exp $
20
 */
21
 
22
#include <inttypes.h>
23
#include <avr/io.h>
24
 
25
#include "eq6.h"
26
#include "serial.h"
27
#include "combine.h"
28
#include "stepper.h"
29
#include "paddle.h"
30
#include "sr.h"
31
 
32
/* This file accepts serial data from a serial guider and performs the
33
 * requested guiding operation.
34
 *
35
 * This interface is also is designed to support future mount management
36
 * operations via the same serial interface
37
 *
38
 * The current protocol is:
39
 *
40
 * [0-9]    Add the number to the "accumulator"
41
 * -        Denote accumulator as negative
42
 * #        Clear the accumulator and flag
43
 * <        Clear the flag
44
 * >        Set the flag
45
 * U        Copy flag state to the DEC UP key
46
 * D        Copy flag state to the DEC DOWN key
47
 * L        Copy flag state to the RA left key
48
 * R        Copy flag state to the RA right key
49
 * C        Release all keys
50
 *
51
 * B        Set DEC backlash to accum
52
 * M        Set DEC backlash mode (+ = finish pos, 0 = none, - = finish neg)
53
 * b        Set RA backlash to accum
54
 * m        Set RA backlash mode (see DEC backlash)
55
 *
56
 * G        Set 2X paddle to guiding speed (0.3x) if flag set, 1X if clear
57
 *
58
 * t        Use halfStep for slow step if flag set, microStep if clear (TEST)
59
 *
60
 * T        Set the tracking rate as-per the accumulator
61
 *          -1 = No tracking (Terrestial)
62
 *          0 = Sidereal
63
 *          1 = Solar / Planetary
64
 *          2 = Lunar
65
 *
66
 * g        Set transmission (gearbox) ratio
67
 *
68
 * The '#' and accumulator support future value-based entries
69
 *
70
 * A subset of LX200 commands are supported for compatibility
71
 * with various autoguiding programs.
72
 *
73
 * :Me# :Mw# :Ms# :Mn#          Start slewing East(right), West(left),
74
 *                              North (up), South (down)
75
 * :Qe# :Qw# :Qs# :Qn# :Q#      Halt selected or all slews
76
 * :RG# :RC# :RM# :RS#          Set guiding rate for LX200 motions
77
 *                              G = 0.3x
78
 *                              C = 1x
79
 *                              M = 8x
80
 *                              S = 16x
81
 *                                      
82
 * ACK                          Returns alignment mode (always 'P' polar)
83
 */
84
#include <avr/interrupt.h>
85
#include <inttypes.h>
86
 
87
#include "paddle.h"
88
#include "eq6.h"
89
#include "combine.h"
90
 
91
/* serialInit() initializes the serial port used for the 
92
 * serial guider input.
93
 *
94
 * Passed:
95
 *         Nothing
96
 *
97
 * Returns:
98
 *         Nothing.
99
 */
100
void
101
serialInit(void)
102
{
103
    // The serial guider is attached to USART1
104
 
105
    // Set serial rate
106
    UBRR1H = (CLK_RATE / GUIDE_BAUD / 16 - 1) >> 8;
107
    UBRR1L = (CLK_RATE / GUIDE_BAUD / 16 - 1) & 0xff;
108
 
109
    /* Setup registers
110
     * 8 bits, no parity, RX enable, TX enable. Only the Rx interrupts are
111
     * enabled at this point.
112
     */
113
    UCSR1B = 0;            // Disable all interrupts
114
    UCSR1C = _BV(URSEL1) | _BV(UCSZ11) | _BV(UCSZ10);
115
    UCSR1B = _BV(RXCIE1) | _BV(RXEN1) | _BV(TXEN1);
116
}
117
 
118
/* serialInt() is called whenever a character is received on USART1.
119
 * These characters are send by the serial guider
120
 *
121
 * Passed:
122
 *         Nothing
123
 *
124
 * Returns:
125
 *         Nothing
126
 *
127
 * Notes:
128
 *         Interrupts are disabled during processing
129
 */
130
SIGNAL(SIG_USART1_RECV)
131
{
132
    /* Variables for flags/accumulator */
133
    static uint8_t      flag = 0;
134
    static uint16_t     accum = 0;
135
    static uint8_t      sign = 0;
136
 
137
    /* Variable holding current guiding rate */
138
    static int8_t       guideRate = SPEED_0_33_X;
139
 
140
    /* Flags holding current requested slewing directions */
141
    static uint8_t      upFlag;
142
    static uint8_t      downFlag;
143
    static uint8_t      leftFlag;
144
    static uint8_t      rightFlag;
145
 
146
    /* LX200 command state */
147
#define LX200_CMD_LEN   8
148
    static char         lxCmd[LX200_CMD_LEN];
149
    static uint8_t      lxPos;
150
 
151
    uint8_t             ch;
152
    uint8_t             dirChg;
153
 
154
    static uint8_t      lxMode;
155
 
156
 
157
    /* Get the character from the port. This will dismiss the interrupt
158
     */
159
    dirChg = 0;
160
    ch = UDR1;
161
    /* UDR1 = ch;       /* Echo for debugging */
162
 
163
    /* This code processes commands when a LX200 command is not currently
164
     * being processed.
165
     */
166
    if (lxMode == 0)
167
    {
168
        switch(ch)
169
        {
170
        case '0' ... '9':
171
            /* Add it to the accumulator */
172
            accum = (accum * 10) + ch - '0';
173
            break;
174
 
175
        case '#':
176
            /* Clear the accumulator */
177
            accum = 0;
178
            sign = 0;
179
            break;
180
 
181
        case '-':
182
            /* Set the sign of the accumulator to negative */
183
            sign = 1;
184
            break;
185
 
186
        case '<':
187
            /* Clear the flag */
188
            flag = 0;
189
            break;
190
 
191
        case '>':
192
            /* Set the flag */
193
            flag = 1;
194
            break;
195
 
196
        case 'U':
197
            /* Guide UP (DEC) */
198
            upFlag = flag;
199
            dirChg = 1;
200
            break;
201
 
202
        case 'D':
203
            /* Guide DOWN (DEC) */
204
            downFlag = flag;
205
            dirChg = 1;
206
            break;
207
 
208
        case 'R':
209
            /* Guide RIGHT (RA) */
210
            rightFlag = flag;
211
            dirChg = 1;
212
            break;
213
 
214
        case 'L':
215
            /* Guide LEFT (RA) */
216
            leftFlag = flag;
217
            dirChg = 1;
218
            break;
219
 
220
        case 'C':
221
            /* Clear all keys */
222
            upFlag = downFlag = leftFlag = rightFlag = 0;
223
            dirChg = 1;
224
            break;
225
 
226
        case 'b':
227
            /* Set RA backlash steps */
228
            raState.backlash = accum;
229
            doSave = 1;
230
            break;
231
 
232
        case 'B':
233
            /* Set DEC backlash steps */
234
            decState.backlash = accum;
235
            doSave = 1;
236
            break;
237
 
238
        case 'm':
239
            /* Set RA backlash mode */
240
            raState.finNeg = raState.finPos = 0;
241
            if (accum != 0)
242
            {
243
                if (sign)
244
                    raState.finNeg = 1;
245
                else
246
                    raState.finPos = 1;
247
            }
248
            doSave = 1;
249
            break;
250
 
251
        case 'M':
252
            /* Set DEC backlash mode */
253
            decState.finNeg = decState.finPos = 0;
254
            if (accum != 0)
255
            {
256
                if (sign)
257
                    decState.finNeg = 1;
258
                else
259
                    decState.finPos = 1;
260
            }
261
            doSave = 1;
262
            break;
263
 
264
        case 'G':
265
            /* Set the speed for the 2x paddle button. This has
266
             * no effect on the rate used for serial commands
267
             */
268
            paddleGuideRate = flag ? SPEED_0_33_X : SPEED_1_X;
269
            doSave = 1;
270
            break;
271
 
272
        case 'T':
273
            /* Set the tracking speed */
274
            setTrackRate(sign ? -accum : accum);
275
            doSave = 1;
276
            break;
277
 
278
        case 'g':       /* Set transmission (gearbox) ratio */
279
            transRatio = accum;
280
            doSave = 1;
281
            break;
282
 
283
        case 't':
284
            /* *TEST* Allow half step table to be specified instead of
285
             * the microstep table
286
             */
287
            doHalfStep = flag;
288
            break;
289
 
290
        case '\006':        /* LX200: ACK */
291
            UDR1 = 'P';
292
            break;
293
 
294
        case ':':           /* LX200: Start command */
295
            /* This indicates the start of a LX200 command */
296
            lxMode = 1;
297
            lxPos = 0;
298
            break;
299
 
300
        default:
301
            /* OK, now we're confused .... */
302
            UDR1 = '?';
303
            break;
304
        }
305
    }
306
    else
307
    {
308
        /* This section of code supports the LX200 commands. They
309
         * have a fundimentally different syntax to the existing
310
         * commands, so they are implemented in this code seperately
311
         * for clarity.
312
         */
313
        if (ch != '#')
314
        {
315
            /* Add this to the command characters so far */
316
            lxCmd[lxPos++] = ch;
317
            if (lxPos == LX200_CMD_LEN)
318
            {
319
                /* Too much data for any command */
320
                UDR1 = '?';
321
                lxMode = 0;
322
            }
323
        }
324
        else
325
        {
326
            /* We are going back to native mode after this */
327
            lxMode = 0;
328
 
329
            if (lxPos >= 1)
330
            {
331
                /* We have a complete LX200 command (without the delimiters).
332
                 * Do what it asks
333
                 */
334
                switch(lxCmd[0])
335
                {
336
                case 'M':       // Start guiding in specified direction
337
                    if (lxPos == 2)
338
                    {
339
                        // We have the right number of chars */
340
                        switch (lxCmd[1])
341
                        {
342
                        case 'n': upFlag = 1; break;
343
                        case 's': downFlag = 1; break;
344
                        case 'e': rightFlag = 1; break;
345
                        case 'w': leftFlag = 1; break;
346
                        default: UDR1 = '?'; break;
347
                        }
348
 
349
                        dirChg = 1;
350
                    }
351
                    break;
352
 
353
                case 'Q':       // Stop guiding in specified direction
354
                    if (lxPos == 1)
355
                    {
356
                        // Stop slewing
357
                        upFlag = downFlag = leftFlag = rightFlag = 0;
358
                        dirChg = 1;
359
                    }
360
                    else if (lxPos == 2)
361
                    {
362
                        // Stop slewing is specified direction
363
                        switch (lxCmd[1])
364
                        {
365
                        case 'n': upFlag = 0; break;
366
                        case 's': downFlag = 0; break;
367
                        case 'e': rightFlag = 0; break;
368
                        case 'w': leftFlag = 0; break;
369
                        default: UDR1 = '?'; break;
370
                        }
371
 
372
                        dirChg = 1;
373
                    } else
374
                        UDR1 = '?';
375
                    break;
376
 
377
                case 'R':           // Set guiding speed
378
                    if (lxPos == 2)
379
                    {
380
                        switch (lxCmd[1])
381
                        {
382
                        case 'G':   guideRate = SPEED_0_33_X; break;
383
                        case 'C':   guideRate = SPEED_1_X; break;
384
                        case 'M':   guideRate = SPEED_8_X; break;
385
                        case 'S':   guideRate = SPEED_16_X; break;
386
                        default: UDR1 = '?'; break;
387
                        }
388
                        dirChg = 1;
389
                    }
390
                    break;
391
                default:
392
                    UDR1 = '?';
393
                }
394
            }
395
        }
396
    }
397
 
398
    /* Update the serial guiding rate data if it has changed */
399
    if (dirChg)
400
    {
401
        if (upFlag)
402
            rateInput.serialDecRate = guideRate;
403
        else if (downFlag)
404
            rateInput.serialDecRate = -guideRate;
405
        else
406
            rateInput.serialDecRate = SPEED_0_X;
407
 
408
        if (rightFlag)
409
            rateInput.serialRaRate = guideRate;
410
        else if (leftFlag)
411
            rateInput.serialRaRate = -guideRate;
412
        else
413
            rateInput.serialRaRate = SPEED_0_X;
414
    }
415
    updateMountSpeed();
416
}