Subversion Repositories ChibiGauge

Rev

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
}