Facebook
From bonebone, 2 Weeks ago, written in Plain Text.
Embed
Download Paste or View Raw
Hits: 125
  1. // ============================ //
  2. // Do not edit this part!!!!    //
  3. // ============================ //
  4. // 0x300001 - CONFIG1H
  5. #pragma config OSC = HSPLL // Oscillator Selection bits (HS oscillator,
  6.                            // PLL enabled (Clock Frequency = 4 x FOSC1))
  7. #pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable bit
  8.                            // (Fail-Safe Clock Monitor disabled)
  9. #pragma config IESO = OFF  // Internal/External Oscillator Switchover bit
  10.                            // (Oscillator Switchover mode disabled)
  11. // 0x300002 - CONFIG2L
  12. #pragma config PWRT = OFF  // Power-up Timer Enable bit (PWRT disabled)
  13. #pragma config BOREN = OFF // Brown-out Reset Enable bits (Brown-out
  14.                            // Reset disabled in hardware and software)
  15. // 0x300003 - CONFIG1H
  16. #pragma config WDT = OFF // Watchdog Timer Enable bit
  17.                          // (WDT disabled (control is placed on the SWDTEN bit))
  18. // 0x300004 - CONFIG3L
  19. // 0x300005 - CONFIG3H
  20. #pragma config LPT1OSC = OFF // Low-Power Timer1 Oscillator Enable bit
  21.                              // (Timer1 configured for higher power operation)
  22. #pragma config MCLRE = ON    // MCLR Pin Enable bit (MCLR pin enabled;
  23.                              // RE3 input pin disabled)
  24. // 0x300006 - CONFIG4L
  25. #pragma config LVP = OFF   // Single-Supply ICSP Enable bit (Single-Supply
  26.                            // ICSP disabled)
  27. #pragma config XINST = OFF // Extended Instruction Set Enable bit
  28.                            // (Instruction set extension and Indexed
  29.                            // Addressing mode disabled (Legacy mode))
  30.  
  31. #pragma config DEBUG = OFF // Disable In-Circuit Debugger
  32.  
  33. #define KHZ 1000UL
  34. #define MHZ (KHZ * KHZ)
  35. #define _XTAL_FREQ (40UL * MHZ)
  36.  
  37. // ============================ //
  38. //             End              //
  39. // ============================ //
  40.  
  41. #include <xc.h>
  42. #include <stdint.h>
  43. #include <math.h>
  44.  
  45. #define T_PRELOAD_LOW 0x6A //   BLINK 250MS
  46. #define T_PRELOAD_HIGH 0x67
  47.  
  48. // Add a structure for pieces
  49. struct current_piece
  50. {
  51.     uint8_t horizontal_port; // 0.C, 1.D, 2.E, 3.F
  52.     uint8_t vertical_port;   // A binary number to represent the vertical port e.g 10000000
  53.     uint8_t type;            // 0.dot, 1.square, 2.l_piece
  54. };
  55.  
  56. // ============================ //
  57. // Global variables             //
  58. // ============================ //
  59.  
  60. // Assign initial piece as a dot:
  61. struct current_piece current_piece = {2, 0b00010000, 0};
  62. struct current_piece anti_piece = {0, 0b00000010, 0};
  63.  
  64. // Needed for interrupt on PORTB to work
  65. volatile uint8_t prevB;
  66.  
  67. // Anti piece rotate state:
  68. // XX -> 0, OX -> 1, XO -> 2, XX -> 3
  69. // OX       XX       XX       XO
  70.  
  71. // Represents the empty block position for the current piece if it is an l-piece:
  72. uint8_t rotate_state = 0;
  73.  
  74. // Submitted lanes for pieces:
  75. uint8_t c_lane = 0b00000000;
  76. uint8_t d_lane = 0b00000000;
  77. uint8_t e_lane = 0b00000000;
  78. uint8_t f_lane = 0b00000000;
  79.  
  80. // Flags for buttons:
  81. uint8_t right_button = 0;
  82. uint8_t up_button = 0;
  83. uint8_t down_button = 0;
  84. uint8_t left_button = 0;
  85.  
  86. // Temp
  87.  
  88. uint8_t x;
  89. uint8_t y;
  90. uint8_t z;
  91. uint8_t t;
  92.  
  93. // ============================ //
  94. // Initialize the system        //
  95. // ============================ //
  96.  
  97. void init()
  98. {
  99.     // 2.2 INPUTS
  100.     // Port G is set as input:
  101.     // RA0: Right
  102.     // RA1: Up
  103.     // RA2: Down
  104.     // RA3: Left
  105.     ADCON1 = 0b00001111;
  106.     LATG = 0x00;
  107.     PORTG = 0x00;
  108.     TRISG = 0x0F;
  109.     LATG = 0x00;
  110.     PORTG = 0x00;
  111.  
  112.     // Port B is also set as input:
  113.     // RB5: Rotate
  114.     // RB6: Submit
  115.     LATB = 0x00;
  116.     PORTB = 0x00;
  117.     TRISB = 0x60;
  118.  
  119.     // 2.3 OUTPUTS
  120.     // C TO F FOR GAME AREA
  121.     // C
  122.     LATC = 0x00;
  123.     PORTC = 0x00;
  124.     TRISC = 0x00;
  125.     // D
  126.     LATD = 0x00;
  127.     PORTD = 0x00;
  128.     TRISD = 0x00;
  129.     // E
  130.     LATE = 0x00;
  131.     PORTE = 0x00;
  132.     TRISE = 0x00;
  133.     // F
  134.     LATF = 0x00;
  135.     PORTF = 0x00;
  136.     TRISF = 0x00;
  137.     // H AND J ? S-10
  138.  
  139.     // Initialize the 7-segment display ports
  140.     TRISJ = 0x00; // Set PORTJ to output
  141.     LATJ = 0x00;  // Clear segments (assumes common cathode display)
  142.  
  143.     TRISH = 0x00; // Set PORTH to output
  144.     LATH = 0x00;  // Disable all 7-segment displays
  145.  
  146.     // Enable the first 7-segment display and set it to show '0'
  147.     LATJ = 0x3F; // '0' on a common cathode 7-segment display
  148. }
  149.  
  150. void initialize_timer_and_interrupts()
  151. {
  152.     // Enable pre-scalar
  153.     // Full pre-scale
  154.     // we also need to do in-code scaling
  155.     T0CON = 0x00;
  156.     T0CONbits.TMR0ON = 1;
  157.     T0CONbits.T0PS2 = 1;
  158.     T0CONbits.T0PS1 = 0;
  159.     T0CONbits.T0PS0 = 1;
  160.     // Pre-load the value
  161.     TMR0H = T_PRELOAD_HIGH;
  162.     TMR0L = T_PRELOAD_LOW;
  163.  
  164.     RCONbits.IPEN = 0;
  165.     INTCON = 0x00;
  166.     INTCONbits.TMR0IE = 1;
  167.     INTCONbits.RBIE = 1;
  168.     INTCONbits.GIE = 1;
  169.     INTCONbits.PEIE = 1;
  170. }
  171.  
  172. // ============================ //
  173. //  Piece related functions     //
  174. // ============================ //
  175. void create_piece()
  176. {
  177.     if (current_piece.type == 0)
  178.     {
  179.         // Last piece was a dot.
  180.         // Create a square and assign it to alive_piece:
  181.         current_piece.horizontal_port = 0;
  182.         current_piece.vertical_port = 0b00000011;
  183.         current_piece.type = 1;
  184.     }
  185.     else if (current_piece.type == 1)
  186.     {
  187.         // Last piece was a square.
  188.         // Create an l-piece and assign it to alive_piece:
  189.         current_piece.horizontal_port = 0;
  190.         current_piece.vertical_port = 0b00000011; // Same as square, we already add anti_piece
  191.         current_piece.type = 2;
  192.         anti_piece.horizontal_port = 0;
  193.         anti_piece.vertical_port = 0b00000010;
  194.         anti_piece.type = 0;
  195.         rotate_state = 0;
  196.     }
  197.     else if (current_piece.type == 2)
  198.     {
  199.         // Last piece was an l-piece.
  200.         // Create a dot and assign it to alive_piece:
  201.         current_piece.horizontal_port = 0;
  202.         current_piece.vertical_port = 0b00000001;
  203.         current_piece.type = 0;
  204.     }
  205. }
  206.  
  207. void submit_piece()
  208. {
  209.     // TODO: Add square and l-piece cases
  210.     switch (current_piece.horizontal_port)
  211.     {
  212.     case 0:
  213.         if (!(c_lane & current_piece.vertical_port))
  214.         {
  215.             c_lane = c_lane | current_piece.vertical_port;
  216.         }
  217.         break;
  218.     case 1:
  219.         if (!(d_lane & current_piece.vertical_port))
  220.         {
  221.             d_lane = d_lane | current_piece.vertical_port;
  222.         }
  223.         break;
  224.     case 2:
  225.         if (!(e_lane & current_piece.vertical_port))
  226.         {
  227.             e_lane = e_lane | current_piece.vertical_port;
  228.         }
  229.         break;
  230.     case 3:
  231.         if (!(f_lane & current_piece.vertical_port))
  232.         {
  233.             f_lane = f_lane | current_piece.vertical_port;
  234.         }
  235.         break;
  236.     default:
  237.         break;
  238.     }
  239. }
  240.  
  241. // ============================ //
  242. //  Interrupt related functions //
  243. // ============================ //
  244.  
  245. __interrupt(high_priority) void handle_interrupt()
  246. {
  247.     if (INTCONbits.RBIF)
  248.     {
  249.  
  250.         // Read the value to satisfy the interrupt
  251.         prevB = PORTB;
  252.  
  253.         // Submit current piece and create a new one
  254.         submit_piece();
  255.         create_piece();
  256.         INTCONbits.RBIF = 0;
  257.     }
  258.     INTCONbits.GIE = 1;
  259. }
  260. // ============================ //
  261. //  Button related functions    //
  262. // ============================ //
  263.  
  264. void move_current_piece_left()
  265. {
  266.     if (current_piece.horizontal_port > 0)
  267.     {
  268.         current_piece.horizontal_port--;
  269.         // Move the anti_piece as well, regardless of the type of the current piece
  270.         anti_piece.horizontal_port--;
  271.     }
  272. }
  273. void move_current_piece_right()
  274. {
  275.     if (current_piece.type == 0)
  276.     {
  277.         if (current_piece.horizontal_port < 3)
  278.         {
  279.             current_piece.horizontal_port++;
  280.         }
  281.     }
  282.     else
  283.     {
  284.         if (current_piece.horizontal_port < 2)
  285.         {
  286.             current_piece.horizontal_port++;
  287.             anti_piece.horizontal_port++;
  288.         }
  289.     }
  290. }
  291. void move_current_piece_down()
  292. {
  293.     if (current_piece.type == 0)
  294.     {
  295.         if (current_piece.vertical_port < 64)
  296.         {
  297.             // If 7th bit is not 1, then move down
  298.             current_piece.vertical_port = current_piece.vertical_port << 1;
  299.         }
  300.     }
  301.     else
  302.     {
  303.         // If 7th and 6th bits are not 1, then move down
  304.         if (!(current_piece.vertical_port & 0b11000000))
  305.         {
  306.             current_piece.vertical_port = current_piece.vertical_port << 1;
  307.             anti_piece.vertical_port = anti_piece.vertical_port << 1;
  308.         }
  309.     }
  310. }
  311. void move_current_piece_up()
  312. {
  313.     if (current_piece.type == 0)
  314.     {
  315.         if (current_piece.vertical_port > 1)
  316.         {
  317.             // If 0th bit is not 1, then move up
  318.             current_piece.vertical_port = current_piece.vertical_port >> 1;
  319.         }
  320.     }
  321.     else
  322.     {
  323.         // If 0th and 1st bits are not 1, then move up
  324.         if (!(current_piece.vertical_port & 0b00000011))
  325.         {
  326.             current_piece.vertical_port = current_piece.vertical_port >> 1;
  327.             anti_piece.vertical_port = anti_piece.vertical_port >> 1;
  328.         }
  329.     }
  330. }
  331.  
  332. // ============================ //
  333. // Polling functions            //
  334. // ============================ //
  335.  
  336. void right_button_task()
  337. {
  338.  
  339.     if (PORTGbits.RG0 == 1)
  340.     {
  341.         right_button = 1;
  342.     }
  343.     else
  344.     {
  345.         if (right_button == 1)
  346.         {
  347.             move_current_piece_right();
  348.             right_button = 0;
  349.         }
  350.     }
  351. }
  352.  
  353. void up_button_task()
  354. {
  355.     if (PORTGbits.RG1 == 1)
  356.     {
  357.         up_button = 1;
  358.     }
  359.     else
  360.     {
  361.         if (up_button == 1)
  362.         {
  363.             move_current_piece_up();
  364.             up_button = 0;
  365.         }
  366.     }
  367. }
  368.  
  369. void down_button_task()
  370. {
  371.     if (PORTGbits.RG2 == 1)
  372.     {
  373.         down_button = 1;
  374.     }
  375.     else
  376.     {
  377.         if (down_button == 1)
  378.         {
  379.             move_current_piece_down();
  380.             down_button = 0;
  381.         }
  382.     }
  383. }
  384.  
  385. void left_button_task()
  386. {
  387.     if (PORTGbits.RG3 == 1)
  388.     {
  389.         left_button = 1;
  390.     }
  391.     else
  392.     {
  393.         if (left_button == 1)
  394.         {
  395.             move_current_piece_left();
  396.             submit_piece();
  397.             left_button = 0;
  398.         }
  399.     }
  400. }
  401.  
  402. // ============================ //
  403. //  Rendering functions         //
  404. // ============================ //
  405.  
  406. void render()
  407. {
  408.  
  409.     if (current_piece.horizontal_port == 0)
  410.     {
  411.         LATC = c_lane | current_piece.vertical_port;
  412.         if (current_piece.type != 0)
  413.         {
  414.             // Whether it is square or l-piece, we need to render right lane as well
  415.             LATD = d_lane | current_piece.vertical_port;
  416.         }
  417.         if (current_piece.type == 2)
  418.         {
  419.             // XX -> 0, OX -> 1, XO -> 2, XX -> 3
  420.             // OX       XX       XX       XO
  421.             // Depending on anti_piece position, remove the anti_piece block by subtracting it from the lane
  422.             switch (rotate_state)
  423.             {
  424.             case 0:
  425.                 LATC = LATC - anti_piece.vertical_port;
  426.                 break;
  427.             case 1:
  428.                 LATC = LATC - anti_piece.vertical_port;
  429.                 break;
  430.             case 2:
  431.                 LATD = LATD - anti_piece.vertical_port;
  432.                 break;
  433.             case 3:
  434.                 LATD = LATD - anti_piece.vertical_port;
  435.                 break;
  436.             default:
  437.                 break;
  438.             }
  439.         }
  440.     }
  441.     else if (current_piece.horizontal_port == 1)
  442.     {
  443.         LATD = d_lane | current_piece.vertical_port;
  444.         if (current_piece.type != 0)
  445.         {
  446.             // Whether it is square or l-piece, we need to render right lane as well
  447.             LATE = e_lane | current_piece.vertical_port;
  448.         }
  449.         if (current_piece.type == 2)
  450.         {
  451.             // XX -> 0, OX -> 1, XO -> 2, XX -> 3
  452.             // OX       XX       XX       XO
  453.             // Depending on anti_piece position, remove the anti_piece block by subtracting it from the lane
  454.             switch (rotate_state)
  455.             {
  456.             case 0:
  457.                 LATD = LATD - anti_piece.vertical_port;
  458.                 break;
  459.             case 1:
  460.                 LATD = LATD - anti_piece.vertical_port;
  461.                 break;
  462.             case 2:
  463.                 LATE = LATE - anti_piece.vertical_port;
  464.                 break;
  465.             case 3:
  466.                 LATE = LATE - anti_piece.vertical_port;
  467.                 break;
  468.             default:
  469.                 break;
  470.             }
  471.         }
  472.     }
  473.     else if (current_piece.horizontal_port == 2)
  474.     {
  475.         LATE = e_lane | current_piece.vertical_port;
  476.         if (current_piece.type != 0)
  477.         {
  478.             // Whether it is square or l-piece, we need to render right lane as well
  479.             LATF = f_lane | current_piece.vertical_port;
  480.         }
  481.         if (current_piece.type == 2)
  482.         {
  483.             // XX -> 0, OX -> 1, XO -> 2, XX -> 3
  484.             // OX       XX       XX       XO
  485.             // Depending on anti_piece position, remove the anti_piece block by subtracting it from the lane
  486.             switch (rotate_state)
  487.             {
  488.             case 0:
  489.                 LATE = LATE - anti_piece.vertical_port;
  490.                 break;
  491.             case 1:
  492.                 LATE = LATE - anti_piece.vertical_port;
  493.                 break;
  494.             case 2:
  495.                 LATF = LATF - anti_piece.vertical_port;
  496.                 break;
  497.             case 3:
  498.                 LATF = LATF - anti_piece.vertical_port;
  499.                 break;
  500.             default:
  501.                 break;
  502.             }
  503.         }
  504.     }
  505.     else if (current_piece.horizontal_port == 3)
  506.     {
  507.         LATF = f_lane | current_piece.vertical_port;
  508.     }
  509. }
  510.  
  511. // ============================ //
  512. //  Main function               //
  513. // ============================ //
  514. void main()
  515. {
  516.     init();
  517.     initialize_timer_and_interrupts();
  518.     prevB = PORTB;
  519.     __delay_ms(100);
  520.     while (1)
  521.     {
  522.         left_button_task();
  523.         up_button_task();
  524.         down_button_task();
  525.         right_button_task();
  526.         render();
  527.     }
  528. }