Rev 7 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 2 | mjames | 1 | /* |
| 2 | ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, |
||
| 3 | 2011,2012 Giovanni Di Sirio. |
||
| 4 | |||
| 5 | This file is part of ChibiOS/RT. |
||
| 6 | |||
| 7 | ChibiOS/RT is free software; you can redistribute it and/or modify |
||
| 8 | it under the terms of the GNU General Public License as published by |
||
| 9 | the Free Software Foundation; either version 3 of the License, or |
||
| 10 | (at your option) any later version. |
||
| 11 | |||
| 12 | ChibiOS/RT is distributed in the hope that it will be useful, |
||
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
| 15 | GNU General Public License for more details. |
||
| 16 | |||
| 17 | You should have received a copy of the GNU General Public License |
||
| 18 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
||
| 19 | |||
| 20 | --- |
||
| 21 | |||
| 22 | A special exception to the GPL can be applied should you wish to distribute |
||
| 23 | a combined work that includes ChibiOS/RT, without being obliged to provide |
||
| 24 | the source code for any proprietary components. See the file exception.txt |
||
| 25 | for full details of how and when the exception can be applied. |
||
| 26 | */ |
||
| 27 | |||
| 28 | #include <stdio.h> |
||
| 29 | #include <string.h> |
||
| 30 | |||
| 31 | #include "ch.h" |
||
| 32 | #include "hal.h" |
||
| 8 | mjames | 33 | // #include "test.h" |
| 2 | mjames | 34 | #include "shell.h" |
| 35 | #include "evtimer.h" |
||
| 36 | #include "chprintf.h" |
||
| 37 | |||
| 38 | #include "shellCmds.h" |
||
| 39 | |||
| 6 | mjames | 40 | #include "ap_math.h" |
| 41 | #include "spiInterface.h" |
||
| 42 | #include "SSD1306.h" |
||
| 43 | #include "font.h" |
||
| 2 | mjames | 44 | |
| 8 | mjames | 45 | static MUTEX_DECL(mutexDisplay); |
| 2 | mjames | 46 | |
| 47 | /*===========================================================================*/ |
||
| 48 | /* Command line related. */ |
||
| 49 | /*===========================================================================*/ |
||
| 50 | |||
| 8 | mjames | 51 | #define SHELL_WA_SIZE THD_WORKING_AREA_SIZE(1024) |
| 52 | #define TEST_WA_SIZE THD_WORKING_AREA_SIZE(256) |
||
| 2 | mjames | 53 | |
| 8 | mjames | 54 | #define RPM_ID 0x10d |
| 55 | |||
| 56 | |||
| 57 | /* |
||
| 58 | * Internal loopback mode, 500KBaud, automatic wakeup, automatic recover |
||
| 59 | * from abort mode. |
||
| 60 | */ |
||
| 61 | |||
| 62 | // CAN_BTR_SJW(n), where n = SJW - 1 |
||
| 63 | // CAN_BTR_BRP(n), where n = prescaler - 1 |
||
| 64 | // CAN_BTR_TS1(n), where n = Seg 1 - 1 |
||
| 65 | // CAN_BTR_TS2(n), where n = Seg 2 - 1 |
||
| 66 | |||
| 67 | static const CANConfig cancfg500 = { |
||
| 68 | CAN_MCR_ABOM | CAN_MCR_AWUM | CAN_MCR_TXFP, |
||
| 69 | CAN_BTR_LBKM | CAN_BTR_SJW(0) | CAN_BTR_TS2(2) | |
||
| 70 | CAN_BTR_TS1(3) | CAN_BTR_BRP(8)}; |
||
| 71 | |||
| 72 | static const CANConfig cancfg1000 = { |
||
| 73 | CAN_MCR_ABOM | CAN_MCR_AWUM | CAN_MCR_TXFP, |
||
| 74 | CAN_BTR_LBKM | CAN_BTR_SJW(0) | CAN_BTR_TS2(2) | |
||
| 75 | CAN_BTR_TS1(4) | CAN_BTR_BRP(3)}; |
||
| 76 | |||
| 2 | mjames | 77 | static const ShellConfig shell_cfg1 = { |
| 8 | mjames | 78 | (BaseSequentialStream *)&SD1, |
| 79 | shellCommands}; |
||
| 2 | mjames | 80 | //////// |
| 81 | // end of shell stuff |
||
| 82 | |||
| 83 | uint16_t sampIndex; |
||
| 84 | |||
| 8 | mjames | 85 | void setDriveA(uint8_t bit) |
| 86 | { |
||
| 87 | if (bit) |
||
| 88 | { |
||
| 6 | mjames | 89 | palSetPad(GPIOA, GPIOA_A1); |
| 90 | palClearPad(GPIOA, GPIOA_A2); |
||
| 8 | mjames | 91 | } |
| 92 | else |
||
| 93 | { |
||
| 2 | mjames | 94 | palClearPad(GPIOA, GPIOA_A1); |
| 95 | palSetPad(GPIOA, GPIOA_A2); |
||
| 96 | } |
||
| 97 | } |
||
| 98 | |||
| 8 | mjames | 99 | void setDriveB(uint8_t bit) |
| 100 | { |
||
| 101 | if (bit) |
||
| 102 | { |
||
| 6 | mjames | 103 | palSetPad(GPIOA, GPIOA_B1); |
| 104 | palClearPad(GPIOA, GPIOA_B2); |
||
| 8 | mjames | 105 | } |
| 106 | else |
||
| 107 | { |
||
| 2 | mjames | 108 | palClearPad(GPIOA, GPIOA_B1); |
| 109 | palSetPad(GPIOA, GPIOA_B2); |
||
| 110 | } |
||
| 111 | } |
||
| 112 | |||
| 6 | mjames | 113 | // dial settings |
| 114 | volatile int origin = 0; |
||
| 115 | ; |
||
| 116 | volatile int target = 0; |
||
| 2 | mjames | 117 | volatile int count = 0; |
| 118 | |||
| 6 | mjames | 119 | volatile bool pause; |
| 120 | // |
||
| 121 | |||
| 8 | mjames | 122 | void setPause(bool p) |
| 123 | { |
||
| 6 | mjames | 124 | pause = p; |
| 125 | } |
||
| 126 | |||
| 8 | mjames | 127 | static THD_WORKING_AREA(waGaugeThread, 512); |
| 128 | static THD_FUNCTION(gaugeThread, p) { |
||
| 129 | (void)p; |
||
| 6 | mjames | 130 | unsigned const fast = 10; |
| 131 | unsigned const slow = 30; |
||
| 132 | unsigned const range = slow - fast; |
||
| 133 | unsigned del = fast; |
||
| 134 | int step = 1; |
||
| 135 | chRegSetThreadName("Step"); |
||
| 8 | mjames | 136 | while (TRUE) |
| 137 | { |
||
| 2 | mjames | 138 | |
| 6 | mjames | 139 | while (pause) |
| 140 | chThdSleep(1000); |
||
| 141 | |||
| 8 | mjames | 142 | switch (count % 4) |
| 143 | { |
||
| 6 | mjames | 144 | case 0: |
| 145 | setDriveA(1); |
||
| 146 | setDriveB(0); |
||
| 147 | break; |
||
| 148 | case 1: |
||
| 149 | setDriveA(1); |
||
| 150 | setDriveB(1); |
||
| 151 | break; |
||
| 152 | case 2: |
||
| 153 | setDriveA(0); |
||
| 154 | setDriveB(1); |
||
| 155 | break; |
||
| 156 | case 3: |
||
| 157 | setDriveA(0); |
||
| 158 | setDriveB(0); |
||
| 159 | break; |
||
| 2 | mjames | 160 | } |
| 161 | |||
| 162 | // all this calculates minimum distance from |
||
| 163 | // target or origin |
||
| 8 | mjames | 164 | int d1 = abs(count - origin); |
| 165 | int d2 = abs(count - target); |
||
| 6 | mjames | 166 | // finally, minimum distance |
| 8 | mjames | 167 | int dist = min(d1,d2); |
| 168 | |||
| 6 | mjames | 169 | del = fast; |
| 170 | if (dist < range) // inside lower bound of distance |
||
| 8 | mjames | 171 | { |
| 6 | mjames | 172 | del = slow - dist; |
| 173 | } |
||
| 174 | chThdSleep(del); |
||
| 2 | mjames | 175 | |
| 8 | mjames | 176 | if (count < target) |
| 177 | { |
||
| 6 | mjames | 178 | step = 1; |
| 179 | } |
||
| 8 | mjames | 180 | if (count > target) |
| 181 | { |
||
| 6 | mjames | 182 | step = -1; |
| 183 | } |
||
| 8 | mjames | 184 | if (count == target) |
| 185 | { |
||
| 6 | mjames | 186 | step = 0; |
| 187 | } |
||
| 188 | count = count + step; |
||
| 189 | } |
||
| 2 | mjames | 190 | } |
| 191 | |||
| 192 | /* |
||
| 193 | * Command Shell Thread |
||
| 194 | */ |
||
| 8 | mjames | 195 | static THD_WORKING_AREA(waShell, 512); |
| 196 | static THD_FUNCTION(shell, p) { |
||
| 197 | (void) p; |
||
| 2 | mjames | 198 | thread_t *shelltp = NULL; |
| 199 | |||
| 200 | chRegSetThreadName("Shell "); |
||
| 6 | mjames | 201 | /* |
| 202 | * in this demo it just performs |
||
| 203 | * a shell respawn upon its termination. |
||
| 204 | */ |
||
| 8 | mjames | 205 | while (true) |
| 206 | { |
||
| 207 | if (!shelltp) |
||
| 208 | { |
||
| 209 | |||
| 210 | shelltp = chThdCreateFromHeap(NULL, SHELL_WA_SIZE, "shell", NORMALPRIO, shellThread, (void *)&shell_cfg1); |
||
| 211 | } |
||
| 212 | else |
||
| 213 | { |
||
| 6 | mjames | 214 | /* If the previous shell exited.*/ |
| 8 | mjames | 215 | if (chThdTerminatedX(shelltp)) |
| 216 | { |
||
| 6 | mjames | 217 | /* Recovers memory of the previous shell.*/ |
| 218 | chThdRelease(shelltp); |
||
| 219 | shelltp = NULL; |
||
| 220 | } |
||
| 221 | } |
||
| 222 | chThdSleepMilliseconds(500); |
||
| 223 | } |
||
| 2 | mjames | 224 | } |
| 225 | |||
| 226 | |||
| 8 | mjames | 227 | static THD_WORKING_AREA(waCanRx, 1024); |
| 228 | static THD_FUNCTION(canRx, p) { |
||
| 229 | (void) p; |
||
| 2 | mjames | 230 | |
| 8 | mjames | 231 | // initialize can bus hardware |
| 232 | event_listener_t el; |
||
| 233 | CANRxFrame rxmsg; |
||
| 2 | mjames | 234 | |
| 8 | mjames | 235 | canStart(&CAND1, &cancfg1000); |
| 6 | mjames | 236 | |
| 8 | mjames | 237 | chRegSetThreadName("CAN receiver"); |
| 238 | chEvtRegister(&CAND1.rxfull_event, &el, 0); |
||
| 239 | while (true) |
||
| 240 | { |
||
| 241 | if (chEvtWaitAnyTimeout(ALL_EVENTS, TIME_MS2I(100)) == 0) |
||
| 242 | continue; |
||
| 243 | while (canReceive(&CAND1, CAN_ANY_MAILBOX, &rxmsg, TIME_IMMEDIATE) == MSG_OK) |
||
| 244 | { |
||
| 245 | /* Process message.*/ |
||
| 246 | } |
||
| 6 | mjames | 247 | } |
| 8 | mjames | 248 | chEvtUnregister(&CAND1.rxfull_event, &el); |
| 6 | mjames | 249 | } |
| 2 | mjames | 250 | /* |
| 251 | * Application entry point. |
||
| 252 | */ |
||
| 8 | mjames | 253 | int main(void) |
| 254 | { |
||
| 255 | // struct EventListener el0, el1; |
||
| 2 | mjames | 256 | |
| 257 | /* |
||
| 258 | * System initializations. |
||
| 259 | * - HAL initialization, this also initializes the configured device drivers |
||
| 260 | * and performs the board-specific initializations. |
||
| 261 | * - Kernel initialization, the main() function becomes a thread and the |
||
| 262 | * RTOS is active. |
||
| 263 | */ |
||
| 264 | halInit(); |
||
| 265 | chSysInit(); |
||
| 266 | |||
| 6 | mjames | 267 | /* |
| 8 | mjames | 268 | * Initializes serial port. |
| 6 | mjames | 269 | */ |
| 8 | mjames | 270 | sdStart(&SD1, NULL); |
| 2 | mjames | 271 | |
| 6 | mjames | 272 | /* |
| 2 | mjames | 273 | * Shell manager initialization. |
| 274 | */ |
||
| 8 | mjames | 275 | // shellInit(); |
| 6 | mjames | 276 | /* |
| 277 | * initialise approximate maths |
||
| 278 | */ |
||
| 279 | ap_init(); |
||
| 2 | mjames | 280 | |
| 6 | mjames | 281 | chMtxLock(&mutexDisplay); |
| 2 | mjames | 282 | |
| 6 | mjames | 283 | /* start the SPI hardware for display */ |
| 284 | ssd1306spiInit(); |
||
| 285 | |||
| 8 | mjames | 286 | ssd1306_begin(SSD1306_SWITCHCAPVCC, 0); |
| 6 | mjames | 287 | |
| 288 | clearDisplay(); |
||
| 289 | |||
| 290 | display(); |
||
| 291 | |||
| 8 | mjames | 292 | chMtxUnlock(&mutexDisplay); |
| 6 | mjames | 293 | |
| 294 | /* |
||
| 2 | mjames | 295 | * Creates the PLL thread |
| 296 | */ |
||
| 8 | mjames | 297 | chThdCreateStatic(waGaugeThread, sizeof(waGaugeThread), NORMALPRIO, gaugeThread, NULL); |
| 2 | mjames | 298 | |
| 8 | mjames | 299 | chThdCreateStatic(waCanRx, sizeof(waCanRx), NORMALPRIO, canRx, NULL); |
| 2 | mjames | 300 | |
| 8 | mjames | 301 | chThdCreateStatic(waShell, sizeof(waShell), NORMALPRIO, shell, NULL); |
| 2 | mjames | 302 | |
| 8 | mjames | 303 | // reset gauge |
| 6 | mjames | 304 | origin = 540; |
| 8 | mjames | 305 | count = 540; |
| 6 | mjames | 306 | target = 0; |
| 307 | chThdSleepMilliseconds(1000); |
||
| 308 | target = 0; |
||
| 2 | mjames | 309 | |
| 6 | mjames | 310 | int frac = 0; |
| 2 | mjames | 311 | /* start the SPI hardware for display */ |
| 8 | mjames | 312 | while (1) |
| 313 | { |
||
| 2 | mjames | 314 | |
| 8 | mjames | 315 | chThdSleepMilliseconds(100); |
| 316 | unsigned const SCALE = frac * 32 + 16; |
||
| 317 | frac = (++frac) % 10; |
||
| 2 | mjames | 318 | |
| 8 | mjames | 319 | // read the dial |
| 2 | mjames | 320 | |
| 8 | mjames | 321 | origin = count; |
| 2 | mjames | 322 | |
| 8 | mjames | 323 | target = target + 1; |
| 2 | mjames | 324 | |
| 8 | mjames | 325 | // target = lidar * 630L / 2000L; |
| 2 | mjames | 326 | |
| 8 | mjames | 327 | if (target > 540) |
| 328 | target = 0; |
||
| 2 | mjames | 329 | |
| 8 | mjames | 330 | chMtxLock(&mutexDisplay); |
| 2 | mjames | 331 | |
| 8 | mjames | 332 | font_gotoxy(0, 0); |
| 333 | clearDisplay(); |
||
| 2 | mjames | 334 | |
| 8 | mjames | 335 | // print_scaled_string("cm:",0,16,4,SCALE); |
| 2 | mjames | 336 | |
| 8 | mjames | 337 | print_digits(0, 0, 4, 1, target, SCALE); |
| 2 | mjames | 338 | |
| 8 | mjames | 339 | chMtxUnlock(&mutexDisplay); |
| 6 | mjames | 340 | |
| 8 | mjames | 341 | display(); |
| 6 | mjames | 342 | } |
| 2 | mjames | 343 | } |