Subversion Repositories ChibiGauge

Rev

Rev 8 | 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>
9 mjames 30
#include <stdlib.h>
31
#include <math.h>
32
 
2 mjames 33
 
34
#include "ch.h"
35
#include "hal.h"
8 mjames 36
// #include "test.h"
2 mjames 37
#include "shell.h"
38
#include "evtimer.h"
39
#include "chprintf.h"
40
 
41
#include "shellCmds.h"
42
 
6 mjames 43
#include "ap_math.h"
44
#include "spiInterface.h"
45
#include "SSD1306.h"
9 mjames 46
#include "Font.h"
2 mjames 47
 
8 mjames 48
static MUTEX_DECL(mutexDisplay);
2 mjames 49
 
50
/*===========================================================================*/
51
/* Command line related.                                                     */
52
/*===========================================================================*/
53
 
8 mjames 54
#define SHELL_WA_SIZE THD_WORKING_AREA_SIZE(1024)
55
#define TEST_WA_SIZE THD_WORKING_AREA_SIZE(256)
2 mjames 56
 
8 mjames 57
#define RPM_ID 0x10d
58
 
9 mjames 59
// 1 megabit CAN 
60
#define CAN_CONFIG1000
8 mjames 61
 
62
/*
63
 * Internal loopback mode, 500KBaud, automatic wakeup, automatic recover
64
 * from abort mode.
65
 */
66
 
67
// CAN_BTR_SJW(n), where n = SJW - 1
68
// CAN_BTR_BRP(n), where n = prescaler - 1
69
// CAN_BTR_TS1(n), where n = Seg 1 - 1
70
// CAN_BTR_TS2(n), where n = Seg 2 - 1
9 mjames 71
#if defined CAN_CONFIG500
8 mjames 72
static const CANConfig cancfg500 = {
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(3) | CAN_BTR_BRP(8)};
9 mjames 76
#elif defined CAN_CONFIG1000
8 mjames 77
static const CANConfig cancfg1000 = {
78
        CAN_MCR_ABOM | CAN_MCR_AWUM | CAN_MCR_TXFP,
79
        CAN_BTR_LBKM | CAN_BTR_SJW(0) | CAN_BTR_TS2(2) |
80
                CAN_BTR_TS1(4) | CAN_BTR_BRP(3)};
9 mjames 81
#endif
2 mjames 82
static const ShellConfig shell_cfg1 = {
8 mjames 83
        (BaseSequentialStream *)&SD1,
84
        shellCommands};
2 mjames 85
////////
86
// end of shell stuff
87
 
88
uint16_t sampIndex;
89
 
8 mjames 90
void setDriveA(uint8_t bit)
91
{
92
        if (bit)
93
        {
6 mjames 94
                palSetPad(GPIOA, GPIOA_A1);
95
                palClearPad(GPIOA, GPIOA_A2);
8 mjames 96
        }
97
        else
98
        {
2 mjames 99
                palClearPad(GPIOA, GPIOA_A1);
100
                palSetPad(GPIOA, GPIOA_A2);
101
        }
102
}
103
 
8 mjames 104
void setDriveB(uint8_t bit)
105
{
106
        if (bit)
107
        {
6 mjames 108
                palSetPad(GPIOA, GPIOA_B1);
109
                palClearPad(GPIOA, GPIOA_B2);
8 mjames 110
        }
111
        else
112
        {
2 mjames 113
                palClearPad(GPIOA, GPIOA_B1);
114
                palSetPad(GPIOA, GPIOA_B2);
115
        }
116
}
117
 
6 mjames 118
// dial settings
119
volatile int origin = 0;
120
;
121
volatile int target = 0;
2 mjames 122
volatile int count = 0;
123
 
6 mjames 124
volatile bool pause;
125
//
126
 
8 mjames 127
void setPause(bool p)
128
{
6 mjames 129
        pause = p;
130
}
131
 
8 mjames 132
static THD_WORKING_AREA(waGaugeThread, 512);
133
static THD_FUNCTION(gaugeThread, p) {
134
        (void)p;
6 mjames 135
        unsigned const fast = 10;
136
        unsigned const slow = 30;
137
        unsigned const range = slow - fast;
138
        unsigned del = fast;
139
        int step = 1;
140
        chRegSetThreadName("Step");
8 mjames 141
        while (TRUE)
142
        {
2 mjames 143
 
6 mjames 144
                while (pause)
145
                        chThdSleep(1000);
146
 
8 mjames 147
                switch (count % 4)
148
                {
6 mjames 149
                case 0:
150
                        setDriveA(1);
151
                        setDriveB(0);
152
                        break;
153
                case 1:
154
                        setDriveA(1);
155
                        setDriveB(1);
156
                        break;
157
                case 2:
158
                        setDriveA(0);
159
                        setDriveB(1);
160
                        break;
161
                case 3:
162
                        setDriveA(0);
163
                        setDriveB(0);
164
                        break;
2 mjames 165
                }
166
 
167
                // all this calculates minimum distance from
168
                // target or origin
8 mjames 169
                int d1 = abs(count - origin);
170
                int d2 = abs(count - target);
6 mjames 171
                // finally, minimum distance
9 mjames 172
                int dist = d1<d2 ? d1 : d2;
8 mjames 173
 
6 mjames 174
                del = fast;
175
                if (dist < range) // inside lower bound of distance
8 mjames 176
                {
6 mjames 177
                        del = slow - dist;
178
                }
179
                chThdSleep(del);
2 mjames 180
 
8 mjames 181
                if (count < target)
182
                {
6 mjames 183
                        step = 1;
184
                }
8 mjames 185
                if (count > target)
186
                {
6 mjames 187
                        step = -1;
188
                }
8 mjames 189
                if (count == target)
190
                {
6 mjames 191
                        step = 0;
192
                }
193
                count = count + step;
194
        }
2 mjames 195
}
196
 
197
/*
198
 * Command Shell Thread
199
 */
8 mjames 200
static THD_WORKING_AREA(waShell, 512);
201
static THD_FUNCTION(shell, p) {
202
        (void) p;
2 mjames 203
        thread_t *shelltp = NULL;
204
 
205
        chRegSetThreadName("Shell ");
6 mjames 206
        /*
207
         * in this demo it just performs
208
         * a shell respawn upon its termination.
209
         */
8 mjames 210
        while (true)
211
        {
212
                if (!shelltp)
213
                {
214
 
215
                        shelltp = chThdCreateFromHeap(NULL, SHELL_WA_SIZE, "shell", NORMALPRIO, shellThread, (void *)&shell_cfg1);
216
                }
217
                else
218
                {
6 mjames 219
                        /* If the previous shell exited.*/
8 mjames 220
                        if (chThdTerminatedX(shelltp))
221
                        {
6 mjames 222
                                /* Recovers memory of the previous shell.*/
223
                                chThdRelease(shelltp);
224
                                shelltp = NULL;
225
                        }
226
                }
227
                chThdSleepMilliseconds(500);
228
        }
2 mjames 229
}
230
 
231
 
8 mjames 232
        static THD_WORKING_AREA(waCanRx, 1024);
233
static THD_FUNCTION(canRx, p) {
234
        (void) p;
2 mjames 235
 
8 mjames 236
        // initialize can bus hardware
237
        event_listener_t el;
238
        CANRxFrame rxmsg;
2 mjames 239
 
8 mjames 240
        canStart(&CAND1, &cancfg1000);
6 mjames 241
 
8 mjames 242
        chRegSetThreadName("CAN receiver");
243
        chEvtRegister(&CAND1.rxfull_event, &el, 0);
244
        while (true)
245
        {
246
                if (chEvtWaitAnyTimeout(ALL_EVENTS, TIME_MS2I(100)) == 0)
247
                        continue;
248
                while (canReceive(&CAND1, CAN_ANY_MAILBOX, &rxmsg, TIME_IMMEDIATE) == MSG_OK)
249
                {
250
                        /* Process message.*/
251
                }
6 mjames 252
        }
8 mjames 253
        chEvtUnregister(&CAND1.rxfull_event, &el);
6 mjames 254
}
2 mjames 255
/*
256
 * Application entry point.
257
 */
8 mjames 258
int main(void)
259
{
260
        //  struct EventListener el0, el1;
2 mjames 261
 
262
        /*
263
         * System initializations.
264
         * - HAL initialization, this also initializes the configured device drivers
265
         *   and performs the board-specific initializations.
266
         * - Kernel initialization, the main() function becomes a thread and the
267
         *   RTOS is active.
268
         */
269
        halInit();
270
        chSysInit();
271
 
6 mjames 272
        /*
8 mjames 273
         * Initializes serial port.
6 mjames 274
         */
8 mjames 275
        sdStart(&SD1, NULL);
2 mjames 276
 
6 mjames 277
        /*
2 mjames 278
         * Shell manager initialization.
279
         */
8 mjames 280
        //      shellInit();
6 mjames 281
        /*
282
         * initialise approximate maths
283
         */
284
        ap_init();
2 mjames 285
 
6 mjames 286
        chMtxLock(&mutexDisplay);
2 mjames 287
 
6 mjames 288
        /* start the SPI hardware for display */
289
        ssd1306spiInit();
290
 
8 mjames 291
        ssd1306_begin(SSD1306_SWITCHCAPVCC, 0);
6 mjames 292
 
293
        clearDisplay();
294
 
295
        display();
296
 
8 mjames 297
        chMtxUnlock(&mutexDisplay);
6 mjames 298
 
299
        /*
2 mjames 300
         * Creates the PLL thread
301
         */
8 mjames 302
        chThdCreateStatic(waGaugeThread, sizeof(waGaugeThread), NORMALPRIO, gaugeThread, NULL);
2 mjames 303
 
8 mjames 304
        chThdCreateStatic(waCanRx, sizeof(waCanRx), NORMALPRIO, canRx, NULL);
2 mjames 305
 
8 mjames 306
        chThdCreateStatic(waShell, sizeof(waShell), NORMALPRIO, shell, NULL);
2 mjames 307
 
8 mjames 308
        // reset gauge
6 mjames 309
        origin = 540;
8 mjames 310
        count = 540;
6 mjames 311
        target = 0;
312
        chThdSleepMilliseconds(1000);
313
        target = 0;
2 mjames 314
 
6 mjames 315
        int frac = 0;
2 mjames 316
        /* start the SPI hardware for display */
8 mjames 317
        while (1)
318
        {
2 mjames 319
 
8 mjames 320
                chThdSleepMilliseconds(100);
321
                unsigned const SCALE = frac * 32 + 16;
9 mjames 322
                ++frac ;
323
                frac %= 10;
2 mjames 324
 
8 mjames 325
                // read the dial
2 mjames 326
 
8 mjames 327
                origin = count;
2 mjames 328
 
8 mjames 329
                target = target + 1;
2 mjames 330
 
8 mjames 331
                // target = lidar * 630L / 2000L;
2 mjames 332
 
8 mjames 333
                if (target > 540)
334
                        target = 0;
2 mjames 335
 
8 mjames 336
                chMtxLock(&mutexDisplay);
2 mjames 337
 
8 mjames 338
                font_gotoxy(0, 0);
339
                clearDisplay();
2 mjames 340
 
8 mjames 341
                //    print_scaled_string("cm:",0,16,4,SCALE);
2 mjames 342
 
8 mjames 343
                print_digits(0, 0, 4, 1, target, SCALE);
2 mjames 344
 
8 mjames 345
                chMtxUnlock(&mutexDisplay);
6 mjames 346
 
8 mjames 347
                display();
6 mjames 348
        }
2 mjames 349
}