copied over all of the custom pcb stuff and switched connectors + added PWM headers to the power board
git-svn-id: https://robotics.mvla.net/svn/frc971/2013/trunk/src@4029 f308d9b7-e957-4cde-b6ac-9a88185e7312
diff --git a/gyro_board/src/usb/CAN.c b/gyro_board/src/usb/CAN.c
new file mode 100644
index 0000000..74e0a62
--- /dev/null
+++ b/gyro_board/src/usb/CAN.c
@@ -0,0 +1,283 @@
+/* Standard includes. */
+#include "stdio.h"
+
+/* Scheduler includes. */
+#include "FreeRTOS.h"
+#include "queue.h"
+#include "task.h"
+
+/* Demo app includes. */
+#include "flash.h"
+#include "partest.h"
+#include "analog.h"
+#include "spi.h"
+#include "LPCUSB/usbapi.h"
+#include "CAN.h"
+
+static xQueueHandle CAN_tx_queue = NULL, CAN_rx_queue = NULL;
+
+/** Send a CAN message. The message is stored by copy.
+ *
+ * \returns Zero on success, and one on failure to queue the message.
+ */
+int CAN_send(can_message *message) {
+ uint32_t sr = CAN1->SR;
+ // Queue the message up in a queue!
+ if (sr & 0x00040404) {
+ uint32_t IFx = (message->RTR << 30) +
+ (message->length << 16) +
+ (message->priority);
+
+ uint32_t data0 = message->wdata[0];
+ uint32_t data1 = message->wdata[1];
+
+ if(sr & 0x00000004){
+ CAN1->TFI1 = IFx;
+ CAN1->TID1 = message->id;
+ CAN1->TDA1 = data0;
+ CAN1->TDB1 = data1;
+ CAN1->CMR = 0x00000021;
+ printf("Writing 1\n");
+ return 0;
+ } else if(sr & 0x00000400) {
+ CAN1->TFI2 = IFx;
+ CAN1->TID2 = message->id;
+ CAN1->TDA2 = data0;
+ CAN1->TDB2 = data1;
+ CAN1->CMR = 0x00000041;
+ return 0;
+ } else if(sr & 0x00040000) {
+ CAN1->TFI3 = IFx;
+ CAN1->TID3 = message->id;
+ CAN1->TDA3 = data0;
+ CAN1->TDB3 = data1;
+ CAN1->CMR = 0x00000081;
+ return 0;
+ }
+ return 1;
+ }
+ return xQueueSend(CAN_tx_queue, message, 0) != pdPASS;
+}
+
+/**
+ * Get a CAN message, blocking if one isn't available.
+ * This is useful for a read/dispatch thread.
+ *
+ * \returns 0 on Success, and nonzero on failure
+ */
+int CAN_get(can_message *message) {
+ // Blocking read the queue.
+ if (xQueueReceive(CAN_rx_queue, message, portMAX_DELAY) == pdFALSE) {
+ return 1;
+ } else {
+ return message->error;
+ }
+}
+
+void CAN_IRQHandler(void) {
+ uint32_t interrupts = CAN1->ICR;
+ long lHigherPriorityTaskWoken = pdFALSE;
+ can_message message;
+ // CAN1->CMR contains all the action items, like initiating a send et all.
+ // On a bus error interrupt, set an error semaphore so the handler can set the LED, or set it ourselfs.
+ printf("CAN interrupt\n");
+
+ if (interrupts & 0x1) {
+ // Recieved a packet.
+ uint32_t rfs = CAN1->RFS;
+
+ message.RTR = (rfs & 0x40000000) >> 30;
+ message.length = (rfs & 0x000f0000) >> 16;
+ message.id = CAN1->RID & 0x000007ff;
+
+ message.wdata[0] = CAN1->RDA;
+ message.wdata[1] = CAN1->RDB;
+
+ // Release the registers
+ CAN1->CMR = 0x00000004;
+
+ message.error = 0;
+
+ xQueueSendFromISR(CAN_rx_queue, &message, &lHigherPriorityTaskWoken);
+ portEND_SWITCHING_ISR(lHigherPriorityTaskWoken);
+ return;
+ }
+
+ if (interrupts & 0x602) {
+ // TX buffers are no longer empty (now empty??)
+ if (xQueueReceiveFromISR(CAN_tx_queue, &message, &lHigherPriorityTaskWoken)) {
+ uint32_t IFx = (message.RTR << 30) +
+ (message.length << 16) +
+ (message.priority);
+ uint32_t data0 = message.wdata[0];
+ uint32_t data1 = message.wdata[1];
+
+ // Message was in the queue, and will now be sent.
+ if (interrupts & 0x2) {
+ // TX buffer 1 is no longer empty
+ CAN1->TFI1 = IFx;
+ CAN1->TID1 = message.id;
+ CAN1->TDA1 = data0;
+ CAN1->TDB1 = data1;
+ CAN1->CMR = 0x00000021;
+ } else if (interrupts & 0x200) {
+ // TX buffer 2 is no longer empty
+ CAN1->TFI2 = IFx;
+ CAN1->TID2 = message.id;
+ CAN1->TDA2 = data0;
+ CAN1->TDB2 = data1;
+ CAN1->CMR = 0x00000041;
+ } else if (interrupts & 0x400) {
+ // TX buffer 3 is no longer empty
+ CAN1->TFI3 = IFx;
+ CAN1->TID3 = message.id;
+ CAN1->TDA3 = data0;
+ CAN1->TDB3 = data1;
+ CAN1->CMR = 0x00000081;
+ }
+ }
+ portEND_SWITCHING_ISR(lHigherPriorityTaskWoken);
+ return;
+ }
+
+ if (interrupts & 0x4) {
+ // Error Warning interrupt
+ message.error = 0x01;
+ if (CAN1->GSR & 0x00000040) {
+ // Reached the limit.
+ message.error = 0x01;
+ } else if (CAN1->GSR & 0x00000080) {
+ // No longer allowed to send.
+ message.error = 0x20;
+ } else {
+ message.error = 0x20;
+ }
+ xQueueSendFromISR(CAN_rx_queue, &message, &lHigherPriorityTaskWoken);
+ portEND_SWITCHING_ISR(lHigherPriorityTaskWoken);
+ return;
+ }
+
+ if (interrupts & 0x8) {
+ // Data overrun
+ CAN1->CMR = 0x00000008;
+ message.error = 0x02;
+ xQueueSendFromISR(CAN_rx_queue, &message, &lHigherPriorityTaskWoken);
+ portEND_SWITCHING_ISR(lHigherPriorityTaskWoken);
+ return;
+ }
+
+ if (interrupts & 0x20) {
+ // Error Passive Interrupt
+ message.error = 0x04;
+ xQueueSendFromISR(CAN_rx_queue, &message, &lHigherPriorityTaskWoken);
+ portEND_SWITCHING_ISR(lHigherPriorityTaskWoken);
+ return;
+ }
+
+ if (interrupts & 0x80) {
+ // Bus Error Interrupt
+ message.error = 0x08;
+ xQueueSendFromISR(CAN_rx_queue, &message, &lHigherPriorityTaskWoken);
+ portEND_SWITCHING_ISR(lHigherPriorityTaskWoken);
+ return;
+ }
+ message.error = 0x10;
+ xQueueSendFromISR(CAN_rx_queue, &message, &lHigherPriorityTaskWoken);
+ portEND_SWITCHING_ISR(lHigherPriorityTaskWoken);
+}
+
+extern int VCOM_getchar(void);
+
+static portTASK_FUNCTION(vCAN1Write, pvParameters) {
+ can_message message;
+ message.RTR = 0;
+ message.id = 12;
+ message.priority = 1;
+ message.length = 4;
+
+ // Enable the pins.
+ PINCON->PINSEL3 = (PINCON->PINSEL3 & 0xffc3cf3f) | 0x00141040;
+
+ portTickType xLastFlashTime;
+ xLastFlashTime = xTaskGetTickCount();
+
+ for (;;) {
+ printf("hello\n");
+
+ int c = VCOM_getchar();
+ while (c != -1) {
+ printf("hello\n");
+ int j = c;
+ printf("Sending data 0x%x\n", j);
+ message.data[0] = j++;
+ message.data[1] = j++;
+ message.data[2] = j++;
+ message.data[3] = j;
+ CAN_send(&message);
+ c = VCOM_getchar();
+ }
+
+ vTaskDelayUntil(&xLastFlashTime, 500);
+ }
+}
+static portTASK_FUNCTION(vCAN1, pvParameters) {
+ portTickType xLastFlashTime;
+
+ CAN_rx_queue = xQueueCreate(20, sizeof(can_message));
+ CAN_tx_queue = xQueueCreate(5, sizeof(char));
+
+ if ((CAN_rx_queue == NULL) || (CAN_tx_queue == NULL)) {
+ /* Not enough heap available to create the buffer queues, can't do
+ * anything so just delete ourselves.
+ */
+ vTaskDelete(NULL);
+ }
+
+ // Enable CAN
+ SC->PCONP |= PCONP_PCCAN1;
+
+ PINCON->PINSEL0 = (PINCON->PINSEL0 & 0xfffffff0) | 0x00000005;
+ PINCON->PINMODE0 = (PINCON->PINMODE0 & 0xfffffffc) | 0x00000001;
+
+ // Enable RX, TX, overrun, Bus Error,
+ // Error Passive/Active, and Error Warning Interupts.
+ NVIC_SetPriority(CAN_IRQn, configCAN_INTERRUPT_PRIORITY);
+ NVIC_EnableIRQ(CAN_IRQn);
+
+ CAN1->IER = 0x000006af;
+
+ // Priority depends on the TX priority register
+ CAN1->MOD = 0x00000008;
+
+ CAN1->CMR = 0x00000004;
+
+ CANAF->AFMR = 0x00000002;
+
+ // CAN clocks. (Defaults look fine)
+
+ /* We need to initialise xLastFlashTime prior to the first call to
+ vTaskDelayUntil(). */
+ xLastFlashTime = xTaskGetTickCount();
+
+ can_message message;
+
+ xTaskCreate(vCAN1Write, (signed char *) "CAN1wx", configMINIMAL_STACK_SIZE + 100, NULL, tskIDLE_PRIORITY + 4, NULL);
+
+ for (;;) {
+ /* Delay for half the flash period then turn the LED on. */
+ if (CAN_get(&message)) {
+ printf("Message error 0x%x\n", message.error);
+ } else {
+ printf("Got a message with a length of %d\n", message.length);
+ printf("data[0] = 0x%x\n", message.data[0]);
+ printf("data[1] = 0x%x\n", message.data[1]);
+ printf("data[2] = 0x%x\n", message.data[2]);
+ printf("data[3] = 0x%x\n", message.data[3]);
+ }
+ }
+}
+
+
+void initCAN(void){
+ xTaskCreate(vCAN1, (signed char *) "CAN1rx", configMINIMAL_STACK_SIZE + 400, NULL, tskIDLE_PRIORITY + 1, NULL);
+}