new servo pos
[aversive.git] / projects / microb2010 / mainboard / ax12_user.c
1 /*  
2  *  Copyright Droids Corporation
3  *  Olivier Matz <zer0@droids-corp.org>
4  * 
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  *  Revision : $Id: ax12_user.c,v 1.3 2009-05-02 10:08:09 zer0 Exp $
20  *
21  */
22
23 #include <aversive.h>
24 #include <aversive/list.h>
25 #include <aversive/error.h>
26
27 #include <i2c.h>
28 #include <ax12.h>
29 #include <uart.h>
30 #include <pwm_ng.h>
31 #include <clock_time.h>
32 #include <spi.h>
33
34 #include <pid.h>
35 #include <quadramp.h>
36 #include <control_system_manager.h>
37 #include <trajectory_manager.h>
38 #include <vect_base.h>
39 #include <lines.h>
40 #include <polygon.h>
41 #include <obstacle_avoidance.h>
42 #include <blocking_detection_manager.h>
43 #include <robot_system.h>
44 #include <position_manager.h>
45
46 #include <rdline.h>
47 #include <parse.h>
48 #include <parse_string.h>
49 #include <parse_num.h>
50
51 #include "main.h"
52
53 /*
54  * Cmdline interface for AX12. Use the PC to command a daisy-chain of
55  * AX12 actuators with a nice command line interface.
56  * 
57  * The circuit should be as following:
58  *
59  *    |----------|
60  *    |     uart3|------->--- PC (baudrate=57600)
61  *    |          |-------<---
62  *    | atmega128|
63  *    |          |
64  *    |     uart0|---->---+-- AX12 (baudrate 115200)
65  *    |          |----<---| 
66  *    |----------|
67  *
68  * Note that RX and TX pins of UART1 are connected together to provide
69  * a half-duplex UART emulation.
70  *
71  */
72
73 #define UART_AX12_NUM 0
74 #define UCSRxB UCSR0B
75 #define AX12_TIMEOUT 5000UL /* in us */
76
77 /********************************* AX12 commands */
78
79 /*
80  * We use synchronous access (not interrupt driven) to the hardware
81  * UART, because we have to be sure that the transmission/reception is
82  * really finished when we return from the functions.
83  *
84  * We don't use the CM-5 circuit as described in the AX12
85  * documentation, we simply connect TX and RX and use TXEN + RXEN +
86  * DDR to manage the port directions.
87  */
88
89 #ifndef HOST_VERSION
90
91 static volatile uint8_t ax12_state = AX12_STATE_READ;
92 extern volatile struct cirbuf g_tx_fifo[]; /* uart fifo */
93 static volatile uint8_t ax12_nsent = 0;
94
95 /* Called by ax12 module to send a character on serial line. Count the
96  * number of transmitted bytes. It will be used in ax12_recv_char() to
97  * drop the bytes that we transmitted. */
98 static int8_t ax12_send_char(uint8_t c)
99 {
100         uart_send(UART_AX12_NUM, c);
101         ax12_nsent++;
102         return 0;
103 }
104
105 /* for atmega256 */
106 #ifndef TXEN
107 #define TXEN TXEN0
108 #endif
109
110 /* called by uart module when the character has been written in
111  * UDR. It does not mean that the byte is physically transmitted. */
112 static void ax12_send_callback(char c)
113 {
114         if (ax12_state == AX12_STATE_READ) {
115                 /* disable TX when last byte is pushed. */
116                 if (CIRBUF_IS_EMPTY(&g_tx_fifo[UART_AX12_NUM]))
117                         UCSRxB &= ~(1<<TXEN);
118         }
119 }
120
121 /* Called by ax12 module when we want to receive a char. Note that we
122  * also receive the bytes we sent ! So we need to drop them. */
123 static int16_t ax12_recv_char(void)
124 {
125         microseconds t = time_get_us2();
126         int c;
127         while (1) {
128                 c = uart_recv_nowait(UART_AX12_NUM);
129                 if (c != -1) {
130                         if (ax12_nsent == 0)
131                                 return c;
132                         ax12_nsent --;
133                 }
134
135                 /* 5 ms timeout */
136                 if ((time_get_us2() - t) > AX12_TIMEOUT)
137                         return -1;
138         }
139         return c;
140 }
141
142 /* called by ax12 module when we want to switch serial line. As we
143  * work in interruption mode, this function can be called to switch
144  * back in read mode even if the bytes are not really transmitted on
145  * the line. That's why in this case we do nothing, we will fall back
146  * in read mode in any case when xmit is finished -- see in
147  * ax12_send_callback() -- */
148 static void ax12_switch_uart(uint8_t state)
149 {
150         uint8_t flags;
151
152         if (state == AX12_STATE_WRITE) {
153                 IRQ_LOCK(flags);
154                 ax12_nsent=0;
155                 while (uart_recv_nowait(UART_AX12_NUM) != -1);
156                 UCSRxB |= (1<<TXEN);
157                 ax12_state = AX12_STATE_WRITE;
158                 IRQ_UNLOCK(flags);
159         }
160         else {
161                 IRQ_LOCK(flags);
162                 if (CIRBUF_IS_EMPTY(&g_tx_fifo[UART_AX12_NUM]))
163                         UCSRxB &= ~(1<<TXEN);
164                 ax12_state = AX12_STATE_READ;
165                 IRQ_UNLOCK(flags);
166         }
167 }
168 #endif
169
170 void ax12_user_init(void)
171 {
172 #ifdef HOST_VERSION
173         return;
174 #else
175         /* AX12 */
176         AX12_init(&gen.ax12);
177         AX12_set_hardware_send(&gen.ax12, ax12_send_char);
178         AX12_set_hardware_recv(&gen.ax12, ax12_recv_char);
179         AX12_set_hardware_switch(&gen.ax12, ax12_switch_uart);
180         uart_register_tx_event(UART_AX12_NUM, ax12_send_callback);
181 #endif
182 }