Facebook
From bonebone, 2 Weeks ago, written in Plain Text.
Embed
Download Paste or View Raw
Hits: 128
  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 piece
  50. {
  51.     uint8_t x;
  52.     uint8_t y;
  53.     uint8_t empty_x;
  54.     uint8_t empty_y;
  55.     // Type of the piece: "dot", "l_piece", "square"
  56.     char *type;
  57. };
  58.  
  59. // ============================ //
  60.  
  61. // Global variables:
  62.  
  63. // Hold the board as an array of 8x4:
  64. // C D E F
  65. // 0 0 0 0
  66. // 0 0 0 0
  67. // 0 0 0 0
  68. // 0 0 0 0
  69. // 0 0 0 0
  70. // 0 0 0 0
  71. // 0 0 0 0
  72. // 0 0 0 0
  73. uint8_t board[8][4];
  74.  
  75. // Type of last created piece:
  76. // 0: dot
  77. // 1: square
  78. // 2: l_piece
  79. uint8_t last_piece = 2;
  80.  
  81. // Alive piece:
  82. struct piece *alive_piece = NULL;
  83.  
  84. // Hold a flag to show alive piece or not:
  85. uint8_t is_alive = 0;
  86.  
  87. // Hold a flag to determine whether game is over or not:
  88. uint8_t is_game_over = 0;
  89.  
  90. // Hold a flag to determine if the alive piece is submitted or not:
  91. uint8_t is_submitted = 0;
  92.  
  93. // Flags for buttons:
  94. uint8_t right_button = 0;
  95. uint8_t up_button = 0;
  96. uint8_t down_button = 0;
  97. uint8_t left_button = 0;
  98.  
  99. // ============================ //
  100.  
  101. // Initialize the board
  102. void init_board()
  103. {
  104.     for (uint8_t i = 0; i < 8; i++)
  105.     {
  106.         for (uint8_t j = 0; j < 4; j++)
  107.         {
  108.             board[i][j] = 0;
  109.         }
  110.     }
  111. }
  112.  
  113. // Submit a piece to board.
  114. void submit_piece(struct piece *piece)
  115. {
  116.     // Before submitting the piece, check if the piece can be submitted.
  117.     // If the piece cannot be submitted, return.
  118.     if (piece->type == "dot")
  119.     {
  120.         if (board[piece->x][piece->y] == 1)
  121.         {
  122.             return;
  123.         }
  124.     }
  125.     else if (piece->type == "l_piece")
  126.     {
  127.         if (piece->empty_x == piece->x && piece->empty_y == piece->y)
  128.         {
  129.             // Empty space is on the top-left.
  130.             // OX
  131.             // XX
  132.             if (board[piece->x + 1][piece->y] == 1 || board[piece->x][piece->y + 1] == 1 || board[piece->x + 1][piece->y + 1] == 1)
  133.             {
  134.                 return;
  135.             }
  136.         }
  137.         else if (piece->empty_x < piece->x && piece->empty_y == piece->y)
  138.         {
  139.             // Empty space is on the top-right.
  140.             // XO
  141.             // XX
  142.             if (board[piece->x][piece->y] == 1 || board[piece->x][piece->y + 1] == 1 || board[piece->x + 1][piece->y + 1] == 1)
  143.             {
  144.                 return;
  145.             }
  146.         }
  147.         else if (piece->x < piece->empty_x && piece->x < piece->empty_y)
  148.         {
  149.             // Empty space is on the bottom-right.
  150.             // XX
  151.             // XO
  152.             if (board[piece->x][piece->y] == 1 || board[piece->x + 1][piece->y] == 1 || board[piece->x][piece->y + 1] == 1)
  153.             {
  154.                 return;
  155.             }
  156.         }
  157.         else if (piece->empty_x == piece->x + 1)
  158.         {
  159.             // Empty space is on the bottom-left.
  160.             // XX
  161.             // OX
  162.             if (board[piece->x][piece->y] == 1 || board[piece->x + 1][piece->y] == 1 || board[piece->x + 1][piece->y + 1] == 1)
  163.             {
  164.                 return;
  165.             }
  166.         }
  167.     }
  168.     else if (piece->type == "square")
  169.     {
  170.         if (board[piece->x][piece->y] == 1 || board[piece->x][piece->y + 1] == 1 || board[piece->x + 1][piece->y] == 1 || board[piece->x + 1][piece->y + 1] == 1)
  171.         {
  172.             return;
  173.         }
  174.     }
  175.     // Set correct values to the board as 1:
  176.     if (piece->type == "dot")
  177.     {
  178.         board[piece->x][piece->y] = 1;
  179.     }
  180.     else if (piece->type == "l_piece")
  181.     {
  182.         if (piece->empty_x == piece->x && piece->empty_y == piece->y)
  183.         {
  184.             // Empty space is on the top-left.
  185.             // OX
  186.             // XX
  187.             board[piece->x + 1][piece->y] = 1;
  188.             board[piece->x][piece->y + 1] = 1;
  189.             board[piece->x + 1][piece->y + 1] = 1;
  190.         }
  191.         else if (piece->empty_x < piece->x && piece->empty_y == piece->y)
  192.         {
  193.             // Empty space is on the top-right.
  194.             // XO
  195.             // XX
  196.             board[piece->x][piece->y] = 1;
  197.             board[piece->x][piece->y + 1] = 1;
  198.             board[piece->x + 1][piece->y + 1] = 1;
  199.         }
  200.         else if (piece->x < piece->empty_x && piece->x < piece->empty_y)
  201.         {
  202.             // Empty space is on the bottom-right.
  203.             // XX
  204.             // XO
  205.             board[piece->x][piece->y] = 1;
  206.             board[piece->x + 1][piece->y] = 1;
  207.             board[piece->x][piece->y + 1] = 1;
  208.         }
  209.         else if (piece->empty_x == piece->x + 1)
  210.         {
  211.             // Empty space is on the bottom-left.
  212.             // XX
  213.             // OX
  214.             board[piece->x][piece->y] = 1;
  215.             board[piece->x + 1][piece->y] = 1;
  216.             board[piece->x + 1][piece->y + 1] = 1;
  217.         }
  218.     }
  219.     else if (piece->type == "square")
  220.     {
  221.         board[piece->x][piece->y] = 1;
  222.         board[piece->x][piece->y + 1] = 1;
  223.         board[piece->x + 1][piece->y] = 1;
  224.         board[piece->x + 1][piece->y + 1] = 1;
  225.     }
  226. }
  227.  
  228. // Add a helper function to rotate the L-Piece
  229. void rotate_l_piece(struct piece *piece)
  230. {
  231.     // Pieces always rotate clockwise.
  232.     // Within given square space, determine the next position of empty space.
  233.     // Depending on the current position of the piece, move the empty space to the next position.
  234.     if (piece->empty_x == piece->x && piece->empty_y == piece->y)
  235.     {
  236.         // Empty space is on the top-left.
  237.         // OX -> XO
  238.         // XX -> XX
  239.         piece->empty_x = piece->x + 1;
  240.     }
  241.     else if (piece->empty_x < piece->x && piece->empty_y == piece->y)
  242.     {
  243.         // Empty space is on the top-right.
  244.         // XO -> XX
  245.         // XX -> XO
  246.         piece->empty_y = piece->y + 1;
  247.     }
  248.     else if (piece->empty_y == piece->y)
  249.     {
  250.         // Empty space is on the bottom-right.
  251.         // XX -> XX
  252.         // XO -> OX
  253.         piece->empty_x = piece->x - 1;
  254.     }
  255.     else if (piece->empty_x == piece->x + 1)
  256.     {
  257.         // Empty space is on the bottom-left.
  258.         // XX -> OX
  259.         // OX -> XX
  260.         piece->empty_y = piece->y - 1;
  261.     }
  262. }
  263.  
  264. // Add helper functions to move pieces.
  265.  
  266. void move_piece_left(struct piece *piece)
  267. {
  268.     if (piece->x == 0)
  269.     {
  270.         return;
  271.     }
  272.     piece->x--;
  273.     piece->empty_x--;
  274. }
  275. void move_piece_right(struct piece *piece)
  276. {
  277.     if (piece->x == 6)
  278.     {
  279.         return;
  280.     }
  281.     piece->x++;
  282.     piece->empty_x++;
  283. }
  284. void move_piece_down(struct piece *piece)
  285. {
  286.     if (piece->y == 6)
  287.     {
  288.         return;
  289.     }
  290.     piece->y++;
  291.     piece->empty_y++;
  292. }
  293. void move_piece_up(struct piece *piece)
  294. {
  295.     if (piece->y == 0)
  296.     {
  297.         return;
  298.     }
  299.     piece->y--;
  300.     piece->empty_y--;
  301. }
  302.  
  303. uint8_t prevB;
  304.  
  305. void poll_porta()
  306. {
  307. }
  308.  
  309. void Init()
  310. {
  311.     // 2.2 INPUTS
  312.     // Port A is set as input:
  313.     // RA0: Right
  314.     // RA1: Up
  315.     // RA2: Down
  316.     // RA3: Left
  317.     LATA = 0x00;
  318.     PORTA = 0x00;
  319.     TRISA = 0x0F;
  320.  
  321.     // Port B is also set as input:
  322.     // RB5: Rotate
  323.     // RB6: Submit
  324.     LATB = 0x00;
  325.     PORTB = 0x00;
  326.     TRISB = 0x60;
  327.  
  328.     // 2.3 OUTPUTS
  329.     // C TO F FOR GAME AREA
  330.     // C
  331.     LATC = 0x00;
  332.     PORTC = 0x00;
  333.     TRISC = 0x00;
  334.     // D
  335.     LATD = 0x00;
  336.     PORTD = 0x00;
  337.     TRISD = 0x00;
  338.     // E
  339.     LATE = 0x00;
  340.     PORTE = 0x00;
  341.     TRISE = 0x00;
  342.     // F
  343.     LATF = 0x00;
  344.     PORTF = 0x00;
  345.     TRISF = 0x00;
  346.     // H AND J ? S-10
  347.  
  348.     // Initialize the 7-segment display ports
  349.     TRISJ = 0x00; // Set PORTJ to output
  350.     LATJ = 0x00;  // Clear segments (assumes common cathode display)
  351.  
  352.     TRISH = 0x00; // Set PORTH to output
  353.     LATH = 0x00;  // Disable all 7-segment displays
  354.  
  355.     // Enable the first 7-segment display and set it to show '0'
  356.     LATH = 0xFF; // Enable D0 (assuming PORTH3 controls D0)
  357.     LATJ = 0x3F; // '0' on a common cathode 7-segment display
  358. }
  359.  
  360. void initialize_timer_and_interrupts()
  361. {
  362.     // Enable pre-scalar
  363.     // Full pre-scale
  364.     // we also need to do in-code scaling
  365.     T0CON = 0x00;
  366.     T0CONbits.TMR0ON = 1;
  367.     T0CONbits.T0PS2 = 1;
  368.     T0CONbits.T0PS1 = 0;
  369.     T0CONbits.T0PS0 = 1;
  370.     // Pre-load the value
  371.     TMR0H = T_PRELOAD_HIGH;
  372.     TMR0L = T_PRELOAD_LOW;
  373.  
  374.     RCONbits.IPEN = 0;
  375.     INTCON = 0x00;
  376.     INTCONbits.TMR0IE = 1;
  377.     INTCONbits.RBIE = 1;
  378.     INTCONbits.GIE = 1;
  379.     INTCONbits.PEIE = 1;
  380. }
  381.  
  382. // ============================ //
  383. //   INTERRUPT SERVICE ROUTINE  //
  384. // ============================ //
  385. __interrupt(high_priority) void handle_interrupt()
  386. {
  387.     // Timer overflowed (333 ms)
  388.     if (INTCONbits.TMR0IF)
  389.     {
  390.         INTCONbits.TMR0IF = 0;
  391.         // Pre-load the value
  392.         TMR0H = T_PRELOAD_HIGH;
  393.         TMR0L = T_PRELOAD_LOW;
  394.  
  395.         // Fully lit LATD
  396.         // Blinks LATD
  397.         // LATD = ~PORTD;
  398.     }
  399.     if (INTCONbits.RBIF)
  400.     {
  401.         // Read the value to satisfy the interrupt
  402.         prevB = PORTB;
  403.  
  404.         LATC = ~PORTC;
  405.  
  406.         // Then clear the bit
  407.         INTCONbits.RBIF = 0;
  408.     }
  409. }
  410.  
  411. __interrupt(low_priority) void handle_interrupt_2()
  412. {
  413. }
  414. /*
  415.     Depending on the value of last_piece, create a piece and assign it to alive_piece.
  416. */
  417. void create_piece()
  418. {
  419.     struct piece piece = {0, 0, 0, 0, ""};
  420.     switch (last_piece)
  421.     {
  422.     case 0:
  423.         // Last piece was a dot.
  424.         // Create a square and assign it to alive_piece:
  425.         piece.x = 0;
  426.         piece.y = 0;
  427.         piece.type = "square";
  428.         last_piece = 1;
  429.         break;
  430.     case 1:
  431.         // Last piece was a square.
  432.         // Create an l-piece and assign it to alive_piece:
  433.         piece.x = 0;
  434.         piece.y = 0;
  435.         piece.empty_x = 0;
  436.         piece.empty_y = 1;
  437.         piece.type = "l_piece";
  438.         last_piece = 2;
  439.         break;
  440.     case 2:
  441.         // Last piece was an l-piece.
  442.         // Create a dot and assign it to alive_piece:
  443.         piece.x = 0;
  444.         piece.y = 0;
  445.         piece.type = "dot";
  446.         last_piece = 0;
  447.         break;
  448.     default:
  449.         break;
  450.     }
  451.     alive_piece = &piece;
  452. }
  453.  
  454. /*
  455.     Whether port A RA0 is pressed or not.
  456. */
  457. void right_button_task()
  458. {
  459.     if (PORTA & 0x01)
  460.     {
  461.         right_button = 1;
  462.     }
  463.     else
  464.     {
  465.         if (right_button == 1)
  466.         {
  467.             move_piece_right(alive_piece);
  468.             right_button = 0;
  469.         }
  470.     }
  471. }
  472.  
  473. /*
  474.     Whether port A RA1 is pressed or not.
  475. */
  476. void up_button_task()
  477. {
  478.     if (PORTA & 0x02)
  479.     {
  480.         up_button = 1;
  481.     }
  482.     else
  483.     {
  484.         if (up_button == 1)
  485.         {
  486.             rotate_l_piece(alive_piece);
  487.             up_button = 0;
  488.         }
  489.     }
  490. }
  491.  
  492. /*
  493.     Whether port A RA2 is pressed or not.
  494. */
  495. void down_button_task()
  496. {
  497.     if (PORTA & 0x04)
  498.     {
  499.         down_button = 1;
  500.     }
  501.     else
  502.     {
  503.         if (down_button == 1)
  504.         {
  505.             move_piece_down(alive_piece);
  506.             down_button = 0;
  507.         }
  508.     }
  509. }
  510.  
  511. /*
  512.     Whether port A RA3 is pressed or not.
  513. */
  514. void left_button_task()
  515. {
  516.     if (PORTA & 0x08)
  517.     {
  518.         left_button = 1;
  519.     }
  520.     else
  521.     {
  522.         if (left_button == 1)
  523.         {
  524.             move_piece_left(alive_piece);
  525.             left_button = 0;
  526.         }
  527.     }
  528. }
  529.  
  530. void render_submitted()
  531. {
  532.     uint8_t c_lane = 0x00;
  533.     uint8_t d_lane = 0x00;
  534.     uint8_t e_lane = 0x00;
  535.     uint8_t f_lane = 0x00;
  536.     // For each lane, calculate decimal value of the port:
  537.     for (uint8_t i = 0; i < 8; i++)
  538.     {
  539.         c_lane = c_lane + pow(2, i) * board[i][0];
  540.         d_lane = d_lane + pow(2, i) * board[i][1];
  541.         e_lane = e_lane + pow(2, i) * board[i][2];
  542.         f_lane = f_lane + pow(2, i) * board[i][3];
  543.     }
  544.     // Assign the calculated values to the ports:
  545.     LATC = c_lane;
  546.     LATD = d_lane;
  547.     LATE = e_lane;
  548.     LATF = f_lane;
  549. }
  550.  
  551. // ============================ //
  552. //            MAIN              //
  553. // ============================ //
  554. void main()
  555. {
  556.     Init();
  557.     initialize_timer_and_interrupts();
  558.  
  559.     prevB = PORTB;
  560.     __delay_ms(100);
  561.  
  562.     // Main Loop
  563.     while (!is_game_over)
  564.     {
  565.         create_piece();
  566.         submit_piece(alive_piece);
  567.         while (!is_submitted)
  568.         {
  569.             left_button_task();
  570.             up_button_task();
  571.             down_button_task();
  572.             right_button_task();
  573.             render_submitted();
  574.         }
  575.         is_submitted = 0;
  576.     }
  577. }