Mouse code for the MacroRat

Dependencies:   ITG3200 QEI

Committer:
sahilmgandhi
Date:
Sat Jun 03 00:22:44 2017 +0000
Revision:
46:b156ef445742
Parent:
18:6a4db94011d3
Final code for internal battlebot competition.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
sahilmgandhi 18:6a4db94011d3 1 /* mbed Microcontroller Library
sahilmgandhi 18:6a4db94011d3 2 * Copyright (c) 2006-2013 ARM Limited
sahilmgandhi 18:6a4db94011d3 3 *
sahilmgandhi 18:6a4db94011d3 4 * Licensed under the Apache License, Version 2.0 (the "License");
sahilmgandhi 18:6a4db94011d3 5 * you may not use this file except in compliance with the License.
sahilmgandhi 18:6a4db94011d3 6 * You may obtain a copy of the License at
sahilmgandhi 18:6a4db94011d3 7 *
sahilmgandhi 18:6a4db94011d3 8 * http://www.apache.org/licenses/LICENSE-2.0
sahilmgandhi 18:6a4db94011d3 9 *
sahilmgandhi 18:6a4db94011d3 10 * Unless required by applicable law or agreed to in writing, software
sahilmgandhi 18:6a4db94011d3 11 * distributed under the License is distributed on an "AS IS" BASIS,
sahilmgandhi 18:6a4db94011d3 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
sahilmgandhi 18:6a4db94011d3 13 * See the License for the specific language governing permissions and
sahilmgandhi 18:6a4db94011d3 14 * limitations under the License.
sahilmgandhi 18:6a4db94011d3 15 */
sahilmgandhi 18:6a4db94011d3 16 #include "can_api.h"
sahilmgandhi 18:6a4db94011d3 17
sahilmgandhi 18:6a4db94011d3 18 #include "cmsis.h"
sahilmgandhi 18:6a4db94011d3 19 #include "mbed_error.h"
sahilmgandhi 18:6a4db94011d3 20
sahilmgandhi 18:6a4db94011d3 21 #include <math.h>
sahilmgandhi 18:6a4db94011d3 22 #include <string.h>
sahilmgandhi 18:6a4db94011d3 23
sahilmgandhi 18:6a4db94011d3 24 /* Handy defines */
sahilmgandhi 18:6a4db94011d3 25 #define MSG_OBJ_MAX 32
sahilmgandhi 18:6a4db94011d3 26 #define DLC_MAX 8
sahilmgandhi 18:6a4db94011d3 27
sahilmgandhi 18:6a4db94011d3 28 #define ID_STD_MASK 0x07FF
sahilmgandhi 18:6a4db94011d3 29 #define ID_EXT_MASK 0x1FFFFFFF
sahilmgandhi 18:6a4db94011d3 30 #define DLC_MASK 0x0F
sahilmgandhi 18:6a4db94011d3 31
sahilmgandhi 18:6a4db94011d3 32 static uint32_t can_irq_id = 0;
sahilmgandhi 18:6a4db94011d3 33 static can_irq_handler irq_handler;
sahilmgandhi 18:6a4db94011d3 34
sahilmgandhi 18:6a4db94011d3 35 static uint32_t can_disable(can_t *obj) {
sahilmgandhi 18:6a4db94011d3 36 uint32_t sm = LPC_CAN->CNTL;
sahilmgandhi 18:6a4db94011d3 37 LPC_CAN->CNTL |= CANCNTL_INIT;
sahilmgandhi 18:6a4db94011d3 38 return sm;
sahilmgandhi 18:6a4db94011d3 39 }
sahilmgandhi 18:6a4db94011d3 40
sahilmgandhi 18:6a4db94011d3 41 static inline void can_enable(can_t *obj) {
sahilmgandhi 18:6a4db94011d3 42 if (LPC_CAN->CNTL & CANCNTL_INIT) {
sahilmgandhi 18:6a4db94011d3 43 LPC_CAN->CNTL &= ~CANCNTL_INIT;
sahilmgandhi 18:6a4db94011d3 44 }
sahilmgandhi 18:6a4db94011d3 45 }
sahilmgandhi 18:6a4db94011d3 46
sahilmgandhi 18:6a4db94011d3 47 int can_mode(can_t *obj, CanMode mode) {
sahilmgandhi 18:6a4db94011d3 48 int success = 0;
sahilmgandhi 18:6a4db94011d3 49 switch (mode) {
sahilmgandhi 18:6a4db94011d3 50 case MODE_RESET:
sahilmgandhi 18:6a4db94011d3 51 LPC_CAN->CNTL &=~CANCNTL_TEST;
sahilmgandhi 18:6a4db94011d3 52 can_disable(obj);
sahilmgandhi 18:6a4db94011d3 53 success = 1;
sahilmgandhi 18:6a4db94011d3 54 break;
sahilmgandhi 18:6a4db94011d3 55 case MODE_NORMAL:
sahilmgandhi 18:6a4db94011d3 56 LPC_CAN->CNTL &=~CANCNTL_TEST;
sahilmgandhi 18:6a4db94011d3 57 can_enable(obj);
sahilmgandhi 18:6a4db94011d3 58 success = 1;
sahilmgandhi 18:6a4db94011d3 59 break;
sahilmgandhi 18:6a4db94011d3 60 case MODE_SILENT:
sahilmgandhi 18:6a4db94011d3 61 LPC_CAN->CNTL |= CANCNTL_TEST;
sahilmgandhi 18:6a4db94011d3 62 LPC_CAN->TEST |= CANTEST_SILENT;
sahilmgandhi 18:6a4db94011d3 63 LPC_CAN->TEST &=~CANTEST_LBACK;
sahilmgandhi 18:6a4db94011d3 64 success = 1;
sahilmgandhi 18:6a4db94011d3 65 break;
sahilmgandhi 18:6a4db94011d3 66 case MODE_TEST_LOCAL:
sahilmgandhi 18:6a4db94011d3 67 LPC_CAN->CNTL |= CANCNTL_TEST;
sahilmgandhi 18:6a4db94011d3 68 LPC_CAN->TEST &=~CANTEST_SILENT;
sahilmgandhi 18:6a4db94011d3 69 LPC_CAN->TEST |= CANTEST_LBACK;
sahilmgandhi 18:6a4db94011d3 70 success = 1;
sahilmgandhi 18:6a4db94011d3 71 break;
sahilmgandhi 18:6a4db94011d3 72 case MODE_TEST_SILENT:
sahilmgandhi 18:6a4db94011d3 73 LPC_CAN->CNTL |= CANCNTL_TEST;
sahilmgandhi 18:6a4db94011d3 74 LPC_CAN->TEST |= (CANTEST_LBACK | CANTEST_SILENT);
sahilmgandhi 18:6a4db94011d3 75 success = 1;
sahilmgandhi 18:6a4db94011d3 76 break;
sahilmgandhi 18:6a4db94011d3 77 case MODE_TEST_GLOBAL:
sahilmgandhi 18:6a4db94011d3 78 default:
sahilmgandhi 18:6a4db94011d3 79 success = 0;
sahilmgandhi 18:6a4db94011d3 80 break;
sahilmgandhi 18:6a4db94011d3 81 }
sahilmgandhi 18:6a4db94011d3 82
sahilmgandhi 18:6a4db94011d3 83 return success;
sahilmgandhi 18:6a4db94011d3 84 }
sahilmgandhi 18:6a4db94011d3 85
sahilmgandhi 18:6a4db94011d3 86 int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t handle) {
sahilmgandhi 18:6a4db94011d3 87 uint16_t i;
sahilmgandhi 18:6a4db94011d3 88
sahilmgandhi 18:6a4db94011d3 89 // Find first free message object
sahilmgandhi 18:6a4db94011d3 90 if(handle == 0) {
sahilmgandhi 18:6a4db94011d3 91 uint32_t msgval = LPC_CAN->MSGV1 | (LPC_CAN->MSGV2 << 16);
sahilmgandhi 18:6a4db94011d3 92 // Find first free messagebox
sahilmgandhi 18:6a4db94011d3 93 for(i = 0; i < 32; i++) {
sahilmgandhi 18:6a4db94011d3 94 if((msgval & (1 << i)) == 0) {
sahilmgandhi 18:6a4db94011d3 95 handle = i+1;
sahilmgandhi 18:6a4db94011d3 96 break;
sahilmgandhi 18:6a4db94011d3 97 }
sahilmgandhi 18:6a4db94011d3 98 }
sahilmgandhi 18:6a4db94011d3 99 }
sahilmgandhi 18:6a4db94011d3 100
sahilmgandhi 18:6a4db94011d3 101 if(handle > 0 && handle < 32) {
sahilmgandhi 18:6a4db94011d3 102 if(format == CANExtended) {
sahilmgandhi 18:6a4db94011d3 103 // Mark message valid, Direction = TX, Extended Frame, Set Identifier and mask everything
sahilmgandhi 18:6a4db94011d3 104 LPC_CAN->IF1_ARB1 = BFN_PREP(id, CANIFn_ARB1_ID);
sahilmgandhi 18:6a4db94011d3 105 LPC_CAN->IF1_ARB2 = CANIFn_ARB2_MSGVAL | CANIFn_ARB2_XTD | BFN_PREP(id >> 16, CANIFn_ARB2_ID);
sahilmgandhi 18:6a4db94011d3 106 LPC_CAN->IF1_MSK1 = BFN_PREP(mask, CANIFn_MSK1_MSK);
sahilmgandhi 18:6a4db94011d3 107 LPC_CAN->IF1_MSK2 = CANIFn_MSK2_MXTD /* | CANIFn_MSK2_MDIR */ | BFN_PREP(mask >> 16, CANIFn_MSK2_MSK);
sahilmgandhi 18:6a4db94011d3 108 }
sahilmgandhi 18:6a4db94011d3 109 else {
sahilmgandhi 18:6a4db94011d3 110 // Mark message valid, Direction = TX, Set Identifier and mask everything
sahilmgandhi 18:6a4db94011d3 111 LPC_CAN->IF1_ARB2 = CANIFn_ARB2_MSGVAL | BFN_PREP(id << 2, CANIFn_ARB2_ID);
sahilmgandhi 18:6a4db94011d3 112 LPC_CAN->IF1_MSK2 = /* CANIFn_MSK2_MDIR | */ BFN_PREP(mask << 2, CANIFn_MSK2_MSK);
sahilmgandhi 18:6a4db94011d3 113 }
sahilmgandhi 18:6a4db94011d3 114
sahilmgandhi 18:6a4db94011d3 115 // Use mask, single message object and set DLC
sahilmgandhi 18:6a4db94011d3 116 LPC_CAN->IF1_MCTRL = CANIFn_MCTRL_UMASK | CANIFn_MCTRL_EOB | CANIFn_MCTRL_RXIE | BFN_PREP(DLC_MAX, CANIFn_MCTRL_DLC);
sahilmgandhi 18:6a4db94011d3 117
sahilmgandhi 18:6a4db94011d3 118 // Transfer all fields to message object
sahilmgandhi 18:6a4db94011d3 119 LPC_CAN->IF1_CMDMSK = CANIFn_CMDMSK_WR | CANIFn_CMDMSK_MASK | CANIFn_CMDMSK_ARB | CANIFn_CMDMSK_CTRL;
sahilmgandhi 18:6a4db94011d3 120
sahilmgandhi 18:6a4db94011d3 121 // Start Transfer to given message number
sahilmgandhi 18:6a4db94011d3 122 LPC_CAN->IF1_CMDREQ = BFN_PREP(handle, CANIFn_CMDREQ_MN);
sahilmgandhi 18:6a4db94011d3 123
sahilmgandhi 18:6a4db94011d3 124 // Wait until transfer to message ram complete - TODO: maybe not block??
sahilmgandhi 18:6a4db94011d3 125 while( LPC_CAN->IF1_CMDREQ & CANIFn_CMDREQ_BUSY );
sahilmgandhi 18:6a4db94011d3 126 }
sahilmgandhi 18:6a4db94011d3 127
sahilmgandhi 18:6a4db94011d3 128 return handle;
sahilmgandhi 18:6a4db94011d3 129 }
sahilmgandhi 18:6a4db94011d3 130
sahilmgandhi 18:6a4db94011d3 131 static inline void can_irq() {
sahilmgandhi 18:6a4db94011d3 132 irq_handler(can_irq_id, IRQ_RX);
sahilmgandhi 18:6a4db94011d3 133 }
sahilmgandhi 18:6a4db94011d3 134
sahilmgandhi 18:6a4db94011d3 135 // Register CAN object's irq handler
sahilmgandhi 18:6a4db94011d3 136 void can_irq_init(can_t *obj, can_irq_handler handler, uint32_t id) {
sahilmgandhi 18:6a4db94011d3 137 irq_handler = handler;
sahilmgandhi 18:6a4db94011d3 138 can_irq_id = id;
sahilmgandhi 18:6a4db94011d3 139 }
sahilmgandhi 18:6a4db94011d3 140
sahilmgandhi 18:6a4db94011d3 141 // Unregister CAN object's irq handler
sahilmgandhi 18:6a4db94011d3 142 void can_irq_free(can_t *obj) {
sahilmgandhi 18:6a4db94011d3 143 LPC_CAN->CNTL &= ~CANCNTL_IE; // Disable Interrupts :)
sahilmgandhi 18:6a4db94011d3 144
sahilmgandhi 18:6a4db94011d3 145 can_irq_id = 0;
sahilmgandhi 18:6a4db94011d3 146 NVIC_DisableIRQ(CAN_IRQn);
sahilmgandhi 18:6a4db94011d3 147 }
sahilmgandhi 18:6a4db94011d3 148
sahilmgandhi 18:6a4db94011d3 149 // Clear or set a irq
sahilmgandhi 18:6a4db94011d3 150 void can_irq_set(can_t *obj, CanIrqType type, uint32_t enable) {
sahilmgandhi 18:6a4db94011d3 151 // Put CAN in Reset Mode and enable interrupt
sahilmgandhi 18:6a4db94011d3 152 can_disable(obj);
sahilmgandhi 18:6a4db94011d3 153 if(enable == 0) {
sahilmgandhi 18:6a4db94011d3 154 LPC_CAN->CNTL &= ~(CANCNTL_IE | CANCNTL_SIE);
sahilmgandhi 18:6a4db94011d3 155 }
sahilmgandhi 18:6a4db94011d3 156 else {
sahilmgandhi 18:6a4db94011d3 157 LPC_CAN->CNTL |= CANCNTL_IE | CANCNTL_SIE;
sahilmgandhi 18:6a4db94011d3 158 }
sahilmgandhi 18:6a4db94011d3 159 // Take it out of reset...
sahilmgandhi 18:6a4db94011d3 160 can_enable(obj);
sahilmgandhi 18:6a4db94011d3 161
sahilmgandhi 18:6a4db94011d3 162 // Enable NVIC if at least 1 interrupt is active
sahilmgandhi 18:6a4db94011d3 163 NVIC_SetVector(CAN_IRQn, (uint32_t) &can_irq);
sahilmgandhi 18:6a4db94011d3 164 NVIC_EnableIRQ(CAN_IRQn);
sahilmgandhi 18:6a4db94011d3 165 }
sahilmgandhi 18:6a4db94011d3 166
sahilmgandhi 18:6a4db94011d3 167 // This table has the sampling points as close to 75% as possible. The first
sahilmgandhi 18:6a4db94011d3 168 // value is TSEG1, the second TSEG2.
sahilmgandhi 18:6a4db94011d3 169 static const int timing_pts[23][2] = {
sahilmgandhi 18:6a4db94011d3 170 {0x0, 0x0}, // 2, 50%
sahilmgandhi 18:6a4db94011d3 171 {0x1, 0x0}, // 3, 67%
sahilmgandhi 18:6a4db94011d3 172 {0x2, 0x0}, // 4, 75%
sahilmgandhi 18:6a4db94011d3 173 {0x3, 0x0}, // 5, 80%
sahilmgandhi 18:6a4db94011d3 174 {0x3, 0x1}, // 6, 67%
sahilmgandhi 18:6a4db94011d3 175 {0x4, 0x1}, // 7, 71%
sahilmgandhi 18:6a4db94011d3 176 {0x5, 0x1}, // 8, 75%
sahilmgandhi 18:6a4db94011d3 177 {0x6, 0x1}, // 9, 78%
sahilmgandhi 18:6a4db94011d3 178 {0x6, 0x2}, // 10, 70%
sahilmgandhi 18:6a4db94011d3 179 {0x7, 0x2}, // 11, 73%
sahilmgandhi 18:6a4db94011d3 180 {0x8, 0x2}, // 12, 75%
sahilmgandhi 18:6a4db94011d3 181 {0x9, 0x2}, // 13, 77%
sahilmgandhi 18:6a4db94011d3 182 {0x9, 0x3}, // 14, 71%
sahilmgandhi 18:6a4db94011d3 183 {0xA, 0x3}, // 15, 73%
sahilmgandhi 18:6a4db94011d3 184 {0xB, 0x3}, // 16, 75%
sahilmgandhi 18:6a4db94011d3 185 {0xC, 0x3}, // 17, 76%
sahilmgandhi 18:6a4db94011d3 186 {0xD, 0x3}, // 18, 78%
sahilmgandhi 18:6a4db94011d3 187 {0xD, 0x4}, // 19, 74%
sahilmgandhi 18:6a4db94011d3 188 {0xE, 0x4}, // 20, 75%
sahilmgandhi 18:6a4db94011d3 189 {0xF, 0x4}, // 21, 76%
sahilmgandhi 18:6a4db94011d3 190 {0xF, 0x5}, // 22, 73%
sahilmgandhi 18:6a4db94011d3 191 {0xF, 0x6}, // 23, 70%
sahilmgandhi 18:6a4db94011d3 192 {0xF, 0x7}, // 24, 67%
sahilmgandhi 18:6a4db94011d3 193 };
sahilmgandhi 18:6a4db94011d3 194
sahilmgandhi 18:6a4db94011d3 195 static unsigned int can_speed(unsigned int sclk, unsigned int cclk, unsigned char psjw) {
sahilmgandhi 18:6a4db94011d3 196 uint32_t btr;
sahilmgandhi 18:6a4db94011d3 197 uint32_t clkdiv = 1;
sahilmgandhi 18:6a4db94011d3 198 uint16_t brp = 0;
sahilmgandhi 18:6a4db94011d3 199 uint32_t calcbit;
sahilmgandhi 18:6a4db94011d3 200 uint32_t bitwidth;
sahilmgandhi 18:6a4db94011d3 201 int hit = 0;
sahilmgandhi 18:6a4db94011d3 202 int bits = 0;
sahilmgandhi 18:6a4db94011d3 203
sahilmgandhi 18:6a4db94011d3 204 bitwidth = sclk / cclk;
sahilmgandhi 18:6a4db94011d3 205
sahilmgandhi 18:6a4db94011d3 206 brp = bitwidth / 0x18;
sahilmgandhi 18:6a4db94011d3 207 while ((!hit) && (brp < bitwidth / 4)) {
sahilmgandhi 18:6a4db94011d3 208 brp++;
sahilmgandhi 18:6a4db94011d3 209 for (bits = 22; bits > 0; bits--) {
sahilmgandhi 18:6a4db94011d3 210 calcbit = (bits + 3) * (brp + 1);
sahilmgandhi 18:6a4db94011d3 211 if (calcbit == bitwidth) {
sahilmgandhi 18:6a4db94011d3 212 hit = 1;
sahilmgandhi 18:6a4db94011d3 213 break;
sahilmgandhi 18:6a4db94011d3 214 }
sahilmgandhi 18:6a4db94011d3 215 }
sahilmgandhi 18:6a4db94011d3 216 }
sahilmgandhi 18:6a4db94011d3 217
sahilmgandhi 18:6a4db94011d3 218 /* This might be funky
sahilmgandhi 18:6a4db94011d3 219 while(btr > 63 && clkdiv < 16) {
sahilmgandhi 18:6a4db94011d3 220 btr = btr / 2;
sahilmgandhi 18:6a4db94011d3 221 clkdiv = clkdiv * 2;
sahilmgandhi 18:6a4db94011d3 222 }
sahilmgandhi 18:6a4db94011d3 223 */
sahilmgandhi 18:6a4db94011d3 224 clkdiv = clkdiv - 1;
sahilmgandhi 18:6a4db94011d3 225
sahilmgandhi 18:6a4db94011d3 226 if (hit) {
sahilmgandhi 18:6a4db94011d3 227 btr = BFN_PREP(timing_pts[bits][1], CANBT_TSEG2)
sahilmgandhi 18:6a4db94011d3 228 | BFN_PREP(timing_pts[bits][0], CANBT_TSEG1)
sahilmgandhi 18:6a4db94011d3 229 | BFN_PREP(psjw, CANBT_SJW)
sahilmgandhi 18:6a4db94011d3 230 | BFN_PREP(brp, CANBT_BRP);
sahilmgandhi 18:6a4db94011d3 231 btr = btr | (clkdiv << 16);
sahilmgandhi 18:6a4db94011d3 232
sahilmgandhi 18:6a4db94011d3 233 } else {
sahilmgandhi 18:6a4db94011d3 234 btr = 0;
sahilmgandhi 18:6a4db94011d3 235 }
sahilmgandhi 18:6a4db94011d3 236
sahilmgandhi 18:6a4db94011d3 237 return btr;
sahilmgandhi 18:6a4db94011d3 238 }
sahilmgandhi 18:6a4db94011d3 239
sahilmgandhi 18:6a4db94011d3 240
sahilmgandhi 18:6a4db94011d3 241 int can_config_rxmsgobj(can_t *obj) {
sahilmgandhi 18:6a4db94011d3 242 uint16_t i = 0;
sahilmgandhi 18:6a4db94011d3 243
sahilmgandhi 18:6a4db94011d3 244 // Make sure the interface is available
sahilmgandhi 18:6a4db94011d3 245 //while( LPC_CAN->IF1_CMDREQ & CANIFn_CMDREQ_BUSY );
sahilmgandhi 18:6a4db94011d3 246
sahilmgandhi 18:6a4db94011d3 247 // Mark message valid, Direction = RX, Don't care about anything else
sahilmgandhi 18:6a4db94011d3 248 LPC_CAN->IF1_ARB1 = 0;
sahilmgandhi 18:6a4db94011d3 249 LPC_CAN->IF1_ARB2 = 0;
sahilmgandhi 18:6a4db94011d3 250 LPC_CAN->IF1_MCTRL = 0;
sahilmgandhi 18:6a4db94011d3 251
sahilmgandhi 18:6a4db94011d3 252 for ( i = 0; i < MSG_OBJ_MAX; i++ )
sahilmgandhi 18:6a4db94011d3 253 {
sahilmgandhi 18:6a4db94011d3 254 // Transfer arb and control fields to message object
sahilmgandhi 18:6a4db94011d3 255 LPC_CAN->IF1_CMDMSK = CANIFn_CMDMSK_WR | CANIFn_CMDMSK_ARB | CANIFn_CMDMSK_CTRL | CANIFn_CMDMSK_TXRQST;
sahilmgandhi 18:6a4db94011d3 256
sahilmgandhi 18:6a4db94011d3 257 // Start Transfer to given message number
sahilmgandhi 18:6a4db94011d3 258 LPC_CAN->IF1_CMDREQ = BFN_PREP(i, CANIFn_CMDREQ_MN);
sahilmgandhi 18:6a4db94011d3 259
sahilmgandhi 18:6a4db94011d3 260 // Wait until transfer to message ram complete - TODO: maybe not block??
sahilmgandhi 18:6a4db94011d3 261 while( LPC_CAN->IF1_CMDREQ & CANIFn_CMDREQ_BUSY );
sahilmgandhi 18:6a4db94011d3 262 }
sahilmgandhi 18:6a4db94011d3 263
sahilmgandhi 18:6a4db94011d3 264 // Accept all messages
sahilmgandhi 18:6a4db94011d3 265 can_filter(obj, 0, 0, CANStandard, 1);
sahilmgandhi 18:6a4db94011d3 266
sahilmgandhi 18:6a4db94011d3 267 return 1;
sahilmgandhi 18:6a4db94011d3 268 }
sahilmgandhi 18:6a4db94011d3 269
sahilmgandhi 18:6a4db94011d3 270
sahilmgandhi 18:6a4db94011d3 271 void can_init(can_t *obj, PinName rd, PinName td) {
sahilmgandhi 18:6a4db94011d3 272 // Enable power and clock
sahilmgandhi 18:6a4db94011d3 273 LPC_SYSCON->PRESETCTRL |= PRESETCTRL_CAN_RST_N;
sahilmgandhi 18:6a4db94011d3 274 LPC_SYSCON->SYSAHBCLKCTRL |= SYSAHBCLKCTRL_CAN;
sahilmgandhi 18:6a4db94011d3 275
sahilmgandhi 18:6a4db94011d3 276 // Enable Initialization mode
sahilmgandhi 18:6a4db94011d3 277 if (!(LPC_CAN->CNTL & CANCNTL_INIT)) {
sahilmgandhi 18:6a4db94011d3 278 LPC_CAN->CNTL |= CANCNTL_INIT;
sahilmgandhi 18:6a4db94011d3 279 }
sahilmgandhi 18:6a4db94011d3 280
sahilmgandhi 18:6a4db94011d3 281 can_frequency(obj, 125000);
sahilmgandhi 18:6a4db94011d3 282
sahilmgandhi 18:6a4db94011d3 283 // Resume operation
sahilmgandhi 18:6a4db94011d3 284 LPC_CAN->CNTL &= ~CANCNTL_INIT;
sahilmgandhi 18:6a4db94011d3 285 while ( LPC_CAN->CNTL & CANCNTL_INIT );
sahilmgandhi 18:6a4db94011d3 286
sahilmgandhi 18:6a4db94011d3 287 // Initialize RX message object
sahilmgandhi 18:6a4db94011d3 288 can_config_rxmsgobj(obj);
sahilmgandhi 18:6a4db94011d3 289 }
sahilmgandhi 18:6a4db94011d3 290
sahilmgandhi 18:6a4db94011d3 291 void can_free(can_t *obj) {
sahilmgandhi 18:6a4db94011d3 292 LPC_SYSCON->SYSAHBCLKCTRL &= ~(SYSAHBCLKCTRL_CAN);
sahilmgandhi 18:6a4db94011d3 293 LPC_SYSCON->PRESETCTRL &= ~(PRESETCTRL_CAN_RST_N);
sahilmgandhi 18:6a4db94011d3 294 }
sahilmgandhi 18:6a4db94011d3 295
sahilmgandhi 18:6a4db94011d3 296 int can_frequency(can_t *obj, int f) {
sahilmgandhi 18:6a4db94011d3 297 int btr = can_speed(SystemCoreClock, (unsigned int)f, 1);
sahilmgandhi 18:6a4db94011d3 298 int clkdiv = (btr >> 16) & 0x0F;
sahilmgandhi 18:6a4db94011d3 299 btr = btr & 0xFFFF;
sahilmgandhi 18:6a4db94011d3 300
sahilmgandhi 18:6a4db94011d3 301 if (btr > 0) {
sahilmgandhi 18:6a4db94011d3 302 uint32_t cntl_init = LPC_CAN->CNTL | CANCNTL_INIT;
sahilmgandhi 18:6a4db94011d3 303 // Set the bit clock
sahilmgandhi 18:6a4db94011d3 304 LPC_CAN->CNTL |= CANCNTL_CCE | CANCNTL_INIT;
sahilmgandhi 18:6a4db94011d3 305 LPC_CAN->CLKDIV = clkdiv;
sahilmgandhi 18:6a4db94011d3 306 LPC_CAN->BT = btr;
sahilmgandhi 18:6a4db94011d3 307 LPC_CAN->BRPE = 0x0000;
sahilmgandhi 18:6a4db94011d3 308 LPC_CAN->CNTL &= ~(CANCNTL_CCE | CANCNTL_INIT);
sahilmgandhi 18:6a4db94011d3 309 LPC_CAN->CNTL |= cntl_init;
sahilmgandhi 18:6a4db94011d3 310 return 1;
sahilmgandhi 18:6a4db94011d3 311 }
sahilmgandhi 18:6a4db94011d3 312 return 0;
sahilmgandhi 18:6a4db94011d3 313 }
sahilmgandhi 18:6a4db94011d3 314
sahilmgandhi 18:6a4db94011d3 315 int can_write(can_t *obj, CAN_Message msg, int cc) {
sahilmgandhi 18:6a4db94011d3 316 uint16_t msgnum = 0;
sahilmgandhi 18:6a4db94011d3 317
sahilmgandhi 18:6a4db94011d3 318 // Make sure controller is enabled
sahilmgandhi 18:6a4db94011d3 319 can_enable(obj);
sahilmgandhi 18:6a4db94011d3 320
sahilmgandhi 18:6a4db94011d3 321 // Make sure the interface is available
sahilmgandhi 18:6a4db94011d3 322 while( LPC_CAN->IF1_CMDREQ & CANIFn_CMDREQ_BUSY );
sahilmgandhi 18:6a4db94011d3 323
sahilmgandhi 18:6a4db94011d3 324 // Set the direction bit based on the message type
sahilmgandhi 18:6a4db94011d3 325 uint32_t direction = 0;
sahilmgandhi 18:6a4db94011d3 326 if (msg.type == CANData) {
sahilmgandhi 18:6a4db94011d3 327 direction = CANIFn_ARB2_DIR;
sahilmgandhi 18:6a4db94011d3 328 }
sahilmgandhi 18:6a4db94011d3 329
sahilmgandhi 18:6a4db94011d3 330 if(msg.format == CANExtended) {
sahilmgandhi 18:6a4db94011d3 331 // Mark message valid, Extended Frame, Set Identifier and mask everything
sahilmgandhi 18:6a4db94011d3 332 LPC_CAN->IF1_ARB1 = BFN_PREP(msg.id, CANIFn_ARB1_ID);
sahilmgandhi 18:6a4db94011d3 333 LPC_CAN->IF1_ARB2 = CANIFn_ARB2_MSGVAL | CANIFn_ARB2_XTD | direction | BFN_PREP(msg.id >> 16, CANIFn_ARB2_ID);
sahilmgandhi 18:6a4db94011d3 334 LPC_CAN->IF1_MSK1 = BFN_PREP(ID_EXT_MASK, CANIFn_MSK1_MSK);
sahilmgandhi 18:6a4db94011d3 335 LPC_CAN->IF1_MSK2 = CANIFn_MSK2_MXTD | CANIFn_MSK2_MDIR | BFN_PREP(ID_EXT_MASK >> 16, CANIFn_MSK2_MSK);
sahilmgandhi 18:6a4db94011d3 336 }
sahilmgandhi 18:6a4db94011d3 337 else {
sahilmgandhi 18:6a4db94011d3 338 // Mark message valid, Set Identifier and mask everything
sahilmgandhi 18:6a4db94011d3 339 LPC_CAN->IF1_ARB2 = CANIFn_ARB2_MSGVAL | direction | BFN_PREP(msg.id << 2, CANIFn_ARB2_ID);
sahilmgandhi 18:6a4db94011d3 340 LPC_CAN->IF1_MSK2 = CANIFn_MSK2_MDIR | BFN_PREP(ID_STD_MASK << 2, CANIFn_MSK2_MSK);
sahilmgandhi 18:6a4db94011d3 341 }
sahilmgandhi 18:6a4db94011d3 342
sahilmgandhi 18:6a4db94011d3 343 // Use mask, request transmission, single message object and set DLC
sahilmgandhi 18:6a4db94011d3 344 LPC_CAN->IF1_MCTRL = CANIFn_MCTRL_UMASK | CANIFn_MCTRL_TXRQST | CANIFn_MCTRL_EOB | BFN_PREP(msg.len, CANIFn_MCTRL_DLC);
sahilmgandhi 18:6a4db94011d3 345
sahilmgandhi 18:6a4db94011d3 346 LPC_CAN->IF1_DA1 = BFN_PREP(msg.data[1], CANIFn_DA1_DATA1) | BFN_PREP(msg.data[0], CANIFn_DA1_DATA0);
sahilmgandhi 18:6a4db94011d3 347 LPC_CAN->IF1_DA2 = BFN_PREP(msg.data[3], CANIFn_DA2_DATA3) | BFN_PREP(msg.data[2], CANIFn_DA2_DATA2);
sahilmgandhi 18:6a4db94011d3 348 LPC_CAN->IF1_DB1 = BFN_PREP(msg.data[5], CANIFn_DB1_DATA5) | BFN_PREP(msg.data[4], CANIFn_DB1_DATA4);
sahilmgandhi 18:6a4db94011d3 349 LPC_CAN->IF1_DB2 = BFN_PREP(msg.data[7], CANIFn_DB2_DATA7) | BFN_PREP(msg.data[6], CANIFn_DB2_DATA6);
sahilmgandhi 18:6a4db94011d3 350
sahilmgandhi 18:6a4db94011d3 351 // Transfer all fields to message object
sahilmgandhi 18:6a4db94011d3 352 LPC_CAN->IF1_CMDMSK = CANIFn_CMDMSK_WR | CANIFn_CMDMSK_MASK | CANIFn_CMDMSK_ARB | CANIFn_CMDMSK_CTRL | CANIFn_CMDMSK_TXRQST | CANIFn_CMDMSK_DATA_A | CANIFn_CMDMSK_DATA_B;
sahilmgandhi 18:6a4db94011d3 353
sahilmgandhi 18:6a4db94011d3 354 // Start Transfer to given message number
sahilmgandhi 18:6a4db94011d3 355 LPC_CAN->IF1_CMDREQ = BFN_PREP(msgnum, CANIFn_CMDREQ_MN);
sahilmgandhi 18:6a4db94011d3 356
sahilmgandhi 18:6a4db94011d3 357 // Wait until transfer to message ram complete - TODO: maybe not block??
sahilmgandhi 18:6a4db94011d3 358 while( LPC_CAN->IF1_CMDREQ & CANIFn_CMDREQ_BUSY);
sahilmgandhi 18:6a4db94011d3 359
sahilmgandhi 18:6a4db94011d3 360 // Wait until TXOK is set, then clear it - TODO: maybe not block
sahilmgandhi 18:6a4db94011d3 361 //while( !(LPC_CAN->STAT & CANSTAT_TXOK) );
sahilmgandhi 18:6a4db94011d3 362 LPC_CAN->STAT &= ~(CANSTAT_TXOK);
sahilmgandhi 18:6a4db94011d3 363
sahilmgandhi 18:6a4db94011d3 364 return 1;
sahilmgandhi 18:6a4db94011d3 365 }
sahilmgandhi 18:6a4db94011d3 366
sahilmgandhi 18:6a4db94011d3 367 int can_read(can_t *obj, CAN_Message *msg, int handle) {
sahilmgandhi 18:6a4db94011d3 368 uint16_t i;
sahilmgandhi 18:6a4db94011d3 369
sahilmgandhi 18:6a4db94011d3 370 // Make sure controller is enabled
sahilmgandhi 18:6a4db94011d3 371 can_enable(obj);
sahilmgandhi 18:6a4db94011d3 372
sahilmgandhi 18:6a4db94011d3 373 // Find first message object with new data
sahilmgandhi 18:6a4db94011d3 374 if(handle == 0) {
sahilmgandhi 18:6a4db94011d3 375 uint32_t newdata = LPC_CAN->ND1 | (LPC_CAN->ND2 << 16);
sahilmgandhi 18:6a4db94011d3 376 // Find first free messagebox
sahilmgandhi 18:6a4db94011d3 377 for(i = 0; i < 32; i++) {
sahilmgandhi 18:6a4db94011d3 378 if(newdata & (1 << i)) {
sahilmgandhi 18:6a4db94011d3 379 handle = i+1;
sahilmgandhi 18:6a4db94011d3 380 break;
sahilmgandhi 18:6a4db94011d3 381 }
sahilmgandhi 18:6a4db94011d3 382 }
sahilmgandhi 18:6a4db94011d3 383 }
sahilmgandhi 18:6a4db94011d3 384
sahilmgandhi 18:6a4db94011d3 385 if(handle > 0 && handle < 32) {
sahilmgandhi 18:6a4db94011d3 386 // Wait until message interface is free
sahilmgandhi 18:6a4db94011d3 387 while( LPC_CAN->IF2_CMDREQ & CANIFn_CMDREQ_BUSY );
sahilmgandhi 18:6a4db94011d3 388
sahilmgandhi 18:6a4db94011d3 389 // Transfer all fields to message object
sahilmgandhi 18:6a4db94011d3 390 LPC_CAN->IF2_CMDMSK = CANIFn_CMDMSK_RD | CANIFn_CMDMSK_MASK | CANIFn_CMDMSK_ARB | CANIFn_CMDMSK_CTRL | CANIFn_CMDMSK_CLRINTPND | CANIFn_CMDMSK_TXRQST | CANIFn_CMDMSK_DATA_A | CANIFn_CMDMSK_DATA_B;
sahilmgandhi 18:6a4db94011d3 391
sahilmgandhi 18:6a4db94011d3 392 // Start Transfer from given message number
sahilmgandhi 18:6a4db94011d3 393 LPC_CAN->IF2_CMDREQ = BFN_PREP(handle, CANIFn_CMDREQ_MN);
sahilmgandhi 18:6a4db94011d3 394
sahilmgandhi 18:6a4db94011d3 395 // Wait until transfer to message ram complete
sahilmgandhi 18:6a4db94011d3 396 while( LPC_CAN->IF2_CMDREQ & CANIFn_CMDREQ_BUSY );
sahilmgandhi 18:6a4db94011d3 397
sahilmgandhi 18:6a4db94011d3 398 if (LPC_CAN->IF2_ARB2 & CANIFn_ARB2_XTD) {
sahilmgandhi 18:6a4db94011d3 399 msg->format = CANExtended;
sahilmgandhi 18:6a4db94011d3 400 msg->id = (LPC_CAN->IF2_ARB1 & CANIFn_ARB2_ID_MASK) << 16;
sahilmgandhi 18:6a4db94011d3 401 msg->id |= (LPC_CAN->IF2_ARB2 & CANIFn_ARB2_ID_MASK);
sahilmgandhi 18:6a4db94011d3 402 }
sahilmgandhi 18:6a4db94011d3 403 else {
sahilmgandhi 18:6a4db94011d3 404 msg->format = CANStandard;
sahilmgandhi 18:6a4db94011d3 405 msg->id = (LPC_CAN->IF2_ARB2 & CANIFn_ARB2_ID_MASK) >> 2;
sahilmgandhi 18:6a4db94011d3 406 }
sahilmgandhi 18:6a4db94011d3 407
sahilmgandhi 18:6a4db94011d3 408 if (LPC_CAN->IF2_ARB2 & CANIFn_ARB2_DIR) {
sahilmgandhi 18:6a4db94011d3 409 msg->type = CANRemote;
sahilmgandhi 18:6a4db94011d3 410 }
sahilmgandhi 18:6a4db94011d3 411 else {
sahilmgandhi 18:6a4db94011d3 412 msg->type = CANData;
sahilmgandhi 18:6a4db94011d3 413 }
sahilmgandhi 18:6a4db94011d3 414
sahilmgandhi 18:6a4db94011d3 415 msg->len = BFN_GET(LPC_CAN->IF2_MCTRL, CANIFn_MCTRL_DLC); // TODO: If > 8, len = 8
sahilmgandhi 18:6a4db94011d3 416 msg->data[0] = BFN_GET(LPC_CAN->IF2_DA1, CANIFn_DA1_DATA0);
sahilmgandhi 18:6a4db94011d3 417 msg->data[1] = BFN_GET(LPC_CAN->IF2_DA1, CANIFn_DA1_DATA1);
sahilmgandhi 18:6a4db94011d3 418 msg->data[2] = BFN_GET(LPC_CAN->IF2_DA2, CANIFn_DA2_DATA2);
sahilmgandhi 18:6a4db94011d3 419 msg->data[3] = BFN_GET(LPC_CAN->IF2_DA2, CANIFn_DA2_DATA3);
sahilmgandhi 18:6a4db94011d3 420 msg->data[4] = BFN_GET(LPC_CAN->IF2_DB1, CANIFn_DB1_DATA4);
sahilmgandhi 18:6a4db94011d3 421 msg->data[5] = BFN_GET(LPC_CAN->IF2_DB1, CANIFn_DB1_DATA5);
sahilmgandhi 18:6a4db94011d3 422 msg->data[6] = BFN_GET(LPC_CAN->IF2_DB2, CANIFn_DB2_DATA6);
sahilmgandhi 18:6a4db94011d3 423 msg->data[7] = BFN_GET(LPC_CAN->IF2_DB2, CANIFn_DB2_DATA7);
sahilmgandhi 18:6a4db94011d3 424
sahilmgandhi 18:6a4db94011d3 425 LPC_CAN->STAT &= ~(CANSTAT_RXOK);
sahilmgandhi 18:6a4db94011d3 426 return 1;
sahilmgandhi 18:6a4db94011d3 427 }
sahilmgandhi 18:6a4db94011d3 428
sahilmgandhi 18:6a4db94011d3 429 return 0;
sahilmgandhi 18:6a4db94011d3 430 }
sahilmgandhi 18:6a4db94011d3 431
sahilmgandhi 18:6a4db94011d3 432 void can_reset(can_t *obj) {
sahilmgandhi 18:6a4db94011d3 433 LPC_SYSCON->PRESETCTRL &= ~PRESETCTRL_CAN_RST_N;
sahilmgandhi 18:6a4db94011d3 434 LPC_CAN->STAT = 0;
sahilmgandhi 18:6a4db94011d3 435
sahilmgandhi 18:6a4db94011d3 436 can_config_rxmsgobj(obj);
sahilmgandhi 18:6a4db94011d3 437 }
sahilmgandhi 18:6a4db94011d3 438
sahilmgandhi 18:6a4db94011d3 439 unsigned char can_rderror(can_t *obj) {
sahilmgandhi 18:6a4db94011d3 440 return BFN_GET(LPC_CAN->EC, CANEC_REC);
sahilmgandhi 18:6a4db94011d3 441 }
sahilmgandhi 18:6a4db94011d3 442
sahilmgandhi 18:6a4db94011d3 443 unsigned char can_tderror(can_t *obj) {
sahilmgandhi 18:6a4db94011d3 444 return BFN_GET(LPC_CAN->EC, CANEC_TEC);
sahilmgandhi 18:6a4db94011d3 445 }
sahilmgandhi 18:6a4db94011d3 446
sahilmgandhi 18:6a4db94011d3 447 void can_monitor(can_t *obj, int silent) {
sahilmgandhi 18:6a4db94011d3 448 if (silent) {
sahilmgandhi 18:6a4db94011d3 449 LPC_CAN->CNTL |= CANCNTL_TEST;
sahilmgandhi 18:6a4db94011d3 450 LPC_CAN->TEST |= CANTEST_SILENT;
sahilmgandhi 18:6a4db94011d3 451 } else {
sahilmgandhi 18:6a4db94011d3 452 LPC_CAN->CNTL &= ~(CANCNTL_TEST);
sahilmgandhi 18:6a4db94011d3 453 LPC_CAN->TEST &= ~CANTEST_SILENT;
sahilmgandhi 18:6a4db94011d3 454 }
sahilmgandhi 18:6a4db94011d3 455
sahilmgandhi 18:6a4db94011d3 456 if (!(LPC_CAN->CNTL & CANCNTL_INIT)) {
sahilmgandhi 18:6a4db94011d3 457 LPC_CAN->CNTL |= CANCNTL_INIT;
sahilmgandhi 18:6a4db94011d3 458 }
sahilmgandhi 18:6a4db94011d3 459 }