Subversion Repositories ChibiGauge

Rev

Rev 8 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  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. #include <stdlib.h>
  31. #include <math.h>
  32.  
  33.  
  34. #include "ch.h"
  35. #include "hal.h"
  36. // #include "test.h"
  37. #include "shell.h"
  38. #include "evtimer.h"
  39. #include "chprintf.h"
  40.  
  41. #include "shellCmds.h"
  42.  
  43. #include "ap_math.h"
  44. #include "spiInterface.h"
  45. #include "SSD1306.h"
  46. #include "Font.h"
  47.  
  48. static MUTEX_DECL(mutexDisplay);
  49.  
  50. /*===========================================================================*/
  51. /* Command line related.                                                     */
  52. /*===========================================================================*/
  53.  
  54. #define SHELL_WA_SIZE THD_WORKING_AREA_SIZE(1024)
  55. #define TEST_WA_SIZE THD_WORKING_AREA_SIZE(256)
  56.  
  57. #define RPM_ID 0x10d
  58.  
  59. // 1 megabit CAN
  60. #define CAN_CONFIG1000
  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
  71. #if defined CAN_CONFIG500
  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)};
  76. #elif defined CAN_CONFIG1000
  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)};
  81. #endif
  82. static const ShellConfig shell_cfg1 = {
  83.         (BaseSequentialStream *)&SD1,
  84.         shellCommands};
  85. ////////
  86. // end of shell stuff
  87.  
  88. uint16_t sampIndex;
  89.  
  90. void setDriveA(uint8_t bit)
  91. {
  92.         if (bit)
  93.         {
  94.                 palSetPad(GPIOA, GPIOA_A1);
  95.                 palClearPad(GPIOA, GPIOA_A2);
  96.         }
  97.         else
  98.         {
  99.                 palClearPad(GPIOA, GPIOA_A1);
  100.                 palSetPad(GPIOA, GPIOA_A2);
  101.         }
  102. }
  103.  
  104. void setDriveB(uint8_t bit)
  105. {
  106.         if (bit)
  107.         {
  108.                 palSetPad(GPIOA, GPIOA_B1);
  109.                 palClearPad(GPIOA, GPIOA_B2);
  110.         }
  111.         else
  112.         {
  113.                 palClearPad(GPIOA, GPIOA_B1);
  114.                 palSetPad(GPIOA, GPIOA_B2);
  115.         }
  116. }
  117.  
  118. // dial settings
  119. volatile int origin = 0;
  120. ;
  121. volatile int target = 0;
  122. volatile int count = 0;
  123.  
  124. volatile bool pause;
  125. //
  126.  
  127. void setPause(bool p)
  128. {
  129.         pause = p;
  130. }
  131.  
  132. static THD_WORKING_AREA(waGaugeThread, 512);
  133. static THD_FUNCTION(gaugeThread, p) {
  134.         (void)p;
  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");
  141.         while (TRUE)
  142.         {
  143.  
  144.                 while (pause)
  145.                         chThdSleep(1000);
  146.  
  147.                 switch (count % 4)
  148.                 {
  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;
  165.                 }
  166.  
  167.                 // all this calculates minimum distance from
  168.                 // target or origin
  169.                 int d1 = abs(count - origin);
  170.                 int d2 = abs(count - target);
  171.                 // finally, minimum distance
  172.                 int dist = d1<d2 ? d1 : d2;
  173.                
  174.                 del = fast;
  175.                 if (dist < range) // inside lower bound of distance
  176.                 {
  177.                         del = slow - dist;
  178.                 }
  179.                 chThdSleep(del);
  180.  
  181.                 if (count < target)
  182.                 {
  183.                         step = 1;
  184.                 }
  185.                 if (count > target)
  186.                 {
  187.                         step = -1;
  188.                 }
  189.                 if (count == target)
  190.                 {
  191.                         step = 0;
  192.                 }
  193.                 count = count + step;
  194.         }
  195. }
  196.  
  197. /*
  198.  * Command Shell Thread
  199.  */
  200. static THD_WORKING_AREA(waShell, 512);
  201. static THD_FUNCTION(shell, p) {
  202.         (void) p;
  203.         thread_t *shelltp = NULL;
  204.  
  205.         chRegSetThreadName("Shell ");
  206.         /*
  207.          * in this demo it just performs
  208.          * a shell respawn upon its termination.
  209.          */
  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.                 {
  219.                         /* If the previous shell exited.*/
  220.                         if (chThdTerminatedX(shelltp))
  221.                         {
  222.                                 /* Recovers memory of the previous shell.*/
  223.                                 chThdRelease(shelltp);
  224.                                 shelltp = NULL;
  225.                         }
  226.                 }
  227.                 chThdSleepMilliseconds(500);
  228.         }
  229. }
  230.  
  231.  
  232.         static THD_WORKING_AREA(waCanRx, 1024);
  233. static THD_FUNCTION(canRx, p) {
  234.         (void) p;
  235.  
  236.         // initialize can bus hardware
  237.         event_listener_t el;
  238.         CANRxFrame rxmsg;
  239.  
  240.         canStart(&CAND1, &cancfg1000);
  241.  
  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.                 }
  252.         }
  253.         chEvtUnregister(&CAND1.rxfull_event, &el);
  254. }
  255. /*
  256.  * Application entry point.
  257.  */
  258. int main(void)
  259. {
  260.         //  struct EventListener el0, el1;
  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.  
  272.         /*
  273.          * Initializes serial port.
  274.          */
  275.         sdStart(&SD1, NULL);
  276.  
  277.         /*
  278.          * Shell manager initialization.
  279.          */
  280.         //      shellInit();
  281.         /*
  282.          * initialise approximate maths
  283.          */
  284.         ap_init();
  285.  
  286.         chMtxLock(&mutexDisplay);
  287.  
  288.         /* start the SPI hardware for display */
  289.         ssd1306spiInit();
  290.  
  291.         ssd1306_begin(SSD1306_SWITCHCAPVCC, 0);
  292.  
  293.         clearDisplay();
  294.  
  295.         display();
  296.  
  297.         chMtxUnlock(&mutexDisplay);
  298.  
  299.         /*
  300.          * Creates the PLL thread
  301.          */
  302.         chThdCreateStatic(waGaugeThread, sizeof(waGaugeThread), NORMALPRIO, gaugeThread, NULL);
  303.  
  304.         chThdCreateStatic(waCanRx, sizeof(waCanRx), NORMALPRIO, canRx, NULL);
  305.  
  306.         chThdCreateStatic(waShell, sizeof(waShell), NORMALPRIO, shell, NULL);
  307.  
  308.         // reset gauge
  309.         origin = 540;
  310.         count = 540;
  311.         target = 0;
  312.         chThdSleepMilliseconds(1000);
  313.         target = 0;
  314.  
  315.         int frac = 0;
  316.         /* start the SPI hardware for display */
  317.         while (1)
  318.         {
  319.  
  320.                 chThdSleepMilliseconds(100);
  321.                 unsigned const SCALE = frac * 32 + 16;
  322.                 ++frac ;
  323.                 frac %= 10;
  324.  
  325.                 // read the dial
  326.  
  327.                 origin = count;
  328.  
  329.                 target = target + 1;
  330.  
  331.                 // target = lidar * 630L / 2000L;
  332.  
  333.                 if (target > 540)
  334.                         target = 0;
  335.  
  336.                 chMtxLock(&mutexDisplay);
  337.  
  338.                 font_gotoxy(0, 0);
  339.                 clearDisplay();
  340.  
  341.                 //    print_scaled_string("cm:",0,16,4,SCALE);
  342.  
  343.                 print_digits(0, 0, 4, 1, target, SCALE);
  344.  
  345.                 chMtxUnlock(&mutexDisplay);
  346.  
  347.                 display();
  348.         }
  349. }
  350.