$search
00001 /* 00002 Aseba - an event-based framework for distributed robot control 00003 Copyright (C) 2007--2010: 00004 Stephane Magnenat <stephane at magnenat dot net> 00005 (http://stephane.magnenat.net) 00006 and other contributors, see authors.txt for details 00007 00008 This program is free software: you can redistribute it and/or modify 00009 it under the terms of the GNU Lesser General Public License as published 00010 by the Free Software Foundation, version 3 of the License. 00011 00012 This program is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU Lesser General Public License for more details. 00016 00017 You should have received a copy of the GNU Lesser General Public License 00018 along with this program. If not, see <http://www.gnu.org/licenses/>. 00019 */ 00020 00021 #include "hardware.h" 00022 #include <transport/can/can-net.h> 00023 #include <common/consts.h> 00024 #include <can/can.h> 00025 #include <dma/dma.h> 00026 #include <gpio/gpio.h> 00027 #include <uart/uart-software-fc.h> 00028 #include <clock/clock.h> 00029 #include <error/error.h> 00030 #include <types/types.h> 00031 #include <timer/timer.h> 00032 #include <ei/ei.h> 00033 #include <adc/adc.h> 00034 00035 #include "morse.h" 00036 00037 00038 _FWDT(FWDTEN_OFF); // Watchdog Timer disabled 00039 _FOSCSEL(FNOSC_FRCPLL); // override oscillator configuration bits 00040 _FOSC(POSCMD_NONE & OSCIOFNC_ON); 00041 // ICD communicates on PGC1/EMUC1 and disable JTAG 00042 _FICD(ICS_PGD1 & JTAGEN_OFF); 00043 00044 #define PRIO_CAN 5 00045 #define PRIO_UART 5 00046 #define PRIO_UART_TH 6 00047 00048 #define TIMER_UART TIMER_1 00049 00050 /* buffers for can-net */ 00051 #define SEND_QUEUE_SIZE 260 00052 static __attribute((far)) CanFrame sendQueue[SEND_QUEUE_SIZE]; 00053 #define RECV_QUEUE_SIZE 1100 00054 static __attribute((far)) CanFrame recvQueue[RECV_QUEUE_SIZE]; 00055 00056 /* buffers for uart */ 00057 static __attribute((far)) __attribute((aligned(2))) unsigned char uartSendBuffer[ASEBA_MAX_OUTER_PACKET_SIZE]; 00058 static unsigned uartSendPos; 00059 static unsigned uartSendSize; 00060 static __attribute((far)) __attribute((aligned(2))) unsigned char uartRecvBuffer[ASEBA_MAX_OUTER_PACKET_SIZE]; 00061 static unsigned uartRecvPos; 00062 00063 00064 00065 volatile int global_flag = 0; 00066 00067 #define OUTPUT_ERROR(err) do{ for(;;) output_error(err,LED0,0,1); }while(0) 00068 00069 static void can_tx_cb(void) 00070 { 00071 if(global_flag) 00072 OUTPUT_ERROR(global_flag); 00073 global_flag = 1; 00074 00075 AsebaCanFrameSent(); 00076 00077 // A message is waiting on the uart (it's complete but still waiting because we were full) 00078 // Check if we can send it now 00079 if ((uartRecvPos >= 6) && (uartRecvPos == 6 + ((uint16 *)uartRecvBuffer)[0])) 00080 { 00081 uint16 source = ((uint16 *)uartRecvBuffer)[1]; 00082 if (AsebaCanSendSpecificSource(uartRecvBuffer+4, uartRecvPos-4, source) == 1) 00083 { 00084 uartRecvPos = 0; 00085 uart_read_pending_data(U_UART); 00086 } 00087 } 00088 global_flag = 0; 00089 } 00090 00091 static void can_rx_cb(const can_frame* frame) 00092 { 00093 if(global_flag) 00094 OUTPUT_ERROR(global_flag); 00095 global_flag = 2; 00096 00097 // we do a nasty cast because the two data structure are compatible, i.e. they have the same leading members 00098 AsebaCanFrameReceived((CanFrame *) frame); 00099 00100 uint16 source; 00101 00102 if(uartSendPos == uartSendSize) 00103 { 00104 int amount = AsebaCanRecv(uartSendBuffer+4, ASEBA_MAX_INNER_PACKET_SIZE, &source); 00105 if (amount > 0) 00106 { 00107 ((uint16 *)uartSendBuffer)[0] = (uint16)amount - 2; 00108 ((uint16 *)uartSendBuffer)[1] = source; 00109 uartSendSize = (unsigned)amount + 4; 00110 00111 if(uart_transmit_byte(U_UART, uartSendBuffer[0])) 00112 uartSendPos = 1; 00113 else 00114 uartSendPos = 0; 00115 } 00116 } 00117 global_flag = 0; 00118 00119 } 00120 00121 static bool uart_rx_cb(int __attribute((unused)) uart_id, unsigned char data, void * __attribute((unused)) user_data) 00122 { 00123 if(global_flag) 00124 OUTPUT_ERROR(global_flag); 00125 global_flag = 3; 00126 00127 // TODO: in case of bug, we might want to test for overflow here, but it should never happen if higher layer conform to specification 00128 uartRecvBuffer[uartRecvPos++] = data; 00129 00130 // if we have received the header and all the message payload data forward it to the can layer 00131 if ((uartRecvPos >= 6) && (uartRecvPos == 6 + ((uint16 *)uartRecvBuffer)[0])) 00132 { 00133 00134 uint16 source = ((uint16 *)uartRecvBuffer)[1]; 00135 if (AsebaCanSendSpecificSource(uartRecvBuffer+4, uartRecvPos-4, source) == 1) 00136 { 00137 // Was able to queue frame to can layer. Setup the buffer pointer for next reception 00138 uartRecvPos = 0; 00139 global_flag = 0; 00140 return true; 00141 } else { 00142 // Stop reception, flow control will help us to not lose any packet 00143 global_flag = 0; 00144 return false; 00145 } 00146 } 00147 global_flag = 0; 00148 return true; 00149 } 00150 00151 static bool uart_tx_cb(int __attribute((unused)) uart_id, unsigned char* data, void* __attribute((unused)) user_data) 00152 { 00153 if(global_flag) 00154 OUTPUT_ERROR(global_flag); 00155 global_flag = 4; 00156 00157 if (uartSendPos < uartSendSize) 00158 { 00159 *data = uartSendBuffer[uartSendPos++]; 00160 global_flag = 0; 00161 return true; 00162 } 00163 else 00164 { 00165 // We finished sending the previous packet 00166 00167 // ...and if there is a new message on CAN, read it 00168 uint16 source; 00169 00170 int amount = AsebaCanRecv(uartSendBuffer+4, ASEBA_MAX_INNER_PACKET_SIZE, &source); 00171 if (amount > 0) 00172 { 00173 ((uint16 *)uartSendBuffer)[0] = (uint16)amount - 2; 00174 ((uint16 *)uartSendBuffer)[1] = source; 00175 uartSendSize = (unsigned)amount + 4; 00176 uartSendPos = 1; 00177 *data = uartSendBuffer[0]; 00178 global_flag = 0; 00179 return true; 00180 } 00181 00182 global_flag = 0; 00183 return false; 00184 } 00185 } 00186 00187 void AsebaIdle(void) { 00188 // Should NEVER be called 00189 OUTPUT_ERROR(5); 00190 } 00191 00192 uint16 AsebaShouldDropPacket(uint16 source, const uint8* data) { 00193 return 0; 00194 } 00195 00196 static void received_packet_dropped(void) 00197 { 00198 // light a LED, we have dropped an aseba message from the CAN because we were not able to send previous ones fast enough on UART 00199 gpio_write(LED1, 0); 00200 } 00201 00202 static void sent_packet_dropped(void) 00203 { 00204 // light a LED, the packet is in fact not dropped because UART has flow control and the translator will try again later 00205 gpio_write(LED1, 0); 00206 } 00207 00208 void __attribute__((noreturn)) error_handler(const char __attribute((unused)) * file, int __attribute((unused)) line, int id, void* __attribute((unused)) arg) { 00209 OUTPUT_ERROR(id); 00210 } 00211 00212 /* initialization and main loop */ 00213 int main(void) 00214 { 00215 int i; 00216 00217 if(_POR) { 00218 _POR = 0; 00219 asm __volatile("reset"); 00220 } 00221 00222 clock_init_internal_rc_30(); 00223 00224 // Wait about 1 s before really starting. The Bluetooth chip need a LOT of time before 00225 // having stable output (else we recieve "Phantom" character on uart) 00226 00227 for(i = 0; i < 1000; i++) 00228 clock_delay_us(1000); 00229 00230 gpio_write(LED0, 1); 00231 gpio_write(LED1, 1); 00232 gpio_set_dir(LED0, GPIO_OUTPUT); 00233 gpio_set_dir(LED1, GPIO_OUTPUT); 00234 00235 error_register_callback(error_handler); 00236 00237 00238 adc1_init_simple(NULL, 1, 0x0UL, 30); 00239 00240 can_init(can_rx_cb, can_tx_cb, DMA_CHANNEL_0, DMA_CHANNEL_1, CAN_SELECT_MODE, 1000, PRIO_CAN); 00241 uart_init(U_UART, 921600, UART_CTS, UART_RTS, TIMER_UART, uart_rx_cb, uart_tx_cb, PRIO_UART_TH, PRIO_UART, NULL); 00242 00243 AsebaCanInit(0, (AsebaCanSendFrameFP)can_send_frame, can_is_frame_room, received_packet_dropped, sent_packet_dropped, sendQueue, SEND_QUEUE_SIZE, recvQueue, RECV_QUEUE_SIZE); 00244 00245 00246 while (1) 00247 { 00248 // Sleep until something happens 00249 Idle(); 00250 }; 00251 } 00252