Advertisement
Guest User

Untitled

a guest
Oct 23rd, 2019
158
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 18.59 KB | None | 0 0
  1. /*
  2. * File: main.c
  3. * Author:
  4. *
  5. * Created on September 14, 2019, 12:00 AM
  6. *
  7.  
  8. *----------------------
  9. Revision History
  10.  
  11. *----------------------
  12. */
  13.  
  14.  
  15. #include <stdio.h>
  16. #include <p18cxxx.h>
  17. #include "ConfigRegsPIC18f4520.h"
  18. #include <delays.h> // For the delay routines used
  19. #include <string.h>
  20. #include <stdlib.h>
  21.  
  22. /*
  23. * LCD display
  24. *
  25. * PORTD
  26. * 0-3: DATA -> LCD DB4-7
  27. * 4: RS -> LCD 4
  28. * 5: R/W -> LCD 5
  29. * 6: E -> LCD 6
  30.  
  31. * One timing cycle is 100ns
  32. * One instruction cycle is 400ns
  33. */
  34.  
  35. // The RS pin is either 0 or 1 to select the corresponding register
  36. #define DATA 1
  37. #define CMD 0
  38.  
  39. #define LCD_PORT PORTD // LCD is on Port D
  40. #define LCD_DIR TRISD // Data direction register for Port D
  41. #define LCD_E PORTDbits.RD6 // LCD Enable bit mask (pin 6)
  42. #define LCD_RS PORTDbits.RD4 // LCD Register Select signal
  43. #define LCD_RW PORTDbits.RD5 // RW pin
  44.  
  45. #define LCD_INIT 0x28 // set 4-bit data, 2-line display, 5x7 font
  46. #define CLR_SCREEN 0x01 // Clears the screen
  47. #define CUR_LINE2 0xC0 // Brings the cursor to the beginning of line 2
  48. #define CUR_SHIFT_DIR 0x6 // Makes the cursor shift right (rather than left) after data is written
  49. #define CUR_RIGHT 0b00010100 // This command shifts the cursor right
  50.  
  51. #define BUFF_SIZE 20 // Input buffer size
  52.  
  53. // The different states of the program
  54. #define ROW_SEL 0
  55. #define POS_SEL 1
  56. #define MSG_IN 2
  57.  
  58. // At 10Mhz, each timing cycle is 100ns
  59. #define delay1ms Delay10KTCYx
  60.  
  61.  
  62. //#pragma code
  63.  
  64. unsigned char rowSelStr[] = " ";
  65. unsigned char posSelStr[] = " ";
  66. unsigned char msgSelStr[] = " ";
  67.  
  68. char string1[] = "Entering";
  69. char string2[] = "User Mode...";
  70. //char string3[] = "Manual Mode...";
  71. //char string4[] = "Assist Mode...";
  72. //char string5[] = "Auto Mode...";
  73. //char string6[] = "Factory Mode...";
  74.  
  75. int modeState = 0; // 0: manual, 1: assist, 2: auto, 3: factory (change to struct/enum later)
  76. int editing = 0;
  77. int selected = 0;
  78. int leftFlag = 0;
  79. int rightFlag = 0;
  80. int functionState = 0;
  81. int displayModeState = 0; // 0: manual, 1: assist, 2: auto, 3: factory (change to struct/enum later)
  82.  
  83.  
  84. char ModeStrings[] =
  85. "Manual Mode... "
  86. "Assist Mode... "
  87. "Auto Mode... "
  88. "Factory Mode... "
  89. ;
  90.  
  91. char ManualFunctions[] =
  92. "Motors: "
  93. "Speed: "
  94. "User mode: "
  95. ;
  96.  
  97. unsigned char FactoryFunctions[] =
  98. "SET_PID_GAINS "
  99. "Max Speed: "
  100. "Max Yaw Rate "
  101. "IR Samples/Est. "
  102. //"SET_IR_SMPL_RATE"
  103. //"SHOW_STATISTICS "
  104. ;
  105. //#define MSG_DISP 3
  106. char state = ROW_SEL; // Initialise
  107.  
  108. // Temporary variable for serial input
  109. char inChar;
  110.  
  111. // Buffer for message input
  112. char msgIn[BUFF_SIZE];
  113. char function1[16];
  114. char description[16];
  115.  
  116. char msgPos = 0;
  117. unsigned char row, pos;
  118.  
  119.  
  120. char * motorString = "OFF";
  121. char * modeString = "MANUAL ";
  122.  
  123.  
  124. unsigned char bufPos = 0;
  125.  
  126. int i;
  127. char rxStr[] = "";
  128. char rxStrPos = 0;
  129.  
  130. void high_interrupt(void);
  131. void highPriorityISR(void);
  132. void rx232(void);
  133. void tx232(char * );
  134. void sendChar(char);
  135.  
  136. char * ptrDesc;
  137.  
  138. /*void delay1ms(char num) {
  139. Delay10KTCYx(num);
  140. }*/
  141.  
  142. #pragma code highIntAddress=0x8
  143. void high_interrupt(void) {
  144. _asm GOTO highPriorityISR _endasm
  145. }
  146.  
  147. void char2LCD(char c, char rs) {
  148.  
  149. // Make sure we've received a valid value
  150. if (rs == CMD || rs == DATA) {
  151.  
  152. char byteHigh, byteLow;
  153.  
  154. // We need to output data on bits 0-3 of PORTD, 4 at a time,
  155. // so we'll prepare the low half and high half
  156. byteLow = (c & 0x0F);
  157. byteHigh = (c & 0xF0) >> 4;
  158.  
  159. // Set the RS pin high or low and clear the other pins
  160. // Also write the high half of the byte
  161. //LCD_PORT = byteHigh|rs;
  162. //PORTD |= LCD_E; // Set PD1 high (the Enable (E) pin)
  163. LCD_PORT = byteHigh; // Reset the pins and put our new data in
  164. LCD_RS = rs; //RS
  165.  
  166. LCD_E = 1; // E
  167.  
  168. // We need to keep E high for at least 140ns ~= 2.3 cycles
  169. Nop();
  170. Nop();
  171. Nop();
  172.  
  173. //LCD_PORT &= ~(LCD_E); // Set PK1 low (the Enable pin)
  174. LCD_E = 0; // E
  175.  
  176. Nop(); // Enable cycle time is 1200ns
  177. Nop();
  178. Nop();
  179.  
  180. LCD_PORT = byteLow; // Reset the pins and put our new data in
  181. LCD_RS = rs; //RS
  182. //LCD_PORT |= LCD_E; // Set PK1 high (the Enable pin)
  183. LCD_E = 1; // E
  184.  
  185. // We need to keep E high for it to read the data
  186. Nop();
  187. Nop();
  188. Nop();
  189.  
  190. LCD_E = 0; // E
  191. //delay1ms(1); // Wait for command to execute
  192. Delay10TCYx(10);
  193. //LCD_PORT = 0; // Clear the pins (not really necessary)
  194. }
  195. }
  196.  
  197. void LCDinit(void) {
  198.  
  199. LCD_DIR = 0;
  200. LCD_PORT = 0;
  201. LCD_RS = 0;
  202. LCD_RW = 0; // Writing only
  203.  
  204. delay1ms(250); // give it time
  205.  
  206. char2LCD(0x32, CMD); //reset
  207. char2LCD(LCD_INIT, CMD); // set 4-bit data, 2-line display, 5x7 font
  208. char2LCD(0x0C, CMD); // turn on display, cursor, not blinking
  209. char2LCD(CUR_SHIFT_DIR, CMD); // move cursor right
  210. char2LCD(0x01, CMD); // clear screen,
  211. char2LCD(0x2, CMD); // move cursor to home
  212.  
  213. //char2LCD(0b010, CMD);
  214. delay1ms(2); // wait until "clear display" command is complete
  215.  
  216. }
  217.  
  218. void str2LCD(char * str, unsigned char pos, unsigned char row) {
  219. // Clear the screen
  220. //char2LCD(CLR_SCREEN, CMD);
  221. //delay1ms(2); // needed for screen clear
  222.  
  223. // Put the cursor on the second row if necessary
  224. if(row) {
  225. char2LCD(CUR_LINE2, CMD);
  226. delay1ms(1);
  227. }
  228.  
  229. // Increment the cursor to the right position
  230. while (pos > 0) {
  231. //char2LCD(' ', DATA);
  232. char2LCD(CUR_RIGHT, CMD);
  233. pos--;
  234. }
  235.  
  236. // Send the string through
  237. while (*str != 0) {
  238. char2LCD(*str, DATA);
  239. str++;
  240. }
  241. }
  242.  
  243. void Print2Lines(char * str1, unsigned char pos1, unsigned char row1, char * str2, unsigned char pos2, unsigned char row2){
  244. char2LCD(CLR_SCREEN, CMD);
  245. delay1ms(2); // needed for screen clear
  246. str2LCD(str1, pos1, row1);
  247. str2LCD(str2, pos2, row2);
  248. }
  249.  
  250.  
  251.  
  252. int motorState = 0;
  253.  
  254. void GetMotorState(){
  255.  
  256. // IN EDITING MODE: if left or right button is pressed, switch the motor state
  257. if(editing&&functionState==0){
  258. if(leftFlag||rightFlag){
  259. motorState^=1;
  260. leftFlag = 0;
  261. rightFlag = 0;
  262. //editing=0;
  263. }
  264.  
  265. }
  266.  
  267. if(motorState){
  268. // strcpypgm2ram(motorString,"ON ");
  269. motorString = "ON ";
  270.  
  271.  
  272. }
  273. else{
  274. // strcpypgm2ram(motorString,"OFF");
  275. motorString = "OFF";
  276.  
  277.  
  278. }
  279.  
  280. if(selected){
  281.  
  282. // COMMUNICATE TO ROBOT THAT WHETHER IT IS ON/OFF
  283. editing = 0;
  284. selected = 0;
  285. }
  286. }
  287.  
  288. int tempModeState=0;
  289.  
  290. void GetModeState() {
  291.  
  292. if(editing){
  293.  
  294. if(leftFlag){
  295. if(tempModeState!=3){
  296. tempModeState++;
  297. }
  298. else {
  299. tempModeState=0;
  300. }
  301. leftFlag=0;
  302. }
  303.  
  304. else if(rightFlag){
  305. if(tempModeState!=0){
  306. tempModeState--;
  307. }
  308. else {
  309. tempModeState=3;
  310. }
  311. rightFlag=0;
  312. }
  313.  
  314. }
  315.  
  316. // SWITCH CASE
  317. if(tempModeState==1){
  318. // strcpypgm2ram(modeString,"ASSIST");
  319. modeString = "ASSIST ";
  320.  
  321. }
  322. else if(tempModeState==2){
  323. // strcpypgm2ram(modeString,"AUTO ");
  324. modeString = "AUTO ";
  325.  
  326.  
  327. }
  328. else if(tempModeState==3){
  329. // strcpypgm2ram(modeString,"FACTORY");
  330. modeString = "FACTORY";
  331.  
  332.  
  333. }
  334. else{
  335. // strcpy(modeString,"MANUAL1 ");
  336. modeString = "MANUAL ";
  337. }
  338.  
  339. if(selected){
  340.  
  341.  
  342. // GET MODE string that it is entering
  343. for(i = 0; i < 16; i++){
  344. description[i] = ModeStrings[tempModeState*16+i];
  345. }
  346.  
  347. Print2Lines(string1, 0, 0, description, 0, 1);
  348.  
  349. for (i = 0; i < 2; i++){
  350. delay1ms(250);
  351. };
  352.  
  353. // COMMUNICATE TO ROBOT WHICH MODE IT IS ENTERING
  354. modeState = tempModeState;
  355.  
  356. functionState = 0; //Will reset function state to be back to 0 so that when you change modes, it displays from the beginning
  357.  
  358. editing = 0;
  359. selected = 0;
  360. }
  361.  
  362. }
  363.  
  364.  
  365.  
  366.  
  367.  
  368. void DisplayManualCommands(){
  369.  
  370.  
  371. for(i = 0; i < 16; i++){
  372. tx232(string1);
  373. function1[i] = ManualFunctions[functionState*16+i];
  374.  
  375. }
  376.  
  377. switch(functionState){
  378. case 0:
  379. GetMotorState();
  380. strcpypgm2ram(description,motorString);
  381. break;
  382. case 1:
  383. strcpypgm2ram(description,"-128 to 128");
  384. break;
  385. case 2:
  386. GetModeState();
  387. strcpypgm2ram(description,modeString);
  388. break;
  389. default:
  390. return;
  391.  
  392. }
  393.  
  394. Print2Lines(function1, 0, 0, description, 0, 1);
  395. }
  396. void DisplayAssistCommands(){
  397. for(i = 0; i < 16; i++){
  398. // tx232(string1);
  399. function1[i] = FactoryFunctions[functionState*16+i];
  400.  
  401. }
  402.  
  403. switch(functionState){
  404. case 0:
  405. //PID GAINS
  406.  
  407. strcpypgm2ram(description,"Kp=0 Ki=0 Kd=0");
  408. break;
  409. case 1:
  410. // SPEED
  411. strcpypgm2ram(description,"Yeetus Feetus");
  412. break;
  413. case 2:
  414. //YAW RATE
  415. // GetModeState();
  416. strcpypgm2ram(description,"Yeehaw 500");
  417. break;
  418. case 3:
  419. // IR samples/est
  420. strcpypgm2ram(description,"IR KMS lol");
  421. default:
  422. return;
  423.  
  424. }
  425.  
  426. Print2Lines(function1, 0, 0, description, 0, 1);}
  427. void DisplayAutoCommands(){
  428. for(i = 0; i < 16; i++){
  429. // tx232(string1);
  430. function1[i] = FactoryFunctions[functionState*16+i];
  431.  
  432. }
  433.  
  434. switch(functionState){
  435. case 0:
  436. //PID GAINS
  437.  
  438. strcpypgm2ram(description,"Kp=0 Ki=0 Kd=0");
  439. break;
  440. case 1:
  441. // SPEED
  442. strcpypgm2ram(description,"Yeetus Feetus");
  443. break;
  444. case 2:
  445. //YAW RATE
  446. // GetModeState();
  447. strcpypgm2ram(description,"Yeehaw 500");
  448. break;
  449. case 3:
  450. // IR samples/est
  451. strcpypgm2ram(description,"IR KMS lol");
  452. default:
  453. return;
  454.  
  455. }
  456.  
  457. Print2Lines(function1, 0, 0, description, 0, 1);}
  458.  
  459. void DisplayFactoryCommands(){
  460.  
  461.  
  462. for(i = 0; i < 16; i++){
  463. // tx232(string1);
  464. function1[i] = FactoryFunctions[functionState*16+i];
  465.  
  466. }
  467.  
  468. switch(functionState){
  469. case 0:
  470. //PID GAINS
  471.  
  472. strcpypgm2ram(description,"Kp=0 Ki=0 Kd=0");
  473. break;
  474. case 1:
  475. // SPEED
  476. strcpypgm2ram(description,"Yeetus Feetus");
  477. break;
  478. case 2:
  479. //YAW RATE
  480. // GetModeState();
  481. strcpypgm2ram(description,"Yeehaw 500");
  482. break;
  483. case 3:
  484. // IR samples/est
  485. strcpypgm2ram(description,"IR KMS lol");
  486. default:
  487. return;
  488.  
  489. }
  490.  
  491. Print2Lines(function1, 0, 0, description, 0, 1);
  492. }
  493.  
  494.  
  495. void SerialInit(void) {
  496. // Enable SCI TX/RX on RC6 (TX) and RC7 (RX)
  497. TRISC = 0b11000000;
  498.  
  499. //TRISA = 0;
  500. // 1 is input, 0 is output
  501. TRISB = 0b00100111;
  502.  
  503. // Enable serial port, SPEN = 1, CREN = 1
  504. RCSTA = 0b10010000;
  505.  
  506. // For 9600 baud rate
  507. // SPBRG = (Fosc/(16*BR))-1 for 8 bit, BRGH = 0
  508. SPBRG = 15;
  509.  
  510. // Enable TX, low speed baud BRGH (/64), CSRC = 1, TXEN = 1
  511. TXSTA = 0b00100000;
  512.  
  513. // GIE, PIE, INT0IE, RBIE on (Note: INT0IF and RBIF are the flags)
  514. //INTCON = 0b11010000; // NO RBIE
  515. INTCON = 0b11011000;
  516.  
  517. // PORTB pull-ups are disabled, all external bits interrupt on rising edge, RB port change is high priority
  518. INTCON2 = 0b11110001;
  519.  
  520. // INT1:2 are high priority, INT1:2 are enabled (Note: INT1IF and INT2IF are the flags)
  521. INTCON3 = 0b11011000;
  522.  
  523.  
  524.  
  525. // RCON = // IPEN = 0 by default
  526.  
  527. // RCIE = 1
  528. PIE1 = 0b00100000;
  529. }
  530.  
  531. // Send a char via serial
  532. void txChar (char c) {
  533. while(((TXSTA >> 1) & 1) == 0) {};
  534. TXREG = c;
  535. }
  536.  
  537. // Send a string via serial
  538. void tx232(char * str) {
  539. // Loop till null terminator
  540. while(*str != 0) {
  541. txChar(*str);
  542. str++;
  543. }
  544. }
  545.  
  546. // Serial receive function
  547. void rx232(void) {
  548. switch (state) {
  549. // Decide what to do with input depending on what stage of the program we're in
  550. case ROW_SEL:
  551. // Takes in a '0' or '1' (doesn't wait for \r)
  552. inChar = RCREG;
  553.  
  554. if ((inChar >= '0') && (inChar <= '1')) {
  555. txChar(inChar); // Send the character back
  556. row = inChar - '0'; // Convert from ASCII to number
  557. state = POS_SEL; // Increment the state
  558. tx232(posSelStr); // Display user prompt for next state
  559. }
  560. break;
  561.  
  562.  
  563. case POS_SEL:
  564. //state = ROW_SEL;
  565. inChar = RCREG;
  566.  
  567. // Check that the input is a number
  568. if ((inChar >= '0') && (inChar <= '9')) {
  569. // Read the position into the msg buffer as it can be more than one character long
  570. msgIn[msgPos] = inChar;
  571.  
  572. txChar(inChar); // Send the character back
  573. msgPos++; // Increment the position for next time
  574.  
  575. // If the user has input two characters, progress to the next step
  576. if(msgPos > 1) {
  577.  
  578. msgIn[msgPos] = 0; // Null terminate
  579. pos = atoi(msgIn); // Convert the input to a number
  580. msgPos = 0; // Reset the msg buffer for msg input
  581. state = MSG_IN; // Increment the state
  582. tx232(msgSelStr); // Send the user prompt for the next state
  583. }
  584.  
  585. } else if((inChar == '\r') && (msgPos == 1)) {
  586. // If the user inputs a single-digit number, they can press enter to progress
  587.  
  588. pos = msgIn[0] - '0'; // Convert the ASCII character previously input to number
  589. msgPos = 0; // Reset the msg buffer for msg input
  590. state = MSG_IN; // Increment the state
  591. tx232(msgSelStr); // Send the user prompt for the next state
  592. }
  593. break;
  594.  
  595. // Message input
  596. case MSG_IN:
  597.  
  598. // Read the character into the next position in the buffer
  599. msgIn[msgPos] = RCREG;
  600. txChar(msgIn[msgPos]); // Send character back
  601.  
  602. // Message is terminated by a carriage return
  603. if(msgIn[msgPos] == '\r') {
  604. msgIn[msgPos] = 0; // Null terminate
  605.  
  606. // Display the message on the LCD
  607. str2LCD(msgIn, pos, row);
  608. state = ROW_SEL; // Go back to the original state
  609. tx232(rowSelStr); // Send the prompt for the new state
  610. msgPos = 0; // Reset the msg buffer
  611. } else {
  612. // If it isn't a \r, increment to the next position of the buffer for the next character
  613. msgPos++;
  614.  
  615. // If the input is longer than the buffer, stop taking data in and just display it
  616. if (msgPos >= BUFF_SIZE) {
  617. // Display the message on the LCD
  618. str2LCD(msgIn, pos, row);
  619. state = ROW_SEL; // Go back to the original state
  620. tx232(rowSelStr); // Send the prompt for the new state
  621. msgPos = 0; // Reset the msg buffer
  622. }
  623. }
  624. break;
  625.  
  626. default:
  627. break;
  628. }
  629.  
  630. return;
  631. }
  632.  
  633.  
  634. //int i;
  635. void main(void) {
  636.  
  637. // initFunctions();
  638. LCDinit();
  639. SerialInit(); // INITs interrupt and PORTB
  640.  
  641. PORTCbits.RC0=0;
  642.  
  643.  
  644. // An initial welcome to show it's working
  645. // for(i = 0; i < 16; i++){
  646. //// tx232(string1);
  647. // string2[i] = ModeStrings[modeState*16+i];
  648. //
  649. // }
  650.  
  651. Print2Lines(string1, 0, 0, string2, 0, 1);
  652.  
  653. for (i = 0; i < 2; i++){
  654. delay1ms(250);
  655. }
  656.  
  657.  
  658. for(i = 0; i < 16; i++){
  659. // tx232(string1);
  660. description[i] = ModeStrings[modeState*16+i];
  661.  
  662. }
  663.  
  664. Print2Lines(string1, 0, 0, description, 0, 1);
  665. for (i = 0; i < 2; i++){
  666. delay1ms(250);
  667. };
  668.  
  669.  
  670. // The initial prompt
  671. tx232(rowSelStr);
  672.  
  673. // Stay in a loop, wait for interrupts
  674. while(1){
  675.  
  676. switch(modeState){
  677. case 0:
  678. DisplayManualCommands();
  679. case 1:
  680. DisplayAssistCommands();
  681. case 2:
  682. DisplayAutoCommands();
  683. case 3:
  684. DisplayFactoryCommands();
  685. }
  686. };
  687.  
  688. return;
  689. }
  690.  
  691. #pragma interrupthigh highPriorityISR
  692. void highPriorityISR(void) {
  693. int maxFunctions = 2;
  694. // SCROLL RIGHT
  695. if(INTCONbits.INT0IF){
  696. /*
  697. * if up is pressed ++position and ? the function of that particular position>?
  698. * if down is pressed --position
  699. * when enter is pressed enter
  700. */
  701.  
  702. PORTCbits.RC0 ^= 1;
  703.  
  704. if(!editing) {
  705. if(functionState<maxFunctions){
  706. functionState++;
  707. }
  708. }
  709. else {
  710. rightFlag = 1;
  711. }
  712.  
  713. INTCONbits.INT0IF=0;
  714.  
  715. }
  716.  
  717. // ENTER
  718. else if(INTCON3bits.INT1IF) {
  719. PORTCbits.RC0 ^= 1;
  720. if(editing){
  721. selected = 1;
  722. //editing = 0;
  723. }
  724. else{
  725. editing = 1;
  726. }
  727.  
  728. INTCON3bits.INT1IF=0;
  729.  
  730.  
  731. }
  732.  
  733. // SCROLL LEFT
  734. else if(INTCON3bits.INT2IF) {
  735. PORTCbits.RC0 ^= 1;
  736.  
  737.  
  738. if(!editing) {
  739. if(functionState>0){
  740. functionState--;
  741. }
  742. }
  743. else {
  744. leftFlag = 1;
  745. }
  746. INTCON3bits.INT2IF=0;
  747.  
  748. }
  749.  
  750. // BACK
  751. else if (INTCONbits.RBIF){
  752. PORTCbits.RC0 ^= 1;
  753. editing = 0;
  754. INTCONbits.RBIF=0;
  755. }
  756.  
  757.  
  758.  
  759.  
  760. // Check that it is indeed the receive interrupt that has triggered
  761. if((PIR1bits.RCIF == 1) && (PIE1bits.RCIE == 1)) {
  762. // Clear the receive flag
  763. PIR1bits.RCIF = 0;
  764. // Deal with the input
  765. rx232();
  766. }
  767. // Shouldn't be necessary but I found that I had to manually re-enable interrupts
  768. INTCONbits.GIE = 1;
  769.  
  770.  
  771.  
  772. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement